diff --git a/src/runtime/stores/formatters.ts b/src/runtime/stores/formatters.ts index d580527..55957f2 100644 --- a/src/runtime/stores/formatters.ts +++ b/src/runtime/stores/formatters.ts @@ -67,7 +67,15 @@ const formatMessage: MessageFormatter = (id, options = {}) => { return message; } - return getMessageFormatter(message, locale).format(values) as string; + let result = message; + + try { + result = getMessageFormatter(message, locale).format(values) as string; + } catch (e) { + console.warn(`[svelte-i18n] Message "${id}" has syntax error:`, e.message); + } + + return result; }; const formatTime: TimeFormatter = (t, options) => { @@ -82,7 +90,10 @@ const formatNumber: NumberFormatter = (n, options) => { return getNumberFormatter(options).format(n); }; -const getJSON: JSONGetter = (id: string, locale = getCurrentLocale()) => { +const getJSON: JSONGetter = ( + id: string, + locale = getCurrentLocale(), +) => { return lookup(id, locale) as T; }; diff --git a/test/fixtures/en.json b/test/fixtures/en.json index 62186de..c42357f 100644 --- a/test/fixtures/en.json +++ b/test/fixtures/en.json @@ -5,5 +5,6 @@ }, "photos": "You have {n, plural, =0 {no photos.} =1 {one photo.} other {# photos.}}", "title": "Page title", - "sneakers": "sneakers" + "sneakers": "sneakers", + "with-syntax-error": "Hello {{name}}!" } diff --git a/test/runtime/stores/formatters.test.ts b/test/runtime/stores/formatters.test.ts index d21adb9..7dfbfb2 100644 --- a/test/runtime/stores/formatters.test.ts +++ b/test/runtime/stores/formatters.test.ts @@ -106,30 +106,43 @@ describe('format message', () => { }); it('errors out when value found is not string', () => { - const { warn } = global.console; - - jest.spyOn(global.console, 'warn').mockImplementation(); + const spy = jest.spyOn(global.console, 'warn').mockImplementation(); expect(typeof formatMessage('form')).toBe('object'); - expect(console.warn).toBeCalledWith( + expect(spy).toBeCalledWith( `[svelte-i18n] Message with id "form" must be of type "string", found: "object". Gettin its value through the "$format" method is deprecated; use the "json" method instead.`, ); - global.console.warn = warn; + spy.mockRestore(); }); it('warn on missing messages', () => { - const { warn } = global.console; - - jest.spyOn(global.console, 'warn').mockImplementation(); + const spy = jest.spyOn(global.console, 'warn').mockImplementation(); formatMessage('missing'); - expect(console.warn).toBeCalledWith( + expect(spy).toBeCalledWith( `[svelte-i18n] The message "missing" was not found in "en".`, ); - global.console.warn = warn; + spy.mockRestore(); + }); + + it('does not throw with invalid syntax', () => { + $locale.set('en'); + const spy = jest.spyOn(global.console, 'warn').mockImplementation(); + + // eslint-disable-next-line line-comment-position + formatMessage('with-syntax-error', { values: { name: 'John' } }); + + expect(spy).toHaveBeenCalledWith( + expect.stringContaining( + `[svelte-i18n] Message "with-syntax-error" has syntax error:`, + ), + expect.anything(), + ); + + spy.mockRestore(); }); });