你想本地化用Avalonia编写的桌面程序吗,让我们看看怎么实现。
要本地化应用程序,我们必须能够
直接在XAML中本地化字符串
访问代码中的本地化字符串
要在XAML中翻译字符串,我们可以使用自定义的MarkupExtension和bindings。
public class LocalizeExtension : MarkupExtension
{
public LocalizeExtension(string key)
{
this.Key = key;
}
public string Key { get; set; }
public string Context { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var keyToUse = Key;
if (!string.IsNullOrWhiteSpace(Context))
keyToUse = $"{Context}/{Key}";
var binding = new ReflectionBindingExtension($"[{keyToUse}]")
{
Mode = BindingMode.OneWay,
Source = Localizer.Instance,
};
return binding.ProvideValue(serviceProvider);
}
}
请注意,除了字符串键,还有一个上下文,用于在不同上下文中对同一字符串进行不同的翻译。
此扩展可用于XAML:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i18n="clr-namespace:AvaloniaLocalizationExample.Localizer"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloniaLocalizationExample.MainWindow"
WindowStartupLocation="CenterScreen"
Width="500" Height="350"
Title="AvaloniaLocalizationExample">
<StackPanel Orientation="Vertical" Margin="15">
<Label Content="{i18n:Localize Language}" />
<ComboBox SelectedIndex="0" SelectionChanged="OnLanguageChanged">
<ComboBoxItem>English</ComboBoxItem>
<ComboBoxItem>Italian</ComboBoxItem>
</ComboBox>
<TextBlock FontSize="21" Text="{i18n:Localize HelloWorld}"/>
<TextBlock FontSize="21" Text="{i18n:Localize HelloWorld, Context=Second}"/>
<TextBlock FontSize="21" Text="{i18n:Localize MissingTranslation}"/>
</StackPanel>
</Window>
我们需要先定义命名空间
xmlns:i18n="clr-namespace:AvaloniaLocalizationExample.Localizer"
然后我们可以使用MarkupExtension绑定字符串
<TextBlock FontSize="21" Text="{i18n:Localize HelloWorld}"/>
现在我们需要一种将字符串翻译成所需语言的方法。一种简单的方法是使用包含上下文/键的JSON文件和相应的翻译文本。我们可以使用assets嵌入JSON文件。
缺少的字符串将显示为语言代码,后跟分号和字符串key。
public class Localizer : INotifyPropertyChanged
{
private const string IndexerName = "Item";
private const string IndexerArrayName = "Item[]";
private Dictionary<string, string> m_Strings = null;
public Localizer()
{
}
public bool LoadLanguage(string language)
{
Language = language;
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
Uri uri = new Uri($"avares://AvaloniaLocalizationExample/Assets/i18n/{language}.json");
if (assets.Exists(uri)) {
using (StreamReader sr = new StreamReader(assets.Open(uri), Encoding.UTF8)) {
m_Strings = JsonConvert.DeserializeObject<Dictionary<string, string>>(sr.ReadToEnd());
}
Invalidate();
return true;
}
return false;
} // LoadLanguage
public string Language { get; private set; }
public string this[string key]
{
get
{
string res;
if (m_Strings != null && m_Strings.TryGetValue(key, out res))
return res.Replace("\\n", "\n");
return $"{Language}:{key}";
}
}
public static Localizer Instance { get; set; } = new Localizer();
public event PropertyChangedEventHandler PropertyChanged;
public void Invalidate()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerName));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerArrayName));
}
}
由于我们使用的是绑定和NotifyPropertyChanged,所以一旦加载新语言,就会应用已翻译的文本。
要访问代码中已翻译的字符串,请使用字符串键使用静态定位器
Localizer.Localizer.Instance["Key"]
您可以在这里下载示例项目(avalonia0.10)
AvaloniaLocalizationExample.zip (118 downloads)