Skip to content
This repository has been archived by the owner on Apr 20, 2018. It is now read-only.

Translation Generator

Alex LaFroscia edited this page Mar 22, 2017 · 3 revisions

Many applications do not need to be translated into multiple languages. However, if you do (or if you like the idea of pulling your text content out of JSX) then a system to manage translations is included as part of this generator.

In order to manage these translations, this generator allows you to create YAML files that make keys to the display values. YAML is great for this because it's both easy to manipulate using automated tools, but also

Using the Generator

This generator only takes a single argument at this time; the locale you want to generate a translation for:

yo skatejs:translation en-US

Translation Subgenerator Basic Usage

This will do a few things:

  • Pull in a new utility module (src/util/translation.js)
  • Create a new translation file (translations/en-US.yml)
  • Install an additional dependency that the helper uses internally

Using the Translation Helper

In order to translate some strings, we first need to create ourselves a translation helper function, which we will address as t.

t is created by calling createTranslationHelper, which is imported from src/util/translation.js. You give createTranslationHelper the locale you want to translate for, and the resulting t function takes the translation keys. If this seems a little magical, I suggest reading up on Closures. Creating t in this way avoids needing to store the current locale in a specific way; see below for a few approaches.

A basic example of using it is as follows:

import createTranslationHelper from '../../util/translation.js';

const t = createTranslationHelper('en-US');

Now, t is a function used for translating keys into en-US! If you had a YAML file at translations/en-US.yml with the following structure:

greeting: Hello World

You could use t like so:

const greeting = t('greeting');
console.log(greeting); // -> Hello World

or in JSX

<p class="greeting">
  { t('greeting') }
</p>

Working with Multiple Locales

Now, why is this actually useful? Imagine you need to localize your component for en-US and fr-FR. You might still have the en-US file shown above, but in addition, have the following content at translations/fr-FR.yml:

greeting: Bonjour le monde

You can dynamically pass the locale to createTranslationHelper; the locale passed there will be matched against the filename within translations/, and that's the file that greeting will be looked up on. This works for any number of locales that you need to support, without needing any kind of conditional logic to show the

Providing the Locale

Now that we know how to manage multiple locales, we still need to determine how we detect and provide that configuration to createTranslationHelper.

One option is create an attribute on your component, and pass it in from wherever your component is used. That might look like this:

import createTranslationHelper from '../../util/translation.js';

const { Component, h, prop } = skate;

export default class extends Component {
  static get is() {
    return 'localized-hello-world';
  }

  static get props() {
    return {
      locale: prop.string({
        attribute: true
      })
    };
  }

  renderCallback({ locale }) {
    const t = createTranslationHelper(locale);
  
    return (
      <p>
        { t('greeting') }
      </p>
    );
  }
}

This component could then be used like:

<localized-hello-world locale="en-US"></localized-hello-world>

to render the text in English, or providing locale="fr-FR" for French.

Organizing Translations

Namespacing Translation Keys

If you have a somewhat complex component, you might want to namespace your translation keys to help keep things organized. For this, you can use "dot notation" to access properties within the YAML file. With a file like this:

header:
  title: My Website

you can access that property using

t('header.title');

Naming Conventions

Generally, everything is driven from the locale identifier, a string that looks like en-US where en specifies the language, and US specifies the country. This is what you would pass into createTranslationHelper and matches the name of the file within the translations/ directory.

However, you're free to name your translations however you want; just know that whatever string you provide when you first run the generator will be the value that createTranslationHelper will expect to receive as well.

Into the Build

How do these YAML files end up in your JavaScript bundle, you may be asking? It's all thanks for the magic of Webpack.

When your code imports a .yml file, Webpack will automatically turn that YAML file into a JSON blob (thanks to the fact that YAML and JSON can be serialized to each other). Then, this JSON block is transparently converted into a module that your code can import, giving you a POJO at runtime.