1 | # ng2-translate [![Build Status](https://travis-ci.org/ocombe/ng2-translate.svg?branch=master)](https://travis-ci.org/ocombe/ng2-translate) [![npm version](https://img.shields.io/npm/v/ng2-translate.svg)](https://www.npmjs.com/package/ng2-translate)
|
2 |
|
3 | An implementation of angular translate for Angular 2.
|
4 |
|
5 | Simple example using ng2-translate: http://plnkr.co/edit/btpW3l0jr5beJVjohy1Q?p=preview
|
6 |
|
7 | Get the complete changelog here: https://github.com/ocombe/ng2-translate/releases
|
8 |
|
9 | * [Installation](#installation)
|
10 | * [Usage](#usage)
|
11 | * [API](#api)
|
12 | * [FAQ](#faq)
|
13 | * [Plugins](#plugins)
|
14 | * [Additional Framework Support](#additional-framework-support)
|
15 |
|
16 |
|
17 | ## Installation
|
18 |
|
19 | First you need to install the npm module:
|
20 |
|
21 | ```sh
|
22 | npm install ng2-translate --save
|
23 | ```
|
24 |
|
25 | **If you use SystemJS** to load your files, you can check the [plunkr example](http://plnkr.co/edit/btpW3l0jr5beJVjohy1Q?p=preview) for a working setup that uses the cdn [https://unpkg.com/](https://unpkg.com/).
|
26 | If you're importing directly from `node_modules`, you should edit your systemjs config file and add `'ng2-translate': 'node_modules/ng2-translate/bundles'` in the map and `'ng2-translate' : { defaultExtension: 'js' }` in packages.
|
27 |
|
28 |
|
29 | ## Usage
|
30 |
|
31 | #### 1. Import the `TranslateModule`:
|
32 |
|
33 | Finally, you can use ng2-translate in your Angular 2 project.It is recommended to import `TranslateModule.forRoot()` in the NgModule of your application.
|
34 |
|
35 | The [`forRoot`](https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root) static method is a convention that provides and configures services at the same time. Make sure you only call this method at the root module of your application, most of the time called `AppModule`. This method allows you to configure the `TranslateModule` loader. By default it will use the `TranslateStaticLoader`, but you can provide another loader instead as a parameter of this method (see below [Write & use your own loader](#write--use-your-own-loader)).
|
36 |
|
37 | For now ng2-translate requires HttpModule from `@angular/http` (this will change soon).
|
38 |
|
39 | ```ts
|
40 | import {BrowserModule} from '@angular/platform-browser';
|
41 | import {NgModule} from '@angular/core';
|
42 | import {HttpModule} from '@angular/http';
|
43 | import {TranslateModule} from 'ng2-translate';
|
44 |
|
45 | @NgModule({
|
46 | imports: [
|
47 | BrowserModule,
|
48 | HttpModule,
|
49 | TranslateModule.forRoot()
|
50 | ],
|
51 | bootstrap: [AppComponent]
|
52 | })
|
53 | export class AppModule { }
|
54 | ```
|
55 |
|
56 | ##### SharedModule
|
57 |
|
58 | If you use a [`SharedModule`](https://angular.io/docs/ts/latest/guide/ngmodule.html#!#shared-modules) that you import in multiple other feature modules, you can easily export the `TranslateModule` to make sure you don't have to import it in every module.
|
59 |
|
60 | ```ts
|
61 | @NgModule({
|
62 | exports: [
|
63 | CommonModule,
|
64 | TranslateModule
|
65 | ]
|
66 | })
|
67 | export class SharedModule { }
|
68 | ```
|
69 |
|
70 | > Note: Never call a `forRoot` static method in the `SharedModule`. You will end up with multiple different instances of a service in your injector tree.
|
71 |
|
72 | ##### Configuration
|
73 |
|
74 | By default, only the `TranslateStaticLoader` is available. It will search for files in `i18n/*.json`, if you want you can customize this behavior by changing the default prefix/suffix:
|
75 |
|
76 | ```ts
|
77 | @NgModule({
|
78 | imports: [
|
79 | BrowserModule,
|
80 | HttpModule,
|
81 | TranslateModule.forRoot({
|
82 | provide: TranslateLoader,
|
83 | useFactory: (http: Http) => new TranslateStaticLoader(http, '/assets/i18n', '.json'),
|
84 | deps: [Http]
|
85 | })
|
86 | ],
|
87 | bootstrap: [AppComponent]
|
88 | })
|
89 | export class AppModule { }
|
90 | ```
|
91 |
|
92 | ##### AoT
|
93 |
|
94 | If you want to configure a custom `TranslateLoader` while using [AoT compilation](https://angular.io/docs/ts/latest/cookbook/aot-compiler.html) or [Ionic 2](http://ionic.io/), you must use an exported function instead of an inline function.
|
95 |
|
96 | ```ts
|
97 | export function createTranslateLoader(http: Http) {
|
98 | return new TranslateStaticLoader(http, './assets/i18n', '.json');
|
99 | }
|
100 |
|
101 | @NgModule({
|
102 | imports: [
|
103 | BrowserModule,
|
104 | HttpModule,
|
105 | TranslateModule.forRoot({
|
106 | provide: TranslateLoader,
|
107 | useFactory: (createTranslateLoader),
|
108 | deps: [Http]
|
109 | })
|
110 | ],
|
111 | bootstrap: [AppComponent]
|
112 | })
|
113 | export class AppModule { }
|
114 | ```
|
115 |
|
116 | #### 2. Init the `TranslateService` for your application:
|
117 |
|
118 | ```ts
|
119 | import {Component} from '@angular/core';
|
120 | import {TranslateService} from 'ng2-translate';
|
121 |
|
122 | @Component({
|
123 | selector: 'app',
|
124 | template: `
|
125 | <div>{{ 'HELLO' | translate:param }}</div>
|
126 | `
|
127 | })
|
128 | export class AppComponent {
|
129 | param = {value: 'world'};
|
130 |
|
131 | constructor(translate: TranslateService) {
|
132 | // this language will be used as a fallback when a translation isn't found in the current language
|
133 | translate.setDefaultLang('en');
|
134 |
|
135 | // the lang to use, if the lang isn't available, it will use the current loader to get them
|
136 | translate.use('en');
|
137 | }
|
138 | }
|
139 | ```
|
140 |
|
141 | #### 3. Define the translations:
|
142 |
|
143 | Once you've imported the `TranslateModule`, you can put your translations in a json file that will be imported with the `TranslateStaticLoader`. The following translations should be stored in `en.json`.
|
144 |
|
145 | ```json
|
146 | {
|
147 | "HELLO": "hello {{value}}"
|
148 | }
|
149 | ```
|
150 |
|
151 | You can also define your translations manually with `setTranslation`.
|
152 |
|
153 | ```ts
|
154 | translate.setTranslation('en', {
|
155 | HELLO: 'hello {{value}}'
|
156 | });
|
157 | ```
|
158 |
|
159 | The `TranslateParser` understands nested JSON objects. This means that you can have a translation that looks like this:
|
160 |
|
161 | ```json
|
162 | {
|
163 | "HOME": {
|
164 | "HELLO": "hello {{value}}"
|
165 | }
|
166 | }
|
167 | ```
|
168 |
|
169 | You can then access the value by using the dot notation, in this case `HOME.HELLO`.
|
170 |
|
171 | #### 4. Use the service, the pipe or the directive:
|
172 |
|
173 | You can either use the `TranslateService`, the `TranslatePipe` or the `TranslateDirective` to get your translation values.
|
174 |
|
175 | With the **service**, it looks like this:
|
176 |
|
177 | ```ts
|
178 | translate.get('HELLO', {value: 'world'}).subscribe((res: string) => {
|
179 | console.log(res);
|
180 | //=> 'hello world'
|
181 | });
|
182 | ```
|
183 |
|
184 | This is how you do it with the **pipe**:
|
185 |
|
186 | ```html
|
187 | <div>{{ 'HELLO' | translate:param }}</div>
|
188 | ```
|
189 |
|
190 | And in your component define `param` like this:
|
191 | ```ts
|
192 | param = {value: 'world'};
|
193 | ```
|
194 |
|
195 | This is how you use the **directive**:
|
196 | ```html
|
197 | <div [translate]="'HELLO'" [translateParams]="{value: 'world'}"></div>
|
198 | ```
|
199 |
|
200 | Or even simpler using the content of your element as a key:
|
201 | ```html
|
202 | <div translate [translateParams]="{value: 'world'}">HELLO</div>
|
203 | ```
|
204 |
|
205 | #### 5. Use HTML tags:
|
206 |
|
207 | You can easily use raw HTML tags within your translations.
|
208 |
|
209 | ```json
|
210 | {
|
211 | "HELLO": "Welcome to my Angular application!<br><strong>This is an amazing app which uses the latest technologies!</strong>"
|
212 | }
|
213 | ```
|
214 |
|
215 | To render them, simply use the `innerHTML` attribute with the pipe on any element.
|
216 |
|
217 | ```html
|
218 | <div [innerHTML]="'HELLO' | translate"></div>
|
219 | ```
|
220 |
|
221 | ## API
|
222 |
|
223 | ### TranslateService
|
224 |
|
225 | #### Properties:
|
226 |
|
227 | - `currentLang`: The lang currently used
|
228 | - `currentLoader`: An instance of the loader currently used (static loader by default)
|
229 | - `onLangChange`: An EventEmitter to listen to lang change events. A `LangChangeEvent` is an object with the properties `lang: string` & `translations: any` (an object containing your translations).
|
230 |
|
231 | example:
|
232 | ```ts
|
233 | onLangChange.subscribe((event: LangChangeEvent) => {
|
234 | // do something
|
235 | });
|
236 | ```
|
237 | - `onTranslationChange`: An EventEmitter to listen to translation change events. A `TranslationChangeEvent` is an object with the properties `lang: string` & `translations: any` (an object containing your translations).
|
238 |
|
239 | example:
|
240 | ```ts
|
241 | onTranslationChange.subscribe((event: TranslationChangeEvent) => {
|
242 | // do something
|
243 | });
|
244 | ```
|
245 | - `onDefaultLangChange`: An EventEmitter to listen to default lang change events. A `DefaultLangChangeEvent` is an object with the properties `lang: string` & `translations: any` (an object containing your translations).
|
246 |
|
247 | example:
|
248 | ```ts
|
249 | onDefaultLangChange.subscribe((event: DefaultLangChangeEvent) => {
|
250 | // do something
|
251 | });
|
252 | ```
|
253 |
|
254 | #### Methods:
|
255 |
|
256 | - `setDefaultLang(lang: string)`: Sets the default language to use as a fallback
|
257 | - `getDefaultLang(): string`: Gets the default language
|
258 | - `use(lang: string): Observable<any>`: Changes the lang currently used
|
259 | - `getTranslation(lang: string): Observable<any>`: Gets an object of translations for a given language with the current loader
|
260 | - `setTranslation(lang: string, translations: Object, shouldMerge: boolean = false)`: Manually sets an object of translations for a given language, set `shouldMerge` to true if you want to append the translations instead of replacing them
|
261 | - `addLangs(langs: Array<string>)`: Add new langs to the list
|
262 | - `getLangs()`: Returns an array of currently available langs
|
263 | - `get(key: string|Array<string>, interpolateParams?: Object): Observable<string|Object>`: Gets the translated value of a key (or an array of keys) or the key if the value was not found
|
264 | - `instant(key: string|Array<string>, interpolateParams?: Object): string|Object`: Gets the instant translated value of a key (or an array of keys). /!\ This method is **synchronous** and the default file loader is asynchronous. You are responsible for knowing when your translations have been loaded and it is safe to use this method. If you are not sure then you should use the `get` method instead.
|
265 | - `set(key: string, value: string, lang?: string)`: Sets the translated value of a key
|
266 | - `reloadLang(lang: string): Observable<string|Object>`: Calls resetLang and retrieves the translations object for the current loader
|
267 | - `resetLang(lang: string)`: Removes the current translations for this lang. /!\ You will have to call `use`, `reloadLang` or `getTranslation` again to be able to get translations
|
268 | - `getBrowserLang(): string | undefined`: Returns the current browser lang if available, or undefined otherwise
|
269 | - `getBrowserCultureLang(): string | undefined`: Returns the current browser culture language name (e.g. "de-DE" if available, or undefined otherwise
|
270 |
|
271 | #### Write & use your own loader
|
272 |
|
273 | If you want to write your own loader, you need to create a class that implements `TranslateLoader`. The only required method is `getTranslation` that must return an `Observable`. If your loader is synchronous, just use [`Observable.of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md) to create an observable from your static value.
|
274 |
|
275 | ##### Example
|
276 |
|
277 | ```ts
|
278 | class CustomLoader implements TranslateLoader {
|
279 | getTranslation(lang: string): Observable<any> {
|
280 | return Observable.of({KEY: 'value'});
|
281 | }
|
282 | }
|
283 | ```
|
284 |
|
285 | Once you've defined your loader, you can provide it in your configuration by adding it to its `providers` property.
|
286 |
|
287 | ```ts
|
288 | @NgModule({
|
289 | imports: [
|
290 | BrowserModule,
|
291 | TranslateModule.forRoot({
|
292 | provide: TranslateLoader,
|
293 | useClass: CustomLoader
|
294 | })
|
295 | ],
|
296 | bootstrap: [AppComponent]
|
297 | })
|
298 | export class AppModule { }
|
299 | ```
|
300 |
|
301 | #### How to handle missing translations
|
302 |
|
303 | You can setup a provider for the `MissingTranslationHandler` in the bootstrap of your application (recommended), or in the `providers` property of a component. It will be called when the requested translation is not available. The only required method is `handle` where you can do whatever you want. If this method returns a value or an observable (that should return a string), then this will be used. Just don't forget that it will be called synchronously from the `instant` method.
|
304 |
|
305 | ##### Example:
|
306 |
|
307 | Create a Missing Translation Handler
|
308 |
|
309 | ```ts
|
310 | import {MissingTranslationHandler, MissingTranslationHandlerParams} from 'ng2-translate';
|
311 |
|
312 | export class MyMissingTranslationHandler implements MissingTranslationHandler {
|
313 | handle(params: MissingTranslationHandlerParams) {
|
314 | return 'some value';
|
315 | }
|
316 | }
|
317 | ```
|
318 |
|
319 | Setup the Missing Translation Handler in your module by adding it to the `providers` list.
|
320 |
|
321 | ```ts
|
322 | @NgModule({
|
323 | imports: [
|
324 | BrowserModule,
|
325 | TranslateModule.forRoot()
|
326 | ],
|
327 | providers: [
|
328 | { provide: MissingTranslationHandler, useClass: MyMissingTranslationHandler }
|
329 | ],
|
330 | bootstrap: [AppComponent]
|
331 | })
|
332 | export class AppModule { }
|
333 | ```
|
334 |
|
335 | ### Parser
|
336 |
|
337 | If you need it for some reason, you can use the `TranslateParser` service.
|
338 |
|
339 | #### Methods:
|
340 | - `interpolate(expr: string, params?: any): string`: Interpolates a string to replace parameters.
|
341 |
|
342 | `This is a {{ key }}` ==> `This is a value` with `params = { key: "value" }`
|
343 | - `getValue(target: any, key: stirng): any`: Gets a value from an object by composed key
|
344 | `parser.getValue({ key1: { keyA: 'valueI' }}, 'key1.keyA') ==> 'valueI'`
|
345 |
|
346 | ## FAQ
|
347 |
|
348 | #### I'm getting an error `No provider for Http!`
|
349 |
|
350 | Because of the TranslateStaticLoader you have to load the HttpModule from `@angular/http`, even if you don't use this Loader
|
351 |
|
352 | #### I'm still using RC4, but I cannot use ng2-translate because I get errors?!
|
353 |
|
354 | If you're still using RC4, you should fix the version of ng2-translate to 2.2.2.
|
355 |
|
356 | #### I'm getting an error `npm ERR! peerinvalid Peer [...]`
|
357 |
|
358 | If you're using npm 2.x, upgrade to npm 3.x, because npm 2 doesn't handle peer dependencies well. With npm 2 you could only use fixed versions, but with npm 3 you can use `^` to use a newer version if available.
|
359 |
|
360 | If you're already on npm 3, check if it's an error (`npm ERR!`) or a warning (`npm WARN!`), warning are just informative and if everything works then don't worry !
|
361 |
|
362 | If you're using an old version of angular 2 and ng2-translate wants a newer version then you should consider upgrading your application to use the newer angular 2 version. I cannot support old versions because the framework keeps doing breaking changes... If it's not an option for you, then check [the changelog](/releases) to know which version is the last compatible version.
|
363 |
|
364 | #### I'm using Ionic 2 and ng2-translate doesn't work
|
365 |
|
366 | Ionic 2 is still using angular 2 RC4, but ng2-translate uses RC5. You should fix the version of ng2-translate to 2.2.2 until Ionic 2 upgrades to RC5.
|
367 |
|
368 |
|
369 | ## Plugins
|
370 | - [Localize Router](https://github.com/Greentube/localize-router) by @meeroslav: An implementation of routes localization for Angular 2. If you need localized urls (for example /fr/page and /en/page).
|
371 | - [.po files Loader](https://www.npmjs.com/package/@biesbjerg/ng2-translate-po-loader) by @biesbjerg: Use .po translation files with ng2-translate
|
372 | - [ng2-translate-extract](https://www.npmjs.com/package/@biesbjerg/ng2-translate-extract) by @biesbjerg: Extract translatable strings from your projects
|
373 |
|
374 | ## Additional Framework Support
|
375 |
|
376 | * [Use with NativeScript](https://github.com/NathanWalker/nativescript-ng2-translate/issues/5#issuecomment-257606661)
|