[WPF]多言語に対応したアプリのサンプルを作成。動的に言語を切り替えることが可能

すごい簡単なサンプルアプリを作成しました。GitHubにも公開しました。

https://github.com/bruno1911/Multilingual

多言語に対応したアプリのサンプルを作成。

アプリの説明

コンボボックスの内容を変更すると、その内容に応じた言語に切り替わるというアプリです。

日本語を選択すると「こんにちは」と表示され、Englishを選択すると「Hello」と表示されます。

言語のリソースを用意する

「Resources.resx」というファイルに、表示する言語の内容を追加します。「Resources.resx」はProperties配下にあります。

名前にキーとなる名称、値に実際に表示させる文字を入力します。今回の場合、名前を「Greeting」、値を「Hello」と入力しています。アクセス修飾子を「Public」にするのもお忘れなく。

次に日本語のリソースを用意します。Propertiesを右クリックして、「追加」-「新しい項目」をクリックします。

「リソースファイル」を選択して、名前を「Resources.ja-JP.resx」としてファイルを追加します。

新しく追加したファイルも名前、値を変更します。名前は英語と同じ内容の「Greeting」、値は「こんにちは」と入力します。アクセス修飾子を「Public」にするのもお忘れなく。

これでリソースの準備は完了です。

コードを修正する

GitHubでも確認することができます。

https://github.com/bruno1911/Multilingual

View

コンボボックスで変更したリソースをTextに表示する簡単なソースです。

<Window x:Class="Multilingual.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:Multilingual.ViewModels"
        Width="200"
        Height="200"
        FontSize="30" >

    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>

    <StackPanel HorizontalAlignment="Center"
                VerticalAlignment="Top">
        <ComboBox ItemsSource="{Binding LanguagesEnum}" 
                  DisplayMemberPath="Value"
                  SelectedValuePath="Key"
                  SelectedValue="{Binding ComboBoxValue}"/>
        <TextBlock Text="{Binding Path=Resources.Greeting, Mode=OneWay}" />
    </StackPanel>
</Window>

ViewModel

コンボボックスの値をバインドしています。その値が変更された場合に、プロパティ変更通知を発生させるようにしています。

using Multilingual.Properties;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Multilingual.ViewModels
{
    public enum Languages
    {
        [Description("日本語")]
        Japanese,
        [Description("English")]
        English,
    }

    public class MainWindowViewModel: INotifyPropertyChanged
    {
        /// <summary>
        /// コンボボックスに表示する内容
        /// </summary>
        public Dictionary<Languages, string> LanguagesEnum { get; } = new Dictionary<Languages, string>();

        public event PropertyChangedEventHandler PropertyChanged;

        public MainWindowViewModel()
        {
            foreach (var value in Enum.GetValues(typeof(Languages)))
            {
                LanguagesEnum.Add((Languages)value, LanguagesExtensions.GetName((Languages)value));
            }
        }

        /// <summary>
        /// 多言語化されたリソースを取得します。
        /// </summary>
        public Resources Resources { get; } = new Resources();

        /// <summary>
        /// 指定されたカルチャ名を使用して、リソースのカルチャを変更します。
        /// </summary>
        /// <param name="name">カルチャの名前。</param>
        public void ChangeCulture(Languages languages)
        {
            Resources.Culture = CultureInfo.GetCultureInfo(ChangeEnumString(languages));
            this.RaisePropertyChanged("Resources");
        }

        public Languages ComboBoxValue
        {
            get { return comboBoxValue; }
            set
            {
                comboBoxValue = value;
                ChangeCulture(comboBoxValue);
            }
        }
        private Languages comboBoxValue = Languages.Japanese;

        private string ChangeEnumString(Languages languages)
        {
            switch (languages)
            {
                case Languages.Japanese: return "ja-JP";
                case Languages.English: return "en-US";
            }
            return "";
        }

        protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    static class LanguagesExtensions
    {
        // 拡張メソッド
        public static string GetName<T>(this T Value)
             where T : struct, IComparable, IConvertible, IFormattable
        {
            if (!(typeof(T).IsEnum))
            {
                throw new InvalidEnumArgumentException();
            }

            var fieldInfo = Value.GetType().GetField(Value.ToString());
            if (fieldInfo == null) return null;

            var attr = (DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));
            if (attr == null) return "";
            return attr.Description;
        }
    }
}

最後に

このアプリを作成するにあたってこちらの記事を参考にさせていただきました。

http://grabacr.net/archives/1647

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA