0

I'm writing some code that rips string literals out of Typescript/JavaScript source as the first stage of a localisation toolchain I have planned.

The fly in the ointment is string interpolation.

I was on the verge of writing a function to transform an interpolation string into a function call that rips the expressions and then replaces the interpolation string with a function call that takes the expressions as parameters.

const a = 5;
const b = 7;
const foo = `first value is ${a + b}, second value is ${a * b}`;

becomes

import { interpolate } from "./my-support-code";
...
const a = 5;
const b = 7;
const foo = interpolate("first value is ${0}, second value is ${1}", [a + b, a * b]);

with the interpolate function working through the array values and replacing strings generated from the ordinal position

function interpolate(template: string, expressions: Array<any>): string {
  for (let i = 0; i < expressions.length; i++) {
    template = template.replace("${" + i + "}", expressions[i].toString());
  }
  return template;
}

This will probably work (not yet tried) but it occurred to me that this is probably a thoroughly invented wheel. The question is basically is there a well-established package that does a comprehensive job of this?

I know the above doesn't localise anything. The point is to be rid of interpolation strings so the substitution mechanism can assume that all strings are simple literals. The base language string taken from the above would be "first value is ${0}, second value is ${1}" and translators would be expected to place the tokens appropriately in whatever string they produce.

Peter Wone
  • 17,965
  • 12
  • 82
  • 134
  • Short answer: No. Long answer: This is *extremely* specific, and highly subjective behaviour, so it's unlikely to ever exist. You'll need to carefully audit your code, identify localization targets, and rewrite them one by one. – tadman Nov 26 '22 at 02:13
  • So the answer is it's too specialised and I'm not re-inventing the wheel and just code it myself. That's a helpful acceptable answer. – Peter Wone Nov 26 '22 at 02:14
  • Tip: Your use of a loop for substitutions is really, *really* sub-optimal. Consider a regex like `/\${(\d+)}/` where you can capture the index and use it in an array lookup. This results in one pass, not *N* passes per number of placeholders. Your code is unnecessarily *O(N^2)*. – tadman Nov 26 '22 at 02:14
  • 1
    It was illustrative. I'm going to use regexes, don't worry. – Peter Wone Nov 26 '22 at 02:15
  • If you're good with regular expressions you can use them identify *probable* localization targets, and perhaps even rewrite into a proposed substitution, but I'd take great care in unleashing some automatic replacement script on your code. It's probably better to vet each one individually. – tadman Nov 26 '22 at 02:16
  • 1
    To be honest the O(n^2) probably doesn't matter, there are rarely more than two or three tokens in a UI string. But yeah looping string replacement is nasty. – Peter Wone Nov 26 '22 at 02:20
  • Famous last words! Someone on your team might get a little ambitious and put in 25 substitutions on a page that sees a *lot* of rendering activity. I always assume the worst, and for something like this, the fix is trivial. `replace()` with a function replacement argument is actually extremely great at this sort of thing, it's near zero effort. – tadman Nov 26 '22 at 02:23
  • See [Defer execution for ES6 Template Literals](/q/22607806/4642212). – Sebastian Simon Nov 26 '22 at 02:29
  • @SebastianSimon while that's not a solution for the immediate problem it's fascinating and sure to be useful. – Peter Wone Nov 26 '22 at 04:35

1 Answers1

1

If you're going to tackle this on a non-trivial sized code base, the best you can really do is:

  1. Write a regular expression to identify common types of localization targets and identify them, probably by file + line number.
  2. Add comments to your code in these locations using a keyword that's easy to git grep for, or even something that can be added to your editor's syntax highlighting rules. Personally I use things like // LOCALIZE.
  3. If you're feeling ambitious, you could implement a rewriter that attempts to convert from template form to your localization's template requirements. Each conversion can be individually inspected, altered as required, and introduced. Hopefully you have test coverage to verify your code still works after this.
tadman
  • 208,517
  • 23
  • 234
  • 262
  • It's a proof of concept for a toolchain to accompany the VS Code extension localisation API. I have an open-source extension project with contributed localisations for several languages and it is a real mission managing updates out to the translators and back into the repo, and there was no support at all for localising anything other than settings descriptions, so I rolled my own. As a result when MS finally created an API I had a lot of feedback for them. I also shared a half-baked arm-wave of toolchain support and, well, me and my big mouth found ourselves _involved_. – Peter Wone Nov 26 '22 at 04:33