修复escape错误

This commit is contained in:
wxzhang 2022-08-08 18:28:56 +08:00
parent f245f4401d
commit 7d0feb00eb
15 changed files with 164 additions and 315 deletions

View File

@ -1,24 +1,17 @@
const i18nPlugin =require("@voerkai18n/babel")
module.exports = {
presets: [
"@babel/preset-env",
{
corejs: {
useBuiltIns: 'entry',
version: "3.8",
proposals: true
}
}
"@babel/preset-env"
],
plugins: [
[
i18nPlugin,
{
// 可选,指定语言文件存放的目录,即保存编译后的语言文件的文件夹
// 可以指定相对路径,也可以指定绝对路径
// location:"",
autoImport:"/src/languages/index.js"
}
]
// [
// i18nPlugin,
// {
// // 可选,指定语言文件存放的目录,即保存编译后的语言文件的文件夹
// // 可以指定相对路径,也可以指定绝对路径
// // location:"",
// autoImport:"/src/languages/index.js"
// }
// ]
]
}

View File

@ -1,5 +1,5 @@
<script setup>
import {reactive } from 'vue'
import { reactive } from 'vue'
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
@ -7,61 +7,66 @@ import China from './components/china.vue'
import Formatters from './components/formatters.vue'
let messages = reactive({
name: t('VoerkaI18n多语言解决方案 ')
name: t('VoerkaI18n多语言解决方案 ')
})
console.log("App=",messages.name)
console.log("App=", messages.name)
setTimeout(() => {
messages.name = 'Vue App 2'
messages.name = 'Vue App 2'
}, 5000)
// console.log(t("Hello world!"))
</script>
<script>
import {reactive } from 'vue'
import { reactive } from 'vue'
export default {
inject: ['i18n'],
data() {
return {
language: this.i18n.activeLanguage,
inject: ['i18n'],
data() {
return {
language: this.i18n.activeLanguage,
}
},
watch: {
},
methods: {
async changeLanguage(value) {
this.i18n.activeLanguage = value
//this.activeLanguage = value
// await this.i18n.change(this.language)
}
}
},
watch: {
},
methods: {
async changeLanguage(value) {
this.i18n.activeLanguage = value
//this.activeLanguage = value
// await this.i18n.change(this.language)
}
}
}
</script>
<template>
<div>
<img alt="Vue logo" src="./assets/logo.png" />
<h1>{{ t("中华人民共和国")}} </h1>
<h2>{{ t("迎接中华民族的伟大复兴")}} </h2>
<China :title="t('中华人民共和国')" />
<Formatters/>
<div>
<img alt="Vue logo" src="./assets/logo.png" />
<h1>{{ t("中华人民共和国") }} </h1>
<h2>{{ t("迎接中华民族的伟大复兴") }} </h2>
<China :title="t('中华人民共和国')" />
<Formatters />
<h5>默认语言{{ i18n.defaultLanguage }}</h5>
<h5>当前语言{{ i18n.activeLanguage.value }}</h5>
<button :key="lng.name" v-for="lng of i18n.languages" @click="i18n.activeLanguage = lng.name" style="padding:8px;margin:8px;cursor:pointer" :style="{'outline' : lng.name === i18n.activeLanguage.value ? '2px red solid' : ''}" >{{ lng.title }}</button>
<button @click="i18n.activeLanguage = 'de'" style="padding:8px;margin:8px;cursor:pointer" :style="{'outline' : i18n.activeLanguage.value === 'de' ? '2px red solid' : ''}" >德语</button>
<button @click="i18n.activeLanguage = 'jp'" style="padding:8px;margin:8px;cursor:pointer" :style="{'outline' : i18n.activeLanguage.value === 'jp' ? '2px red solid' : ''}" >日语</button>
</div>
<button :key="lng.name" v-for="lng of i18n.languages" @click="i18n.activeLanguage = lng.name"
style="padding:8px;margin:8px;cursor:pointer"
:style="{ 'outline': lng.name === i18n.activeLanguage.value ? '2px red solid' : '' }">{{ lng.title
}}</button>
<button @click="i18n.activeLanguage = 'de'" style="padding:8px;margin:8px;cursor:pointer"
:style="{ 'outline': i18n.activeLanguage.value === 'de' ? '2px red solid' : '' }">德语</button>
<button @click="i18n.activeLanguage = 'jp'" style="padding:8px;margin:8px;cursor:pointer"
:style="{ 'outline': i18n.activeLanguage.value === 'jp' ? '2px red solid' : '' }">日语</button>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

View File

@ -1,4 +1,4 @@
import { defineConfig } from 'vite'
import { defineConfig,loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import legacy from '@vitejs/plugin-legacy'
import { babel } from '@rollup/plugin-babel';
@ -19,5 +19,8 @@ export default defineConfig({
alias:{
//"voerkai18n":"./languages/index.js"
}
},
define:{
'process.env':{...process.env, ...loadEnv("dev", process.cwd())}
}
})

View File

@ -1,8 +1,8 @@
module.exports = {
"1": "支持的语言\\t: {}",
"2": "默认语言\\t: {}",
"3": "激活语言\\t: {}",
"4": "名称空间\\t: {}",
export default {
"1": "支持的语言\t: {}",
"2": "默认语言\t: {}",
"3": "激活语言\t: {}",
"4": "名称空间\t: {}",
"5": " - 更新格式化器:{}",
"6": " - 访问入口文件: {}",
"7": "加载多语言配置文件<{}>失败: {} ",
@ -26,7 +26,7 @@ module.exports = {
"25": "编译指定项目的语言包",
"26": "输出模块类型,取值auto,esm,cjs",
"27": "语言包文件夹<{}>不存在",
"28": "语言配置文件{}文件已存在,跳过创建。\\n使用{}可以重新覆盖创建",
"28": "语言配置文件{}文件已存在,跳过创建。\n使用{}可以重新覆盖创建",
"29": "生成语言配置文件:{}",
"30": "拟支持的语言:{}",
"31": "初始化成功,下一步:",
@ -34,7 +34,7 @@ module.exports = {
"33": " - 运行<{}>扫描提取要翻译的文本",
"34": " - 运行<{}>编译语言包",
"35": "创建语言包文件夹: {}",
"36": "模块类型\\t: {}",
"36": "模块类型\t: {}",
"37": "编译结果输出至:{}",
"38": "读取语言文件{}失败:{}",
"39": " - 语言包文件: {}",

View File

@ -1,8 +1,8 @@
module.exports = {
"1": "Supported languages\\t: {}",
"2": "Default language\\t: {}",
"3": "Active language\\t\\t: {}",
"4": "Namespaces\\t\\t: {}",
export default {
"1": "Supported languages\t: {}",
"2": "Default language\t: {}",
"3": "Active language\t\t: {}",
"4": "Namespaces\t\t: {}",
"5": " - Update formatters:{}",
"6": " - Entry of language: {}",
"7": "Failed to load multilingual configuration file <{}>: {}",
@ -26,7 +26,7 @@ module.exports = {
"25": "Compiles the language messages for project",
"26": "Output module type, values auto, esm, cjs",
"27": "The language messages folder <{}> does not exist",
"28": "Language configuration {} file already exists, skipping creation\\n use {} to overwrite the creation",
"28": "Language configuration {} file already exists, skipping creation\n use {} to overwrite the creation",
"29": "Generate language configuration: {}",
"30": "Languages to be supported{}",
"31": "Initialization succeeded, next step",
@ -34,7 +34,7 @@ module.exports = {
"33": " - Run <{}> scan to extract the messages to be translated",
"34": " - Run <{}> compile language messages",
"35": "Create <languages> folder: {}",
"36": "Type of module\\t\\t: {}",
"36": "Type of module\t\t: {}",
"37": "Compile to{}",
"38": "Error while read language file{}: {}",
"39": " - Language file: {}",

View File

@ -46,7 +46,7 @@
*
*/
module.exports = {
export default {
// 在所有语言下生效的格式化器
"*":{
//[格式化名称]:(value)=>{...},

View File

@ -1,8 +1,8 @@
module.exports = {
"支持的语言\\t: {}": 1,
"默认语言\\t: {}": 2,
"激活语言\\t: {}": 3,
"名称空间\\t: {}": 4,
export default {
"支持的语言\t: {}": 1,
"默认语言\t: {}": 2,
"激活语言\t: {}": 3,
"名称空间\t: {}": 4,
" - 更新格式化器:{}": 5,
" - 访问入口文件: {}": 6,
"加载多语言配置文件<{}>失败: {} ": 7,
@ -26,7 +26,7 @@ module.exports = {
"编译指定项目的语言包": 25,
"输出模块类型,取值auto,esm,cjs": 26,
"语言包文件夹<{}>不存在": 27,
"语言配置文件{}文件已存在,跳过创建。\\n使用{}可以重新覆盖创建": 28,
"语言配置文件{}文件已存在,跳过创建。\n使用{}可以重新覆盖创建": 28,
"生成语言配置文件:{}": 29,
"拟支持的语言:{}": 30,
"初始化成功,下一步:": 31,
@ -34,7 +34,7 @@ module.exports = {
" - 运行<{}>扫描提取要翻译的文本": 33,
" - 运行<{}>编译语言包": 34,
"创建语言包文件夹: {}": 35,
"模块类型\\t: {}": 36,
"模块类型\t: {}": 36,
"编译结果输出至:{}": 37,
"读取语言文件{}失败:{}": 38,
" - 语言包文件: {}": 39,

View File

@ -1,9 +1,10 @@
const messageIds = require("./idMap")
const { translate,i18nScope } = require("./runtime.js")
import messageIds from "./idMap.js"
import runtime from "./runtime.js"
const { translate,i18nScope } = runtime
const formatters = require("./formatters.js")
const defaultMessages = require("./zh.js")
import formatters from "./formatters.js"
import defaultMessages from "./zh.js"
const activeMessages = defaultMessages
@ -12,15 +13,15 @@ const scopeSettings = {
"languages": [
{
"name": "zh",
"title": "zh"
"title": "中文"
},
{
"name": "en",
"title": "en"
"title": "英文"
},
{
"name": "de",
"title": "de"
"title": "德语"
}
],
"defaultLanguage": "zh",
@ -44,6 +45,8 @@ const scope = new i18nScope({
// 翻译函数
const scopedTtranslate = translate.bind(scope)
module.exports.t = scopedTtranslate
module.exports.i18nScope = scope
export {
scopedTtranslate as t,
scope as i18nScope
}

View File

@ -1,11 +1,9 @@
'use strict';
/**
* 判断是否是JSON对象
* @param {*} obj
* @returns
*/
function isPlainObject$2(obj){
function isPlainObject$1(obj){
if (typeof obj !== 'object' || obj === null) return false;
var proto = Object.getPrototypeOf(obj);
if (proto === null) return true;
@ -82,7 +80,7 @@ function deepMerge$1(toObj,formObj,options={}){
var utils ={
isPlainObject: isPlainObject$2,
isPlainObject: isPlainObject$1,
isNumber: isNumber$1,
deepMerge: deepMerge$1,
getDataTypeName: getDataTypeName$1
@ -121,24 +119,21 @@ var eventemitter = class EventEmitter{
}
};
const { isPlainObject: isPlainObject$1 } = utils;
const DataTypes$1 = ["String","Number","Boolean","Object","Array","Function","Null","Undefined","Symbol","Date","RegExp","Error"];
var scope = class i18nScope {
constructor(options={},callback){
// 每个作用域都有一个唯一的id
this._id = options.id || (new Date().getTime().toString()+parseInt(Math.random()*1000));
this._languages = options.languages; // 当前作用域的语言列表
this._languages = options.languages; // 当前作用域的语言列表
this._defaultLanguage = options.defaultLanguage || "zh"; // 默认语言名称
this._activeLanguage = options.activeLanguage; // 当前语言名称
this._activeLanguage = options.activeLanguage; // 当前语言名称
this._default = options.default; // 默认语言包
this._messages = options.messages; // 当前语言包
this._idMap = options.idMap; // 消息id映射列表
this._formatters = options.formatters; // 当前作用域的格式化函数列表
this._loaders = options.loaders; // 异步加载语言文件的函数列表
this._global = null; // 引用全局VoerkaI18n配置注册后自动引用
this._patchMessages = {}; // 语言包补丁信息 {<language>:{....},<language>:{....}}
// 主要用来缓存格式化器的引用,当使用格式化器时可以直接引用,避免检索
this.$cache={
activeLanguage : null,
@ -154,10 +149,8 @@ var scope = class i18nScope {
activeLanguage : this.activeLanguage,
languages: options.languages,
});
}
}
this.global = globalThis.VoerkaI18n;
this._mergePatchedMessages();
this._patch(this._messages,this.activeLanguage);
// 正在加载语言包标识
this._loading=false;
// 在全局注册作用域
@ -177,8 +170,6 @@ var scope = class i18nScope {
get idMap(){return this._idMap}
// 当前作用域的格式化函数列表
get formatters(){return this._formatters}
// 当前作用域支持的语言
get languages(){return this._languages}
// 异步加载语言文件的函数列表
get loaders(){return this._loaders}
// 引用全局VoerkaI18n配置注册后自动引用
@ -202,13 +193,6 @@ var scope = class i18nScope {
this.formatters[language][name] = formatter;
}
}
/**
* 注册默认文本信息加载器
* @param {Function} 必须是异步函数或者是返回Promise
*/
registerDefaultLoader(fn){
this.global.registerDefaultLoader(fn);
}
/**
* 回退到默认语言
*/
@ -226,90 +210,22 @@ var scope = class i18nScope {
// 默认语言,默认语言采用静态加载方式,只需要简单的替换即可
if(newLanguage === this.defaultLanguage){
this._messages = this._default;
await this._patch(this._messages,newLanguage); // 异步补丁
return
}
// 非默认语言需要异步加载语言包文件,加载器是一个异步函数
// 如果没有加载器,则无法加载语言包,因此回退到默认语言
let loader = this.loaders[newLanguage];
try{
if(typeof(loader) === "function"){
const loader = this.loaders[newLanguage];
if(typeof(loader) === "function"){
try{
this._messages = (await loader()).default;
this._activeLanguage = newLanguage;
await this._patch(this._messages,newLanguage);
}else if(typeof(this.global.defaultMessageLoader) === "function"){// 如果该语言没有指定加载器,则使用全局配置的默认加载器
this._messages = await this.global.loadMessagesFromDefaultLoader(newLanguage,this);
this._activeLanguage = newLanguage;
}else {
}catch(e){
console.warn(`Error while loading language <${newLanguage}> on i18nScope(${this.id}): ${e.message}`);
this._fallback();
}
}catch(e){
console.warn(`Error while loading language <${newLanguage}> on i18nScope(${this.id}): ${e.message}`);
}
}else {
this._fallback();
}
}
/**
* 当指定了默认语言包加载器后会从服务加载语言补丁包来更新本地的语言包
*
* 补丁包会自动存储到本地的LocalStorage中
*
* @param {*} messages
* @param {*} newLanguage
* @returns
*/
async _patch(messages,newLanguage){
if(typeof(this.global.loadMessagesFromDefaultLoader) !== 'function') return
try{
let pachedMessages = await this.global.loadMessagesFromDefaultLoader(newLanguage,this);
if(isPlainObject$1(pachedMessages)){
Object.assign(messages,pachedMessages);
this._savePatchedMessages(pachedMessages,newLanguage);
}
}catch{}
}
/**
* 从本地存储中读取语言包补丁合并到当前语言包中
*/
_mergePatchedMessages(){
let patchedMessages= this._getPatchedMessages(this.activeLanguage);
if(isPlainObject$1(patchedMessages)){
Object.assign(this._messages,patchedMessages);
}
}
/**
* 将读取的补丁包保存到本地的LocalStorage中
*
* 为什么要保存到本地的LocalStorage中
*
* 因为默认语言是静态嵌入到源码中的而加载语言包补丁是延后异步的
* 当应用启动第一次就会渲染出来的是没有打过补丁的内容
*
* - 如果还需要等待从服务器加载语言补丁合并后再渲染会影响速度
* - 如果不等待从服务器加载语言补丁就渲染则会先显示未打补丁的内容然后在打完补丁后再对应用进行重新渲染生效
* 这明显不是个好的方式
*
* 因此采用的方式是
* - 加载语言包补丁后将之保存到到本地的LocalStorage中
* - 当应用加载时会查询是否存在补丁如果存在就会合并渲染
* -
*
* @param {*} messages
*/
_savePatchedMessages(messages,language){
try{
if(globalThis.localStorage){
globalThis.localStorage.setItem(`voerkai18n_${this.id}_${language}_patched_messages`, JSON.stringify(messages));
}
}catch(e){
console.error("Error while save voerkai18n patched messages:",e.message);
}
}
_getPatchedMessages(language){
try{
return JSON.parse(localStorage.getItem(`voerkai18n_${this.id}_${language}_patched_messages`))
}catch(e){
return {}
}
}
}
// 以下方法引用全局VoerkaI18n实例的方法
get on(){return this.global.on.bind(this.global)}
@ -362,28 +278,20 @@ var formatters = {
$types:{
Date:(value)=>value.toLocaleString()
},
// 日期
date: (value)=> value.toLocaleDateString(),
shortdate: (value)=> `${value.getFullYear()}-${value.getMonth()+1}-${value.getDate()}`,
// 时间
time:(value)=> value.toLocaleTimeString(),
shorttime:(value)=> value.toLocaleTimeString(),
date: (value)=> value.toLocaleDateString(),
dict, //字典格式化器
},
zh:{
$types:{
Date:(value)=> `${value.getFullYear()}${value.getMonth()+1}${value.getDate()}${value.getHours()}${value.getMinutes()}${value.getSeconds()}`
},
// 日期
date: (value)=> `${value.getFullYear()}${value.getMonth()+1}${value.getDate()}`,
shortdate: (value)=> `${value.getFullYear()}-${value.getMonth()+1}-${value.getDate()}`,
// 时间
shortime:(value)=> value.toLocaleTimeString(),
time:(value)=>`${value.getHours()}${value.getMinutes()}${value.getSeconds()}`,
// 货币
currency:(value)=>`${value}`,
date: (value)=> `${value.getFullYear()}${value.getMonth()+1}${value.getDate()}`,
shortdate: (value)=> `${value.getFullYear()}-${value.getMonth()+1}-${value.getDate()}`,
currency:(value)=>`${value}`,
},
en:{
currency:(value)=>{
@ -931,7 +839,6 @@ function translate(message) {
I18nManager.instance = this;
this._settings = deepMerge(defaultLanguageSettings,settings);
this._scopes=[];
this._defaultMessageLoader = null; // 默认文本加载器
return I18nManager.instance;
}
get settings(){ return this._settings }
@ -944,22 +851,17 @@ function translate(message) {
get languages(){ return this._settings.languages}
// 内置格式化器
get formatters(){ return inlineFormatters }
get defaultMessageLoader(){ return this._defaultMessageLoader}
// 通过默认加载器加载文件
async loadMessagesFromDefaultLoader(newLanguage,scope){
if(typeof(this._defaultMessageLoader) != "function") return //throw new Error("No default message loader specified")
return await this._defaultMessageLoader.call(scope,newLanguage,scope)
}
/**
* 切换语言
*/
async change(value){
value=value.trim();
if(this.languages.findIndex(lang=>lang.name === value)!==-1 || typeof(this._defaultMessageLoader)==="function"){
if(this.languages.findIndex(lang=>lang.name === value)!==-1){
// 通知所有作用域刷新到对应的语言包
await this._refreshScopes(value);
this._settings.activeLanguage = value;
await this.emit(value); /// 触发语言切换事件
this._settings.activeLanguage = value;
/// 触发语言切换事件
await this.emit(value);
}else {
throw new Error("Not supported language:"+value)
}
@ -981,7 +883,7 @@ function translate(message) {
}
}catch(e){
console.warn("Error while refreshing i18n scopes:",e.message);
}
}
}
/**
*
@ -1019,25 +921,6 @@ function translate(message) {
this.formatters[language][name] = formatter;
}
}
/**
* 注册默认文本信息加载器
*/
registerDefaultLoader(fn){
if(typeof(fn) !== 'function') throw new Error("The default loader must be a async function or promise returned")
this._defaultMessageLoader = fn;
this.refresh();
}
async refresh(){
try{
let requests = this._scopes.map(scope=>scope.refresh());
if(Promise.allSettled){
await Promise.allSettled(requests);
}else {
await Promise.all(requests);
}
}catch{}
}
}
var runtime ={
@ -1052,4 +935,4 @@ var runtime ={
isPlainObject
};
module.exports = runtime;
export { runtime as default };

View File

@ -2,15 +2,15 @@
"languages": [
{
"name": "zh",
"title": "zh"
"title": "中文"
},
{
"name": "en",
"title": "en"
"title": "英文"
},
{
"name": "de",
"title": "de"
"title": "德语"
}
],
"defaultLanguage": "zh",

View File

@ -1,35 +1,35 @@
{
"支持的语言\\t: {}": {
"en": "Supported languages\\t: {}",
"支持的语言\t: {}": {
"en": "Supported languages\t: {}",
"$file": [
"compile.command.js",
"extract.plugin.js"
],
"de": "支持的语言\\t: {}"
"de": "支持的语言\t: {}"
},
"默认语言\\t: {}": {
"en": "Default language\\t: {}",
"默认语言\t: {}": {
"en": "Default language\t: {}",
"$file": [
"compile.command.js",
"extract.plugin.js"
],
"de": "默认语言\\t: {}"
"de": "默认语言\t: {}"
},
"激活语言\\t: {}": {
"en": "Active language\\t\\t: {}",
"激活语言\t: {}": {
"en": "Active language\t\t: {}",
"$file": [
"compile.command.js",
"extract.plugin.js"
],
"de": "激活语言\\t: {}"
"de": "激活语言\t: {}"
},
"名称空间\\t: {}": {
"en": "Namespaces\\t\\t: {}",
"名称空间\t: {}": {
"en": "Namespaces\t\t: {}",
"$file": [
"compile.command.js",
"extract.plugin.js"
],
"de": "名称空间\\t: {}"
"de": "名称空间\t: {}"
},
" - 更新格式化器:{}": {
"en": " - Update formatters:{}",
@ -192,12 +192,12 @@
],
"de": "语言包文件夹<{}>不存在"
},
"语言配置文件{}文件已存在,跳过创建。\\n使用{}可以重新覆盖创建": {
"en": "Language configuration {} file already exists, skipping creation\\n use {} to overwrite the creation",
"语言配置文件{}文件已存在,跳过创建。\n使用{}可以重新覆盖创建": {
"en": "Language configuration {} file already exists, skipping creation\n use {} to overwrite the creation",
"$file": [
"init.command.js"
],
"de": "语言配置文件{}文件已存在,跳过创建。\\n使用{}可以重新覆盖创建"
"de": "语言配置文件{}文件已存在,跳过创建。\n使用{}可以重新覆盖创建"
},
"生成语言配置文件:{}": {
"en": "Generate language configuration: {}",
@ -248,12 +248,12 @@
],
"de": "创建语言包文件夹: {}"
},
"模块类型\\t: {}": {
"en": "Type of module\\t\\t: {}",
"模块类型\t: {}": {
"en": "Type of module\t\t: {}",
"$file": [
"compile.command.js"
],
"de": "模块类型\\t: {}"
"de": "模块类型\t: {}"
},
"编译结果输出至:{}": {
"en": "Compile to{}",

View File

@ -1,8 +1,8 @@
module.exports = {
"1": "支持的语言\\t: {}",
"2": "默认语言\\t: {}",
"3": "激活语言\\t: {}",
"4": "名称空间\\t: {}",
export default {
"1": "支持的语言\t: {}",
"2": "默认语言\t: {}",
"3": "激活语言\t: {}",
"4": "名称空间\t: {}",
"5": " - 更新格式化器:{}",
"6": " - 访问入口文件: {}",
"7": "加载多语言配置文件<{}>失败: {} ",
@ -26,7 +26,7 @@ module.exports = {
"25": "编译指定项目的语言包",
"26": "输出模块类型,取值auto,esm,cjs",
"27": "语言包文件夹<{}>不存在",
"28": "语言配置文件{}文件已存在,跳过创建。\\n使用{}可以重新覆盖创建",
"28": "语言配置文件{}文件已存在,跳过创建。\n使用{}可以重新覆盖创建",
"29": "生成语言配置文件:{}",
"30": "拟支持的语言:{}",
"31": "初始化成功,下一步:",
@ -34,7 +34,7 @@ module.exports = {
"33": " - 运行<{}>扫描提取要翻译的文本",
"34": " - 运行<{}>编译语言包",
"35": "创建语言包文件夹: {}",
"36": "模块类型\\t: {}",
"36": "模块类型\t: {}",
"37": "编译结果输出至:{}",
"38": "读取语言文件{}失败:{}",
"39": " - 语言包文件: {}",

View File

@ -428,48 +428,6 @@ function getPluraMessage(messages,value){
}
}
// if(!String.prototype.replaceAll){
// String.prototype.replaceAll = function(searchValue,replaceValue){
// if (!searchValue) return this
// if(typeof(searchValue)==="string"){
// return this.replace(new RegExp(searchValue,"gm"),replaceValue);
// }else if (searchValue instanceof RegExp) {
// const { global: globalFlag } = searchValue;
// if (!globalFlag) {
// throw new TypeError(
// '`String.prototype.replaceAll` ponyfill called with a non-global RegExp argument'
// );
// }
// return this.replace(searchValue, replaceValue);
// }
// }
// }
function escape(str){
return str.replaceAll(/\\(?![trnbvf'"]{1})/g,"\\\\")
.replaceAll("\t","\\t")
.replaceAll("\n","\\n")
.replaceAll("\b","\\b")
.replaceAll("\r","\\r")
.replaceAll("\f","\\f")
.replaceAll("\'","\\'")
.replaceAll('\"','\\"')
.replaceAll('\v','\\v')
}
function unescape(str){
return str
.replaceAll("\\t","\t")
.replaceAll("\\n","\n")
.replaceAll("\\b","\b")
.replaceAll("\\r","\r")
.replaceAll("\\f","\f")
.replaceAll("\\'","\'")
.replaceAll('\\"','\"')
.replaceAll('\\v','\v')
.replaceAll(/\\\\(?![trnbvf'"]{1})/g,"\\")
}
/**
* 翻译函数
*
@ -532,10 +490,8 @@ function translate(message) {
}else{
// 2.2 从当前语言包中取得翻译文本模板字符串
// 如果没有启用babel插件将源文本转换为msgId需要先将文本内容转换为msgId
// JSON.stringify在进行转换时会将\t\n\r转换为\\t\\n\\r,这样在进行匹配时就出错
let msgId = isMessageId(content) ? content : scope.idMap[escape(content)]
let msgId = isMessageId(content) ? content : scope.idMap[content]
content = scope.messages[msgId] || content
content = Array.isArray(content) ? content.map(v=>unescape(v)) : unescape(content)
}
// 2. 处理复数
// 经过上面的处理content可能是字符串或者数组
@ -550,8 +506,7 @@ function translate(message) {
}else{ // 如果找不到复数变量,则使用第一个内容
content = content[0]
}
}
}
// 进行插值处理
if(vars.length==0){
return content

View File

@ -56,24 +56,13 @@ const importTRegex = /^[^\w\r\n]*import\s*\{(.*)\bt\b(.*)\}\sfrom/gm
}
function escape(str){
return str.replaceAll(/\\(?![trnbvf'"]{1})/g,"\\\\")
.replaceAll("\t","\\t")
.replaceAll("\n","\\n")
.replaceAll("\b","\\b")
.replaceAll("\r","\\r")
.replaceAll("\f","\\f")
.replaceAll("\'","\\'")
.replaceAll('\"','\\"')
.replaceAll('\v','\\v')
}
function replaceCode(code, idmap) {
return code.replaceAll(TranslateRegex, (text) => {
let message = escape(text)
return code.replaceAll(TranslateRegex, (message) => {
if(message in idmap) {
return idmap[message]
}else{
return text
return message
}
})
}

View File

@ -11,8 +11,25 @@
*/
import { cat } from "shelljs"
import { computed,reactive,ref } from "vue"
function forceUpdate(app){
function updateComponent(inst){
if(inst && inst.update) inst.update()
if(inst.subTree && inst.subTree.children){
inst.subTree.children.forEach( vnode=>{
if(vnode && vnode.component) updateComponent(vnode.component)
})
}
}
try{
renderComponent(app._instance.root)
}catch(e){
console.warn("forceUpdate error: ",e.message)
}
}
export default {
install: (app, opts={}) => {
let options = Object.assign({
@ -46,7 +63,8 @@ export default {
get: () => activeLanguage,
set: (value) => i18nScope.global.change(value).then(()=>{
if(options.forceUpdate){
app._instance.update()
//app._instance.update()
forceUpdate(app)
}
})
}),