首页演练场案例展示应用文档博客
    • English英语
      EN
    • русский俄语
      RU
    • 日本語日语
      JA
    • français法语
      FR
    • 한국어韩语
      KO
    • 中文中文
      ZH
    • español西班牙语
      ES
    • Deutsch德语
      DE
    • العربية阿拉伯语
      AR
    • italiano意大利语
      IT
    • British English英国英语
      EN-GB
    • português葡萄牙语
      PT
    • हिन्दी印地语
      HI
    • Türkçe土耳其语
      TR
    • polski波兰语
      PL
    • Indonesia印度尼西亚语
      ID
    • Tiếng Việt越南语
      VI
    • українська乌克兰语
      UK
    /
    按框架筛选文档
    Alt+←
    为什么Intlayer?
    开始
    概念
    • Intlayer如何工作
    • 配置
    • TestFillBuildWatchExtractLoginPushPullConfigurationListVersionEditorLiveDebugDoc ReviewDoc TranslateSDK
    • 可视化编辑器
    • CMS
    • CI/CD集成
    • 翻译复数枚举条件性别插入文件嵌套MarkdownHTML函数获取
    • 每个语言环境的文件
    • 编译器
    • 自动填充
    • 测试
    • 打包优化
    环境
    • Next.js 14和应用路由器
      Next.js 15
      Next.js 无 locale URL
      Next.js和页面路由器
      编译器
    • Tanstack Start Solid
    • Astro和React
      Astro和Svelte
      Astro和Vue
      Astro和Solid
      Astro和Preact
      Astro和Lit
      Astro和Vanilla JS
    • React Router v7
      React Router v7 (fs-routes)
      Compiler
    • Nuxt和Vue
    • Vite和Solid
    • SvelteKit
    • Vite和Preact
    • Vite和Vanilla JS
    • Vite和Lit
    • Angular 19 (Webpack)
      Analog
    • React CRA
    • React Native和Expo
    • Express.js
      NestJS
      Fastify
      Hono
      Adonis
    • Lynx和React
    Plugins
    • JSON
    • gettext (.po)
    VS Code扩展
    代理
    • MCP服务器
    • 代理技能
    发布
    • v8
    • v7
    • v6
    基准测试
    • Next.js
    • TanStack
    • Vue
    • Solid
    • Svelte
    博客
    问问题
    1. Documentation
    2. 环境
    3. Sveltekit
    \n\n\n

    {$content.title}

    \n\n

    {@const Title = $content.title}</h1>\n<!-- 以字符串形式渲染内容 -->\n<div aria-label={$content.title.value}></div>\n<div aria-label={$content.title.toString()}></div>\n<div aria-label={String($content.title)}></div>\n```\n\n### (可选)步骤6:设置路由\n\n以下步骤展示了如何在 SvelteKit 中设置基于语言环境的路由。这允许您的 URL 包含语言环境前缀(例如 `/en/about`,`/fr/about`),以提升 SEO 和用户体验。\n\n```bash\n.\n└─── src\n ├── app.d.ts # 定义语言环境类型\n ├── hooks.server.ts # 管理语言环境路由\n ├── lib\n │   └── getLocale.ts # 从请求头、cookies 检查语言环境\n ├── params\n │   └── locale.ts # 定义语言环境参数\n └── routes\n ├── [[locale=locale]] # 使用路由组包裹以设置语言环境\n │   ├── +layout.svelte # 路由的本地布局\n │   ├── +layout.ts\n │   ├── +page.svelte\n │   ├── +page.ts\n │   └── about\n │      ├── +page.svelte\n │      └── +page.ts\n └── +layout.svelte # 字体和全局样式的根布局\n```\n\n### 第7步:处理服务器端的语言环境检测(Hooks)\n\n在 SvelteKit 中,服务器需要知道用户的语言环境,以便在 SSR 期间渲染正确的内容。我们使用 `hooks.server.ts` 从 URL 或 cookie 中检测语言环境。\n\n创建或修改 `src/hooks.server.ts`:\n\n```typescript fileName=\"src/hooks.server.ts\"\nimport type { Handle } from \"@sveltejs/kit\";\nimport { getLocalizedUrl } from \"intlayer\";\nimport { getLocale } from \"$lib/getLocale\";\n\nexport const handle: Handle = async ({ event, resolve }) => {\n const detectedLocale = getLocale(event);\n\n // 检查当前路径是否已以某个语言环境开头(例如 /fr, /en)\n const pathname = event.url.pathname;\n const targetPathname = getLocalizedUrl(pathname, detectedLocale);\n\n // 如果 URL 中没有语言环境(例如用户访问 \"/\"),则重定向\n if (targetPathname !== pathname) {\n return new Response(undefined, {\n headers: { Location: targetPathname },\n status: 307, // 临时重定向\n });\n }\n\n return resolve(event, {\n transformPageChunk: ({ html }) => html.replace(\"%lang%\", detectedLocale),\n });\n};\n```\n\n然后,创建一个辅助函数从请求事件中获取用户的语言环境:\n\n```typescript fileName=\"src/lib/getLocale.ts\"\nimport {\n configuration,\n getLocaleFromStorage,\n localeDetector,\n type Locale,\n} from \"intlayer\";\nimport type { RequestEvent } from \"@sveltejs/kit\";\n\n/**\n * 从请求事件中获取用户的语言环境。\n * 此函数用于 `src/hooks.server.ts` 中的 `handle` 钩子。\n *\n * 它首先尝试从 Intlayer 存储(cookies 或自定义头)中获取语言环境。\n * 如果未找到语言环境,则回退到浏览器的 \"Accept-Language\" 协商。\n *\n * @param event - 来自 SvelteKit 的请求事件\n * @returns 用户的语言环境\n */\nexport const getLocale = (event: RequestEvent): Locale => {\n const defaultLocale = configuration?.internationalization?.defaultLocale;\n\n // 尝试从 Intlayer 存储(Cookies 或头)中获取语言环境\n const storedLocale = getLocaleFromStorage({\n // SvelteKit cookies 访问\n getCookie: (name: string) => event.cookies.get(name) ?? null,\n // SvelteKit headers 访问\n getHeader: (name: string) => event.request.headers.get(name) ?? null,\n });\n\n if (storedLocale) {\n return storedLocale;\n }\n\n // 回退到浏览器的 \"Accept-Language\" 协商\n const negotiatorHeaders: Record<string, string> = {};\n\n // 将 SvelteKit Headers 对象转换为普通的 Record<string, string>\n event.request.headers.forEach((value, key) => {\n negotiatorHeaders[key] = value;\n });\n\n // 从 `Accept-Language` 头检查语言环境\n const userFallbackLocale = localeDetector(negotiatorHeaders);\n\n if (userFallbackLocale) {\n return userFallbackLocale;\n }\n\n // 如果没有匹配,返回默认语言环境\n return defaultLocale;\n};\n```\n\n> `getLocaleFromStorage` 将根据您的配置从请求头或 cookie 中检查语言环境。更多详情请参见 [Configuration](https://intlayer.org/doc/configuration)。\n\n> `localeDetector` 函数会处理 `Accept-Language` 请求头并返回最佳匹配的语言环境。\n\n如果未配置语言环境,我们希望返回 404 错误。为简化操作,我们可以创建一个 `match` 函数来检查语言环境是否有效:\n\n```ts fileName=\"/src/params/locale.ts\"import { defaultLocale, locales, type Locale } from \"intlayer\";\nexport const match = (param: Locale = defaultLocale): boolean =>\n locales.includes(param);\n```\n\n> **注意:** 请确保您的 `src/app.d.ts` 中包含语言环境的定义:\n>\n> ```typescript\n> declare global {\n> namespace App {\n> interface Locals {\n> locale: import(\"intlayer\").Locale;\n> }\n> }\n> }\n> ```\n\n对于 `+layout.svelte` 文件,我们可以删除所有内容,只保留与国际化无关的静态内容:\n\n```svelte fileName=\"src/+layout.svelte\"\n<script lang=\"ts\">\n\t import './layout.css';\n\n let { children } = $props();\n</script>\n\n<div class=\"app\">\n\t{@render children()}\n</div>\n\n<style>\n\t.app {\n /* */\n\t}\n</style>\n```\n\n然后,在 `[[locale=locale]]` 组下创建一个新的页面和布局:\n\n```ts fileName=\"src/routes/[[locale=locale]]/+layout.ts\"\nimport type { Load } from \"@sveltejs/kit\";\nimport { defaultLocale, type Locale } from \"intlayer\";\n\nexport const prerender = true;\n\n// 使用通用的 Load 类型\nexport const load: Load = ({ params }) => {\n const locale: Locale = (params.locale as Locale) ?? defaultLocale;\n\n return {\n locale,\n };\n};\n```\n\n```svelte fileName=\"src/routes/[[locale=locale]]/+layout.svelte\"\n<script lang=\"ts\">\n\timport type { Snippet } from 'svelte';\n\timport { useIntlayer, setupIntlayer } from \"svelte-intlayer\";\n\timport Header from './Header.svelte';\n\timport type { LayoutData } from './$types';\n\n\tlet { children, data }: { children: Snippet, data: LayoutData } = $props();\n\n\t// 使用路由中的 locale 初始化 Intlayer\n $effect(() => {\n setupIntlayer(data.locale);\n });\n\t// 使用布局内容字典\n\tconst layoutContent = useIntlayer('layout');\n</script>\n\n<Header />\n\n<main>\n\t{@render children()}\n</main>\n\n<footer>\n\t<p>\n\t\t{$layoutContent.footer.prefix.value}{' '}\n\t\t<a href=\"https://svelte.dev/docs/kit\">{$layoutContent.footer.linkLabel.value}</a>{' '}\n\t\t{$layoutContent.footer.suffix.value}\n\t</p>\n</footer>\n\n<style>\n /* */\n</style>\n```\n\n```ts fileName=\"src/routes/[[locale=locale]]/+page.ts\"\nexport const prerender = true;\n```\n\n```svelte fileName=\"src/routes/[[locale=locale]]/+page.svelte\"\n<script lang=\"ts\">\n\timport { useIntlayer } from \"svelte-intlayer\";\n\n\t// 使用主页内容字典\n\tconst homeContent = useIntlayer('home');\n</script>\n\n<svelte:head>\n\t<title>{$homeContent.title.value}\n\n\n
    \n\t

    \n\t\t{$homeContent.title}\n\t

    \n
    \n\n\n```\n\n### (可选)步骤 8:国际化链接\n\n为了SEO,建议在路由前加上语言前缀(例如 `/en/about`,`/fr/about`)。该组件会自动为任何链接添加当前语言的前缀。\n\n```svelte fileName=\"src/lib/components/LocalizedLink.svelte\"\n\n\n\n \n\n```\n\n如果你使用 SvelteKit 的 `goto`,可以用相同的逻辑结合 `getLocalizedUrl` 来跳转到本地化的URL:\n\n```typescript\nimport { goto } from \"$app/navigation\";\nimport { getLocalizedUrl } from \"intlayer\";\nimport { useLocale } from \"svelte-intlayer\";\n\nconst { locale } = useLocale();\nconst localizedPath = getLocalizedUrl(\"/about\", $locale);\ngoto(localizedPath); // 根据语言环境导航到 /en/about 或 /fr/about\n```\n\n### (可选)步骤 9:语言切换器\n\n为了允许用户切换语言,更新 URL。\n\n```svelte fileName=\"src/lib/components/LanguageSwitcher.svelte\"\n\n\n
      \n {#each availableLocales as localeEl}\n
    • \n {\n e.preventDefault();\n setLocale(localeEl); // 将在存储中设置语言环境并触发 onLocaleChange\n }}\n class:active={$locale === localeEl}\n >\n {getLocaleName(localeEl)}\n \n
    • \n {/each}\n
    \n\n\n```\n\n### (可选)步骤 10:添加后端代理\n\n要为您的 SvelteKit 应用添加后端代理,可以使用 `vite-intlayer` 插件提供的 `intlayerProxy` 函数。该插件将根据 URL、Cookie 和浏览器语言偏好自动检测用户的最佳语言环境。\n\n```ts fileName=\"vite.config.ts\"\nimport { defineConfig } from \"vite\";\nimport { intlayer, intlayerProxy } from \"vite-intlayer\";\nimport { sveltekit } from \"@sveltejs/kit/vite\";\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n intlayerProxy(), // should be placed first\n intlayer(),\n sveltekit(),\n ],],\n});\n```\n\n### (可选)步骤 11:设置 intlayer 编辑器 / CMS\n\n要设置 intlayer 编辑器,您必须遵循 [intlayer 编辑器文档](/zh/doc/concept/editor)。\n\n要设置 intlayer CMS,您必须遵循 [intlayer CMS 文档](/zh/doc/concept/cms)。\n\n要能够可视化 intlayer 编辑器选择器,您必须在 intlayer 内容中使用组件语法。\n\n```svelte fileName=\"Component.svelte\"\n\n\n
    \n\n \n

    {$content.title}

    \n\n \n {@const Component = $content.component}\n
    \n```\n\n### Git 配置\n\n建议忽略 Intlayer 生成的文件。\n\n```plaintext fileName=\".gitignore\"\n# 忽略 Intlayer 生成的文件\n.intlayer\n```\n\n---\n\n### (可选) 步骤 1 : 提取组件内容\n\n如果您有现有的代码库,转换数千个文件可能会非常耗时。\n\n为了简化此过程,Intlayer 提出了 [编译器](/zh/doc/compiler) / [提取器](/zh/doc/concept/cli/extract) 来转换您的组件并提取内容。\n\n要进行设置,您可以在 `intlayer.config.ts` 文件中添加 `compiler` 部分:\n\n```typescript fileName=\"intlayer.config.ts\" codeFormat={[\"typescript\", \"esm\", \"commonjs\"]}\nimport { type IntlayerConfig } from \"intlayer\";\n\nconst config: IntlayerConfig = {\n // ... 您的其他配置\n compiler: {\n /**\n * 指示是否应启用编译器。\n */\n enabled: true,\n\n /**\n * 定义输出文件路径\n */\n output: ({ fileName, extension }) => `./${fileName}${extension}`,\n\n /**\n * 指示在转换后是否应保存组件。这样,编译器只需运行一次即可转换应用程序,然后即可将其删除。\n */\n saveComponents: false,\n\n /**\n * 字典键前缀\n */\n dictionaryKeyPrefix: \"\",\n },\n};\n\nexport default config;\n```\n\n\n \n\n运行提取器以转换组件并提取内容\n\n```bash packageManager=\"npm\"\nnpx intlayer extract\n```\n\n```bash packageManager=\"pnpm\"\npnpm intlayer extract\n```\n\n```bash packageManager=\"yarn\"\nyarn intlayer extract\n```\n\n```bash packageManager=\"bun\"\nbun x intlayer extract\n```\n\n \n \n\n更新您的 `vite.config.ts` 以包含 `intlayerCompiler` 插件:\n\n```ts fileName=\"vite.config.ts\"\nimport { defineConfig } from \"vite\";\nimport { intlayer, intlayerCompiler } from \"vite-intlayer\";\n\nexport default defineConfig({\n plugins: [\n intlayer(),\n intlayerCompiler(), // 添加编译器插件\n ],\n});\n```\n\n```bash packageManager=\"npm\"\nnpm run build # 或 npm run dev\n```\n\n```bash packageManager=\"pnpm\"\npnpm run build # 或 pnpm run dev\n```\n\n```bash packageManager=\"yarn\"\nyarn build # 或 yarn dev\n```\n\n```bash packageManager=\"bun\"\nbun run build # Or bun run dev\n```\n\n \n\n\n### 深入了解\n\n- **可视化编辑器**:集成[Intlayer 可视化编辑器](/zh/doc/concept/editor),以便直接从用户界面编辑翻译内容。\n- **CMS**:使用[Intlayer CMS](/zh/doc/concept/cms)实现内容管理的外部化。\n","about":"了解如何使您的 SvelteKit 网站支持多语言。按照文档使用服务器端渲染 (SSR) 进行国际化 (i18n) 和翻译。","url":"https://intlayer.org/zh/doc/environment/sveltekit","datePublished":"20-11-2025","dateModified":"06-05-2026","keywords":"国际化, 文档, Intlayer, SvelteKit, JavaScript, SSR","license":"https://raw.githubusercontent.com/aymericzip/intlayer/refs/heads/main/LICENSE","audience":{"@type":"Audience","audienceType":"开发者,内容经理"}}
    Creation:2025-11-20Last update:2026-05-06
    在 GitHub 上查看应用程序模板

    此页面有可用的应用程序模板。

    查看展示应用

    此页面链接到模板的在线演示。

    将此文档参考到您的 AI 助手
    ChatGPT
    Claude
    DeepSeek
    Google AI mode
    Gemini
    Perplexity
    Mistral
    Grok

    使用您最喜欢的AI助手总结文档,并引用此页面和AI提供商

    版本历史

    1. "更新 Solid useIntlayer API 用法以直接访问属性"
      v8.9.02026/5/4
    2. "添加 init 命令"
      v7.5.92025/12/30
    3. "初始化历史记录"
      v7.1.102025/11/20

    此页面的内容已使用 AI 翻译。

    查看英文原文的最新版本
    编辑此文档

    如果您有改善此文档的想法,请随时通过在GitHub上提交拉取请求来贡献。

    文档的 GitHub 链接
    Copy

    复制文档 Markdown 到剪贴板

    使用 Intlayer 翻译您的 SvelteKit 网站 | 国际化 (i18n)

    ide.intlayer.org
    intlayer-sveltekit-template.vercel.app

    目录

    什么是 Intlayer?

    Intlayer 是一个创新的开源国际化 (i18n) 库,旨在简化现代 Web 应用中的多语言支持。它与 SvelteKit 的服务器端渲染 (SSR) 功能无缝协作。

    使用 Intlayer,您可以:

    • 通过组件级声明式字典轻松管理翻译。
    • 动态本地化元数据、路由和内容。
    • 通过自动生成的类型确保 TypeScript 支持。
    • 利用 SvelteKit 的 SSR 实现对搜索引擎友好的国际化。

    在 SvelteKit 应用中设置 Intlayer 的分步指南

    首先,创建一个新的 SvelteKit 项目。以下是我们将要构建的最终结构:

    bash
    复制代码

    复制代码到剪贴板

    .├── intlayer.config.ts├── package.json├── src│   ├── app.d.ts│   ├── app.html│   ├── hooks.server.ts│   ├── lib│   │   ├── getLocale.ts│   │   ├── LocaleSwitcher.svelte│   │   └── LocalizedLink.svelte│   ├── params│   │   └── locale.ts│   └── routes│       ├── [[locale=locale]]│       │   ├── +layout.svelte│       │   ├── +layout.ts│       │   ├── +page.svelte│       │   ├── +page.ts│       │   ├── about│       │   │   ├── +page.svelte│       │   │   ├── +page.ts│       │   │   └── page.content.ts│       │   ├── Counter.content.ts│       │   ├── Counter.svelte│       │   ├── Header.content.ts│       │   ├── Header.svelte│       │   ├── home.content.ts│       │   └── layout.content.ts│       ├── +layout.svelte│       └── layout.css├── static│   ├── favicon.svg│   └── robots.txt├── svelte.config.js├── tsconfig.json└── vite.config.ts

    第一步:安装依赖

    使用 npm 安装必要的包:

    bash
    复制代码

    复制代码到剪贴板

    npm install intlayer svelte-intlayernpm install vite-intlayer --save-devnpx intlayer init
    • intlayer:核心的国际化(i18n)包。
    • svelte-intlayer:为 Svelte/SvelteKit 提供上下文提供者和存储。
    • vite-intlayer:Vite 插件,用于将内容声明集成到构建流程中。

    第二步:配置你的项目

    在项目根目录创建一个配置文件:

    intlayer.config.ts
    复制代码

    复制代码到剪贴板

    import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],    defaultLocale: Locales.ENGLISH,  },};export default config;

    第3步:在你的 Vite 配置中集成 Intlayer

    更新你的 vite.config.ts 文件以包含 Intlayer 插件。该插件负责内容文件的转译。

    vite.config.ts
    复制代码

    复制代码到剪贴板

    import { sveltekit } from "@sveltejs/kit/vite";import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";export default defineConfig({  plugins: [intlayer(), sveltekit()], // 顺序很重要,Intlayer 应该放在 SvelteKit 之前});

    第4步:声明您的内容

    在您的 src 文件夹中的任意位置创建内容声明文件(例如,src/lib/content 或与组件放在一起)。这些文件使用 t() 函数为每个语言环境定义您的应用程序可翻译的内容。

    第5步:在您的组件中使用 Intlayer

    现在你可以在任何 Svelte 组件中使用 useIntlayer 函数。它返回一个响应式存储,当语言环境变化时会自动更新。该函数会自动遵循当前语言环境(无论是在 SSR 还是客户端导航期间)。

    注意: useIntlayer 返回一个 Svelte 存储,因此你需要使用 `--- createdAt: 2025-11-20 updatedAt: 2026-05-06 title: 如何翻译您的 SvelteKit 应用 – 2025 年国际化 (i18n) 指南 description: 了解如何使您的 SvelteKit 网站支持多语言。按照文档使用服务器端渲染 (SSR) 进行国际化 (i18n) 和翻译。 keywords:

    • 国际化
    • 文档
    • Intlayer
    • SvelteKit
    • JavaScript
    • SSR slugs:
    • doc
    • environment
    • sveltekit applicationTemplate: https://github.com/aymericzip/intlayer-sveltekit-template history:
    • version: 7.1.10 date: 2025-11-20 changes: 初始化历史记录

    使用 Intlayer 翻译您的 SvelteKit 网站 | 国际化 (i18n)

    目录

    什么是 Intlayer?

    Intlayer 是一个创新的开源国际化 (i18n) 库,旨在简化现代 Web 应用中的多语言支持。它与 SvelteKit 的服务器端渲染 (SSR) 功能无缝协作。

    使用 Intlayer,您可以:

    • 通过组件级声明式字典轻松管理翻译。
    • 动态本地化元数据、路由和内容。
    • 通过自动生成的类型确保 TypeScript 支持。
    • 利用 SvelteKit 的 SSR 实现对搜索引擎友好的国际化。

    在 SvelteKit 应用中设置 Intlayer 的分步指南

    首先,创建一个新的 SvelteKit 项目。以下是我们将要构建的最终结构:

    bash
    复制代码

    复制代码到剪贴板

    .├── intlayer.config.ts├── package.json├── src│   ├── app.d.ts│   ├── app.html│   ├── hooks.server.ts│   ├── lib│   │   ├── getLocale.ts│   │   ├── LocaleSwitcher.svelte│   │   └── LocalizedLink.svelte│   ├── params│   │   └── locale.ts│   └── routes│       ├── [[locale=locale]]│       │   ├── +layout.svelte│       │   ├── +layout.ts│       │   ├── +page.svelte│       │   ├── +page.ts│       │   ├── about│       │   │   ├── +page.svelte│       │   │   ├── +page.ts│       │   │   └── page.content.ts│       │   ├── Counter.content.ts│       │   ├── Counter.svelte│       │   ├── Header.content.ts│       │   ├── Header.svelte│       │   ├── home.content.ts│       │   └── layout.content.ts│       ├── +layout.svelte│       └── layout.css├── static│   ├── favicon.svg│   └── robots.txt├── svelte.config.js├── tsconfig.json└── vite.config.ts

    第一步:安装依赖

    使用 npm 安装必要的包:

    bash
    复制代码

    复制代码到剪贴板

    npm install intlayer svelte-intlayernpm install vite-intlayer --save-devnpx intlayer init
    • intlayer:核心的国际化(i18n)包。
    • svelte-intlayer:为 Svelte/SvelteKit 提供上下文提供者和存储。
    • vite-intlayer:Vite 插件,用于将内容声明集成到构建流程中。

    第二步:配置你的项目

    在项目根目录创建一个配置文件:

    intlayer.config.ts
    复制代码

    复制代码到剪贴板

    import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],    defaultLocale: Locales.ENGLISH,  },};export default config;

    第3步:在你的 Vite 配置中集成 Intlayer

    更新你的 vite.config.ts 文件以包含 Intlayer 插件。该插件负责内容文件的转译。

    vite.config.ts
    复制代码

    复制代码到剪贴板

    import { sveltekit } from "@sveltejs/kit/vite";import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";export default defineConfig({  plugins: [intlayer(), sveltekit()], // 顺序很重要,Intlayer 应该放在 SvelteKit 之前});

    第4步:声明您的内容

    在您的 src 文件夹中的任意位置创建内容声明文件(例如,src/lib/content 或与组件放在一起)。这些文件使用 t() 函数为每个语言环境定义您的应用程序可翻译的内容。

    第5步:在您的组件中使用 Intlayer

    前缀来访问其响应式值(例如,$content.title)。

    src/lib/components/Component.svelte
    复制代码

    复制代码到剪贴板

    <script lang="ts">  import { useIntlayer } from "svelte-intlayer";  // "hero-section" 对应于步骤4中定义的键  const content = useIntlayer("hero-section");</script><!-- 以简单内容渲染内容 --><h1>{$content.title}</h1><!-- 使用编辑器渲染可编辑内容 --><h1>{@const Title = $content.title}<Title /></h1><!-- 以字符串形式渲染内容 --><div aria-label={$content.title.value}></div><div aria-label={$content.title.toString()}></div><div aria-label={String($content.title)}></div>

    (可选)步骤6:设置路由

    以下步骤展示了如何在 SvelteKit 中设置基于语言环境的路由。这允许您的 URL 包含语言环境前缀(例如 /en/about,/fr/about),以提升 SEO 和用户体验。

    bash
    复制代码

    复制代码到剪贴板

    .└─── src    ├── app.d.ts                  # 定义语言环境类型    ├── hooks.server.ts           # 管理语言环境路由    ├── lib    │   └── getLocale.ts          # 从请求头、cookies 检查语言环境    ├── params    │   └── locale.ts             # 定义语言环境参数    └── routes        ├── [[locale=locale]]     # 使用路由组包裹以设置语言环境        │   ├── +layout.svelte    # 路由的本地布局        │   ├── +layout.ts        │   ├── +page.svelte        │   ├── +page.ts        │   └── about        │       ├── +page.svelte        │       └── +page.ts        └── +layout.svelte         # 字体和全局样式的根布局

    第7步:处理服务器端的语言环境检测(Hooks)

    在 SvelteKit 中,服务器需要知道用户的语言环境,以便在 SSR 期间渲染正确的内容。我们使用 hooks.server.ts 从 URL 或 cookie 中检测语言环境。

    创建或修改 src/hooks.server.ts:

    src/hooks.server.ts
    复制代码

    复制代码到剪贴板

    import type { Handle } from "@sveltejs/kit";import { getLocalizedUrl } from "intlayer";import { getLocale } from "$lib/getLocale";export const handle: Handle = async ({ event, resolve }) => {  const detectedLocale = getLocale(event);  // 检查当前路径是否已以某个语言环境开头(例如 /fr, /en)  const pathname = event.url.pathname;  const targetPathname = getLocalizedUrl(pathname, detectedLocale);  // 如果 URL 中没有语言环境(例如用户访问 "/"),则重定向  if (targetPathname !== pathname) {    return new Response(undefined, {      headers: { Location: targetPathname },      status: 307, // 临时重定向    });  }  return resolve(event, {    transformPageChunk: ({ html }) => html.replace("%lang%", detectedLocale),  });};

    然后,创建一个辅助函数从请求事件中获取用户的语言环境:

    src/lib/getLocale.ts
    复制代码

    复制代码到剪贴板

    import {  configuration,  getLocaleFromStorage,  localeDetector,  type Locale,} from "intlayer";import type { RequestEvent } from "@sveltejs/kit";/** * 从请求事件中获取用户的语言环境。 * 此函数用于 `src/hooks.server.ts` 中的 `handle` 钩子。 * * 它首先尝试从 Intlayer 存储(cookies 或自定义头)中获取语言环境。 * 如果未找到语言环境,则回退到浏览器的 "Accept-Language" 协商。 * * @param event - 来自 SvelteKit 的请求事件 * @returns 用户的语言环境 */export const getLocale = (event: RequestEvent): Locale => {  const defaultLocale = configuration?.internationalization?.defaultLocale;  // 尝试从 Intlayer 存储(Cookies 或头)中获取语言环境  const storedLocale = getLocaleFromStorage({    // SvelteKit cookies 访问    getCookie: (name: string) => event.cookies.get(name) ?? null,    // SvelteKit headers 访问    getHeader: (name: string) => event.request.headers.get(name) ?? null,  });  if (storedLocale) {    return storedLocale;  }  // 回退到浏览器的 "Accept-Language" 协商  const negotiatorHeaders: Record<string, string> = {};  // 将 SvelteKit Headers 对象转换为普通的 Record<string, string>  event.request.headers.forEach((value, key) => {    negotiatorHeaders[key] = value;  });  // 从 `Accept-Language` 头检查语言环境  const userFallbackLocale = localeDetector(negotiatorHeaders);  if (userFallbackLocale) {    return userFallbackLocale;  }  // 如果没有匹配,返回默认语言环境  return defaultLocale;};
    getLocaleFromStorage 将根据您的配置从请求头或 cookie 中检查语言环境。更多详情请参见 Configuration。
    localeDetector 函数会处理 Accept-Language 请求头并返回最佳匹配的语言环境。

    如果未配置语言环境,我们希望返回 404 错误。为简化操作,我们可以创建一个 match 函数来检查语言环境是否有效:

    /src/params/locale.ts
    复制代码

    复制代码到剪贴板

    export const match = (param: Locale = defaultLocale): boolean =>  locales.includes(param);

    注意: 请确保您的 src/app.d.ts 中包含语言环境的定义:

    typescript
    复制代码

    复制代码到剪贴板

    declare global {  namespace App {    interface Locals {      locale: import("intlayer").Locale;    }  }}

    对于 +layout.svelte 文件,我们可以删除所有内容,只保留与国际化无关的静态内容:

    src/+layout.svelte
    复制代码

    复制代码到剪贴板

    <script lang="ts">     import './layout.css';    let { children } = $props();</script><div class="app">    {@render children()}</div><style>    .app {    /*  */    }</style>

    然后,在 [[locale=locale]] 组下创建一个新的页面和布局:

    src/routes/[[locale=locale]]/+layout.ts
    复制代码

    复制代码到剪贴板

    import type { Load } from "@sveltejs/kit";import { defaultLocale, type Locale } from "intlayer";export const prerender = true;// 使用通用的 Load 类型export const load: Load = ({ params }) => {  const locale: Locale = (params.locale as Locale) ?? defaultLocale;  return {    locale,  };};
    src/routes/[[locale=locale]]/+layout.svelte
    复制代码

    复制代码到剪贴板

    <script lang="ts">    import type { Snippet } from 'svelte';    import { useIntlayer, setupIntlayer } from "svelte-intlayer";    import Header from './Header.svelte';    import type { LayoutData } from './$types';    let { children, data }: { children: Snippet, data: LayoutData } = $props();    // 使用路由中的 locale 初始化 Intlayer  $effect(() => {      setupIntlayer(data.locale);  });    // 使用布局内容字典    const layoutContent = useIntlayer('layout');</script><Header /><main>    {@render children()}</main><footer>    <p>        {$layoutContent.footer.prefix.value}{' '}        <a href="https://svelte.dev/docs/kit">{$layoutContent.footer.linkLabel.value}</a>{' '}        {$layoutContent.footer.suffix.value}    </p></footer><style>  /*  */</style>
    src/routes/[[locale=locale]]/+page.ts
    复制代码

    复制代码到剪贴板

    export const prerender = true;
    src/routes/[[locale=locale]]/+page.svelte
    复制代码

    复制代码到剪贴板

    <script lang="ts">    import { useIntlayer } from "svelte-intlayer";    // 使用主页内容字典    const homeContent = useIntlayer('home');</script><svelte:head>    <title>{$homeContent.title.value}</title></svelte:head><section>    <h1>        {$homeContent.title}    </h1></section><style>  /*  */</style>

    (可选)步骤 8:国际化链接

    为了SEO,建议在路由前加上语言前缀(例如 /en/about,/fr/about)。该组件会自动为任何链接添加当前语言的前缀。

    src/lib/components/LocalizedLink.svelte
    复制代码

    复制代码到剪贴板

    <script lang="ts">  import { getLocalizedUrl } from "intlayer";  import { useLocale } from "svelte-intlayer";  let { href = "" } = $props();  const { locale } = useLocale();  // 辅助函数:为URL添加当前语言前缀  $: localizedHref = getLocalizedUrl(href, $locale);</script><a href={localizedHref}>  <slot /></a>

    如果你使用 SvelteKit 的 goto,可以用相同的逻辑结合 getLocalizedUrl 来跳转到本地化的URL:

    typescript
    复制代码

    复制代码到剪贴板

    import { goto } from "$app/navigation";import { getLocalizedUrl } from "intlayer";import { useLocale } from "svelte-intlayer";const { locale } = useLocale();const localizedPath = getLocalizedUrl("/about", $locale);goto(localizedPath); // 根据语言环境导航到 /en/about 或 /fr/about

    (可选)步骤 9:语言切换器

    为了允许用户切换语言,更新 URL。

    src/lib/components/LanguageSwitcher.svelte
    复制代码

    复制代码到剪贴板

    <script lang="ts">  import { getLocalizedUrl, getLocaleName } from 'intlayer';  import { useLocale } from "svelte-intlayer";  import { page } from '$app/stores';  import { goto } from '$app/navigation';  const { locale, setLocale, availableLocales } = useLocale({    onLocaleChange: (newLocale) => {      const localizedPath = getLocalizedUrl($page.url.pathname, newLocale);      goto(localizedPath);    },  });</script><ul class="locale-list">  {#each availableLocales as localeEl}    <li>      <a        href={getLocalizedUrl($page.url.pathname, localeEl)}        onclick={(e) => {          e.preventDefault();          setLocale(localeEl); // 将在存储中设置语言环境并触发 onLocaleChange        }}        class:active={$locale === localeEl}      >        {getLocaleName(localeEl)}      </a>    </li>  {/each}</ul><style>  /* */</style>

    (可选)步骤 10:添加后端代理

    要为您的 SvelteKit 应用添加后端代理,可以使用 vite-intlayer 插件提供的 intlayerProxy 函数。该插件将根据 URL、Cookie 和浏览器语言偏好自动检测用户的最佳语言环境。

    vite.config.ts
    复制代码

    复制代码到剪贴板

    import { defineConfig } from "vite";import { intlayer, intlayerProxy } from "vite-intlayer";import { sveltekit } from "@sveltejs/kit/vite";// https://vitejs.dev/config/export default defineConfig({  plugins: [    intlayerProxy(), // should be placed first    intlayer(),    sveltekit(),  ],],});

    (可选)步骤 11:设置 intlayer 编辑器 / CMS

    要设置 intlayer 编辑器,您必须遵循 intlayer 编辑器文档。

    要设置 intlayer CMS,您必须遵循 intlayer CMS 文档。

    要能够可视化 intlayer 编辑器选择器,您必须在 intlayer 内容中使用组件语法。

    Component.svelte
    复制代码

    复制代码到剪贴板

    <script lang="ts">  import { useIntlayer } from "svelte-intlayer";  const content = useIntlayer("component");</script><div>  <!-- 以简单内容方式渲染内容 -->  <h1>{$content.title}</h1>  <!-- 以组件方式渲染内容(编辑器所需) -->  {@const Component = $content.component}<Component /></div>

    Git 配置

    建议忽略 Intlayer 生成的文件。

    .gitignore
    复制代码

    复制代码到剪贴板

    # 忽略 Intlayer 生成的文件.intlayer

    (可选) 步骤 1 : 提取组件内容

    如果您有现有的代码库,转换数千个文件可能会非常耗时。

    为了简化此过程,Intlayer 提出了 编译器 / 提取器 来转换您的组件并提取内容。

    要进行设置,您可以在 intlayer.config.ts 文件中添加 compiler 部分:

    intlayer.config.ts
    复制代码

    复制代码到剪贴板

    import { type IntlayerConfig } from "intlayer";
    
    const config: IntlayerConfig = {
      // ... 您的其他配置
      compiler: {
        /**
         * 指示是否应启用编译器。
         */
        enabled: true,
    
        /**
         * 定义输出文件路径
         */
        output: ({ fileName, extension }) => `./${fileName}${extension}`,
    
        /**
         * 指示在转换后是否应保存组件。这样,编译器只需运行一次即可转换应用程序,然后即可将其删除。
         */
        saveComponents: false,
    
        /**
         * 字典键前缀
         */
        dictionaryKeyPrefix: "",
      },
    };
    
    export default config;

    运行提取器以转换组件并提取内容

    bash
    复制代码

    复制代码到剪贴板

    npx intlayer extract

    更新您的 vite.config.ts 以包含 intlayerCompiler 插件:

    vite.config.ts
    复制代码

    复制代码到剪贴板

    import { defineConfig } from "vite";import { intlayer, intlayerCompiler } from "vite-intlayer";export default defineConfig({ plugins: [   intlayer(),   intlayerCompiler(), // 添加编译器插件 ],});
    bash
    复制代码

    复制代码到剪贴板

    npm run build # 或 npm run dev

    深入了解

    • 可视化编辑器:集成Intlayer 可视化编辑器,以便直接从用户界面编辑翻译内容。
    • CMS:使用Intlayer CMS实现内容管理的外部化。
    Vite和Svelte
    Vite和Preact

    Alt+→

    在此页面

      讨论是匿名的,并会定期审查以解决常见问题。欢迎分享功能想法、对文档的反馈或任何与 Intlayer 相关的内容, 我们会利用这些意见来制定路线图并改进产品。

      .├── intlayer.config.ts├── package.json├── src│   ├── app.d.ts│   ├── app.html│   ├── hooks.server.ts│   ├── lib│   │   ├── getLocale.ts│   │   ├── LocaleSwitcher.svelte│   │   └── LocalizedLink.svelte│   ├── params│   │   └── locale.ts│   └── routes│       ├── [[locale=locale]]│       │   ├── +layout.svelte│       │   ├── +layout.ts│       │   ├── +page.svelte│       │   ├── +page.ts│       │   ├── about│       │   │   ├── +page.svelte│       │   │   ├── +page.ts│       │   │   └── page.content.ts│       │   ├── Counter.content.ts│       │   ├── Counter.svelte│       │   ├── Header.content.ts│       │   ├── Header.svelte│       │   ├── home.content.ts│       │   └── layout.content.ts│       ├── +layout.svelte│       └── layout.css├── static│   ├── favicon.svg│   └── robots.txt├── svelte.config.js├── tsconfig.json└── vite.config.ts
      npm install intlayer svelte-intlayernpm install vite-intlayer --save-devnpx intlayer init
      import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],    defaultLocale: Locales.ENGLISH,  },};export default config;
      import { sveltekit } from "@sveltejs/kit/vite";import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";export default defineConfig({  plugins: [intlayer(), sveltekit()], // 顺序很重要,Intlayer 应该放在 SvelteKit 之前});
      .├── intlayer.config.ts├── package.json├── src│   ├── app.d.ts│   ├── app.html│   ├── hooks.server.ts│   ├── lib│   │   ├── getLocale.ts│   │   ├── LocaleSwitcher.svelte│   │   └── LocalizedLink.svelte│   ├── params│   │   └── locale.ts│   └── routes│       ├── [[locale=locale]]│       │   ├── +layout.svelte│       │   ├── +layout.ts│       │   ├── +page.svelte│       │   ├── +page.ts│       │   ├── about│       │   │   ├── +page.svelte│       │   │   ├── +page.ts│       │   │   └── page.content.ts│       │   ├── Counter.content.ts│       │   ├── Counter.svelte│       │   ├── Header.content.ts│       │   ├── Header.svelte│       │   ├── home.content.ts│       │   └── layout.content.ts│       ├── +layout.svelte│       └── layout.css├── static│   ├── favicon.svg│   └── robots.txt├── svelte.config.js├── tsconfig.json└── vite.config.ts
      npm install intlayer svelte-intlayernpm install vite-intlayer --save-devnpx intlayer init
      import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],    defaultLocale: Locales.ENGLISH,  },};export default config;
      import { sveltekit } from "@sveltejs/kit/vite";import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";export default defineConfig({  plugins: [intlayer(), sveltekit()], // 顺序很重要,Intlayer 应该放在 SvelteKit 之前});
      <script lang="ts">  import { useIntlayer } from "svelte-intlayer";  // "hero-section" 对应于步骤4中定义的键  const content = useIntlayer("hero-section");</script><!-- 以简单内容渲染内容 --><h1>{$content.title}</h1><!-- 使用编辑器渲染可编辑内容 --><h1>{@const Title = $content.title}<Title /></h1><!-- 以字符串形式渲染内容 --><div aria-label={$content.title.value}></div><div aria-label={$content.title.toString()}></div><div aria-label={String($content.title)}></div>
      .└─── src    ├── app.d.ts                  # 定义语言环境类型    ├── hooks.server.ts           # 管理语言环境路由    ├── lib    │   └── getLocale.ts          # 从请求头、cookies 检查语言环境    ├── params    │   └── locale.ts             # 定义语言环境参数    └── routes        ├── [[locale=locale]]     # 使用路由组包裹以设置语言环境        │   ├── +layout.svelte    # 路由的本地布局        │   ├── +layout.ts        │   ├── +page.svelte        │   ├── +page.ts        │   └── about        │       ├── +page.svelte        │       └── +page.ts        └── +layout.svelte         # 字体和全局样式的根布局
      import type { Handle } from "@sveltejs/kit";import { getLocalizedUrl } from "intlayer";import { getLocale } from "$lib/getLocale";export const handle: Handle = async ({ event, resolve }) => {  const detectedLocale = getLocale(event);  // 检查当前路径是否已以某个语言环境开头(例如 /fr, /en)  const pathname = event.url.pathname;  const targetPathname = getLocalizedUrl(pathname, detectedLocale);  // 如果 URL 中没有语言环境(例如用户访问 "/"),则重定向  if (targetPathname !== pathname) {    return new Response(undefined, {      headers: { Location: targetPathname },      status: 307, // 临时重定向    });  }  return resolve(event, {    transformPageChunk: ({ html }) => html.replace("%lang%", detectedLocale),  });};
      import {  configuration,  getLocaleFromStorage,  localeDetector,  type Locale,} from "intlayer";import type { RequestEvent } from "@sveltejs/kit";/** * 从请求事件中获取用户的语言环境。 * 此函数用于 `src/hooks.server.ts` 中的 `handle` 钩子。 * * 它首先尝试从 Intlayer 存储(cookies 或自定义头)中获取语言环境。 * 如果未找到语言环境,则回退到浏览器的 "Accept-Language" 协商。 * * @param event - 来自 SvelteKit 的请求事件 * @returns 用户的语言环境 */export const getLocale = (event: RequestEvent): Locale => {  const defaultLocale = configuration?.internationalization?.defaultLocale;  // 尝试从 Intlayer 存储(Cookies 或头)中获取语言环境  const storedLocale = getLocaleFromStorage({    // SvelteKit cookies 访问    getCookie: (name: string) => event.cookies.get(name) ?? null,    // SvelteKit headers 访问    getHeader: (name: string) => event.request.headers.get(name) ?? null,  });  if (storedLocale) {    return storedLocale;  }  // 回退到浏览器的 "Accept-Language" 协商  const negotiatorHeaders: Record<string, string> = {};  // 将 SvelteKit Headers 对象转换为普通的 Record<string, string>  event.request.headers.forEach((value, key) => {    negotiatorHeaders[key] = value;  });  // 从 `Accept-Language` 头检查语言环境  const userFallbackLocale = localeDetector(negotiatorHeaders);  if (userFallbackLocale) {    return userFallbackLocale;  }  // 如果没有匹配,返回默认语言环境  return defaultLocale;};
      export const match = (param: Locale = defaultLocale): boolean =>  locales.includes(param);
      declare global {  namespace App {    interface Locals {      locale: import("intlayer").Locale;    }  }}
      <script lang="ts">     import './layout.css';    let { children } = $props();</script><div class="app">    {@render children()}</div><style>    .app {    /*  */    }</style>
      import type { Load } from "@sveltejs/kit";import { defaultLocale, type Locale } from "intlayer";export const prerender = true;// 使用通用的 Load 类型export const load: Load = ({ params }) => {  const locale: Locale = (params.locale as Locale) ?? defaultLocale;  return {    locale,  };};
      <script lang="ts">    import type { Snippet } from 'svelte';    import { useIntlayer, setupIntlayer } from "svelte-intlayer";    import Header from './Header.svelte';    import type { LayoutData } from './$types';    let { children, data }: { children: Snippet, data: LayoutData } = $props();    // 使用路由中的 locale 初始化 Intlayer  $effect(() => {      setupIntlayer(data.locale);  });    // 使用布局内容字典    const layoutContent = useIntlayer('layout');</script><Header /><main>    {@render children()}</main><footer>    <p>        {$layoutContent.footer.prefix.value}{' '}        <a href="https://svelte.dev/docs/kit">{$layoutContent.footer.linkLabel.value}</a>{' '}        {$layoutContent.footer.suffix.value}    </p></footer><style>  /*  */</style>
      export const prerender = true;
      <script lang="ts">    import { useIntlayer } from "svelte-intlayer";    // 使用主页内容字典    const homeContent = useIntlayer('home');</script><svelte:head>    <title>{$homeContent.title.value}</title></svelte:head><section>    <h1>        {$homeContent.title}    </h1></section><style>  /*  */</style>
      <script lang="ts">  import { getLocalizedUrl } from "intlayer";  import { useLocale } from "svelte-intlayer";  let { href = "" } = $props();  const { locale } = useLocale();  // 辅助函数:为URL添加当前语言前缀  $: localizedHref = getLocalizedUrl(href, $locale);</script><a href={localizedHref}>  <slot /></a>
      import { goto } from "$app/navigation";import { getLocalizedUrl } from "intlayer";import { useLocale } from "svelte-intlayer";const { locale } = useLocale();const localizedPath = getLocalizedUrl("/about", $locale);goto(localizedPath); // 根据语言环境导航到 /en/about 或 /fr/about
      <script lang="ts">  import { getLocalizedUrl, getLocaleName } from 'intlayer';  import { useLocale } from "svelte-intlayer";  import { page } from '$app/stores';  import { goto } from '$app/navigation';  const { locale, setLocale, availableLocales } = useLocale({    onLocaleChange: (newLocale) => {      const localizedPath = getLocalizedUrl($page.url.pathname, newLocale);      goto(localizedPath);    },  });</script><ul class="locale-list">  {#each availableLocales as localeEl}    <li>      <a        href={getLocalizedUrl($page.url.pathname, localeEl)}        onclick={(e) => {          e.preventDefault();          setLocale(localeEl); // 将在存储中设置语言环境并触发 onLocaleChange        }}        class:active={$locale === localeEl}      >        {getLocaleName(localeEl)}      </a>    </li>  {/each}</ul><style>  /* */</style>
      import { defineConfig } from "vite";import { intlayer, intlayerProxy } from "vite-intlayer";import { sveltekit } from "@sveltejs/kit/vite";// https://vitejs.dev/config/export default defineConfig({  plugins: [    intlayerProxy(), // should be placed first    intlayer(),    sveltekit(),  ],],});
      <script lang="ts">  import { useIntlayer } from "svelte-intlayer";  const content = useIntlayer("component");</script><div>  <!-- 以简单内容方式渲染内容 -->  <h1>{$content.title}</h1>  <!-- 以组件方式渲染内容(编辑器所需) -->  {@const Component = $content.component}<Component /></div>
      # 忽略 Intlayer 生成的文件.intlayer
      npx intlayer extract
      import { defineConfig } from "vite";import { intlayer, intlayerCompiler } from "vite-intlayer";export default defineConfig({ plugins: [   intlayer(),   intlayerCompiler(), // 添加编译器插件 ],});
      npm run build # 或 npm run dev