Internationalization
Multi-language support with next-intl
Internationalization
Chameleon supports multiple languages using next-intl for internationalization and localization.
Overview
The internationalization system provides English and Chinese language support with automatic locale detection, dynamic language switching, and comprehensive translation management. The system uses next-intl for message formatting, date/time localization, and number formatting.
Setup
Environment Configuration
# Supported locales
NEXT_PUBLIC_LOCALES="en,zh"
# Default locale
NEXT_PUBLIC_DEFAULT_LOCALE="en"
Locale Configuration
// src/i18n/locale.ts
export const locales = ["en", "zh"] as const;
export const defaultLocale = "en" as const;
export type Locale = (typeof locales)[number];
Usage
Basic Translation
// In components
import { useTranslations } from "next-intl";
export function MyComponent() {
const t = useTranslations("common");
return (
<div>
<h1>{t("title")}</h1>
<p>{t("description")}</p>
</div>
);
}
Server Components
// In server components
import { getTranslations } from "next-intl/server";
export default async function Page() {
const t = await getTranslations("page");
return (
<div>
<h1>{t("title")}</h1>
</div>
);
}
Dynamic Messages
// With parameters
const t = useTranslations("user");
return (
<div>
<p>{t("welcome", { name: user.name })}</p>
<p>{t("credits", { count: user.credits })}</p>
</div>
);
Date and Number Formatting
import { useFormatter } from "next-intl";
export function FormattedContent() {
const format = useFormatter();
return (
<div>
<p>{format.dateTime(new Date(), "short")}</p>
<p>{format.number(1234.56, "currency")}</p>
</div>
);
}
File Structure
Translation Files
src/i18n/
├── messages/
│ ├── en.json # English translations
│ └── zh.json # Chinese translations
├── pages/
│ ├── landing/
│ │ ├── en.json # Landing page translations
│ │ └── zh.json
│ ├── pricing/
│ │ ├── en.json # Pricing page translations
│ │ └── zh.json
│ └── admin/
│ ├── en.json # Admin page translations
│ └── zh.json
└── locale.ts # Locale configuration
Translation File Example
// src/i18n/messages/en.json
{
"common": {
"title": "Welcome to Chameleon",
"description": "AI-powered content generation",
"loading": "Loading...",
"error": "An error occurred"
},
"navigation": {
"home": "Home",
"pricing": "Pricing",
"dashboard": "Dashboard"
}
}
// src/i18n/messages/zh.json
{
"common": {
"title": "欢迎使用 Chameleon",
"description": "AI 驱动的内容生成",
"loading": "加载中...",
"error": "发生错误"
},
"navigation": {
"home": "首页",
"pricing": "价格",
"dashboard": "控制台"
}
}
Language Switching
Language Switcher Component
// src/components/language-switcher.tsx
import { useLocale } from "next-intl";
import { useRouter, usePathname } from "next/navigation";
export function LanguageSwitcher() {
const locale = useLocale();
const router = useRouter();
const pathname = usePathname();
const switchLanguage = (newLocale: string) => {
const newPath = pathname.replace(`/${locale}`, `/${newLocale}`);
router.push(newPath);
};
return (
<select value={locale} onChange={(e) => switchLanguage(e.target.value)}>
<option value="en">English</option>
<option value="zh">中文</option>
</select>
);
}
URL Structure
/en/ # English homepage
/zh/ # Chinese homepage
/en/pricing # English pricing page
/zh/pricing # Chinese pricing page
/en/admin # English admin panel
/zh/admin # Chinese admin panel
File Locations
src/i18n/locale.ts- Locale configurationsrc/i18n/messages/- Global translation filessrc/i18n/pages/- Page-specific translationssrc/middleware.ts- Locale routing middlewaresrc/app/[locale]/- Localized app routes
Common Tasks
Add New Translation
- Add key to English file (
src/i18n/messages/en.json) - Add translation to Chinese file (
src/i18n/messages/zh.json) - Use in component with
useTranslations
Add New Language
- Add locale to
src/i18n/locale.ts - Create translation files for new language
- Update language switcher component
- Test all pages in new language
Page-Specific Translations
// src/i18n/pages/landing/en.json
{
"hero": {
"title": "Generate AI Content",
"subtitle": "Create amazing content with AI"
}
}
// In landing page component
const t = useTranslations("landing.hero");
return <h1>{t("title")}</h1>;
Dynamic Content Translation
// For database content
const getLocalizedContent = (content: any, locale: string) => {
return content[locale] || content.en || content;
};
Troubleshooting
Translation not showing
Problem: Text shows translation key instead of translated text
Solution:
- Check translation key exists in JSON files
- Verify namespace is correct in
useTranslations - Check locale is properly set
- Clear browser cache
Language not switching
Problem: Language switcher not working
Solution:
- Check middleware is properly configured
- Verify locale routing is working
- Check URL structure matches expected format
- Ensure translation files exist for all locales
Missing translations
Problem: Some text not translated
Solution:
- Add missing keys to translation files
- Check for typos in translation keys
- Verify namespace structure
- Test with different locales
Next Steps
- Landing Page - Customize landing page content
- Admin System - Admin panel localization
- SEO - Multi-language SEO