如何用最简单的方法让WPF程序支持多国语言,并且语言文字用户可以随意编辑?

支持多语言的核心无非是,切换Applicaion级别的ResourceDictionary

 

语言文件随意编辑,无非是在程序启动时,加载一下某个资源文件而已。

 

为了支持界面使用多语言,我们自己定义了一个Resource扩展标记。

 

同时,为了防止,用户误将语言资源删除,而引起界面无任何文字的情况,我们内部定义了一个默认的资源文件,这样就不会没有显示了。

 

资源文件的目录结构:

Languages目录下有Default.xaml, en-US.xaml, zh-CN.xaml等

 

先上核心读取类LanguageReader:

 

#region Header



/**

 * <pre>

 *

 *  Work Force Management

 *  File: LanguageReader.cs

 *

 *  Grandsys, Inc.

 *  Copyright (C): 2009

 *

 *  Description:

 *  Init LanguageReader

 *

 *  Note

 *  Created By: Prime Li at 7/15/2009 2:10:04 PM

 *

 * </pre>

 */



#endregion Header



namespace Luna.Globalization

{

    using System;

    using System.Globalization;

    using System.IO;

    using System.Windows;

    using System.Windows.Markup;



    /// <summary>

    /// Read the Language

    /// </summary>

    public static class LanguageReader

    {

        #region Fields



        private const string LANGUAGE_PATH = @".\Languages\";

        private const string RESOURCE_FILE = @".\Resources\ApplicationResource.xaml";

        private static ResourceDictionary _currentLanguage;

        private static ResourceDictionary _defaultLanguage;



        #endregion Fields



        static LanguageReader()

        {

            Uri uri = new Uri("Luna.Globalization;component/Languages/default.xaml", UriKind.RelativeOrAbsolute);

            _defaultLanguage = Application.LoadComponent(uri) as ResourceDictionary;

            _currentLanguage = _defaultLanguage;

        }



        #region Methods



        /// <summary>

        /// Loads the specified culture.

        /// </summary>

        /// <param name="culture">The culture.</param>

        public static void Load(string culture)

        {

            bool isExistLanguage = CheckLanguageName(culture);

            if (isExistLanguage)

            {

                string path = LANGUAGE_PATH + culture + ".xaml";

                using (FileStream fs = File.OpenRead(path))

                {

                    _currentLanguage = XamlReader.Load(fs) as ResourceDictionary;

                    if (Application.Current.Resources.MergedDictionaries.Contains(_currentLanguage))

                    {

                        Application.Current.Resources.MergedDictionaries.Remove(_currentLanguage);

                    }



                    Application.Current.Resources.MergedDictionaries.Add(_currentLanguage);

                }



                Application.Current.Dispatcher.Thread.CurrentCulture = CultureInfo.GetCultureInfo(culture);

                Application.Current.Dispatcher.Thread.CurrentUICulture = CultureInfo.GetCultureInfo(culture);

            }

            else

            {

                //Use default Language

                Application.Current.Dispatcher.Thread.CurrentCulture = CultureInfo.GetCultureInfo("zh-CN");

                Application.Current.Dispatcher.Thread.CurrentUICulture = CultureInfo.GetCultureInfo("zh-CN");

            }

        }



        public static void LoadResource(string fileName)

        {

            if (File.Exists(fileName))

            {

                using (FileStream fs = File.OpenRead(fileName))

                {

                    ResourceDictionary dic = XamlReader.Load(fs) as ResourceDictionary;

                    Application.Current.Resources.MergedDictionaries.Add(dic);

                }

            }

        }



        public static void LoadDefaultResource()

        {

            LoadResource(RESOURCE_FILE);

        }



        /// <summary>

        /// Gets the value.

        /// </summary>

        /// <param name="key">The key.</param>

        /// <returns></returns>

        public static string GetValue(string key)

        {

            object value = GetValue((object)key);

            if (value == null)

                return string.Empty;

            return value.ToString();

        }



        /// <summary>

        /// Gets the value.

        /// </summary>

        /// <param name="key">The key.</param>

        /// <returns></returns>

        public static object GetValue(object key)

        {

            object value = _currentLanguage[key];

            if (value == null)

                value = _defaultLanguage[key];

            return value;

        }



        /// <summary>

        /// Gets the value.

        /// </summary>

        /// <typeparam name="T"></typeparam>

        /// <param name="key">The key.</param>

        /// <returns></returns>

        public static T GetValue<T>(object key)

        {

            object value = GetValue(key);

            if (value == null)

                return default(T);

            return (T)value;

        }



        public static bool ContainsKey(string key)

        {

            return ContainsKey((object)key);

        }



        public static bool ContainsKey(object key)

        {

            return _currentLanguage.Contains(key) || _defaultLanguage.Contains(key);

        }



        /// <summary>

        /// Checks the name of the language.

        /// </summary>

        /// <param name="languageName">Name of the language.</param>

        /// <returns></returns>

        private static bool CheckLanguageName(string languageName)

        {

            var allLanguageNames = Directory.GetFiles(LANGUAGE_PATH);

            foreach (var name in allLanguageNames)

            {

                if (name.Contains(languageName))

                {

                    return true;

                }

            }



            return false;

        }



        #endregion Methods

    }

}

然后就是自己的Resource扩展标记

 

using System;

using System.Windows;

using System.Windows.Markup;



namespace Luna.Globalization

{

    [MarkupExtensionReturnType(typeof(object)), Localizability(LocalizationCategory.NeverLocalize)]

    public class ResourceExtension : MarkupExtension

    {

        public ResourceExtension()

        { }



        public ResourceExtension(object key)

        {

            Key = key;

        }



        public override object ProvideValue(IServiceProvider serviceProvider)

        {

            return LanguageReader.GetValue(Key);

        }



        [ConstructorArgument("Key")]

        public object Key

        { get; set; }

    }

}



如何使用?

在App.config里面配置:

 

<add key="Language" value="zh-TW" />

在App.xaml.cs的启动时加载:

 

LanguageReader.Load(ConfigurationManager.AppSettings["Language"]);

 

 

在XAML文件里面使用:

 

 

<TextBlock Text="{inf:Resource OK}"/>

 

你可能感兴趣的:(WPF)