@lingui/macro 3.17.2 → 4.0.0-next.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/build/global.d.ts +2 -0
- package/build/index.d.ts +131 -42
- package/build/index.js +57 -49
- package/build/macroJs.js +127 -99
- package/build/macroJsx.js +136 -116
- package/build/utils.js +0 -11
- package/index.d.ts +297 -0
- package/package.json +24 -9
- package/CHANGELOG.md +0 -449
package/build/global.d.ts
CHANGED
package/build/index.d.ts
CHANGED
|
@@ -1,16 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
import type {
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
import type { ReactElement, ReactNode, VFC, FC } from "react"
|
|
3
|
+
import type { I18n, MessageDescriptor } from "@lingui/core"
|
|
3
4
|
import type { TransRenderProps } from "@lingui/react"
|
|
4
5
|
|
|
5
|
-
export type
|
|
6
|
-
|
|
6
|
+
export type ChoiceOptions = {
|
|
7
|
+
/** Offset of value when calculating plural forms */
|
|
7
8
|
offset?: number
|
|
8
|
-
zero?:
|
|
9
|
-
one?:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
zero?: string
|
|
10
|
+
one?: string
|
|
11
|
+
two?: string
|
|
12
|
+
few?: string
|
|
13
|
+
many?: string
|
|
14
|
+
|
|
15
|
+
/** Catch-all option */
|
|
16
|
+
other?: string
|
|
17
|
+
/** Exact match form, corresponds to =N rule */
|
|
18
|
+
[digit: `${number}`]: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type MacroMessageDescriptor = (
|
|
22
|
+
| {
|
|
23
|
+
id: string
|
|
24
|
+
message?: string
|
|
25
|
+
}
|
|
26
|
+
| {
|
|
27
|
+
id?: string
|
|
28
|
+
message: string
|
|
29
|
+
}
|
|
30
|
+
) & {
|
|
31
|
+
comment?: string
|
|
32
|
+
context?: string
|
|
33
|
+
}
|
|
14
34
|
|
|
15
35
|
/**
|
|
16
36
|
* Translates a message descriptor
|
|
@@ -36,7 +56,7 @@ export type ChoiceOptions<T = string> = {
|
|
|
36
56
|
*
|
|
37
57
|
* @param descriptor The message descriptor to translate
|
|
38
58
|
*/
|
|
39
|
-
export function t(descriptor:
|
|
59
|
+
export function t(descriptor: MacroMessageDescriptor): string
|
|
40
60
|
|
|
41
61
|
/**
|
|
42
62
|
* Translates a template string using the global I18n instance
|
|
@@ -79,7 +99,7 @@ export function t(
|
|
|
79
99
|
*/
|
|
80
100
|
export function t(i18n: I18n): {
|
|
81
101
|
(literals: TemplateStringsArray, ...placeholders: any[]): string
|
|
82
|
-
(descriptor:
|
|
102
|
+
(descriptor: MacroMessageDescriptor): string
|
|
83
103
|
}
|
|
84
104
|
|
|
85
105
|
/**
|
|
@@ -124,6 +144,12 @@ export function selectOrdinal(
|
|
|
124
144
|
options: ChoiceOptions
|
|
125
145
|
): string
|
|
126
146
|
|
|
147
|
+
type SelectOptions = {
|
|
148
|
+
/** Catch-all option */
|
|
149
|
+
other: string
|
|
150
|
+
[matches: string]: string
|
|
151
|
+
}
|
|
152
|
+
|
|
127
153
|
/**
|
|
128
154
|
* Selects a translation based on a value
|
|
129
155
|
*
|
|
@@ -144,7 +170,7 @@ export function selectOrdinal(
|
|
|
144
170
|
* @param value The key of choices to use
|
|
145
171
|
* @param choices
|
|
146
172
|
*/
|
|
147
|
-
export function select(value: string, choices:
|
|
173
|
+
export function select(value: string, choices: SelectOptions): string
|
|
148
174
|
|
|
149
175
|
/**
|
|
150
176
|
* Define a message for later use
|
|
@@ -163,46 +189,109 @@ export function select(value: string, choices: ChoiceOptions): string
|
|
|
163
189
|
*
|
|
164
190
|
* @param descriptor The message descriptor
|
|
165
191
|
*/
|
|
166
|
-
export function defineMessage(
|
|
192
|
+
export function defineMessage(
|
|
193
|
+
descriptor: MacroMessageDescriptor
|
|
194
|
+
): MessageDescriptor
|
|
167
195
|
|
|
168
|
-
|
|
196
|
+
type CommonProps = {
|
|
169
197
|
id?: string
|
|
170
198
|
comment?: string
|
|
171
|
-
values?: Record<string, unknown>
|
|
172
199
|
context?: string
|
|
173
|
-
children?: React.ReactNode
|
|
174
|
-
component?: React.ComponentType<TransRenderProps>
|
|
175
200
|
render?: (props: TransRenderProps) => ReactElement<any, any> | null
|
|
176
201
|
i18n?: I18n
|
|
177
202
|
}
|
|
178
203
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
} &
|
|
182
|
-
|
|
204
|
+
type TransProps = {
|
|
205
|
+
children: ReactNode
|
|
206
|
+
} & CommonProps
|
|
207
|
+
|
|
208
|
+
type PluralChoiceProps = {
|
|
209
|
+
value: string | number
|
|
210
|
+
/** Offset of value when calculating plural forms */
|
|
211
|
+
offset?: number
|
|
212
|
+
zero?: ReactNode
|
|
213
|
+
one?: ReactNode
|
|
214
|
+
two?: ReactNode
|
|
215
|
+
few?: ReactNode
|
|
216
|
+
many?: ReactNode
|
|
217
|
+
|
|
218
|
+
/** Catch-all option */
|
|
219
|
+
other: ReactNode
|
|
220
|
+
/** Exact match form, corresponds to =N rule */
|
|
221
|
+
[digit: `_${number}`]: ReactNode
|
|
222
|
+
} & CommonProps
|
|
223
|
+
|
|
224
|
+
type SelectChoiceProps = {
|
|
225
|
+
value: string
|
|
226
|
+
/** Catch-all option */
|
|
227
|
+
other: ReactNode
|
|
228
|
+
[option: `_${string}`]: ReactNode
|
|
229
|
+
} & CommonProps
|
|
183
230
|
|
|
184
231
|
/**
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* then we should be able to specify that key of values is same type as value.
|
|
189
|
-
* We would be able to remove separate type Values = {...} definition
|
|
190
|
-
* eg.
|
|
191
|
-
* type SelectProps<Values> = {
|
|
192
|
-
* value?: Values
|
|
193
|
-
* [key: Values]: string
|
|
194
|
-
* }
|
|
232
|
+
* Trans is the basic macro for static messages,
|
|
233
|
+
* messages with variables, but also for messages with inline markup
|
|
195
234
|
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```
|
|
237
|
+
* <Trans>Hello {username}. Read the <a href="/docs">docs</a>.</Trans>
|
|
238
|
+
* ```
|
|
239
|
+
* @example
|
|
240
|
+
* ```
|
|
241
|
+
* <Trans id="custom.id">Hello {username}.</Trans>
|
|
242
|
+
* ```
|
|
196
243
|
*/
|
|
197
|
-
|
|
244
|
+
export const Trans: FC<TransProps>
|
|
198
245
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Props of Plural macro are transformed into plural format.
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```
|
|
251
|
+
* import { Plural } from "@lingui/macro"
|
|
252
|
+
* <Plural value={numBooks} one="Book" other="Books" />
|
|
253
|
+
*
|
|
254
|
+
* // ↓ ↓ ↓ ↓ ↓ ↓
|
|
255
|
+
* import { Trans } from "@lingui/react"
|
|
256
|
+
* <Trans id="{numBooks, plural, one {Book} other {Books}}" values={{ numBooks }} />
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
export const Plural: VFC<PluralChoiceProps>
|
|
260
|
+
/**
|
|
261
|
+
* Props of SelectOrdinal macro are transformed into selectOrdinal format.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```
|
|
265
|
+
* // count == 1 -> 1st
|
|
266
|
+
* // count == 2 -> 2nd
|
|
267
|
+
* // count == 3 -> 3rd
|
|
268
|
+
* // count == 4 -> 4th
|
|
269
|
+
* <SelectOrdinal
|
|
270
|
+
* value={count}
|
|
271
|
+
* one="#st"
|
|
272
|
+
* two="#nd"
|
|
273
|
+
* few="#rd"
|
|
274
|
+
* other="#th"
|
|
275
|
+
* />
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
export const SelectOrdinal: VFC<PluralChoiceProps>
|
|
204
279
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
280
|
+
/**
|
|
281
|
+
* Props of Select macro are transformed into select format
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```
|
|
285
|
+
* // gender == "female" -> Her book
|
|
286
|
+
* // gender == "male" -> His book
|
|
287
|
+
* // gender == "non-binary" -> Their book
|
|
288
|
+
*
|
|
289
|
+
* <Select
|
|
290
|
+
* value={gender}
|
|
291
|
+
* _male="His book"
|
|
292
|
+
* _female="Her book"
|
|
293
|
+
* other="Their book"
|
|
294
|
+
* />
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
297
|
+
export const Select: VFC<SelectChoiceProps>
|
package/build/index.js
CHANGED
|
@@ -10,74 +10,80 @@ var _macroJs = _interopRequireDefault(require("./macroJs"));
|
|
|
10
10
|
var _macroJsx = _interopRequireDefault(require("./macroJsx"));
|
|
11
11
|
var _types = require("@babel/types");
|
|
12
12
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
const config = (0, _conf.getConfig)({
|
|
14
|
-
configPath: process.env.LINGUI_CONFIG
|
|
15
|
-
});
|
|
16
|
-
const getSymbolSource = name => {
|
|
17
|
-
if (Array.isArray(config.runtimeConfigModule)) {
|
|
18
|
-
if (name === "i18n") {
|
|
19
|
-
return config.runtimeConfigModule;
|
|
20
|
-
} else {
|
|
21
|
-
return ["@lingui/react", name];
|
|
22
|
-
}
|
|
23
|
-
} else {
|
|
24
|
-
if (config.runtimeConfigModule[name]) {
|
|
25
|
-
return config.runtimeConfigModule[name];
|
|
26
|
-
} else {
|
|
27
|
-
return ["@lingui/react", name];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
const [i18nImportModule, i18nImportName = "i18n"] = getSymbolSource("i18n");
|
|
32
|
-
const [TransImportModule, TransImportName = "Trans"] = getSymbolSource("Trans");
|
|
33
13
|
const jsMacroTags = new Set(["defineMessage", "arg", "t", "plural", "select", "selectOrdinal"]);
|
|
34
14
|
const jsxMacroTags = new Set(["Trans", "Plural", "Select", "SelectOrdinal"]);
|
|
15
|
+
let config;
|
|
16
|
+
function getConfig(_config) {
|
|
17
|
+
if (_config) {
|
|
18
|
+
config = _config;
|
|
19
|
+
}
|
|
20
|
+
if (!config) {
|
|
21
|
+
config = (0, _conf.getConfig)();
|
|
22
|
+
}
|
|
23
|
+
return config;
|
|
24
|
+
}
|
|
35
25
|
function macro({
|
|
36
26
|
references,
|
|
37
27
|
state,
|
|
38
|
-
babel
|
|
28
|
+
babel,
|
|
29
|
+
config
|
|
39
30
|
}) {
|
|
40
|
-
const
|
|
41
|
-
const
|
|
31
|
+
const opts = config;
|
|
32
|
+
const {
|
|
33
|
+
i18nImportModule,
|
|
34
|
+
i18nImportName,
|
|
35
|
+
TransImportModule,
|
|
36
|
+
TransImportName
|
|
37
|
+
} = getConfig(opts.linguiConfig).runtimeConfigModule;
|
|
38
|
+
const jsxNodes = new Set();
|
|
39
|
+
const jsNodes = new Set();
|
|
42
40
|
let needsI18nImport = false;
|
|
41
|
+
let nameMap = new Map();
|
|
43
42
|
Object.keys(references).forEach(tagName => {
|
|
44
43
|
const nodes = references[tagName];
|
|
45
44
|
if (jsMacroTags.has(tagName)) {
|
|
46
|
-
nodes.forEach(
|
|
47
|
-
|
|
45
|
+
nodes.forEach(path => {
|
|
46
|
+
nameMap.set(tagName, path.node.name);
|
|
47
|
+
jsNodes.add(path.parentPath);
|
|
48
48
|
});
|
|
49
49
|
} else if (jsxMacroTags.has(tagName)) {
|
|
50
|
-
nodes.
|
|
50
|
+
// babel-plugin-macros return JSXIdentifier nodes.
|
|
51
|
+
// Which is for every JSX element would be presented twice (opening / close)
|
|
52
|
+
// Here we're taking JSXElement and dedupe it.
|
|
53
|
+
nodes.forEach(path => {
|
|
54
|
+
nameMap.set(tagName, path.node.name);
|
|
55
|
+
|
|
51
56
|
// identifier.openingElement.jsxElement
|
|
52
|
-
jsxNodes.
|
|
57
|
+
jsxNodes.add(path.parentPath.parentPath);
|
|
53
58
|
});
|
|
54
59
|
} else {
|
|
55
60
|
throw nodes[0].buildCodeFrameError(`Unknown macro ${tagName}`);
|
|
56
61
|
}
|
|
57
62
|
});
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
const stripNonEssentialProps = process.env.NODE_ENV == "production" && !opts.extract;
|
|
64
|
+
const jsNodesArray = Array.from(jsNodes);
|
|
65
|
+
jsNodesArray.filter(isRootPath(jsNodesArray)).forEach(path => {
|
|
60
66
|
const macro = new _macroJs.default(babel, {
|
|
61
|
-
i18nImportName
|
|
67
|
+
i18nImportName,
|
|
68
|
+
stripNonEssentialProps,
|
|
69
|
+
nameMap
|
|
62
70
|
});
|
|
63
71
|
if (macro.replacePath(path)) needsI18nImport = true;
|
|
64
72
|
});
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const macro = new _macroJsx.default(babel
|
|
73
|
+
const jsxNodesArray = Array.from(jsxNodes);
|
|
74
|
+
jsxNodesArray.filter(isRootPath(jsxNodesArray)).forEach(path => {
|
|
75
|
+
const macro = new _macroJsx.default(babel, {
|
|
76
|
+
stripNonEssentialProps,
|
|
77
|
+
nameMap
|
|
78
|
+
});
|
|
68
79
|
macro.replacePath(path);
|
|
69
80
|
});
|
|
70
81
|
if (needsI18nImport) {
|
|
71
82
|
addImport(babel, state, i18nImportModule, i18nImportName);
|
|
72
83
|
}
|
|
73
|
-
if (jsxNodes.
|
|
84
|
+
if (jsxNodes.size) {
|
|
74
85
|
addImport(babel, state, TransImportModule, TransImportName);
|
|
75
86
|
}
|
|
76
|
-
if (process.env.LINGUI_EXTRACT === "1") {
|
|
77
|
-
return {
|
|
78
|
-
keepImports: true
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
87
|
}
|
|
82
88
|
function addImport(babel, state, module, importName) {
|
|
83
89
|
const {
|
|
@@ -98,6 +104,14 @@ function addImport(babel, state, module, importName) {
|
|
|
98
104
|
state.file.path.node.body.unshift(t.importDeclaration([t.importSpecifier(tIdentifier, tIdentifier)], t.stringLiteral(module)));
|
|
99
105
|
}
|
|
100
106
|
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Filtering nested macro calls
|
|
110
|
+
*
|
|
111
|
+
* <Macro>
|
|
112
|
+
* <Macro /> <-- this would be filtered out
|
|
113
|
+
* </Macro>
|
|
114
|
+
*/
|
|
101
115
|
function isRootPath(allPath) {
|
|
102
116
|
return node => function traverse(path) {
|
|
103
117
|
if (!path.parentPath) {
|
|
@@ -107,15 +121,7 @@ function isRootPath(allPath) {
|
|
|
107
121
|
}
|
|
108
122
|
}(node);
|
|
109
123
|
}
|
|
110
|
-
|
|
111
|
-
const alreadyVisited = path => {
|
|
112
|
-
if (alreadyVisitedCache.has(path)) {
|
|
113
|
-
return true;
|
|
114
|
-
} else {
|
|
115
|
-
alreadyVisitedCache.add(path);
|
|
116
|
-
return false;
|
|
117
|
-
}
|
|
118
|
-
};
|
|
124
|
+
;
|
|
119
125
|
[...jsMacroTags, ...jsxMacroTags].forEach(name => {
|
|
120
126
|
Object.defineProperty(module.exports, name, {
|
|
121
127
|
get() {
|
|
@@ -123,5 +129,7 @@ const alreadyVisited = path => {
|
|
|
123
129
|
}
|
|
124
130
|
});
|
|
125
131
|
});
|
|
126
|
-
var _default = (0, _babelPluginMacros.createMacro)(macro
|
|
132
|
+
var _default = (0, _babelPluginMacros.createMacro)(macro, {
|
|
133
|
+
configName: "lingui"
|
|
134
|
+
});
|
|
127
135
|
exports.default = _default;
|