mirror of
https://github.com/cupcakearmy/svelte-i18n.git
synced 2024-11-16 18:10:43 +01:00
feat: introduce handleMissingMessage (#175)
* feat: introduce onMissingMessageHandler * Update src/runtime/types/index.ts Co-authored-by: Christian Kaisermann <christian@kaisermann.me> * Update src/runtime/configs.ts Co-authored-by: Christian Kaisermann <christian@kaisermann.me> * Update src/runtime/types/index.ts Co-authored-by: Christian Kaisermann <christian@kaisermann.me> * Update src/runtime/stores/formatters.ts Co-authored-by: Christian Kaisermann <christian@kaisermann.me> * Update test/runtime/stores/formatters.test.ts Co-authored-by: Christian Kaisermann <christian@kaisermann.me> * Update test/runtime/stores/formatters.test.ts Co-authored-by: Christian Kaisermann <christian@kaisermann.me> * rename to handleMissingKey and optionally use return as default value * rename also in the defaultOptions * test for optional default result from handleMissingKey Co-authored-by: Christian Kaisermann <christian@kaisermann.me>
This commit is contained in:
parent
9467cfb78b
commit
a8b5df0442
@ -26,27 +26,41 @@ Method responsible for configuring some of the library behaviours such as the gl
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
interface InitOptions {
|
interface InitOptions {
|
||||||
// the global fallback locale
|
/** The global fallback locale **/
|
||||||
fallbackLocale: string
|
fallbackLocale: string;
|
||||||
// the app initial locale
|
/** The app initial locale **/
|
||||||
initialLocale?: string
|
initialLocale?: string | null;
|
||||||
// custom time/date/number formats
|
/** Custom time/date/number formats **/
|
||||||
formats?: Formats
|
formats?: Formats;
|
||||||
// loading delay interval
|
/** Loading delay interval **/
|
||||||
loadingDelay?: number
|
loadingDelay?: number;
|
||||||
|
/**
|
||||||
|
* @deprecated Use `handleMissingMessage` instead.
|
||||||
|
* */
|
||||||
|
warnOnMissingMessages?: boolean;
|
||||||
|
/**
|
||||||
|
* Optional method that is executed whenever a message is missing.
|
||||||
|
* It may return a string to use as the fallback.
|
||||||
|
*/
|
||||||
|
handleMissingMessage?: MissingKeyHandler;
|
||||||
|
/**
|
||||||
|
* Whether to treat HTML/XML tags as string literal instead of parsing them as tag token.
|
||||||
|
* When this is false we only allow simple tags without any attributes
|
||||||
|
* */
|
||||||
|
ignoreTag: boolean;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Example**:
|
**Example**:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init } from 'svelte-i18n'
|
import { init } from 'svelte-i18n';
|
||||||
|
|
||||||
init({
|
init({
|
||||||
// fallback to en if current locale is not in the dictionary
|
// fallback to en if current locale is not in the dictionary
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
initialLocale: 'pt-br',
|
initialLocale: 'pt-br',
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Custom formats
|
##### Custom formats
|
||||||
@ -55,9 +69,9 @@ It's possible to define custom format styles via the `formats` property if you w
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
interface Formats {
|
interface Formats {
|
||||||
number: Record<string, Intl.NumberFormatOptions>
|
number: Record<string, Intl.NumberFormatOptions>;
|
||||||
date: Record<string, Intl.DateTimeFormatOptions>
|
date: Record<string, Intl.DateTimeFormatOptions>;
|
||||||
time: Record<string, Intl.DateTimeFormatOptions>
|
time: Record<string, Intl.DateTimeFormatOptions>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -66,7 +80,7 @@ Please refer to the [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs
|
|||||||
**Example**:
|
**Example**:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init } from 'svelte-i18n'
|
import { init } from 'svelte-i18n';
|
||||||
|
|
||||||
init({
|
init({
|
||||||
// fallback to en if current locale is not in the dictionary
|
// fallback to en if current locale is not in the dictionary
|
||||||
@ -76,13 +90,11 @@ init({
|
|||||||
EUR: { style: 'currency', currency: 'EUR' },
|
EUR: { style: 'currency', currency: 'EUR' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div>
|
<div>{$_.number(123456.789, { format: 'EUR' })}</div>
|
||||||
{$_.number(123456.789, { format: 'EUR' })}
|
|
||||||
</div>
|
|
||||||
<!-- 123.456,79 € -->
|
<!-- 123.456,79 € -->
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -96,13 +108,13 @@ Utility method to help getting a initial locale based on a pattern of the curren
|
|||||||
**Example**:
|
**Example**:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init, getLocaleFromHostname } from 'svelte-i18n'
|
import { init, getLocaleFromHostname } from 'svelte-i18n';
|
||||||
|
|
||||||
init({
|
init({
|
||||||
// fallback to en if current locale is not in the dictionary
|
// fallback to en if current locale is not in the dictionary
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
initialLocale: getLocaleFromHostname(/^(.*?)\./),
|
initialLocale: getLocaleFromHostname(/^(.*?)\./),
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `getLocaleFromPathname`
|
#### `getLocaleFromPathname`
|
||||||
@ -116,13 +128,13 @@ Utility method to help getting a initial locale based on a pattern of the curren
|
|||||||
**Example**:
|
**Example**:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init, getLocaleFromPathname } from 'svelte-i18n'
|
import { init, getLocaleFromPathname } from 'svelte-i18n';
|
||||||
|
|
||||||
init({
|
init({
|
||||||
// fallback to en if current locale is not in the dictionary
|
// fallback to en if current locale is not in the dictionary
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
initialLocale: getLocaleFromPathname(/^\/(.*?)\//),
|
initialLocale: getLocaleFromPathname(/^\/(.*?)\//),
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `getLocaleFromNavigator`
|
#### `getLocaleFromNavigator`
|
||||||
@ -136,13 +148,13 @@ Utility method to help getting a initial locale based on the browser's `navigato
|
|||||||
**Example**:
|
**Example**:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init, getLocaleFromNavigator } from 'svelte-i18n'
|
import { init, getLocaleFromNavigator } from 'svelte-i18n';
|
||||||
|
|
||||||
init({
|
init({
|
||||||
// fallback to en if current locale is not in the dictionary
|
// fallback to en if current locale is not in the dictionary
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
initialLocale: getLocaleFromNavigator(),
|
initialLocale: getLocaleFromNavigator(),
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `getLocaleFromQueryString`
|
#### `getLocaleFromQueryString`
|
||||||
@ -154,13 +166,13 @@ init({
|
|||||||
Utility method to help getting a initial locale based on a query string value.
|
Utility method to help getting a initial locale based on a query string value.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init, getLocaleFromQueryString } from 'svelte-i18n'
|
import { init, getLocaleFromQueryString } from 'svelte-i18n';
|
||||||
|
|
||||||
init({
|
init({
|
||||||
// fallback to en if current locale is not in the dictionary
|
// fallback to en if current locale is not in the dictionary
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
initialLocale: getLocaleFromQueryString('lang'),
|
initialLocale: getLocaleFromQueryString('lang'),
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `getLocaleFromHash`
|
#### `getLocaleFromHash`
|
||||||
@ -174,13 +186,13 @@ Utility method to help getting a initial locale based on a hash `{key}={value}`
|
|||||||
**Example**:
|
**Example**:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init, getLocaleFromHash } from 'svelte-i18n'
|
import { init, getLocaleFromHash } from 'svelte-i18n';
|
||||||
|
|
||||||
init({
|
init({
|
||||||
// fallback to en if current locale is not in the dictionary
|
// fallback to en if current locale is not in the dictionary
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
initialLocale: getLocaleFromHash('lang'),
|
initialLocale: getLocaleFromHash('lang'),
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `addMessages`
|
#### `addMessages`
|
||||||
@ -224,10 +236,10 @@ Registers an async message `loader` for the specified `locale`. The loader queue
|
|||||||
**Example**:
|
**Example**:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { register } from 'svelte-i18n'
|
import { register } from 'svelte-i18n';
|
||||||
|
|
||||||
register('en', () => import('./_locales/en.json'))
|
register('en', () => import('./_locales/en.json'));
|
||||||
register('pt', () => import('./_locales/pt.json'))
|
register('pt', () => import('./_locales/pt.json'));
|
||||||
```
|
```
|
||||||
|
|
||||||
See [how to asynchronously load dictionaries](/svelte-i18n/blob/master/docs#22-asynchronous).
|
See [how to asynchronously load dictionaries](/svelte-i18n/blob/master/docs#22-asynchronous).
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import type { ConfigureOptions, ConfigureOptionsInit } from './types';
|
import type {
|
||||||
import { $locale } from './stores/locale';
|
ConfigureOptions,
|
||||||
|
ConfigureOptionsInit,
|
||||||
|
MissingKeyHandlerInput,
|
||||||
|
} from './types';
|
||||||
|
import { $locale, getCurrentLocale, getPossibleLocales } from './stores/locale';
|
||||||
|
import { hasLocaleQueue } from './includes/loaderQueue';
|
||||||
|
|
||||||
interface Formats {
|
interface Formats {
|
||||||
number: Record<string, any>;
|
number: Record<string, any>;
|
||||||
@ -38,11 +43,28 @@ export const defaultFormats: Formats = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default missing key handler used in case "warnOnMissingMessages" is set to true.
|
||||||
|
*/
|
||||||
|
function defaultMissingKeyHandler({ locale, id }: MissingKeyHandlerInput) {
|
||||||
|
// istanbul ignore next
|
||||||
|
console.warn(
|
||||||
|
`[svelte-i18n] The message "${id}" was not found in "${getPossibleLocales(
|
||||||
|
locale,
|
||||||
|
).join('", "')}".${
|
||||||
|
hasLocaleQueue(getCurrentLocale())
|
||||||
|
? `\n\nNote: there are at least one loader still registered to this locale that wasn't executed.`
|
||||||
|
: ''
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export const defaultOptions: ConfigureOptions = {
|
export const defaultOptions: ConfigureOptions = {
|
||||||
fallbackLocale: null as any,
|
fallbackLocale: null as any,
|
||||||
loadingDelay: 200,
|
loadingDelay: 200,
|
||||||
formats: defaultFormats,
|
formats: defaultFormats,
|
||||||
warnOnMissingMessages: true,
|
warnOnMissingMessages: true,
|
||||||
|
handleMissingMessage: undefined,
|
||||||
ignoreTag: true,
|
ignoreTag: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,6 +79,18 @@ export function init(opts: ConfigureOptionsInit) {
|
|||||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
||||||
const initialLocale = opts.initialLocale || opts.fallbackLocale;
|
const initialLocale = opts.initialLocale || opts.fallbackLocale;
|
||||||
|
|
||||||
|
if (rest.warnOnMissingMessages) {
|
||||||
|
delete rest.warnOnMissingMessages;
|
||||||
|
|
||||||
|
if (rest.handleMissingMessage == null) {
|
||||||
|
rest.handleMissingMessage = defaultMissingKeyHandler;
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
'[svelte-i18n] The "warnOnMissingMessages" option is deprecated. Please use the "handleMissingMessage" option instead.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Object.assign(options, rest, { initialLocale });
|
Object.assign(options, rest, { initialLocale });
|
||||||
|
|
||||||
if (formats) {
|
if (formats) {
|
||||||
|
@ -9,7 +9,6 @@ import type {
|
|||||||
JSONGetter,
|
JSONGetter,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { lookup } from '../includes/lookup';
|
import { lookup } from '../includes/lookup';
|
||||||
import { hasLocaleQueue } from '../includes/loaderQueue';
|
|
||||||
import {
|
import {
|
||||||
getMessageFormatter,
|
getMessageFormatter,
|
||||||
getTimeFormatter,
|
getTimeFormatter,
|
||||||
@ -18,7 +17,7 @@ import {
|
|||||||
} from '../includes/formatters';
|
} from '../includes/formatters';
|
||||||
import { getOptions } from '../configs';
|
import { getOptions } from '../configs';
|
||||||
import { $dictionary } from './dictionary';
|
import { $dictionary } from './dictionary';
|
||||||
import { getCurrentLocale, getPossibleLocales, $locale } from './locale';
|
import { getCurrentLocale, $locale } from './locale';
|
||||||
|
|
||||||
const formatMessage: MessageFormatter = (id, options = {}) => {
|
const formatMessage: MessageFormatter = (id, options = {}) => {
|
||||||
let messageObj = options as MessageObject;
|
let messageObj = options as MessageObject;
|
||||||
@ -43,20 +42,10 @@ const formatMessage: MessageFormatter = (id, options = {}) => {
|
|||||||
let message = lookup(id, locale);
|
let message = lookup(id, locale);
|
||||||
|
|
||||||
if (!message) {
|
if (!message) {
|
||||||
if (getOptions().warnOnMissingMessages) {
|
message =
|
||||||
// istanbul ignore next
|
getOptions().handleMissingMessage?.({ locale, id, defaultValue }) ??
|
||||||
console.warn(
|
defaultValue ??
|
||||||
`[svelte-i18n] The message "${id}" was not found in "${getPossibleLocales(
|
id;
|
||||||
locale,
|
|
||||||
).join('", "')}".${
|
|
||||||
hasLocaleQueue(getCurrentLocale())
|
|
||||||
? `\n\nNote: there are at least one loader still registered to this locale that wasn't executed.`
|
|
||||||
: ''
|
|
||||||
}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
message = defaultValue ?? id;
|
|
||||||
} else if (typeof message !== 'string') {
|
} else if (typeof message !== 'string') {
|
||||||
console.warn(
|
console.warn(
|
||||||
`[svelte-i18n] Message with id "${id}" must be of type "string", found: "${typeof message}". Gettin its value through the "$format" method is deprecated; use the "json" method instead.`,
|
`[svelte-i18n] Message with id "${id}" must be of type "string", found: "${typeof message}". Gettin its value through the "$format" method is deprecated; use the "json" method instead.`,
|
||||||
|
@ -72,12 +72,40 @@ export interface MessagesLoader {
|
|||||||
(): Promise<any>;
|
(): Promise<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type MissingKeyHandlerInput = {
|
||||||
|
locale: string;
|
||||||
|
id: string;
|
||||||
|
defaultValue: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MissingKeyHandlerOutput = string | void | undefined;
|
||||||
|
|
||||||
|
export type MissingKeyHandler = (
|
||||||
|
input: MissingKeyHandlerInput,
|
||||||
|
) => MissingKeyHandlerOutput;
|
||||||
|
|
||||||
export interface ConfigureOptions {
|
export interface ConfigureOptions {
|
||||||
|
/** The global fallback locale * */
|
||||||
fallbackLocale: string;
|
fallbackLocale: string;
|
||||||
|
/** The app initial locale * */
|
||||||
initialLocale?: string | null;
|
initialLocale?: string | null;
|
||||||
|
/** Custom time/date/number formats * */
|
||||||
formats: Formats;
|
formats: Formats;
|
||||||
|
/** Loading delay interval * */
|
||||||
loadingDelay: number;
|
loadingDelay: number;
|
||||||
warnOnMissingMessages: boolean;
|
/**
|
||||||
|
* @deprecated Use `handleMissingMessage` instead.
|
||||||
|
* */
|
||||||
|
warnOnMissingMessages?: boolean;
|
||||||
|
/**
|
||||||
|
* Optional method that is executed whenever a message is missing.
|
||||||
|
* It may return a string to use as the fallback.
|
||||||
|
*/
|
||||||
|
handleMissingMessage?: MissingKeyHandler;
|
||||||
|
/**
|
||||||
|
* Whether to treat HTML/XML tags as string literal instead of parsing them as tag token.
|
||||||
|
* When this is false we only allow simple tags without any attributes
|
||||||
|
* */
|
||||||
ignoreTag: boolean;
|
ignoreTag: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
/* eslint-disable node/global-require */
|
/* eslint-disable node/global-require */
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
import {
|
import { init, getOptions, defaultFormats } from '../../src/runtime/configs';
|
||||||
init,
|
|
||||||
getOptions,
|
|
||||||
defaultOptions,
|
|
||||||
defaultFormats,
|
|
||||||
} from '../../src/runtime/configs';
|
|
||||||
import { $locale } from '../../src/runtime/stores/locale';
|
import { $locale } from '../../src/runtime/stores/locale';
|
||||||
|
|
||||||
|
const warnSpy = jest.spyOn(global.console, 'warn').mockImplementation();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
init(defaultOptions as any);
|
warnSpy.mockReset();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('inits the fallback locale', () => {
|
test('inits the fallback locale', () => {
|
||||||
expect(getOptions().fallbackLocale).toBeNull();
|
expect(getOptions().fallbackLocale).toBeNull();
|
||||||
|
|
||||||
init({
|
init({
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
});
|
});
|
||||||
@ -45,3 +43,20 @@ test('sets the minimum delay to set the loading store value', () => {
|
|||||||
init({ fallbackLocale: 'en', loadingDelay: 300 });
|
init({ fallbackLocale: 'en', loadingDelay: 300 });
|
||||||
expect(getOptions().loadingDelay).toBe(300);
|
expect(getOptions().loadingDelay).toBe(300);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('defines default missing key handler if "warnOnMissingMessages" is "true"', () => {
|
||||||
|
init({ fallbackLocale: 'en', warnOnMissingMessages: true });
|
||||||
|
expect(typeof getOptions().handleMissingMessage).toBe('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('warns about using deprecated "warnOnMissingMessages" alongside "handleMissingMessage"', () => {
|
||||||
|
init({
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
warnOnMissingMessages: true,
|
||||||
|
handleMissingMessage() {},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(warnSpy).toHaveBeenCalledWith(
|
||||||
|
'[svelte-i18n] The "warnOnMissingMessages" option is deprecated. Please use the "handleMissingMessage" option instead.',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
@ -7,6 +7,7 @@ import type {
|
|||||||
TimeFormatter,
|
TimeFormatter,
|
||||||
DateFormatter,
|
DateFormatter,
|
||||||
NumberFormatter,
|
NumberFormatter,
|
||||||
|
MissingKeyHandler,
|
||||||
} from '../../../src/runtime/types/index';
|
} from '../../../src/runtime/types/index';
|
||||||
import {
|
import {
|
||||||
$format,
|
$format,
|
||||||
@ -39,12 +40,10 @@ addMessages('pt', require('../../fixtures/pt.json'));
|
|||||||
addMessages('pt-BR', require('../../fixtures/pt-BR.json'));
|
addMessages('pt-BR', require('../../fixtures/pt-BR.json'));
|
||||||
addMessages('pt-PT', require('../../fixtures/pt-PT.json'));
|
addMessages('pt-PT', require('../../fixtures/pt-PT.json'));
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
init({ fallbackLocale: 'en' });
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('format message', () => {
|
describe('format message', () => {
|
||||||
it('formats a message by its id and the current locale', () => {
|
it('formats a message by its id and the current locale', () => {
|
||||||
|
init({ fallbackLocale: 'en' });
|
||||||
|
|
||||||
expect(formatMessage({ id: 'form.field_1_name' })).toBe('Name');
|
expect(formatMessage({ id: 'form.field_1_name' })).toBe('Name');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -55,6 +54,8 @@ describe('format message', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('formats a message with interpolated values', () => {
|
it('formats a message with interpolated values', () => {
|
||||||
|
init({ fallbackLocale: 'en' });
|
||||||
|
|
||||||
expect(formatMessage({ id: 'photos', values: { n: 0 } })).toBe(
|
expect(formatMessage({ id: 'photos', values: { n: 0 } })).toBe(
|
||||||
'You have no photos.',
|
'You have no photos.',
|
||||||
);
|
);
|
||||||
@ -67,6 +68,8 @@ describe('format message', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('formats the default value with interpolated values', () => {
|
it('formats the default value with interpolated values', () => {
|
||||||
|
init({ fallbackLocale: 'en' });
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
formatMessage({
|
formatMessage({
|
||||||
id: 'non-existent',
|
id: 'non-existent',
|
||||||
@ -77,6 +80,8 @@ describe('format message', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('formats the key with interpolated values', () => {
|
it('formats the key with interpolated values', () => {
|
||||||
|
init({ fallbackLocale: 'en' });
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
formatMessage({
|
formatMessage({
|
||||||
id: '{food}',
|
id: '{food}',
|
||||||
@ -86,27 +91,38 @@ describe('format message', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('accepts a message id as first argument', () => {
|
it('accepts a message id as first argument', () => {
|
||||||
|
init({ fallbackLocale: 'en' });
|
||||||
|
|
||||||
expect(formatMessage('form.field_1_name')).toBe('Name');
|
expect(formatMessage('form.field_1_name')).toBe('Name');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts a message id as first argument and formatting options as second', () => {
|
it('accepts a message id as first argument and formatting options as second', () => {
|
||||||
|
init({ fallbackLocale: 'en' });
|
||||||
|
|
||||||
expect(formatMessage('form.field_1_name', { locale: 'pt' })).toBe('Nome');
|
expect(formatMessage('form.field_1_name', { locale: 'pt' })).toBe('Nome');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if no locale is set', () => {
|
it('throws if no locale is set', () => {
|
||||||
|
init({ fallbackLocale: 'en' });
|
||||||
|
|
||||||
$locale.set(null);
|
$locale.set(null);
|
||||||
|
|
||||||
expect(() => formatMessage('form.field_1_name')).toThrow(
|
expect(() => formatMessage('form.field_1_name')).toThrow(
|
||||||
'[svelte-i18n] Cannot format a message without first setting the initial locale.',
|
'[svelte-i18n] Cannot format a message without first setting the initial locale.',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses a missing message default value', () => {
|
it('uses a missing message default value', () => {
|
||||||
|
init({ fallbackLocale: 'en' });
|
||||||
|
|
||||||
expect(formatMessage('missing', { default: 'Missing Default' })).toBe(
|
expect(formatMessage('missing', { default: 'Missing Default' })).toBe(
|
||||||
'Missing Default',
|
'Missing Default',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('errors out when value found is not string', () => {
|
it('errors out when value found is not string', () => {
|
||||||
|
init({ fallbackLocale: 'en' });
|
||||||
|
|
||||||
const spy = jest.spyOn(global.console, 'warn').mockImplementation();
|
const spy = jest.spyOn(global.console, 'warn').mockImplementation();
|
||||||
|
|
||||||
expect(typeof formatMessage('form')).toBe('object');
|
expect(typeof formatMessage('form')).toBe('object');
|
||||||
@ -117,7 +133,12 @@ describe('format message', () => {
|
|||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('warn on missing messages', () => {
|
it('warn on missing messages if "warnOnMissingMessages" is true', () => {
|
||||||
|
init({
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
warnOnMissingMessages: true,
|
||||||
|
});
|
||||||
|
|
||||||
const spy = jest.spyOn(global.console, 'warn').mockImplementation();
|
const spy = jest.spyOn(global.console, 'warn').mockImplementation();
|
||||||
|
|
||||||
formatMessage('missing');
|
formatMessage('missing');
|
||||||
@ -129,7 +150,18 @@ describe('format message', () => {
|
|||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('uses result of handleMissingMessage handler', () => {
|
||||||
|
init({
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
handleMissingMessage: () => 'from handler',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(formatMessage('should-default')).toBe('from handler');
|
||||||
|
});
|
||||||
|
|
||||||
it('does not throw with invalid syntax', () => {
|
it('does not throw with invalid syntax', () => {
|
||||||
|
init({ fallbackLocale: 'en' });
|
||||||
|
|
||||||
$locale.set('en');
|
$locale.set('en');
|
||||||
const spy = jest.spyOn(global.console, 'warn').mockImplementation();
|
const spy = jest.spyOn(global.console, 'warn').mockImplementation();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user