update typescript runtime

This commit is contained in:
wxzhang 2023-04-02 22:01:20 +08:00
parent f59c165e71
commit 64f9eaa93a
7 changed files with 316 additions and 138 deletions

View File

@ -530,6 +530,7 @@ export default {
- 指定`global=true`将该文件声明的所有格式化器均注册到全局中
```javascript | pure
export default {
global:true,
$config:{...},
$types:{... },
[格式化名称]:(value,...args,$config)=>{.....},
@ -544,6 +545,7 @@ export default {
$config:{...},
$types:{... },
[格式化名称]:(value,...args,$config)=>{.....},
// 以下全部注册到全局`VoerkaI18n`实例中
global:{
$config:{...},
$types:{... },

View File

@ -0,0 +1,154 @@
/**
*
* *
*
*
*/
import { VoerkaI18nFormatter, VoerkaI18nFormatters, VoerkaI18nFormattersLoader, VoerkaI18nLanguageFormatters, SupportedDateTypes, VoerkaI18nFormatterConfigs, Formatter } from './types';
import { DataTypes } from './utils';
import { get as getByPath } from "flex-tools/object/get"
export interface VoerkaI18nScopeCache{
activeLanguage :string | null,
typedFormatters: VoerkaI18nLanguageFormatters,
formatters : VoerkaI18nLanguageFormatters,
}
export class FormattersNotLoadedError extends Error{
constructor(language:string){
super(`Formatters of language<${language}> is not loaded,try to call load()`)
}
}
const EmptyFormatters:any = {
$config:{},
$types:{}
}
export class VoerkaI18nFormatterRegistry{
// 由于语言的格式化器集合允许是一个异步加载块所以需要一个ready标志
// 当语言格式化器集合加载完成后ready标志才会变为true
#ready:boolean = false
#formatters:VoerkaI18nLanguageFormatters = {}
#language:string = 'zh'
constructor(formatters?:VoerkaI18nLanguageFormatters){
this.#formatters = formatters || {}
}
/**
*
*/
get language(){ return this.#language }
set language(language:string){
this.#language = language
if(!(language in this.formatters)){
(this.formatters[language] as any) = Object.assign({},EmptyFormatters)
}
this.#ready = typeof(this.#formatters[language]) != 'function'
}
/**
*
value=>{...}
register(name,value=>{...}) // 注册到所有语言
register(name,value=>{...},{langauge:"zh"}) // 注册到zh语言
register(name,value=>{...},{langauge:"en"}) // 注册到en语言
register("Date",value=>{...},{langauge:"en"}) // 注册到en语言的默认数据类型格式化器
register(name,value=>{...},{langauge:["zh","cht"]}) // 注册到zh和cht语言
register(name,value=>{...},{langauge:"zh,cht"})
@param {*} formatter
@param language : 字符串或数组
*
使,
*/
register(name:string, formatter:VoerkaI18nFormatter, {language = "*"}:{ language: string | string[] } ) {
if (!isFunction(formatter) || typeof name !== "string") {
throw new TypeError("Formatter must be a function");
}
const languages = Array.isArray(language) ? language: language ? language.split(","): [];
languages.forEach((lngName:string) => {
if(!(lngName in this.#formatters)) {
this.#formatters[lngName] = { }
}
if(typeof(this.#formatters[lngName])!="function"){
let lngFormatters = this.#formatters[lngName] as VoerkaI18nFormatters
if (DataTypes.includes(name)) {
if(!lngFormatters.$types){
lngFormatters.$types = {}
}
lngFormatters.$types![name] = formatter
} else {
lngFormatters[name] = formatter;
}
}
});
}
registerLanguageFormatters(language:string,formatters:VoerkaI18nFormatters | VoerkaI18nFormattersLoader){
this.#formatters[language] = formatters
}
/**
*
* @param formatters
*/
loadInitials(formatters:VoerkaI18nLanguageFormatters){
this.#formatters=formatters
}
/**
*
* @param language
*/
getConfig(language?:string){
return language ? getByPath(this.#formatters,`${language}.$config`,{defaultValue:{}}) : {}
}
/**
*
* @param language
*/
hasLanguage(language:string){
return language in this.#formatters
}
//****************** 以下方法和属性只作用于当前语言 *********************** */
/**
* ()=>import(...)Promise时load()
*
* 使
*
*/
async load(){
let loader = this.#formatters[this.#language] as VoerkaI18nFormattersLoader
if(typeof(loader) === 'function'){
this.#formatters[this.#language] = await loader()
this.#ready = true
}// 如果是一个对象,则直接返回,不需要调用
}
/**
*
*/
get formatters(){
if(!this.#ready) throw new FormattersNotLoadedError(this.#language)
return this.#formatters[this.#language] as VoerkaI18nFormatters
}
/**
*
* @param name
*/
get(name:string,dataType?:SupportedDateTypes):VoerkaI18nFormatter | undefined{
if(!this.#ready) throw new FormattersNotLoadedError(this.#language)
const lngFormatters = this.#formatters[this.#language] as VoerkaI18nFormatters
if(dataType && (dataType in lngFormatters.$types!)){
return lngFormatters.$types![dataType]
}else if(name in lngFormatters){
return lngFormatters[name]
}
}
/**
*
*/
get config(){
if(!this.#ready) throw new FormattersNotLoadedError(this.#language)
return (this.#formatters[this.#language] as VoerkaI18nFormatters).$config as VoerkaI18nFormatterConfigs
}
}

View File

@ -3,10 +3,9 @@
*
*/
const {
CN_DATETIME_UNITS,CN_WEEK_DAYS,CN_SHORT_WEEK_DAYS, CN_MONTH_NAMES, CN_SHORT_MONTH_NAMES,
chineseNumberFormatter,rmbFormater
} = require("../datatypes/chinese")
import { chineseNumberFormatter,rmbFormater } from "../datatypes/chinese"
module.exports = {
// 配置参数: 格式化器函数的最后一个参数就是该配置参数
@ -71,7 +70,7 @@ module.exports = {
}
},
$types: {
Boolean : value =>value ? "是":"否"
Boolean : (value:any) =>value ? "是":"否"
},
// 中文货币big=true代表大写形式
rmb : rmbFormater,

View File

@ -306,7 +306,7 @@ function executeFormatter(value, formatters, scope, template) {
for (let formatter of formatters) {
try {
result = formatter(result, scope.activeFormatterConfig);
} catch (e) {
} catch (e:any) {
e.formatter = formatter.$name;
if (scope.debug)
console.error(`Error while execute i18n formatter<${formatter.$name}> for ${template}: ${e.message} `);
@ -463,9 +463,3 @@ export function replaceInterpolatedVars(this:VoerkaI18nScope,template:string, ..
);
}
}
module.exports = {
forEachInterpolatedVars, // 遍历插值变量并替换
getInterpolatedVars, // 获取指定字符串中的插件值变量列表
replaceInterpolatedVars // 替换插值变量
};

View File

@ -4,8 +4,9 @@ import {DataTypes} from "./utils"
import { EventEmitter } from "./eventemitter"
import inlineFormatters from "./formatters"
import { VoerkaI18nScope } from "./scope"
import type { VoerkaI18nLanguage, VoerkaI18nFormatters, VoerkaI18nDefaultMessageLoader, VoerkaI18nFormatter, VoerkaI18nTypesFormatters } from "./types"
import type { VoerkaI18nLanguageDefine, VoerkaI18nLanguageFormatters, VoerkaI18nDefaultMessageLoader, VoerkaI18nFormatter, VoerkaI18nTypesFormatters } from "./types"
import { SupportedDateTypes } from './types';
import { VoerkaI18nFormatterRegistry } from "./formatterRegistry"
// 默认语言配置
const defaultLanguageSettings = {
@ -23,8 +24,8 @@ export interface VoerkaI18nManagerOptions {
debug?: boolean
defaultLanguage: string
activeLanguage: string
formatters: VoerkaI18nFormatters
languages: VoerkaI18nLanguage[]
formatters: VoerkaI18nLanguageFormatters
languages: VoerkaI18nLanguageDefine[]
}
/**
*
@ -47,6 +48,7 @@ export class VoerkaI18nManager extends EventEmitter{
#options?:Required<VoerkaI18nManagerOptions>
#scopes:VoerkaI18nScope[] = []
#defaultMessageLoader?:VoerkaI18nDefaultMessageLoader
#formatterRegistry!:VoerkaI18nFormatterRegistry
constructor(options?:VoerkaI18nManagerOptions){
super()
if(VoerkaI18nManager.instance){
@ -54,6 +56,8 @@ export class VoerkaI18nManager extends EventEmitter{
}
VoerkaI18nManager.instance = this;
this.#options = deepMerge(defaultLanguageSettings,options) as Required<VoerkaI18nManagerOptions>
this.#formatterRegistry = new VoerkaI18nFormatterRegistry()
this.loadInitialFormatters() // 加载初始格式化器
this.#scopes=[] // 保存VoerkaI18nScope实例
}
get debug(){return this.#options!.debug}
@ -62,8 +66,18 @@ export class VoerkaI18nManager extends EventEmitter{
get activeLanguage(){ return this.#options!.activeLanguage} // 当前激活语言 名称
get defaultLanguage(){ return this.#options!.defaultLanguage} // 默认语言名称
get languages(){ return this.#options!.languages} // 支持的语言列表
get formatters(){ return this.#options!.formatters } // 内置格式化器{*:{$config,$types,...},zh:{$config,$types,...},en:{$config,$types,...}}
get defaultMessageLoader(){ return this.#defaultMessageLoader} // 默认语言包加载器
get formatters(){return this.#formatterRegistry!}
/**
*
*/
private loadInitialFormatters(){
if(this.#options?.formatters){
this.#formatterRegistry.loadInitials(this.#options!.formatters)
delete (this.#options as any).formatters
}
}
// 通过默认加载器加载文件
async loadMessagesFromDefaultLoader(newLanguage:string,scope:VoerkaI18nScope){
@ -134,17 +148,7 @@ export class VoerkaI18nManager extends EventEmitter{
language : 声明该格式化器适用语言
*/
registerFormatter(name:string,formatter:VoerkaI18nFormatter,{language="*"}:{language:string | string[] | '*'}){
if(!isFunction(formatter) || typeof(name)!=="string"){
throw new TypeError("Formatter must be a function")
}
const languages = Array.isArray(language) ? language : (language ? language.split(",") : [])
languages.forEach((lng:string)=>{
if(DataTypes.includes(name)){
(this.formatters[lng].$types as VoerkaI18nTypesFormatters)[name] = formatter
}else{
this.formatters[lng][name] = formatter
}
})
this.#formatterRegistry.register(name,formatter,{language})
}
/**
*

View File

@ -11,22 +11,25 @@ import type {
VoerkaI18nFormatterConfigs,
VoerkaI18nDefaultMessageLoader,
VoerkaI18nFormatter,
VoerkaI18nFormatters,
VoerkaI18nLanguageFormatters,
Voerkai18nIdMap,
VoerkaI18nLanguage,
VoerkaI18nLanguageDefine,
VoerkaI18nLanguageMessages,
VoerkaI18nLanguagePack,
VoerkaI18nScopeCache,
VoerkaI18nTranslate,
VoerkaI18nLoaders,
VoerkaI18nTypesFormatters,
VoerkaI18nLanguageFormatters
VoerkaI18nFormatters,
VoerkaI18nDynamicLanguageMessages,
VoerkaI18nTypesFormatterConfigs
} from "./types"
import { VoerkaI18nFormatterRegistry } from './formatterRegistry';
export interface VoerkaI18nScopeOptions {
id?: string
debug?: boolean
languages: VoerkaI18nLanguage[] // 当前作用域支持的语言列表
languages: VoerkaI18nLanguageDefine[] // 当前作用域支持的语言列表
defaultLanguage: string // 默认语言名称
activeLanguage: string // 当前语言名称
default: VoerkaI18nLanguageMessages // 默认语言包
@ -42,10 +45,11 @@ export class VoerkaI18nScope {
#refreshing:boolean = false
#patchMessages:VoerkaI18nLanguagePack = {}
#t:VoerkaI18nTranslate
#activeFormatters:VoerkaI18nLanguageFormatters = {}
#activeFormatters:VoerkaI18nFormatters = {}
#activeFormatterConfig: VoerkaI18nFormatterConfigs={}
#cache:VoerkaI18nScopeCache
#messages:VoerkaI18nLanguageMessages = {}
#formatterRegistry:VoerkaI18nFormatterRegistry
constructor(options:VoerkaI18nScopeOptions, callback:(e?:Error)=>void) {
this.#options = assignObject({
id : Date.now().toString() + parseInt(String(Math.random() * 1000)),
@ -81,7 +85,8 @@ export class VoerkaI18nScope {
}
this.#t = translate.bind(this)
this.#global = globalThis.VoerkaI18n as unknown as VoerkaI18nManager;
this._initFormatters(this.activeLanguage) // 初始化活动的格式化器
this.#formatterRegistry = new VoerkaI18nFormatterRegistry()
this.loadFormatters(this.activeLanguage) // 初始化活动的格式化器
this._mergePatchedMessages(); // 从本地缓存中读取并合并补丁语言包
this._patch(this.messages, this.activeLanguage); // 延后执行补丁命令,该命令会向远程下载补丁包
this.register(callback); // 在全局注册作用域
@ -96,8 +101,8 @@ export class VoerkaI18nScope {
get languages() {return this.#options.languages;} // 当前作用域支持的语言列表[{name,title,fallback}]
get loaders() { return this.#options.loaders;} // 异步加载语言文件的函数列表
get global() { return this.#global;} // 引用全局VoerkaI18n配置注册后自动引用
get formatters() { return this.#options.formatters;} // 当前作用域的所有格式化器定义 {<语言名称>: {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () => {}}}
get activeFormatters() {return this.#activeFormatters} // 当前作用域激活的格式化器定义 {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () = >{}}
get formatters() { return this.#formatterRegistry;} // 当前作用域的所有格式化器定义 {<语言名称>: {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () => {}}}
get activeFormatters() {return this.#formatterRegistry.formatters} // 当前作用域激活的格式化器定义 {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () = >{}}
get activeFormatterConfig(){return this.#activeFormatterConfig} // 当前格式化器合并后的配置参数,参数已经合并了全局格式化器中的参数
get cache(){return this.#cache }
set cache(value:VoerkaI18nScopeCache){ this.#cache=value }
@ -110,7 +115,7 @@ export class VoerkaI18nScope {
*/
_initiLanguages(){
if(!Array.isArray(this.languages)){
console.warn("[VoerkaI18n] 无效的语言配置")
console.warn("[VoerkaI18n] invalid languages config,use default languages config instead.")
this.#options.languages = [
{name: "zh",title: "中文"},
{name: "en",title: "英文"}
@ -148,59 +153,68 @@ export class VoerkaI18nScope {
asGlobal : 注册到全局
*/
registerFormatter(name:string, formatter:VoerkaI18nFormatter, {language = "*", asGlobal= true}:{ language: string | string[] | "*", asGlobal :boolean } ) {
if (!isFunction(formatter) || typeof name !== "string") {
throw new TypeError("Formatter must be a function");
}
const languages = Array.isArray(language) ? language: language ? language.split(","): [];
if(asGlobal){
this.global.registerFormatter(name, formatter, {language});
}else{
languages.forEach((lng) => {
if(!(lng in this.formatters)) this.formatters[lng] = {}
if (DataTypes.includes(name)) {
(this.formatters[lng].$types as VoerkaI18nTypesFormatters)[name] = formatter
} else {
this.formatters[lng][name] = formatter;
}
});
this.#formatterRegistry.register(name, formatter, {language});
}
}
/**
*
* registerFormatters({"*":{...},zh:{...},en:{...}})
* registerFormatters({"*":{...},zh:{...},en:{...}},true)
* @param {*} formatters ={"*":{...},zh:{...},en:{...}}
* @returns
*/
registerFormatters(formatters:VoerkaI18nFormatters,asGlobal=false) {
Object.entries(formatters).forEach(([language,fns])=>{
Object.entries(fns).forEach(([name,formatter])=>{
this.registerFormatter(name,formatter,{language,asGlobal})
})
})
}
// /**
// * 注册多种语言的格式化器
// * '*': 代表适用于所有语言
// * registerFormatters({"*":{...},zh:{...},en:VoerkaI18nFormatters})
// * registerFormatters({"*":{...},zh:{...},en:{...}},true) 在全局注册
// * @param {*} langformatters ={"*":{...},zh:{...},en:{...}}
// * @returns
// */
// registerFormatters(langformatters:VoerkaI18nLanguageFormatters,asGlobal=false) {
// Object.entries(langformatters).forEach(([langName,formatters])=>{
// if(isPlainObject(formatters)){
// this.#options.formatters[langName] = formatters
// }
// })
// }
/**
*
*
* #activeFormatters={$config:{...},$types:{...},[]:()=>{...},[]:()=>{...},...}}
* #activeFormatters={
* global:{...} // 或true代表注册到全局
* $config:{...},
* $types:{...},
* []:()=>{...},
* []:()=>{...},
* ...
* }
*/
private _initFormatters(newLanguage:string){
// 全局格式化器,用来注册到全局
Object.entries(this.formatters).forEach(([langName,formatters])=>{
if(formatters.global===true){
this.registerFormatters({[langName]:formatters},true)
private loadFormatters(newLanguage:string){
this.#formatterRegistry.language = newLanguage
// 初始化格式化器
this.formatters.loadInitials(this.#options.formatters)
if(this.#options.formatters)
// 将配置中的指定为全局的格式化器注册到全局
Object.entries(this.#options.formatters).forEach(([langName,formatters])=>{
if(typeof(formatters)=='function'){
this.#formatterRegistry.registerLanguageFormatters(langName,formatters)
}else if(isPlainObject(formatters.global)){
this.registerFormatters({[langName]:formatters.global as any},true)
if(formatters.global===true){
this.#formatterRegistry.registerLanguageFormatters(langName,formatters)
}else if(isPlainObject(formatters.global)){
this.global.formatters.registerLanguageFormatters(langName,formatters.global as VoerkaI18nFormatters)
}
delete formatters.global
}
})
// 保存到Registry中就可以从options中删除了
delete (this.#options as any).formatters
// 初始化格式化器
try {
if (newLanguage in this.formatters) {
this.#activeFormatters = this.formatters[newLanguage];
if (this.formatters.hasLanguage(newLanguage)) {
} else {
if (this.debug) console.warn(`Not initialize <${newLanguage}> formatters.`);
}
this._generateFormatterConfig(newLanguage)
} catch (e) {
} catch (e:any) {
if (this.debug) console.error(`Error while initialize ${newLanguage} formatters: ${e.message}`);
}
}
@ -219,13 +233,10 @@ export class VoerkaI18nScope {
*/
async _changeFormatters(newLanguage:string) {
try {
if (newLanguage in this.formatters) {
let loader = this.formatters[newLanguage];
if (isPlainObject(loader)) {
this.#activeFormatters = loader as unknown as VoerkaI18nFormatters;
} else if (isFunction(loader)) {
this.#activeFormatters = (await (loader as Function).call(this)).default;
}
if (this.formatters.hasLanguage(newLanguage)) {
this.formatters.language = newLanguage
// 如果该语言的格式化器集合是异步加载,需要等待加载完成
await this.formatters.load()
// 合并生成格式化器的配置参数,当执行格式化器时该参数将被传递给格式化器
this._generateFormatterConfig(newLanguage)
} else {
@ -237,25 +248,31 @@ export class VoerkaI18nScope {
}
/**
*
*
* - global.formatters[*].$config
* - global.formatters[fallbackLanguage].$config
* - global.formatters[language].$config
* - scope.activeFormatters.$config
* - this.formatters[*].$config
* - this.formatters[fallbackLanguage].$config
* - this.formatters[language].$config
*/
_generateFormatterConfig(language:string){
try{
const fallbackLanguage = this.getLanguage(language).fallback;
const fallbackLanguage = this.getLanguage(language)?.fallback;
let configSources = [
getByPath(this.#global.formatters,`${fallbackLanguage}.$config`,{}),
getByPath(this.#global.formatters,"*.$config",{}),
getByPath(this.formatters,`${fallbackLanguage}.$config`,{}),
getByPath(this._formatter,"*.$config",{}),
getByPath(this.#global.formatters,`${language}.$config`,{}),
getByPath(this.#activeFormatters,"$config",{})
// 从全局读取
this.#global.formatters.getConfig('*'),
this.#global.formatters.getConfig(fallbackLanguage),
this.#global.formatters.config,
// 从当前Scope读取
this.formatters.getConfig('*'),
this.formatters.getConfig(fallbackLanguage),
this.formatters.config
]
return this.#activeFormatterConfig = configSources.reduce((finalConfig, config)=>{
if(isPlainObject(config)) deepMerge(finalConfig,config,{newObject:false})
return this.#activeFormatterConfig = configSources.reduce((finalConfig, curConfig)=>{
if(isPlainObject(curConfig)) deepMerge(finalConfig,curConfig,{newObject:false,array:'replace'})
return finalConfig
},deepClone(getByPath(this.#global.formatters,`*.$config`,{})))
},{})
}catch(e){
if(this.debug) console.error(`Error while generate <${language}> formatter options: `,e)
@ -275,7 +292,7 @@ export class VoerkaI18nScope {
* @param {*} language
* @returns
*/
getLanguage(language:string):VoerkaI18nLanguage | undefined{
private getLanguage(language:string):VoerkaI18nLanguageDefine | undefined{
let index = this.languages.findIndex((lng) => lng.name == language);
if (index !== -1) return this.languages[index];
}
@ -285,12 +302,12 @@ export class VoerkaI18nScope {
* @returns
*/
hasLanguage(language:string) {
return this.languages.indexOf((lang:VoerkaI18nLanguage) => lang.name == language) !== -1;
return this.languages.indexOf((lang:VoerkaI18nLanguageDefine) => lang.name == language) !== -1;
}
/**
* 退
*/
_fallback() {
private _fallback() {
this.#options.messages = this.default;
this.#options.activeLanguage = this.defaultLanguage;
}
@ -319,25 +336,25 @@ export class VoerkaI18nScope {
} else if (isFunction(loader)) { // 语言包异步chunk
newMessages = (await loader()).default;
} else if (isFunction(this.global.defaultMessageLoader)) { // 从远程加载语言包:如果该语言没有指定加载器,则使用全局配置的默认加载器
const loadedMessages = await this.global.loadMessagesFromDefaultLoader(newLanguage,this);
const loadedMessages = (await this.global.loadMessagesFromDefaultLoader(newLanguage,this)) as unknown as VoerkaI18nDynamicLanguageMessages;
if(isPlainObject(loadedMessages)){
useRemote = true
// 需要保存动态语言包中的$config合并到对应语言的格式化器配置
if(isPlainObject(loadedMessages.$config)){
this._formatters[newLanguage] = {
$config : loadedMessages.$config
this.formatters[newLanguage] = {
$config : loadedMessages.$config as any
}
delete loadedMessages.$config
}
newMessages = Object.assign({},this._default,loadedMessages);
newMessages = Object.assign({},this.default,loadedMessages);
}
}
if(newMessages){
this._messages = newMessages
this._activeLanguage = newLanguage;
this.#options.messages = newMessages
this.#options.activeLanguage = newLanguage;
// 打语言包补丁, 如果是从远程加载语言包则不需要再打补丁了
if(!useRemote) {
await this._patch(this._messages, newLanguage);
await this._patch(this.#options.messages, newLanguage);
}
// 切换到对应语言的格式化器
await this._changeFormatters(newLanguage);
@ -361,10 +378,10 @@ export class VoerkaI18nScope {
* @param {*} newLanguage
* @returns
*/
async _patch(messages, newLanguage) {
private async _patch(messages:VoerkaI18nLanguageMessages, newLanguage:string) {
if (!isFunction(this.global.loadMessagesFromDefaultLoader)) return;
try {
let pachedMessages = await this.global.loadMessagesFromDefaultLoader(newLanguage,this);
let pachedMessages = (await this.global.loadMessagesFromDefaultLoader(newLanguage,this)) as unknown as VoerkaI18nLanguageMessages;
if (isPlainObject(pachedMessages)) {
Object.assign(messages, pachedMessages);
this._savePatchedMessages(pachedMessages, newLanguage);
@ -376,10 +393,10 @@ export class VoerkaI18nScope {
/**
*
*/
_mergePatchedMessages() {
private _mergePatchedMessages() {
let patchedMessages = this._getPatchedMessages(this.activeLanguage);
if (isPlainObject(patchedMessages)) {
Object.assign(this._messages, patchedMessages);
Object.assign(this.#options.messages, patchedMessages);
}
}
/**
@ -400,13 +417,13 @@ export class VoerkaI18nScope {
*
* @param {*} messages
*/
_savePatchedMessages(messages, language) {
private _savePatchedMessages(messages:VoerkaI18nLanguageMessages, language:string) {
try {
if (globalThis.localStorage) {
globalThis.localStorage.setItem(`voerkai18n_${this.id}_${language}_patched_messages`,JSON.stringify(messages));
}
} catch (e) {
if (this.cache._debug) console.error("Error while save voerkai18n patched messages:",e);
} catch (e:any) {
if (this.debug) console.error("Error while save voerkai18n patched messages:",e);
}
}
/**
@ -414,18 +431,18 @@ export class VoerkaI18nScope {
* @param {*} language
* @returns
*/
_getPatchedMessages(language) {
private _getPatchedMessages(language:string) {
try {
return JSON.parse(localStorage.getItem(`voerkai18n_${this.id}_${language}_patched_messages`));
return JSON.parse((localStorage as any).getItem(`voerkai18n_${this.id}_${language}_patched_messages`));
} catch (e) {
return {};
}
}
// 以下方法引用全局VoerkaI18n实例的方法
on() {return this.#global.on(...arguments); }
off() {return this.#global.off(...arguments); }
offAll() {return this.#global.offAll(...arguments);}
async change(language) {
on(callback:Function) {return this.#global.on(callback); }
off(callback:Function) {return this.#global.off(callback); }
offAll() {return this.#global.offAll();}
async change(language:string) {
await this.#global.change(language);
}
};

View File

@ -8,14 +8,19 @@ declare global {
export type SupportedDateTypes = "String" | "Number" | "Boolean" | "Object" | "Array" | "Function" | "Error" | "Symbol" | "RegExp" | "Date" | "Null" | "Undefined" | "Set" | "Map" | "WeakSet" | "WeakMap"
export type VoerkaI18nLanguageMessages = Record<string, string | string[]>
export type VoerkaI18nLanguageMessages = Record<string, string | string[]> & {
$config?: VoerkaI18nTypesFormatterConfigs
}
export type VoerkaI18nDynamicLanguageMessages = Record<string, string | string[]> & {
$config?: VoerkaI18nTypesFormatterConfigs
}
export interface VoerkaI18nLanguagePack {
[language: string]: VoerkaI18nLanguageMessages
}
export type Voerkai18nIdMap = Record<string, number>
export interface VoerkaI18nLanguage {
export interface VoerkaI18nLanguageDefine {
name: string
title?: string
default?: boolean
@ -24,22 +29,25 @@ export interface VoerkaI18nLanguage {
export type VoerkaI18nFormatterConfigs = Record<string, any>
export type VoerkaI18nFormatter = (value: string, ...args: any[]) => string
export type VoerkaI18nFormatter = (value: string,args: any[],$config:VoerkI18nFormatterConfigs) => string
export type VoerkaI18nTypesFormatters=Record<SupportedDateTypes | string, VoerkaI18nFormatter>
export type VoerkaI18nTypesFormatterConfigs= Record<SupportedDateTypes | string, Record<string,any>>
//
export type VoerkaI18nLanguageFormatters = {
global?: true | Exclude<VoerkaI18nFormatters,'global'> // 是否全局格式化器
export type VoerkaI18nFormattersLoader = (()=>Promise<VoerkaI18nFormatters>)
// 每一个语言的格式化器定义={$types:{...},$config:{...},[格式化器名称]: () => {},[格式化器名称]: () => {}
// 在formatters/xxxx.ts里面进行配置
export type VoerkaI18nFormatters = ({
global?: boolean | Omit<VoerkaI18nFormatters,'global'> // 是否全局格式化器
$types?:VoerkaI18nTypesFormatters
$config?: VoerkaI18nTypesFormatterConfigs
} & {
[DataTypeName in SupportedDateTypes]?: VoerkaI18nFormatter
} & {
[key: string]: VoerkaI18nFormatter
}
})
// 包括语言的{"*":{...},zh:{...},en:{...}}
// 声明格式化器
export type VoerkaI18nFormatters = Record<string,VoerkaI18nLanguageFormatters>
export type VoerkaI18nLanguageFormatters = Record<string,VoerkaI18nFormatters | VoerkaI18nFormattersLoader>
@ -53,8 +61,8 @@ export type VoerkaI18nDefaultMessageLoader = (this:VoerkaI18nScope,newLanguage:s
export interface VoerkaI18nScopeCache{
activeLanguage :string | null,
typedFormatters: VoerkaI18nFormatters,
formatters : VoerkaI18nFormatters,
typedFormatters: VoerkaI18nLanguageFormatters,
formatters : VoerkaI18nLanguageFormatters,
}
export type TranslateMessageVars = number | boolean | string | Function | Date
@ -63,7 +71,7 @@ export interface VoerkaI18nTranslate {
(message: string, vars?: Record<string, TranslateMessageVars>): string
}
export interface VoerkaI18nSupportedLanguages {
[key: string]: VoerkaI18nLanguage
[key: string]: VoerkaI18nLanguageDefine
}