Localization

Blockly provides a system for localizing the text in an application, such as tooltips, context menus, and the text on blocks. It uses this system to localize its own text; you can use it to localize text unique to your application.

Note: Localization is the same as translation, except that it allows translations to be different for different countries, such as different translations into Portuguese in Portugal and Brazil.

How the localization system works

The localization system consists of localization tokens, localization tables, and functions that use the tables to replace tokens with localized strings.

Localization tokens

A localization token is a short string that represents text that needs to be localized. For example, a tooltip in a custom date block might use the token MY_DATE_TOOLTIP. Localization tokens are used in code in place of text. At runtime, Blockly replaces these tokens with localized strings.

Localization tables

A localization table, also known as a string table or message table, is an object that maps localization tokens to localized strings. You need a different table for each locale. For example, if you want to support English and Spanish, your English table might contain:

enTable.MY_DATE_TOOLTIP = 'Enter a date.';

and your Spanish table might contain:

esTable.MY_DATE_TOOLTIP = 'Introduzca una fecha.';

Blockly includes localization tables for its own text. They are available in the Blockly distribution as files named blockly/msg/xx.js, where xx is the locale code.

You need to create localization tables for your own text. At run time, you load the localization tables -- Blockly's and yours -- for the chosen locale into Blockly.Msg, which is the localization table that Blockly uses internally.

Use the localization system

Before using the localization system, you need to decide how many locales you want to support and whether you plan to support more locales in the future.

Define and use localization tokens

When supporting multiple locales, you need to define and use localization tokens for all of your custom text.

Define localization tokens

For each string that needs to be localized, define a token. You may want to use a custom prefix with your tokens to avoid collisions with any tokens Blockly adds in the future.

For example, if you have a single custom block and a single custom category, you might define the following tokens:

MY_DATE_BLOCK_TEXT
MY_DATE_TOOLTIP
MY_DATE_HELPURL
MY_DATE_CATEGORY

Define localization tables

For each locale you want to support, define a localization table. For example:

// English localization table: my_tokens_en.js
export const myEnTable = {
  MY_DATE_BLOCK_TEXT: 'Date %1',
  MY_DATE_TOOLTIP: 'Enter a date.',
  MY_DATE_HELPURL: 'https://myownpersonaldomain.com/help/en/dateblock'
  MY_DATE_CATEGORY: 'Dates',
}

// Spanish localization table: my_tokens_es.js
export const myEsTable = {
  MY_DATE_BLOCK_TEXT: 'Fecha %1',
  MY_DATE_TOOLTIP: 'Introduzca una fecha.',
  MY_DATE_HELPURL: 'https://myownpersonaldomain.com/help/es/dateblock'
  MY_DATE_CATEGORY: 'Fechas',
}

Use localization tokens in JSON

To use localization tokens in JSON, replace the string to be localized with a token reference. A token reference has the form %{BKY_TOKEN}. For example:

Blockly.common.defineBlocksWithJsonArray([{
  type: 'my_date',
  message0: '%{BKY_MY_DATE_BLOCK_TEXT}',
  args0: [
    {
      type: 'field_input',
      name: 'DATE',
    }
  ],
  output: 'Date',
  colour: '%{BKY_MY_DATE_COLOUR}',
  tooltip: '%{BKY_MY_DATE_TOOLTIP}',
  helpUrl: '%{BKY_MY_DATE_HELPURL}',
  extensions: ['validate_date'],
}]);

When the JSON is processed -- in this case, when the block is instantiated -- Blockly looks up the tokens in Blockly.Msg and replaces them with localized strings. If it doesn't find a token, it leaves the reference in place and emits a warning.

For a complete list of where token references can be used, see the appendix.

JSON message interpolation

The message keys in a JSON block definition define the inputs and fields (including labels) in a block. The use of token references in these keys allows a single block definition to adapt to the vocabulary, word ordering, and direction of multiple locales. For example, here is Blockly's lists_repeat block in four different languages:

lists_repeat block in English
lists_repeat block in Spanish
lists_repeat block in Korean
lists_repeat block in right-to-left Arabic

All of these blocks share the same block definition, whose message0 key is:

message0: %{BKY_LISTS_REPEAT_TITLE},

The value of this token in the English localization table is:

Blockly.Msg['LISTS_REPEAT_TITLE'] = 'create list with item %1 repeated %2 times';

The interpolation markers (%1 and %2) correspond to the block's defined inputs and fields, and the text between the markers is converted into unnamed label fields. Because the text for message0 is stored in localization tables and not the block definition, a single block definition in JSON can support different orderings of inputs and fields:

// In Spanish: label, input, label, input, label
Blockly.Msg['LISTS_REPEAT_TITLE'] = "crear lista con el elemento %1 repetido %2 veces";
// In Korean: input, label, input, label, input (dummy)
Blockly.Msg['LISTS_REPEAT_TITLE'] = "%1을 %2번 넣어, 리스트 생성";

This is not possible for block definitions in JavaScript, where different orderings of inputs and fields require different sequences of function calls.

When using right-to-left languages, write the message string in visual order, and do not include Unicode direction commands:

// In Arabic. Note how %2 is left of %1, since it reads right to left.
Blockly.Msg['LISTS_REPEAT_TITLE'] = "إنشئ قائمة مع العنصر  %1 %2 مرات";

For more information about how Blockly converts message keys into inputs and fields, see Define block structure in JSON.

Use localization tokens in JavaScript

To use localization tokens in JavaScript, replace the string to be localized with Blockly.Msg['TOKEN']. For example:

// Return the text for a localized context menu item.
displayText: () => Blockly.Msg['MY_CONTEXT_MENU_ITEM'];

Except as noted in the appendix, Blockly doesn't parse token references in JavaScript:

// Doesn't work. Returns '%{BKY_MY_CONTEXT_MENU_ITEM}'.
displayText: () => '%{BKY_MY_CONTEXT_MENU_ITEM}';

Choose a locale

How to choose a locale is application-specific and outside the scope of Blockly. For example, your application might always use the same locale, determine the locale from the URL or URL parameters, or let users choose a locale from a list.

As a general rule, you should choose a locale and load the corresponding localization tables before you create a workspace. If you choose a different locale and load new tables after creating a workspace, you'll have to re-create the workspace: Blockly does not update the existing toolbox or blocks to use the new locale automatically. To preserve the user's work (if any), save the state before you re-create the workspace and re-load it after.

Load a Blockly localization table

Blockly provides localization tables for all of its own text, such as the text on built-in blocks. Unless you are using the en locale, which is loaded by default, you need to load the Blockly localization table for your locale.

Blockly's localization tables are stored in files named blockly/msg/xx.js, where xx is the locale code. For a list of supported locales, see the files in blockly/msg/json.

Load a Blockly localization table with npm

When you import Blockly with import * as Blockly from 'blockly'; you'll get the default modules: Blockly core, Blockly built-in blocks, the JavaScript generator, and the Blockly localization table for the English (en) locale.

To load the Blockly localization table for a different locale using npm:

  1. Import Blockly default modules:

    import * as Blockly from 'blockly/core';
    import 'blockly/blocks';
    import 'blockly/javascript'; // Or the generator of your choice
    
  2. Import the Blockly localization table for your locale. For example, to import the table for the Spanish (es) locale:

    import * as Es from 'blockly/msg/es';
    
  3. Load the table with Blockly.setLocale. This function copies the table into the Blockly.Msg object.

    Blockly.setLocale(Es);
    

    setLocale is only included in the npm release of Blockly.

Load a Blockly localization table without npm

To load a Blockly localization table without using npm, use a <script> tag to load the table from the msg directory. For example:

<script src="../../blockly_compressed.js"></script>
<script src="../../blocks_compressed.js"></script>
<script src="../../msg/es.js"></script>

The localization table is loaded automatically.

Load your own localization table

If you define your own localization tables, you need to load the table for your chosen locale.

  • If you are using npm, you can do this with Blockly.setLocale:

    import * as Es from 'blockly/msg/es';
    import {myEsTable} from '../my_tokens_es';
    Blockly.setLocale(Es);
    Blockly.setLocale(myEsTable);
    

    setLocale copies each key-value pair from the input object into Blockly.Msg. You can call it multiple times with distinct keys, but calling it a second time with a duplicate key overwrites the first.

  • If you are not using npm, you must copy your table into Blockly.Msg by hand. (setLocale is only included in the npm release of Blockly.) The easiest way to do this is to define your own version of setLocale.

    function mySetLocale(locale) {
      Object.keys(locale).forEach(function (k) {
        Blockly.Msg[k] = locale[k];
      }
    }
    
    mySetLocale(myEsTable);
    

Functions to resolve token references

Blockly provides two functions for resolving token references: Blockly.utils.parsing.replaceMessageReferences (commonly used) and Blockly.utils.parsing.tokenizeInterpolation (rarely used). In most cases, you don't need to call either of these functions. This is because Blockly already calls them in the places it supports token references. For example, Blockly uses these functions to resolve token references in the messageN, tooltip, and helpUrl keys in a JSON block definition.

One place you might need to use replaceMessageReferences is in custom fields. If your custom field accepts token references in any of its options, use replaceMessageReferences to resolve them. For more information, see JSON and registration.

  • Right-to-left languages: See the RTL demo.
  • Help localize Blockly's text: See Translating in the section on contributing to Blockly.

Appendix: Where token references are allowed

You can use token references in the following JSON keys:

  • In category toolbox definitions:
    • name
    • colour
  • In block definitions:
    • messageN
    • tooltip
    • helpUrl
    • colour
  • In the options passed to all fields:
    • tooltip
  • In the nested arrays passed to options in field_dropdown:
    • The first element, when the first element is a string
    • The value of alt, when the first element is an object describing an image
  • In the options passed to field_variable:
    • variable
  • In the options passed to field_label and field_label_serializable:
    • text
  • In the options passed to field_image:
    • height
    • width
    • src
    • alt
  • In themes:
    • colour in category styles
    • colourPrimary, colourSecondary, and colourTertiary in block styles

And as argument values in the following methods:

  • Block.setColour
  • Blockly.utils.extensions.buildTooltipForDropDown
  • Blockly.utils.extensions.buildTooltipWithFieldText
  • Blockly.utils.parsing.parseBlockColour

And in the XML definition of a toolbox in the following attributes of <category>:

  • name
  • colour

For more information about using token references as colour values, see Colour references.