Declare localization to read the active language, the active country, and the country and language choices served by this storefront. Available countries come from enabled markets, and available languages are the ones offered in the active country. Show these choices rather than an unrestricted list of countries or languages.
localization.locale is the active language tag. localization.country is the country the shopper is shopping in, with its name and currency; it is null when no country is known. localization.baseline_locale is the language that needs no language prefix for the current serving context. Use routes and the URLs supplied on resources for navigation; use localization_set to change the shopper's choice.
Country addresses#
On a shared domain, each country the store sells to has its own address. The store's own country uses plain paths, with a language prefix only for a language other than the default, for example /products/mug and /fr/products/mug. Every other country uses a /{locale}-{country} prefix, even in the default language, for example /en-gb/products/mug and /fr-be/products/mug. A domain dedicated to one country serves only that country and adds a language prefix only for its other languages.
Opening a country address shops in that country, so a shared link keeps its country. Links from routes and the url fields on resources already carry the right prefix; build links from them rather than composing prefixes yourself.
Country and language switchers#
Use one localization_set form for the country and another for the language, as below. When a form sends only country_code, the currency becomes that country's currency and the language becomes the country's default language. When a form sends only locale, the country stays the same: the domain's own country, otherwise the country in the current address, otherwise the country saved for this visitor, otherwise the store's country.
{% form 'localization_set' %}
<label>Country or region
<select name="country_code">
{% for country in localization.available_countries %}
<option value="{{ country.iso_code }}"{% if country.selected %} selected{% endif %}>{{ country.name }} ({{ country.currency_code }})</option>
{% endfor %}
</select>
</label>
<button type="submit">Update country</button>
{% endform %}
{% form 'localization_set' %}
<label>Language
<select name="locale">
{% for language in localization.available_languages %}
<option value="{{ language.iso_code }}"{% if language.selected %} selected{% endif %}>{{ language.native_name }}</option>
{% endfor %}
</select>
</label>
<button type="submit">Update language</button>
{% endform %}
A form that sends both fields must pick a language offered in the chosen country; otherwise the action refuses the choice with STOREFRONT_UNSUPPORTED_LANGUAGE. The action redirects to the current page at its address for the new choice. A country may serve only the storefront's primary language until other languages are assigned to it, and changing the language never changes the currency. Fields and errors are on Localization and consent.
Formatting prices#
Money values carry amount and currency_code. Currency determines decimal precision; the active locale determines digits, separators, grouping, and symbol placement. For example, INR zero can display as 0,00 ₹ in French while remaining INR. Use money instead of joining an amount and a currency symbol yourself.
{% if product.price %}
<span>{{ product.price.current | money: isolate: true }}</span>
{% endif %}
The isolate option keeps money readable next to text of a different direction. Language options also provide rtl for direction-aware controls. Follow the money and locale guide for currency precision and right-to-left examples.
Country and language suggestions#
localization_prompt.should_show tells your suggestion section whether to appear for this visitor. Use suggested_country_code and the supplied available choices when offering a change; respect the visitor's selection and dismissal. A suggestion does not itself change their country or language.