update for typescript
This commit is contained in:
parent
a9f63c2c35
commit
88db8cb686
@ -6,13 +6,21 @@ import zhFormatters from '../formatters/zh';
|
||||
import enFormatters from '../formatters/en';
|
||||
import { VoerkaI18nManager } from '../manager';
|
||||
import { VoerkaI18nFormatterRegistry } from '../formatterRegistry';
|
||||
import { VoerkaI18nLanguageMessages } from '../types';
|
||||
|
||||
import { VoerkaI18nLanguageMessages, VoerkaI18nFormatterConfigs } from '../types';
|
||||
import { deepMerge } from 'flex-tools/object/deepMerge';
|
||||
import { isPlainObject } from 'flex-tools/typecheck/isPlainObject';
|
||||
import { default as inlineFormatters } from '../formatters';
|
||||
|
||||
function mergeFormattersConfigs(configSources:any[]){
|
||||
return configSources.reduce((finalConfig, curConfig)=>{
|
||||
if(isPlainObject(curConfig)) deepMerge(finalConfig,curConfig,{newObject:false,array:'replace'})
|
||||
return finalConfig
|
||||
},{})
|
||||
}
|
||||
const zhMessages:VoerkaI18nLanguageMessages = {
|
||||
$config:{
|
||||
x:{a:1},
|
||||
y:{b:1}
|
||||
add:{a:1},
|
||||
dec:{b:1}
|
||||
},
|
||||
"1": "你好",
|
||||
"2": "你好,{name}",
|
||||
@ -42,19 +50,51 @@ const languages = [
|
||||
{ name: "en"}
|
||||
]
|
||||
|
||||
Object.assign(zhFormatters.$config,{
|
||||
x:{x1:1,x2:2},
|
||||
y:{y1:1,y2:2}
|
||||
})
|
||||
Object.assign(enFormatters.$config,{
|
||||
x:{x1:11,x2:22},
|
||||
y:{y1:11,y2:22},
|
||||
z:{z1:11,z2:22}
|
||||
})
|
||||
|
||||
const formatters ={
|
||||
zh:zhFormatters,
|
||||
en:enFormatters,
|
||||
"*":{
|
||||
$config:{
|
||||
x:{g:1},
|
||||
y:{g:1},
|
||||
g:{g1:1,g2:2}
|
||||
},
|
||||
add:(value:any,args?:any[],$config?:VoerkaI18nFormatterConfigs)=>'*'+ value+1,
|
||||
},
|
||||
zh:{
|
||||
first:(value:any)=>'ZH'+value[0],
|
||||
...zhFormatters
|
||||
},
|
||||
en:{
|
||||
first:(value:any)=>'EN'+value[0],
|
||||
...enFormatters,
|
||||
},
|
||||
jp:()=>{}
|
||||
}
|
||||
|
||||
describe("VoerkaI18nScope", () => {
|
||||
let scope = new VoerkaI18nScope({
|
||||
id: "test",
|
||||
languages,
|
||||
idMap,
|
||||
messages,
|
||||
formatters
|
||||
describe("VoerkaI18nScope", () => {
|
||||
let scope:VoerkaI18nScope;
|
||||
beforeAll(async ()=>{
|
||||
return new Promise((resolve)=>{
|
||||
scope = new VoerkaI18nScope({
|
||||
id: "test",
|
||||
languages,
|
||||
idMap,
|
||||
messages,
|
||||
formatters,
|
||||
callback:()=>{
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
test("成功创建实例", () => {
|
||||
expect(scope).toBeInstanceOf(VoerkaI18nScope)
|
||||
@ -63,20 +103,50 @@ describe("VoerkaI18nScope", () => {
|
||||
expect(scope.messages).toEqual(messages)
|
||||
expect(scope.default).toEqual(zhMessages)
|
||||
expect(scope.current).toEqual(zhMessages)
|
||||
expect(scope.idMap).toEqual(idMap)
|
||||
// 格式化器配置
|
||||
expect(scope.formatters).toBeInstanceOf(VoerkaI18nFormatterRegistry)
|
||||
expect(scope.formatters.language).toBe("zh")
|
||||
expect(scope.formatters.formatters).toEqual(formatters)
|
||||
expect(scope.formatters.config).toBe(zhFormatters.$config)
|
||||
expect(scope.formatters.types).toBe(zhFormatters.$types)
|
||||
|
||||
|
||||
expect(scope.idMap).toEqual(idMap)
|
||||
// 全局管理器
|
||||
expect(scope.global).toBeInstanceOf(VoerkaI18nManager)
|
||||
})
|
||||
|
||||
|
||||
test("格式化器配置", async () => {
|
||||
expect(scope.formatters).toBeInstanceOf(VoerkaI18nFormatterRegistry)
|
||||
expect(scope.formatters.activeLanguage).toBe("zh")
|
||||
expect(scope.formatters.formatters).toEqual(formatters)
|
||||
expect(scope.formatters.config).toBe(zhFormatters.$config)
|
||||
expect(scope.formatters.types).toBe(zhFormatters.$types)
|
||||
})
|
||||
test("查找格式化器", async () => {
|
||||
expect(scope.formatters.get("add")).toBe(formatters['*'].add)
|
||||
expect(scope.formatters.get("first")).toBe(formatters.zh.first)
|
||||
await scope.change("en")
|
||||
expect(scope.formatters.get("first")).toBe(formatters.en.first)
|
||||
})
|
||||
test("格式化器配置", async () => {
|
||||
let fallbackLanguage = scope.getLanguage(scope.activeLanguage)?.fallback
|
||||
const globalFormatters = inlineFormatters
|
||||
let scopeConfig = mergeFormattersConfigs([
|
||||
globalFormatters['*'].$config,
|
||||
(fallbackLanguage! in globalFormatters) ? (globalFormatters as any)?.[fallbackLanguage!].$config:{},
|
||||
globalFormatters.zh.$config,
|
||||
formatters['*'].$config,
|
||||
(fallbackLanguage! in formatters) ? (formatters as any)?.[fallbackLanguage!]?.$config:{},
|
||||
formatters.zh.$config
|
||||
])
|
||||
expect(scope.formatters.config).toEqual(scopeConfig)
|
||||
//
|
||||
await scope.change("en")
|
||||
fallbackLanguage = scope.getLanguage(scope.activeLanguage)?.fallback
|
||||
scopeConfig = mergeFormattersConfigs([
|
||||
globalFormatters['*'].$config,
|
||||
(fallbackLanguage! in globalFormatters) ? (globalFormatters as any)?.[fallbackLanguage!].$config:{},
|
||||
// globalFormatters.zh.$config,
|
||||
formatters['*'].$config,
|
||||
(fallbackLanguage! in formatters) ? (formatters as any)?.[fallbackLanguage!]?.$config:{},
|
||||
formatters.en.$config
|
||||
])
|
||||
expect(scope.formatters.config).toEqual(scopeConfig)
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
test('translate', () => {})
|
||||
|
@ -6,13 +6,19 @@
|
||||
*/
|
||||
import { isPlainObject } from 'flex-tools/typecheck/isPlainObject';
|
||||
import type { VoerkaI18nScope } from './scope';
|
||||
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';
|
||||
|
||||
import { VoerkaI18nFormatter,
|
||||
VoerkaI18nFormatters,
|
||||
VoerkaI18nFormattersLoader,
|
||||
VoerkaI18nLanguageFormatters,
|
||||
SupportedDateTypes,
|
||||
VoerkaI18nFormatterConfigs,
|
||||
VoerkaI18nTypesFormatters
|
||||
} from './types';
|
||||
|
||||
export interface VoerkaI18nScopeCache{
|
||||
activeLanguage :string | null,
|
||||
@ -46,14 +52,15 @@ export class VoerkaI18nFormatterRegistry{
|
||||
#activeFormatters:VoerkaI18nFormatters = {}
|
||||
#activeFormattersConfigs :VoerkaI18nFormatterConfigs = {}
|
||||
#scope?:VoerkaI18nScope
|
||||
#language:string // 当前语言
|
||||
#language?:string // 当前语言
|
||||
#formatterCache:VoerkaI18nScopeFormatterCache = {typedFormatters:{},formatters:{}}
|
||||
constructor(scope?:VoerkaI18nScope){
|
||||
this.#scope = scope
|
||||
this.#language = scope?.activeLanguage || "zh"
|
||||
this.#scope = scope
|
||||
}
|
||||
get activeLanguage(){ return this.#language } // 当前语言
|
||||
get activeFormatters(){ return this.#activeFormatters } // 当前语言的格式化器集合
|
||||
get activeLanguage(){
|
||||
if(!this.#language) this.#language = this.#scope?.activeLanguage || "zh"
|
||||
return this.#language
|
||||
} // 当前语言
|
||||
get scope(){ return this.#scope }
|
||||
/**
|
||||
* 当切换语言时,切换当前语言的格式化器
|
||||
@ -62,7 +69,7 @@ export class VoerkaI18nFormatterRegistry{
|
||||
*/
|
||||
async change(language:string){
|
||||
try {
|
||||
if (language in this.formatters) {
|
||||
if (language in this. formatters) {
|
||||
this.#language = language
|
||||
const formatters = this.formatters[language]
|
||||
if(isFunction(formatters)){
|
||||
@ -81,19 +88,19 @@ export class VoerkaI18nFormatterRegistry{
|
||||
if (this.scope?.debug) console.error(`Error loading ${language} formatters: ${e.message}`);
|
||||
}
|
||||
}
|
||||
private async generateFormattersConfigs(language:string){
|
||||
private generateFormattersConfigs(language:string){
|
||||
try{
|
||||
const configSources = [ ]
|
||||
const fallbackLanguage = this.scope?.getLanguage(language)?.fallback || 'en';
|
||||
const fallbackLanguage = this.scope?.getLanguage(language)?.fallback ;
|
||||
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)
|
||||
if(fallbackLanguage) configSources.push(this.scope.global.formatters.getConfig(fallbackLanguage))
|
||||
configSources.push(this.scope.global.formatters.getConfig(language))
|
||||
}
|
||||
// 从当前Scope读取
|
||||
configSources.push(this.getConfig('*'))
|
||||
configSources.push(this.getConfig(fallbackLanguage))
|
||||
configSources.push(this.config)
|
||||
if(fallbackLanguage) configSources.push(this.getConfig(fallbackLanguage))
|
||||
configSources.push(this.getConfig(language))
|
||||
// 合并当前语言的格式化器配置参数
|
||||
this.#activeFormattersConfigs = configSources.reduce((finalConfig, curConfig)=>{
|
||||
if(isPlainObject(curConfig)) deepMerge(finalConfig,curConfig,{newObject:false,array:'replace'})
|
||||
@ -182,11 +189,12 @@ export class VoerkaI18nFormatterRegistry{
|
||||
//****************** 以下方法和属性只作用于当前语言 *********************** */
|
||||
|
||||
get formatters(){ return this.#formatters } // 所有语言的格式化器集合
|
||||
get activeFormatters(){ return this.#activeFormatters } // 当前语言的格式化器集合
|
||||
/**
|
||||
* 当前语言的格式化器配置
|
||||
*/
|
||||
get config(){
|
||||
return (this.#activeFormatters as VoerkaI18nFormatters).$config as VoerkaI18nFormatterConfigs
|
||||
return this.#activeFormattersConfigs
|
||||
}
|
||||
get types(){
|
||||
return (this.#activeFormatters as VoerkaI18nFormatters).$types as VoerkaI18nFormatterConfigs
|
||||
@ -213,28 +221,28 @@ export class VoerkaI18nFormatterRegistry{
|
||||
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 fallbackLanguage = this.scope?.getLanguage(this.activeLanguage)?.fallback
|
||||
|
||||
// 先在当前作用域中查找,再在全局查找
|
||||
const targets =[]
|
||||
|
||||
if(on=="types"){
|
||||
targets.push(this.types)
|
||||
targets.push(this.getTypes(fallbackLanguage))
|
||||
if(fallbackLanguage) 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))
|
||||
if(fallbackLanguage) 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.#activeFormatters)
|
||||
if(fallbackLanguage) 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("*"))
|
||||
targets.push(this.scope?.global.formatters.activeFormatters)
|
||||
if(fallbackLanguage) targets.push(this.scope?.global.formatters.getFormatters(fallbackLanguage))
|
||||
targets.push(this.scope?.global.formatters.getFormatters("*"))
|
||||
}
|
||||
}
|
||||
// 查找指定名称的格式化器
|
||||
|
@ -8,9 +8,7 @@ import zhFormatters from "./zh"
|
||||
import defaultFormatters from "./default"
|
||||
|
||||
export default {
|
||||
"*":{
|
||||
...enFormatters,
|
||||
...defaultFormatters
|
||||
},
|
||||
"*":defaultFormatters,
|
||||
en:enFormatters,
|
||||
zh:zhFormatters
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ function executeChecker(checker:FormatterChecker, value:any,scope:VoerkaI18nScop
|
||||
let result = { value, next: "skip" };
|
||||
if (!isFunction(checker)) return result;
|
||||
try {
|
||||
const r = checker(value,scope.activeFormatterConfig);
|
||||
const r = checker(value,scope.formatters.config);
|
||||
if (isPlainObject(r) && ("next" in r) && ("value" in r)) {
|
||||
Object.assign(result, r);
|
||||
} else {
|
||||
@ -174,7 +174,7 @@ function executeFormatter(value:any, formatters:VoerkaI18nFormatter[], scope:Voe
|
||||
// 3. 分别执行格式化器函数
|
||||
for (let formatter of formatters) {
|
||||
try {
|
||||
result = formatter(result, [result],scope.activeFormatterConfig);
|
||||
result = formatter(result, [result],scope.formatters.config);
|
||||
} catch (e:any) {
|
||||
e.formatter = (formatter as any).$name;
|
||||
if (scope.debug)
|
||||
@ -234,7 +234,9 @@ function wrapperFormatters(scope:VoerkaI18nScope, activeLanguage:string, formatt
|
||||
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);
|
||||
formatter = (value:any, args?:any[],config?:VoerkaI18nFormatterConfigs) =>{
|
||||
return (fn as Function).call(scope.formatters.config, value, args, config);
|
||||
}
|
||||
} else {
|
||||
// 格式化器无效或者没有定义时,查看当前值是否具有同名的原型方法,如果有则执行调用
|
||||
// 比如padStart格式化器是String的原型方法,不需要配置就可以直接作为格式化器调用
|
||||
@ -264,7 +266,7 @@ function wrapperFormatters(scope:VoerkaI18nScope, activeLanguage:string, formatt
|
||||
function getFormattedValue(scope:VoerkaI18nScope, activeLanguage:string, formatters:FormatterDefineChain, value:any, template:string) {
|
||||
// 1. 取得格式化器函数列表,然后经过包装以传入当前格式化器的配置参数
|
||||
const formatterFuncs = wrapperFormatters(scope, activeLanguage, formatters);
|
||||
// 3. 执行格式化器
|
||||
// 2. 执行格式化器
|
||||
// EMPTY和ERROR是默认两个格式化器,如果只有两个则说明在t(...)中没有指定格式化器
|
||||
if (formatterFuncs.length == 2) {
|
||||
// 当没有格式化器时,查询是否指定了默认数据类型的格式化器,如果有则执行
|
||||
|
@ -4,8 +4,7 @@ import { EventEmitter } from "./eventemitter"
|
||||
import inlineFormatters from "./formatters"
|
||||
import type { VoerkaI18nScope } from "./scope"
|
||||
import type { VoerkaI18nLanguageDefine, VoerkaI18nLanguageFormatters, VoerkaI18nDefaultMessageLoader, VoerkaI18nFormatter, VoerkaI18nTypesFormatters } from "./types"
|
||||
import { VoerkaI18nFormatterRegistry } from "./formatterRegistry"
|
||||
import { DataTypes } from "./utils"
|
||||
import { VoerkaI18nFormatterRegistry } from "./formatterRegistry"
|
||||
|
||||
// 默认语言配置
|
||||
const defaultLanguageSettings = {
|
||||
|
@ -4,7 +4,6 @@ import { translate } from "./translate"
|
||||
import { assignObject } from "flex-tools/object/assignObject"
|
||||
import {VoerkaI18nManager } from "./manager"
|
||||
import type {
|
||||
VoerkaI18nFormatterConfigs,
|
||||
VoerkaI18nDefaultMessageLoader,
|
||||
VoerkaI18nFormatter,
|
||||
VoerkaI18nLanguageFormatters,
|
||||
@ -12,27 +11,26 @@ import type {
|
||||
VoerkaI18nLanguageDefine,
|
||||
VoerkaI18nLanguageMessages,
|
||||
VoerkaI18nLanguagePack,
|
||||
VoerkaI18nTranslate,
|
||||
VoerkaI18nMessageLoaders,
|
||||
VoerkaI18nTypesFormatters,
|
||||
VoerkaI18nFormatters,
|
||||
VoerkaI18nTranslate,
|
||||
VoerkaI18nDynamicLanguageMessages,
|
||||
VoerkaI18nLanguageMessagePack,
|
||||
VoerkaI18nMessageLoader,
|
||||
VoerkaI18nLanguageMessagePack,
|
||||
VoerkaI18nMessageLoader,
|
||||
} from "./types"
|
||||
import { VoerkaI18nFormatterRegistry } from './formatterRegistry';
|
||||
import { InvalidLanguageError } from "./errors"
|
||||
import { randomId } from "./utils"
|
||||
import { DefaultLanguageSettings, DefaultFallbackLanguage } from './consts';
|
||||
|
||||
export interface VoerkaI18nScopeOptions {
|
||||
id?: string
|
||||
debug?: boolean
|
||||
languages: VoerkaI18nLanguageDefine[] // 当前作用域支持的语言列表
|
||||
defaultLanguage?: string // 默认语言名称
|
||||
activeLanguage?: string // 当前语言名称
|
||||
messages: VoerkaI18nLanguageMessagePack // 当前语言包
|
||||
idMap: Voerkai18nIdMap // 消息id映射列表
|
||||
languages: VoerkaI18nLanguageDefine[] // 当前作用域支持的语言列表
|
||||
defaultLanguage?: string // 默认语言名称
|
||||
activeLanguage?: string // 当前语言名称
|
||||
messages: VoerkaI18nLanguageMessagePack // 当前语言包
|
||||
idMap: Voerkai18nIdMap // 消息id映射列表
|
||||
formatters: VoerkaI18nLanguageFormatters // 当前作用域的格式化函数列表{<lang>: {$types,$config,[格式化器名称]: () => {},[格式化器名称]: () => {}}}
|
||||
callback?:(e?:Error)=>void // 当注册到全局管理器后的回调函数
|
||||
}
|
||||
|
||||
export class VoerkaI18nScope {
|
||||
@ -40,14 +38,17 @@ export class VoerkaI18nScope {
|
||||
#global:VoerkaI18nManager // 引用全局VoerkaI18nManager配置,注册后自动引用
|
||||
#refreshing:boolean = false
|
||||
#t:VoerkaI18nTranslate
|
||||
#activeFormatters:VoerkaI18nFormatters = {}
|
||||
#activeFormatterConfig: VoerkaI18nFormatterConfigs={}
|
||||
#formatterRegistry:VoerkaI18nFormatterRegistry
|
||||
#formatterRegistry?:VoerkaI18nFormatterRegistry
|
||||
#defaultLanguage:string ='zh'
|
||||
#activeLanguage:string='zh'
|
||||
#currentMessages:VoerkaI18nLanguageMessages = {} // 当前语言包
|
||||
#patchedMessages:VoerkaI18nLanguagePack = {} // 补丁语言包
|
||||
constructor(options:VoerkaI18nScopeOptions, callback?:(e?:Error)=>void) {
|
||||
/**
|
||||
*
|
||||
* @param options
|
||||
* @param callback 当前作用域初始化完成后的回调函数
|
||||
*/
|
||||
constructor(options:VoerkaI18nScopeOptions) {
|
||||
this.#options = assignObject({
|
||||
id : randomId(), // 作用域唯一id
|
||||
debug : false,
|
||||
@ -56,62 +57,51 @@ export class VoerkaI18nScope {
|
||||
idMap : {}, // 消息id映射列表
|
||||
formatters : {}, // 当前作用域的格式化函数列表{<lang>: {$types,$config,[格式化器名称]: () => {},[格式化器名称]: () => {}}}
|
||||
},options) as Required<VoerkaI18nScopeOptions>
|
||||
this.#formatterRegistry= new VoerkaI18nFormatterRegistry(this)
|
||||
// 初始化
|
||||
this.init()
|
||||
// 将当前实例注册到全局单例VoerkaI18nManager中
|
||||
this.#global = this.registerToManager(callback)
|
||||
// 从本地缓存中读取并合并补丁语言包
|
||||
this._mergePatchedMessages();
|
||||
// 延后执行补丁命令,该命令会向远程下载补丁包
|
||||
this._patch(this.#currentMessages, this.activeLanguage);
|
||||
this.#global = this.registerToManager()
|
||||
this.#t = translate.bind(this)
|
||||
}
|
||||
get id() {return this.#options.id;} // 作用域唯一id
|
||||
get debug() {return this.#options.debug;} // 调试开关
|
||||
get defaultLanguage() {return this.#global.defaultLanguage;} // 默认语言名称
|
||||
get activeLanguage() {return this.#global.activeLanguage;} // 默认语言名称
|
||||
get id() {return this.#options.id;} // 作用域唯一id
|
||||
get debug() {return this.#options.debug;} // 调试开关
|
||||
get defaultLanguage() {return this.#global.defaultLanguage;} // 默认语言名称
|
||||
get activeLanguage() {return this.#global.activeLanguage;} // 默认语言名称
|
||||
// 默认语言包,只能静态语言包,不能是动态语言包
|
||||
get default() {return this.#options.messages[this.#defaultLanguage] as VoerkaI18nLanguageMessages;}
|
||||
get current() {return this.#currentMessages;} // 当前语言包
|
||||
get messages() {return this.#options.messages; } // 所有语言包
|
||||
get idMap() {return this.#options.idMap;} // 消息id映射列表
|
||||
get languages() {return this.#options.languages;} // 当前作用域支持的语言列表[{name,title,fallback}]
|
||||
get global() { return this.#global;} // 引用全局VoerkaI18n配置,注册后自动引用
|
||||
get formatters() { return this.#formatterRegistry;} // 当前作用域的所有格式化器定义 {<语言名称>: {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () => {}}}
|
||||
get activeFormatters() {return this.#formatterRegistry.formatters} // 当前作用域激活的格式化器定义 {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () = >{}}
|
||||
get activeFormatterConfig(){return this.#activeFormatterConfig} // 当前格式化器合并后的配置参数,参数已经合并了全局格式化器中的参数
|
||||
get translate(){return this.#t}
|
||||
get current() {return this.#currentMessages;} // 当前语言包
|
||||
get messages() {return this.#options.messages; } // 所有语言包
|
||||
get idMap() {return this.#options.idMap;} // 消息id映射列表
|
||||
get languages() {return this.#options.languages;} // 当前作用域支持的语言列表[{name,title,fallback}]
|
||||
get global() { return this.#global;} // 引用全局VoerkaI18n配置,注册后自动引用
|
||||
get formatters() { return this.#formatterRegistry!;} // 当前作用域的所有格式化器定义 {<语言名称>: {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () => {}}}
|
||||
get activeFormatters() {return this.#formatterRegistry!.formatters} // 当前作用域激活的格式化器定义 {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () = >{}}
|
||||
get t(){return this.#t}
|
||||
|
||||
/**
|
||||
* 对输入的语言配置进行处理
|
||||
* - 将en配置为默认回退语言
|
||||
* - 确保提供了有效的默认语言和活动语言
|
||||
*/
|
||||
private init(){
|
||||
// 1. 检测语言配置列表是否有效
|
||||
if(!Array.isArray(this.languages)){
|
||||
console.warn("[VoerkaI18n] invalid languages config,use default languages config instead.")
|
||||
this.#options.languages = [
|
||||
{name: "zh",title: "中文",default:true,active:true},
|
||||
{name: "en",title: "英文"}
|
||||
]
|
||||
this.#options.languages =Object.assign([],DefaultLanguageSettings)
|
||||
}else{
|
||||
if(this.languages.length==0){
|
||||
throw new Error("[VoerkaI18n] invalid languages config, languages must not be empty.")
|
||||
}
|
||||
}
|
||||
// 2.为语言配置默认回退语言,并且提取默认语言和活动语言
|
||||
this.languages.forEach(language=>{
|
||||
if(!language.fallback) language.fallback = "en"
|
||||
if(!language.fallback) language.fallback = DefaultFallbackLanguage
|
||||
if(language.default) this.#defaultLanguage = language.name
|
||||
if(language.active) this.#activeLanguage = language.name
|
||||
})
|
||||
// 确保提供了有效的默认语言和活动语言
|
||||
// 3. 确保提供了有效的默认语言和活动语言
|
||||
const lanMessages = this.#options.messages
|
||||
if(!(this.#defaultLanguage in lanMessages)) {
|
||||
this.#defaultLanguage = Object.keys(lanMessages)[0]
|
||||
}
|
||||
|
||||
if(!(this.#activeLanguage in lanMessages)){
|
||||
this.#activeLanguage = this.#defaultLanguage
|
||||
}
|
||||
|
||||
if(!(this.#defaultLanguage in lanMessages)) this.#defaultLanguage = Object.keys(lanMessages)[0]
|
||||
if(!(this.#activeLanguage in lanMessages)) this.#activeLanguage = this.#defaultLanguage
|
||||
if(!(this.#defaultLanguage in lanMessages)){
|
||||
throw new Error("[VoerkaI18n] invalid <defaultLanguage> config, messages not specified.")
|
||||
}
|
||||
@ -141,9 +131,31 @@ export class VoerkaI18nScope {
|
||||
}
|
||||
this.#global = globalThis.VoerkaI18n as unknown as VoerkaI18nManager;
|
||||
if (!isFunction(callback)) callback = () => {};
|
||||
this.#global.register(this).then(()=>(callback as any)()).catch((e)=>(callback as any)(e));
|
||||
this.#global.register(this)
|
||||
.then(this.onRegisterSuccess.bind(this))
|
||||
.catch(this.onRegisterFail.bind(this))
|
||||
return this.#global
|
||||
}
|
||||
/**
|
||||
* 当注册到Manager后,执行注册后的操作
|
||||
*/
|
||||
private onRegisterSuccess(){
|
||||
if(typeof(this.#options.callback)=='function'){
|
||||
this.#options.callback.call(this)
|
||||
}
|
||||
// 从本地缓存中读取并合并补丁语言包
|
||||
this._mergePatchedMessages();
|
||||
// 延后执行补丁命令,该命令会向远程下载补丁包
|
||||
this._patch(this.#currentMessages, this.activeLanguage);
|
||||
}
|
||||
/**
|
||||
* 当注册到Manager失败时,执行注册失败后的操作
|
||||
*/
|
||||
private onRegisterFail(e:any){
|
||||
if(typeof(this.#options.callback)=='function'){
|
||||
this.#options.callback.call(this,e)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 注册格式化器
|
||||
*
|
||||
@ -165,7 +177,7 @@ export class VoerkaI18nScope {
|
||||
if(asGlobal){
|
||||
this.global.registerFormatter(name, formatter, {language});
|
||||
}else{
|
||||
this.#formatterRegistry.register(name, formatter, {language});
|
||||
this.formatters!.register(name, formatter, {language});
|
||||
}
|
||||
}
|
||||
// /**
|
||||
@ -195,11 +207,10 @@ export class VoerkaI18nScope {
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
private loadInitialFormatters(){
|
||||
private loadInitialFormatters(){
|
||||
this.#formatterRegistry= new VoerkaI18nFormatterRegistry(this)
|
||||
// 初始化格式化器
|
||||
this.formatters.loadInitials(this.#options.formatters)
|
||||
// 切换到当前语言的格式化器上下文
|
||||
this.formatters.change(this.activeLanguage)
|
||||
// 保存到Registry中,就可以从options中删除了
|
||||
delete (this.#options as any).formatters
|
||||
}
|
||||
@ -230,9 +241,9 @@ export class VoerkaI18nScope {
|
||||
/**
|
||||
* 回退到默认语言
|
||||
*/
|
||||
private _fallback() {
|
||||
private fallbackToDefault() {
|
||||
this.#currentMessages = this.default;
|
||||
this.#activeLanguage = this.defaultLanguage;
|
||||
this.#activeLanguage = this.#defaultLanguage;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@ -240,8 +251,7 @@ export class VoerkaI18nScope {
|
||||
*
|
||||
* - 简单的对象{}
|
||||
* - 或者是一个返回Promise<VoerkaI18nLanguageMessages>的异步函数
|
||||
* - 或者是全局的默认加载器
|
||||
*
|
||||
* - 或者是全局的默认加载器
|
||||
*
|
||||
* @param language 语言名称
|
||||
* @returns
|
||||
@ -302,11 +312,11 @@ export class VoerkaI18nScope {
|
||||
// 切换到对应语言的格式化器
|
||||
await this.formatters.change(newLanguage);
|
||||
}else{
|
||||
this._fallback();
|
||||
this.fallbackToDefault();
|
||||
}
|
||||
}catch(e:any){
|
||||
if (this.debug) console.warn(`Error while loading language <${newLanguage}> on i18nScope(${this.id}): ${e.message}`);
|
||||
this._fallback();
|
||||
this.fallbackToDefault();
|
||||
} finally {
|
||||
this.#refreshing = false;
|
||||
}
|
||||
|
@ -119,13 +119,13 @@ export function translate(this:VoerkaI18nScope,message:string,...args:any[]):str
|
||||
// 当源文件运用了babel插件后会将原始文本内容转换为msgId
|
||||
// 如果是msgId则从scope.default中读取,scope.default=默认语言包={<id>:<message>}
|
||||
if(isMessageId(result)){
|
||||
result = scope.default[result] || message
|
||||
result = (scope.default as any)[result] || message
|
||||
}
|
||||
}else{
|
||||
// 2.2 从当前语言包中取得翻译文本模板字符串
|
||||
// 如果没有启用babel插件将源文本转换为msgId,需要先将文本内容转换为msgId
|
||||
let msgId = isMessageId(result) ? result : scope.idMap[result]
|
||||
result = scope.current[msgId] || result
|
||||
result = (scope.current as any)[msgId] || result
|
||||
}
|
||||
// 2. 处理复数
|
||||
// 经过上面的处理,content可能是字符串或者数组
|
||||
|
Loading…
x
Reference in New Issue
Block a user