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.
If you only ever want to support a single locale, enter your text directly in your code. You don't need to use localization tokens.
- If your locale is English (
en
), you don't need to do anything else. The Blockly localization table for theen
locale is loaded by default. - If your locale is not
en
, load the Blockly localization table for that locale.
- If your locale is English (
If you want to support multiple locales now or in the future:
- Define and use localization tokens for your custom text.
- Decide how users will choose a locale.
- Load the Blockly localization table for the locale.
- Load your localization table for the locale.
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:
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:
Import Blockly default modules:
import * as Blockly from 'blockly/core'; import 'blockly/blocks'; import 'blockly/javascript'; // Or the generator of your choice
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';
Load the table with
Blockly.setLocale
. This function copies the table into theBlockly.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 intoBlockly.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 ofsetLocale
.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.
Related topics
- 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
infield_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
andfield_label_serializable
:text
- In the options passed to
field_image
:height
width
src
alt
- In themes:
colour
in category stylescolourPrimary
,colourSecondary
, andcolourTertiary
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.