From e060827dc11b1e958c034b5b146e5dcc8cadac85 Mon Sep 17 00:00:00 2001 From: wxzhang Date: Thu, 13 Apr 2023 20:39:34 +0800 Subject: [PATCH] update --- packages/runtime/src/__tests__/index.test.ts | 11 ++++++- packages/runtime/src/datatypes/chinese.ts | 2 +- packages/runtime/src/datatypes/datetime.ts | 2 +- packages/runtime/src/datatypes/numeric.ts | 2 +- packages/runtime/src/formatter.ts | 24 +++++++++------ packages/runtime/src/formatterRegistry.ts | 1 + packages/runtime/src/formatters/default.ts | 32 ++++++++------------ packages/runtime/src/translate.ts | 22 +------------- packages/runtime/src/utils.ts | 12 +++++++- 9 files changed, 52 insertions(+), 56 deletions(-) diff --git a/packages/runtime/src/__tests__/index.test.ts b/packages/runtime/src/__tests__/index.test.ts index 5fea37c..a19615c 100644 --- a/packages/runtime/src/__tests__/index.test.ts +++ b/packages/runtime/src/__tests__/index.test.ts @@ -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 ") }) + + test('空值格式化器',async () => { + expect(t("hello {|bookname|empty('空')}",undefined)).toBe("hello 《空》") + }) + +}) + +describe('内置格式化器', () => { + }) \ No newline at end of file diff --git a/packages/runtime/src/datatypes/chinese.ts b/packages/runtime/src/datatypes/chinese.ts index d1ff0a2..a3a8a1c 100644 --- a/packages/runtime/src/datatypes/chinese.ts +++ b/packages/runtime/src/datatypes/chinese.ts @@ -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" diff --git a/packages/runtime/src/datatypes/datetime.ts b/packages/runtime/src/datatypes/datetime.ts index a92cba6..2172b54 100644 --- a/packages/runtime/src/datatypes/datetime.ts +++ b/packages/runtime/src/datatypes/datetime.ts @@ -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" diff --git a/packages/runtime/src/datatypes/numeric.ts b/packages/runtime/src/datatypes/numeric.ts index 02528f7..9f2d177 100644 --- a/packages/runtime/src/datatypes/numeric.ts +++ b/packages/runtime/src/datatypes/numeric.ts @@ -9,7 +9,7 @@ * */ import { toNumber } from "../utils" -import { Formatter } from "../formatter" +import { IFormatter } from "../formatter" import { toCurrency } from "./currency" import { VoerkaI18nFormatter } from '../types'; diff --git a/packages/runtime/src/formatter.ts b/packages/runtime/src/formatter.ts index 3fbec1a..c9baa8b 100644 --- a/packages/runtime/src/formatter.ts +++ b/packages/runtime/src/formatter.ts @@ -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 | null, // 可选的,声明参数顺序,如果是变参的,则需要传入null configKey?: string // 声明该格式化器在$config中的路径,支持简单的使用.的路径语法 } -export function createFormatter(fn: Formatter, options?: FormatterOptions, defaultParams?: Record) { +export function createFormatter(fn: IFormatter, options?: FormatterOptions, defaultParams?: Record) { 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) { +export const createFlexFormatter = function (fn: IFormatter, options: FormatterOptions, defaultParams?: Record) { const opts = assignObject({ params: {} }, options) - const $flexFormatter = Formatter(function (this: any, value: string,args: string[],$config:Record ) { + const $flexFormatter = Formatter(function (this: any, value: VarValueType,args: string[],$config:Record ) { // 2. 从语言配置中读取默认参数 let finalParams = (options.params || {}).reduce((r: Record, name: string) => { r[name] = $config[name] == undefined ? (defaultParams || {})[name] : $config[name] diff --git a/packages/runtime/src/formatterRegistry.ts b/packages/runtime/src/formatterRegistry.ts index 6840fb8..5c0aa7f 100644 --- a/packages/runtime/src/formatterRegistry.ts +++ b/packages/runtime/src/formatterRegistry.ts @@ -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 = {} diff --git a/packages/runtime/src/formatters/default.ts b/packages/runtime/src/formatters/default.ts index 322cc68..6a002a2 100644 --- a/packages/runtime/src/formatters/default.ts +++ b/packages/runtime/src/formatters/default.ts @@ -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 -} \ No newline at end of file + \ No newline at end of file diff --git a/packages/runtime/src/translate.ts b/packages/runtime/src/translate.ts index 8bd34d3..5d8d89f 100644 --- a/packages/runtime/src/translate.ts +++ b/packages/runtime/src/translate.ts @@ -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=默认语言包={:} - // 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 // 出错则返回原始文本 } diff --git a/packages/runtime/src/utils.ts b/packages/runtime/src/utils.ts index 83c866d..ffae577 100644 --- a/packages/runtime/src/utils.ts +++ b/packages/runtime/src/utils.ts @@ -75,4 +75,14 @@ export function toBoolean(value:any){ export function randomId():string{ return Date.now().toString() + parseInt(String(Math.random() * 1000)) -} \ No newline at end of file +} +// const varRegexp = /\{([^\}]*)\}/gm +// /** +// * 返回字符串中变量的数量 +// * @param str +// */ +// export function getVarCount(str:string){ +// const matches = str.match(varRegexp) +// return matches ? matches.length : 0 +// } + \ No newline at end of file