diff --git a/src/runtime/modules/formatters.ts b/src/runtime/modules/formatters.ts index fc3f150..7c1d02c 100644 --- a/src/runtime/modules/formatters.ts +++ b/src/runtime/modules/formatters.ts @@ -29,6 +29,16 @@ type MemoizedDateTimeFormatterFactoryOptional = MemoizedIntlFormatterOptional< Intl.DateTimeFormatOptions >; +type MemoizedMessageFormatterFactory = (options: { + message: string; + locale: string; +}) => IntlMessageFormat; + +type MemoizedMessageFormatterFactoryOptional = ( + message: string, + locale?: string, +) => IntlMessageFormat; + const getIntlFormatterOptions = ( type: 'time' | 'number' | 'date', name: string, @@ -90,6 +100,13 @@ const createTimeFormatter: MemoizedDateTimeFormatterFactory = monadicMemoize( }, ); +const createMessageFormatter: MemoizedMessageFormatterFactory = monadicMemoize( + ({ message, locale }) => + new IntlMessageFormat(message, locale, getOptions().formats, { + ignoreTag: getOptions().ignoreTag, + }), +); + export const getNumberFormatter: MemoizedNumberFormatterFactoryOptional = ({ locale = getCurrentLocale(), ...args @@ -105,10 +122,8 @@ export const getTimeFormatter: MemoizedDateTimeFormatterFactoryOptional = ({ ...args } = {}) => createTimeFormatter({ locale, ...args }); -export const getMessageFormatter = monadicMemoize( +export const getMessageFormatter: MemoizedMessageFormatterFactoryOptional = ( + message, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - (message: string, locale: string = getCurrentLocale()!) => - new IntlMessageFormat(message, locale, getOptions().formats, { - ignoreTag: getOptions().ignoreTag, - }), -); + locale = getCurrentLocale()!, +) => createMessageFormatter({ message, locale }); diff --git a/src/runtime/modules/memoize.ts b/src/runtime/modules/memoize.ts index 12398af..9f4ab0c 100644 --- a/src/runtime/modules/memoize.ts +++ b/src/runtime/modules/memoize.ts @@ -1,9 +1,11 @@ -// eslint-disable-next-line @typescript-eslint/ban-types -type MemoizedFunction = (fn: F) => F; +type MemoizedFunction = (arg: T) => R; -const monadicMemoize: MemoizedFunction = (fn) => { +const monadicMemoize = ( + fn: MemoizedFunction, +): MemoizedFunction => { const cache = Object.create(null); - const memoizedFn: any = (arg: unknown) => { + + return (arg) => { const cacheKey = JSON.stringify(arg); if (cacheKey in cache) { @@ -12,8 +14,6 @@ const monadicMemoize: MemoizedFunction = (fn) => { return (cache[cacheKey] = fn(arg)); }; - - return memoizedFn; }; export { monadicMemoize }; diff --git a/test/runtime/modules/formatters.test.ts b/test/runtime/modules/formatters.test.ts index e37966d..88898a9 100644 --- a/test/runtime/modules/formatters.test.ts +++ b/test/runtime/modules/formatters.test.ts @@ -210,4 +210,34 @@ describe('message formatter', () => { }), ).toBe('Page: 2/10'); }); + + it('formats a message with interpolated number according to the provided locale', () => { + expect( + getMessageFormatter('{count, number} pages', 'en').format({ + count: 10_000, + }), + ).toBe('10,000 pages'); + + expect( + getMessageFormatter('{count, number} pages', 'nl').format({ + count: 10_000, + }), + ).toBe('10.000 pages'); + }); + + it('formats a message with interpolated number according to the currently set locale', () => { + locale.set('en'); + expect( + getMessageFormatter('{count, number} pages').format({ + count: 10_000, + }), + ).toBe('10,000 pages'); + + locale.set('nl'); + expect( + getMessageFormatter('{count, number} pages').format({ + count: 10_000, + }), + ).toBe('10.000 pages'); + }); });