--- title: Localization API description: >- The Localization API lets you translate strings, format numbers and dates, and read the buyer's language, country, and currency context. Use this API to build extensions that adapt their content and behavior to the customer's locale, including support for pluralization and dynamic values in translations. api_version: 2025-07 api_name: customer-account-ui-extensions source_url: html: >- https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/target-apis/platform-apis/localization-api md: >- https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/target-apis/platform-apis/localization-api.md --- Migrate to Polaris Version 2025-07 is the last API version to support React-based UI components. Later versions use [web components](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/polaris-web-components), native UI elements with built-in accessibility, better performance, and consistent styling with [Shopify's design system](https://shopify.dev/docs/apps/design). Check out the [migration guide](https://shopify.dev/docs/apps/build/customer-accounts/migrate-to-web-components) to upgrade your extension. # Localization API The Localization API lets you translate strings, format numbers and dates, and read the buyer's language, country, and currency context. Use this API to build extensions that adapt their content and behavior to the customer's locale, including support for pluralization and dynamic values in translations. ### Use cases * **Display translated content**: Render UI strings in the customer's preferred language using translation keys defined in locale JSON files. * **Format numbers and currency**: Use `shopify.i18n.formatNumber()` to display numbers, prices, and quantities in the customer's locale format. * **Show country-specific messaging**: Read the customer's country from `shopify.localization.country` to conditionally display region-specific notices, shipping information, or promotions. * **Handle pluralization**: Use the `count` option in `shopify.i18n.translate()` to automatically select the correct plural form based on the customer's locale rules. ### Support Targets (25) ### Supported targets * Customer​Account::Kitchen​Sink * [customer-account.​footer.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/footer#footer-render-after-) * [customer-account.​order-index.​announcement.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/order-index#order-index-targets) * [customer-account.​order-index.​block.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/order-index#order-index-block-) * [customer-account.​order-status.​announcement.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/order-status#order-status-announcement-) * [customer-account.​order-status.​block.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/order-status#order-status-block-) * [customer-account.​order-status.​cart-line-item.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/order-status#cart-line-item-render-after-) * [customer-account.​order-status.​cart-line-list.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/order-status#cart-line-list-render-after-) * [customer-account.​order-status.​customer-information.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/order-status#customer-information-render-after-) * [customer-account.​order-status.​fulfillment-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/fulfillment-status#fulfillment-status-targets) * [customer-account.​order-status.​payment-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/payments-and-returns#payments-and-returns-targets) * [customer-account.​order-status.​return-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/payments-and-returns#return-details-render-after-) * [customer-account.​order-status.​unfulfilled-items.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/fulfillment-status#unfulfilled-items-render-after-) * [customer-account.​order.​action.​menu-item.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/order-actions#order-action-menu-item-) * [customer-account.​order.​action.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/order-actions#order-action-) * [customer-account.​order.​page.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/full-page#order-specific-full-page-) * [customer-account.​page.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/full-page#customer-account-full-page-) * [customer-account.​profile.​addresses.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/profile-page-default#profile-page-default-targets-) * [customer-account.​profile.​announcement.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/profile-page-default#announcement-) * [customer-account.​profile.​block.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/profile-page-default#profile-block-) * [customer-account.​profile.​company-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/profile-page-b2b#profile-page-b2b-targets-) * [customer-account.​profile.​company-location-addresses.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/profile-page-b2b#company-location-addresses-render-after-) * [customer-account.​profile.​company-location-payment.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/profile-page-b2b#company-location-payment-render-after-) * [customer-account.​profile.​company-location-staff.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/targets/profile-page-b2b#company-location-staff-render-after-) * customer-account.​profile.​payment.​render-after ### Properties The Localization API object provides localization and translation utilities for customer account extensions. Access the following properties on the API object to translate strings, format values, and read the buyer's language and country context. * **i18n** **I18n** **required** Utilities for translating strings, formatting currencies, numbers, and dates according to the buyer's locale. Supports both the buyer's locale and the extension's fallback locale. * **localization** **Localization** **required** The buyer's language, country, and locale context. For formatting utilities, use the `i18n` object instead. ### I18n Utilities for translating strings, formatting currencies, numbers, and dates according to the buyer's locale. Supports both the buyer's locale and the extension's fallback locale. * formatCurrency Returns a localized currency string. This function behaves like the standard \[\`Intl.NumberFormat()\`]\(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Intl/NumberFormat) with a style of \`currency\` applied. Uses the buyer's locale by default. ```ts (number: number | bigint, options?: { inExtensionLocale?: boolean; } & NumberFormatOptions) => string ``` * formatDate Returns a localized date string. This function behaves like the standard \[\`Intl.DateTimeFormat()\`]\(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Intl/DateTimeFormat) and uses the buyer's locale by default. Formatting \[options]\(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Intl/DateTimeFormat#using\_options) can be passed in as options. ```ts (date: Date, options?: { inExtensionLocale?: boolean; } & DateTimeFormatOptions) => string ``` * formatNumber Returns a localized number string. This function behaves like the standard \[\`Intl.NumberFormat()\`]\(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Intl/NumberFormat) with a style of \`decimal\` applied. Uses the buyer's locale by default. ```ts (number: number | bigint, options?: { inExtensionLocale?: boolean; } & NumberFormatOptions) => string ``` * translate Returns translated content in the buyer's locale, as supported by the extension. - \`options.count\` is a special numeric value used in pluralization. - The other option keys and values are treated as replacements for interpolation. - If the replacements are all primitives, then \`translate()\` returns a single string. - If replacements contain UI components, then \`translate()\` returns an array of elements. ```ts I18nTranslate ``` ### I18nTranslate The signature for the \`i18n.translate()\` function. Returns translated content matching a key in a locale file, with support for pluralization and interpolation. ### Localization The buyer’s language, country, and locale context in the customer account. Use this to adapt content to the buyer’s region and language preferences. * country The buyer's country context in the customer account, as a \`StatefulRemoteSubscribable\` that updates if the buyer changes their country. The value is \`undefined\` if the country is unknown. ```ts StatefulRemoteSubscribable ``` * extensionLanguage The buyer's language, as supported by the extension. If the buyer's actual language is not supported by the extension, this is the fallback locale used for translations. For example, if the buyer's language is \`fr-CA\` but your extension only supports translations for \`fr\`, then the \`isoCode\` for this language is \`fr\`. If your extension doesn't provide French translations at all, this value is the default locale for your extension (that is, the one matching your \`.default.json\` file). ```ts StatefulRemoteSubscribable ``` * language The language the buyer sees in the customer account pages. ```ts StatefulRemoteSubscribable ``` ### Country A buyer's country, identified by its ISO country code. * isoCode The ISO-3166-1 code for this country. ```ts CountryCode ``` ### CountryCode ```ts 'AC' | 'AD' | 'AE' | 'AF' | 'AG' | 'AI' | 'AL' | 'AM' | 'AN' | 'AO' | 'AR' | 'AT' | 'AU' | 'AW' | 'AX' | 'AZ' | 'BA' | 'BB' | 'BD' | 'BE' | 'BF' | 'BG' | 'BH' | 'BI' | 'BJ' | 'BL' | 'BM' | 'BN' | 'BO' | 'BQ' | 'BR' | 'BS' | 'BT' | 'BV' | 'BW' | 'BY' | 'BZ' | 'CA' | 'CC' | 'CD' | 'CF' | 'CG' | 'CH' | 'CI' | 'CK' | 'CL' | 'CM' | 'CN' | 'CO' | 'CR' | 'CU' | 'CV' | 'CW' | 'CX' | 'CY' | 'CZ' | 'DE' | 'DJ' | 'DK' | 'DM' | 'DO' | 'DZ' | 'EC' | 'EE' | 'EG' | 'EH' | 'ER' | 'ES' | 'ET' | 'FI' | 'FJ' | 'FK' | 'FO' | 'FR' | 'GA' | 'GB' | 'GD' | 'GE' | 'GF' | 'GG' | 'GH' | 'GI' | 'GL' | 'GM' | 'GN' | 'GP' | 'GQ' | 'GR' | 'GS' | 'GT' | 'GW' | 'GY' | 'HK' | 'HM' | 'HN' | 'HR' | 'HT' | 'HU' | 'ID' | 'IE' | 'IL' | 'IM' | 'IN' | 'IO' | 'IQ' | 'IR' | 'IS' | 'IT' | 'JE' | 'JM' | 'JO' | 'JP' | 'KE' | 'KG' | 'KH' | 'KI' | 'KM' | 'KN' | 'KP' | 'KR' | 'KW' | 'KY' | 'KZ' | 'LA' | 'LB' | 'LC' | 'LI' | 'LK' | 'LR' | 'LS' | 'LT' | 'LU' | 'LV' | 'LY' | 'MA' | 'MC' | 'MD' | 'ME' | 'MF' | 'MG' | 'MK' | 'ML' | 'MM' | 'MN' | 'MO' | 'MQ' | 'MR' | 'MS' | 'MT' | 'MU' | 'MV' | 'MW' | 'MX' | 'MY' | 'MZ' | 'NA' | 'NC' | 'NE' | 'NF' | 'NG' | 'NI' | 'NL' | 'NO' | 'NP' | 'NR' | 'NU' | 'NZ' | 'OM' | 'PA' | 'PE' | 'PF' | 'PG' | 'PH' | 'PK' | 'PL' | 'PM' | 'PN' | 'PS' | 'PT' | 'PY' | 'QA' | 'RE' | 'RO' | 'RS' | 'RU' | 'RW' | 'SA' | 'SB' | 'SC' | 'SD' | 'SE' | 'SG' | 'SH' | 'SI' | 'SJ' | 'SK' | 'SL' | 'SM' | 'SN' | 'SO' | 'SR' | 'SS' | 'ST' | 'SV' | 'SX' | 'SY' | 'SZ' | 'TA' | 'TC' | 'TD' | 'TF' | 'TG' | 'TH' | 'TJ' | 'TK' | 'TL' | 'TM' | 'TN' | 'TO' | 'TR' | 'TT' | 'TV' | 'TW' | 'TZ' | 'UA' | 'UG' | 'UM' | 'US' | 'UY' | 'UZ' | 'VA' | 'VC' | 'VE' | 'VG' | 'VN' | 'VU' | 'WF' | 'WS' | 'XK' | 'YE' | 'YT' | 'ZA' | 'ZM' | 'ZW' | 'ZZ' ``` ### Language Represents the buyer's language as a \[BCP-47 standard]\(https://en.wikipedia.org/wiki/IETF\_language\_tag) language tag. * isoCode The \[BCP-47]\(https://en.wikipedia.org/wiki/IETF\_language\_tag) language tag. May include a dash followed by an \[ISO 3166-1 Alpha-2]\(https://en.wikipedia.org/wiki/ISO\_3166-1\_alpha-2) region subtag. ```ts string ``` Examples ### Examples * #### Translate a static string ##### Description Render a translated string from a locale file using \`shopify.i18n.translate()\`. This example displays a welcome message that automatically adapts to the customer's language. ##### React ```tsx /* See the locales/en.default.json tab for the translation keys and values for this example */ import { reactExtension, Text, useTranslate, } from '@shopify/ui-extensions-react/customer-account'; export default reactExtension( 'customer-account.order-status.block.render', () => , ); function Extension() { const translate = useTranslate(); return ( {translate('welcomeMessage')} ); } ``` ##### TS ```js /* See the locales/en.default.json tab for the translation keys and values for this example */ import {extension} from '@shopify/ui-extensions/customer-account'; export default extension( 'customer-account.order-status.block.render', (root, {i18n}) => { const welcomeMsg = i18n.translate( 'welcomeMessage', ); root.appendChild(root.createText(welcomeMsg)); }, ); ``` ##### locales/en.default.json ```json { "welcomeMessage": "Welcome to our store!" } ``` * #### Display country-specific content ##### Description Read the customer's country to conditionally render region-specific messaging. This example checks whether the customer is in Canada and displays a shipping delay warning if so. ##### React ```tsx /* See the locales/en.default.json tab for the translation keys and values for this example */ import { Banner, reactExtension, useI18n, useLocalizationCountry, } from '@shopify/ui-extensions-react/customer-account'; export default reactExtension( 'customer-account.order-index.block.render', () => , ); function Extension() { const i18n = useI18n(); const country = useLocalizationCountry(); if (country?.isoCode === 'CA') { return ( ); } return null; } ``` ##### TS ```js /* See the locales/en.default.json tab for the translation keys and values for this example */ import { extension, Banner, } from '@shopify/ui-extensions/customer-account'; export default extension( 'customer-account.order-index.block.render', (root, {i18n, localization}) => { const country = localization.country.current; if (country?.isoCode === 'CA') { const app = root.createComponent(Banner, { title: i18n.translate( 'canadaPostWarningMessage', ), }); root.appendChild(app); } }, ); ``` ##### locales/en.default.json ```json { "canadaPostWarningMessage": "Canada Post has issued a red delivery service alert for Ontario due to a severe snowstorm, suspending package delivery and collection for the week." } ``` * #### Translate a string with pluralization ##### Description Use the \`count\` option to render the correct plural form for the customer's locale. This example translates a loyalty points message that differs between singular and plural based on the point count. ##### React ```tsx /* See the locales/en.default.json tab for the translation keys and values for this example */ import { reactExtension, Banner, useApi, useTranslate, } from '@shopify/ui-extensions-react/customer-account'; export default reactExtension( 'customer-account.order-status.block.render', () => , ); function Extension() { const {i18n} = useApi(); const translate = useTranslate(); const points = 10000; const formattedPoints = i18n.formatNumber(points); // Translate the loyalty points message, using pluralization to differentiate messages const loyaltyPointsMsg = translate( 'loyaltyPoints', { count: points, formattedPoints, }, ); return ; } ``` ##### TS ```js /* See the locales/en.default.json tab for the translation keys and values for this example */ import { extension, Banner, } from '@shopify/ui-extensions/customer-account'; export default extension( 'customer-account.order-status.block.render', (root, {i18n}) => { const points = 10000; const formattedPoints = i18n.formatNumber(points); // Translate the loyalty points message, using pluralization to differentiate messages const loyaltyPointsMsg = i18n.translate( 'loyaltyPoints', { count: points, formattedPoints, }, ); const app = root.createComponent(Banner, { title: loyaltyPointsMsg, }); root.appendChild(app); }, ); ``` ##### locales/en.default.json ```json { "loyaltyPoints": { "one": "You have {{formattedPoints}} loyalty point", "other": "You have {{formattedPoints}} loyalty points" } } ``` *** ## Best practices * **Define a default locale file**: Always include a `locales/en.default.json` file as the fallback. This ensures your extension displays meaningful content even when a translation for the customer's language isn't available. * **Use dynamic values instead of string concatenation**: Pass variables through the `translate()` options object (for example, `{{formattedPoints}}`) rather than concatenating translated fragments. This keeps translations flexible across languages with different word orders. * **Format numbers with `shopify.i18n.formatNumber()`**: Don't manually format numbers with `toLocaleString()`. The built-in formatter respects the store's locale configuration and produces consistent results. * **Guard against missing localization data**: Check that `shopify.localization.country` and other localization properties are defined before using them. These values load asynchronously and may be `undefined` on the initial render. *** ## Limitations * Translation keys must be defined in static JSON locale files bundled with the extension. You can't load translations dynamically at runtime. * The `translate()` method only supports the pluralization categories defined by the Unicode CLDR for the active locale (for example, `one`, `other`, `few`, `many`). Custom plural categories aren't supported. * Country and language values reflect the customer's current session context. They can't be overridden programmatically by the extension. ***