@jsverse/transloco-locale
Version:
The localization (l10n) library plugin for Transloco
1,200 lines (1,184 loc) • 35.7 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, inject, DestroyRef, Injectable, ChangeDetectorRef, Pipe, NgModule, makeEnvironmentProviders } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { TranslocoService, getBrowserCultureLang } from '@jsverse/transloco';
import { BehaviorSubject } from 'rxjs';
import { distinctUntilChanged, map, filter } from 'rxjs/operators';
import { toNumber, isNil } from '@jsverse/utils';
const ISO8601_DATE_REGEX = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
/**
* Checks if a given value is a valid BCP 47 language tag.
*
* Validation is delegated to `Intl.getCanonicalLocales`, which means all
* formats accepted by the platform are accepted here — including single
* subtags, case-insensitive region codes, and script subtags. This is
* intentionally more permissive than a hand-rolled regex so
* that values coming directly from `navigator.language` (e.g. `"de"` on
* Firefox or `"de-de"` on Safari) are treated as valid.
*
* @param value - The value to check.
* @returns `true` if `value` is a valid BCP 47 language tag, `false` otherwise.
*
* @example
* // Single primary language subtag (e.g. Firefox)
* isLocaleFormat('de') // true
*
* @example
* // Standard language-REGION tag
* isLocaleFormat('en-US') // true
*
* @example
* // Case-insensitive region (e.g. Safari)
* isLocaleFormat('de-de') // true
*
* @example
* // Script subtag
* isLocaleFormat('zh-Hant-TW') // true
*
* @example
* // Invalid tag
* isLocaleFormat('not valid') // false
* isLocaleFormat('') // false
* isLocaleFormat(null) // false
*/
function isLocaleFormat(value) {
try {
return (typeof value === 'string' && Intl.getCanonicalLocales(value).length > 0);
}
catch {
return false;
}
}
function localizeNumber(value, locale, options) {
const number = toNumber(value);
return number !== null
? new Intl.NumberFormat(locale, options).format(number)
: '';
}
function localizeDate(date, locale, options) {
if (isDate(date)) {
return new Intl.DateTimeFormat(locale, options).format(date);
}
return '';
}
function isDate(value) {
return value instanceof Date && !isNaN(value);
}
function toDate(value) {
let match;
if (typeof value === 'string') {
value = value.trim();
}
if (isDate(value)) {
return value;
}
if (!isNaN(value - parseFloat(value))) {
return new Date(parseFloat(value));
}
if (typeof value === 'string' && /^(\d{4}-\d{1,2}-\d{1,2})$/.test(value)) {
const [y, m, d] = value.split('-').map((val) => parseInt(val, 10));
return new Date(y, m - 1, d);
}
if (typeof value === 'string' && (match = value.match(ISO8601_DATE_REGEX))) {
return isoStringToDate(match);
}
return new Date(value);
}
function isoStringToDate(match) {
const date = new Date(0);
let tzHour = 0;
let tzMin = 0;
const dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear;
const timeSetter = match[8] ? date.setUTCHours : date.setHours;
if (match[9]) {
tzHour = +(match[9] + match[10]);
tzMin = +(match[9] + match[11]);
}
dateSetter.call(date, +match[1], +match[2] - 1, +match[3]);
const h = +(match[4] || '0') - tzHour;
const m = +(match[5] || '0') - tzMin;
const s = +(match[6] || '0');
const ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
timeSetter.call(date, h, m, s, ms);
return date;
}
function getDefaultOptions(locale, style, localeConfig) {
const defaultConfig = (localeConfig.global?.[style] ?? {});
const settings = (localeConfig.localeBased?.[locale] ??
{});
return Reflect.has(settings, style)
? { ...defaultConfig, ...settings[style] }
: defaultConfig;
}
var LOCALE_CURRENCY = {
'aa-DJ': 'DJF',
'aa-ER': 'ERN',
'aa-ET': 'ETB',
'ab-GE': 'ETB',
'ab-TR': 'ETB',
'af-BW': 'ETB',
'af-NA': 'ETB',
'af-ZA': 'ZAR',
'ak-GH': 'ZAR',
'am-ET': 'ETB',
'am-IL': 'ETB',
'ar-AE': 'AED',
'ar-AR': 'AED',
'ar-BH': 'BHD',
'ar-CM': 'BHD',
'ar-CY': 'BHD',
'ar-DJ': 'BHD',
'ar-DZ': 'DZD',
'ar-EG': 'EGP',
'ar-EH': 'EGP',
'ar-ER': 'EGP',
'ar-IL': 'EGP',
'ar-IQ': 'IQD',
'ar-IR': 'IQD',
'ar-JO': 'JOD',
'ar-KE': 'JOD',
'ar-KM': 'JOD',
'ar-KW': 'KWD',
'ar-LB': 'LBP',
'ar-LY': 'LYD',
'ar-MA': 'MAD',
'ar-ML': 'MAD',
'ar-MR': 'MAD',
'ar-NE': 'MAD',
'ar-NG': 'MAD',
'ar-OM': 'OMR',
'ar-PS': 'OMR',
'ar-QA': 'QAR',
'ar-SA': 'SAR',
'ar-SD': 'SDD',
'ar-SS': 'SDD',
'ar-SY': 'SYP',
'ar-TD': 'SYP',
'ar-TJ': 'SYP',
'ar-TN': 'TND',
'ar-TR': 'TND',
'ar-YE': 'YER',
'as-IN': 'INR',
'av-RU': 'INR',
'ay-BO': 'INR',
'ay-PE': 'INR',
'az-AZ': 'AZM',
'ba-RU': 'AZM',
'be-BY': 'BYR',
'be-PL': 'BYR',
'be-UA': 'BYR',
'bg-BG': 'BGN',
'bg-GR': 'BGN',
'bg-MD': 'BGN',
'bg-RO': 'BGN',
'bg-TR': 'BGN',
'bg-UA': 'BGN',
'bi-VU': 'BGN',
'bm-ML': 'BGN',
'bn-BD': 'BDT',
'bn-GB': 'BDT',
'bn-IN': 'INR',
'bn-NP': 'INR',
'bo-CN': 'CNY',
'bo-IN': 'INR',
'bo-NP': 'INR',
'br-FR': 'EUR',
'bs-BA': 'BAM',
'ca-AD': 'EUR',
'ca-ES': 'EUR',
'ca-FR': 'EUR',
'ca-IT': 'EUR',
'ce-RU': 'EUR',
'ch-GU': 'EUR',
'ch-MP': 'EUR',
'co-FR': 'EUR',
'cs-CZ': 'CZK',
'cv-RU': 'RUB',
'cy-AR': 'RUB',
'cy-GB': 'GBP',
'da-DE': 'GBP',
'da-DK': 'DKK',
'da-GL': 'DKK',
'da-IS': 'DKK',
'de-AT': 'EUR',
'de-BE': 'EUR',
'de-BR': 'EUR',
'de-CA': 'EUR',
'de-CH': 'CHF',
'de-CZ': 'CHF',
'de-DE': 'EUR',
'de-DK': 'EUR',
'de-HU': 'EUR',
'de-IT': 'EUR',
'de-KZ': 'EUR',
'de-LI': 'EUR',
'de-LU': 'EUR',
'de-NA': 'EUR',
'de-PL': 'EUR',
'de-PY': 'EUR',
'de-RO': 'EUR',
'de-SK': 'EUR',
'de-US': 'EUR',
'dv-IN': 'EUR',
'dv-MV': 'MVR',
'dz-BT': 'BTN',
'dz-IN': 'BTN',
'ee-GH': 'BTN',
'ee-TG': 'BTN',
'el-AL': 'BTN',
'el-CY': 'EUR',
'el-DE': 'EUR',
'el-EG': 'EUR',
'el-GB': 'EUR',
'el-GR': 'EUR',
'el-IT': 'EUR',
'el-RO': 'EUR',
'el-TR': 'EUR',
'el-UA': 'EUR',
'en-AC': 'EUR',
'en-AG': 'XCD',
'en-AI': 'XCD',
'en-AS': 'XCD',
'en-AU': 'AUD',
'en-AW': 'AUD',
'en-BB': 'AUD',
'en-BE': 'AUD',
'en-BM': 'AUD',
'en-BN': 'AUD',
'en-BS': 'AUD',
'en-BW': 'BWP',
'en-BZ': 'BWP',
'en-CA': 'CAD',
'en-CC': 'CAD',
'en-CK': 'CAD',
'en-CM': 'CAD',
'en-CN': 'CAD',
'en-CX': 'CAD',
'en-DE': 'CAD',
'en-DG': 'CAD',
'en-DM': 'CAD',
'en-DO': 'CAD',
'en-ES': 'CAD',
'en-ET': 'CAD',
'en-FI': 'CAD',
'en-FJ': 'CAD',
'en-FK': 'CAD',
'en-FM': 'CAD',
'en-FR': 'CAD',
'en-GB': 'GBP',
'en-GD': 'GBP',
'en-GG': 'GBP',
'en-GH': 'GBP',
'en-GI': 'GBP',
'en-GM': 'GBP',
'en-GU': 'GBP',
'en-GY': 'GBP',
'en-HK': 'HKD',
'en-HN': 'HKD',
'en-IE': 'EUR',
'en-IL': 'EUR',
'en-IM': 'EUR',
'en-IN': 'INR',
'en-IO': 'INR',
'en-IT': 'INR',
'en-JE': 'INR',
'en-JM': 'INR',
'en-KE': 'INR',
'en-KI': 'INR',
'en-KN': 'INR',
'en-KY': 'INR',
'en-LB': 'INR',
'en-LC': 'INR',
'en-LK': 'INR',
'en-LR': 'INR',
'en-LS': 'INR',
'en-MG': 'INR',
'en-MH': 'INR',
'en-MP': 'INR',
'en-MS': 'INR',
'en-MT': 'INR',
'en-MU': 'INR',
'en-MW': 'INR',
'en-MY': 'INR',
'en-NA': 'INR',
'en-NF': 'INR',
'en-NG': 'NGN',
'en-NL': 'NGN',
'en-NR': 'NGN',
'en-NU': 'NGN',
'en-NZ': 'NZD',
'en-PA': 'NZD',
'en-PG': 'NZD',
'en-PH': 'PHP',
'en-PI': 'PHP',
'en-PK': 'PHP',
'en-PM': 'PHP',
'en-PN': 'PHP',
'en-PR': 'PHP',
'en-PW': 'PHP',
'en-RW': 'PHP',
'en-SB': 'PHP',
'en-SC': 'PHP',
'en-SG': 'SGD',
'en-SH': 'SGD',
'en-SL': 'SGD',
'en-SS': 'SGD',
'en-SZ': 'SGD',
'en-TA': 'SGD',
'en-TC': 'SGD',
'en-TK': 'SGD',
'en-TO': 'SGD',
'en-TT': 'SGD',
'en-TV': 'SGD',
'en-TZ': 'SGD',
'en-UD': 'SGD',
'en-UG': 'SGD',
'en-UM': 'SGD',
'en-US': 'USD',
'en-VC': 'USD',
'en-VG': 'USD',
'en-VI': 'USD',
'en-VU': 'USD',
'en-WS': 'USD',
'en-ZA': 'ZAR',
'en-ZM': 'ZAR',
'en-ZW': 'ZWD',
'eo-EO': 'ZWD',
'eo-SM': 'ZWD',
'es-AD': 'ZWD',
'es-AR': 'ARS',
'es-BO': 'BOB',
'es-BZ': 'BOB',
'es-CL': 'CLP',
'es-CO': 'COP',
'es-CR': 'CRC',
'es-CU': 'CRC',
'es-DE': 'CRC',
'es-DO': 'DOP',
'es-EA': 'DOP',
'es-EC': 'USD',
'es-ES': 'EUR',
'es-GQ': 'EUR',
'es-GT': 'GTQ',
'es-HN': 'HNL',
'es-IC': 'HNL',
'es-LA': 'HNL',
'es-MA': 'HNL',
'es-MX': 'MXN',
'es-NI': 'NIO',
'es-PA': 'PAB',
'es-PE': 'PEN',
'es-PH': 'PEN',
'es-PR': 'USD',
'es-PY': 'PYG',
'es-SV': 'SVC',
'es-TT': 'SVC',
'es-US': 'USD',
'es-UY': 'UYU',
'es-VE': 'VEB',
'et-EE': 'EEK',
'et-FI': 'EEK',
'eu-ES': 'EUR',
'eu-FR': 'EUR',
'fa-AE': 'EUR',
'fa-AF': 'EUR',
'fa-IQ': 'EUR',
'fa-IR': 'IRR',
'fa-OM': 'IRR',
'fa-PK': 'IRR',
'fa-QA': 'IRR',
'fa-TJ': 'IRR',
'fb-LT': 'IRR',
'ff-GN': 'IRR',
'ff-MR': 'IRR',
'ff-SN': 'IRR',
'fi-FI': 'EUR',
'fi-RU': 'EUR',
'fi-SE': 'EUR',
'fj-FJ': 'EUR',
'fo-FO': 'DKK',
'fr-AD': 'DKK',
'fr-BE': 'EUR',
'fr-BF': 'EUR',
'fr-BI': 'EUR',
'fr-BJ': 'EUR',
'fr-BL': 'EUR',
'fr-CA': 'CAD',
'fr-CD': 'CAD',
'fr-CF': 'CAD',
'fr-CG': 'CAD',
'fr-CH': 'CHF',
'fr-CI': 'CHF',
'fr-CM': 'CHF',
'fr-CP': 'CHF',
'fr-DJ': 'CHF',
'fr-DZ': 'CHF',
'fr-FR': 'EUR',
'fr-GA': 'EUR',
'fr-GB': 'EUR',
'fr-GF': 'EUR',
'fr-GN': 'EUR',
'fr-GP': 'EUR',
'fr-GQ': 'EUR',
'fr-HT': 'EUR',
'fr-IT': 'EUR',
'fr-KM': 'EUR',
'fr-LB': 'EUR',
'fr-LU': 'EUR',
'fr-MA': 'EUR',
'fr-MC': 'EUR',
'fr-MF': 'EUR',
'fr-MG': 'EUR',
'fr-ML': 'EUR',
'fr-MQ': 'EUR',
'fr-MR': 'EUR',
'fr-MU': 'EUR',
'fr-NC': 'EUR',
'fr-NE': 'EUR',
'fr-PF': 'EUR',
'fr-PM': 'EUR',
'fr-RE': 'EUR',
'fr-RW': 'EUR',
'fr-SC': 'EUR',
'fr-SN': 'EUR',
'fr-SY': 'EUR',
'fr-TD': 'EUR',
'fr-TF': 'EUR',
'fr-TG': 'EUR',
'fr-TN': 'EUR',
'fr-US': 'EUR',
'fr-VU': 'EUR',
'fr-WF': 'EUR',
'fr-YT': 'EUR',
'fy-NL': 'EUR',
'ga-GB': 'EUR',
'ga-IE': 'EUR',
'gd-GB': 'GBP',
'gl-ES': 'EUR',
'gl-PT': 'EUR',
'gn-AR': 'EUR',
'gn-BO': 'EUR',
'gn-PY': 'EUR',
'gu-IN': 'INR',
'gu-KE': 'INR',
'gv-IM': 'INR',
'he-IL': 'ILS',
'hi-FJ': 'ILS',
'hi-IN': 'INR',
'hi-NP': 'INR',
'hi-UG': 'INR',
'hi-ZA': 'INR',
'ho-PG': 'INR',
'hr-AT': 'INR',
'hr-BA': 'INR',
'hr-DE': 'INR',
'hr-HR': 'HRK',
'hr-HU': 'HRK',
'hr-IT': 'HRK',
'ht-HT': 'HTG',
'hu-AT': 'HTG',
'hu-HU': 'HUF',
'hu-IL': 'HUF',
'hu-RO': 'HUF',
'hu-RS': 'HUF',
'hu-SI': 'HUF',
'hu-SK': 'HUF',
'hu-UA': 'HUF',
'hy-AM': 'AMD',
'hy-CY': 'AMD',
'hy-GE': 'AMD',
'hy-IR': 'AMD',
'hy-LB': 'AMD',
'hy-SY': 'AMD',
'hy-TR': 'AMD',
'ia-SE': 'AMD',
'id-ID': 'IDR',
'id-NL': 'IDR',
'ig-NG': 'NGN',
'ii-CN': 'NGN',
'ik-US': 'NGN',
'is-IS': 'ISK',
'it-AU': 'ISK',
'it-BR': 'ISK',
'it-CA': 'ISK',
'it-CH': 'CHF',
'it-DE': 'CHF',
'it-FR': 'CHF',
'it-GB': 'CHF',
'it-HR': 'CHF',
'it-IT': 'EUR',
'it-SI': 'EUR',
'it-SM': 'EUR',
'it-US': 'EUR',
'it-VA': 'EUR',
'iu-GL': 'EUR',
'ja-BR': 'EUR',
'ja-JP': 'JPY',
'jv-ID': 'JPY',
'jv-MY': 'JPY',
'ka-GE': 'GEL',
'ka-IR': 'GEL',
'ka-TR': 'GEL',
'kg-CD': 'GEL',
'ki-KE': 'GEL',
'kj-NA': 'GEL',
'kl-DK': 'GEL',
'kl-GL': 'DKK',
'km-KH': 'KHR',
'kn-IN': 'INR',
'ko-BR': 'INR',
'ko-CN': 'INR',
'ko-JP': 'INR',
'ko-KP': 'INR',
'ko-KR': 'KRW',
'ko-US': 'KRW',
'ks-GB': 'KRW',
'ks-IN': 'INR',
'ks-PK': 'INR',
'ku-TR': 'TRY',
'kw-GB': 'GBP',
'la-VA': 'GBP',
'lb-LU': 'GBP',
'lg-UG': 'UGX',
'li-NL': 'EUR',
'ln-CD': 'EUR',
'ln-CG': 'EUR',
'lo-LA': 'LAK',
'lt-LT': 'LTL',
'lu-CD': 'LTL',
'lv-LV': 'LVL',
'mg-MG': 'MGA',
'mh-MH': 'MGA',
'mi-NZ': 'NZD',
'mk-AL': 'NZD',
'mk-GR': 'NZD',
'mk-MK': 'MKD',
'ml-AE': 'MKD',
'ml-BH': 'MKD',
'ml-GB': 'MKD',
'ml-IL': 'MKD',
'ml-IN': 'INR',
'ml-MY': 'INR',
'ml-QA': 'INR',
'ml-SG': 'INR',
'mr-IN': 'INR',
'ms-BN': 'INR',
'ms-CC': 'INR',
'ms-ID': 'INR',
'ms-MY': 'MYR',
'ms-SG': 'MYR',
'mt-MT': 'EUR',
'my-BD': 'EUR',
'my-MM': 'MMK',
'na-NR': 'MMK',
'nb-NO': 'NOK',
'nb-SJ': 'NOK',
'nd-ZW': 'NOK',
'ne-BT': 'NOK',
'ne-IN': 'NOK',
'ne-NP': 'INR',
'ng-NA': 'INR',
'nl-AW': 'AWG',
'nl-BE': 'EUR',
'nl-DE': 'EUR',
'nl-FR': 'EUR',
'nl-NL': 'EUR',
'nl-SR': 'EUR',
'nn-NO': 'NOK',
'nr-ZA': 'ZAR',
'nv-US': 'ZAR',
'ny-MW': 'ZAR',
'ny-MZ': 'ZAR',
'ny-ZM': 'ZAR',
'ny-ZW': 'ZAR',
'oc-FR': 'EUR',
'om-ET': 'ETB',
'om-KE': 'KES',
'om-SO': 'KES',
'or-IN': 'INR',
'os-GE': 'INR',
'pa-IN': 'INR',
'pl-CZ': 'INR',
'pl-DE': 'INR',
'pl-IL': 'INR',
'pl-PL': 'PLN',
'pl-RO': 'PLN',
'pl-SK': 'PLN',
'pl-UA': 'PLN',
'ps-AE': 'PLN',
'ps-AF': 'AFN',
'ps-IR': 'AFN',
'ps-PK': 'AFN',
'pt-AG': 'AFN',
'pt-AO': 'AFN',
'pt-BR': 'BRL',
'pt-CV': 'BRL',
'pt-FR': 'BRL',
'pt-GW': 'BRL',
'pt-MO': 'BRL',
'pt-MZ': 'BRL',
'pt-PT': 'EUR',
'pt-ST': 'EUR',
'pt-TL': 'EUR',
'qu-BO': 'EUR',
'qu-PE': 'EUR',
'rm-CH': 'EUR',
'rn-BI': 'EUR',
'ro-HU': 'EUR',
'ro-IL': 'EUR',
'ro-MD': 'EUR',
'ro-RO': 'RON',
'ro-RS': 'RON',
'ro-UA': 'RON',
'ru-BY': 'RON',
'ru-CN': 'RON',
'ru-DE': 'RON',
'ru-EE': 'RON',
'ru-FI': 'RON',
'ru-GE': 'RON',
'ru-IL': 'RON',
'ru-KG': 'RON',
'ru-KZ': 'RON',
'ru-LT': 'RON',
'ru-LV': 'RON',
'ru-MD': 'RON',
'ru-MN': 'RON',
'ru-RU': 'RUB',
'ru-SJ': 'RUB',
'ru-TM': 'RUB',
'ru-UA': 'UAH',
'ru-US': 'UAH',
'ru-UZ': 'UAH',
'rw-CD': 'UAH',
'rw-RW': 'RWF',
'rw-UG': 'RWF',
'sa-IN': 'INR',
'se-FI': 'INR',
'se-NO': 'NOK',
'se-SE': 'NOK',
'sg-CF': 'NOK',
'si-LK': 'LKR',
'sk-HU': 'LKR',
'sk-RS': 'LKR',
'sk-SK': 'EUR',
'sl-AT': 'EUR',
'sl-HU': 'EUR',
'sl-IT': 'EUR',
'sl-SI': 'EUR',
'sm-AS': 'EUR',
'sm-WS': 'EUR',
'sn-ZW': 'EUR',
'so-DJ': 'DJF',
'so-ET': 'ETB',
'so-KE': 'ETB',
'so-SO': 'SOS',
'sq-AL': 'ALL',
'sq-GR': 'ALL',
'sq-ME': 'ALL',
'sq-MK': 'MKD',
'sq-RS': 'MKD',
'sq-TR': 'MKD',
'sr-RS': 'RSD',
'ss-LS': 'RSD',
'ss-SZ': 'RSD',
'ss-ZA': 'ZAR',
'st-LS': 'ZAR',
'st-ZA': 'ZAR',
'su-ID': 'ZAR',
'sv-AX': 'ZAR',
'sv-FI': 'EUR',
'sv-SE': 'SEK',
'sw-BI': 'SEK',
'sw-CD': 'SEK',
'sw-KE': 'SEK',
'sw-MZ': 'SEK',
'sw-SO': 'SEK',
'sw-TZ': 'SEK',
'sw-UG': 'SEK',
'sw-YT': 'SEK',
'sw-ZA': 'SEK',
'ta-IN': 'INR',
'ta-LK': 'INR',
'ta-MU': 'INR',
'ta-MY': 'INR',
'ta-RE': 'INR',
'ta-SG': 'INR',
'te-IN': 'INR',
'th-TH': 'THB',
'ti-ER': 'ERN',
'ti-ET': 'ETB',
'ti-IL': 'ETB',
'tk-AF': 'ETB',
'tk-IR': 'ETB',
'tk-TM': 'TMM',
'tl-PH': 'PHP',
'tl-US': 'PHP',
'tn-BW': 'PHP',
'tn-NA': 'PHP',
'tn-ZA': 'ZAR',
'tn-ZW': 'ZAR',
'to-TO': 'ZAR',
'tr-BG': 'ZAR',
'tr-CY': 'TRY',
'tr-DE': 'TRY',
'tr-GR': 'TRY',
'tr-MK': 'TRY',
'tr-NL': 'TRY',
'tr-RO': 'TRY',
'tr-TR': 'TRY',
'tr-UA': 'TRY',
'tr-UZ': 'TRY',
'ts-MZ': 'TRY',
'ts-SZ': 'TRY',
'ts-ZA': 'ZAR',
'tt-RU': 'RUB',
'ty-PF': 'RUB',
'uk-PL': 'RUB',
'uk-SK': 'RUB',
'uk-UA': 'UAH',
'ur-IN': 'UAH',
'ur-MU': 'UAH',
'ur-PK': 'PKR',
've-ZA': 'ZAR',
've-ZW': 'ZAR',
'vi-CN': 'ZAR',
'vi-US': 'ZAR',
'vi-VN': 'VND',
'wa-BE': 'EUR',
'xh-LS': 'EUR',
'xh-ZA': 'ZAR',
'yi-UA': 'ZAR',
'yo-BJ': 'ZAR',
'yo-NG': 'NGN',
'za-CN': 'NGN',
'zh-CN': 'CNY',
'zh-HK': 'HKD',
'zh-TW': 'TWD',
'zu-LS': 'TWD',
'zu-MW': 'TWD',
'zu-MZ': 'TWD',
'zu-SZ': 'TWD',
'zu-ZA': 'ZAR',
};
const defaultConfig = {
localeConfig: {
global: {},
localeBased: {},
},
defaultLocale: 'en-US',
defaultCurrency: 'USD',
localeToCurrencyMapping: LOCALE_CURRENCY,
langToLocaleMapping: {},
};
const TRANSLOCO_LOCALE_DEFAULT_LOCALE = new InjectionToken('TRANSLOCO_LOCALE_DEFAULT_LOCALE');
const TRANSLOCO_LOCALE_DEFAULT_CURRENCY = new InjectionToken('TRANSLOCO_LOCALE_DEFAULT_CURRENCY');
const TRANSLOCO_LOCALE_LANG_MAPPING = new InjectionToken('TRANSLOCO_LOCALE_LANG_MAPPING');
const TRANSLOCO_LOCALE_CONFIG = new InjectionToken('TRANSLOCO_LOCALE_CONFIG');
const TRANSLOCO_LOCALE_CURRENCY_MAPPING = new InjectionToken('TRANSLOCO_LOCALE_CURRENCY_MAPPING');
const TRANSLOCO_DATE_TRANSFORMER = new InjectionToken('TRANSLOCO_DATE_TRANSFORMER');
const TRANSLOCO_NUMBER_TRANSFORMER = new InjectionToken('TRANSLOCO_NUMBER_TRANSFORMER');
class DefaultDateTransformer {
transform(date, locale, options) {
return localizeDate(date, locale, options);
}
}
class DefaultNumberTransformer {
transform(value, type, locale, options) {
return localizeNumber(value, locale, { ...options, style: type });
}
}
class TranslocoLocaleService {
translocoService = inject(TranslocoService);
langLocaleMapping = inject(TRANSLOCO_LOCALE_LANG_MAPPING);
defaultLocale = inject(TRANSLOCO_LOCALE_DEFAULT_LOCALE);
defaultCurrency = inject(TRANSLOCO_LOCALE_DEFAULT_CURRENCY);
localeCurrencyMapping = inject(TRANSLOCO_LOCALE_CURRENCY_MAPPING);
numberTransformer = inject(TRANSLOCO_NUMBER_TRANSFORMER);
dateTransformer = inject(TRANSLOCO_DATE_TRANSFORMER);
localeConfig = inject(TRANSLOCO_LOCALE_CONFIG);
browserLocale = getBrowserCultureLang() || this.defaultLocale;
_locale = '';
locale = new BehaviorSubject(this._locale);
localeChanges$ = this.locale.pipe(distinctUntilChanged());
constructor() {
inject(DestroyRef).onDestroy(() => {
// Complete subjects to release observers if users forget to unsubscribe manually.
// This is important in server-side rendering.
this.locale.complete();
this.locale.unsubscribe();
});
// Initialize locale with fallback chain
this.setLocale(this.initializeLocale());
// Subscribe to language changes
this.translocoService.langChanges$
.pipe(map((lang) => this.toLocale(lang)), filter(Boolean), takeUntilDestroyed())
.subscribe((locale) => this.setLocale(locale));
}
getDefaultLocale() {
return this.defaultLocale;
}
getLocale() {
return this._locale;
}
setLocale(locale) {
if (!isLocaleFormat(locale)) {
console.error(`${locale} isn't a valid locale format`);
return;
}
this.locale.next(locale);
this._locale = locale;
}
/**
* Get the currency symbol for the currently set locale.
*/
getCurrencySymbol(locale = this.getLocale()) {
const currency = this.localeCurrencyMapping[locale];
const numberFormat = new Intl.NumberFormat(locale, {
style: 'currency',
currencyDisplay: 'symbol',
currency,
minimumFractionDigits: 0,
maximumFractionDigits: 0,
});
const pivot = 0;
return numberFormat
.format(pivot)
.split(pivot.toString())
.map((element) => element.trim())
.find((element) => !!element);
}
/**
* Transform a date into the locale's date format.
*
* The date expression: a `Date` object, a number
* (milliseconds since UTC epoch), or an ISO string (https://www.w3.org/TR/NOTE-datetime).
*
* @example
*
* localizeDate(new Date(2019, 9, 7, 12, 0, 0)) // 10/7/2019
* localizeDate(date, 'en-US', { dateStyle: 'medium', timeStyle: 'medium' }) // Sep 10, 2019, 10:46:12 PM
* localizeDate(date) 'en-US', { timeZone: 'UTC', timeStyle: 'full' } // 7:40:32 PM Coordinated Universal Time
* localizeDate(1, 'en-US', { dateStyle: 'medium' }) // Jan 1, 1970
* localizeDate('2019-02-08', 'en-US', { dateStyle: 'medium' }) // Feb 8, 2019
*/
localizeDate(date, locale = this.getLocale(), options = {}) {
const resolved = options ?? getDefaultOptions(locale, 'date', this.localeConfig);
return this.dateTransformer.transform(toDate(date), locale, resolved);
}
/**
* Transform a number into the locale's number format according to the number type.
*
* localizeNumber(1234567890, 'decimal') // 1,234,567,890
* localizeNumber(0.5, 'percent') // 50%
* localizeNumber(1000, 'currency') // $1,000.00
*/
localizeNumber(value, style, locale = this.getLocale(), options) {
let resolved = options ?? getDefaultOptions(locale, style, this.localeConfig);
if (style === 'currency') {
resolved = {
...resolved,
currency: resolved.currency || this._resolveCurrencyCode(locale),
};
}
return this.numberTransformer.transform(value, style, locale, resolved);
}
/**
* @internal
*/
_resolveCurrencyCode(locale = this.getLocale()) {
return this.localeCurrencyMapping[locale] || this.defaultCurrency;
}
toLocale(val) {
if (this.langLocaleMapping[val]) {
return this.langLocaleMapping[val];
}
if (isLocaleFormat(val)) {
return val;
}
return '';
}
/*
* Get the browser's language and validate.
* If the browser's language is not set, it will fall back to the active language from TranslocoService.
* If active language from TranslocoService is not valid, it will fall back to the default locale.
* If the default locale is not valid, it will return the default locale as a string
*/
initializeLocale() {
const browserLocale = this.toLocale(this.browserLocale);
if (browserLocale)
return browserLocale;
const activeLang = this.translocoService.getActiveLang();
if (activeLang) {
const locale = this.toLocale(activeLang);
if (locale)
return locale;
}
const defaultLocaleResolved = this.toLocale(this.defaultLocale);
if (defaultLocaleResolved)
return defaultLocaleResolved;
return this.defaultLocale; // Fallback to a default locale
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoLocaleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoLocaleService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoLocaleService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [] });
class BaseLocalePipe {
localeService = inject(TranslocoLocaleService);
cdr = inject(ChangeDetectorRef);
localeChangeSub = this.localeService.localeChanges$.subscribe(() => this.cdr.markForCheck());
getLocale(locale) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return locale || this.localeService.getLocale();
}
ngOnDestroy() {
this.localeChangeSub?.unsubscribe();
// Caretaker note: it's important to clean up references to subscriptions since they save the `next`
// callback within its `destination` property, preventing classes from being GC'd.
this.localeChangeSub = null;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: BaseLocalePipe, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: BaseLocalePipe });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: BaseLocalePipe, decorators: [{
type: Injectable
}] });
class TranslocoCurrencyPipe extends BaseLocalePipe {
localeConfig = inject(TRANSLOCO_LOCALE_CONFIG);
/**
* Transform a given number into the locale's currency format.
*
* @example
*
* 1000000 | translocoCurrency: 'symbol' : {} : USD // $1,000,000.00
* 1000000 | translocoCurrency: 'name' : {} : USD // 1,000,000.00 US dollars
* 1000000 | translocoCurrency: 'symbol' : {minimumFractionDigits: 0 } : USD // $1,000,000
* 1000000 | translocoCurrency: 'symbol' : {minimumFractionDigits: 0 } : CAD // CA$1,000,000
* 1000000 | translocoCurrency: 'narrowSymbol' : {minimumFractionDigits: 0 } : CAD // $1,000,000
*
*/
transform(value, display = 'symbol', numberFormatOptions = {}, currencyCode, locale) {
if (isNil(value))
return '';
locale = this.getLocale(locale);
const options = {
...getDefaultOptions(locale, 'currency', this.localeConfig),
...numberFormatOptions,
currencyDisplay: display,
currency: currencyCode || this.localeService._resolveCurrencyCode(),
};
return this.localeService.localizeNumber(value, 'currency', locale, options);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoCurrencyPipe, deps: null, target: i0.ɵɵFactoryTarget.Pipe });
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.9", ngImport: i0, type: TranslocoCurrencyPipe, isStandalone: true, name: "translocoCurrency", pure: false });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoCurrencyPipe, decorators: [{
type: Pipe,
args: [{
name: 'translocoCurrency',
pure: false,
standalone: true,
}]
}] });
class TranslocoDatePipe extends BaseLocalePipe {
localeConfig = inject(TRANSLOCO_LOCALE_CONFIG);
/**
* Transform a date into the locale's date format.
*
* The date expression: a `Date` object, a number
* (milliseconds since UTC epoch), or an ISO string (https://www.w3.org/TR/NOTE-datetime).
*
* @example
*
* date | translocoDate: {} : en-US // 9/10/2019
* date | translocoDate: { dateStyle: 'medium', timeStyle: 'medium' } : en-US // Sep 10, 2019, 10:46:12 PM
* date | translocoDate: { timeZone: 'UTC', timeStyle: 'full' } : en-US // 7:40:32 PM Coordinated Universal Time
* 1 | translocoDate: { dateStyle: 'medium' } // Jan 1, 1970
* '2019-02-08' | translocoDate: { dateStyle: 'medium' } // Feb 8, 2019
*/
transform(date, options = {}, locale) {
if (isNil(date))
return '';
locale = this.getLocale(locale);
return this.localeService.localizeDate(date, locale, {
...getDefaultOptions(locale, 'date', this.localeConfig),
...options,
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoDatePipe, deps: null, target: i0.ɵɵFactoryTarget.Pipe });
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.9", ngImport: i0, type: TranslocoDatePipe, isStandalone: true, name: "translocoDate", pure: false });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoDatePipe, decorators: [{
type: Pipe,
args: [{
name: 'translocoDate',
pure: false,
standalone: true,
}]
}] });
class TranslocoDecimalPipe extends BaseLocalePipe {
localeConfig = inject(TRANSLOCO_LOCALE_CONFIG);
/**
* Transform a given number into the locale's currency format.
*
* @example
*
* 1234567890 | translocoDecimal: {} : en-US // 1,234,567,890
* 1234567890 | translocoDecimal: {useGrouping: false}: en-US // 1234567890
*
*/
transform(value, numberFormatOptions = {}, locale) {
if (isNil(value))
return '';
locale = this.getLocale(locale);
const options = {
...getDefaultOptions(locale, 'decimal', this.localeConfig),
...numberFormatOptions,
};
return this.localeService.localizeNumber(value, 'decimal', locale, options);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoDecimalPipe, deps: null, target: i0.ɵɵFactoryTarget.Pipe });
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.9", ngImport: i0, type: TranslocoDecimalPipe, isStandalone: true, name: "translocoDecimal", pure: false });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoDecimalPipe, decorators: [{
type: Pipe,
args: [{
name: 'translocoDecimal',
pure: false,
standalone: true,
}]
}] });
class TranslocoPercentPipe extends BaseLocalePipe {
localeConfig = inject(TRANSLOCO_LOCALE_CONFIG);
/**
* Transform a given number into the locale's currency format.
*
* @example
*
* 1 | translocoPercent : {} : en-US // 100%
* "1" | translocoPercent : {} : en-US // 100%
*
*/
transform(value, numberFormatOptions = {}, locale) {
if (isNil(value))
return '';
locale = this.getLocale(locale);
const options = {
...getDefaultOptions(locale, 'percent', this.localeConfig),
...numberFormatOptions,
};
return this.localeService.localizeNumber(value, 'percent', locale, options);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoPercentPipe, deps: null, target: i0.ɵɵFactoryTarget.Pipe });
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.9", ngImport: i0, type: TranslocoPercentPipe, isStandalone: true, name: "translocoPercent", pure: false });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoPercentPipe, decorators: [{
type: Pipe,
args: [{
name: 'translocoPercent',
pure: false,
standalone: true,
}]
}] });
const decl = [
TranslocoCurrencyPipe,
TranslocoDatePipe,
TranslocoDecimalPipe,
TranslocoPercentPipe,
];
class TranslocoLocaleModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoLocaleModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.9", ngImport: i0, type: TranslocoLocaleModule, imports: [TranslocoCurrencyPipe,
TranslocoDatePipe,
TranslocoDecimalPipe,
TranslocoPercentPipe], exports: [TranslocoCurrencyPipe,
TranslocoDatePipe,
TranslocoDecimalPipe,
TranslocoPercentPipe] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoLocaleModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TranslocoLocaleModule, decorators: [{
type: NgModule,
args: [{
imports: decl,
exports: decl,
}]
}] });
function provideTranslocoLocale(config) {
const merged = {
...defaultConfig,
...config,
};
return [
provideTranslocoLocaleConfig(merged.localeConfig),
provideTranslocoDefaultLocale(merged.defaultLocale),
provideTranslocoDefaultCurrency(merged.defaultCurrency),
provideTranslocoLocaleLangMapping(merged.langToLocaleMapping),
provideTranslocoLocaleCurrencyMapping(merged.localeToCurrencyMapping),
provideTranslocoDateTransformer(DefaultDateTransformer),
provideTranslocoNumberTransformer(DefaultNumberTransformer),
];
}
function provideTranslocoLocaleConfig(config) {
return makeEnvironmentProviders([
{
provide: TRANSLOCO_LOCALE_CONFIG,
useValue: config,
},
]);
}
function provideTranslocoLocaleLangMapping(langToLocale) {
return makeEnvironmentProviders([
{
provide: TRANSLOCO_LOCALE_LANG_MAPPING,
useValue: langToLocale,
},
]);
}
function provideTranslocoLocaleCurrencyMapping(localeToCurrency) {
return makeEnvironmentProviders([
{
provide: TRANSLOCO_LOCALE_CURRENCY_MAPPING,
useValue: localeToCurrency,
},
]);
}
function provideTranslocoDefaultLocale(defaultLocale) {
return makeEnvironmentProviders([
{
provide: TRANSLOCO_LOCALE_DEFAULT_LOCALE,
useValue: defaultLocale,
},
]);
}
function provideTranslocoDefaultCurrency(defaultCurrency) {
return makeEnvironmentProviders([
{
provide: TRANSLOCO_LOCALE_DEFAULT_CURRENCY,
useValue: defaultCurrency,
},
]);
}
function provideTranslocoDateTransformer(transformer) {
return makeEnvironmentProviders([
{
provide: TRANSLOCO_DATE_TRANSFORMER,
useClass: transformer,
},
]);
}
function provideTranslocoNumberTransformer(transformer) {
return makeEnvironmentProviders([
{
provide: TRANSLOCO_NUMBER_TRANSFORMER,
useClass: transformer,
},
]);
}
/**
* Generated bundle index. Do not edit.
*/
export { BaseLocalePipe, DefaultDateTransformer, DefaultNumberTransformer, TRANSLOCO_DATE_TRANSFORMER, TRANSLOCO_LOCALE_CONFIG, TRANSLOCO_LOCALE_CURRENCY_MAPPING, TRANSLOCO_LOCALE_DEFAULT_CURRENCY, TRANSLOCO_LOCALE_DEFAULT_LOCALE, TRANSLOCO_LOCALE_LANG_MAPPING, TRANSLOCO_NUMBER_TRANSFORMER, TranslocoCurrencyPipe, TranslocoDatePipe, TranslocoDecimalPipe, TranslocoLocaleModule, TranslocoLocaleService, TranslocoPercentPipe, provideTranslocoDateTransformer, provideTranslocoDefaultCurrency, provideTranslocoDefaultLocale, provideTranslocoLocale, provideTranslocoLocaleConfig, provideTranslocoLocaleCurrencyMapping, provideTranslocoLocaleLangMapping, provideTranslocoNumberTransformer };
//# sourceMappingURL=jsverse-transloco-locale.mjs.map