c# - 本地化 xml 标签中的值

标签 c# wpf mvvm localization

这是整个代码流的概述。

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;
    }
}

最终这会通过 View 模型进入 xaml。
 <TextBlock x:Name="FnNameLbl" Text="{Binding Path=ParameterName}" >
 <ComboBox ItemSource="{binding protset}" displaymemeberpath="{binding path=current Value}">

protset 是 ObservableCollection。

现在,像 submit、apply 这样的 UI 标签已经通过 resx 文件进行了本地化。

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

乐队1
带2

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

最佳答案

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

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;
    }
}

关于c# - 本地化 xml 标签中的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17613176/

相关文章:

c# - Azure 函数获取登录标识

c# - 使用 VS2010 运行 StyleCop 时出现 CA2000 Microsoft.Reliability 错误

c# - Xaml 条目 MVVM 数据绑定(bind)

wpf - 如何将 WPF 中的命令绑定(bind)到控件的双击事件处理程序?

wpf - 为什么这在 mvvm 模式中是正确的,而 messageBox 不是?我看不出区别(MVVM Light)

c# - 流动客户端主题时如何在 C# HttpClient 中设置 OIDC/OAuth 持有者 token

c# - 取消请求会降低网络速度

c# - Telerik radgridview 合并/组

C# 特定字符数的通配符

wpf - WPF 中的拖放