UNPKG

intl-messageformat

Version:

Formats ICU Message strings with number, date, plural, and select placeholders to create localized messages.

239 lines (238 loc) 8.51 kB
/* Copyright (c) 2014, Yahoo! Inc. All rights reserved. Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. */ import { __assign, __rest, __spreadArray } from "tslib"; import { memoize, strategies } from '@formatjs/fast-memoize'; import { parse, } from '@formatjs/icu-messageformat-parser'; import { formatToParts, PART_TYPE, } from './formatters'; // -- MessageFormat -------------------------------------------------------- function mergeConfig(c1, c2) { if (!c2) { return c1; } return __assign(__assign(__assign({}, (c1 || {})), (c2 || {})), Object.keys(c1).reduce(function (all, k) { all[k] = __assign(__assign({}, c1[k]), (c2[k] || {})); return all; }, {})); } function mergeConfigs(defaultConfig, configs) { if (!configs) { return defaultConfig; } return Object.keys(defaultConfig).reduce(function (all, k) { all[k] = mergeConfig(defaultConfig[k], configs[k]); return all; }, __assign({}, defaultConfig)); } function createFastMemoizeCache(store) { return { create: function () { return { get: function (key) { return store[key]; }, set: function (key, value) { store[key] = value; }, }; }, }; } function createDefaultFormatters(cache) { if (cache === void 0) { cache = { number: {}, dateTime: {}, pluralRules: {}, }; } return { getNumberFormat: memoize(function () { var _a; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return new ((_a = Intl.NumberFormat).bind.apply(_a, __spreadArray([void 0], args, false)))(); }, { cache: createFastMemoizeCache(cache.number), strategy: strategies.variadic, }), getDateTimeFormat: memoize(function () { var _a; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return new ((_a = Intl.DateTimeFormat).bind.apply(_a, __spreadArray([void 0], args, false)))(); }, { cache: createFastMemoizeCache(cache.dateTime), strategy: strategies.variadic, }), getPluralRules: memoize(function () { var _a; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return new ((_a = Intl.PluralRules).bind.apply(_a, __spreadArray([void 0], args, false)))(); }, { cache: createFastMemoizeCache(cache.pluralRules), strategy: strategies.variadic, }), }; } var IntlMessageFormat = /** @class */ (function () { function IntlMessageFormat(message, locales, overrideFormats, opts) { if (locales === void 0) { locales = IntlMessageFormat.defaultLocale; } var _this = this; this.formatterCache = { number: {}, dateTime: {}, pluralRules: {}, }; this.format = function (values) { var parts = _this.formatToParts(values); // Hot path for straight simple msg translations if (parts.length === 1) { return parts[0].value; } var result = parts.reduce(function (all, part) { if (!all.length || part.type !== PART_TYPE.literal || typeof all[all.length - 1] !== 'string') { all.push(part.value); } else { all[all.length - 1] += part.value; } return all; }, []); if (result.length <= 1) { return result[0] || ''; } return result; }; this.formatToParts = function (values) { return formatToParts(_this.ast, _this.locales, _this.formatters, _this.formats, values, undefined, _this.message); }; this.resolvedOptions = function () { var _a; return ({ locale: ((_a = _this.resolvedLocale) === null || _a === void 0 ? void 0 : _a.toString()) || Intl.NumberFormat.supportedLocalesOf(_this.locales)[0], }); }; this.getAst = function () { return _this.ast; }; // Defined first because it's used to build the format pattern. this.locales = locales; this.resolvedLocale = IntlMessageFormat.resolveLocale(locales); if (typeof message === 'string') { this.message = message; if (!IntlMessageFormat.__parse) { throw new TypeError('IntlMessageFormat.__parse must be set to process `message` of type `string`'); } var _a = opts || {}, formatters = _a.formatters, parseOpts = __rest(_a, ["formatters"]); // Parse string messages into an AST. this.ast = IntlMessageFormat.__parse(message, __assign(__assign({}, parseOpts), { locale: this.resolvedLocale })); } else { this.ast = message; } if (!Array.isArray(this.ast)) { throw new TypeError('A message must be provided as a String or AST.'); } // Creates a new object with the specified `formats` merged with the default // formats. this.formats = mergeConfigs(IntlMessageFormat.formats, overrideFormats); this.formatters = (opts && opts.formatters) || createDefaultFormatters(this.formatterCache); } Object.defineProperty(IntlMessageFormat, "defaultLocale", { get: function () { if (!IntlMessageFormat.memoizedDefaultLocale) { IntlMessageFormat.memoizedDefaultLocale = new Intl.NumberFormat().resolvedOptions().locale; } return IntlMessageFormat.memoizedDefaultLocale; }, enumerable: false, configurable: true }); IntlMessageFormat.memoizedDefaultLocale = null; IntlMessageFormat.resolveLocale = function (locales) { if (typeof Intl.Locale === 'undefined') { return; } var supportedLocales = Intl.NumberFormat.supportedLocalesOf(locales); if (supportedLocales.length > 0) { return new Intl.Locale(supportedLocales[0]); } return new Intl.Locale(typeof locales === 'string' ? locales : locales[0]); }; IntlMessageFormat.__parse = parse; // Default format options used as the prototype of the `formats` provided to the // constructor. These are used when constructing the internal Intl.NumberFormat // and Intl.DateTimeFormat instances. IntlMessageFormat.formats = { number: { integer: { maximumFractionDigits: 0, }, currency: { style: 'currency', }, percent: { style: 'percent', }, }, date: { short: { month: 'numeric', day: 'numeric', year: '2-digit', }, medium: { month: 'short', day: 'numeric', year: 'numeric', }, long: { month: 'long', day: 'numeric', year: 'numeric', }, full: { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric', }, }, time: { short: { hour: 'numeric', minute: 'numeric', }, medium: { hour: 'numeric', minute: 'numeric', second: 'numeric', }, long: { hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short', }, full: { hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short', }, }, }; return IntlMessageFormat; }()); export { IntlMessageFormat };