From be994496cdf90ed29ef76153b6d39bbe12e12fb2 Mon Sep 17 00:00:00 2001 From: Olivier Combe Date: Tue, 4 Jul 2017 17:07:11 +0200 Subject: [PATCH] docs(core): add docs for i18n tokens (#17920) PR Close #17920 --- .../i18n/doc-files/app.locale_data.ts | 3 +- .../i18n/doc-files/app.locale_data_extra.ts | 6 +- aio/content/guide/i18n.md | 82 +++++++++++++------ packages/core/src/i18n/tokens.ts | 74 +++++++++++++++++ 4 files changed, 134 insertions(+), 31 deletions(-) diff --git a/aio/content/examples/i18n/doc-files/app.locale_data.ts b/aio/content/examples/i18n/doc-files/app.locale_data.ts index b7d637489f..05c83be034 100644 --- a/aio/content/examples/i18n/doc-files/app.locale_data.ts +++ b/aio/content/examples/i18n/doc-files/app.locale_data.ts @@ -2,5 +2,6 @@ import { registerLocaleData } from '@angular/common'; import localeFr from '@angular/common/locales/fr'; -registerLocaleData(localeFr); +// the second parameter 'fr' is optional +registerLocaleData(localeFr, 'fr'); // #enddocregion import-locale diff --git a/aio/content/examples/i18n/doc-files/app.locale_data_extra.ts b/aio/content/examples/i18n/doc-files/app.locale_data_extra.ts index 69e637d6a7..05b7b80d53 100644 --- a/aio/content/examples/i18n/doc-files/app.locale_data_extra.ts +++ b/aio/content/examples/i18n/doc-files/app.locale_data_extra.ts @@ -1,7 +1,7 @@ // #docregion import-locale-extra import { registerLocaleData } from '@angular/common'; -import localeFrCa from '@angular/common/locales/fr-CA'; -import localeFrCaExtra from '@angular/common/locales/extra/fr-CA'; +import localeFr from '@angular/common/locales/fr'; +import localeFrExtra from '@angular/common/locales/extra/fr'; -registerLocaleData(localeFrCa, localeFrCaExtra); +registerLocaleData(localeFr, 'fr-FR', localeFrExtra); // #enddocregion import-locale-extra diff --git a/aio/content/guide/i18n.md b/aio/content/guide/i18n.md index d046aec5c6..aea41cff3f 100644 --- a/aio/content/guide/i18n.md +++ b/aio/content/guide/i18n.md @@ -8,7 +8,6 @@ See the i18n Example for a an AOT-compiled app, translated into French. {@a angular-i18n} - ## Angular and i18n Angular simplifies the following aspects of internationalization: @@ -62,6 +61,23 @@ For more information about Unicode locale identifiers, see the For a complete list of locales supported by Angular, see [the Angular repository](https://github.com/angular/angular/tree/master/packages/common/locales). +The locale identifiers used by CLDR and Angular are based on [BCP47](http://www.rfc-editor.org/rfc/bcp/bcp47.txt). +These specifications change over time; the following table maps previous identifiers to current ones at +time of writing: + +| Locale name | Old locale id | New locale id | +|-------------------------------|-------------------|---------------| +| Indonesian | in | id | +| Hebrew | iw | he | +| Romanian Moldova | mo | ro-MD | +| Norwegian Bokmål | no, no-NO | nb | +| Serbian Latin | sh | sr-Latn | +| Filipino | tl | fil | +| Portuguese Brazil | pt-BR | pt | +| Chinese Simplified | zh-cn, zh-Hans-CN | zh-Hans | +| Chinese Traditional | zh-tw, zh-Hant-TW | zh-Hant | +| Chinese Traditional Hong Kong | zh-hk | zh-Hant-HK | + ## i18n pipes @@ -78,6 +94,14 @@ If you want to import locale data for other languages, you can do it manually: +The first parameter is an object containing the locale data imported from `@angular/common/locales`. +By default, the imported locale data is registered with the locale id that is defined in the Angular +locale data itself. +If you want to register the imported locale data with another locale id, use the second parameter to +specify a custom locale id. For example, Angular's locale data defines the locale id for French as +"fr". You can use the second parameter to associate the imported French locale data with the custom +locale id "fr-FR instead of "fr". + The files in `@angular/common/locales` contain most of the locale data that you need, but some advanced formatting options might only be available in the extra dataset that you can import from `@angular/common/locales/extra`. An error message informs you when this is the case. @@ -118,7 +142,6 @@ in the target language. You need to build and deploy a separate version of the app for each supported language. {@a i18n-attribute} - ### Mark text with the i18n attribute The Angular `i18n` attribute marks translatable content. Place it on every element tag whose fixed @@ -144,7 +167,6 @@ To mark the greeting for translation, add the `i18n` attribute to the `

` tag {@a help-translator} - ### Help the translator with a description and meaning To translate a text message accurately, the translator may need additional information or context. @@ -175,7 +197,6 @@ text messages with different descriptions (not different meanings), then they ar {@a custom-id} - ### Set a custom id for persistence and maintenance The angular i18n extractor tool generates a file with a translation unit entry for each `i18n` @@ -250,7 +271,6 @@ the same text, `Bonjour`: {@a no-element} - ### Translate text without creating an element If there is a section of text that you would like to translate, you can wrap it in a `` tag. @@ -262,7 +282,6 @@ The `` is transformed into an html comment: {@a translate-attributes} - ## Add i18n translation attributes You also can translate attributes. @@ -286,7 +305,6 @@ You also can assign a meaning, description, and id with the `i18n-x="|< syntax. {@a plural-ICU} - ## Translate singular and plural Different languages have different pluralization rules. @@ -342,7 +360,6 @@ for two, three, or any other number if the pluralization rules were different. F {@a select-ICU} - ## Select among alternative text messages If your template needs to display different text messages depending on the value of a variable, you @@ -360,7 +377,6 @@ The message maps those values to the appropriate translations: {@a nesting-ICUS} - ## Nesting plural and select ICU expressions You can also nest different ICU expressions together, as shown in this example: @@ -369,7 +385,6 @@ You can also nest different ICU expressions together, as shown in this example: {@a ng-xi18n} - ## Create a translation source file with _ng xi18n_ Use the `ng xi18n` command provided by the CLI to extract the text messages marked with `i18n` into @@ -394,7 +409,6 @@ package, or you can manually use the CLI Webpack plugin `ExtractI18nPlugin` from {@a other-formats} - ### Other translation formats Angular i18n tooling supports three translation formats: @@ -422,7 +436,6 @@ The sample in this guide uses the default XLIFF 1.2 format. {@a ng-xi18n-options} - ### Other options You can specify the output path used by the CLI to extract your translation source file with @@ -456,7 +469,6 @@ file. This information is not used by Angular, but external translation tools ma {@a translate} - ## Translate text messages The `ng xi18n` command generates a translation source file named `messages.xlf` in the project `src` @@ -466,7 +478,6 @@ The next step is to translate this source file into the specific language translation files. The example in this guide creates a French translation file. {@a localization-folder} - ### Create a localization folder Most apps are translated into more than one other language. For this reason, it is standard practice @@ -500,7 +511,6 @@ For this example: If you were translating to other languages, you would repeat these steps for each target language. {@a translate-text-nodes} - ### Translate text nodes In a large translation project, you would send the `messages.fr.xlf` file to a French translator who @@ -544,7 +554,6 @@ This sample file is easy to translate without a special editor or knowledge of F {@a translate-plural-select} - ## Translate plural and select expressions _Plural_ and _select_ ICU expressions are extracted separately, so they require special attention @@ -555,7 +564,6 @@ elsewhere in the source template. In this example, you know the translation unit must be just below the translation unit for the logo. {@a translate-plural} - ### Translate _plural_ To translate a `plural`, translate its ICU format match values: @@ -567,7 +575,6 @@ You can add or remove plural cases, with each language having its own cardinalit [CLDR plural rules](http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html).) {@a translate-select} - ### Translate _select_ Below is the content of our example `select` ICU expression in the component template: @@ -598,7 +605,6 @@ Here they are together, after translation: {@a translate-nested} - ### Translate a nested expression A nested expression is similar to the previous examples. As in the previous example, there are @@ -621,7 +627,6 @@ The entire template translation is complete. The next section describes how to l into the app. {@a app-pre-translation} - ### The app and its translation file The sample app and its translation file are now as follows: @@ -640,7 +645,6 @@ The sample app and its translation file are now as follows: {@a merge} - ## Merge the completed translation file into the app To merge the translated text into component templates, compile the app with the completed @@ -656,12 +660,11 @@ format that Angular understands, such as `.xtb`. How you provide this information depends upon whether you compile with the JIT compiler or the AOT compiler. - * With [AOT](guide/i18n#aot), you pass the information as a CLI parameter. - * With [JIT](guide/i18n#jit), you provide the information at bootstrap time. + * With [AOT](guide/i18n#merge-aot), you pass the information as a CLI parameter. + * With [JIT](guide/i18n#merge-jit), you provide the information at bootstrap time. -{@a aot} - +{@a merge-aot} ### Merge with the AOT compiler The AOT (_Ahead-of-Time_) compiler is part of a build process that produces a small, fast, @@ -685,8 +688,7 @@ guide: ng serve --aot --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr -{@a jit} - +{@a merge-jit} ### Merge with the JIT compiler The JIT compiler compiles the app in the browser as the app loads. @@ -713,3 +715,29 @@ Then provide the `LOCALE_ID` in the main module: + + +{@a missing-translation} +### Report missing translations +By default, when a translation is missing, the build succeeds but generates a warning such as +`Missing translation for message "foo"`. You can configure the level of warning that is generated by +the Angular compiler: + +* Error: throw an error. If you are using AOT compilation, the build will fail. If you are using JIT +compilation, the app will fail to load. +* Warning (default): show a 'Missing translation' warning in the console or shell. +* Ignore: do nothing. + +If you use the AOT compiler, specify the warning level by using the CLI parameter +`--missingTranslation`. The example below shows how to set the warning level to error: + + + ng serve --aot --missingTranslation=error + + +If you use the JIT compiler, specify the warning level in the compiler config at bootstrap by adding +the 'MissingTranslationStrategy' property. The example below shows how to set the warning level to +error: + + + diff --git a/packages/core/src/i18n/tokens.ts b/packages/core/src/i18n/tokens.ts index da156b7fef..7bbec4939d 100644 --- a/packages/core/src/i18n/tokens.ts +++ b/packages/core/src/i18n/tokens.ts @@ -9,21 +9,95 @@ import {InjectionToken} from '../di/injection_token'; /** + * Provide this token to set the locale of your application. + * It is used for i18n extraction, by i18n pipes (DatePipe, I18nPluralPipe, CurrencyPipe, + * DecimalPipe and PercentPipe) and by ICU expressions. + * + * See the {@linkDocs guide/i18n#setting-up-locale i18n guide} for more information. + * + * ### Example + * + * ```typescript + * import { LOCALE_ID } from '@angular/core'; + * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + * import { AppModule } from './app/app.module'; + * + * platformBrowserDynamic().bootstrapModule(AppModule, { + * providers: [{provide: LOCALE_ID, useValue: 'en-US' }] + * }); + * ``` + * * @experimental i18n support is experimental. */ export const LOCALE_ID = new InjectionToken('LocaleId'); /** + * Use this token at bootstrap to provide the content of your translation file (`xtb`, + * `xlf` or `xlf2`) when you want to translate your application in another language. + * + * See the {@linkDocs guide/i18n#merge i18n guide} for more information. + * + * ### Example + * + * ```typescript + * import { TRANSLATIONS } from '@angular/core'; + * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + * import { AppModule } from './app/app.module'; + * + * // content of your translation file + * const translations = '....'; + * + * platformBrowserDynamic().bootstrapModule(AppModule, { + * providers: [{provide: TRANSLATIONS, useValue: translations }] + * }); + * ``` + * * @experimental i18n support is experimental. */ export const TRANSLATIONS = new InjectionToken('Translations'); /** + * Provide this token at bootstrap to set the format of your {@link TRANSLATIONS}: `xtb`, + * `xlf` or `xlf2`. + * + * See the {@linkDocs guide/i18n#merge i18n guide} for more information. + * + * ### Example + * + * ```typescript + * import { TRANSLATIONS_FORMAT } from '@angular/core'; + * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + * import { AppModule } from './app/app.module'; + * + * platformBrowserDynamic().bootstrapModule(AppModule, { + * providers: [{provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }] + * }); + * ``` + * * @experimental i18n support is experimental. */ export const TRANSLATIONS_FORMAT = new InjectionToken('TranslationsFormat'); /** + * Use this enum at bootstrap as an option of `bootstrapModule` to define the strategy + * that the compiler should use in case of missing translations: + * - Error: throw if you have missing translations. + * - Warning (default): show a warning in the console and/or shell. + * - Ignore: do nothing. + * + * See the {@linkDocs guide/i18n#missing-translation i18n guide} for more information. + * + * ### Example + * ```typescript + * import { MissingTranslationStrategy } from '@angular/core'; + * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + * import { AppModule } from './app/app.module'; + * + * platformBrowserDynamic().bootstrapModule(AppModule, { + * missingTranslation: MissingTranslationStrategy.Error + * }); + * ``` + * * @experimental i18n support is experimental. */ export enum MissingTranslationStrategy {