素晴らしい質問です。思いつく解決策は次の 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
たり、パーサーを使用したり、他のハッカーに従事したりしたくない場合は、力ずくで置き換えてください。