shopify i18n basics

Locale File Structure

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "shopify i18n basics" with this command: npx skills add sarojpunde/shopify-dev-toolkit-claude-plugins/sarojpunde-shopify-dev-toolkit-claude-plugins-shopify-i18n-basics

Shopify i18n Basics

Locale File Structure

Shopify themes use JSON files in the locales/ directory:

locales/ ├── en.default.json # English (default language) ├── en.default.schema.json # English schema translations ├── fr.json # French translations ├── fr.schema.json # French schema translations ├── de.json # German translations └── de.schema.json # German schema translations

File Types

  1. Content Translations (en.default.json)

Used for theme content displayed to customers:

{ "general": { "search": "Search", "cart": "Cart", "menu": "Menu", "close": "Close", "loading": "Loading...", "continue_shopping": "Continue Shopping" }, "product": { "add_to_cart": "Add to Cart", "sold_out": "Sold Out", "unavailable": "Unavailable", "price": "Price", "vendor": "Vendor" }, "cart": { "title": "Your Cart", "empty": "Your cart is empty", "subtotal": "Subtotal", "checkout": "Checkout" } }

  1. Schema Translations (en.default.schema.json)

Used for Theme Editor labels:

{ "sections": { "featured_products": { "name": "Featured Products", "settings": { "heading": { "label": "Heading", "info": "Section heading text" }, "collection": { "label": "Collection" } } } } }

Using Translations in Liquid

Basic Translation

{{ 'general.search' | t }} {{ 'product.add_to_cart' | t }} {{ 'cart.title' | t }}

Translation with Variables

{%- # In locale file -%} { "cart": { "item_count": "{{ count }} items" } }

{%- # In Liquid -%} {{ 'cart.item_count' | t: count: cart.item_count }}

Translation with HTML

{%- # In locale file -%} { "general": { "continue_html": "Continue <span>shopping</span>" } }

{%- # In Liquid -%} {{ 'general.continue_html' | t }}

Translation in Schema

{% schema %} { "name": "t:sections.featured_products.name", "settings": [ { "type": "text", "id": "heading", "label": "t:sections.featured_products.settings.heading.label" } ] } {% endschema %}

Common Translation Patterns

General UI

{ "general": { "search": "Search", "cart": "Cart", "menu": "Menu", "close": "Close", "loading": "Loading...", "buttons": { "learn_more": "Learn More", "shop_now": "Shop Now", "view_all": "View All" }, "forms": { "submit": "Submit", "email": "Email", "name": "Name", "message": "Message" } } }

Product-Specific

{ "product": { "add_to_cart": "Add to Cart", "sold_out": "Sold Out", "unavailable": "Unavailable", "in_stock": "In Stock", "out_of_stock": "Out of Stock", "price": { "from": "From {{ price }}", "regular_price": "Regular price", "sale_price": "Sale price" } } }

Cart & Checkout

{ "cart": { "title": "Cart", "empty": "Your cart is empty", "item_count": "{{ count }} items", "subtotal": "Subtotal", "shipping": "Shipping", "total": "Total", "checkout": "Checkout", "remove": "Remove" } }

Forms & Errors

{ "forms": { "contact": { "name": "Name", "email": "Email", "message": "Message", "send": "Send Message", "success": "Thank you for your message!", "error": "Please correct the errors below" } }, "errors": { "general": "An error occurred", "required_field": "This field is required", "invalid_email": "Please enter a valid email" } }

Adding New Languages

Step 1: Create Translation Files

locales/fr.json (French content):

{ "general": { "search": "Rechercher", "cart": "Panier", "menu": "Menu", "close": "Fermer" }, "product": { "add_to_cart": "Ajouter au panier", "sold_out": "Épuisé" }, "cart": { "title": "Votre panier", "empty": "Votre panier est vide", "checkout": "Commander" } }

locales/fr.schema.json (French schema):

{ "sections": { "featured_products": { "name": "Produits vedettes", "settings": { "heading": { "label": "Titre" }, "collection": { "label": "Collection" } } } } }

Step 2: Use in Liquid

The | t filter automatically uses the correct translation based on the store's language:

{%- # Automatically shows "Search" in English, "Rechercher" in French -%} <button>{{ 'general.search' | t }}</button>

Best Practices

  1. Use Clear, Descriptive Keys

{%- # Good -%} { "product": { "add_to_cart": "Add to Cart" } }

{%- # Bad -%} { "prod": { "btn1": "Add to Cart" } }

  1. Organize Logically

{ "general": { ... }, # General UI "navigation": { ... }, # Navigation items "product": { ... }, # Product-related "cart": { ... }, # Cart-related "forms": { ... } # Forms }

  1. Keep Keys Consistent Across Languages

en.default.json:

{ "product": { "add_to_cart": "Add to Cart" } }

fr.json (same structure):

{ "product": { "add_to_cart": "Ajouter au panier" } }

  1. Use Nested Objects for Clarity

{%- # Good -%} { "forms": { "contact": { "name": "Name", "email": "Email" } } }

{%- # Less clear -%} { "forms": { "contact_name": "Name", "contact_email": "Email" } }

  1. Handle Pluralization

{ "cart": { "item_count_one": "{{ count }} item", "item_count_other": "{{ count }} items" } }

{% if cart.item_count == 1 %} {{ 'cart.item_count_one' | t: count: cart.item_count }} {% else %} {{ 'cart.item_count_other' | t: count: cart.item_count }} {% endif %}

  1. Document Variables

{ "_comment": "{{ price }} will be replaced with the actual price", "product": { "from_price": "From {{ price }}" } }

  1. Avoid Hardcoding Text

{%- # Bad -%} <h2>Featured Products</h2>

{%- # Good -%} <h2>{{ 'sections.featured_products.heading' | t }}</h2>

Common Translation Keys

Navigation

{ "navigation": { "home": "Home", "shop": "Shop", "collections": "Collections", "about": "About", "contact": "Contact" } }

Accessibility

{ "accessibility": { "skip_to_content": "Skip to content", "close_menu": "Close menu", "open_menu": "Open menu", "next_slide": "Next slide", "previous_slide": "Previous slide" } }

Date & Time

{ "date": { "months": { "january": "January", "february": "February" }, "days": { "monday": "Monday", "tuesday": "Tuesday" } } }

Complete Example

locales/en.default.json:

{ "general": { "search": "Search", "cart": "Cart", "menu": "Menu" }, "product": { "add_to_cart": "Add to Cart", "from_price": "From {{ price }}" }, "cart": { "title": "Your Cart", "empty": "Your cart is empty" } }

sections/featured-products.liquid:

<section> <h2>{{ 'sections.featured_products.heading' | t }}</h2>

{%- for product in collection.products -%} <div> <h3>{{ product.title }}</h3> <p>{{ 'product.from_price' | t: price: product.price | money }}</p> <button>{{ 'product.add_to_cart' | t }}</button> </div> {%- endfor -%} </section>

Use translation keys consistently to create themes that work seamlessly in multiple languages.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

shopify workflow & tools

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

polaris-fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

shopify-api-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

shopify section patterns

No summary provided by upstream source.

Repository SourceNeeds Review