Using Internationalization
Nexty.dev uses the next-intl
library to implement complete multilingual support, providing a flexible internationalization solution that includes route-level language switching, automatic language detection, and other features.
Through this documentation, you will learn the basic usage of next-intl
, methods for extending new languages and translation content, and the advanced multilingual features supported by Nexty.dev.
File Structure
i18n/
├── messages/ # Translation files directory
│ ├── en/ # English translations
│ │ └── common.json
│ ├── zh/ # Chinese translations
│ │ └── common.json
│ └── ja/ # Japanese translations
│ └── common.json
├── request.ts # next-intl request configuration
└── routing.ts # Route and language configuration
components/
├── LocaleSwitcher.tsx # Language switcher component
└── LanguageDetectionAlert.tsx # Language detection alert component
stores/
└── localeStore.ts # Language state management
middleware.ts # Middleware configuration
next.config.mjs # Next.js configuration
Basic Usage
Using Translations in Components
In frontend components, use useLocale
to get the current language and useTranslations
to get translation content.
import { useLocale, useTranslations } from 'next-intl';
export default function MyComponent() {
const locale = useLocale();
const t = useTranslations('Home');
return (
<div>
<h1>{t('title')}</h1>
<p>{t('description')}</p>
</div>
);
}
Using in Server Components
In server components, use getLocale
to get the current language and getTranslations
to get translation content.
import { getLocale, getTranslations } from 'next-intl/server';
export default async function ServerComponent() {
const locale = await getLocale();
const t = await getTranslations('Home');
return (
<div>
<h1>{t('title')}</h1>
</div>
);
}
Good to know
If server components are not using
async
, you can also useuseLocale
anduseTranslations
, andnext-intl
will handle this automatically.
Using Translations with Parameters
In JSON file:
{
"welcome": "Welcome, {name}!",
"countdown": "Closing in {countdown} seconds"
}
In component:
const message = t('welcome', { name: 'John' });
const timer = t('countdown', { countdown: countdown.toString() });
Using Raw Data
For complex data structures (like arrays, objects), use t.raw()
:
const headerLinks = t.raw('Header.links') as HeaderLink[];
const features = t.raw('Landing.Features.items');
Internationalized Link Component
Use the Link
component exposed by @/i18n/routing
. You don't need to write language prefixes in href
, as next-intl
will automatically handle them based on the current language.
import { Link as I18nLink } from '@/i18n/routing';
<I18nLink href="/about">
{t('aboutUs')}
</I18nLink>
Internationalized useRouter
Use the useRouter
component exposed by @/i18n/routing
. Similarly, you don't need to write language prefixes, as next-intl
will automatically handle them based on the current language.
import { useRouter } from '@/i18n/routing';
const router = useRouter();
const handleClick = () => {
router.push('/dashboard');
};
Steps to Add New Languages
Step 1. Modify Language Configuration
Add the new language in i18n/routing.ts
:
export const LOCALES = ['en', 'zh', 'ja', 'ko'] // Add Korean
export const DEFAULT_LOCALE = 'en'
export const LOCALE_NAMES: Record<string, string> = {
'en': "English",
'zh': "中文",
'ja': "日本語",
'ko': "한국어", // Add Korean display name
};
Step 2. Create Translation Files
Create new language directory and translation files:
mkdir i18n/messages/ko
cp i18n/messages/en/common.json i18n/messages/ko/common.json
Step 3. Translate Content
Edit i18n/messages/ko/common.json
and translate all English content to Korean.
Step 4. Update Route Redirects (Optional)
If needed, add corresponding redirect rules in next.config.mjs
:
{
source: "/ko/dashboard",
destination: "/ko/dashboard/settings",
permanent: true,
}
Multi-file Translation Architecture
When there's a lot of translation content, it's recommended to split translation files into multiple modules:
Create Modular File Structure
i18n/messages/en/
├── common.json # Common translations
├── Landing.json # Authentication related
├── Dashboard.json # Dashboard
└── Blog.json # Blog
Modify request.ts Configuration
import { getRequestConfig } from 'next-intl/server';
import { routing } from './routing';
export default getRequestConfig(async ({ requestLocale }) => {
let locale = await requestLocale;
if (!locale || !routing.locales.includes(locale as any)) {
locale = routing.defaultLocale;
}
// Dynamically import all translation files
const common = (await import(`./messages/${locale}/common.json`)).default;
const Landing = (await import(`./messages/${locale}/Landing.json`)).default;
const Dashboard = (await import(`./messages/${locale}/Dashboard.json`)).default;
const Blog = (await import(`./messages/${locale}/Blog.json`)).default;
return {
locale,
messages: {
...common,
Landing,
Dashboard,
Blog,
}
};
});
Using Namespaces
// Use specific namespace
const t = useTranslations('Dashboard.User.Settings');
const tLanding = useTranslations('Landing');
const tBlog = useTranslations('Blog');
File Organization Recommendations
// common.json - Site-wide common
{
"header": {...},
"footer": {...},
"common": {...}
}
// Landing.json - Landing page
{
"login": {...},
"register": {...},
"forgotPassword": {...}
}
// Dashboard.json - Dashboard module
{
"sidebar": {...},
"settings": {...},
"profile": {...}
}
Advanced Features of Nexty.dev
Language Detection and Alerts
The system automatically detects the browser language when users first visit. If it doesn't match the current website language, a switching prompt will be displayed:
- 10-second countdown with automatic close
- Users can manually close
- Closed state is saved for 30 days (via Cookie)
Within the Cookie validity period, when visiting the website again, the language will automatically switch.
SEO Optimization
Each language version generates independent URLs and metadata:
import { constructMetadata } from "@/lib/metadata";
export async function generateMetadata({ params }: MetadataProps): Promise<Metadata> {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: "Home" });
return constructMetadata({
page: "Home",
title: t("title"),
description: t("description"),
locale: locale as Locale,
path: `/`,
});
}