Avalanche.Localization.ITextLocalizer
ITextLocalizer localizes strings from localization content.
/// <summary>Text localizer</summary>
public interface ITextLocalizer : ILocalizer<ITemplatePrintable>
{
/// <summary>
/// Get localized text for key "Namespace.Name".
///
/// If <see cref="ILocalizer.Namespace"/> or <paramref name="name"/> is null, then counter part is used as key without separator '.'.
/// </summary>
new ILocalizedText? this[string? name] { get; }
}
/// <summary>Text localizer</summary>
public interface ITextLocalizer<Namespace> : ITextLocalizer, ILocalizer<ITemplatePrintable, Namespace> { }
/// <summary>Text localizer</summary>
public interface ITextLocalizer<Namespace, CultureProvider> : ITextLocalizer<Namespace>, ILocalizer<ITemplatePrintable, Namespace, CultureProvider> where CultureProvider : ICultureProvider { }
ITextLocalizer service returns printable texts for full keys. Active culture is read from Thread.CurrentThread.
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot();
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer (Uses Thread.CurrentThread.CurrentUICulture)
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer>()!;
// Read "Resources/en/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en");
ITemplatePrintable? printable = textLocalizer["Namespace.Apples.Count"];
WriteLine(printable!.Print(new object[] { 1 })); // "You've got an apple."
// Read "Resources/fi/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("fi");
ITemplatePrintable? printablefi = textLocalizer["Namespace.Apples.Count"];
WriteLine(printablefi!.Print(new object[] { 1 })); // "Sinulla on yksi omena."
ITextLocalizer<Namespace> uses key that is concatenation of "Namespace.Name". Full type name is used, but unlike with IStringLocalizer, the key is not prefixed with assembly name and resource name from IOptions<LocalizationOptions>.
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot();
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer (Uses Thread.CurrentThread.CurrentUICulture)
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer<Namespace.Apples>>()!;
// Read "Resources/en/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en");
ITemplatePrintable? printable = textLocalizer["Count"];
WriteLine(printable!.Print(new object[] { 1 })); // "You've got an apple."
// Read "Resources/fi/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("fi");
ITemplatePrintable? printablefi = textLocalizer["Count"];
WriteLine(printablefi!.Print(new object[] { 1 })); // "Sinulla on yksi omena."
If Namespace has generics, then '<' and '>' are used in the key. For example ITextLocalizer<IList<IString>> seaches for keys under namespace "System.Collections.Generic.IList<System.String>".
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot();
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer for namespace "System.Collections.Generic.IList<System.String>"
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer<System.Collections.Generic.IList<System.String>>>()!;
// Read "Resources/en/System.Collections.Generic.l.yaml" or "Resources/System.Collections.Generic.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en");
ITemplatePrintable? printable = textLocalizer[null];
WriteLine(printable!.Print(null)); // "List of strings"
// Read "Resources/fi/System.Collections.Generic.l.yaml" or "Resources/System.Collections.Generic.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("fi");
ITemplatePrintable? printablefi = textLocalizer[null];
WriteLine(printablefi!.Print(null)); // "Lista merkkijonoja"
Note that Windows file system cannot have '<' and '>' characters in the file name, therefore localization lines cannot be suppled in "System.Collections.Generic.IList<System.String>.l.yml" file. However, lines can be supplied and detected in a file to a parent namespaces, e.g.: Resources/System.Collections.Generic.l.yaml.
TemplateFormat: Brace
PluralRules: Unicode.CLDR41
Items:
- Key: System.Collections.Generic.IList<System.String>
Text: "List of strings"
Culture: en
- Key: System.Collections.Generic.IList<System.String>
Text: "Lista merkkijonoja"
Culture: fi
ITextLocalizer<Namespace, CultureProvider> derives active culture from CultureProvider type. It must implement ICultureProvider, and must have a parameterless constructor or have a ServiceDescriptor.
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot();
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer, active culture from CultureInfo.CurrentCulture
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer<Namespace.Apples, CultureProvider.CurrentCulture>>()!;
// Read "Resources/en/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en");
ITemplatePrintable? printable = textLocalizer["Count"];
WriteLine(printable!.Print(new object[] { 1 })); // "You've got an apple."
// Read "Resources/fi/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("fi");
ITemplatePrintable? printablefi = textLocalizer["Count"];
WriteLine(printablefi!.Print(new object[] { 1 })); // "Sinulla on yksi omena."
ICultureProvider can be added to service collection to override the default CultureProvider.CurrentThread.
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot()
.AddSingleton(typeof(ICultureProvider), CultureProvider.CurrentCulture.Instance);
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer (Uses Thread.CurrentThread.CurrentUICulture, Thread.CurrentThread.CurrentCulture)
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer>()!;
// Read "Resources/en/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en");
ITemplatePrintable? printable = textLocalizer["Namespace.Apples.Count"];
WriteLine(printable!.Print(new object[] { 1 })); // "You've got an apple."
// Read "Resources/fi/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("fi");
ITemplatePrintable? printablefi = textLocalizer["Namespace.Apples.Count"];
WriteLine(printablefi!.Print(new object[] { 1 })); // "Sinulla on yksi omena."
ILogger service is notified on unsuccessful localization.
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot()
.AddLogging(loggingBuilder => loggingBuilder.SetMinimumLevel(LogLevel.Trace).AddConsole());
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer (Uses Thread.CurrentThread.CurrentUICulture)
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer>()!;
// Assign active culture
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en");
// Try to get non-existent text
ITemplatePrintable? printable = textLocalizer["NonExistant"];
dbug: Avalanche.Localization.TextLocalizer[-1599422402] Localization line was not found: Key=NonExistant, Culture=en
ILocalizer
/// <summary>Base interface for localizer.</summary>
public interface ILocalizer
{
/// <summary>Namespace prefix</summary>
string? Namespace { get; set; }
/// <summary>Resource Type</summary>
Type ResourceType { get; }
/// <summary>Applicable actice culture provider</summary>
ICultureProvider CultureProvider { get; set; }
/// <summary>
/// Get localized resource for <paramref name="name"/>.
///
/// If <see cref="ILocalizer.Namespace"/> or <paramref name="name"/> is null, then counter part is used as key without separator '.'.
/// </summary>
ILocalized? this[string? name] { get; }
}
/// <summary><typeparamref name="T"/> localizer.</summary>
/// <typeparam name="T">Resource type</typeparam>
public interface ILocalizer<out T> : ILocalizer
{
/// <summary>
/// Get localized resource for <paramref name="name"/>.
///
/// If <see cref="ILocalizer.Namespace"/> or <paramref name="name"/> is null, then counter part is used as key without separator '.'.
/// </summary>
new ILocalized<T>? this[string? name] { get; }
}
/// <summary><typeparamref name="T"/> for <typeparamref name="Namespace"/>.</summary>
/// <typeparam name="T">Resource type</typeparam>
/// <typeparam name="Namespace">Key namespace</typeparam>
public interface ILocalizer<T, Namespace> : ILocalizer<T> { }
/// <summary><typeparamref name="T"/> localizer for <typeparamref name="Namespace"/> using <typeparamref name="CultureProvider"/>.</summary>
/// <remarks>This interfaces is typically used with dependency injection.</remarks>
/// <typeparam name="T">Resource type</typeparam>
/// <typeparam name="Namespace">Key namespace</typeparam>
/// <typeparam name="CultureProvider">Culture provider type. Type must have a parameterless constructor.</typeparam>
public interface ILocalizer<T, Namespace, CultureProvider> : ILocalizer<T, Namespace> where CultureProvider : ICultureProvider { }
Resources/Namespace.Apples.l.yaml
TemplateFormat: Brace
PluralRules: Unicode.CLDR41
English:
- Culture: en
Items:
- Key: Namespace.Apples.Count
Cases:
- Text: "You've got an apple."
Plurals: "0:cardinal:one"
- Text: "You've got {0} apples."
Plurals: "0:cardinal:other"
Finnish:
- Culture: fi
Items:
- Key: Namespace.Apples.Count
Cases:
- Text: "Sinulla on yksi omena."
Plurals: "0:cardinal:one"
- Text: "Sinulla on {0} omenaa."
Plurals: "0:cardinal:other"
Resources/sv/Namespace.Apples.l.yaml
TemplateFormat: Brace
PluralRules: Unicode.CLDR41
Swedish:
- Culture: sv
Items:
- Key: Namespace.Apples.Count
Cases:
- Text: "Du har ett äpple."
Plurals: "0:cardinal:one"
- Text: "Du har {0} äpplen."
Plurals: "0:cardinal:other"
Full Example
Full example
using System.Globalization;
using Avalanche.Localization;
using Avalanche.Template;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using static System.Console;
class textlocalizer
{
public static void Run()
{
{
// <01>
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot();
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer (Uses Thread.CurrentThread.CurrentUICulture)
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer>()!;
// Read "Resources/en/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en");
ITemplatePrintable? printable = textLocalizer["Namespace.Apples.Count"];
WriteLine(printable!.Print(new object[] { 1 })); // "You've got an apple."
// Read "Resources/fi/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("fi");
ITemplatePrintable? printablefi = textLocalizer["Namespace.Apples.Count"];
WriteLine(printablefi!.Print(new object[] { 1 })); // "Sinulla on yksi omena."
// </01>
}
{
// <02>
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot();
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer (Uses Thread.CurrentThread.CurrentUICulture)
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer<Namespace.Apples>>()!;
// Read "Resources/en/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en");
ITemplatePrintable? printable = textLocalizer["Count"];
WriteLine(printable!.Print(new object[] { 1 })); // "You've got an apple."
// Read "Resources/fi/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("fi");
ITemplatePrintable? printablefi = textLocalizer["Count"];
WriteLine(printablefi!.Print(new object[] { 1 })); // "Sinulla on yksi omena."
// </02>
}
{
// <03>
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot();
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer for namespace "System.Collections.Generic.IList<System.String>"
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer<System.Collections.Generic.IList<System.String>>>()!;
// Read "Resources/en/System.Collections.Generic.l.yaml" or "Resources/System.Collections.Generic.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en");
ITemplatePrintable? printable = textLocalizer[null];
WriteLine(printable!.Print(null)); // "List of strings"
// Read "Resources/fi/System.Collections.Generic.l.yaml" or "Resources/System.Collections.Generic.l.yaml"
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("fi");
ITemplatePrintable? printablefi = textLocalizer[null];
WriteLine(printablefi!.Print(null)); // "Lista merkkijonoja"
// </03>
}
{
// <04>
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot();
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer, active culture from CultureInfo.CurrentCulture
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer<Namespace.Apples, CultureProvider.CurrentCulture>>()!;
// Read "Resources/en/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en");
ITemplatePrintable? printable = textLocalizer["Count"];
WriteLine(printable!.Print(new object[] { 1 })); // "You've got an apple."
// Read "Resources/fi/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("fi");
ITemplatePrintable? printablefi = textLocalizer["Count"];
WriteLine(printablefi!.Print(new object[] { 1 })); // "Sinulla on yksi omena."
// </04>
}
{
// <05>
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot()
.AddSingleton(typeof(ICultureProvider), CultureProvider.CurrentCulture.Instance);
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer (Uses Thread.CurrentThread.CurrentUICulture, Thread.CurrentThread.CurrentCulture)
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer>()!;
// Read "Resources/en/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en");
ITemplatePrintable? printable = textLocalizer["Namespace.Apples.Count"];
WriteLine(printable!.Print(new object[] { 1 })); // "You've got an apple."
// Read "Resources/fi/Namespace.Apples.l.yaml" or "Resources/Namespace.Apples.l.yaml"
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("fi");
ITemplatePrintable? printablefi = textLocalizer["Namespace.Apples.Count"];
WriteLine(printablefi!.Print(new object[] { 1 })); // "Sinulla on yksi omena."
// </05>
}
{
// <06>
// Add service descriptors
IServiceCollection serviceCollection = new ServiceCollection()
.AddAvalancheLocalizationService()
.AddAvalancheLocalizationFileSystemApplicationRoot()
.AddLogging(loggingBuilder => loggingBuilder.SetMinimumLevel(LogLevel.Trace).AddConsole());
// Build service
using ServiceProvider service = serviceCollection.BuildServiceProvider();
// Get ITextLocalizer (Uses Thread.CurrentThread.CurrentUICulture)
ITextLocalizer textLocalizer = service.GetService<ITextLocalizer>()!;
// Assign active culture
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en");
// Try to get non-existent text
ITemplatePrintable? printable = textLocalizer["NonExistant"];
// </06>
}
}
}