@discord/intl 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/format.js +8 -7
- package/dist/intl-manager.js +6 -2
- package/dist/message.js +6 -5
- package/package.json +2 -2
- package/src/format.ts +8 -15
- package/src/intl-manager.ts +10 -2
- package/src/message.ts +7 -5
package/dist/format.js
CHANGED
|
@@ -37,16 +37,17 @@ exports.FormatBuilder = FormatBuilder;
|
|
|
37
37
|
function bindFormatValuesWithBuilder(builder, nodes, locales, formatters, formatConfig, values = {}, currentPluralValue, originalMessage) {
|
|
38
38
|
var _a, _b;
|
|
39
39
|
// Hot path for static messages that are just parsed as a single string element.
|
|
40
|
-
if (nodes.length === 1 && nodes[0][
|
|
41
|
-
builder.pushLiteralText(nodes[0][
|
|
40
|
+
if (nodes.length === 1 && typeof nodes[0][0] === 'string') {
|
|
41
|
+
builder.pushLiteralText(nodes[0][0]);
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
for (const node of nodes) {
|
|
45
45
|
const nodeType = node[intl_ast_1.AstNodeIndices.Type];
|
|
46
|
+
if (typeof nodeType === 'string') {
|
|
47
|
+
builder.pushLiteralText(nodeType);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
46
50
|
switch (nodeType) {
|
|
47
|
-
case intl_ast_1.FormatJsNodeType.Literal:
|
|
48
|
-
builder.pushLiteralText(node[intl_ast_1.AstNodeIndices.Value]);
|
|
49
|
-
continue;
|
|
50
51
|
case intl_ast_1.FormatJsNodeType.Pound:
|
|
51
52
|
// Replace `#` in plural rules with the actual numeric value. Only
|
|
52
53
|
// numeric values are replaced, otherwise the value is completed ignored?
|
|
@@ -150,7 +151,7 @@ function bindFormatValuesWithBuilder(builder, nodes, locales, formatters, format
|
|
|
150
151
|
if (option == null) {
|
|
151
152
|
throw `${value} is not a known option for select value ${variableName}. Valid options are ${Object.keys(options).join(', ')}`;
|
|
152
153
|
}
|
|
153
|
-
bindFormatValuesWithBuilder(builder, option
|
|
154
|
+
bindFormatValuesWithBuilder(builder, option, locales, formatters, formatConfig, values);
|
|
154
155
|
break;
|
|
155
156
|
}
|
|
156
157
|
case intl_ast_1.FormatJsNodeType.Plural: {
|
|
@@ -172,7 +173,7 @@ function bindFormatValuesWithBuilder(builder, nodes, locales, formatters, format
|
|
|
172
173
|
if (option == null) {
|
|
173
174
|
throw `${value} is not a known option for plural value ${variableName}. Valid options are ${Object.keys(options).join(', ')}`;
|
|
174
175
|
}
|
|
175
|
-
bindFormatValuesWithBuilder(builder, option
|
|
176
|
+
bindFormatValuesWithBuilder(builder, option, locales, formatters, formatConfig, values,
|
|
176
177
|
// @ts-expect-error assert this `as number` properly.
|
|
177
178
|
value - ((_b = node.offset) !== null && _b !== void 0 ? _b : 0));
|
|
178
179
|
break;
|
package/dist/intl-manager.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.IntlManager = exports.DEFAULT_LOCALE = void 0;
|
|
4
|
-
const intl_ast_1 = require("@discord/intl-ast");
|
|
5
4
|
const intl_1 = require("@formatjs/intl");
|
|
6
5
|
const format_1 = require("./format");
|
|
7
6
|
const format_config_1 = require("./format-config");
|
|
@@ -72,12 +71,17 @@ class IntlManager {
|
|
|
72
71
|
const resolved = message(this.currentLocale);
|
|
73
72
|
if (resolved == null || resolved.ast.length === 0)
|
|
74
73
|
return '';
|
|
74
|
+
const value = resolved.ast[0];
|
|
75
|
+
if (typeof value[0] !== 'string') {
|
|
76
|
+
throw new Error('Attempted to call `string` formatting on a non-literal message: ' +
|
|
77
|
+
JSON.stringify(resolved));
|
|
78
|
+
}
|
|
75
79
|
// TODO: Figure out how to make this typing exact. This currently relies on
|
|
76
80
|
// the generic typing being sound enough to know that the message can only
|
|
77
81
|
// contain a single static text node and no placeholders or rich text.
|
|
78
82
|
// As it stands, this is _technically_ typed as string | undefined, even though
|
|
79
83
|
// TypeScript doesn't actually complain about it.
|
|
80
|
-
return
|
|
84
|
+
return value[0];
|
|
81
85
|
}
|
|
82
86
|
/**
|
|
83
87
|
* Return a raw string representing the syntax of the original message, as
|
package/dist/message.js
CHANGED
|
@@ -22,10 +22,11 @@ exports.InternalIntlMessage = InternalIntlMessage;
|
|
|
22
22
|
// appended, rather than creating a bunch of intermediate strings.
|
|
23
23
|
function serializeAst(ast, result) {
|
|
24
24
|
for (const node of ast) {
|
|
25
|
+
if (typeof node[0] === 'string') {
|
|
26
|
+
result.value += node[0];
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
25
29
|
switch (node[intl_ast_1.AstNodeIndices.Type]) {
|
|
26
|
-
case intl_ast_1.FormatJsNodeType.Literal:
|
|
27
|
-
result.value += node[intl_ast_1.AstNodeIndices.Value];
|
|
28
|
-
return;
|
|
29
30
|
case intl_ast_1.FormatJsNodeType.Argument:
|
|
30
31
|
// Empties are an artifact of our parsing strategy, not necessary here.
|
|
31
32
|
if (result.value === '$_')
|
|
@@ -61,7 +62,7 @@ function serializeAst(ast, result) {
|
|
|
61
62
|
}
|
|
62
63
|
for (const [name, arm] of Object.entries(node[intl_ast_1.AstNodeIndices.Options])) {
|
|
63
64
|
result.value += ' ' + name + ' {';
|
|
64
|
-
serializeAst(arm
|
|
65
|
+
serializeAst(arm, result);
|
|
65
66
|
result.value += '}';
|
|
66
67
|
}
|
|
67
68
|
return;
|
|
@@ -73,7 +74,7 @@ function serializeAst(ast, result) {
|
|
|
73
74
|
result.value += '{' + node[intl_ast_1.AstNodeIndices.Value] + ', select, ';
|
|
74
75
|
for (const [name, arm] of Object.entries(node[intl_ast_1.AstNodeIndices.Options])) {
|
|
75
76
|
result.value += ' ' + name + ' {';
|
|
76
|
-
serializeAst(arm
|
|
77
|
+
serializeAst(arm, result);
|
|
77
78
|
result.value += '}';
|
|
78
79
|
}
|
|
79
80
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@discord/intl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Client runtime for managing messages and translations in a React project.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@formatjs/intl": "^2.10.1",
|
|
20
20
|
"@intrnl/xxhash64": "^0.1.2",
|
|
21
21
|
"intl-messageformat": "^10.5.11",
|
|
22
|
-
"@discord/intl-ast": "0.
|
|
22
|
+
"@discord/intl-ast": "0.7.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@swc/cli": "^0.3.12",
|
package/src/format.ts
CHANGED
|
@@ -56,18 +56,18 @@ export function bindFormatValuesWithBuilder<T, Builder extends FormatBuilder<T>>
|
|
|
56
56
|
originalMessage?: string,
|
|
57
57
|
) {
|
|
58
58
|
// Hot path for static messages that are just parsed as a single string element.
|
|
59
|
-
if (nodes.length === 1 && nodes[0][
|
|
60
|
-
builder.pushLiteralText(nodes[0][
|
|
59
|
+
if (nodes.length === 1 && typeof nodes[0][0] === 'string') {
|
|
60
|
+
builder.pushLiteralText(nodes[0][0]);
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
for (const node of nodes) {
|
|
65
65
|
const nodeType = node[AstNodeIndices.Type];
|
|
66
|
+
if (typeof nodeType === 'string') {
|
|
67
|
+
builder.pushLiteralText(nodeType);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
66
70
|
switch (nodeType) {
|
|
67
|
-
case FormatJsNodeType.Literal:
|
|
68
|
-
builder.pushLiteralText(node[AstNodeIndices.Value]);
|
|
69
|
-
continue;
|
|
70
|
-
|
|
71
71
|
case FormatJsNodeType.Pound:
|
|
72
72
|
// Replace `#` in plural rules with the actual numeric value. Only
|
|
73
73
|
// numeric values are replaced, otherwise the value is completed ignored?
|
|
@@ -184,14 +184,7 @@ export function bindFormatValuesWithBuilder<T, Builder extends FormatBuilder<T>>
|
|
|
184
184
|
if (option == null) {
|
|
185
185
|
throw `${value} is not a known option for select value ${variableName}. Valid options are ${Object.keys(options).join(', ')}`;
|
|
186
186
|
}
|
|
187
|
-
bindFormatValuesWithBuilder(
|
|
188
|
-
builder,
|
|
189
|
-
option.value,
|
|
190
|
-
locales,
|
|
191
|
-
formatters,
|
|
192
|
-
formatConfig,
|
|
193
|
-
values,
|
|
194
|
-
);
|
|
187
|
+
bindFormatValuesWithBuilder(builder, option, locales, formatters, formatConfig, values);
|
|
195
188
|
break;
|
|
196
189
|
}
|
|
197
190
|
|
|
@@ -215,7 +208,7 @@ export function bindFormatValuesWithBuilder<T, Builder extends FormatBuilder<T>>
|
|
|
215
208
|
}
|
|
216
209
|
bindFormatValuesWithBuilder(
|
|
217
210
|
builder,
|
|
218
|
-
option
|
|
211
|
+
option,
|
|
219
212
|
locales,
|
|
220
213
|
formatters,
|
|
221
214
|
formatConfig,
|
package/src/intl-manager.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LiteralNode } from '@discord/intl-ast';
|
|
2
2
|
import { createIntl, IntlShape } from '@formatjs/intl';
|
|
3
3
|
import { Formatters } from 'intl-messageformat';
|
|
4
4
|
|
|
@@ -120,12 +120,20 @@ export class IntlManager {
|
|
|
120
120
|
const resolved = message(this.currentLocale);
|
|
121
121
|
if (resolved == null || resolved.ast.length === 0) return '';
|
|
122
122
|
|
|
123
|
+
const value = resolved.ast[0] as LiteralNode;
|
|
124
|
+
if (typeof value[0] !== 'string') {
|
|
125
|
+
throw new Error(
|
|
126
|
+
'Attempted to call `string` formatting on a non-literal message: ' +
|
|
127
|
+
JSON.stringify(resolved),
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
123
131
|
// TODO: Figure out how to make this typing exact. This currently relies on
|
|
124
132
|
// the generic typing being sound enough to know that the message can only
|
|
125
133
|
// contain a single static text node and no placeholders or rich text.
|
|
126
134
|
// As it stands, this is _technically_ typed as string | undefined, even though
|
|
127
135
|
// TypeScript doesn't actually complain about it.
|
|
128
|
-
return
|
|
136
|
+
return value[0];
|
|
129
137
|
}
|
|
130
138
|
|
|
131
139
|
/**
|
package/src/message.ts
CHANGED
|
@@ -32,10 +32,12 @@ export class InternalIntlMessage {
|
|
|
32
32
|
// appended, rather than creating a bunch of intermediate strings.
|
|
33
33
|
function serializeAst(ast: AstNode[], result: { value: string }) {
|
|
34
34
|
for (const node of ast) {
|
|
35
|
+
if (typeof node[0] === 'string') {
|
|
36
|
+
result.value += node[0];
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
35
40
|
switch (node[AstNodeIndices.Type]) {
|
|
36
|
-
case FormatJsNodeType.Literal:
|
|
37
|
-
result.value += node[AstNodeIndices.Value];
|
|
38
|
-
return;
|
|
39
41
|
case FormatJsNodeType.Argument:
|
|
40
42
|
// Empties are an artifact of our parsing strategy, not necessary here.
|
|
41
43
|
if (result.value === '$_') return;
|
|
@@ -71,7 +73,7 @@ function serializeAst(ast: AstNode[], result: { value: string }) {
|
|
|
71
73
|
}
|
|
72
74
|
for (const [name, arm] of Object.entries(node[AstNodeIndices.Options])) {
|
|
73
75
|
result.value += ' ' + name + ' {';
|
|
74
|
-
serializeAst(arm
|
|
76
|
+
serializeAst(arm, result);
|
|
75
77
|
result.value += '}';
|
|
76
78
|
}
|
|
77
79
|
return;
|
|
@@ -83,7 +85,7 @@ function serializeAst(ast: AstNode[], result: { value: string }) {
|
|
|
83
85
|
result.value += '{' + node[AstNodeIndices.Value] + ', select, ';
|
|
84
86
|
for (const [name, arm] of Object.entries(node[AstNodeIndices.Options])) {
|
|
85
87
|
result.value += ' ' + name + ' {';
|
|
86
|
-
serializeAst(arm
|
|
88
|
+
serializeAst(arm, result);
|
|
87
89
|
result.value += '}';
|
|
88
90
|
}
|
|
89
91
|
return;
|