Localization (l10n) and internationalization (i18n)¶
Because HortiView will be an internationally widely used application, there is a need for a proper implementation of translations throughout the application. That means we need to support multiple languages, currencies, and regions across the globe.
For module development, this means we need to implement some kind of translation logic that translates every text users can see while using the application.
In general, most internationalization/localization solutions use some kind of translation-to-identifier logic, where each string or text is represented by a unique identifier. This identifier is used to translate the text using a translation file that contains the translation for the currently selected language.
There are many frameworks that already solve this exact issue. One of them is i18next, an i18n-library for JavaScript applications. It simplifies the implementation of localization by managing translations and other locale-specific functionalities. Here's how it works:
recommended but not required
The usage of i18next is not required, but as we use it in the platform itself and the modules, it can be seen as a best-practice implementation of internationalization.
- Translation Files: i18next uses JSON or YAML files to store translations. Each file corresponds to a specific language (e.g., en.json for English, de.json for German, or es.json for Spanish).
- Language Detection: The library can automatically detect the user's preferred language based on browser settings, cookies, or URL parameters, if configured correctly.
- Interpolation: i18next supports placeholders in translations, allowing dynamic content to be inserted (e.g., "Hello, {{name}}!").
- Middleware Integration: i18next integrates seamlessly with frameworks like React, Angular, and Vue.js, as well as server-side environments like Node.js.
The HortiView platform already uses this library to translate everything. The user's language preference is stored in the user profile and will be used to initialize the translation. Users can change their language at any time via the settings menu:
Implementation in modules¶
Requirements
This implementation requires setting up i18next in the module as well.
It is important to create a new instance for your module. Otherwise, the implementation could interfere with the platform's initialization of i18next.
For easy synchronization, we pass the user's currently chosen language locale to the modules. In base modules (and the template), we use this language locale to trigger a language switch/initialization of the module's i18n with the help of a hook implementation:
The effect hook listens to changes in the passed language variables and keeps them synchronized with the HortiView platform.
Provide translations to the platform | Breadcrumb¶
required for breadcrumb
This step is important if you use the platform's breadcrumb.
If your module uses some kind of navigation or routing, you will probably want to use the platform's breadcrumb. This provides a module with the function to navigate between pages/routes using a breadcrumb. The breadcrumb is automatically calculated based on the routes of a module.
Each breadcrumb part corresponds to a segment of the URL and is automatically translated using a translation string for the currently selected language. This translation string needs to be provided by you via the addBreadcrumbTranslation function (see Base Methods). In the base module, this logic is implemented by default for every route:
Lines 73-75 iterate over every route that is passed to the ModuleBase via the route configuration (see RouteConfig.tsx). It uses the configured translationKey of the passed RouteConfig.tsx and adds the current translation (based on the currently selected language) for all routes that have a translationKey configured.
This requires a proper translation provided in the translation files, which are normally located in a path like this:
- locales/en-US.json
- locales/es-MX.json
- [...other supported languages...]
If we take a look on the base-templates translation, we can see, that we have a translation for the testpage:
A translation for the module name and the base route is automatically provided by the platform with the ID and the ModuleName.
Translations for dynamic keys
If you want to include translations for dynamic route elements, like IDs, you need to call the addBreadcrumbTranslation function in your dynamic route component, depending on the ID itself. This ensures that if the ID changes, you still add the translation for the new/changed ID:
Example Route¶
modules/[id of the module]/season/[Dynamic RouteKey - ID of a season]
Example RouteConfig¶
RouteConfig.tsx | |
---|---|
The route-defining path-value will be used for the automatic translation, so you need to provide a key for this in the route-configuration.
Implementation of translations¶
The [id of the module] will be automatically translated by HortiView with your module name.
The [Dynamic RouteKey - ID of a season] can be translated by calling the addBreadcrumbTranslation function each time the value of :id changes inside the Season component. The implementation could look like this:
We get the addBreadcrumbTranslation function via the useBaseProps-Hook from the ModuleBase-Dependency and simply add the translated (name of the season) for the identifier of the season (ID, that is used in the route) in a key-value pair. Keep in mind, that this method will be passed to every module (as property, so you don't need the template for this)