0
# Macro Functions
1
2
The @lingui/core/macro module provides compile-time translation helpers that are transformed by Babel during the build process. These macros enable optimal runtime performance by pre-compiling ICU MessageFormat strings and extracting translatable messages for localization workflows.
3
4
## Capabilities
5
6
### Translation Macro (t)
7
8
The primary macro for translating messages with multiple overloads supporting different usage patterns.
9
10
```typescript { .api }
11
/**
12
* Translate a message descriptor with full metadata
13
* @param descriptor - Message descriptor with id, message, comment
14
* @returns Translated string (transformed at compile time)
15
*/
16
function t(descriptor: MacroMessageDescriptor): string;
17
18
/**
19
* Translate a template literal with interpolation
20
* @param literals - Template string array
21
* @param placeholders - Values for interpolation
22
* @returns Translated string (transformed at compile time)
23
*/
24
function t(
25
literals: TemplateStringsArray,
26
...placeholders: MessagePlaceholder[]
27
): string;
28
29
/**
30
* @deprecated Translate using specific I18n instance (use i18n._(msg`...`) instead)
31
* @param i18n - I18n instance to use for translation
32
* @returns Translation functions bound to the instance
33
*/
34
function t(i18n: I18n): {
35
(literals: TemplateStringsArray, ...placeholders: any[]): string;
36
(descriptor: MacroMessageDescriptor): string;
37
};
38
39
type MacroMessageDescriptor = (
40
| { id: string; message?: string }
41
| { id?: string; message: string }
42
) & {
43
comment?: string;
44
context?: string;
45
};
46
47
type MessagePlaceholder = string | number | LabeledExpression<string | number>;
48
type LabeledExpression<T> = Record<string, T>;
49
```
50
51
**Usage Examples:**
52
53
```typescript
54
import { t } from "@lingui/core/macro";
55
56
// Template literal with interpolation
57
const greeting = t`Hello ${name}!`;
58
59
// Message descriptor with metadata
60
const welcome = t({
61
id: "welcome.message",
62
message: `Welcome to our app, ${userName}!`,
63
comment: "Greeting shown on the welcome page"
64
});
65
66
// Simple message with auto-generated ID
67
const confirm = t({ message: "Are you sure?" });
68
69
// Message with explicit ID only
70
const error = t({ id: "error.network" });
71
```
72
73
### Pluralization Macro (plural)
74
75
Handles pluralization using ICU MessageFormat plural rules.
76
77
```typescript { .api }
78
/**
79
* Pluralize a message based on a numeric value
80
* @param value - Number or labeled expression determining plural form
81
* @param options - Plural form options (one, other, etc.)
82
* @returns Pluralized string (transformed at compile time)
83
*/
84
function plural(
85
value: number | string | LabeledExpression<number | string>,
86
options: ChoiceOptions
87
): string;
88
89
interface ChoiceOptions {
90
/** Offset for plural calculation (default: 0) */
91
offset?: number;
92
/** Exact match for zero */
93
zero?: string;
94
/** Singular form */
95
one?: string;
96
/** Dual form (some languages) */
97
two?: string;
98
/** Few form (some languages) */
99
few?: string;
100
/** Many form (some languages) */
101
many?: string;
102
/** Default/fallback form (required) */
103
other: string;
104
/** Exact numeric matches (e.g., "0": "no items") */
105
[digit: `${number}`]: string;
106
}
107
```
108
109
**Usage Examples:**
110
111
```typescript
112
import { plural } from "@lingui/core/macro";
113
114
// Basic pluralization
115
const itemCount = plural(count, {
116
one: "1 item",
117
other: "# items"
118
});
119
120
// Complex pluralization with offset
121
const commentCount = plural(commentCount, {
122
offset: 1,
123
"0": "No comments",
124
"1": "1 comment",
125
one: "1 other comment",
126
other: "# other comments"
127
});
128
129
// Using labeled expression
130
const messageCount = plural({count}, {
131
zero: "No messages",
132
one: "One message",
133
other: "{count} messages"
134
});
135
```
136
137
### Ordinal Pluralization Macro (selectOrdinal)
138
139
Handles ordinal pluralization (1st, 2nd, 3rd, etc.) using ICU MessageFormat ordinal rules.
140
141
```typescript { .api }
142
/**
143
* Select ordinal plural form (1st, 2nd, 3rd, etc.)
144
* @param value - Number or labeled expression for ordinal selection
145
* @param options - Ordinal form options
146
* @returns Ordinal string (transformed at compile time)
147
*/
148
function selectOrdinal(
149
value: number | string | LabeledExpression<number | string>,
150
options: ChoiceOptions
151
): string;
152
```
153
154
**Usage Examples:**
155
156
```typescript
157
import { selectOrdinal } from "@lingui/core/macro";
158
159
// Ordinal positioning
160
const position = selectOrdinal(place, {
161
one: "#st place",
162
two: "#nd place",
163
few: "#rd place",
164
other: "#th place"
165
});
166
167
// Birthday ordinals
168
const birthday = selectOrdinal({age}, {
169
one: "{age}st birthday",
170
two: "{age}nd birthday",
171
few: "{age}rd birthday",
172
other: "{age}th birthday"
173
});
174
```
175
176
### Selection Macro (select)
177
178
Conditional selection based on string values, similar to switch statements.
179
180
```typescript { .api }
181
/**
182
* Select a message based on a string value
183
* @param value - String or labeled expression for selection
184
* @param choices - Object mapping values to messages
185
* @returns Selected string (transformed at compile time)
186
*/
187
function select(
188
value: string | LabeledExpression<string>,
189
choices: SelectOptions
190
): string;
191
192
interface SelectOptions {
193
/** Default/fallback choice (required) */
194
other: string;
195
/** Specific value matches */
196
[matches: string]: string;
197
}
198
```
199
200
**Usage Examples:**
201
202
```typescript
203
import { select } from "@lingui/core/macro";
204
205
// Gender selection
206
const pronoun = select(gender, {
207
male: "he",
208
female: "she",
209
other: "they"
210
});
211
212
// Status-based messages
213
const statusMessage = select({status}, {
214
pending: "Your order is being processed",
215
shipped: "Your order has been shipped",
216
delivered: "Your order has been delivered",
217
other: "Unknown status: {status}"
218
});
219
```
220
221
### Message Definition Macros
222
223
Macros for defining messages without immediate translation, useful for message extraction and deferred translation.
224
225
```typescript { .api }
226
/**
227
* Define a message for later translation
228
* @param descriptor - Message descriptor with metadata
229
* @returns MessageDescriptor object (not translated)
230
*/
231
function defineMessage(descriptor: MacroMessageDescriptor): MessageDescriptor;
232
233
/**
234
* Define a message using template literal syntax
235
* @param literals - Template string array
236
* @param placeholders - Values for interpolation
237
* @returns MessageDescriptor object (not translated)
238
*/
239
function defineMessage(
240
literals: TemplateStringsArray,
241
...placeholders: MessagePlaceholder[]
242
): MessageDescriptor;
243
244
/**
245
* Alias for defineMessage (shorter syntax)
246
*/
247
const msg: typeof defineMessage;
248
```
249
250
**Usage Examples:**
251
252
```typescript
253
import { defineMessage, msg } from "@lingui/core/macro";
254
255
// Define messages without translation
256
const messages = {
257
welcome: defineMessage({
258
id: "app.welcome",
259
message: "Welcome to our application!",
260
comment: "Main welcome message"
261
}),
262
263
goodbye: msg`Goodbye, ${userName}!`
264
};
265
266
// Later translate using I18n instance
267
const welcomeText = i18n._(messages.welcome);
268
const goodbyeText = i18n._(messages.goodbye, { userName: "Alice" });
269
```
270
271
### Placeholder Helper
272
273
Helper function for creating labeled expressions with meaningful names.
274
275
```typescript { .api }
276
/**
277
* Create a labeled placeholder for better message readability
278
* @param def - Object mapping labels to values
279
* @returns Labeled expression string
280
*/
281
function ph(def: LabeledExpression<string | number>): string;
282
```
283
284
**Usage Examples:**
285
286
```typescript
287
import { t, ph } from "@lingui/core/macro";
288
289
// Using ph for clearer placeholder names
290
const message = t`User ${ph({userName: user.name})} has ${ph({count: user.messages.length})} messages`;
291
292
// Equivalent to but more readable than:
293
const message2 = t`User ${user.name} has ${user.messages.length} messages`;
294
```
295
296
## Macro Transformation
297
298
All macro functions are transformed during the build process by `@lingui/babel-plugin-lingui-macro`. The macros:
299
300
1. **Extract messages** for translation workflows
301
2. **Generate message IDs** automatically or use provided IDs
302
3. **Compile ICU MessageFormat** for optimal runtime performance
303
4. **Replace macro calls** with optimized runtime code
304
305
**Build-time transformation example:**
306
307
```typescript
308
// Source code
309
const message = t`Hello ${name}!`;
310
311
// Transformed code (simplified)
312
const message = i18n._("Hello {name}!", { name });
313
```
314
315
## Integration with I18n Instances
316
317
While macros work with the global i18n instance by default, they can be used with specific instances:
318
319
```typescript
320
import { i18n } from "@lingui/core";
321
import { msg } from "@lingui/core/macro";
322
323
// Define message
324
const welcomeMsg = msg`Welcome ${userName}!`;
325
326
// Translate with specific instance
327
const translated = i18n._(welcomeMsg, { userName: "Bob" });
328
```
329
330
## Development vs Production
331
332
- **Development**: Macros can compile messages at runtime when a message compiler is available
333
- **Production**: Messages should be pre-compiled during build for optimal performance and smaller bundles
334
- **Message extraction**: Macros enable automatic extraction of translatable strings for localization workflows