This commit is contained in:
wxzhang 2023-04-07 21:54:31 +08:00
parent 5ab0146e99
commit a9f63c2c35
6 changed files with 205 additions and 338 deletions

View File

@ -4,12 +4,14 @@
*
*
*/
import { FormatterStore } from './formatterStore';
import { isPlainObject } from 'flex-tools/typecheck/isPlainObject';
import type { VoerkaI18nScope } from './scope';
import { VoerkaI18nFormatter, VoerkaI18nFormatters, VoerkaI18nFormattersLoader, VoerkaI18nLanguageFormatters, SupportedDateTypes, VoerkaI18nFormatterConfigs } from './types';
import { VoerkaI18nFormatter, VoerkaI18nFormatters, VoerkaI18nFormattersLoader, VoerkaI18nLanguageFormatters, SupportedDateTypes, VoerkaI18nFormatterConfigs, VoerkaI18nTypesFormatters } from './types';
import { DataTypes } from './utils';
import { get as getByPath } from "flex-tools/object/get"
import { isFunction } from 'flex-tools/typecheck/isFunction';
import { deepMerge } from 'flex-tools/object/deepMerge';
import { assignObject } from 'flex-tools/object/assignObject';
export interface VoerkaI18nScopeCache{
@ -23,30 +25,100 @@ export class FormattersNotLoadedError extends Error{
super(`Formatters of language<${language}> is not loaded,try to call load()`)
}
}
export interface GetFormatterOptions{
on:"types" | "scope"
inGlobal?:boolean // 在全局中查找
}
const EmptyFormatters:any = {
$config:{},
$types:{}
}
export class VoerkaI18nFormatterRegistry extends FormatterStore{
// 由于语言的格式化器集合允许是一个异步加载块所以需要一个ready标志
// 当语言格式化器集合加载完成后ready标志才会变为true
#ready:boolean = false
#language:string = 'zh'
constructor(scope:VoerkaI18nScope){
super()
export interface VoerkaI18nScopeFormatterCache{
typedFormatters:VoerkaI18nTypesFormatters,
formatters : Record<string,VoerkaI18nFormatter>,
}
export class VoerkaI18nFormatterRegistry{
#formatters:VoerkaI18nLanguageFormatters = {}
#activeFormatters:VoerkaI18nFormatters = {}
#activeFormattersConfigs :VoerkaI18nFormatterConfigs = {}
#scope?:VoerkaI18nScope
#language:string // 当前语言
#formatterCache:VoerkaI18nScopeFormatterCache = {typedFormatters:{},formatters:{}}
constructor(scope?:VoerkaI18nScope){
this.#scope = scope
this.#language = scope?.activeLanguage || "zh"
}
get activeLanguage(){ return this.#language } // 当前语言
get activeFormatters(){ return this.#activeFormatters } // 当前语言的格式化器集合
get scope(){ return this.#scope }
/**
*
*
* @param language
*/
async change(language:string){
try {
if (language in this.formatters) {
this.#language = language
const formatters = this.formatters[language]
if(isFunction(formatters)){
this.#activeFormatters = await (formatters as Function)() // 如果格式化器集合是异步加载,则需要等待加载完成
}else{
this.#activeFormatters = formatters as VoerkaI18nFormatters
}
// 合并生成格式化器的配置参数,当执行格式化器时该参数将被传递给格式化器
this.generateFormattersConfigs(language)
// 清空缓存
this.#formatterCache = {typedFormatters:{},formatters:{}}
} else {
if (this.scope?.debug) console.warn(`Not configured <${language}> formatters.`);
}
} catch (e:any) {
if (this.scope?.debug) console.error(`Error loading ${language} formatters: ${e.message}`);
}
}
private async generateFormattersConfigs(language:string){
try{
const configSources = [ ]
const fallbackLanguage = this.scope?.getLanguage(language)?.fallback || 'en';
if(this.scope){ // 从全局Scope读取
configSources.push(this.scope.global.formatters.getConfig('*'))
configSources.push(this.scope.global.formatters.getConfig(fallbackLanguage))
configSources.push(this.scope.global.formatters.config)
}
// 从当前Scope读取
configSources.push(this.getConfig('*'))
configSources.push(this.getConfig(fallbackLanguage))
configSources.push(this.config)
// 合并当前语言的格式化器配置参数
this.#activeFormattersConfigs = configSources.reduce((finalConfig, curConfig)=>{
if(isPlainObject(curConfig)) deepMerge(finalConfig,curConfig,{newObject:false,array:'replace'})
return finalConfig
},{})
}catch(e){
if(this.scope?.debug) console.error(`Error while generate <${language}> formatter options: `,e)
this.#activeFormattersConfigs = {}
}
}
updateConfig(language:string,config:VoerkaI18nFormatterConfigs){
if(language in this.#formatters ){
let formatters = this.#formatters[language] as VoerkaI18nFormatters
if(!("$config" in formatters)) formatters.$config = {}
assignObject(formatters.$config as object ,config)
}
if(language === this.#language){
this.generateFormattersConfigs(language)
}
}
/**
*
*
* @param language
* @param 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'
}
registerLanguageFormatters(language:string,formatters:VoerkaI18nFormatters | VoerkaI18nFormattersLoader){
this.#formatters[language] = formatters
}
@ -55,98 +127,131 @@ export class VoerkaI18nFormatterRegistry extends FormatterStore{
* @param formatters
*/
loadInitials(formatters:VoerkaI18nLanguageFormatters){
this.#formatters=formatters
this.#formatters = formatters
}
/**
*
* @param name
* @param formatter
* @param language '*';
*
*
*/
register(name:string | SupportedDateTypes, 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 any
if (DataTypes.includes(name)) {
if(!lngFormatters.$types) lngFormatters.$types = {}
lngFormatters.$types![name] = formatter
} else {
lngFormatters[name] = formatter;
}
}
});
}
//****************** 以下方法可以获取指定语言的格式化器 *********************** */
/**
*
* @param language
*/
getConfig(language?:string){
if(language== this.#language) return this.#activeFormattersConfigs
return language ? getByPath(this.#formatters,`${language}.$config`,{defaultValue:{}}) : {}
}
/**
*/
getTypes(language?:string){
if(language== this.#language) return this.activeFormatters.$types
return language ? getByPath(this.#formatters,`${language}.$types`,{defaultValue:{}}) : {}
}
/**
*/
getFormatters(language?:string){
if(language== this.#language) return this.activeFormatters
return language ? getByPath(this.#formatters,language,{defaultValue:{}}) : {}
}
/**
*
* @param language
* @param config
*/
updateConfig(language:string,config:VoerkaI18nFormatterConfigs){
if(language in this.#formatters){
const formatters = this.#formatters[language]
if(typeof(formatters)=='function'){
throw new FormattersNotLoadedError(language)
}else{
if(!formatters.$config){
formatters.$config = {}
}
Object.assign(formatters.$config,config)
}
}
}
/**
*
* @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 any
if(dataType && (dataType in lngFormatters.$types!)){
return lngFormatters.$types![dataType]
}else if(name in lngFormatters){
return lngFormatters[name]
}
}
get formatters(){ return this.#formatters } // 所有语言的格式化器集合
/**
*
*/
get config(){
if(!this.#ready) throw new FormattersNotLoadedError(this.#language)
return (this.#formatters[this.#language] as VoerkaI18nFormatters).$config as VoerkaI18nFormatterConfigs
return (this.#activeFormatters as VoerkaI18nFormatters).$config as VoerkaI18nFormatterConfigs
}
get types(){
if(!this.#ready) throw new FormattersNotLoadedError(this.#language)
return (this.#formatters[this.#language] as VoerkaI18nFormatters).$types as VoerkaI18nFormatterConfigs
return (this.#activeFormatters as VoerkaI18nFormatters).$types as VoerkaI18nFormatterConfigs
}
/**
*
* @param name
*
* @param options = {
* inGlobal: true, // 是否从全局作用域中查找
* inTypes: true, // 是否从全局作用域中查找数据类型的格式化器
* inScope: true, // 是否从当前作用域中查找
* }
*
*/
get(name:string,options?:GetFormatterOptions):VoerkaI18nFormatter | undefined{
const {on,inGlobal} = assignObject({
on:"scope",
inGlobal:true
},options)
// 直接从缓存中获取
if(on=="types" && name in this.#formatterCache.typedFormatters) return this.#formatterCache.typedFormatters[name as SupportedDateTypes]
if(on=="scope" && name in this.#formatterCache.formatters) return this.#formatterCache.formatters[name]
const fallbackLanguage = this.scope?.getLanguage(this.activeLanguage)?.fallback || 'en';
// 先在当前作用域中查找,再在全局查找
const targets =[]
if(on=="types"){
targets.push(this.types)
targets.push(this.getTypes(fallbackLanguage))
targets.push(this.getTypes("*"))
if(inGlobal){
targets.push(this.scope?.global.formatters.types)
targets.push(this.scope?.global.formatters.getTypes(fallbackLanguage))
targets.push(this.scope?.global.formatters.getTypes("*"))
}
}else if(on=='scope'){
targets.push(this.formatters)
targets.push(this.getFormatters(fallbackLanguage))
targets.push(this.getFormatters("*"))
if(inGlobal){
targets.push(this.scope?.global.formatters.types)
targets.push(this.scope?.global.formatters.getTypes(fallbackLanguage))
targets.push(this.scope?.global.formatters.getTypes("*"))
}
}
// 查找指定名称的格式化器
for (const target of targets) {
if (!target) continue;
if(target && name in target){
const formatter = target[name]
if (isFunction(formatter)) {
// 缓存起来,下次直接返回避免重复查找
if(on=="types"){
this.#formatterCache.typedFormatters[name as SupportedDateTypes] = formatter
}else{
this.#formatterCache.formatters[name] = formatter
}
return formatter
}
}
}
}
}

View File

@ -1,37 +0,0 @@
import { isFunction } from "flex-tools/typecheck/isFunction";
import { SupportedDateTypes, VoerkaI18nFormatter, VoerkaI18nLanguageFormatters } from "./types";
import { DataTypes } from "./utils";
export class FormatterStore{
#formatters:VoerkaI18nLanguageFormatters = {}
constructor(formatters?:VoerkaI18nLanguageFormatters){
if(formatters) this.#formatters = formatters
}
get formatters(){ return this.#formatters }
register(name:string | SupportedDateTypes, 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 any
if (DataTypes.includes(name)) {
if(!lngFormatters.$types) lngFormatters.$types = {}
lngFormatters.$types![name] = formatter
} else {
lngFormatters[name] = formatter;
}
}
});
}
getLanguageFormatters(language:string){
if(language in this.#formatters){
return this.#formatters[language]
}else{
return this.#formatters["*"]
}
}
}

View File

@ -98,111 +98,8 @@ function forEachInterpolatedVars(str:string, replacer:InterpolatedVarReplacer, o
return result;
}
/**
*
* @param {*} scope
* @param {*} activeLanguage
*/
function resetScopeCache(scope:VoerkaI18nScope, activeLanguage:string | null) {
scope.cache = { activeLanguage, typedFormatters: {}, formatters: {} };
}
/**
*
*
* ,
*
const formatters = {
"*":{
$types:{...} // 在所有语言下只作用于特定数据类型的格式化器
}, // 在所有语言下生效的格式化器
zh:{
$types:{
[]:(value)=>{...} // 默认
},
[]:(value)=>{...},
[]:(value)=>{...},
[]:(value)=>{...},
},
en:{.....}
}
* @param {*} scope
* @param {*} activeLanguage
* @param {*} dataType
* @returns {Function}
*/
function getDataTypeDefaultFormatter(scope:VoerkaI18nScope, activeLanguage:string , dataType:SupportedDateTypes) {
// 当指定数据类型的的默认格式化器的缓存处理
if (!scope.cache) resetScopeCache(scope,activeLanguage);
if (scope.cache.activeLanguage === activeLanguage) {
if (scope.cache.typedFormatters && dataType in scope.cache.typedFormatters)
return scope.cache.typedFormatters[dataType];
} else {
resetScopeCache(scope, activeLanguage); // 当语言切换时清空缓存
}
const fallbackLanguage = scope.getLanguage(activeLanguage)?.fallback;
// 先在当前作用域中查找,再在全局查找
const targets = [
scope.formatters.types,
scope.formatters.getTypes(fallbackLanguage),
scope.formatters.getTypes("*"),
scope.global.formatters.types,
scope.global.formatters.getTypes(fallbackLanguage),
scope.global.formatters.getTypes("*"),
];
for (const target of targets) {
if (!target) continue;
if(target){
if (isPlainObject(target.$types) && isFunction(target.$types?.[dataType])) {
return (scope.cache.typedFormatters[dataType] = target.$types[dataType]);
}
}
}
}
/**
*
*
*
* -
* -
* - 退
* -
* -
*
* @param {*} scope
* @param {*} activeLanguage
* @param {*} name
* @returns {Function}
*/
function getFormatter(scope:VoerkaI18nScope, activeLanguage:string, name:string) {
// 1. 从缓存中直接读取: 缓存格式化器引用,避免重复检索
if (!scope.cache) resetScopeCache(scope,activeLanguage);
if (scope.cache.activeLanguage === activeLanguage) {
if (name in scope.cache.formatters)
return scope.cache.formatters[name];
} else { // 当语言切换时清空缓存
resetScopeCache(scope, activeLanguage);
}
const fallbackLanguage = scope.getLanguage(activeLanguage)?.fallback;
// 2. 先在当前作用域中查找,再在全局查找 formatters={$types,$config,[格式化器名称]:()=>{},[格式化器名称]:()=>{}}
const range = [
scope.formatters.formatters,
scope.formatters.getFormatters(fallbackLanguage),
scope.formatters.getFormatters('*'),
scope.global.formatters.formatters,
scope.global.formatters.getFormatters(fallbackLanguage),
scope.global.formatters.getFormatters('*'),
];
for (const formatters of range) {
if (!formatters) continue;
if (isFunction(formatters[name])) {
return (scope.cache.formatters[name] = formatters[name]);
}
}
}
export type FormatterChecker = ((value:any,config?:VoerkaI18nFormatterConfigs)=>any) & {
$name:string
}
@ -334,7 +231,7 @@ function wrapperFormatters(scope:VoerkaI18nScope, activeLanguage:string, formatt
let wrappedFormatters:VoerkaI18nFormatter[] = [];
addDefaultFormatters(formatters);
for (let [name, args] of formatters) {
let fn = getFormatter(scope, activeLanguage, name);
let fn = scope.formatters.get(name,{on:'scope'})
let formatter;
if (isFunction(fn)) {
formatter = (value:any, args?:any[],config?:VoerkaI18nFormatterConfigs) =>fn.call(scope.activeFormatterConfig, value, args, config);
@ -371,11 +268,7 @@ function getFormattedValue(scope:VoerkaI18nScope, activeLanguage:string, formatt
// EMPTY和ERROR是默认两个格式化器如果只有两个则说明在t(...)中没有指定格式化器
if (formatterFuncs.length == 2) {
// 当没有格式化器时,查询是否指定了默认数据类型的格式化器,如果有则执行
const defaultFormatter = getDataTypeDefaultFormatter(
scope,
activeLanguage,
getDataTypeName(value)
);
const defaultFormatter = scope.formatters.get(getDataTypeName(value),{on:'types'})
if (defaultFormatter) {
return executeFormatter(value, [defaultFormatter], scope, template);
}

View File

@ -47,7 +47,7 @@ export class VoerkaI18nManager extends EventEmitter{
#options?:Required<VoerkaI18nManagerOptions>
#scopes:VoerkaI18nScope[] = []
#defaultMessageLoader?:VoerkaI18nDefaultMessageLoader
#formatters:VoerkaI18nLanguageFormatters = {}
#formatters:VoerkaI18nFormatterRegistry = new VoerkaI18nFormatterRegistry()
constructor(options?:VoerkaI18nManagerOptions){
super()
if(VoerkaI18nManager.instance){
@ -72,7 +72,7 @@ export class VoerkaI18nManager extends EventEmitter{
*/
private loadInitialFormatters(){
if(this.#options?.formatters){
this.#formatters = this.#options!.formatters
this.#formatters.loadInitials(this.#options.formatters)
delete (this.#options as any).formatters
}
}
@ -149,19 +149,7 @@ export class VoerkaI18nManager extends EventEmitter{
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 any
if (DataTypes.includes(name)) {
if(!lngFormatters.$types) lngFormatters.$types = {}
lngFormatters.$types![name] = formatter
} else {
lngFormatters[name] = formatter;
}
}
});
this.#formatters.register(name,formatter,{language})
}
/**
*
@ -171,6 +159,9 @@ export class VoerkaI18nManager extends EventEmitter{
this.#defaultMessageLoader = fn
this.refresh()
}
/**
*
*/
async refresh(){
try{
let requests = this.#scopes.map(scope=>scope.refresh())

View File

@ -1,7 +1,6 @@
import { isPlainObject } from "flex-tools/typecheck/isPlainObject"
import { isFunction } from "flex-tools/typecheck/isFunction"
import { translate } from "./translate"
import { deepMerge } from "flex-tools/object/deepMerge"
import { assignObject } from "flex-tools/object/assignObject"
import {VoerkaI18nManager } from "./manager"
import type {
@ -13,7 +12,6 @@ import type {
VoerkaI18nLanguageDefine,
VoerkaI18nLanguageMessages,
VoerkaI18nLanguagePack,
VoerkaI18nScopeCache,
VoerkaI18nTranslate,
VoerkaI18nMessageLoaders,
VoerkaI18nTypesFormatters,
@ -44,8 +42,7 @@ export class VoerkaI18nScope {
#t:VoerkaI18nTranslate
#activeFormatters:VoerkaI18nFormatters = {}
#activeFormatterConfig: VoerkaI18nFormatterConfigs={}
#cache:VoerkaI18nScopeCache
#formatterRegistry:VoerkaI18nFormatterRegistry = new VoerkaI18nFormatterRegistry()
#formatterRegistry:VoerkaI18nFormatterRegistry
#defaultLanguage:string ='zh'
#activeLanguage:string='zh'
#currentMessages:VoerkaI18nLanguageMessages = {} // 当前语言包
@ -58,13 +55,8 @@ export class VoerkaI18nScope {
messages : {}, // 所有语言包={[language]:VoerkaI18nLanguageMessages}
idMap : {}, // 消息id映射列表
formatters : {}, // 当前作用域的格式化函数列表{<lang>: {$types,$config,[格式化器名称]: () => {},[格式化器名称]: () => {}}}
},options) as Required<VoerkaI18nScopeOptions>
// 用来缓存格式化器的引用,当使用格式化器时可以直接引用,减少检索遍历
this.#cache = {
activeLanguage : this.#options.activeLanguage,
typedFormatters: {},
formatters : {},
};
},options) as Required<VoerkaI18nScopeOptions>
this.#formatterRegistry= new VoerkaI18nFormatterRegistry(this)
// 初始化
this.init()
// 将当前实例注册到全局单例VoerkaI18nManager中
@ -89,8 +81,6 @@ export class VoerkaI18nScope {
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 }
get translate(){return this.#t}
get t(){return this.#t}
@ -208,80 +198,11 @@ export class VoerkaI18nScope {
private loadInitialFormatters(){
// 初始化格式化器
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)){
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
}
})
// 切换到当前语言的格式化器上下文
this.formatters.change(this.activeLanguage)
// 保存到Registry中就可以从options中删除了
delete (this.#options as any).formatters
// 切换到当前语言的格式化器上下文
this.changeFormatters(this.activeLanguage)
}
/**
*
*
*
*
*
*
* $config参数采用合并继承机制,
*
*
* @param {*} language
*/
private async changeFormatters(newLanguage:string) {
try {
if (this.formatters.hasLanguage(newLanguage)) {
this.formatters.language = newLanguage
// 如果该语言的格式化器集合是异步加载,需要等待加载完成
await this.formatters.load()
// 合并生成格式化器的配置参数,当执行格式化器时该参数将被传递给格式化器
this._generateFormatterConfig(newLanguage)
} else {
if (this.debug) console.warn(`Not configured <${newLanguage}> formatters.`);
}
} catch (e:any) {
if (this.debug) console.error(`Error loading ${newLanguage} formatters: ${e.message}`);
}
}
/**
*
*/
private _generateFormatterConfig(language:string){
try{
const fallbackLanguage = this.getLanguage(language)?.fallback;
let configSources = [
// 从全局读取
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, curConfig)=>{
if(isPlainObject(curConfig)) deepMerge(finalConfig,curConfig,{newObject:false,array:'replace'})
return finalConfig
},{})
}catch(e){
if(this.debug) console.error(`Error while generate <${language}> formatter options: `,e)
return this.#activeFormatters.$config || {}
}
}
/**
*
* @param {Function} Promise
@ -364,7 +285,7 @@ export class VoerkaI18nScope {
if (newLanguage === this.defaultLanguage) {
this.#currentMessages = this.default;
await this._patch(this.#currentMessages, newLanguage); // 异步补丁
await this.changeFormatters(newLanguage);
await this.formatters.change(newLanguage);
this.#refreshing = false
return;
}else{ // 非默认语言可以是静态语言包也可以是异步加载语言包
@ -379,7 +300,7 @@ export class VoerkaI18nScope {
await this._patch(this.#currentMessages, newLanguage);
}
// 切换到对应语言的格式化器
await this.changeFormatters(newLanguage);
await this.formatters.change(newLanguage);
}else{
this._fallback();
}

View File

@ -62,12 +62,6 @@ export interface VoerkaI18nMessageLoaders {
export type VoerkaI18nDefaultMessageLoader = (this:VoerkaI18nScope,newLanguage:string,scope:VoerkaI18nScope)=>Promise<VoerkaI18nLanguageMessages>
export interface VoerkaI18nScopeCache{
activeLanguage :string | null,
typedFormatters: VoerkaI18nLanguageFormatters,
formatters : VoerkaI18nLanguageFormatters,
}
export type TranslateMessageVars = number | boolean | string | Function | Date
export interface VoerkaI18nTranslate {
(message: string, ...args: TranslateMessageVars[]): string