Match-id-417ad546618f89732bb60368a0b25e5f7f547b20
This commit is contained in:
commit
9fbaf33e17
|
@ -4,7 +4,7 @@
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "build/intl.umd.js",
|
"main": "build/intl.umd.js",
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"types": "build/@types/index.d.ts",
|
"types": "build/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"demo-serve": "webpack serve --mode=development",
|
"demo-serve": "webpack serve --mode=development",
|
||||||
"rollup-build": "rollup --config rollup.config.js",
|
"rollup-build": "rollup --config rollup.config.js",
|
||||||
|
|
|
@ -17,8 +17,9 @@ import EventDispatcher from '../utils/eventListener';
|
||||||
import DateTimeFormatter from "../format/fomatters/DateTimeFormatter";
|
import DateTimeFormatter from "../format/fomatters/DateTimeFormatter";
|
||||||
import NumberFormatter from "../format/fomatters/NumberFormatter";
|
import NumberFormatter from "../format/fomatters/NumberFormatter";
|
||||||
import { getFormatMessage } from '../format/getFormatMessage';
|
import { getFormatMessage } from '../format/getFormatMessage';
|
||||||
import { I18nProps, MessageDescriptor, MessageOptions } from '../types/interfaces';
|
import {I18nCache, I18nProps, MessageDescriptor, MessageOptions} from '../types/interfaces';
|
||||||
import { Locale, Locales, Messages, AllLocaleConfig, AllMessages, LocaleConfig, Error, Events } from '../types/types';
|
import { Locale, Locales, Messages, AllLocaleConfig, AllMessages, LocaleConfig, Error, Events } from '../types/types';
|
||||||
|
import creatI18nCache from "../format/cache/cache";
|
||||||
|
|
||||||
export class I18n extends EventDispatcher<Events> {
|
export class I18n extends EventDispatcher<Events> {
|
||||||
public locale: Locale;
|
public locale: Locale;
|
||||||
|
@ -26,7 +27,7 @@ export class I18n extends EventDispatcher<Events> {
|
||||||
private readonly _localeConfig: AllLocaleConfig;
|
private readonly _localeConfig: AllLocaleConfig;
|
||||||
private readonly allMessages: AllMessages;
|
private readonly allMessages: AllMessages;
|
||||||
public readonly error?: Error;
|
public readonly error?: Error;
|
||||||
public readonly useMemorize?: boolean;
|
public readonly cache?: I18nCache;
|
||||||
|
|
||||||
constructor(props: I18nProps) {
|
constructor(props: I18nProps) {
|
||||||
super();
|
super();
|
||||||
|
@ -48,6 +49,8 @@ export class I18n extends EventDispatcher<Events> {
|
||||||
this.formatMessage = this.formatMessage.bind(this);
|
this.formatMessage = this.formatMessage.bind(this);
|
||||||
this.formatDate = this.formatDate.bind(this);
|
this.formatDate = this.formatDate.bind(this);
|
||||||
this.formatNumber = this.formatNumber.bind(this);
|
this.formatNumber = this.formatNumber.bind(this);
|
||||||
|
|
||||||
|
this.cache = props.cache ?? creatI18nCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
get messages(): string | Messages | AllMessages {
|
get messages(): string | Messages | AllMessages {
|
||||||
|
@ -115,18 +118,18 @@ export class I18n extends EventDispatcher<Events> {
|
||||||
formatMessage(
|
formatMessage(
|
||||||
id: MessageDescriptor | string,
|
id: MessageDescriptor | string,
|
||||||
values: Object | undefined = {},
|
values: Object | undefined = {},
|
||||||
{ message, context, formatOptions, useMemorize}: MessageOptions = {},
|
{ message, context, formatOptions}: MessageOptions = {},
|
||||||
) {
|
) {
|
||||||
return getFormatMessage(this, id, values, { message, context, formatOptions, useMemorize});
|
return getFormatMessage(this, id, values, { message, context, formatOptions});
|
||||||
}
|
}
|
||||||
|
|
||||||
formatDate(value: string | Date, formatOptions?: Intl.DateTimeFormatOptions): string {
|
formatDate(value: string | Date, formatOptions?: Intl.DateTimeFormatOptions): string {
|
||||||
const dateTimeFormatter = new DateTimeFormatter(this.locale || this.locales, formatOptions, this.useMemorize);
|
const dateTimeFormatter = new DateTimeFormatter(this.locale || this.locales, formatOptions, this.cache);
|
||||||
return dateTimeFormatter.dateTimeFormat(value);
|
return dateTimeFormatter.dateTimeFormat(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
formatNumber(value: number, formatOptions?: Intl.NumberFormatOptions): string {
|
formatNumber(value: number, formatOptions?: Intl.NumberFormatOptions): string {
|
||||||
const numberFormatter = new NumberFormatter(this.locale || this.locales, formatOptions, this.useMemorize);
|
const numberFormatter = new NumberFormatter(this.locale || this.locales, formatOptions, this.cache);
|
||||||
return numberFormatter.numberFormat(value);
|
return numberFormatter.numberFormat(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
*/
|
*/
|
||||||
import Inula, { useRef, useState, useEffect, useMemo, Component } from 'inulajs';
|
import Inula, { useRef, useState, useEffect, useMemo } from 'inulajs';
|
||||||
import utils from '../../utils/utils';
|
|
||||||
import { InjectProvider } from './InjectI18n';
|
import { InjectProvider } from './InjectI18n';
|
||||||
import I18n, { createI18nInstance } from '../I18n';
|
import I18n, { createI18nInstance } from '../I18n';
|
||||||
import { I18nProviderProps } from '../../types/types';
|
import { I18nProviderProps } from '../../types/types';
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*/
|
*/
|
||||||
import { configProps, I18nCache } from '../types/interfaces';
|
import { configProps, I18nCache } from '../types/interfaces';
|
||||||
import I18n, { createI18nInstance } from './I18n';
|
import I18n, { createI18nInstance } from './I18n';
|
||||||
|
import creatI18nCache from '../format/cache/cache';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* createI18n hook函数,用于创建国际化i8n实例,以进行相关的数据操作
|
* createI18n hook函数,用于创建国际化i8n实例,以进行相关的数据操作
|
||||||
|
@ -22,9 +23,9 @@ import I18n, { createI18nInstance } from './I18n';
|
||||||
export const createI18n = (config: configProps, cache?: I18nCache): I18n => {
|
export const createI18n = (config: configProps, cache?: I18nCache): I18n => {
|
||||||
const { locale, defaultLocale, messages } = config;
|
const { locale, defaultLocale, messages } = config;
|
||||||
return createI18nInstance({
|
return createI18nInstance({
|
||||||
locale: locale || defaultLocale || 'en',
|
locale: locale || defaultLocale || 'zh',
|
||||||
messages: messages,
|
messages: messages,
|
||||||
useMemorize: !!cache,
|
cache: cache ?? creatI18nCache(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
import { UNICODE_REG } from '../constants';
|
import { UNICODE_REG } from '../constants';
|
||||||
import { CompiledMessage, Locale, LocaleConfig, Locales } from '../types/types';
|
import { CompiledMessage, Locale, LocaleConfig, Locales } from '../types/types';
|
||||||
import generateFormatters from './generateFormatters';
|
import generateFormatters from './generateFormatters';
|
||||||
import { FormatOptions } from '../types/interfaces';
|
import {FormatOptions, I18nCache} from '../types/interfaces';
|
||||||
|
import {createIntlCache} from "../../index";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取翻译结果
|
* 获取翻译结果
|
||||||
|
@ -26,14 +27,14 @@ class Translation {
|
||||||
private readonly locale: Locale;
|
private readonly locale: Locale;
|
||||||
private readonly locales: Locales;
|
private readonly locales: Locales;
|
||||||
private readonly localeConfig: Record<string, any>;
|
private readonly localeConfig: Record<string, any>;
|
||||||
private readonly useMemorize?: boolean;
|
private readonly cache: I18nCache;
|
||||||
|
|
||||||
constructor(compiledMessage, locale, locales, localeConfig, memorize?) {
|
constructor(compiledMessage, locale, locales, localeConfig, cache?) {
|
||||||
this.compiledMessage = compiledMessage;
|
this.compiledMessage = compiledMessage;
|
||||||
this.locale = locale;
|
this.locale = locale;
|
||||||
this.locales = locales;
|
this.locales = locales;
|
||||||
this.localeConfig = localeConfig;
|
this.localeConfig = localeConfig;
|
||||||
this.useMemorize = memorize ?? true;
|
this.cache = cache ?? createIntlCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,12 +48,11 @@ class Translation {
|
||||||
values: object,
|
values: object,
|
||||||
formatOptions: FormatOptions,
|
formatOptions: FormatOptions,
|
||||||
localeConfig: LocaleConfig,
|
localeConfig: LocaleConfig,
|
||||||
useMemorize?: boolean
|
|
||||||
) => {
|
) => {
|
||||||
const textFormatter = (name: string, type: string, format: any) => {
|
const textFormatter = (name: string, type: string, format: any) => {
|
||||||
const formatters = generateFormatters(locale, locales, localeConfig, formatOptions);
|
const formatters = generateFormatters(locale, locales, localeConfig, formatOptions, this.cache);
|
||||||
const value = values[name];
|
const value = values[name];
|
||||||
const formatter = formatters[type](value, format, useMemorize);
|
const formatter = formatters[type](value, format);
|
||||||
|
|
||||||
let message;
|
let message;
|
||||||
if (typeof formatter === 'function') {
|
if (typeof formatter === 'function') {
|
||||||
|
@ -73,7 +73,6 @@ class Translation {
|
||||||
values,
|
values,
|
||||||
formatOptions,
|
formatOptions,
|
||||||
this.localeConfig,
|
this.localeConfig,
|
||||||
this.useMemorize
|
|
||||||
);
|
);
|
||||||
// 通过递归方法formatCore进行格式化处理
|
// 通过递归方法formatCore进行格式化处理
|
||||||
const result = this.formatMessage(this.compiledMessage, textFormatter);
|
const result = this.formatMessage(this.compiledMessage, textFormatter);
|
||||||
|
|
|
@ -22,7 +22,6 @@ function creatI18nCache(): I18nCache {
|
||||||
dateTimeFormat: {},
|
dateTimeFormat: {},
|
||||||
numberFormat: {},
|
numberFormat: {},
|
||||||
plurals: {},
|
plurals: {},
|
||||||
messages: {},
|
|
||||||
select: {},
|
select: {},
|
||||||
octothorpe: {},
|
octothorpe: {},
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
import creatI18nCache from '../cache/cache';
|
import creatI18nCache from '../cache/cache';
|
||||||
import utils from '../../utils/utils';
|
import utils from '../../utils/utils';
|
||||||
import { DatePool, Locales } from '../../types/types';
|
import { DatePool, Locales } from '../../types/types';
|
||||||
|
import {I18nCache} from "../../types/interfaces";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 时间格式化
|
* 时间格式化
|
||||||
|
@ -23,17 +24,13 @@ import { DatePool, Locales } from '../../types/types';
|
||||||
class DateTimeFormatter {
|
class DateTimeFormatter {
|
||||||
private readonly locales: Locales;
|
private readonly locales: Locales;
|
||||||
private readonly formatOptions: Intl.DateTimeFormatOptions;
|
private readonly formatOptions: Intl.DateTimeFormatOptions;
|
||||||
|
|
||||||
// 是否进行存储
|
|
||||||
private readonly useMemorize: boolean;
|
|
||||||
|
|
||||||
// 创建一个缓存对象,用于存储DateTimeFormat的对象
|
// 创建一个缓存对象,用于存储DateTimeFormat的对象
|
||||||
private cache = creatI18nCache().dateTimeFormat;
|
private readonly cache?: I18nCache;
|
||||||
|
|
||||||
constructor(locales: Locales, formatOptions?: Intl.DateTimeFormatOptions, useMemorize?: boolean) {
|
constructor(locales: Locales, formatOptions?: Intl.DateTimeFormatOptions, cache?: I18nCache) {
|
||||||
this.locales = locales;
|
this.locales = locales;
|
||||||
this.formatOptions = formatOptions ?? {};
|
this.formatOptions = formatOptions ?? {};
|
||||||
this.useMemorize = useMemorize ?? true;
|
this.cache = cache ?? creatI18nCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
dateTimeFormat(value: DatePool, formatOptions?: Intl.DateTimeFormatOptions): string {
|
dateTimeFormat(value: DatePool, formatOptions?: Intl.DateTimeFormatOptions): string {
|
||||||
|
@ -45,16 +42,16 @@ class DateTimeFormatter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果启用了记忆化且已经有对应的数字格式化器缓存,则直接返回缓存中的格式化结果。否则创建新的格式化数据,并进行缓存
|
// 如果启用了记忆化且已经有对应的数字格式化器缓存,则直接返回缓存中的格式化结果。否则创建新的格式化数据,并进行缓存
|
||||||
if (this.useMemorize) {
|
if (this.cache?.dateTimeFormat) {
|
||||||
// 造缓存的key,key包含区域设置和日期时间格式选项
|
// 造缓存的key,key包含区域设置和日期时间格式选项
|
||||||
const cacheKey = utils.generateKey<Intl.DateTimeFormatOptions>(this.locales, options);
|
const cacheKey = utils.generateKey<Intl.DateTimeFormatOptions>(this.locales, options);
|
||||||
|
|
||||||
if (this.cache[cacheKey]) {
|
if (this.cache.dateTimeFormat[cacheKey]) {
|
||||||
return this.cache[cacheKey].format(value);
|
return this.cache.dateTimeFormat[cacheKey].format(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询缓存中的key, 若无key则创建新key
|
// 查询缓存中的key, 若无key则创建新key
|
||||||
this.cache[cacheKey] = formatter;
|
this.cache.dateTimeFormat[cacheKey] = formatter;
|
||||||
return formatter.format(value);
|
return formatter.format(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
import creatI18nCache from '../cache/cache';
|
import creatI18nCache from '../cache/cache';
|
||||||
import { Locales } from '../../types/types';
|
import { Locales } from '../../types/types';
|
||||||
import utils from '../../utils/utils';
|
import utils from '../../utils/utils';
|
||||||
|
import {I18nCache} from "../../types/interfaces";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数字格式化
|
* 数字格式化
|
||||||
|
@ -23,13 +24,12 @@ import utils from '../../utils/utils';
|
||||||
class NumberFormatter {
|
class NumberFormatter {
|
||||||
private readonly locales: Locales;
|
private readonly locales: Locales;
|
||||||
private readonly formatOption?: Intl.NumberFormatOptions;
|
private readonly formatOption?: Intl.NumberFormatOptions;
|
||||||
private readonly useMemorize?: boolean;
|
private cache?: I18nCache; // 创建一个缓存对象,用于缓存已经创建的数字格式化器
|
||||||
private cache = creatI18nCache().numberFormat; // 创建一个缓存对象,用于缓存已经创建的数字格式化器
|
|
||||||
|
|
||||||
constructor(locales: Locales, formatOption?: Intl.NumberFormatOptions, useMemorize?: boolean) {
|
constructor(locales: Locales, formatOption?: Intl.NumberFormatOptions, cache?: I18nCache) {
|
||||||
this.locales = locales;
|
this.locales = locales;
|
||||||
this.formatOption = formatOption ?? {};
|
this.formatOption = formatOption ?? {};
|
||||||
this.useMemorize = useMemorize ?? true;
|
this.cache = cache ?? creatI18nCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
numberFormat(value: number, formatOption?: Intl.NumberFormatOptions): string {
|
numberFormat(value: number, formatOption?: Intl.NumberFormatOptions): string {
|
||||||
|
@ -37,15 +37,15 @@ class NumberFormatter {
|
||||||
const formatter = new Intl.NumberFormat(this.locales, options);
|
const formatter = new Intl.NumberFormat(this.locales, options);
|
||||||
|
|
||||||
// 如果启用了记忆化且已经有对应的数字格式化器缓存,则直接返回缓存中的格式化结果。否则创建新的格式化数据,并进行缓存
|
// 如果启用了记忆化且已经有对应的数字格式化器缓存,则直接返回缓存中的格式化结果。否则创建新的格式化数据,并进行缓存
|
||||||
if (this.useMemorize) {
|
if (this.cache?.numberFormat) {
|
||||||
// 造缓存的key,key包含区域设置数字格式选项
|
// 造缓存的key,key包含区域设置数字格式选项
|
||||||
const cacheKey = utils.generateKey<Intl.NumberFormatOptions>(this.locales, options);
|
const cacheKey = utils.generateKey<Intl.NumberFormatOptions>(this.locales, options);
|
||||||
|
|
||||||
if (this.cache[cacheKey]) {
|
if (this.cache.numberFormat[cacheKey]) {
|
||||||
return this.cache[cacheKey].format(value);
|
return this.cache.numberFormat[cacheKey].format(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cache[cacheKey] = formatter;
|
this.cache.numberFormat[cacheKey] = formatter;
|
||||||
return formatter.format(value);
|
return formatter.format(value);
|
||||||
}
|
}
|
||||||
return formatter.format(value);
|
return formatter.format(value);
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
import utils from '../../utils/utils';
|
import utils from '../../utils/utils';
|
||||||
import NumberFormatter from './NumberFormatter';
|
import NumberFormatter from './NumberFormatter';
|
||||||
import { Locale, Locales } from '../../types/types';
|
import { Locale, Locales } from '../../types/types';
|
||||||
|
import {I18nCache} from "../../types/interfaces";
|
||||||
|
import {createIntlCache} from "../../../index";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 复数格式化
|
* 复数格式化
|
||||||
|
@ -25,15 +27,14 @@ class PluralFormatter {
|
||||||
private readonly locales: Locales;
|
private readonly locales: Locales;
|
||||||
private readonly value: number;
|
private readonly value: number;
|
||||||
private readonly message: any;
|
private readonly message: any;
|
||||||
private readonly useMemorize: boolean;
|
private readonly cache: I18nCache;
|
||||||
private octothorpe: Record<string, any> = {};
|
|
||||||
|
|
||||||
constructor(locale, locales, value, message, useMemorize?) {
|
constructor(locale, locales, value, message, cache?) {
|
||||||
this.locale = locale;
|
this.locale = locale;
|
||||||
this.locales = locales;
|
this.locales = locales;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.useMemorize = useMemorize ?? true;
|
this.cache = cache ?? createIntlCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将 message中的“#”替换为指定数字value,并返回新的字符串或者字符串数组
|
// 将 message中的“#”替换为指定数字value,并返回新的字符串或者字符串数组
|
||||||
|
@ -44,17 +45,17 @@ class PluralFormatter {
|
||||||
const numberFormatter = new NumberFormatter(this.locales);
|
const numberFormatter = new NumberFormatter(this.locales);
|
||||||
const valueStr = numberFormatter.numberFormat(this.value);
|
const valueStr = numberFormatter.numberFormat(this.value);
|
||||||
|
|
||||||
if (this.useMemorize) {
|
if (this.cache.octothorpe) {
|
||||||
// 创建key,用于唯一标识
|
// 创建key,用于唯一标识
|
||||||
const cacheKey = utils.generateKey<Intl.NumberFormatOptions>(this.locale, this.message);
|
const cacheKey = utils.generateKey<Intl.NumberFormatOptions>(this.locale, this.message);
|
||||||
|
|
||||||
// 如果key存在,则使用缓存中的替代
|
// 如果key存在,则使用缓存中的替代
|
||||||
if (this.octothorpe[cacheKey]) {
|
if (this.cache.octothorpe[cacheKey]) {
|
||||||
return messages.map(msg => (typeof msg === 'string' ? msg.replace('#', this.octothorpe[cacheKey]) : msg));
|
return messages.map(msg => (typeof msg === 'string' ? msg.replace('#', this.cache.octothorpe[cacheKey]) : msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果不存在,则进行缓存
|
// 如果不存在,则进行缓存
|
||||||
this.octothorpe[cacheKey] = valueStr;
|
this.cache.octothorpe[cacheKey] = valueStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return messages.map(msg => (typeof msg === 'string' ? msg.replace('#', valueStr) : msg));
|
return messages.map(msg => (typeof msg === 'string' ? msg.replace('#', valueStr) : msg));
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
import utils from '../../utils/utils';
|
import utils from '../../utils/utils';
|
||||||
import { Locale } from '../../types/types';
|
import { Locale } from '../../types/types';
|
||||||
|
import {I18nCache} from "../../types/interfaces";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规则选择器
|
* 规则选择器
|
||||||
|
@ -23,24 +24,25 @@ import { Locale } from '../../types/types';
|
||||||
*/
|
*/
|
||||||
class SelectFormatter {
|
class SelectFormatter {
|
||||||
private readonly locale: Locale;
|
private readonly locale: Locale;
|
||||||
private selectCache = {};
|
private readonly cache: I18nCache;
|
||||||
|
|
||||||
constructor(locale) {
|
constructor(locale, cache) {
|
||||||
this.locale = locale;
|
this.locale = locale;
|
||||||
|
this.cache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRule(value, rules, useMemorize?) {
|
getRule(value, rules) {
|
||||||
if (useMemorize) {
|
if (this.cache.select) {
|
||||||
// 创建key,用于唯一标识
|
// 创建key,用于唯一标识
|
||||||
const cacheKey = utils.generateKey<Intl.NumberFormatOptions>(this.locale, rules);
|
const cacheKey = utils.generateKey<Intl.NumberFormatOptions>(this.locale, rules);
|
||||||
|
|
||||||
// 如果key存在,则使用缓存中的替代
|
// 如果key存在,则使用缓存中的替代
|
||||||
if (this.selectCache[cacheKey]) {
|
if (this.cache.select[cacheKey]) {
|
||||||
return this.selectCache[cacheKey][value] || this.selectCache[cacheKey].other;
|
return this.cache.select[cacheKey][value] || this.cache.select[cacheKey].other;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果不存在,则进行缓存
|
// 如果不存在,则进行缓存
|
||||||
this.selectCache[cacheKey] = rules;
|
this.cache.select[cacheKey] = rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rules[value] || rules.other;
|
return rules[value] || rules.other;
|
||||||
|
|
|
@ -18,7 +18,8 @@ import NumberFormatter from './fomatters/NumberFormatter';
|
||||||
import { DatePool, Locale, Locales, SelectPool } from '../types/types';
|
import { DatePool, Locale, Locales, SelectPool } from '../types/types';
|
||||||
import PluralFormatter from './fomatters/PluralFormatter';
|
import PluralFormatter from './fomatters/PluralFormatter';
|
||||||
import SelectFormatter from './fomatters/SelectFormatter';
|
import SelectFormatter from './fomatters/SelectFormatter';
|
||||||
import { FormatOptions, IntlMessageFormat } from '../types/interfaces';
|
import {FormatOptions, I18nCache, IntlMessageFormat} from '../types/interfaces';
|
||||||
|
import cache from "./cache/cache";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认格式化接口
|
* 默认格式化接口
|
||||||
|
@ -27,7 +28,8 @@ const generateFormatters = (
|
||||||
locale: Locale | Locales,
|
locale: Locale | Locales,
|
||||||
locales: Locales,
|
locales: Locales,
|
||||||
localeConfig: Record<string, any> = { plurals: undefined },
|
localeConfig: Record<string, any> = { plurals: undefined },
|
||||||
formatOptions: FormatOptions = {} // 自定义格式对象
|
formatOptions: FormatOptions = {}, // 自定义格式对象
|
||||||
|
cache: I18nCache
|
||||||
): IntlMessageFormat => {
|
): IntlMessageFormat => {
|
||||||
locale = locales || locale;
|
locale = locales || locale;
|
||||||
const { plurals } = localeConfig;
|
const { plurals } = localeConfig;
|
||||||
|
@ -45,13 +47,13 @@ const generateFormatters = (
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// 复数规则
|
// 复数规则
|
||||||
plural: (value: number, { offset = 0, ...rules }, useMemorize?) => {
|
plural: (value: number, { offset = 0, ...rules }) => {
|
||||||
const pluralFormatter = new PluralFormatter(
|
const pluralFormatter = new PluralFormatter(
|
||||||
locale,
|
locale,
|
||||||
locales,
|
locales,
|
||||||
value - offset,
|
value - offset,
|
||||||
rules[value] || rules[(plurals as any)?.(value - offset)] || rules.other,
|
rules[value] || rules[(plurals as any)?.(value - offset)] || rules.other,
|
||||||
useMemorize
|
cache
|
||||||
);
|
);
|
||||||
return pluralFormatter.replaceSymbol.bind(pluralFormatter);
|
return pluralFormatter.replaceSymbol.bind(pluralFormatter);
|
||||||
},
|
},
|
||||||
|
@ -63,14 +65,14 @@ const generateFormatters = (
|
||||||
},
|
},
|
||||||
|
|
||||||
// 选择规则,如果规则对象中包含与该值相对应的属性,则返回该属性的值;否则,返回 "other" 属性的值。
|
// 选择规则,如果规则对象中包含与该值相对应的属性,则返回该属性的值;否则,返回 "other" 属性的值。
|
||||||
select: (value: SelectPool, formatRules, useMemorize?) => {
|
select: (value: SelectPool, formatRules) => {
|
||||||
const selectFormatter = new SelectFormatter(locale);
|
const selectFormatter = new SelectFormatter(locale, cache);
|
||||||
return selectFormatter.getRule(value, formatRules, useMemorize);
|
return selectFormatter.getRule(value, formatRules);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 用于将数字格式化为字符串,接受一个数字和一个格式化规则。它会根据规则返回格式化后的字符串。
|
// 用于将数字格式化为字符串,接受一个数字和一个格式化规则。它会根据规则返回格式化后的字符串。
|
||||||
numberFormat: (value: number, formatOption, useMemorize) => {
|
numberFormat: (value: number, formatOption) => {
|
||||||
return new NumberFormatter(locales, getStyleOption(formatOption), useMemorize).numberFormat(value);
|
return new NumberFormatter(locales, getStyleOption(formatOption), cache).numberFormat(value);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 用于将日期格式化为字符串,接受一个日期对象和一个格式化规则。它会根据规则返回格式化后的字符串。
|
// 用于将日期格式化为字符串,接受一个日期对象和一个格式化规则。它会根据规则返回格式化后的字符串。
|
||||||
|
@ -83,8 +85,8 @@ const generateFormatters = (
|
||||||
* @param formatOption { year: 'numeric', month: 'long', day: 'numeric' }
|
* @param formatOption { year: 'numeric', month: 'long', day: 'numeric' }
|
||||||
* @param useMemorize
|
* @param useMemorize
|
||||||
*/
|
*/
|
||||||
dateTimeFormat: (value: DatePool, formatOption, useMemorize) => {
|
dateTimeFormat: (value: DatePool, formatOption) => {
|
||||||
return new DateTimeFormatter(locales, getStyleOption(formatOption), useMemorize).dateTimeFormat(
|
return new DateTimeFormatter(locales, getStyleOption(formatOption), cache).dateTimeFormat(
|
||||||
value,
|
value,
|
||||||
formatOption
|
formatOption
|
||||||
);
|
);
|
||||||
|
|
|
@ -18,6 +18,7 @@ import Translation from './Translation';
|
||||||
import I18n from '../core/I18n';
|
import I18n from '../core/I18n';
|
||||||
import { MessageDescriptor, MessageOptions } from '../types/interfaces';
|
import { MessageDescriptor, MessageOptions } from '../types/interfaces';
|
||||||
import { CompiledMessage } from '../types/types';
|
import { CompiledMessage } from '../types/types';
|
||||||
|
import creatI18nCache from "./cache/cache";
|
||||||
|
|
||||||
export function getFormatMessage(
|
export function getFormatMessage(
|
||||||
i18n: I18n,
|
i18n: I18n,
|
||||||
|
@ -25,8 +26,8 @@ export function getFormatMessage(
|
||||||
values: Object | undefined = {},
|
values: Object | undefined = {},
|
||||||
options: MessageOptions = {}
|
options: MessageOptions = {}
|
||||||
) {
|
) {
|
||||||
let { message, context, formatOptions, useMemorize } = options;
|
let { message, context, formatOptions } = options;
|
||||||
const memorize = useMemorize ?? i18n.useMemorize;
|
const cache = i18n.cache ?? creatI18nCache();
|
||||||
if (typeof id !== 'string') {
|
if (typeof id !== 'string') {
|
||||||
values = values || id.defaultValues;
|
values = values || id.defaultValues;
|
||||||
message = id.message || id.defaultMessage;
|
message = id.message || id.defaultMessage;
|
||||||
|
@ -59,6 +60,6 @@ export function getFormatMessage(
|
||||||
// 对解析的messages进行parse解析,并输出解析后的Token
|
// 对解析的messages进行parse解析,并输出解析后的Token
|
||||||
compliedMessage = typeof compliedMessage === 'string' ? utils.compile(compliedMessage) : compliedMessage;
|
compliedMessage = typeof compliedMessage === 'string' ? utils.compile(compliedMessage) : compliedMessage;
|
||||||
|
|
||||||
const translation = new Translation(compliedMessage, i18n.locale, i18n.locales, i18n.localeConfig, memorize);
|
const translation = new Translation(compliedMessage, i18n.locale, i18n.locales, i18n.localeConfig, cache);
|
||||||
return translation.translate(values, formatOptions);
|
return translation.translate(values, formatOptions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,6 @@ export interface MessageOptions {
|
||||||
message?: string;
|
message?: string;
|
||||||
context?: string;
|
context?: string;
|
||||||
formatOptions?: FormatOptions;
|
formatOptions?: FormatOptions;
|
||||||
useMemorize?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// I18n类的缓存定义
|
// I18n类的缓存定义
|
||||||
|
@ -54,8 +53,7 @@ export interface I18nCache {
|
||||||
dateTimeFormat: Record<string, Intl.DateTimeFormat>;
|
dateTimeFormat: Record<string, Intl.DateTimeFormat>;
|
||||||
numberFormat: Record<string, Intl.NumberFormat>;
|
numberFormat: Record<string, Intl.NumberFormat>;
|
||||||
plurals: Record<string, Intl.PluralRules>;
|
plurals: Record<string, Intl.PluralRules>;
|
||||||
messages: Record<string, IntlMessageFormat>;
|
select: Record<string, any>;
|
||||||
select: Record<string, object>;
|
|
||||||
octothorpe: Record<string, any>;
|
octothorpe: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +63,7 @@ export interface I18nProps {
|
||||||
locales?: Locales;
|
locales?: Locales;
|
||||||
messages?: AllMessages;
|
messages?: AllMessages;
|
||||||
localeConfig?: AllLocaleConfig;
|
localeConfig?: AllLocaleConfig;
|
||||||
useMemorize?: boolean;
|
cache?: I18nCache;
|
||||||
error?: Error;
|
error?: Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,23 +89,41 @@ export interface configProps {
|
||||||
defaultLocale?: string;
|
defaultLocale?: string;
|
||||||
RenderOnLocaleChange?: boolean;
|
RenderOnLocaleChange?: boolean;
|
||||||
children?: any;
|
children?: any;
|
||||||
uesMemorize?: boolean;
|
onWarn?: Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IntlMessageFormat extends configProps, MessageOptions {
|
export interface IntlMessageFormat extends configProps, MessageOptions {
|
||||||
plural: (
|
plural: (
|
||||||
value: number,
|
value: number,
|
||||||
{ offset, ...rules }: { [x: string]: any; offset?: number },
|
{
|
||||||
useMemorize?: boolean
|
offset,
|
||||||
|
...rules
|
||||||
|
}: {
|
||||||
|
[x: string]: any;
|
||||||
|
offset?: number | undefined;
|
||||||
|
}
|
||||||
) => (ctx: any) => any[];
|
) => (ctx: any) => any[];
|
||||||
selectordinal: (
|
selectordinal: (
|
||||||
value: number,
|
value: number,
|
||||||
{ offset, ...rules }: { [x: string]: any; offset?: number },
|
{
|
||||||
useMemorize?: boolean
|
offset,
|
||||||
|
...rules
|
||||||
|
}: {
|
||||||
|
[x: string]: any;
|
||||||
|
offset?: number | undefined;
|
||||||
|
}
|
||||||
) => (ctx: any) => any[];
|
) => (ctx: any) => any[];
|
||||||
select: (value: SelectPool, formatRules: any, useMemorize?: boolean) => any;
|
select: (value: SelectPool, formatRules: any) => any;
|
||||||
numberFormat: (value: number, formatOption: any, useMemorize: boolean) => string;
|
numberFormat: (value: number, formatOption: any) => string;
|
||||||
dateTimeFormat: (value: DatePool, formatOption: any, useMemorize: boolean) => string;
|
/**
|
||||||
|
* eg: { year: 'numeric', month: 'long', day: 'numeric' } 是一个用于指定DateTimeFormatter如何将日期对象转换为字符串的参数。
|
||||||
|
* \year: 'numeric' 表示年份的表示方式是数字形式(比如2023)。
|
||||||
|
* month: 'long' 表示月份的表示方式是全名(比如January)。
|
||||||
|
* day: 'numeric' 表示日期的表示方式是数字形式(比如1号)。
|
||||||
|
* @param value
|
||||||
|
* @param formatOption { year: 'numeric', month: 'long', day: 'numeric' }
|
||||||
|
*/
|
||||||
|
dateTimeFormat: (value: DatePool, formatOption: any) => string;
|
||||||
undefined: (value: any) => any;
|
undefined: (value: any) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ describe('I18n', () => {
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
messages: {
|
messages: {
|
||||||
en: messages,
|
en: messages,
|
||||||
fr:{}
|
fr: {},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -13,66 +13,63 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from 'react'
|
import * as React from 'react';
|
||||||
import {render} from '@testing-library/react'
|
import { render } from '@testing-library/react';
|
||||||
import {IntlProvider, useIntl} from "../../../index";
|
import { IntlProvider, useIntl } from '../../../index';
|
||||||
|
|
||||||
const FunctionComponent = ({spy}: { spy?: Function }) => {
|
const FunctionComponent = ({ spy }: { spy?: Function }) => {
|
||||||
const {i18n} = useIntl()
|
const { i18n } = useIntl();
|
||||||
spy!(i18n.locale)
|
spy!(i18n.locale);
|
||||||
return null
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
const FC = () => {
|
const FC = () => {
|
||||||
const i18n = useIntl()
|
const i18n = useIntl();
|
||||||
return i18n.formatNumber(10000, {style: 'currency', currency: 'USD'}) as any
|
return i18n.formatNumber(10000, { style: 'currency', currency: 'USD' }) as any;
|
||||||
}
|
};
|
||||||
|
|
||||||
describe('useIntl() hooks', () => {
|
describe('useIntl() hooks', () => {
|
||||||
it('throws when <IntlProvider> is missing from ancestry', () => {
|
it('throws when <IntlProvider> is missing from ancestry', () => {
|
||||||
// So it doesn't spam the console
|
// So it doesn't spam the console
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => {
|
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
})
|
expect(() => render(<FunctionComponent />)).toThrow('I18n object is not found!');
|
||||||
expect(() => render(<FunctionComponent/>)).toThrow(
|
});
|
||||||
'I18n object is not found!'
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('hooks onto the intl context', () => {
|
it('hooks onto the intl context', () => {
|
||||||
const spy = jest.fn()
|
const spy = jest.fn();
|
||||||
render(
|
render(
|
||||||
<IntlProvider locale="en">
|
<IntlProvider locale="en">
|
||||||
<FunctionComponent spy={spy}/>
|
<FunctionComponent spy={spy} />
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
)
|
);
|
||||||
expect(spy).toHaveBeenCalledWith('en')
|
expect(spy).toHaveBeenCalledWith('en');
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should work when switching locale on provider', () => {
|
it('should work when switching locale on provider', () => {
|
||||||
const {rerender, getByTestId} = render(
|
const { rerender, getByTestId } = render(
|
||||||
<IntlProvider locale="en">
|
<IntlProvider locale="en">
|
||||||
<span data-testid="comp">
|
<span data-testid="comp">
|
||||||
<FC/>
|
<FC />
|
||||||
</span>
|
</span>
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
)
|
);
|
||||||
expect(getByTestId('comp')).toMatchSnapshot()
|
expect(getByTestId('comp')).toMatchSnapshot();
|
||||||
rerender(
|
rerender(
|
||||||
<IntlProvider locale="es">
|
<IntlProvider locale="es">
|
||||||
<span data-testid="comp">
|
<span data-testid="comp">
|
||||||
<FC/>
|
<FC />
|
||||||
</span>
|
</span>
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
)
|
);
|
||||||
expect(getByTestId('comp')).toMatchSnapshot()
|
expect(getByTestId('comp')).toMatchSnapshot();
|
||||||
rerender(
|
rerender(
|
||||||
<IntlProvider locale="en">
|
<IntlProvider locale="en">
|
||||||
<span data-testid="comp">
|
<span data-testid="comp">
|
||||||
<FC/>
|
<FC />
|
||||||
</span>
|
</span>
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
)
|
);
|
||||||
|
|
||||||
expect(getByTestId('comp')).toMatchSnapshot()
|
expect(getByTestId('comp')).toMatchSnapshot();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Translation from '../../src/format/Translation';
|
import Translation from '../../src/format/Translation';
|
||||||
|
import {createIntlCache} from "../../index";
|
||||||
|
|
||||||
describe('Translation', () => {
|
describe('Translation', () => {
|
||||||
let translation;
|
let translation;
|
||||||
|
@ -23,8 +24,7 @@ describe('Translation', () => {
|
||||||
const locale = 'en';
|
const locale = 'en';
|
||||||
const locales = {};
|
const locales = {};
|
||||||
const localeConfig = {};
|
const localeConfig = {};
|
||||||
const useMemorize = true;
|
translation = new Translation(compiledMessage, locale, locales, localeConfig, createIntlCache());
|
||||||
translation = new Translation(compiledMessage, locale, locales, localeConfig, useMemorize);
|
|
||||||
});
|
});
|
||||||
describe('formatMessage', () => {
|
describe('formatMessage', () => {
|
||||||
it('should return the message if it is not an array', () => {
|
it('should return the message if it is not an array', () => {
|
||||||
|
|
|
@ -21,7 +21,6 @@ describe('creatI18nCache', () => {
|
||||||
expect(intlCache).toEqual({
|
expect(intlCache).toEqual({
|
||||||
dateTimeFormat: {},
|
dateTimeFormat: {},
|
||||||
numberFormat: {},
|
numberFormat: {},
|
||||||
messages: {},
|
|
||||||
plurals: {},
|
plurals: {},
|
||||||
select: {},
|
select: {},
|
||||||
octothorpe: {},
|
octothorpe: {},
|
||||||
|
|
|
@ -43,7 +43,6 @@ describe('compile', function () {
|
||||||
|
|
||||||
it('should compile message with variable', function () {
|
it('should compile message with variable', function () {
|
||||||
const cache = utils.compile('Hey {name}!');
|
const cache = utils.compile('Hey {name}!');
|
||||||
console.log(cache)
|
|
||||||
expect(new Translation(cache, 'en', [], {}).translate({})).toEqual('Hey {name}!');
|
expect(new Translation(cache, 'en', [], {}).translate({})).toEqual('Hey {name}!');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -58,7 +57,6 @@ describe('compile', function () {
|
||||||
expect(translate({ value: 1 })).toEqual('1 Book');
|
expect(translate({ value: 1 })).toEqual('1 Book');
|
||||||
expect(translate({ value: 2 })).toEqual('2 Books');
|
expect(translate({ value: 2 })).toEqual('2 Books');
|
||||||
|
|
||||||
|
|
||||||
const translatePlurals = prepare('{value, plural, offset:1 =0 {No Books} one {# Book} other {# Books}}');
|
const translatePlurals = prepare('{value, plural, offset:1 =0 {No Books} one {# Book} other {# Books}}');
|
||||||
|
|
||||||
expect(translatePlurals({ value: 0 })).toEqual('No Books');
|
expect(translatePlurals({ value: 0 })).toEqual('No Books');
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DateTimeFormatter } from '../../../index';
|
import { DateTimeFormatter } from '../../../index';
|
||||||
|
import creatI18nCache from "../../../src/format/cache/cache";
|
||||||
|
|
||||||
describe('DateTimeFormatter', () => {
|
describe('DateTimeFormatter', () => {
|
||||||
const date = new Date('2023-04-03T12:34:56Z');
|
const date = new Date('2023-04-03T12:34:56Z');
|
||||||
|
@ -25,7 +26,7 @@ describe('DateTimeFormatter', () => {
|
||||||
const firstRunResult = firstRunt1 - firstRunt0;
|
const firstRunResult = firstRunt1 - firstRunt0;
|
||||||
|
|
||||||
const seconddRunt0 = performance.now();
|
const seconddRunt0 = performance.now();
|
||||||
const dateTimeFormatter2 = new DateTimeFormatter('es', {}, false);
|
const dateTimeFormatter2 = new DateTimeFormatter('es', {});
|
||||||
dateTimeFormatter2.dateTimeFormat(new Date());
|
dateTimeFormatter2.dateTimeFormat(new Date());
|
||||||
const seconddRunt1 = performance.now();
|
const seconddRunt1 = performance.now();
|
||||||
const secondRunResult = seconddRunt1 - seconddRunt0;
|
const secondRunResult = seconddRunt1 - seconddRunt0;
|
||||||
|
@ -62,8 +63,8 @@ describe('DateTimeFormatter', () => {
|
||||||
|
|
||||||
it('should not memoize formatter instances when memoize is false', () => {
|
it('should not memoize formatter instances when memoize is false', () => {
|
||||||
const spy = jest.spyOn(Intl, 'DateTimeFormat');
|
const spy = jest.spyOn(Intl, 'DateTimeFormat');
|
||||||
const formatter1 = new DateTimeFormatter('en-US', { month: 'short' }, false);
|
const formatter1 = new DateTimeFormatter('en-US', { month: 'short' });
|
||||||
const formatter2 = new DateTimeFormatter('en-US', { month: 'short' }, false);
|
const formatter2 = new DateTimeFormatter('en-US', { month: 'short' });
|
||||||
formatter1.dateTimeFormat(date);
|
formatter1.dateTimeFormat(date);
|
||||||
formatter2.dateTimeFormat(date);
|
formatter2.dateTimeFormat(date);
|
||||||
expect(spy).toHaveBeenCalledTimes(5);
|
expect(spy).toHaveBeenCalledTimes(5);
|
||||||
|
@ -91,7 +92,7 @@ describe('DateTimeFormatter', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should format using memorized formatter when useMemorize is true', () => {
|
it('should format using memorized formatter when useMemorize is true', () => {
|
||||||
const formatter = new DateTimeFormatter('en-US',{"year":'numeric'}, true);
|
const formatter = new DateTimeFormatter('en-US',{"year":'numeric'}, creatI18nCache());
|
||||||
const date = new Date(2023, 0, 1);
|
const date = new Date(2023, 0, 1);
|
||||||
const formatted1 = formatter.dateTimeFormat(date);
|
const formatted1 = formatter.dateTimeFormat(date);
|
||||||
const formatted2 = formatter.dateTimeFormat(date);
|
const formatted2 = formatter.dateTimeFormat(date);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { NumberFormatter } from '../../../index';
|
import { NumberFormatter } from '../../../index';
|
||||||
|
import creatI18nCache from "../../../src/format/cache/cache";
|
||||||
|
|
||||||
describe('NumberFormatter', () => {
|
describe('NumberFormatter', () => {
|
||||||
it('number formatter is memoized', async () => {
|
it('number formatter is memoized', async () => {
|
||||||
|
@ -24,7 +25,7 @@ describe('NumberFormatter', () => {
|
||||||
const firstRunResult = firstRunt1 - firstRunt0;
|
const firstRunResult = firstRunt1 - firstRunt0;
|
||||||
|
|
||||||
const seconddRunt0 = performance.now();
|
const seconddRunt0 = performance.now();
|
||||||
const numberFormatter = new NumberFormatter('es', {}, false);
|
const numberFormatter = new NumberFormatter('es', {});
|
||||||
numberFormatter.numberFormat(10000);
|
numberFormatter.numberFormat(10000);
|
||||||
const secondRunt1 = performance.now();
|
const secondRunt1 = performance.now();
|
||||||
const secondRunResult = secondRunt1 - seconddRunt0;
|
const secondRunResult = secondRunt1 - seconddRunt0;
|
||||||
|
@ -82,7 +83,7 @@ describe('NumberFormatter', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should format using memorized formatter when useMemorize is true', () => {
|
it('should format using memorized formatter when useMemorize is true', () => {
|
||||||
const formatter = new NumberFormatter('en-US', undefined, true);
|
const formatter = new NumberFormatter('en-US', undefined, creatI18nCache());
|
||||||
const number = 12345.6789;
|
const number = 12345.6789;
|
||||||
const formatted1 = formatter.numberFormat(number);
|
const formatted1 = formatter.numberFormat(number);
|
||||||
const formatted2 = formatter.numberFormat(number);
|
const formatted2 = formatter.numberFormat(number);
|
||||||
|
@ -90,7 +91,7 @@ describe('NumberFormatter', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a new formatter when useMemorize is false', () => {
|
it('should create a new formatter when useMemorize is false', () => {
|
||||||
const formatter = new NumberFormatter('en-US', undefined, false);
|
const formatter = new NumberFormatter('en-US', undefined);
|
||||||
const number = 12345.6789;
|
const number = 12345.6789;
|
||||||
const formatted1 = formatter.numberFormat(number);
|
const formatted1 = formatter.numberFormat(number);
|
||||||
const formatted2 = formatter.numberFormat(number);
|
const formatted2 = formatter.numberFormat(number);
|
||||||
|
|
|
@ -61,7 +61,7 @@ describe('ruleUtils test', () => {
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
ruleUtils.getReg(input);
|
ruleUtils.getReg(input);
|
||||||
}).toThrowError('Signs Prohibited');
|
}).toThrowError('prohibition sign');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when input regular expression object has forbidden flags', () => {
|
it('should throw an error when input regular expression object has forbidden flags', () => {
|
||||||
|
|
Loading…
Reference in New Issue