simply-translate-angular v0.30.0-pre.2
Simply Translate for Angular
Simplest translations for Angular (tested for v10+).
Breaking changes
(v0.30.0-pre.1)
PRERELEASE: Not stable, may change
- removed
initmethod in root import - changed injections: instead of
deps[]useInjectoras first parameter of provided functions - changed resolver
- standalone ready
- added
EnvironmentProvidersas preferable initialization (provideTranslation) - changed
translatedirective it is now structural
(v0.20.0)
- see plain JS library changes.
- deprecated
initmethod in root import. Instead useaddMiddleware,loadDictionariesandfinalmethods instead. langandfallbackLangnow in the root import.- added middleware pipeline (see Pipeline).
- removed
$lessproperty. Instead of$lessuseplaceholder = 'single'. - added
fallbackproperty to directive. defaultLangrenamed tolang.extendinforChildinitialization changed toloadDictionaries.- added language detection change for directives and pipes
- after initialization
langandfallbackLangcan 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-angularInitialize
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}]`);
}
},
];
},
)
),
],
};2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago