Theme Locale Files

How a theme ships its translations: locales/*.json, the default locale, and resolution.

A theme owns its own strings. Every piece of text a section renders through the t filter — and every editor-facing setting label — comes from locale files the theme ships in its bundle. The platform provides the mechanism (the files' contract, the t filter, the editor lookup); the theme author provides the strings. Platform locale files are never involved: your theme's text is yours to write and yours to translate.

The file layout#

text
locales/
  en.json           storefront strings — what {{ 'key' | t }} renders
  en.schema.json    editor labels — what the merchant sees on your settings
  fr.json
  fr.schema.json
  de.json
  de.schema.json

Two files per locale, both flat JSON objects of string → string. .json is the storefront namespace: the shopper-facing strings sections render via t. .schema.json is the schema namespace: translations for editor labels, resolved when a merchant edits your sections in their admin language. Files live directly under locales/ (no subfolders), named by the locale code (en.json, pt-BR.json). The theme's default locale is declared in theme.json (default_locale) — there is no special ".default" filename.

json
{
  "add_to_cart": "Add to cart",
  "sold_out": "Sold out",
  "greeting": "Welcome back, {{ name }}!"
}

Keys are yours to name (dots are allowed in keys — "cart.title" is one flat key, not nesting). Values are strings; a value may contain {{ placeholder }} slots filled by t's named arguments.

Resolution#

For a buyer whose locale is L, {{ 'key' | t }} resolves in exactly this order: 1) locales/L.json — the buyer's locale, if the theme ships it; 2) locales/<default_locale>.json — the theme's declared default; 3) neither has the key → the literal text "translation missing: L.key" renders. The marker is deliberate: a missing string is visible in preview and review instead of silently blank, and a shipped store never crashes over a translation. Ship your default-locale file complete; add other locales as you translate them — a locale you don't ship simply falls back to your default.

Merchant overrides#

Merchants can override the VALUE of any string from their admin without touching your theme — the platform stores those overrides separately and layers them over your files at render. Your files stay pristine (a theme update never fights a merchant's wording), and the KEYS are always yours: merchants can reword what you declared, never add or remove strings. If you remove a key in an update, any override of it simply stops applying.

Validation at import#

Rule

1

Every file under locales/ must parse as flat string→string JSON.

2

File names must be a valid locale + .json or .schema.json, directly under locales/.

3

The default locale declared in theme.json should ship its files — that is the floor every buyer falls back to.