to expand on the "replace html with unique placeholders" solution:
i found that google, in rare cases, also translates numbers!
for example google translated [15]
to [fünfzehn]
in english to german.
my current solution is to encode my index numbers with special characters.
the 12 safe symbols that are never changed by google are []^'*-/_{}<>
(can change in future).
(todo: test more combinations of symbols and languages. can be automated.)
note: google can replace --
with -
, for example, so i also avoid repetitions.
$
is also preserved, but the order can be changed, e.g. from @$
to $@
const codeNumKey = "^'*-/_{}<>"; // 10 digits = 0123456789
const codeNumBase = codeNumKey.length;
const encodeNumTable = Object.fromEntries(codeNumKey.split('').map((c, i) => [i, c]));
function encodeNum(num) {
return num.toString(codeNumBase).split('').map(i => encodeNumTable[i]).join('');
}
const decodeNumTable = Object.fromEntries(codeNumKey.split('').map((c, i) => [c, i]));
function decodeNum(str) {
return parseInt(str.replace(/[\s+\u200B]/sg, '').split('').map(c => decodeNumTable[c]).join(''), codeNumBase);
}
// google can translate -- to -
// so we use "safe" ids without repetition
function getNextSafeId(lastId) {
for (let id = (lastId + 1); ; id++) {
let idStr = id.toString();
let idSafe = true;
for (let charIdx = 0; charIdx < (idStr.length - 1); charIdx++) {
if (idStr[charIdx] == idStr[charIdx + 1]) {
// found repetition
idSafe = false;
//if (showDebug) console.log(`skip unsafe id ${id}`);
break;
}
}
if (idSafe) return id;
}
}
google will insert spaces (\x20
) and zero-width spaces (\u200B
) between the characters, so we must parse them too. i remove \u200B
completely, cos i dont have it in my input text
i also encode indents, because google will change indent, for example add one space before every line
sample input:
<div>
<b>hello</b>
</div>
encoded:
[}^_]
[}^{]
hello
[}^}]
[}^<]
translated:
[ } ^ _ ]
[ } ^ { ]
こんにちは
[ } ^ } ]
[ } ^ < ]
decoded numbers:
decodeNum(String.raw`[ } ^ _ ]`) == 705
decodeNum(String.raw`[ } ^ { ]`) == 706
decodeNum(String.raw`[ } ^ } ]`) == 707
decodeNum(String.raw`[ } ^ < ]`) == 708
output:
<div>
<b>こんにちは</b>
</div>
my translate script has 700 lines, but also includes code to extract and insert text into my html source files. maybe someone wants to refactor this into a library? : )
im using the official webinterface of google translate, so i can fix translations with the help of google's dictionary. this can be an advantage, compared to other tools like doctranslate
my use case: translate my book of 30 pages html, with bold text, custom xml tags, custom html entities, pre tags, tables, ... working stable so far
update: this fails on complex texts, where google translate can change the order of words in a sentence, and then also the order of html tags is broken. so currently, im converting my html to docx, let google translate the docx file, and then i convert back from docx to html.