Global configuration
Configuration properties that you commonly use across your Next.js app can be set globally.
Note that if you're using the Server Components
beta (opens in a new tab),
you can set these properties in the global request configuration
(i18n.ts
) (opens in a new tab)
to use them in Server Components.
Time zone
If possible, you should configure an explicit time zone, as this affects the rendering of dates and times. By default, the available time zone of the runtime will be used: In Node.js this is the time zone that is configured for the server and in the browser this is the local time zone of the user. As the time zone of the server and the one from the user can be different, this might be problematic when your app is both rendered on the server as well as on the client side.
To ensure consistency, you can globally define a time zone:
<NextIntlClientProvider timeZone="Europe/Vienna">...<NextIntlClientProvider>
The time zone can either be static in your app, or alternatively read from the user profile if you store such a setting. The available time zone names can be looked up in the tz database (opens in a new tab).
Global now value
To avoid mismatches between the server and client environment, it is recommended to configure a static global now
value on the provider:
<NextIntlClientProvider
// This value can be generated in data fetching
// functions to make sure it's consistent
now={now}
...
>
<App />
</NextIntlClientProvider>
This value will be used as the default for the relativeTime
function as well as returned during the initial render of useNow
.
Important: When you cache the rendered markup (e.g. when using static
rendering (opens in a new tab)),
the formatted value will become stale. Therefore either regenerate these pages
regularly or use the updateInterval
option of
useNow
on the client side.
For consistent results in end-to-end tests, it can be helpful to mock this value to a constant value, e.g. based on an environment parameter.
Global formats
To achieve consistent date, time, number and list formatting, you can define a set of global formats.
<NextIntlClientProvider
...
formats={{
dateTime: {
short: {
day: 'numeric',
month: 'short',
year: 'numeric'
}
},
number: {
precise: {
maximumFractionDigits: 5
}
},
list: {
enumeration: {
style: 'long',
type: 'conjunction'
}
}
}}
>
<App />
</NextIntlClientProvider>
import {useFormatter} from 'next-intl';
function Component() {
const format = useFormatter();
format.dateTime(new Date('2020-11-20T10:36:01.516Z'), 'short');
format.number(47.414329182, 'precise');
format.list(['HTML', 'CSS', 'JavaScript'], 'enumeration');
}
Global formats for numbers, dates and times can be referenced in messages too.
{
"ordered": "You've ordered this product on {orderDate, date, short}",
"latitude": "Latitude: {latitude, number, precise}"
}
import {useTranslations} from 'next-intl';
function Component() {
const t = useTranslations();
t('ordered', {orderDate: new Date('2020-11-20T10:36:01.516Z')});
t('latitude', {latitude: 47.414329182});
}
Default translation values
To achieve consistent usage of translation values and reduce redundancy, you can define a set of global default values. This configuration also can be used to apply consistent styling of commonly used rich text elements.
<NextIntlClientProvider
...
defaultTranslationValues={{
important: (chunks) => <b>{chunks}</b>,
value: 123
}}
>
<App />
</NextIntlClientProvider>
The defaults will be overridden by locally provided values.
Retrieve provider config
As a convenience, two hooks exist that allow to read configuration that was globally configured.
import {useLocale, useTimeZone} from 'next-intl';
function Component() {
// Returns either an explicitly configured locale from the provider
// or if internationalized routing is used in the pages directory,
// it returns the configured locale from Next.js.
const locale = useLocale();
// Note that this will be `undefined` if no explicit
// `timeZone` was configured on the provider.
const timeZone = useTimeZone();
}
Error handling
By default, when a message fails to resolve or when the formatting failed, an error will be printed on the console. In this case ${namespace}.${key}
will be rendered instead to keep your app running.
This behavior can be customized with the onError
and getMessageFallback
configuration option.
import {NextIntlClientProvider, IntlErrorCode} from 'next-intl';
function onError(error) {
if (error.code === IntlErrorCode.MISSING_MESSAGE) {
// Missing translations are expected and should only log an error
console.error(error);
} else {
// Other errors indicate a bug in the app and should be reported
reportToErrorTracking(error);
}
}
function getMessageFallback({namespace, key, error}) {
const path = [namespace, key].filter((part) => part != null).join('.');
if (error.code === IntlErrorCode.MISSING_MESSAGE) {
return `${path} is not yet translated`;
} else {
return `Dear developer, please fix this message: ${path}`;
}
}
<NextIntlClientProvider ... onError={onError} getMessageFallback={getMessageFallback}>
<App />
</NextIntlClientProvider>
Fallbacks from other locales
If you have incomplete messages for a given locale and would like to use messages from another locale as a fallback, you can merge the two before passing them to NextIntlClientProvider
.
import deepmerge from 'deepmerge';
const userMessages = (await import(`../../messages/${locale}.json`)).default;
const defaultMessages = (await import(`../../messages/en.json`)).default;
const messages = deepmerge(defaultMessages, userMessages);