修复escape错误
This commit is contained in:
parent
f245f4401d
commit
7d0feb00eb
@ -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"
|
||||
// }
|
||||
// ]
|
||||
]
|
||||
}
|
@ -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>
|
||||
|
@ -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())}
|
||||
}
|
||||
})
|
||||
|
@ -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": " - 语言包文件: {}",
|
||||
|
@ -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: {}",
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
*
|
||||
*/
|
||||
module.exports = {
|
||||
export default {
|
||||
// 在所有语言下生效的格式化器
|
||||
"*":{
|
||||
//[格式化名称]:(value)=>{...},
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 };
|
||||
|
@ -2,15 +2,15 @@
|
||||
"languages": [
|
||||
{
|
||||
"name": "zh",
|
||||
"title": "zh"
|
||||
"title": "中文"
|
||||
},
|
||||
{
|
||||
"name": "en",
|
||||
"title": "en"
|
||||
"title": "英文"
|
||||
},
|
||||
{
|
||||
"name": "de",
|
||||
"title": "de"
|
||||
"title": "德语"
|
||||
}
|
||||
],
|
||||
"defaultLanguage": "zh",
|
||||
|
@ -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:{}",
|
||||
|
@ -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": " - 语言包文件: {}",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
})
|
||||
}),
|
||||
|
Loading…
x
Reference in New Issue
Block a user