-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #73 from zhangfisher/3.0
3.0
- Loading branch information
Showing
14 changed files
with
380 additions
and
239 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* | ||
* 提供格式化相关逻辑 | ||
* | ||
*/ | ||
|
||
import type { VoerkaI18nScope } from "../../scope"; | ||
import { VoerkaI18nFormatter } from "../../types"; | ||
import { VoerkaI18nFormatterManager } from "./manager"; | ||
|
||
|
||
export class FormatterMixin{ | ||
private _formatters:VoerkaI18nFormatterManager | null = null | ||
get formatters() { return this._formatters!;} // 当前作用域的所有格式化器定义 {<语言名称>: {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () => {}}} | ||
|
||
protected initFormatters(this:VoerkaI18nScope){ | ||
this._formatters = new VoerkaI18nFormatterManager(this) | ||
} | ||
|
||
|
||
|
||
/** | ||
* 初始化格式化器 | ||
* 激活和默认语言的格式化器采用静态导入的形式,而没有采用异步块的形式,这是为了确保首次加载时的能马上读取,而不能采用延迟加载方式 | ||
* #activeFormatters={ | ||
* global:{...} // 或true代表注册到全局 | ||
* $config:{...}, | ||
* $types:{...}, | ||
* [格式化器名称]:()=>{...}, | ||
* [格式化器名称]:()=>{...}, | ||
* ... | ||
* } | ||
*/ | ||
// private _loadInitialFormatters(){ | ||
// this._formatterRegistry= new VoerkaI18nFormatterManager(this) | ||
// // 初始化格式化器 | ||
// this.formatters.loadInitials(this._options.formatters) | ||
// // 保存到Registry中,就可以从options中删除了 | ||
// delete (this.options as any).formatters | ||
// } | ||
|
||
/** | ||
* 注册格式化器 | ||
* | ||
* 格式化器是一个简单的同步函数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 : 字符串或数组,声明该格式化器适用语言 | ||
*代表适用于所有语言 | ||
语言名称,语言名称数组,或者使用,分割的语言名称字符串 | ||
asGlobal : 注册到全局 | ||
*/ | ||
registerFormatter(this:VoerkaI18nScope,name:string, formatter:VoerkaI18nFormatter, options?:{ language?: string | string[] | "*", asGlobal?:boolean } ) { | ||
const {language = "*", asGlobal= true} = options || {} | ||
if(asGlobal){ | ||
this.global.registerFormatter(name, formatter, {language}); | ||
}else{ | ||
this.formatters.register(name, formatter, {language}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/** | ||
* | ||
* 提供翻译函数 | ||
* | ||
*/ | ||
import { isNumber } from "flex-tools/typecheck/isNumber" | ||
import { isPlainObject } from "flex-tools/typecheck/isPlainObject" | ||
import { isFunction } from "flex-tools/typecheck/isFunction" | ||
import type { VoerkaI18nScope } from "../scope" | ||
import { isMessageId } from "../utils/isMessageId" | ||
|
||
|
||
|
||
|
||
export class TranslateMixin{ | ||
|
||
/** | ||
* 根据值的单数和复数形式,从messages中取得相应的消息 | ||
* | ||
* @param {*} messages 复数形式的文本内容 = [<=0时的内容>,<=1时的内容>,<=2时的内容>,...] | ||
* @param {*} value | ||
*/ | ||
private _getPluraMessage(messages:string | string[],value:number){ | ||
try{ | ||
if(Array.isArray(messages)){ | ||
return messages.length > value ? messages[value] : messages[messages.length-1] | ||
}else{ | ||
return messages | ||
} | ||
}catch{ | ||
return Array.isArray(messages) ? messages[0] : messages | ||
} | ||
} | ||
|
||
translate(this:VoerkaI18nScope,message:string,...args:any[]):string { | ||
// 如果内容是复数,则其值是一个数组,数组中的每个元素是从1-N数量形式的文本内容 | ||
let result:string | string[] = message | ||
let vars=[] // 插值变量列表 | ||
let pluraValue = null // 复数值 | ||
|
||
if(!(typeof(message)==="string")) return message | ||
try{ | ||
// 1. 预处理变量: 复数变量保存至pluralVars中 , 变量如果是Function则调用 | ||
if(arguments.length === 2 && isPlainObject(arguments[1])){// 字典插值 | ||
const dictVars:Record<string,any>=arguments[1] | ||
for(const [name,value] of Object.entries(dictVars)){ | ||
if(isFunction(value)){ | ||
try{ | ||
dictVars[name] = value() | ||
}catch{ | ||
dictVars[name] = value | ||
} | ||
} | ||
// 以$开头的视为复数变量,记录下来 | ||
const isNum:boolean = typeof(dictVars[name])==="number" | ||
if((pluraValue==null && isNum) || name.startsWith("$") && isNum){ | ||
pluraValue = dictVars[name] | ||
} | ||
} | ||
vars = [dictVars] | ||
}else if(arguments.length >= 2){ // 位置插值 | ||
vars = [...arguments].splice(1).map((arg)=>{ | ||
try{ | ||
arg = isFunction(arg) ? arg() : arg | ||
// 约定:位置参数中以第一个数值变量作为指示复数变量 | ||
if(isNumber(arg)) pluraValue = parseInt(arg) | ||
}catch{ | ||
return String(arg) | ||
} | ||
return arg | ||
}) | ||
} | ||
|
||
if(isMessageId(message)){ // 如果是数字id, | ||
result = (this.current as any)[message] || message | ||
}else{ | ||
const msgId = this.idMap[message] | ||
// 语言包可能是使用idMap映射过的,则需要转换 | ||
result = (msgId ? (this.current as any)[msgId] : (this.current as any)[message]) ?? message | ||
} | ||
|
||
// 2. 处理复数 | ||
// 经过上面的处理,content可能是字符串或者数组 | ||
// content = "原始文本内容" || 复数形式["原始文本内容","原始文本内容"....] | ||
// 如果是数组说明要启用复数机制,需要根据插值变量中的某个变量来判断复数形式 | ||
if(Array.isArray(result) && result.length>0){ | ||
// 如果存在复数命名变量,只取第一个复数变量 | ||
if(pluraValue!==null){ // 启用的是位置插值 | ||
result = this._getPluraMessage(result,pluraValue) | ||
}else{ // 如果找不到复数变量,则使用第一个内容 | ||
result = result[0] | ||
} | ||
} | ||
// 如果没有传入插值变量,则直接返回 | ||
if(args.length===0) return result as string | ||
// 进行插值处理 | ||
return this.interpolator.replace(result as string,...vars) | ||
}catch{ | ||
return result as any // 出错则返回原始文本 | ||
} | ||
|
||
} | ||
} | ||
|
||
|
||
|
Oops, something went wrong.