@ultraq/icu-message-formatter 0.12.0 → 0.13.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,21 +1,9 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
6
- var _classCallCheck = require('@babel/runtime/helpers/classCallCheck');
7
- var _createClass = require('@babel/runtime/helpers/createClass');
8
3
  var _defineProperty = require('@babel/runtime/helpers/defineProperty');
9
4
  var arrayUtils = require('@ultraq/array-utils');
10
5
  var functionUtils = require('@ultraq/function-utils');
11
6
 
12
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
-
14
- var _slicedToArray__default = /*#__PURE__*/_interopDefaultLegacy(_slicedToArray);
15
- var _classCallCheck__default = /*#__PURE__*/_interopDefaultLegacy(_classCallCheck);
16
- var _createClass__default = /*#__PURE__*/_interopDefaultLegacy(_createClass);
17
- var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
18
-
19
7
  /*
20
8
  * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)
21
9
  *
@@ -33,389 +21,380 @@ var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_definePropert
33
21
  */
34
22
 
35
23
  /**
36
- * Most branch-based type handlers are based around "cases".
37
- * For example, `select` and `plural` compare compare a value
38
- * to "case keys" to choose a subtranslation.
24
+ * @typedef ParseCasesResult
25
+ * @property {string[]} args
26
+ * A list of prepended arguments.
27
+ * @property {Record<string,string>} cases
28
+ * A map of all cases.
29
+ */
30
+
31
+ /**
32
+ * Most branch-based type handlers are based around "cases". For example,
33
+ * `select` and `plural` compare compare a value to "case keys" to choose a
34
+ * subtranslation.
39
35
  *
40
- * This util splits "matches" portions provided to the aforementioned
41
- * handlers into case strings, and extracts any prepended arguments
42
- * (for example, `plural` supports an `offset:n` argument used for
43
- * populating the magic `#` variable).
36
+ * This util splits "matches" portions provided to the aforementioned handlers
37
+ * into case strings, and extracts any prepended arguments (for example,
38
+ * `plural` supports an `offset:n` argument used for populating the magic `#`
39
+ * variable).
44
40
  *
45
- * @param {String} string
46
- * @return {Object} The `cases` key points to a map of all cases.
47
- * The `arguments` key points to a list of prepended arguments.
41
+ * @param {string} string
42
+ * @return {ParseCasesResult}
48
43
  */
49
44
  function parseCases(string) {
50
- var isWhitespace = function isWhitespace(ch) {
51
- return /\s/.test(ch);
52
- };
53
-
54
- var args = [];
55
- var cases = {};
56
- var currTermStart = 0;
57
- var latestTerm = null;
58
- var inTerm = false;
59
- var i = 0;
60
-
45
+ const isWhitespace = ch => /\s/.test(ch);
46
+ const args = [];
47
+ const cases = {};
48
+ let currTermStart = 0;
49
+ let latestTerm = null;
50
+ let inTerm = false;
51
+ let i = 0;
61
52
  while (i < string.length) {
62
53
  // Term ended
63
54
  if (inTerm && (isWhitespace(string[i]) || string[i] === '{')) {
64
55
  inTerm = false;
65
- latestTerm = string.slice(currTermStart, i); // We want to process the opening char again so the case will be properly registered.
56
+ latestTerm = string.slice(currTermStart, i);
66
57
 
58
+ // We want to process the opening char again so the case will be properly registered.
67
59
  if (string[i] === '{') {
68
60
  i--;
69
61
  }
70
- } // New term
62
+ }
63
+
64
+ // New term
71
65
  else if (!inTerm && !isWhitespace(string[i])) {
72
- var caseBody = string[i] === '{'; // If there's a previous term, we can either handle a whole
73
- // case, or add that as an argument.
66
+ const caseBody = string[i] === '{';
74
67
 
68
+ // If there's a previous term, we can either handle a whole
69
+ // case, or add that as an argument.
75
70
  if (latestTerm && caseBody) {
76
- var branchEndIndex = findClosingBracket(string, i);
77
-
71
+ const branchEndIndex = findClosingBracket(string, i);
78
72
  if (branchEndIndex === -1) {
79
- throw new Error("Unbalanced curly braces in string: \"".concat(string, "\""));
73
+ throw new Error(`Unbalanced curly braces in string: "${string}"`);
80
74
  }
81
-
82
75
  cases[latestTerm] = string.slice(i + 1, branchEndIndex); // Don't include the braces
83
76
 
84
77
  i = branchEndIndex; // Will be moved up where needed at end of loop.
85
-
86
78
  latestTerm = null;
87
79
  } else {
88
80
  if (latestTerm) {
89
81
  args.push(latestTerm);
90
82
  latestTerm = null;
91
83
  }
92
-
93
84
  inTerm = true;
94
85
  currTermStart = i;
95
86
  }
96
87
  }
97
-
98
88
  i++;
99
89
  }
100
-
101
90
  if (inTerm) {
102
91
  latestTerm = string.slice(currTermStart);
103
92
  }
104
-
105
93
  if (latestTerm) {
106
94
  args.push(latestTerm);
107
95
  }
108
-
109
96
  return {
110
- args: args,
111
- cases: cases
97
+ args,
98
+ cases
112
99
  };
113
100
  }
101
+
114
102
  /**
115
103
  * Finds the index of the matching closing curly bracket, including through
116
104
  * strings that could have nested brackets.
117
105
  *
118
- * @param {String} string
119
- * @param {Number} fromIndex
120
- * @return {Number} The index of the matching closing bracket, or -1 if no
121
- * closing bracket could be found.
106
+ * @param {string} string
107
+ * @param {number} fromIndex
108
+ * @return {number}
109
+ * The index of the matching closing bracket, or -1 if no closing bracket
110
+ * could be found.
122
111
  */
123
-
124
112
  function findClosingBracket(string, fromIndex) {
125
- var depth = 0;
126
-
127
- for (var i = fromIndex + 1; i < string.length; i++) {
128
- var char = string.charAt(i);
129
-
113
+ let depth = 0;
114
+ for (let i = fromIndex + 1; i < string.length; i++) {
115
+ let char = string.charAt(i);
130
116
  if (char === '}') {
131
117
  if (depth === 0) {
132
118
  return i;
133
119
  }
134
-
135
120
  depth--;
136
121
  } else if (char === '{') {
137
122
  depth++;
138
123
  }
139
124
  }
140
-
141
125
  return -1;
142
126
  }
127
+
143
128
  /**
144
129
  * Split a `{key, type, format}` block into those 3 parts, taking into account
145
130
  * nested message syntax that can exist in the `format` part.
146
131
  *
147
- * @param {String} block
148
- * @return {Array}
132
+ * @param {string} block
133
+ * @return {string[]}
149
134
  * An array with `key`, `type`, and `format` items in that order, if present
150
135
  * in the formatted argument block.
151
136
  */
152
-
153
137
  function splitFormattedArgument(block) {
154
138
  return split(block.slice(1, -1), ',', 3);
155
139
  }
140
+
156
141
  /**
157
142
  * Like `String.prototype.split()` but where the limit parameter causes the
158
143
  * remainder of the string to be grouped together in a final entry.
159
144
  *
160
145
  * @private
161
- * @param {String} string
162
- * @param {String} separator
163
- * @param {Number} limit
164
- * @param {Array} [accumulator=[]]
165
- * @return {Array}
146
+ * @param {string} string
147
+ * @param {string} separator
148
+ * @param {number} limit
149
+ * @param {string[]} accumulator
150
+ * @return {string[]}
166
151
  */
167
-
168
152
  function split(string, separator, limit) {
169
- var accumulator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
170
-
153
+ let accumulator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
171
154
  if (!string) {
172
155
  return accumulator;
173
156
  }
174
-
175
157
  if (limit === 1) {
176
158
  accumulator.push(string);
177
159
  return accumulator;
178
160
  }
179
-
180
- var indexOfDelimiter = string.indexOf(separator);
181
-
161
+ let indexOfDelimiter = string.indexOf(separator);
182
162
  if (indexOfDelimiter === -1) {
183
163
  accumulator.push(string);
184
164
  return accumulator;
185
165
  }
186
-
187
- var head = string.substring(0, indexOfDelimiter).trim();
188
- var tail = string.substring(indexOfDelimiter + separator.length + 1).trim();
166
+ let head = string.substring(0, indexOfDelimiter).trim();
167
+ let tail = string.substring(indexOfDelimiter + separator.length + 1).trim();
189
168
  accumulator.push(head);
190
169
  return split(tail, separator, limit - 1, accumulator);
191
170
  }
192
171
 
172
+ /**
173
+ * @typedef {Record<string,any>} FormatValues
174
+ */
175
+
176
+ /**
177
+ * @callback ProcessFunction
178
+ * @param {string} message
179
+ * @param {FormatValues} [values={}]
180
+ * @return {any[]}
181
+ */
182
+
183
+ /**
184
+ * @callback TypeHandler
185
+ * @param {any} value
186
+ * The object which matched the key of the block being processed.
187
+ * @param {string} matches
188
+ * Any format options associated with the block being processed.
189
+ * @param {string} locale
190
+ * The locale to use for formatting.
191
+ * @param {FormatValues} values
192
+ * The object of placeholder data given to the original `format`/`process`
193
+ * call.
194
+ * @param {ProcessFunction} process
195
+ * The `process` function itself so that sub-messages can be processed by type
196
+ * handlers.
197
+ * @return {any | any[]}
198
+ */
199
+
193
200
  /**
194
201
  * The main class for formatting messages.
195
202
  *
196
203
  * @author Emanuel Rabina
197
204
  */
198
-
199
- var MessageFormatter = /*#__PURE__*/function () {
205
+ class MessageFormatter {
200
206
  /**
201
207
  * Creates a new formatter that can work using any of the custom type handlers
202
208
  * you register.
203
209
  *
204
- * @param {String} locale
205
- * @param {Object} [typeHandlers={}]
210
+ * @param {string} locale
211
+ * @param {Record<string,TypeHandler>} [typeHandlers]
206
212
  * Optional object where the keys are the names of the types to register,
207
213
  * their values being the functions that will return a nicely formatted
208
214
  * string for the data and locale they are given.
209
215
  */
210
- function MessageFormatter(locale) {
216
+ constructor(locale) {
211
217
  var _this = this;
212
-
213
- var typeHandlers = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
214
-
215
- _classCallCheck__default["default"](this, MessageFormatter);
216
-
217
- _defineProperty__default["default"](this, "format", functionUtils.memoize(function (message) {
218
- var values = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
218
+ let typeHandlers = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
219
+ /**
220
+ * Formats an ICU message syntax string using `values` for placeholder data
221
+ * and any currently-registered type handlers.
222
+ *
223
+ * @type {(message: string, values?: FormatValues) => string}
224
+ */
225
+ _defineProperty(this, "format", functionUtils.memoize(function (message) {
226
+ let values = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
219
227
  return arrayUtils.flatten(_this.process(message, values)).join('');
220
228
  }));
221
-
222
229
  this.locale = locale;
223
230
  this.typeHandlers = typeHandlers;
224
231
  }
225
232
  /**
226
- * Formats an ICU message syntax string using `values` for placeholder data
227
- * and any currently-registered type handlers.
233
+ * Process an ICU message syntax string using `values` for placeholder data
234
+ * and any currently-registered type handlers. The result of this method is
235
+ * an array of the component parts after they have been processed in turn by
236
+ * their own type handlers. This raw output is useful for other renderers,
237
+ * eg: React where components can be used instead of being forced to return
238
+ * raw strings.
228
239
  *
229
- * @param {String} message
230
- * @param {Object} [values={}]
231
- * @return {String}
240
+ * This method is used by {@link MessageFormatter#format} where it acts as a
241
+ * string renderer.
242
+ *
243
+ * @param {string} message
244
+ * @param {FormatValues} [values]
245
+ * @return {any[]}
232
246
  */
233
-
234
-
235
- _createClass__default["default"](MessageFormatter, [{
236
- key: "process",
237
- value:
238
- /**
239
- * Process an ICU message syntax string using `values` for placeholder data
240
- * and any currently-registered type handlers. The result of this method is
241
- * an array of the component parts after they have been processed in turn by
242
- * their own type handlers. This raw output is useful for other renderers,
243
- * eg: React where components can be used instead of being forced to return
244
- * raw strings.
245
- *
246
- * This method is used by {@link MessageFormatter#format} where it acts as a
247
- * string renderer.
248
- *
249
- * @param {String} message
250
- * @param {Object} [values={}]
251
- * @return {Array}
252
- */
253
- function process(message) {
254
- var values = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
255
-
256
- if (!message) {
257
- return [];
258
- }
259
-
260
- var blockStartIndex = message.indexOf('{');
261
-
262
- if (blockStartIndex !== -1) {
263
- var blockEndIndex = findClosingBracket(message, blockStartIndex);
264
-
265
- if (blockEndIndex !== -1) {
266
- var block = message.substring(blockStartIndex, blockEndIndex + 1);
267
-
268
- if (block) {
269
- var result = [];
270
- var head = message.substring(0, blockStartIndex);
271
-
272
- if (head) {
273
- result.push(head);
274
- }
275
-
276
- var _splitFormattedArgume = splitFormattedArgument(block),
277
- _splitFormattedArgume2 = _slicedToArray__default["default"](_splitFormattedArgume, 3),
278
- key = _splitFormattedArgume2[0],
279
- type = _splitFormattedArgume2[1],
280
- format = _splitFormattedArgume2[2];
281
-
282
- var body = values[key];
283
-
284
- if (body === null || body === undefined) {
285
- body = '';
286
- }
287
-
288
- var typeHandler = type && this.typeHandlers[type];
289
- result.push(typeHandler ? typeHandler(body, format, this.locale, values, this.process.bind(this)) : body);
290
- var tail = message.substring(blockEndIndex + 1);
291
-
292
- if (tail) {
293
- result.push(this.process(tail, values));
294
- }
295
-
296
- return result;
247
+ process(message) {
248
+ let values = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
249
+ if (!message) {
250
+ return [];
251
+ }
252
+ let blockStartIndex = message.indexOf('{');
253
+ if (blockStartIndex !== -1) {
254
+ let blockEndIndex = findClosingBracket(message, blockStartIndex);
255
+ if (blockEndIndex !== -1) {
256
+ let block = message.substring(blockStartIndex, blockEndIndex + 1);
257
+ if (block) {
258
+ let result = [];
259
+ let head = message.substring(0, blockStartIndex);
260
+ if (head) {
261
+ result.push(head);
262
+ }
263
+ let [key, type, format] = splitFormattedArgument(block);
264
+ let body = values[key];
265
+ if (body === null || body === undefined) {
266
+ body = '';
297
267
  }
298
- } else {
299
- throw new Error("Unbalanced curly braces in string: \"".concat(message, "\""));
268
+ let typeHandler = type && this.typeHandlers[type];
269
+ result.push(typeHandler ? typeHandler(body, format, this.locale, values, this.process.bind(this)) : body);
270
+ let tail = message.substring(blockEndIndex + 1);
271
+ if (tail) {
272
+ result.push(this.process(tail, values));
273
+ }
274
+ return result;
300
275
  }
276
+ } else {
277
+ throw new Error(`Unbalanced curly braces in string: "${message}"`);
301
278
  }
302
-
303
- return [message];
304
279
  }
305
- }]);
280
+ return [message];
281
+ }
282
+ }
306
283
 
307
- return MessageFormatter;
308
- }();
284
+ /*
285
+ * Copyright 2019, Emanuel Rabina (http://www.ultraq.net.nz/)
286
+ *
287
+ * Licensed under the Apache License, Version 2.0 (the "License");
288
+ * you may not use this file except in compliance with the License.
289
+ * You may obtain a copy of the License at
290
+ *
291
+ * http://www.apache.org/licenses/LICENSE-2.0
292
+ *
293
+ * Unless required by applicable law or agreed to in writing, software
294
+ * distributed under the License is distributed on an "AS IS" BASIS,
295
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
296
+ * See the License for the specific language governing permissions and
297
+ * limitations under the License.
298
+ */
309
299
 
310
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
300
+ let pluralFormatter;
301
+ let keyCounter = 0;
311
302
 
312
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
313
- var pluralFormatter;
314
- var keyCounter = 0; // All the special keywords that can be used in `plural` blocks for the various branches
303
+ // All the special keywords that can be used in `plural` blocks for the various branches
304
+ const ONE = 'one';
305
+ const OTHER$1 = 'other';
315
306
 
316
- var ONE = 'one';
317
- var OTHER$1 = 'other';
318
307
  /**
319
308
  * @private
320
- * @param {String} caseBody
321
- * @param {Number} value
322
- * @return {Object} {caseBody: string, numberValues: object}
309
+ * @param {string} caseBody
310
+ * @param {number} value
311
+ * @return {{caseBody: string, numberValues: object}}
323
312
  */
324
-
325
313
  function replaceNumberSign(caseBody, value) {
326
- var i = 0;
327
- var output = '';
328
- var numBraces = 0;
329
- var numberValues = {};
330
-
314
+ let i = 0;
315
+ let output = '';
316
+ let numBraces = 0;
317
+ const numberValues = {};
331
318
  while (i < caseBody.length) {
332
319
  if (caseBody[i] === '#' && !numBraces) {
333
- var keyParam = "__hashToken".concat(keyCounter++);
334
- output += "{".concat(keyParam, ", number}");
320
+ let keyParam = `__hashToken${keyCounter++}`;
321
+ output += `{${keyParam}, number}`;
335
322
  numberValues[keyParam] = value;
336
323
  } else {
337
324
  output += caseBody[i];
338
325
  }
339
-
340
326
  if (caseBody[i] === '{') {
341
327
  numBraces++;
342
328
  } else if (caseBody[i] === '}') {
343
329
  numBraces--;
344
330
  }
345
-
346
331
  i++;
347
332
  }
348
-
349
333
  return {
350
334
  caseBody: output,
351
- numberValues: numberValues
335
+ numberValues
352
336
  };
353
337
  }
338
+
354
339
  /**
355
340
  * Handler for `plural` statements within ICU message syntax strings. Returns
356
341
  * a formatted string for the branch that closely matches the current value.
357
342
  *
358
343
  * See https://formatjs.io/docs/core-concepts/icu-syntax#plural-format for more
359
344
  * details on how the `plural` statement works.
360
- *
361
- * @param {String} value
362
- * @param {String} matches
363
- * @param {String} locale
364
- * @param {String} values
365
- * @param {Function} format
366
- * @return {String}
345
+ *
346
+ * @param {string} value
347
+ * @param {string} matches
348
+ * @param {string} locale
349
+ * @param {Record<string,any>} values
350
+ * @param {(message: string, values?: Record<string,any>) => any[]} process
351
+ * @return {any | any[]}
367
352
  */
368
-
369
-
370
353
  function pluralTypeHandler(value) {
371
- var matches = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
372
- var locale = arguments.length > 2 ? arguments[2] : undefined;
373
- var values = arguments.length > 3 ? arguments[3] : undefined;
374
- var format = arguments.length > 4 ? arguments[4] : undefined;
375
-
376
- var _parseCases = parseCases(matches),
377
- args = _parseCases.args,
378
- cases = _parseCases.cases;
379
-
380
- var intValue = parseInt(value);
381
- args.forEach(function (arg) {
354
+ let matches = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
355
+ let locale = arguments.length > 2 ? arguments[2] : undefined;
356
+ let values = arguments.length > 3 ? arguments[3] : undefined;
357
+ let process = arguments.length > 4 ? arguments[4] : undefined;
358
+ const {
359
+ args,
360
+ cases
361
+ } = parseCases(matches);
362
+ let intValue = parseInt(value);
363
+ args.forEach(arg => {
382
364
  if (arg.startsWith('offset:')) {
383
365
  intValue -= parseInt(arg.slice('offset:'.length));
384
366
  }
385
367
  });
386
- var keywordPossibilities = [];
387
-
368
+ const keywordPossibilities = [];
388
369
  if ('PluralRules' in Intl) {
389
370
  // Effectively memoize because instantiation of `Int.*` objects is expensive.
390
371
  if (pluralFormatter === undefined || pluralFormatter.resolvedOptions().locale !== locale) {
391
372
  pluralFormatter = new Intl.PluralRules(locale);
392
373
  }
374
+ const pluralKeyword = pluralFormatter.select(intValue);
393
375
 
394
- var pluralKeyword = pluralFormatter.select(intValue); // Other is always added last with least priority, so we don't want to add it here.
395
-
376
+ // Other is always added last with least priority, so we don't want to add it here.
396
377
  if (pluralKeyword !== OTHER$1) {
397
378
  keywordPossibilities.push(pluralKeyword);
398
379
  }
399
380
  }
400
-
401
381
  if (intValue === 1) {
402
382
  keywordPossibilities.push(ONE);
403
383
  }
404
-
405
- keywordPossibilities.push("=".concat(intValue), OTHER$1);
406
-
407
- for (var i = 0; i < keywordPossibilities.length; i++) {
408
- var keyword = keywordPossibilities[i];
409
-
384
+ keywordPossibilities.push(`=${intValue}`, OTHER$1);
385
+ for (let i = 0; i < keywordPossibilities.length; i++) {
386
+ const keyword = keywordPossibilities[i];
410
387
  if (keyword in cases) {
411
- var _replaceNumberSign = replaceNumberSign(cases[keyword], intValue),
412
- caseBody = _replaceNumberSign.caseBody,
413
- numberValues = _replaceNumberSign.numberValues;
414
-
415
- return format(caseBody, _objectSpread(_objectSpread({}, values), numberValues));
388
+ const {
389
+ caseBody,
390
+ numberValues
391
+ } = replaceNumberSign(cases[keyword], intValue);
392
+ return process(caseBody, {
393
+ ...values,
394
+ ...numberValues
395
+ });
416
396
  }
417
397
  }
418
-
419
398
  return value;
420
399
  }
421
400
 
@@ -434,7 +413,9 @@ function pluralTypeHandler(value) {
434
413
  * See the License for the specific language governing permissions and
435
414
  * limitations under the License.
436
415
  */
437
- var OTHER = 'other';
416
+
417
+ const OTHER = 'other';
418
+
438
419
  /**
439
420
  * Handler for `select` statements within ICU message syntax strings. Returns
440
421
  * a formatted string for the branch that closely matches the current value.
@@ -442,28 +423,25 @@ var OTHER = 'other';
442
423
  * See https://formatjs.io/docs/core-concepts/icu-syntax#select-format for more
443
424
  * details on how the `select` statement works.
444
425
  *
445
- * @param {String} value
446
- * @param {String} matches
447
- * @param {String} locale
448
- * @param {String} values
449
- * @param {Function} format
450
- * @return {String}
426
+ * @param {string} value
427
+ * @param {string} matches
428
+ * @param {string} locale
429
+ * @param {Record<string,any>} values
430
+ * @param {(message: string, values?: Record<string,any>) => any[]} process
431
+ * @return {any | any[]}
451
432
  */
452
-
453
433
  function selectTypeHandler(value) {
454
- var matches = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
455
- var values = arguments.length > 3 ? arguments[3] : undefined;
456
- var format = arguments.length > 4 ? arguments[4] : undefined;
457
-
458
- var _parseCases = parseCases(matches),
459
- cases = _parseCases.cases;
460
-
434
+ let matches = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
435
+ let values = arguments.length > 3 ? arguments[3] : undefined;
436
+ let process = arguments.length > 4 ? arguments[4] : undefined;
437
+ const {
438
+ cases
439
+ } = parseCases(matches);
461
440
  if (value in cases) {
462
- return format(cases[value], values);
441
+ return process(cases[value], values);
463
442
  } else if (OTHER in cases) {
464
- return format(cases[OTHER], values);
443
+ return process(cases[OTHER], values);
465
444
  }
466
-
467
445
  return value;
468
446
  }
469
447