vue-i18n使用方法

vue-i18n是一个做多语言国际化开发的插件

1.首先安装必要的依赖

npm install vue-i18n@next xlsx --save

2.创建项目目录结构

3.创建 Excel 翻译文件 (translations.xlsx)

4.创建生成脚本(scripts/generateTranslations.js)

import xlsx from 'xlsx';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

// 获取 __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 检查 Excel 文件是否能正常打开和读取:
const excelPath = 'translations.xlsx';
if (!fs.existsSync(excelPath)) {
  console.error(`Excel file not found at: ${excelPath}`);
  process.exit(1);
}

try {
  // 读取 Excel 文件
  console.log('Reading Excel file...');
  const workbook = xlsx.readFile('translations.xlsx');
  
  // 获取第一个工作表
  const sheetName = workbook.SheetNames[0];
  console.log('Sheet name:', sheetName);
  
  const sheet = workbook.Sheets[sheetName];
  
  // 转换为 JSON 并打印第一行数据进行检查
  const data = xlsx.utils.sheet_to_json(sheet);
  console.log('First row of data:', data[0]);
  
  if (!data || data.length === 0) {
    throw new Error('Excel file is empty or has invalid format');
  }

  // 检查数据格式
  if (!data[0].key) {
    throw new Error('Excel file must have a "key" column');
  }

  // 支持的语言列表
  const languages = ["zh-CN","zh-TW","zh-HK","ko","ja","en","de",'es',"nl","pl","no","tr","fi","fr","it",'sv',"hu","lt","bg","lv","ru","cs","da","ro","hr","uk","el","ar","he","ms","id","th","vi","fil","ca","sl","et","pt-PT","pt-BR"];

  // 确保目录存在
  const localesDir = path.join(__dirname, '../src/i18n/locales');
  if (!fs.existsSync(localesDir)) {
    fs.mkdirSync(localesDir, { recursive: true });
  }

  // 生成带注释的对象字符串
  function generateObjectString(obj, indent = 0, zhTranslations = {}) {
    let result = '{\n';
    for (const [key, value] of Object.entries(obj)) {
      const spaces = ' '.repeat(indent + 2);
      if (typeof value === 'object') {
        result += `${spaces}// ${key} 相关翻译\n`;
        result += `${spaces}${key}: ${generateObjectString(value, indent + 2, zhTranslations[key] || {})},\n\n`;
      } else {
        // 获取中文翻译作为注释
        const zhValue = zhTranslations[key] || '';
        result += `${spaces}// ${zhValue}\n`;
        result += `${spaces}${key}: "${value}",\n\n`;
      }
    }
    result += ' '.repeat(indent) + '}';
    return result;
  }

  // 首先生成中文翻译对象(用于其他语言的注释)
  const zhTranslations = {};
  data.forEach(row => {
    const keys = row.key.split('.');
    let current = zhTranslations;
    
    keys.forEach((key, index) => {
      if (index === keys.length - 1) {
        current[key] = row['zh-CN'] || '';
      } else {
        current[key] = current[key] || {};
        current = current[key];
      }
    });
  });

  // 为每种语言生成翻译文件
  languages.forEach(lang => {
    const translations = {};
    
    data.forEach(row => {
      const keys = row.key.split('.');
      let current = translations;
      
      keys.forEach((key, index) => {
        if (index === keys.length - 1) {
          current[key] = row[lang] || '';
        } else {
          current[key] = current[key] || {};
          current = current[key];
        }
      });
    });

    // 生成文件内容
    const fileContent = `// ${lang} 语言包\nexport default ${generateObjectString(translations, 0, zhTranslations)}`;
    
    fs.writeFileSync(
      path.join(localesDir, `${lang}.ts`),
      fileContent
    );
  });

  console.log('Translation files generated执行成功!');
} catch (error) {
  console.error('Error occurred:', error.message);
  console.error('Error details:', error);
  process.exit(1);
}

5.创建 i18n 配置文件 (src/i18n/index.ts)

  import { createI18n } from 'vue-i18n'
import zhCN from './locales/zh-CN'
import en from './locales/en'
import ja from './locales/ja'
import ko from './locales/ko'
// ... 导入其他语言

const i18n = createI18n({
  legacy: false,
  locale: localStorage.getItem('language') || 'zh-CN',
  fallbackLocale: 'en',
  messages: {
    'zh-CN': zhCN,
    'en': en,
    'ja': ja,
    'ko': ko,
    // ... 其他语言
  }
})

export default i18n

6.创建 i18n 插件 (src/plugins/i18n.ts)

  import type { App } from 'vue'
import i18n from '../i18n'

export default {
  // 直接使用$t方法就行
  install: (app: App) => {
    // 添加全局属性
    app.config.globalProperties.$t = i18n.global.t

    // 添加全局方法
    app.provide('i18n', {
      t: i18n.global.t,
      locale: i18n.global.locale
    })

    // 添加全局指令
    app.directive('t', {
      mounted(el, binding) {
        el.textContent = i18n.global.t(binding.value)
      },
      updated(el, binding) {
        el.textContent = i18n.global.t(binding.value)
      }
    })
  }
}

7.在主文件中注册 (src/main.ts)

import { createApp } from 'vue'
import App from './App.vue'
import i18n from './i18n'
import i18nPlugin from './plugins/i18n'

const app = createApp(App)

app.use(i18n)
app.use(i18nPlugin)
app.mount('#app')

8.在 package.json 中添加生成命令

{
  "scripts": {
    "generate-translations": "node scripts/generateTranslations.js"
  }
}

使用示例:

在模板中使用:

<template>
  <div>{{ $t('language.select') }}</div>
</template>

在 store 中使用:

import { defineStore } from 'pinia'
import i18n from '@/i18n'

export const useStore = defineStore('store', {
  state: () => ({
    // ... state
  }),
  getters: {
    translatedText() {
      return i18n.global.t('language.select')
    }
  }
})

语言切换功能:

const handleChangeLanguage = (langCode: string) => {
  // 更新 i18n 语言
  i18n.global.locale.value = langCode
  // 保存到本地存储
  localStorage.setItem('language', langCode)
}
posted @ 2025-03-24 22:53  韩德才  阅读(352)  评论(0)    收藏  举报