# Localization Finqu themes support multiple languages through JSON files in the `locales/` directory. ## Storefront translations Each language needs a locale file: ``` locales/ en.json fi.json sv.json ``` Use translation keys in your Liquid templates: ```liquid {{ 'general.add_to_cart' | t }} ``` Keys are nested in the JSON file: ```json { "general": { "add_to_cart": "Add to cart" } } ``` The active language comes from the customer's locale (`request.locale`). ## Schema translations Section, block, and setting labels shown in the **theme designer** can be translated separately from storefront copy using schema locale files: ``` locales/ en.json en.schema.json fi.json fi.schema.json ``` | File | Purpose | |------|---------| | `{lang}.json` | Strings customers see on the storefront | | `{lang}.schema.json` | Labels merchants see in the designer (section names, setting labels, block titles, preset names) | At runtime, schema translations are merged into the corresponding locale for the storefront. You do not need to duplicate schema labels inside `fi.json` unless the same string is also used on the storefront. ### Translation keys (`t:`) In schema JSON (sections, blocks, `settings_schema.json`, and `settings_data.json`), reference schema locale files with a `t:` prefix: ```json { "type": "checkbox", "id": "showPromotion", "label": "t:blocks.product-title-price.settings.showPromotion.label" } ``` The path after `t:` maps to nested keys in `{lang}.schema.json` using dot notation: ```json { "blocks": { "product-title-price": { "settings": { "showPromotion": { "label": "Näytä tarjous" } } } } } ``` **Rules:** - Use **nested JSON objects**, not flat keys like `"blocks.foo.label": "..."`. - Keys are **case-sensitive** — `product-template` and `PRODUCT-TEMPLATE` are different paths. - If a key is missing in the active language, Finqu falls back to `en.schema.json`. - On the **storefront**, `t:` values are resolved when Liquid reads setting values. - In the **theme designer**, `t:` values are resolved when schemas and preset data are loaded for the active preview language. ### Inline localization objects You can also localize schema labels inline with language-keyed objects: ```liquid {% schema %} { "name": { "en": "Hero banner", "fi": "Hero-banneri" }, "settings": [ { "type": "text", "id": "heading", "label": { "en": "Heading", "fi": "Otsikko" } } ] } {% endschema %} ``` Both formats work in the designer: | Format | Where translations live | Best for | |--------|-------------------------|----------| | `t:sections.hero.name` | `locales/{lang}.schema.json` | Large themes, many sections/blocks | | `{ "en": "...", "fi": "..." }` | Inline in the schema file | Small schemas, few labels | You can mix both in the same theme. ## What is translated in the designer The theme designer resolves schema translations for the **preview language** (language picker in the designer navbar, stored in the `fnq-designer-locale` cookie). When the preview language changes, section, block, and theme labels reload in that language. | UI area | Source | Supported formats | |---------|--------|-------------------| | Section sidebar titles | Section schema | `t:` keys, inline objects | | Block sidebar titles | Block schema | `t:` keys, inline objects | | Setting labels and info text | Section/block/theme schema | `t:` keys, inline objects | | Section add dialog preset variants | Section schema `presets` | Locale maps, arrays, `t:` keys, inline objects | | Block add dialog preset variants | Block schema `presets` | Locale maps, arrays, `t:` keys, inline objects | | Theme style presets | `config/settings_data.json` → `presets` | Locale snapshots, `t:` keys, inline objects | | Style editor / style picker presets | `settings_schema.json` setting `presets` | Locale maps, `t:` keys, inline objects | | Section and block categories | `settings_schema.json` | `t:` keys, inline objects | ## Presets Presets ship default configuration for themes, sections, and blocks. To target different markets, define **full preset content per locale** — not just translated labels. Finqu resolves presets for the active language: 1. **Storefront** — customer's locale (`request.locale`) 2. **Designer** — preview language from the navbar (`fnq-designer-locale` cookie) Resolution order: active locale → `default` → first available entry. Preset `settings` can include rich text, images, block instances, and layout values. Values inside presets can also use `t:` keys; those resolve when the preset is loaded for the active language. ### Locale-keyed preset maps The primary format groups preset variants by locale code: ```json "presets": { "fi": [ { "name": "t:sections.hero.presets.default.name", "settings": { "heading": "Tervetuloa", "body": "

Suomenkielinen rich text -sisältö

" } } ], "default": [ { "name": "Default hero", "settings": { "heading": "Welcome", "body": "

English rich text content

" } } ] } ``` When a Finnish customer views the storefront, Finqu uses the `fi` preset settings. Other locales fall back to `default`. You can also use a flat array when one configuration is enough for all languages: ```json "presets": [ { "name": "t:sections.two-columns.presets.columns-2.name", "settings": { "left_column_width": 50, "right_column_width": 50 } } ] ``` ### Theme-level presets Whole-store style variants live in `config/settings_data.json`. Each preset can include locale-specific snapshots: ```json { "presets": { "minimal": { "id": "minimal", "name": "t:presets.minimal.name", "default": { "settings": { }, "templates": { }, "sections": [ ] }, "fi": { "settings": { }, "templates": { }, "sections": [ ] } } } } ``` When a merchant picks or previews a theme preset, Finqu loads the snapshot for the active locale. Preset names still resolve via `t:` keys or inline `{ en, fi }` objects: ```json { "presets": { "minimal": { "name": "Minimalistinen" } } } ``` ### Section and block schema presets Section and block schemas use locale-keyed preset maps to ship market-specific defaults — copy, rich text, images, and layout together: ```liquid {% schema %} { "name": "t:sections.footer.name", "presets": { "fi": [ { "settings": { "heading": "Ota yhteyttä", "body": "

Suomenkielinen sisältö

" } } ], "default": [ { "settings": { "heading": "Contact us", "body": "

English content

" } } ] } } {% endschema %} ``` When a merchant adds the section or block, the designer applies the preset for the current preview language. For multiple layout variants within one locale, each locale entry is an array of preset objects: ```json "presets": { "default": [ { "name": "Columns 2", "settings": { "left_column_width": 50 } }, { "name": "Columns 3", "settings": { "left_column_width": 33 } } ], "fi": [ { "name": "Sarakkeet 2", "settings": { "left_column_width": 50 } }, { "name": "Sarakkeet 3", "settings": { "left_column_width": 33 } } ] } ``` ### Setting-level presets Theme settings with `style-editor` or `style-picker` can wrap style presets by locale: ```json { "type": "style-editor", "id": "buttons", "presets": { "fi": { "primary": { "name": "t:settings.buttons.presets.primary.name", "default": { "border_radius": 0 } } }, "default": { "primary": { "name": "Primary", "default": { "border_radius": 4 } } } } } ``` Or use a single id-keyed map when styles are the same across markets: ```json { "type": "style-editor", "id": "buttons", "presets": { "primary": { "name": "t:settings.buttons.presets.primary.name", "default": { } } } } ``` ## Example `locales/fi.schema.json` ```json { "sections": { "hero": { "name": "Hero-banneri", "settings": { "heading": { "label": "Otsikko" } } }, "product-template": { "name": "Tuotesivu" } }, "blocks": { "product-page-title": { "name": "Tuotteen otsikko", "settings": { "showVendor": { "label": "Näytä valmistaja" } } } }, "presets": { "minimal": { "name": "Minimalistinen" } } } ``` Referenced from schema as: - `"name": "t:sections.hero.name"` - `"label": "t:blocks.product-page-title.settings.showVendor.label"` - `"name": "t:presets.minimal.name"` ## Best practices - Keep storefront copy in `{lang}.json` and designer labels in `{lang}.schema.json` or inline schema objects. - Use locale-keyed preset maps (`fi`, `default`, etc.) to ship market-specific defaults — rich text, images, and layout together. - Prefer `t:` keys inside preset `name` fields and `{lang}.schema.json` when labels repeat across locales. - Use inline `{ en, fi }` objects for small schemas or few labels. - Ship a locale file for every language your theme claims to support. - Use the same language codes as your store's enabled locales (`en`, `fi`, `sv`, etc.). - Keep translation key paths stable — use preset slugs and setting ids, not array indexes, in `t:` paths where possible. - Test the designer with the preview language picker, not only the merchant UI language. - Test the storefront with the store locale picker or `localization` form on a deployed store. ## Related articles - [Theme Structure](/build-with-finqu/liquid-themes/theme-structure) - [Settings](/build-with-finqu/liquid-themes/settings) - [Sections](/build-with-finqu/liquid-themes/sections)