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 pilation 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 es to mind?
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 pilation 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 es to mind?
Share Improve this question edited Jan 21, 2016 at 4:05 user663031 asked Jan 19, 2016 at 16:34 domokundomokun 3,0034 gold badges31 silver badges55 bronze badges 5-
1
No, you can't "dumb down" a template string without losing the "smart" properties (which include string expansion). Notice that
(`A ${b=alert()}`)
will executealert()
, which won't happen with'A ${b=alert()}'
– Ismael Miguel Commented Jan 19, 2016 at 16:36 -
1
I know that. I don't need the smartness in
gettext
, since it is not smart enough to understand template strings. (I have clarified even more my question) – domokun Commented Jan 19, 2016 at 16:40 - Are you just asking about the string interpolation, or do you need template tags as well? – Bergi Commented Jan 20, 2016 at 1:59
- Have you tried a transpiler like babel? – Bergi Commented Jan 20, 2016 at 2:00
-
the transpiler is not a viable option because translation strings are wrapped in a function that gets transformed as well. E.g.
t('translate me')
bees something likefunction(par, 0)('translate me')
, whichgettext
doesn't understand – domokun Commented Jan 20, 2016 at 12:09
2 Answers
Reset to default 8Great question. There are four solutions that e 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/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.
Currently, I am working on a localization solution that is based on es6 template literals. You can check out it here - https://c-3po.js. This project has extraction functionality (based on the babel plugin). And also you can use it to build localized js. Here is how it looks like:
t`Hello ${name}`
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744294349a4567188.html
评论列表(0条)