173 lines
6.7 KiB
JavaScript
173 lines
6.7 KiB
JavaScript
const {DataTypes,getDataTypeName,isFunction,deepMerge,toBoolean} = require("./utils")
|
||
const {createFormatter,Formatter,FlexFormatter,createFlexFormatter} = require("./formatter")
|
||
const { toDate } = require("./datatypes/datetime")
|
||
const { toNumber } = require("./datatypes/numeric")
|
||
const EventEmitter = require("./eventemitter")
|
||
const inlineFormatters = require("./formatters")
|
||
const VoerkaI18nScope = require("./scope")
|
||
const { translate } = require("./translate")
|
||
|
||
// 默认语言配置
|
||
const defaultLanguageSettings = {
|
||
debug : true,
|
||
defaultLanguage: "zh",
|
||
activeLanguage : "zh",
|
||
formatters : inlineFormatters,
|
||
languages : [
|
||
{name:"zh",title:"中文",default:true},
|
||
{name:"en",title:"英文"}
|
||
]
|
||
}
|
||
|
||
/**
|
||
* 多语言管理类
|
||
*
|
||
* 当导入编译后的多语言文件时(import("./languages")),会自动生成全局实例VoerkaI18n
|
||
*
|
||
* VoerkaI18n.languages // 返回支持的语言列表
|
||
* VoerkaI18n.defaultLanguage // 默认语言
|
||
* VoerkaI18n.language // 当前语言
|
||
* VoerkaI18n.change(language) // 切换到新的语言
|
||
*
|
||
*
|
||
* VoerkaI18n.on("change",(language)=>{}) // 注册语言切换事件
|
||
* VoerkaI18n.off("change",(language)=>{})
|
||
*
|
||
* */
|
||
class VoerkaI18nManager extends EventEmitter{
|
||
constructor(settings={}){
|
||
super()
|
||
if(VoerkaI18nManager.instance!=null){
|
||
return VoerkaI18nManager.instance;
|
||
}
|
||
VoerkaI18nManager.instance = this;
|
||
this._settings = deepMerge(defaultLanguageSettings,settings)
|
||
this._scopes=[] // 保存VoerkaI18nScope实例
|
||
this._defaultMessageLoader = null // 默认语言包加载器
|
||
}
|
||
get settings(){ return this._settings } // 配置参数
|
||
get scopes(){ return this._scopes } // 注册的报有VoerkaI18nScope实例q
|
||
get activeLanguage(){ return this._settings.activeLanguage} // 当前激活语言 名称
|
||
get defaultLanguage(){ return this._settings.defaultLanguage} // 默认语言名称
|
||
get languages(){ return this._settings.languages} // 支持的语言列表
|
||
get formatters(){ return this._settings.formatters } // 内置格式化器{*:{$config,$types,...},zh:{$config,$types,...},en:{$config,$types,...}}
|
||
get defaultMessageLoader(){ return this._defaultMessageLoader} // 默认语言包加载器
|
||
|
||
// 通过默认加载器加载文件
|
||
async loadMessagesFromDefaultLoader(newLanguage,scope){
|
||
if(!isFunction(this._defaultMessageLoader)) return //throw new Error("No default message loader specified")
|
||
return await this._defaultMessageLoader.call(scope,newLanguage,scope)
|
||
}
|
||
/**
|
||
* 切换语言
|
||
*/
|
||
async change(language){
|
||
if(this.languages.findIndex(lang=>lang.name === language)!==-1 || isFunction(this._defaultMessageLoader)){
|
||
await this._refreshScopes(language) // 通知所有作用域刷新到对应的语言包
|
||
this._settings.activeLanguage = language
|
||
await this.emit(language) // 触发语言切换事件
|
||
return language
|
||
}else{
|
||
throw new Error("Not supported language:"+language)
|
||
}
|
||
}
|
||
/**
|
||
* 当切换语言时调用此方法来加载更新语言包
|
||
* @param {*} newLanguage
|
||
*/
|
||
async _refreshScopes(newLanguage){
|
||
try{
|
||
const scopeRefreshers = this._scopes.map(scope=>{
|
||
return scope.refresh(newLanguage)
|
||
})
|
||
if(Promise.allSettled){
|
||
await Promise.allSettled(scopeRefreshers)
|
||
}else{
|
||
await Promise.all(scopeRefreshers)
|
||
}
|
||
}catch(e){
|
||
console.warn("Error while refreshing i18n scopes:",e.message)
|
||
}
|
||
}
|
||
/**
|
||
*
|
||
* 注册一个新的作用域
|
||
*
|
||
* 每一个库均对应一个作用域,每个作用域可以有多个语言包,且对应一个翻译函数
|
||
* 除了默认语言外,其他语言采用动态加载的方式
|
||
*
|
||
* @param {*} scope
|
||
*/
|
||
async register(scope){
|
||
if(!(scope instanceof VoerkaI18nScope)){
|
||
throw new TypeError("Scope must be an instance of VoerkaI18nScope")
|
||
}
|
||
this._scopes.push(scope)
|
||
await scope.refresh(this.activeLanguage)
|
||
}
|
||
/**
|
||
* 注册全局格式化器
|
||
* 格式化器是一个简单的同步函数value=>{...},用来对输入进行格式化后返回结果
|
||
*
|
||
* registerFormatter(name,value=>{...}) // 注册到所有语言
|
||
* registerFormatter(name,value=>{...},{langauge:"zh"}) // 注册到zh语言
|
||
* registerFormatter(name,value=>{...},{langauge:"en"}) // 注册到en语言
|
||
registerFormatter("Date",value=>{...},{langauge:"en"}) // 注册到en语言的默认数据类型格式化器
|
||
registerFormatter(name,value=>{...},{langauge:["zh","cht"]}) // 注册到zh和cht语言
|
||
registerFormatter(name,value=>{...},{langauge:"zh,cht"})
|
||
|
||
|
||
* @param {*} formatter
|
||
language : 声明该格式化器适用语言
|
||
isGlobal : 注册到全局
|
||
*/
|
||
registerFormatter(name,formatter,{language="*"}={}){
|
||
if(!isFunction(formatter) || typeof(name)!=="string"){
|
||
throw new TypeError("Formatter must be a function")
|
||
}
|
||
language = Array.isArray(language) ? language : (language ? language.split(",") : [])
|
||
language.forEach(lng=>{
|
||
if(DataTypes.includes(name)){
|
||
this.formatters[lng].$types[name] = formatter
|
||
}else{
|
||
this.formatters[lng][name] = formatter
|
||
}
|
||
})
|
||
}
|
||
/**
|
||
* 注册默认文本信息加载器
|
||
*/
|
||
registerDefaultLoader(fn){
|
||
if(!isFunction(fn)) 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(e){
|
||
if(this._debug) console.error(`Error while refresh voerkai18n scopes:${e.message}`)
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
module.exports ={
|
||
toDate,
|
||
toNumber,
|
||
toBoolean,
|
||
deepMerge,
|
||
VoerkaI18nManager,
|
||
translate,
|
||
VoerkaI18nScope,
|
||
createFormatter,
|
||
Formatter,
|
||
createFlexFormatter,
|
||
FlexFormatter,
|
||
getDataTypeName
|
||
} |