-
Notifications
You must be signed in to change notification settings - Fork 2
Translation Generator
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
This generator only takes a single argument at this time; the locale
you want to generate a translation for:
yo skatejs:translation en-US
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
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>
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
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.
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');
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.
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.