@lingui/macro 3.10.2 → 3.12.1

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/global.d.ts CHANGED
@@ -1,16 +1,83 @@
1
- declare module '@lingui/macro' {
2
- import type { MessageDescriptor } from "@lingui/core"
1
+ declare module "@lingui/macro" {
2
+ import type { MessageDescriptor, I18n } from "@lingui/core"
3
3
 
4
4
  export type BasicType = {
5
5
  id?: string
6
6
  comment?: string
7
7
  }
8
8
 
9
+ /**
10
+ * Translates a message descriptor
11
+ *
12
+ * @example
13
+ * ```
14
+ * import { t } from "@lingui/macro";
15
+ * const message = t({
16
+ * id: "msg.hello",
17
+ * comment: "Greetings at the homepage",
18
+ * message: `Hello ${name}`,
19
+ * });
20
+ * ```
21
+ *
22
+ * @example
23
+ * ```
24
+ * import { t } from "@lingui/macro";
25
+ * const message = t({
26
+ * id: "msg.plural",
27
+ * message: plural(value, { one: "...", other: "..." }),
28
+ * });
29
+ * ```
30
+ *
31
+ * @param descriptor The message descriptor to translate
32
+ */
33
+ export function t(descriptor: MessageDescriptor): string
34
+
35
+ /**
36
+ * Translates a template string using the global I18n instance
37
+ *
38
+ * @example
39
+ * ```
40
+ * import { t } from "@lingui/macro";
41
+ * const message = t`Hello ${name}`;
42
+ * ```
43
+ */
9
44
  export function t(
10
- literals: TemplateStringsArray | MessageDescriptor,
45
+ literals: TemplateStringsArray,
11
46
  ...placeholders: any[]
12
47
  ): string
13
48
 
49
+ /**
50
+ * Translates a template string or message descriptor using a given I18n instance
51
+ *
52
+ * @example
53
+ * ```
54
+ * import { t } from "@lingui/macro";
55
+ * import { I18n } from "@lingui/core";
56
+ * const i18n = new I18n({
57
+ * locale: "nl",
58
+ * messages: { "Hello {0}": "Hallo {0}" },
59
+ * });
60
+ * const message = t(i18n)`Hello ${name}`;
61
+ * ```
62
+ *
63
+ * @example
64
+ * ```
65
+ * import { t } from "@lingui/macro";
66
+ * import { I18n } from "@lingui/core";
67
+ * const i18n = new I18n({
68
+ * locale: "nl",
69
+ * messages: { "Hello {0}": "Hallo {0}" },
70
+ * });
71
+ * const message = t(i18n)({ message: `Hello ${name}` });
72
+ * ```
73
+ */
74
+ export function t(
75
+ i18n: I18n
76
+ ): {
77
+ (literals: TemplateStringsArray, ...placeholders: any[]): string
78
+ (descriptor: MessageDescriptor): string
79
+ }
80
+
14
81
  export type UnderscoreDigit<T = string> = { [digit: string]: T }
15
82
  export type ChoiceOptions<T = string> = {
16
83
  offset?: number
@@ -21,20 +88,107 @@ declare module '@lingui/macro' {
21
88
  other?: T
22
89
  } & UnderscoreDigit<T>
23
90
 
24
- export function plural(arg: number | string, options: ChoiceOptions & BasicType): string
91
+ /**
92
+ * Pluralize a message
93
+ *
94
+ * @example
95
+ * ```
96
+ * import { plural } from "@lingui/macro";
97
+ * const message = plural(count, {
98
+ * one: "# Book",
99
+ * other: "# Books",
100
+ * });
101
+ * ```
102
+ *
103
+ * @param value Determines the plural form
104
+ * @param options Object with available plural forms
105
+ */
106
+ export function plural(
107
+ value: number | string,
108
+ options: ChoiceOptions & BasicType
109
+ ): string
110
+
111
+ /**
112
+ * Pluralize a message using ordinal forms
113
+ *
114
+ * Similar to `plural` but instead of using cardinal plural forms,
115
+ * it uses ordinal forms.
116
+ *
117
+ * @example
118
+ * ```
119
+ * import { selectOrdinal } from "@lingui/macro";
120
+ * const message = selectOrdinal(count, {
121
+ * one: "1st",
122
+ * two: "2nd",
123
+ * few: "3rd",
124
+ * other: "#th",
125
+ * });
126
+ * ```
127
+ *
128
+ * @param value Determines the plural form
129
+ * @param options Object with available plural forms
130
+ */
25
131
  export function selectOrdinal(
26
- arg: number | string,
132
+ value: number | string,
27
133
  options: ChoiceOptions & BasicType
28
134
  ): string
29
- export function select(arg: string, choices: Record<string, string> & BasicType): string
135
+
136
+ /**
137
+ * Selects a translation based on a value
138
+ *
139
+ * Select works like a switch statement. It will
140
+ * select one of the forms in `options` object which
141
+ * key matches exactly `value`.
142
+ *
143
+ * @example
144
+ * ```
145
+ * import { select } from "@lingui/macro";
146
+ * const message = select(gender, {
147
+ * male: "he",
148
+ * female: "she",
149
+ * other: "they",
150
+ * });
151
+ * ```
152
+ *
153
+ * @param value The key of choices to use
154
+ * @param choices
155
+ */
156
+ export function select(
157
+ value: string,
158
+ choices: Record<string, string> & BasicType
159
+ ): string
160
+
161
+ /**
162
+ * Defines multiple messages for extraction
163
+ */
30
164
  export function defineMessages<M extends Record<string, MessageDescriptor>>(
31
165
  messages: M
32
166
  ): M
33
- export function defineMessage(descriptor: MessageDescriptor): MessageDescriptor
167
+
168
+ /**
169
+ * Define a message for later use
170
+ *
171
+ * `defineMessage` can be used to add comments for translators,
172
+ * or to override the message ID.
173
+ *
174
+ * @example
175
+ * ```
176
+ * import { defineMessage } from "@lingui/macro";
177
+ * const message = defineMessage({
178
+ * comment: "Greetings on the welcome page",
179
+ * message: `Welcome, ${name}!`,
180
+ * });
181
+ * ```
182
+ *
183
+ * @param descriptor The message descriptor
184
+ */
185
+ export function defineMessage(
186
+ descriptor: MessageDescriptor
187
+ ): MessageDescriptor
34
188
 
35
189
  export type ChoiceProps = {
36
190
  value?: string | number
37
- } & ChoiceOptions<string>
191
+ } & ChoiceOptions<string>
38
192
 
39
193
  /**
40
194
  * The types should be changed after this PR is merged
@@ -60,4 +214,4 @@ declare module '@lingui/macro' {
60
214
  export const Plural: any
61
215
  export const Select: any
62
216
  export const SelectOrdinal: any
63
- }
217
+ }
package/index.d.ts CHANGED
@@ -1,12 +1,7 @@
1
1
  import type { ReactElement, ComponentType, ReactNode } from "react"
2
- import type { MessageDescriptor } from "@lingui/core"
2
+ import type { MessageDescriptor, I18n } from "@lingui/core"
3
3
  import type { TransRenderProps } from "@lingui/react"
4
4
 
5
- export function t(
6
- literals: TemplateStringsArray | MessageDescriptor,
7
- ...placeholders: any[]
8
- ): string
9
-
10
5
  export type UnderscoreDigit<T = string> = { [digit: string]: T }
11
6
  export type ChoiceOptions<T = string> = {
12
7
  offset?: number
@@ -17,15 +12,168 @@ export type ChoiceOptions<T = string> = {
17
12
  other?: T
18
13
  } & UnderscoreDigit<T>
19
14
 
20
- export function plural(arg: number | string, options: ChoiceOptions): string
15
+ /**
16
+ * Translates a message descriptor
17
+ *
18
+ * @example
19
+ * ```
20
+ * import { t } from "@lingui/macro";
21
+ * const message = t({
22
+ * id: "msg.hello",
23
+ * comment: "Greetings at the homepage",
24
+ * message: `Hello ${name}`,
25
+ * });
26
+ * ```
27
+ *
28
+ * @example
29
+ * ```
30
+ * import { t } from "@lingui/macro";
31
+ * const message = t({
32
+ * id: "msg.plural",
33
+ * message: plural(value, { one: "...", other: "..." }),
34
+ * });
35
+ * ```
36
+ *
37
+ * @param descriptor The message descriptor to translate
38
+ */
39
+ export function t(descriptor: MessageDescriptor): string
40
+
41
+ /**
42
+ * Translates a template string using the global I18n instance
43
+ *
44
+ * @example
45
+ * ```
46
+ * import { t } from "@lingui/macro";
47
+ * const message = t`Hello ${name}`;
48
+ * ```
49
+ */
50
+ export function t(
51
+ literals: TemplateStringsArray,
52
+ ...placeholders: any[]
53
+ ): string
54
+
55
+ /**
56
+ * Translates a template string or message descriptor using a given I18n instance
57
+ *
58
+ * @example
59
+ * ```
60
+ * import { t } from "@lingui/macro";
61
+ * import { I18n } from "@lingui/core";
62
+ * const i18n = new I18n({
63
+ * locale: "nl",
64
+ * messages: { "Hello {0}": "Hallo {0}" },
65
+ * });
66
+ * const message = t(i18n)`Hello ${name}`;
67
+ * ```
68
+ *
69
+ * @example
70
+ * ```
71
+ * import { t } from "@lingui/macro";
72
+ * import { I18n } from "@lingui/core";
73
+ * const i18n = new I18n({
74
+ * locale: "nl",
75
+ * messages: { "Hello {0}": "Hallo {0}" },
76
+ * });
77
+ * const message = t(i18n)({ message: `Hello ${name}` });
78
+ * ```
79
+ */
80
+ export function t(
81
+ i18n: I18n
82
+ ): {
83
+ (literals: TemplateStringsArray, ...placeholders: any[]): string
84
+ (descriptor: MessageDescriptor): string
85
+ }
86
+
87
+ /**
88
+ * Pluralize a message
89
+ *
90
+ * @example
91
+ * ```
92
+ * import { plural } from "@lingui/macro";
93
+ * const message = plural(count, {
94
+ * one: "# Book",
95
+ * other: "# Books",
96
+ * });
97
+ * ```
98
+ *
99
+ * @param value Determines the plural form
100
+ * @param options Object with available plural forms
101
+ */
102
+ export function plural(value: number | string, options: ChoiceOptions): string
103
+
104
+ /**
105
+ * Pluralize a message using ordinal forms
106
+ *
107
+ * Similar to `plural` but instead of using cardinal plural forms,
108
+ * it uses ordinal forms.
109
+ *
110
+ * @example
111
+ * ```
112
+ * import { selectOrdinal } from "@lingui/macro";
113
+ * const message = selectOrdinal(count, {
114
+ * one: "1st",
115
+ * two: "2nd",
116
+ * few: "3rd",
117
+ * other: "#th",
118
+ * });
119
+ * ```
120
+ *
121
+ * @param value Determines the plural form
122
+ * @param options Object with available plural forms
123
+ */
21
124
  export function selectOrdinal(
22
- arg: number | string,
125
+ value: number | string,
23
126
  options: ChoiceOptions
24
127
  ): string
25
- export function select(arg: string, choices: Record<string, string>): string
128
+
129
+ /**
130
+ * Selects a translation based on a value
131
+ *
132
+ * Select works like a switch statement. It will
133
+ * select one of the forms in `options` object which
134
+ * key matches exactly `value`.
135
+ *
136
+ * @example
137
+ * ```
138
+ * import { select } from "@lingui/macro";
139
+ * const message = select(gender, {
140
+ * male: "he",
141
+ * female: "she",
142
+ * other: "they",
143
+ * });
144
+ * ```
145
+ *
146
+ * @param value The key of choices to use
147
+ * @param choices
148
+ */
149
+ export function select(value: string, choices: ChoiceOptions): string
150
+
151
+ /**
152
+ * Defines multiple messages for extraction
153
+ *
154
+ * @see {@link defineMessage} for more details
155
+ */
26
156
  export function defineMessages<M extends Record<string, MessageDescriptor>>(
27
157
  messages: M
28
158
  ): M
159
+
160
+ /**
161
+ * Define a message for later use
162
+ *
163
+ * `defineMessage` can be used to add comments for translators,
164
+ * or to override the message ID.
165
+ *
166
+ * @example
167
+ * ```
168
+ * import { defineMessage } from "@lingui/macro";
169
+ * const message = defineMessage({
170
+ * comment: "Greetings on the welcome page",
171
+ * message: `Welcome, ${name}!`,
172
+ * });
173
+ * ```
174
+ *
175
+ * @param descriptor The message descriptor
176
+ */
29
177
  export function defineMessage(descriptor: MessageDescriptor): MessageDescriptor
30
178
 
31
179
  export type TransProps = {
package/index.js CHANGED
@@ -55,6 +55,7 @@ function macro(_ref) {
55
55
  babel = _ref.babel;
56
56
  var jsxNodes = [];
57
57
  var jsNodes = [];
58
+ var needsI18nImport = false;
58
59
  Object.keys(references).forEach(function (tagName) {
59
60
  var nodes = references[tagName];
60
61
  var macroType = getMacroType(tagName);
@@ -79,7 +80,7 @@ function macro(_ref) {
79
80
  var macro = new _macroJs.default(babel, {
80
81
  i18nImportName: i18nImportName
81
82
  });
82
- macro.replacePath(path);
83
+ if (macro.replacePath(path)) needsI18nImport = true;
83
84
  });
84
85
  jsxNodes.filter(isRootPath(jsxNodes)).forEach(function (path) {
85
86
  if (alreadyVisited(path)) return;
@@ -87,7 +88,7 @@ function macro(_ref) {
87
88
  macro.replacePath(path);
88
89
  });
89
90
 
90
- if (jsNodes.length) {
91
+ if (needsI18nImport) {
91
92
  addImport(babel, state, i18nImportModule, i18nImportName);
92
93
  }
93
94
 
package/macroJs.js CHANGED
@@ -53,7 +53,7 @@ var MacroJs = /*#__PURE__*/function () {
53
53
  (0, _defineProperty2.default)(this, "types", void 0);
54
54
  (0, _defineProperty2.default)(this, "i18nImportName", void 0);
55
55
  (0, _defineProperty2.default)(this, "_expressionIndex", void 0);
56
- (0, _defineProperty2.default)(this, "replacePathWithMessage", function (path, _ref3) {
56
+ (0, _defineProperty2.default)(this, "replacePathWithMessage", function (path, _ref3, linguiInstance) {
57
57
  var id = _ref3.id,
58
58
  message = _ref3.message,
59
59
  values = _ref3.values,
@@ -87,7 +87,7 @@ var MacroJs = /*#__PURE__*/function () {
87
87
  args.push(_this.types.objectExpression(options));
88
88
  }
89
89
 
90
- var newNode = _this.types.callExpression(_this.types.memberExpression(_this.types.identifier(_this.i18nImportName), _this.types.identifier("_")), args); // preserve line number
90
+ var newNode = _this.types.callExpression(_this.types.memberExpression(linguiInstance !== null && linguiInstance !== void 0 ? linguiInstance : _this.types.identifier(_this.i18nImportName), _this.types.identifier("_")), args); // preserve line number
91
91
 
92
92
 
93
93
  newNode.loc = path.node.loc;
@@ -102,24 +102,60 @@ var MacroJs = /*#__PURE__*/function () {
102
102
  if (_this.isDefineMessage(path.node)) {
103
103
  _this.replaceDefineMessage(path);
104
104
 
105
- return;
105
+ return true;
106
+ } // t(i18nInstance)`Message` -> i18nInstance._('Message')
107
+
108
+
109
+ if (_this.types.isCallExpression(path.node) && _this.types.isTaggedTemplateExpression(path.parentPath.node) && _this.types.isIdentifier(path.node.arguments[0]) && _this.isIdentifier(path.node.callee, "t")) {
110
+ // Use the first argument as i18n instance instead of the default i18n instance
111
+ var i18nInstance = path.node.arguments[0];
112
+
113
+ var _tokens = _this.tokenizeNode(path.parentPath.node);
114
+
115
+ var _messageFormat = new _icu.default();
116
+
117
+ var _messageFormat$fromTo = _messageFormat.fromTokens(_tokens),
118
+ _messageRaw = _messageFormat$fromTo.message,
119
+ _values = _messageFormat$fromTo.values,
120
+ _id = _messageFormat$fromTo.id,
121
+ _comment = _messageFormat$fromTo.comment;
122
+
123
+ var _message = normalizeWhitespace(_messageRaw);
124
+
125
+ _this.replacePathWithMessage(path.parentPath, {
126
+ id: _id,
127
+ message: _message,
128
+ values: _values,
129
+ comment: _comment
130
+ }, i18nInstance);
131
+
132
+ return false;
133
+ } // t(i18nInstance)(messageDescriptor) -> i18nInstance._(messageDescriptor)
134
+
135
+
136
+ if (_this.types.isCallExpression(path.node) && _this.types.isCallExpression(path.parentPath.node) && _this.types.isIdentifier(path.node.arguments[0]) && _this.isIdentifier(path.node.callee, "t")) {
137
+ var _i18nInstance = path.node.arguments[0];
138
+
139
+ _this.replaceTAsFunction(path.parentPath, _i18nInstance);
140
+
141
+ return false;
106
142
  }
107
143
 
108
144
  if (_this.types.isCallExpression(path.node) && _this.isIdentifier(path.node.callee, "t")) {
109
145
  _this.replaceTAsFunction(path);
110
146
 
111
- return;
147
+ return true;
112
148
  }
113
149
 
114
150
  var tokens = _this.tokenizeNode(path.node);
115
151
 
116
152
  var messageFormat = new _icu.default();
117
153
 
118
- var _messageFormat$fromTo = messageFormat.fromTokens(tokens),
119
- messageRaw = _messageFormat$fromTo.message,
120
- values = _messageFormat$fromTo.values,
121
- id = _messageFormat$fromTo.id,
122
- comment = _messageFormat$fromTo.comment;
154
+ var _messageFormat$fromTo2 = messageFormat.fromTokens(tokens),
155
+ messageRaw = _messageFormat$fromTo2.message,
156
+ values = _messageFormat$fromTo2.values,
157
+ id = _messageFormat$fromTo2.id,
158
+ comment = _messageFormat$fromTo2.comment;
123
159
 
124
160
  var message = normalizeWhitespace(messageRaw);
125
161
 
@@ -129,6 +165,8 @@ var MacroJs = /*#__PURE__*/function () {
129
165
  values: values,
130
166
  comment: comment
131
167
  });
168
+
169
+ return true;
132
170
  });
133
171
  (0, _defineProperty2.default)(this, "replaceDefineMessage", function (path) {
134
172
  // reset the expression counter
@@ -138,10 +176,10 @@ var MacroJs = /*#__PURE__*/function () {
138
176
 
139
177
  path.replaceWith(descriptor);
140
178
  });
141
- (0, _defineProperty2.default)(this, "replaceTAsFunction", function (path) {
179
+ (0, _defineProperty2.default)(this, "replaceTAsFunction", function (path, linguiInstance) {
142
180
  var descriptor = _this.processDescriptor(path.node.arguments[0]);
143
181
 
144
- var newNode = _this.types.callExpression(_this.types.memberExpression(_this.types.identifier(_this.i18nImportName), _this.types.identifier("_")), [descriptor]);
182
+ var newNode = _this.types.callExpression(_this.types.memberExpression(linguiInstance !== null && linguiInstance !== void 0 ? linguiInstance : _this.types.identifier(_this.i18nImportName), _this.types.identifier("_")), [descriptor]);
145
183
 
146
184
  path.replaceWith(newNode);
147
185
  });
@@ -166,9 +204,9 @@ var MacroJs = /*#__PURE__*/function () {
166
204
  if (tokens != null) {
167
205
  var messageFormat = new _icu.default();
168
206
 
169
- var _messageFormat$fromTo2 = messageFormat.fromTokens(tokens),
170
- messageRaw = _messageFormat$fromTo2.message,
171
- values = _messageFormat$fromTo2.values;
207
+ var _messageFormat$fromTo3 = messageFormat.fromTokens(tokens),
208
+ messageRaw = _messageFormat$fromTo3.message,
209
+ values = _messageFormat$fromTo3.values;
172
210
 
173
211
  var message = normalizeWhitespace(messageRaw);
174
212
  messageNode = _this.types.stringLiteral(message);
@@ -210,7 +248,9 @@ var MacroJs = /*#__PURE__*/function () {
210
248
  quasis: R.map(function (text) {
211
249
  // Don't output tokens without text.
212
250
  // if it's an unicode we keep the cooked value because it's the parsed value by babel (without unicode chars)
213
- var value = /\\u[a-fA-F0-9]{4}/g.test(text.value.raw) ? text.value.cooked : text.value.raw;
251
+ // This regex will detect if a string contains unicode chars, when they're we should interpolate them
252
+ // why? because platforms like react native doesn't parse them, just doing a JSON.parse makes them UTF-8 friendly
253
+ var value = /\\u[a-fA-F0-9]{4}|\\x[a-fA-F0-9]{2}/g.test(text.value.raw) ? text.value.cooked : text.value.raw;
214
254
  if (value === "") return null;
215
255
  return {
216
256
  type: "text",
package/macroJsx.js CHANGED
@@ -193,8 +193,10 @@ var MacroJSX = /*#__PURE__*/function () {
193
193
  var tokenize = R.pipe( // Don"t output tokens without text.
194
194
  R.evolve({
195
195
  quasis: R.map(function (text) {
196
- // Don"t output tokens without text.
197
- var value = /\\u[a-fA-F0-9]{4}/g.test(text.value.raw) ? text.value.cooked : text.value.raw;
196
+ // if it's an unicode we keep the cooked value because it's the parsed value by babel (without unicode chars)
197
+ // This regex will detect if a string contains unicode chars, when they're we should interpolate them
198
+ // why? because platforms like react native doesn't parse them, just doing a JSON.parse makes them UTF-8 friendly
199
+ var value = /\\u[a-fA-F0-9]{4}|\\x[a-fA-F0-9]{2}/g.test(text.value.raw) ? text.value.cooked : text.value.raw;
198
200
  if (value === "") return null;
199
201
  return _this.tokenizeText(_this.clearBackslashes(value));
200
202
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingui/macro",
3
- "version": "3.10.2",
3
+ "version": "3.12.1",
4
4
  "description": "Macro for generating messages in ICU MessageFormat syntax",
5
5
  "main": "index.js",
6
6
  "author": {
@@ -30,7 +30,7 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@babel/runtime": "^7.11.2",
33
- "@lingui/conf": "^3.10.2",
33
+ "@lingui/conf": "^3.12.1",
34
34
  "ramda": "^0.27.1"
35
35
  },
36
36
  "peerDependencies": {