国际化配置
详细介绍 IndieShow 项目的多语言国际化系统,包括语言配置、翻译文件结构、在组件中使用翻译,以及语言切换功能的实现,帮助你轻松创建多语言网站
IndieShow-Starter-Nuxt 使用 @nuxtjs/i18n 模块提供完整的国际化支持,让您的网站能够服务全球用户。默认支持中文和英文,并且可以轻松扩展到其他语言。
国际化架构概述
项目的国际化系统由以下几个部分组成:
- 核心配置:
i18n.config.ts和i18n/config.ts中的 i18n 配置 - 语言包:
i18n/locales/{language}/目录存放各语言的翻译文件
基础配置
1. 配置文件
i18n/config.ts
import type { LocaleObject } from "@nuxtjs/i18n"
// 支持的语言列表
export const LOCALES: LocaleObject[] = [
{
code: "en",
iso: "en-US",
name: "English",
dir: "ltr",
file: "en/index.ts",
},
{
code: "zh",
iso: "zh-CN",
name: "中文",
dir: "ltr",
file: "zh/index.ts",
},
]
// 默认语言
export const DEFAULT_LOCALE = "en"
// i18n 配置
export const i18nConfig = {
defaultLocale: DEFAULT_LOCALE,
detectBrowserLanguage: {
useCookie: true,
cookieKey: "i18n_redirected",
alwaysRedirect: true,
redirectOn: "root",
},
langDir: "locales",
lazy: false,
locales: LOCALES,
strategy: "prefix_except_default",
customRoutes: "config",
vueI18n: "../i18n.config.ts",
precompile: {
strictMessage: true,
escapeHtml: true,
},
}i18n.config.ts
import type { I18nOptions } from "vue-i18n"
import { DEFAULT_LOCALE } from "./i18n/config"
export default defineI18nConfig(
(): I18nOptions => ({
legacy: false,
locale: DEFAULT_LOCALE,
fallbackLocale: DEFAULT_LOCALE,
messages: {
en: {},
zh: {},
},
missingWarn: false,
fallbackWarn: false,
silentTranslationWarn: true,
}),
)2. 语言文件结构
项目使用以下目录结构组织语言文件:
i18n/
locales/
en/
index.ts # 英文翻译入口文件
nav.json # 导航栏翻译
seo.json # SEO相关翻译
showcase.json # 展示页面翻译
site.json # 网站基础信息翻译
components.json # 组件相关翻译
cta.json # 号召性用语翻译
features.json # 功能特性翻译
footer.json # 页脚翻译
group.json # 用户交流页面翻译
zh/
index.ts # 中文翻译入口文件
nav.json # 导航栏翻译
seo.json # SEO相关翻译
showcase.json # 展示页面翻译
site.json # 网站基础信息翻译
components.json # 组件相关翻译
cta.json # 号召性用语翻译
features.json # 功能特性翻译
footer.json # 页脚翻译
group.json # 用户交流页面翻译
ko/
index.ts # 韩语翻译入口文件
nav.json # 导航栏翻译
seo.json # SEO相关翻译
showcase.json # 展示页面翻译
site.json # 网站基础信息翻译
components.json # 组件相关翻译
cta.json # 号召性用语翻译
features.json # 功能特性翻译
footer.json # 页脚翻译
group.json # 用户交流页面翻译性能优化,按需加载语言文件:
export default {
nav: await import("./nav.json").then((m) => m.default),
seo: await import("./seo.json").then((m) => m.default),
showcase: await import("./showcase.json").then((m) => m.default),
site: await import("./site.json").then((m) => m.default),
components: await import("./components.json").then((m) => m.default),
cta: await import("./cta.json").then((m) => m.default),
features: await import("./features.json").then((m) => m.default),
footer: await import("./footer.json").then((m) => m.default),
group: await import("./group.json").then((m) => m.default),
}使用指南
1. 基本翻译
<template>
<div>
<h1>{{ $t('home.title') }}</h1>
<p>{{ $t('home.description') }}</p>
<button>{{ $t('common.buttons.get_started') }}</button>
</div>
</template>
<script setup>
const { t } = useI18n()
// 在 script 中使用
const title = t('home.title')
</script>2. 语言切换
项目提供了内置的语言切换组件 CommonLocaleSwitch.vue,它具有以下特点:
- 支持下拉菜单选择语言
- 包含无障碍支持
- 响应式设计
- 集成工具提示
- 支持键盘导航
<script setup lang="ts">
import { onClickOutside } from "@vueuse/core"
import { useI18n } from "#imports"
import { useI18nLocale } from "~/composables/useLocale"
import type { LocaleItem, LocaleObject } from "~/types/i18n"
// 获取国际化相关的方法和状态
const { locales, locale, t } = useI18n()
const { switchLocale } = useI18nLocale()
// 控制语言选择菜单的显示状态
const isLocaleMenuOpen = ref(false)
// 处理语言切换
async function handleLocaleSwitch(item: LocaleItem) {
if (item.value === locale.value) {
isLocaleMenuOpen.value = false
return
}
try {
await switchLocale(item.value)
isLocaleMenuOpen.value = false
}
catch (error) {
console.error("切换语言失败:", error)
}
}
</script>
<template>
<div ref="localeMenuRef" class="relative">
<UTooltip :text="t('components.locale_switch.tooltip')">
<UButton
color="gray"
variant="ghost"
@click="toggleLocaleMenu"
>
<div class="flex items-center space-x-1.5">
<UIcon name="lucide:globe" class="locale-icon" />
<span class="text-sm font-medium">{{ currentLocale.name }}</span>
<UIcon
name="lucide:chevron-down"
:class="{ 'rotate-180': isLocaleMenuOpen }"
/>
</div>
</UButton>
</UTooltip>
<!-- 语言选择下拉菜单 -->
<div
v-show="isLocaleMenuOpen"
class="absolute left-1/2 -translate-x-1/2 top-[60px] w-36 rounded-lg bg-white"
role="menu"
>
<button
v-for="item in localeItems"
:key="item.value"
class="locale-menu-item"
@click="handleLocaleSwitch(item)"
>
<div class="flex items-center w-full">
<div class="w-6 flex items-center justify-center">
<UIcon
v-if="item.value === locale"
name="lucide:check"
class="h-4 w-4"
/>
</div>
<span>{{ item.label }}</span>
</div>
</button>
</div>
</div>
</template>3. 路由国际化
项目使用 prefix_except_default 策略,URL 结构如下:
- 默认语言(英文):
https://yoursite.com/page - 其他语言(中文):
https://yoursite.com/zh/page
在组件中使用 useI18nLocale 组合式函数来处理国际化路由:
<script setup>
import { useI18nLocale } from "~/composables/useLocale"
const { getLocalePath } = useI18nLocale()
// 生成本地化路径
const localizedPath = getLocalePath("/about")
</script>
<template>
<NuxtLink :to="getLocalePath('/')">
{{ t('nav.home') }}
</NuxtLink>
</template>添加新语言
配置语言
在 i18n/config.ts 的 LOCALES 数组中添加新语言配置:
export const LOCALES: LocaleObject[] = [
{
code: "en",
iso: "en-US",
name: "English",
dir: "ltr",
file: "en/index.ts",
},
{
code: "zh",
iso: "zh-CN",
name: "中文",
dir: "ltr",
file: "zh/index.ts",
},
{
code: "ko",
iso: "ko-KR",
name: "한국어",
dir: "ltr",
file: "ko/index.ts",
},
]创建语言目录
在 i18n/locales 目录下创建新语言的文件夹和入口文件:
i18n/
locales/
ko/
index.ts # 入口文件
nav.json # 导航栏翻译
seo.json # SEO相关翻译
showcase.json # 展示页面翻译
site.json # 网站基础信息翻译
components.json # 组件相关翻译
cta.json # 号召性用语翻译
features.json # 功能特性翻译
footer.json # 页脚翻译
group.json # 分组相关翻译添加入口文件
创建新语言的入口文件 i18n/locales/ko/index.ts:
export default {
nav: await import("./nav.json").then((m) => m.default),
seo: await import("./seo.json").then((m) => m.default),
showcase: await import("./showcase.json").then((m) => m.default),
site: await import("./site.json").then((m) => m.default),
components: await import("./components.json").then((m) => m.default),
cta: await import("./cta.json").then((m) => m.default),
features: await import("./features.json").then((m) => m.default),
footer: await import("./footer.json").then((m) => m.default),
group: await import("./group.json").then((m) => m.default),
}添加翻译文件
创建所有必需的翻译文件,例如 nav.json:
{
"home": "홈",
"features": "기능",
"showcase": "쇼케이스",
"about": "소개"
}更新配置
在 i18n.config.ts 中添加新语言:
export default defineI18nConfig(
(): I18nOptions => ({
legacy: false,
locale: DEFAULT_LOCALE,
fallbackLocale: DEFAULT_LOCALE,
messages: {
en: {},
zh: {},
ko: {},
},
missingWarn: false,
fallbackWarn: false,
silentTranslationWarn: true,
}),
)