スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
Prev.    Category    Next 

XAML のマークアップ拡張を使った WPF での国際化

今回は XAML のマークアップ拡張機能を利用して、 WPF で国際化をする方法についての記事です。

前に Resx のリソースファイルと StaticResource を使った国際化について書きました。 そちらの方法で国際化はできるのですが、一つ問題があります。 .NET 自体のバグだと思うのですが、最初のビルドやリビルドで作成した実行ファイルでは XamlParseException という実行時例外のエラーが発生してしまう点です。
これはソースファイルなどをちょこっと変えてビルドするとエラーはでなくなります。 ただ、少し不便ですし、ビルドサーバーでのビルドといった場合に困ります。


今回の方法は Resx ファイルのリソースを使うところは同じで、 国際化した文字列を取得するのにマークアップ拡張を使うようにします。
XAML に直接記述していくことになるので、はっきり言って、こちらの方がめんどくさいです。 その代わり、エラーはでなくなります。

なお、今回の方法に関しては以下のサイトを参考にさせていただきました。

プロジェクトとリソースの準備

サンプルを作りながら、国際化の方法を説明していきます。 前の回と同じところは詳しい説明は省略しているので、そちらの記事をご覧ください。


まず、プロジェクトを作成して以下のような画面を作成します。 ここではまだボタンとタイトルの文字設定はやらずにそのままにしておきます。
cs_i18n_layout.png

次に Resource.resx, Resource.ja-JP.resx の 2 つのリソースを作成します。
リソースを利用するための App.xaml への修正も今回は必要ありません。

Resources.resx :
English resource

Resources.ja-JP.resx :
cs_i18n_res_ja.png

マークアップ拡張

XAML にはマークアップ拡張という機能があり、 XAML の記述を拡張することができます。
これは {{StaticResource xxxx}} のような記法で、 StaticResource や Binding に使われています。 このマークアップ拡張は自分でも追加することができます。これを利用して国際化します。

拡張定義の追加

追加は MarkupExtension を継承したクラスで行います。
クラスの追加で、以下のファイルをプロジェクトに追加します。

TrExtension.cs :
    [MarkupExtensionReturnTypeAttribute(typeof(string))]
    public class TrExtension : MarkupExtension
    {

        string _key;

        public TrExtension(string key)
        {
            _key = key;
        }

        const string NotFoundError = "#StringNotFound#";

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (string.IsNullOrEmpty(_key))
                return NotFoundError;

            return Properties.Resources.ResourceManager.GetString(_key) ?? NotFoundError;
        }

    }
クラス名の Extension の前(Tr)が XAML での呼び出し用の名前です。

マークアップ拡張による国際化は例外が発生しない以外にも利点があります。 今回は resx のリソースを使って国際化していますが、 ProvideValue() のメソッドの中身を変えることによって、 独自の方法で国際化するといったことも可能になります。

XAML での記述

拡張した定義を使う場合には各 XAML ファイルで次のような記述を行います。

MainWindow.xaml :
<Window x:Class="MarkupI18nSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:MarkupI18nSample"
        Title="{my:Tr UiWindowTitle}" Height="171" Width="338">
    <Grid>
        <Button Content="{my:Tr UiButtonGreet}" Height="23" HorizontalAlignment="Left" Margin="117,52,0,0" Name="buttonGreet" VerticalAlignment="Top" Width="75" Click="buttonGreet_Click" />
    </Grid>
</Window>
記述のスタイルは {{my:Tr キーワード}} の形式です。 my でネームスペースを表すようにしています。


これでコンパイルすれば、デザイン用の画面でも国際化されて表示されているはずです。

サンプルコード

XAML 外のコード中でのリソースの利用法や言語切り替え用のコードなどは前回と同じです。
それらのコードも追加したサンプルコードもあげておきます。

その他の国際化方法

WPF での国際化について今回少し調べて見ました。
おそらく国際化に関しては以下のサイトが一番詳しいと思います。
WPF での国際化の方法は 3 通りほどあるようです。 LocBaml を使った方法は MSDN に書かれている方法なのですが、試したところ上手く動きませんでした。
やり方も csproj を直接編集する必要があったり、 LocBaml も使い勝手が悪い上にちゃんと更新もされていなかったり と Microsoft が本気でこの方法を勧めているのか疑問です。

WPF の国際化はどれも問題があり、 これ といった方法がありません。
個人的には resx を使用した方法がいいと思うのですが、 バグが解消されるまでは、今回のマークアップ拡張を利用した方法も使い分けていく必要があるかなと思います。


また、有料のツールを使ってもよいということであれば、 Sisulizer というツールがよく使われているようです。
関連記事
スポンサーサイト
Prev.    Category    Next 

Facebook コメント


コメント

コメントの投稿

Font & Icon
非公開コメント

このページをシェア
アクセスカウンター
アクセスランキング
[ジャンルランキング]
コンピュータ
10位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
3位
アクセスランキングを見る>>
カレンダー(アーカイブ)
プルダウン 降順 昇順 年別

10月 | 2017年11月 | 12月
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -


はてな新着記事
はてな人気記事
ブロとも申請フォーム
プロフィール

yohshiy

Author:yohshiy
職業プログラマー。
仕事は主に C++ ですが、軽い言語マニアなので、色々使っています。

はてブ:yohshiy のブックマーク
Twitter:@yohshiy

サイト紹介
プログラミング好きのブログです。プログラミング関連の話題や公開ソフトの開発記などを雑多に書いてます。ただ、たまに英語やネット系の話になることも。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。