{"id":13481611,"url":"https://github.com/robisim74/angular-l10n","last_synced_at":"2025-05-16T04:03:12.870Z","repository":{"id":53083292,"uuid":"41914426","full_name":"robisim74/angular-l10n","owner":"robisim74","description":"Angular library to translate texts, dates and numbers","archived":false,"fork":false,"pushed_at":"2025-04-16T07:28:20.000Z","size":12264,"stargazers_count":381,"open_issues_count":0,"forks_count":56,"subscribers_count":26,"default_branch":"master","last_synced_at":"2025-04-16T09:56:55.634Z","etag":null,"topics":["angular","localization","translate","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robisim74.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2015-09-04T12:25:25.000Z","updated_at":"2025-04-16T07:28:25.000Z","dependencies_parsed_at":"2024-01-04T22:29:49.943Z","dependency_job_id":"ded68099-1436-415a-bb76-9f6a4fb961d5","html_url":"https://github.com/robisim74/angular-l10n","commit_stats":{"total_commits":673,"total_committers":16,"mean_commits":42.0625,"dds":0.04160475482912329,"last_synced_commit":"c70c4c9cd5f563338888f423c548c5738cbf2616"},"previous_names":["robisim74/angular2localization"],"tags_count":116,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robisim74%2Fangular-l10n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robisim74%2Fangular-l10n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robisim74%2Fangular-l10n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robisim74%2Fangular-l10n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robisim74","download_url":"https://codeload.github.com/robisim74/angular-l10n/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254464891,"owners_count":22075570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","localization","translate","typescript"],"created_at":"2024-07-31T17:00:53.327Z","updated_at":"2025-05-16T04:03:12.792Z","avatar_url":"https://github.com/robisim74.png","language":"TypeScript","funding_links":[],"categories":["Awesome Angular [![Awesome TipeIO](https://img.shields.io/badge/Awesome%20Angular-@TipeIO-6C6AE7.svg)](https://github.com/gdi2290/awesome-angular) [![Awesome devarchy.com](https://img.shields.io/badge/Awesome%20Angular-@devarchy.com-86BDC1.svg)](https://github.com/brillout/awesome-angular-components)","Development Utilities","UI","Uncategorized"],"sub_categories":["Angular \u003ca id=\"angular\"\u003e\u003c/a\u003e","Internationalization","Localization","Uncategorized"],"readme":"# Angular l10n\n![Node.js CI](https://github.com/robisim74/angular-l10n/workflows/Node.js%20CI/badge.svg) [![npm version](https://badge.fury.io/js/angular-l10n.svg)](https://badge.fury.io/js/angular-l10n) [![npm](https://img.shields.io/npm/dm/angular-l10n.svg)](https://www.npmjs.com/package/angular-l10n) [![npm](https://img.shields.io/npm/l/angular-l10n.svg)](https://www.npmjs.com/package/angular-l10n)\n\u003e Angular library to translate texts, dates and numbers\n\nThis library is for localization of **Angular** apps. It allows, in addition to translation, to format dates and numbers through [Internationalization API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)\n\n\n## Table of Contents\n- [Installation](#installation)\n- [Usage](#usage)\n- [Lazy loading](#lazy-loading)\n- [Localized routing](#localized-routing)\n- [Server Side Rendering](#server-side-rendering)\n- [Types](#types)\n- [Contributing](#contributing)\n- [Versions](./versions.md)\n\n\n## Installation\n```Shell\nnpm install angular-l10n --save \n```\n\n\n## Usage\n- Sample [standalone app](projects/angular-l10n-app)\n- Sample [SSR app](projects/angular-l10n-ssr)\n- Live example on [StackBlitz](https://stackblitz.com/edit/angular-l10n)\n\n### Configuration\nCreate the configuration:\n\n_src/app/l10n-config.ts_\n```TypeScript\nexport const l10nConfig: L10nConfig = {\n  format: 'language-region',\n  providers: [\n    { name: 'app', asset: 'app' }\n  ],\n  cache: true,\n  keySeparator: '.',\n  defaultLocale: { language: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles' },\n  schema: [\n    { locale: { language: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles' } },\n    { locale: { language: 'it-IT', currency: 'EUR', timeZone: 'Europe/Rome' } }\n  ]\n};\n\n@Injectable() export class TranslationLoader implements L10nTranslationLoader {\n  public get(language: string, provider: L10nProvider): Observable\u003c{ [key: string]: any }\u003e {\n    /**\n     * Translation files are lazy-loaded via dynamic import and will be split into separate chunks during build.\n     * Assets names and keys must be valid variable names\n     */\n    const data = import(`../i18n/${language}/${provider.asset}.json`);\n    return from(data);\n  }\n}\n```\nThe implementation of `L10nTranslationLoader` class-interface above creates a js chunk for each translation file in the `src/i18n/[language]/[asset].json` folder during the build:\n\n_src/i18n/en-US/app.json_\n```Json\n{\n  \"home\": {\n    \"greeting\": \"Hello world!\",\n    \"whoIAm\": \"I am {{name}}\",\n    \"devs\": {\n      \"one\": \"One software developer\",\n      \"other\": \"{{value}} software developers\"\n    }\n  }\n}\n```\n\n\u003e Note. The implementation above of `L10nTranslationLoader` is just an example: you can load the translation data in the way you prefer.\n\nRegister the configuration:\n\n_src/app/app.config.ts_\n```TypeScript\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideL10nTranslation(\n      l10nConfig,\n      {\n        translationLoader: TranslationLoader\n      }\n    ),\n    provideL10nIntl()\n  ]\n};\n```\nor with modules:\n\n_src/app/app.module.ts_\n```TypeScript\n@NgModule({\n  imports: [\n    L10nTranslationModule.forRoot(\n      l10nConfig,\n      {\n        translationLoader: TranslationLoader\n      }\n    ),\n    L10nIntlModule\n  ]\n})\nexport class AppModule { }\n```\n\n### Getting the translation\n#### Pure Pipes\n```Html\n\u003c!-- translate pipe --\u003e\n\u003cp\u003e{{ 'home.greeting' | translate:locale.language }}\u003c/p\u003e\n\u003c!-- Hello world! --\u003e\n\n\u003c!-- translate pipe with params --\u003e\n\u003cp\u003e{{ 'home.whoIAm' | translate:locale.language:{ name: 'Angular l10n' } }}\u003c/p\u003e\n\u003c!-- I am Angular l10n --\u003e\n\n\u003c!-- l10nPlural pipe --\u003e\n\u003cp\u003e{{ 2 | l10nPlural:locale.language:'home.devs' }}\u003c/p\u003e\n\u003c!-- 2 software developers --\u003e\n\n\u003c!-- l10nDate pipe --\u003e\n\u003cp\u003e{{ today | l10nDate:locale.language:{ dateStyle: 'full', timeStyle: 'short' } }}\u003c/p\u003e\n\u003c!-- Friday, May 12, 2023 at 1:59 PM --\u003e\n\n\u003c!-- l10nTimeAgo pipe --\u003e\n\u003cp\u003e{{ -1 | l10nTimeAgo:locale.language:'second':{ numeric:'always', style:'long' } }}\u003c/p\u003e\n\u003c!-- 1 second ago --\u003e\n\n\u003c!-- l10nNumber pipe --\u003e\n\u003cp\u003e{{ 1000 | l10nNumber:locale.language:{ digits: '1.2-2', style: 'currency' } }}\u003c/p\u003e\n\u003c!-- $1,000.00 --\u003e\n\n\u003c!-- l10nDisplayNames pipe --\u003e\n\u003cp\u003e{{ 'en-US' | l10nDisplayNames:locale.language:{ type: 'language' } }}\u003c/p\u003e\n\u003c!-- American English --\u003e\n```\nPure pipes need to know when the _locale_ changes. So import `L10nLocale` injection token in every component that uses them:\n```TypeScript\n@Component({\n  standalone: true,\n  imports: [\n    L10nTranslatePipe\n  ]\n})\nexport class PipeComponent {\n  locale = inject(L10N_LOCALE);\n}\n```\nor with modules:\n```TypeScript\nexport class PipeComponent {\n    locale = inject(L10N_LOCALE);\n}\n```\n\n#### OnPush Change Detection Strategy\nTo support this strategy, there is an `Async` version of each pipe, which recognizes by itself when the _locale_ changes:\n```Html\n\u003cp\u003e{{ 'greeting' | translateAsync }}\u003c/p\u003e\n```\n\n#### Directives\n\u003e Directives manipulate the DOM\n```Html\n\u003c!-- l10nTranslate directive --\u003e\n\u003cp l10nTranslate\u003ehome.greeting\u003c/p\u003e\n\n\u003c!-- l10nTranslate directive with attributes --\u003e\n\u003cp l10n-title title=\"greeting\" l10nTranslate\u003ehome.greeting\u003c/p\u003e\n\n\u003c!-- l10nTranslate directive with params --\u003e\n\u003cp [params]=\"{ name: 'Angular l10n' }\" l10nTranslate\u003ehome.whoIAm\u003c/p\u003e\n\n\u003c!-- l10nPlural directive --\u003e\n\u003cp prefix=\"devs\" l10nPlural\u003e2\u003c/p\u003e\n```\n\n#### APIs\n`L10nTranslationService` provides:\n\n- `setLocale(locale: L10nLocale): Promise\u003cvoid\u003e` Changes the current locale and load the translation data\n- `onChange(): Observable\u003cL10nLocale\u003e` Fired every time the translation data has been loaded. Returns the locale\n- `onError(): Observable\u003cany\u003e` Fired when the translation data could not been loaded. Returns the error\n- `translate(keys: string | string[], params?: any, language?: string): string | any` Translates a key or an array of keys\n\n### Changing the locale\nYou can change the _locale_ at runtime at any time by calling the `setLocale` method of `L10nTranslationService`:\n```Html\n\u003cbutton *ngFor=\"let item of schema\" (click)=\"setLocale(item.locale)\"\u003e\n  {{ item.locale.language | l10nDisplayNames:locale.language:{ type: 'language' } }}\n\u003c/button\u003e\n```\n\n```TypeScript\nexport class AppComponent {\n\n  schema = this.config.schema;\n\n  constructor(\n    @Inject(L10N_LOCALE) public locale: L10nLocale,\n    @Inject(L10N_CONFIG) private config: L10nConfig,\n    private translation: L10nTranslationService\n  ) { }\n\n  setLocale(locale: L10nLocale): void {\n    this.translation.setLocale(locale);\n  }\n}\n```\n\n### Class-interfaces\nThe following features can be customized. You just have to implement the indicated class-interface and pass the token during configuration.\n\n#### Translation Loader\nBy default, you can only pass JavaScript objects as translation data provider. To implement a different loader, you can implement the `L10nTranslationLoader` class-interface, as in the example above.\n```TypeScript\nexport declare abstract class L10nTranslationLoader {\n  /**\n    * This method must contain the logic to get translation data.\n    * @param language The current language\n    * @param provider The provider of the translations data\n    * @return An object of translation data for the language: {key: value}\n    */\n  abstract get(language: string, provider: L10nProvider): Observable\u003c{\n      [key: string]: any;\n  }\u003e;\n}\n```\n\n#### Locale resolver\nBy default, the library attempts to set the _locale_ using the user's browser language, before falling back to the _default locale_. You can change this behavior by implementing the `L10nLocaleResolver` class-interface, for example to get the language from the URL.\n```TypeScript\nexport declare abstract class L10nLocaleResolver {\n  /**\n   * This method must contain the logic to get the locale.\n   * @return The locale\n   */\n  abstract get(): Promise\u003cL10nLocale | null\u003e;\n}\n```\n\n#### Storage\nBy default, the library does not store the _locale_. To store it implement the `L10nStorage` class-interface using what you need, such as web storage or cookie, so that the next time the user has the _locale_ he selected.\n```TypeScript\nexport declare abstract class L10nStorage {\n  /**\n   * This method must contain the logic to read the storage.\n   * @return A promise with the value of the locale\n   */\n  abstract read(): Promise\u003cL10nLocale | null\u003e;\n  /**\n   * This method must contain the logic to write the storage.\n   * @param locale The current locale\n   */\n  abstract write(locale: L10nLocale): Promise\u003cvoid\u003e;\n}\n```\n\n#### Missing Translation Handler\nIf a key is not found, the same key is returned. To return a different value, you can implement the `L10nMissingTranslationHandler` class-interface.\n```TypeScript\nexport declare abstract class L10nMissingTranslationHandler {\n  /**\n   * This method must contain the logic to handle missing values.\n   * @param key The key that has been requested\n   * @param value Null or empty string\n   * @param params Optional parameters contained in the key\n   * @return The value\n   */\n  abstract handle(key: string, value?: string, params?: any): string | any;\n}\n```\n\n#### Translation fallback\nIf you enable translation fallback in configuration, the translation data will be merged in the following order:\n- `'language'`\n- `'language[-script]'`\n- `'language[-script][-region]'`\n\nTo change it, implement the `L10nTranslationFallback` class-interface.\n```TypeScript\nexport declare abstract class L10nTranslationFallback {\n  /**\n   * This method must contain the logic to get the ordered loaders.\n   * @param language The current language\n   * @param provider The provider of the translations data\n   * @return An array of loaders\n   */\n  abstract get(language: string, provider: L10nProvider): Observable\u003cany\u003e[];\n}\n```\nE.g.:\n```TypeScript\n@Injectable() export class TranslationFallback implements L10nTranslationFallback {\n\n  constructor(\n    @Inject(L10N_CONFIG) private config: L10nConfig,\n    private cache: L10nCache,\n    private translationLoader: L10nTranslationLoader\n  ) { }\n\n  public get(language: string, provider: L10nProvider): Observable\u003cany\u003e[] {\n    const loaders: Observable\u003cany\u003e[] = [];\n    // Fallback current lang to en\n    const languages = ['en', language];\n    for (const lang of languages) {\n        if (this.config.cache) {\n            loaders.push(\n                this.cache.read(`${provider.name}-${lang}`,\n                    this.translationLoader.get(lang, provider))\n            );\n        } else {\n            loaders.push(this.translationLoader.get(lang, provider));\n        }\n    }\n    return loaders;\n  }\n}\n```\n\n#### Loader\nIf you need to preload some data before initialization of the library, you can implement the `L10nLoader` class-interface.\n```TypeScript\nexport declare abstract class L10nTranslationLoader {\n  /**\n   * This method must contain the logic to get translation data.\n   * @param language The current language\n   * @param provider The provider of the translations data\n   * @return An object of translation data for the language: {key: value}\n   */\n  abstract get(language: string, provider: L10nProvider): Observable\u003c{[key: string]: any;}\u003e;\n}\n```\nE.g.:\n```TypeScript\n@Injectable() export class AppLoader implements L10nLoader {\n  constructor(private translation: L10nTranslationService) { }\n\n  public async init(): Promise\u003cvoid\u003e {\n      await ... // Some custom data loading action\n      await this.translation.init();\n  }\n}\n```\n\n#### Validation\nThere are two directives, that you can use with Template driven or Reactive forms: `l10nValidateNumber` and `l10nValidateDate`. To use them, you have to implement the `L10nValidation` class-interface, and import it with the `L10nValidationModule` module.\n```TypeScript\nexport declare abstract class L10nValidation {\n  /**\n   * This method must contain the logic to convert a string to a number.\n   * @param value The string to be parsed\n   * @param options A L10n or Intl NumberFormatOptions object\n   * @param language The current language\n   * @return The parsed number\n   */\n  abstract parseNumber(value: string, options?: L10nNumberFormatOptions, language?: string): number | null;\n  /**\n   * This method must contain the logic to convert a string to a date.\n   * @param value The string to be parsed\n   * @param options A L10n or Intl DateTimeFormatOptions object\n   * @param language The current language\n   * @return The parsed date\n   */\n  abstract parseDate(value: string, options?: L10nDateTimeFormatOptions, language?: string): Date | null;\n}\n```\n\n## Lazy loading\nIf you want to add new providers to a lazy loaded component or module, you can use `resolveL10n` function in your routes:\n```TypeScript\nconst routes: Routes = [\n  {\n    path: 'lazy',\n    loadComponent: () =\u003e import('./lazy/lazy.component').then(m =\u003e m.LazyComponent),\n    resolve: { l10n: resolveL10n },\n    data: {\n      l10nProviders: [{ name: 'lazy', asset: 'lazy' }]\n    }\n  }\n];\n```\nOr to lazy load a module:\n```TypeScript\nconst routes: Routes = [\n  {\n    path: 'lazy',\n    loadChildren: () =\u003e import('./lazy/lazy.module').then(m =\u003e m.LazyModule),\n    resolve: { l10n: resolveL10n },\n    data: {\n      l10nProviders: [{ name: 'lazy', asset: 'lazy' }]\n    }\n  }\n];\n```\nand import the modules you need:\n```TypeScript\n@NgModule({\n  declarations: [LazyComponent],\n  imports: [\n      L10nTranslationModule\n  ]\n})\nexport class LazyModule { }\n```\n\n\n## Localized routing\nLet's assume that we want to create a navigation of this type:\n- default language (en-US): routes not localized `http://localhost:4200/home`\n- other languages (it-IT): localized routes `http://localhost:4200/it-IT/home`\n\nIn `routes` root level add `:lang` param to create `localizedRoutes`:\n```TypeScript\nconst routes: Routes = [\n  { path: 'home', component: HomeComponent },\n  {\n    path: 'lazy',\n    loadChildren: () =\u003e import('./lazy/lazy.module').then(m =\u003e m.LazyModule),\n    resolve: { l10n: resolveL10n },\n    data: {\n      l10nProviders: [{ name: 'lazy', asset: 'lazy' }]\n    }\n  }\n];\n\nexport const localizedRoutes: Routes = [\n  { path: '', redirectTo: 'home', pathMatch: 'full' },\n  ...routes,\n  {\n    path: ':lang', // prepend [lang] to all routes\n    children: routes\n  },\n  { path: '**', redirectTo: 'home' }\n];\n```\nand provide it to the router.\n\nNow let's implement the `L10nLocaleResolver` class-interface to get the language from the URL:\n\n_src/app/l10n-config.ts_\n```TypeScript\n@Injectable() export class LocaleResolver implements L10nLocaleResolver {\n\n  constructor(@Inject(L10N_CONFIG) private config: L10nConfig, private location: Location) { }\n\n  public async get(): Promise\u003cL10nLocale | null\u003e {\n    const path = this.location.path();\n\n    for (const schema of this.config.schema) {\n      const language = schema.locale.language;\n      if (new RegExp(`(\\/${language}\\/)|(\\/${language}$)|(\\/(${language})(?=\\\\?))`).test(path)) {\n        return Promise.resolve(schema.locale);\n      }\n    }\n    return Promise.resolve(null);\n  }\n}\n```\nand add it to configuration using `provideL10nTranslation` or `L10nTranslationModule` with modules.\n\nWhen the app starts, the library will call the `get` method of `LocaleResolver` and use the locale of the URL or the default locale.\n\n\u003e Do not implement storage when using the localized router, because the language of the URL may be inconsistent with the saved one\n\nTo change language at runtime, we can't use the `setLocale` method, but we have to navigate to the localized URL without reloading the page. We replace the `setLocale` method with the new `navigateByLocale` and we add `pathLang` to router links:\n```Html\n\u003ca routerLink=\"{{pathLang}}/home\"\u003eHome\u003c/a\u003e\n\u003ca routerLink=\"{{pathLang}}/lazy\"\u003eLazy\u003c/a\u003e\n\n\u003cbutton *ngFor=\"let item of schema\" (click)=\"navigateByLocale(item.locale)\"\u003e\n  {{ item.locale.language | l10nDisplayNames:locale.language:{ type: 'language' } }}\n\u003c/button\u003e\n```\n\n```TypeScript\nexport class AppComponent implements OnInit {\n\n  /**\n   * Handle page back/forward\n   */\n  @HostListener('window:popstate', ['$event'])\n  onPopState() {\n    this.translation.init();\n  }\n\n  schema = this.config.schema;\n\n  pathLang = this.getPathLang();\n\n  constructor(\n    @Inject(L10N_LOCALE) public locale: L10nLocale,\n    @Inject(L10N_CONFIG) private config: L10nConfig,\n    private translation: L10nTranslationService,\n    private location: Location,\n    private router: Router\n  ) { }\n\n  ngOnInit() {\n    // Update path language\n    this.translation.onChange().subscribe({\n      next: () =\u003e {\n        this.pathLang = this.getPathLang();\n      }\n    });\n  }\n\n  /**\n   * Replace the locale and navigate to the new URL\n   */\n  navigateByLocale(locale: L10nLocale) {\n    let path = this.location.path();\n    if (this.locale.language !== this.config.defaultLocale.language) {\n      if (locale.language !== this.config.defaultLocale.language) {\n        path = path.replace(`/${this.locale.language}`, `/${locale.language}`);\n      } else {\n        path = path.replace(`/${this.locale.language}`, '');\n      }\n    } else if (locale.language !== this.config.defaultLocale.language) {\n      path = `/${locale.language}${path}`;\n    }\n\n    this.router.navigate([path]).then(() =\u003e {\n      this.translation.init();\n    });\n  }\n\n  getPathLang() {\n    return this.locale.language !== this.config.defaultLocale.language ?\n      this.locale.language :\n      '';\n  }\n}\n```\nHere we are doing three things:\n- we update `pathLang` provided to router links every time the locale changes\n- we implement `navigateByLocale` method, which takes care of replacing the language and navigating to the new URL\n- we handle page back/forward events\n\n\n## Server Side Rendering\nYou can find a complete sample app [here](projects/angular-l10n-ssr)\n\nWhat is important to know:\n- `DirectiveComponent` has `ngSkipHydration` enabled because directives manipolate the DOM\n- `prerender` is enabled in `angular.json`\n- `routes.tsx` file contains localized routes (to prerender pages in different languages)\n\n## Types\nAngular l10n types that it is useful to know:\n- `L10nConfig` Contains:\n    - `format` Format of the translation language. Pattern: `language[-script][-region]`\n    - `providers` The providers of the translations data\n    - `keySeparator` Sets key separator\n    - `defaultLocale` Defines the default locale to be used\n    - `schema` Provides the schema of the supported locales\n     \n    Optionally:\n    - `fallback` Translation fallback\n    - `cache` Caching for providers\n\n- `L10nLocale` Contains a `language`, in the format `language[-script][-region][-extension]`, where:\n    - `language` ISO 639 two-letter or three-letter code\n    - `script` ISO 15924 four-letter script code\n    - `region` ISO 3166 two-letter, uppercase code\n    - `extension` 'u' (Unicode) extensions\n     \n    Optionally:\n    - `currency` ISO 4217 three-letter code\n    - `timezone` From the IANA time zone database\n    - `units` Key value pairs of unit identifiers\n\n- `L10nFormat` Shows the format of the _language_ to be used for translations. The supported formats are: `'language' | 'language-script' | 'language-region' | 'language-script-region'`. So, for example, you can have a _language_ like `en-US-u-ca-gregory-nu-latn` to format dates and numbers, but only use the `en-US` for translations setting `'language-region'`\n- `L10nDateTimeFormatOptions` The type of _options_ used to format dates. Extends the Intl `DateTimeFormatOptions` interface, replacing the _dateStyle_ and _timeStyle_ attributes. See [DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) for more details on available options\n- `L10nNumberFormatOptions` The type of _options_ used to format numbers. Extends the Intl `NumberFormatOptions` interface, adding the _digits_ attribute. See [NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat) for more details on available options\n\n\n## Contributing\n- First, install the packages \u0026 build the library:\n    ```Shell\n    npm install\n    npm run build:watch\n    ```\n\n- Testing:\n    ```Shell\n    npm run test:watch\n    ```\n\n- Serving the sample app:\n    ```Shell\n    npm start\n    ```\n\n- Serving the sample ssr app:\n    ```Shell\n    npm run dev:ssr\n    ```\n\n\n## License\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobisim74%2Fangular-l10n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobisim74%2Fangular-l10n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobisim74%2Fangular-l10n/lists"}