Internationalization - i18n
The @genesislcap/foundation-i18n package provides a collection of services and utilities based on the i18next framework to enable your application to handle more than one language.
Key features
- Easy integration: Quick set-up with modern JavaScript frameworks and libraries.
- Dynamic language switching: The user can select to change language on the fly without reloading the application.
- Module federation support: Share and load translations dynamically across different micro front-ends or modules.
- Dependency injection: Integrate i18n services into your components using dependency injection.
Importing and configuring i18n
Once you have installed foundation-i18n, you can import the necessary modules from @genesislcap/foundation-i18n and configure your language settings.
Here is an example that provides headings in both English and Portuguese:
import { defaultI18nextConfig, I18nextConfig } from '@genesislcap/foundation-i18n';
// Tip: Extend or modify the defaultI18nextConfig as needed.
Registration.instance<I18nextConfig>(I18nextConfig, {
...defaultI18nextConfig,
lng: 'pt', // en is the default language but you can change it here or by tweaking the defaultI18nextConfig
resources: {
en: {
translation: {
Home: 'Home',
Admin: 'Admin',
Reporting: 'Reporting',
Notifications: 'Notifications',
['Features Lab']: 'Features Lab',
},
},
pt: {
translation: {
Home: 'Início',
Admin: 'Administração',
Reporting: 'Relatórios',
Notifications: 'Notificações',
['Features Lab']: 'Laboratório de Funcionalidades',
},
},
},
});
This could live in your application’s entry point, such as main.ts or a similar file.
Storing translation information in JSON
Alternatively, you can use a JSON file to store your translations and load them dynamically. For example:
{
"en": {
"translation": {
"Home": "Home",
"Admin": "Admin",
"Reporting": "Reporting",
"Notifications": "Notifications",
"Features Lab": "Features Lab"
}
},
"pt": {
"translation": {
"Home": "Início",
"Admin": "Administração",
"Reporting": "Relatórios",
"Notifications": "Notificações",
"Features Lab": "Laboratório de Funcionalidades"
}
}
}
Then, import the JSON file and use it in your configuration:
import { defaultI18nextConfig, I18nextConfig } from '@genesislcap/foundation-i18n';
import translations from './translations.json';
Registration.instance<I18nextConfig>(I18nextConfig, {
...defaultI18nextConfig,
lng: 'en',
resources: translations,
});
addResources
You can add resources dynamically and whenever necessary.
This is useful when:
- you have a large number of translations
- you need to from a different source
- you want to load translations at a different time from the initial set-up
This will overwrite any resources you have set previously.
import { I18next } from '@genesislcap/foundation-i18n';
import translations from './translations.json';
export class MyExampleClass {
@I18next i18next!: I18next;
addResources() {
this.i18next.addResources(translations);
}
}
Usage
foundation-i18n enables your application to change languages dynamically, without needing to reload:
import { I18next } from '@genesislcap/foundation-i18n';
import { customElement, FASTElement, html } from '@microsoft/fast-element';
import translations from './translations.json';
@customElement({
name: 'my-example-component',
template: html`
<zero-button @click=${() => addResources()}>Add Translation Resources</zero-button>
<zero-button @click=${() => switchLanguage()}>Switch between PT and EN</zero-button>
<zero-button @click=${() => translateWords()}>Translate i18n Resource Words</zero-button>
`,
})
export class MyExampleComponent extends FASTElement {
@I18next i18next!: I18next;
addResources() {
this.i18next.addResources(translations);
}
switchLanguage() {
if (this.i18next.language === 'pt') {
this.i18next.changeLanguage('en');
} else {
this.i18next.changeLanguage('pt');
}
}
translateWords() {
console.log(this.i18next.t('Home')); // if pt, it will log Início, if en, it will log Home
console.log(this.i18next.t('Admin')); // if pt, it will log Administração, if en, it will log Admin
console.log(this.i18next.t('Reporting')); // if pt, it will log Relatórios, if en, it will log Reporting
console.log(this.i18next.t('Notifications')); // if pt, it will log Notificações, if en, it will log Notifications
console.log(this.i18next.t('Features Lab')); // if pt, it will log Laboratório de Funcionalidades, if en, it will log Features Lab
}
}
Integrating with other libraries
Angular example
To integrate @genesislcap/foundation-i18n with an Angular application, you can configure i18next in a service and use it throughout your components.
i18n.service.ts
import { Injectable } from '@angular/core';
import { defaultI18nextConfig, I18next } from '@genesislcap/foundation-i18n';
import translations from './translations.json';
import { DI } from '@microsoft/fast-element';
@Injectable({
providedIn: 'root',
})
export class I18nService {
private container = DI.getOrCreateDOMContainer();
private i18n = this.container.get(I18nService);
constructor() {
this.i18n.init({
...defaultI18nextConfig,
lng: 'en',
resources: translations,
});
}
switchLanguage() {
const newLanguage = this.i18n.language === 'en' ? 'pt' : 'en';
this.i18n.changeLanguage(newLanguage);
}
translate(key: string): string {
return this.i18n.t(key);
}
}
app.component.ts
import { Component } from '@angular/core';
import { I18nService } from './i18n.service';
@Component({
selector: 'app-root',
template: `
<button (click)="switchLanguage()">Switch Language</button>
<p>{{ translate('Home') }}</p>
<p>{{ translate('Admin') }}</p>
<p>{{ translate('Reporting') }}</p>
`,
})
export class AppComponent {
constructor(private i18nService: I18nService) {}
switchLanguage() {
this.i18nService.switchLanguage();
}
translate(key: string): string {
return this.i18nService.translate(key);
}
}
React example
To integrate @genesislcap/foundation-i18n with a React application, create a separate service for handling i18next just as you would create other services.
i18nService.js
import { defaultI18nextConfig, I18next } from '@genesislcap/foundation-i18n';
import { DI } from '@microsoft/fast-foundation';
import translations from './translations.json';
class I18nService {
private container = DI.getOrCreateDOMContainer();
private i18n: Connect = this.container.get(I18next);
constructor() {
this.i18n.init({
...defaultI18nextConfig,
lng: 'en',
resources: translations,
});
}
switchLanguage() {
const newLanguage = this.i18n.language === 'en' ? 'pt' : 'en';
this.i18n.changeLanguage(newLanguage);
}
translate(key) {
return this.i18n.t(key);
}
}
export const i18nService = new I18nService();
App.js
import React from 'react';
import { i18nService } from './i18nService';
const App = () => {
const switchLanguage = () => {
i18nService.switchLanguage();
};
return (
<div>
<button onClick={switchLanguage}>Switch Language</button>
<p>{i18nService.translate('Home')}</p>
<p>{i18nService.translate('Admin')}</p>
<p>{i18nService.translate('Reporting')}</p>
</div>
);
};
export default App;
Installation
To enable this module in your application, follow the steps below.
- Add
@genesislcap/foundation-i18nas a dependency in yourpackage.jsonfile.
{
"dependencies": {
"@genesislcap/foundation-i18n": "latest"
},
}
- Run the
$ npm run bootstrapcommand again. (Whenever you change the dependencies of your project, you should always run this command to rebuild.) You can find more information in the package.json basics page.