simply-translate-angular
v0.30.0-pre.2
Published
[Simplest translations](https://www.npmjs.com/package/simply-translate) for Angular _(tested for v10+)_.
Downloads
107
Maintainers
Readme
Simply Translate for Angular
Simplest translations for Angular (tested for v10+).
Breaking changes
(v0.30.0-pre.1)
PRERELEASE: Not stable, may change
- removed
init
method in root import - changed injections: instead of
deps[]
useInjector
as first parameter of provided functions - changed resolver
- standalone ready
- added
EnvironmentProviders
as preferable initialization (provideTranslation
) - changed
translate
directive it is now structural
(v0.20.0)
- see plain JS library changes.
- deprecated
init
method in root import. Instead useaddMiddleware
,loadDictionaries
andfinal
methods instead. lang
andfallbackLang
now in the root import.- added middleware pipeline (see Pipeline).
- removed
$less
property. Instead of$less
useplaceholder = 'single'
. - added
fallback
property to directive. defaultLang
renamed tolang
.extend
inforChild
initialization changed toloadDictionaries
.- added language detection change for directives and pipes
- after initialization
lang
andfallbackLang
can be changed only fromTranslateRootService
. - removed dynamic cache.
Basics
Please use link above to learn more about basic interaction, dictionaries, pluralization, cases, etc.
Install
npm i simply-translate-angular
Initialize
import { provideTranslation, withDictionary } from 'simply-translate-angular';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(),
provideTranslation(
{
lang: 'ru-RU',
fallbackLang: 'ru-RU',
},
withDictionary(({ lang }, inject) => {
const client = inject.get(HttpClient);
return client.get(...).pipe(map((result) => ({[lang]: result})));
})
),
],
};
import { TranslateModule, TranslateService } from 'simply-translate-angular';
@NgModule({
declarations: [AppComponent, AppViewComponent],
imports: [
TranslateModule.forRoot({
// language
lang: window.navigator.language,
fallbackLang: 'ru-RU',
// static dictionaries
dictionaries:{'ru-RU':{...}}
// load dictionaries
loadDictionaries:({lang, fallbackLang}, injector) => {
const client = injector.get(HttpClient);
return client.get(...).pipe(map((result) => ({[lang]: result})));
}
})
]
});
Use Directive
<!-- use default language -->
<h2 *translate="'hello_user'; values:{ user: 'Oleg' }; let result = value;">{{ result }}</h2>
<!-- use other language -->
<h2 *translate="'hello_user'; to:'ru-RU';values:{ user: 'Oleg' }; let result = value">{{ result }}</h2>
<!-- use fallback -->
<h2 *translate="'hello_user_not_there'; values:{ user: 'Oleg' }; fallback:'Hello user'; let result = value">{{ result }}</h2>
Directives will detect dynamic language change by default. Use [detect] property to disable it.
<h2 *translate="'hello_user'; values:{ user: 'Oleg' }; detect:false; let result = value;">{{ result }}</h2>
Directive can use inner text as a fallback.
Use Pipe
<h2>{{ 'hello_user' | translate: { user: 'Oleg' } }}</h2>
<!-- use other language -->
<h2>{{ 'hello_user' | translateTo: 'ru-RU': { user: 'Oleg' } }}</h2>
<!-- use fallback -->
<h2>{{ 'hello_user_not_there' | translate: { user: 'Oleg' } : 'Hello ${user}'}}</h2>
Pipes are pure by default. However if application has dynamic language change you may use special impure directive (it has internal dirty check), it will detect language changes as well as pipe parameters.
<h2>{{ 'hello_user' | translate$: { user: 'Oleg' } }}</h2>
Use Service
@Component({
...
})
export class Component {
hello: string;
constructor(private translate: TranslateService) {
// use default language
this.hello = translate.translate('hello_user', { user: 'Oleg' })
// use other language
this.hello = translate.translateTo('ru-RU','hello_user', { user: 'Oleg' })
// use fallback
this.hello = translate.translateTo('ru-RU','hello_user_not_there', { user: 'Oleg' }, 'Hello ${user}')
}
}
To change language use TranslateRootService
lang
property.
To detect changes subscribe on languageChange$
and dictionaryChange$
. Note that loadDictionaries
method in root settings will not execute when language changes.
export class Component {
constructor(private rootTranslate: TranslateRootService) {
rootTranslate.lang = 'en-US';
}
}
Load dictionaries
You can use loader helper.
function getDictionary(lang: string, client: HttpClient) {
return client.get<Dictionary>(`/assets/translations/${lang}.json`);
}
Provider
You can use withDictionary
feature to fetch dictionaries.
import { provideTranslation, withDictionary } from 'simply-translate-angular';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(),
provideTranslation(
{
lang: 'ru-RU',
fallbackLang: 'en-US',
},
withDictionary(({ langm fallbackLang }, inject) => {
const client = inject.get(HttpClient);
return forkJoin([getDictionary(lang, client), getDictionary(fallbackLang, client)]).pipe(
map(([current, fallback]) => {
return { [lang]: current, [fallbackLang]: fallback };
})
);
})
),
],
};
Or split into two withDictionary
withDictionary(({ fallbackLang }, inject) => {
const client = inject.get(HttpClient);
return getDictionary(fallbackLang, client).pipe(
map((fallback) => {
return { [fallbackLang]: fallback };
})
);
}),
withDictionary(({ lang }, inject) => {
const client = inject.get(HttpClient);
return getDictionary(lang, client).pipe(
map((dictionary) => {
return { [lang]: dictionary };
})
);
}),
forRoot
initialization allows you to fetch dictionaries with its loadDictionaries
field. It returns Observable
that contains set of dictionaries
import { TranslateModule } from 'simply-translate-angular';
@NgModule({
declarations: [...],
imports: [
...
TranslateModule.forRoot({
lang: window.navigator.language,
fallbackLang: 'ru-RU',
loadDictionaries: ({lang, fallbackLang}, injector) => {
const client = injector.get(HttpClient)
const res$ = forkJoin([getDictionary(lang, client), getDictionary(fbLang, client)]).pipe(
map((res) => {
return { [lang]: res[0], fbLang: res[1] };
})
);
return res$;
},
}),
...
],
...
})
Note: it is might be useful to hardcode fallback dictionary in .ts or .json file then import it rather then use http client to download.
import fallback from './translations/fallback';
provideTranslation(
{
lang: 'en-US',
fallbackLang: 'en-US',
},
withDictionary(({ fallbackLang }) => fallback),
withDictionary(/* Regular load*/)
),
TranslateModule.forRoot({
...
fallbackLang: env.fallbackLanguage,
dictionaries: {
[env.fallbackLanguage]: fallback,
},
loadDictionaries: /* Regular load */
...
})
Lazy
Load dictionaries for Lazy modules or components things become a little more complicated. To add synchronous dictionaries it is the same as for Root
import { extendTranslation } from 'simply-translate-angular';
@Component({
standalone: true,
providers:[
...extendTranslation(withDictionaryExtend(({ lang }) => (...)),
],
template: `...`,
})
export class DynamicComponent {
constructor() {}
}
@NgModule({
declarations: [...],
imports: [
TranslateModule.forChild({
deps: [ HttpClient ],
dictionaries: ({ lang }) => (...),
...
})
]
})
export class DynamicModule {}
But to Asynchronously load dictionaries you would need to use translateResolve
.
Do not forget to provide service for lazy routes with extendTranslation
in providers
of route
export const routes: Routes = [
{
path: '...',
loadComponent: () => import('./dynamic/dynamic.component').then((m) => m.DynamicComponent),
resolve: translateResolve(
withDictionary(({ lang }, inject) => {
const client = inject.get(HttpClient);
return getDictionary(lang, client).pipe(
map((current) => {
return { [lang]: current };
})
);
}),
),
providers: [
...extendTranslation()
]
}
For rare cases you may use id
parameter for sub modules or components, that allows having different values with same key.
Unique values will be available only for modules with that special id
and for that special id
.
import { extendTranslation } from 'simply-translate-angular';
@Component({
standalone: true,
providers: [...extendTranslation(withIdentifier('my unique id'))],
template: `...`,
})
export class DynamicComponent {
constructor() {}
}
@NgModule({
declarations: [...],
imports: [
TranslateModule.forChild({
id: 'my unique id'
dictionaries: ({ lang }) => ({[lang]:{
'key':'Value for Lazy'
}})
})
]
})
Pipeline
Currently it is possible to append middleware to the end of translation pipeline.
It might be specially useful to add logger or rarely fine-tune translation result.
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(),
provideTranslation(...,
withMiddleware(()=>
(injector) => {
const logger = injector.get(Logger)
return [
({params, result}) => {
if (result.fallingBack) {
logger.log(`Translation absent [${params.lang}:${params.key}]`);
}
},
];
},
)
),
],
};
@NgModule({
declarations: [...],
imports: [
...
TranslateModule.forRoot({
addMiddleware: (injector) => {
const logger = injector.get(Logger);
return [
({params, result}) => {
if (result.fallingBack) {
logger.log(`Translation absent [${params.lang}:${params.key}]`);
}
},
];
},
}),
...
],
...
})