Message formatting
18ways uses waysParser by default. That parser is what lets you keep the source copy readable
while still handling variables and locale-aware formatting.
Variables
Dùng dấu ngoặc nhọn cho biến. Với <T>, bạn có thể giữ giá trị nội tuyến ngay cạnh thông báo.
const label = await engine.t('Welcome back, {name}', {
vars: { name: 'Ada' },
});Pluralization
Use ICU-style plural blocks when the sentence genuinely changes shape.
const summary = await engine.t(
'{count, plural, =0{No messages} =1{One message} other{{count} messages}}',
{
vars: { count: 3 },
}
);Dates and money
If you pass a real Date or a money-like object with amount and currency, 18ways will format
it automatically even with a bare placeholder like {publishedAt} or {renewalTotal}.
Use the explicit formatter only when you want to control the output, such as dateStyle:long or a
custom money divisor.
const publishedAt = new Date('2026-03-14T09:00:00Z');
const renewalTotal = {
amount: 1900,
currency: 'USD',
};
const updatedLabel = await engine.t('Last updated {publishedAt}', {
vars: { publishedAt },
});
const totalLabel = await engine.t('Renewal total {renewalTotal}', {
vars: { renewalTotal },
});
const detailedDate = await engine.t('Detailed date: {publishedAt, date, dateStyle:long}', {
vars: { publishedAt },
});By default, money amounts are treated as minor units. If you already have major units, use the
explicit money formatter with divisor: 1.
Select blocks
Use select when the copy depends on a small set of discrete values.
const banner = await engine.t(
'{isSignedIn, select, true{Welcome back, {name}} false{Sign in to continue} other{Sign in to continue}}',
{
vars: {
isSignedIn: true,
name: 'Ada',
},
}
);Component composition
@18ways/core returns strings. If you need rich text, keep the sentence whole and handle markup in
your own renderer.
const cta = await engine.t('Click here to see more');If your app needs automatic JSX composition, move up to @18ways/react or @18ways/next.
Practical rule
If the sentence can be written as a complete phrase with a few variables, keep it in one message. That makes translation quality dramatically better than stitching fragments together in code.