Skip to content

Languages and RTL

A store publishes one or more languages in Settings › Languages. The primary language has no URL prefix; the others live under /ar/, /fr/ and so on.

  • URLs: routes, every url property and url settings include the language prefix.
  • Content: product titles, collection descriptions, pages, menus and section settings come in the page’s language when the merchant has translated them.
  • hreflang: content_for_header adds <link rel="alternate" hreflang> for every published language, and the sitemap lists the alternates.
  • A language suggestion: when a visitor’s browser prefers another published language, a small banner offers it.

Set the language and direction on <html>:

<html lang="{{ request.locale.iso_code }}" dir="{{ request.locale.direction }}">

and print text through t, never hard-coded. Layout and spacing for right-to-left pages are in RTL and Arabic typography.

{%- if localization.available_languages.size > 1 -%}
{%- form 'localization', id: 'LanguageForm' -%}
<input type="hidden" name="return_to" value="{{ request.path }}">
<label for="LanguageSelect" class="visually-hidden">{{ 'localization.language_label' | t }}</label>
<select id="LanguageSelect" name="locale_code" onchange="this.form.submit()">
{%- for language in localization.available_languages -%}
<option value="{{ language.iso_code }}" lang="{{ language.iso_code }}" {% if language.iso_code == localization.language.iso_code %}selected{% endif %}>
{{ language.endonym_name }}
</option>
{%- endfor -%}
</select>
{%- endform -%}
{%- endif -%}

The form posts to /localization, remembers the choice and sends the shopper to the same page in the new language. Show each language in its own name (endonym_name: English, العربية) with a lang attribute, so screen readers pronounce it right.

Plain links work too, without a form:

{%- for language in localization.available_languages -%}
<a href="{{ language.root_url }}" lang="{{ language.iso_code }}" hreflang="{{ language.iso_code }}">{{ language.endonym_name }}</a>
{%- endfor -%}

A store sells in its own currency; localization.country is the store’s country. Prices are always in shop.currency.

date prints Arabic month names on Arabic pages and takes calendar: 'hijri'. Prices use Western digits in every language, so they’re the same in the cart, on receipts and in WhatsApp messages.

Was this page helpful?