Table of Contents

Strings and Translations

The main purpose of Tlumach is to provide localized / translated strings picked from translation files in a handy way.

Each string is identified by a string key; translation files are sets of key-value pair in different formats. Each string together with its key makes a translation unit.

Keys are case-insensitive and should be valid identifiers in .NET format. A valid identifier must start with a letter or '_' (underscore) which may be followed by a zero or more letters, digits, and underscores:

These are the sample valid keys:

valid_key=text
_validKey=text
_1_key=text

When Generator is used, keys become variable names, so if you use some analyzer that enforces the style of variable names, be sure that your keys follow that style at least in the default file.

Groups of Strings

If a file format supports grouping, translation units can be grouped. When a translation unit belongs to a group, the name of the group becomes a prefix of the key, joined with the key using '.' (dot).

E.g., you can have the "greetings" group in the translation file, with "hello" and "goodbye" entries in it:

[greetings]
hello=Hello
goodbye=Bye

These units can be accessed by using the "greetings.hello" and "greetings.goodbye" keys respectively. When Generator is used, groups become nested classes in the main class being generated, i.e., "greetings" will be a nested class, and "hello" and "goodbye" will be variables in this class.

Groups may be nested:

[greetings]
hello=How do you do!
goodbye=Goodbye!

[greetings.Informal]
hello=Hello
goodbye=Bye

This configuration will give you the "greetings" class and the "Informal" class inside the "greetings" class. The first two units will be "greetings.hello" and "greetings.goodbye", and the last two will be "greetings.Informal.hello" and "greetings.Informal.goodbye" respectively.

Regular and Templated Strings

If a string is not templated, i.e., does not contain placeholders, Tlumach provides this string as is. If you use generated translation units, you can access the text using the instance of TranslationUnit that has the name equal to the key of the needed string. If you work directly with TranslationManager, use one of the GetValue() methods (GetValue(string), GetValue(string, CultureInfo), GetValue(TranslationConfiguration, string, CultureInfo)) to obtain an instance of TranslationEntry and read the value of the Text property.

If you have a translation unit, you can check in code if it is templated (contains placeholders) by checking its ContainsPlaceholders property.

If a string is templated, an application can retrieve it from the translation manager as a template and handle the placeholders as it likes, or the application can use the capabilities of Tlumach to process templates and fill the template with actual values.

To obtain the template when using Generator, the application can call the GetValueAsTemplate(CultureInfo) method.

When working directly with TranslationManager, the application can call one of the GetValue() methods (GetValue(string), GetValue(string, CultureInfo), GetValue(TranslationConfiguration, string, CultureInfo)) that return an instance of TranslationEntry and read the value of the Text property.

To let Tlumach process the template, you can inspect the ContainsPlaceholders property of this entry and if it is true, use one of the ProcessTemplatedValue() methods (ProcessTemplatedValue(CultureInfo, TextFormat, IDictionary<string, object?>), ProcessTemplatedValue(CultureInfo, TextFormat, OrderedDictionary), ProcessTemplatedValue(CultureInfo, TextFormat, object), ProcessTemplatedValue(CultureInfo, TextFormat, params object?[])) to fill the template with the data.

Templated Translation Units and XAML

Since version 1.1, Tlumach supports XAML bindings to translation units even when they are templated. To let this approach work, you have two options:

  1. Pre-fill translation units which contain placeholders with values. To do this, use the CachePlaceholderValue(string, object?) method to add values for the template. You can update the values in the cache using the same method or remove them from the cache using the <Tlumach.BaseTranslationUnit.ForgetPlaceholderValue(System.String)> method. In both cases, if you have bindings to this unit, you need to notify them about the change. Do this by calling the NotifyPlaceholdersUpdated() method of the corresponding unit.
  2. Handle the OnPlaceholderValueNeeded event and provide the values dynamically. The event parameters let you specify that you want the provided value to be cached. If you do this, the event won't fire for this parameter the next time the value of the translation unit is requested. You can remove the value from the cache using the ForgetPlaceholderValue(string) method; if you call it, use the NotifyPlaceholdersUpdated() method to update the bindings. Note that if the data which you provide for the placeholder changes in background, you will still want to notify the UI that the final text of the unit changes. This is also done via the NotifyPlaceholdersUpdated() method.

Current and Other Locales

TranslationManager has a CurrentCulture property which is used as a default culture, for which translation units are retrieved.

This CurrentCulture property is useful primarily in UI applications where XAML properties are bound to generated translation units: the text provided to the bound controls is defined by the value of this property.

If you are using one of the methods for retrieval of translation units mentioned above in their overloads that don't include a culture, the value of CurrentCulture is used there too.

To change the language of the UI in your XAML-based project, change the value of CurrentCulture. This will notify the bindings and also cause the OnCultureChanged event to fire.

Overriding Translation Files

Sometimes, it is necessary to provide a specific phrase regardless of its presence in a translation file. Maybe, the string is completely missing from the translation, or, maybe, your application configuration allows administrators to define some messages for their users.

To address these needs, TranslationManager includes several events:

Untranslatable Strings as Translation Units

Sometimes, it is necessary to represent a constant or untranslatable string (e.g., coming outside of the translation file) as a translation unit. This is mostly needed when lists of translation units are bound to XAML list-like elements. For this purpose, Tlumach includes the UntranslatedUnit class and the classes with the same name for XAML, UWP, and WinUI. An application can create such a unit and add it to the list as necessary.

Untranslated units may contain placeholders, which will be processed the same way any regular translation unit is.

When UntranslatedUnit is created using the UntranslatedUnit(string, TranslationManager, TranslationConfiguration, bool) constructor, the TranslationManager parameter may be set to Empty (recommended), or you can reference an existing instance of TranslationManager. The TranslationConfiguration parameter should be set to some configuration, from which the value of TextProcessingMode will be picked if necessary, when placeholders are processed.