To create multilingual interfaces Angular offers to use the HTML markup mechanism of the templates with a special marker i18n, which after compilation is removed from the final code. To do this, it is enough to specify this marker as an attribute of the tag surrounding the text.
<h1 i18n>Hello baby!</h1>
For a marker, you can specify additional parameters that are displayed in specialized editors used for translation and complement the translated text with service information designed to help the translator. These parameters are transmitted in the format "Value | Description" or only "Description".
<h1 i18n="An introduction header for this sample">Hello baby!</h1> <h1 i18n="User welcome|An introduction header for this sample">Hello baby!</h1>
It is possible to specify a marker for text that is not surrounded by a tag. For this purpose, either a special empty tag is used which is not rendered in the final code.
<ng-container i18n>I don't output any element</ng-container>
or special comment
')
I don't output any element either
It is also possible to do a translation for tag attributes. Such as alt, title, ...
<img [src]="logo" i18n-title title="Angular logo" />
Plural
The ending of words for the plural is based on the rules
http://unisource.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules and
http://cldr.unisource.org/index/cldr-spec/plural-rules in the format:
<span i18n>{wolves, plural, =0 {no wolves} =1 {one wolf} =2 {two wolves} other {a wolf pack}}</span>
wolves - the name of the variable containing the number
plural - the name of the type of transformation
= 0 - possible variable value, {no wolves} - displayed text for this value
= 1 - the possible value of the variable, {one wolf} - the displayed text for this value
= 2 - possible variable value, {two wolves} - displayed text for this value
other - if the variable value is not specified, {a wolf pack} - the displayed text for this value
The following options are possible:
- = 0
- = 1
- = 2
- few (... 3-10 or 5-10, depends on localization rules)
- other (default value for all unspecified options)
Select
Allows you to select a value based on a literal variable:
<span i18n>The hero is {gender, select, m {male} f {female}}</span>
gender - the name of the variable containing the value
select - the name of the conversion type
m is the possible value of the variable, {male} is the displayed text for the given value
f - possible variable value, {female} - displayed text for this value
ng-xi18n
To extract the lines from the application, the special utility
ng-xi18n is included in the angular-cli:
./node_modules/.bin/ng-xi18n -p src/tsconfig.json
This utility searches for i18n marker in templates and copies the corresponding text to form an XML file of XLIFF format (version 1.2) from it.
The XML Message Bundle (XMB) format is also supported. To do this, set the appropriate key:
./node_modules/.bin/ng-xi18n
Then the XML file can be sent to the translator who can edit it with one of the specialized editors. The resulting file should be saved in the i18n folder and contain the localization language in its name. For example, in the case of the Spanish language, from the original
messages.xlf we get
messages.es.xlf . A separate file must be created for each interface language.
In order for the translation file to be used by Angular, you need to add the following code to main.ts:
// import {TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID} from '@angular/core'; // XML let current_language = 'ru'; import {RU_TRANS} from './i18n/messages.' + current_language;
There is one remark. If we use angular-cli, then at present we cannot independently (officially) change the configuration of the webpack and accordingly we cannot add the raw rule for files with the xlf extension, which allows importing them directly. Therefore, for the time being, you have to insert them into the wrapper file (messages.ru.ts):
export const RU_TRANS = `
Configuring in main.ts
platformBrowserDynamic().bootstrapModule(AppModule, { providers: [ {provide: TRANSLATIONS, useValue: RU_TRANS}, {provide: TRANSLATIONS_FORMAT, useValue: 'xlf'}, {provide: LOCALE_ID, useValue: current_language} ] });
Unfortunately, the internalization described above has a number of pitfalls and limitations due to which it can only be used in projects with the simplest interface:
- when changing the contents of the tag, even those not related to the text being translated, subsequent extraction can change the ID, which in turn leads to compilation errors of the application.
- extraction occurs only from HTML files and is not possible for dynamic content (for example, any lists or dropboxes)
This puts an end to this approach for use in most projects saturated with dynamic content and using interrelated dropboxes.
Work on these issues is happening and perhaps in versions Angular 4 or 5 internationalization will be brought to mind.
Therefore, the only working solution, as before, remains the ng2-translate.
ng2-translate
ngx-translate.comIt is the indirect heir to the well-known angular-translate module.
Also uses the translate filter. In addition, translation texts are stored in JSON files in the same format as in angular-translate.
All this makes it very easy to transfer patterns from ng1 to ng2. In essence, all that is required is to do the following:
Add dependency to the application module in the
src / app / app.module.ts file import { HttpModule, Http } from '@angular/http'; import { TranslateModule, TranslateLoader, TranslateStaticLoader } from 'ng2-translate/ng2-translate'; @NgModule({ ... imports: [ ... HttpModule, TranslateModule.forRoot({ provide: TranslateLoader, // i18n useFactory: (http: Http) => new TranslateStaticLoader(http, '/assets/i18n', '.json'), deps: [Http] }) ], providers: [], bootstrap: [AppComponent] })
The above example of loading dependencies is relevant for
the 5th version of ng2-translate .
The module itself connects JSON files located in the i18n folder. Therefore, manually importing them is not required.
It is also necessary to specify the used language in the root component:
import {TranslateService} from 'ng2-translate'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app works!'; constructor(translate: TranslateService) {
Actually this is all that is needed. The module is ready for operation.The JSON file format is very simple (key: translation):
{ "HELLO": "" }
Further, in HTML, you can respectively use translate in the following forms:
<div>{{'HELLO' | translate}}</div> <div [translate]="'HELLO'" [translateParams]="{value: 'world'}"></div> <div translate [translateParams]="{value: 'world'}">HELLO</div>
You can also use TranslateService in components.
Update (4.3.2017):Literally the day before, the 6th version was released, in which
ng2-translate was renamed to
ngx-translate to comply with the official convention.
In addition,
fundamental changes have occurred . The only TranslateStaticLoader was rendered into a standalone module and renamed to TranslateHttpLoader. Accordingly, the syntax for loading a module in app.module.ts is as follows:
import { HttpModule, Http } from '@angular/http'; import {TranslateModule, TranslateLoader} from "@ngx-translate/core"; // import {TranslateHttpLoader} from "@ngx-translate/http-loader"; // @NgModule({ ... imports: [ ... HttpModule, TranslateModule.forRoot({ provide: TranslateLoader, // i18n useFactory: (http: Http) => new TranslateHttpLoader(http, "i18n/", ".json"), // deps: [Http] }) ], providers: [], bootstrap: [AppComponent] })