Adding Translations
Add new translatable strings, use them in Liquid, and keep translations in sync.
Add a storefront string
Storefront strings are customer-facing: button labels, error messages, headings.
1. Add the key to English
Edit theme/locales/en.default.json:
{
"products": {
"product": {
"your_new_key": "Your new English string"
}
}
}2. Use it in Liquid
<label>{{ 'products.product.your_new_key' | t }}</label>With variables:
{{ 'general.pagination.page' | t: number: current_page }}With HTML (use _html suffix):
{{ 'general.password_page.admin_link_html' | t }}3. Translate
set -a && source .env && set +a
python3 scripts/translate-locales.py sync4. Verify
python3 scripts/translate-locales.py checkAdd a schema string
Schema strings are merchant-facing: section names, setting labels, help text.
1. Add the key to English
Edit theme/locales/en.default.schema.json:
{
"sections": {
"featured_collection": {
"settings": {
"show_vendor": {
"label": "Show product vendor"
}
}
}
}
}2. Reference in your schema
{
"type": "checkbox",
"id": "show_vendor",
"label": "t:sections.featured_collection.settings.show_vendor.label",
"default": false
}3. Translate and verify
set -a && source .env && set +a
python3 scripts/translate-locales.py sync
python3 scripts/translate-locales.py checkPlural strings
Define plural forms in English:
{
"sections": {
"header": {
"cart_count": {
"one": "{{ count }} item",
"other": "{{ count }} items"
}
}
}
}Shopify selects the correct form based on count:
{{ 'sections.header.cart_count' | t: count: cart.item_count }}The translation pipeline generates the correct CLDR plural categories for each language (e.g., Polish gets one, few, many, other).
Key naming conventions
Storefront (en.default.json)
{category}.{subcategory}.{key_name}| Category | Examples |
|---|---|
general | general.search.submit, general.pagination.next |
accessibility | accessibility.close, accessibility.skip_to_text |
products | products.product.add_to_cart |
sections | sections.header.cart_count |
templates | templates.cart.title |
Schema (en.default.schema.json)
sections.{section_name}.settings.{setting_id}.label
sections.{section_name}.presets.name
blocks.{block_name}.settings.{setting_id}.labelRules
snake_casefor all key segments- Suffix HTML keys with
_html - Use
_labelfor form labels,_placeholderfor placeholders,_errorfor validation - Keep keys concise:
add_to_cartnotbutton_text_for_adding_item_to_cart
Audit for hardcoded text
Use the /shopify-liquid-translator skill to find English text not wrapped in translation filters:
/shopify-liquid-translator auditIt scans .liquid files, reports hardcoded strings, and can extract them into locale files. Run sync afterward to translate the new keys.
Regenerate a corrupted file
rm theme/locales/fr.json theme/locales/fr.schema.json
set -a && source .env && set +a
python3 scripts/translate-locales.py fr
python3 scripts/translate-locales.py check frForce a complete retranslation:
python3 scripts/translate-locales.py full frCI validation
Every PR runs python3 scripts/translate-locales.py check via i18n-check.yml. If it fails, run sync locally, commit the updated locale files, and push.
Next steps
- Translation Pipeline — How the script works under the hood
- i18n Overview — Quick start and language list