本地化

Blockly 提供了一种用于本地化应用中文本(例如提示、上下文菜单和块上的文本)的系统。它使用此系统来本地化自己的文本;您也可以使用它来本地化应用特有的文本。

注意:本地化与翻译相同,但允许针对不同国家/地区使用不同的翻译,例如在葡萄牙和巴西使用不同的葡萄牙语翻译。

本地化系统的运作方式

本地化系统由本地化令牌、本地化表和使用表将令牌替换为本地化字符串的函数组成。

本地化令牌

本地化令牌是一个短字符串,表示需要本地化的文本。例如,自定义日期块中的提示可能使用令牌 MY_DATE_TOOLTIP。本地化令牌在代码中用于替代文本。在运行时,Blockly 会将这些令牌替换为本地化字符串。

本地化表

本地化表(也称为字符串表或消息表)是一种将本地化令牌映射到本地化字符串的对象。您需要为每个语言区域创建不同的表格。例如,如果您要支持英语和西班牙语,则英语表格可能包含:

enTable.MY_DATE_TOOLTIP = 'Enter a date.';

而西班牙语表格可能包含:

esTable.MY_DATE_TOOLTIP = 'Introduzca una fecha.';

Blockly 包含其自身文本的本地化表格。它们在 Blockly 发行版中以名为 blockly/msg/xx.js 的文件的形式提供,其中 xx 是语言区域代码。

您需要为自己的文本创建本地化表。在运行时,您将所选语言区域的本地化表(Blockly 的和您自己的)加载到 Blockly.Msg,这是 Blockly 在内部使用的本地化表。

使用本地化系统

在使用本地化系统之前,您需要确定要支持多少个语言区域,以及是否计划将来支持更多语言区域。

定义和使用本地化令牌

支持多种语言区域时,您需要为所有自定义文本定义和使用本地化令牌。

定义本地化令牌

对于需要本地化的每个字符串,请定义一个令牌。您可能需要为令牌使用自定义前缀,以免与 Blockly 日后添加的任何令牌发生冲突。

例如,如果您只有一个自定义版块和一个自定义类别,则可以定义以下令牌:

MY_DATE_BLOCK_TEXT
MY_DATE_TOOLTIP
MY_DATE_HELPURL
MY_DATE_CATEGORY

定义本地化表

为您要支持的每个语言区域定义一个本地化表。例如:

// 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',
}

在 JSON 中使用本地化令牌

如需在 JSON 中使用本地化令牌,请将要本地化的字符串替换为令牌引用。令牌引用的格式为 %{BKY_TOKEN}。例如:

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'],
}]);

在处理 JSON 时(在本例中,即在实例化代码块时),Blockly 会在 Blockly.Msg 中查找令牌,并将其替换为本地化字符串。如果未找到令牌,则会保留引用并发出警告。

如需查看可使用令牌引用的位置的完整列表,请参阅附录

JSON 消息插值

JSON 分块定义中的 message 键用于定义分块中的输入和字段(包括标签)。通过在这些键中使用令牌引用,单个块定义可以适应多个语言区域的词汇、字词顺序和方向。例如,以下是 Blockly 的 lists_repeat 块,以四种不同的语言显示:

英语版 lists_repeat 块
西班牙语中的 lists_repeat 块
韩语中的 lists_repeat 块
从右向左的阿拉伯语中的 lists_repeat 块

所有这些块都使用相同的块定义,其 message0 键为:

message0: %{BKY_LISTS_REPEAT_TITLE},

英语本地化表格中此令牌的值为:

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

插值标记 (%1%2) 对应于块定义的输入和字段,并且标记之间的文本会转换为无名标签字段。由于 message0 的文本存储在本地化表中,而不是在块定义中,因此 JSON 中的单个块定义可以支持输入和字段的不同排序:

// 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번 넣어, 리스트 생성";

但在 JavaScript 中,块定义无法做到这一点,因为输入和字段的不同排序需要不同的函数调用序列。

使用从右到左的语言时,请按视觉顺序编写消息字符串,并且不要添加 Unicode 方向命令:

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

如需详细了解 Blockly 如何将 message 键转换为输入和字段,请参阅在 JSON 中定义块结构

在 JavaScript 中使用本地化令牌

如需在 JavaScript 中使用本地化令牌,请将要本地化的字符串替换为 Blockly.Msg['TOKEN']。例如:

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

附录中所述的情况外,Blockly 不会解析 JavaScript 中的令牌引用:

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

选择语言区域

如何选择语言区域因应用而异,超出了 Blockly 的范围。 例如,您的应用可以始终使用相同的语言区域,根据网址或网址参数确定语言区域,或者让用户从列表中选择语言区域。

一般而言,您应先选择语言区域并加载相应的本地化表,然后再创建工作区。如果您在创建工作区后选择了其他语言区域并加载了新表格,则必须重新创建工作区:Blockly 不会自动更新现有的工具箱或积木块以使用新语言区域。如需保留用户的工作(如果有),请先保存状态,然后再重新创建工作区并重新加载该工作区。

加载 Blockly 本地化表

Blockly 为其自己的所有文本(例如内置块中的文本)提供了本地化表格。除非您使用默认加载的 en 语言区域,否则您需要加载适用于您所用语言区域的 Blockly 本地化表。

Blockly 的本地化表存储在名为 blockly/msg/xx.js 的文件中,其中 xx 是语言区域代码。如需查看受支持语言区域的列表,请参阅 blockly/msg/json 中的文件。

使用 npm 加载 Blockly 本地化表

使用 import * as Blockly from 'blockly'; 导入 Blockly 时,您将获得默认模块:Blockly 核心、Blockly 内置块、JavaScript 生成器,以及适用于英语 (en) 语言区域的 Blockly 本地化表。

如需使用 npm 加载其他语言区域的 Blockly 本地化表,请执行以下操作:

  1. 导入 Blockly 默认模块:

    import * as Blockly from 'blockly/core';
    import 'blockly/blocks';
    import 'blockly/javascript'; // Or the generator of your choice
    
  2. 导入适用于您语言区域的 Blockly 本地化表。例如,如需为西班牙语 (es) 语言区域导入表,请执行以下操作:

    import * as Es from 'blockly/msg/es';
    
  3. 使用 Blockly.setLocale 加载表格。此函数会将表格复制到 Blockly.Msg 对象中。

    Blockly.setLocale(Es);
    

    setLocale 仅包含在 Blockly 的 npm 版本中。

在不使用 npm 的情况下加载 Blockly 本地化表

如需在不使用 npm 的情况下加载 Blockly 本地化表,请使用 <script> 标记从 msg 目录加载表。例如:

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

系统会自动加载本地化表。

加载您自己的本地化表

如果您定义了自己的本地化表,则需要为所选语言区域加载该表。

  • 如果您使用的是 npm,则可以使用 Blockly.setLocale 执行此操作:

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

    setLocale 会将输入对象中的每个键值对复制到 Blockly.Msg。您可以使用不同的键多次调用此方法,但如果使用重复的键第二次调用此方法,则会覆盖第一次调用。

  • 如果您不使用 npm,则必须手动将表格复制到 Blockly.Msg。(setLocale 仅包含在 Blockly 的 npm 版本中。)最简单的方法是定义您自己的 setLocale 版本。

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

用于解析令牌引用的函数

Blockly 提供了两个用于解析令牌引用的函数:Blockly.utils.parsing.replaceMessageReferences(常用)和 Blockly.utils.parsing.tokenizeInterpolation(很少用)。在大多数情况下,您无需调用这两种函数。这是因为 Blockly 已在支持令牌引用的位置调用了它们。例如,Blockly 使用这些函数来解析 JSON 块定义中的 messageNtooltiphelpUrl 键中的令牌引用。

您可能需要在自定义字段中使用 replaceMessageReferences。如果您的自定义字段接受其任何选项中的令牌引用,请使用 replaceMessageReferences 解析这些引用。如需了解详情,请参阅 JSON 和注册

  • 从右到左书写的语言:请参阅 RTL 演示
  • 帮助本地化 Blockly 中的文本:请参阅关于为 Blockly 贡献的部分中的翻译

附录:允许使用令牌引用的位置

您可以在以下 JSON 键中使用令牌引用

  • 在类别工具箱定义中:
    • name
    • colour
  • 在块定义中:
    • messageN
    • tooltip
    • helpUrl
    • colour
  • 在传递给所有字段的选项中:
    • tooltip
  • field_dropdown 中传递给 options嵌套数组中:
    • 第一个元素(如果第一个元素是字符串)
    • 当第一个元素是描述图片的对象时,alt 的值
  • 在传递给 field_variable 的选项中:
    • variable
  • 在传递给 field_labelfield_label_serializable 的选项中:
    • text
  • 在传递给 field_image 的选项中:
    • height
    • width
    • src
    • alt
  • 在主题中:
    • 类别样式中的 colour
    • 块样式的 colourPrimarycolourSecondarycolourTertiary

并在以下方法中作为参数值:

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

在工具箱的 XML 定义中,在 <category> 的以下属性中:

  • name
  • colour

如需详细了解如何将令牌引用用作颜色值,请参阅颜色引用