Localization and consent

Change the visitor's country and language, and record their cookie-consent choice.

POST /localization
{% form 'localization_set' %}

Changes the visitor's country, language, or both. A form submission redirects to the same page at the address for the new choice; JSON returns the new localization and redirect_url.

Form fields

country_code Optional

ISO country code from localization.available_countries. Omit it to change only the language; the current country is kept.

locale Optional

Language code from localization.available_languages. Omit it to change only the country; the language then becomes the new country's default language.

return_to Optional

Path on this storefront to return to. Defaults to the referring page. The path is readdressed for the new country and language.

_format Optional

Set to json when submitting with fetch; omit for the normal browser redirect.

Validation

Send country_code, locale, or both. Values must come from localization.available_countries and localization.available_languages, and a language must be offered in the chosen country. When only locale is sent, the current country is kept: the domain's own country when the domain has one, otherwise the country in the page address (/{locale}-{country}), otherwise the country saved on the visitor session, otherwise the store's country. When only country_code is sent, the language becomes that country's default language. return_to is reduced to a path on this storefront and addressed for the new choice.

Limits

External return URLs are never used as destinations.

Response

{
  success:true,
  data:{market,
  currency,
  localization,
  available_countries,
  available_languages,
  stamped,
  redirect_url},
  user_errors
}

stamped is true when the choice was saved to the visitor session. A refused choice returns HTTP 400 with success: false and user_errors: STOREFRONT_UNSUPPORTED_COUNTRY, STOREFRONT_UNSUPPORTED_LANGUAGE, or STOREFRONT_LOCALIZATION_CHOICE_REQUIRED when neither field is sent. A form submission redirects to redirect_url with HTTP 303 and reports a refusal through form_notice.

Country and language switchers#

{% form 'localization_set' %} posts to /localization. Send country_code, locale, or both: a country picker sends only country_code, and a language picker sends only locale. Take the values from localization.available_countries and localization.available_languages, described in Locale, country, and currency.

vascula
{% for country in localization.available_countries %}
  {% form 'localization_set' %}
    <input type="hidden" name="country_code" value="{{ country.iso_code }}">
    <button type="submit"{% if country.selected %} aria-current="true"{% endif %}>{{ country.flag }} {{ country.name }} ({{ country.currency_code }})</button>
  {% endform %}
{% endfor %}

{% for language in localization.available_languages %}
  {% form 'localization_set' %}
    <input type="hidden" name="locale" value="{{ language.iso_code }}">
    <button type="submit"{% if language.selected %} aria-current="true"{% endif %}>{{ language.native_name | default: language.name }}</button>
  {% endform %}
{% endfor %}

When only locale is sent, the visitor keeps their current country: the domain's own country when the domain has one, otherwise the country in the page address (/{locale}-{country}), otherwise the country saved for the visitor, otherwise the store's country. When only country_code is sent, the currency becomes that country's currency and the language becomes the country's default language. When both are sent, the language must be offered in that country.

A form submission redirects (HTTP 303) to the page the visitor came from, at its address for the new country and language. With JSON, redirect_url carries that address and the storefront bridge navigates to it.

Errors#

Refused choices return success: false with user_errors, and change nothing.

Code

HTTP status

When

STOREFRONT_LOCALIZATION_CHOICE_REQUIRED

400

localization_set received neither country_code nor locale.

STOREFRONT_UNSUPPORTED_COUNTRY

400

The country is not one of localization.available_countries. field is country_code.

STOREFRONT_UNSUPPORTED_LANGUAGE

400

The language is not offered in the chosen country. field is locale.

STOREFRONT_CONSENT_CATEGORY_INVALID

400

consent_give received a category outside the platform set. field is categories.

STOREFRONT_RUNTIME_CSRF_INVALID

403

The CSRF token is missing or expired, or the visitor has no session.

STOREFRONT_RUNTIME_INTERNAL

500

A temporary failure. Try again.

json
{
  "success": false,
  "user_errors": [
    {
      "code": "STOREFRONT_UNSUPPORTED_COUNTRY",
      "message": "The country ZZ is not available for this store.",
      "locale": "en",
      "params": [{ "key": "code", "value": "ZZ" }],
      "field": ["country_code"]
    }
  ]
}

After a native form submission, a refusal appears in form_notice on the next page: STOREFRONT_LOCALIZATION_UNAVAILABLE for a country or language that is not offered, STOREFRONT_LOCALIZATION_CHOICE_REQUIRED, or STOREFRONT_CONSENT_CATEGORY_INVALID.

consent_give and consent_withdraw record the visitor's choice on their visitor session. Build the banner from the CTX consent root as shown in Customers, carts, and consent, and see Consent categories for what each category covers and when visitors are asked.

Order tracking and recommendation clicks are on their own pages in this section.