@discord/intl 0.10.0-rc.4 → 0.10.2

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 CHANGED
@@ -35,7 +35,7 @@ class FormatBuilder {
35
35
  }
36
36
  exports.FormatBuilder = FormatBuilder;
37
37
  function bindFormatValuesWithBuilder(builder, nodes, locales, formatters, formatConfig, values = {}, currentPluralValue, originalMessage) {
38
- var _a, _b;
38
+ var _a;
39
39
  // Hot path for static messages that are just parsed as a single string element.
40
40
  if (nodes.length === 1 && typeof nodes[0] === 'string') {
41
41
  builder.pushLiteralText(nodes[0]);
@@ -146,17 +146,16 @@ function bindFormatValuesWithBuilder(builder, nodes, locales, formatters, format
146
146
  break;
147
147
  }
148
148
  case intl_ast_1.FormatJsNodeType.Select: {
149
- const value = node[1 /* AstNodeIndices.Value */];
149
+ const requestedOption = value;
150
150
  const options = node[2 /* AstNodeIndices.Options */];
151
- const option = value in options ? options[value] : options.other;
151
+ const option = requestedOption in options ? options[requestedOption] : options.other;
152
152
  if (option == null) {
153
- throw `${value} is not a known option for select value ${variableName}. Valid options are ${Object.keys(options).join(', ')}`;
153
+ throw `${requestedOption} is not a known option for select value ${variableName}. Valid options are ${Object.keys(options).join(', ')}`;
154
154
  }
155
155
  bindFormatValuesWithBuilder(builder, option, locales, formatters, formatConfig, values);
156
156
  break;
157
157
  }
158
158
  case intl_ast_1.FormatJsNodeType.Plural: {
159
- const value = node[1 /* AstNodeIndices.Value */];
160
159
  const options = node[2 /* AstNodeIndices.Options */];
161
160
  const offset = node[3 /* AstNodeIndices.Offset */];
162
161
  const pluralType = node[4 /* AstNodeIndices.PluralType */];
@@ -175,8 +174,8 @@ function bindFormatValuesWithBuilder(builder, nodes, locales, formatters, format
175
174
  throw `${value} is not a known option for plural value ${variableName}. Valid options are ${Object.keys(options).join(', ')}`;
176
175
  }
177
176
  bindFormatValuesWithBuilder(builder, option, locales, formatters, formatConfig, values,
178
- // @ts-expect-error assert this `as number` properly.
179
- value - ((_b = node.offset) !== null && _b !== void 0 ? _b : 0));
177
+ // @ts-expect-error assert this `as number` properly
178
+ value - (offset !== null && offset !== void 0 ? offset : 0));
180
179
  break;
181
180
  }
182
181
  }
@@ -2,17 +2,12 @@ import { AstNode, FullFormatJsNode } from '@discord/intl-ast';
2
2
  import { InternalIntlMessage } from './message';
3
3
  /**
4
4
  * Type representing the serialized content of a translations file, which is a record of hashed
5
- * message keys to their AST structure. This type represents both compressed, keyless AstNodes as
6
- * well as fully-typed, object FullFormatJsNodes as the message content, since either can be given
7
- * depending on the configuration of the bundler/compiler.
5
+ * message keys to their AST structure. This type represents both compressed, keyless AstNodes and
6
+ * fully-typed, object FullFormatJsNodes as the message content, since either can be given depending
7
+ * on the configuration of the bundler/compiler.
8
8
  */
9
9
  type MessagesData = Record<string, AstNode[] | FullFormatJsNode[]>;
10
- export interface IntlMessageGetterAdditions {
11
- onChange(callback: () => void): () => void;
12
- }
13
- export interface IntlMessageGetter extends IntlMessageGetterAdditions {
14
- (locale: LocaleId): InternalIntlMessage;
15
- }
10
+ export type IntlMessageGetter = (this: MessageLoader, locale: LocaleId) => InternalIntlMessage;
16
11
  export type LocaleId = string;
17
12
  export type LocaleImportMap = Record<LocaleId, () => Promise<{
18
13
  default: MessagesData;
@@ -103,6 +98,13 @@ export declare class MessageLoader {
103
98
  * for `get` with the that key as the first argument, allowing consumers to
104
99
  * just call the function with a locale to retrieve the translated message
105
100
  * for that key.
101
+ *
102
+ * This method is provided as a way to generate binds _at runtime_, but for
103
+ * very-large messages files (e.g., thousands of messages), this can be a
104
+ * non-negligible cost. Where feasible, consider generating these binds
105
+ * at build/bundle time, especially in cases where they can be substantially
106
+ * minified (i.e., Hermes bytecode). This is provided automatically as an
107
+ * option when using one of `@discord/intl`'s transformers.
106
108
  */
107
109
  getBinds(): Record<string, IntlMessageGetter>;
108
110
  _loadLocale(locale: LocaleId): Promise<void>;
@@ -105,14 +105,18 @@ class MessageLoader {
105
105
  * for `get` with the that key as the first argument, allowing consumers to
106
106
  * just call the function with a locale to retrieve the translated message
107
107
  * for that key.
108
+ *
109
+ * This method is provided as a way to generate binds _at runtime_, but for
110
+ * very-large messages files (e.g., thousands of messages), this can be a
111
+ * non-negligible cost. Where feasible, consider generating these binds
112
+ * at build/bundle time, especially in cases where they can be substantially
113
+ * minified (i.e., Hermes bytecode). This is provided automatically as an
114
+ * option when using one of `@discord/intl`'s transformers.
108
115
  */
109
116
  getBinds() {
110
- const onChange = this.onChange.bind(this);
111
117
  const result = {};
112
118
  for (const key of this.messageKeys) {
113
- const bound = (locale) => this.get(key, locale);
114
- bound.onChange = onChange;
115
- result[key] = bound;
119
+ result[key] = this.get.bind(this, key);
116
120
  }
117
121
  return result;
118
122
  }
package/dist/types.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { InternalIntlMessage } from './message';
2
- import type { IntlMessageGetterAdditions } from './message-loader';
3
2
  import { FormatBuilderConstructor } from './format';
4
3
 
5
4
  /**
@@ -42,7 +41,7 @@ export type IntlTime = string | number | Date | null | undefined;
42
41
  export type PlainIntlMessage = string;
43
42
  export type AnyIntlMessage = PlainIntlMessage | InternalIntlMessage;
44
43
 
45
- export interface IntlMessageGetter extends IntlMessageGetterAdditions {
44
+ export interface IntlMessageGetter {
46
45
  (locale: string): InternalIntlMessage | PlainIntlMessage;
47
46
  }
48
47
 
@@ -52,8 +51,7 @@ export interface IntlMessageGetter extends IntlMessageGetterAdditions {
52
51
  * value types that are required to format the message, or `{}` to represent
53
52
  * that there are no values required and the message is a plain string.
54
53
  */
55
- export interface TypedIntlMessageGetter<FormatValues extends object>
56
- extends IntlMessageGetterAdditions {
54
+ export interface TypedIntlMessageGetter<FormatValues extends object> {
57
55
  // TODO: This is lossy and unfortunate that typing can't be propagated
58
56
  // to the returned message type, but doing so causes problems with
59
57
  // contravariance of the type. When returning a message getter from a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@discord/intl",
3
- "version": "0.10.0-rc.4",
3
+ "version": "0.10.2",
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.10.0-rc.4"
22
+ "@discord/intl-ast": "0.10.2"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@swc/cli": "^0.3.12",
package/src/format.ts CHANGED
@@ -192,18 +192,17 @@ export function bindFormatValuesWithBuilder<T, Builder extends FormatBuilder<T>>
192
192
  }
193
193
 
194
194
  case FormatJsNodeType.Select: {
195
- const value = node[AstNodeIndices.Value];
195
+ const requestedOption = value as string;
196
196
  const options = node[AstNodeIndices.Options];
197
- const option = value in options ? options[value] : options.other;
197
+ const option = requestedOption in options ? options[requestedOption] : options.other;
198
198
  if (option == null) {
199
- throw `${value} is not a known option for select value ${variableName}. Valid options are ${Object.keys(options).join(', ')}`;
199
+ throw `${requestedOption} is not a known option for select value ${variableName}. Valid options are ${Object.keys(options).join(', ')}`;
200
200
  }
201
201
  bindFormatValuesWithBuilder(builder, option, locales, formatters, formatConfig, values);
202
202
  break;
203
203
  }
204
204
 
205
205
  case FormatJsNodeType.Plural: {
206
- const value = node[AstNodeIndices.Value];
207
206
  const options = node[AstNodeIndices.Options];
208
207
  const offset = node[AstNodeIndices.Offset];
209
208
  const pluralType = node[AstNodeIndices.PluralType];
@@ -227,8 +226,8 @@ export function bindFormatValuesWithBuilder<T, Builder extends FormatBuilder<T>>
227
226
  formatters,
228
227
  formatConfig,
229
228
  values,
230
- // @ts-expect-error assert this `as number` properly.
231
- (value as number) - (node.offset ?? 0),
229
+ // @ts-expect-error assert this `as number` properly
230
+ (value as number) - (offset ?? 0),
232
231
  );
233
232
  break;
234
233
  }
@@ -3,18 +3,13 @@ import { InternalIntlMessage } from './message';
3
3
 
4
4
  /**
5
5
  * Type representing the serialized content of a translations file, which is a record of hashed
6
- * message keys to their AST structure. This type represents both compressed, keyless AstNodes as
7
- * well as fully-typed, object FullFormatJsNodes as the message content, since either can be given
8
- * depending on the configuration of the bundler/compiler.
6
+ * message keys to their AST structure. This type represents both compressed, keyless AstNodes and
7
+ * fully-typed, object FullFormatJsNodes as the message content, since either can be given depending
8
+ * on the configuration of the bundler/compiler.
9
9
  */
10
10
  type MessagesData = Record<string, AstNode[] | FullFormatJsNode[]>;
11
- export interface IntlMessageGetterAdditions {
12
- onChange(callback: () => void): () => void;
13
- }
14
11
 
15
- export interface IntlMessageGetter extends IntlMessageGetterAdditions {
16
- (locale: LocaleId): InternalIntlMessage;
17
- }
12
+ export type IntlMessageGetter = (this: MessageLoader, locale: LocaleId) => InternalIntlMessage;
18
13
 
19
14
  export type LocaleId = string;
20
15
 
@@ -191,14 +186,18 @@ export class MessageLoader {
191
186
  * for `get` with the that key as the first argument, allowing consumers to
192
187
  * just call the function with a locale to retrieve the translated message
193
188
  * for that key.
189
+ *
190
+ * This method is provided as a way to generate binds _at runtime_, but for
191
+ * very-large messages files (e.g., thousands of messages), this can be a
192
+ * non-negligible cost. Where feasible, consider generating these binds
193
+ * at build/bundle time, especially in cases where they can be substantially
194
+ * minified (i.e., Hermes bytecode). This is provided automatically as an
195
+ * option when using one of `@discord/intl`'s transformers.
194
196
  */
195
197
  getBinds(): Record<string, IntlMessageGetter> {
196
- const onChange = this.onChange.bind(this);
197
198
  const result: Record<string, IntlMessageGetter> = {};
198
199
  for (const key of this.messageKeys) {
199
- const bound = (locale: LocaleId) => this.get(key, locale);
200
- bound.onChange = onChange;
201
- result[key] = bound;
200
+ result[key] = this.get.bind(this, key);
202
201
  }
203
202
 
204
203
  return result;
package/src/types.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { InternalIntlMessage } from './message';
2
- import type { IntlMessageGetterAdditions } from './message-loader';
3
2
  import { FormatBuilderConstructor } from './format';
4
3
 
5
4
  /**
@@ -42,7 +41,7 @@ export type IntlTime = string | number | Date | null | undefined;
42
41
  export type PlainIntlMessage = string;
43
42
  export type AnyIntlMessage = PlainIntlMessage | InternalIntlMessage;
44
43
 
45
- export interface IntlMessageGetter extends IntlMessageGetterAdditions {
44
+ export interface IntlMessageGetter {
46
45
  (locale: string): InternalIntlMessage | PlainIntlMessage;
47
46
  }
48
47
 
@@ -52,8 +51,7 @@ export interface IntlMessageGetter extends IntlMessageGetterAdditions {
52
51
  * value types that are required to format the message, or `{}` to represent
53
52
  * that there are no values required and the message is a plain string.
54
53
  */
55
- export interface TypedIntlMessageGetter<FormatValues extends object>
56
- extends IntlMessageGetterAdditions {
54
+ export interface TypedIntlMessageGetter<FormatValues extends object> {
57
55
  // TODO: This is lossy and unfortunate that typing can't be propagated
58
56
  // to the returned message type, but doing so causes problems with
59
57
  // contravariance of the type. When returning a message getter from a