@luxalgo/vela 0.8.5 → 0.9.1

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.
Files changed (139) hide show
  1. package/dist/{DataProvider-DdqMxKdl.d.cts → DataProvider-B5i0_yY4.d.cts} +1 -1
  2. package/dist/{DataProvider-BUdlkx9I.d.ts → DataProvider-CPFgSyAm.d.ts} +1 -1
  3. package/dist/{chunk-QYIO37K7.js → chunk-3H6JO4VL.js} +2405 -1542
  4. package/dist/{chunk-BN4DNS3O.js → chunk-BLVL7WXF.js} +1156 -468
  5. package/dist/chunk-O6L27KRB.js +1331 -0
  6. package/dist/{chunk-WY5H4S4I.js → chunk-PZN4RS4T.js} +91 -36
  7. package/dist/{chunk-ALTGHKIM.js → chunk-Q7POFYNE.js} +516 -406
  8. package/dist/{chunk-AUOB7A5Y.js → chunk-WHPQQYH7.js} +29 -13
  9. package/dist/{contributions-D8xuYc9U.d.cts → contributions-BfBaF6eE.d.ts} +71 -22
  10. package/dist/{contributions-P9fBBuY1.d.ts → contributions-DupwEkzc.d.cts} +71 -22
  11. package/dist/index.cjs +4040 -2087
  12. package/dist/index.d.cts +53 -25
  13. package/dist/index.d.ts +53 -25
  14. package/dist/index.js +5 -5
  15. package/dist/{keymap-CGOz5F5f.d.cts → keymap-C48ughm6.d.ts} +9 -6
  16. package/dist/{keymap-CGOz5F5f.d.ts → keymap-W0hiajU6.d.cts} +9 -6
  17. package/dist/locales/ar.cjs +2262 -0
  18. package/dist/locales/ar.d.cts +5 -0
  19. package/dist/locales/ar.d.ts +5 -0
  20. package/dist/locales/ar.js +2260 -0
  21. package/dist/locales/de.cjs +2262 -0
  22. package/dist/locales/de.d.cts +5 -0
  23. package/dist/locales/de.d.ts +5 -0
  24. package/dist/locales/de.js +2260 -0
  25. package/dist/locales/en.cjs +2262 -0
  26. package/dist/locales/en.d.cts +5 -0
  27. package/dist/locales/en.d.ts +5 -0
  28. package/dist/locales/en.js +2260 -0
  29. package/dist/locales/es.cjs +2262 -0
  30. package/dist/locales/es.d.cts +5 -0
  31. package/dist/locales/es.d.ts +5 -0
  32. package/dist/locales/es.js +2260 -0
  33. package/dist/locales/fr.cjs +2262 -0
  34. package/dist/locales/fr.d.cts +5 -0
  35. package/dist/locales/fr.d.ts +5 -0
  36. package/dist/locales/fr.js +2260 -0
  37. package/dist/locales/he.cjs +2262 -0
  38. package/dist/locales/he.d.cts +5 -0
  39. package/dist/locales/he.d.ts +5 -0
  40. package/dist/locales/he.js +2260 -0
  41. package/dist/locales/hi.cjs +2262 -0
  42. package/dist/locales/hi.d.cts +5 -0
  43. package/dist/locales/hi.d.ts +5 -0
  44. package/dist/locales/hi.js +2260 -0
  45. package/dist/locales/id.cjs +2262 -0
  46. package/dist/locales/id.d.cts +5 -0
  47. package/dist/locales/id.d.ts +5 -0
  48. package/dist/locales/id.js +2260 -0
  49. package/dist/locales/it.cjs +2262 -0
  50. package/dist/locales/it.d.cts +5 -0
  51. package/dist/locales/it.d.ts +5 -0
  52. package/dist/locales/it.js +2260 -0
  53. package/dist/locales/ja.cjs +2262 -0
  54. package/dist/locales/ja.d.cts +5 -0
  55. package/dist/locales/ja.d.ts +5 -0
  56. package/dist/locales/ja.js +2260 -0
  57. package/dist/locales/ko.cjs +2262 -0
  58. package/dist/locales/ko.d.cts +5 -0
  59. package/dist/locales/ko.d.ts +5 -0
  60. package/dist/locales/ko.js +2260 -0
  61. package/dist/locales/ms.cjs +2262 -0
  62. package/dist/locales/ms.d.cts +5 -0
  63. package/dist/locales/ms.d.ts +5 -0
  64. package/dist/locales/ms.js +2260 -0
  65. package/dist/locales/pl.cjs +2262 -0
  66. package/dist/locales/pl.d.cts +5 -0
  67. package/dist/locales/pl.d.ts +5 -0
  68. package/dist/locales/pl.js +2260 -0
  69. package/dist/locales/pt-BR.cjs +2262 -0
  70. package/dist/locales/pt-BR.d.cts +5 -0
  71. package/dist/locales/pt-BR.d.ts +5 -0
  72. package/dist/locales/pt-BR.js +2260 -0
  73. package/dist/locales/ru.cjs +2262 -0
  74. package/dist/locales/ru.d.cts +5 -0
  75. package/dist/locales/ru.d.ts +5 -0
  76. package/dist/locales/ru.js +2260 -0
  77. package/dist/locales/th.cjs +2262 -0
  78. package/dist/locales/th.d.cts +5 -0
  79. package/dist/locales/th.d.ts +5 -0
  80. package/dist/locales/th.js +2260 -0
  81. package/dist/locales/tr.cjs +2262 -0
  82. package/dist/locales/tr.d.cts +5 -0
  83. package/dist/locales/tr.d.ts +5 -0
  84. package/dist/locales/tr.js +2260 -0
  85. package/dist/locales/vi.cjs +2262 -0
  86. package/dist/locales/vi.d.cts +5 -0
  87. package/dist/locales/vi.d.ts +5 -0
  88. package/dist/locales/vi.js +2260 -0
  89. package/dist/locales/zh-Hans.cjs +2262 -0
  90. package/dist/locales/zh-Hans.d.cts +5 -0
  91. package/dist/locales/zh-Hans.d.ts +5 -0
  92. package/dist/locales/zh-Hans.js +2260 -0
  93. package/dist/locales/zh-Hant.cjs +2262 -0
  94. package/dist/locales/zh-Hant.d.cts +5 -0
  95. package/dist/locales/zh-Hant.d.ts +5 -0
  96. package/dist/locales/zh-Hant.js +2260 -0
  97. package/dist/{options-BI5Tp32b.d.ts → options-B7aL1pbf.d.ts} +74 -9
  98. package/dist/{options-BI5Tp32b.d.cts → options-I1H2HDWw.d.cts} +74 -9
  99. package/dist/{plugin-B8F1nor8.d.cts → plugin-BGz-Vsdv.d.cts} +81 -35
  100. package/dist/{plugin-D5Z-Q6TX.d.ts → plugin-BZHypj8h.d.ts} +81 -35
  101. package/dist/plugin.cjs +1268 -319
  102. package/dist/plugin.d.cts +7 -6
  103. package/dist/plugin.d.ts +7 -6
  104. package/dist/plugin.js +3 -3
  105. package/dist/providers/binance.cjs +1 -1
  106. package/dist/providers/binance.d.cts +3 -2
  107. package/dist/providers/binance.d.ts +3 -2
  108. package/dist/providers/binance.js +1 -1
  109. package/dist/providers/coinbase.cjs +1 -1
  110. package/dist/providers/coinbase.d.cts +3 -2
  111. package/dist/providers/coinbase.d.ts +3 -2
  112. package/dist/providers/coinbase.js +1 -1
  113. package/dist/providers/hyperliquid.cjs +1 -1
  114. package/dist/providers/hyperliquid.d.cts +3 -2
  115. package/dist/providers/hyperliquid.d.ts +3 -2
  116. package/dist/providers/hyperliquid.js +1 -1
  117. package/dist/{side-panel-_2UK1gSm.d.ts → side-panel-BEQJqSjR.d.cts} +14 -2
  118. package/dist/{side-panel-_2UK1gSm.d.cts → side-panel-Ud0SBAnE.d.ts} +14 -2
  119. package/dist/{statusline-model-CTwtDIca.d.cts → statusline-model-Dfb_GD9u.d.ts} +14 -3
  120. package/dist/{statusline-model-D9kWC9X5.d.ts → statusline-model-PHt0YhmI.d.cts} +14 -3
  121. package/dist/types-Bwf63xGI.d.cts +2518 -0
  122. package/dist/types-Bwf63xGI.d.ts +2518 -0
  123. package/dist/ui.cjs +1008 -56
  124. package/dist/ui.d.cts +21 -2
  125. package/dist/ui.d.ts +21 -2
  126. package/dist/ui.js +3 -3
  127. package/dist/vela.global.js +4005 -2054
  128. package/dist/vela.global.min.js +57 -57
  129. package/dist/widget.cjs +5384 -2698
  130. package/dist/widget.d.cts +100 -26
  131. package/dist/widget.d.ts +100 -26
  132. package/dist/widget.js +19 -11
  133. package/dist/workspace.cjs +5373 -2705
  134. package/dist/workspace.d.cts +63 -15
  135. package/dist/workspace.d.ts +63 -15
  136. package/dist/workspace.js +6 -6
  137. package/package.json +9 -2
  138. package/dist/chunk-I2U4NZD2.js +0 -340
  139. /package/dist/{chunk-W5YPYZ2P.js → chunk-3EYCX2L4.js} +0 -0
package/dist/plugin.cjs CHANGED
@@ -1,6 +1,913 @@
1
1
  'use strict';
2
2
 
3
+ // src/core/i18n/message.ts
4
+ function msg(id, defaultMessage) {
5
+ return Object.freeze({ id, defaultMessage });
6
+ }
7
+ function withValues(message, values) {
8
+ return Object.freeze({ id: message.id, defaultMessage: message.defaultMessage, values: { ...message.values, ...values } });
9
+ }
10
+
11
+ // src/core/format/numbers.ts
12
+ var BIDI_MARKS = /[‎‏؜]/g;
13
+ function stripBidiMarks(text) {
14
+ return text.replace(BIDI_MARKS, "");
15
+ }
16
+ var numberFormats = /* @__PURE__ */ new Map();
17
+ function numberFormat(settings, options) {
18
+ const key = `${settings.locale}|${settings.numberingSystem}|${JSON.stringify(options)}`;
19
+ let nf = numberFormats.get(key);
20
+ if (!nf) {
21
+ try {
22
+ nf = new Intl.NumberFormat(settings.locale, { ...options, numberingSystem: settings.numberingSystem });
23
+ } catch {
24
+ nf = new Intl.NumberFormat("en", options);
25
+ }
26
+ numberFormats.set(key, nf);
27
+ }
28
+ return nf;
29
+ }
30
+ var symbolCache = /* @__PURE__ */ new Map();
31
+ function numberSymbols(settings) {
32
+ const key = `${settings.locale}|${settings.numberingSystem}`;
33
+ let sym = symbolCache.get(key);
34
+ if (sym) return sym;
35
+ const parts = numberFormat(settings, { useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 1 }).formatToParts(-1.5);
36
+ const decimal = stripBidiMarks(parts.find((p) => p.type === "decimal")?.value ?? ".") || ".";
37
+ const minus = stripBidiMarks(parts.find((p) => p.type === "minusSign")?.value ?? "-") || "-";
38
+ const plain = numberFormat(settings, { useGrouping: false, maximumFractionDigits: 0 });
39
+ const digits = Array.from({ length: 10 }, (_, d) => stripBidiMarks(plain.format(d)));
40
+ const ascii = decimal === "." && minus === "-" && digits.every((d, i) => d === String(i));
41
+ sym = { ascii, decimal, minus, digits };
42
+ symbolCache.set(key, sym);
43
+ return sym;
44
+ }
45
+ function localizeAscii(text, settings) {
46
+ const sym = numberSymbols(settings);
47
+ if (sym.ascii) return text;
48
+ let out = "";
49
+ for (const ch of text) {
50
+ const code = ch.charCodeAt(0);
51
+ if (code >= 48 && code <= 57) out += sym.digits[code - 48];
52
+ else if (ch === ".") out += sym.decimal;
53
+ else if (ch === "-") out += sym.minus;
54
+ else out += ch;
55
+ }
56
+ return out;
57
+ }
58
+ function localizeDigits(text, settings) {
59
+ const sym = numberSymbols(settings);
60
+ if (sym.digits.every((d, i) => d === String(i))) return text;
61
+ return text.replace(/[0-9]/g, (d) => sym.digits[Number(d)]);
62
+ }
63
+ var clampDecimals = (d) => Number.isFinite(d) ? Math.max(0, Math.min(20, Math.trunc(d))) : 2;
64
+ function formatFixed(value, decimals, settings) {
65
+ return localizeAscii(value.toFixed(clampDecimals(decimals)), settings);
66
+ }
67
+ function formatGrouped(value, decimals, settings) {
68
+ const d = clampDecimals(decimals);
69
+ return stripBidiMarks(numberFormat(settings, { minimumFractionDigits: d, maximumFractionDigits: d }).format(value));
70
+ }
71
+ function formatMessageNumber(value, settings, style) {
72
+ if (style === "integer") return stripBidiMarks(numberFormat(settings, { maximumFractionDigits: 0 }).format(value));
73
+ if (style === "percent") return stripBidiMarks(numberFormat(settings, { style: "percent" }).format(value));
74
+ return stripBidiMarks(numberFormat(settings, {}).format(value));
75
+ }
76
+ function formatPercent(value, options, settings) {
77
+ const d = clampDecimals(options?.decimals ?? 2);
78
+ const signed2 = options?.signed ?? true;
79
+ if (settings.english) {
80
+ const text = signed2 ? `${value >= 0 ? "+" : "-"}${Math.abs(value).toFixed(d)}%` : `${value.toFixed(d)}%`;
81
+ return localizeAscii(text, settings);
82
+ }
83
+ const nf = numberFormat(settings, { style: "percent", minimumFractionDigits: d, maximumFractionDigits: d, signDisplay: signed2 ? "always" : "auto" });
84
+ return stripBidiMarks(nf.format(value / 100));
85
+ }
86
+ function formatPrice(value, options, settings) {
87
+ const mode = options.mode ?? "price";
88
+ if (mode === "percent") return formatPercent(value, { decimals: options.decimals, signed: true }, settings);
89
+ if (mode === "indexed" || !options.grouping) return formatFixed(value, options.decimals, settings);
90
+ return formatGrouped(value, options.decimals, settings);
91
+ }
92
+ var COMPACT_STEPS = [
93
+ [1e9, "B"],
94
+ [1e6, "M"],
95
+ [1e3, "K"]
96
+ ];
97
+ function formatCompact(value, options, settings) {
98
+ const d = clampDecimals(options?.decimals ?? 2);
99
+ const trim = options?.trimZeros ?? true;
100
+ if (settings.english) {
101
+ const a = Math.abs(value);
102
+ let div = 1;
103
+ let suffix = "";
104
+ for (const [step, s] of COMPACT_STEPS) {
105
+ if (a >= step) {
106
+ div = step;
107
+ suffix = s;
108
+ break;
109
+ }
110
+ }
111
+ const scaled = value / div;
112
+ const text = trim ? Number(scaled.toFixed(d)).toString() : scaled.toFixed(d);
113
+ return localizeAscii(text, settings) + suffix;
114
+ }
115
+ const nf = numberFormat(settings, { notation: "compact", compactDisplay: "short", maximumFractionDigits: d, minimumFractionDigits: trim ? 0 : d });
116
+ return stripBidiMarks(nf.format(value));
117
+ }
118
+
119
+ // src/core/format/dates.ts
120
+ var EN_MONTHS_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
121
+ var EN_WEEKDAYS_SHORT = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
122
+ var pad2 = (n) => n < 10 ? `0${n}` : String(n);
123
+ var DAY_MS = 864e5;
124
+ var zoneParsers = /* @__PURE__ */ new Map();
125
+ function zoneOffsetMs(ms, timeZone) {
126
+ if (!timeZone || timeZone === "UTC") return 0;
127
+ let dtf = zoneParsers.get(timeZone);
128
+ if (dtf === void 0) {
129
+ try {
130
+ dtf = new Intl.DateTimeFormat("en-US", {
131
+ timeZone,
132
+ hourCycle: "h23",
133
+ year: "numeric",
134
+ month: "2-digit",
135
+ day: "2-digit",
136
+ hour: "2-digit",
137
+ minute: "2-digit",
138
+ second: "2-digit"
139
+ });
140
+ } catch {
141
+ dtf = null;
142
+ }
143
+ zoneParsers.set(timeZone, dtf);
144
+ }
145
+ if (!dtf) return 0;
146
+ try {
147
+ const parts = dtf.formatToParts(new Date(ms));
148
+ const get = (t) => Number(parts.find((p) => p.type === t)?.value);
149
+ const asUTC = Date.UTC(get("year"), get("month") - 1, get("day"), get("hour") % 24, get("minute"), get("second"));
150
+ return asUTC - ms;
151
+ } catch {
152
+ return 0;
153
+ }
154
+ }
155
+ var dateFormats = /* @__PURE__ */ new Map();
156
+ function dateFormat(settings, options) {
157
+ const key = `${settings.locale}|${settings.numberingSystem}|${JSON.stringify(options)}`;
158
+ let dtf = dateFormats.get(key);
159
+ if (!dtf) {
160
+ const full = { ...options, timeZone: "UTC", calendar: "gregory", numberingSystem: settings.numberingSystem };
161
+ try {
162
+ dtf = new Intl.DateTimeFormat(settings.locale, full);
163
+ } catch {
164
+ dtf = new Intl.DateTimeFormat("en", { ...options, timeZone: "UTC", calendar: "gregory" });
165
+ }
166
+ dateFormats.set(key, dtf);
167
+ }
168
+ return dtf;
169
+ }
170
+ function clockOptions(settings) {
171
+ if (settings.hourCycle === "h23") return { hour: "2-digit", minute: "2-digit", hourCycle: "h23" };
172
+ if (settings.hourCycle === "h12") return { hour: "numeric", minute: "2-digit", hourCycle: "h12" };
173
+ return { hour: "numeric", minute: "2-digit" };
174
+ }
175
+ function englishClock(wall, settings) {
176
+ if (settings.hourCycle === "h23") return localizeAscii(`${pad2(wall.getUTCHours())}:${pad2(wall.getUTCMinutes())}`, settings);
177
+ return stripBidiMarks(dateFormat(settings, clockOptions(settings)).format(wall));
178
+ }
179
+ var TICK_OPTIONS = {
180
+ year: { year: "numeric" },
181
+ month: { month: "short" },
182
+ day: { month: "short", day: "numeric" }
183
+ };
184
+ var isClockUnit = (unit) => unit === "hour" || unit === "minute" || unit === "second";
185
+ function formatTimeTick(ms, options, settings) {
186
+ const wall = new Date(ms + (options.offsetMs ?? 0));
187
+ const unit = options.unit;
188
+ if (settings.english) {
189
+ if (isClockUnit(unit)) return englishClock(wall, settings);
190
+ const month = EN_MONTHS_SHORT[wall.getUTCMonth()];
191
+ if (unit === "year") return localizeAscii(String(wall.getUTCFullYear()), settings);
192
+ if (unit === "month") return month;
193
+ return localizeAscii(`${month} ${wall.getUTCDate()}`, settings);
194
+ }
195
+ const opts = isClockUnit(unit) ? clockOptions(settings) : TICK_OPTIONS[unit];
196
+ return stripBidiMarks(dateFormat(settings, opts).format(wall));
197
+ }
198
+ function formatTimeStamp(ms, options, settings) {
199
+ const wall = new Date(ms + zoneOffsetMs(ms, options?.timeZone ?? "UTC"));
200
+ const withTime = options?.withTime ?? true;
201
+ if (settings.english) {
202
+ const date = localizeAscii(
203
+ `${EN_WEEKDAYS_SHORT[wall.getUTCDay()]} ${wall.getUTCDate()} ${EN_MONTHS_SHORT[wall.getUTCMonth()]} '${pad2(wall.getUTCFullYear() % 100)}`,
204
+ settings
205
+ );
206
+ return withTime ? `${date} ${englishClock(wall, settings)}` : date;
207
+ }
208
+ const opts = { weekday: "short", day: "numeric", month: "short", year: "2-digit", ...withTime ? clockOptions(settings) : {} };
209
+ return stripBidiMarks(dateFormat(settings, opts).format(wall));
210
+ }
211
+ function countdownText(ms) {
212
+ const total = Math.max(0, Math.ceil(ms / 1e3));
213
+ const s = total % 60;
214
+ const m = Math.floor(total / 60) % 60;
215
+ const h = Math.floor(total / 3600);
216
+ const pad = (v) => String(v).padStart(2, "0");
217
+ return h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${pad(m)}:${pad(s)}`;
218
+ }
219
+ function spanParts(ms) {
220
+ const m = Math.abs(ms);
221
+ const HR = 36e5;
222
+ const MIN2 = 6e4;
223
+ if (m >= DAY_MS) {
224
+ const d = Math.floor(m / DAY_MS);
225
+ const h = Math.round(m % DAY_MS / HR);
226
+ return h ? [[d, "day"], [h, "hour"]] : [[d, "day"]];
227
+ }
228
+ if (m >= HR) {
229
+ const h = Math.floor(m / HR);
230
+ const mn = Math.round(m % HR / MIN2);
231
+ return mn ? [[h, "hour"], [mn, "minute"]] : [[h, "hour"]];
232
+ }
233
+ if (m >= MIN2) return [[Math.round(m / MIN2), "minute"]];
234
+ return [[Math.round(m / 1e3), "second"]];
235
+ }
236
+ var EN_UNIT = { day: "d", hour: "h", minute: "m", second: "s" };
237
+ function formatDuration(ms, options, settings) {
238
+ if ((options?.style ?? "countdown") === "countdown") return localizeDigits(countdownText(ms), settings);
239
+ const parts = spanParts(ms);
240
+ if (settings.english) return localizeDigits(parts.map(([n, u]) => `${n}${EN_UNIT[u]}`).join(" "), settings);
241
+ return parts.map(([n, unit]) => stripBidiMarks(numberFormat(settings, { style: "unit", unit, unitDisplay: "narrow" }).format(n))).join(" ");
242
+ }
243
+ var clockFormats = /* @__PURE__ */ new Map();
244
+ function formatClock(ms, options, settings) {
245
+ const timeZone = options?.timeZone ?? "UTC";
246
+ const seconds = options?.seconds ?? true;
247
+ const english2 = settings.english && settings.hourCycle === "h23";
248
+ const key = `${english2 ? "en-GB" : settings.locale}|${settings.numberingSystem}|${settings.hourCycle}|${timeZone}|${seconds}`;
249
+ let dtf = clockFormats.get(key);
250
+ if (dtf === void 0) {
251
+ const base = { hour: "2-digit", minute: "2-digit", ...seconds ? { second: "2-digit" } : {}, timeZone };
252
+ try {
253
+ dtf = english2 ? new Intl.DateTimeFormat("en-GB", { ...base, hour12: false }) : new Intl.DateTimeFormat(settings.locale, {
254
+ ...base,
255
+ calendar: "gregory",
256
+ numberingSystem: settings.numberingSystem,
257
+ ...settings.hourCycle === "locale" ? {} : { hourCycle: settings.hourCycle }
258
+ });
259
+ } catch {
260
+ dtf = null;
261
+ }
262
+ clockFormats.set(key, dtf);
263
+ }
264
+ if (!dtf) return "";
265
+ try {
266
+ return stripBidiMarks(dtf.format(new Date(ms)));
267
+ } catch {
268
+ return "";
269
+ }
270
+ }
271
+
272
+ // src/core/format/formatters.ts
273
+ function builtinFormatters(settings) {
274
+ return {
275
+ price: (value, options) => formatPrice(value, options, settings),
276
+ percent: (value, options) => formatPercent(value, options, settings),
277
+ compact: (value, options) => formatCompact(value, options, settings),
278
+ timeTick: (ms, options) => formatTimeTick(ms, options, settings),
279
+ timeStamp: (ms, options) => formatTimeStamp(ms, options, settings),
280
+ duration: (ms, options) => formatDuration(ms, options, settings),
281
+ clock: (ms, options) => formatClock(ms, options, settings)
282
+ };
283
+ }
284
+ var ENGLISH_SETTINGS = Object.freeze({ locale: "en", numberingSystem: "latn", hourCycle: "h23", english: true });
285
+ var warned = false;
286
+ function viaHost(host, value, ctx, fallback) {
287
+ try {
288
+ const out = host(value, ctx);
289
+ if (typeof out === "string") return out;
290
+ } catch (err) {
291
+ if (!warned) {
292
+ warned = true;
293
+ console.warn("[vela] a host formatter threw; the built-in formatting is used instead.", err);
294
+ }
295
+ }
296
+ return fallback();
297
+ }
298
+ function resolveFormatters(settings, overrides) {
299
+ const base = builtinFormatters(settings);
300
+ if (!overrides) return base;
301
+ const ctx = (surface, defaultSurface, timeZone, fallback) => ({
302
+ locale: settings.locale,
303
+ timeZone: timeZone ?? "UTC",
304
+ surface: surface ?? defaultSurface,
305
+ fallback
306
+ });
307
+ const o = overrides;
308
+ return {
309
+ price(value, options) {
310
+ const fallback = () => base.price(value, options);
311
+ if (typeof o.price !== "function") return fallback();
312
+ return viaHost(o.price, value, { ...ctx(options.surface, "priceAxis", void 0, fallback), decimals: options.decimals, mintick: options.mintick, mode: options.mode ?? "price", paneId: options.paneId, grouping: options.grouping ?? false }, fallback);
313
+ },
314
+ percent(value, options) {
315
+ const fallback = () => base.percent(value, options);
316
+ if (typeof o.percent !== "function") return fallback();
317
+ return viaHost(o.percent, value, { ...ctx(options?.surface, "statusLine", void 0, fallback), decimals: options?.decimals ?? 2, signed: options?.signed ?? true }, fallback);
318
+ },
319
+ compact(value, options) {
320
+ const fallback = () => base.compact(value, options);
321
+ if (typeof o.compact !== "function") return fallback();
322
+ return viaHost(o.compact, value, { ...ctx(options?.surface, "priceAxis", void 0, fallback), decimals: options?.decimals ?? 2, trimZeros: options?.trimZeros ?? true }, fallback);
323
+ },
324
+ timeTick(ms, options) {
325
+ const fallback = () => base.timeTick(ms, options);
326
+ if (typeof o.timeTick !== "function") return fallback();
327
+ return viaHost(o.timeTick, ms, { ...ctx(options.surface, "timeAxis", options.timeZone, fallback), unit: options.unit, major: options.major, offsetMs: options.offsetMs ?? 0 }, fallback);
328
+ },
329
+ timeStamp(ms, options) {
330
+ const fallback = () => base.timeStamp(ms, options);
331
+ if (typeof o.timeStamp !== "function") return fallback();
332
+ return viaHost(o.timeStamp, ms, { ...ctx(options?.surface, "crosshair", options?.timeZone, fallback), withTime: options?.withTime ?? true }, fallback);
333
+ },
334
+ duration(ms, options) {
335
+ const fallback = () => base.duration(ms, options);
336
+ if (typeof o.duration !== "function") return fallback();
337
+ return viaHost(o.duration, ms, { ...ctx(options?.surface, "lastPrice", void 0, fallback), style: options?.style ?? "countdown" }, fallback);
338
+ },
339
+ clock(ms, options) {
340
+ const fallback = () => base.clock(ms, options);
341
+ if (typeof o.clock !== "function") return fallback();
342
+ return viaHost(o.clock, ms, { ...ctx(options?.surface, "clock", options?.timeZone, fallback), seconds: options?.seconds ?? true }, fallback);
343
+ }
344
+ };
345
+ }
346
+
347
+ // src/core/i18n/icu.ts
348
+ var Parser = class {
349
+ constructor(src) {
350
+ this.src = src;
351
+ this.i = 0;
352
+ }
353
+ parse() {
354
+ const nodes = this.message(false, 0);
355
+ if (this.i < this.src.length) throw this.error("unmatched }");
356
+ return nodes;
357
+ }
358
+ error(what) {
359
+ return new SyntaxError(`[vela] message syntax: ${what} at ${this.i} in "${this.src}"`);
360
+ }
361
+ /** Text and arguments up to an unmatched `}` (left unread) or the end. */
362
+ message(inPlural, depth) {
363
+ if (depth > 8) throw this.error("nesting too deep");
364
+ const src = this.src;
365
+ const out = [];
366
+ let text = "";
367
+ const flush = () => {
368
+ if (text) out.push(text);
369
+ text = "";
370
+ };
371
+ while (this.i < src.length) {
372
+ const ch = src[this.i];
373
+ if (ch === "'") {
374
+ const next = src[this.i + 1];
375
+ if (next === "'") {
376
+ text += "'";
377
+ this.i += 2;
378
+ } else if (next === "{" || next === "}" || inPlural && next === "#") {
379
+ this.i += 1;
380
+ while (this.i < src.length) {
381
+ const c = src[this.i];
382
+ if (c === "'") {
383
+ if (src[this.i + 1] === "'") {
384
+ text += "'";
385
+ this.i += 2;
386
+ continue;
387
+ }
388
+ this.i += 1;
389
+ break;
390
+ }
391
+ text += c;
392
+ this.i += 1;
393
+ }
394
+ } else {
395
+ text += "'";
396
+ this.i += 1;
397
+ }
398
+ } else if (ch === "{") {
399
+ flush();
400
+ this.i += 1;
401
+ out.push(this.argument(depth));
402
+ } else if (ch === "}") {
403
+ break;
404
+ } else if (ch === "#" && inPlural) {
405
+ flush();
406
+ out.push({ kind: "pound" });
407
+ this.i += 1;
408
+ } else {
409
+ text += ch;
410
+ this.i += 1;
411
+ }
412
+ }
413
+ flush();
414
+ return out;
415
+ }
416
+ skipSpace() {
417
+ while (this.i < this.src.length && /\s/.test(this.src[this.i])) this.i += 1;
418
+ }
419
+ word() {
420
+ this.skipSpace();
421
+ const start = this.i;
422
+ while (this.i < this.src.length && !/[\s,{}]/.test(this.src[this.i])) this.i += 1;
423
+ return this.src.slice(start, this.i);
424
+ }
425
+ expect(ch) {
426
+ this.skipSpace();
427
+ if (this.src[this.i] !== ch) throw this.error(`expected "${ch}"`);
428
+ this.i += 1;
429
+ }
430
+ /** After a `{`: the argument through its closing `}`. */
431
+ argument(depth) {
432
+ const name = this.word();
433
+ if (!name) throw this.error("empty argument name");
434
+ this.skipSpace();
435
+ if (this.src[this.i] === "}") {
436
+ this.i += 1;
437
+ return { kind: "arg", name };
438
+ }
439
+ this.expect(",");
440
+ const type = this.word();
441
+ this.skipSpace();
442
+ if (type === "number") {
443
+ let style;
444
+ if (this.src[this.i] === ",") {
445
+ this.i += 1;
446
+ style = this.word() || void 0;
447
+ }
448
+ this.expect("}");
449
+ return { kind: "arg", name, format: "number", style };
450
+ }
451
+ if (type === "plural" || type === "selectordinal" || type === "select") {
452
+ this.expect(",");
453
+ let offset = 0;
454
+ this.skipSpace();
455
+ if (type !== "select" && this.src.startsWith("offset:", this.i)) {
456
+ this.i += "offset:".length;
457
+ offset = Number(this.word());
458
+ if (!Number.isFinite(offset)) throw this.error("bad offset");
459
+ }
460
+ const options = {};
461
+ for (; ; ) {
462
+ this.skipSpace();
463
+ if (this.src[this.i] === "}") {
464
+ this.i += 1;
465
+ break;
466
+ }
467
+ const key = this.word();
468
+ if (!key) throw this.error("expected a selector");
469
+ this.expect("{");
470
+ options[key] = this.message(type !== "select", depth + 1);
471
+ this.expect("}");
472
+ }
473
+ if (!options.other) throw this.error(`"${name}" has no "other" option`);
474
+ return type === "select" ? { kind: "select", name, options } : { kind: "plural", name, ordinal: type === "selectordinal", offset, options };
475
+ }
476
+ throw this.error(`unknown argument type "${type}"`);
477
+ }
478
+ };
479
+ var parsed = /* @__PURE__ */ new Map();
480
+ var PARSE_CACHE_CAP = 2e3;
481
+ function parseMessage(source) {
482
+ let nodes = parsed.get(source);
483
+ if (!nodes) {
484
+ nodes = new Parser(source).parse();
485
+ if (parsed.size >= PARSE_CACHE_CAP) parsed.clear();
486
+ parsed.set(source, nodes);
487
+ }
488
+ return nodes;
489
+ }
490
+ var pluralRules = /* @__PURE__ */ new Map();
491
+ function rulesFor(locale, ordinal) {
492
+ const key = `${locale}|${ordinal ? "o" : "c"}`;
493
+ let pr = pluralRules.get(key);
494
+ if (!pr) {
495
+ try {
496
+ pr = new Intl.PluralRules(locale, { type: ordinal ? "ordinal" : "cardinal" });
497
+ } catch {
498
+ pr = new Intl.PluralRules("en", { type: ordinal ? "ordinal" : "cardinal" });
499
+ }
500
+ pluralRules.set(key, pr);
501
+ }
502
+ return pr;
503
+ }
504
+ function render(nodes, values, rt, pound) {
505
+ let out = "";
506
+ for (const node of nodes) {
507
+ if (typeof node === "string") {
508
+ out += node;
509
+ continue;
510
+ }
511
+ if (node.kind === "pound") {
512
+ out += pound == null ? "#" : rt.formatNumber(pound);
513
+ continue;
514
+ }
515
+ const raw = values?.[node.name];
516
+ if (node.kind === "arg") {
517
+ if (raw === void 0) out += `{${node.name}}`;
518
+ else if (typeof raw === "number") out += rt.formatNumber(raw, node.format === "number" ? node.style : void 0);
519
+ else if (node.format === "number" && raw.trim() !== "" && Number.isFinite(Number(raw))) out += rt.formatNumber(Number(raw), node.style);
520
+ else out += raw;
521
+ continue;
522
+ }
523
+ if (node.kind === "select") {
524
+ const branch2 = node.options[String(raw)] ?? node.options.other;
525
+ out += render(branch2, values, rt, pound);
526
+ continue;
527
+ }
528
+ const n = typeof raw === "number" ? raw : Number(raw);
529
+ let branch;
530
+ if (Number.isFinite(n)) {
531
+ branch = node.options[`=${n}`] ?? node.options[rulesFor(rt.locale, node.ordinal).select(n - node.offset)];
532
+ }
533
+ out += render(branch ?? node.options.other, values, rt, Number.isFinite(n) ? n - node.offset : null);
534
+ }
535
+ return out;
536
+ }
537
+ function formatMessage(source, values, rt) {
538
+ if (source.indexOf("{") < 0 && source.indexOf("'") < 0) return source;
539
+ return render(parseMessage(source), values, rt, null);
540
+ }
541
+
542
+ // src/core/format/calendar.ts
543
+ var SUNDAY_REGIONS = /* @__PURE__ */ new Set([
544
+ "AG",
545
+ "AS",
546
+ "BD",
547
+ "BR",
548
+ "BS",
549
+ "BT",
550
+ "BW",
551
+ "BZ",
552
+ "CA",
553
+ "CN",
554
+ "CO",
555
+ "DM",
556
+ "DO",
557
+ "ET",
558
+ "GT",
559
+ "GU",
560
+ "HK",
561
+ "HN",
562
+ "ID",
563
+ "IL",
564
+ "IN",
565
+ "JM",
566
+ "JP",
567
+ "KE",
568
+ "KH",
569
+ "KR",
570
+ "LA",
571
+ "MH",
572
+ "MM",
573
+ "MO",
574
+ "MT",
575
+ "MX",
576
+ "MZ",
577
+ "NI",
578
+ "NP",
579
+ "PA",
580
+ "PE",
581
+ "PH",
582
+ "PK",
583
+ "PR",
584
+ "PT",
585
+ "PY",
586
+ "SA",
587
+ "SG",
588
+ "SV",
589
+ "TH",
590
+ "TT",
591
+ "TW",
592
+ "UM",
593
+ "US",
594
+ "VE",
595
+ "VI",
596
+ "WS",
597
+ "YE",
598
+ "ZA",
599
+ "ZW"
600
+ ]);
601
+ var SATURDAY_REGIONS = /* @__PURE__ */ new Set(["AE", "AF", "BH", "DJ", "DZ", "EG", "IQ", "IR", "JO", "KW", "LY", "OM", "QA", "SD", "SY"]);
602
+ function localeWeekStart(locale) {
603
+ let loc;
604
+ try {
605
+ loc = new Intl.Locale(locale);
606
+ } catch {
607
+ return 1;
608
+ }
609
+ try {
610
+ const wl = loc;
611
+ const info = typeof wl.getWeekInfo === "function" ? wl.getWeekInfo() : wl.weekInfo;
612
+ const firstDay = info?.firstDay;
613
+ if (typeof firstDay === "number") return firstDay === 7 ? 0 : firstDay === 6 ? 6 : 1;
614
+ } catch {
615
+ }
616
+ let region = loc.region;
617
+ if (!region) {
618
+ try {
619
+ region = loc.maximize().region;
620
+ } catch {
621
+ region = void 0;
622
+ }
623
+ }
624
+ if (region && SUNDAY_REGIONS.has(region)) return 0;
625
+ if (region && SATURDAY_REGIONS.has(region)) return 6;
626
+ return 1;
627
+ }
628
+
629
+ // src/core/i18n/locale.ts
630
+ function canonicalLocale(tag) {
631
+ const raw = typeof tag === "string" ? tag.trim() : "";
632
+ if (!raw) return "en";
633
+ try {
634
+ return Intl.getCanonicalLocales(raw)[0] ?? raw;
635
+ } catch {
636
+ return raw;
637
+ }
638
+ }
639
+ function parseLocale(tag) {
640
+ try {
641
+ return new Intl.Locale(tag);
642
+ } catch {
643
+ return null;
644
+ }
645
+ }
646
+ function languageOf(tag) {
647
+ return (parseLocale(tag)?.language ?? tag.split(/[-_]/)[0] ?? tag).toLowerCase();
648
+ }
649
+ function fallbackChain(tag) {
650
+ const out = [];
651
+ const add = (t) => {
652
+ if (t && !out.includes(t)) out.push(t);
653
+ };
654
+ add(tag);
655
+ const loc = parseLocale(tag);
656
+ if (loc) {
657
+ const base = loc.baseName;
658
+ add(base);
659
+ const parts = base.split("-");
660
+ let impliedScript;
661
+ if (!loc.script) {
662
+ try {
663
+ impliedScript = loc.maximize().script;
664
+ } catch {
665
+ impliedScript = void 0;
666
+ }
667
+ }
668
+ for (let i = parts.length - 1; i >= 1; i -= 1) {
669
+ if (i === 1 && impliedScript && loc.region) add(`${loc.language}-${impliedScript}`);
670
+ add(parts.slice(0, i).join("-"));
671
+ }
672
+ if (impliedScript && !loc.region) add(`${loc.language}-${impliedScript}`);
673
+ try {
674
+ const usual = new Intl.Locale(loc.language).maximize();
675
+ if (usual.region && usual.script === (loc.script ?? impliedScript)) add(`${loc.language}-${usual.region}`);
676
+ } catch {
677
+ }
678
+ }
679
+ add("en");
680
+ return out;
681
+ }
682
+ var RTL_SCRIPTS = /* @__PURE__ */ new Set(["Arab", "Hebr", "Thaa", "Syrc", "Nkoo", "Adlm", "Rohg", "Mand", "Samr", "Yezi"]);
683
+ var RTL_LANGUAGES = /* @__PURE__ */ new Set(["ar", "he", "iw", "fa", "ur", "ps", "sd", "ug", "yi", "dv", "ckb", "ks"]);
684
+ function localeDirection(tag) {
685
+ const loc = parseLocale(tag);
686
+ if (loc) {
687
+ try {
688
+ const tl = loc;
689
+ const info = typeof tl.getTextInfo === "function" ? tl.getTextInfo() : tl.textInfo;
690
+ if (info?.direction === "rtl" || info?.direction === "ltr") return info.direction;
691
+ } catch {
692
+ }
693
+ try {
694
+ const script = loc.script ?? loc.maximize().script;
695
+ if (script) return RTL_SCRIPTS.has(script) ? "rtl" : "ltr";
696
+ } catch {
697
+ }
698
+ }
699
+ return RTL_LANGUAGES.has(languageOf(tag)) ? "rtl" : "ltr";
700
+ }
701
+ var numberingCache = /* @__PURE__ */ new Map();
702
+ function resolveNumberingSystem(tag, requested) {
703
+ const key = `${tag}|${requested ?? ""}`;
704
+ const cached = numberingCache.get(key);
705
+ if (cached) return cached;
706
+ let nu = "latn";
707
+ try {
708
+ if (requested === "locale") nu = new Intl.NumberFormat(tag).resolvedOptions().numberingSystem;
709
+ else if (requested) nu = new Intl.NumberFormat(tag, { numberingSystem: requested }).resolvedOptions().numberingSystem;
710
+ else {
711
+ const ext = parseLocale(tag)?.numberingSystem;
712
+ if (ext) nu = new Intl.NumberFormat(tag).resolvedOptions().numberingSystem;
713
+ }
714
+ } catch {
715
+ nu = "latn";
716
+ }
717
+ numberingCache.set(key, nu);
718
+ return nu;
719
+ }
720
+
721
+ // src/core/i18n/registry.ts
722
+ var entries = [];
723
+ var version = 0;
724
+ var merged = /* @__PURE__ */ new Map();
725
+ function registerLocale(pack) {
726
+ if (!pack || typeof pack.locale !== "string" || !pack.messages || typeof pack.messages !== "object") {
727
+ throw new TypeError("[vela] registerLocale expects { locale: string, messages: Record<string, string> }");
728
+ }
729
+ const entry = { tag: canonicalLocale(pack.locale), messages: pack.messages };
730
+ entries.push(entry);
731
+ version += 1;
732
+ let disposed = false;
733
+ return () => {
734
+ if (disposed) return;
735
+ disposed = true;
736
+ const i = entries.indexOf(entry);
737
+ if (i >= 0) {
738
+ entries.splice(i, 1);
739
+ version += 1;
740
+ }
741
+ };
742
+ }
743
+ function registeredLocales() {
744
+ return [...new Set(entries.map((e) => e.tag))];
745
+ }
746
+ function messagesFor(chain) {
747
+ const key = chain.join("|");
748
+ const hit = merged.get(key);
749
+ if (hit && hit.version === version) return hit.map;
750
+ const map = /* @__PURE__ */ new Map();
751
+ for (let c = chain.length - 1; c >= 0; c -= 1) {
752
+ const tag = chain[c];
753
+ for (const e of entries) {
754
+ if (e.tag !== tag) continue;
755
+ for (const [id, text] of Object.entries(e.messages)) {
756
+ if (typeof text === "string") map.set(id, text);
757
+ }
758
+ }
759
+ }
760
+ merged.set(key, { version, map });
761
+ return map;
762
+ }
763
+
764
+ // src/core/i18n/translator.ts
765
+ function isMessageDescriptor(m) {
766
+ return typeof m === "object" && m !== null && typeof m.id === "string" && typeof m.defaultMessage === "string";
767
+ }
768
+ var warnedSyntax = false;
769
+ function resolveArgs(args, resolve) {
770
+ if (!args) return void 0;
771
+ let out = null;
772
+ for (const key of Object.keys(args)) {
773
+ const v = args[key];
774
+ if (typeof v === "object" && v !== null) {
775
+ out ?? (out = { ...args });
776
+ out[key] = resolve(v);
777
+ }
778
+ }
779
+ return out ?? args;
780
+ }
781
+ var LocaleState = class {
782
+ constructor(options = {}) {
783
+ this.runtime = {
784
+ locale: "en",
785
+ formatNumber: (value, style) => formatMessageNumber(value, this.settings, style)
786
+ };
787
+ this.opts = { ...options };
788
+ this.resolve();
789
+ }
790
+ /** The options as last set (unresolved). */
791
+ get options() {
792
+ return this.opts;
793
+ }
794
+ /** Whether the host chose a locale; Vela stamps `lang` only then. */
795
+ get localeExplicit() {
796
+ return this.opts.locale !== void 0;
797
+ }
798
+ /** Whether the host chose a direction; Vela stamps `dir` only then. */
799
+ get directionExplicit() {
800
+ return this.opts.direction !== void 0;
801
+ }
802
+ /** Apply a change: fields present in `next` replace (an explicit `undefined` restores
803
+ * the default), absent fields keep their current value. */
804
+ update(next) {
805
+ const patch = typeof next === "string" ? { locale: next } : next;
806
+ this.opts = { ...this.opts, ...patch };
807
+ for (const key of Object.keys(this.opts)) {
808
+ if (this.opts[key] === void 0) delete this.opts[key];
809
+ }
810
+ this.resolve();
811
+ }
812
+ resolve() {
813
+ const o = this.opts;
814
+ const locale = canonicalLocale(o.locale);
815
+ const numberingSystem = resolveNumberingSystem(locale, o.numberingSystem);
816
+ const hourCycle = o.hourCycle === "h12" || o.hourCycle === "locale" ? o.hourCycle : "h23";
817
+ this.settings = { locale, numberingSystem, hourCycle, english: languageOf(locale) === "en" };
818
+ this.chain = fallbackChain(locale);
819
+ this.resolvedDirection = o.direction === "rtl" || o.direction === "ltr" ? o.direction : o.direction === "auto" ? localeDirection(locale) : "ltr";
820
+ this.resolvedWeekStart = o.weekStart === 0 || o.weekStart === 1 || o.weekStart === 6 ? o.weekStart : localeWeekStart(locale);
821
+ this.runtime.locale = locale;
822
+ this.formatters = resolveFormatters(this.settings, o.formatters);
823
+ }
824
+ get locale() {
825
+ return this.settings.locale;
826
+ }
827
+ get direction() {
828
+ return this.resolvedDirection;
829
+ }
830
+ get numberingSystem() {
831
+ return this.settings.numberingSystem;
832
+ }
833
+ get hourCycle() {
834
+ return this.settings.hourCycle;
835
+ }
836
+ get weekStart() {
837
+ return this.resolvedWeekStart;
838
+ }
839
+ get format() {
840
+ return this.formatters;
841
+ }
842
+ /** The resolved settings the built-in formatters and calendar helpers read. */
843
+ get formatSettings() {
844
+ return this.settings;
845
+ }
846
+ t(message, args) {
847
+ if (typeof message === "string") return message;
848
+ if (!isMessageDescriptor(message)) return message == null ? "" : String(message);
849
+ const { id, defaultMessage } = message;
850
+ const bound = message.values;
851
+ const values = resolveArgs(bound ? args ? { ...bound, ...args } : bound : args, (m) => this.t(m));
852
+ const override = this.opts.messages?.[id];
853
+ const source = typeof override === "string" ? override : messagesFor(this.chain).get(id) ?? defaultMessage;
854
+ try {
855
+ return formatMessage(source, values, this.runtime);
856
+ } catch (err) {
857
+ if (!warnedSyntax) {
858
+ warnedSyntax = true;
859
+ console.warn(`[vela] message "${id}" could not be formatted; the English text is used instead.`, err);
860
+ }
861
+ if (source === defaultMessage) return defaultMessage;
862
+ try {
863
+ return formatMessage(defaultMessage, values, this.runtime);
864
+ } catch {
865
+ return defaultMessage;
866
+ }
867
+ }
868
+ }
869
+ };
870
+ function createTranslator(options) {
871
+ return new LocaleState(options);
872
+ }
873
+ var english = null;
874
+ function englishTranslator() {
875
+ english ?? (english = new LocaleState());
876
+ return english;
877
+ }
878
+ function formatSettingsOf(i18n) {
879
+ if (i18n instanceof LocaleState) return i18n.formatSettings;
880
+ if (!i18n) return englishTranslator().formatSettings;
881
+ return { locale: i18n.locale, numberingSystem: i18n.numberingSystem, hourCycle: i18n.hourCycle, english: languageOf(i18n.locale) === "en" };
882
+ }
883
+
884
+ // src/core/i18n/text.ts
885
+ var ENGLISH_RUNTIME = {
886
+ locale: "en",
887
+ formatNumber: (value, style) => formatMessageNumber(value, ENGLISH_SETTINGS, style)
888
+ };
889
+ function sourceText(message, values) {
890
+ if (message == null) return "";
891
+ if (typeof message === "string") return message;
892
+ if (!isMessageDescriptor(message)) return String(message);
893
+ const bound = message.values;
894
+ const all = resolveArgs(bound ? bound : values, (m) => sourceText(m));
895
+ try {
896
+ return formatMessage(message.defaultMessage, all, ENGLISH_RUNTIME);
897
+ } catch {
898
+ return message.defaultMessage;
899
+ }
900
+ }
901
+ function textOf(i18n, message, values) {
902
+ return (i18n ?? englishTranslator()).t(message, values);
903
+ }
904
+ function localizeNumberText(text, i18n) {
905
+ return localizeAscii(text, formatSettingsOf(i18n));
906
+ }
907
+
3
908
  // src/chart-types/registry.ts
909
+ var RANGE_MIN = msg("chart.settings.rangeMin", "{label} — min");
910
+ var RANGE_MAX = msg("chart.settings.rangeMax", "{label} — max");
4
911
  function normalizeSettingsRow(r) {
5
912
  switch (r.kind) {
6
913
  case "row":
@@ -22,9 +929,9 @@ function normalizeSettingsRow(r) {
22
929
  return {
23
930
  label: r.label,
24
931
  controls: [
25
- { kind: "number", key: r.minKey, label: `${r.label} \u2014 min`, defval: r.defval, min: r.min, max: r.max, step: r.step, placeholder: r.placeholder },
26
- { kind: "hint", text: "\u2013" },
27
- { kind: "number", key: r.maxKey, label: `${r.label} \u2014 max`, defval: r.defval, min: r.min, max: r.max, step: r.step, placeholder: r.placeholder }
932
+ { kind: "number", key: r.minKey, label: withValues(RANGE_MIN, { label: r.label }), defval: r.defval, min: r.min, max: r.max, step: r.step, placeholder: r.placeholder },
933
+ { kind: "hint", text: "–" },
934
+ { kind: "number", key: r.maxKey, label: withValues(RANGE_MAX, { label: r.label }), defval: r.defval, min: r.min, max: r.max, step: r.step, placeholder: r.placeholder }
28
935
  ],
29
936
  when: r.when
30
937
  };
@@ -84,8 +991,15 @@ function registerNativeIndicator(descriptor) {
84
991
  function unregisterNativeIndicator(type) {
85
992
  REGISTRY.delete(type);
86
993
  }
87
- function getNativeIndicator(type) {
88
- return REGISTRY.get(type);
994
+ function resolved(d, i18n) {
995
+ if (typeof d.title === "string" && (d.shortTitle === void 0 || typeof d.shortTitle === "string")) return d;
996
+ const names = { title: textOf(i18n, d.title) };
997
+ if (d.shortTitle !== void 0) names.shortTitle = textOf(i18n, d.shortTitle);
998
+ return Object.assign(Object.create(d), names);
999
+ }
1000
+ function getNativeIndicator(type, i18n) {
1001
+ const d = REGISTRY.get(type);
1002
+ return d ? resolved(d, i18n) : void 0;
89
1003
  }
90
1004
  function nativeIndicatorTypes() {
91
1005
  return [...REGISTRY.keys()];
@@ -144,7 +1058,7 @@ function topbarActionOverride(id) {
144
1058
  }
145
1059
  function registerWidgetAction(desc) {
146
1060
  if (builtinTopbarSet.has(desc.id) && !overridableSet.has(desc.id)) {
147
- console.warn(`[vela] widget action "${desc.id}": this built-in topbar slot is a stateful control and cannot be overridden \u2014 ignored. Overridable slots: ${OVERRIDABLE_TOPBAR_IDS.join(", ")}.`);
1061
+ console.warn(`[vela] widget action "${desc.id}": this built-in topbar slot is a stateful control and cannot be overridden — ignored. Overridable slots: ${OVERRIDABLE_TOPBAR_IDS.join(", ")}.`);
148
1062
  return () => void 0;
149
1063
  }
150
1064
  registry3.set(desc.id, desc);
@@ -222,12 +1136,11 @@ function unregisterDefaultEngine(language) {
222
1136
  function resolveEngines(overrides) {
223
1137
  return { ...Object.fromEntries(defaultEngines), ...overrides };
224
1138
  }
225
-
226
- // src/widget/context-menu-model.ts
227
1139
  var CONTEXT_MENU_BUILTIN_ORDER = {
228
1140
  body: { "reset-view": -30, "remove-drawings": -20, "remove-indicators": -10, settings: 1e3 },
229
1141
  "price-axis": {
230
1142
  auto: -80,
1143
+ "price-only": -75,
231
1144
  invert: -70,
232
1145
  "scale:regular": -60,
233
1146
  "scale:percent": -50,
@@ -397,13 +1310,11 @@ registerIcon(
397
1310
  "send-back",
398
1311
  svg24('<rect x="8.5" y="8.5" width="7" height="7" rx="1.5" fill="currentColor" stroke="none" opacity="0.35"/><path d="M4.5 10.5V6a1.5 1.5 0 0 1 1.5-1.5h4.5"/><path d="M19.5 13.5V18a1.5 1.5 0 0 1-1.5 1.5h-4.5"/><rect x="8.5" y="8.5" width="7" height="7" rx="1.5"/>')
399
1312
  );
400
- registerIcon("r-squared", '<svg viewBox="0 0 24 24" width="1em" height="1em" fill="currentColor" stroke="none"><text x="2.5" y="17.5" font-size="14" font-family="serif">R\xB2</text></svg>');
1313
+ registerIcon("r-squared", '<svg viewBox="0 0 24 24" width="1em" height="1em" fill="currentColor" stroke="none"><text x="2.5" y="17.5" font-size="14" font-family="serif">R²</text></svg>');
401
1314
  registerIcon("bands", svg24('<path d="M3 6h18"/><path d="M3 18h18"/><path d="M3 12h18" stroke-dasharray="3 3"/>'));
402
1315
  registerIcon("dedekind", svg24('<path d="M2 20h20"/><path d="M4 20a8 8 0 0 1 16 0"/><path d="M8 20a4 4 0 0 1 8 0"/><path d="M12 4v16"/>'));
403
1316
  registerIcon("sonic", svg24('<circle cx="15" cy="12" r="4"/><circle cx="12" cy="12" r="2.5"/><path d="M8 5v14"/>'));
404
1317
  registerIcon("supersonic", svg24('<circle cx="16" cy="12" r="3.5"/><path d="M6 12 15 6M6 12 15 18"/>'));
405
-
406
- // src/widget/side-panel.ts
407
1318
  var DEFAULT_PANEL_WIDTH = 280;
408
1319
  var DEFAULT_PANEL_MIN_WIDTH = 200;
409
1320
  var DEFAULT_PANEL_MAX_WIDTH = 640;
@@ -458,15 +1369,15 @@ var MIN = 6e4;
458
1369
  var HOUR = 60 * MIN;
459
1370
  var DAY = 24 * HOUR;
460
1371
  var TIMEFRAME_BANDS = [
461
- { key: "s", label: "Sec", fromMs: 0 },
462
- { key: "1", label: "1m", fromMs: MIN },
463
- { key: "5", label: "5m", fromMs: 5 * MIN },
464
- { key: "15", label: "15m", fromMs: 15 * MIN },
465
- { key: "60", label: "1H", fromMs: HOUR },
466
- { key: "240", label: "4H", fromMs: 4 * HOUR },
467
- { key: "D", label: "D", fromMs: DAY },
468
- { key: "W", label: "W", fromMs: 7 * DAY },
469
- { key: "M", label: "M", fromMs: 28 * DAY }
1372
+ { key: "s", label: msg("drawing.showOn.seconds", "Sec"), fromMs: 0 },
1373
+ { key: "1", label: msg("drawing.showOn.minute1", "1m"), fromMs: MIN },
1374
+ { key: "5", label: msg("drawing.showOn.minute5", "5m"), fromMs: 5 * MIN },
1375
+ { key: "15", label: msg("drawing.showOn.minute15", "15m"), fromMs: 15 * MIN },
1376
+ { key: "60", label: msg("drawing.showOn.hour1", "1H"), fromMs: HOUR },
1377
+ { key: "240", label: msg("drawing.showOn.hour4", "4H"), fromMs: 4 * HOUR },
1378
+ { key: "D", label: msg("drawing.showOn.day", "D"), fromMs: DAY },
1379
+ { key: "W", label: msg("drawing.showOn.week", "W"), fromMs: 7 * DAY },
1380
+ { key: "M", label: msg("drawing.showOn.month", "M"), fromMs: 28 * DAY }
470
1381
  ];
471
1382
  var BAND_KEYS = new Set(TIMEFRAME_BANDS.map((b) => b.key));
472
1383
  function sanitizeShowOn(v) {
@@ -546,6 +1457,12 @@ var _Drawing = class _Drawing {
546
1457
  }
547
1458
  return { min: lo, max: hi };
548
1459
  }
1460
+ /** The text a fresh drawing of this type starts with ("Note", "Callout"), as a message,
1461
+ * or null for a type that seeds none. A new drawing stores its English source; the chart
1462
+ * that places one interactively writes it in its own language instead. */
1463
+ placeholderText() {
1464
+ return null;
1465
+ }
549
1466
  /**
550
1467
  * Editable per-level config for a rich "gear" settings panel (Fibonacci levels):
551
1468
  * each entry's `color` / `enabled` / `label` is mutated via a `levels.<i>.<field>`
@@ -612,28 +1529,33 @@ function setByPath(obj, path, value) {
612
1529
 
613
1530
  // src/core/drawings/schema.ts
614
1531
  var LINE_STYLE_OPTIONS = [
615
- { value: "solid", label: "Solid" },
616
- { value: "dashed", label: "Dashed" },
617
- { value: "dotted", label: "Dotted" }
1532
+ { value: "solid", label: msg("drawing.option.solid", "Solid") },
1533
+ { value: "dashed", label: msg("drawing.option.dashed", "Dashed") },
1534
+ { value: "dotted", label: msg("drawing.option.dotted", "Dotted") }
618
1535
  ];
619
1536
  var LINE_FIELDS = [
620
- { path: "style.lineColor", label: "Line color", kind: "color", group: "line" },
621
- { path: "style.lineWidth", label: "Line width", kind: "number", min: 1, max: 10, step: 1, group: "line" },
622
- { path: "style.lineStyle", label: "Line style", kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" }
1537
+ { path: "style.lineColor", label: msg("drawing.field.lineColor", "Line color"), kind: "color", group: "line" },
1538
+ { path: "style.lineWidth", label: msg("drawing.field.lineWidth", "Line width"), kind: "number", min: 1, max: 10, step: 1, group: "line" },
1539
+ { path: "style.lineStyle", label: msg("drawing.field.lineStyle", "Line style"), kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" }
1540
+ ];
1541
+ var BORDER_FIELDS = [
1542
+ { path: "style.lineColor", label: msg("drawing.field.borderColor", "Border color"), kind: "color", group: "line" },
1543
+ { path: "style.lineWidth", label: msg("drawing.field.borderWidth", "Border width"), kind: "number", min: 1, max: 10, step: 1, group: "line" },
1544
+ { path: "style.lineStyle", label: msg("drawing.field.borderStyle", "Border style"), kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" }
623
1545
  ];
624
- var FILL_FIELDS = [{ path: "style.fillColor", label: "Fill color", kind: "color", group: "fill" }];
1546
+ var FILL_FIELDS = [{ path: "style.fillColor", label: msg("drawing.field.fillColor", "Fill color"), kind: "color", group: "fill" }];
625
1547
  var TEXT_SIZE_OPTIONS = [
626
- { value: "small", label: "Small" },
627
- { value: "normal", label: "Normal" },
628
- { value: "large", label: "Large" },
629
- { value: "huge", label: "Huge" }
1548
+ { value: "small", label: msg("drawing.option.small", "Small") },
1549
+ { value: "normal", label: msg("drawing.option.normal", "Normal") },
1550
+ { value: "large", label: msg("drawing.option.large", "Large") },
1551
+ { value: "huge", label: msg("drawing.option.huge", "Huge") }
630
1552
  ];
631
1553
  var TEXT_FIELDS = [
632
- { path: "text.value", label: "Text", kind: "text", group: "text" },
633
- { path: "text.color", label: "Text color", kind: "color", group: "text" },
634
- { path: "text.size", label: "Text size", kind: "select", options: TEXT_SIZE_OPTIONS, group: "text" },
635
- { path: "text.bold", label: "Bold", kind: "boolean", group: "text" },
636
- { path: "text.italic", label: "Italic", kind: "boolean", group: "text" }
1554
+ { path: "text.value", label: msg("drawing.field.text", "Text"), kind: "text", group: "text" },
1555
+ { path: "text.color", label: msg("drawing.field.textColor", "Text color"), kind: "color", group: "text" },
1556
+ { path: "text.size", label: msg("drawing.field.textSize", "Text size"), kind: "select", options: TEXT_SIZE_OPTIONS, group: "text" },
1557
+ { path: "text.bold", label: msg("drawing.field.bold", "Bold"), kind: "boolean", group: "text" },
1558
+ { path: "text.italic", label: msg("drawing.field.italic", "Italic"), kind: "boolean", group: "text" }
637
1559
  ];
638
1560
 
639
1561
  // src/core/drawings/hittest.ts
@@ -751,9 +1673,9 @@ var TrendLine = class extends Drawing {
751
1673
  return {
752
1674
  fields: [
753
1675
  ...LINE_FIELDS,
754
- { path: "style.arrowRight", label: "Arrow", kind: "boolean", group: "line" },
755
- { path: "style.extendLeft", label: "Extend left", kind: "boolean", group: "line" },
756
- { path: "style.extendRight", label: "Extend right", kind: "boolean", group: "line" },
1676
+ { path: "style.arrowRight", label: msg("drawing.trendline.arrowRight", "Arrow"), kind: "boolean", group: "line" },
1677
+ { path: "style.extendLeft", label: msg("drawing.trendline.extendLeft", "Extend left"), kind: "boolean", group: "line" },
1678
+ { path: "style.extendRight", label: msg("drawing.trendline.extendRight", "Extend right"), kind: "boolean", group: "line" },
757
1679
  ...TEXT_FIELDS
758
1680
  ]
759
1681
  };
@@ -1102,8 +2024,8 @@ var Box = class extends Drawing {
1102
2024
  schema() {
1103
2025
  return {
1104
2026
  fields: [
1105
- ...LINE_FIELDS.map((f) => ({ ...f, label: f.label.replace("Line", "Border") })),
1106
- { path: "style.fillColor", label: "Fill color", kind: "color", group: "fill" },
2027
+ ...BORDER_FIELDS,
2028
+ { path: "style.fillColor", label: msg("drawing.box.fillColor", "Fill color"), kind: "color", group: "fill" },
1107
2029
  ...TEXT_FIELDS
1108
2030
  ]
1109
2031
  };
@@ -1113,13 +2035,16 @@ var Box = class extends Drawing {
1113
2035
  // src/core/drawings/types/PinnedLabel.ts
1114
2036
  var SIZE_PX = { tiny: 10, small: 12, normal: 14, large: 18, huge: 24, auto: 14 };
1115
2037
  var PinnedLabel = class extends Drawing {
1116
- /** The placeholder string when no text has been entered yet. */
2038
+ /** The placeholder text when no text has been entered yet. */
1117
2039
  defaultLabel() {
1118
- return "Text";
2040
+ return msg("drawing.text.placeholder", "Text");
2041
+ }
2042
+ placeholderText() {
2043
+ return this.defaultLabel();
1119
2044
  }
1120
2045
  /** The string used to size the approximate hit box (subclasses with computed text override it). */
1121
2046
  labelText() {
1122
- return this.text?.value ?? this.defaultLabel();
2047
+ return this.text?.value ?? sourceText(this.defaultLabel());
1123
2048
  }
1124
2049
  anchorSchema() {
1125
2050
  return { min: 1, max: 1, slots: [{ role: "p", free: "both" }] };
@@ -1173,10 +2098,10 @@ var Note = class extends PinnedLabel {
1173
2098
  constructor(init) {
1174
2099
  super(init);
1175
2100
  this.type = "note";
1176
- if (!this.text) this.text = defaultText("Note");
2101
+ if (!this.text) this.text = defaultText(sourceText(this.defaultLabel()));
1177
2102
  }
1178
2103
  defaultLabel() {
1179
- return "Note";
2104
+ return msg("drawing.note.placeholder", "Note");
1180
2105
  }
1181
2106
  schema() {
1182
2107
  return { fields: [...LINE_FIELDS, ...FILL_FIELDS, ...TEXT_FIELDS], textIsContent: true };
@@ -1205,15 +2130,19 @@ var SIZE_PX2 = { tiny: 10, small: 12, normal: 14, large: 18, huge: 24, auto: 14
1205
2130
  var CalloutBase = class extends Drawing {
1206
2131
  constructor(init) {
1207
2132
  super(init);
1208
- if (!this.text) this.text = defaultText(this.defaultLabel());
2133
+ if (!this.text) this.text = defaultText(sourceText(this.defaultLabel()));
1209
2134
  }
1210
2135
  /** The placeholder text seeded for a fresh annotation. */
1211
2136
  defaultLabel() {
1212
- return "Callout";
2137
+ return msg("drawing.callout.placeholder", "Callout");
2138
+ }
2139
+ placeholderText() {
2140
+ const label = this.defaultLabel();
2141
+ return sourceText(label) === "" ? null : label;
1213
2142
  }
1214
2143
  /** The string used to size the approximate hit box (auto-text subclasses override it). */
1215
2144
  labelText() {
1216
- return this.text?.value ?? this.defaultLabel();
2145
+ return this.text?.value ?? sourceText(this.defaultLabel());
1217
2146
  }
1218
2147
  anchorSchema() {
1219
2148
  return { min: 2, max: 2, slots: [{ role: "target", free: "both" }, { role: "box", free: "both" }] };
@@ -1318,7 +2247,7 @@ var Comment = class extends CalloutBase {
1318
2247
  this.type = "comment";
1319
2248
  }
1320
2249
  defaultLabel() {
1321
- return "Comment";
2250
+ return msg("drawing.comment.placeholder", "Comment");
1322
2251
  }
1323
2252
  };
1324
2253
 
@@ -1329,7 +2258,7 @@ var Signpost = class extends CalloutBase {
1329
2258
  this.type = "signpost";
1330
2259
  }
1331
2260
  defaultLabel() {
1332
- return "Signpost";
2261
+ return msg("drawing.signpost.placeholder", "Signpost");
1333
2262
  }
1334
2263
  };
1335
2264
 
@@ -1758,15 +2687,15 @@ var RegressionChannel = class extends Drawing {
1758
2687
  schema() {
1759
2688
  return {
1760
2689
  fields: [
1761
- { path: "reg.midColor", label: "Midline color", kind: "color", group: "line" },
1762
- { path: "reg.midStyle", label: "Midline style", kind: "lineStyle", group: "line" },
1763
- { path: "reg.upperColor", label: "Upper line color", kind: "color", group: "line" },
1764
- { path: "reg.upperStyle", label: "Upper line style", kind: "lineStyle", group: "line" },
1765
- { path: "reg.lowerColor", label: "Lower line color", kind: "color", group: "line" },
1766
- { path: "reg.lowerStyle", label: "Lower line style", kind: "lineStyle", group: "line" },
1767
- { path: "reg.upperFill", label: "Upper fill", kind: "color", group: "fill" },
1768
- { path: "reg.lowerFill", label: "Lower fill", kind: "color", group: "fill" },
1769
- { path: "reg.showR2", label: "Show R\xB2", kind: "boolean", group: "behavior" }
2690
+ { path: "reg.midColor", label: msg("drawing.regressionchannel.regMidColor", "Midline color"), kind: "color", group: "line" },
2691
+ { path: "reg.midStyle", label: msg("drawing.regressionchannel.regMidStyle", "Midline style"), kind: "lineStyle", group: "line" },
2692
+ { path: "reg.upperColor", label: msg("drawing.regressionchannel.regUpperColor", "Upper line color"), kind: "color", group: "line" },
2693
+ { path: "reg.upperStyle", label: msg("drawing.regressionchannel.regUpperStyle", "Upper line style"), kind: "lineStyle", group: "line" },
2694
+ { path: "reg.lowerColor", label: msg("drawing.regressionchannel.regLowerColor", "Lower line color"), kind: "color", group: "line" },
2695
+ { path: "reg.lowerStyle", label: msg("drawing.regressionchannel.regLowerStyle", "Lower line style"), kind: "lineStyle", group: "line" },
2696
+ { path: "reg.upperFill", label: msg("drawing.regressionchannel.regUpperFill", "Upper fill"), kind: "color", group: "fill" },
2697
+ { path: "reg.lowerFill", label: msg("drawing.regressionchannel.regLowerFill", "Lower fill"), kind: "color", group: "fill" },
2698
+ { path: "reg.showR2", label: msg("drawing.regressionchannel.regShowR2", "Show R²"), kind: "boolean", group: "behavior" }
1770
2699
  ]
1771
2700
  };
1772
2701
  }
@@ -1916,12 +2845,12 @@ var AnchoredVwap = class extends Drawing {
1916
2845
  schema() {
1917
2846
  return {
1918
2847
  fields: [
1919
- { path: "vwap.midColor", label: "VWAP color", kind: "color", group: "line" },
1920
- { path: "vwap.midStyle", label: "VWAP style", kind: "lineStyle", group: "line" },
1921
- { path: "vwap.multiplier", label: "Band multiplier", kind: "number", min: 0.5, max: 5, step: 0.5, group: "behavior" },
1922
- { path: "vwap.upperColor", label: "Upper band color", kind: "color", group: "line" },
1923
- { path: "vwap.lowerColor", label: "Lower band color", kind: "color", group: "line" },
1924
- { path: "vwap.bandFill", label: "Band fill", kind: "color", group: "fill" }
2848
+ { path: "vwap.midColor", label: msg("drawing.anchoredvwap.vwapMidColor", "VWAP color"), kind: "color", group: "line" },
2849
+ { path: "vwap.midStyle", label: msg("drawing.anchoredvwap.vwapMidStyle", "VWAP style"), kind: "lineStyle", group: "line" },
2850
+ { path: "vwap.multiplier", label: msg("drawing.anchoredvwap.vwapMultiplier", "Band multiplier"), kind: "number", min: 0.5, max: 5, step: 0.5, group: "behavior" },
2851
+ { path: "vwap.upperColor", label: msg("drawing.anchoredvwap.vwapUpperColor", "Upper band color"), kind: "color", group: "line" },
2852
+ { path: "vwap.lowerColor", label: msg("drawing.anchoredvwap.vwapLowerColor", "Lower band color"), kind: "color", group: "line" },
2853
+ { path: "vwap.bandFill", label: msg("drawing.anchoredvwap.vwapBandFill", "Band fill"), kind: "color", group: "fill" }
1925
2854
  ]
1926
2855
  };
1927
2856
  }
@@ -2224,38 +3153,38 @@ var FixedRangeVolumeProfile = class extends Drawing {
2224
3153
  schema() {
2225
3154
  return {
2226
3155
  fields: [
2227
- { path: "frvp.rows", label: "Rows", kind: "number", min: 1, max: 500, step: 1, group: "behavior" },
2228
- { path: "frvp.valueAreaPct", label: "Value Area", kind: "number", min: 0, max: 100, step: 1, group: "behavior" },
2229
- { path: "frvp.widthPct", label: "Width %", kind: "number", min: 0, max: 100, step: 1, group: "behavior" },
3156
+ { path: "frvp.rows", label: msg("drawing.fixedrangevp.frvpRows", "Rows"), kind: "number", min: 1, max: 500, step: 1, group: "behavior" },
3157
+ { path: "frvp.valueAreaPct", label: msg("drawing.fixedrangevp.frvpValueAreaPct", "Value Area"), kind: "number", min: 0, max: 100, step: 1, group: "behavior" },
3158
+ { path: "frvp.widthPct", label: msg("drawing.fixedrangevp.frvpWidthPct", "Width %"), kind: "number", min: 0, max: 100, step: 1, group: "behavior" },
2230
3159
  {
2231
3160
  path: "frvp.anchor",
2232
- label: "Anchor",
3161
+ label: msg("drawing.fixedrangevp.frvpAnchor", "Anchor"),
2233
3162
  kind: "select",
2234
3163
  options: [
2235
- { value: "right", label: "Right" },
2236
- { value: "left", label: "Left" }
3164
+ { value: "right", label: msg("drawing.fixedrangevp.option.right", "Right") },
3165
+ { value: "left", label: msg("drawing.fixedrangevp.option.left", "Left") }
2237
3166
  ],
2238
3167
  group: "behavior"
2239
3168
  },
2240
- { path: "frvp.upColor", label: "Up Volume", kind: "color", group: "fill" },
2241
- { path: "frvp.downColor", label: "Down Volume", kind: "color", group: "fill" },
2242
- { path: "frvp.vaUpColor", label: "Value Area Up", kind: "color", group: "fill" },
2243
- { path: "frvp.vaDownColor", label: "Value Area Down", kind: "color", group: "fill" },
2244
- { path: "frvp.showVah", label: "VAH", kind: "boolean", group: "line" },
2245
- { path: "frvp.vahColor", label: "VAH color", kind: "color", group: "line" },
2246
- { path: "frvp.vahStyle", label: "VAH style", kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" },
2247
- { path: "frvp.showVal", label: "VAL", kind: "boolean", group: "line" },
2248
- { path: "frvp.valColor", label: "VAL color", kind: "color", group: "line" },
2249
- { path: "frvp.valStyle", label: "VAL style", kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" },
2250
- { path: "frvp.showPoc", label: "POC", kind: "boolean", group: "line" },
2251
- { path: "frvp.pocColor", label: "POC color", kind: "color", group: "line" },
2252
- { path: "frvp.pocStyle", label: "POC style", kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" },
2253
- { path: "frvp.showDevelopingPoc", label: "Developing POC", kind: "boolean", group: "line" },
2254
- { path: "frvp.developingPocColor", label: "Developing POC color", kind: "color", group: "line" },
2255
- { path: "frvp.developingPocStyle", label: "Developing POC style", kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" },
2256
- { path: "frvp.showDevelopingVa", label: "Developing VA", kind: "boolean", group: "line" },
2257
- { path: "frvp.developingVaColor", label: "Developing VA color", kind: "color", group: "line" },
2258
- { path: "frvp.developingVaStyle", label: "Developing VA style", kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" }
3169
+ { path: "frvp.upColor", label: msg("drawing.fixedrangevp.frvpUpColor", "Up Volume"), kind: "color", group: "fill" },
3170
+ { path: "frvp.downColor", label: msg("drawing.fixedrangevp.frvpDownColor", "Down Volume"), kind: "color", group: "fill" },
3171
+ { path: "frvp.vaUpColor", label: msg("drawing.fixedrangevp.frvpVaUpColor", "Value Area Up"), kind: "color", group: "fill" },
3172
+ { path: "frvp.vaDownColor", label: msg("drawing.fixedrangevp.frvpVaDownColor", "Value Area Down"), kind: "color", group: "fill" },
3173
+ { path: "frvp.showVah", label: msg("drawing.fixedrangevp.frvpShowVah", "VAH"), kind: "boolean", group: "line" },
3174
+ { path: "frvp.vahColor", label: msg("drawing.fixedrangevp.frvpVahColor", "VAH color"), kind: "color", group: "line" },
3175
+ { path: "frvp.vahStyle", label: msg("drawing.fixedrangevp.frvpVahStyle", "VAH style"), kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" },
3176
+ { path: "frvp.showVal", label: msg("drawing.fixedrangevp.frvpShowVal", "VAL"), kind: "boolean", group: "line" },
3177
+ { path: "frvp.valColor", label: msg("drawing.fixedrangevp.frvpValColor", "VAL color"), kind: "color", group: "line" },
3178
+ { path: "frvp.valStyle", label: msg("drawing.fixedrangevp.frvpValStyle", "VAL style"), kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" },
3179
+ { path: "frvp.showPoc", label: msg("drawing.fixedrangevp.frvpShowPoc", "POC"), kind: "boolean", group: "line" },
3180
+ { path: "frvp.pocColor", label: msg("drawing.fixedrangevp.frvpPocColor", "POC color"), kind: "color", group: "line" },
3181
+ { path: "frvp.pocStyle", label: msg("drawing.fixedrangevp.frvpPocStyle", "POC style"), kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" },
3182
+ { path: "frvp.showDevelopingPoc", label: msg("drawing.fixedrangevp.frvpShowDevelopingPoc", "Developing POC"), kind: "boolean", group: "line" },
3183
+ { path: "frvp.developingPocColor", label: msg("drawing.fixedrangevp.frvpDevelopingPocColor", "Developing POC color"), kind: "color", group: "line" },
3184
+ { path: "frvp.developingPocStyle", label: msg("drawing.fixedrangevp.frvpDevelopingPocStyle", "Developing POC style"), kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" },
3185
+ { path: "frvp.showDevelopingVa", label: msg("drawing.fixedrangevp.frvpShowDevelopingVa", "Developing VA"), kind: "boolean", group: "line" },
3186
+ { path: "frvp.developingVaColor", label: msg("drawing.fixedrangevp.frvpDevelopingVaColor", "Developing VA color"), kind: "color", group: "line" },
3187
+ { path: "frvp.developingVaStyle", label: msg("drawing.fixedrangevp.frvpDevelopingVaStyle", "Developing VA style"), kind: "lineStyle", options: LINE_STYLE_OPTIONS, group: "line" }
2259
3188
  ]
2260
3189
  };
2261
3190
  }
@@ -2525,8 +3454,8 @@ var Arrow = class extends Drawing {
2525
3454
  return {
2526
3455
  fields: [
2527
3456
  ...LINE_FIELDS,
2528
- { path: "style.arrowRight", label: "Head (end)", kind: "boolean", group: "line" },
2529
- { path: "style.arrowLeft", label: "Head (start)", kind: "boolean", group: "line" },
3457
+ { path: "style.arrowRight", label: msg("drawing.arrow.arrowRight", "Head (end)"), kind: "boolean", group: "line" },
3458
+ { path: "style.arrowLeft", label: msg("drawing.arrow.arrowLeft", "Head (start)"), kind: "boolean", group: "line" },
2530
3459
  ...TEXT_FIELDS
2531
3460
  ]
2532
3461
  };
@@ -2716,8 +3645,8 @@ var Freehand = class extends BrushStroke {
2716
3645
 
2717
3646
  // src/core/drawings/types/Highlighter.ts
2718
3647
  var HIGHLIGHTER_FIELDS = [
2719
- { path: "style.lineColor", label: "Color", kind: "color", group: "line" },
2720
- { path: "style.lineWidth", label: "Width", kind: "number", min: 4, max: 60, step: 1, group: "line" }
3648
+ { path: "style.lineColor", label: msg("drawing.highlighter.lineColor", "Color"), kind: "color", group: "line" },
3649
+ { path: "style.lineWidth", label: msg("drawing.highlighter.lineWidth", "Width"), kind: "number", min: 4, max: 60, step: 1, group: "line" }
2721
3650
  ];
2722
3651
  var Highlighter = class extends BrushStroke {
2723
3652
  constructor() {
@@ -2836,7 +3765,7 @@ var RotatedRect = class extends SegmentDrawing {
2836
3765
  return { min: Math.min(...ps), max: Math.max(...ps) };
2837
3766
  }
2838
3767
  schema() {
2839
- return { fields: [...LINE_FIELDS.map((f) => ({ ...f, label: f.label.replace("Line", "Border") })), ...FILL_FIELDS, ...TEXT_FIELDS] };
3768
+ return { fields: [...BORDER_FIELDS, ...FILL_FIELDS, ...TEXT_FIELDS] };
2840
3769
  }
2841
3770
  };
2842
3771
 
@@ -2918,7 +3847,7 @@ var Arc = class extends SegmentDrawing {
2918
3847
  return { min: Math.min(...ps), max: Math.max(...ps) };
2919
3848
  }
2920
3849
  schema() {
2921
- return { fields: [...LINE_FIELDS.map((f) => ({ ...f, label: f.label.replace("Line", "Border") })), ...FILL_FIELDS, ...TEXT_FIELDS] };
3850
+ return { fields: [...BORDER_FIELDS, ...FILL_FIELDS, ...TEXT_FIELDS] };
2922
3851
  }
2923
3852
  };
2924
3853
 
@@ -3034,7 +3963,7 @@ var ArrowMark = class extends Drawing {
3034
3963
  return a ? { min: a.price, max: a.price } : null;
3035
3964
  }
3036
3965
  schema() {
3037
- return { fields: [{ path: "style.lineColor", label: "Color", kind: "color", group: "line" }, ...TEXT_FIELDS] };
3966
+ return { fields: [{ path: "style.lineColor", label: msg("drawing.arrowmarkup.lineColor", "Color"), kind: "color", group: "line" }, ...TEXT_FIELDS] };
3038
3967
  }
3039
3968
  };
3040
3969
  var ArrowMarkUp = class extends ArrowMark {
@@ -3057,7 +3986,7 @@ var ArrowMarkDown = class extends ArrowMark {
3057
3986
  };
3058
3987
 
3059
3988
  // src/core/drawings/types/GlyphStamp.ts
3060
- var GLYPH_OPTIONS = ["\u2605", "\u2606", "\u25CF", "\u25C6", "\u25B2", "\u25BC", "\u27A4", "\u2691", "\u271A", "\u2715", "\u2764", "\u2666"];
3989
+ var GLYPH_OPTIONS = ["★", "☆", "●", "◆", "▲", "▼", "➤", "⚑", "✚", "✕", "❤", "♦"];
3061
3990
  var STAMP_SIZE_OPTIONS = ["small", "normal", "large", "huge"];
3062
3991
  var STAMP_PX = { small: 16, normal: 22, large: 32, huge: 44 };
3063
3992
  var GlyphStamp = class extends Drawing {
@@ -3106,9 +4035,9 @@ var GlyphStamp = class extends Drawing {
3106
4035
  schema() {
3107
4036
  return {
3108
4037
  fields: [
3109
- { path: "glyph", label: "Icon", kind: "select", options: GLYPH_OPTIONS.map((g) => ({ value: g, label: g })), group: "line" },
3110
- { path: "size", label: "Size", kind: "select", options: STAMP_SIZE_OPTIONS.map((s) => ({ value: s, label: s })), group: "line" },
3111
- { path: "style.lineColor", label: "Color", kind: "color", group: "line" },
4038
+ { path: "glyph", label: msg("drawing.flagmark.glyph", "Icon"), kind: "select", options: GLYPH_OPTIONS.map((g) => ({ value: g, label: g })), group: "line" },
4039
+ { path: "size", label: msg("drawing.flagmark.size", "Size"), kind: "select", options: STAMP_SIZE_OPTIONS.map((s) => ({ value: s, label: s })), group: "line" },
4040
+ { path: "style.lineColor", label: msg("drawing.flagmark.lineColor", "Color"), kind: "color", group: "line" },
3112
4041
  ...TEXT_FIELDS
3113
4042
  ]
3114
4043
  };
@@ -3127,7 +4056,7 @@ var FlagMark = class extends GlyphStamp {
3127
4056
  this.type = "flagmark";
3128
4057
  }
3129
4058
  defaultGlyph() {
3130
- return "\u2691";
4059
+ return "⚑";
3131
4060
  }
3132
4061
  };
3133
4062
  var IconStamp = class extends GlyphStamp {
@@ -3136,7 +4065,7 @@ var IconStamp = class extends GlyphStamp {
3136
4065
  this.type = "iconstamp";
3137
4066
  }
3138
4067
  defaultGlyph() {
3139
- return "\u2605";
4068
+ return "★";
3140
4069
  }
3141
4070
  };
3142
4071
 
@@ -3203,8 +4132,8 @@ var FibRatios = class extends Drawing {
3203
4132
  }
3204
4133
  readProps(props) {
3205
4134
  if (Array.isArray(props.levels)) {
3206
- const parsed = props.levels.map(sanitizeLevel).filter((l) => l != null);
3207
- if (parsed.length) this.levels = parsed;
4135
+ const parsed2 = props.levels.map(sanitizeLevel).filter((l) => l != null);
4136
+ if (parsed2.length) this.levels = parsed2;
3208
4137
  }
3209
4138
  if (isFibSize(props.numbersSize)) this.numbersSize = props.numbersSize;
3210
4139
  if (isFibSize(props.labelsSize)) this.labelsSize = props.labelsSize;
@@ -3295,8 +4224,8 @@ var FibLevels = class extends FibRatios {
3295
4224
  return {
3296
4225
  fields: [
3297
4226
  ...base.fields,
3298
- { path: "style.extendLeft", label: "Extend left", kind: "boolean", group: "line" },
3299
- { path: "style.extendRight", label: "Extend right", kind: "boolean", group: "line" }
4227
+ { path: "style.extendLeft", label: msg("drawing.field.extendLeft", "Extend left"), kind: "boolean", group: "line" },
4228
+ { path: "style.extendRight", label: msg("drawing.field.extendRight", "Extend right"), kind: "boolean", group: "line" }
3300
4229
  ]
3301
4230
  };
3302
4231
  }
@@ -3415,19 +4344,19 @@ function ladder(ratios, on, colors = {}) {
3415
4344
  var FIB_PRESETS = [
3416
4345
  {
3417
4346
  key: "classic",
3418
- label: "Classic",
4347
+ label: msg("drawing.fibPreset.classic", "Classic"),
3419
4348
  reverse: false,
3420
4349
  levels: ladder(LADDER, [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1])
3421
4350
  },
3422
4351
  {
3423
4352
  key: "extension",
3424
- label: "Extension",
4353
+ label: msg("drawing.fibPreset.extension", "Extension"),
3425
4354
  reverse: true,
3426
4355
  levels: ladder(LADDER, [0, 1, 1.272, 1.414, 1.618, 2, 2.618, 3.618, 4.236])
3427
4356
  },
3428
4357
  {
3429
4358
  key: "ote",
3430
- label: "OTE",
4359
+ label: msg("drawing.fibPreset.ote", "OTE"),
3431
4360
  reverse: false,
3432
4361
  // The entry zone reads as one band.
3433
4362
  levels: ladder(OTE_LADDER, [0, 0.5, 0.62, 0.705, 0.79, 1, -0.27, -0.62], { "0.62": LEVEL_AMBER, "0.79": LEVEL_AMBER })
@@ -4376,7 +5305,7 @@ var DedekindTessellation = class extends Drawing {
4376
5305
  ...LINE_FIELDS,
4377
5306
  {
4378
5307
  path: "maxCurvature",
4379
- label: "Max curvature",
5308
+ label: msg("drawing.dedekind.maxCurvature", "Max curvature"),
4380
5309
  kind: "number",
4381
5310
  min: 4,
4382
5311
  max: 64,
@@ -4416,7 +5345,7 @@ function sanitizeLevel2(v) {
4416
5345
  }
4417
5346
  var SHOW_RATIOS_FIELD = {
4418
5347
  path: "showRatios",
4419
- label: "Show ratios",
5348
+ label: msg("drawing.sonic.showRatios", "Show ratios"),
4420
5349
  kind: "boolean",
4421
5350
  group: "behavior"
4422
5351
  };
@@ -4568,7 +5497,7 @@ var MachFigure = class extends Drawing {
4568
5497
  ...LINE_FIELDS,
4569
5498
  {
4570
5499
  path: "waveCount",
4571
- label: "Waves",
5500
+ label: msg("drawing.sonic.waveCount", "Waves"),
4572
5501
  kind: "number",
4573
5502
  min: 3,
4574
5503
  max: 12,
@@ -4593,8 +5522,8 @@ var MachFigure = class extends Drawing {
4593
5522
  }
4594
5523
  if (typeof props.showRatios === "boolean") this.showRatios = props.showRatios;
4595
5524
  if (Array.isArray(props.levels)) {
4596
- const parsed = props.levels.map(sanitizeLevel2).filter((l) => l != null);
4597
- if (parsed.length) this.levels = parsed;
5525
+ const parsed2 = props.levels.map(sanitizeLevel2).filter((l) => l != null);
5526
+ if (parsed2.length) this.levels = parsed2;
4598
5527
  }
4599
5528
  }
4600
5529
  };
@@ -4628,7 +5557,7 @@ var Supersonic = class extends MachFigure {
4628
5557
  ...LINE_FIELDS,
4629
5558
  {
4630
5559
  path: "mach",
4631
- label: "Mach number",
5560
+ label: msg("drawing.supersonic.mach", "Mach number"),
4632
5561
  kind: "number",
4633
5562
  min: 1.5,
4634
5563
  max: 5,
@@ -4637,7 +5566,7 @@ var Supersonic = class extends MachFigure {
4637
5566
  },
4638
5567
  {
4639
5568
  path: "waveCount",
4640
- label: "Waves",
5569
+ label: msg("drawing.supersonic.waveCount", "Waves"),
4641
5570
  kind: "number",
4642
5571
  min: 3,
4643
5572
  max: 12,
@@ -4702,7 +5631,7 @@ var GoldenSupersonic = class extends MachFigure {
4702
5631
  ...LINE_FIELDS,
4703
5632
  {
4704
5633
  path: "mach",
4705
- label: "Mach number",
5634
+ label: msg("drawing.goldensupersonic.mach", "Mach number"),
4706
5635
  kind: "number",
4707
5636
  min: 1.5,
4708
5637
  max: 5,
@@ -4859,13 +5788,16 @@ var ElliottCorrection = class extends PatternDrawing {
4859
5788
  };
4860
5789
 
4861
5790
  // src/core/drawings/types/HeadShoulders.ts
5791
+ var LEFT_SHOULDER = msg("drawing.headshoulders.leftShoulder", "LS");
5792
+ var HEAD = msg("drawing.headshoulders.head", "H");
5793
+ var RIGHT_SHOULDER = msg("drawing.headshoulders.rightShoulder", "RS");
4862
5794
  var HeadShoulders = class extends PatternDrawing {
4863
5795
  constructor() {
4864
5796
  super(...arguments);
4865
5797
  this.type = "headshoulders";
4866
5798
  }
4867
5799
  vertexLabels() {
4868
- return ["", "LS", "", "H", "", "RS", ""];
5800
+ return ["", LEFT_SHOULDER, "", HEAD, "", RIGHT_SHOULDER, ""];
4869
5801
  }
4870
5802
  necklineIndices() {
4871
5803
  return [2, 4];
@@ -4929,7 +5861,7 @@ var Gartley = class extends HarmonicPattern {
4929
5861
  this.type = "gartley";
4930
5862
  }
4931
5863
  patternName() {
4932
- return "Gartley";
5864
+ return msg("drawing.gartley.patternName", "Gartley");
4933
5865
  }
4934
5866
  ranges() {
4935
5867
  return { ab: { min: 0.55, max: 0.68 }, bc: { min: 0.382, max: 0.886 }, cd: { min: 1.13, max: 1.618 }, ad: { min: 0.74, max: 0.83 } };
@@ -4943,7 +5875,7 @@ var Bat = class extends HarmonicPattern {
4943
5875
  this.type = "bat";
4944
5876
  }
4945
5877
  patternName() {
4946
- return "Bat";
5878
+ return msg("drawing.bat.patternName", "Bat");
4947
5879
  }
4948
5880
  ranges() {
4949
5881
  return { ab: { min: 0.382, max: 0.5 }, bc: { min: 0.382, max: 0.886 }, cd: { min: 1.618, max: 2.618 }, ad: { min: 0.84, max: 0.92 } };
@@ -4957,7 +5889,7 @@ var Butterfly = class extends HarmonicPattern {
4957
5889
  this.type = "butterfly";
4958
5890
  }
4959
5891
  patternName() {
4960
- return "Butterfly";
5892
+ return msg("drawing.butterfly.patternName", "Butterfly");
4961
5893
  }
4962
5894
  ranges() {
4963
5895
  return { ab: { min: 0.74, max: 0.83 }, bc: { min: 0.382, max: 0.886 }, cd: { min: 1.618, max: 2.618 }, ad: { min: 1.272, max: 1.618 } };
@@ -4971,7 +5903,7 @@ var Crab = class extends HarmonicPattern {
4971
5903
  this.type = "crab";
4972
5904
  }
4973
5905
  patternName() {
4974
- return "Crab";
5906
+ return msg("drawing.crab.patternName", "Crab");
4975
5907
  }
4976
5908
  ranges() {
4977
5909
  return { ab: { min: 0.382, max: 0.618 }, bc: { min: 0.382, max: 0.886 }, cd: { min: 2.618, max: 3.618 }, ad: { min: 1.55, max: 1.69 } };
@@ -4985,7 +5917,7 @@ var Shark = class extends HarmonicPattern {
4985
5917
  this.type = "shark";
4986
5918
  }
4987
5919
  patternName() {
4988
- return "Shark";
5920
+ return msg("drawing.shark.patternName", "Shark");
4989
5921
  }
4990
5922
  ranges() {
4991
5923
  return { ab: { min: 0.382, max: 0.618 }, bc: { min: 1.13, max: 1.618 }, cd: { min: 1.618, max: 2.24 }, ad: { min: 0.886, max: 1.13 } };
@@ -5001,7 +5933,7 @@ var Cypher = class extends HarmonicPattern {
5001
5933
  this.type = "cypher";
5002
5934
  }
5003
5935
  patternName() {
5004
- return "Cypher";
5936
+ return msg("drawing.cypher.patternName", "Cypher");
5005
5937
  }
5006
5938
  ranges() {
5007
5939
  return { ab: { min: 0.382, max: 0.618 }, bc: { min: 0, max: Infinity }, cd: { min: 0, max: Infinity }, ad: { min: 0, max: Infinity } };
@@ -5035,27 +5967,13 @@ var Cypher = class extends HarmonicPattern {
5035
5967
  };
5036
5968
 
5037
5969
  // src/core/drawings/types/MeasureBox.ts
5970
+ var MEASURE_TEXT = {
5971
+ priceChange: msg("drawing.measure.priceChange", "{change} ({percent}%)"),
5972
+ barsAndDuration: msg("drawing.measure.barsAndDuration", "{count, plural, one {{bars} bar} other {{bars} bars}}, {duration}")
5973
+ };
5038
5974
  function signed(n) {
5039
5975
  return `${n >= 0 ? "+" : ""}${n.toFixed(2)}`;
5040
5976
  }
5041
- function formatDuration(ms) {
5042
- const m = Math.abs(ms);
5043
- const DAY2 = 864e5;
5044
- const HR = 36e5;
5045
- const MIN2 = 6e4;
5046
- if (m >= DAY2) {
5047
- const d = Math.floor(m / DAY2);
5048
- const h = Math.round(m % DAY2 / HR);
5049
- return h ? `${d}d ${h}h` : `${d}d`;
5050
- }
5051
- if (m >= HR) {
5052
- const h = Math.floor(m / HR);
5053
- const mn = Math.round(m % HR / MIN2);
5054
- return mn ? `${h}h ${mn}m` : `${h}h`;
5055
- }
5056
- if (m >= MIN2) return `${Math.round(m / MIN2)}m`;
5057
- return `${Math.round(m / 1e3)}s`;
5058
- }
5059
5977
  var MeasureBox = class extends Drawing {
5060
5978
  constructor(init) {
5061
5979
  super(init);
@@ -5067,11 +5985,12 @@ var MeasureBox = class extends Drawing {
5067
5985
  }
5068
5986
  // Placed click-move-click (the inherited 'click' mode): first click sets a corner, the second
5069
5987
  // sets the opposite one — consistent with the box/Gann tools.
5070
- /** The measurement lines, filtered by the enabled toggles. */
5071
- measureLabel(proj) {
5988
+ /** The measurement lines, filtered by the enabled toggles, in `i18n`'s language
5989
+ * (English without one). */
5990
+ measureLabel(proj, i18n) {
5072
5991
  const lines = [];
5073
- if (this.showPrice) lines.push(this.priceLabel());
5074
- if (this.showDate) lines.push(this.timeLabel(proj));
5992
+ if (this.showPrice) lines.push(this.priceLabel(i18n));
5993
+ if (this.showDate) lines.push(this.timeLabel(proj, i18n));
5075
5994
  return lines;
5076
5995
  }
5077
5996
  /** Up (later price ≥ earlier) → green; else red. */
@@ -5081,22 +6000,22 @@ var MeasureBox = class extends Drawing {
5081
6000
  return a != null && b != null && b.price >= a.price;
5082
6001
  }
5083
6002
  /** Formatted `Δprice (Δ%)` between the two anchors. */
5084
- priceLabel() {
6003
+ priceLabel(i18n) {
5085
6004
  const a = this.anchors[0];
5086
6005
  const b = this.anchors[1];
5087
6006
  if (!a || !b) return "";
5088
6007
  const delta = b.price - a.price;
5089
6008
  const percent = a.price !== 0 ? delta / a.price * 100 : 0;
5090
- return `${signed(delta)} (${signed(percent)}%)`;
6009
+ return textOf(i18n, MEASURE_TEXT.priceChange, { change: localizeNumberText(signed(delta), i18n), percent: localizeNumberText(signed(percent), i18n) });
5091
6010
  }
5092
6011
  /** Formatted `N bars, duration` between the two anchors (bars only when the projector knows). */
5093
- timeLabel(proj) {
6012
+ timeLabel(proj, i18n) {
5094
6013
  const a = this.anchors[0];
5095
6014
  const b = this.anchors[1];
5096
6015
  if (!a || !b) return "";
5097
- const duration = formatDuration(b.time - a.time);
6016
+ const duration = (i18n ?? englishTranslator()).format.duration(b.time - a.time, { style: "span", surface: "drawing" });
5098
6017
  const bars = proj.barsBetween ? Math.round(proj.barsBetween(a.time, b.time)) : null;
5099
- return bars != null ? `${bars} bars, ${duration}` : duration;
6018
+ return bars != null ? textOf(i18n, MEASURE_TEXT.barsAndDuration, { count: bars, bars: localizeNumberText(String(bars), i18n), duration }) : duration;
5100
6019
  }
5101
6020
  rect(proj) {
5102
6021
  const a = this.anchors[0];
@@ -5132,12 +6051,12 @@ var MeasureBox = class extends Drawing {
5132
6051
  schema() {
5133
6052
  return {
5134
6053
  fields: [
5135
- { path: "showPrice", label: "Show price", kind: "boolean", group: "behavior" },
5136
- { path: "showDate", label: "Show date", kind: "boolean", group: "behavior" },
6054
+ { path: "showPrice", label: msg("drawing.measure.showPrice", "Show price"), kind: "boolean", group: "behavior" },
6055
+ { path: "showDate", label: msg("drawing.measure.showDate", "Show date"), kind: "boolean", group: "behavior" },
5137
6056
  ...LINE_FIELDS.filter((f) => f.path !== "style.lineColor"),
5138
6057
  // box border (the fill is direction-tinted)
5139
- { path: "text.color", label: "Text color", kind: "color", group: "text" },
5140
- { path: "text.size", label: "Text size", kind: "select", options: TEXT_SIZE_OPTIONS, group: "text" }
6058
+ { path: "text.color", label: msg("drawing.field.textColor", "Text color"), kind: "color", group: "text" },
6059
+ { path: "text.size", label: msg("drawing.field.textSize", "Text size"), kind: "select", options: TEXT_SIZE_OPTIONS, group: "text" }
5141
6060
  ]
5142
6061
  };
5143
6062
  }
@@ -5159,9 +6078,17 @@ var DatePriceRange = class extends MeasureBox {
5159
6078
  };
5160
6079
 
5161
6080
  // src/core/drawings/types/PositionTool.ts
6081
+ var POSITION_TEXT = {
6082
+ header: msg("drawing.position.header", "{direction, select, long {LONG} other {SHORT}} · R:R {ratio}"),
6083
+ lossSize: msg("drawing.position.lossSize", "Loss {loss} · Size {size}"),
6084
+ target: msg("drawing.position.targetLabel", "Target +{percent}%"),
6085
+ targetAt: msg("drawing.position.targetLabelAt", "Target +{percent}% @ {price}"),
6086
+ stop: msg("drawing.position.stopLabel", "Stop −{percent}%"),
6087
+ stopAt: msg("drawing.position.stopLabelAt", "Stop −{percent}% @ {price}")
6088
+ };
5162
6089
  var DIRECTION_OPTIONS = [
5163
- { value: "long", label: "Long" },
5164
- { value: "short", label: "Short" }
6090
+ { value: "long", label: msg("drawing.position.option.long", "Long") },
6091
+ { value: "short", label: msg("drawing.position.option.short", "Short") }
5165
6092
  ];
5166
6093
  var _PositionTool = class _PositionTool extends Drawing {
5167
6094
  constructor(init) {
@@ -5339,7 +6266,7 @@ var _PositionTool = class _PositionTool extends Drawing {
5339
6266
  const p = this.prices();
5340
6267
  return p && p.entry !== 0 ? Math.abs(p.entry - p.stop) / p.entry * 100 : 0;
5341
6268
  }
5342
- /** Dollar amount risked at the stop = accountBalance × riskPercent / 100. */
6269
+ /** Amount risked at the stop, in the balance's units = accountBalance × riskPercent / 100. */
5343
6270
  dollarLoss() {
5344
6271
  return Math.max(0, this.accountBalance) * (Math.max(0, this.riskPercent) / 100);
5345
6272
  }
@@ -5351,25 +6278,34 @@ var _PositionTool = class _PositionTool extends Drawing {
5351
6278
  return risk < 1e-9 ? 0 : this.dollarLoss() / risk;
5352
6279
  }
5353
6280
  // ── painted label lines (each respects its own toggle; the painter checks showText) ──
5354
- /** `DIR · R:R x.xx` — the always-on header when text is shown. */
5355
- headerLabel() {
5356
- return `${this.directionLabel()} \xB7 R:R ${this.rr().toFixed(2)}`;
6281
+ /** `DIR · R:R x.xx` — the always-on header when text is shown, in `i18n`'s language
6282
+ * (English without one). */
6283
+ headerLabel(i18n) {
6284
+ return textOf(i18n, POSITION_TEXT.header, {
6285
+ direction: this.directionLabel() === "LONG" ? "long" : "short",
6286
+ ratio: localizeNumberText(this.rr().toFixed(2), i18n)
6287
+ });
5357
6288
  }
5358
- /** `Loss $… · Size …` — the painter hides it when showLossSize is off. */
5359
- lossSizeLabel() {
5360
- return `Loss $${formatMoney(this.dollarLoss())} \xB7 Size ${formatQty(this.positionSize())}`;
6289
+ /** `Loss … · Size …` — the painter hides it when showLossSize is off. */
6290
+ lossSizeLabel(i18n) {
6291
+ return textOf(i18n, POSITION_TEXT.lossSize, {
6292
+ loss: localizeNumberText(formatMoney(this.dollarLoss()), i18n),
6293
+ size: localizeNumberText(formatQty(this.positionSize()), i18n)
6294
+ });
5361
6295
  }
5362
6296
  /** `Target +x.xx%`, with the level price appended when showPrices is on. */
5363
- targetLabel() {
6297
+ targetLabel(i18n) {
5364
6298
  const p = this.prices();
5365
- const at = this.showPrices && p ? ` @ ${formatPrice(p.target)}` : "";
5366
- return `Target +${this.rewardPct().toFixed(2)}%${at}`;
6299
+ const percent = localizeNumberText(this.rewardPct().toFixed(2), i18n);
6300
+ if (this.showPrices && p) return textOf(i18n, POSITION_TEXT.targetAt, { percent, price: localizeNumberText(formatPrice2(p.target), i18n) });
6301
+ return textOf(i18n, POSITION_TEXT.target, { percent });
5367
6302
  }
5368
6303
  /** `Stop −x.xx%`, with the level price appended when showPrices is on. */
5369
- stopLabel() {
6304
+ stopLabel(i18n) {
5370
6305
  const p = this.prices();
5371
- const at = this.showPrices && p ? ` @ ${formatPrice(p.stop)}` : "";
5372
- return `Stop \u2212${this.riskPct().toFixed(2)}%${at}`;
6306
+ const percent = localizeNumberText(this.riskPct().toFixed(2), i18n);
6307
+ if (this.showPrices && p) return textOf(i18n, POSITION_TEXT.stopAt, { percent, price: localizeNumberText(formatPrice2(p.stop), i18n) });
6308
+ return textOf(i18n, POSITION_TEXT.stop, { percent });
5373
6309
  }
5374
6310
  // ── stop/target input units (the gear panel's Price / Points dropdowns) ──
5375
6311
  /** The stop or target expressed in the given unit: the absolute price, or the distance from
@@ -5438,24 +6374,24 @@ var _PositionTool = class _PositionTool extends Drawing {
5438
6374
  schema() {
5439
6375
  return {
5440
6376
  fields: [
5441
- { path: "riskPercent", label: "Risk %", kind: "number", min: 0, max: 100, step: 0.1, group: "behavior" },
5442
- { path: "accountBalance", label: "Account balance", kind: "number", min: 0, max: 1e12, step: 1, group: "behavior" },
5443
- { path: "quantity", label: "Position size", kind: "number", group: "behavior" },
5444
- { path: "direction", label: "Direction", kind: "select", options: DIRECTION_OPTIONS, group: "behavior" },
5445
- { path: "entryPrice", label: "Entry price", kind: "number", group: "behavior" },
5446
- { path: "stopPrice", label: "Stop price", kind: "number", group: "behavior" },
5447
- { path: "targetPrice", label: "Target price", kind: "number", group: "behavior" },
5448
- { path: "showText", label: "Show text", kind: "boolean", group: "behavior" },
5449
- { path: "showHeader", label: "Show direction & ratio", kind: "boolean", group: "behavior" },
5450
- { path: "showLossSize", label: "Show loss & size", kind: "boolean", group: "behavior" },
5451
- { path: "showTargetLabel", label: "Show target label", kind: "boolean", group: "behavior" },
5452
- { path: "showStopLabel", label: "Show stop label", kind: "boolean", group: "behavior" },
5453
- { path: "showPrices", label: "Show level prices", kind: "boolean", group: "behavior" },
5454
- { path: "profitColor", label: "Profit zone", kind: "color", group: "fill" },
5455
- { path: "lossColor", label: "Loss zone", kind: "color", group: "fill" },
6377
+ { path: "riskPercent", label: msg("drawing.position.riskPercent", "Risk %"), kind: "number", min: 0, max: 100, step: 0.1, group: "behavior" },
6378
+ { path: "accountBalance", label: msg("drawing.position.accountBalance", "Account balance"), kind: "number", min: 0, max: 1e12, step: 1, group: "behavior" },
6379
+ { path: "quantity", label: msg("drawing.position.quantity", "Position size"), kind: "number", group: "behavior" },
6380
+ { path: "direction", label: msg("drawing.position.direction", "Direction"), kind: "select", options: DIRECTION_OPTIONS, group: "behavior" },
6381
+ { path: "entryPrice", label: msg("drawing.position.entryPrice", "Entry price"), kind: "number", group: "behavior" },
6382
+ { path: "stopPrice", label: msg("drawing.position.stopPrice", "Stop price"), kind: "number", group: "behavior" },
6383
+ { path: "targetPrice", label: msg("drawing.position.targetPrice", "Target price"), kind: "number", group: "behavior" },
6384
+ { path: "showText", label: msg("drawing.position.showText", "Show text"), kind: "boolean", group: "behavior" },
6385
+ { path: "showHeader", label: msg("drawing.position.showHeader", "Show direction & ratio"), kind: "boolean", group: "behavior" },
6386
+ { path: "showLossSize", label: msg("drawing.position.showLossSize", "Show loss & size"), kind: "boolean", group: "behavior" },
6387
+ { path: "showTargetLabel", label: msg("drawing.position.showTargetLabel", "Show target label"), kind: "boolean", group: "behavior" },
6388
+ { path: "showStopLabel", label: msg("drawing.position.showStopLabel", "Show stop label"), kind: "boolean", group: "behavior" },
6389
+ { path: "showPrices", label: msg("drawing.position.showPrices", "Show level prices"), kind: "boolean", group: "behavior" },
6390
+ { path: "profitColor", label: msg("drawing.position.profitColor", "Profit zone"), kind: "color", group: "fill" },
6391
+ { path: "lossColor", label: msg("drawing.position.lossColor", "Loss zone"), kind: "color", group: "fill" },
5456
6392
  ...LINE_FIELDS.filter((f) => f.path !== "style.lineColor"),
5457
- { path: "text.color", label: "Text color", kind: "color", group: "text" },
5458
- { path: "text.size", label: "Text size", kind: "select", options: TEXT_SIZE_OPTIONS, group: "text" }
6393
+ { path: "text.color", label: msg("drawing.position.textColor", "Text color"), kind: "color", group: "text" },
6394
+ { path: "text.size", label: msg("drawing.position.textSize", "Text size"), kind: "select", options: TEXT_SIZE_OPTIONS, group: "text" }
5459
6395
  ]
5460
6396
  };
5461
6397
  }
@@ -5513,7 +6449,7 @@ function formatQty(n) {
5513
6449
  if (n >= 1) return n.toFixed(4).replace(/\.?0+$/, "");
5514
6450
  return n.toPrecision(4).replace(/\.?0+$/, "");
5515
6451
  }
5516
- function formatPrice(n) {
6452
+ function formatPrice2(n) {
5517
6453
  if (!Number.isFinite(n)) return "0";
5518
6454
  if (Math.abs(n) >= 1) return n.toFixed(2);
5519
6455
  return n.toPrecision(4).replace(/\.?0+$/, "");
@@ -5524,14 +6460,14 @@ function roundFloat(n) {
5524
6460
 
5525
6461
  // src/core/drawings/types/Magnifier.ts
5526
6462
  var MAGNIFIER_TIMEFRAME_OPTIONS = [
5527
- { value: "auto", label: "Auto", ms: 0 },
5528
- { value: "1", label: "1m", ms: 6e4 },
5529
- { value: "5", label: "5m", ms: 3e5 },
5530
- { value: "15", label: "15m", ms: 9e5 },
5531
- { value: "30", label: "30m", ms: 18e5 },
5532
- { value: "60", label: "1h", ms: 36e5 },
5533
- { value: "240", label: "4h", ms: 144e5 },
5534
- { value: "D", label: "1D", ms: 864e5 }
6463
+ { value: "auto", label: msg("drawing.magnifier.option.auto", "Auto"), ms: 0 },
6464
+ { value: "1", label: msg("drawing.magnifier.option.n1", "1m"), ms: 6e4 },
6465
+ { value: "5", label: msg("drawing.magnifier.option.n5", "5m"), ms: 3e5 },
6466
+ { value: "15", label: msg("drawing.magnifier.option.n15", "15m"), ms: 9e5 },
6467
+ { value: "30", label: msg("drawing.magnifier.option.n30", "30m"), ms: 18e5 },
6468
+ { value: "60", label: msg("drawing.magnifier.option.n60", "1h"), ms: 36e5 },
6469
+ { value: "240", label: msg("drawing.magnifier.option.n240", "4h"), ms: 144e5 },
6470
+ { value: "D", label: msg("drawing.magnifier.option.d", "1D"), ms: 864e5 }
5535
6471
  ];
5536
6472
  function defaultMagnifierStyle() {
5537
6473
  return { timeframe: "auto", upColor: "", downColor: "" };
@@ -5597,14 +6533,14 @@ var Magnifier = class extends Drawing {
5597
6533
  fields: [
5598
6534
  {
5599
6535
  path: "magnifier.timeframe",
5600
- label: "Timeframe",
6536
+ label: msg("drawing.magnifier.magnifierTimeframe", "Timeframe"),
5601
6537
  kind: "select",
5602
6538
  options: MAGNIFIER_TIMEFRAME_OPTIONS,
5603
6539
  group: "behavior"
5604
6540
  },
5605
- ...LINE_FIELDS.map((f) => ({ ...f, label: f.label.replace("Line", "Border") })),
5606
- { path: "magnifier.upColor", label: "Up candles", kind: "color", group: "fill" },
5607
- { path: "magnifier.downColor", label: "Down candles", kind: "color", group: "fill" }
6541
+ ...BORDER_FIELDS,
6542
+ { path: "magnifier.upColor", label: msg("drawing.magnifier.magnifierUpColor", "Up candles"), kind: "color", group: "fill" },
6543
+ { path: "magnifier.downColor", label: msg("drawing.magnifier.magnifierDownColor", "Down candles"), kind: "color", group: "fill" }
5608
6544
  ]
5609
6545
  };
5610
6546
  }
@@ -5807,10 +6743,10 @@ var PriceActionZone = class extends PriceActionTool {
5807
6743
 
5808
6744
  // src/core/drawings/types/FairValueGap.ts
5809
6745
  var EXTEND_OPTIONS = [
5810
- { value: "tested", label: "Until tested" },
5811
- { value: "half", label: "Until 50%" },
5812
- { value: "filled", label: "Until filled" },
5813
- { value: "always", label: "Always" }
6746
+ { value: "tested", label: msg("drawing.fairvaluegap.option.tested", "Until tested") },
6747
+ { value: "half", label: msg("drawing.fairvaluegap.option.half", "Until 50%") },
6748
+ { value: "filled", label: msg("drawing.fairvaluegap.option.filled", "Until filled") },
6749
+ { value: "always", label: msg("drawing.fairvaluegap.option.always", "Always") }
5814
6750
  ];
5815
6751
  function defaults2() {
5816
6752
  return { extend: "filled", upColor: `${BULLISH}33`, downColor: `${BEARISH}33`, midline: true, border: false, fade: true, inverse: false };
@@ -5834,13 +6770,13 @@ var FairValueGap = class extends PriceActionZone {
5834
6770
  schema() {
5835
6771
  return {
5836
6772
  fields: [
5837
- { path: "gap.extend", label: "Extend right", kind: "select", options: EXTEND_OPTIONS, group: "behavior" },
5838
- { path: "gap.upColor", label: "Bullish", kind: "color", group: "fill" },
5839
- { path: "gap.downColor", label: "Bearish", kind: "color", group: "fill" },
5840
- { path: "gap.midline", label: "Midline", kind: "boolean", group: "line" },
5841
- { path: "gap.border", label: "Border", kind: "boolean", group: "line" },
5842
- { path: "gap.fade", label: "Fade at end", kind: "boolean", group: "behavior", when: { path: "gap.extend", in: ["tested", "half", "filled"] } },
5843
- { path: "gap.inverse", label: "Flip on close", kind: "boolean", group: "behavior", when: { path: "gap.extend", in: ["filled"] } }
6773
+ { path: "gap.extend", label: msg("drawing.fairvaluegap.gapExtend", "Extend right"), kind: "select", options: EXTEND_OPTIONS, group: "behavior" },
6774
+ { path: "gap.upColor", label: msg("drawing.fairvaluegap.gapUpColor", "Bullish"), kind: "color", group: "fill" },
6775
+ { path: "gap.downColor", label: msg("drawing.fairvaluegap.gapDownColor", "Bearish"), kind: "color", group: "fill" },
6776
+ { path: "gap.midline", label: msg("drawing.fairvaluegap.gapMidline", "Midline"), kind: "boolean", group: "line" },
6777
+ { path: "gap.border", label: msg("drawing.fairvaluegap.gapBorder", "Border"), kind: "boolean", group: "line" },
6778
+ { path: "gap.fade", label: msg("drawing.fairvaluegap.gapFade", "Fade at end"), kind: "boolean", group: "behavior", when: { path: "gap.extend", in: ["tested", "half", "filled"] } },
6779
+ { path: "gap.inverse", label: msg("drawing.fairvaluegap.gapInverse", "Flip on close"), kind: "boolean", group: "behavior", when: { path: "gap.extend", in: ["filled"] } }
5844
6780
  ]
5845
6781
  };
5846
6782
  }
@@ -5864,14 +6800,14 @@ var FairValueGap = class extends PriceActionZone {
5864
6800
 
5865
6801
  // src/core/drawings/types/OrderBlock.ts
5866
6802
  var RANGE_OPTIONS = [
5867
- { value: "body", label: "Body" },
5868
- { value: "wick", label: "Full range" }
6803
+ { value: "body", label: msg("drawing.orderblock.option.body", "Body") },
6804
+ { value: "wick", label: msg("drawing.orderblock.option.wick", "Full range") }
5869
6805
  ];
5870
6806
  var EXTEND_OPTIONS2 = [
5871
- { value: "tested", label: "Until tested" },
5872
- { value: "half", label: "Until 50%" },
5873
- { value: "broken", label: "Until broken" },
5874
- { value: "always", label: "Always" }
6807
+ { value: "tested", label: msg("drawing.orderblock.option.tested", "Until tested") },
6808
+ { value: "half", label: msg("drawing.orderblock.option.half", "Until 50%") },
6809
+ { value: "broken", label: msg("drawing.orderblock.option.broken", "Until broken") },
6810
+ { value: "always", label: msg("drawing.orderblock.option.always", "Always") }
5875
6811
  ];
5876
6812
  function defaults3() {
5877
6813
  return { range: "body", extend: "broken", upColor: `${BULLISH}29`, downColor: `${BEARISH}29`, midline: true, border: true, fade: true, breaker: true };
@@ -5895,14 +6831,14 @@ var OrderBlock = class extends PriceActionZone {
5895
6831
  schema() {
5896
6832
  return {
5897
6833
  fields: [
5898
- { path: "block.range", label: "Zone", kind: "select", options: RANGE_OPTIONS, group: "behavior" },
5899
- { path: "block.extend", label: "Extend right", kind: "select", options: EXTEND_OPTIONS2, group: "behavior" },
5900
- { path: "block.upColor", label: "Bullish", kind: "color", group: "fill" },
5901
- { path: "block.downColor", label: "Bearish", kind: "color", group: "fill" },
5902
- { path: "block.midline", label: "Midline", kind: "boolean", group: "line" },
5903
- { path: "block.border", label: "Border", kind: "boolean", group: "line" },
5904
- { path: "block.fade", label: "Fade at end", kind: "boolean", group: "behavior", when: { path: "block.extend", in: ["tested", "half", "broken"] } },
5905
- { path: "block.breaker", label: "Breaker", kind: "boolean", group: "behavior", when: { path: "block.extend", in: ["broken"] } }
6834
+ { path: "block.range", label: msg("drawing.orderblock.blockRange", "Zone"), kind: "select", options: RANGE_OPTIONS, group: "behavior" },
6835
+ { path: "block.extend", label: msg("drawing.orderblock.blockExtend", "Extend right"), kind: "select", options: EXTEND_OPTIONS2, group: "behavior" },
6836
+ { path: "block.upColor", label: msg("drawing.orderblock.blockUpColor", "Bullish"), kind: "color", group: "fill" },
6837
+ { path: "block.downColor", label: msg("drawing.orderblock.blockDownColor", "Bearish"), kind: "color", group: "fill" },
6838
+ { path: "block.midline", label: msg("drawing.orderblock.blockMidline", "Midline"), kind: "boolean", group: "line" },
6839
+ { path: "block.border", label: msg("drawing.orderblock.blockBorder", "Border"), kind: "boolean", group: "line" },
6840
+ { path: "block.fade", label: msg("drawing.orderblock.blockFade", "Fade at end"), kind: "boolean", group: "behavior", when: { path: "block.extend", in: ["tested", "half", "broken"] } },
6841
+ { path: "block.breaker", label: msg("drawing.orderblock.blockBreaker", "Breaker"), kind: "boolean", group: "behavior", when: { path: "block.extend", in: ["broken"] } }
5906
6842
  ]
5907
6843
  };
5908
6844
  }
@@ -5927,9 +6863,9 @@ var OrderBlock = class extends PriceActionZone {
5927
6863
 
5928
6864
  // src/core/drawings/types/Liquidity.ts
5929
6865
  var EXTEND_OPTIONS3 = [
5930
- { value: "swept", label: "Until swept" },
5931
- { value: "broken", label: "Until broken" },
5932
- { value: "always", label: "Always" }
6866
+ { value: "swept", label: msg("drawing.liquidity.option.swept", "Until swept") },
6867
+ { value: "broken", label: msg("drawing.liquidity.option.broken", "Until broken") },
6868
+ { value: "always", label: msg("drawing.liquidity.option.always", "Always") }
5933
6869
  ];
5934
6870
  function defaults4() {
5935
6871
  return { extend: "swept", markSweep: true };
@@ -5985,8 +6921,8 @@ var Liquidity = class extends PriceActionTool {
5985
6921
  return {
5986
6922
  fields: [
5987
6923
  ...LINE_FIELDS,
5988
- { path: "liq.extend", label: "Extend right", kind: "select", options: EXTEND_OPTIONS3, group: "behavior" },
5989
- { path: "liq.markSweep", label: "Mark sweep", kind: "boolean", group: "behavior" }
6924
+ { path: "liq.extend", label: msg("drawing.liquidity.liqExtend", "Extend right"), kind: "select", options: EXTEND_OPTIONS3, group: "behavior" },
6925
+ { path: "liq.markSweep", label: msg("drawing.liquidity.liqMarkSweep", "Mark sweep"), kind: "boolean", group: "behavior" }
5990
6926
  ]
5991
6927
  };
5992
6928
  }
@@ -6008,18 +6944,26 @@ var REGISTRY2 = /* @__PURE__ */ new Map();
6008
6944
  function registerDrawingType(meta) {
6009
6945
  REGISTRY2.set(meta.type, meta);
6010
6946
  }
6011
- function getDrawingType(type) {
6012
- return REGISTRY2.get(type);
6947
+ function resolved2(meta, i18n) {
6948
+ if (typeof meta.label === "string" && (meta.placementHint === void 0 || typeof meta.placementHint === "string")) return meta;
6949
+ const out = { ...meta, label: textOf(i18n, meta.label), placementHint: void 0 };
6950
+ if (meta.placementHint !== void 0) out.placementHint = textOf(i18n, meta.placementHint);
6951
+ else delete out.placementHint;
6952
+ return out;
6953
+ }
6954
+ function getDrawingType(type, i18n) {
6955
+ const meta = REGISTRY2.get(type);
6956
+ return meta ? resolved2(meta, i18n) : void 0;
6013
6957
  }
6014
- function drawingTypes() {
6015
- return [...REGISTRY2.values()];
6958
+ function drawingTypes(i18n) {
6959
+ return [...REGISTRY2.values()].map((meta) => resolved2(meta, i18n));
6016
6960
  }
6017
6961
  var LINE_ICON = svg24('<line x1="4" y1="19" x2="20" y2="5"/>');
6018
6962
  var HLINE_ICON = svg24('<line x1="3" y1="12" x2="21" y2="12"/>');
6019
6963
  registerDrawingType({
6020
6964
  type: "trendline",
6021
6965
  group: "lines",
6022
- label: "Trend Line",
6966
+ label: msg("drawing.trendline.label", "Trend Line"),
6023
6967
  icon: LINE_ICON,
6024
6968
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6025
6969
  create: (init) => new TrendLine(init)
@@ -6027,7 +6971,7 @@ registerDrawingType({
6027
6971
  registerDrawingType({
6028
6972
  type: "hline",
6029
6973
  group: "lines",
6030
- label: "Horizontal Line",
6974
+ label: msg("drawing.hline.label", "Horizontal Line"),
6031
6975
  icon: HLINE_ICON,
6032
6976
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "dashed" },
6033
6977
  create: (init) => new HorizontalLine(init)
@@ -6038,7 +6982,7 @@ var TEXT_ICON = svg24('<path d="M5 6h14M12 6v13"/>');
6038
6982
  registerDrawingType({
6039
6983
  type: "ray",
6040
6984
  group: "lines",
6041
- label: "Ray",
6985
+ label: msg("drawing.ray.label", "Ray"),
6042
6986
  icon: RAY_ICON,
6043
6987
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6044
6988
  create: (init) => new Ray(init)
@@ -6052,7 +6996,7 @@ var TRENDANGLE_ICON = svg24('<path d="M4 20 20 6"/><path d="M4 20 15 20"/><path
6052
6996
  registerDrawingType({
6053
6997
  type: "extendedline",
6054
6998
  group: "lines",
6055
- label: "Extended Line",
6999
+ label: msg("drawing.extendedline.label", "Extended Line"),
6056
7000
  icon: EXTLINE_ICON,
6057
7001
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6058
7002
  create: (init) => new ExtendedLine(init)
@@ -6060,7 +7004,7 @@ registerDrawingType({
6060
7004
  registerDrawingType({
6061
7005
  type: "vline",
6062
7006
  group: "lines",
6063
- label: "Vertical Line",
7007
+ label: msg("drawing.vline.label", "Vertical Line"),
6064
7008
  icon: VLINE_ICON,
6065
7009
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6066
7010
  create: (init) => new VerticalLine(init)
@@ -6068,7 +7012,7 @@ registerDrawingType({
6068
7012
  registerDrawingType({
6069
7013
  type: "hray",
6070
7014
  group: "lines",
6071
- label: "Horizontal Ray",
7015
+ label: msg("drawing.hray.label", "Horizontal Ray"),
6072
7016
  icon: HRAY_ICON,
6073
7017
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6074
7018
  create: (init) => new HorizontalRay(init)
@@ -6076,7 +7020,7 @@ registerDrawingType({
6076
7020
  registerDrawingType({
6077
7021
  type: "crossline",
6078
7022
  group: "lines",
6079
- label: "Cross Line",
7023
+ label: msg("drawing.crossline.label", "Cross Line"),
6080
7024
  icon: CROSSLINE_ICON,
6081
7025
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6082
7026
  create: (init) => new CrossLine(init)
@@ -6084,7 +7028,7 @@ registerDrawingType({
6084
7028
  registerDrawingType({
6085
7029
  type: "infoline",
6086
7030
  group: "lines",
6087
- label: "Info Line",
7031
+ label: msg("drawing.infoline.label", "Info Line"),
6088
7032
  icon: INFOLINE_ICON,
6089
7033
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6090
7034
  create: (init) => new InfoLine(init)
@@ -6092,7 +7036,7 @@ registerDrawingType({
6092
7036
  registerDrawingType({
6093
7037
  type: "trendangle",
6094
7038
  group: "lines",
6095
- label: "Trend Angle",
7039
+ label: msg("drawing.trendangle.label", "Trend Angle"),
6096
7040
  icon: TRENDANGLE_ICON,
6097
7041
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6098
7042
  create: (init) => new TrendAngle(init)
@@ -6100,7 +7044,7 @@ registerDrawingType({
6100
7044
  registerDrawingType({
6101
7045
  type: "box",
6102
7046
  group: "shapes",
6103
- label: "Rectangle",
7047
+ label: msg("drawing.box.label", "Rectangle"),
6104
7048
  icon: BOX_ICON,
6105
7049
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}26` },
6106
7050
  create: (init) => new Box(init)
@@ -6108,7 +7052,7 @@ registerDrawingType({
6108
7052
  registerDrawingType({
6109
7053
  type: "text",
6110
7054
  group: "annotations",
6111
- label: "Text",
7055
+ label: msg("drawing.text.label", "Text"),
6112
7056
  icon: TEXT_ICON,
6113
7057
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6114
7058
  create: (init) => new TextLabel(init)
@@ -6117,7 +7061,7 @@ var CALLOUT_ICON = svg24('<path d="M5 4h14a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-6l-5 5
6117
7061
  registerDrawingType({
6118
7062
  type: "callout",
6119
7063
  group: "annotations",
6120
- label: "Callout",
7064
+ label: msg("drawing.callout.label", "Callout"),
6121
7065
  icon: CALLOUT_ICON,
6122
7066
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}d9` },
6123
7067
  create: (init) => new Callout(init)
@@ -6130,7 +7074,7 @@ var SIGNPOST_ICON = svg24('<path d="M12 11.5V21"/><rect x="5" y="4" width="14" h
6130
7074
  registerDrawingType({
6131
7075
  type: "note",
6132
7076
  group: "annotations",
6133
- label: "Note",
7077
+ label: msg("drawing.note.label", "Note"),
6134
7078
  icon: NOTE_ICON,
6135
7079
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}d9` },
6136
7080
  create: (init) => new Note(init)
@@ -6138,7 +7082,7 @@ registerDrawingType({
6138
7082
  registerDrawingType({
6139
7083
  type: "pricenote",
6140
7084
  group: "annotations",
6141
- label: "Price Note",
7085
+ label: msg("drawing.pricenote.label", "Price Note"),
6142
7086
  icon: PRICE_NOTE_ICON,
6143
7087
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}d9` },
6144
7088
  create: (init) => new PriceNote(init)
@@ -6146,7 +7090,7 @@ registerDrawingType({
6146
7090
  registerDrawingType({
6147
7091
  type: "comment",
6148
7092
  group: "annotations",
6149
- label: "Comment",
7093
+ label: msg("drawing.comment.label", "Comment"),
6150
7094
  icon: COMMENT_ICON,
6151
7095
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}d9` },
6152
7096
  create: (init) => new Comment(init)
@@ -6154,7 +7098,7 @@ registerDrawingType({
6154
7098
  registerDrawingType({
6155
7099
  type: "pricelabel",
6156
7100
  group: "annotations",
6157
- label: "Price Label",
7101
+ label: msg("drawing.pricelabel.label", "Price Label"),
6158
7102
  icon: PRICE_LABEL_ICON,
6159
7103
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}d9` },
6160
7104
  create: (init) => new PriceLabel(init)
@@ -6162,7 +7106,7 @@ registerDrawingType({
6162
7106
  registerDrawingType({
6163
7107
  type: "signpost",
6164
7108
  group: "annotations",
6165
- label: "Signpost",
7109
+ label: msg("drawing.signpost.label", "Signpost"),
6166
7110
  icon: SIGNPOST_ICON,
6167
7111
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}d9` },
6168
7112
  create: (init) => new Signpost(init)
@@ -6173,7 +7117,7 @@ var PITCHFORK_ICON = svg24('<circle cx="4" cy="12" r="1.6" fill="currentColor"/>
6173
7117
  registerDrawingType({
6174
7118
  type: "parallelchannel",
6175
7119
  group: "channels",
6176
- label: "Parallel Channel",
7120
+ label: msg("drawing.parallelchannel.label", "Parallel Channel"),
6177
7121
  icon: PARALLEL_ICON,
6178
7122
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}1a` },
6179
7123
  create: (init) => new ParallelChannel(init)
@@ -6181,7 +7125,7 @@ registerDrawingType({
6181
7125
  registerDrawingType({
6182
7126
  type: "disjointchannel",
6183
7127
  group: "channels",
6184
- label: "Disjoint Channel",
7128
+ label: msg("drawing.disjointchannel.label", "Disjoint Channel"),
6185
7129
  icon: DISJOINT_ICON,
6186
7130
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}1a` },
6187
7131
  create: (init) => new DisjointChannel(init)
@@ -6190,7 +7134,7 @@ var FLATTOP_ICON = svg24('<line x1="3" y1="7" x2="21" y2="7"/><line x1="3" y1="1
6190
7134
  registerDrawingType({
6191
7135
  type: "flattopbottom",
6192
7136
  group: "channels",
6193
- label: "Flat Top/Bottom",
7137
+ label: msg("drawing.flattopbottom.label", "Flat Top/Bottom"),
6194
7138
  icon: FLATTOP_ICON,
6195
7139
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}1a` },
6196
7140
  create: (init) => new FlatTopBottom(init)
@@ -6199,7 +7143,7 @@ var REGRESSION_ICON = svg24('<line x1="3" y1="8" x2="21" y2="4"/><line x1="3" y1
6199
7143
  registerDrawingType({
6200
7144
  type: "regressionchannel",
6201
7145
  group: "channels",
6202
- label: "Linear Regression",
7146
+ label: msg("drawing.regressionchannel.label", "Linear Regression"),
6203
7147
  icon: REGRESSION_ICON,
6204
7148
  defaultStyle: { lineColor: NEUTRAL, lineWidth: 1, lineStyle: "solid" },
6205
7149
  create: (init) => new RegressionChannel(init)
@@ -6207,7 +7151,7 @@ registerDrawingType({
6207
7151
  registerDrawingType({
6208
7152
  type: "pitchfork",
6209
7153
  group: "pitchforks",
6210
- label: "Pitchfork",
7154
+ label: msg("drawing.pitchfork.label", "Pitchfork"),
6211
7155
  icon: PITCHFORK_ICON,
6212
7156
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6213
7157
  create: (init) => new Pitchfork(init)
@@ -6218,7 +7162,7 @@ var INSIDE_ICON = svg24('<line x1="4" y1="12" x2="10" y2="12"/><line x1="10" y1=
6218
7162
  registerDrawingType({
6219
7163
  type: "schiffpitchfork",
6220
7164
  group: "pitchforks",
6221
- label: "Schiff Pitchfork",
7165
+ label: msg("drawing.schiffpitchfork.label", "Schiff Pitchfork"),
6222
7166
  icon: SCHIFF_ICON,
6223
7167
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6224
7168
  create: (init) => new SchiffPitchfork(init)
@@ -6226,7 +7170,7 @@ registerDrawingType({
6226
7170
  registerDrawingType({
6227
7171
  type: "modifiedschiffpitchfork",
6228
7172
  group: "pitchforks",
6229
- label: "Modified Schiff Pitchfork",
7173
+ label: msg("drawing.modifiedschiffpitchfork.label", "Modified Schiff Pitchfork"),
6230
7174
  icon: MODSCHIFF_ICON,
6231
7175
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6232
7176
  create: (init) => new ModifiedSchiffPitchfork(init)
@@ -6234,7 +7178,7 @@ registerDrawingType({
6234
7178
  registerDrawingType({
6235
7179
  type: "insidepitchfork",
6236
7180
  group: "pitchforks",
6237
- label: "Inside Pitchfork",
7181
+ label: msg("drawing.insidepitchfork.label", "Inside Pitchfork"),
6238
7182
  icon: INSIDE_ICON,
6239
7183
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6240
7184
  create: (init) => new InsidePitchfork(init)
@@ -6245,7 +7189,7 @@ var TRIANGLE_ICON = svg24('<path d="M12 4 20 19 4 19Z"/>');
6245
7189
  registerDrawingType({
6246
7190
  type: "arrow",
6247
7191
  group: "shapes",
6248
- label: "Arrow",
7192
+ label: msg("drawing.arrow.label", "Arrow"),
6249
7193
  icon: ARROW_ICON,
6250
7194
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid", arrowRight: true },
6251
7195
  create: (init) => new Arrow(init)
@@ -6253,7 +7197,7 @@ registerDrawingType({
6253
7197
  registerDrawingType({
6254
7198
  type: "ellipse",
6255
7199
  group: "shapes",
6256
- label: "Ellipse",
7200
+ label: msg("drawing.ellipse.label", "Ellipse"),
6257
7201
  icon: ELLIPSE_ICON,
6258
7202
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}1a` },
6259
7203
  create: (init) => new Ellipse(init)
@@ -6261,7 +7205,7 @@ registerDrawingType({
6261
7205
  registerDrawingType({
6262
7206
  type: "triangle",
6263
7207
  group: "shapes",
6264
- label: "Triangle",
7208
+ label: msg("drawing.triangle.label", "Triangle"),
6265
7209
  icon: TRIANGLE_ICON,
6266
7210
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}1a` },
6267
7211
  create: (init) => new Triangle(init)
@@ -6272,7 +7216,7 @@ var HIGHLIGHTER_ICON = svg24('<path d="M9 11 15 5l4 4-6 6H9Z"/><path d="M9 15l-2
6272
7216
  registerDrawingType({
6273
7217
  type: "polyline",
6274
7218
  group: "shapes",
6275
- label: "Polyline",
7219
+ label: msg("drawing.polyline.label", "Polyline"),
6276
7220
  icon: POLYLINE_ICON,
6277
7221
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6278
7222
  create: (init) => new Polyline(init)
@@ -6280,7 +7224,7 @@ registerDrawingType({
6280
7224
  registerDrawingType({
6281
7225
  type: "freehand",
6282
7226
  group: "shapes",
6283
- label: "Brush",
7227
+ label: msg("drawing.freehand.label", "Brush"),
6284
7228
  icon: FREEHAND_ICON,
6285
7229
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6286
7230
  create: (init) => new Freehand(init)
@@ -6288,7 +7232,7 @@ registerDrawingType({
6288
7232
  registerDrawingType({
6289
7233
  type: "highlighter",
6290
7234
  group: "shapes",
6291
- label: "Highlighter",
7235
+ label: msg("drawing.highlighter.label", "Highlighter"),
6292
7236
  icon: HIGHLIGHTER_ICON,
6293
7237
  // A marker: wide + translucent by default (the alpha in the color is the highlight's see-through).
6294
7238
  defaultStyle: { lineColor: `${MARKER}59`, lineWidth: 14, lineStyle: "solid" },
@@ -6304,7 +7248,7 @@ var ARROW_DOWN_ICON = svg24('<path d="M12 5 12 19"/><path d="M6 13 12 19 18 13"/
6304
7248
  registerDrawingType({
6305
7249
  type: "circle",
6306
7250
  group: "shapes",
6307
- label: "Circle",
7251
+ label: msg("drawing.circle.label", "Circle"),
6308
7252
  icon: CIRCLE_ICON,
6309
7253
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}1a` },
6310
7254
  create: (init) => new Circle(init)
@@ -6312,7 +7256,7 @@ registerDrawingType({
6312
7256
  registerDrawingType({
6313
7257
  type: "rotatedrect",
6314
7258
  group: "shapes",
6315
- label: "Rotated Rectangle",
7259
+ label: msg("drawing.rotatedrect.label", "Rotated Rectangle"),
6316
7260
  icon: ROTRECT_ICON,
6317
7261
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}26` },
6318
7262
  create: (init) => new RotatedRect(init)
@@ -6320,7 +7264,7 @@ registerDrawingType({
6320
7264
  registerDrawingType({
6321
7265
  type: "path",
6322
7266
  group: "shapes",
6323
- label: "Path",
7267
+ label: msg("drawing.path.label", "Path"),
6324
7268
  icon: PATH_ICON,
6325
7269
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6326
7270
  create: (init) => new Path(init)
@@ -6328,7 +7272,7 @@ registerDrawingType({
6328
7272
  registerDrawingType({
6329
7273
  type: "arc",
6330
7274
  group: "shapes",
6331
- label: "Arc",
7275
+ label: msg("drawing.arc.label", "Arc"),
6332
7276
  icon: ARC_ICON,
6333
7277
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid", fillColor: `${DEFAULT_DRAWING_COLOR}26` },
6334
7278
  create: (init) => new Arc(init)
@@ -6336,7 +7280,7 @@ registerDrawingType({
6336
7280
  registerDrawingType({
6337
7281
  type: "curve",
6338
7282
  group: "shapes",
6339
- label: "Curve",
7283
+ label: msg("drawing.curve.label", "Curve"),
6340
7284
  icon: CURVE_ICON,
6341
7285
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6342
7286
  create: (init) => new Curve(init)
@@ -6344,7 +7288,7 @@ registerDrawingType({
6344
7288
  registerDrawingType({
6345
7289
  type: "arrowmarkup",
6346
7290
  group: "shapes",
6347
- label: "Arrow Mark Up",
7291
+ label: msg("drawing.arrowmarkup.label", "Arrow Mark Up"),
6348
7292
  icon: ARROW_UP_ICON,
6349
7293
  defaultStyle: { lineColor: BULLISH, lineWidth: 1, lineStyle: "solid" },
6350
7294
  create: (init) => new ArrowMarkUp(init)
@@ -6352,7 +7296,7 @@ registerDrawingType({
6352
7296
  registerDrawingType({
6353
7297
  type: "arrowmarkdown",
6354
7298
  group: "shapes",
6355
- label: "Arrow Mark Down",
7299
+ label: msg("drawing.arrowmarkdown.label", "Arrow Mark Down"),
6356
7300
  icon: ARROW_DOWN_ICON,
6357
7301
  defaultStyle: { lineColor: BEARISH, lineWidth: 1, lineStyle: "solid" },
6358
7302
  create: (init) => new ArrowMarkDown(init)
@@ -6362,7 +7306,7 @@ var ICON_STAMP_ICON = svg24('<path d="m12 3 2.6 5.8 6.4.6-4.8 4.2 1.4 6.2L12 16.
6362
7306
  registerDrawingType({
6363
7307
  type: "flagmark",
6364
7308
  group: "stamps",
6365
- label: "Flag",
7309
+ label: msg("drawing.flagmark.label", "Flag"),
6366
7310
  icon: FLAG_MARK_ICON,
6367
7311
  defaultStyle: { lineColor: ACCENT, lineWidth: 1, lineStyle: "solid" },
6368
7312
  create: (init) => new FlagMark(init)
@@ -6370,7 +7314,7 @@ registerDrawingType({
6370
7314
  registerDrawingType({
6371
7315
  type: "iconstamp",
6372
7316
  group: "stamps",
6373
- label: "Icon",
7317
+ label: msg("drawing.iconstamp.label", "Icon"),
6374
7318
  icon: ICON_STAMP_ICON,
6375
7319
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6376
7320
  create: (init) => new IconStamp(init)
@@ -6380,7 +7324,7 @@ var FIB_EXTEND_ICON = svg24('<line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1
6380
7324
  registerDrawingType({
6381
7325
  type: "fibretracement",
6382
7326
  group: "fibonacci",
6383
- label: "Fib Retracement",
7327
+ label: msg("drawing.fibretracement.label", "Fib Retracement"),
6384
7328
  icon: FIB_RETRACE_ICON,
6385
7329
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6386
7330
  create: (init) => new FibRetracement(init)
@@ -6388,7 +7332,7 @@ registerDrawingType({
6388
7332
  registerDrawingType({
6389
7333
  type: "fibextension",
6390
7334
  group: "fibonacci",
6391
- label: "Fib Extension",
7335
+ label: msg("drawing.fibextension.label", "Fib Extension"),
6392
7336
  icon: FIB_EXTEND_ICON,
6393
7337
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6394
7338
  create: (init) => new FibExtension(init)
@@ -6397,7 +7341,7 @@ var FIB_TREND_ICON = svg24('<path d="M3 20 10 9l4 5"/><path d="M14 14h7M14 9h7M1
6397
7341
  registerDrawingType({
6398
7342
  type: "fibextensiontrend",
6399
7343
  group: "fibonacci",
6400
- label: "Trend-Based Fib Extension",
7344
+ label: msg("drawing.fibextensiontrend.label", "Trend-Based Fib Extension"),
6401
7345
  icon: FIB_TREND_ICON,
6402
7346
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6403
7347
  create: (init) => new FibExtensionTrend(init)
@@ -6407,7 +7351,7 @@ var FIB_TZ_ICON = svg24('<path d="M3 5v14M6 5v14M11 5v14M19 5v14"/>');
6407
7351
  registerDrawingType({
6408
7352
  type: "fibfan",
6409
7353
  group: "fibonacci",
6410
- label: "Fib Fan",
7354
+ label: msg("drawing.fibfan.label", "Fib Fan"),
6411
7355
  icon: FIB_FAN_ICON,
6412
7356
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6413
7357
  create: (init) => new FibFan(init)
@@ -6415,7 +7359,7 @@ registerDrawingType({
6415
7359
  registerDrawingType({
6416
7360
  type: "fibtimezones",
6417
7361
  group: "fibonacci",
6418
- label: "Fib Time Zones",
7362
+ label: msg("drawing.fibtimezones.label", "Fib Time Zones"),
6419
7363
  icon: FIB_TZ_ICON,
6420
7364
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "dashed" },
6421
7365
  create: (init) => new FibTimeZones(init)
@@ -6426,7 +7370,7 @@ var FIB_TRENDTIME_ICON = svg24('<path d="M3 19 9 8M9 8 12 5v14M14 5v14M18 5v14M2
6426
7370
  registerDrawingType({
6427
7371
  type: "fibchannel",
6428
7372
  group: "fibonacci",
6429
- label: "Fib Channel",
7373
+ label: msg("drawing.fibchannel.label", "Fib Channel"),
6430
7374
  icon: FIB_CHANNEL_ICON,
6431
7375
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6432
7376
  create: (init) => new FibChannel(init)
@@ -6434,7 +7378,7 @@ registerDrawingType({
6434
7378
  registerDrawingType({
6435
7379
  type: "fibspeedfan",
6436
7380
  group: "fibonacci",
6437
- label: "Fib Speed Resistance Fan",
7381
+ label: msg("drawing.fibspeedfan.label", "Fib Speed Resistance Fan"),
6438
7382
  icon: FIB_SPEEDFAN_ICON,
6439
7383
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6440
7384
  create: (init) => new FibSpeedFan(init)
@@ -6442,7 +7386,7 @@ registerDrawingType({
6442
7386
  registerDrawingType({
6443
7387
  type: "trendfibtime",
6444
7388
  group: "fibonacci",
6445
- label: "Trend-Based Fib Time",
7389
+ label: msg("drawing.trendfibtime.label", "Trend-Based Fib Time"),
6446
7390
  icon: FIB_TRENDTIME_ICON,
6447
7391
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "dashed" },
6448
7392
  create: (init) => new TrendFibTime(init)
@@ -6454,7 +7398,7 @@ var FIB_SPIRAL_ICON = svg24('<path d="M13 12a2 2 0 1 1-2-2 4 4 0 0 1 4 4 6 6 0 0
6454
7398
  registerDrawingType({
6455
7399
  type: "fibcircles",
6456
7400
  group: "fibonacci",
6457
- label: "Fib Circles",
7401
+ label: msg("drawing.fibcircles.label", "Fib Circles"),
6458
7402
  icon: FIB_CIRCLES_ICON,
6459
7403
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6460
7404
  create: (init) => new FibCircles(init)
@@ -6462,7 +7406,7 @@ registerDrawingType({
6462
7406
  registerDrawingType({
6463
7407
  type: "fibarcs",
6464
7408
  group: "fibonacci",
6465
- label: "Fib Speed Resistance Arcs",
7409
+ label: msg("drawing.fibarcs.label", "Fib Speed Resistance Arcs"),
6466
7410
  icon: FIB_ARCS_ICON,
6467
7411
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6468
7412
  create: (init) => new FibArcs(init)
@@ -6470,7 +7414,7 @@ registerDrawingType({
6470
7414
  registerDrawingType({
6471
7415
  type: "fibwedge",
6472
7416
  group: "fibonacci",
6473
- label: "Fib Wedge",
7417
+ label: msg("drawing.fibwedge.label", "Fib Wedge"),
6474
7418
  icon: FIB_WEDGE_ICON,
6475
7419
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6476
7420
  create: (init) => new FibWedge(init)
@@ -6478,7 +7422,7 @@ registerDrawingType({
6478
7422
  registerDrawingType({
6479
7423
  type: "fibspiral",
6480
7424
  group: "fibonacci",
6481
- label: "Fib Spiral",
7425
+ label: msg("drawing.fibspiral.label", "Fib Spiral"),
6482
7426
  icon: FIB_SPIRAL_ICON,
6483
7427
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 2, lineStyle: "solid" },
6484
7428
  create: (init) => new FibSpiral(init)
@@ -6488,7 +7432,7 @@ var GANN_BOX_ICON = svg24('<rect x="4" y="4" width="16" height="16" rx="1"/><pat
6488
7432
  registerDrawingType({
6489
7433
  type: "gannfan",
6490
7434
  group: "fibonacci",
6491
- label: "Gann Fan",
7435
+ label: msg("drawing.gannfan.label", "Gann Fan"),
6492
7436
  icon: GANN_FAN_ICON,
6493
7437
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6494
7438
  create: (init) => new GannFan(init)
@@ -6496,7 +7440,7 @@ registerDrawingType({
6496
7440
  registerDrawingType({
6497
7441
  type: "gannbox",
6498
7442
  group: "fibonacci",
6499
- label: "Gann Box",
7443
+ label: msg("drawing.gannbox.label", "Gann Box"),
6500
7444
  icon: GANN_BOX_ICON,
6501
7445
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6502
7446
  create: (init) => new GannBox(init)
@@ -6505,7 +7449,7 @@ var GANN_SQUARE_ICON = svg24('<rect x="4" y="4" width="16" height="16" rx="1"/><
6505
7449
  registerDrawingType({
6506
7450
  type: "gannsquare",
6507
7451
  group: "fibonacci",
6508
- label: "Gann Square",
7452
+ label: msg("drawing.gannsquare.label", "Gann Square"),
6509
7453
  icon: GANN_SQUARE_ICON,
6510
7454
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6511
7455
  create: (init) => new GannSquare(init)
@@ -6516,7 +7460,7 @@ var DEDEKIND_ICON = svg24(
6516
7460
  registerDrawingType({
6517
7461
  type: "dedekind",
6518
7462
  group: "geometry",
6519
- label: "Dedekind Tessellation",
7463
+ label: msg("drawing.dedekind.label", "Dedekind Tessellation"),
6520
7464
  icon: DEDEKIND_ICON,
6521
7465
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6522
7466
  create: (init) => new DedekindTessellation(init)
@@ -6530,7 +7474,7 @@ var SUPERSONIC_ICON = svg24(
6530
7474
  registerDrawingType({
6531
7475
  type: "sonic",
6532
7476
  group: "geometry",
6533
- label: "Sonic",
7477
+ label: msg("drawing.sonic.label", "Sonic"),
6534
7478
  icon: SONIC_ICON,
6535
7479
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6536
7480
  create: (init) => new Sonic(init)
@@ -6538,7 +7482,7 @@ registerDrawingType({
6538
7482
  registerDrawingType({
6539
7483
  type: "supersonic",
6540
7484
  group: "geometry",
6541
- label: "Supersonic",
7485
+ label: msg("drawing.supersonic.label", "Supersonic"),
6542
7486
  icon: SUPERSONIC_ICON,
6543
7487
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6544
7488
  create: (init) => new Supersonic(init)
@@ -6552,7 +7496,7 @@ var GOLDEN_SUPERSONIC_ICON = svg24(
6552
7496
  registerDrawingType({
6553
7497
  type: "goldensonic",
6554
7498
  group: "geometry",
6555
- label: "Golden Sonic",
7499
+ label: msg("drawing.goldensonic.label", "Golden Sonic"),
6556
7500
  icon: GOLDEN_SONIC_ICON,
6557
7501
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6558
7502
  create: (init) => new GoldenSonic(init)
@@ -6560,7 +7504,7 @@ registerDrawingType({
6560
7504
  registerDrawingType({
6561
7505
  type: "goldensupersonic",
6562
7506
  group: "geometry",
6563
- label: "Golden Supersonic",
7507
+ label: msg("drawing.goldensupersonic.label", "Golden Supersonic"),
6564
7508
  icon: GOLDEN_SUPERSONIC_ICON,
6565
7509
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6566
7510
  create: (init) => new GoldenSupersonic(init)
@@ -6573,7 +7517,7 @@ var HEAD_SHOULDERS_ICON = svg24('<path d="M3 18 6 12 9 16 12 5 15 16 18 12 21 18
6573
7517
  registerDrawingType({
6574
7518
  type: "xabcd",
6575
7519
  group: "patterns",
6576
- label: "XABCD Pattern",
7520
+ label: msg("drawing.xabcd.label", "XABCD Pattern"),
6577
7521
  icon: XABCD_ICON,
6578
7522
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6579
7523
  create: (init) => new XABCD(init)
@@ -6581,7 +7525,7 @@ registerDrawingType({
6581
7525
  registerDrawingType({
6582
7526
  type: "abcd",
6583
7527
  group: "patterns",
6584
- label: "ABCD Pattern",
7528
+ label: msg("drawing.abcd.label", "ABCD Pattern"),
6585
7529
  icon: ABCD_ICON,
6586
7530
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6587
7531
  create: (init) => new ABCDPattern(init)
@@ -6589,7 +7533,7 @@ registerDrawingType({
6589
7533
  registerDrawingType({
6590
7534
  type: "elliottimpulse",
6591
7535
  group: "patterns",
6592
- label: "Elliott Impulse Wave (1-5)",
7536
+ label: msg("drawing.elliottimpulse.label", "Elliott Impulse Wave (1-5)"),
6593
7537
  icon: ELLIOTT_IMPULSE_ICON,
6594
7538
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6595
7539
  create: (init) => new ElliottImpulse(init)
@@ -6597,7 +7541,7 @@ registerDrawingType({
6597
7541
  registerDrawingType({
6598
7542
  type: "elliottcorrection",
6599
7543
  group: "patterns",
6600
- label: "Elliott Correction Wave (ABC)",
7544
+ label: msg("drawing.elliottcorrection.label", "Elliott Correction Wave (ABC)"),
6601
7545
  icon: ELLIOTT_CORRECTION_ICON,
6602
7546
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6603
7547
  create: (init) => new ElliottCorrection(init)
@@ -6605,24 +7549,24 @@ registerDrawingType({
6605
7549
  registerDrawingType({
6606
7550
  type: "headshoulders",
6607
7551
  group: "patterns",
6608
- label: "Head & Shoulders",
7552
+ label: msg("drawing.headshoulders.label", "Head & Shoulders"),
6609
7553
  icon: HEAD_SHOULDERS_ICON,
6610
7554
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6611
7555
  create: (init) => new HeadShoulders(init)
6612
7556
  });
6613
7557
  var HARMONIC_ICON = svg24('<path d="M3 17 7 6 12 14 17 5 21 16"/><path d="M3 17 21 16" opacity="0.45"/>');
6614
7558
  var harmonic = { group: "patterns", icon: HARMONIC_ICON, defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" } };
6615
- registerDrawingType({ type: "gartley", label: "Gartley", ...harmonic, create: (init) => new Gartley(init) });
6616
- registerDrawingType({ type: "bat", label: "Bat", ...harmonic, create: (init) => new Bat(init) });
6617
- registerDrawingType({ type: "butterfly", label: "Butterfly", ...harmonic, create: (init) => new Butterfly(init) });
6618
- registerDrawingType({ type: "crab", label: "Crab", ...harmonic, create: (init) => new Crab(init) });
6619
- registerDrawingType({ type: "shark", label: "Shark", ...harmonic, create: (init) => new Shark(init) });
6620
- registerDrawingType({ type: "cypher", label: "Cypher", ...harmonic, create: (init) => new Cypher(init) });
7559
+ registerDrawingType({ type: "gartley", label: msg("drawing.gartley.label", "Gartley"), ...harmonic, create: (init) => new Gartley(init) });
7560
+ registerDrawingType({ type: "bat", label: msg("drawing.bat.label", "Bat"), ...harmonic, create: (init) => new Bat(init) });
7561
+ registerDrawingType({ type: "butterfly", label: msg("drawing.butterfly.label", "Butterfly"), ...harmonic, create: (init) => new Butterfly(init) });
7562
+ registerDrawingType({ type: "crab", label: msg("drawing.crab.label", "Crab"), ...harmonic, create: (init) => new Crab(init) });
7563
+ registerDrawingType({ type: "shark", label: msg("drawing.shark.label", "Shark"), ...harmonic, create: (init) => new Shark(init) });
7564
+ registerDrawingType({ type: "cypher", label: msg("drawing.cypher.label", "Cypher"), ...harmonic, create: (init) => new Cypher(init) });
6621
7565
  var MEASURE_ICON = svg24('<rect x="4" y="6" width="16" height="12" rx="1"/><path d="M4 18 20 6" opacity="0.5"/>');
6622
7566
  registerDrawingType({
6623
7567
  type: "datepricerange",
6624
7568
  group: "measure",
6625
- label: "Date & Price Range",
7569
+ label: msg("drawing.datepricerange.label", "Date & Price Range"),
6626
7570
  icon: MEASURE_ICON,
6627
7571
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6628
7572
  create: (init) => new DatePriceRange(init)
@@ -6633,7 +7577,7 @@ var POSITION_ICON = svg24(
6633
7577
  registerDrawingType({
6634
7578
  type: "position",
6635
7579
  group: "measure",
6636
- label: "Long/Short Position",
7580
+ label: msg("drawing.position.label", "Long/Short Position"),
6637
7581
  icon: POSITION_ICON,
6638
7582
  defaultStyle: { lineColor: DEFAULT_DRAWING_COLOR, lineWidth: 1, lineStyle: "solid" },
6639
7583
  create: (init) => new PositionTool(init)
@@ -6644,21 +7588,21 @@ var MAGNIFIER_ICON = svg24(
6644
7588
  registerDrawingType({
6645
7589
  type: "magnifier",
6646
7590
  group: "measure",
6647
- label: "Magnifier",
7591
+ label: msg("drawing.magnifier.label", "Magnifier"),
6648
7592
  icon: MAGNIFIER_ICON,
6649
7593
  // An empty border color means the THEME's contrast ink (white on dark, black on
6650
7594
  // light), resolved at paint time so it follows theme switches; a user pick wins.
6651
7595
  defaultStyle: { lineColor: "", lineWidth: 1, lineStyle: "solid" },
6652
7596
  coversSeries: true,
6653
7597
  // the inset's backdrop must sit over the base candles it replaces
6654
- placementHint: "Drag an area on the chart to view it at a lower timeframe",
7598
+ placementHint: msg("drawing.magnifier.placementHint", "Drag an area on the chart to view it at a lower timeframe"),
6655
7599
  create: (init) => new Magnifier(init)
6656
7600
  });
6657
7601
  var VWAP_ICON = svg24('<line x1="5" y1="3" x2="5" y2="21"/><path d="M5 16c4 0 5-9 8-9s3 5 8 3"/>');
6658
7602
  registerDrawingType({
6659
7603
  type: "anchoredvwap",
6660
7604
  group: "measure",
6661
- label: "Anchored VWAP",
7605
+ label: msg("drawing.anchoredvwap.label", "Anchored VWAP"),
6662
7606
  icon: VWAP_ICON,
6663
7607
  defaultStyle: { lineColor: INFO, lineWidth: 2, lineStyle: "solid" },
6664
7608
  create: (init) => new AnchoredVwap(init)
@@ -6667,7 +7611,7 @@ var FRVP_ICON = svg24('<path d="M4 4v16"/><path d="M4 8h10"/><path d="M4 12h14"/
6667
7611
  registerDrawingType({
6668
7612
  type: "fixedrangevp",
6669
7613
  group: "measure",
6670
- label: "Fixed Range Volume Profile",
7614
+ label: msg("drawing.fixedrangevp.label", "Fixed Range Volume Profile"),
6671
7615
  icon: FRVP_ICON,
6672
7616
  defaultStyle: { lineColor: BULLISH, lineWidth: 1, lineStyle: "solid" },
6673
7617
  create: (init) => new FixedRangeVolumeProfile(init)
@@ -6678,28 +7622,28 @@ var LIQUIDITY_ICON = svg24('<path d="M3 8h12" stroke-dasharray="2.5 2.5"/><path
6678
7622
  registerDrawingType({
6679
7623
  type: "fairvaluegap",
6680
7624
  group: "priceaction",
6681
- label: "Fair Value Gap",
7625
+ label: msg("drawing.fairvaluegap.label", "Fair Value Gap"),
6682
7626
  icon: FVG_ICON,
6683
7627
  defaultStyle: { lineColor: BULLISH, lineWidth: 1, lineStyle: "solid" },
6684
- placementHint: "Click the middle candle of a gap",
7628
+ placementHint: msg("drawing.fairvaluegap.placementHint", "Click the middle candle of a gap"),
6685
7629
  create: (init) => new FairValueGap(init)
6686
7630
  });
6687
7631
  registerDrawingType({
6688
7632
  type: "orderblock",
6689
7633
  group: "priceaction",
6690
- label: "Order Block",
7634
+ label: msg("drawing.orderblock.label", "Order Block"),
6691
7635
  icon: ORDER_BLOCK_ICON,
6692
7636
  defaultStyle: { lineColor: BULLISH, lineWidth: 1, lineStyle: "solid" },
6693
- placementHint: "Click the candle that forms the block",
7637
+ placementHint: msg("drawing.orderblock.placementHint", "Click the candle that forms the block"),
6694
7638
  create: (init) => new OrderBlock(init)
6695
7639
  });
6696
7640
  registerDrawingType({
6697
7641
  type: "liquidity",
6698
7642
  group: "priceaction",
6699
- label: "Liquidity",
7643
+ label: msg("drawing.liquidity.label", "Liquidity"),
6700
7644
  icon: LIQUIDITY_ICON,
6701
7645
  defaultStyle: { lineColor: WARNING, lineWidth: 1, lineStyle: "solid" },
6702
- placementHint: "Click near a candle's high or low",
7646
+ placementHint: msg("drawing.liquidity.placementHint", "Click near a candle's high or low"),
6703
7647
  create: (init) => new Liquidity(init)
6704
7648
  });
6705
7649
 
@@ -6765,6 +7709,7 @@ exports.categoricalColor = categoricalColor;
6765
7709
  exports.chartType = chartType;
6766
7710
  exports.chartTypes = chartTypes;
6767
7711
  exports.clampPanelWidth = clampPanelWidth;
7712
+ exports.createTranslator = createTranslator;
6768
7713
  exports.drawingTypes = drawingTypes;
6769
7714
  exports.getDrawingType = getDrawingType;
6770
7715
  exports.getNativeIndicator = getNativeIndicator;
@@ -6773,6 +7718,7 @@ exports.inputDeltas = inputDeltas;
6773
7718
  exports.inputVisible = inputVisible;
6774
7719
  exports.legendActions = legendActions;
6775
7720
  exports.legendCallouts = legendCallouts;
7721
+ exports.msg = msg;
6776
7722
  exports.nativeIndicatorTypes = nativeIndicatorTypes;
6777
7723
  exports.normalizeSettingsRow = normalizeSettingsRow;
6778
7724
  exports.registerChartType = registerChartType;
@@ -6780,6 +7726,7 @@ exports.registerDefaultEngine = registerDefaultEngine;
6780
7726
  exports.registerIcon = registerIcon;
6781
7727
  exports.registerLegendAction = registerLegendAction;
6782
7728
  exports.registerLegendCallout = registerLegendCallout;
7729
+ exports.registerLocale = registerLocale;
6783
7730
  exports.registerNativeIndicator = registerNativeIndicator;
6784
7731
  exports.registerRendererDefaults = registerRendererDefaults;
6785
7732
  exports.registerRendererLayer = registerRendererLayer;
@@ -6788,6 +7735,7 @@ exports.registerStatePersistence = registerStatePersistence;
6788
7735
  exports.registerSymbolRanking = registerSymbolRanking;
6789
7736
  exports.registerWidgetAction = registerWidgetAction;
6790
7737
  exports.registerWidgetAttachment = registerWidgetAttachment;
7738
+ exports.registeredLocales = registeredLocales;
6791
7739
  exports.rendererDefaults = rendererDefaults;
6792
7740
  exports.rendererLayers = rendererLayers;
6793
7741
  exports.resolveEngines = resolveEngines;
@@ -6813,3 +7761,4 @@ exports.unregisterWidgetAction = unregisterWidgetAction;
6813
7761
  exports.unregisterWidgetAttachment = unregisterWidgetAttachment;
6814
7762
  exports.widgetActions = widgetActions;
6815
7763
  exports.widgetAttachments = widgetAttachments;
7764
+ exports.withValues = withValues;