Vue3+tsx+vite+vue-i18n多语言动态国际化配置

1,211 阅读1分钟

1、项目安装vue-i18n

vue-i18n官网地址:vue-i18n.intlify.dev

npm安装: 需要注意的是截至2023-08-29vue-i18n的最新版本为9.2.2,但是在ts中使用这个版本会报一个类型错误,说无法找到vue-i18n的声明文件,具体错误和解决方案请见github.com/intlify/vue…

npm i vue-i18n@^9.3.0-beta.25 -S
// or
pnpm i vue-i18n@^9.3.0-beta.25 -S
// or
yarn add vue-i18n@^9.3.0-beta.25 --save

2、在src下新建language文件夹

image.png

在language文件夹中新建locales文件夹,用于存放语言json,这个json文件的字段最好都一一对应

zh-CN.json

{
  "common": {
    "hello": "你好",
    "home": "首页",
    "test": "测试"
  }
}

en-US.json

{
  "common": {
    "hello": "Hello",
    "home": "home",
    "test": "test"
  }
}

index.ts

import { createI18n } from "vue-i18n";
import zhCN from "./locales/zh-CN.json";
import enUS from "./locales/en-US.json";

const messages = {
  "zh-CN": {
    ...zhCN,
  },
  "en-US": {
    ...enUS,
  },
};

const i18n = createI18n({
  legacy: false, // 现在是composition api,所以设置为false
  locale: "zh-CN", // 设置默认语言
  messages,
});

export default i18n;

3、在main.ts中引入并挂载vue-i18n

main.ts

import { createApp } from "vue";
import App from "./App";

// 引入i18n
import i18n from "./language";

const app = createApp(App);
app.use(i18n); // 全局注册
app.mount("#app");

4、组件中使用

export default defineComponent({
  name: "HomeView",
  setup() {
    const { t, locale } = useI18n();
    console.log(locale.value); // 当前设置的语言
    const active = ref(false);
    // 切换语言
    const changeLanguage = (value: boolean) => {
      if (value) {
        locale.value = "en-US";
      } else {
        locale.value = "zh-CN";
      }
    };

    return () => {
      return (
        <div class="w-[100vw] h-[100vh] px-[20px] py-[20px] overflow-hidden">
          {t("common.hello")}
          <NSwitch v-model:value={active.value} onUpdateValue={changeLanguage} />
        </div>
      );
    };
  },
});

5、添加typescript类型提示

在src下新建types文件夹,types文件夹下新建i18n.ts和index.ts

image.png

i18n.ts

import type zhCN from "@/language/locales/zh-CN.json";

export type Lang = "zh-CN" | "en-US";

export type MessageSchema = typeof zhCN;

type Concat<K extends string, V extends string> = `${K}.${V}`;

type Flatten<T, K extends string = ""> = T extends Record<string, any>
  ? {
      [P in keyof T]: Flatten<T[P], K extends "" ? P : Concat<K, P & string>>;
    }[keyof T]
  : K;

export type MessageKeySchema = Flatten<MessageSchema>;

index.ts

export * from "./i18n";

在每次使用时引入类型

import type { Lang, MessageSchema } from "@/types";

export default defineComponent({
  name: "HomeView",
  setup() {
    const { t, locale } = useI18n<{ message: MessageSchema }, Lang>();
    console.log(locale.value);
    console.log(import.meta.env.VITE_PORT);
    const active = ref(false);
    const test = (value: boolean) => {
      if (value) {
        locale.value = "en-US";
      } else {
        locale.value = "zh-CN";
      }
    };

    return () => {
      return (
        <div class="w-[100vw] h-[100vh] px-[20px] py-[20px] overflow-hidden">
          {t("common.hello")}

          <NSwitch v-model:value={active.value} onUpdateValue={test} />
        </div>
      );
    };
  },
});

这样在写的时候就会有类型提示

image.png