core-base.cjs.prod.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /*!
  2. * @intlify/core-base v9.1.9
  3. * (c) 2021 kazuya kawaguchi
  4. * Released under the MIT License.
  5. */
  6. 'use strict';
  7. Object.defineProperty(exports, '__esModule', { value: true });
  8. var messageResolver = require('@intlify/message-resolver');
  9. var runtime = require('@intlify/runtime');
  10. var messageCompiler = require('@intlify/message-compiler');
  11. var shared = require('@intlify/shared');
  12. var devtoolsIf = require('@intlify/devtools-if');
  13. let devtools = null;
  14. function setDevToolsHook(hook) {
  15. devtools = hook;
  16. }
  17. function getDevToolsHook() {
  18. return devtools;
  19. }
  20. function initI18nDevTools(i18n, version, meta) {
  21. // TODO: queue if devtools is undefined
  22. devtools &&
  23. devtools.emit(devtoolsIf.IntlifyDevToolsHooks.I18nInit, {
  24. timestamp: Date.now(),
  25. i18n,
  26. version,
  27. meta
  28. });
  29. }
  30. const translateDevTools = /* #__PURE__*/ createDevToolsHook(devtoolsIf.IntlifyDevToolsHooks.FunctionTranslate);
  31. function createDevToolsHook(hook) {
  32. return (payloads) => devtools && devtools.emit(hook, payloads);
  33. }
  34. /** @internal */
  35. const warnMessages = {
  36. [0 /* NOT_FOUND_KEY */]: `Not found '{key}' key in '{locale}' locale messages.`,
  37. [1 /* FALLBACK_TO_TRANSLATE */]: `Fall back to translate '{key}' key with '{target}' locale.`,
  38. [2 /* CANNOT_FORMAT_NUMBER */]: `Cannot format a number value due to not supported Intl.NumberFormat.`,
  39. [3 /* FALLBACK_TO_NUMBER_FORMAT */]: `Fall back to number format '{key}' key with '{target}' locale.`,
  40. [4 /* CANNOT_FORMAT_DATE */]: `Cannot format a date value due to not supported Intl.DateTimeFormat.`,
  41. [5 /* FALLBACK_TO_DATE_FORMAT */]: `Fall back to datetime format '{key}' key with '{target}' locale.`
  42. };
  43. function getWarnMessage(code, ...args) {
  44. return shared.format(warnMessages[code], ...args);
  45. }
  46. /**
  47. * Intlify core-base version
  48. * @internal
  49. */
  50. const VERSION = '9.1.9';
  51. const NOT_REOSLVED = -1;
  52. const MISSING_RESOLVE_VALUE = '';
  53. function getDefaultLinkedModifiers() {
  54. return {
  55. upper: (val) => (shared.isString(val) ? val.toUpperCase() : val),
  56. lower: (val) => (shared.isString(val) ? val.toLowerCase() : val),
  57. // prettier-ignore
  58. capitalize: (val) => (shared.isString(val)
  59. ? `${val.charAt(0).toLocaleUpperCase()}${val.substr(1)}`
  60. : val)
  61. };
  62. }
  63. let _compiler;
  64. function registerMessageCompiler(compiler) {
  65. _compiler = compiler;
  66. }
  67. // Additional Meta for Intlify DevTools
  68. let _additionalMeta = null;
  69. const setAdditionalMeta = /* #__PURE__*/ (meta) => {
  70. _additionalMeta = meta;
  71. };
  72. const getAdditionalMeta = /* #__PURE__*/ () => _additionalMeta;
  73. // ID for CoreContext
  74. let _cid = 0;
  75. function createCoreContext(options = {}) {
  76. // setup options
  77. const version = shared.isString(options.version) ? options.version : VERSION;
  78. const locale = shared.isString(options.locale) ? options.locale : 'en-US';
  79. const fallbackLocale = shared.isArray(options.fallbackLocale) ||
  80. shared.isPlainObject(options.fallbackLocale) ||
  81. shared.isString(options.fallbackLocale) ||
  82. options.fallbackLocale === false
  83. ? options.fallbackLocale
  84. : locale;
  85. const messages = shared.isPlainObject(options.messages)
  86. ? options.messages
  87. : { [locale]: {} };
  88. const datetimeFormats = shared.isPlainObject(options.datetimeFormats)
  89. ? options.datetimeFormats
  90. : { [locale]: {} };
  91. const numberFormats = shared.isPlainObject(options.numberFormats)
  92. ? options.numberFormats
  93. : { [locale]: {} };
  94. const modifiers = shared.assign({}, options.modifiers || {}, getDefaultLinkedModifiers());
  95. const pluralRules = options.pluralRules || {};
  96. const missing = shared.isFunction(options.missing) ? options.missing : null;
  97. const missingWarn = shared.isBoolean(options.missingWarn) || shared.isRegExp(options.missingWarn)
  98. ? options.missingWarn
  99. : true;
  100. const fallbackWarn = shared.isBoolean(options.fallbackWarn) || shared.isRegExp(options.fallbackWarn)
  101. ? options.fallbackWarn
  102. : true;
  103. const fallbackFormat = !!options.fallbackFormat;
  104. const unresolving = !!options.unresolving;
  105. const postTranslation = shared.isFunction(options.postTranslation)
  106. ? options.postTranslation
  107. : null;
  108. const processor = shared.isPlainObject(options.processor) ? options.processor : null;
  109. const warnHtmlMessage = shared.isBoolean(options.warnHtmlMessage)
  110. ? options.warnHtmlMessage
  111. : true;
  112. const escapeParameter = !!options.escapeParameter;
  113. const messageCompiler = shared.isFunction(options.messageCompiler)
  114. ? options.messageCompiler
  115. : _compiler;
  116. const onWarn = shared.isFunction(options.onWarn) ? options.onWarn : shared.warn;
  117. // setup internal options
  118. const internalOptions = options;
  119. const __datetimeFormatters = shared.isObject(internalOptions.__datetimeFormatters)
  120. ? internalOptions.__datetimeFormatters
  121. : new Map();
  122. const __numberFormatters = shared.isObject(internalOptions.__numberFormatters)
  123. ? internalOptions.__numberFormatters
  124. : new Map();
  125. const __meta = shared.isObject(internalOptions.__meta) ? internalOptions.__meta : {};
  126. _cid++;
  127. const context = {
  128. version,
  129. cid: _cid,
  130. locale,
  131. fallbackLocale,
  132. messages,
  133. datetimeFormats,
  134. numberFormats,
  135. modifiers,
  136. pluralRules,
  137. missing,
  138. missingWarn,
  139. fallbackWarn,
  140. fallbackFormat,
  141. unresolving,
  142. postTranslation,
  143. processor,
  144. warnHtmlMessage,
  145. escapeParameter,
  146. messageCompiler,
  147. onWarn,
  148. __datetimeFormatters,
  149. __numberFormatters,
  150. __meta
  151. };
  152. return context;
  153. }
  154. /** @internal */
  155. function isTranslateFallbackWarn(fallback, key) {
  156. return fallback instanceof RegExp ? fallback.test(key) : fallback;
  157. }
  158. /** @internal */
  159. function isTranslateMissingWarn(missing, key) {
  160. return missing instanceof RegExp ? missing.test(key) : missing;
  161. }
  162. /** @internal */
  163. function handleMissing(context, key, locale, missingWarn, type) {
  164. const { missing, onWarn } = context;
  165. if (missing !== null) {
  166. const ret = missing(context, locale, key, type);
  167. return shared.isString(ret) ? ret : key;
  168. }
  169. else {
  170. return key;
  171. }
  172. }
  173. /** @internal */
  174. function getLocaleChain(ctx, fallback, start) {
  175. const context = ctx;
  176. if (!context.__localeChainCache) {
  177. context.__localeChainCache = new Map();
  178. }
  179. let chain = context.__localeChainCache.get(start);
  180. if (!chain) {
  181. chain = [];
  182. // first block defined by start
  183. let block = [start];
  184. // while any intervening block found
  185. while (shared.isArray(block)) {
  186. block = appendBlockToChain(chain, block, fallback);
  187. }
  188. // prettier-ignore
  189. // last block defined by default
  190. const defaults = shared.isArray(fallback)
  191. ? fallback
  192. : shared.isPlainObject(fallback)
  193. ? fallback['default']
  194. ? fallback['default']
  195. : null
  196. : fallback;
  197. // convert defaults to array
  198. block = shared.isString(defaults) ? [defaults] : defaults;
  199. if (shared.isArray(block)) {
  200. appendBlockToChain(chain, block, false);
  201. }
  202. context.__localeChainCache.set(start, chain);
  203. }
  204. return chain;
  205. }
  206. function appendBlockToChain(chain, block, blocks) {
  207. let follow = true;
  208. for (let i = 0; i < block.length && shared.isBoolean(follow); i++) {
  209. const locale = block[i];
  210. if (shared.isString(locale)) {
  211. follow = appendLocaleToChain(chain, block[i], blocks);
  212. }
  213. }
  214. return follow;
  215. }
  216. function appendLocaleToChain(chain, locale, blocks) {
  217. let follow;
  218. const tokens = locale.split('-');
  219. do {
  220. const target = tokens.join('-');
  221. follow = appendItemToChain(chain, target, blocks);
  222. tokens.splice(-1, 1);
  223. } while (tokens.length && follow === true);
  224. return follow;
  225. }
  226. function appendItemToChain(chain, target, blocks) {
  227. let follow = false;
  228. if (!chain.includes(target)) {
  229. follow = true;
  230. if (target) {
  231. follow = target[target.length - 1] !== '!';
  232. const locale = target.replace(/!/g, '');
  233. chain.push(locale);
  234. if ((shared.isArray(blocks) || shared.isPlainObject(blocks)) &&
  235. blocks[locale] // eslint-disable-line @typescript-eslint/no-explicit-any
  236. ) {
  237. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  238. follow = blocks[locale];
  239. }
  240. }
  241. }
  242. return follow;
  243. }
  244. /** @internal */
  245. function updateFallbackLocale(ctx, locale, fallback) {
  246. const context = ctx;
  247. context.__localeChainCache = new Map();
  248. getLocaleChain(ctx, fallback, locale);
  249. }
  250. const defaultOnCacheKey = (source) => source;
  251. let compileCache = Object.create(null);
  252. function clearCompileCache() {
  253. compileCache = Object.create(null);
  254. }
  255. function compileToFunction(source, options = {}) {
  256. {
  257. // check caches
  258. const onCacheKey = options.onCacheKey || defaultOnCacheKey;
  259. const key = onCacheKey(source);
  260. const cached = compileCache[key];
  261. if (cached) {
  262. return cached;
  263. }
  264. // compile error detecting
  265. let occurred = false;
  266. const onError = options.onError || messageCompiler.defaultOnError;
  267. options.onError = (err) => {
  268. occurred = true;
  269. onError(err);
  270. };
  271. // compile
  272. const { code } = messageCompiler.baseCompile(source, options);
  273. // evaluate function
  274. const msg = new Function(`return ${code}`)();
  275. // if occurred compile error, don't cache
  276. return !occurred ? (compileCache[key] = msg) : msg;
  277. }
  278. }
  279. function createCoreError(code) {
  280. return messageCompiler.createCompileError(code, null, undefined);
  281. }
  282. const NOOP_MESSAGE_FUNCTION = () => '';
  283. const isMessageFunction = (val) => shared.isFunction(val);
  284. // implementation of `translate` function
  285. function translate(context, ...args) {
  286. const { fallbackFormat, postTranslation, unresolving, fallbackLocale, messages } = context;
  287. const [key, options] = parseTranslateArgs(...args);
  288. const missingWarn = shared.isBoolean(options.missingWarn)
  289. ? options.missingWarn
  290. : context.missingWarn;
  291. const fallbackWarn = shared.isBoolean(options.fallbackWarn)
  292. ? options.fallbackWarn
  293. : context.fallbackWarn;
  294. const escapeParameter = shared.isBoolean(options.escapeParameter)
  295. ? options.escapeParameter
  296. : context.escapeParameter;
  297. const resolvedMessage = !!options.resolvedMessage;
  298. // prettier-ignore
  299. const defaultMsgOrKey = shared.isString(options.default) || shared.isBoolean(options.default) // default by function option
  300. ? !shared.isBoolean(options.default)
  301. ? options.default
  302. : key
  303. : fallbackFormat // default by `fallbackFormat` option
  304. ? key
  305. : '';
  306. const enableDefaultMsg = fallbackFormat || defaultMsgOrKey !== '';
  307. const locale = shared.isString(options.locale) ? options.locale : context.locale;
  308. // escape params
  309. escapeParameter && escapeParams(options);
  310. // resolve message format
  311. // eslint-disable-next-line prefer-const
  312. let [format, targetLocale, message] = !resolvedMessage
  313. ? resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn)
  314. : [
  315. key,
  316. locale,
  317. messages[locale] || {}
  318. ];
  319. // if you use default message, set it as message format!
  320. let cacheBaseKey = key;
  321. if (!resolvedMessage &&
  322. !(shared.isString(format) || isMessageFunction(format))) {
  323. if (enableDefaultMsg) {
  324. format = defaultMsgOrKey;
  325. cacheBaseKey = format;
  326. }
  327. }
  328. // checking message format and target locale
  329. if (!resolvedMessage &&
  330. (!(shared.isString(format) || isMessageFunction(format)) ||
  331. !shared.isString(targetLocale))) {
  332. return unresolving ? NOT_REOSLVED : key;
  333. }
  334. // setup compile error detecting
  335. let occurred = false;
  336. const errorDetector = () => {
  337. occurred = true;
  338. };
  339. // compile message format
  340. const msg = !isMessageFunction(format)
  341. ? compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, errorDetector)
  342. : format;
  343. // if occurred compile error, return the message format
  344. if (occurred) {
  345. return format;
  346. }
  347. // evaluate message with context
  348. const ctxOptions = getMessageContextOptions(context, targetLocale, message, options);
  349. const msgContext = runtime.createMessageContext(ctxOptions);
  350. const messaged = evaluateMessage(context, msg, msgContext);
  351. // if use post translation option, proceed it with handler
  352. const ret = postTranslation ? postTranslation(messaged) : messaged;
  353. return ret;
  354. }
  355. function escapeParams(options) {
  356. if (shared.isArray(options.list)) {
  357. options.list = options.list.map(item => shared.isString(item) ? shared.escapeHtml(item) : item);
  358. }
  359. else if (shared.isObject(options.named)) {
  360. Object.keys(options.named).forEach(key => {
  361. if (shared.isString(options.named[key])) {
  362. options.named[key] = shared.escapeHtml(options.named[key]);
  363. }
  364. });
  365. }
  366. }
  367. function resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn) {
  368. const { messages, onWarn } = context;
  369. const locales = getLocaleChain(context, fallbackLocale, locale);
  370. let message = {};
  371. let targetLocale;
  372. let format = null;
  373. const type = 'translate';
  374. for (let i = 0; i < locales.length; i++) {
  375. targetLocale = locales[i];
  376. message =
  377. messages[targetLocale] || {};
  378. if ((format = messageResolver.resolveValue(message, key)) === null) {
  379. // if null, resolve with object key path
  380. format = message[key]; // eslint-disable-line @typescript-eslint/no-explicit-any
  381. }
  382. if (shared.isString(format) || shared.isFunction(format))
  383. break;
  384. const missingRet = handleMissing(context, key, targetLocale, missingWarn, type);
  385. if (missingRet !== key) {
  386. format = missingRet;
  387. }
  388. }
  389. return [format, targetLocale, message];
  390. }
  391. function compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, errorDetector) {
  392. const { messageCompiler, warnHtmlMessage } = context;
  393. if (isMessageFunction(format)) {
  394. const msg = format;
  395. msg.locale = msg.locale || targetLocale;
  396. msg.key = msg.key || key;
  397. return msg;
  398. }
  399. const msg = messageCompiler(format, getCompileOptions(context, targetLocale, cacheBaseKey, format, warnHtmlMessage, errorDetector));
  400. msg.locale = targetLocale;
  401. msg.key = key;
  402. msg.source = format;
  403. return msg;
  404. }
  405. function evaluateMessage(context, msg, msgCtx) {
  406. const messaged = msg(msgCtx);
  407. return messaged;
  408. }
  409. /** @internal */
  410. function parseTranslateArgs(...args) {
  411. const [arg1, arg2, arg3] = args;
  412. const options = {};
  413. if (!shared.isString(arg1) && !shared.isNumber(arg1) && !isMessageFunction(arg1)) {
  414. throw createCoreError(14 /* INVALID_ARGUMENT */);
  415. }
  416. // prettier-ignore
  417. const key = shared.isNumber(arg1)
  418. ? String(arg1)
  419. : isMessageFunction(arg1)
  420. ? arg1
  421. : arg1;
  422. if (shared.isNumber(arg2)) {
  423. options.plural = arg2;
  424. }
  425. else if (shared.isString(arg2)) {
  426. options.default = arg2;
  427. }
  428. else if (shared.isPlainObject(arg2) && !shared.isEmptyObject(arg2)) {
  429. options.named = arg2;
  430. }
  431. else if (shared.isArray(arg2)) {
  432. options.list = arg2;
  433. }
  434. if (shared.isNumber(arg3)) {
  435. options.plural = arg3;
  436. }
  437. else if (shared.isString(arg3)) {
  438. options.default = arg3;
  439. }
  440. else if (shared.isPlainObject(arg3)) {
  441. shared.assign(options, arg3);
  442. }
  443. return [key, options];
  444. }
  445. function getCompileOptions(context, locale, key, source, warnHtmlMessage, errorDetector) {
  446. return {
  447. warnHtmlMessage,
  448. onError: (err) => {
  449. errorDetector && errorDetector(err);
  450. {
  451. throw err;
  452. }
  453. },
  454. onCacheKey: (source) => shared.generateFormatCacheKey(locale, key, source)
  455. };
  456. }
  457. function getMessageContextOptions(context, locale, message, options) {
  458. const { modifiers, pluralRules } = context;
  459. const resolveMessage = (key) => {
  460. const val = messageResolver.resolveValue(message, key);
  461. if (shared.isString(val)) {
  462. let occurred = false;
  463. const errorDetector = () => {
  464. occurred = true;
  465. };
  466. const msg = compileMessageFormat(context, key, locale, val, key, errorDetector);
  467. return !occurred
  468. ? msg
  469. : NOOP_MESSAGE_FUNCTION;
  470. }
  471. else if (isMessageFunction(val)) {
  472. return val;
  473. }
  474. else {
  475. // TODO: should be implemented warning message
  476. return NOOP_MESSAGE_FUNCTION;
  477. }
  478. };
  479. const ctxOptions = {
  480. locale,
  481. modifiers,
  482. pluralRules,
  483. messages: resolveMessage
  484. };
  485. if (context.processor) {
  486. ctxOptions.processor = context.processor;
  487. }
  488. if (options.list) {
  489. ctxOptions.list = options.list;
  490. }
  491. if (options.named) {
  492. ctxOptions.named = options.named;
  493. }
  494. if (shared.isNumber(options.plural)) {
  495. ctxOptions.pluralIndex = options.plural;
  496. }
  497. return ctxOptions;
  498. }
  499. // implementation of `datetime` function
  500. function datetime(context, ...args) {
  501. const { datetimeFormats, unresolving, fallbackLocale, onWarn } = context;
  502. const { __datetimeFormatters } = context;
  503. const [key, value, options, overrides] = parseDateTimeArgs(...args);
  504. const missingWarn = shared.isBoolean(options.missingWarn)
  505. ? options.missingWarn
  506. : context.missingWarn;
  507. shared.isBoolean(options.fallbackWarn)
  508. ? options.fallbackWarn
  509. : context.fallbackWarn;
  510. const part = !!options.part;
  511. const locale = shared.isString(options.locale) ? options.locale : context.locale;
  512. const locales = getLocaleChain(context, fallbackLocale, locale);
  513. if (!shared.isString(key) || key === '') {
  514. return new Intl.DateTimeFormat(locale).format(value);
  515. }
  516. // resolve format
  517. let datetimeFormat = {};
  518. let targetLocale;
  519. let format = null;
  520. const type = 'datetime format';
  521. for (let i = 0; i < locales.length; i++) {
  522. targetLocale = locales[i];
  523. datetimeFormat =
  524. datetimeFormats[targetLocale] || {};
  525. format = datetimeFormat[key];
  526. if (shared.isPlainObject(format))
  527. break;
  528. handleMissing(context, key, targetLocale, missingWarn, type);
  529. }
  530. // checking format and target locale
  531. if (!shared.isPlainObject(format) || !shared.isString(targetLocale)) {
  532. return unresolving ? NOT_REOSLVED : key;
  533. }
  534. let id = `${targetLocale}__${key}`;
  535. if (!shared.isEmptyObject(overrides)) {
  536. id = `${id}__${JSON.stringify(overrides)}`;
  537. }
  538. let formatter = __datetimeFormatters.get(id);
  539. if (!formatter) {
  540. formatter = new Intl.DateTimeFormat(targetLocale, shared.assign({}, format, overrides));
  541. __datetimeFormatters.set(id, formatter);
  542. }
  543. return !part ? formatter.format(value) : formatter.formatToParts(value);
  544. }
  545. /** @internal */
  546. function parseDateTimeArgs(...args) {
  547. const [arg1, arg2, arg3, arg4] = args;
  548. let options = {};
  549. let overrides = {};
  550. let value;
  551. if (shared.isString(arg1)) {
  552. // Only allow ISO strings - other date formats are often supported,
  553. // but may cause different results in different browsers.
  554. if (!/\d{4}-\d{2}-\d{2}(T.*)?/.test(arg1)) {
  555. throw createCoreError(16 /* INVALID_ISO_DATE_ARGUMENT */);
  556. }
  557. value = new Date(arg1);
  558. try {
  559. // This will fail if the date is not valid
  560. value.toISOString();
  561. }
  562. catch (e) {
  563. throw createCoreError(16 /* INVALID_ISO_DATE_ARGUMENT */);
  564. }
  565. }
  566. else if (shared.isDate(arg1)) {
  567. if (isNaN(arg1.getTime())) {
  568. throw createCoreError(15 /* INVALID_DATE_ARGUMENT */);
  569. }
  570. value = arg1;
  571. }
  572. else if (shared.isNumber(arg1)) {
  573. value = arg1;
  574. }
  575. else {
  576. throw createCoreError(14 /* INVALID_ARGUMENT */);
  577. }
  578. if (shared.isString(arg2)) {
  579. options.key = arg2;
  580. }
  581. else if (shared.isPlainObject(arg2)) {
  582. options = arg2;
  583. }
  584. if (shared.isString(arg3)) {
  585. options.locale = arg3;
  586. }
  587. else if (shared.isPlainObject(arg3)) {
  588. overrides = arg3;
  589. }
  590. if (shared.isPlainObject(arg4)) {
  591. overrides = arg4;
  592. }
  593. return [options.key || '', value, options, overrides];
  594. }
  595. /** @internal */
  596. function clearDateTimeFormat(ctx, locale, format) {
  597. const context = ctx;
  598. for (const key in format) {
  599. const id = `${locale}__${key}`;
  600. if (!context.__datetimeFormatters.has(id)) {
  601. continue;
  602. }
  603. context.__datetimeFormatters.delete(id);
  604. }
  605. }
  606. // implementation of `number` function
  607. function number(context, ...args) {
  608. const { numberFormats, unresolving, fallbackLocale, onWarn } = context;
  609. const { __numberFormatters } = context;
  610. const [key, value, options, overrides] = parseNumberArgs(...args);
  611. const missingWarn = shared.isBoolean(options.missingWarn)
  612. ? options.missingWarn
  613. : context.missingWarn;
  614. shared.isBoolean(options.fallbackWarn)
  615. ? options.fallbackWarn
  616. : context.fallbackWarn;
  617. const part = !!options.part;
  618. const locale = shared.isString(options.locale) ? options.locale : context.locale;
  619. const locales = getLocaleChain(context, fallbackLocale, locale);
  620. if (!shared.isString(key) || key === '') {
  621. return new Intl.NumberFormat(locale).format(value);
  622. }
  623. // resolve format
  624. let numberFormat = {};
  625. let targetLocale;
  626. let format = null;
  627. const type = 'number format';
  628. for (let i = 0; i < locales.length; i++) {
  629. targetLocale = locales[i];
  630. numberFormat =
  631. numberFormats[targetLocale] || {};
  632. format = numberFormat[key];
  633. if (shared.isPlainObject(format))
  634. break;
  635. handleMissing(context, key, targetLocale, missingWarn, type);
  636. }
  637. // checking format and target locale
  638. if (!shared.isPlainObject(format) || !shared.isString(targetLocale)) {
  639. return unresolving ? NOT_REOSLVED : key;
  640. }
  641. let id = `${targetLocale}__${key}`;
  642. if (!shared.isEmptyObject(overrides)) {
  643. id = `${id}__${JSON.stringify(overrides)}`;
  644. }
  645. let formatter = __numberFormatters.get(id);
  646. if (!formatter) {
  647. formatter = new Intl.NumberFormat(targetLocale, shared.assign({}, format, overrides));
  648. __numberFormatters.set(id, formatter);
  649. }
  650. return !part ? formatter.format(value) : formatter.formatToParts(value);
  651. }
  652. /** @internal */
  653. function parseNumberArgs(...args) {
  654. const [arg1, arg2, arg3, arg4] = args;
  655. let options = {};
  656. let overrides = {};
  657. if (!shared.isNumber(arg1)) {
  658. throw createCoreError(14 /* INVALID_ARGUMENT */);
  659. }
  660. const value = arg1;
  661. if (shared.isString(arg2)) {
  662. options.key = arg2;
  663. }
  664. else if (shared.isPlainObject(arg2)) {
  665. options = arg2;
  666. }
  667. if (shared.isString(arg3)) {
  668. options.locale = arg3;
  669. }
  670. else if (shared.isPlainObject(arg3)) {
  671. overrides = arg3;
  672. }
  673. if (shared.isPlainObject(arg4)) {
  674. overrides = arg4;
  675. }
  676. return [options.key || '', value, options, overrides];
  677. }
  678. /** @internal */
  679. function clearNumberFormat(ctx, locale, format) {
  680. const context = ctx;
  681. for (const key in format) {
  682. const id = `${locale}__${key}`;
  683. if (!context.__numberFormatters.has(id)) {
  684. continue;
  685. }
  686. context.__numberFormatters.delete(id);
  687. }
  688. }
  689. exports.createCompileError = messageCompiler.createCompileError;
  690. exports.MISSING_RESOLVE_VALUE = MISSING_RESOLVE_VALUE;
  691. exports.NOT_REOSLVED = NOT_REOSLVED;
  692. exports.VERSION = VERSION;
  693. exports.clearCompileCache = clearCompileCache;
  694. exports.clearDateTimeFormat = clearDateTimeFormat;
  695. exports.clearNumberFormat = clearNumberFormat;
  696. exports.compileToFunction = compileToFunction;
  697. exports.createCoreContext = createCoreContext;
  698. exports.createCoreError = createCoreError;
  699. exports.datetime = datetime;
  700. exports.getAdditionalMeta = getAdditionalMeta;
  701. exports.getDevToolsHook = getDevToolsHook;
  702. exports.getLocaleChain = getLocaleChain;
  703. exports.getWarnMessage = getWarnMessage;
  704. exports.handleMissing = handleMissing;
  705. exports.initI18nDevTools = initI18nDevTools;
  706. exports.isMessageFunction = isMessageFunction;
  707. exports.isTranslateFallbackWarn = isTranslateFallbackWarn;
  708. exports.isTranslateMissingWarn = isTranslateMissingWarn;
  709. exports.number = number;
  710. exports.parseDateTimeArgs = parseDateTimeArgs;
  711. exports.parseNumberArgs = parseNumberArgs;
  712. exports.parseTranslateArgs = parseTranslateArgs;
  713. exports.registerMessageCompiler = registerMessageCompiler;
  714. exports.setAdditionalMeta = setAdditionalMeta;
  715. exports.setDevToolsHook = setDevToolsHook;
  716. exports.translate = translate;
  717. exports.translateDevTools = translateDevTools;
  718. exports.updateFallbackLocale = updateFallbackLocale;
  719. Object.keys(messageResolver).forEach(function (k) {
  720. if (k !== 'default' && !exports.hasOwnProperty(k)) exports[k] = messageResolver[k];
  721. });
  722. Object.keys(runtime).forEach(function (k) {
  723. if (k !== 'default' && !exports.hasOwnProperty(k)) exports[k] = runtime[k];
  724. });