LocalizableString type
The type GroupeIsa.Neos.Shared.Localization.LocalizableString is a string that can be localized into multiple languages.
See the LocalizableString API documentation for more information.
LocalizableString is immutable, which means that once it is created, it cannot be changed.
This type can be used for entity properties and it is persisted as a JSON object in the database.
This type is transpiled into a record type in typescript.
Breaking changes in version 2.2
Before version 2.2, the LocalizableString type was inherited from ReadOnlyDictionarty<string, string>. This is no longer the case.
In version 2.2, the LocalizableString implementation use composition instead of inheritance in order to support oData select and expand queries.
This difference should create some breaking changes in the way you use the LocalizableString type, below are the changes you should be aware of:
Enumerating the LocalizableString
In version prior to 2.2, you could enumerate the LocalizableString as a ReadOnlyDictionary<string, string>. This is no longer possible.
var localizableString = new LocalizableString(new Dictionary<string, string>
{
{ "en", "Hello" },
{ "fr", "Bonjour" }
});
foreach (var localizedString in localizableString) // This will not compile
{
}
You should modify your code to use the LocalizableString methods to enumerate the localized strings.
var localizableString = new LocalizableString(new Dictionary<string, string>
{
{ "en", "Hello" },
{ "fr", "Bonjour" }
});
foreach (var localizedString in localizableString.AsEnumerable())
{
}
Another example using the Select method from the System.Linq namespace.
var localizableString = new LocalizableString(new Dictionary<string, string>
{
{ "en", "Hello" },
{ "fr", "Bonjour" }
});
var languages = localizableString.Where(ls => ls.Value.Length > 100).Select(ls => ls.Key) // This will not compile
You should modify your code to use AsEnumerable method.
var localizableString = new LocalizableString(new Dictionary<string, string>
{
{ "en", "Hello" },
{ "fr", "Bonjour" }
});
var languages = localizableString.AsEnumerable().Where(ls => ls.Value.Length > 100).Select(ls => ls.Key)
Convert the LocalizableString to a dictionary
In version 2.2 and later, an implicit operator converts the localizableString into a dictionary.
However, you should explicitly convert the LocalizableString to a dictionary using the ToDictionary method in some case where implicit conversion is not possible.
For example using the BeEquivalentTo method from the FluentAssertions library.
var localizableString = new LocalizableString(new Dictionary<string, string>
{
{ "en", "Hello" },
{ "fr", "Bonjour" }
});
localizableString.Should().BeEquivalentTo(new Dictionary<string, string>
{
{ "en", "Hello" },
{ "fr", "Bonjour" }
}); // This will compile but will fail at runtime
you should modify your code to use the ToDictionary method.
var localizableString = new LocalizableString(new Dictionary<string, string>
{
{ "en", "Hello" },
{ "fr", "Bonjour" }
});
localizableString.ToDictionary().Should().BeEquivalentTo(new Dictionary<string, string>
{
{ "en", "Hello" },
{ "fr", "Bonjour" }
});
you can also cast the LocalizableString to a dictionary.
var localizableString = new LocalizableString(new Dictionary<string, string>
{
{ "en", "Hello" },
{ "fr", "Bonjour" }
});
((Dictionary<string, string>)localizableString).Should().BeEquivalentTo(new Dictionary<string, string>
{
{ "en", "Hello" },
{ "fr", "Bonjour" }
});
Getting a translation with a fallback to the default language from a LocalizableString
GetTranslationOrDefault returns the translation of a LocalizableString for a language, or the translation for the cluster's default language when that language has no translation.
Since the inner workings of localizable strings vary between the server and the client, different signatures of the method exist. You can use the following guide to know when to use the right signature.
| Signature | Server C# | UI C# | Returns |
|---|---|---|---|
GetTranslationOrDefault() |
⛔ Available but not recommended | ✅ Available | string in the current language if present in the LocalizableString, falls back to the default language |
GetTranslationOrDefault(string language) |
⛔ Available but not recommended | ✅ Available | string in the specified language if present in the LocalizableString, falls back to the default language |
GetTranslationOrDefault(ILocalizationSettings settings) |
✅ Available | ❌ Not available | string in the current language of the settings if present in the LocalizableString, falls back to the default language of settings |
GetTranslationOrDefault(string? language, ILocalizationSettings? settings) |
✅ Available | ❌ Not available | string in the specified language (or in the current language of the settings when not specified) if present in the LocalizableString, falls back to the default language of settings |
Server side example: getting a translation in the language of the client that made the request
...
ILocalizationSettings _localizationSettings; // Injected
string captionInClientLanguage = localizableStringWithTranslationInClientLanguage.GetTranslationOrDefault(_localizationSettings);
string captionInDefaultLanguage = localizableStringWithoutTranslationInClientLanguage.GetTranslationOrDefault(_localizationSettings);
Server side example: getting a translation in a specific language
...
ILocalizationSettings _localizationSettings; // Injected
string captionInFr = localizableStringWithTranslationInFr.GetTranslationOrDefault("fr", _localizationSettings);
string captionInDefaultLanguage = localizableStringWithoutTranslationInFr.GetTranslationOrDefault("fr", _localizationSettings);
UI example: getting a translation in the language of the client
string captionInClientLanguage = localizableStringWithTranslationInClientLanguage.GetTranslationOrDefault();
string captionInDefaultLanguage = localizableStringWithoutTranslationInClientLanguage.GetTranslationOrDefault();
UI example: getting a translation in a specific language
string captionInFr = localizableStringWithTranslationInFr.GetTranslationOrDefault("fr");
string captionInDefaultLanguage = localizableStringWithoutTranslationInFr.GetTranslationOrDefault("fr");
Getting a LocalizableString from a resource on server side
When the server sends text to the client that is displayed to the user, it is crucial to use LocalizableString as users can use different languages.
Ideally, texts should be created as translated C# resources or string resources in Neos Studio. Then you can create a LocalizableString from the resource using the following methods:
ILocalizationSettings _localizationSettings; // Injected
LocalizableString localizableString1 = LocalizableString.FromResource(
_localizationSettings,
Resources.MyModule.ResourceManager,
nameof(Resources.MyModule.MyCaption));
string caption1 = localizableString1["en"];
string name = "Richard";
int age = 41;
LocalizableString localizableString2 = LocalizableString.FromFormattedResource(
_localizationSettings,
Resources.MyModule.ResourceManager,
nameof(Resources.MyModule.MyCaptionWithFormat),
name,
age);
string caption2 = localizableString2.GetTranslationOrDefault("fr");
Additionally, you can use resources extension methods GetLocalizableString and GetFormattedLocalizableString provided by namespace GroupeIsa.Neos.Domain :
using GroupeIsa.Neos.Domain;
...
ILocalizationSettings _localizationSettings; // Injected
LocalizableString localizableString1 = Resources.MyModule.GetLocalizableString(
_localizationSettings,
nameof(Resources.MyModule.MyCaption));
string caption1 = localizableString1.GetTranslationOrDefault("en");
string name = "Richard";
int age = 41;
LocalizableString localizableString2 = Resources.MyModule.GetFormattedLocalizableString(
_localizationSettings,
nameof(Resources.MyModule.MyCaptionWithFormat),
name,
age);
string caption2 = localizableString2["fr"];