How to Add a Locale, Language, and Sales Channel in the Nimara Storefront?

Expanding to a new market? This step-by-step guide shows you how to add a new sales channel in Saleor and update the Nimara codebase to support a new locale and language, which is everything you need to get it running smoothly.

We’ll use Spanish as an example, but the same structure applies to any locale or market.

This guide assumes you already have a working Saleor setup and access to the Nimara codebase.

Step 1: Add a New Sales Channel in Saleor

Start by adding a new sales channel in your e-commerce engine. Since Nimara is designed to work flexibly with platforms like Saleor, we’ll use it here to set up support for Spanish, including a dedicated channel and locale.

Head to your Saleor dashboard:

  • Configuration → Channels → Create Channel

For the Shipping Zones, I selected all of Europe, as in my case, orders will be fulfilled from a warehouse in Germany.

After setting up the new channel, assign the products you want to be available in that channel. Then jump into the Nimara codebase.

Step 2: Update Types for Locales, Languages, and Currencies

Let’s start with types. Correctly typing everything from the beginning helps avoid issues down the line. 

Head over to: apps/storefront/src/regions/types.ts

Add Spanish to the Supported Languages

Extend the SUPPORTED_LANGUAGES definition - in this example, we’re adding Spanish:

--- a/apps/storefront/src/regions/types.ts
+++ b/apps/storefront/src/regions/types.ts
@@ -10,7 +10,7 @@ import {
 /**
  * Defines available languages in the App.
  */
-export const SUPPORTED_LANGUAGES = ["us", "gb"] as const;
+export const SUPPORTED_LANGUAGES = ["us", "gb", "es"] as const;
 export type LanguageId = (typeof SUPPORTED_LANGUAGES)[number];
 
 /**

Add Spanish Locale

Locales link language to regional formatting. So we add the new locale to SUPPORTED_LOCALES:

@@ -19,6 +19,7 @@ export type LanguageId = (typeof SUPPORTED_LANGUAGES)[number];
 export const SUPPORTED_LOCALES = [
   "en-GB",
   "en-US",
+  "es-ES",
 ] as const satisfies AllLocale[];

Add Market for Spain (if it's a new sales channel)

If you added a brand new sales channel (not just a new language for an existing channel), also update SUPPORTED_MARKETS:

@@ -26,7 +27,7 @@ export const DEFAULT_LOCALE = "en-US" as const satisfies AllLocale;
 /**
  * Defines available markets in the App.
  */
-export const SUPPORTED_MARKETS = ["gb", "us"] as const;
+export const SUPPORTED_MARKETS = ["gb", "us", "es"] as const;
 export type MarketId = (typeof SUPPORTED_MARKETS)[number];
 
 /**

Add Currency

Spain uses the Euro, so we must include that by adding it to SUPPORTED_CURRENCIES:

@@ -35,6 +36,7 @@ export type MarketId = (typeof SUPPORTED_MARKETS)[number];
 export const SUPPORTED_CURRENCIES = [
   "USD",
   "GBP",
+  "EUR",
 ] as const satisfies AllCurrency[];

Step 3: Update Routing for the New Locale

Now let’s move on to the routing.ts file, located at: apps/storefront/src/i18n/routing.ts

Add a new locale prefix:

--- a/apps/storefront/src/i18n/routing.ts
+++ b/apps/storefront/src/i18n/routing.ts
@@ -9,6 +9,7 @@ import {
 
 export const localePrefixes = {
   "en-GB": "/gb",
+  "es-ES": "/es",
 } as const satisfies Record<
   Exclude<SupportedLocale, typeof DEFAULT_LOCALE>,
   string

This ensures URLs like /es/products resolve correctly.

Step 4: Register the Locale Globally

One last thing: don’t forget to add the new locale to ALL_LOCALES in: packages/domain/src/consts.ts

--- a/packages/domain/src/consts.ts
+++ b/packages/domain/src/consts.ts
@@ -256,7 +256,14 @@ export const ALLOWED_COUNTRY_CODES = [
  */
 export type AllCountryCode = (typeof ALLOWED_COUNTRY_CODES)[number];
 
-export const ALL_LOCALES = ["en", "en-US", "en-GB", "ja-JP", "pl-PL"] as const;
+export const ALL_LOCALES = [
+  "en",
+  "en-US",
+  "en-GB",
+  "ja-JP",
+  "pl-PL",
+  "es-ES",
+] as const;

Step 5: Configure a New Locale, Language, and Market

If you've typed everything correctly, this next part should be straightforward. 

Now we wire everything up in the main configuration. This step links locales to specific channels, defines the new language, and tells the app how to handle the Spanish market.

Go to:apps/storefront/src/regions/config.ts

Map the Locale to the Channel

Your editor will likely point out any missing values. Start with LOCALE_CHANNEL_MAP:

--- a/apps/storefront/src/regions/config.ts
+++ b/apps/storefront/src/regions/config.ts
@@ -13,6 +13,7 @@ export const LOCALE_CHANNEL_MAP: Record<
 > = {
   "en-GB": "gb",
   "en-US": "us",
+  "es-ES": "es",
 };

Add Language Entry

Each language has metadata: name, code, and locale. Now add your language to the LANGUAGES object:

@@ -28,6 +29,12 @@ export const LANGUAGES = {
     code: "EN_US",
     locale: "en-US",
   },
+  ES: {
+    id: "es",
+    name: "Español (España)",
+    code: "ES_ES",
+    locale: "es-ES",
+  },
 } satisfies Record<Uppercase<LanguageId>, Language>;

Define the Market

Finally, define the new market: its ID, name, default language, currency, and Saleor channel.

@@ -51,4 +58,14 @@ export const MARKETS = {
     defaultLanguage: LANGUAGES.US,
     supportedLanguages: [LANGUAGES.US],
   },
+  ES: {
+    id: "es",
+    name: "España",
+    channel: "channel-es",
+    currency: "EUR",
+    continent: "Europe",
+    countryCode: "ES",
+    defaultLanguage: LANGUAGES.ES,
+    supportedLanguages: [LANGUAGES.ES],
+  },
 } satisfies Record<Uppercase<MarketId>, Market>;

Step 6: Add Translation Files

You’ll need a translation file so the UI shows proper Spanish labels and messages.

  1. Use the existing en-GB.json file as a reference: apps/storefront/messages/en-GB.json
  2. Create a new file: apps/storefront/messages/es-ES.json
  3. and translate all values accordingly.

Step 7: Test Your Changes

Time to verify everything works as expected. Start the dev server:

pnpm dev:storefront

Then open your browser and switch to the new Spanish locale. You should see:

  • Only products assigned to the Spanish channel
  • Prices in EUR
  • Translations from es-ES.json file

You're all set! Nimara should now fully support your new Spanish market. If you need to add more markets, just repeat the same structure.

Want to Build Something More Complex?

Do you need more than multiple languages and channels? Whether you require custom pricing rules, localized content, or tailored fulfillment logic, Nimara can adjust to your needs. Just let us know, and we’ll be happy to help.

Have Questions or Ideas? 

Drop us a message on Discord - we can’t wait to hear from you!

Join Discord

Let’s engineer great products and systems together

Have a particular project in mind? Contact us help you to transform your ideas into a unique end-to-end product.