Internationalization (I18n)
Messages & ICU Syntax
Format strings with ICU message syntax in VitNode, including variables, pluralization, rich text tags, and select rules.
VitNode localizes strings using standard ICU MessageFormat, parsed and rendered through use-intl.
Quick start
1. Define Message Strings
{
"@vitnode/blog": {
"welcome": "Welcome back, {name}!",
"articles_count": "{count, plural, =0 {No articles} one {1 article} other {# articles}}",
"terms_notice": "By clicking continue, you agree to our <link>Terms of Service</link>."
}
}2. Render in React Components
import { useTranslations } from "use-intl"
import { Link } from "@tanstack/react-router"
export const BlogHeader = ({ count, name }: { count: number; name: string }) => {
const t = useTranslations("@vitnode/blog")
return (
<header className="flex flex-col gap-2">
<h1>{t("welcome", { name })}</h1>
<p>{t("articles_count", { count })}</p>
{/* Rich text with custom tags */}
<small className="text-muted-foreground">
{t.rich("terms_notice", {
link: (chunks) => <Link to="/terms" className="underline">{chunks}</Link>,
})}
</small>
</header>
)
}ICU Syntax Reference
1. Variables & Numbers
{
"price": "Total: {amount, number, ::currency/USD}",
"date": "Published on {date, date, medium}"
}2. Cardinal Pluralization
{
"unread": "{count, plural, =0 {No unread messages} one {1 unread message} other {# unread messages}}"
}3. Select / Enums
{
"status": "{status, select, draft {Draft} published {Published} other {Archived}}"
}Where Message Files Live
| Folder | Audience | Purpose |
|---|---|---|
src/locales/{locale}.json | Frontend | Browser UI, page text, and AdminCP navigation |
src/locales/api/{locale}.json | API Server | Transactional emails and backend validation errors |