UNPKG

@jsverse/transloco-locale

Version:

The localization (l10n) library plugin for Transloco

99 lines 12.2 kB
import { toNumber } from '@jsverse/utils'; export 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 */ export function isLocaleFormat(value) { try { return (typeof value === 'string' && Intl.getCanonicalLocales(value).length > 0); } catch { return false; } } export function localizeNumber(value, locale, options) { const number = toNumber(value); return number !== null ? new Intl.NumberFormat(locale, options).format(number) : ''; } export function localizeDate(date, locale, options) { if (isDate(date)) { return new Intl.DateTimeFormat(locale, options).format(date); } return ''; } export function isDate(value) { return value instanceof Date && !isNaN(value); } export 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); } export 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; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2xpYnMvdHJhbnNsb2NvLWxvY2FsZS9zcmMvbGliL2hlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBSTFDLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUM3QixzR0FBc0csQ0FBQztBQUV6Rzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtDRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsS0FBVTtJQUN2QyxJQUFJLENBQUM7UUFDSCxPQUFPLENBQ0wsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUN4RSxDQUFDO0lBQ0osQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztBQUNILENBQUM7QUFFRCxNQUFNLFVBQVUsY0FBYyxDQUM1QixLQUFzQixFQUN0QixNQUFjLEVBQ2QsT0FBaUM7SUFFakMsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQy9CLE9BQU8sTUFBTSxLQUFLLElBQUk7UUFDcEIsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUN2RCxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQ1QsQ0FBQztBQUVELE1BQU0sVUFBVSxZQUFZLENBQzFCLElBQVUsRUFDVixNQUFjLEVBQ2QsT0FBMEI7SUFFMUIsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUNqQixPQUFPLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsT0FBYyxDQUFDLENBQUMsTUFBTSxDQUFD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R0FBRyxNQUFNLENBQUM7SUFDOUMsTUFBTSxDQUFDLEdBQVcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDN0MsTUFBTSxDQUFDLEdBQVcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUNyQyxNQUFNLEVBQUUsR0FBVyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUN6RSxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNuQyxPQUFPLElBQUksQ0FBQztBQUNkLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB0b051bWJlciB9IGZyb20gJ0Bqc3ZlcnNlL3V0aWxzJztcblxuaW1wb3J0IHsgRGF0ZUZvcm1hdE9wdGlvbnMsIExvY2FsZSB9IGZyb20gJy4vdHJhbnNsb2NvLWxvY2FsZS50eXBlcyc7XG5cbmV4cG9ydCBjb25zdCBJU084NjAxX0RBVEVfUkVHRVggPVxuICAvXihcXGR7NH0pLT8oXFxkXFxkKS0/KFxcZFxcZCkoPzpUKFxcZFxcZCkoPzo6PyhcXGRcXGQpKD86Oj8oXFxkXFxkKSg/OlxcLihcXGQrKSk/KT8pPyhafChbKy1dKShcXGRcXGQpOj8oXFxkXFxkKSk/KT8kLztcblxuLyoqXG4gKiBDaGVja3MgaWYgYSBnaXZlbiB2YWx1ZSBpcyBhIHZhbGlkIEJDUCA0NyBsYW5ndWFnZSB0YWcuXG4gKlxuICogVmFsaWRhdGlvbiBpcyBkZWxlZ2F0ZWQgdG8gYEludGwuZ2V0Q2Fub25pY2FsTG9jYWxlc2AsIHdoaWNoIG1lYW5zIGFsbFxuICogZm9ybWF0cyBhY2NlcHRlZCBieSB0aGUgcGxhdGZvcm0gYXJlIGFjY2VwdGVkIGhlcmUg4oCUIGluY2x1ZGluZyBzaW5nbGVcbiAqIHN1YnRhZ3MsIGNhc2UtaW5zZW5zaXRpdmUgcmVnaW9uIGNvZGVzLCBhbmQgc2NyaXB0IHN1YnRhZ3MuIFRoaXMgaXNcbiAqIGludGVudGlvbmFsbHkgbW9yZSBwZXJtaXNzaXZlIHRoYW4gYSBoYW5kLXJvbGxlZCByZWdleCBzb1xuICogdGhhdCB2YWx1ZXMgY29taW5nIGRpcmVjdGx5IGZyb20gYG5hdmlnYXRvci5sYW5ndWFnZWAgKGUuZy4gYFwiZGVcImAgb25cbiAqIEZpcmVmb3ggb3IgYFwiZGUtZGVcImAgb24gU2FmYXJpKSBhcmUgdHJlYXRlZCBhcyB2YWxpZC5cbiAqXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHZhbGlkIEJDUCA0NyBsYW5ndWFnZSB0YWcsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBTaW5nbGUgcHJpbWFyeSBsYW5ndWFnZSBzdWJ0YWcgKGUuZy4gRmlyZWZveClcbiAqIGlzTG9jYWxlRm9ybWF0KCdkZScpIC8vIHRydWVcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gU3RhbmRhcmQgbGFuZ3VhZ2UtUkVHSU9OIHRhZ1xuICogaXNMb2NhbGVGb3JtYXQoJ2VuLVVTJykgLy8gdHJ1ZVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBDYXNlLWluc2Vuc2l0aXZlIHJlZ2lvbiAoZS5nLiBTYWZhcmkpXG4gKiBpc0xvY2FsZUZvcm1hdCgnZGUtZGUnKSAvLyB0cnVlXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFNjcmlwdCBzdWJ0YWdcbiAqIGlzTG9jYWxlRm9ybWF0KCd6aC1IYW50LVRXJykgLy8gdHJ1ZVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBJbnZhbGlkIHRhZ1xuICogaXNMb2NhbGVGb3JtYXQoJ25vdCB2YWxpZCcpIC8vIGZhbHNlXG4gKiBpc0xvY2FsZUZvcm1hdCgnJykgLy8gZmFsc2VcbiAqIGlzTG9jYWxlRm9ybWF0KG51bGwpIC8vIGZhbHNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0xvY2FsZUZvcm1hdCh2YWx1ZTogYW55KTogdmFsdWUgaXMgTG9jYWxlIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gKFxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiBJbnRsLmdldENhbm9uaWNhbExvY2FsZXModmFsdWUpLmxlbmd0aCA+IDBcbiAgICApO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvY2FsaXplTnVtYmVyKFxuICB2YWx1ZTogbnVtYmVyIHwgc3RyaW5nLFxuICBsb2NhbGU6IExvY2FsZSxcbiAgb3B0aW9uczogSW50bC5OdW1iZXJGb3JtYXRPcHRpb25zLFxuKTogc3RyaW5nIHtcbiAgY29uc3QgbnVtYmVyID0gdG9OdW1iZXIodmFsdWUpO1xuICByZXR1cm4gbnVtYmVyICE9PSBudWxsXG4gICAgPyBuZXcgSW50bC5OdW1iZXJGb3JtYXQobG9jYWxlLCBvcHRpb25zKS5mb3JtYXQobnVtYmVyKVxuICAgIDogJyc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2NhbGl6ZURhdGUoXG4gIGRhdGU6IERhdGUsXG4gIGxvY2FsZTogTG9jYWxlLFxuICBvcHRpb25zOiBEYXRlRm9ybWF0T3B0aW9ucyxcbik6IHN0cmluZyB7XG4gIGlmIChpc0RhdGUoZGF0ZSkpIHtcbiAgICByZXR1cm4gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQobG9jYWxlLCBvcHRpb25zIGFzIGFueSkuZm9ybWF0KGRhdGUpO1xuICB9XG4gIHJldHVybiAnJztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzRGF0ZSh2YWx1ZTogYW55KTogYm9vbGVhbiB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIERhdGUgJiYgIWlzTmFOKDxhbnk+dmFsdWUpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9EYXRlKHZhbHVlOiBhbnkpOiBEYXRlIHtcbiAgbGV0IG1hdGNoOiBSZWdFeHBNYXRjaEFycmF5IHwgbnVsbDtcblxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIHZhbHVlID0gdmFsdWUudHJpbSgpO1xuICB9XG5cbiAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBpZiAoIWlzTmFOKHZhbHVlIC0gcGFyc2VGbG9hdCh2YWx1ZSkpKSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKHBhcnNlRmxvYXQodmFsdWUpKTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIC9eKFxcZHs0fS1cXGR7MSwyfS1cXGR7MSwyfSkkLy50ZXN0KHZhbHVlKSkge1xuICAgIGNvbnN0IFt5LCBtLCBkXSA9IHZhbHVlLnNwbGl0KCctJykubWFwKCh2YWw6IHN0cmluZykgPT4gcGFyc2VJbnQodmFsLCAxMCkpO1xuICAgIHJldHVybiBuZXcgRGF0ZSh5LCBtIC0gMSwgZCk7XG4gIH1cblxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiAobWF0Y2ggPSB2YWx1ZS5tYXRjaChJU084NjAxX0RBVEVfUkVHRVgpKSkge1xuICAgIHJldHVybiBpc29TdHJpbmdUb0RhdGUobWF0Y2gpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBEYXRlKHZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzb1N0cmluZ1RvRGF0ZShtYXRjaDogUmVnRXhwTWF0Y2hBcnJheSk6IERhdGUge1xuICBjb25zdCBkYXRlOiBEYXRlID0gbmV3IERhdGUoMCk7XG4gIGxldCB0ekhvdXIgPSAwO1xuICBsZXQgdHpNaW4gPSAwO1xuICBjb25zdCBkYXRlU2V0dGVyID0gbWF0Y2hbOF0gPyBkYXRlLnNldFVUQ0Z1bGxZZWFyIDogZGF0ZS5zZXRGdWxsWWVhcjtcbiAgY29uc3QgdGltZVNldHRlciA9IG1hdGNoWzhdID8gZGF0ZS5zZXRVVENIb3VycyA6IGRhdGUuc2V0SG91cnM7XG4gIGlmIChtYXRjaFs5XSkge1xuICAgIHR6SG91ciA9ICsobWF0Y2hbOV0gKyBtYXRjaFsxMF0pO1xuICAgIHR6TWluID0gKyhtYXRjaFs5XSArIG1hdGNoWzExXSk7XG4gIH1cbiAgZGF0ZVNldHRlci5jYWxsKGRhdGUsICttYXRjaFsxXSwgK21hdGNoWzJdIC0gMSwgK21hdGNoWzNdKTtcbiAgY29uc3QgaDogbnVtYmVyID0gKyhtYXRjaFs0XSB8fCAnMCcpIC0gdHpIb3VyO1xuICBjb25zdCBtOiBudW1iZXIgPSArKG1hdGNoWzVdIHx8ICcwJykgLSB0ek1pbjtcbiAgY29uc3QgczogbnVtYmVyID0gKyhtYXRjaFs2XSB8fCAnMCcpO1xuICBjb25zdCBtczogbnVtYmVyID0gTWF0aC5yb3VuZChwYXJzZUZsb2F0KCcwLicgKyAobWF0Y2hbN10gfHwgMCkpICogMTAwMCk7XG4gIHRpbWVTZXR0ZXIuY2FsbChkYXRlLCBoLCBtLCBzLCBtcyk7XG4gIHJldHVybiBkYXRlO1xufVxuIl19