在xml标记内本地化值

时间:2013-07-12 10:45:53

标签: 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;
    }
}

此前,它通过视图模型进入xaml。

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

protset是ObservableCollection。

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

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

频带1 BAND2

我看到的样本主要涉及本地化ui相关标签和内容。虽然我们在这种情况下部分地处理ui,但它的价值来自必须本地化的业务流程。

1 个答案:

答案 0 :(得分:0)

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

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