Localization (multi-language)
Hyprism ships with English (default) and German translations covering both the storefront (what customers see) and the theme editor (what merchants see when customizing). This chapter covers using the built-in locales, adding new languages, and the translation architecture.
15.1 The two layers of localization
Section titled “15.1 The two layers of localization”Shopify themes have two parallel translation systems:
| Layer | What it translates | File |
|---|---|---|
| Storefront | Buttons, labels, messages visible to customers | locales/en.default.json, locales/de.json, locales/X.json |
| Theme editor | Settings labels, info-text, dropdown options visible to merchants | locales/en.default.schema.json, locales/de.schema.json, locales/X.schema.json |
The storefront locale is what controls what your customers read. The theme editor locale is what controls what you read when customizing the theme.
For most merchants, only the storefront matters. The theme-editor locale is automatically read based on the language setting of your Shopify Admin account.
15.2 Built-in EN + DE
Section titled “15.2 Built-in EN + DE”What’s translated
Section titled “What’s translated”- All theme strings — error messages, button labels, empty-state copy, accessibility labels
- All section settings — 2,809 customizer-schema keys, in a deduplicated namespace that re-uses common labels across sections. The English and German schema files carry exactly the same key count; the theme’s pre-push checks fail on a missing one.
- All section names and presets — visible in the “Add section” picker
Enabling German on your storefront
Section titled “Enabling German on your storefront”- Shopify Admin → Settings → Languages.
- Add language → German.
- Click Publish next to German.
The German storefront is now available. To make it the default for German-speaking visitors, configure Shopify Markets (per-country language preferences).
Switching between languages on the storefront
Section titled “Switching between languages on the storefront”Hyprism’s footer-localization block (chapter 5) provides a language switcher. Add it to your footer to give visitors a UI to switch languages.
Alternatively, Shopify auto-detects browser language and redirects to the appropriate locale (if Markets is configured).
15.3 Adding a new language
Section titled “15.3 Adding a new language”To add a new language (e.g., French, Spanish, Italian, Dutch, Portuguese):
Step 1: enable on Shopify
Section titled “Step 1: enable on Shopify”Shopify Admin → Settings → Languages → Add language → pick the target.
The new language is “unpublished” — visitors can’t see it yet.
Step 2: translate storefront strings
Section titled “Step 2: translate storefront strings”Two options:
Option A: use the Translate & Adapt app (recommended)
Shopify offers a free app called Translate & Adapt that translates your store content using machine translation, with optional manual review.
- Install Translate & Adapt from the Shopify App Store.
- Add your new language.
- The app translates products, collections, articles, pages, and theme strings automatically.
- Review and edit translations as needed.
Option B: edit JSON directly
For developers / advanced users:
- Create
locales/{lang}.json(copyen.default.jsonas a starting point). - Translate every value to the target language (the keys stay the same).
- Push to Shopify with
shopify theme push.
Step 3: translate theme-editor strings (optional)
Section titled “Step 3: translate theme-editor strings (optional)”If you want the theme editor to render in the new language too (for merchants who admin in that language):
- Create
locales/{lang}.schema.json(copyen.default.schema.json). - Translate the values.
- Push.
This is optional — the Shopify Theme Store doesn’t require theme-editor translations beyond English. But it’s a nice touch for stores managed by non-English-speaking teams.
Step 4: publish
Section titled “Step 4: publish”Shopify Admin → Settings → Languages → click Publish next to the new language.
15.4 hreflang
Section titled “15.4 hreflang”Hyprism’s meta-tags.liquid snippet auto-emits hreflang annotations for every published locale:
<link rel="alternate" hreflang="en" href="https://yourstore.com/en/product-handle"><link rel="alternate" hreflang="de" href="https://yourstore.com/de/product-handle"><link rel="alternate" hreflang="x-default" href="https://yourstore.com/product-handle">This tells Google “this page exists in these languages at these URLs” — Google then serves the right language to the right visitor.
15.5 RTL (right-to-left) support
Section titled “15.5 RTL (right-to-left) support”Hyprism’s CSS is partially RTL-aware — most layout uses CSS logical properties (margin-inline-start instead of margin-left), which automatically flip in RTL languages (Arabic, Hebrew, Persian).
Some legacy CSS still uses physical properties (margin-left / margin-right) — these would need manual RTL overrides. For an Arabic or Hebrew storefront, expect to make some manual CSS adjustments.
If RTL is critical for your business, plan for ~10–20 hours of polish work in addition to the base translation.
15.6 Locale-specific overrides
Section titled “15.6 Locale-specific overrides”You can override theme settings per locale. Example: different hero image for English vs German.
Shopify’s mechanism: publish multiple theme versions, each configured for a specific locale.
Or use the Translate & Adapt app which lets you swap images / videos / specific section settings per locale.
15.7 Currency
Section titled “15.7 Currency”Currency is separate from language — Shopify’s Markets feature controls per-country currency display.
| Setting | Where | What it does |
|---|---|---|
| Shop currency | Shopify Admin → Settings → General | Your base currency for transactions |
| Display currency | Shopify Markets | Per-country presentation currency |
| Auto-format | Auto | Hyprism renders every price through Shopify’s money filter, which follows shop.money_format |
The footer-localization block shows the current country/currency and lets visitors switch.
⛔⛔ A price does not follow the page language
Section titled “⛔⛔ A price does not follow the page language”shop.money_format is a shop setting, not a visitor-locale one. On a German page of a US-currency store the price still reads $3,500.00, with a comma as the thousands separator and a dot before the decimals — measured, not assumed. That is correct behaviour: a currency has one canonical format, and a German-formatted dollar amount would be a different-looking number, not a translated one.
⭐ What this means when you add custom code: never assemble a price in JavaScript. '$' + (cents / 100).toFixed(2) is wrong even in the shop’s own currency, because toFixed knows nothing about a thousands separator — the same page then shows $3500.00 from your script next to $3,500.00 from the server.
Hyprism exposes exactly one formatter for this, window.neGeld(cents), defined in layout/theme.liquid and fed from data-ne-money-format (which is shop.money_format). Use it.
⚠️ Watch the units. /cart.js and /products/….js return cents; /search/suggest.json returns a string in currency units. Feeding the latter to a cents formatter without × 100 shows $35.00 instead of $3,500.00 — and that looks plausible enough to ship.
15.8 Translation toolchain (engineering note)
Section titled “15.8 Translation toolchain (engineering note)”The locale files are large: 561 storefront keys and 2,809 schema keys per language — 6,740 strings across English and German. They were produced by migrating hard-coded English in the schemas to t: references, deduplicating labels that repeat across sections, machine-translating EN → DE, and then a manual pass for the terms a machine gets wrong.
⚠️ The scripts that did it are not shipped with the theme. An earlier version of this chapter gave a copy-paste recipe naming four of them; they lived in the build repo, not in scripts/, so the recipe could not work. What follows is the approach, not a command line.
To add a language:
- Copy
locales/de.schema.jsontolocales/<code>.schema.jsonandlocales/de.jsontolocales/<code>.json— starting from German rather than English keeps you honest about which strings are real translations and which are still placeholders. - Machine-translate the values, leaving every key untouched. The key count must not change; a missing key renders as a silent “translation missing” that
theme checkdoes not catch. - Do a manual pass over the terms a machine gets wrong. In German that was roughly 400 corrections across four rounds — mostly UI vocabulary where the literal translation is not what the interface calls the thing.
- Publish the language in Shopify Admin → Settings → Languages.
⛔ Two rules that cost real time to learn:
- Runtime keys (
| tin markup) belong inlocales/*.json; schema keys (t:inside{% raw %}{% schema %}{% endraw %}) belong inlocales/*.schema.json. Mixing them produces aTranslationKeyExistserror at push. - A block heading set in a JSON template is not in a locale file at all. It sits as a value inside
templates/*.jsonand is translated through Shopify’s translatable-resources API, not by editing a file. It is the blind spot of every file-based translation tool.
⚠️ A machine translation service’s free tier is usually measured in characters per month; one language of this theme is roughly 46k characters, so a handful of languages will exhaust a 500k monthly allowance.
Chapter 16 — App compatibility — integrating apps with Hyprism.