Internationalization (i18n)
Learn how to add multi-language support to your Sushify Next.js application using next-intl
Sushify Next.js includes built-in internationalization (i18n) support powered by next-intl, making it easy to build multilingual applications with type-safe translations.
Features
- Multiple Languages: Support for unlimited languages
- Type-Safe Translations: Full TypeScript support with autocomplete
- Locale-Specific Routing: Automatic locale detection and routing
- Number & Date Formatting: Locale-aware formatting
- Server & Client Components: Works in both server and client components
- SEO-Friendly: Proper hreflang tags and locale-specific URLs
- Dynamic Content: Translate dynamic content from your database
Configuration
1. Supported Locales
Configure supported languages in your config:
export const config = {
i18n: {
enabled: true,
locales: {
en: {
currency: "USD",
label: "English",
},
zh: {
currency: "CNY",
label: "简体中文",
},
es: {
currency: "EUR",
label: "Español",
},
de: {
currency: "EUR",
label: "Deutsch",
},
},
defaultLocale: "en",
defaultCurrency: "USD",
localeCookieName: "NEXT_LOCALE",
},
};2. Translation Files
Translations are organized in JSON files by locale:
├── en.json # English translations
├── zh.json # Chinese (Simplified) translations
├── es.json # Spanish translations
└── de.json # German translationsExample translation file:
{
"navigation": {
"home": "Home",
"pricing": "Pricing",
"about": "About",
"contact": "Contact"
},
"buttons": {
"submit": "Submit",
"cancel": "Cancel",
"save": "Save",
"delete": "Delete"
},
"messages": {
"success": "Operation completed successfully",
"error": "An error occurred",
"loading": "Loading..."
}
}{
"navigation": {
"home": "Startseite",
"pricing": "Preise",
"about": "Über uns",
"contact": "Kontakt"
},
"buttons": {
"submit": "Absenden",
"cancel": "Abbrechen",
"save": "Speichern",
"delete": "Löschen"
},
"messages": {
"success": "Vorgang erfolgreich abgeschlossen",
"error": "Ein Fehler ist aufgetreten",
"loading": "Wird geladen..."
}
}Usage
Server Components
Use translations in server components:
import { getTranslations } from "next-intl/server";
export default async function HomePage() {
const t = await getTranslations();
return (
<div>
<h1>{t("navigation.home")}</h1>
<button>{t("buttons.submit")}</button>
</div>
);
}Client Components
Use translations in client components:
"use client";
import { useTranslations } from "next-intl";
export function SubmitButton() {
const t = useTranslations();
return (
<button type="submit">
{t("buttons.submit")}
</button>
);
}Rich Text Formatting
Format text with HTML tags:
{
"terms": "By signing up, you agree to our <link>Terms of Service</link>"
}import { useTranslations } from "next-intl";
import Link from "next/link";
function SignupPage() {
const t = useTranslations("auth");
return (
<p>
{t.rich("terms", {
link: (chunks) => (
<Link href="/terms" className="underline">
{chunks}
</Link>
),
})}
</p>
);
}Email Translations
Send localized emails:
import { sendEmail } from "@repo/mail";
await sendEmail({
to: user.email,
templateId: "welcome",
locale: user.locale, // Use user's preferred language
context: {
name: user.name,
},
});Adding a New Language
- Add to config:
locales: {
// ...existing locales
ja: {
currency: "JPY",
label: "日本語",
},
}- Create translation file:
cp packages/i18n/translations/en.json packages/i18n/translations/ja.json-
Translate content: Update the JSON file with Japanese translations
-
Test: Verify all pages render correctly in the new language