This commit is contained in:
wxzhang 2023-04-13 20:39:34 +08:00
parent 1cf4f313b3
commit e060827dc1
9 changed files with 52 additions and 56 deletions

View File

@ -207,7 +207,6 @@ describe("格式化化配置与参数", () => {
})
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)
@ -312,7 +311,17 @@ describe('插值变量格式化器', () => {
expect(t("hello {|bookname}","tom")).toBe("hello 《tom》")
expect(t("hello {|bookname('#')}","tom")).toBe("hello #tom#")
expect(t("hello {|bookname('#','!')}","tom")).toBe("hello #tom!")
expect(t("hello {|bookname|bookname|bookname}","tom")).toBe("hello 《《《tom》》》")
await scope.change("en")
expect(t("hello {|bookname}","tom")).toBe("hello <tom>")
})
test('空值格式化器',async () => {
expect(t("hello {|bookname|empty('空')}",undefined)).toBe("hello 《空》")
})
})
describe('内置格式化器', () => {
})

View File

@ -5,7 +5,7 @@
*/
import { FlexFormatter, Formatter } from '../formatter'
import { FlexFormatter, IFormatter } from '../formatter'
import { toChineseNumber } from "flex-tools/chinese/toChineseNumber"
import { toChineseCurrency } from "flex-tools/chinese/toChineseCurrency"

View File

@ -4,7 +4,7 @@
*/
import { toDate } from '../utils'
import { Formatter } from '../formatter';
import { IFormatter } from '../formatter';
import { formatDateTime } from "flex-tools/misc/formatDateTime"
import { relativeTime } from "flex-tools/misc/relativeTime"
import { assignObject } from "flex-tools/object/assignObject"

View File

@ -9,7 +9,7 @@
*
*/
import { toNumber } from "../utils"
import { Formatter } from "../formatter"
import { IFormatter } from "../formatter"
import { toCurrency } from "./currency"
import { VoerkaI18nFormatter } from '../types';

View File

@ -16,6 +16,7 @@ import { isFunction } from "flex-tools/typecheck/isFunction"
import { isPlainObject } from "flex-tools/typecheck/isPlainObject"
import { safeParseJson } from "flex-tools/object/safeParseJson"
import { assignObject } from "flex-tools/object/assignObject"
import { VoerkaI18nFormatterConfigs } from './types';
/**
使便
@ -269,18 +270,23 @@ function parseFormaterParams(strParams: string): any[] {
* @param {*} defaultParams
* @returns
*/
export type Formatter = (this: any, value: string, ...args: any[]) => string
export type VarValueType = string | Error | undefined | null
export type IFormatter = (this: any, value: VarValueType, args: any[],config:VoerkaI18nFormatterConfigs) => string
export interface FormatterOptions {
normalize?: (value: string) => any // 对输入值进行规范化处理,如进行时间格式化时,为了提高更好的兼容性,支持数字时间戳/字符串/Date等需要对输入值进行处理如强制类型转换等
params?: Record<string, any> | null, // 可选的声明参数顺序如果是变参的则需要传入null
configKey?: string // 声明该格式化器在$config中的路径支持简单的使用.的路径语法
}
export function createFormatter(fn: Formatter, options?: FormatterOptions, defaultParams?: Record<string, any>) {
export function createFormatter(fn: IFormatter, options?: FormatterOptions, defaultParams?: Record<string, any>) {
let opts = assignObject({
normalize: null, // 对输入值进行规范化处理,如进行时间格式化时,为了提高更好的兼容性,支持数字时间戳/字符串/Date等需要对输入值进行处理如强制类型转换等
params: null, // 可选的声明参数顺序如果是变参的则需要传入null
configKey: null // 声明该格式化器在$config中的路径支持简单的使用.的路径语法
normalize: null, // 对输入值进行规范化处理,如进行时间格式化时,为了提高更好的兼容性,支持数字时间戳/字符串/Date等需要对输入值进行处理如强制类型转换等
params: null, // 可选的声明参数顺序如果是变参的则需要传入null
configKey: null // 声明该格式化器在config中的路径支持简单的使用.的路径语法
}, options)
// 最后一个参数是传入activeFormatterConfig参数
@ -289,9 +295,7 @@ export function createFormatter(fn: Formatter, options?: FormatterOptions, defau
let finalValue = value
// 1. 输入值规范处理,主要是进行类型转换,确保输入的数据类型及相关格式的正确性,提高数据容错性
if (isFunction(opts.normalize)) {
try {
finalValue = opts.normalize(finalValue)
} catch { }
try {finalValue = opts.normalize(finalValue)} catch { }
}
// 2. 读取activeFormatterConfig
let activeFormatterConfigs = args.length > 0 ? args[args.length - 1] : {}
@ -335,11 +339,11 @@ export function createFormatter(fn: Formatter, options?: FormatterOptions, defau
* @param {*} options
* @param {*} defaultParams
*/
export const createFlexFormatter = function (fn: Formatter, options: FormatterOptions, defaultParams?: Record<string, any>) {
export const createFlexFormatter = function (fn: IFormatter, options: FormatterOptions, defaultParams?: Record<string, any>) {
const opts = assignObject({
params: {}
}, options)
const $flexFormatter = Formatter(function (this: any, value: string,args: string[],$config:Record<string,any> ) {
const $flexFormatter = Formatter(function (this: any, value: VarValueType,args: string[],$config:Record<string,any> ) {
// 2. 从语言配置中读取默认参数
let finalParams = (options.params || {}).reduce((r: Record<string, any>, name: string) => {
r[name] = $config[name] == undefined ? (defaultParams || {})[name] : $config[name]

View File

@ -151,6 +151,7 @@ export class VoerkaI18nFormatterRegistry{
languages.forEach((lngName:string) => {
if(!(lngName in this.#formatters)) this.#formatters[lngName] = {}
if(typeof(this.#formatters[lngName])!="function"){
if(!this.#formatters[lngName]) this.#formatters[lngName] = {}
let lngFormatters = this.#formatters[lngName] as any
if (DataTypes.includes(name)) {
if(!lngFormatters.$types) lngFormatters.$types = {}

View File

@ -1,7 +1,7 @@
import { assignObject } from 'flex-tools/object/assignObject';
import { VoerkaI18nFormatterConfigs } from '../types';
import { toNumber } from "../utils"
import { Formatter } from "../formatter"
import { IFormatter, VarValueType,Formatter } from "../formatter"
/**
*
@ -12,7 +12,7 @@ import { Formatter } from "../formatter"
* @param {...any} args
* @returns
*/
function dict(key:string, values:any) {
export function dict(key:string, values:any) {
if(key in values){
return values[key]
}else{
@ -39,8 +39,8 @@ function dict(key:string, values:any) {
* @paran {String} next true/false,break,skip,break
* @param {*} config
*/
const empty = Formatter(function(value:any,escapeValue:any,next: 'break' | 'ignore',$config:VoerkaI18nFormatterConfigs){
let opts = assignObject({escape:"",next:'break',values:[]},$config)
export const empty = Formatter(function(value:VarValueType,[escapeValue,next]:[escapeValue:any,next: 'break' | 'ignore'],config:VoerkaI18nFormatterConfigs){
let opts = assignObject({escape:"",next:'break',values:[]},config)
if(escapeValue!=undefined) opts.escape = escapeValue
let emptyValues = [undefined,null]
if(Array.isArray(opts.values)) emptyValues.push(...opts.values)
@ -72,8 +72,8 @@ const empty = Formatter(function(value:any,escapeValue:any,next: 'break' | 'igno
* @param {*} config
* @returns
*/
const error = Formatter(function(value:any,escapeValue:any,next:'break' | 'ignore',$config:VoerkaI18nFormatterConfigs){
if(value instanceof Error){
export const error = Formatter(function(value:string,escapeValue:any,next:'break' | 'ignore',$config:VoerkaI18nFormatterConfigs){
if(typeof(value)=='object' && (value instanceof Error)){
try{
let opts = assignObject({escape:null,next:'break'},$config)
if(escapeValue!=undefined) opts.escape = escapeValue
@ -100,8 +100,8 @@ const error = Formatter(function(value:any,escapeValue:any,next:'break' | 'ignor
* @param {*} prefix
* @returns
*/
export function prefix(value:any,prefix:string="") {
return prefix ? `${prefix}${value}` : value
export function prefix(value:string,[prefix]:[prefix:string]) {
return prefix ? `${prefix || ''}${value}` : value
}
/**
*
@ -109,8 +109,8 @@ export function prefix(value:any,prefix:string="") {
* @param {*} suffix
* @returns
*/
export function suffix(value:any,suffix:string="") {
return suffix ? `${value}${suffix}` : value
export function suffix(value:string,[suffix]:[suffix:string]) {
return suffix ? `${value}${suffix || ''}` : value
}
const FILE_SIZE_SECTIONS = [
@ -141,7 +141,7 @@ const FILE_SIZE_WHOLE_UNITS = ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "
* @param {*} brief
* @param {*} options
*/
export const filesize= Formatter((value:any,unit:string,brief:boolean=true,$config:VoerkaI18nFormatterConfigs)=>{
export const filesize= Formatter((value:string,unit:string,brief:boolean=true,$config:VoerkaI18nFormatterConfigs)=>{
let v = toNumber(value)
let unitIndex
if(unit==undefined || unit=="auto"){
@ -163,12 +163,4 @@ const FILE_SIZE_WHOLE_UNITS = ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "
configKey:"fileSize"
})
export default {
dict,
empty,
error,
prefix,
suffix,
filesize
}

View File

@ -83,22 +83,6 @@ export function translate(this:VoerkaI18nScope,message:string,...args:any[]):str
})
}
// 3. 取得翻译文本模板字符串
// if(activeLanguage === scope.defaultLanguage){
// // 2.1 从默认语言中取得翻译文本模板字符串
// // 如果当前语言就是默认语言,不需要查询加载,只需要做插值变换即可
// // 当源文件运用了babel插件后会将原始文本内容转换为msgId
// // 如果是msgId则从scope.default中读取,scope.default=默认语言包={<id>:<message>}
// if(isMessageId(result)){
// result = (scope.default as any)[result] || message
// }
// }else{
// // 2.2 从当前语言包中取得翻译文本模板字符串
// // 如果没有启用babel插件将源文本转换为msgId需要先将文本内容转换为msgId
// let msgId = isMessageId(result) ? result : scope.idMap[result]
// result = (scope.current as any)[msgId] || result
// }
if(isMessageId(message)){
const msgId = scope.idMap[message]
result = (scope.current as any)[msgId] || message
@ -119,11 +103,7 @@ export function translate(this:VoerkaI18nScope,message:string,...args:any[]):str
}
}
// 进行插值处理
if(vars.length==0){
return result as string
}else{
return replaceInterpolatedVars.call(scope,result as string,...vars)
}
return replaceInterpolatedVars.call(scope,result as string,...vars)
}catch(e){
return result as any // 出错则返回原始文本
}

View File

@ -75,4 +75,14 @@ export function toBoolean(value:any){
export function randomId():string{
return Date.now().toString() + parseInt(String(Math.random() * 1000))
}
}
// const varRegexp = /\{([^\}]*)\}/gm
// /**
// * 返回字符串中变量的数量
// * @param str
// */
// export function getVarCount(str:string){
// const matches = str.match(varRegexp)
// return matches ? matches.length : 0
// }