Internalization Support
Internalization support in Sciter's JSX...
Sciter 为 JSX 文本翻译提供了内置的、零运行时成本的机制。
Current state of affairs of i18n support in ReactJS.
请考虑以下使用 JSX 文本的函数:
render() {
return <caption>Settings</caption>;
}
这绝对是翻译成其他语言的主题。
理想情况下,在俄语版本的应用程序中,函数应如下所示:
render() {
return <caption>Настройки</caption>;
}
这里的“理想情况下”意味着应用程序的英语和俄语版本将以相同的速度和 CPU 负载运行。每次我们执行 render()
函数时,无论我们使用哪种语言,我们的 JavaScript VM 都将以完全相同的运行时成本加载和输出字符串文字。
但实际上翻译会增加运行时成本,例如,在 React-i18n 中,我们可能会看到这样的建议:
render() {
return <caption>{t('Settings')}</caption>;
}
请注意,每次调用 render()
它时,它都会 a) 调用全局 t()
函数,该函数将执行 b) 在某些转换表中查找“设置”键以替换字符串。
(a)和(b)显然都具有非零运行时成本。通常,同时执行两个步骤都不是问题,但是如果您有动态UI怎么办?在每次渲染时,它都会执行相同的查找步骤 - 不好,只是浪费 CPU 资源。
为了解决这个问题,Sciter 提供了 mechansim,其中查找只会发生一次 - 在 JS 编译阶段 - 稍后的 render() 调用将使用已经翻译的字符串文字。
Static translation markers
Literal strings to translate
为了在 JS 源代码中将字符串文字定义为可翻译的,在字符串文字前面加上 @
符号:
const title = @"Meeting preferences";
在解析此类文字时,Sciter 运行时将调用 JSX_translateText(text)
翻译钩子函数,并将其 resuslt 作为字符串文本放入字节码中。
所谓的 translationID,即翻译表中文本的唯一标识符,将设置为文本内容 - "Meeting preferences"
在本例中。
Parametrized literal strings to translate
语言可能因短语中的单词顺序而异。一种可能的处理方法是使用参数化格式字符串,例如:
const greeting = @"Hello %1%, today is %2%".format(name,date.toLocaleDateString());
在这种情况下 JSX_translateText()
,将使用 "Hello %1%, today is %2%"
字符串调用。例如,对于俄语翻译,它可能会返回 "%1%, привет, сегодня %2%"
。使用的格式化字符串将是 "Вася, привет, сегодня 31.02.2021"
请注意,使用上面的非标准 format
字符串方法,您可以在源代码中定义为:
String.prototype.format = function(...values) {
return this.replace(/%([0-9]+)%/g, (match, index) => values[index - 1] ?? match );
};
JSX attribute to translate
为了定义作为翻译主题的 HTML 属性,在其名称前面加上 @
符号并提供初始值:
<button @title="Meeting preferences">Show preferences</button>
在解析此类属性时,Sciter 运行时将调用 JSX_translateText(text)
翻译钩子函数,并将其 resuslt 作为字符串文本放入字节码中。最后,DOM 元素将转换 title
属性且不带 @
标记。
所谓的 translationID,即翻译表中文本的唯一标识符,将设置为初始属性文本 - "Meeting preferences"
在本例中。
JSX text to translate
为了将 DOM 元素标记为可翻译的,请放置标准 @
符号或 @name
其属性:
<button @>Show preferences</button>
在解析此类元素时,Sciter 运行时将调用 JSX_translateText(text)
翻译钩子函数,并将其 resuslt 作为字符串文字(文本)放入字节码中。该文本将出现在最终的 DOM 中。
在这种情况下,TranslationID 将是原始元素的文本,或者(如果 @name
使用标记)名称。
JSX text span to translate
有时我们只需要翻译文本的一部分。在这种情况下,我们可以使用“可翻译片段”标记:
render() {
return <caption><@>Hello</>, {userName}!</caption>;
}
这 <@>...</>
标志着文本片段是可翻译的。该片段将是其翻译 ID。
Dynamic translation markers
在某些情况下,我们需要更复杂的翻译处理,而不仅仅是静态大小写。考虑我们需要输出一些像瓶子计数器一样的东西:
render() {
return <span @>{n} bottles</span>;
}
理想情况下,我们应该有这样的输出:“没有瓶子”、“1 瓶”、“2 瓶”......在一般情况下,我们不能只用静态表来处理这样的结构——数字规则 a) 在不同的语言中是不同的,b) 可能非常复杂,c) 在不同的上下文中可能不同。
在这种情况下,唯一的选择是将此类逻辑实现为函数。在这种情况下,Sciter 运行时将调用 JSX_translateNode(node)
翻译钩子函数。
Sciter translation hooks
转换钩子是自定义函数,需要在应用程序端定义以支持转换。
JSX_translateText()
调用以转换静态文本 - 属性值或元素的文本:
JSX_translateText = function(text, context, type) {
...
}
参数:
text - 字符串,要翻译的文本;
context - 字符串,对于属性,它是属性的名称,对于元素,它是标签名称;
type - int,0 - 它是一个属性,1 - 元素的文本,2 - 字符串文字
该函数应返回一个字符串 - 转换的结果。
JSX_translateNode()
用于翻译动态文本,例如将某些数值复数化:
JSX_translateNode = function(node, translationId) {
...
}
参数:
node - 虚拟 DOM 节点,3 元素元组:[“tag”,{attributes},[children]];
translationId - 字符串,内容字符串如“{} bottles”或显式 ID,如 “nbottles”
<span @nbottles>{n} bottles</span>
该函数应返回虚拟 DOM 节点 - 转换结果。用于 JSX(tag,{...},[...])
返回转换后的虚拟 DOM 元素。
Translation environment variables
这些全局变量在钩子函数JSX_translateXXX可用:
JSX_translationFileName
string,源脚本文件的 URL。
JSX_translationlineNo
整数、字符串或 JSX 文本的行号。
JSX_translationContext
字符串,翻译上下文。翻译上下文在源代码中由第一个位置有 @
符号的注释定义,例如:
/*@Host meeting*/
let text = @"Host";
在这种情况下 JSX_translateText()
,将调用为 JSX_translateText("Host")
函数 JSX_translationContext
变量,并且函数内部变量将具有 "Host meeting"
值。
注意:有些单词在不同的上下文中可能有不同的翻译,因此需要一些澄清才能正确翻译。例如,“主持人”可以是名词,例如“主机”,也可以是动词,如“主持会议”。
JSX_translateTags
这是默认情况下需要翻译的标签映射 - 没有翻译标记。
例:
JSX_translateTags = {
"caption": true,
"label": true,
"button": true,
"span": true,
};
Declaring translation hooks
在加载构成应用程序其余部分的脚本之前,需要定义转换钩子。原因:钩子应存在于使用其服务的脚本的解析/编译时。
可能的情况:
In different script sections:
<head>
<script type="module" src="i18n/hooks.js" />
<script type="module" src="application/main.js" />
</head>
第一个脚本将安装钩子,第二个脚本是应用程序的主根脚本。
Framed application:
<head>
<script type="module" src="i18n.js" />
</head>
<body>
<frame lang="en" src="application.htm" />
</body>
这种设置允许在运行时切换 UI 语言。若要更改 UI 语言i18n.js脚本应:
加载相应的转换表;
frame 元素上的 set
lang
属性(可选);在框架中重新加载“application.htm” - 脚本将被重新加载,因此使用新翻译重新编译;
Instrumental hooks
应用程序可以定义钩子的工具版本,以生成所需格式的翻译表原型:JSON、PO(gettext 格式)等。