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.
Prerequisite
If we you're not yet familiar how localization works in amCharts 5, we suggest reading "Locales" tutorial first.
Creating a new locale
Getting started
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.
Naming the file
Name the file using syntax language_COUNTRY.ts
(e.g. pt_BR
meaning Brazilian Portuguese).
NOTEIf we are creating a plain JavaScript locale file, we'll want to use .js
extension instead.
Adding a header
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 */
/** * amCharts 5 Translation file * Locale: es_ES * Language: Spanish (Spain) * Author: Dominick Green */
File structure
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", // ... }
/** * amCharts 5 Translation file * Locale: es_ES * Language: Spanish (Spain) * Author: Dominick Green */ var am5locales_es_ES = 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.
Types of the translatable prompts
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.
Basic phrases and words
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", // ... }
var am5locales_nl_NL = { // ... "Zoom Out": "Uitzoomen", "Play": "Afspelen", "Stop": "Stoppen", // ... }
Special keys
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", // ... }
var am5locales_nl_NL = { // ... "_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.
Ordinals
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; }", // ... }
var am5locales_en_US = { // ... "_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)"; },", // ... }
var am5locales_lt_LT = { // ... "_dateOrd": function(day: number): string { return "-a(s)"; },", // ... }
Placeholders
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": "", // ... }
var am5locales_en_US = { // ... "From %1 to %2": "", "From %1": "", "To %1": "", // ... }
Those are placeholders, that will be replaced with actual values.
IMPORTANTThe translation must include all the same placeholders, however their position is not important. Choose the position which suits the translation best.
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", // ... }
var am5locales_es_ES = { // ... "From %1 to %2": "De %1 a %2", "From %1": "Desde %1", "To %1": "Hasta %1", // ... }
Untranslated prompts
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.
Empty prompts
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, // ... }
Using a custom locale
There are a few ways to use newly-created locales.
Loading a file
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";
<script src="/our/custom/locale.js"></script>
Then just set it via root.locale
:
root.locale = am5locales_xx_XX;
root.locale = am5locales_xx_XX;
In-line translation
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;
var 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", // ... };
root.locale = { // ... "Zoom Out": "Uitzoomen", "Play": "Afspelen", "Stop": "Stoppen", // ... };
Modifying individual prompts
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";
root.locale["_decimalSeparator"] = ","; root.locale["_thousandSeparator"] = " "; root.locale["Export"] = "Save";
Extending locale with custom prompts
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.
Adding custom translations
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!");
root.language.setTranslationAny("Hello!", "¡Hola!");
We can also add many translations in one go using setTranslationsAny()
:
root.language.setTranslationsAny({ "Hello!": "¡Hola!", "Bye": "Adios" });
root.language.setTranslationsAny({ "Hello!": "¡Hola!", "Bye": "Adios" });
NOTEsetTranslationsAny()
method is available from version 5.3.3
and up.
Translating custom prompts
A translateAny()
method, as the name implies, will translate any prompt - both built-in and custom ones.
console.log(root.language.translateAny("Hello!"));
console.log(root.language.translateAny("Hello!"));
Translating Stock Chart
Please refer to "Translating Stock Chart" tutorial.