修改格式化器全局注册方法

This commit is contained in:
wxzhang 2022-08-25 22:05:29 +08:00
parent ac5ea795dc
commit 0f08a77555
13 changed files with 82 additions and 161 deletions

View File

@ -2,7 +2,7 @@
## 概念
格式化器是`voerkai18n`中引入的用来对翻译内容中的插值变量进行链式处理的一种机制,目的是为不同的语言下对内容中的插值变量进行动态处理机制。格式化器机制为`voerkai18n`中的日期时间、货币等多语言输出提供了强大灵活、可扩展、可配置的处理方案。
格式化器是`voerkai18n`中引入的用来对翻译内容中的插值变量进行链式处理的一种机制,目的是为不同的语言下对内容中的插值变量进行动态处理。格式化器机制为`voerkai18n`中的日期时间、货币等多语言输出提供了强大灵活、可扩展、可配置的处理方案。
格式化器具有以下特点:

View File

@ -6,9 +6,11 @@
- 新增加日期格式化
- 新增加货币格式化
- 调整运行时代码组织
## 2022/8/7
- 更新文档
## 2022/8/5
- 增加语言包补丁功能,可以在应用上线后动态更新修复翻译错误

View File

@ -172,8 +172,6 @@ module.exports =async function compile(langFolder,opts={}){
languages.forEach(lang=>{
generateFormatterFile(lang.name,{formattersFolder,templateContext,moduleType})
})
templateContext.comments = "注册到全局的格式化器"
generateFormatterFile("global",{formattersFolder,templateContext,moduleType})
// 6. 生成编译后的访问入口文件
const entryFile = path.join(langFolder,"index.js")

View File

@ -1,7 +1,5 @@
/**
格式化器用来对翻译文本内容中的插值变量进行处理
如何编写格式器请参阅官网
@ -11,6 +9,7 @@
// import { Formatter,FlexFormatter } from "./runtime"
export default {
// global : true, // 是否注册到全局false只在当前scope生效
// 直接对内置格式化器进行配置,请参阅官网文档
// $config:{
// datetime : {

View File

@ -1,7 +1,5 @@
/**
格式化器用来对翻译文本内容中的插值变量进行处理
如何编写格式器请参阅官网
@ -11,6 +9,7 @@
// import { Formatter,FlexFormatter } from "./runtime"
export default {
// global : true, // 是否注册到全局false只在当前scope生效
// 直接对内置格式化器进行配置,请参阅官网文档
// $config:{
// datetime : {

View File

@ -1,106 +0,0 @@
/**
注册到全局的格式化器
格式化器用来对翻译文本内容中的插值变量进行处理
如何编写格式器请参阅官网
*/
// import { Formatter,FlexFormatter } from "./runtime"
export default {
// 直接对内置格式化器进行配置,请参阅官网文档
// $config:{
// datetime : {
// units : ["Year","Quarter","Month","Week","Day","Hour","Minute","Second","Millisecond","Microsecond"],
// date :{
// long : 'YYYY/MM/DD HH:mm:ss',
// short : "YYYY/MM/DD",
// format : "local"
// },
// quarter : {
// long : ["First Quarter","Second Quarter","Third Quarter","Fourth Quarter"],
// short : ["Q1","Q2","Q3","Q4"],
// format : "short"
// },
// month:{
// long : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
// short : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"],
// format : "long" // 0-长名称1-短名称2-数字
// },
// weekday:{
// long : ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
// short : ["Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat"],
// format : "long", // 0-长名称1-短名称2-数字
// },
// time : {
// long : "HH:mm:ss",
// short : "HH:mm:ss",
// format : 'local'
// },
// timeSlots : {
// slots : [12],
// lowerCases : ["am","pm"],
// upperCases : ["AM","PM"]
// },
// relativeTime : {
// units : ["seconds","minutes","hours","days","weeks","months","years"],
// now : "Now",
// before : "{value} {unit} ago",
// after : "after {value} {unit}"
// }
// },
// currency : {
// default : "{symbol}{value}{unit}",
// long : "{prefix} {symbol}{value}{unit}{suffix}",
// short : "{symbol}{value}{unit}",
// custom : "{prefix} {symbol}{value}{unit}{suffix}",
// format : "default",
// //--
// units : [""," thousands"," millions"," billions"," trillions"], //千,百万,十亿,万亿
// radix : 3, // 进制即三位一进中文是4位一进
// symbol : "$", // 符号
// prefix : "USD", // 前缀
// suffix : "", // 后缀
// division : 3, // ,分割位
// precision : 2, // 精度
// },
// number : {
// division : 3, // , 分割位3代表每3位添加一个,
// precision : 0 // 精度,即保留小数点位置,0代表不限
// },
// empty:{
// //values : [], // 可选定义空值如果想让0,''也为空值可以指定values=[0,'']
// escape : "", // 当空值时显示的备用值
// next : 'break' // 当空值时下一步的行为: break=中止;skip=跳过
// },
// error : {
// //当错误时显示的内容支持的插值变量有message=错误信息,error=错误类名,也可以是一个返回上面内容的同步函数
// escape : null, // 默认当错误时显示空内容
// next : 'break' // 当出错时下一步的行为: break=中止;skip=忽略
// },
// fileSize:{
// brief : ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB","NB","DB"],
// whole : ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "TeraBytes", "PetaBytes", "ExaBytes", "ZetaBytes", "YottaBytes","DoggaBytes"],
// precision: 2 // 小数精度
// }
// },
// 改变特定数据类型的默认格式化器
// $types:{
// Date : dateFormatter,
// Null : value =>"",
// Undefined: value =>"",
// Error : value => "ERROR",
// Boolean : value =>value ? "True":"False",
// Number : numberFormartter
// }
// 以下可以自定义编写格式化器
// xxxx : value => { ... },
// xxxx : (value,$config) => { ... },
// xxxx : (value,...args,$config) => { ... },
// xxxx : Formatter(value,...args,$config) => { ... },
// xxxx : FlexFormatter(value,params,$config) => { ... },
}

View File

@ -1,7 +1,5 @@
/**
格式化器用来对翻译文本内容中的插值变量进行处理
如何编写格式器请参阅官网
@ -11,6 +9,7 @@
// import { Formatter,FlexFormatter } from "./runtime"
export default {
// global : true, // 是否注册到全局false只在当前scope生效
// 直接对内置格式化器进行配置,请参阅官网文档
// $config:{
// datetime : {

View File

@ -2,7 +2,6 @@
import messageIds from "./idMap.js" // 语言ID映射文件
import runtime from "./runtime.js" // 运行时
const { translate,i18nScope } = runtime
import globalFormatters from "./formatters/global.js" // 注册到全局的格式化器
import defaultFormatters from "./formatters/zh.js" // 默认语言格式化器
const activeFormatters = defaultFormatters // 激活语言格式化器
@ -31,7 +30,6 @@ const scopeSettings = {
"namespaces": {}
}
const formatters = {
"*" : globalFormatters,
'zh' : defaultFormatters,
'en' : ()=>import("./formatters/en.js"),
'de' : ()=>import("./formatters/de.js")

View File

@ -1659,8 +1659,8 @@ var en = {
next : 'break' // 当出错时下一步的行为: break=中止;skip=忽略
},
fileSize:{
brief : ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB","NB","DB"],
whole : ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "TeraBytes", "PetaBytes", "ExaBytes", "ZetaBytes", "YottaBytes","DoggaBytes"],
brief: ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB","NB","DB"],
whole:["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "TeraBytes", "PetaBytes", "ExaBytes", "ZetaBytes", "YottaBytes","DoggaBytes"],
precision: 2 // 小数精度
}
},
@ -1965,6 +1965,8 @@ const empty = Formatter$1(function(value,escapeValue,next,$config){
{ value | error('ERROR:{ error}',) } == 显示error.constructor.name
* @param {*} value
* @param {*} escapeValue
* @param {*} next 下一步的行为取值break,ignore
@ -2171,7 +2173,11 @@ var scope = class i18nScope {
if (!isFunction$2(formatter) || typeof name !== "string") {
throw new TypeError("Formatter must be a function");
}
language = Array.isArray(language) ? language: language ? language.split(","): [];
language = Array.isArray(language)
? language
: language
? language.split(",")
: [];
if (asGlobal) {
this.global.registerFormatter(name, formatter, { language });
} else {

View File

@ -2,7 +2,6 @@
import messageIds from "./idMap.js" // 语言ID映射文件
{{if inlineRuntime }}import runtime from "./runtime.js" // 运行时
const { translate,i18nScope } = runtime
import globalFormatters from "./formatters/global.js" // 注册到全局的格式化器
import defaultFormatters from "./formatters/{{defaultLanguage}}.js" // 默认语言格式化器
{{if defaultLanguage === activeLanguage}}const activeFormatters = defaultFormatters{{else}}import activeFormatters from "./formatters/{{activeLanguage}}.js"{{/if}} // 激活语言格式化器
{{else}}import { translate,i18nScope } from "@voerkai18n/runtime"
@ -13,7 +12,6 @@ import defaultMessages from "./{{defaultLanguage}}.js"
{{else}}
const messageIds = require("./idMap")
{{if inlineRuntime }}const { translate,i18nScope } = require("./runtime.js")
const globalFormatters = require("./formatters/global.js") // 注册到全局的格式化器
const defaultFormatters = require("./formatters/{{defaultLanguage}}.js")
{{if defaultLanguage === activeLanguage}}const activeFormatters = defaultFormatters{{else}}const activeFormatters = require("./formatters/{{activeLanguage}}.js"){{/if}}
{{else}}const { translate,i18nScope } = require("@voerkai18n/runtime")
@ -26,7 +24,6 @@ const defaultMessages = require("./{{defaultLanguage}}.js") // 默认语
// 语言配置文件
const scopeSettings = {{@ settings}}
const formatters = {
"*" : globalFormatters,
{{each languages}}{{if $value.name == defaultLanguage}}'{{defaultLanguage}}' : defaultFormatters{{if $index !== languages.length - 1}},{{/if}}
{{else if $value.name == activeLanguage}}{{if defaultLanguage !== activeLanguage}}'{{activeLanguage}}':activeFormatters{{/if}}{{if $index !== languages.length - 1}},{{/if}}
{{else}}'{{$value.name}}' : ()=>import("./formatters/{{$value.name}}.js"){{if $index !== languages.length - 1}},{{'\n\t'}}{{/if}}{{/if}}{{/each}}

View File

@ -1,7 +1,5 @@
/**
{{comments}}
格式化器用来对翻译文本内容中的插值变量进行处理
如何编写格式器请参阅官网
@ -12,6 +10,15 @@
// import { Formatter,FlexFormatter } from "./runtime"
export default{{else}}//const { Formatter,FlexFormatter } = require("./runtime")
module.exports = {{/if}} {
// global : true, // 简单地设置为true,代表当前所有格式化器均注册到全局false只在当前scope生效
// global : { // 仅将里面的格式化器注册到全局
// $config:{... }
// xxxx : value => { ... },
// xxxx : (value,$config) => { ... },
// xxxx : (value,...args,$config) => { ... },
// xxxx : Formatter(value,...args,$config) => { ... },
// xxxx : FlexFormatter(value,params,$config) => { ... },
//}, // 是否注册到全局false只在当前scope生效
// 直接对内置格式化器进行配置,请参阅官网文档
// $config:{
// datetime : {

View File

@ -209,6 +209,7 @@ function getFormatter(scope, activeLanguage, name) {
scope.activeFormatters,
scope.formatters[fallbackLanguage], // 如果指定了回退语言时,也在该回退语言中查找
scope.global.formatters[activeLanguage], // 适用于activeLanguage全局格式化器
scope.global.formatters[fallbackLanguage],
scope.global.formatters["*"], // 适用于所有语言的格式化器
];
for (const formatters of range) {

View File

@ -21,6 +21,7 @@ module.exports = class i18nScope {
typedFormatters: {},
formatters : {},
};
this._initiLanguages()
// 如果不存在全局VoerkaI18n实例说明当前Scope是唯一或第一个加载的作用域则自动创建全局VoerkaI18n实例
if (!globalThis.VoerkaI18n) {
const { I18nManager } = require("./");
@ -51,6 +52,16 @@ module.exports = class i18nScope {
get activeFormatters() {return this._activeFormatters} // 当前作用域激活的格式化器定义 {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () = >{}}
get activeFormatterConfig(){return this._activeFormatterConfig} // 当前格式化器合并后的配置参数,参数已经合并了全局格式化器中的参数
/**
* 对输入的语言配置进行处理
* - 将en配置为默认回退语言
*/
_initiLanguages(){
Object.entries(this._languages).forEach(([name,language])=>{
if(!language.fallback) language.fallback = "en"
})
}
/**
* 在全局注册作用域当前作用域
* @param {*} callback 注册成功后的回调
@ -107,43 +118,20 @@ module.exports = class i18nScope {
})
})
}
/**
* 注册默认文本信息加载器
* @param {Function} 必须是异步函数或者是返回Promise
*/
registerDefaultLoader(fn) {
this.global.registerDefaultLoader(fn);
}
/**
* 获取指定语言信息
* @param {*} language
* @returns
*/
getLanguage(language) {
let index = this._languages.findIndex((lng) => lng.name == language);
if (index !== -1) return this._languages[index];
}
/**
* 返回是否存在指定的语言
* @param {*} language 语言名称
* @returns
*/
hasLanguage(language) {
return this._languages.indexOf((lang) => lang.name == language) !== -1;
}
/**
* 回退到默认语言
*/
_fallback() {
this._messages = this._default;
this._activeLanguage = this.defaultLanguage;
}
/**
* 初始化格式化器
* 激活和默认语言的格式化器采用静态导入的形式而没有采用异步块的形式这是为了确保首次加载时的能马上读取而不能采用延迟加载方式
* _activeFormatters={$config:{...},$types:{...},[格式化器名称]:()=>{...},[格式化器名称]:()=>{...},...}}
*/
_initFormatters(newLanguage){
_initFormatters(newLanguage){
// 全局格式化器,用来注册到全局
Object.entries(this._formatters).forEach(([langName,formatters])=>{
if(formatters.global===true){
this.registerFormatters({[langName]:formatters},true)
}else if(isPlainObject(formatters.global)){
this.registerFormatters({[langName]:formatters.global},true)
}
})
this._activeFormatters = {}
try {
if (newLanguage in this._formatters) {
@ -205,6 +193,39 @@ module.exports = class i18nScope {
}
return this._activeFormatterConfig = options
}
/**
* 注册默认文本信息加载器
* @param {Function} 必须是异步函数或者是返回Promise
*/
registerDefaultLoader(fn) {
this.global.registerDefaultLoader(fn);
}
/**
* 获取指定语言信息
* @param {*} language
* @returns
*/
getLanguage(language) {
let index = this._languages.findIndex((lng) => lng.name == language);
if (index !== -1) return this._languages[index];
}
/**
* 返回是否存在指定的语言
* @param {*} language 语言名称
* @returns
*/
hasLanguage(language) {
return this._languages.indexOf((lang) => lang.name == language) !== -1;
}
/**
* 回退到默认语言
*/
_fallback() {
this._messages = this._default;
this._activeLanguage = this.defaultLanguage;
}
/**
* 刷新当前语言包
* @param {*} newLanguage