@intlify/core-base 11.2.8 → 11.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * core-base v11.2.8
3
- * (c) 2025 kazuya kawaguchi
2
+ * core-base v11.3.0
3
+ * (c) 2026 kazuya kawaguchi
4
4
  * Released under the MIT License.
5
5
  */
6
6
  'use strict';
@@ -671,6 +671,7 @@ function resolveValue(obj, path) {
671
671
  }
672
672
  // resolve path value
673
673
  const len = hit.length;
674
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- for generic object
674
675
  let last = obj;
675
676
  let i = 0;
676
677
  while (i < len) {
@@ -683,6 +684,12 @@ function resolveValue(obj, path) {
683
684
  if (AST_NODE_PROPS_KEYS.includes(key) && isMessageAST(last)) {
684
685
  return null;
685
686
  }
687
+ if (!shared.isObject(last)) {
688
+ return null;
689
+ }
690
+ if (!shared.hasOwn(last, key)) {
691
+ return null;
692
+ }
686
693
  const val = last[key];
687
694
  if (val === undefined) {
688
695
  return null;
@@ -703,9 +710,11 @@ const CoreWarnCodes = {
703
710
  FALLBACK_TO_NUMBER_FORMAT: 4,
704
711
  CANNOT_FORMAT_DATE: 5,
705
712
  FALLBACK_TO_DATE_FORMAT: 6,
706
- EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER: 7
713
+ EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER: 7,
714
+ INVALID_NUMBER_ARGUMENT: 8,
715
+ INVALID_DATE_ARGUMENT: 9
707
716
  };
708
- const CORE_WARN_CODES_EXTEND_POINT = 8;
717
+ const CORE_WARN_CODES_EXTEND_POINT = 10;
709
718
  /** @internal */
710
719
  const warnMessages = {
711
720
  [CoreWarnCodes.NOT_FOUND_KEY]: `Not found '{key}' key in '{locale}' locale messages.`,
@@ -714,7 +723,9 @@ const warnMessages = {
714
723
  [CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT]: `Fall back to number format '{key}' key with '{target}' locale.`,
715
724
  [CoreWarnCodes.CANNOT_FORMAT_DATE]: `Cannot format a date value due to not supported Intl.DateTimeFormat.`,
716
725
  [CoreWarnCodes.FALLBACK_TO_DATE_FORMAT]: `Fall back to datetime format '{key}' key with '{target}' locale.`,
717
- [CoreWarnCodes.EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER]: `This project is using Custom Message Compiler, which is an experimental feature. It may receive breaking changes or be removed in the future.`
726
+ [CoreWarnCodes.EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER]: `This project is using Custom Message Compiler, which is an experimental feature. It may receive breaking changes or be removed in the future.`,
727
+ [CoreWarnCodes.INVALID_NUMBER_ARGUMENT]: `Invalid argument for number formatting: expected a number but received '{value}'.`,
728
+ [CoreWarnCodes.INVALID_DATE_ARGUMENT]: `Invalid argument for datetime formatting: expected a Date, number, or ISO string but received '{value}'.`
718
729
  };
719
730
  function getWarnMessage(code, ...args) {
720
731
  return shared.format(warnMessages[code], ...args);
@@ -725,7 +736,7 @@ function getWarnMessage(code, ...args) {
725
736
  * Intlify core-base version
726
737
  * @internal
727
738
  */
728
- const VERSION = '11.2.8';
739
+ const VERSION = '11.3.0';
729
740
  const NOT_REOSLVED = -1;
730
741
  const DEFAULT_LOCALE = 'en-US';
731
742
  const MISSING_RESOLVE_VALUE = '';
@@ -950,6 +961,9 @@ function isImplicitFallback(targetLocale, locales) {
950
961
  function datetime(context, ...args) {
951
962
  const { datetimeFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
952
963
  const { __datetimeFormatters } = context;
964
+ if (!shared.isString(args[0]) && !shared.isDate(args[0]) && !shared.isNumber(args[0])) {
965
+ return MISSING_RESOLVE_VALUE;
966
+ }
953
967
  const [key, value, options, overrides] = parseDateTimeArgs(...args);
954
968
  const missingWarn = shared.isBoolean(options.missingWarn)
955
969
  ? options.missingWarn
@@ -962,7 +976,7 @@ function datetime(context, ...args) {
962
976
  const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
963
977
  fallbackLocale, locale);
964
978
  if (!shared.isString(key) || key === '') {
965
- return new Intl.DateTimeFormat(locale, overrides).format(value);
979
+ return new Intl.DateTimeFormat(locale.replace(/!/g, ''), overrides).format(value);
966
980
  }
967
981
  // resolve format
968
982
  let datetimeFormat = {};
@@ -1097,6 +1111,9 @@ function clearDateTimeFormat(ctx, locale, format) {
1097
1111
  function number(context, ...args) {
1098
1112
  const { numberFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
1099
1113
  const { __numberFormatters } = context;
1114
+ if (!shared.isNumber(args[0])) {
1115
+ return MISSING_RESOLVE_VALUE;
1116
+ }
1100
1117
  const [key, value, options, overrides] = parseNumberArgs(...args);
1101
1118
  const missingWarn = shared.isBoolean(options.missingWarn)
1102
1119
  ? options.missingWarn
@@ -1109,7 +1126,7 @@ function number(context, ...args) {
1109
1126
  const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
1110
1127
  fallbackLocale, locale);
1111
1128
  if (!shared.isString(key) || key === '') {
1112
- return new Intl.NumberFormat(locale, overrides).format(value);
1129
+ return new Intl.NumberFormat(locale.replace(/!/g, ''), overrides).format(value);
1113
1130
  }
1114
1131
  // resolve format
1115
1132
  let numberFormat = {};
@@ -1215,59 +1232,43 @@ const DEFAULT_NORMALIZE = (values) => values.length === 0 ? '' : shared.join(val
1215
1232
  const DEFAULT_INTERPOLATE = shared.toDisplayString;
1216
1233
  function pluralDefault(choice, choicesLength) {
1217
1234
  choice = Math.abs(choice);
1235
+ // singular (0) | plural (1)
1218
1236
  if (choicesLength === 2) {
1219
1237
  // prettier-ignore
1220
- return choice
1221
- ? choice > 1
1222
- ? 1
1223
- : 0
1238
+ return choice === 1
1239
+ ? 0
1224
1240
  : 1;
1225
1241
  }
1226
- return choice ? Math.min(choice, 2) : 0;
1242
+ // zero (0) | singular (1) | plural (2)
1243
+ return Math.min(choice, 2);
1227
1244
  }
1228
1245
  function getPluralIndex(options) {
1229
1246
  // prettier-ignore
1230
1247
  const index = shared.isNumber(options.pluralIndex)
1231
1248
  ? options.pluralIndex
1232
1249
  : -1;
1233
- // prettier-ignore
1234
- return options.named && (shared.isNumber(options.named.count) || shared.isNumber(options.named.n))
1235
- ? shared.isNumber(options.named.count)
1236
- ? options.named.count
1237
- : shared.isNumber(options.named.n)
1238
- ? options.named.n
1239
- : index
1240
- : index;
1241
- }
1242
- function normalizeNamed(pluralIndex, props) {
1243
- if (!props.count) {
1244
- props.count = pluralIndex;
1245
- }
1246
- if (!props.n) {
1247
- props.n = pluralIndex;
1248
- }
1250
+ return shared.isNumber(options.named?.count)
1251
+ ? options.named.count
1252
+ : shared.isNumber(options.named?.n)
1253
+ ? options.named.n
1254
+ : index;
1249
1255
  }
1250
1256
  function createMessageContext(options = {}) {
1251
1257
  const locale = options.locale;
1252
1258
  const pluralIndex = getPluralIndex(options);
1253
- const pluralRule = shared.isObject(options.pluralRules) &&
1254
- shared.isString(locale) &&
1255
- shared.isFunction(options.pluralRules[locale])
1259
+ const pluralRule = shared.isString(locale) && shared.isFunction(options.pluralRules?.[locale])
1256
1260
  ? options.pluralRules[locale]
1257
1261
  : pluralDefault;
1258
- const orgPluralRule = shared.isObject(options.pluralRules) &&
1259
- shared.isString(locale) &&
1260
- shared.isFunction(options.pluralRules[locale])
1261
- ? pluralDefault
1262
- : undefined;
1263
- const plural = (messages) => {
1264
- return messages[pluralRule(pluralIndex, messages.length, orgPluralRule)];
1265
- };
1262
+ const orgPluralRule = pluralRule === pluralDefault ? undefined : pluralDefault;
1263
+ const plural = (messages) => messages[pluralRule(pluralIndex, messages.length, orgPluralRule)];
1266
1264
  const _list = options.list || [];
1267
1265
  const list = (index) => _list[index];
1268
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1269
- const _named = options.named || shared.create();
1270
- shared.isNumber(options.pluralIndex) && normalizeNamed(pluralIndex, _named);
1266
+ const _named = options.named || shared.create(); // eslint-disable-line @typescript-eslint/no-explicit-any
1267
+ // normalize named
1268
+ if (shared.isNumber(options.pluralIndex)) {
1269
+ _named.count ||= options.pluralIndex;
1270
+ _named.n ||= options.pluralIndex;
1271
+ }
1271
1272
  const named = (key) => _named[key];
1272
1273
  function message(key, useLinked) {
1273
1274
  // prettier-ignore
@@ -1285,14 +1286,13 @@ function createMessageContext(options = {}) {
1285
1286
  const _modifier = (name) => options.modifiers
1286
1287
  ? options.modifiers[name]
1287
1288
  : DEFAULT_MODIFIER;
1288
- const normalize = shared.isPlainObject(options.processor) && shared.isFunction(options.processor.normalize)
1289
+ const normalize = shared.isFunction(options.processor?.normalize)
1289
1290
  ? options.processor.normalize
1290
1291
  : DEFAULT_NORMALIZE;
1291
- const interpolate = shared.isPlainObject(options.processor) &&
1292
- shared.isFunction(options.processor.interpolate)
1292
+ const interpolate = shared.isFunction(options.processor?.interpolate)
1293
1293
  ? options.processor.interpolate
1294
1294
  : DEFAULT_INTERPOLATE;
1295
- const type = shared.isPlainObject(options.processor) && shared.isString(options.processor.type)
1295
+ const type = shared.isString(options.processor?.type)
1296
1296
  ? options.processor.type
1297
1297
  : DEFAULT_MESSAGE_DATA_TYPE;
1298
1298
  const linked = (key, ...args) => {
@@ -1317,11 +1317,13 @@ function createMessageContext(options = {}) {
1317
1317
  }
1318
1318
  }
1319
1319
  const ret = message(key, true)(ctx);
1320
+ // If the linked message is not resolved (empty string), fall back to the key itself
1321
+ const resolved = ret === '' || ret === undefined ? key : ret;
1320
1322
  const msg =
1321
1323
  // The message in vnode resolved with linked are returned as an array by processor.nomalize
1322
- type === 'vnode' && shared.isArray(ret) && modifier
1323
- ? ret[0]
1324
- : ret;
1324
+ type === 'vnode' && shared.isArray(resolved) && modifier
1325
+ ? resolved[0]
1326
+ : resolved;
1325
1327
  return modifier ? _modifier(modifier)(msg, type) : msg;
1326
1328
  };
1327
1329
  const ctx = {
@@ -1539,9 +1541,7 @@ function getCompileContext(context, locale, key, source, warnHtmlMessage, onErro
1539
1541
  warnHtmlMessage,
1540
1542
  onError: (err) => {
1541
1543
  onError && onError(err);
1542
- {
1543
- throw err;
1544
- }
1544
+ throw err;
1545
1545
  },
1546
1546
  onCacheKey: (source) => shared.generateFormatCacheKey(locale, key, source)
1547
1547
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlify/core-base",
3
- "version": "11.2.8",
3
+ "version": "11.3.0",
4
4
  "description": "@intlify/core-base",
5
5
  "keywords": [
6
6
  "core",
@@ -33,11 +33,9 @@
33
33
  "jsdelivr": "dist/core-base.global.js",
34
34
  "types": "dist/core-base.d.ts",
35
35
  "dependencies": {
36
- "@intlify/message-compiler": "11.2.8",
37
- "@intlify/shared": "11.2.8"
38
- },
39
- "devDependencies": {
40
- "@intlify/devtools-types": "11.2.8"
36
+ "@intlify/devtools-types": "11.3.0",
37
+ "@intlify/message-compiler": "11.3.0",
38
+ "@intlify/shared": "11.3.0"
41
39
  },
42
40
  "engines": {
43
41
  "node": ">= 16"