Product
Introducing License Enforcement in Socket
Ensure open-source compliance with Socket’s License Enforcement Beta. Set up your License Policy and secure your software!
angular-i18next
Advanced tools
i18next v8.4+ integration with angular v2.0+
Related packages also has implementations for:
1. Install package
npm install i18next --save
npm install angular-i18next --save
2. Import I18NextModule to AppModule
import { I18NextModule } from 'angular-i18next';
@NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent
],
import: [
I18NextModule.forRoot()
]
})
export class AppModule {}
3. Import I18NextModule.forRoot() to AppModule and setup provider with "init" method (use native options). Angular would not load until i18next initialize event fired
export function appInit(i18next: ITranslationService) {
return () => i18next.init({
whitelist: ['en', 'ru'],
fallbackLng: 'en',
debug: true,
returnEmptyString: false,
ns: [
'translation',
'validation',
'error'
],
});
}
export function localeIdFactory(i18next: ITranslationService) {
return i18next.language;
}
export const I18N_PROVIDERS = [
{
provide: APP_INITIALIZER,
useFactory: appInit,
deps: [I18NEXT_SERVICE],
multi: true
},
{
provide: LOCALE_ID,
deps: [I18NEXT_SERVICE],
useFactory: localeIdFactory
}];
@NgModule({
imports: [
...
I18NextModule.forRoot()
],
providers: [
...
I18N_PROVIDERS,
],
bootstrap: [AppComponent]
})
export class AppModule {
}
Use "i18next" pipe to translate key:
<div>{{ 'test' | i18next }}</div>
Passing "t options":
<div>{{ 'test' | i18next: { count: 5, nsSeparator: '#' } }}</div>
Trigger native i18next format method by using I18NextFormatPipe or I18NextPipe with option 'format':
{{ 'any_key' | i18next | i18nextFormat }}
{{ 'any_key' | i18next: { format: 'cap' } }}
{{ 'any_key' | i18nextCap }}
Note: Using "i18nextCap" you will get the same result as i18next: { format: 'cap' }
REMEMBER that format will not work until you set "interpolation.format" function in i18next options.
I18NextModule has static method static interpolationFormat(customFormat: Function = null): Function
that can be used as default interpolation format function (it provides 'upper', 'cap' and 'lower' formatters). You also can pass your custom function to be called after I18NextModule formatters:
const i18nextOptions = {
whitelist: ['en', 'ru'],
ns: [
'translation',
'validation',
'error',
],
interpolation: {
format: I18NextModule.interpolationFormat((value, format, lng) => {
if(value instanceof Date)
return moment(value).format(format);
return value;
});
// format: I18NextModule.interpolationFormat()
}
};
Subscribing to event observables:
this.i18NextService.events.languageChanged.subscribe(lang => {
// do something
})
Add a provider to module/component if you want to prefix child i18next keys:
{
provide: I18NEXT_NAMESPACE,
useValue: 'feature' // set 'feature:' prefix
}
{
provide: I18NEXT_SCOPE,
useValue: 'person' // set 'person.' prefix
}
Since v3.1.0+ it is possible to pass array of namespaces (or scopes). Key would fallback to next namespace in array if the previous failed to resolve.
[feature_validators:key, validators:key]
{
provide: I18NEXT_NAMESPACE,
useValue: ['feature_validators', 'validators']
}
NOTE: Do NOT use default (or custom) i18next delimiters in namespace names.
If you want to turn on document title localization resolve Title as I18NextTitle
imported from 'angular-i18next':
{
provide: Title,
useClass: I18NextTitle
}
Also you can implement your own Title service with specific behavior. Inject I18NextPipe
(or I18NextService
) to service/component:
import { Injectable, Inject } from '@angular/core';
import { Title, DOCUMENT } from '@angular/platform-browser';
import { I18NextPipe } from 'angular-i18next';
@Injectable()
export class I18NextTitle extends Title {
constructor(private i18nextPipe: I18NextPipe, @Inject(DOCUMENT) doc) {
super(doc);
}
setTitle(value: string) {
return super.setTitle(this.translate(value));
}
private translate(text: string) {
return this.i18nextPipe.transform(text, { format: 'cap'});
}
}
Ways to use I18NextService in your code:
Warning: Injection of I18NextService is possible, but it would not consider I18NEXT_NAMESPACE and I18NEXT_SCOPE providers. There are 2 possible reasons to inject I18NextService: initialization and subscription to its events. In all other cases inject I18NextPipe.
export class AppComponent implements OnInit {
constructor(private router: Router,
private title: Title,
@Inject(I18NEXT_SERVICE) private i18NextService: ITranslationService)
export class AppComponent implements OnInit {
constructor(private router: Router,
private title: Title,
private i18NextService: I18NextService)
Error handling is now configurable:
`I18NextModule.forRoot({ errorHandlingStrategy: StrictErrorHandlingStrategy })`
Use I18NEXT_NAMESPACE_RESOLVER in your routes to to load i18next namespace.
Note: It is not neccesary to register lazy loading namespaces in global i18next options.
{
path: 'rich_form',
loadChildren: 'app/features/rich_form_feature/RichFormFeatureModule#RichFormFeatureModule',
data: {
i18nextNamespaces: ['feature.rich_form']
},
resolve: {
i18next: I18NEXT_NAMESPACE_RESOLVER
}
},
Use I18NextService.loadNamespaces() method to load namespaces in code.
import { I18NextModule, ITranslationService, I18NEXT_SERVICE } from 'angular-i18next';
import Backend from 'i18next-xhr-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
// For older i18next plugin versions
// import * as Backend from 'i18next-xhr-backend';
// import * as LanguageDetector from 'i18next-browser-languagedetector';
...
i18next.use(Backend)
.use(LanguageDetector)
.init(i18nextOptions)
Angular would not load until i18next initialize event fired
export function appInit(i18next: ITranslationService) {
return () => i18next.init();
}
export function localeIdFactory(i18next: ITranslationService) {
return i18next.language;
}
export const I18N_PROVIDERS = [
{
provide: APP_INITIALIZER,
useFactory: appInit,
deps: [I18NEXT_SERVICE],
multi: true
},
{
provide: LOCALE_ID,
deps: [I18NEXT_SERVICE],
useFactory: localeIdFactory
}];
export class AppComponent implements OnInit {
constructor(private router: Router,
private title: Title,
@Inject(I18NEXT_SERVICE) private i18NextService: ITranslationService) {
// page title subscription
// https://toddmotto.com/dynamic-page-titles-angular-2-router-events#final-code
this.router.events
.filter(event => event instanceof NavigationEnd)
.map(() => this.router.routerState.root)
.map(route => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter(route => route.outlet === 'primary')
.mergeMap(route => route.data)
.subscribe((event) => this.updatePageTitle(event['title']));
}
ngOnInit() {
this.i18NextService.events.languageChanged.subscribe(lang => {
let root = this.router.routerState.root;
if (root != null && root.firstChild != null) {
let data: any = root.firstChild.data;
this.updatePageTitle(data && data.value && data.value.title);
}
});
}
updatePageTitle(title: string): void {
let newTitle = title || 'application_title';
this.title.setTitle(newTitle);
}
}
Routes example:
const appRoutes: Routes = [
{
path: 'error',
component: AppErrorComponent,
data: { title: 'error:error_occured' }
},
{
path: 'denied',
component: AccessDeniedComponent,
data: { title: 'error:access_denied' }
}
];
List of packages to integrate angular and i18next more deeply:
You might want to unit-test project components that are using i18next pipes
Example tests setup: /tests/projectTests/projectTests.spec.ts
Live DEMO Demo app source code now awailable: https://github.com/Romanchuk/angular-i18next-demo
It's not yet deployed as public web site.
To run:
npm install
npm start
Hey dude! Help me out for a couple of :beers:!
Поддержи проект - угости автора кружечкой пива!
FAQs
i18next module for Angular
The npm package angular-i18next receives a total of 17,641 weekly downloads. As such, angular-i18next popularity was classified as popular.
We found that angular-i18next demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Ensure open-source compliance with Socket’s License Enforcement Beta. Set up your License Policy and secure your software!
Product
We're launching a new set of license analysis and compliance features for analyzing, managing, and complying with licenses across a range of supported languages and ecosystems.
Product
We're excited to introduce Socket Optimize, a powerful CLI command to secure open source dependencies with tested, optimized package overrides.