@odoo/o-spreadsheet 19.3.16 → 19.3.17

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.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 19.3.16
6
- * @date 2026-08-12T09:15:31.627Z
7
- * @hash 464be42
5
+ * @version 19.3.17
6
+ * @date 2026-08-21T15:31:50.940Z
7
+ * @hash cf8c614
8
8
  */
9
9
 
10
10
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
@@ -4070,6 +4070,18 @@ function toString(data) {
4070
4070
  default: return "";
4071
4071
  }
4072
4072
  }
4073
+ /**
4074
+ * Only converts the decimal separator, ignore number format such as % or dates
4075
+ */
4076
+ function toLocaleString(data, locale) {
4077
+ const value = toValue(data);
4078
+ switch (typeof value) {
4079
+ case "string": return value;
4080
+ case "number": return value.toString().replace(".", locale.decimalSeparator);
4081
+ case "boolean": return value ? "TRUE" : "FALSE";
4082
+ default: return "";
4083
+ }
4084
+ }
4073
4085
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
4074
4086
  const normalizeString = memoize(function normalizeString(str) {
4075
4087
  return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
@@ -29088,12 +29100,13 @@ var FilterMenu = class extends _odoo_owl.Component {
29088
29100
  }
29089
29101
  sortFilterZone(sortDirection) {
29090
29102
  const filterPosition = this.props.filterPosition;
29091
- const tableZone = this.table?.range.zone;
29103
+ const table = this.table;
29104
+ const tableZone = table?.range.zone;
29092
29105
  if (!filterPosition || !tableZone || tableZone.top === tableZone.bottom) return;
29093
29106
  const sheetId = this.env.model.getters.getActiveSheetId();
29094
29107
  const contentZone = {
29095
29108
  ...tableZone,
29096
- top: tableZone.top + 1
29109
+ top: tableZone.top + table.config.numberOfHeaders
29097
29110
  };
29098
29111
  const sortAnchor = {
29099
29112
  col: filterPosition.col,
@@ -77399,7 +77412,7 @@ const ARRAYTOTEXT = {
77399
77412
  else if (_format === 0) {
77400
77413
  const rowSeparator = this.locale.decimalSeparator === "," ? "/" : ",";
77401
77414
  return transposeMatrix(_array).flatMap((row) => row.map((value) => {
77402
- return isEvaluationError(value.value) ? value.value : toString(value);
77415
+ return isEvaluationError(value.value) ? value.value : toLocaleString(value, this.locale);
77403
77416
  })).join(rowSeparator);
77404
77417
  } else return new EvaluationError(_t("Format must be 0 or 1"));
77405
77418
  },
@@ -83160,7 +83173,7 @@ const CONCAT = {
83160
83173
  description: _t("Concatenation of two values."),
83161
83174
  args: [arg("value1 (string)", _t("The value to which value2 will be appended.")), arg("value2 (string)", _t("The value to append to value1."))],
83162
83175
  compute: function(value1, value2) {
83163
- return toString(value1) + toString(value2);
83176
+ return toLocaleString(value1, this.locale) + toLocaleString(value2, this.locale);
83164
83177
  },
83165
83178
  isExported: true
83166
83179
  };
@@ -84025,7 +84038,7 @@ const CLEAN = {
84025
84038
  description: _t("Remove non-printable characters from a piece of text."),
84026
84039
  args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
84027
84040
  compute: function(text) {
84028
- const _text = toString(text);
84041
+ const _text = toLocaleString(text, this.locale);
84029
84042
  let cleanedStr = "";
84030
84043
  for (const char of _text) if (char && char.charCodeAt(0) > 31) cleanedStr += char;
84031
84044
  return cleanedStr;
@@ -84036,7 +84049,7 @@ const CONCATENATE = {
84036
84049
  description: _t("Appends strings to one another."),
84037
84050
  args: [arg("string (string, range<string>, repeating)", _t("String to append in sequence."))],
84038
84051
  compute: function(...datas) {
84039
- return reduceAny(datas, (acc, a) => acc + toString(a), "");
84052
+ return reduceAny(datas, (acc, a) => acc + toLocaleString(a, this.locale), "");
84040
84053
  },
84041
84054
  isExported: true
84042
84055
  };
@@ -84044,7 +84057,7 @@ const EXACT = {
84044
84057
  description: _t("Tests whether two strings are identical."),
84045
84058
  args: [arg("string1 (string)", _t("The first string to compare.")), arg("string2 (string)", _t("The second string to compare."))],
84046
84059
  compute: function(string1, string2) {
84047
- return toString(string1) === toString(string2);
84060
+ return toLocaleString(string1, this.locale) === toLocaleString(string2, this.locale);
84048
84061
  },
84049
84062
  isExported: true
84050
84063
  };
@@ -84056,8 +84069,8 @@ const FIND = {
84056
84069
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
84057
84070
  ],
84058
84071
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
84059
- const _searchFor = toString(searchFor);
84060
- const _textToSearch = toString(textToSearch);
84072
+ const _searchFor = toLocaleString(searchFor, this.locale);
84073
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
84061
84074
  const _startingAt = toNumber(startingAt, this.locale);
84062
84075
  if (_textToSearch === "") return new EvaluationError(_t("The text_to_search must be non-empty."));
84063
84076
  if (_startingAt < 1) return new EvaluationError(_t("The starting_at (%s) must be greater than or equal to 1.", _startingAt));
@@ -84094,8 +84107,8 @@ const JOIN = {
84094
84107
  description: _t("Concatenates elements of arrays with delimiter."),
84095
84108
  args: [arg("delimiter (string)", _t("The character or string to place between each concatenated value.")), arg("value_or_array (string, range<string>, repeating)", _t("Value to be appended using delimiter."))],
84096
84109
  compute: function(delimiter, ...valuesOrArrays) {
84097
- const _delimiter = toString(delimiter);
84098
- return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toString(a), "");
84110
+ const _delimiter = toLocaleString(delimiter, this.locale);
84111
+ return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toLocaleString(a, this.locale), "");
84099
84112
  }
84100
84113
  };
84101
84114
  const LEFT = {
@@ -84104,7 +84117,7 @@ const LEFT = {
84104
84117
  compute: function(text, ...args) {
84105
84118
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
84106
84119
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
84107
- return toString(text).substring(0, _numberOfCharacters);
84120
+ return toLocaleString(text, this.locale).substring(0, _numberOfCharacters);
84108
84121
  },
84109
84122
  isExported: true
84110
84123
  };
@@ -84112,7 +84125,7 @@ const LEN = {
84112
84125
  description: _t("Length of a string."),
84113
84126
  args: [arg("text (string)", _t("The string whose length will be returned."))],
84114
84127
  compute: function(text) {
84115
- return toString(text).length;
84128
+ return toLocaleString(text, this.locale).length;
84116
84129
  },
84117
84130
  isExported: true
84118
84131
  };
@@ -84120,7 +84133,7 @@ const LOWER = {
84120
84133
  description: _t("Converts a specified string to lowercase."),
84121
84134
  args: [arg("text (string)", _t("The string to convert to lowercase."))],
84122
84135
  compute: function(text) {
84123
- return toString(text).toLowerCase();
84136
+ return toLocaleString(text, this.locale).toLowerCase();
84124
84137
  },
84125
84138
  isExported: true
84126
84139
  };
@@ -84132,7 +84145,7 @@ const MID = {
84132
84145
  arg("extract_length (number)", _t("The length of the segment to extract."))
84133
84146
  ],
84134
84147
  compute: function(text, starting_at, extract_length) {
84135
- const _text = toString(text);
84148
+ const _text = toLocaleString(text, this.locale);
84136
84149
  const _starting_at = toNumber(starting_at, this.locale);
84137
84150
  const _extract_length = toNumber(extract_length, this.locale);
84138
84151
  if (_starting_at < 1) return new EvaluationError(_t("The starting_at argument (%s) must be positive greater than one.", _starting_at.toString()));
@@ -84145,7 +84158,7 @@ const PROPER = {
84145
84158
  description: _t("Capitalizes each word in a specified string."),
84146
84159
  args: [arg("text_to_capitalize (string)", _t("The text which will be returned with the first letter of each word in uppercase and all other letters in lowercase."))],
84147
84160
  compute: function(text) {
84148
- return toString(text).replace(wordRegex, (word) => {
84161
+ return toLocaleString(text, this.locale).replace(wordRegex, (word) => {
84149
84162
  return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
84150
84163
  });
84151
84164
  },
@@ -84293,9 +84306,9 @@ const REPLACE = {
84293
84306
  compute: function(text, position, length, newText) {
84294
84307
  const _position = toNumber(position, this.locale);
84295
84308
  if (_position < 1) return new EvaluationError(_t("The position (%s) must be greater than or equal to 1.", _position));
84296
- const _text = toString(text);
84309
+ const _text = toLocaleString(text, this.locale);
84297
84310
  const _length = toNumber(length, this.locale);
84298
- const _newText = toString(newText);
84311
+ const _newText = toLocaleString(newText, this.locale);
84299
84312
  return _text.substring(0, _position - 1) + _newText + _text.substring(_position - 1 + _length);
84300
84313
  },
84301
84314
  isExported: true
@@ -84306,7 +84319,7 @@ const RIGHT = {
84306
84319
  compute: function(text, ...args) {
84307
84320
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
84308
84321
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
84309
- const _text = toString(text);
84322
+ const _text = toLocaleString(text, this.locale);
84310
84323
  const stringLength = _text.length;
84311
84324
  return _text.substring(stringLength - _numberOfCharacters, stringLength);
84312
84325
  },
@@ -84320,8 +84333,8 @@ const SEARCH = {
84320
84333
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
84321
84334
  ],
84322
84335
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
84323
- const _searchFor = toString(searchFor).toLowerCase();
84324
- const _textToSearch = toString(textToSearch).toLowerCase();
84336
+ const _searchFor = toLocaleString(searchFor, this.locale).toLowerCase();
84337
+ const _textToSearch = toLocaleString(textToSearch, this.locale).toLowerCase();
84325
84338
  const _startingAt = toNumber(startingAt, this.locale);
84326
84339
  if (_textToSearch === "") return {
84327
84340
  value: CellErrorType.GenericError,
@@ -84351,8 +84364,8 @@ const SPLIT = {
84351
84364
  arg(`remove_empty_text (boolean, default=${SPLIT_DEFAULT_REMOVE_EMPTY_TEXT})`, _t("Whether or not to remove empty text messages from the split results. The default behavior is to treat consecutive delimiters as one (if TRUE). If FALSE, empty cells values are added between consecutive delimiters."))
84352
84365
  ],
84353
84366
  compute: function(text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
84354
- const _text = toString(text);
84355
- const _delimiter = escapeRegExp(toString(delimiter));
84367
+ const _text = toLocaleString(text, this.locale);
84368
+ const _delimiter = escapeRegExp(toLocaleString(delimiter, this.locale));
84356
84369
  const _splitByEach = toBoolean(splitByEach);
84357
84370
  const _removeEmptyText = toBoolean(removeEmptyText);
84358
84371
  if (_delimiter.length <= 0) return new EvaluationError(_t("The delimiter (%s) must be not be empty.", _delimiter));
@@ -84374,10 +84387,10 @@ const SUBSTITUTE = {
84374
84387
  compute: function(textToSearch, searchFor, replaceWith, occurrenceNumber) {
84375
84388
  const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
84376
84389
  if (_occurrenceNumber < 0) return new EvaluationError(_t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber));
84377
- const _textToSearch = toString(textToSearch);
84378
- const _searchFor = toString(searchFor);
84390
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
84391
+ const _searchFor = toLocaleString(searchFor, this.locale);
84379
84392
  if (_searchFor === "") return _textToSearch;
84380
- const _replaceWith = toString(replaceWith);
84393
+ const _replaceWith = toLocaleString(replaceWith, this.locale);
84381
84394
  const reg = new RegExp(escapeRegExp(_searchFor), "g");
84382
84395
  if (_occurrenceNumber === 0) return _textToSearch.replace(reg, _replaceWith);
84383
84396
  let n = 0;
@@ -84400,10 +84413,10 @@ const TEXTJOIN = {
84400
84413
  arg("texts (string, range<string>, repeating)", _t("Text item to join."))
84401
84414
  ],
84402
84415
  compute: function(delimiter, ignoreEmpty = { value: TEXTJOIN_DEFAULT_IGNORE_EMPTY }, ...textsOrArrays) {
84403
- const _delimiter = toString(delimiter);
84416
+ const _delimiter = toLocaleString(delimiter, this.locale);
84404
84417
  const _ignoreEmpty = toBoolean(ignoreEmpty);
84405
84418
  let n = 0;
84406
- return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toString(a) === "") ? (n++ ? acc + _delimiter : "") + toString(a) : acc, "");
84419
+ return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toLocaleString(a, this.locale) === "") ? (n++ ? acc + _delimiter : "") + toLocaleString(a, this.locale) : acc, "");
84407
84420
  },
84408
84421
  isExported: true
84409
84422
  };
@@ -84456,7 +84469,7 @@ const TRIM = {
84456
84469
  description: _t("Removes space characters."),
84457
84470
  args: [arg("text (string)", _t("The text or reference to a cell containing text to be trimmed."))],
84458
84471
  compute: function(text) {
84459
- return trimContent(toString(text));
84472
+ return trimContent(toLocaleString(text, this.locale));
84460
84473
  },
84461
84474
  isExported: true
84462
84475
  };
@@ -84464,7 +84477,7 @@ const UPPER = {
84464
84477
  description: _t("Converts a specified string to uppercase."),
84465
84478
  args: [arg("text (string)", _t("The string to convert to uppercase."))],
84466
84479
  compute: function(text) {
84467
- return toString(text).toUpperCase();
84480
+ return toLocaleString(text, this.locale).toUpperCase();
84468
84481
  },
84469
84482
  isExported: true
84470
84483
  };
@@ -84561,7 +84574,7 @@ const HYPERLINK = {
84561
84574
  args: [arg("url (string)", _t("The full URL of the link enclosed in quotation marks.")), arg("link_label (string, optional)", _t("The text to display in the cell, enclosed in quotation marks."))],
84562
84575
  compute: function(url, linkLabel) {
84563
84576
  const processedUrl = toString(url).trim();
84564
- const processedLabel = toString(linkLabel) || processedUrl;
84577
+ const processedLabel = toLocaleString(linkLabel, this.locale) || processedUrl;
84565
84578
  if (processedUrl === "") return processedLabel;
84566
84579
  return markdownLink(processedLabel, processedUrl);
84567
84580
  },
@@ -84958,6 +84971,6 @@ exports.stores = stores;
84958
84971
  exports.tokenColors = tokenColors;
84959
84972
  exports.tokenize = tokenize;
84960
84973
 
84961
- __info__.version = "19.3.16";
84962
- __info__.date = "2026-08-12T09:15:31.627Z";
84963
- __info__.hash = "464be42";
84974
+ __info__.version = "19.3.17";
84975
+ __info__.date = "2026-08-21T15:31:50.940Z";
84976
+ __info__.hash = "cf8c614";
@@ -2,9 +2,9 @@
2
2
  /*
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 19.3.16
6
- * @date 2026-08-12T09:15:33.329Z
7
- * @hash 464be42
5
+ * @version 19.3.17
6
+ * @date 2026-08-21T15:31:52.347Z
7
+ * @hash cf8c614
8
8
  */
9
9
  :root {
10
10
  --os-gray-100: light-dark(#f9fafb, #1b1d26);
@@ -300,6 +300,7 @@
300
300
  .os-input {
301
301
  border-width: 0 0 1px 0;
302
302
  border-color: transparent;
303
+ border-style: solid;
303
304
  outline: none;
304
305
  text-overflow: ellipsis;
305
306
  color: var(--os-text-body);
@@ -630,6 +631,7 @@
630
631
  width: 100%;
631
632
  outline: none;
632
633
  border-color: var(--os-border-color);
634
+ border-style: solid;
633
635
  color: var(--os-gray-900);
634
636
 
635
637
  &::placeholder {
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 19.3.16
6
- * @date 2026-08-12T09:15:31.627Z
7
- * @hash 464be42
5
+ * @version 19.3.17
6
+ * @date 2026-08-21T15:31:50.940Z
7
+ * @hash cf8c614
8
8
  */
9
9
 
10
10
  import { App, Component, blockDom, markRaw, onMounted, onPatched, onWillPatch, onWillStart, onWillUnmount, onWillUpdateProps, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, whenReady, xml } from "@odoo/owl";
@@ -4069,6 +4069,18 @@ function toString(data) {
4069
4069
  default: return "";
4070
4070
  }
4071
4071
  }
4072
+ /**
4073
+ * Only converts the decimal separator, ignore number format such as % or dates
4074
+ */
4075
+ function toLocaleString(data, locale) {
4076
+ const value = toValue(data);
4077
+ switch (typeof value) {
4078
+ case "string": return value;
4079
+ case "number": return value.toString().replace(".", locale.decimalSeparator);
4080
+ case "boolean": return value ? "TRUE" : "FALSE";
4081
+ default: return "";
4082
+ }
4083
+ }
4072
4084
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
4073
4085
  const normalizeString = memoize(function normalizeString(str) {
4074
4086
  return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
@@ -29087,12 +29099,13 @@ var FilterMenu = class extends Component {
29087
29099
  }
29088
29100
  sortFilterZone(sortDirection) {
29089
29101
  const filterPosition = this.props.filterPosition;
29090
- const tableZone = this.table?.range.zone;
29102
+ const table = this.table;
29103
+ const tableZone = table?.range.zone;
29091
29104
  if (!filterPosition || !tableZone || tableZone.top === tableZone.bottom) return;
29092
29105
  const sheetId = this.env.model.getters.getActiveSheetId();
29093
29106
  const contentZone = {
29094
29107
  ...tableZone,
29095
- top: tableZone.top + 1
29108
+ top: tableZone.top + table.config.numberOfHeaders
29096
29109
  };
29097
29110
  const sortAnchor = {
29098
29111
  col: filterPosition.col,
@@ -77214,7 +77227,7 @@ const ARRAYTOTEXT = {
77214
77227
  else if (_format === 0) {
77215
77228
  const rowSeparator = this.locale.decimalSeparator === "," ? "/" : ",";
77216
77229
  return transposeMatrix(_array).flatMap((row) => row.map((value) => {
77217
- return isEvaluationError(value.value) ? value.value : toString(value);
77230
+ return isEvaluationError(value.value) ? value.value : toLocaleString(value, this.locale);
77218
77231
  })).join(rowSeparator);
77219
77232
  } else return new EvaluationError(_t("Format must be 0 or 1"));
77220
77233
  },
@@ -82975,7 +82988,7 @@ const CONCAT = {
82975
82988
  description: _t("Concatenation of two values."),
82976
82989
  args: [arg("value1 (string)", _t("The value to which value2 will be appended.")), arg("value2 (string)", _t("The value to append to value1."))],
82977
82990
  compute: function(value1, value2) {
82978
- return toString(value1) + toString(value2);
82991
+ return toLocaleString(value1, this.locale) + toLocaleString(value2, this.locale);
82979
82992
  },
82980
82993
  isExported: true
82981
82994
  };
@@ -83840,7 +83853,7 @@ const CLEAN = {
83840
83853
  description: _t("Remove non-printable characters from a piece of text."),
83841
83854
  args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
83842
83855
  compute: function(text) {
83843
- const _text = toString(text);
83856
+ const _text = toLocaleString(text, this.locale);
83844
83857
  let cleanedStr = "";
83845
83858
  for (const char of _text) if (char && char.charCodeAt(0) > 31) cleanedStr += char;
83846
83859
  return cleanedStr;
@@ -83851,7 +83864,7 @@ const CONCATENATE = {
83851
83864
  description: _t("Appends strings to one another."),
83852
83865
  args: [arg("string (string, range<string>, repeating)", _t("String to append in sequence."))],
83853
83866
  compute: function(...datas) {
83854
- return reduceAny(datas, (acc, a) => acc + toString(a), "");
83867
+ return reduceAny(datas, (acc, a) => acc + toLocaleString(a, this.locale), "");
83855
83868
  },
83856
83869
  isExported: true
83857
83870
  };
@@ -83859,7 +83872,7 @@ const EXACT = {
83859
83872
  description: _t("Tests whether two strings are identical."),
83860
83873
  args: [arg("string1 (string)", _t("The first string to compare.")), arg("string2 (string)", _t("The second string to compare."))],
83861
83874
  compute: function(string1, string2) {
83862
- return toString(string1) === toString(string2);
83875
+ return toLocaleString(string1, this.locale) === toLocaleString(string2, this.locale);
83863
83876
  },
83864
83877
  isExported: true
83865
83878
  };
@@ -83871,8 +83884,8 @@ const FIND = {
83871
83884
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
83872
83885
  ],
83873
83886
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
83874
- const _searchFor = toString(searchFor);
83875
- const _textToSearch = toString(textToSearch);
83887
+ const _searchFor = toLocaleString(searchFor, this.locale);
83888
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
83876
83889
  const _startingAt = toNumber(startingAt, this.locale);
83877
83890
  if (_textToSearch === "") return new EvaluationError(_t("The text_to_search must be non-empty."));
83878
83891
  if (_startingAt < 1) return new EvaluationError(_t("The starting_at (%s) must be greater than or equal to 1.", _startingAt));
@@ -83909,8 +83922,8 @@ const JOIN = {
83909
83922
  description: _t("Concatenates elements of arrays with delimiter."),
83910
83923
  args: [arg("delimiter (string)", _t("The character or string to place between each concatenated value.")), arg("value_or_array (string, range<string>, repeating)", _t("Value to be appended using delimiter."))],
83911
83924
  compute: function(delimiter, ...valuesOrArrays) {
83912
- const _delimiter = toString(delimiter);
83913
- return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toString(a), "");
83925
+ const _delimiter = toLocaleString(delimiter, this.locale);
83926
+ return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toLocaleString(a, this.locale), "");
83914
83927
  }
83915
83928
  };
83916
83929
  const LEFT = {
@@ -83919,7 +83932,7 @@ const LEFT = {
83919
83932
  compute: function(text, ...args) {
83920
83933
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
83921
83934
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
83922
- return toString(text).substring(0, _numberOfCharacters);
83935
+ return toLocaleString(text, this.locale).substring(0, _numberOfCharacters);
83923
83936
  },
83924
83937
  isExported: true
83925
83938
  };
@@ -83927,7 +83940,7 @@ const LEN = {
83927
83940
  description: _t("Length of a string."),
83928
83941
  args: [arg("text (string)", _t("The string whose length will be returned."))],
83929
83942
  compute: function(text) {
83930
- return toString(text).length;
83943
+ return toLocaleString(text, this.locale).length;
83931
83944
  },
83932
83945
  isExported: true
83933
83946
  };
@@ -83935,7 +83948,7 @@ const LOWER = {
83935
83948
  description: _t("Converts a specified string to lowercase."),
83936
83949
  args: [arg("text (string)", _t("The string to convert to lowercase."))],
83937
83950
  compute: function(text) {
83938
- return toString(text).toLowerCase();
83951
+ return toLocaleString(text, this.locale).toLowerCase();
83939
83952
  },
83940
83953
  isExported: true
83941
83954
  };
@@ -83947,7 +83960,7 @@ const MID = {
83947
83960
  arg("extract_length (number)", _t("The length of the segment to extract."))
83948
83961
  ],
83949
83962
  compute: function(text, starting_at, extract_length) {
83950
- const _text = toString(text);
83963
+ const _text = toLocaleString(text, this.locale);
83951
83964
  const _starting_at = toNumber(starting_at, this.locale);
83952
83965
  const _extract_length = toNumber(extract_length, this.locale);
83953
83966
  if (_starting_at < 1) return new EvaluationError(_t("The starting_at argument (%s) must be positive greater than one.", _starting_at.toString()));
@@ -83960,7 +83973,7 @@ const PROPER = {
83960
83973
  description: _t("Capitalizes each word in a specified string."),
83961
83974
  args: [arg("text_to_capitalize (string)", _t("The text which will be returned with the first letter of each word in uppercase and all other letters in lowercase."))],
83962
83975
  compute: function(text) {
83963
- return toString(text).replace(wordRegex, (word) => {
83976
+ return toLocaleString(text, this.locale).replace(wordRegex, (word) => {
83964
83977
  return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
83965
83978
  });
83966
83979
  },
@@ -84108,9 +84121,9 @@ const REPLACE = {
84108
84121
  compute: function(text, position, length, newText) {
84109
84122
  const _position = toNumber(position, this.locale);
84110
84123
  if (_position < 1) return new EvaluationError(_t("The position (%s) must be greater than or equal to 1.", _position));
84111
- const _text = toString(text);
84124
+ const _text = toLocaleString(text, this.locale);
84112
84125
  const _length = toNumber(length, this.locale);
84113
- const _newText = toString(newText);
84126
+ const _newText = toLocaleString(newText, this.locale);
84114
84127
  return _text.substring(0, _position - 1) + _newText + _text.substring(_position - 1 + _length);
84115
84128
  },
84116
84129
  isExported: true
@@ -84121,7 +84134,7 @@ const RIGHT = {
84121
84134
  compute: function(text, ...args) {
84122
84135
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
84123
84136
  if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
84124
- const _text = toString(text);
84137
+ const _text = toLocaleString(text, this.locale);
84125
84138
  const stringLength = _text.length;
84126
84139
  return _text.substring(stringLength - _numberOfCharacters, stringLength);
84127
84140
  },
@@ -84135,8 +84148,8 @@ const SEARCH = {
84135
84148
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
84136
84149
  ],
84137
84150
  compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
84138
- const _searchFor = toString(searchFor).toLowerCase();
84139
- const _textToSearch = toString(textToSearch).toLowerCase();
84151
+ const _searchFor = toLocaleString(searchFor, this.locale).toLowerCase();
84152
+ const _textToSearch = toLocaleString(textToSearch, this.locale).toLowerCase();
84140
84153
  const _startingAt = toNumber(startingAt, this.locale);
84141
84154
  if (_textToSearch === "") return {
84142
84155
  value: CellErrorType.GenericError,
@@ -84166,8 +84179,8 @@ const SPLIT = {
84166
84179
  arg(`remove_empty_text (boolean, default=${SPLIT_DEFAULT_REMOVE_EMPTY_TEXT})`, _t("Whether or not to remove empty text messages from the split results. The default behavior is to treat consecutive delimiters as one (if TRUE). If FALSE, empty cells values are added between consecutive delimiters."))
84167
84180
  ],
84168
84181
  compute: function(text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
84169
- const _text = toString(text);
84170
- const _delimiter = escapeRegExp(toString(delimiter));
84182
+ const _text = toLocaleString(text, this.locale);
84183
+ const _delimiter = escapeRegExp(toLocaleString(delimiter, this.locale));
84171
84184
  const _splitByEach = toBoolean(splitByEach);
84172
84185
  const _removeEmptyText = toBoolean(removeEmptyText);
84173
84186
  if (_delimiter.length <= 0) return new EvaluationError(_t("The delimiter (%s) must be not be empty.", _delimiter));
@@ -84189,10 +84202,10 @@ const SUBSTITUTE = {
84189
84202
  compute: function(textToSearch, searchFor, replaceWith, occurrenceNumber) {
84190
84203
  const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
84191
84204
  if (_occurrenceNumber < 0) return new EvaluationError(_t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber));
84192
- const _textToSearch = toString(textToSearch);
84193
- const _searchFor = toString(searchFor);
84205
+ const _textToSearch = toLocaleString(textToSearch, this.locale);
84206
+ const _searchFor = toLocaleString(searchFor, this.locale);
84194
84207
  if (_searchFor === "") return _textToSearch;
84195
- const _replaceWith = toString(replaceWith);
84208
+ const _replaceWith = toLocaleString(replaceWith, this.locale);
84196
84209
  const reg = new RegExp(escapeRegExp(_searchFor), "g");
84197
84210
  if (_occurrenceNumber === 0) return _textToSearch.replace(reg, _replaceWith);
84198
84211
  let n = 0;
@@ -84215,10 +84228,10 @@ const TEXTJOIN = {
84215
84228
  arg("texts (string, range<string>, repeating)", _t("Text item to join."))
84216
84229
  ],
84217
84230
  compute: function(delimiter, ignoreEmpty = { value: TEXTJOIN_DEFAULT_IGNORE_EMPTY }, ...textsOrArrays) {
84218
- const _delimiter = toString(delimiter);
84231
+ const _delimiter = toLocaleString(delimiter, this.locale);
84219
84232
  const _ignoreEmpty = toBoolean(ignoreEmpty);
84220
84233
  let n = 0;
84221
- return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toString(a) === "") ? (n++ ? acc + _delimiter : "") + toString(a) : acc, "");
84234
+ return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toLocaleString(a, this.locale) === "") ? (n++ ? acc + _delimiter : "") + toLocaleString(a, this.locale) : acc, "");
84222
84235
  },
84223
84236
  isExported: true
84224
84237
  };
@@ -84271,7 +84284,7 @@ const TRIM = {
84271
84284
  description: _t("Removes space characters."),
84272
84285
  args: [arg("text (string)", _t("The text or reference to a cell containing text to be trimmed."))],
84273
84286
  compute: function(text) {
84274
- return trimContent(toString(text));
84287
+ return trimContent(toLocaleString(text, this.locale));
84275
84288
  },
84276
84289
  isExported: true
84277
84290
  };
@@ -84279,7 +84292,7 @@ const UPPER = {
84279
84292
  description: _t("Converts a specified string to uppercase."),
84280
84293
  args: [arg("text (string)", _t("The string to convert to uppercase."))],
84281
84294
  compute: function(text) {
84282
- return toString(text).toUpperCase();
84295
+ return toLocaleString(text, this.locale).toUpperCase();
84283
84296
  },
84284
84297
  isExported: true
84285
84298
  };
@@ -84376,7 +84389,7 @@ const HYPERLINK = {
84376
84389
  args: [arg("url (string)", _t("The full URL of the link enclosed in quotation marks.")), arg("link_label (string, optional)", _t("The text to display in the cell, enclosed in quotation marks."))],
84377
84390
  compute: function(url, linkLabel) {
84378
84391
  const processedUrl = toString(url).trim();
84379
- const processedLabel = toString(linkLabel) || processedUrl;
84392
+ const processedLabel = toLocaleString(linkLabel, this.locale) || processedUrl;
84380
84393
  if (processedUrl === "") return processedLabel;
84381
84394
  return markdownLink(processedLabel, processedUrl);
84382
84395
  },
@@ -84715,6 +84728,6 @@ const chartHelpers = {
84715
84728
  //#endregion
84716
84729
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CompiledFormula, CorePlugin, CoreViewPlugin, DEFAULT_LOCALE, DEFAULT_LOCALES, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, canExecuteInReadonly, categories, chartHelpers, components, constants, convertAstNodes, coreTypes, createAutocompleteArgumentsProvider, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, isCoreCommand, isSheetDependent, iterateAstNodes, links, load, lockedSheetAllowedCommands, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
84717
84730
 
84718
- __info__.version = "19.3.16";
84719
- __info__.date = "2026-08-12T09:15:31.627Z";
84720
- __info__.hash = "464be42";
84731
+ __info__.version = "19.3.17";
84732
+ __info__.date = "2026-08-21T15:31:50.940Z";
84733
+ __info__.hash = "cf8c614";