L’internazionalizzazione delle applicazioni è un’area di sviluppo dalle mille sfaccettature, incentrata sulla messa a disposizione e sulla facilità di utilizzo delle applicazioni per un pubblico mondiale. Questa pagina descrive gli strumenti di internazionalizzazione (i18n), che possono aiutare a rendere l’applicazione disponibile in più lingue.
Configurazione dizionari
Dopo aver configurato il TranslateModule, è possibile inserire le traduzioni in un file json che verrà importato con il TranslateHttpLoader. Le seguenti traduzioni vengono archiviate in due diversi json: en.json (dizionario inglese) e it.json (dizionario italiano). Ma nessuno ci impedisce di creare altri dizionari (ad esempio de.json).
Il TranslateParser accetta oggetti JSON nidificati. Ciò significa che sarà possibile avere traduzioni simili alle seguenti:
it.json
{
"today": "Oggi",
"day-labels": {
"mo": "Lun",
"tu": "Mar",
"we": "Mer",
"th": "Gio",
"fr": "Ven",
"sa": "Sab",
"su": "Dom"
},
"month-labels": {
"1": "Gen",
"2": "Feb",
"3": "Mar",
"4": "Apr",
"5": "Mag",
"6": "Giu",
"7": "Lug",
"8": "Ago",
"9": "Set",
"10": "Ott",
"11": "Nov",
"12": "Dic"
},
"Yes": "Sì",
"No": "No",
"Cancel": "Annulla",
"Clear": "Pulisci",
...
}
en.json
{
"today": "Today",
"day-labels": {
"mo": "Mon",
"tu": "Tue",
"we": "Wed",
"th": "Thu",
"fr": "Fri",
"sa": "Sat",
"su": "Sun"
},
"month-labels": {
"1": "Jan",
"2": "Feb",
"3": "Mar",
"4": "Apr",
"5": "May",
"6": "Jun",
"7": "Jul",
"8": "Aug",
"9": "Sep",
"10": "Oct",
"11": "Nov",
"12": "Dec"
},
"Yes": "Yes",
"No": "No",
"Cancel": "Cancel",
"Clear": "Clear",
...
}
Configurazione dei moduli
Per rendere funzionante il multilingua, è necessario configurare i moduli di base come negli esempi seguenti. Se si è utilizzato lo Scarface per creare il progetto, i seguenti passi non saranno necessari:
Il primo passo per iniziare, è configurare un factory che funga da loader delle traduzioni, come di seguito:
export function TranslateHttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
Nell’esempio sopra viene usato TranslateHttpLoader per caricare le traduzioni da “/assets/i18n/[lang].json ” ([lang] è la lingua corrente, che per inglese potrebbe essere en). E’ necessario importare TranslateModule.forRoot() nell’NgModule principale dell’applicazione. Il metodo statico forRoot è una convenzione che fornisce e configura servizi allo stesso tempo. E’ necessario assicurarsi di chiamare questo metodo solo nel modulo principale dell’applicazione (AppModule). Questo metodo consente di configurare TranslateModule specificando un loader, un parser e/o un gestore di traduzioni.
import { HttpClient } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { LocaleService } from '@ca-webstack/ng-i18n';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
...
@NgModule({
declarations: [
...
],
imports:[
...
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: TranslateHttpLoaderFactory,
deps: [HttpClient]
}
}),
...
],
providers: [
...
],
bootstrap: [...]
})
export class AppModule {
constructor(translate: TranslateService, locale: LocaleService) {
const lang = navigator.language.substring(0, 2);
translate.setDefaultLang('it');
translate.use(lang);
translate.addLangs(['it', 'en']);
locale.setLocale(lang);
}
}
Se si desidera configurare un TranslateLoader personalizzato (ad es. per caricare traduzioni dal server anziché dalle risorse locali), è necessario modificare l’implementazione del factory
...
export class CustomTranslateLoader implements TranslateLoader {
constructor(private readonly http: HttpClient) { }
public getTranslation(lang: string): Observable {
return this.http.get(`${Config.API}/api/i18n/${lang}`);
}
}
export function TranslateHttpLoaderFactory(http: HttpClient) {
return new CustomTranslateLoader(http);
}
...
Se si utilizza uno SharedModule che viene importato in altri moduli (ad esempio ComponentsModule), è possibile importare e quindi esportare TranslateModule per assicurarsi di non doverlo importare in ogni modulo.
...
import { TranslateModule } from '@ngx-translate/core';
@NgModule({
declarations: [],
imports: [
...
TranslateModule
],
exports: [
...
TranslateModule
],
...
Allo stesso modo, se si desidera utilizzare il modulo i18n (servizi e pipe) per tradurre mstring (chiave:valore) è necessario importare ed esportare i18nModule.
...
import { I18nModule } from '@ca-webstack/ng-i18n';
@NgModule({
declarations: [],
imports: [
...
I18nModule
],
exports: [
...
I18nModule
],
...
Service Injection
E’ possibile sfruttare tutte le funzionalità offerte dal modulo Translate e dal modulo i18n, iniettando ovunque i relativi servizi singleton.
import { TranslateService } from '@ngx-translate/core';
import { I18nService } from '@ca-webstack/ng-i18n';
...
public constructor( ...
private _translateService: TranslateService,
private _i18nService: I18nService ) {
...
...
E’ possibile sottoscriversi all’evento di cambio-lingua, come di seguito:
...
this._translateService.onLangChange.subscribe((lang: string) => ...));
...
Verificare qual è la lingua corrente:
...
this._translateService.currentLang
...
Cambiare lingua:
...
this._translateService.use('en');
...
E’ possibile anche definire le traduzioni manualmente con il metodo setTranslation:
...
this._translateService.setTranslation('en', {
HELLO: 'hello {{value}}'
});
...
Tradurre una chiave direttamente da servizio:
...
await this._translateService.get('localized-string').toPromise()
...
Tradurre oggetti di tipo MString:
...
await this._i18nService.get({ key: 'localized-string', default: 'Localized string' }).toPromise();
await this._i18nService.get('localized-string').toPromise();
...
Pipe
Oltre al TranslateService, è possibile utilizzare la TranslatePipe per ottenere i valori di traduzione:
Questa è una stringa localizzata Questa è una variabile localizzata Ciao world Ciao Mondo Questa è una MString Fallback localized-string-2 Fallback string
Typescript file
...
protected localizedString = 'localized-variable';
protected i18nString = { key: 'i18n-mstring', default: 'Fallback string' };
protected i18nString2 = { key: 'i18n-mstring-2', default: 'Fallback string' };
...
it.json
{
...
"localized-string": "Questa è una stringa localizzata",
"localized-variable": "Questa è una variabile localizzata",
"i18n-mstring": "Questa è una MString",
"hello": "Ciao {{value}}",
"world": "Mondo"
...
}
en.json
{
...
"localized-string": "This is a localized string",
"localized-variable": "This is a localized variable",
"i18n-mstring": "This is an MString",
"hello": "Hello {{value}}",
"world": "World"
...
}
HTML File
<p>{{'localized-string' | translate}}</p>
<p>{{localizedString | translate}}</p>
<p>{{ 'hello' | translate:{value: 'world'} }}</p>
<p>{{ 'hello' | translate:{value: ('world' | translate)} }}</p>
<p>{{i18nString | i18n}}</p>
<br>
<p><b>Fallback</b></p>
<p>{{'localized-string-2' | translate}}</p>
<p>{{i18nString2 | i18n}}</p>
Directive
Oltre al TranslateService ed alla TranslatePipe, è possibile utilizzare la TranslateDirective per ottenere i valori di traduzione:
Questa è una stringa localizzata Questa è una variabile localizzata Ciao world Ciao Mondo
Typescript file
...
protected localizedString = 'localized-variable';
...
it.json
{
...
"localized-string": "Questa è una stringa localizzata",
"localized-variable": "Questa è una variabile localizzata",
"hello": "Ciao {{value}}",
"world": "Mondo",
...
}
en.json
{
...
"localized-string": "This is a localized string",
"localized-variable": "This is a localized variable",
"i18n-mstring": "This is an MString",
"hello": "Hello {{value}}",
"world": "World",
...
}
HTML File
<p translate>localized-string</p>
<p translate>{{localizedString}}</p>
<p translate [translateParams]="{value: 'world'}">hello</p>
<p translate [translateParams]="{value: 'world' | translate}">hello</p>