Locale
Locale Configuration
Locale Pattern
On our web infrastructure, the "locale" is the URL prefix with the pattern: xx-xx.
- The first two letters indicate the language code used on those pages. This code must comply with ISO 639.
- The last two letters indicate the country code option used on those pages. This code must comply with ISO 3166.
Configuring a new locale
To enable a new locale, it needs to be done on both BE (Back-End) and FE (Front-End) sides.
On the FE side, it is necessary to register a new locale in the Next.js configuration (next.config.js) by modifying the i18n configuration in the packages/core/i18n/shared.js file. Add the configuration of the locale that will be enabled in the localesWithCurrency.
exports.localesWithCurrency = [
//..other locale
{
languageTag: 'en-JP',
defaultCurrency: 'JPY',
allowedCurrencies: ['JPY'],
},
{
languageTag: 'ja-JP',
defaultCurrency: 'JPY',
allowedCurrencies: ['JPY'],
},
];
If we do not add the locale to the Next.js configuration, that locale will be treated as a page not found (404).
On the BE side, it is necessary to register a new locale to ensure its inclusion in the API response /v2/locale-currency. From a logical standpoint, when a page receives a request, the system checks the locale prefix and verifies its validity from the backend.
If we do not add the locale to BE configuration, redirection occurs by removing the current locale.
Extracting locale data
There are 2 hooks that you can use to get user prefered locale and list of supported locales.
useLocale
This return LocaleInfo object with type as follows:
type LocaleInfo = {
// lowercase 2 digit language code, e.g: en
language: string;
// lowercase 2 digit country code, e.g: us
country: string;
// BCP 47 language tag, e.g: en-US
languageTag: string;
// default currency for this locale
defaultCurrency: string;
};
You can use country or language to create quick implementation of locale specific UI, meanwhile languageTag is usually used for i18n purpose.
import React from 'react';
import { useLocale } from '@traveloka/core';
function Component(props) {
const { languageTag } = useLocale();
const dateFormatter = new Intl.DateTimeFormat(languageTag);
return dateFormatter.format(props.date);
}
Note: we don't recommend doing some kind of locale-based feature control using this method. Use proper feature control API for that.
useLocales
This returns Array<LocaleInfo> similar to useLocale above containing all available locales in current request.
import { useLocales } from '@traveloka/core';
function Component(props) {
const locales = useLocales();
return locales.map(locale => {
const localeLabel = props.localeDisplayMap[locale.languageTag];
return <span>{localeLabel}</span>;
});
}
You should be rarely using this locales unless you're rendering list of available locales or finding correct value to change locale.
Usage in data-fetching functions
It's exposed as the rawAppContext argument (the second argument of your data-fetching function).
(1) staticProps example
export const getStaticProps = staticProps({
path: '/flight/trpc-playground',
resources: [],
async getStaticProps(ctx, rawAppContext) {
const { locale, locales } = rawAppContext;
return {};
},
});
(2) getInitialProps example
Page.getInitialProps = async (ctx, rawAppContext) => {
const { locale, locales } = rawAppContext;
return {};
};