Skip to content

Localization _ LocalizationFormatter

Martin Camitz edited this page Oct 18, 2024 · 4 revisions

The LocalizationFormatter localizes literals and placeholders.

Syntax Details

{ :L ( lang ) : literal }

Any value :formatter-name (lang) literal
Any value "L" language code the literal to localize

{ Any value : L (lang) : { placeholder } }

Any value :formatter-name (lang) placeholder
Any value "L" language code the nested placeholder

Configuration:

string Name: default is L
The name to use a named formatter

Configuration in SmartSettings.Localization

ILocalizationProvider? LocalizationProvider: default is null.
Can be set to the standard LocalizationProvider, which handles resx resource files.

Features

  • The standard LocalizationProvider, handles resx resource files. A fallback culture can be set. It will be used, in case no item for a certain culture could be found in any of the resources. LocalizationProvider can search an unlimited number of resoures.
  • All IFormatters can also make use of localization, if needed.
  • Issues with localization throw a LocalizationFormattingException, which is derived from FormattingException.

Examples

The culture-specific results shown here are included in embedded resource files, which are omitted for brevity. Full source code: see LocalizationFormatterTests.

Localize pure literals into Spanish:

// "WeTranslateText" and its translations
// are entries in the resource file

// culture supplied as a format option
Smart.Format("{:L(es):WeTranslateText}");

// culture supplied as an argument to the formatter
var culture = CultureInfo.GetCultureInfo("es");
Smart.Format(culture, "{:L:WeTranslateText}");

// outputs for both: "Traducimos el texto"

Localized strings may contain placeholders

// "has {:#,#} inhabitants}" and its translations
// are entries in the resource file

Smart.Format("{0} {1:L(en):has {:#,#} inhabitants}", "X-City", 8900000);
// outputs: "X-City has 8,900,000 inhabitants"

Smart.Format("{0} {1:L(es):has {:#,#} inhabitants}", "X-City", 8900000);
// outputs: "X-City tiene 8.900.000 habitantes"

The string to localize may contain nested placeholders

Nested formats are also supported. This is useful, if the string to localize contains a placeholder instead of pure text.

Example: If the format is "{:L(fr):{ProductType}}", the ProductType placeholder will be replaced with the variable content "pen". "pen" will in turn be localiced to "bic" for the FR locale.

Use Localization together with other formatters

By example of pluralization

// "{} item", "{} items" and its translations
// are entries in the resource file

Smart.Format("{0:plural:{:L(en):{} item}|{:L(en):{} items}}", 0);
// outputs for English: 0 items

Smart.Format("{0:plural:{:L(fr):{} item}|{:L(fr):{} items}}", 0);
// outputs for French: 0 élément

Smart.Format("{0:plural:{:L(fr):{} item}|{:L(fr):{} items}}", 200);
// outputs for French: 200 éléments

Use a Custom ILocalizationProvider

Create your custom ILocalizationProvider implementation:

public class DictLocalizationProvider : ILocalizationProvider
{
    private readonly Dictionary<string, Dictionary<string, string>> _translations;

    public DictLocalizationProvider()
    {
        _translations = new Dictionary<string, Dictionary<string, string>> {
            { "en", new Dictionary<string, string> { { "COUNTRY", "country" } } },
            { "fr", new Dictionary<string, string> { { "COUNTRY", "pays" } } },
            { "es", new Dictionary<string, string> { { "COUNTRY", "país" } } }
        };
    }

    public string? GetString(string name)
    {
        return GetTranslation(name, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName);
    }

    public string? GetString(string name, string cultureName)
    {
        return GetTranslation(name, cultureName);
    }

    public string? GetString(string name, CultureInfo cultureInfo)
    {
        return GetTranslation(name, cultureInfo.TwoLetterISOLanguageName);
    }

    private string? GetTranslation(string name, string cultureName)
    {
        if (!_translations.TryGetValue(cultureName, out var entry)) return null;
        return entry.TryGetValue(name, out var localized) ? localized : null;
    }
}

Use it:

// Change settings for your provider
Smart.Default.Settings.Localization.LocalizationProvider = new DictLocalizationProvider();
// Add the formatter
Smart.Default.AddExtensions(new LocalizationFormatter());

Smart.Format("{:L(en):COUNTRY} * {:L(fr):COUNTRY} * {:L(es):COUNTRY}");
// Output: "country * pays * país"
Clone this wiki locally