你能“哑巴” ES6模板字符串到正常字符串? [英] Can you "dumb down" ES6 template strings to normal strings?

查看:154
本文介绍了你能“哑巴” ES6模板字符串到正常字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须解决 gettext 的限制,以识别ES6模板字符串,并考虑将模板字符串的非插值作为编译步骤,以便在代码中只有正常字符串。



基本上我想要实现的是将这个

  const adjective ='wonderful'
const something =`看,我是一个$ {形容词} string`

console.log(东西)
> 看,我是一个奇妙的字符串

到这个

  const adjective ='wonderful'
const something ='看,我是一个$ {形容词}字符串'

console.log (something)
> 看,我是一个$ {形容词}字符串

实现这一点的一个残酷的方法是使用 sed ,但绝对不是更优雅(也可能也容易出错)

  seds / \` /'/ gFILENAME 

任何更好,更清洁的想法想到吗?

解决方案

很好的问题。有四种解决方法,请注意:



1。蛮力



如您所建议的那样,在扫描可翻译字符串之前,强制更换反引号带引号,只要您了解风险, 。例如,请考虑:

 你好,这个字是在backticks

另一个边缘案例是

 `$ { `我是嵌套的``

这种方法也会打破多行模板字符串。 >

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 ,我是一个$ {形容词}字符串); 
const something = eval_template(template,{adjective});

eval_template 将字符串转换为评估模板。需要在模板字符串中使用的任何变量作为第二个参数传递的对象的一部分(因为使用创建的函数)提供给 eval_template 函数在全局范围内,不能访问局部变量,所以我们必须传递它们)。它实现如下:

  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);
}

认为这有点尴尬。这种方法的唯一优点是它不需要进行预扫描重写。



次要点,但如果原始模板字符串是多行的,则不能直接重写作为常规字符串。在这种情况下,您可以将其作为背面勾选的模板字符串,但将 $ 作为 \ $ 并且一切都会很好:



底线:除非你想重写 xgettext ,使用解析器或参与在其他骇客中,做蛮力更换。


I have to work around the limitation of gettext to recognise ES6 template strings, and I thought about getting the "non interpolated value" of the template strings as a compilation step, in order to have only "normal" strings in the code.

Basically what I would like to achieve is transform this

const adjective = 'wonderful'
const something = `Look, I am a ${adjective} string`

console.log(something)
> "Look, I am a wonderful string"

into this

const adjective = 'wonderful'
const something = 'Look, I am a ${adjective} string'

console.log(something)
> "Look, I am a ${adjective} string"

One brutal way of achieving this is using sed, but it's most certainly not the more elegant (and probably also error prone)

sed "s/\`/'/g" FILENAME

Any better and cleaner idea comes to mind?

解决方案

Great question. There are four solutions that come to mind:

1. Brute force

A brute force replacement of backticks with quote marks prior to scanning for translatable strings, as you suggested, is not a horrible idea, as long as you understand the risks. For instance, consider:

"hello, this word is in `backticks`"

Another edge case is

`${`I am nested`}`

This approach will also break multi-line template strings.

2. Fix xgettext

Of course, the "correct" solution is to write a fork of xgettext that deals with template strings. Then you could just write

const something = _(`Look, I am a ${adjective} string`);

Unfortunately, this could be harder that it seems. There is a bunch of hard-wired logic inside xgettext related to strings. If you were to undertake this project, many would thank you.

3. Using a parser

The more robust alternative is to use a JavaScript parser such as Esprima. These parsers expose the ability to pick up tokens (such as template strings). As you can see at http://esprima.org/demo/parse.html, the relevant token type to look for is TemplateLiteral.

4. Unadvisable hacks

Another (bad?) idea is to write template strings as regular strings to start with, then treat them as template strings at run-time. We define a function eval_template:

const template = _("Look, I am a ${adjective} string");
const something = eval_template(template, {adjective});

eval_template converts a string into an evaluated template. Any variable in local scope used in the template string needs to be provided to eval_template as part of the object passed in the second parameter (because functions created using Function are in the global scope and cannot access local variables, so we have to pass them in). It is implemented as follows:

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);
}

Granted, this is a bit awkward. The only advantage of this approach is that it requires no pre-scan rewriting.

Minor point, but if the original template string is multi-line, you cannot directly rewrite it as a regular string. In that case, you can leave it as a back-ticked template string but escape the $ as \$, and all will be well:

Bottom line: unless you want to rewrite xgettext, use a parser, or engage in other hackery, do the brute force replacement.

这篇关于你能“哑巴” ES6模板字符串到正常字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆