+
\ No newline at end of file
diff --git a/public/docs/_examples/i18n/ts/app/app.component.ts b/public/docs/_examples/i18n/ts/app/app.component.ts
new file mode 100644
index 0000000000..76c99e60c7
--- /dev/null
+++ b/public/docs/_examples/i18n/ts/app/app.component.ts
@@ -0,0 +1,10 @@
+// #docregion
+import { Component } from '@angular/core';
+
+@Component({
+ moduleId: module.id,
+ selector: 'my-app',
+ templateUrl: './app.component.html'
+})
+export class AppComponent { }
+
diff --git a/public/docs/_examples/i18n/ts/app/app.module.ts b/public/docs/_examples/i18n/ts/app/app.module.ts
new file mode 100644
index 0000000000..a8b40a7650
--- /dev/null
+++ b/public/docs/_examples/i18n/ts/app/app.module.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [ BrowserModule ],
+ declarations: [ AppComponent ],
+ bootstrap: [ AppComponent ]
+})
+
+export class AppModule { }
diff --git a/public/docs/_examples/i18n/ts/app/main.1.ts b/public/docs/_examples/i18n/ts/app/main.1.ts
new file mode 100644
index 0000000000..e11324f519
--- /dev/null
+++ b/public/docs/_examples/i18n/ts/app/main.1.ts
@@ -0,0 +1,7 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app.module';
+
+const platform = platformBrowserDynamic();
+platform.bootstrapModule(AppModule);
diff --git a/public/docs/_examples/i18n/ts/app/main.ts b/public/docs/_examples/i18n/ts/app/main.ts
new file mode 100644
index 0000000000..76801570b0
--- /dev/null
+++ b/public/docs/_examples/i18n/ts/app/main.ts
@@ -0,0 +1,19 @@
+// #docregion
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID } from '@angular/core';
+
+import { AppModule } from './app.module';
+import { TRANSLATION } from './messages.fr';
+
+// Compile using french translations
+const platform = platformBrowserDynamic();
+platform.bootstrapModule(
+ AppModule,
+ {
+ providers: [
+ {provide: TRANSLATIONS, useValue: TRANSLATION},
+ {provide: TRANSLATIONS_FORMAT, useValue: 'xlf'},
+ {provide: LOCALE_ID, useValue: 'fr'}
+ ]
+ }
+);
diff --git a/public/docs/_examples/i18n/ts/app/messages.fr.1.ts b/public/docs/_examples/i18n/ts/app/messages.fr.1.ts
new file mode 100644
index 0000000000..5f78563420
--- /dev/null
+++ b/public/docs/_examples/i18n/ts/app/messages.fr.1.ts
@@ -0,0 +1,5 @@
+// #docregion
+export const TRANSLATION = `
+
+`;
+
diff --git a/public/docs/_examples/i18n/ts/app/messages.fr.ts b/public/docs/_examples/i18n/ts/app/messages.fr.ts
new file mode 100644
index 0000000000..c01e1c02bd
--- /dev/null
+++ b/public/docs/_examples/i18n/ts/app/messages.fr.ts
@@ -0,0 +1,17 @@
+// #docregion
+export const TRANSLATION = `
+
+
+
+
+
+ Hello i18n!
+ Bonjour i18n!
+ An introduction header for this sample
+ User welcome
+
+
+
+
+`;
+
diff --git a/public/docs/_examples/i18n/ts/example-config.json b/public/docs/_examples/i18n/ts/example-config.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/public/docs/_examples/i18n/ts/index.html b/public/docs/_examples/i18n/ts/index.html
new file mode 100644
index 0000000000..685110c5d1
--- /dev/null
+++ b/public/docs/_examples/i18n/ts/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+ Angular i18n example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
diff --git a/public/docs/_examples/i18n/ts/messages.fr.xlf b/public/docs/_examples/i18n/ts/messages.fr.xlf
new file mode 100644
index 0000000000..f6b0094bd9
--- /dev/null
+++ b/public/docs/_examples/i18n/ts/messages.fr.xlf
@@ -0,0 +1,13 @@
+
+
+
+
+
+ Hello i18n!
+
+ An introduction header for this sample
+ User welcome
+
+
+
+
\ No newline at end of file
diff --git a/public/docs/_examples/i18n/ts/messages.fr.xlf.ts b/public/docs/_examples/i18n/ts/messages.fr.xlf.ts
new file mode 100644
index 0000000000..a8b3923dc8
--- /dev/null
+++ b/public/docs/_examples/i18n/ts/messages.fr.xlf.ts
@@ -0,0 +1,15 @@
+/* tslint:disable */
+// #docregion
+
+
+
+
+
+ Hello i18n!
+
+ An introduction header for this sample
+ User welcome
+
+
+
+
\ No newline at end of file
diff --git a/public/docs/_examples/i18n/ts/plnkr.json b/public/docs/_examples/i18n/ts/plnkr.json
new file mode 100644
index 0000000000..9886709b1e
--- /dev/null
+++ b/public/docs/_examples/i18n/ts/plnkr.json
@@ -0,0 +1,10 @@
+{
+ "description": "i18n",
+ "files": [
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!**/*.[1].*",
+ "!**/*.metadata.json"
+ ],
+ "tags": ["i18n"]
+}
\ No newline at end of file
diff --git a/public/docs/_examples/package.json b/public/docs/_examples/package.json
index 7baee8a5a9..693ce2a99d 100644
--- a/public/docs/_examples/package.json
+++ b/public/docs/_examples/package.json
@@ -20,7 +20,8 @@
"test:webpack": "karma start karma.webpack.conf.js",
"build:webpack": "rimraf dist && webpack --config config/webpack.prod.js --bail",
"build:cli": "ng build",
- "build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup.js"
+ "build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup.js",
+ "extract": "ng-xi18n"
},
"keywords": [],
"author": "",
diff --git a/public/docs/dart/latest/guide/i18n.jade b/public/docs/dart/latest/guide/i18n.jade
new file mode 100644
index 0000000000..6778b6af28
--- /dev/null
+++ b/public/docs/dart/latest/guide/i18n.jade
@@ -0,0 +1 @@
+!= partial("../../../_includes/_ts-temp")
diff --git a/public/docs/js/latest/guide/i18n.jade b/public/docs/js/latest/guide/i18n.jade
new file mode 100644
index 0000000000..6778b6af28
--- /dev/null
+++ b/public/docs/js/latest/guide/i18n.jade
@@ -0,0 +1 @@
+!= partial("../../../_includes/_ts-temp")
diff --git a/public/docs/ts/latest/guide/_data.json b/public/docs/ts/latest/guide/_data.json
index 2bd99c1ca6..0ccac518fe 100644
--- a/public/docs/ts/latest/guide/_data.json
+++ b/public/docs/ts/latest/guide/_data.json
@@ -105,6 +105,11 @@
"intro": "Talk to a remote server with an HTTP Client."
},
+ "i18n": {
+ "title": "Internationalization",
+ "intro": "Translate your application into multiple languages"
+ },
+
"lifecycle-hooks": {
"title": "Lifecycle Hooks",
"intro": "Angular calls lifecycle hook methods on directives and components as it creates, changes, and destroys them."
diff --git a/public/docs/ts/latest/guide/i18n.jade b/public/docs/ts/latest/guide/i18n.jade
new file mode 100644
index 0000000000..8d69c169fd
--- /dev/null
+++ b/public/docs/ts/latest/guide/i18n.jade
@@ -0,0 +1,262 @@
+include ../_util-fns
+
+:marked
+ With internationalization, also known as i18n, we can display our website in multiple languages.
+ Angular provides tools to export translation files that translators can work on.
+ Those finished translations can then be merged with your application to make it
+ available to multiple audiences.
+
+
+ ## Table of contents
+
+ * [Angular and i18n](#angular-i18n)
+ * [The i18n attribute](#the-i18n-attribute)
+ * [Extract messages with ng-xi18n](#ng-xi18n)
+ * [Translate messages](#translate)
+ * [Merging translations](#merging-translations)
+ * [JiT configuration](#jit-configuration)
+ * [AoT configuration](#aot-configuration)
+
+:marked
+ **Try it out**. Here's a link to a of the JiT application.
+
+
+a(id="angular-i18n")
+.l-main-section
+:marked
+ ## Angular and i18n
+
+ Angular allows us to replace text in our application with the translation of our choice.
+
+ We would usually start with a working application that already has text in a single language.
+ We then extract from our app a translation file that translators can open on their translation software to work on the translation.
+ Finally we use their translation on our app to override the original text.
+
+ We can then build the application for each language we need, and deploy each translated application separately.
+
+
+a(id="the-i18n-attribute")
+.l-main-section
+:marked
+ ### i18n attribute
+
+ The `i18n` attribute is a market for translatable content.
+
+ We'll start with a simple greeting in a `
` tag:
+
++makeExample('i18n/ts/app/app.component.1.html', 'greeting', 'app/app.component.html')(format=".")
+
+:marked
+ We simply add the attribute `i18n` to our tag to mark it as a translation point.
+
++makeExample('i18n/ts/app/app.component.1.html', 'i18n-attribute', 'app/app.component.html')(format=".")
+
+:marked
+ To help the translators, we can add more information about the meaning and context of this string.
+ Simply add a description to the i18n attribute:
+
++makeExample('i18n/ts/app/app.component.1.html', 'i18n-attribute-desc', 'app/app.component.html')(format=".")
+
+:marked
+ We can add some meaning as well, separate the meaning from the description with the `|` character:
+
++makeExample('i18n/ts/app/app.component.html', 'i18n-attribute-meaning', 'app/app.component.html')(format=".")
+
+:marked
+ While the same text with the same meaning should have the same translation,
+ the same text with *different meanings* can have different translations.
+ Both the meaning and the description will be extracted by our messages extractor and added to the messages file.
+
+ This will help our translators to translate our application with a better understanding of what our text means.
+
+
+a(id="ng-xi18n")
+.l-main-section
+:marked
+ ### Extract messages with ng-xi18n
+
+ Now that our template has been updated to support i18n translations, we can use the `ng-xi18n` messages extractor.
+
+ This CLI tool is based on `ngc` and is available in the `@angular/compiler-cli` npm package.
+ You can read more about `ngc` on the [AoT cookbook](../cookbook/aot-compiler.html).
+
+ To use it, the first thing that we have to do is to install it and it's `platform-server` peer dependency:
+
+code-example(language="sh" class="code-shell").
+ npm install @angular/compiler-cli @angular/platform-server --save
+
+:marked
+ Like `ngc`, `ng-xi18n` is based on `tsc`, the TypeScript compiler.
+ We can use it to generate our transfile file at the root of our project:
+
+code-example(language="sh" class="code-shell").
+ ./node_modules/.bin/ng-xi18n
+
+:marked
+ The translation file is generated by default in the format `XML Localisation Interchange File Format` (XLIFF, version 1.2).
+
+ `ng-x18n` and Angular also supports the `XML Message Bundle`(XMB) format. We can switch to this
+ format by adding the `--i18nFormat=xmb` to our command.
+
+.alert.is-helpful
+ :marked
+ It is considered good practice to create a new npm command that will be used to run `ng-xi18n`.
+
+ Edit `package.json` and add the following command in the `scripts` property: `"extract": "ng-xi18n"`.
+ We can now generate our translations using the command `npm run extract`.
+
+
+a(id="translate")
+.l-main-section
+:marked
+ ### Translate le message
+
+ Now that we have generated a `./messages.xlf` file we could edit it, or send it to
+ translators to edit, using one of the many editors that support `xlf`.
+ You can find a list of editors [here](https://en.wikipedia.org/wiki/XLIFF#Editors).
+
+ For the sake of simplicity, we will make our French translation by editing the translation file manually in our text editor.
+
+ Make a copy of `messages.xlf` called `messages.fr.xlf`, open it and find the following section:
+
+ ```
+
+ Hello i18n!
+
+ An introduction header for this sample
+ User welcome
+
+ ```
+
+ This XML element represents the translation of our header tag.
+ You might have a different string in `id="af2ccf4b5dba59616e92cf1531505af02da8f6d2"`, this is normal.
+ It depends on the content of the message and it's meaning, so if you change either it will also change.
+
+ Replace `` with `Bonjour i18n!` to add our French translation.
+ That's all for our french translation!
+
+.alert.is-helpful
+ :marked
+ Whenever we add new messages - or edit existing ones - in our application, we have to repeat this process.
+
+ Using specialized translation software can help us find out easily what new translations have been generated by
+ the messages extractor.
+
+
+a(id="merging-translations")
+.l-main-section
+:marked
+ ## Merging translations
+
+ Now that we have a localized file, we can tell Angular to use it for all of our elements that have the `i18n` marker.
+
+ Angular understands `xlf`, `xlif` and `xtb` formats, but we have to provide these messages into our application.
+
+ However, our paths diverge depending on whether we use JiT or AoT:
+
+ * if we are using Just-in-Time compilation, we must incorporate our translation file content into
+ our application code at bootstrap time.
+ * if we are using Ahead-in-Time compilation, we can include our translation file via `ngc` options.
+
+ In both approaches the general idea is the same. we have to give angular these three things:
+ * Translations file
+ * Translation file format
+ * Locale ID (`en-US` for instance)
+
+ Our untranslated app now looks like this:
+
++makeTabs(`
+ i18n/ts/app/app.component.html,
+ i18n/ts/app/app.component.ts,
+ i18n/ts/app/app.module.ts,
+ i18n/ts/app/main.1.ts,
+ i18n/ts/messages.fr.xlf.ts
+`, '', `
+ app/app.component.html,
+ app/app.component.ts,
+ app/app.module.ts,
+ app/main.ts,
+ messages.fr.xlf
+`)
+
+a(id="jit-configuration")
+.l-main-section
+:marked
+ ### Merge translations with the JiT approach
+
+ When we use JiT, we'll provide those three things when bootstrapping out `AppModule`.
+
+ We have to provide three values: `TRANSLATIONS`, `TRANSLATIONS_FORMAT` and `LOCALE_ID`.
+ * `TRANSLATIONS` is a string containing the content of our `messages` file for the chosen locale.
+ * `TRANSLATIONS_FORMAT` is either `xlf`, `xlif` or `xtb` depending on the format of our `messages` file.
+ * `LOCALE_ID` is a string representing the locale of our chosen language.
+
+ Starting out with our default `main.ts`:
+
++makeExample('i18n/ts/app/main.1.ts', null, 'app/main.ts')(format=".")
+
+:marked
+ We'll import `TRANSLATIONS`, `TRANSLATIONS_FORMAT` and `LOCALE_ID` from `@angular/core`, then
+ use them to provide our own values in the `providers` array:
+
++makeExample('i18n/ts/app/main.ts', null, 'app/main.ts')(format=".")
+
+:marked
+ But... We don't have a `./messages.fr.ts` file yet.
+
+ Since TypeScript is unable to import an `xlf` file, we have to create a `.ts` file that exports the content of our
+ `messages.fr.xlf` file.
+
+ Create `app/messages.fr.ts`. We just want to export a string, so we'll start out with a very
+ simple file exporting an empty template literal:
+
++makeExample('i18n/ts/app/messages.fr.1.ts', null, 'app/messages.fr.ts')(format=".")
+
+:marked
+ Now copy the contents of `message.fr.xlf` into the empty template literal:
+
++makeExample('i18n/ts/app/messages.fr.ts', null, 'app/messages.fr.ts')(format=".")
+
+.alert.is-helpful
+ :marked
+ If you use Webpack you can use the [raw loader](https://github.com/webpack/raw-loader) to import your translations
+ file directly like this: `const TRANSLATION = require("raw!./i18n/messages.fr.xlf");`
+
+:marked
+ That's it, our application is now internationalized! Angular will replace the content of our elements using
+ the `i18n` attribute with the french translations that we provided at bootstrap.
+
+ Your JiT app should now look just like the app at the end of [Merging translations](#merging-translations)
+ except for these two files:
+
++makeTabs(`
+ i18n/ts/app/main.ts,
+ i18n/ts/app/messages.fr.ts
+ `, '', `
+ app/main.ts,
+ app/messages.fr.ts
+ `)
+
+a(id="aot-configuration")
+.l-main-section
+:marked
+ ### Merge translations with the AoT approach
+
+ Using the AoT approach requires a little bit of setup to make the `ngc` compiler work. Start with
+ the files shown at the end of [Merging translations](#merging-translations) and refer to the
+ [AoT cookbook](../cookbook/aot-compiler.html) to make it AoT ready.
+
+ Once our project is AoT-ready, we will use `ngc` to compile a version of our application per locale. To do that
+ we will add three arguments to the cli command:
+ * `--i18nFile`: the path to our localization file
+ * `--locale`: the name of the locale
+ * `--i18nFormat`: the format of our localization file
+
+code-example(language="sh" class="code-shell").
+ ./node_modules/.bin/ngc --i18nFile=./messages.fr.xlf --locale=fr --i18nFormat=xlf
+
+:marked
+ That's all that we have to do! The `ngc` compiler will replace the content of our elements that have
+ the i18n attribute with our translations in the AoT generated templates.
+
+