Vue3+Vue-i18n+I18N ALLY+VSCODE 自动翻译多国语言

news2025/2/25 15:26:31

ps: 效果图放前面,符合的往下看,不符合的出门右转,希望多多点赞评论支持。

请添加图片描述

  • 三种语言模式,分别是中文、英文、日文
    在这里插入图片描述
  • 批量翻译
    在这里插入图片描述
  • 最后的结果
    在这里插入图片描述

配置vue-i18n

1、下载安装vue-i18n,@9以上的版本。
2、创建对应文件夹
在这里插入图片描述
3、对应文件夹中代码如下

helper.ts

import type { LocaleType } from '@/types/i18n';
import { set } from 'lodash-es';

export const loadLocalePool: LocaleType[] = [];

export function setHtmlPageLang(locale: LocaleType) {
    document.querySelector('html')?.setAttribute('lang', locale);
}

export function setLoadLocalePool(cb: (loadLocalePool: LocaleType[]) => void) {
    cb(loadLocalePool);
}
export function genMessage(langs: Record<string, Record<string, any>>, prefix = 'lang') {
    const obj: Recordable = {};
    
    Object.keys(langs).forEach((key) => {
        const langFileModule = langs[key].default;
        let fileName = key.replace(`./${prefix}/`, '').replace(/^\.\//, '');
        const lastIndex = fileName.lastIndexOf('.');
        fileName = fileName.substring(0, lastIndex);
        const keyList = fileName.split('/');
        const moduleName = keyList.shift();
        const objKey = keyList.join('.');

        if (moduleName) {
            if (objKey) {
                set(obj, moduleName, obj[moduleName] || {});
                set(obj[moduleName], objKey, langFileModule);
            } else {
                set(obj, moduleName, langFileModule || {});
            }
        }
    });
    return obj;
}

setupI18n.ts

import type { App } from 'vue';
import type { I18n, I18nOptions } from 'vue-i18n';
import { createI18n } from 'vue-i18n';
import { setHtmlPageLang, setLoadLocalePool } from './helper';
import { useLocaleStore } from '@/store/modules/locale'

export let i18n: ReturnType<typeof createI18n>;
async function createI18nOptions(): Promise<I18nOptions> {
    const store = useLocaleStore()
    const locale = store.getLocalInfo
    const defaultLocal = await import(`./lang/${locale}.ts`);
    const message = defaultLocal.default?.message ?? {};

    setHtmlPageLang(locale);
    setLoadLocalePool((loadLocalePool) => {
        loadLocalePool.push(locale);
    });
    return {
        legacy: false, //false:新版API 
        locale,//当前语言
        fallbackLocale: 'zh_CN', //找不到语言环境,回滚到中文
        messages: {
            [locale]: message, //对应的语言环境具体值
        },
        availableLocales: ['zh_CN', 'en'],//包含的语言种类
        sync: true,  //是否从全局继承语言环境
        silentTranslationWarn: true, //true:关闭翻译警告
        missingWarn: false,//是否显示缺失翻译的警告信息
        silentFallbackWarn: true,//忽略回退警告
    };
}
export async function setupI18n(app: App) {
    const options = await createI18nOptions();
    i18n = createI18n(options) as I18n;
    app.use(i18n);
}

useLocale.ts

import type { LocaleType } from '@/types/i18n';
import { i18n } from './setupI18n';
import { unref, computed } from 'vue';
import { useLocaleStore } from '@/store/modules/locale'
import { loadLocalePool, setHtmlPageLang } from './helper';
interface LangModule {
    message: Recordable;
    dateLocale: Recordable;
    dateLocaleName: string;
}

function setI18nLanguage(locale: LocaleType) {
    const store = useLocaleStore()
    if (i18n.mode === 'legacy') {
        i18n.global.locale = locale;
    } else {
        (i18n.global.locale as any).value = locale;
    }
    store.setLocaleInfo({ locale })
    setHtmlPageLang(locale);
}

export function useLocale() {
    const store = useLocaleStore()
    const getLocale = computed(() => store.getLocalInfo);
    const getShowLocalePicker = computed(() => store.getShowPicker);
    const getAntdLocale = computed((): any => {
        return i18n.global.getLocaleMessage(store.getAntdLocale);
    });
    async function changeLocale(locale: LocaleType) {
        const globalI18n = i18n.global;
        const currentLocale = unref(globalI18n.locale);
        if (currentLocale === locale) {
            return locale;
        }
        if (loadLocalePool.includes(locale)) {
            setI18nLanguage(locale);
            return locale;
        }
        const langModule = ((await import(`./lang/${locale}.ts`)) as any).default as LangModule;
        if (!langModule) return;
        const { message } = langModule;

        globalI18n.setLocaleMessage(locale, message);
        loadLocalePool.push(locale);
        setI18nLanguage(locale);
        return locale;
    }
    return {
        getLocale,
        getShowLocalePicker,
        changeLocale,
        getAntdLocale,
    };
}

4、创建全局当前语言类型值,如果需要刷新保持,还应将值保存到localStorage中。

locale.ts

import { defineStore } from 'pinia';
import type { LocaleType } from '@/types/i18n'
type LocaleState = {
    localInfo: LocaleType,
    availableLocales: LocaleType[],
    showPicker: boolean,
    antdLocale: LocaleType
}
type SetLocalInfoOpt = {
    locale: LocaleType,
}
export const useLocaleStore = defineStore({
    id: 'app-locale',
    state: (): LocaleState => ({
        localInfo: 'zh_CN',
        showPicker: false,
        availableLocales: [],
        antdLocale: 'zh_CN'
    }),
    getters: {
        getLocalInfo(): LocaleType {
            return this.localInfo
        },
        getShowPicker(): boolean {
            return this.showPicker
        },
        getAntdLocale(): LocaleType{
            return this.antdLocale
        }
    },
    actions: {
        setLocaleInfo({ locale }: SetLocalInfoOpt) {
            this.localInfo = locale
        },
    }
})

5、lang文件夹下创建对应翻译的入口en.ts\ja.ts\zh_CH.ts

import { genMessage } from '../helper';
import antdLocale from 'ant-design-vue/es/locale/en_US';//更改对应的类型

const modules:Record<string, Record<string, any>> = import.meta.globEager('./en/**/*.json'); //更改对应的类型
export default {
  message: {
    ...genMessage(modules, 'en'),//更改对应的类型
    antdLocale,
  },
  dateLocale: null,
  dateLocaleName: 'en',//更改对应的类型
};

5、main.ts中引入

import { setupI18n } from '@/locales/setupI18n';
await setupI18n(app);

6、页面中引入

<template>
    <p>
        <a-button @click="onChange('zh_CN')">中文</a-button>
        <a-button @click="onChange('en')">英文</a-button>
        <a-button @click="onChange('ja')">日文</a-button>
    </p>
    <div>{{ t('common.a') }}</div>
    <div>{{ t('common.b') }}</div>
    <div>{{ t('common.c') }}</div>
    <div>{{ t('common.d') }}</div>
    <div>{{ t('common.e') }}</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { useI18n } from '@/hooks/web/useI18n';
import type { LocaleType } from '@/types/i18n';
import { useLocale } from '@/locales/useLocale';
export default defineComponent({
    setup() {

        const { changeLocale } = useLocale();
        const { t } = useI18n();
        async function onChange(local: LocaleType) {
            await changeLocale(local as LocaleType);
        }
        return {
            t,
            onChange
        }
    }
})
</script>
<style lang="less"></style>

至此,页面上的语言切换可以了。接下来是如何自动翻译

VSCODE插件I18n Ally

1、插件市场下载
在这里插入图片描述
2、在.vscode下新建settings.json文件
在这里插入图片描述
3、在配置文件中新增关于i18n的设置。

{
    "i18n-ally.localesPaths": [
        "src/locales/lang"
    ], // 翻译文件路径 (自动生成) 相对于项目根目录的语言环境目录路径
    "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
    "i18n-ally.enabledParsers": [
        "json"
    ],
    "i18n-ally.sourceLanguage": "zh-CN",
    "i18n-ally.displayLanguage": "zh-CN",
    "i18n-ally.enabledFrameworks": [
        "vue",
        "react"
    ],
    // 如下须要手动配置
    "i18n-ally.keystyle": "nested", // 翻译路径格式 (翻译后变量格式 nested:嵌套式  flat:扁平式)
    "i18n-ally.sortKeys": true,
    "i18n-ally.namespace": true,
    "i18n-ally.translate.engines": [
        "google",
        "deepl"
    ], // 翻译器
    "i18n-ally.extract.keygenStyle": "camelCase", // 翻译字段命名样式采用驼峰
}

备注“i18n-ally.localesPaths”这个是你翻译文件的路径、“i18n-ally.translate.engines”翻译器,需要科学上网(fq)。

4、配置成功后,鼠标移动上去会显示当前翻译结果,失败的可以关闭编译器重启。
在这里插入图片描述
5、批量翻译,点击编译器左下角翻译的图标,然后再翻译进度中找到,未翻译的语言。空值右边对应有个地球图标。单击翻译即可。

在这里插入图片描述

有些人写的翻译是json文件有的是TS文件,注意配置的时候和lang文件夹下面的入口文件
不要写错了。
写在最后,有问题可评论,可私聊。欢迎讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/982114.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【迪文屏幕】开发资料

1、应用手册 《T5L DGUSII 应用开发指南202306.pdf》&#xff0c;这个文档上面&#xff0c;详细介绍了各种控件的使用方法。 这个文档可以在官方论坛上找到&#xff0c;也可以直接在csdn上下载。 2、DGUS Tool 界面设计工具&#xff0c;根据所选屏幕的系统选择对应的工具&am…

MES管理系统中,物料BOM为何如此重要

在制造企业中&#xff0c;物料清单&#xff08;BOM&#xff09;是描述产品组成结构的核心文件。它列出了制造产品所需的全部零件和组件&#xff0c;以及这些零件和组件的数量和所需工艺。BOM是MES生产管理系统的主要对象之一&#xff0c;它对于生产计划的制定、工艺路线的选择、…

Redis未授权访问漏洞实战

文章目录 概述Redis概述Redis 介绍Redis 简单使用Redis未授权漏洞危害 漏洞复现启动靶场环境POC漏洞验证EXP漏洞利用 总结 本次测试仅供学习使用&#xff0c;如若非法他用&#xff0c;与平台和本文作者无关&#xff0c;需自行负责&#xff01; 概述 ​ 本文章主要是针对于vulh…

JDK源码解析-ConcurrentHashMap

1. ConcurrentHashMap 思考&#xff1a;HashTable是线程安全的&#xff0c;为什么不推荐使用&#xff1f; HashTable是一个线程安全的类&#xff0c;它使用synchronized来锁住整张Hash表来实现线程安全&#xff0c;即每次锁住整张表让线程独占&#xff0c;相当于所有线程进行…

封装一个贡献度面板组件

说在前面 贡献度面板&#xff08;Contribution Graph&#xff09;是指在代码仓库中按时间展示每位开发者的提交情况的可视化图表。它会显示不同日期的提交次数&#xff0c;并用颜色的深浅表示提交的数量。 贡献度面板展现的好处有以下几点&#xff1a; 可视化展示&#xff1…

Linux常用命令——cpio命令

在线Linux命令查询工具 cpio 用来建立、还原备份档的工具程序 补充说明 cpio命令主要是用来建立或者还原备份档的工具程序&#xff0c;cpio命令可以复制文件到归档包中&#xff0c;或者从归档包中复制文件。 语法 cpio(选项)选项 -0或--null&#xff1a;接受新增列控制字…

Windows11 设置移动热点 共享WIFI无线上网

Windows11 设置移动热点 共享WIFI无线上网 打开设置 键盘同时按下 windows i 在设置中点击 网络和 internet 移动热点 编辑移动热点参数 移动热点无接入上网设备 移动热点接入上网设备

Leetcode.174 地下城游戏

题目链接 Leetcode.174 地下城游戏 hard 题目描述 恶魔们抓住了公主并将她关在了地下城 d u n g e o n dungeon dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里&#xff0c;他必须穿过地下城并通过对抗恶魔来拯救公…

【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka

作者简介 前言 博主之前写过一个完整的MQ系列&#xff0c;包含RabbitMQ、RocketMQ、Kafka&#xff0c;从安装使用到底层机制、原理。专栏地址&#xff1a; https://blog.csdn.net/joker_zjn/category_12142400.html?spm1001.2014.3001.5482 本文是该系列的清单综述&#xf…

ChatGPT集锦

目录 1. 一条指令让ChatGPT变的更强大2. 对ChatGPT提问时,常见的10种错误描述3. Custom instructions如何设置1. 一条指令让ChatGPT变的更强大 在使用GPT的过程中,如何让AI更清晰地了解你的需求很重要?今天分享一个指令,可以让GPT成为你的好同事,与你一起分析和解决问题,…

MySQL数据库进阶实战:优化性能、提高安全性和实现高可用性

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 当涉及到MySQL数据库的进…

【2023年11月第四版教材】第10章《进度管理》(合集篇)

第10章《进度管理》&#xff08;合集篇&#xff09; 1 章节说明2 管理基础3 管理过程3.1 管理的过程★★★3.2 管理ITTO汇总★★★ 4 规划进度管理4.1 进度管理计划★★★5 定义活动5.1 滚动式规划★★★5.2 里程碑清单★★★ 6 排列活动顺序6.1 紧前关系绘图法★★★6.2 箭线图…

SpringMVC(一)

1.SpringMVC简介 1.1 什么是MVC MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器来划分 M:Model,模型层&#xff0c;指工程中的JavaBean,作用是处理数据 JavaBean分为两类&#xff1a; 一类称为实体类Bean:专门存储业务逻辑的&#xff0c;如Student、Us…

mybatisplus多租户原理略解

概述 当前mybatisPlus版本 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.2</version> </dependency>jdk版本&#xff1a;17 springboot版本&#xff1a;…

高速路自动驾驶功能HWP功能定义

一、功能定义 高速路自动驾驶功能HWP是指在一般畅通高速公路或城市快速路上驾驶员可以放开双手双脚&#xff0c;同时注意力可在较长时间内从驾驶环境中转移&#xff0c;做一些诸如看手机、接电话、看风景等活动&#xff0c;该系统最低工作速度为60kph。 如上两种不同环境和速度…

判断数据类型是否为时间区间pd.api.types.is_period_dtype()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 判断数据类型 是否为时间区间 pd.api.types.is_period_dtype() 选择题 下列说法错误的是? import pandas as pd a pd.Series(pd.period_range(2023-01-01, periods3)) print(【显示】a) p…

【Two Stream network (Tsn)】(二) 阅读笔记

贡献 将深度神经网络应用于视频动作识别的难点&#xff0c;是如何同时利用好静止图像上的 appearance information以及物体之间的运动信息motion information。本文主要有三点贡献&#xff1a; 1.提出了一种融合时间流和空间流的双流网络&#xff1b; 2.证明了直接在光流上训…

IDEA运行Java代码报错Command line is too long

Error running xxx: Command line is too long. Shorten command line for xxx or also for Application default configuration.解决方案一 在项目下的.idea/workspace.xml 中 <component name“PropertiesComponent”> 标签下加入 <property name“dynamic.classpa…

学习笔记——Java入门第二季

1.1 介绍类与对象 类和对象的关系&#xff1a; 时间万物皆对象。对象是具体的事物&#xff0c;是类的具体事例 类是抽象的概念&#xff0c;是对象的模板。 new关键字是创建实例对象最重要的标志 Dog duoduonew Dog(); Dog luckynew Dog(); 这样就创建了两个对象并且在java内…

软件系统功能测试的依据

验收测试 一、软件系统功能测试的依据&#xff1a; 采用GB/T 25000.51-2016系统与软件工程系统与软件质量要求和评价(SQuaRE)第51部分&#xff1a;就绪可用软件产品(RUSP)作为测试依据 二、常用功能测试方法&#xff1a; 界面测试 是指对使用界面的软件进行的软件测试&…