update for ts
This commit is contained in:
parent
e02835fa50
commit
105a75bc59
@ -36,7 +36,7 @@ const loaders = {
|
||||
// 语言作用域
|
||||
const scope = new VoerkaI18nScope({
|
||||
...scopeSettings, // languages,defaultLanguage,activeLanguage,namespaces,formatters
|
||||
id : "reactapp", // 当前作用域的id,自动取当前工程的package.json的name
|
||||
id : "reactapp", // 当前作用域的id,自动取当前工程的package.json的name
|
||||
debug : false, // 是否在控制台输出高度信息
|
||||
default : defaultMessages, // 默认语言包
|
||||
messages : activeMessages, // 当前语言包
|
||||
|
@ -0,0 +1,64 @@
|
||||
|
||||
|
||||
import {test,vi,describe,expect,afterAll,beforeAll} from 'vitest'
|
||||
import { VoerkaI18nScope } from '../scope'
|
||||
import zhFormatters from '../formatters/zh';
|
||||
import enFormatters from '../formatters/en';
|
||||
|
||||
|
||||
const zhMessages={
|
||||
"1": "你好",
|
||||
"2": "你好,{name}",
|
||||
"3": "中国",
|
||||
"4": ["我有一部车","我有很多部车"]
|
||||
}
|
||||
const enMessages={
|
||||
"1": "hello",
|
||||
"2": "hello,{name}",
|
||||
"3": "china",
|
||||
"4": "I have {} cars"
|
||||
}
|
||||
|
||||
const messages = {
|
||||
zh: zhMessages,
|
||||
en: enMessages
|
||||
}
|
||||
|
||||
const idMap={
|
||||
"你好":1,
|
||||
"你好,{name}":2,
|
||||
"中国":3,
|
||||
"我有{}部车":4
|
||||
}
|
||||
const languages = [
|
||||
{ name: "zh",default:true,active:true},
|
||||
{ name: "en"}
|
||||
]
|
||||
|
||||
const formatters ={
|
||||
zh:zhFormatters,
|
||||
en:enFormatters
|
||||
}
|
||||
|
||||
describe("VoerkaI18nScope", () => {
|
||||
let scope = new VoerkaI18nScope({
|
||||
id: "test",
|
||||
languages,
|
||||
idMap,
|
||||
messages,
|
||||
formatters
|
||||
})
|
||||
test("成功创建实例", () => {
|
||||
expect(scope).toBeInstanceOf(VoerkaI18nScope)
|
||||
expect(scope.activeLanguage).toBe("zh")
|
||||
expect(scope.defaultLanguage).toBe("zh")
|
||||
expect(scope.messages).toEqual(messages)
|
||||
expect(scope.default).toEqual(zhMessages)
|
||||
expect(scope.current).toEqual(zhMessages)
|
||||
expect(scope.idMap).toEqual(idMap)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
test('translate', () => {})
|
||||
|
@ -10,14 +10,14 @@ import { toChineseNumber } from "flex-tools/chinese/toChineseNumber"
|
||||
import { toChineseCurrency } from "flex-tools/chinese/toChineseCurrency"
|
||||
|
||||
|
||||
export const chineseNumberFormatter = Formatter((value: number, isBig: boolean, $config: any) => {
|
||||
return toChineseNumber(value, isBig)
|
||||
export const chineseNumberFormatter = Formatter((value: any, [isBig]:[isBig: boolean], $config) => {
|
||||
return toChineseNumber(value, isBig) as string
|
||||
}, {
|
||||
params: ["isBig"]
|
||||
})
|
||||
|
||||
|
||||
export const rmbFormater = FlexFormatter((value:number | string, params : any, $config:any) => {
|
||||
export const rmbFormater = FlexFormatter((value:number | string, [params] : any[], $config:any) => {
|
||||
return toChineseCurrency(value, params, $config)
|
||||
}, {
|
||||
params: ["big", "prefix", "unit", "suffix"],
|
||||
|
@ -98,7 +98,7 @@ export const currencyFormatter = FlexFormatter((value:string | number,params:Rec
|
||||
}
|
||||
return toCurrency(value,params,$config)
|
||||
},{
|
||||
normalize: toNumber,
|
||||
normalize: (value:string)=>toNumber(value),
|
||||
params : ["format","unit","precision","prefix","suffix","division","symbol","radix"],
|
||||
configKey: "currency"
|
||||
},{
|
||||
|
@ -3,18 +3,16 @@
|
||||
处理日期时间相关
|
||||
|
||||
*/
|
||||
const { isFunction,replaceAll,toDate } = require('../utils')
|
||||
const { Formatter } = require('../formatter');
|
||||
import { toDate } from '../utils'
|
||||
import { Formatter } from '../formatter';
|
||||
import { formatDateTime } from "flex-tools/misc/formatDateTime"
|
||||
import { relativeTime } from "flex-tools/misc/relativeTime"
|
||||
import { assignObject } from "flex-tools/object/assignObject"
|
||||
|
||||
import { isFunction } from "flex-tools/typecheck/isFunction"
|
||||
|
||||
|
||||
function formatTime(value:number ,template="HH:mm:ss"){
|
||||
return formatDateTime(value,template,{
|
||||
|
||||
})
|
||||
return formatDateTime(value,template,{})
|
||||
}
|
||||
|
||||
|
||||
@ -29,9 +27,10 @@ function formatTime(value:number ,template="HH:mm:ss"){
|
||||
*
|
||||
**/
|
||||
export type FormatterTransformer = (value:any,format:string)=>string
|
||||
|
||||
export function createDateTimeFormatter(options={},transformer:FormatterTransformer){
|
||||
let opts = assignObject({presets:{}},options)
|
||||
return Formatter(function(value,format,$config){
|
||||
return Formatter(function(this:any,value:any,[format]:any[],$config:Record<string,any>){
|
||||
if((format in opts.presets) && isFunction(opts.presets[format])){
|
||||
return opts.presets[format](value)
|
||||
}else if((format in $config)){
|
||||
@ -53,17 +52,17 @@ export function createDateTimeFormatter(options={},transformer:FormatterTransfor
|
||||
* - format取值:local,long,short,iso,gmt,utc,<模板字符串>
|
||||
* - 默认值由$config.datetime.date.format指定
|
||||
*/
|
||||
const dateFormatter = createDateTimeFormatter({
|
||||
export const dateFormatter = createDateTimeFormatter({
|
||||
normalize: toDate,
|
||||
params : ["format"],
|
||||
configKey: "datetime.date",
|
||||
presets : {
|
||||
local: value=>value.toLocaleString(),
|
||||
iso : value=>value.toISOString(),
|
||||
utc : value=>value.toUTCString(),
|
||||
gmt : value=>value.toGMTString()
|
||||
local: (value:any)=>value.toLocaleString(),
|
||||
iso : (value:any)=>value.toISOString(),
|
||||
utc : (value:any)=>value.toUTCString(),
|
||||
gmt : (value:any)=>value.toGMTString()
|
||||
}
|
||||
},formatDatetime)
|
||||
},formatDateTime)
|
||||
|
||||
|
||||
/**
|
||||
@ -71,8 +70,8 @@ export function createDateTimeFormatter(options={},transformer:FormatterTransfor
|
||||
* - format: long,short,number
|
||||
* - 默认值是 short
|
||||
*/
|
||||
const quarterFormatter = createDateTimeFormatter({
|
||||
normalize : value=>{
|
||||
export const quarterFormatter = createDateTimeFormatter({
|
||||
normalize : (value:any)=>{
|
||||
const month = value.getMonth() + 1
|
||||
return Math.floor( ( month % 3 == 0 ? ( month / 3 ) : (month / 3 + 1 ) ))
|
||||
},
|
||||
@ -85,7 +84,7 @@ const quarterFormatter = createDateTimeFormatter({
|
||||
* - format: long,short,number
|
||||
* - 默认值是 short
|
||||
*/
|
||||
const monthFormatter = createDateTimeFormatter({
|
||||
export const monthFormatter = createDateTimeFormatter({
|
||||
normalize: (value:Date)=> value.getMonth() + 1,
|
||||
params : ["format"],
|
||||
configKey: "datetime.month"
|
||||
@ -96,7 +95,7 @@ const monthFormatter = createDateTimeFormatter({
|
||||
* - format: long,short,number
|
||||
* - 默认值是 long
|
||||
*/
|
||||
const weekdayFormatter = createDateTimeFormatter({
|
||||
export const weekdayFormatter = createDateTimeFormatter({
|
||||
normalize: (value:Date)=> value.getDay(),
|
||||
params : ["format"],
|
||||
configKey: "datetime.weekday"
|
||||
@ -107,7 +106,7 @@ const weekdayFormatter = createDateTimeFormatter({
|
||||
* - format取值:local,long,short,timestamp,<模板字符串>
|
||||
* - 默认值由$config.datetime.time.format指定
|
||||
*/
|
||||
const timeFormatter = createDateTimeFormatter({
|
||||
export const timeFormatter = createDateTimeFormatter({
|
||||
normalize : toDate,
|
||||
params : ["format"],
|
||||
configKey : "datetime.time",
|
||||
@ -122,7 +121,7 @@ const weekdayFormatter = createDateTimeFormatter({
|
||||
* @param {*} value
|
||||
* @param {*} baseTime 基准时间,默认是相对现在
|
||||
*/
|
||||
const relativeTimeFormatter = Formatter((value:Date,baseTime:Date,$config:any)=>{
|
||||
export const relativeTimeFormatter = Formatter((value:any,[baseTime]:[Date],$config:any)=>{
|
||||
//const { units,now,before,base = Date.now() , after } = $config
|
||||
return relativeTime(value, $config)
|
||||
},{
|
||||
|
@ -8,16 +8,17 @@
|
||||
* { value | number('big') }
|
||||
*
|
||||
*/
|
||||
const { isNumber,toNumber } = require("../utils")
|
||||
const { Formatter } = require("../formatter")
|
||||
const { toCurrency } = require("./currency")
|
||||
import { toNumber } from "../utils"
|
||||
import { Formatter } from "../formatter"
|
||||
import { toCurrency } from "./currency"
|
||||
import { VoerkaI18nFormatter } from '../types';
|
||||
|
||||
const numberFormartter = Formatter(function(value,precision,division,$config){
|
||||
export const numberFormartter = Formatter(function(value:any,[precision,division]:[number,number],$config:any){
|
||||
return toCurrency(value, { division, precision},$config)
|
||||
},{
|
||||
normalize: toNumber,
|
||||
params:["precision","division"],
|
||||
configKey: "number"
|
||||
})
|
||||
}) as VoerkaI18nFormatter
|
||||
|
||||
|
@ -271,8 +271,8 @@ function parseFormaterParams(strParams: string): any[] {
|
||||
*/
|
||||
export type Formatter = (this: any, value: string, ...args: any[]) => string
|
||||
export interface FormatterOptions {
|
||||
normalize?: (value: string) => string // 对输入值进行规范化处理,如进行时间格式化时,为了提高更好的兼容性,支持数字时间戳/字符串/Date等,需要对输入值进行处理,如强制类型转换等
|
||||
params?: Record<string, any>, // 可选的,声明参数顺序,如果是变参的,则需要传入null
|
||||
normalize?: (value: string) => any // 对输入值进行规范化处理,如进行时间格式化时,为了提高更好的兼容性,支持数字时间戳/字符串/Date等,需要对输入值进行处理,如强制类型转换等
|
||||
params?: Record<string, any> | null, // 可选的,声明参数顺序,如果是变参的,则需要传入null
|
||||
configKey?: string // 声明该格式化器在$config中的路径,支持简单的使用.的路径语法
|
||||
}
|
||||
|
||||
@ -285,7 +285,7 @@ export function createFormatter(fn: Formatter, options?: FormatterOptions, defau
|
||||
|
||||
// 最后一个参数是传入activeFormatterConfig参数
|
||||
// 并且格式化器的this指向的是activeFormatterConfig
|
||||
const $formatter = function (this: any, value: string, ...args: any[]) {
|
||||
const $formatter = function (this: any, value: string, args: any[],$config:Record<string,any>) {
|
||||
let finalValue = value
|
||||
// 1. 输入值规范处理,主要是进行类型转换,确保输入的数据类型及相关格式的正确性,提高数据容错性
|
||||
if (isFunction(opts.normalize)) {
|
||||
@ -312,7 +312,7 @@ export function createFormatter(fn: Formatter, options?: FormatterOptions, defau
|
||||
if (args[i] !== undefined) finalArgs[i] = args[i]
|
||||
}
|
||||
}
|
||||
return fn.call(this, finalValue, ...finalArgs, formatterConfig)
|
||||
return fn.call(this, finalValue, finalArgs, formatterConfig)
|
||||
}
|
||||
$formatter.configurable = true
|
||||
return $formatter
|
||||
@ -339,9 +339,7 @@ export const createFlexFormatter = function (fn: Formatter, options: FormatterOp
|
||||
const opts = assignObject({
|
||||
params: {}
|
||||
}, options)
|
||||
const $flexFormatter = Formatter(function (this: any, value: string, ...args: string[]) {
|
||||
// 1. 最后一个参数总是代表格式化器的参数,不同语言不一样
|
||||
let $config = args[args.length - 1] as unknown as Record<string, any>
|
||||
const $flexFormatter = Formatter(function (this: any, value: string,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]
|
||||
@ -361,6 +359,7 @@ export const createFlexFormatter = function (fn: Formatter, options: FormatterOp
|
||||
}
|
||||
|
||||
|
||||
export const Formatter = createFormatter
|
||||
|
||||
export const FlexFormatter = createFlexFormatter
|
||||
|
||||
|
@ -4,9 +4,10 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
import { VoerkaI18nFormatter, VoerkaI18nFormatters, VoerkaI18nFormattersLoader, VoerkaI18nLanguageFormatters, SupportedDateTypes, VoerkaI18nFormatterConfigs, Formatter } from './types';
|
||||
import { VoerkaI18nFormatter, VoerkaI18nFormatters, VoerkaI18nFormattersLoader, VoerkaI18nLanguageFormatters, SupportedDateTypes, VoerkaI18nFormatterConfigs } from './types';
|
||||
import { DataTypes } from './utils';
|
||||
import { get as getByPath } from "flex-tools/object/get"
|
||||
import { isFunction } from 'flex-tools/typecheck/isFunction';
|
||||
|
||||
|
||||
export interface VoerkaI18nScopeCache{
|
||||
@ -41,7 +42,7 @@ export class VoerkaI18nFormatterRegistry{
|
||||
set language(language:string){
|
||||
this.#language = language
|
||||
if(!(language in this.formatters)){
|
||||
(this.formatters[language] as any) = Object.assign({},EmptyFormatters)
|
||||
(this.#formatters[language] as any) = Object.assign({},EmptyFormatters)
|
||||
}
|
||||
this.#ready = typeof(this.#formatters[language]) != 'function'
|
||||
}
|
||||
@ -63,7 +64,7 @@ export class VoerkaI18nFormatterRegistry{
|
||||
*代表适用于所有语言
|
||||
语言名称,语言名称数组,或者使用,分割的语言名称字符串
|
||||
*/
|
||||
register(name:string, formatter:VoerkaI18nFormatter, {language = "*"}:{ language: string | string[] } ) {
|
||||
register(name:string | SupportedDateTypes, formatter:VoerkaI18nFormatter, {language = "*"}:{ language: string | string[] } ) {
|
||||
if (!isFunction(formatter) || typeof name !== "string") {
|
||||
throw new TypeError("Formatter must be a function");
|
||||
}
|
||||
@ -73,7 +74,7 @@ export class VoerkaI18nFormatterRegistry{
|
||||
this.#formatters[lngName] = { }
|
||||
}
|
||||
if(typeof(this.#formatters[lngName])!="function"){
|
||||
let lngFormatters = this.#formatters[lngName] as VoerkaI18nFormatters
|
||||
let lngFormatters = this.#formatters[lngName] as any
|
||||
if (DataTypes.includes(name)) {
|
||||
if(!lngFormatters.$types){
|
||||
lngFormatters.$types = {}
|
||||
@ -168,7 +169,7 @@ export class VoerkaI18nFormatterRegistry{
|
||||
*/
|
||||
get(name:string,dataType?:SupportedDateTypes):VoerkaI18nFormatter | undefined{
|
||||
if(!this.#ready) throw new FormattersNotLoadedError(this.#language)
|
||||
const lngFormatters = this.#formatters[this.#language] as VoerkaI18nFormatters
|
||||
const lngFormatters = this.#formatters[this.#language] as any
|
||||
if(dataType && (dataType in lngFormatters.$types!)){
|
||||
return lngFormatters.$types![dataType]
|
||||
}else if(name in lngFormatters){
|
||||
|
@ -1,5 +1,7 @@
|
||||
const { toNumber,isFunction } = require("../utils")
|
||||
const { Formatter } = require("../formatter")
|
||||
import { assignObject } from 'flex-tools/object/assignObject';
|
||||
import { VoerkaI18nFormatterConfigs } from '../types';
|
||||
import { toNumber } from "../utils"
|
||||
import { Formatter } from "../formatter"
|
||||
|
||||
/**
|
||||
* 字典格式化器
|
||||
@ -10,11 +12,11 @@ const { Formatter } = require("../formatter")
|
||||
* @param {...any} args
|
||||
* @returns
|
||||
*/
|
||||
function dict(key, values) {
|
||||
function dict(key:string, values:any) {
|
||||
if(key in values){
|
||||
return values[key]
|
||||
}else{
|
||||
return ("default" in values) ? values[key] : value
|
||||
return ("default" in values) ? values[key] : values
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,10 +39,8 @@ const { Formatter } = require("../formatter")
|
||||
* @paran {String} next 下一步行为,取值true/false,break,skip,默认是break
|
||||
* @param {*} config
|
||||
*/
|
||||
const empty = Formatter(function(value,escapeValue,next,$config){
|
||||
if(next===false) next = 'break'
|
||||
if(next===true) next = 'skip'
|
||||
let opts = Object.assign({escape:"",next:'break',values:[]},$config)
|
||||
const empty = Formatter(function(value:any,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,10 +72,10 @@ const empty = Formatter(function(value,escapeValue,next,$config){
|
||||
* @param {*} config 格式化器的全局配置参数
|
||||
* @returns
|
||||
*/
|
||||
const error = Formatter(function(value,escapeValue,next,$config){
|
||||
const error = Formatter(function(value:any,escapeValue:any,next:'break' | 'ignore',$config:VoerkaI18nFormatterConfigs){
|
||||
if(value instanceof Error){
|
||||
try{
|
||||
let opts = Object.assign({escape:null,next:'break'},$config)
|
||||
let opts = assignObject({escape:null,next:'break'},$config)
|
||||
if(escapeValue!=undefined) opts.escape = escapeValue
|
||||
if(next!=undefined) opts.next = next
|
||||
return {
|
||||
@ -100,7 +100,7 @@ const error = Formatter(function(value,escapeValue,next,$config){
|
||||
* @param {*} prefix
|
||||
* @returns
|
||||
*/
|
||||
function prefix(value,prefix="") {
|
||||
export function prefix(value:any,prefix:string="") {
|
||||
return prefix ? `${prefix}${value}` : value
|
||||
}
|
||||
/**
|
||||
@ -109,7 +109,7 @@ function prefix(value,prefix="") {
|
||||
* @param {*} suffix
|
||||
* @returns
|
||||
*/
|
||||
function suffix(value,suffix="") {
|
||||
export function suffix(value:any,suffix:string="") {
|
||||
return suffix ? `${value}${suffix}` : value
|
||||
}
|
||||
|
||||
@ -141,7 +141,7 @@ const FILE_SIZE_WHOLE_UNITS = ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "
|
||||
* @param {*} brief 是否采用简称单位
|
||||
* @param {*} options
|
||||
*/
|
||||
const filesize= Formatter((value,unit,brief=true,$config)=>{
|
||||
export const filesize= Formatter((value:any,unit:string,brief:boolean=true,$config:VoerkaI18nFormatterConfigs)=>{
|
||||
let v = toNumber(value)
|
||||
let unitIndex
|
||||
if(unit==undefined || unit=="auto"){
|
||||
@ -164,13 +164,11 @@ const FILE_SIZE_WHOLE_UNITS = ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "
|
||||
})
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
dict,
|
||||
empty,
|
||||
error,
|
||||
prefix,
|
||||
suffix,
|
||||
filesize,
|
||||
error,
|
||||
empty
|
||||
}
|
||||
|
||||
filesize
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
|
||||
import { Formatter } fom "../formatter"
|
||||
import { dateFormatter,quarterFormatter,monthFormatter,weekdayFormatter,timeFormatter,relativeTimeFormatter } from "../datatypes/datetime"
|
||||
import { numberFormartter } from "../datatypes/numeric"
|
||||
import { currencyFormatter } from "../datatypes/currency"
|
||||
@ -149,11 +148,11 @@ export default {
|
||||
},
|
||||
// 默认数据类型的格式化器
|
||||
$types: {
|
||||
Date : dateFormatter,
|
||||
Null : value =>"",
|
||||
Undefined: value =>"",
|
||||
Error : value => "ERROR",
|
||||
Boolean : value =>value ? "True":"False",
|
||||
// Date : dateFormatter,
|
||||
Null : (value: any) =>"",
|
||||
Undefined: (value: any) =>"",
|
||||
Error : (value: any) => "ERROR",
|
||||
Boolean : (value: any) =>value ? "True":"False",
|
||||
Number : numberFormartter
|
||||
},
|
||||
// 以下是格式化定义
|
||||
|
@ -5,9 +5,10 @@
|
||||
|
||||
import { chineseNumberFormatter,rmbFormater } from "../datatypes/chinese"
|
||||
|
||||
import {CN_DATETIME_UNITS, CN_MONTH_NAMES, CN_SHORT_MONTH_NAMES, CN_SHORT_WEEK_DAYS, CN_WEEK_DAYS } from "flex-tools/chinese/consts"
|
||||
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
// 配置参数: 格式化器函数的最后一个参数就是该配置参数
|
||||
$config:{
|
||||
datetime : {
|
||||
|
@ -1,3 +1,4 @@
|
||||
// @ts-ignore
|
||||
import replaceAll from "string.prototype.replaceall"
|
||||
replaceAll.shim()
|
||||
|
||||
|
@ -203,7 +203,9 @@ function getFormatter(scope:VoerkaI18nScope, activeLanguage:string, name:string)
|
||||
}
|
||||
}
|
||||
}
|
||||
export type FormatterChecker = (value:any,config?:VoerkaI18nFormatterConfigs)=>any;
|
||||
export type FormatterChecker = ((value:any,config?:VoerkaI18nFormatterConfigs)=>any) & {
|
||||
$name:string
|
||||
}
|
||||
|
||||
/**
|
||||
* Checker是一种特殊的格式化器,会在特定的时间执行
|
||||
@ -242,7 +244,7 @@ function executeChecker(checker:FormatterChecker, value:any,scope:VoerkaI18nScop
|
||||
* @param {FormatterDefineChain} formatters 经过解析过的格式化器参数链 ,多个格式化器函数(经过包装过的)顺序执行,前一个输出作为下一个格式化器的输入
|
||||
* formatters [ [<格式化器名称>,[<参数>,<参数>,...],[<格式化器名称>,[<参数>,<参数>,...]],...]
|
||||
*/
|
||||
function executeFormatter(value:any, formatters:FormatterDefineChain, scope:VoerkaI18nScope, template:string) {
|
||||
function executeFormatter(value:any, formatters:VoerkaI18nFormatter[], scope:VoerkaI18nScope, template:string) {
|
||||
if (formatters.length === 0) return value;
|
||||
let result = value;
|
||||
// 1. 空值检查
|
||||
@ -258,11 +260,11 @@ function executeFormatter(value:any, formatters:FormatterDefineChain, scope:Voer
|
||||
}
|
||||
// 2. 错误检查
|
||||
const errorCheckerIndex = formatters.findIndex((func) => (func as any).$name === "error" );
|
||||
let errorChecker;
|
||||
let errorChecker:FormatterChecker;
|
||||
if (errorCheckerIndex != -1) {
|
||||
errorChecker = formatters.splice(errorCheckerIndex, 1)[0] as unknown as FormatterChecker
|
||||
if (result instanceof Error) {
|
||||
result.formatter = formatter.$name;
|
||||
(result as any).formatter = errorChecker.$name;
|
||||
const { value, next } = executeChecker(errorChecker, result,scope);
|
||||
if (next == "break") {
|
||||
return value;
|
||||
@ -275,13 +277,13 @@ function executeFormatter(value:any, formatters:FormatterDefineChain, scope:Voer
|
||||
// 3. 分别执行格式化器函数
|
||||
for (let formatter of formatters) {
|
||||
try {
|
||||
result = formatter(result, scope.activeFormatterConfig);
|
||||
result = formatter(result, [result],scope.activeFormatterConfig);
|
||||
} catch (e:any) {
|
||||
e.formatter = formatter.$name;
|
||||
e.formatter = (formatter as any).$name;
|
||||
if (scope.debug)
|
||||
console.error(`Error while execute i18n formatter<${formatter.$name}> for ${template}: ${e.message} `);
|
||||
if (isFunction(errorChecker)) {
|
||||
const { value, next } = executeChecker(errorChecker, result);
|
||||
console.error(`Error while execute i18n formatter<${(formatter as any).$name}> for ${template}: ${e.message} `);
|
||||
if (isFunction(errorChecker!)) {
|
||||
const { value, next } = executeChecker(errorChecker!, result,scope);
|
||||
if (next == "break") {
|
||||
if (value !== undefined) result = value;
|
||||
break;
|
||||
@ -329,13 +331,13 @@ function addDefaultFormatters(formatters:FormatterDefineChain) {
|
||||
*
|
||||
*/
|
||||
function wrapperFormatters(scope:VoerkaI18nScope, activeLanguage:string, formatters:FormatterDefineChain) {
|
||||
let wrappedFormatters = [];
|
||||
let wrappedFormatters:VoerkaI18nFormatter[] = [];
|
||||
addDefaultFormatters(formatters);
|
||||
for (let [name, args] of formatters) {
|
||||
let fn = getFormatter(scope, activeLanguage, name);
|
||||
let formatter;
|
||||
if (isFunction(fn)) {
|
||||
formatter = (value:any, config:VoerkaI18nFormatterConfigs) =>fn.call(scope.activeFormatterConfig, value, args, config);
|
||||
formatter = (value:any, args?:any[],config?:VoerkaI18nFormatterConfigs) =>fn.call(scope.activeFormatterConfig, value, args, config);
|
||||
} else {
|
||||
// 格式化器无效或者没有定义时,查看当前值是否具有同名的原型方法,如果有则执行调用
|
||||
// 比如padStart格式化器是String的原型方法,不需要配置就可以直接作为格式化器调用
|
||||
@ -362,7 +364,7 @@ function wrapperFormatters(scope:VoerkaI18nScope, activeLanguage:string, formatt
|
||||
* @param {*} value
|
||||
* @returns
|
||||
*/
|
||||
function getFormattedValue(scope:VoerkaI18nScope, activeLanguage:string, formatters:FormatterDefineChain, value, template) {
|
||||
function getFormattedValue(scope:VoerkaI18nScope, activeLanguage:string, formatters:FormatterDefineChain, value:any, template:string) {
|
||||
// 1. 取得格式化器函数列表,然后经过包装以传入当前格式化器的配置参数
|
||||
const formatterFuncs = wrapperFormatters(scope, activeLanguage, formatters);
|
||||
// 3. 执行格式化器
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { isFunction } from "flex-tools/typecheck/isFunction"
|
||||
import { deepMerge } from "flex-tools/object/deepMerge"
|
||||
import {DataTypes} from "./utils"
|
||||
import { EventEmitter } from "./eventemitter"
|
||||
import inlineFormatters from "./formatters"
|
||||
import { VoerkaI18nScope } from "./scope"
|
||||
import type { VoerkaI18nScope } from "./scope"
|
||||
import type { VoerkaI18nLanguageDefine, VoerkaI18nLanguageFormatters, VoerkaI18nDefaultMessageLoader, VoerkaI18nFormatter, VoerkaI18nTypesFormatters } from "./types"
|
||||
import { SupportedDateTypes } from './types';
|
||||
import { VoerkaI18nFormatterRegistry } from "./formatterRegistry"
|
||||
|
||||
// 默认语言配置
|
||||
@ -24,7 +22,7 @@ export interface VoerkaI18nManagerOptions {
|
||||
debug?: boolean
|
||||
defaultLanguage: string
|
||||
activeLanguage: string
|
||||
formatters: VoerkaI18nLanguageFormatters
|
||||
formatters?: VoerkaI18nLanguageFormatters
|
||||
languages: VoerkaI18nLanguageDefine[]
|
||||
}
|
||||
/**
|
||||
@ -126,9 +124,9 @@ export class VoerkaI18nManager extends EventEmitter{
|
||||
* @param {*} scope
|
||||
*/
|
||||
async register(scope:VoerkaI18nScope){
|
||||
if(!(scope instanceof VoerkaI18nScope)){
|
||||
throw new TypeError("Scope must be an instance of VoerkaI18nScope")
|
||||
}
|
||||
// if(!(scope instanceof VoerkaI18nScope)){
|
||||
// throw new TypeError("Scope must be an instance of VoerkaI18nScope")
|
||||
// }
|
||||
this.#scopes.push(scope)
|
||||
return await scope.refresh(this.activeLanguage)
|
||||
}
|
||||
|
@ -1,12 +1,9 @@
|
||||
import { DataTypes } from "./utils"
|
||||
import { isPlainObject } from "flex-tools/typecheck/isPlainObject"
|
||||
import { isFunction } from "flex-tools/typecheck/isFunction"
|
||||
import { deepClone } from "flex-tools/object/deepClone"
|
||||
import { get as getByPath } from "flex-tools/object/get"
|
||||
import { isFunction } from "flex-tools/typecheck/isFunction"
|
||||
import { translate } from "./translate"
|
||||
import { deepMerge } from "flex-tools/object/deepMerge"
|
||||
import { assignObject } from "flex-tools/object/assignObject"
|
||||
import type {VoerkaI18nManager } from "./manager"
|
||||
import {VoerkaI18nManager } from "./manager"
|
||||
import type {
|
||||
VoerkaI18nFormatterConfigs,
|
||||
VoerkaI18nDefaultMessageLoader,
|
||||
@ -18,10 +15,12 @@ import type {
|
||||
VoerkaI18nLanguagePack,
|
||||
VoerkaI18nScopeCache,
|
||||
VoerkaI18nTranslate,
|
||||
VoerkaI18nLoaders,
|
||||
VoerkaI18nMessageLoaders,
|
||||
VoerkaI18nTypesFormatters,
|
||||
VoerkaI18nFormatters,
|
||||
VoerkaI18nDynamicLanguageMessages,
|
||||
VoerkaI18nLanguageMessagePack,
|
||||
VoerkaI18nMessageLoader,
|
||||
} from "./types"
|
||||
import { VoerkaI18nFormatterRegistry } from './formatterRegistry';
|
||||
import { InvalidLanguageError } from "./errors"
|
||||
@ -29,14 +28,12 @@ import { InvalidLanguageError } from "./errors"
|
||||
export interface VoerkaI18nScopeOptions {
|
||||
id?: string
|
||||
debug?: boolean
|
||||
languages: VoerkaI18nLanguageDefine[] // 当前作用域支持的语言列表
|
||||
defaultLanguage: string // 默认语言名称
|
||||
activeLanguage: string // 当前语言名称
|
||||
default: VoerkaI18nLanguageMessages // 默认语言包
|
||||
messages: VoerkaI18nLanguageMessages // 当前语言包
|
||||
languages: VoerkaI18nLanguageDefine[] // 当前作用域支持的语言列表
|
||||
defaultLanguage?: string // 默认语言名称
|
||||
activeLanguage?: string // 当前语言名称
|
||||
messages: VoerkaI18nLanguageMessagePack // 当前语言包
|
||||
idMap: Voerkai18nIdMap // 消息id映射列表
|
||||
formatters: VoerkaI18nLanguageFormatters // 当前作用域的格式化函数列表{<lang>: {$types,$config,[格式化器名称]: () => {},[格式化器名称]: () => {}}}
|
||||
loaders: VoerkaI18nLoaders; // 异步加载语言文件的函数列表
|
||||
formatters: VoerkaI18nLanguageFormatters // 当前作用域的格式化函数列表{<lang>: {$types,$config,[格式化器名称]: () => {},[格式化器名称]: () => {}}}
|
||||
}
|
||||
|
||||
export class VoerkaI18nScope {
|
||||
@ -48,83 +45,99 @@ export class VoerkaI18nScope {
|
||||
#activeFormatters:VoerkaI18nFormatters = {}
|
||||
#activeFormatterConfig: VoerkaI18nFormatterConfigs={}
|
||||
#cache:VoerkaI18nScopeCache
|
||||
#messages:VoerkaI18nLanguageMessages = {}
|
||||
#formatterRegistry:VoerkaI18nFormatterRegistry
|
||||
constructor(options:VoerkaI18nScopeOptions, callback:(e?:Error)=>void) {
|
||||
#defaultLanguage:string ='zh'
|
||||
#activeLanguage:string='zh'
|
||||
#currentMessages:VoerkaI18nLanguageMessages = {} // 当前语言包
|
||||
constructor(options:VoerkaI18nScopeOptions, callback?:(e?:Error)=>void) {
|
||||
this.#options = assignObject({
|
||||
id : Date.now().toString() + parseInt(String(Math.random() * 1000)),
|
||||
debug : false,
|
||||
languages : {}, // 当前作用域支持的语言列表
|
||||
defaultLanguage: "zh", // 默认语言名称
|
||||
activeLanguage : "zh", // 当前语言名称
|
||||
default : {}, // 默认语言包
|
||||
messages : {}, // 当前语言包
|
||||
idMap : {}, // 消息id映射列表
|
||||
formatters : {}, // 当前作用域的格式化函数列表{<lang>: {$types,$config,[格式化器名称]: () => {},[格式化器名称]: () => {}}}
|
||||
loaders : {} // 异步加载语言文件的函数列表
|
||||
messages : {}, // 所有语言包={[language]:VoerkaI18nLanguageMessages}
|
||||
idMap : {}, // 消息id映射列表
|
||||
formatters : {}, // 当前作用域的格式化函数列表{<lang>: {$types,$config,[格式化器名称]: () => {},[格式化器名称]: () => {}}}
|
||||
},options) as Required<VoerkaI18nScopeOptions>
|
||||
|
||||
this.#patchMessages = {}; // 语言包补丁信息{<language>: {....},<language>:{....}}
|
||||
this.#refreshing = false; // 正在加载语言包标识
|
||||
// 用来缓存格式化器的引用,当使用格式化器时可以直接引用,减少检索遍历
|
||||
this.#cache = {
|
||||
activeLanguage : this.#options.activeLanguage,
|
||||
typedFormatters: {},
|
||||
formatters : {},
|
||||
};
|
||||
// 初始化
|
||||
this._initiLanguages()
|
||||
// 如果不存在全局VoerkaI18n实例,说明当前Scope是唯一或第一个加载的作用域,则自动创建全局VoerkaI18n实例
|
||||
if (!globalThis.VoerkaI18n) {
|
||||
const { VoerkaI18nManager } = require("./");
|
||||
globalThis.VoerkaI18n = new VoerkaI18nManager({
|
||||
debug : this.debug,
|
||||
defaultLanguage: this.defaultLanguage,
|
||||
activeLanguage : this.activeLanguage,
|
||||
defaultLanguage: this.#defaultLanguage,
|
||||
activeLanguage : this.#activeLanguage,
|
||||
languages : options.languages,
|
||||
});
|
||||
}
|
||||
this.#t = translate.bind(this)
|
||||
this.#global = globalThis.VoerkaI18n as unknown as VoerkaI18nManager;
|
||||
this.#formatterRegistry = new VoerkaI18nFormatterRegistry()
|
||||
this.loadFormatters(this.activeLanguage) // 初始化活动的格式化器
|
||||
this._mergePatchedMessages(); // 从本地缓存中读取并合并补丁语言包
|
||||
this._patch(this.messages, this.activeLanguage); // 延后执行补丁命令,该命令会向远程下载补丁包
|
||||
this.register(callback); // 在全局注册作用域
|
||||
this._patch(this.#currentMessages, this.activeLanguage); // 延后执行补丁命令,该命令会向远程下载补丁包
|
||||
if(callback) this.register(callback); // 在全局注册作用域
|
||||
}
|
||||
get id() {return this.#options.id;} // 作用域唯一id
|
||||
get debug() {return this.#options.debug;} // 调试开关
|
||||
get defaultLanguage() {return this.#options.defaultLanguage;} // 默认语言名称
|
||||
get defaultLanguage() {return this.#global.defaultLanguage;} // 默认语言名称
|
||||
get activeLanguage() {return this.#global.activeLanguage;} // 默认语言名称
|
||||
get default() {return this.#options.default;} // 默认语言包
|
||||
get messages() {return this.#options.messages; } // 当前语言包
|
||||
// 默认语言包,只能静态语言包,不能是动态语言包
|
||||
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 loaders() { return this.#options.loaders;} // 异步加载语言文件的函数列表
|
||||
get global() { return this.#global;} // 引用全局VoerkaI18n配置,注册后自动引用
|
||||
get formatters() { return this.#formatterRegistry;} // 当前作用域的所有格式化器定义 {<语言名称>: {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () => {}}}
|
||||
get activeFormatters() {return this.#formatterRegistry.formatters} // 当前作用域激活的格式化器定义 {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () = >{}}
|
||||
get formatters() { return this.#formatterRegistry;} // 当前作用域的所有格式化器定义 {<语言名称>: {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () => {}}}
|
||||
get activeFormatters() {return this.#formatterRegistry.formatters} // 当前作用域激活的格式化器定义 {$types,$config,[格式化器名称]: () = >{},[格式化器名称]: () = >{}}
|
||||
get activeFormatterConfig(){return this.#activeFormatterConfig} // 当前格式化器合并后的配置参数,参数已经合并了全局格式化器中的参数
|
||||
get cache(){return this.#cache }
|
||||
set cache(value:VoerkaI18nScopeCache){ this.#cache=value }
|
||||
get translate(){return this.#t}
|
||||
get t(){return this.#t}
|
||||
get t(){return this.#t}
|
||||
|
||||
/**
|
||||
* 对输入的语言配置进行处理
|
||||
* - 将en配置为默认回退语言
|
||||
* - 确保提供了有效的默认语言和活动语言
|
||||
*/
|
||||
_initiLanguages(){
|
||||
if(!Array.isArray(this.languages)){
|
||||
console.warn("[VoerkaI18n] invalid languages config,use default languages config instead.")
|
||||
this.#options.languages = [
|
||||
{name: "zh",title: "中文"},
|
||||
{name: "zh",title: "中文",default:true,active:true},
|
||||
{name: "en",title: "英文"}
|
||||
]
|
||||
}
|
||||
// 将en配置为默认回退语言
|
||||
this.languages.forEach(language=>{
|
||||
if(!language.fallback) language.fallback = "en"
|
||||
if(language.default) this.#defaultLanguage = language.name
|
||||
if(language.active) this.#activeLanguage = language.name
|
||||
})
|
||||
// 确保提供了有效的默认语言和活动语言
|
||||
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)){
|
||||
throw new Error("[VoerkaI18n] invalid <defaultLanguage> config, messages not specified.")
|
||||
}
|
||||
// 初始化时,默认和激活的语言包只能是静态语言包,不能是动态语言包
|
||||
// 因为初始化时激活语言需要马上显示,如果是异步语言包,会导致显示延迟
|
||||
if(isFunction(this.messages[this.#defaultLanguage])){
|
||||
throw new Error("[VoerkaI18n] invalid <defaultLanguage> config, messages must be static.")
|
||||
}
|
||||
this.#currentMessages = this.messages[this.#activeLanguage] as VoerkaI18nLanguageMessages
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,8 +145,8 @@ export class VoerkaI18nScope {
|
||||
* @param {*} callback 注册成功后的回调
|
||||
*/
|
||||
register(callback:(e?:Error)=>void) {
|
||||
if (!isFunction(callback)) callback = () => {};
|
||||
this.global.register(this).then(()=>callback()).catch((e)=>callback(e));
|
||||
if (!isFunction(callback)) callback = () => {};
|
||||
this.global.register(this).then(()=>callback()).catch((e)=>callback(e));
|
||||
}
|
||||
/**
|
||||
* 注册格式化器
|
||||
@ -186,10 +199,10 @@ export class VoerkaI18nScope {
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
private loadFormatters(newLanguage:string){
|
||||
this.#formatterRegistry.language = newLanguage
|
||||
private loadFormatters(newLanguage:string){
|
||||
// 初始化格式化器
|
||||
this.formatters.loadInitials(this.#options.formatters)
|
||||
this.#formatterRegistry.language = newLanguage
|
||||
if(this.#options.formatters)
|
||||
// 将配置中的指定为全局的格式化器注册到全局
|
||||
Object.entries(this.#options.formatters).forEach(([langName,formatters])=>{
|
||||
@ -308,29 +321,31 @@ export class VoerkaI18nScope {
|
||||
* 回退到默认语言
|
||||
*/
|
||||
private _fallback() {
|
||||
this.#options.messages = this.default;
|
||||
this.#options.activeLanguage = this.defaultLanguage;
|
||||
this.#currentMessages = this.default;
|
||||
this.#activeLanguage = this.defaultLanguage;
|
||||
}
|
||||
/**
|
||||
* 语言信息包可以是:
|
||||
*
|
||||
* 加载指定语言的语言包
|
||||
*
|
||||
* - 简单的对象{}
|
||||
* - 或者是一个返回Promise<VoerkaI18nLanguageMessages>的异步函数
|
||||
*
|
||||
* - 或者是全局的默认加载器
|
||||
*
|
||||
*
|
||||
* @param language 语言名称
|
||||
* @returns
|
||||
*/
|
||||
private async loadLanguageMessages(language:string):Promise<VoerkaI18nLanguageMessages>{
|
||||
if(!this.hasLanguage(language)) throw new InvalidLanguageError(`Not found language <${language}>`)
|
||||
// if(!this.hasLanguage(language)) throw new InvalidLanguageError(`Not found language <${language}>`)
|
||||
// 非默认语言可以是:语言包对象,也可以是一个异步加载语言包文件,加载器是一个异步函数
|
||||
// 如果没有加载器,则无法加载语言包,因此回退到默认语言
|
||||
let loader = this.loaders[language];
|
||||
let loader = this.messages[language];
|
||||
let messages:VoerkaI18nLanguageMessages = {}
|
||||
if (isPlainObject(loader)) { // 静态语言包
|
||||
messages = loader as unknown as VoerkaI18nLanguageMessages;
|
||||
} else if (isFunction(loader)) { // 语言包异步chunk
|
||||
messages = (await loader()).default;
|
||||
messages = (await (loader as VoerkaI18nMessageLoader))().default;
|
||||
} else if (isFunction(this.global.defaultMessageLoader)) {
|
||||
// 从远程加载语言包:如果该语言没有指定加载器,则使用全局配置的默认加载器
|
||||
const loadedMessages = (await this.global.loadMessagesFromDefaultLoader(language,this)) as unknown as VoerkaI18nDynamicLanguageMessages;
|
||||
@ -344,7 +359,9 @@ export class VoerkaI18nScope {
|
||||
$remote : true // 添加一个标识,表示该语言包是从远程加载的
|
||||
},this.default,loadedMessages); // 合并默认语言包和动态语言包,这样就可以局部覆盖默认语言包
|
||||
}
|
||||
}
|
||||
}else{
|
||||
throw new Error(`Not found loader for language <${language}>`)
|
||||
}
|
||||
return messages
|
||||
}
|
||||
/**
|
||||
@ -356,8 +373,8 @@ export class VoerkaI18nScope {
|
||||
if (!newLanguage) newLanguage = this.activeLanguage;
|
||||
// 默认语言:由于默认语言采用静态加载方式而不是异步块,因此只需要简单的替换即可
|
||||
if (newLanguage === this.defaultLanguage) {
|
||||
this.#options.messages = this.default;
|
||||
await this._patch(this.#options.messages, newLanguage); // 异步补丁
|
||||
this.#currentMessages = this.default;
|
||||
await this._patch(this.#currentMessages, newLanguage); // 异步补丁
|
||||
await this._changeFormatters(newLanguage);
|
||||
this.#refreshing = false
|
||||
return;
|
||||
@ -365,12 +382,12 @@ export class VoerkaI18nScope {
|
||||
try{
|
||||
let messages = await this.loadLanguageMessages(newLanguage)
|
||||
if(messages){
|
||||
this.#options.messages = messages
|
||||
this.#options.activeLanguage = newLanguage;
|
||||
this.#currentMessages = messages
|
||||
this.#activeLanguage = newLanguage;
|
||||
// 打语言包补丁, 如果是从远程加载语言包则不需要再打补丁了
|
||||
// 因为远程加载的语言包已经是补丁过的了
|
||||
if(!messages.$remote) {
|
||||
await this._patch(this.#options.messages, newLanguage);
|
||||
await this._patch(this.#currentMessages, newLanguage);
|
||||
}
|
||||
// 切换到对应语言的格式化器
|
||||
await this._changeFormatters(newLanguage);
|
||||
@ -458,6 +475,7 @@ export class VoerkaI18nScope {
|
||||
on(callback:Function) {return this.#global.on(callback); }
|
||||
off(callback:Function) {return this.#global.off(callback); }
|
||||
offAll() {return this.#global.offAll();}
|
||||
|
||||
async change(language:string) {
|
||||
await this.#global.change(language);
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ export function translate(this:VoerkaI18nScope,message:string,...args:any[]):str
|
||||
// 2.2 从当前语言包中取得翻译文本模板字符串
|
||||
// 如果没有启用babel插件将源文本转换为msgId,需要先将文本内容转换为msgId
|
||||
let msgId = isMessageId(result) ? result : scope.idMap[result]
|
||||
result = scope.messages[msgId] || result
|
||||
result = scope.current[msgId] || result
|
||||
}
|
||||
// 2. 处理复数
|
||||
// 经过上面的处理,content可能是字符串或者数组
|
||||
|
@ -8,9 +8,13 @@ declare global {
|
||||
|
||||
export type SupportedDateTypes = "String" | "Number" | "Boolean" | "Object" | "Array" | "Function" | "Error" | "Symbol" | "RegExp" | "Date" | "Null" | "Undefined" | "Set" | "Map" | "WeakSet" | "WeakMap"
|
||||
|
||||
// 语言包
|
||||
export type VoerkaI18nLanguageMessages = Record<string, string | string[]> & {
|
||||
$config?: VoerkaI18nTypesFormatterConfigs
|
||||
}
|
||||
|
||||
export type VoerkaI18nLanguageMessagePack = Record<string, VoerkaI18nLanguageMessages | VoerkaI18nMessageLoader>
|
||||
|
||||
export type VoerkaI18nDynamicLanguageMessages = Record<string, string | string[]> & {
|
||||
$config?: VoerkaI18nTypesFormatterConfigs
|
||||
}
|
||||
@ -23,38 +27,36 @@ export type Voerkai18nIdMap = Record<string, number>
|
||||
export interface VoerkaI18nLanguageDefine {
|
||||
name: string
|
||||
title?: string
|
||||
default?: boolean
|
||||
default?: boolean // 是否默认语言
|
||||
active?: boolean
|
||||
fallback?: string
|
||||
}
|
||||
|
||||
|
||||
export type VoerkaI18nFormatterConfigs = Record<string, any>
|
||||
export type VoerkaI18nFormatter = (value: string,args: any[],$config:VoerkI18nFormatterConfigs) => string
|
||||
export type VoerkaI18nTypesFormatters=Record<SupportedDateTypes | string, VoerkaI18nFormatter>
|
||||
export type VoerkaI18nTypesFormatterConfigs= Record<SupportedDateTypes | string, Record<string,any>>
|
||||
export type VoerkaI18nFormatter = ((value: string,args?: any[],$config?:VoerkI18nFormatterConfigs) => string)
|
||||
export type VoerkaI18nTypesFormatters=Partial<Record<SupportedDateTypes, VoerkaI18nFormatter>>
|
||||
export type VoerkaI18nTypesFormatterConfig= Partial<Record<string, any>>
|
||||
export type VoerkaI18nTypesFormatterConfigs= Partial<Record<SupportedDateTypes | string, Record<string,any>>>
|
||||
export type VoerkaI18nFormattersLoader = (()=>Promise<VoerkaI18nFormatters>)
|
||||
// 每一个语言的格式化器定义={$types:{...},$config:{...},[格式化器名称]: () => {},[格式化器名称]: () => {}
|
||||
// 在formatters/xxxx.ts里面进行配置
|
||||
export type VoerkaI18nFormatters = ({
|
||||
export type VoerkaI18nFormatters = {
|
||||
global?: boolean | Omit<VoerkaI18nFormatters,'global'> // 是否全局格式化器
|
||||
$types?:VoerkaI18nTypesFormatters
|
||||
$config?: VoerkaI18nTypesFormatterConfigs
|
||||
} & {
|
||||
[DataTypeName in SupportedDateTypes]?: VoerkaI18nFormatter
|
||||
} & {
|
||||
} | {
|
||||
[key: string]: VoerkaI18nFormatter
|
||||
})
|
||||
}
|
||||
|
||||
// 包括语言的{"*":{...},zh:{...},en:{...}}
|
||||
// 声明格式化器
|
||||
export type VoerkaI18nLanguageFormatters = Record<string,VoerkaI18nFormatters | VoerkaI18nFormattersLoader>
|
||||
export type VoerkaI18nLanguageFormatters = Record<string,VoerkaI18nFormatters | VoerkaI18nMessageLoader>
|
||||
|
||||
|
||||
|
||||
//
|
||||
export type VoerkaI18nLoader = () => Awaited<Promise<any>>
|
||||
export interface VoerkaI18nLoaders {
|
||||
[key: string]: VoerkaI18nLoader
|
||||
export type VoerkaI18nMessageLoader = () => Awaited<Promise<any>>
|
||||
export interface VoerkaI18nMessageLoaders {
|
||||
[key: string]: VoerkaI18nMessageLoader
|
||||
}
|
||||
|
||||
export type VoerkaI18nDefaultMessageLoader = (this:VoerkaI18nScope,newLanguage:string,scope:VoerkaI18nScope)=>Promise<VoerkaI18nLanguageMessages>
|
||||
@ -145,14 +147,13 @@ export interface FormatterDefine {
|
||||
}
|
||||
// 创建格式化器
|
||||
export type CreateFormatterType = (fn: Function, options: CreateFormatterOptions, defaultParams: Record<string, any>) => FormatterDefine
|
||||
export var createFormatter: CreateFormatterType
|
||||
export var Formatter: CreateFormatterType
|
||||
// export var createFormatter: CreateFormatterType
|
||||
// export var Formatter: CreateFormatterType
|
||||
|
||||
export type CreateFlexFormatterType = (fn: Function, options: CreateFormatterOptions, defaultParams: Record<string, any>) => FormatterDefine
|
||||
export var createFlexFormatter: CreateFlexFormatterType
|
||||
export var FlexFormatter: CreateFlexFormatterType
|
||||
export var getDataTypeName: (value: any) => string
|
||||
export var toDate: (value: any) => Date | number
|
||||
export var toNumber: (value: any, defaultValue: number) => number
|
||||
export var toBoolean: (value: any) => boolean
|
||||
// export var createFlexFormatter: CreateFlexFormatterType
|
||||
// export var FlexFormatter: CreateFlexFormatterType
|
||||
// export var getDataTypeName: (value: any) => string
|
||||
// export var toDate: (value: any) => Date | number
|
||||
// export var toBoolean: (value: any) => boolean
|
||||
|
||||
|
@ -44,12 +44,12 @@ export const DataTypes = ["String","Number","Boolean","Object","Array","Functio
|
||||
/**
|
||||
* 转换为数字类型
|
||||
*/
|
||||
export function toNumber(value:any,defualt=0):number {
|
||||
export function toNumber(value:any):number {
|
||||
try {
|
||||
if (isNumber(value)) {
|
||||
return parseFloat(value)
|
||||
} else {
|
||||
return defualt
|
||||
return 0
|
||||
}
|
||||
} catch {
|
||||
return value
|
||||
|
Loading…
x
Reference in New Issue
Block a user