Internationalization
We're using
react-intl
version2.4.0
or compatible.
The Frontastic API hub inherently knows about internationalization. The locale of the consumer browsing the page is available, the configuration of the project (locales configured for the project and the default locale) as well as translatable data.
We support multi-language and multi-region setups which can be done in different ways depending on your requirements.
There are generally 3 things that can be translated or adapted to the target regions by other means:
- Frontastic page structure and data
- Data from external APIs (products, content, …)
- User interface strings (buttons, captions, …)
Not only can each Frontastic project be multi-lingual and multi-region, but you can also have a dedicated Frontastic project by region or language.
We can identify languages and regions by their locale. For example, en_GB
would stand for English - Great Britain. This is especially important for slight variations in languages, like the difference between English in Great Britain and the USA, but also for countries using multiple languages, like Switzerland (de_CH
for German, fr_CH
for French and it_CH
for Italian).
Frontastic page structure and data
The simplest way to set up internationalization in Frontastic is just a single language per project. If you'd like to do this, just tell us to create multiple projects, with 1 language each.
The other way to do this is to use a single project with multiple languages. This way, the structure and pages are shared across all languages. You can still overwrite pages for a certain language or locale, for example, to show different start pages to customers from Germany. You would also need to define a default language.
Or, both mechanisms can be combined:
- English website (
en_GB
) - Swiss website (
de_CH
,fr_CH
,it_CH
) with a similar page folder tree as the English website, but different pages
If a single project defines multiple locales all contents of fields configured as translatable can be translated in the Frontastic studio.
For more information on how a project can be set up, see this article.
Data from external APIs
The API hub always determines the locale of the user based on the locale configured for the current project and the accept header sent by the user's browser. For all subsequent requests, this locale will be used, except if the user chooses a different locale manually. This mechanism can be changed and extended. So, we always know which locale the current user uses.
The user's current locale is passed to all API requests (ProductAPI, ContentAPI, …) and those APIs can modify queries based on that and should only return data in the current user's locale.
Some APIs need even more information than language and region in the locale, which is supported by Frontastic. The system is also currency aware, which is especially important for commerce APIs, so you could use [email protected]
to use Euro instead of Pounds when shopping even in Great Britain.
If there's some additional logic wanted like a fallback from de_AT
and de_DE
to just de
(because you don't want to maintain dedicated product descriptions in Austrian German and German) this logic has to be implemented either in the API itself or inside the mapping in the API abstraction in Frontastic.
User interface strings
(Also known as internationalization of Frontastic components)
Making Frontastic component data translatable
There are 3 field types in Frontastic components that can be translatable, they are:
- 'string'
- 'text'
- 'markdown'
These field types are
translatable
by default so if you don't want these to betranslatable
you need to explicitly switch the setting tofalse
.
For example:
{
...
"schema": [
{
"name": "Copy",
"fields": [
...
{
"label": "Title",
"field": "title",
"type": "string",
"translatable": false
},
{
"label": "CTA",
"field": "callToAction",
"type": "string",
}
]
}
]
}
This will give the user of the Frontastic studio the possibility to configure a setting callToAction
for each of the locales available in the project but not the title
.
Defining translatable data
Once you receive translatable data in your Frontastic component you'll see that the data format changes. Instead of retrieving a single instance of the value type, you receive a HashMap that uses locales as an index and has a value type assigned to each of these keys. For example:
{
data: {
// ...
CTA: {
'en_GB': true,
'de_DE': false,
'de_CH': true,
}
}
}
You'll then need to determine the correct one for your situation (see later section on advanced internationalization handling). But for textual values API hub provides a shortcut.
Translating textual data
If you defined a text field that's translatable
as below in the JSON tab, you can simply render the description in the user's language using the JSX.
{
...
"schema": [
{
"name": "Configuration",
"fields": [
...
{
"label": "Description",
"field": "description",
"type": "text"
}
]
}
]
}
import Translatable from 'frontastic-catwalk/src/js/component/translatable'
class TranslationExampleTastic extends Component {
render () {
return (<Translatable value={this.props.data.description} />
}
}
export default TranslationExampleTastic
The Translatable
helper component will retrieve the users preferred locale and the locales configured for the project. It'll work out the best possible match from the given value
and render it. It will also render a ´with the CSS class
untranslated` around it if an exact match can't be found. Feel free to style this in your development or staging environment so that you can easily spot missing translations.
Automatic translation
If you only have simple string fields in your Frontastic components that are translatable, you can try our withTranslatedTasticData
higher-order component.
This will pass all string Frontastic component fields that are translatable as an already translated string. This means you don't need to use the <Translatable />
helper component anymore. Our <TranslationExampleTastic />
helper component from before would look like this:
import withTranslatedTasticData from "frontastic-catwalk/src/js/component/withTranslatedTasticData";
class TranslationExampleTastic extends Component {
render() {
return this.props.data.description;
}
}
export default withTranslatedTasticData(TranslationExampleTastic);
Working manually with internationalized data
If you need to work with more advanced data structures, numbers or you have advanced requirements than our Translatable
helper component provided, you can handle internationalization by yourself. To do this, you need to retrieve the involved locale from the Redux Store using a connector function:
export default connect(
(globalState, props) => {
return {
currentLocale: globalState.app.context.locale,
defaultLocale: globalState.app.context.project.defaultLanguage
}
}
)(AdvancedTranslationExample)
The currentLocale
prop will contain the locale preferred by the current user and defaultLocale
can be used as a fallback for missing translations.
Frontastic component configuration versus code
So, should you put translations into a Frontastic component configuration or in the code itself? Well, that depends on whether you want these values to be editable in the Frontastic studio or not.
Where you have a field type of string available in your Frontastic component configuration, that's translatable by default. This means translations can be changed within the Frontastic studio.
If you have content that's more static and it won't often need to be translated, for example, a button that says "OK", then this should go into the code.
We use React-Intl
for this and it's where you can use the FormattedMessage
component. Our DependencyInjector
gives you the ability to overwrite our default App.IntlProvider
, see here.
Updated about 1 year ago