import{_ as s,c as i,o as a,aj as n}from"./chunks/framework.DNhrqZu5.js";const F=JSON.parse('{"title":"i18n 文本多语言解决方案","description":"","frontmatter":{},"headers":[],"relativePath":"guide/vue3/i18n.md","filePath":"guide/vue3/i18n.md","lastUpdated":1777342606000}'),h={name:"guide/vue3/i18n.md"},l=n(`

i18n 文本多语言解决方案

项目采用 vue-i18n 实现多语言,并支持按需懒加载语言包,提升首屏加载速度。

目录结构

bash
├── locales
   ├── index.ts          # i18n 配置和初始化
   ├── lang-base.ts      # 基础语言配置
   └── langs
       ├── en-US
   └── common.json
       └── zh-CN
           └── common.json

核心实现

typescript
import { createI18n } from "vue-i18n";
import type { App } from "vue";

const LOCALE_KEY = "lang";
const DEFAULT_LOCALE = "zh-CN";

// 扫描所有语言文件(懒加载)
const modules = import.meta.glob("./langs/**/*.json");

// i18n 实例(初始不加载 messages,按需加载)
export const i18n = createI18n({
  legacy: false,
  globalInjection: true,
  locale: "",
  fallbackLocale: DEFAULT_LOCALE,
  messages: {},
});

// 设置语言
export async function setLang(locale?: string) {
  const target = locale || localStorage.getItem(LOCALE_KEY) || DEFAULT_LOCALE;

  if (!i18n.global.availableLocales.includes(target)) {
    // 按需加载语言包
    const loader = localeLoaders[target];
    if (loader) {
      const messages = await loader();
      i18n.global.setLocaleMessage(target, messages);
    }
  }

  i18n.global.locale.value = target;
  localStorage.setItem(LOCALE_KEY, target);
  document.documentElement.lang = target;
}

// 初始化(main.ts 调用)
export async function setupI18n(app: App) {
  app.use(i18n);
  await setLang();
}

在组件中切换语言

html
<script setup lang="ts">
  import { setLang } from "@/locales";

  const changeLang = (type: string) => {
    setLang(type);
  };
</script>

<template>
  <button @click="changeLang('zh-CN')">中文</button>
  <button @click="changeLang('en-US')">English</button>
</template>

在模板中使用

html
<template>
  <div>{{ $t('common.title') }}</div>
</template>

CSS 图片多语言方案

目前在业务开发中,CSS 的样式多语言也会经常用到。这里提供 scss 的图片多语言方案:

scss
@mixin main-lang-bg($width, $height, $preUrl, $posUrl) {
  width: $width;
  height: $height;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  @include loop-lang-bg($preUrl, $posUrl);
}

@mixin loop-lang-bg($preUrl, $posUrl) {
  $list: zh-CN, en-US;
  @each $i in $list {
    &.#{$i} {
      background-image: url("#{$preUrl}/#{$i}/#{$posUrl}");
    }
  }
}

使用方式

html
<template>
  <div :class="['btn-confirm', i18n.global.locale.value]"></div>
</template>
<script lang="ts" setup>
  import { i18n } from "@/locales";
</script>
<style lang="scss" scoped>
  .btn-confirm {
    @include main-lang-bg(302px, 82px, "@/assets/button", "confirm.png");
  }
</style>
`,15),k=[l];function t(p,e,E,r,g,d){return a(),i("div",null,k)}const c=s(h,[["render",t]]);export{F as __pageData,c as default};