i18n
Messages
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 the 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 them in a component
import { useTranslations } from "use-intl"
import { HrefLink } from "@vitnode/core/tanstack/link"
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) => <HrefLink className="underline" href="/terms">{chunks}</HrefLink>,
})}
</small>
</header>
)
}ICU syntax
Variables and numbers
{
"price": "Total: {amount, number, ::currency/USD}",
"date": "Published on {date, date, medium}"
}Plurals
{
"unread": "{count, plural, =0 {No unread messages} one {1 unread message} other {# unread messages}}"
}Select
{
"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 | Emails and other output with no UI. API responses return i18n keys, which the frontend translates |