@discord/intl 0.2.0-canary.cad566b → 0.2.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/index.d.ts +1 -2
- package/dist/index.js +3 -5
- package/dist/intl-manager.d.ts +7 -0
- package/dist/intl-manager.js +12 -5
- package/dist/message-loader.d.ts +3 -33
- package/dist/message-loader.js +15 -113
- package/dist/message.d.ts +15 -1
- package/dist/message.js +83 -1
- package/package.json +1 -1
- package/src/index.ts +2 -2
- package/src/intl-manager.ts +15 -5
- package/src/message-loader.ts +15 -90
- package/src/message.ts +36 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { RichTextNode } from './formatters';
|
|
3
|
+
export { IntlManager, createLoader, DEFAULT_LOCALE, type FormatFunction } from './intl-manager';
|
|
3
4
|
export * from './formatters';
|
|
4
|
-
export { IntlManager, DEFAULT_LOCALE, type FormatFunction } from './intl-manager';
|
|
5
|
-
export { createLoader, waitForAllDefaultIntlMessagesLoaded } from './message-loader';
|
|
6
5
|
export type * from './types.d.ts';
|
|
7
6
|
/**
|
|
8
7
|
* A type representing any message that has been formatted using one of the
|
package/dist/index.js
CHANGED
|
@@ -14,11 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
18
|
-
__exportStar(require("./formatters"), exports);
|
|
17
|
+
exports.DEFAULT_LOCALE = exports.createLoader = exports.IntlManager = void 0;
|
|
19
18
|
var intl_manager_1 = require("./intl-manager");
|
|
20
19
|
Object.defineProperty(exports, "IntlManager", { enumerable: true, get: function () { return intl_manager_1.IntlManager; } });
|
|
20
|
+
Object.defineProperty(exports, "createLoader", { enumerable: true, get: function () { return intl_manager_1.createLoader; } });
|
|
21
21
|
Object.defineProperty(exports, "DEFAULT_LOCALE", { enumerable: true, get: function () { return intl_manager_1.DEFAULT_LOCALE; } });
|
|
22
|
-
|
|
23
|
-
Object.defineProperty(exports, "createLoader", { enumerable: true, get: function () { return message_loader_1.createLoader; } });
|
|
24
|
-
Object.defineProperty(exports, "waitForAllDefaultIntlMessagesLoaded", { enumerable: true, get: function () { return message_loader_1.waitForAllDefaultIntlMessagesLoaded; } });
|
|
22
|
+
__exportStar(require("./formatters"), exports);
|
package/dist/intl-manager.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IntlShape } from '@formatjs/intl';
|
|
2
|
+
import { LocaleId, LocaleImportMap, MessageLoader } from './message-loader';
|
|
2
3
|
import type { FormatterImplementation, IntlMessageGetter, RequiredFormatValues, TypedIntlMessageGetter } from './types';
|
|
3
4
|
import { InternalIntlMessage } from './message';
|
|
4
5
|
import { FormatBuilderConstructor } from './format';
|
|
@@ -47,4 +48,10 @@ export declare class IntlManager {
|
|
|
47
48
|
string<T extends TypedIntlMessageGetter<undefined>>(message: T): string;
|
|
48
49
|
bindFormatValues<T>(Builder: FormatBuilderConstructor<T>, message: InternalIntlMessage, values: Record<string, any>): T[];
|
|
49
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Create a new MessageLoader, which handles lazily loading messages for
|
|
53
|
+
* different locales and sanity checks as needed to provide accessors for each
|
|
54
|
+
* message defined in `messageKeys`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createLoader(messageKeys: string[], localeImportMap: LocaleImportMap, defaultLocale: LocaleId): MessageLoader;
|
|
50
57
|
export {};
|
package/dist/intl-manager.js
CHANGED
|
@@ -28,8 +28,10 @@ var __read = (this && this.__read) || function (o, n) {
|
|
|
28
28
|
};
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
30
|
exports.IntlManager = exports.DEFAULT_LOCALE = void 0;
|
|
31
|
+
exports.createLoader = createLoader;
|
|
31
32
|
var intl_1 = require("@formatjs/intl");
|
|
32
33
|
var intl_messageformat_1 = require("intl-messageformat");
|
|
34
|
+
var message_loader_1 = require("./message-loader");
|
|
33
35
|
var format_1 = require("./format");
|
|
34
36
|
/**
|
|
35
37
|
* Fallback locale used for all internationalization when an operation in the
|
|
@@ -120,11 +122,8 @@ var IntlManager = /** @class */ (function () {
|
|
|
120
122
|
* immediately return the plain string value of the message in the current locale.
|
|
121
123
|
*/
|
|
122
124
|
IntlManager.prototype.string = function (message) {
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
// the message can only contain a single static text node and no
|
|
126
|
-
// placeholders or rich text.
|
|
127
|
-
return message(this.currentLocale).ast[0].value;
|
|
125
|
+
// TODO: Figure out how to make this typing exact.
|
|
126
|
+
return message(this.currentLocale).message;
|
|
128
127
|
};
|
|
129
128
|
IntlManager.prototype.bindFormatValues = function (Builder, message, values) {
|
|
130
129
|
return (0, format_1.bindFormatValues)(Builder, message.ast, [this.currentLocale, this.defaultLocale], this.intl.formatters, this.intl.formats, values);
|
|
@@ -132,3 +131,11 @@ var IntlManager = /** @class */ (function () {
|
|
|
132
131
|
return IntlManager;
|
|
133
132
|
}());
|
|
134
133
|
exports.IntlManager = IntlManager;
|
|
134
|
+
/**
|
|
135
|
+
* Create a new MessageLoader, which handles lazily loading messages for
|
|
136
|
+
* different locales and sanity checks as needed to provide accessors for each
|
|
137
|
+
* message defined in `messageKeys`.
|
|
138
|
+
*/
|
|
139
|
+
function createLoader(messageKeys, localeImportMap, defaultLocale) {
|
|
140
|
+
return new message_loader_1.MessageLoader(messageKeys, localeImportMap, defaultLocale);
|
|
141
|
+
}
|
package/dist/message-loader.d.ts
CHANGED
|
@@ -28,17 +28,9 @@ export declare class MessageLoader {
|
|
|
28
28
|
* then a request has already been made to load the locale and it is waiting
|
|
29
29
|
* to resolve.
|
|
30
30
|
*/
|
|
31
|
-
_localeLoadingPromises: Record<LocaleId, {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* If the locale is currently being loaded, this Promise will exist and
|
|
36
|
-
* represent that loading status. Otherwise, this value is undefined.
|
|
37
|
-
*/
|
|
38
|
-
current?: Promise<{
|
|
39
|
-
default: MessagesData;
|
|
40
|
-
}> | undefined;
|
|
41
|
-
}>;
|
|
31
|
+
_localeLoadingPromises: Record<LocaleId, Promise<{
|
|
32
|
+
default: MessagesData;
|
|
33
|
+
}> | undefined>;
|
|
42
34
|
/**
|
|
43
35
|
* Map of pre-parsed messages, keyed by the message key and locale
|
|
44
36
|
*/
|
|
@@ -107,27 +99,5 @@ export declare class MessageLoader {
|
|
|
107
99
|
* Subscribe to events about when a locale has loaded.
|
|
108
100
|
*/
|
|
109
101
|
onChange(callback: () => void): () => void;
|
|
110
|
-
isLocaleLoaded(locale: LocaleId, requireCurrent?: boolean): boolean;
|
|
111
|
-
waitForLocaleLoaded(locale: LocaleId, requireCurrent?: boolean): Promise<void>;
|
|
112
|
-
/**
|
|
113
|
-
* Returns true if this loader's default locale has finished loading. When
|
|
114
|
-
* true, all messages managed by this loader are guaranteed to have _a_
|
|
115
|
-
* render-able value, even if one does not exist in the current locale.
|
|
116
|
-
*/
|
|
117
|
-
waitForDefaultLocale(requireCurrent?: boolean): Promise<void>;
|
|
118
102
|
}
|
|
119
|
-
/**
|
|
120
|
-
* Returns a new Promise that resolves after all currently-registered message
|
|
121
|
-
* loaders have finished successfully loading their default locale content.
|
|
122
|
-
* Once this Promise has resolved, all messages that currently exist in the
|
|
123
|
-
* application (i.e., within all modules that have been imported or required in
|
|
124
|
-
* the current session) can be guaranteed to have _a_ render-able value.
|
|
125
|
-
*/
|
|
126
|
-
export declare function waitForAllDefaultIntlMessagesLoaded(): Promise<void>;
|
|
127
|
-
/**
|
|
128
|
-
* Create a new MessageLoader, which handles lazily loading messages for
|
|
129
|
-
* different locales and sanity checks as needed to provide accessors for each
|
|
130
|
-
* message defined in `messageKeys`.
|
|
131
|
-
*/
|
|
132
|
-
export declare function createLoader(messageKeys: string[], localeImportMap: LocaleImportMap, defaultLocale: LocaleId): MessageLoader;
|
|
133
103
|
export {};
|
package/dist/message-loader.js
CHANGED
|
@@ -64,8 +64,6 @@ var __read = (this && this.__read) || function (o, n) {
|
|
|
64
64
|
};
|
|
65
65
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
66
66
|
exports.MessageLoader = void 0;
|
|
67
|
-
exports.waitForAllDefaultIntlMessagesLoaded = waitForAllDefaultIntlMessagesLoaded;
|
|
68
|
-
exports.createLoader = createLoader;
|
|
69
67
|
var message_1 = require("./message");
|
|
70
68
|
var MessageLoader = /** @class */ (function () {
|
|
71
69
|
function MessageLoader(messageKeys, localeImportMap, defaultLocale) {
|
|
@@ -80,24 +78,17 @@ var MessageLoader = /** @class */ (function () {
|
|
|
80
78
|
this._parseCache = new Map();
|
|
81
79
|
this._subscribers = new Set();
|
|
82
80
|
this._loadLocale(this.defaultLocale);
|
|
83
|
-
this.fallbackMessage = new message_1.InternalIntlMessage(
|
|
81
|
+
this.fallbackMessage = new message_1.InternalIntlMessage('THIS MESSAGE FAILED TO LOAD', 'en-US');
|
|
84
82
|
// In cases where hot module replacement is available, set up cache clearing whenever the
|
|
85
83
|
// targets change so that values are always replaced.
|
|
86
84
|
// @ts-expect-error `hot` not defined in types.
|
|
87
85
|
if (module.hot) {
|
|
88
86
|
var _loop_1 = function (locale, file) {
|
|
89
87
|
// @ts-expect-error `hot` not defined in types.
|
|
90
|
-
module.hot.accept(file, function () {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
case 1:
|
|
95
|
-
_a.sent();
|
|
96
|
-
this._parseCache.clear();
|
|
97
|
-
return [2 /*return*/];
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}); });
|
|
88
|
+
module.hot.accept(file, function () {
|
|
89
|
+
_this._parseCache.clear();
|
|
90
|
+
_this._loadLocale(locale);
|
|
91
|
+
});
|
|
101
92
|
};
|
|
102
93
|
try {
|
|
103
94
|
for (var _b = __values(Object.entries(localeImportMap)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
@@ -128,8 +119,9 @@ var MessageLoader = /** @class */ (function () {
|
|
|
128
119
|
MessageLoader.prototype.get = function (key, locale) {
|
|
129
120
|
var _a;
|
|
130
121
|
var value = (_a = this.getMessageValue(key, locale)) !== null && _a !== void 0 ? _a : this.getMessageValue(key, this.defaultLocale);
|
|
131
|
-
if (value != null)
|
|
122
|
+
if (value != null) {
|
|
132
123
|
return value;
|
|
124
|
+
}
|
|
133
125
|
// If the message couldn't be found in either the requested nor the default locale, then
|
|
134
126
|
// nothing can be done.
|
|
135
127
|
var errorKey = this._debugKeyMap != null ? "\"".concat(this._debugKeyMap[key], "\" (").concat(key, ")") : undefined;
|
|
@@ -150,25 +142,20 @@ var MessageLoader = /** @class */ (function () {
|
|
|
150
142
|
* returning.
|
|
151
143
|
*/
|
|
152
144
|
MessageLoader.prototype.getMessageValue = function (key, locale) {
|
|
153
|
-
var _a, _b, _c;
|
|
154
145
|
var cacheKey = key + '@' + locale;
|
|
155
146
|
var cachedValue = this._parseCache.get(cacheKey);
|
|
156
147
|
if (cachedValue != null)
|
|
157
148
|
return cachedValue;
|
|
158
|
-
// Return early if this locale
|
|
159
|
-
|
|
160
|
-
if (!((_b = (_a = this._localeLoadingPromises[locale]) === null || _a === void 0 ? void 0 : _a.initialized) !== null && _b !== void 0 ? _b : false) ||
|
|
161
|
-
((_c = this._localeLoadingPromises[locale]) === null || _c === void 0 ? void 0 : _c.current) != null) {
|
|
149
|
+
// Return early if this locale is still in the process of being loaded.
|
|
150
|
+
if (this._localeLoadingPromises[locale] != null) {
|
|
162
151
|
return undefined;
|
|
163
152
|
}
|
|
164
153
|
// If not, check whether it's been loaded and trigger a load if not.
|
|
165
154
|
if (this.messages[locale] == null) {
|
|
166
|
-
// Ensure the locale
|
|
155
|
+
// Ensure the locale is loaded, if it is supported
|
|
167
156
|
if (this.supportedLocales.includes(locale)) {
|
|
168
157
|
this._loadLocale(locale);
|
|
169
158
|
}
|
|
170
|
-
// ...But that means it definitely won't be available on this tick,
|
|
171
|
-
// so return undefined.
|
|
172
159
|
return undefined;
|
|
173
160
|
}
|
|
174
161
|
// Then try to return the loaded message.
|
|
@@ -199,7 +186,7 @@ var MessageLoader = /** @class */ (function () {
|
|
|
199
186
|
};
|
|
200
187
|
MessageLoader.prototype._loadLocale = function (locale) {
|
|
201
188
|
return __awaiter(this, void 0, void 0, function () {
|
|
202
|
-
var
|
|
189
|
+
var loadingPromise, _a, _b;
|
|
203
190
|
return __generator(this, function (_c) {
|
|
204
191
|
switch (_c.label) {
|
|
205
192
|
case 0:
|
|
@@ -216,14 +203,14 @@ var MessageLoader = /** @class */ (function () {
|
|
|
216
203
|
// If the locale is already set in `messages`, then it doesn't need to be loaded again.
|
|
217
204
|
if (this.messages[locale] != null)
|
|
218
205
|
return [2 /*return*/];
|
|
219
|
-
|
|
220
|
-
this._localeLoadingPromises[locale] =
|
|
206
|
+
loadingPromise = this.localeImportMap[locale]();
|
|
207
|
+
this._localeLoadingPromises[locale] = loadingPromise;
|
|
221
208
|
_a = this.messages;
|
|
222
209
|
_b = locale;
|
|
223
|
-
return [4 /*yield*/,
|
|
210
|
+
return [4 /*yield*/, loadingPromise];
|
|
224
211
|
case 1:
|
|
225
212
|
_a[_b] = (_c.sent()).default;
|
|
226
|
-
this._localeLoadingPromises[locale]
|
|
213
|
+
delete this._localeLoadingPromises[locale];
|
|
227
214
|
this.emitChange();
|
|
228
215
|
return [2 /*return*/];
|
|
229
216
|
}
|
|
@@ -258,91 +245,6 @@ var MessageLoader = /** @class */ (function () {
|
|
|
258
245
|
this._subscribers.add(callback);
|
|
259
246
|
return function () { return _this._subscribers.delete(callback); };
|
|
260
247
|
};
|
|
261
|
-
MessageLoader.prototype.isLocaleLoaded = function (locale, requireCurrent) {
|
|
262
|
-
if (requireCurrent === void 0) { requireCurrent = false; }
|
|
263
|
-
var ref = this._localeLoadingPromises[locale];
|
|
264
|
-
// Ensure the locale at least exists and is initialized.
|
|
265
|
-
if (ref == null || ref.initialized == false)
|
|
266
|
-
return false;
|
|
267
|
-
// `current` will be deleted once the locale has loaded, so if it is null,
|
|
268
|
-
// then the locale data is current.
|
|
269
|
-
if (requireCurrent)
|
|
270
|
-
return ref.current == null;
|
|
271
|
-
// Otherwise, initialization is enough.
|
|
272
|
-
return true;
|
|
273
|
-
};
|
|
274
|
-
MessageLoader.prototype.waitForLocaleLoaded = function (locale_1) {
|
|
275
|
-
return __awaiter(this, arguments, void 0, function (locale, requireCurrent) {
|
|
276
|
-
var ref;
|
|
277
|
-
if (requireCurrent === void 0) { requireCurrent = false; }
|
|
278
|
-
return __generator(this, function (_a) {
|
|
279
|
-
switch (_a.label) {
|
|
280
|
-
case 0:
|
|
281
|
-
ref = this._localeLoadingPromises[locale];
|
|
282
|
-
// If the locale hasn't been loaded at all, kick off the load and return
|
|
283
|
-
// that Promise directly.
|
|
284
|
-
if (ref == null)
|
|
285
|
-
return [2 /*return*/, this._loadLocale(locale)];
|
|
286
|
-
// If initialization is enough for this request, just resolve immediately.
|
|
287
|
-
if (ref.initialized && !requireCurrent)
|
|
288
|
-
return [2 /*return*/];
|
|
289
|
-
// Otherwise, check the `current` loading state on the object, and if that
|
|
290
|
-
// doesn't exist, then the locale data is already finished loading, and the
|
|
291
|
-
// containing Promise will just resolve with `undefined`.
|
|
292
|
-
return [4 /*yield*/, ref.current];
|
|
293
|
-
case 1:
|
|
294
|
-
// Otherwise, check the `current` loading state on the object, and if that
|
|
295
|
-
// doesn't exist, then the locale data is already finished loading, and the
|
|
296
|
-
// containing Promise will just resolve with `undefined`.
|
|
297
|
-
_a.sent();
|
|
298
|
-
return [2 /*return*/];
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
});
|
|
302
|
-
};
|
|
303
|
-
/**
|
|
304
|
-
* Returns true if this loader's default locale has finished loading. When
|
|
305
|
-
* true, all messages managed by this loader are guaranteed to have _a_
|
|
306
|
-
* render-able value, even if one does not exist in the current locale.
|
|
307
|
-
*/
|
|
308
|
-
MessageLoader.prototype.waitForDefaultLocale = function () {
|
|
309
|
-
return __awaiter(this, arguments, void 0, function (requireCurrent) {
|
|
310
|
-
if (requireCurrent === void 0) { requireCurrent = false; }
|
|
311
|
-
return __generator(this, function (_a) {
|
|
312
|
-
return [2 /*return*/, this.waitForLocaleLoaded(this.defaultLocale, requireCurrent)];
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
};
|
|
316
248
|
return MessageLoader;
|
|
317
249
|
}());
|
|
318
250
|
exports.MessageLoader = MessageLoader;
|
|
319
|
-
var LOADER_REGISTRY = [];
|
|
320
|
-
/**
|
|
321
|
-
* Returns a new Promise that resolves after all currently-registered message
|
|
322
|
-
* loaders have finished successfully loading their default locale content.
|
|
323
|
-
* Once this Promise has resolved, all messages that currently exist in the
|
|
324
|
-
* application (i.e., within all modules that have been imported or required in
|
|
325
|
-
* the current session) can be guaranteed to have _a_ render-able value.
|
|
326
|
-
*/
|
|
327
|
-
function waitForAllDefaultIntlMessagesLoaded() {
|
|
328
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
329
|
-
return __generator(this, function (_a) {
|
|
330
|
-
switch (_a.label) {
|
|
331
|
-
case 0: return [4 /*yield*/, Promise.all(LOADER_REGISTRY.map(function (loader) { return loader.waitForDefaultLocale(); }))];
|
|
332
|
-
case 1:
|
|
333
|
-
_a.sent();
|
|
334
|
-
return [2 /*return*/];
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Create a new MessageLoader, which handles lazily loading messages for
|
|
341
|
-
* different locales and sanity checks as needed to provide accessors for each
|
|
342
|
-
* message defined in `messageKeys`.
|
|
343
|
-
*/
|
|
344
|
-
function createLoader(messageKeys, localeImportMap, defaultLocale) {
|
|
345
|
-
var loader = new MessageLoader(messageKeys, localeImportMap, defaultLocale);
|
|
346
|
-
LOADER_REGISTRY.push(loader);
|
|
347
|
-
return loader;
|
|
348
|
-
}
|
package/dist/message.d.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { FormatJsNode } from './keyless-json';
|
|
2
2
|
export declare class InternalIntlMessage {
|
|
3
3
|
locale: string;
|
|
4
|
+
message?: string;
|
|
4
5
|
ast: FormatJsNode[];
|
|
5
|
-
|
|
6
|
+
/**
|
|
7
|
+
* A stripped-down representation of the message with no rich formatting
|
|
8
|
+
* elements preserved. This will be lazily created the first time it is
|
|
9
|
+
* requested (e.g., by calling `formatToPlainString`).
|
|
10
|
+
*/
|
|
11
|
+
get plainAst(): FormatJsNode[];
|
|
12
|
+
_plainAst: FormatJsNode[];
|
|
13
|
+
constructor(messageOrAst: string | FormatJsNode[], locale: string);
|
|
14
|
+
/**
|
|
15
|
+
* Returns the same element with any formatting tags removed. If the element
|
|
16
|
+
* itself is a tag, the children will be hoisted and returned, otherwise the
|
|
17
|
+
* element is returned as an array of itself.
|
|
18
|
+
*/
|
|
19
|
+
private _removeRichTags;
|
|
6
20
|
}
|
package/dist/message.js
CHANGED
|
@@ -1,11 +1,93 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __values = (this && this.__values) || function(o) {
|
|
3
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
4
|
+
if (m) return m.call(o);
|
|
5
|
+
if (o && typeof o.length === "number") return {
|
|
6
|
+
next: function () {
|
|
7
|
+
if (o && i >= o.length) o = void 0;
|
|
8
|
+
return { value: o && o[i++], done: !o };
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
12
|
+
};
|
|
13
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
14
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
15
|
+
if (!m) return o;
|
|
16
|
+
var i = m.call(o), r, ar = [], e;
|
|
17
|
+
try {
|
|
18
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
19
|
+
}
|
|
20
|
+
catch (error) { e = { error: error }; }
|
|
21
|
+
finally {
|
|
22
|
+
try {
|
|
23
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
24
|
+
}
|
|
25
|
+
finally { if (e) throw e.error; }
|
|
26
|
+
}
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
30
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
31
|
+
if (ar || !(i in from)) {
|
|
32
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
33
|
+
ar[i] = from[i];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
37
|
+
};
|
|
2
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
39
|
exports.InternalIntlMessage = void 0;
|
|
40
|
+
var keyless_json_1 = require("./keyless-json");
|
|
4
41
|
var InternalIntlMessage = /** @class */ (function () {
|
|
5
42
|
function InternalIntlMessage(messageOrAst, locale) {
|
|
6
43
|
this.locale = locale;
|
|
7
|
-
|
|
44
|
+
if (typeof messageOrAst === 'string') {
|
|
45
|
+
this.message = messageOrAst;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this.ast = messageOrAst;
|
|
49
|
+
}
|
|
8
50
|
}
|
|
51
|
+
Object.defineProperty(InternalIntlMessage.prototype, "plainAst", {
|
|
52
|
+
/**
|
|
53
|
+
* A stripped-down representation of the message with no rich formatting
|
|
54
|
+
* elements preserved. This will be lazily created the first time it is
|
|
55
|
+
* requested (e.g., by calling `formatToPlainString`).
|
|
56
|
+
*/
|
|
57
|
+
get: function () {
|
|
58
|
+
return (this._plainAst = this._removeRichTags(this.ast));
|
|
59
|
+
},
|
|
60
|
+
enumerable: false,
|
|
61
|
+
configurable: true
|
|
62
|
+
});
|
|
63
|
+
/**
|
|
64
|
+
* Returns the same element with any formatting tags removed. If the element
|
|
65
|
+
* itself is a tag, the children will be hoisted and returned, otherwise the
|
|
66
|
+
* element is returned as an array of itself.
|
|
67
|
+
*/
|
|
68
|
+
InternalIntlMessage.prototype._removeRichTags = function (nodes) {
|
|
69
|
+
var e_1, _a;
|
|
70
|
+
var result = new Array(nodes.length);
|
|
71
|
+
try {
|
|
72
|
+
for (var nodes_1 = __values(nodes), nodes_1_1 = nodes_1.next(); !nodes_1_1.done; nodes_1_1 = nodes_1.next()) {
|
|
73
|
+
var node = nodes_1_1.value;
|
|
74
|
+
if (node.type === keyless_json_1.FormatJsNodeType.Tag) {
|
|
75
|
+
result.push.apply(result, __spreadArray([], __read(this._removeRichTags(node.children)), false));
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
result.push(node);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
83
|
+
finally {
|
|
84
|
+
try {
|
|
85
|
+
if (nodes_1_1 && !nodes_1_1.done && (_a = nodes_1.return)) _a.call(nodes_1);
|
|
86
|
+
}
|
|
87
|
+
finally { if (e_1) throw e_1.error; }
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
};
|
|
9
91
|
return InternalIntlMessage;
|
|
10
92
|
}());
|
|
11
93
|
exports.InternalIntlMessage = InternalIntlMessage;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { RichTextNode } from './formatters';
|
|
3
3
|
|
|
4
|
+
export { IntlManager, createLoader, DEFAULT_LOCALE, type FormatFunction } from './intl-manager';
|
|
4
5
|
export * from './formatters';
|
|
5
|
-
|
|
6
|
-
export { createLoader, waitForAllDefaultIntlMessagesLoaded } from './message-loader';
|
|
6
|
+
|
|
7
7
|
export type * from './types.d.ts';
|
|
8
8
|
|
|
9
9
|
/**
|
package/src/intl-manager.ts
CHANGED
|
@@ -116,11 +116,8 @@ export class IntlManager {
|
|
|
116
116
|
* immediately return the plain string value of the message in the current locale.
|
|
117
117
|
*/
|
|
118
118
|
string<T extends TypedIntlMessageGetter<undefined>>(message: T): string {
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
// the message can only contain a single static text node and no
|
|
122
|
-
// placeholders or rich text.
|
|
123
|
-
return message(this.currentLocale).ast[0].value;
|
|
119
|
+
// TODO: Figure out how to make this typing exact.
|
|
120
|
+
return message(this.currentLocale).message;
|
|
124
121
|
}
|
|
125
122
|
|
|
126
123
|
bindFormatValues<T>(
|
|
@@ -138,3 +135,16 @@ export class IntlManager {
|
|
|
138
135
|
);
|
|
139
136
|
}
|
|
140
137
|
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Create a new MessageLoader, which handles lazily loading messages for
|
|
141
|
+
* different locales and sanity checks as needed to provide accessors for each
|
|
142
|
+
* message defined in `messageKeys`.
|
|
143
|
+
*/
|
|
144
|
+
export function createLoader(
|
|
145
|
+
messageKeys: string[],
|
|
146
|
+
localeImportMap: LocaleImportMap,
|
|
147
|
+
defaultLocale: LocaleId,
|
|
148
|
+
) {
|
|
149
|
+
return new MessageLoader(messageKeys, localeImportMap, defaultLocale);
|
|
150
|
+
}
|
package/src/message-loader.ts
CHANGED
|
@@ -32,18 +32,7 @@ export class MessageLoader {
|
|
|
32
32
|
* then a request has already been made to load the locale and it is waiting
|
|
33
33
|
* to resolve.
|
|
34
34
|
*/
|
|
35
|
-
_localeLoadingPromises: Record<
|
|
36
|
-
LocaleId,
|
|
37
|
-
{
|
|
38
|
-
/**`true` if this locale has been loaded at least once. */
|
|
39
|
-
initialized: boolean;
|
|
40
|
-
/**
|
|
41
|
-
* If the locale is currently being loaded, this Promise will exist and
|
|
42
|
-
* represent that loading status. Otherwise, this value is undefined.
|
|
43
|
-
*/
|
|
44
|
-
current?: Promise<{ default: MessagesData }> | undefined;
|
|
45
|
-
}
|
|
46
|
-
>;
|
|
35
|
+
_localeLoadingPromises: Record<LocaleId, Promise<{ default: MessagesData }> | undefined>;
|
|
47
36
|
|
|
48
37
|
/**
|
|
49
38
|
* Map of pre-parsed messages, keyed by the message key and locale
|
|
@@ -96,7 +85,7 @@ export class MessageLoader {
|
|
|
96
85
|
this._subscribers = new Set();
|
|
97
86
|
|
|
98
87
|
this._loadLocale(this.defaultLocale);
|
|
99
|
-
this.fallbackMessage = new InternalIntlMessage(
|
|
88
|
+
this.fallbackMessage = new InternalIntlMessage('THIS MESSAGE FAILED TO LOAD', 'en-US');
|
|
100
89
|
|
|
101
90
|
// In cases where hot module replacement is available, set up cache clearing whenever the
|
|
102
91
|
// targets change so that values are always replaced.
|
|
@@ -104,9 +93,9 @@ export class MessageLoader {
|
|
|
104
93
|
if (module.hot) {
|
|
105
94
|
for (const [locale, file] of Object.entries(localeImportMap)) {
|
|
106
95
|
// @ts-expect-error `hot` not defined in types.
|
|
107
|
-
module.hot.accept(file,
|
|
108
|
-
await this._loadLocale(locale);
|
|
96
|
+
module.hot.accept(file, () => {
|
|
109
97
|
this._parseCache.clear();
|
|
98
|
+
this._loadLocale(locale);
|
|
110
99
|
});
|
|
111
100
|
}
|
|
112
101
|
}
|
|
@@ -127,7 +116,9 @@ export class MessageLoader {
|
|
|
127
116
|
get(key: string, locale: LocaleId): InternalIntlMessage {
|
|
128
117
|
const value =
|
|
129
118
|
this.getMessageValue(key, locale) ?? this.getMessageValue(key, this.defaultLocale);
|
|
130
|
-
if (value != null)
|
|
119
|
+
if (value != null) {
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
131
122
|
|
|
132
123
|
// If the message couldn't be found in either the requested nor the default locale, then
|
|
133
124
|
// nothing can be done.
|
|
@@ -158,23 +149,18 @@ export class MessageLoader {
|
|
|
158
149
|
const cachedValue = this._parseCache.get(cacheKey);
|
|
159
150
|
if (cachedValue != null) return cachedValue;
|
|
160
151
|
|
|
161
|
-
// Return early if this locale
|
|
162
|
-
|
|
163
|
-
if (
|
|
164
|
-
!(this._localeLoadingPromises[locale]?.initialized ?? false) ||
|
|
165
|
-
this._localeLoadingPromises[locale]?.current != null
|
|
166
|
-
) {
|
|
152
|
+
// Return early if this locale is still in the process of being loaded.
|
|
153
|
+
if (this._localeLoadingPromises[locale] != null) {
|
|
167
154
|
return undefined;
|
|
168
155
|
}
|
|
169
156
|
|
|
170
157
|
// If not, check whether it's been loaded and trigger a load if not.
|
|
171
158
|
if (this.messages[locale] == null) {
|
|
172
|
-
// Ensure the locale
|
|
159
|
+
// Ensure the locale is loaded, if it is supported
|
|
173
160
|
if (this.supportedLocales.includes(locale)) {
|
|
174
161
|
this._loadLocale(locale);
|
|
175
162
|
}
|
|
176
|
-
|
|
177
|
-
// so return undefined.
|
|
163
|
+
|
|
178
164
|
return undefined;
|
|
179
165
|
}
|
|
180
166
|
|
|
@@ -227,10 +213,10 @@ export class MessageLoader {
|
|
|
227
213
|
// If the locale is already set in `messages`, then it doesn't need to be loaded again.
|
|
228
214
|
if (this.messages[locale] != null) return;
|
|
229
215
|
|
|
230
|
-
const
|
|
231
|
-
this._localeLoadingPromises[locale] =
|
|
232
|
-
this.messages[locale] = (await
|
|
233
|
-
this._localeLoadingPromises[locale]
|
|
216
|
+
const loadingPromise = this.localeImportMap[locale]();
|
|
217
|
+
this._localeLoadingPromises[locale] = loadingPromise;
|
|
218
|
+
this.messages[locale] = (await loadingPromise).default;
|
|
219
|
+
delete this._localeLoadingPromises[locale];
|
|
234
220
|
this.emitChange();
|
|
235
221
|
}
|
|
236
222
|
|
|
@@ -252,65 +238,4 @@ export class MessageLoader {
|
|
|
252
238
|
|
|
253
239
|
return () => this._subscribers.delete(callback);
|
|
254
240
|
}
|
|
255
|
-
|
|
256
|
-
isLocaleLoaded(locale: LocaleId, requireCurrent: boolean = false): boolean {
|
|
257
|
-
const ref = this._localeLoadingPromises[locale];
|
|
258
|
-
// Ensure the locale at least exists and is initialized.
|
|
259
|
-
if (ref == null || ref.initialized == false) return false;
|
|
260
|
-
// `current` will be deleted once the locale has loaded, so if it is null,
|
|
261
|
-
// then the locale data is current.
|
|
262
|
-
if (requireCurrent) return ref.current == null;
|
|
263
|
-
// Otherwise, initialization is enough.
|
|
264
|
-
return true;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
async waitForLocaleLoaded(locale: LocaleId, requireCurrent = false): Promise<void> {
|
|
268
|
-
const ref = this._localeLoadingPromises[locale];
|
|
269
|
-
// If the locale hasn't been loaded at all, kick off the load and return
|
|
270
|
-
// that Promise directly.
|
|
271
|
-
if (ref == null) return this._loadLocale(locale);
|
|
272
|
-
// If initialization is enough for this request, just resolve immediately.
|
|
273
|
-
if (ref.initialized && !requireCurrent) return;
|
|
274
|
-
// Otherwise, check the `current` loading state on the object, and if that
|
|
275
|
-
// doesn't exist, then the locale data is already finished loading, and the
|
|
276
|
-
// containing Promise will just resolve with `undefined`.
|
|
277
|
-
await ref.current;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Returns true if this loader's default locale has finished loading. When
|
|
282
|
-
* true, all messages managed by this loader are guaranteed to have _a_
|
|
283
|
-
* render-able value, even if one does not exist in the current locale.
|
|
284
|
-
*/
|
|
285
|
-
async waitForDefaultLocale(requireCurrent = false): Promise<void> {
|
|
286
|
-
return this.waitForLocaleLoaded(this.defaultLocale, requireCurrent);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const LOADER_REGISTRY: MessageLoader[] = [];
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Returns a new Promise that resolves after all currently-registered message
|
|
294
|
-
* loaders have finished successfully loading their default locale content.
|
|
295
|
-
* Once this Promise has resolved, all messages that currently exist in the
|
|
296
|
-
* application (i.e., within all modules that have been imported or required in
|
|
297
|
-
* the current session) can be guaranteed to have _a_ render-able value.
|
|
298
|
-
*/
|
|
299
|
-
export async function waitForAllDefaultIntlMessagesLoaded(): Promise<void> {
|
|
300
|
-
await Promise.all(LOADER_REGISTRY.map((loader) => loader.waitForDefaultLocale()));
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Create a new MessageLoader, which handles lazily loading messages for
|
|
305
|
-
* different locales and sanity checks as needed to provide accessors for each
|
|
306
|
-
* message defined in `messageKeys`.
|
|
307
|
-
*/
|
|
308
|
-
export function createLoader(
|
|
309
|
-
messageKeys: string[],
|
|
310
|
-
localeImportMap: LocaleImportMap,
|
|
311
|
-
defaultLocale: LocaleId,
|
|
312
|
-
) {
|
|
313
|
-
const loader = new MessageLoader(messageKeys, localeImportMap, defaultLocale);
|
|
314
|
-
LOADER_REGISTRY.push(loader);
|
|
315
|
-
return loader;
|
|
316
241
|
}
|
package/src/message.ts
CHANGED
|
@@ -1,11 +1,44 @@
|
|
|
1
|
-
import { FormatJsNode } from './keyless-json';
|
|
1
|
+
import { FormatJsNode, FormatJsNodeType } from './keyless-json';
|
|
2
2
|
|
|
3
3
|
export class InternalIntlMessage {
|
|
4
4
|
locale: string;
|
|
5
|
+
message?: string;
|
|
5
6
|
ast: FormatJsNode[];
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
/**
|
|
9
|
+
* A stripped-down representation of the message with no rich formatting
|
|
10
|
+
* elements preserved. This will be lazily created the first time it is
|
|
11
|
+
* requested (e.g., by calling `formatToPlainString`).
|
|
12
|
+
*/
|
|
13
|
+
get plainAst(): FormatJsNode[] {
|
|
14
|
+
return (this._plainAst = this._removeRichTags(this.ast));
|
|
15
|
+
}
|
|
16
|
+
_plainAst: FormatJsNode[];
|
|
17
|
+
|
|
18
|
+
constructor(messageOrAst: string | FormatJsNode[], locale: string) {
|
|
8
19
|
this.locale = locale;
|
|
9
|
-
|
|
20
|
+
|
|
21
|
+
if (typeof messageOrAst === 'string') {
|
|
22
|
+
this.message = messageOrAst;
|
|
23
|
+
} else {
|
|
24
|
+
this.ast = messageOrAst;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns the same element with any formatting tags removed. If the element
|
|
30
|
+
* itself is a tag, the children will be hoisted and returned, otherwise the
|
|
31
|
+
* element is returned as an array of itself.
|
|
32
|
+
*/
|
|
33
|
+
private _removeRichTags(nodes: FormatJsNode[]): FormatJsNode[] {
|
|
34
|
+
const result = new Array(nodes.length);
|
|
35
|
+
for (const node of nodes) {
|
|
36
|
+
if (node.type === FormatJsNodeType.Tag) {
|
|
37
|
+
result.push(...this._removeRichTags(node.children));
|
|
38
|
+
} else {
|
|
39
|
+
result.push(node);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
10
43
|
}
|
|
11
44
|
}
|