Multilingual management
Lagoon centralizes displayed texts in Dico.xml files. Each key is then referenced in the UI or in code, which avoids hard-coded labels.
Location of the Dico.xml files
| Project | Usage |
|---|---|
App.Client | User interface texts. |
App.Server | Server messages, API errors, and notifications. |
App.Shared | Texts shared between Client, Server, and Shared, for example enums. |
Dictionary format
<?xml version="1.0" encoding="UTF-8"?>
<root>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="" id="root">
<xsd:element name="string">
<xsd:complexType>
<xsd:attribute name="key" use="required" type="xsd:string" />
<xsd:attribute id="fr-FR" name="fr" use="required" type="xsd:string" />
<xsd:attribute id="en-US" name="en" use="required" type="xsd:string" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
<!-- Sample -->
<string key="lblSampleKey" fr="Traduction en français" en="English translation" />
</root>
In this example, only the fr-FR and en-US cultures are present. You can add new languages by adding the corresponding attributes to the schema and to the entries.
Usage in C#
using Lagoon.Helpers;
public class MyService
{
public string GetTranslatedContent()
{
// Translates the key into the current culture.
return "lblSampleKey".Translate();
}
}
Usage in markup
Most Lagoon components automatically translate values prefixed with #.
@inherits LgComponentBase
<LgLabel Text="#lblSampleKey" />
<LgButton Text="#save" OnClick="SaveAsync" />
public partial class MyComponent : LgComponentBase
{
private Task SaveAsync(ActionEventArgs args)
{
// Deliberately minimal example: the actual action depends on the page.
return Task.CompletedTask;
}
}
If a component does not directly handle the # prefix, use manual translation.
@inherits LgComponentBase
<LgLabel Text='@("lblSampleKey".Translate())' />
Formatting with Translate()
Translate() supports string.Format placeholder zones.
<string key="lblWelcomeUser" fr="Bienvenue {0} ! Dernière connexion le {1}" en="Welcome {0}! Last login on {1}" />
public string GetWelcomeMessage(string userName, string lastLoginDate)
{
// Injects the values into placeholders {0} and {1} of the dictionary entry.
return "lblWelcomeUser".Translate(userName, lastLoginDate);
}
To display multiline text, you can store \r\n or 
 in the dictionary and apply a white-space: pre-wrap style to the element that displays the text.
Overriding Lagoon keys
Lagoon components also use dictionary keys. An application can override an existing key by declaring the same key in its own Dico.xml.
Hot loading on the client side
A component inheriting from LgComponentBase can load or override translations at runtime with App.LoadLanguages(...).
public partial class MyComponent : LgComponentBase
{
public void LoadLanguage()
{
Dictionary<string, Dictionary<string, string>> dicoToLoad = new();
Dictionary<string, string> fr = new();
Dictionary<string, string> en = new();
fr.Add("lblSampleKey", "La traduction en français");
en.Add("lblSampleKey", "English translation");
dicoToLoad.Add("fr", fr);
dicoToLoad.Add("en", en);
// Loads the translations and refreshes the components using the dictionary.
App.LoadLanguages(dicoToLoad);
}
}
A key defined in Dico.xml is overridden by App.LoadLanguages(...). If the key does not exist, it is added.
Hot loading on the server side
On the server side, dynamic loading is done through the Lagoon application manager.
public class LanguageService
{
public void LoadLanguages(Dictionary<string, Dictionary<string, string>> dico)
{
// Loads translations server-side for translated API responses.
LgApplicationBase.Current.LoadLanguages(dico);
}
}
Client / server synchronization
No specific action is required to synchronize the language between the UI and the APIs: when the client changes language, subsequent requests receive server responses in the same language when Translate() is used server-side.
Useful characters in XML
| Sequence | Result |
|---|---|
&amp; | & |
&lt; | < |
&gt; | > |

 | Line break |
• | Black bullet |