cavalion-js 1.0.84 → 1.0.85
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/CHANGELOG.md +50 -0
- package/package.json +1 -1
- package/src/console/node/vcl/Component.js +14 -6
- package/src/entities/expand.js +137 -21
- package/src/js/_js.js +1 -0
- package/src/js/extensions.js +94 -35
- package/src/locale.js +10 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,53 @@
|
|
|
1
|
+
### `2026/03/16` 1.0.85 Formatting and entity expansion updates
|
|
2
|
+
|
|
3
|
+
**console/node/vcl/Component.js**:
|
|
4
|
+
|
|
5
|
+
* Adds root-component console rendering with `uri#hashCode`
|
|
6
|
+
* Keeps non-root `Component` labels unchanged; still shows `:root` and `:selected` markers.
|
|
7
|
+
* **Breaking**: code using `expand.Entity(...)` must migrate to `expand.newEntity(...)`.
|
|
8
|
+
|
|
9
|
+
**entities/expand.js**:
|
|
10
|
+
|
|
11
|
+
* Renames `expand.Entity` to `expand.newEntity` in
|
|
12
|
+
* Adds `expand.DefaultEntity` for generic alias-based `join()` and `expand()` behavior.
|
|
13
|
+
* Improves `expand.attributes4()` fallback handling for unknown entity relations and single-item tuple paths.
|
|
14
|
+
* Extends `prefixId()` to preserve `count:id` selectors without prepending `id,`.
|
|
15
|
+
|
|
16
|
+
**js/_js.js**:
|
|
17
|
+
|
|
18
|
+
* Adds `js.qq(a, b)` for nullish fallback values.
|
|
19
|
+
* Fixes `String.format()` width and padding behavior for `%d`, including negative zero-padded numbers.
|
|
20
|
+
* Fixes `String.format()` float formatting for `%f`, including width, precision, and negative values.
|
|
21
|
+
* Fixes string alignment in `String.format()` for `%s`/`%H`/`%n`; left/right padding now behaves consistently.
|
|
22
|
+
* Improves `%` specifier parsing to stop safely at end-of-format input.
|
|
23
|
+
* Adjusts numeric formatting to return the original positive value when fixed `"0000"` formatting collapses to `"0"`.
|
|
24
|
+
|
|
25
|
+
**locale.js**:
|
|
26
|
+
|
|
27
|
+
* Adds `locale.prefixed(...).prefixed(...)` chaining in `src/locale.js`.
|
|
28
|
+
* Fixes prefixed locale fallback output so missing keys do not duplicate the prefix.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### `2026/02/05` Introducing entities.expand
|
|
32
|
+
|
|
33
|
+
It turns `expand.js` from a small “string builder” helper into a mini expansion/join framework.
|
|
34
|
+
|
|
35
|
+
* **Before:** the module essentially returned a function that, given an attribute (or list of attributes) plus a `path`, produced strings like `path.attr`, with some support for comma lists, aliases (`"id foo"`), and typed prefixes (`"Type:attr"`). Arrays were turned into a **comma-joined string**.
|
|
36
|
+
|
|
37
|
+
* **Now:** it exports a reusable `expand(expanderFn, as, path)` function plus an **`Entity` factory** (`expand.Entity(...)`) that builds an object representing an entity with:
|
|
38
|
+
|
|
39
|
+
* **Named expanders** generated from a `paths` map (so you can call `Entity.bedrijf("id")` and get `meetpunt.onderzoek.bedrijf.id`).
|
|
40
|
+
* A **`join(alias, attributes)`** method that resolves a join alias (case-insensitive) to one of those expanders via a mapping; unknown aliases now **throw an error**.
|
|
41
|
+
* An **`expand(...)`** convenience method that expands multiple attributes using `expand.attributes4(...)`.
|
|
42
|
+
|
|
43
|
+
* **Normalization changes:**
|
|
44
|
+
|
|
45
|
+
* Comma-separated strings are split and **trimmed**.
|
|
46
|
+
* If `as` is an array, it maps each item through the expander and returns an **array** (not a comma-joined string).
|
|
47
|
+
* There’s a helper that **auto-prefixes `"id"`** (e.g., ensures `"id"` is included in expansions) and supports mixed input shapes (strings and `[expanderName, attrs]` tuples).
|
|
48
|
+
|
|
49
|
+
Overall, it standardizes how “expand fields” and “join expansions” are defined and executed, moving from ad-hoc string concatenation to an entity-centric API with explicit alias resolution and stricter error handling.
|
|
50
|
+
|
|
1
51
|
### `2026/01/18` - 1.0.84
|
|
2
52
|
|
|
3
53
|
EM now uses the browser’s fetch API instead of jQuery.
|
package/package.json
CHANGED
|
@@ -16,17 +16,25 @@ define(function(require) {
|
|
|
16
16
|
/** @overrides ../Node.prototype.initializeValue */
|
|
17
17
|
// node.innerHTML = String.format("%H<span class='uri'> - %H</span>",
|
|
18
18
|
// js.nameOf(this._value), this._value.getUri());
|
|
19
|
-
var
|
|
19
|
+
var isRoot = this._value.isRootComponent();
|
|
20
|
+
var root = isRoot ? ":root" : "";
|
|
20
21
|
var uri = this._value._uri;//this._value.isRootComponent() ? this._value._uri : this._value.getUri();
|
|
21
22
|
if(uri !== this._value.getUri()) {
|
|
22
23
|
uri = js.sf("%s - %s", uri, this._value.getUri());
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
+
|
|
25
26
|
var selected = this._value.isSelected && this._value.isSelected() ? ":selected" : "";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
if(isRoot) {
|
|
28
|
+
node.innerHTML = String.format(
|
|
29
|
+
"%H#%s<span class='uri'> - %H%H%H</span>",
|
|
30
|
+
uri, this._value.hashCode(), js.nameOf(this._value),
|
|
31
|
+
root, selected);
|
|
32
|
+
} else {
|
|
33
|
+
node.innerHTML = String.format(
|
|
34
|
+
"%H<span class='uri'> - %H%H%H</span>",
|
|
35
|
+
js.nameOf(this._value),
|
|
36
|
+
uri, root, selected);
|
|
37
|
+
}
|
|
30
38
|
}
|
|
31
39
|
},
|
|
32
40
|
statics: {
|
package/src/entities/expand.js
CHANGED
|
@@ -1,30 +1,146 @@
|
|
|
1
|
-
define([], () =>
|
|
2
|
-
if(as === undefined) {
|
|
3
|
-
return path;
|
|
4
|
-
}
|
|
5
|
-
if(typeof as === "string" && as.indexOf(",") !== -1) {
|
|
6
|
-
as = as.split(",");
|
|
7
|
-
}
|
|
1
|
+
define(["js"], (js) => {
|
|
8
2
|
|
|
9
|
-
|
|
10
|
-
return as.map(fn).join(",");
|
|
11
|
-
}
|
|
3
|
+
// TODO join and expand => @join, @expand
|
|
12
4
|
|
|
13
|
-
|
|
14
|
-
|
|
5
|
+
const KEY_name = "@_name", KEY_expanders = "@_expanders";
|
|
6
|
+
|
|
7
|
+
function Entity(name) {
|
|
8
|
+
this[KEY_name] = name;
|
|
9
|
+
this[KEY_expanders] = {};
|
|
10
|
+
}
|
|
11
|
+
Entity.prototype.join = function(alias, attributes) {
|
|
12
|
+
const expanders = this[KEY_expanders];
|
|
13
|
+
const expander = expanders[alias] || expanders[alias.toLowerCase()];
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
alias = " " + as.pop();
|
|
15
|
+
if(!expander) {
|
|
16
|
+
throw new Error("Unknown join alias/entity: " + alias);
|
|
19
17
|
}
|
|
20
|
-
as = as.pop();
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
return expander(attributes);
|
|
20
|
+
};
|
|
21
|
+
Entity.prototype.expand = function(...args) {
|
|
22
|
+
const arr = (args.length === 1 && Array.isArray(args[0])) ? args[0] : args;
|
|
23
|
+
return expand.attributes4(this, arr);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const isFn = (f) => typeof f === "function";
|
|
27
|
+
const makeFn = (path) => {
|
|
28
|
+
/**
|
|
29
|
+
* makeFn(path) -> function(as) { ... }
|
|
30
|
+
* Creates a self-recursive expander that calls expand(fn, as, path).
|
|
31
|
+
*/
|
|
32
|
+
function fn(as) {
|
|
33
|
+
return expand(fn, as, path);
|
|
34
|
+
}
|
|
35
|
+
return fn;
|
|
36
|
+
};
|
|
37
|
+
const prefixId = (s) => !s ? "id" : s.startsWith("id") || s.startsWith("count:id") ? s : "id," + s;
|
|
38
|
+
|
|
39
|
+
function expand(expander, as, path) {
|
|
40
|
+
/**
|
|
41
|
+
* expand(expanderFn, as, path)
|
|
42
|
+
*
|
|
43
|
+
* - If as === undefined: returns path (so expanders can self-describe)
|
|
44
|
+
* - If as is "a,b,c": treated as ["a","b","c"]
|
|
45
|
+
* - If as is Array: maps each element through the same expander
|
|
46
|
+
* - If as contains "attr alias": returns "path.attr alias"
|
|
47
|
+
* - If as contains "type:attr": returns "type:path.attr"
|
|
48
|
+
*/
|
|
49
|
+
if(as === undefined) {
|
|
50
|
+
return path;
|
|
51
|
+
}
|
|
52
|
+
if(typeof as === "string" && as.indexOf(",") !== -1) {
|
|
53
|
+
as = as.split(",").map(function(s) { return s.trim(); });
|
|
54
|
+
}
|
|
55
|
+
if(Array.isArray(as)) {
|
|
56
|
+
return as.map(function(a) { return expander(a); });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var attr = String(as);
|
|
60
|
+
|
|
61
|
+
if(path) {
|
|
62
|
+
// typed prefix: "Watermonster:id" => "Watermonster:path.id"
|
|
63
|
+
if(attr.indexOf(":") !== -1) {
|
|
64
|
+
var t = attr.split(":");
|
|
65
|
+
return js.sf("%s:%s.%s", t[0], path, t[1]);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// aliasing: "id foo" => "path.id foo"
|
|
69
|
+
if(attr.indexOf(" ") !== -1) {
|
|
70
|
+
var parts = attr.split(" ");
|
|
71
|
+
return js.sf("%s.%s %s", path, parts[0], parts.slice(1).join(" "));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
return js.sf("%s.%s", path, attr);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// No path: just return the attribute as-is (e.g. root filter fields)
|
|
79
|
+
return attr;
|
|
80
|
+
}
|
|
81
|
+
expand.newEntity = function(name, paths, joinToExpander) {
|
|
82
|
+
/**
|
|
83
|
+
* expand.entity(name, paths, joinToExpander)
|
|
84
|
+
*
|
|
85
|
+
* paths: { bedrijf: "meetpunt.onderzoek.bedrijf", ... }
|
|
86
|
+
* joinToExpander: { Watermonster: "watermonsters", ... }
|
|
87
|
+
*
|
|
88
|
+
* Returns an object where each expander is available directly as a method:
|
|
89
|
+
* Entity.bedrijf("id") -> "meetpunt.onderzoek.bedrijf.id"
|
|
90
|
+
*
|
|
91
|
+
* Also provides:
|
|
92
|
+
* Entity.join("Bedrijf", "id") -> same, via joinToExpander / expanders lookup
|
|
93
|
+
*/
|
|
94
|
+
const entity = new Entity(name);
|
|
95
|
+
|
|
96
|
+
// Build expanders and attach them as direct methods (Entity.bedrijf(...))
|
|
97
|
+
for(const k in paths) {
|
|
98
|
+
if(paths.hasOwnProperty(k)) {
|
|
99
|
+
const fn = makeFn(paths[k] || undefined);
|
|
100
|
+
entity[KEY_expanders][k] = fn;
|
|
101
|
+
if(!entity[k]) entity[k] = fn;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Normalize join map keys to lower-case
|
|
106
|
+
for(const j in joinToExpander) {
|
|
107
|
+
if(joinToExpander.hasOwnProperty(j) && !entity[KEY_expanders][j]) {
|
|
108
|
+
entity[KEY_expanders][j] = entity[KEY_expanders][joinToExpander[j]];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return entity;
|
|
113
|
+
};
|
|
114
|
+
expand.attributes4 = (entity, arr) => arr.map(a => {
|
|
115
|
+
if(a instanceof Array) {
|
|
116
|
+
if(!entity[a[0]]) {
|
|
117
|
+
if(a.length === 1) {
|
|
118
|
+
return a[0] + ".id";
|
|
119
|
+
}
|
|
120
|
+
return prefixId(a[1]).split(",").map(s => a[0] + "." + s);
|
|
121
|
+
}
|
|
122
|
+
return entity[a[0]](prefixId(a[1]));
|
|
123
|
+
} else if(typeof a === "string") {
|
|
124
|
+
return prefixId(a).split(",");
|
|
125
|
+
}
|
|
126
|
+
}).flat();
|
|
127
|
+
|
|
128
|
+
function DefaultEntity(name) {
|
|
129
|
+
this[KEY_name] = name;
|
|
130
|
+
this.join = (alias, attributes) => {
|
|
131
|
+
return attributes.split(",").map(a => [alias, a].join("."));
|
|
132
|
+
},
|
|
133
|
+
this.expand = (...args) => {
|
|
134
|
+
return args.map(a => {
|
|
135
|
+
if(a instanceof Array) {
|
|
136
|
+
const arr = prefixId(a[1]).split(",");
|
|
137
|
+
return arr.map(path => [a[0], path].join("."));
|
|
138
|
+
} else if(typeof a === "string") {
|
|
139
|
+
return prefixId(a).split(",");
|
|
140
|
+
}
|
|
141
|
+
});
|
|
25
142
|
}
|
|
26
|
-
return js.sf("%s.%s%s", path, as, alias);
|
|
27
143
|
}
|
|
28
144
|
|
|
29
|
-
return
|
|
145
|
+
return js.mi(expand, { DefaultEntity });
|
|
30
146
|
});
|
package/src/js/_js.js
CHANGED
|
@@ -49,6 +49,7 @@ define(function(require) {
|
|
|
49
49
|
sj: serialize.serialize, //JSON.stringify,
|
|
50
50
|
pj: serialize.deserialize, //JSON.parse,
|
|
51
51
|
sf: String.format,
|
|
52
|
+
qq: (a, b) => (a === null || a === undefined) ? b : a,
|
|
52
53
|
eval: global[tlc("EVAL")],
|
|
53
54
|
nameOf: nameOf,
|
|
54
55
|
defineClass: defineClass,
|
package/src/js/extensions.js
CHANGED
|
@@ -309,12 +309,12 @@ const stringify = (obj) => {
|
|
|
309
309
|
*/
|
|
310
310
|
var s = [];
|
|
311
311
|
var idx = -1, pos = 0;
|
|
312
|
-
var
|
|
312
|
+
var argi = 1;
|
|
313
313
|
var specifiers = "cdfsHn";
|
|
314
|
-
|
|
314
|
+
|
|
315
315
|
do {
|
|
316
316
|
idx = fmt.indexOf("%", ++idx);
|
|
317
|
-
|
|
317
|
+
|
|
318
318
|
if(idx !== -1) {
|
|
319
319
|
if(fmt.charAt(idx + 1) === "%") {
|
|
320
320
|
s.push(fmt.substring(pos, idx));
|
|
@@ -323,29 +323,45 @@ const stringify = (obj) => {
|
|
|
323
323
|
pos = idx + 1;
|
|
324
324
|
} else {
|
|
325
325
|
s.push(fmt.substring(pos, idx));
|
|
326
|
-
|
|
327
|
-
|
|
326
|
+
|
|
327
|
+
var mod = "";
|
|
328
|
+
var ch = fmt.charAt(idx + 1);
|
|
329
|
+
|
|
330
|
+
while(specifiers.indexOf(ch) === -1 && ch !== "") {
|
|
328
331
|
mod += ch;
|
|
329
332
|
idx++;
|
|
330
333
|
ch = fmt.charAt(idx + 1);
|
|
331
334
|
}
|
|
335
|
+
|
|
332
336
|
if(ch === "c") {
|
|
333
337
|
if(mod === "*") {
|
|
334
|
-
var n = arguments[
|
|
338
|
+
var n = arguments[argi++];
|
|
335
339
|
while(n--) {
|
|
336
|
-
s.push(arguments[
|
|
340
|
+
s.push(arguments[argi]);
|
|
337
341
|
}
|
|
338
|
-
|
|
342
|
+
argi++;
|
|
339
343
|
} else {
|
|
340
|
-
s.push(arguments[
|
|
344
|
+
s.push(arguments[argi++]);
|
|
341
345
|
}
|
|
346
|
+
|
|
342
347
|
} else if(ch === "d") {
|
|
343
|
-
var
|
|
348
|
+
var n = parseInt(arguments[argi++], 10);
|
|
349
|
+
var value = "" + n;
|
|
350
|
+
|
|
344
351
|
if(mod.length) {
|
|
352
|
+
var len;
|
|
353
|
+
|
|
345
354
|
if(mod.charAt(0) === "0") {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
355
|
+
len = parseInt(mod.substring(1), 10) || 0;
|
|
356
|
+
|
|
357
|
+
if(value.charAt(0) === "-") {
|
|
358
|
+
while(value.length < len) {
|
|
359
|
+
value = "-0" + value.substring(1);
|
|
360
|
+
}
|
|
361
|
+
} else {
|
|
362
|
+
while(value.length < len) {
|
|
363
|
+
value = "0" + value;
|
|
364
|
+
}
|
|
349
365
|
}
|
|
350
366
|
} else {
|
|
351
367
|
len = parseInt(mod, 10) || 0;
|
|
@@ -354,57 +370,98 @@ const stringify = (obj) => {
|
|
|
354
370
|
}
|
|
355
371
|
}
|
|
356
372
|
}
|
|
373
|
+
|
|
357
374
|
s.push(value);
|
|
375
|
+
|
|
358
376
|
} else if(ch === "f") {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
377
|
+
var parts = mod.split(".");
|
|
378
|
+
var raw = Number(arguments[argi++]);
|
|
379
|
+
|
|
380
|
+
if(parts.length === 2 && !isNaN(raw)) {
|
|
381
|
+
var widthSpec = parts[0];
|
|
382
|
+
var precision = parseInt(parts[1], 10);
|
|
383
|
+
if(isNaN(precision)) {
|
|
384
|
+
precision = 0;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
var negative = raw < 0 || (raw === 0 && 1 / raw < 0);
|
|
388
|
+
var abs = Math.abs(raw);
|
|
389
|
+
var fixed = abs.toFixed(precision);
|
|
390
|
+
var out = negative ? "-" + fixed : fixed;
|
|
391
|
+
|
|
392
|
+
if(widthSpec.length) {
|
|
393
|
+
var width;
|
|
394
|
+
|
|
395
|
+
if(widthSpec.charAt(0) === "0") {
|
|
396
|
+
width = parseInt(widthSpec.substring(1), 10) || 0;
|
|
397
|
+
|
|
398
|
+
if(out.charAt(0) === "-") {
|
|
399
|
+
while(out.length < width) {
|
|
400
|
+
out = "-0" + out.substring(1);
|
|
401
|
+
}
|
|
402
|
+
} else {
|
|
403
|
+
while(out.length < width) {
|
|
404
|
+
out = "0" + out;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
} else {
|
|
408
|
+
width = parseInt(widthSpec, 10) || 0;
|
|
409
|
+
while(out.length < width) {
|
|
410
|
+
out = " " + out;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
369
413
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
414
|
+
|
|
415
|
+
s.push(out);
|
|
416
|
+
} else {
|
|
417
|
+
s.push(arguments[argi - 1]);
|
|
418
|
+
}
|
|
419
|
+
|
|
374
420
|
} else if(ch === "s" || ch === "H" || ch === "n") {
|
|
421
|
+
var value;
|
|
422
|
+
var len;
|
|
423
|
+
|
|
375
424
|
if(ch === "n") {
|
|
376
|
-
value = String.of(arguments[
|
|
425
|
+
value = String.of(arguments[argi++]);
|
|
377
426
|
} else {
|
|
378
|
-
value = "" + arguments[
|
|
427
|
+
value = "" + arguments[argi++];
|
|
379
428
|
}
|
|
429
|
+
|
|
380
430
|
if(mod.charAt(0) === "-") {
|
|
381
431
|
len = parseInt(mod.substring(1), 10) || 0;
|
|
382
432
|
while(value.length < len) {
|
|
383
|
-
value
|
|
433
|
+
value += " ";
|
|
384
434
|
}
|
|
385
435
|
} else {
|
|
386
436
|
len = parseInt(mod, 10) || 0;
|
|
387
437
|
if(mod === "*") {
|
|
388
438
|
len = parseInt(value, 10);
|
|
389
|
-
value = "" + arguments[
|
|
439
|
+
value = "" + arguments[argi++];
|
|
390
440
|
}
|
|
391
441
|
while(value.length < len) {
|
|
392
|
-
value
|
|
442
|
+
value = " " + value;
|
|
393
443
|
}
|
|
394
444
|
}
|
|
445
|
+
|
|
395
446
|
if(ch === "H" && value) {
|
|
396
447
|
try {
|
|
397
448
|
value = String.escapeHtml(value);
|
|
398
|
-
} catch(e) {
|
|
449
|
+
} catch(e) {
|
|
450
|
+
value = e.message;
|
|
451
|
+
}
|
|
399
452
|
}
|
|
453
|
+
|
|
400
454
|
s.push(value);
|
|
455
|
+
|
|
401
456
|
} else {
|
|
402
|
-
s.push(arguments[
|
|
457
|
+
s.push(arguments[argi++]);
|
|
403
458
|
}
|
|
459
|
+
|
|
404
460
|
pos = idx + 2;
|
|
405
461
|
}
|
|
406
462
|
}
|
|
407
463
|
} while(idx !== -1);
|
|
464
|
+
|
|
408
465
|
s.push(fmt.substring(pos));
|
|
409
466
|
return s.join("");
|
|
410
467
|
};
|
|
@@ -455,7 +512,9 @@ const stringify = (obj) => {
|
|
|
455
512
|
n = parseFloat(n);
|
|
456
513
|
|
|
457
514
|
if((i = r.indexOf("0000")) > dot) {
|
|
458
|
-
|
|
515
|
+
var t = n.toFixed(i - dot - 1);
|
|
516
|
+
if(t === "0" && n > 0) return n;
|
|
517
|
+
return t;
|
|
459
518
|
}
|
|
460
519
|
if((i = r.indexOf("9999")) > dot) {
|
|
461
520
|
return n.toFixed(i - dot - 1);
|
package/src/locale.js
CHANGED
|
@@ -117,7 +117,7 @@ define(function(require) {
|
|
|
117
117
|
var arr = (window.locale.missing = (window.locale.missing || []));
|
|
118
118
|
arr.push(id);
|
|
119
119
|
// console.warn("undefined locale: " + id);
|
|
120
|
-
|
|
120
|
+
r = "{" + id + "}";
|
|
121
121
|
} else if(typeof r === "function" && r.name === "locale") {
|
|
122
122
|
/* automagically call functions named locale */
|
|
123
123
|
r = r.apply(this, arguments);
|
|
@@ -172,11 +172,18 @@ define(function(require) {
|
|
|
172
172
|
} else {
|
|
173
173
|
args[0] = [prefix, id];
|
|
174
174
|
}
|
|
175
|
-
|
|
175
|
+
const r = locale.apply(this, args);
|
|
176
|
+
if(typeof r === "string" && r.endsWith("}") && r.startsWith("{" + prefix)) {
|
|
177
|
+
return "{" + r.substring(prefix.length + 1);
|
|
178
|
+
}
|
|
179
|
+
return r;
|
|
176
180
|
};
|
|
177
181
|
|
|
178
182
|
prefixed.has = (id) => locale.has(prefix + id);
|
|
179
|
-
|
|
183
|
+
prefixed.prefixed = (prefix2) => {
|
|
184
|
+
return locale.prefixed(prefix + prefix2);
|
|
185
|
+
};
|
|
186
|
+
|
|
180
187
|
return prefixed;
|
|
181
188
|
};
|
|
182
189
|
locale.define = function(prefix, defaults) {
|