【问题标题】:Localising values within xml tags本地化 xml 标签中的值
【发布时间】:2013-07-10 21:26:45
【问题描述】:

这是整个代码流程的概述。

FormatCode.xml 是这种格式的输入文件之一。

<FormatCode id="405">

<Map>
<enumvalue>0</enumvalue> 
<actualvalue>Off</actualvalue>
</Map>

<Map>
<enumvalue>1</enumvalue> 
<actualvalue>Band1</actualvalue>
</Map>

<Map>
<enumvalue>2</enumvalue> 
<actualvalue>Band2</actualvalue>
</Map>

<Map>
<enumvalue>3</enumvalue> 
<actualvalue>Band3</actualvalue>
</Map>
 </FormatCode>

我的应用程序将此 xml 文件中的值读取到模型中的以下 CLR 对象中。其他 xml 文件也用作类中某些字段的输入,但我们不要打扰。

public class parameter
{
    public string ParameterName
    {
        get;
        set;
    }
    public string Enumvalue
    {
        get;
        set;
    }
    public string CurrentValue
    {
        get;
        set;
    }
}

最终这会通过视图模型进入 xaml。

 <TextBlock x:Name="FnNameLbl" Text="{Binding Path=ParameterName}" >
 <ComboBox ItemSource="{binding protset}" displaymemeberpath="{binding path=current Value}">

protset 是 ObservableCollection。

现在提交、应用等 UI 标签已经通过 resx 文件本地化了。

我的问题是将 formatcode.xml 中的值本地化为英语、德语、中文等的最佳方法是什么。

Band1 乐队2

我看到的示例主要处理与 ui 相关的标签和内容的本地化。尽管在这种情况下我们部分处理了 ui,但它的值来自必须本地化的业务流程。

【问题讨论】:

    标签: c# wpf mvvm localization


    【解决方案1】:

    您是否尝试过使用绑定转换器?这是我使用的,以及执行实际翻译的翻译字符串扩展器。

    public class LocalizeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is string)
            {
                return ((string)value).Translate(culture);
            }
            return null;
    
        }
    
        public object ConvertBack(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is string)
            {
                return (string)value;
            }
            return null;
        }
    }
    

    我在下面包含了使用 xml 文件进行本地化的代码。您甚至可以以交互方式更新 xml。选择器只是我们用来向用户呈现选择列表的对话框。它的实现是微不足道的,不包括在内。 TextEntry 类似,一个接受用户输入的对话框。

    在我的基本窗口类中,我添加了一个 TextInput 侦听器来捕获 CTRL+T(更新翻译 xml)或 CTRL+I(交互式)。

    window.TextInput += (sender, args) =>
    {
        if (args.ControlText == "\x14") // Ctrl+T
        {
            "".Translate(true);
        }
        if (args.ControlText == "\x09") // Ctrl+I
        {
            "".Translate(true, true);
        }
    };
    
    public static class LocalExtensions
    {
        private static Dictionary<string,SortedDictionary<string,string>> languages = new Dictionary<string,SortedDictionary<string,string>>(5);
        private static bool autoAdd;
        public static bool interactiveAdd;
    
        public static string Translate(this String phrase, bool autoAdd, bool interactive = false)
        {
            var cultures = CultureInfo.GetCultures(CultureTypes.InstalledWin32Cultures);
            var chooser = new Chooser(Application.Current.Windows[0], "Translate from English To:", cultures.Select(culture => culture.EnglishName));
            chooser.ShowDialog();
            var selectedCulture = cultures.First(candidate => candidate.EnglishName == chooser.selectedItem);
    
            Localize.SetDefaultCulture(selectedCulture);
    
            LocalExtensions.autoAdd = autoAdd;
            LocalExtensions.interactiveAdd = interactive;
    
            return phrase.Translate();
        }
        public static string Translate(this String phrase)
        {
            return phrase.Translate(CultureInfo.CurrentCulture);
        }
        public static string Translate(this String phrase, CultureInfo culture) {
            if (String.IsNullOrWhiteSpace(phrase)) return phrase;
    
    
            var lang = culture.TwoLetterISOLanguageName;
            SortedDictionary<string,string> translations;
            if (!Directory.Exists(@"Languages"))
            {
                return phrase;
            }
            var pathName = FindFile("Languages\\" + lang + ".xml");
    
            if ( !languages.ContainsKey(lang) ) {
                try {
                    var xaml = File.ReadAllText(pathName, Encoding.UTF8);
                    translations = (SortedDictionary<string, string>)XamlServices.Parse(xaml);
                } catch(Exception) {
                    translations = new SortedDictionary<string,string>();
                }
                languages.Add(lang,translations);
            } else {
                translations = languages[lang];
            }
    
            if (translations.ContainsKey(phrase))
            {
                // return the translation for the specified phrase
                var tran = translations[phrase];
                var result = InteractiveUpdate(phrase, tran);
                if ( result != tran ) {
                    translations[phrase] = result;
                    SaveChanges(translations,pathName);
                }
                return translations[phrase];
            }
    
            // HACK: This is enabled by pressing CTRL+T on any window in the App.
            // Please note that any phrases in that window will not be translated
            // only phrases loaded in subsequent windows.
            if (LocalExtensions.autoAdd)
            {
                var result = InteractiveUpdate(phrase,phrase);
                translations.Add(phrase, result);
                SaveChanges(translations, pathName);
            }
            return phrase;
        }
        private static void SaveChanges(SortedDictionary<string,string> translations, string pathName)
        {
                var writer = new StreamWriter(pathName, false, Encoding.UTF8);
                XamlServices.Save(writer, translations);
                writer.Close();
        }
        private static string InteractiveUpdate(String phrase, String tran)
        {
            // HACK: Interactive update will be enabled by pressing CTRL+I on any window.
            // The same caveat applies here as with autoAdd above.
            if (interactiveAdd && !phrase.StartsWith("pack:"))
            {
                interactiveAdd = autoAdd = false;
    
                var tb = new TextBox
                {
                    TextWrapping = TextWrapping.Wrap,
                    AcceptsReturn = true,
                    Height = double.NaN,
                    Width = double.NaN,
                    Text = tran
                };
                var te = new TextEntry(Application.Current.Windows[0],"Please translate:",tb,TextEntryType.AlphaNumeric);
                te.blurEnabled = false;
                te.ShowDialog();
                tran = tb.Text;
    
                interactiveAdd = autoAdd = true;
            }
            return tran;
        }
    
        private static string FindFile(string fileName)
        {
            var candidatePath = fileName;
            if (!File.Exists(fileName))
            {
                candidatePath = AppDomain.CurrentDomain.BaseDirectory + "\\" + fileName;
                if (!File.Exists(candidatePath) && ApplicationDeployment.IsNetworkDeployed)
                {
                    candidatePath = ApplicationDeployment.CurrentDeployment.DataDirectory + "\\" + fileName;
                }
            }
            return candidatePath;
        }
    }
    

    【讨论】:

    • 感谢您的努力伙伴。我需要一段时间才能吸收这一切。
    猜你喜欢
    • 2011-09-19
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 2021-02-17
    • 2013-01-18
    • 1970-01-01
    相关资源
    最近更新 更多