npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

simply-translate-angular

v0.30.0-pre.2

Published

[Simplest translations](https://www.npmjs.com/package/simply-translate) for Angular _(tested for v10+)_.

Downloads

118

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[] use Injector 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 use addMiddleware, loadDictionaries and final methods instead.
  • lang and fallbackLang now in the root import.
  • added middleware pipeline (see Pipeline).
  • removed $less property. Instead of $less use placeholder = 'single'.
  • added fallback property to directive.
  • defaultLang renamed to lang.
  • extend in forChild initialization changed to loadDictionaries.
  • added language detection change for directives and pipes
  • after initialization lang and fallbackLang can be changed only from TranslateRootService.
  • 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})));
      }
    })
  ]
});

See Load dictionaries

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}]`);
            }
          },
        ];
      },
    }),
    ...
  ],
  ...
})