spree-i18n
Localize a Spree application — the `spree_i18n` gem with 60+ locale packs, the v5.4+ Translations Center for product/CMS content (CSV import/export), Rails i18n basics applied to Spree (translation files, locale switching, pluralization, interpolation), per-Market locale routing in the headless storefront, RTL languages, and translating extensions. Use when localizing a Spree store, adding a new locale, or building i18n-aware extensions.
Best use case
spree-i18n is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Localize a Spree application — the `spree_i18n` gem with 60+ locale packs, the v5.4+ Translations Center for product/CMS content (CSV import/export), Rails i18n basics applied to Spree (translation files, locale switching, pluralization, interpolation), per-Market locale routing in the headless storefront, RTL languages, and translating extensions. Use when localizing a Spree store, adding a new locale, or building i18n-aware extensions.
Teams using spree-i18n should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/spree-i18n/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How spree-i18n Compares
| Feature / Agent | spree-i18n | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Localize a Spree application — the `spree_i18n` gem with 60+ locale packs, the v5.4+ Translations Center for product/CMS content (CSV import/export), Rails i18n basics applied to Spree (translation files, locale switching, pluralization, interpolation), per-Market locale routing in the headless storefront, RTL languages, and translating extensions. Use when localizing a Spree store, adding a new locale, or building i18n-aware extensions.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Spree i18n & Localization
## Before writing code
**Fetch live docs**:
1. Fetch https://spreecommerce.org/docs/developer/core-concepts/translations for the v5+ translation model.
2. Fetch https://github.com/spree-contrib/spree_i18n (README) for the current locale-pack inventory.
3. Cross-reference https://guides.rubyonrails.org/i18n.html for Rails-side i18n basics.
4. Check the v5.4 announcement for Translations Center features.
5. Verify which locales ship vs. which require the `spree_i18n` gem on top of `spree`.
## Conceptual Architecture
### Two Layers of Localization
| Layer | What it translates |
|-------|--------------------|
| **`spree_i18n` gem** | UI labels — admin chrome, checkout strings, error messages, attribute names |
| **Translations Center (v5.4+)** | Per-record content — product names, descriptions, taxon names, CMS page bodies |
Both layers cooperate — `spree_i18n` localizes the UI shell; Translations Center localizes the *data inside* the shell.
### `spree_i18n` Inventory
Provides translation YAML files for 60+ locales (verify against the live gem). Add to Gemfile:
```ruby
gem 'spree_i18n'
```
Locales include English, Spanish, French, German, Italian, Portuguese (BR + PT), Dutch, Polish, Czech, Russian, Ukrainian, Japanese, Korean, Chinese (Simplified + Traditional), Arabic, Hebrew, Turkish, Hindi, and many more.
### Setting Available and Default Locales
```ruby
# config/application.rb
config.i18n.available_locales = %i[en de fr es it]
config.i18n.default_locale = :en
config.i18n.fallbacks = true
```
Per-Store locale (v5+):
```ruby
Spree::Store.default.update!(default_locale: 'de', supported_locales: 'en,de,fr')
```
### Locale Switching in Requests
In the storefront (Next.js), locale is part of the URL: `/de/products/...`. In Rails admin, locale comes from `current_user.locale` or a `?locale=de` param.
```ruby
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :set_locale
def set_locale
I18n.locale = params[:locale] || current_store.default_locale || I18n.default_locale
end
def default_url_options
{ locale: I18n.locale }
end
end
```
### Translations Center (v5.4+)
For content stored in DB (product names, descriptions, taxon labels, CMS pages, blog posts), Spree v5.4+ provides the **Translations Center** — an admin UI + CSV import/export to manage per-record translations.
The underlying mechanism is **Mobility** (or similar — verify the gem Spree uses currently) which stores translations in JSON columns or sidecar tables:
```ruby
product.name # current locale
I18n.with_locale(:de) { product.name } # German
product.name_translations # { 'en' => 'Tee', 'de' => 'T-Shirt' }
```
### CSV Import/Export Flow
1. Admin → Translations → Export → choose models + locales → download CSV
2. Send to translators (or feed to a translation service)
3. Re-import → Spree updates per-record translations
4. Background job (Sidekiq) processes large imports
### Per-Market Locale Routing (Headless)
The Next.js storefront's market routing handles locale:
```
/us/en/products/classic-tee -> US market, English
/de/de/produkte/classic-tee -> DE market, German
/eu/fr/produits/classic-tee -> EU market, French
```
Routes are localizable — the storefront generates language-specific slugs.
### RTL Languages
Arabic, Hebrew, Persian. Tailwind 4 has built-in RTL support via `dir="rtl"` on the `<html>` element. The Spree storefront includes RTL CSS variants — verify on the current release.
```html
<html lang="ar" dir="rtl">
```
### Date / Currency / Number Formatting
Use Rails' built-in helpers:
```ruby
I18n.l(order.created_at, format: :short) # localized date
number_to_currency(product.price, locale: I18n.locale)
```
### Translating an Extension
```yaml
# config/locales/en.yml
en:
spree_my_extension:
products:
featured_label: "Featured"
out_of_stock: "Currently unavailable"
```
```erb
<%= t('spree_my_extension.products.featured_label') %>
```
For other locales, ship parallel YAML files (`de.yml`, `fr.yml`).
## Implementation Guidance
### Adding a New Locale to an Existing Store
```bash
bundle add spree_i18n
```
```ruby
# config/application.rb
config.i18n.available_locales = config.i18n.available_locales + [:ja]
```
```ruby
# In admin or via console
Spree::Store.default.update!(supported_locales: 'en,ja')
```
Then translate per-record content via Translations Center.
### Translating Validation Messages
Spree's validation messages live in `spree_i18n`'s locale files. Override for a specific message:
```yaml
# config/locales/en.yml
en:
errors:
messages:
blank: "is required"
activerecord:
errors:
models:
spree/order:
attributes:
email:
blank: "We need your email to contact you"
```
### Localizing Email Templates
```ruby
# app/mailers/spree/order_mailer.rb (or decorator)
def confirm_email(order, resend = false)
@order = order
I18n.with_locale(order.user&.locale || order.store.default_locale) do
mail(to: @order.email, subject: t('.subject', store: @order.store.name))
end
end
```
### Translating Product Names Programmatically
```ruby
product.name_translations = { 'en' => 'Classic Tee', 'de' => 'Klassisches T-Shirt' }
product.save!
```
(Verify the exact column / method name for translation storage in your version.)
### URL Slug Translations
For SEO, taxons and products can have per-locale slugs:
```ruby
taxon.slug_translations # { 'en' => 'shirts', 'de' => 'hemden' }
```
The storefront's router resolves `/de/hemden/...` to the right taxon.
### Pluralization
```yaml
en:
cart:
items:
one: "1 item"
other: "%{count} items"
```
```erb
<%= t('cart.items', count: @cart.line_items.sum(:quantity)) %>
```
For locales with complex plural rules (Polish, Russian, Arabic), Rails i18n + the cldr-rules backend handles them — verify the gem.
### Testing Translations
```ruby
RSpec.describe 'Checkout', type: :system do
context 'in German' do
before { I18n.locale = :de }
after { I18n.locale = :en }
it 'shows German UI' do
visit '/de/cart'
expect(page).to have_content('Warenkorb')
end
end
end
```
### Common Pitfalls
- **Forgetting to add the locale to `available_locales`** — Rails falls back to default silently.
- **Hardcoding strings in extension views** — extracts run finds untranslated ones; lint with `i18n-tasks`.
- **Per-store locales not enforced** — `Store#supported_locales` is descriptive; you still need URL routing to enforce.
- **CSV imports overwriting recent edits** — back up before bulk import.
- **RTL CSS bleeding into LTR sections** — test mixed-direction layouts.
- **Date formats inconsistent** — define `:short`, `:long`, `:default` formats per locale.
- **Slugs not translated** — fine for English-only sites, breaks SEO for multi-language.
- **Translation Center disabled** — older Spree versions don't have it; users hit a 404.
Always cross-reference `spree_i18n` for locale-pack coverage and the v5.4 Translations Center docs for per-record translation patterns.Related Skills
spree-upgrades
Upgrade a Spree application — version-to-version migration paths (v4 → v5 is a major rewrite; v5.x → v5.y are simpler), Gemfile pinning strategy, decorator brittleness across versions, deprecated gems to remove (`spree_auth_devise`, `deface`, `spree_backend`), API v2 → v3 migration via `spree_legacy_api_v2`, admin Bootstrap → Tailwind transition, the upgrade guide workflow, and rollback strategy. Use when planning a Spree upgrade or auditing technical debt blocking one.
spree-typescript-sdk
Build storefronts and integrations using `@spree/sdk` — the official TypeScript SDK for Spree's API v3 (v5.4+). Covers installation, the resource-builder pattern (`spree.products.list`, `spree.checkout.create`, etc.), Zod schema validation, server-only auth (httpOnly JWTs, never exposing API keys), error handling, typing customizations, and pinning SDK versions to backend Spree releases. Use when integrating Spree into a Next.js / Node.js / TypeScript project.
spree-testing
Test Spree applications and extensions with RSpec — `spree_dev_tools` gem (v5.2+) for factories and helpers, FactoryBot patterns (prefer `build` over `create`), Capybara feature specs, controller/request specs, testing decorators and subscribers, dummy app for extension testing, system specs for the Hotwire admin, and CI patterns. Use when writing Spree tests, setting up CI, or refactoring slow specs.
spree-shipping-fulfillment
Build and customize Spree's shipping and fulfillment — ShippingMethod, ShippingCategory, Zone/ZoneMember, ShippingRate, the Stock::Estimator service, StockLocation/StockItem/StockMovement, multi-shipment orders, ShippingCalculator classes (FlatRate, FlatPercentItemTotal, PerItem, FlexiRate), shipment state machine, returns (ReturnAuthorization → CustomerReturn → Reimbursement → Refund), and integrating carrier APIs (UPS, FedEx, ShipStation). Use when configuring shipping rules, building fulfillment integrations, or debugging shipping-rate calculations.
spree-setup
Bootstrap a new Spree project — `create-spree-app` CLI (v5.2+), `spree-starter` Rails backend, the Next.js storefront repo, `bin/rails g spree:install`, sample data, Docker Compose, and the PostgreSQL + Redis + Sidekiq prerequisites. Use when starting a new Spree project from scratch or onboarding an existing repo.
spree-security
Secure a Spree deployment — Rails credentials and env-var hygiene, Devise auth (Spree v5 ships it in-core; `spree_auth_devise` is archived), CanCanCan authorization rules, Doorkeeper OAuth2 scopes, Storefront publishable key vs admin API key, webhook HMAC verification, OWASP Top 10 for Rails (mass assignment, CSRF, SQL injection via Ransack, XSS, IDOR through prefixed IDs), PCI scope (Spree never touches raw cards thanks to gateway tokenization), and multi-store data isolation. Use when auditing a Spree app, hardening a deploy, or addressing a security incident.
spree-promotions
Build and customize Spree's promotions engine — Promotion + PromotionRule + PromotionAction + CouponCode + Adjustment, the bundled rules (FirstOrder/ItemTotal/Product/Taxon/User/OneUsePerUser/Country/CustomerGroup/etc.), bundled actions (CreateAdjustment/CreateItemAdjustments/FreeShipping/CreateLineItems), Calculator classes, coupon batches with CSV export, the v5.1+ advanced rule-based engine, and authoring custom rules/actions/calculators. Use when modeling promotions, building discount UIs, or extending the promotions engine.
spree-performance
Profile and optimize a Spree application — N+1 queries with bullet/scout, database indexing strategy for Spree's polymorphic associations, Rails fragment + Russian doll caching, ActiveStorage variant pre-generation, Sidekiq queue tuning, MeiliSearch vs Postgres FTS tradeoffs, Puma worker/thread sizing, CDN strategy for catalog pages, asset precompile time, and load testing. Use when Spree is slow, the database is hot, or you're preparing for a traffic spike (Black Friday, launch).
spree-payments
Integrate payment gateways with Spree — PaymentMethod model, the v5.4+ PaymentSession provider-agnostic checkout flow, Stripe via `spree_stripe` (Apple/Google Pay, Link, Connect for marketplaces), Adyen via `spree_adyen`, PayPal via `spree_paypal_checkout`, StoreCredit / GiftCard as payment methods, refunds, payment state machine, and authoring a custom gateway. Use when wiring a payment integration, handling webhooks from a gateway, or debugging payment-state issues.
spree-multi-store
Configure Spree for multi-store and multi-region commerce — one Rails install running many `Store` records, the v5.4+ `Market` model (currency + locale + payment methods + shipping per region), what's shared vs per-store (products+inventory+customers shared; orders+payments+themes per-store), the Marketplace module (Enterprise — vendors/commission/payouts via Stripe Connect), and the Multi-tenant SaaS model. Use when planning a multi-brand or multi-region Spree deployment.
spree-legacy-api-v2
Work with Spree's legacy v2 APIs — JSON:API-style Storefront API at `/api/v2/storefront/*` and Platform API at `/api/v2/platform/*`, Doorkeeper OAuth2 (password grant for storefront, client_credentials + admin scope for platform), the `spree_legacy_api_v2` gem (required in v5+ for backward compatibility), and migration patterns to API v3. Use when maintaining a v2 client during a migration window, integrating an older partner system, or deciding when to cut over to v3.
spree-headless-storefront
Build with Spree's headless Next.js storefront — the official `spree/storefront` repo (Next.js 16 App Router with Server Actions and Turbopack, React 19 Server Components, Tailwind CSS 4, TypeScript 5, `@spree/sdk`, Sentry), server-only auth (httpOnly JWT cookies + publishable key), MeiliSearch faceted catalog, one-page checkout with Apple/Google Pay/Klarna/Affirm/SEPA, multi-region market routing, GA4 + JSON-LD SEO, and Vercel/Docker deployment. Use when forking or customizing the storefront, or evaluating headless adoption.