Back to Spree

Localization

docs/api-reference/store-api/localization.mdx

5.4.27.6 KB
Original Source

The Store API supports multi-language, multi-currency, and market-aware responses. Use request headers to control the locale, currency, and country for each request.

Headers

HeaderExampleDescription
X-Spree-LocalefrLanguage for translated content (product names, descriptions, etc.)
X-Spree-CurrencyEURCurrency for prices and totals
X-Spree-CountryFRCountry ISO code for market resolution

Client-Level Defaults

Set locale, currency, and country once at initialization — all subsequent requests use these defaults:

typescript
import { createClient } from '@spree/sdk'

const client = createClient({
  baseUrl: 'https://api.mystore.com',
  publishableKey: 'pk_xxx',
  locale: 'fr',
  currency: 'EUR',
  country: 'FR',
})

// All requests use fr/EUR/FR automatically
const products = await client.products.list()

Update defaults at any time:

typescript
client.setLocale('de')
client.setCurrency('EUR')
client.setCountry('DE')

Per-Request Overrides

Override client defaults for individual requests:

<CodeGroup>
typescript
const products = await client.products.list({}, {
  locale: 'fr',
  currency: 'EUR',
  country: 'FR',
})
bash
curl -G 'http://localhost:3000/api/v3/store/products' \
  -H 'X-Spree-Api-Key: pk_xxx' \
  -H 'X-Spree-Locale: fr' \
  -H 'X-Spree-Currency: EUR'
</CodeGroup>

Country and Markets

The X-Spree-Country header resolves the customer's market, which influences default locale and currency. Markets allow you to configure different pricing, languages, and product availability per region.

<CodeGroup>
typescript
// Setting country automatically resolves the market
const products = await client.products.list({}, {
  country: 'DE', // Resolves German market → EUR, de locale
})
bash
curl -G 'http://localhost:3000/api/v3/store/products' \
  -H 'X-Spree-Api-Key: pk_xxx' \
  -H 'X-Spree-Country: DE'
</CodeGroup>

When a market is resolved from the country:

  1. The market's default locale is used (unless overridden by X-Spree-Locale)
  2. The market's default currency is used (unless overridden by X-Spree-Currency)

You can also resolve the market explicitly using the Markets API:

<CodeGroup>
typescript
// Resolve which market applies for a country
const market = await client.markets.resolve('DE')
// => { id: "mkt_xxx", name: "Europe", currency: "EUR", default_locale: "de", ... }

// Then set the client defaults
client.setLocale(market.default_locale)
client.setCurrency(market.currency)
client.setCountry('DE')
bash
# Resolve market by country
curl 'http://localhost:3000/api/v3/store/markets/resolve?country=DE' \
  -H 'X-Spree-Api-Key: pk_xxx'
</CodeGroup>

Resolution Priority

Each value is resolved in the following order:

Locale

  1. X-Spree-Locale header
  2. locale query parameter
  3. Market default locale (if country is set)
  4. Store default locale

Currency

  1. X-Spree-Currency header
  2. currency query parameter
  3. Market default currency (if country is set)
  4. Store default currency

Market

  1. X-Spree-Country header
  2. country query parameter
<Note> The locale and currency must be supported by the current store. If an unsupported value is provided, the API falls back to the store's default. </Note>

Translated Content

When a locale is set, all translatable fields are returned in the requested language. This includes product names, descriptions, category names, and other content managed through translations.

<CodeGroup>
typescript
// English (default)
const enProduct = await client.products.get('spree-tote')
console.log(enProduct.name) // "Spree Tote"

// French
const frProduct = await client.products.get('spree-tote', {}, {
  locale: 'fr',
})
console.log(frProduct.name) // "Sac Spree"
bash
# English
curl 'http://localhost:3000/api/v3/store/products/spree-tote' \
  -H 'X-Spree-Api-Key: pk_xxx' \
  -H 'X-Spree-Locale: en'

# French
curl 'http://localhost:3000/api/v3/store/products/spree-tote' \
  -H 'X-Spree-Api-Key: pk_xxx' \
  -H 'X-Spree-Locale: fr'
</CodeGroup>

If a translation doesn't exist for the requested locale, the API falls back to the store's default locale automatically.

Currency-Aware Prices

All price fields in the response reflect the requested currency:

<CodeGroup>
typescript
// USD prices
const usdProduct = await client.products.get('spree-tote', {}, {
  currency: 'USD',
})
console.log(usdProduct.price) // { amount: "15.99", currency: "USD" }

// EUR prices
const eurProduct = await client.products.get('spree-tote', {}, {
  currency: 'EUR',
})
console.log(eurProduct.price) // { amount: "14.49", currency: "EUR" }
bash
# USD prices
curl 'http://localhost:3000/api/v3/store/products/spree-tote' \
  -H 'X-Spree-Api-Key: pk_xxx' \
  -H 'X-Spree-Currency: USD'

# EUR prices
curl 'http://localhost:3000/api/v3/store/products/spree-tote' \
  -H 'X-Spree-Api-Key: pk_xxx' \
  -H 'X-Spree-Currency: EUR'
</CodeGroup>

Discovering Available Options

Use the dedicated endpoints to discover which markets, countries, locales, and currencies are available. These are derived from your store's markets configuration.

Markets

List all markets to get the full picture of regions, currencies, and supported locales:

<CodeGroup>
typescript
const { data: markets } = await client.markets.list()
// [
//   { id: "mkt_xxx", name: "North America", currency: "USD", default_locale: "en",
//     supported_locales: ["en", "es"], countries: [{ iso: "US", ... }, { iso: "CA", ... }] },
//   { id: "mkt_yyy", name: "Europe", currency: "EUR", default_locale: "de",
//     supported_locales: ["de", "en", "fr"], countries: [{ iso: "DE", ... }, { iso: "FR", ... }] },
// ]
bash
curl 'http://localhost:3000/api/v3/store/markets' \
  -H 'X-Spree-Api-Key: pk_xxx'
</CodeGroup>

Countries

List all countries or countries within a specific market. Each country includes its market's currency and supported locales:

<CodeGroup>
typescript
// All countries across all markets
const { data: countries } = await client.countries.list()

// Countries in a specific market (useful for checkout address forms)
const { data: marketCountries } = await client.markets.countries.list('mkt_xxx')

// Get a single country with states
const usa = await client.countries.get('US', {
  expand: ['states'],
})
console.log(usa.states) // [{ abbr: "CA", name: "California" }, ...]
bash
# All countries
curl 'http://localhost:3000/api/v3/store/countries' \
  -H 'X-Spree-Api-Key: pk_xxx'

# Countries in a specific market
curl 'http://localhost:3000/api/v3/store/markets/mkt_xxx/countries' \
  -H 'X-Spree-Api-Key: pk_xxx'

# Get a country with states
curl 'http://localhost:3000/api/v3/store/countries/US?expand=states' \
  -H 'X-Spree-Api-Key: pk_xxx'
</CodeGroup>

Locales

<CodeGroup>
typescript
const { data: locales } = await client.locales.list()
// [{ code: "en", name: "English" }, { code: "fr", name: "French" }, ...]
bash
curl 'http://localhost:3000/api/v3/store/locales' \
  -H 'X-Spree-Api-Key: pk_xxx'
</CodeGroup>

Currencies

<CodeGroup>
typescript
const { data: currencies } = await client.currencies.list()
// [{ iso_code: "USD", name: "US Dollar", symbol: "$" }, { iso_code: "EUR", name: "Euro", symbol: "€" }, ...]
bash
curl 'http://localhost:3000/api/v3/store/currencies' \
  -H 'X-Spree-Api-Key: pk_xxx'
</CodeGroup>