多语言使用与扩展指南
Nexty.dev 使用 next-intl
库实现完整的多语言支持,提供了灵活的国际化解决方案,包括路由级别的语言切换、自动语言检测等功能。
通过这篇文档,你将了解 next-intl
的基本用法、新语言和翻译内容的扩展方法以及 Nexty.dev 支持的多语言高级特性。
文件结构
i18n/
├── messages/ # 翻译文件目录
│ ├── en/ # 英语翻译
│ │ └── common.json
│ ├── zh/ # 中文翻译
│ │ └── common.json
│ └── ja/ # 日语翻译
│ └── common.json
├── request.ts # next-intl 请求配置
└── routing.ts # 路由和语言配置
components/
├── LocaleSwitcher.tsx # 语言切换组件
└── LanguageDetectionAlert.tsx # 语言检测提醒组件
stores/
└── localeStore.ts # 语言状态管理
middleware.ts # 中间件配置
next.config.mjs # Next.js 配置
基本用法
在组件中使用翻译
在前端组件中,使用 useLocale
获取当前语言,使用 useTranslations
获取翻译内容;。
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>
);
}
在服务端组件中使用
在服务端组件中,使用 getLocale
获取当前语言,使用 getTranslations
获取翻译内容。
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>
);
}
提示
如果服务器组件没有使用
async
,则也可以使用useLocale
和useTranslations
,next-intl
会自动处理。
使用带参数的翻译
JSON 文件中:
{
"welcome": "Welcome, {name}!",
"countdown": "Closing in {countdown} seconds"
}
组件中:
const message = t('welcome', { name: 'John' });
const timer = t('countdown', { countdown: countdown.toString() });
使用原始数据
对于复杂的数据结构(如数组、对象),使用 t.raw()
:
const headerLinks = t.raw('Header.links') as HeaderLink[];
const features = t.raw('Landing.Features.items');
国际化 Link 组件
使用 @/i18n/routing
暴露出来的 Link
组件,href
不需要写语言前缀,next-intl
会根据当前语言自动处理。
import { Link as I18nLink } from '@/i18n/routing';
<I18nLink href="/about">
{t('aboutUs')}
</I18nLink>
国际化 useRouter
使用 @/i18n/routing
暴露出来的 useRouter
组件,同样不需要写语言前缀,next-intl
会根据当前语言自动处理。
import { useRouter } from '@/i18n/routing';
const router = useRouter();
const handleClick = () => {
router.push('/dashboard');
};
扩展新语言步骤
步骤1. 修改语言配置
在 i18n/routing.ts
中添加新语言:
export const LOCALES = ['en', 'zh', 'ja', 'ko'] // 添加韩语
export const DEFAULT_LOCALE = 'en'
export const LOCALE_NAMES: Record<string, string> = {
'en': "English",
'zh': "中文",
'ja': "日本語",
'ko': "한국어", // 添加韩语显示名称
};
步骤2. 创建翻译文件
创建新的语言目录和翻译文件:
mkdir i18n/messages/ko
cp i18n/messages/en/common.json i18n/messages/ko/common.json
步骤3. 翻译内容
编辑 i18n/messages/ko/common.json
,将所有英语内容翻译为韩语。
步骤4. 更新路由重定向(可选)
如果需要,在 next.config.mjs
中添加对应的重定向规则:
{
source: "/ko/dashboard",
destination: "/ko/dashboard/settings",
permanent: true,
}
多文件翻译架构
当翻译内容很多时,推荐将翻译文件拆分为多个模块:
创建模块化文件结构
i18n/messages/en/
├── common.json # 通用翻译
├── Landing.json # 认证相关
├── Dashboard.json # 仪表板
└── Blog.json # 博客
修改 request.ts 配置
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;
}
// 动态导入所有翻译文件
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,
}
};
});
使用命名空间
// 使用特定命名空间
const t = useTranslations('Dashboard.User.Settings');
const tLanding = useTranslations('Landing');
const tBlog = useTranslations('Blog');
文件组织建议
// common.json - 全站通用
{
"header": {...},
"footer": {...},
"common": {...}
}
// Landing.json - 落地页
{
"login": {...},
"register": {...},
"forgotPassword": {...}
}
// Dashboard.json - 仪表板模块
{
"sidebar": {...},
"settings": {...},
"profile": {...}
}
Nexty.dev 的高级特性
语言检测与提醒
系统会在用户首次访问时自动检测浏览器语言,如果与当前网站语言不符,会显示切换提醒:
- 10秒倒计时自动关闭
- 用户可手动关闭
- 关闭状态保存30天(通过Cookie)
在 Cookie 有效期内将再次访问网站,将自动切换语言。
SEO 优化
每个语言版本都会生成独立的URL和元数据:
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: `/`,
});
}