9

ES6 テンプレート文字列を認識するという制限を回避するgettext必要があり、コードに「通常の」文字列のみを含めるために、コンパイル手順としてテンプレート文字列の「補間されていない値」を取得することを考えました。

基本的に私が達成したいのは、これを変換することです

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"

これを達成するための残忍な方法の 1 つは を使用するsedことです。

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

より良い、よりクリーンなアイデアが頭に浮かびますか?

4

2 に答える 2

8

素晴らしい質問です。思いつく解決策は次の 4 つです。

1.ブルートフォース

あなたが提案したように、翻訳可能な文字列をスキャンする前に、逆引用符を引用符で力ずくで置き換えることは、リスクを理解している限り、恐ろしい考えではありません。たとえば、次のことを考慮してください。

"hello, this word is in `backticks`"

別のエッジケースは

`${`I am nested`}`

このアプローチでは、複数行のテンプレート文字列も壊れます。

2.修正xgettext

もちろん、「正しい」解決策はxgettext、テンプレート文字列を処理する fork を作成することです。次に、あなたはただ書くことができます

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

残念ながら、これは見た目より難しいかもしれません。xgettext 内には、文字列に関連する一連のハードワイヤード ロジックがあります。もしあなたがこのプロジェクトを引き受けたら、多くの人が感謝します。

3. パーサーの使用

より堅牢な代替手段は、Esprima などの JavaScript パーサーを使用することです。これらのパーサーは、トークン (テンプレート文字列など) を取得する機能を公開します。http://esprima.org/demo/parse.htmlでわかるように、検索する関連トークン タイプはTemplateLiteral.

4. お勧めできないハッキング

もう 1 つの (悪い?) アイデアは、最初はテンプレート文字列を通常の文字列として記述し、実行時にそれらをテンプレート文字列として扱うことです。関数を定義しますeval_template:

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

eval_template文字列を評価済みテンプレートに変換します。テンプレート文字列で使用されるローカル スコープの変数はeval_template、2 番目のパラメーターで渡されるオブジェクトの一部として提供される必要があります (を使用して作成された関数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たり、パーサーを使用したり、他のハッカーに従事したりしたくない場合は、力ずくで置き換えてください。

于 2016-01-19T17:43:55.280 に答える