全栈开发个人博客02:国际化

next-intl 是一个用于 Next.js 应用的国际化库,简化了多语言支持,通过 useTranslationsFormattedMessage 等组件来管理翻译内容,支持构建时静态渲染,服务端组件和客户端组件都可以使用。

1. 配置国际化

  • 安装依赖
bash 复制代码
pnpm add next-intl
  • 使用 App Router with routing 的国际化配置,根据官网配置完成后,文件结构如下:
bash 复制代码
├── messages
│   ├── en.json
│   └── ...
├── next.config.ts
└── src
    ├── i18n
    │   ├── routing.ts
    │   ├── navigation.ts
    │   └── request.ts
    ├── middleware.ts
    └── app
        └── [locale]
            ├── layout.tsx
            └── page.tsx

2. 支持静态渲染

  1. 在 layout.tsx 中添加 generateStaticParams 方法,为所有路由开启静态渲染
tsx 复制代码
// src/app/[locale]/layout.tsx
import { routing } from '@/i18n/routing'
export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }))
}
  1. 在 所有 layout.tsx 和 page.tsx 中使用 setRequestLocale 设置请求的国际化语言
tsx 复制代码
// src/app/[locale]/layout.tsx
import { setRequestLocale } from 'next-intl'

setRequestLocale(locale)
tsx 复制代码
// src/app/[locale]/page.tsx
import { setRequestLocale } from 'next-intl'

setRequestLocale(locale)

3. 根域名需要重定向到默认语言

tsx 复制代码
// src/app/page.tsx
import { redirect } from 'next/navigation'

export default function RootPage() {
  redirect('/en')
}

4. 切换域名使用i18n自带的router.replace(),保留当前用户访问路径

tsx 复制代码
// LocaleSwitcherSelect.tsx

'use client'
import { useParams } from 'next/navigation'
import { usePathname, useRouter } from '@/i18n/navigation'
import { Locale, routing } from '@/i18n/routing'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { Languages } from 'lucide-react'
import { useLocale, useTranslations } from 'next-intl'
import { useTransition } from 'react'
type Props = {
  defaultValue: string
  items: Array<{ value: string; label: string }>
  label: string
}

function LocaleSwitcherSelect({ defaultValue, items, label }: Props) {
  const [isPending, startTransition] = useTransition()
  const router = useRouter()
  const pathname = usePathname()
  const params = useParams()

  function onChange(value: string) {
    const nextLocale = value as Locale
    startTransition(() => {
      router.replace({ pathname, params }, { locale: nextLocale })
    })
  }

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <div className="hover:bg-accent hover:text-accent-foreground cursor-pointer p-2 transition-colors">
          <Languages className="size-4" />
        </div>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end">
        {items.map((item) => (
          <DropdownMenuItem
            key={item.value}
            onClick={() => onChange(item.value)}
          >
            {item.label}
          </DropdownMenuItem>
        ))}
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

export default function LocaleSwitcher() {
  const t = useTranslations('LocaleSwitcher')
  const locale = useLocale()

  return (
    <LocaleSwitcherSelect
      defaultValue={locale}
      items={routing.locales.map((locale) => ({
        value: locale,
        label: t(locale),
      }))}
      label={t('label')}
    />
  )
}
相关推荐
社恐的下水道蟑螂1 天前
深入掌握 AI 全栈项目中的路由功能:从基础到进阶的全面解析
前端·react.js·全栈
JOEH601 天前
🛡️ 微服务雪崩救星:Sentinel 限流熔断实战,3行代码搞定高可用!
后端·全栈
前端付豪1 天前
必知 Express和 MVC
前端·node.js·全栈
lihouyi1 天前
Shell入门指南
自动化运维·全栈
心在飞扬2 天前
langchain学习总结-Runnable组件 bind 函数
全栈
飞雪飘摇2 天前
摆脱重复劳动的引力:深入解析 Elpis 框架的“配置驱动”哲学
全栈
陈佬昔没带相机3 天前
2025年终总结:Vibe Coding 之后,胆儿肥了
ai编程·全栈·next.js
mCell3 天前
2025:被 AI 推着往前走的一年
agent·年终总结·全栈
ohyeah5 天前
打造 AI 驱动的 Git 提交规范助手:基于 React + Express + Ollama+langchain 的全栈实践
langchain·全栈·ollama
秋天的一阵风6 天前
🎥解决前端 “复现难”:rrweb 录制回放从入门到精通(下)
前端·开源·全栈