使用您最喜欢的AI助手总结文档,并引用此页面和AI提供商
通过将 Intlayer MCP 服务器集成到您的 AI 助手,您可以直接从 ChatGPT、DeepSeek、Cursor、VSCode 等获取所有文档。
查看 MCP 服务器文档此页面的内容已使用 AI 翻译。
查看英文原文的最新版本如果您有改善此文档的想法,请随时通过在GitHub上提交拉取请求来贡献。
文档的 GitHub 链接复制文档 Markdown 到剪贴板
使用 Intlayer 和 Tanstack Start 开始国际化 (i18n)
本指南演示如何在 Tanstack Start 项目中集成 Intlayer,实现无缝国际化,支持基于区域设置的路由、TypeScript 支持以及现代开发实践。
什么是 Intlayer?
Intlayer 是一个创新的开源国际化(i18n)库,旨在简化现代 Web 应用中的多语言支持。
使用 Intlayer,您可以:
- 通过组件级声明式字典轻松管理翻译。
- 动态本地化元数据、路由和内容。
- 通过自动生成的类型确保 TypeScript 支持,提升自动补全和错误检测能力。
- 享受高级功能,如动态区域设置检测和切换。
- 通过 Tanstack Start 的基于文件的路由系统启用区域设置感知路由。
在 Tanstack Start 应用中设置 Intlayer 的分步指南
第一步:创建项目
首先,按照 TanStack Start 网站上的新建项目指南创建一个新的 TanStack Start 项目。
第二步:安装 Intlayer 包
使用您喜欢的包管理器安装所需的包:
npm install intlayer react-intlayernpm install vite-intlayer --save-dev
intlayer
react-intlayer
将 Intlayer 集成到 React 应用中的包。它为 React 国际化提供上下文提供者和钩子。vite-intlayer
包含用于将 Intlayer 集成到Vite 打包器的 Vite 插件,以及用于检测用户首选语言、管理 Cookie 和处理 URL 重定向的中间件。
第三步:项目配置
创建一个配置文件来配置您的应用程序语言:
复制代码到剪贴板
import type { IntlayerConfig } from "intlayer";import { Locales } from "intlayer";const config: IntlayerConfig = { internationalization: { defaultLocale: Locales.ENGLISH, locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], },};export default config;
通过此配置文件,您可以设置本地化 URL、中间件重定向、cookie 名称、内容声明的位置和扩展名、禁用控制台中的 Intlayer 日志等。有关可用参数的完整列表,请参阅配置文档。
第4步:在您的 Vite 配置中集成 Intlayer
将 intlayer 插件添加到您的配置中:
复制代码到剪贴板
import { reactRouter } from "@react-router/dev/vite";import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";import tsconfigPaths from "vite-tsconfig-paths";export default defineConfig({ plugins: [reactRouter(), tsconfigPaths(), intlayer()],});
intlayer() Vite 插件用于将 Intlayer 集成到 Vite 中。它确保构建内容声明文件并在开发模式下监视它们。它在 Vite 应用中定义了 Intlayer 环境变量。此外,它还提供别名以优化性能。
第5步:创建布局组件
设置您的根布局和特定语言环境的布局:
根布局
复制代码到剪贴板
import { createFileRoute, Navigate, Outlet } from "@tanstack/react-router";import { IntlayerProvider, useLocale } from "react-intlayer";import { useI18nHTMLAttributes } from "@/hooks/useI18nHTMLAttributes";export const Route = createFileRoute("/{-$locale}")({ component: LayoutComponent,});function LayoutComponent() { const { defaultLocale } = useLocale(); const { locale } = Route.useParams(); return ( <IntlayerProvider locale={defaultLocale}> <Outlet /> </IntlayerProvider> );}
第6步:声明您的内容
创建并管理您的内容声明以存储翻译:
复制代码到剪贴板
import type { Dictionary } from "intlayer";import { t } from "intlayer";const appContent = { content: { links: { about: t({ zh: "关于", en: "About", es: "Acerca de", fr: "À propos", }), home: t({ zh: "首页", en: "Home", es: "Inicio", fr: "Accueil", }), }, meta: { description: t({ zh: "这是一个使用 Intlayer 和 TanStack Router 的示例", en: "This is an example of using Intlayer with TanStack Router", es: "Este es un ejemplo de uso de Intlayer con TanStack Router", fr: "Ceci est un exemple d'utilisation d'Intlayer avec TanStack Router", }), }, title: t({ zh: "欢迎使用 Intlayer + TanStack Router", en: "Welcome to Intlayer + TanStack Router", es: "Bienvenido a Intlayer + TanStack Router", fr: "Bienvenue à Intlayer + TanStack Router", }), }, key: "app",} satisfies Dictionary;export default appContent;
您的内容声明可以在应用程序中的任何位置定义,只要它们被包含在 contentDir 目录中(默认是 ./app)。并且文件扩展名需匹配内容声明文件扩展名(默认是 .content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx})。
更多详情,请参阅内容声明文档。
第7步:创建支持多语言的组件和钩子
创建一个用于多语言导航的 LocalizedLink 组件:
复制代码到剪贴板
import type { FC } from "react";import { Link, type LinkComponentProps } from "@tanstack/react-router";import { useLocale } from "intlayer";export const LOCALE_ROUTE = "{-$locale}" as const;// 主要工具类型export type RemoveLocaleParam<T> = T extends string ? RemoveLocaleFromString<T> : T;export type To = RemoveLocaleParam<LinkComponentProps["to"]>;type CollapseDoubleSlashes<S extends string> = S extends `${infer H}//${infer T}` ? CollapseDoubleSlashes<`${H}/${T}`> : S;type LocalizedLinkProps = { to?: To;} & Omit<LinkComponentProps, "to">;// 辅助类型type RemoveAll< S extends string, Sub extends string,> = S extends `${infer H}${Sub}${infer T}` ? RemoveAll<`${H}${T}`, Sub> : S;type RemoveLocaleFromString<S extends string> = CollapseDoubleSlashes< RemoveAll<S, typeof LOCALE_ROUTE>>;export const LocalizedLink: FC<LocalizedLinkProps> = (props) => { const { locale } = useLocale(); return ( <Link {...props} params={{ locale, ...(typeof props?.params === "object" ? props?.params : {}), }} to={`/${LOCALE_ROUTE}${props.to}` as LinkComponentProps["to"]} /> );};
该组件有两个目标:
- 移除 URL 中不必要的 {-$locale} 前缀。
- 将 locale 参数注入 URL,确保用户被直接重定向到本地化路由。
接下来我们可以创建一个用于编程导航的 useLocalizedNavigate 钩子:
复制代码到剪贴板
import { useLocale } from "react-intlayer";import { useNavigate } from "@tanstack/react-router";import { LOCALE_ROUTE } from "@/components/localized-link";import type { FileRouteTypes } from "@/routeTree.gen";export const useLocalizedNavigate = () => { const navigate = useNavigate(); const { locale } = useLocale(); type StripLocalePrefix<T extends string> = T extends | `/${typeof LOCALE_ROUTE}` | `/${typeof LOCALE_ROUTE}/` ? "/" // 去除本地化前缀后返回根路径 : T extends `/${typeof LOCALE_ROUTE}/${infer Rest}` ? `/${Rest}` // 去除本地化前缀后返回剩余路径 : never; type LocalizedTo = StripLocalePrefix<FileRouteTypes["to"]>; interface LocalizedNavigate { (to: LocalizedTo): ReturnType<typeof navigate>; ( opts: { to: LocalizedTo } & Record<string, unknown> ): ReturnType<typeof navigate>; } const localizedNavigate: LocalizedNavigate = (args: any) => { if (typeof args === "string") { return navigate({ to: `/${LOCALE_ROUTE}${args}`, params: { locale } }); } const { to, ...rest } = args; const localedTo = `/${LOCALE_ROUTE}${to}` as any; return navigate({ to: localedTo, params: { locale, ...rest } as any }); }; return localizedNavigate;};
第8步:在您的页面中使用 Intlayer
在整个应用程序中访问您的内容字典:
本地化首页
复制代码到剪贴板
import { createFileRoute } from "@tanstack/react-router";import { getIntlayer } from "intlayer";import { useIntlayer } from "react-intlayer";import LocaleSwitcher from "@/components/locale-switcher";import { LocalizedLink } from "@/components/localized-link";import { useLocalizedNavigate } from "@/hooks/useLocalizedNavigate";export const Route = createFileRoute("/{-$locale}/")({ component: RouteComponent, head: ({ params }) => { const { locale } = params; const metaContent = getIntlayer("app", locale); return { meta: [ { title: metaContent.title }, { content: metaContent.meta.description, name: "description" }, ], }; },});function RouteComponent() { const content = useIntlayer("app"); const navigate = useLocalizedNavigate(); return ( <div> <div> {content.title} <LocaleSwitcher /> <div> <LocalizedLink to="/">{content.links.home}</LocalizedLink> <LocalizedLink to="/about">{content.links.about}</LocalizedLink> </div> <div> <button onClick={() => navigate({ to: "/" })}> {content.links.home} </button> <button onClick={() => navigate({ to: "/about" })}> {content.links.about} </button> </div> </div> </div> );}
要了解更多关于 useIntlayer 钩子的内容,请参阅文档。
第9步:创建语言切换组件
创建一个组件,允许用户切换语言:
复制代码到剪贴板
import type { FC } from "react";import { useLocation } from "@tanstack/react-router";import { getHTMLTextDir, getLocaleName, getPathWithoutLocale } from "intlayer";import { setLocaleCookie, useIntlayer, useLocale } from "react-intlayer";import { LocalizedLink, To } from "./localized-link";export const LocaleSwitcher: FC = () => { const { localeSwitcherLabel } = useIntlayer("locale-switcher"); // 使用 useIntlayer 钩子获取语言切换器标签 const { pathname } = useLocation(); // 获取当前路径名 const { availableLocales, locale } = useLocale(); // 获取可用语言列表和当前语言 const pathWithoutLocale = getPathWithoutLocale(pathname); // 获取不带语言前缀的路径 return ( <ol> {availableLocales.map((localeEl) => ( <li key={localeEl}> <LocalizedLink aria-current={localeEl === locale ? "page" : undefined} // 当前语言时设置 aria-current 为 page aria-label={`${localeSwitcherLabel.value} ${getLocaleName(localeEl)}`} // 设置无障碍标签,显示语言切换器标签和语言名称 onClick={() => setLocaleCookie(localeEl)} // 点击时设置语言 cookie params={{ locale: localeEl }} // 传递语言参数 to={pathWithoutLocale as To} // 跳转到不带语言前缀的路径 > <span> {/* 语言环境 - 例如 FR */} {localeItem} </span> <span> {/* 语言在其自身语言环境中的名称 - 例如 Français */} {getLocaleName(localeItem, locale)} </span> <span dir={getHTMLTextDir(localeItem)} lang={localeItem}> {/* 语言在当前语言环境中的名称 - 例如当前语言环境为 Locales.SPANISH 时显示 Francés */} {getLocaleName(localeItem)} </span> <span dir="ltr" lang={Locales.ENGLISH}> {/* 语言的英文名称 - 例如 French */} {getLocaleName(localeItem, Locales.ENGLISH)} </span> </LocalizedLink> </li> ))} </ol> );};
要了解有关 useLocale 钩子的更多信息,请参阅文档。
第10步:添加 HTML 属性管理(可选)
创建一个钩子来管理 HTML 的 lang 和 dir 属性:
复制代码到剪贴板
// src/hooks/useI18nHTMLAttributes.tsximport { getHTMLTextDir } from "intlayer";import { useEffect } from "react";import { useLocale } from "react-intlayer";export const useI18nHTMLAttributes = () => { const { locale } = useLocale(); useEffect(() => { document.documentElement.lang = locale; document.documentElement.dir = getHTMLTextDir(locale); }, [locale]);};
然后在你的根组件中使用它:
复制代码到剪贴板
import { createFileRoute, Navigate, Outlet } from "@tanstack/react-router";import { IntlayerProvider, useLocale } from "react-intlayer";import { useI18nHTMLAttributes } from "@/hooks/useI18nHTMLAttributes"; // 导入钩子export const Route = createFileRoute("/{-$locale}")({ component: LayoutComponent,});function LayoutComponent() { useI18nHTMLAttributes(); // 添加此行 const { defaultLocale } = useLocale(); const { locale } = Route.useParams(); return ( <IntlayerProvider locale={locale ?? defaultLocale}> <Outlet /> </IntlayerProvider> );}
第11步:添加中间件(可选)
您还可以使用 intlayerMiddleware 为您的应用程序添加服务器端路由。该插件将根据 URL 自动检测当前语言环境,并设置相应的语言环境 Cookie。如果未指定语言环境,插件将根据用户浏览器的语言偏好确定最合适的语言环境。如果未检测到语言环境,它将重定向到默认语言环境。
注意,要在生产环境中使用 intlayerMiddleware,您需要将 vite-intlayer 包从 devDependencies 切换到 dependencies。
复制代码到剪贴板
import { reactRouter } from "@react-router/dev/vite";import tailwindcss from "@tailwindcss/vite";import { defineConfig } from "vite";import { intlayer, intlayerMiddleware } from "vite-intlayer";import tsconfigPaths from "vite-tsconfig-paths";export default defineConfig({ plugins: [ tailwindcss(), reactRouter(), tsconfigPaths(), intlayer(), intlayerMiddleware(), ],});
第12步:配置 TypeScript(可选)
Intlayer 使用模块增强来利用 TypeScript 的优势,使您的代码库更健壮。
确保您的 TypeScript 配置包含自动生成的类型:
复制代码到剪贴板
{ // ... 您现有的配置 include: [ // ... 您现有的包含项 ".intlayer/**/*.ts", // 包含自动生成的类型 ],}
Git 配置
建议忽略 Intlayer 生成的文件。这样可以避免将它们提交到您的 Git 仓库中。
要做到这一点,您可以将以下指令添加到您的 .gitignore 文件中:
复制代码到剪贴板
# 忽略 Intlayer 生成的文件.intlayer
VS Code 扩展
为了提升您使用 Intlayer 的开发体验,您可以安装官方的 Intlayer VS Code 扩展。
该扩展提供:
- 翻译键的自动补全。
- 缺失翻译的实时错误检测。
- 翻译内容的内联预览。
- 轻松创建和更新翻译的快速操作。
有关如何使用该扩展的更多详细信息,请参阅Intlayer VS Code 扩展文档。
深入探索
要进一步使用,您可以实现可视化编辑器或使用内容管理系统(CMS)将内容外部化。
文档参考
本综合指南提供了将 Intlayer 与 Tanstack Start 集成所需的一切,支持完全国际化的应用程序,具备基于区域设置的路由和 TypeScript 支持。
文档历史
版本 | 日期 | 变更内容 |
---|---|---|
5.8.1 | 2025-09-09 | 为 Tanstack Start 添加支持 |