开源软件名称(OpenSource Name):GuOrg/Gu.Localization开源软件地址(OpenSource Url):https://github.com/GuOrg/Gu.Localization开源编程语言(OpenSource Language):C# 98.0%开源软件介绍(OpenSource Introduction):Gu.Localization.Contents.
Quickstart
<Window
x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:localize="http://gu.se/Localization"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:properties="clr-namespace:WpfApp1.Properties"
Title="MainWindow"
mc:Ignorable="d">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<localize:LanguageSelector AutogenerateLanguages="True" />
<TextBlock Grid.Column="1" Text="{localize:Static properties:Resources.Some_text}" />
</Grid>
</Window> Renders:
Note: If you get errors about missing Note: To set the translation programmatically write: Note: Make sure to add Note: Intsall For working with resx in Visual Studio ResXManager is a nice extension. NeutralResourcesLanguageAdding: [assembly:NeutralResourcesLanguage("en")] To Usage in XAML.The library has a The markupextension has ErrorHandling = ErrorHandling.ReturnErrorInfoPreserveNeutral as default, it encodes errors in the result, see ErrorFormats) Simple exampleFor each language, create a resource.xx.resx file. You can use ResXManager to do this for you. <UserControl ...
xmlns:l="clr-namespace:Gu.Wpf.Localization;assembly=Gu.Wpf.Localization"
xmlns:p="clr-namespace:AppNamespace.Properties"
xmlns:local="clr-namespace:YourNamespace;assembly=Gu.Localization">
...
<!-- Dropbownbox to select a language -->
<ComboBox x:Name="LanguageComboBox"
ItemsSource="{Binding Path=(localization:Translator.Cultures)}"
SelectedItem="{Binding Path=(localization:Translator.Culture),
Converter={x:Static l:CultureOrDefaultConverter.Default}}" />
<!-- Label that changes translation upon language selection -->
<Label Content="{l:Static p:Resources.ResourceKeyName}" /> With converterWhen <TextBlock Text="{Binding Source={l:Static p:Resources.TranslatedToAll}, Path=Translated, Converter={x:Static local:StringToUpperConverter.Default}}" /> [ValueConversion(typeof(string), typeof(string))]
public sealed class StringToUpperConverter : IValueConverter
{
public static readonly StringToUpperConverter Default = new StringToUpperConverter();
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value switch
{
string { } s => s.ToUpper(culture),
null => null,
_ => throw new ArgumentException($"Expected a string, was: {value.GetType()} with value: {value}"),
};
}
object IValueConverter.ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotSupportedException($"{nameof(StringToUpperConverter)} can only be used in OneWay bindings");
}
} Bind a localized string.<Window ...
xmlns:p="clr-namespace:Gu.Wpf.Localization.Demo.WithResources.Properties"
xmlns:l="http://gu.se/Localization">
...
<TextBlock Text="{l:Static p:Resources.SomeResource}" />
<TextBlock Text="{l:Enum ResourceManager={x:Static p:Resources.ResourceManager},
Member={x:Static local:SomeEnum.SomeMember}}" />
... The above will show SomeResource in the Errorhandling.By setting the attached property <Grid l:ErrorHandling.Mode="ReturnErrorInfo"
... >
...
<TextBlock Text="{l:Static p:Resources.SomeResource}" />
<TextBlock Text="{l:Enum ResourceManager={x:Static p:Resources.ResourceManager},
Member={x:Static local:SomeEnum.SomeMember}}" />
... CurrentCulture.A markupextension for accessing <Grid numeric:NumericBox.Culture="{l:CurrentCulture}"
... >
...
<StackPanel Orientation="Horizontal">
<TextBlock Text="Effective culture: " />
<TextBlock Text="{l:CurrentCulture}" />
</StackPanel>
... Binding to Culture and Culture in XAML.The static properties support binding. Use this XAML for a twoway binding: <Window ...
xmlns:localization="clr-namespace:Gu.Localization;assembly=Gu.Localization">
...
<TextBox Text="{Binding Path=(localization:Translator.Culture)}" /> Usage in code.The API is not super clean, introducing a helper like this can clean things up a bit. Creating it like the above is pretty verbose. Introducing a helper like below can clean it up some. The analyzer checks calls to this method but it assumes:
namespace YourNamespace.Properties
{
using Gu.Localization;
using Gu.Localization.Properties;
public static class Translate
{
/// <summary>Call like this: Translate.Key(nameof(Resources.Saved_file__0_)).</summary>
/// <param name="key">A key in Properties.Resources</param>
/// <param name="errorHandling">How to handle translation errors like missing key or culture.</param>
/// <returns>A translation for the key.</returns>
public static string Key(string key, ErrorHandling errorHandling = ErrorHandling.ReturnErrorInfoPreserveNeutral)
{
return TranslationFor(key, errorHandling).Translated;
}
/// <summary>Call like this: Translate.Key(nameof(Resources.Saved_file__0_)).</summary>
/// <param name="key">A key in Properties.Resources</param>
/// <param name="errorHandling">How to handle translation errors like missing key or culture.</param>
/// <returns>A translation for the key.</returns>
public static ITranslation TranslationFor(string key, ErrorHandling errorHandling = ErrorHandling.ReturnErrorInfoPreserveNeutral)
{
return Gu.Localization.Translation.GetOrCreate(Resources.ResourceManager, key, errorHandling);
}
}
} Translator.Culture.Get or set the current culture. The default is Culture.Get or set the current culture. The default is CurrentCulture.Get the culture used in translations. By the following mechanism:
Cultures.Get a list with the available cultures. Cultures are found by looking in current directory and scanning for satellite assemblies. ErrorHandling.Get or set how errors are handled. The default value is Translate.Translate a key in a ResourceManager. Use global culture & error handling: Translator.Culture = CultureInfo.GetCultureInfo("en"); // no need to set this every time, just for illustration purposes here.
string inEnglish = Translator.Translate(Properties.Resources.ResourceManager,
nameof(Properties.Resources.SomeResource)); Translate to neutral culture:string neutral = Translator.Translate(Properties.Resources.ResourceManager,
nameof(Properties.Resources.SomeResource),
CultureInfo.InvariantCulture); Translate to explicit culture:string inSwedish = Translator.Translate(Properties.Resources.ResourceManager,
nameof(Properties.Resources.SomeResource),
CultureInfo.GetCultureInfo("sv")); Override global error handling (throw on error):Translator.ErrorHandling = ErrorHandling.ReturnErrorInfo; // no need to set this every time, just for illustration purposes here.
string inSwedish = Translator.Translate(Properties.Resources.ResourceManager,
nameof(Properties.Resources.SomeResource),
ErrorHandling.Throw); Override global error handling (return info about error):Translator.ErrorHandling = ErrorHandling.Throw; // no need to set this every time, just for illustration purposes here.
string inSwedish = Translator.Translate(Properties.Resources.ResourceManager,
nameof(Properties.Resources.SomeResource),
ErrorHandling.ReturnErrorInfo); Translate with parameter:Translator.Culture = CultureInfo.GetCultureInfo("en");
string inSwedish = Translator.Translate(Properties.Resources.ResourceManager,
nameof(Properties.Resources.SomeResource__0__),
foo); MissingTranslation.An event that notifies when the key or culture is missing. Can be used for logging. Translator.MissingTranslation += (sender, args) => Log($"Missing translation for {args.Key} when translating to {args.Language}."); Translator<T>.Same as translator but used like Translation.An object with a Translated property that is a string with the value in GetOrCreate.Returns an Translation translation = Translation.GetOrCreate(Properties.Resources.ResourceManager, nameof(Properties.Resources.SomeResource)) StaticTranslation.An implementation of |