IndieShow 图标IndieShow 使用文档

国际化配置

详细介绍 IndieShow 项目的多语言国际化系统,包括语言配置、翻译文件结构、在组件中使用翻译,以及语言切换功能的实现,帮助你轻松创建多语言网站

IndieShow-Starter-Nuxt 使用 @nuxtjs/i18n 模块提供完整的国际化支持,让您的网站能够服务全球用户。默认支持中文和英文,并且可以轻松扩展到其他语言。

国际化架构概述

项目的国际化系统由以下几个部分组成:

  1. 核心配置: i18n.config.tsi18n/config.ts 中的 i18n 配置
  2. 语言包: i18n/locales/{language}/ 目录存放各语言的翻译文件

基础配置

1. 配置文件

i18n/config.ts

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

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       # 用户交流页面翻译

性能优化,按需加载语言文件:

i18n/locales/zh/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),
}

使用指南

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,它具有以下特点:

  • 支持下拉菜单选择语言
  • 包含无障碍支持
  • 响应式设计
  • 集成工具提示
  • 支持键盘导航
components/common/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.tsLOCALES 数组中添加新语言配置:

i18n/config.ts
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

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

i18n/locales/ko/nav.json
{
  "home": "홈",
  "features": "기능",
  "showcase": "쇼케이스",
  "about": "소개"
}

更新配置

i18n.config.ts 中添加新语言:

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,
  }),
)

常见问题

相关资源

下一步