Skip to content

Creating translations

amCharts 5 uses locale objects to modify textual prompts as well as other location-specific options like number separators, date formats, etc. This tutorial will look at ways to create your own locales or modify existing ones.

If we you’re not yet familiar how localization works in amCharts 5, we suggest reading “Locales” tutorial first.

The best way to get started is to grab existing locale file from amCharts 5 sources, and creating a copy of it.

We suggest using en.ts file which is for International English and is a default locale.

Name the file using syntax language_COUNTRY.ts (e.g. pt_BR meaning Brazilian Portuguese).

A header of the locale file conveys information about the language this file is for.

It can also contain information about the author of the translation.

Make sure you include appropriate header with your locale file.

The template en.ts already includes a header placeholder, which you can use as a template.

Example:

/**
* amCharts 5 Translation file
* Locale: es_ES
* Language: Spanish (Spain)
* Author: Dominick Green
*/

Basically, a locale is defined by a single object with key/value pairs.

Each key is a prompt/format ID (usually a version of the prompt in International English), and each value is a translation/format/etc.

A sample locale might look like this:

{
// ...
"January": "Enero",
"February": "Febrero",
"March": "Marzo",
"April": "Abril",
"May": "Mayo",
"June": "Junio",
"July": "Julio",
"August": "Agosto",
"September": "Septiembre",
"October": "Octubre",
"November": "Noviembre",
"December": "Diciembre",
// ...
}

The actual code will depend on whether we are creating a translation for use in TypeScript or plain JavaScript.

/**
* amCharts 5 Translation file
* Locale: es_ES
* Language: Spanish (Spain)
* Author: Dominick Green
*/
export default {
// ...
"January": "Enero",
"February": "Febrero",
"March": "Marzo",
"April": "Abril",
"May": "Mayo",
"June": "Junio",
"July": "Julio",
"August": "Agosto",
"September": "Septiembre",
"October": "Octubre",
"November": "Noviembre",
"December": "Diciembre",
// ...
}

If we are creating a JavaScript locale file, we need to pay attention to the name of the global variable we are defining.

It should follow default syntax for amCharts 5: am5locales_[language]_[country], e.g. am5locales_es_ES for Spain.

As you explore the template en.ts, you’ll notice that some keys are not English phrases or words, and that some of the values are not actually strings.

Let’s explore these different types of translatable elements.

Those are the base of the translations. They come in a very predictable pattern: English phrase or word as a key, and exact translation as a value. E.g.:

export default {
// ...
"Zoom Out": "Uitzoomen",
"Play": "Afspelen",
"Stop": "Stoppen",
// ...
}

Each locale is responsible not only for translating words and phrases, but also defining number and date/time formats for the target country.

Some keys in the translation files are not phrases in English, but rather some internal code, denoting a specific format:

export default {
// ...
"_decimalSeparator": ",",
"_thousandSeparator": " ",
// ...
"_date_day": "yyyy-MM-dd",
// ...
}

The "_decimalSeparator" above instructs that we want to use a comma as a decimal separator in numbers. The "_thousandSeparator" says we want our thousands to be separate by a space.

"_date_day" set the default date format when we want to show a particular date.

en.ts file might contain further tips and guidelines for each group of such special translations.

These are not basic values, but rather functions, that return a prompt, based on the actual value.

For example, a number suffix which denotes number’s position. E.g 1st, 2nd, 3rd, 4th, 21st, etc.

The reason why we need to use a function, as opposed to just translating "st", "nd", is that those might not necessarily be like this in other languages.

We can’t predict how different languages treat ordinals, so we must leave to a translator to come up with a function that generates a proper ordinal for a number, supplied as a parameter.

Here’s how ordinal function looks like for English:

export default {
// ...
"_dateOrd": function(day: number): string {
let res = "th";
if ((day < 11) || (day > 13)) {
switch (day % 10) {
case 1:
res = "st";
break;
case 2:
res = "nd";
break;
case 3:
res = "rd"
break;
}
}
return res;
}",
// ...
}

For some languages, like Lithuanian, ordinals do not differ for numbers, so the function would look quite straightforward:

export default {
// ...
"_dateOrd": function(day: number): string {
return "-a(s)";
},",
// ...
}

You will also notice, that some prompts contain numbers prefixed with a percent sign, e.g.:

export default {
// ...
"From %1 to %2": "",
"From %1": "",
"To %1": "",
// ...
}

Those are placeholders, that will be replaced with actual values.

Here’s how Spanish translation might look for the above:

export default {
// ...
"From %1 to %2": "De %1 a %2",
"From %1": "Desde %1",
"To %1": "Hasta %1",
// ...
}

An empty string "" in translation means “use default English” prompt.

If the translation is not necessary, e.g. as most prompts and formats in variations of English, or if you can’t translate some of the prompts right now, simply leave the translation as an empty string. The chart will fall back to English for just those untranslated ones.

If for some reason you want to display nothing instead of an English phrase, use null instead:

export default {
// ...
"AM": null,
"PM": null,
// ...
}
var am5locales_nl_NL = {
// ...
"AM": null,
"PM": null,
// ...
}

There are a few ways to use newly-created locales.

We can save the locale as a .ts or .js file, then load it like any other bundled locale:

import am5locales_xx_XX from "our/custom/locale.ts";

Then just set it via root.locale:

root.locale = am5locales_xx_XX;

We can also create translations in-line, directly with our chart code:

const am5locales_nl_NL = {
// ...
"Zoom Out": "Uitzoomen",
"Play": "Afspelen",
"Stop": "Stoppen",
// ...
}
root.locale = am5locales_nl_NL;

Or even setting it directly to root.locale, without creating a variable:

root.locale = {
// ...
"Zoom Out": "Uitzoomen",
"Play": "Afspelen",
"Stop": "Stoppen",
// ...
};

In some cases we might be generally happy with existing default or bundled translation, and would just need to modify a single prompt or two.

This way we can directly access the locale object and modify its values:

root.locale["_decimalSeparator"] = ",";
root.locale["_thousandSeparator"] = " ";
root.locale["Export"] = "Save";

The above functionality was dealing with hardcoded list of prompts.

Using any prompts outside of the built-in list, would result in errors in strongly typed languages like TypeScript.

In the following section, we will explore ways to add “non-standard” prompts as well as ways to translate them.

We can use Language methods setTranslationAny() and setTranslationsAny() to add custom prompts without triggering any errors or warnings.

setTranslationAny() adds a single translation:

root.language.setTranslationAny("Hello!", "¡Hola!");

We can also add many translations in one go using setTranslationsAny():

root.language.setTranslationsAny({
"Hello!": "¡Hola!",
"Bye": "Adios"
});

A translateAny() method, as the name implies, will translate any prompt - both built-in and custom ones.

console.log(root.language.translateAny("Hello!"));

Please refer to “Translating Stock Chart” tutorial.