Skip to main content

Translation files

Translations are stored in JSON files in the folder public/locales/{locale}/{namespace}.json

Namespaces​

Oneki.js supports splitting translations into multiple files, called namespaces.

Separating translations into multiple files offers the following advantages:

  • Only the necessary translation files are loaded
  • The size of the translation files remains under control

Common namespace​

By convention, the default namespace is named common and is automatically loaded.
It's a good practice to put everything that is common to the whole application in this file (for example: the text of the navigation bar).
For small applications, it's common to put all translations only in this file.

Example​

Let's assume that the translation files are divided into 3 namespaces:

  • common.json
  • users.json
  • admin.json

and that the "admin" page only needs the translations of the namespaces "admin" and "common". This is specified via the useTranslation hook:

// if common is not specified, it's automatically added to the list of required namespaces
const [T, t, locale, loading] = useTranslation(['admin', 'common']);

Therefore when the page "admin" is displayed, only the files "common.json" and "admin.json" are loaded.

JSON files​

Not embedded in javascript bundle​

The JSON files must be stored in the folder public/locales/{locale}/{namespace}.json where:

  • locale is one of the language supported by the app (en, fr, es, ...)
  • namespace is the name of the namespace (see above)
My-App
├─ public
│ ├─ locales
│ │ └─ en // locales in english
│ │ │ ├─ admin.json
│ │ │ └─ common.json
│ │ │
│ │ └─ fr // locales in french
│ │ │ ├─ admin.json
│ │ │ └─ common.json
│ └─ ...

useTranslation hook will lazy load these files from the server when needed.

Embedded in javascript bundle​

The translations can be embedded directly in the javascript bundle by adding them directly in the initial state of the redux store

TODO: example

Content​

The content of a translation file is a simple JSON key/value file like this:

{
"Welcome": "Bienvenue"
}

Plural key​

A key can be prefixed to support plurals:

{
"User": "Utilisateur",
"plural::User": "Utilisateurs"
}

Complex key / value​

The key and value can be more complex and look like the content of a JSX component:

{
// Basic example
"Welcome": "Bienvenue", // <T>Welcome<T>

// example of a translation containing a variable. The key is not equal to the value (the key is therefore an alias)
// Example: <T alias="Welcome">Welcome {{name}} !</T>
"Welcome": "Bienvenue {{name}} !",

// Same example as above but the key is not an alias. The key is therefore equal to the content of the default language
// Example: <T>Welcome {{name}} !</T>
"Welcome {{name}} !": "Bienvenue {{name}}!",

// The value is more complex
// Example:
// <T alias="complex">
// Hello{' '}
// <b>
// <i>mister</i> {{ firstname }} {{ lastname }} <i>male</i>
// </b>{' '}
// <u>address</u>
// </T>
//
// Please note that lastname and firstname are reversed
"complex": "Bonjour <1><2>monsieur</2> {{lastname}} {{firstname}} <3>masculin</3></1> <4>adresse</4>",

// Same example as above but when the alias is not specified
// Example: <T>User <b>{{name}}</b> is connected</T>
"User <1>{{name}}</1> is connected": "Utilisateur <1>{{name}}</1> est connecté"
}

Modifiers​

For advanced use cases, you can add one or several modifiers to a variable like this:

{
// Basic example: first name will be in uppercase
// Example: <T>Welcome {{firstname}}</T>
"Welcome {{firstname}}": "Welcome {{firstname | uppercase}}", // <T>Welcome {{firstname}}<T>
}

A modifier is a function with at least two parameters:

  • value: the value of the variable to which the modifier is applied
  • locale: the current locale

The modifiers must be defined in src/settings.ts with the key i18n.modifiers.

export default {
i18n: {
...
modifiers: {
uppercase: (value, locale) => value ? value.toUpperCase() : value
}
}
}

Modifiers with parameters​

You can even pass one or more parameters to a modifier like this

{
// display only the 5 first characters of the firstname
// example: <T>Welcome {{firstname}}<T>
"Welcome {{firstname}}": "Welcome {{firstname | maxlength(5)}}",
}

The modifier defined in src/settings.ts looks like this:

export default {
i18n: {
...
modifiers: {
maxlength: (value, locale, length) => value ? value.substring(length) : value
}
}
}