UNPKG

@jsverse/transloco-locale

Version:

The localization (l10n) library plugin for Transloco

1,200 lines (1,184 loc) 35.7 kB
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