Translation Keys

Translation keys exist in JSON files and are invoked based on the user’s browser language. With a Stencil theme, you can define multiple translations for each theme based on a predefined schema.

BigCommerce does not provide translations for the theme’s content, however, you have the option of localizing your themes for desired target languages, based on the provided schema. Theme developers are not required to localize or translate a theme in order to make it work.


Translating a Theme

In order to translate a theme, you must create a JSON file for each language you choose to support and include key-value pairs for the text blocks that you choose to translate. The translated values will be displayed to visitors who have selected the corresponding language in their browser’s locale preferences.

Stencil automatically detects the Accept-Language request HTTP header from the visitor’s browser. If a Stencil theme does not contain a JSON file matching any of the visitor’s preferred browser languages, the theme will fall back to the values in the default English-language JSON file.

Stencil’s multi-language capabilities are limited to the particular key-value pairs you specify in the theme. Stencil themes do not translate content rendered from a store’s catalog database (i.e. the name of a product).

Full Support for Multiple Languages

If you want to fully support multiple languages, we recommend you set up a separate storefront for each language. This will enable you to completely customize your content (including your product catalog) for each target audience.


Required Subdirectory

Within each Stencil theme, a top level /lang/ subdirectory is reserved for localization and internationalization. This /lang/ subdirectory, as well as the /lang/en.json (which contains English-language defaults), must be present in order for a Stencil theme to properly function.

You can localize a theme by providing other appropriate .json translation files in the /lang/ subdirectory. One JSON file is required for each language that you want to support. (These can include non-U.S. versions of English, each with their own spellings.)

In these files, you would define key and values corresponding to the text blocks in your theme’s templates that you choose to translate.


The Schema

Name your translation files based on the BCP47 specification of language and region codes. For a summary of how these codes are designed, see the World Wide Web Consortium’s overview.

You can find a list of code subtags in the IANA Language Subtag Registry. These subtags are primitives that you can combine to create file names’ prefixes for individual regions. Here are some examples:

Localization file name Corresponding regional language variant Subtags used
en.json English (default file) en (English)
en-US.json American English en (English) + US (United States)
en-AU.json Australian English en (English) + AU (Australia)
fr.json French en (French)
fr-CA.json Canadian French fr (French) + CA (Canada)

For more examples of frequently-used codes, see the following linked table’s “LCID string” (middle) column: http://www.science.co.il/Language/Locale-codes.asp.


Localization File Structure

The .json translation files have a straightforward structure of key-value pairs. Here is an example, from Cornerstone’s en.json file:

"welcome_back": "Welcome back, {name}"

Above, "welcome_back" is an arbitrary key name for a welcome message. The string "Welcome back, {name}" is its assigned value for English-language stores.

If you design your theme’s storefront pages to refer to this message by its generic key name "welcome_back", they can pass its localized value in other languages, as that value is defined in each language’s .json file.

Key-value pairs are grouped into objects, as you can see in this longer example below:

Objects with translation key-value pairs
{
   "header": {
    "welcome_back": "Welcome back, {name}"
   },
   "prelaunch": {
    "coming_soon": "Coming Soon",
    "intro": "This store will be launching shortly. Please visit again!"
   },
   "cart": {
    "items": "{NUM, plural, =0{(0 items)} one {(# item)} other {(# items)}}",
    "label": "Cart",
    "is_empty": "Your cart is empty",
     "coupon_code": "Coupon Code",
    "gift_certificate": "Gift Certificate",
    "freeshipping": "Free Shipping",
    "shipping_peritem": "Per Item Shipping",
    "shipping_estimator": {
        "add_info": "Add Info",
        "select_a_country": "Select a Country",
        "select_a_state": "Select a State",
        "estimate_shipping": "Estimate Shipping"
    }
   },
}

Invoking a Translation Key

Once keys and values are defined in the .json translation files, you can invoke dynamic translation strings using the the custom {{lang}} Handlebars helper. To invoke a defined translation key, you would follow this generic format:

Syntax to invoke a defined translation key
{{lang "translation.key" optionalVariable=”someValue”}}

Here is how this works. In a non-internationalized theme, a storefront page might include a string like this:

Non-internationalized theme example
<a href="{{ urls.account }}">Welcome Back <span>{{ customer.name }}</span></a>

The corresponding internationalized version would substitute the text with the fully dynamic {{ lang }} Handlebars helper shown below:

<a href="{{ urls.account }}">{{ lang "header.welcome_back" name=customer.name }}</a>

File Permissions Required

Be sure to set permission 644 (rw-r–r–) on any new translation files that you add. Without these permissions, running your theme locally will fail, with multiple error messages. Bundling your theme will also fail, blocking its upload to a store.


Localization Example

Here is an example based on cornerstone/templates/components/cart/shipping-estimator.html within Cornerstone.

In the excerpt below, each highlighted {{lang...}} statement is a Handlebars helper. Each of the statements abstracts the message indicated by its (English-language) key name to enable internationalization of that message:

<div class="shipping-estimator" style="display: none;">
    <form class="estimator-form">
      <button class="shipping-estimate-hide">{{lang 'cancel'}}</button>
      <select name="shipping-country">
      <option>{{lang 'cart.shipping_estimator.select_a_country'}}</option>
      {{#each countries}}
          <option value="{{id}}" {{#if selected}}selected="selected"{{/if}}>
                {{name}}
          </option>
      {{/each}}
      </select>
      <select name="shipping-state">
      <option>{{lang 'cart.shipping_estimator.select_a_state'}}</option>
      {{#each states}}
          <option value="{{id}}" {{#if selected}}selected="selected"{{/if}}>
              {{name}}
          </option>
      {{/each}}
      </select>
      <input type="text" name="shipping-zip" value="{{selected_zip}}">
      <button class="shipping-estimate-submit">{{lang 'cart.shipping_estimator.estimate_shipping'}}
      </button>
    </form>
    <div class="shipping-quotes"></div>
</div>

In the excerpts below, you can see that the default theme’s /lang/en.json file includes matches, and value definitions, for each of the translation keys in the Handlebars helpers above.

{
  "header": {
        "welcome_back": "Welcome back, {name}"
  },
  // ...
      "label": "Cart",
        "is_empty": "Your cart is empty",
        "coupon_code": "Coupon Code",
        "gift_certificate": "Gift Certificate",
        "freeshipping": "Free Shipping",
        "shipping_peritem": "Per Item Shipping",
      "shipping_estimator": {
            "add_info": "Add Info",
          "select_a_country": "Select a Country",
          "select_a_state": "Select a State",
          "estimate_shipping": "Estimate Shipping"
      }
  },
  "common": {
        "currency_converter": "Currency Converter",
        "newsletter_signup": "Sign up for our newsletter",
        "form_submit": "Submit",
        "required": "Required",
        "email_address": "Email Address",
      "edit": "Edit",
      "no": "No",
      "yes": "Yes",
      "cancel": "Cancel",
      "share": "Share",
      "delete": "Delete",
      "public": "Public",
        "private": "Private",
        "view_all": "View All",
        "paginator": {
            "page_of": "Page {current} of {total}"
      },
      // ...

Translation files for other languages would use the same format to define these keys’ values in their respective languages.


Resources

Additional Resources