langsys-js-typescript 0.6.3 → 0.6.5

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.
package/dist/index.mjs CHANGED
@@ -1,5 +1,36 @@
1
1
  import { IntlMessageFormat } from 'intl-messageformat';
2
2
 
3
+ // src/logger.ts
4
+ var STYLES = {
5
+ log: "display:inline-block;background:rgb(239,239,244);color:black;font-weight:bold;padding:3px 7px;border-radius:3px",
6
+ warn: "display:inline-block;background:gold;color:black;font-weight:bold;padding:3px 7px;border-radius:3px",
7
+ error: "display:inline-block;background:#e0005a;color:#fff;font-weight:bold;padding:3px 7px;border-radius:3px"
8
+ };
9
+ var supportsStyle = typeof window !== "undefined";
10
+ function emit(level, label, args) {
11
+ if (supportsStyle) {
12
+ console[level](`%c${label}`, STYLES[level], ...args);
13
+ } else {
14
+ console[level](`[${label}]`, ...args);
15
+ }
16
+ }
17
+ var Logger = class {
18
+ constructor(debugEnabled = false) {
19
+ this.debugEnabled = debugEnabled;
20
+ }
21
+ log(...args) {
22
+ if (!this.debugEnabled) return;
23
+ emit("log", "Langsys Debug", args);
24
+ }
25
+ warn(...args) {
26
+ emit("warn", "Langsys Warning", args);
27
+ }
28
+ error(...args) {
29
+ emit("error", "Langsys Error", args);
30
+ }
31
+ };
32
+ var logger = new Logger(false);
33
+
3
34
  // src/locale.ts
4
35
  function canonicalizeLocale(locale) {
5
36
  if (!locale || typeof locale !== "string") return locale;
@@ -8,6 +39,9 @@ function canonicalizeLocale(locale) {
8
39
  const [canonical] = Intl.getCanonicalLocales(cleaned);
9
40
  return canonical ?? cleaned;
10
41
  } catch {
42
+ if (logger.debugEnabled) logger.warn(
43
+ `"${locale}" is not a valid BCP 47 locale tag. Falling back to best-effort casing, which will very likely miss the catalog and render base language with no other symptom.`
44
+ );
11
45
  return cleaned.split("-").map((part, i) => {
12
46
  if (i === 0) return part.toLowerCase();
13
47
  if (part.length === 4) return part[0].toUpperCase() + part.slice(1).toLowerCase();
@@ -51,37 +85,6 @@ function getValue(signal) {
51
85
  return signal.get();
52
86
  }
53
87
 
54
- // src/logger.ts
55
- var STYLES = {
56
- log: "display:inline-block;background:rgb(239,239,244);color:black;font-weight:bold;padding:3px 7px;border-radius:3px",
57
- warn: "display:inline-block;background:gold;color:black;font-weight:bold;padding:3px 7px;border-radius:3px",
58
- error: "display:inline-block;background:#e0005a;color:#fff;font-weight:bold;padding:3px 7px;border-radius:3px"
59
- };
60
- var supportsStyle = typeof window !== "undefined";
61
- function emit(level, label, args) {
62
- if (supportsStyle) {
63
- console[level](`%c${label}`, STYLES[level], ...args);
64
- } else {
65
- console[level](`[${label}]`, ...args);
66
- }
67
- }
68
- var Logger = class {
69
- constructor(debugEnabled = false) {
70
- this.debugEnabled = debugEnabled;
71
- }
72
- log(...args) {
73
- if (!this.debugEnabled) return;
74
- emit("log", "Langsys Debug", args);
75
- }
76
- warn(...args) {
77
- emit("warn", "Langsys Warning", args);
78
- }
79
- error(...args) {
80
- emit("error", "Langsys Error", args);
81
- }
82
- };
83
- var logger = new Logger(false);
84
-
85
88
  // src/api.ts
86
89
  var LangsysAppAPIClass = class {
87
90
  constructor() {
@@ -287,14 +290,76 @@ function warnUnmatchedParams(source, texts, params, context) {
287
290
  }
288
291
  function interpolate(template, params, locale) {
289
292
  if (isICU(template)) {
290
- try {
291
- return new IntlMessageFormat(template, locale || "en").format(params);
292
- } catch {
293
- return simpleInterpolate(template, params, locale);
293
+ const resolved = locale || "en";
294
+ const hasNullParam = !!params && Object.values(params).some((value) => value === null);
295
+ if (!hasNullParam) {
296
+ try {
297
+ return new IntlMessageFormat(template, resolved).format(params);
298
+ } catch {
299
+ }
300
+ }
301
+ {
302
+ try {
303
+ const ast = new IntlMessageFormat(template, resolved).ast;
304
+ if (!Array.isArray(ast)) return simpleInterpolate(template, params, locale);
305
+ const recovered = _recoverMissingArgs(JSON.parse(JSON.stringify(ast)), params);
306
+ return new IntlMessageFormat(recovered, resolved).format(params);
307
+ } catch {
308
+ return simpleInterpolate(template, params, locale);
309
+ }
294
310
  }
295
311
  }
296
312
  return simpleInterpolate(template, params, locale);
297
313
  }
314
+ var ICU_LITERAL = 0;
315
+ var ICU_ARGUMENT = 1;
316
+ var ICU_NUMBER = 2;
317
+ var ICU_DATE = 3;
318
+ var ICU_TIME = 4;
319
+ var ICU_SELECT = 5;
320
+ var ICU_PLURAL = 6;
321
+ var ICU_POUND = 7;
322
+ var ICU_TAG = 8;
323
+ function _recoverMissingArgs(nodes, params) {
324
+ const out = [];
325
+ for (const node of nodes) {
326
+ const name = node.value;
327
+ const value = name !== void 0 && name in params ? params[name] : void 0;
328
+ const supplied = value !== void 0 && value !== null;
329
+ if (node.type === ICU_TAG) {
330
+ out.push({ ...node, children: _recoverMissingArgs(node.children ?? [], params) });
331
+ continue;
332
+ }
333
+ if (node.type === ICU_SELECT || node.type === ICU_PLURAL) {
334
+ if (supplied) {
335
+ const options = {};
336
+ for (const [key, branch2] of Object.entries(node.options ?? {})) {
337
+ options[key] = { value: _recoverMissingArgs(branch2.value, params) };
338
+ }
339
+ out.push({ ...node, options });
340
+ continue;
341
+ }
342
+ const other = node.options?.other;
343
+ if (!other) {
344
+ out.push(node);
345
+ continue;
346
+ }
347
+ const branch = _recoverMissingArgs(other.value, params);
348
+ out.push(
349
+ ...branch.map(
350
+ (child) => child.type === ICU_POUND ? { type: ICU_LITERAL, value: `{${name}}` } : child
351
+ )
352
+ );
353
+ continue;
354
+ }
355
+ if (!supplied && (node.type === ICU_ARGUMENT || node.type === ICU_NUMBER || node.type === ICU_DATE || node.type === ICU_TIME)) {
356
+ out.push({ type: ICU_LITERAL, value: `{${name}}` });
357
+ continue;
358
+ }
359
+ out.push(node);
360
+ }
361
+ return out;
362
+ }
298
363
  function simpleInterpolate(template, params, locale) {
299
364
  return template.replace(/\{([^{},]+)\}/g, (match, rawKey) => {
300
365
  const key = rawKey.trim();