好问题。想到了四种解决方案:
1.蛮力
正如您所建议的,在扫描可翻译字符串之前用引号强力替换反引号并不是一个可怕的想法,只要您了解风险。例如,考虑:
"hello, this word is in `backticks`"
另一个极端情况是
`${`I am nested`}`
这种方法也会破坏多行模板字符串。
2.修复xgettext
当然,“正确”的解决方案是编写一个xgettext
处理模板字符串的分支。然后你可以写
const something = _(`Look, I am a ${adjective} string`);
不幸的是,这可能比看起来更难。xgettext 内部有一堆与字符串相关的硬连线逻辑。如果你要承担这个项目,很多人会感谢你。
3. 使用解析器
更强大的替代方法是使用 JavaScript 解析器,例如 Esprima。这些解析器公开了获取标记(例如模板字符串)的能力。正如您在http://esprima.org/demo/parse.html中看到的,要查找的相关令牌类型是TemplateLiteral
.
4. 不明智的黑客攻击
另一个(坏的?)想法是将模板字符串作为常规字符串开始编写,然后在运行时将它们视为模板字符串。我们定义一个函数eval_template
:
const template = _("Look, I am a ${adjective} string");
const something = eval_template(template, {adjective});
eval_template
将字符串转换为评估的模板。模板字符串中使用的局部范围内的任何变量都需要eval_template
作为传递给第二个参数的对象的一部分提供(因为使用创建的函数Function
在全局范围内并且无法访问局部变量,因此我们必须将它们传递进去)。它的实现如下:
function eval_template_(s, params) {
var keys = Object.keys(params);
var vals = keys.map(key => params[key]);
var f = Function(...keys, "return `" + s + "`");
return f(...vals);
}
诚然,这有点尴尬。这种方法的唯一优点是它不需要预扫描重写。
小问题,但是如果原始模板字符串是多行的,则不能直接将其重写为常规字符串。在这种情况下,您可以将其保留为反引号的模板字符串,但将$
as转义\$
,一切都会好起来的:
底线:除非您想重写xgettext
、使用解析器或从事其他黑客行为,否则请进行蛮力替换。