代码之家  ›  专栏  ›  技术社区  ›  domokun

你能把ES6模板字符串“哑”成普通字符串吗?

  •  9
  • domokun  · 技术社区  · 8 年前

    我必须克服 gettext 为了识别ES6模板字符串,我考虑将模板字符串的“非内插值”作为编译步骤,以便代码中只有“普通”字符串。

    基本上,我想实现的是改变这个

    const adjective = 'wonderful'
    const something = `Look, I am a ${adjective} string`
    
    console.log(something)
    > "Look, I am a wonderful string"
    

    进入这个

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

    实现这一目标的一个残酷方法是使用 sed ,但它肯定不是更优雅(而且可能也容易出错)

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

    我想到了更好更干净的主意吗?

    2 回复  |  直到 8 年前
        1
  •  8
  •   user663031 user663031    8 年前

    好问题。我们想到了四种解决方案:

    1.暴力

    正如你所建议的,在扫描可翻译字符串之前,用引号强行替换反勾号并不是一个可怕的主意,只要你了解其中的风险。例如,考虑:

    "hello, this word is in `backticks`"
    

    另一种边缘情况是

    `${`I am nested`}`
    

    这种方法还将打破多行模板字符串。

    2.固定 xgettext

    当然,“正确”的解决方案是编写 xget文本 处理模板字符串。然后你就可以写了

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

    评估模板 将字符串转换为计算模板。模板字符串中使用的本地范围内的任何变量都需要提供给 评估模板 作为第二个参数中传递的对象的一部分(因为使用 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);
    }
    

    当然,这有点尴尬。这种方法的唯一优点是不需要预扫描重写。

    次要点,但如果原始模板字符串是多行的,则不能直接将其重写为常规字符串。在这种情况下,您可以将其保留为反勾选的模板字符串,但可以转义 $ \$ ,一切都会好起来:

    底线:除非你想重写 xget文本 ,使用解析器,或从事其他黑客活动,进行暴力替换。

        2
  •  0
  •   AlexMost    7 年前

    目前,我正在开发一个基于es6模板文字的本地化解决方案。你可以在这里查看- https://c-3po.js.org 。此项目具有提取功能(基于babel插件)。您还可以使用它来构建本地化的js。下面是它的样子:

    t`Hello ${name}`