这是整个代码流的概述。
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/