> Portal Navigation: > > - Append `.md` to any URL under `https://dev.wix.com/docs/` to get its markdown version. > - Pages are either content pages (article or reference text) or menu pages (a list of links to child pages). > - To get a menu page, truncate any URL to a parent path and append `.md` (e.g. `https://dev.wix.com/docs/sdk.md`, `https://dev.wix.com/docs/sdk/core-modules.md`). > - Top-level index of all portals: https://dev.wix.com/docs/llms.txt > - Full concatenated docs: https://dev.wix.com/docs/llms-full.txt ## Resource: Implement Localization in your App Extensions ## Article: Implement Localization in your App Extensions ## Article Link: https://dev.wix.com/docs/build-apps/launch-your-app/localization/implement-localization-in-your-app-extensions.md ## Article Content: # Implement Localization in your App Extensions When localizing your app, you may need to display text in the user's chosen language. Users can set different languages for different interfaces. For example, they may choose one language for the dashboard, but allow their site users to set a different language for the site. This means your app needs to retrieve the chosen settings for each [extension](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/about-extensions.md). The essentials SDK's [`i18n` submodule](https://dev.wix.com/docs/sdk/core-modules/essentials/i18n.md) allows app extensions to access the active language and locale settings of a site's [interfaces](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/about-extensions.md#frontend-interfaces). This article outlines the recommended steps for using the SDK to display localized text in different parts of your app. > **Note:** This article uses the [FormatJS' `react-intl` package](https://formatjs.io/docs/react-intl/), but you may use any other localization library. Make sure to install your chosen package in your app before starting to code. ## Step 1 | Prepare translations For each language your app supports, create a JSON file containing all your app's strings. > **Notes:** > - You can save your JSON files wherever you like in your code. > - Anything contained in `{}` represents variables. The [Intl MessageFormat](https://formatjs.io/docs/intl-messageformat) uses [ICU message syntax](https://unicode-org.github.io/icu/userguide/format_parse/messages/) and [CLDR locale data](http://cldr.unicode.org/). For example, to support English and Spanish, create 2 JSON files: **`src/intl/messages/en.json`** ```json { "greeting": "Hello, {name}!", "welcome": "Welcome to our app!", "todayIs": "Today is {ts, date, ::yyyyMMdd}" } ``` **`src/intl/messages/es.json`** ```json { "greeting": "Hola, {name}!", "welcome": "Bienvenido a nuestra aplicación!", "todayIs": "Hoy es {ts, date, ::yyyyMMdd}" } ``` ## Step 2 | Create a function to load the messages JSON file Create and export a helper function that loads the correct messages JSON based on the extension's language: 1. Create a file to host the helper function. For example, `src/intl/load-messages.js`. 1. Import `i18n` from `@wix/essentials`: ```js import { i18n } from "@wix/essentials"; ``` 1. Create and export a function that calls [`i18n.getLanguage()`](https://dev.wix.com/docs/sdk/core-modules/essentials/i18n.md#getlanguage) and returns the correct messages JSON based on the language retrieved. \ For example: ```js export async function loadMessages() { switch (i18n.getLanguage()) { case "es": return (await import("./es.json")).default; default: return (await import("./en.json")).default; } } ``` At the end of this step, your file should look similar to this: **`src/intl/load-messages.js`** ```js import { i18n } from "@wix/essentials"; export async function loadMessages() { switch (i18n.getLanguage()) { case "es": return (await import("./es.json")).default; default: return (await import("./en.json")).default; } } ``` ## Step 3 | Initialize `intl` This step is implemented differently depending on whether your app's extensions use React or plain JavaScript. ### React Render your extensions using the `IntlProvider` component from the [`react-intl` package](https://formatjs.io/docs/react-intl/). To avoid repeating this code for each of your apps' extension, create a higher order component (HOC) that you can use to wrap your extensions with `IntlProvider`: 1. Create a component called `withIntlProvider`. This is your HOC that will wrap your extensions with `IntlProvider`. 1. Create a state variable. 1. Using `useEffect()`, when the component loads, call `loadMessages()` that you defined in [Step 2](#step-2--create-a-function-to-load-the-messages-json-file), and then save the response in your state variable. 1. If `loadMessages()` doesn't return a value, the component should return `null`. 1. Return an [`IntlProvider` component](https://formatjs.io/docs/react-intl/components#intlprovider) with the following props: - Pass the loaded messages to the `messages` prop. - Pass the value of [`i18n.getLocale()`](https://dev.wix.com/docs/sdk/core-modules/essentials/i18n.md#getlanguage) to the `locale` prop. - Set the default locale. - Pass `` as the children prop. At the end of this step, your file should look like this: **`src/intl/withIntlProvider.jsx`** ```js import { i18n } from "@wix/essentials"; import React from "react"; import { IntlProvider } from "react-intl"; import { loadMessages } from "./load-messages"; // Edit according to where you saved your file. export function withIntlProvider(Component) { return (props => { const [messagesInLanguage, setMessagesInLanguage] = React.useState(null); React.useEffect(() => { loadMessages().then((data) => { setMessagesInLanguage(data) }); }, []); if (!messagesInLanguage) { return null; } return ( ) }) } ``` ### Plain JavaScript You will need an [`intl`](https://formatjs.io/docs/intl/) object instance to format your messages. To create this instance: 1. Create a file, such as `src/intl/create-intl.js` and add the following import statements: ```js import { i18n } from "@wix/essentials"; import { createIntlCache, createIntl as createIntlCore } from "react-intl"; import { loadMessages } from "./load-messages"; // Edit according to where you saved your file. ``` 1. Create and export a function called `createIntl`. 1. Your `createIntl` function should return the result of calling `createIntlCore()` and passing the following parameters. - An object containing: - `locale`: Use the value returned by [`i18n.getLocale()`](https://dev.wix.com/docs/sdk/core-modules/essentials/i18n.md#getlanguage). - `messages`: Use the value returned by `loadMessages()`, defined in [Step 2](#step-2--create-a-function-to-load-the-messages-json-file). - The value returned by [`creatIntlCache()`](https://formatjs.io/docs/intl/#createintlcache); At the end of this step, your file should look like this: **`src/intl/create-intl.js`** ```js import { i18n } from "@wix/essentials"; import { createIntlCache, createIntl as createIntlCore } from "react-intl"; import { loadMessages } from "./load-messages"; export async function createIntl() { return createIntlCore( { locale: i18n.getLocale(), messages: await loadMessages(), }, createIntlCache() ); } ``` ## Step 4 | Display localized text in your app's extensions Retrieve and render localized text. This step is implemented differently depending on whether your app's extensions use React or plain JavaScript. ### React To display localized code, wrap your extension with the `withIntlProvider()` function that you defined in [Step 3](#step-3--initialize-intl), and use the [`FormattedMessage` component](https://formatjs.io/docs/react-intl/components/#formattedmessage) to display your text. > **Note:** You only need to wrap the components in your extension that need to access the localized text. However, wrapping your main app extension component with `withIntlProvider()` makes further development smoother. #### Example The following example uses `FormattedMessage` with the following props: - `id`: The key of the message you want to render from your JSON file. - `defaultMessage`: The message to render if no message is retrieved. - `values`: An object of the variable values to use in the message. **`src/dashboard/pages/page.tsx`** ```js import React from "react"; import { withIntlProvider } from "../intl/withIntlProvider"; function MyAppPage() { return (

); } export default withIntlProvider(MyAppPage); ``` ### Plain JavaScript To display localized code: 1. Call the `createIntl()` function that you defined in [Step 3](#step-3--initialize-intl) to create an `intl` instance 1. Use the [`formatMessage` property](https://formatjs.io/docs/intl/#formatmessage) to return your translated text. For example: **`src/site/embedded-scripts/my-script/index.ts`** ```js import { createIntl } from "../../../intl/create-intl"; const intl = await createIntl(); console.log( intl.formatMessage( { id: "todayIs", defaultMessage: "Today is {ts, date, ::yyyyMMdd}" }, { ts: Date.now() } ) ); ```