Is it possible in HTML5 to give translation service a hint for translating a specific element

174 Views Asked by At

I would like a specific element to be translated in a specific way for a specific language pair. For example, a movie-related web page like:

<!DOCTYPE html>
<html lang="tr">
...
<p>
 <span>Kamera:</span>
 <span translate="no">XYZ</span>
</p>

when translated (by Google) from Turkish to English, it becomes:

Camera: XYZ

which is OK. But when translated to Greek, it becomes:

ΦΩΤΟΓΡΑΦΙΚΗ ΜΗΧΑΝΗ: XYZ

which is not correct in this context and also the letter case becomes strangely UPPERCASE.

So, I would like to be able to give a hint to the translation engine, with a code like this:

<p>
 <span translate="tr:el:Κάμερα">Kamera:</span>
 <span translate="no">XYZ</span>
</p>

I know that the HTML code above is invalid. Is there a pure HTML-type method to give such hints to translation engines? A Google-specific method might also help.

4

There are 4 best solutions below

2
iDibya.com On

This is one way you can do it.

        function customizeTranslations() {
            const kameraElement = document.getElementById('kamera');
            const xyzElement = document.getElementById('xyz');

            const customTranslations = {
            'Kamera:': 'Camera:',
            'XYZ': 'Custom Translation for XYZ'
            };
            if (kameraElement.textContent in customTranslations) {
                kameraElement.textContent = customTranslations[kameraElement.textContent];
            }
            if (xyzElement.textContent in customTranslations) {
                xyzElement.textContent = customTranslations[xyzElement.textContent];
            }
        }
    <h1>Translation with Hints</h1>
    <p>
        <span id="kamera">Kamera:</span>
        <span id="xyz">XYZ</span>
    </p>
    <button onclick="customizeTranslations()">Customize Translations</button>

2
Iłya Bursov On

I don't know any good solution to that problem, though you can try to exploit css queries to replace content, something like this:

<!DOCTYPE html>
<html lang="tr">
<head>
<title>test</title>
<style>
:lang(el) span[data-translate-el-camera] span {
    display: none;
}
:lang(el) span[data-translate-el-camera]:after {
    content: "Κάμερα";
}
</style>
</head>
<body>
<p>
 <span data-translate-el-camera><span>Kamera:</span></span>
 <span translate="no">XYZ</span>
</p>
</body>

it is not very reliable method, but it works at least in chrome

1
0x01010 On

Yes, we can do it with MutationObservers, this code will run if any element's class or _msttexthash attribute changes. Chrome adds translated-ltr class to document when translated and Edge adds _msttexthash attribute to elements when translated

const attributeAddedCallback = function (mutationsList) {
    // Now this will run on any class change or _msttexthash attribute change
};
// Observe for changes on translate
const observer = new MutationObserver(attributeAddedCallback);
observer.observe(langspan, { attributes: true, subtree: true, attributeFilter: ['class', '_msttexthash'] });

Now we must check if page translated

const attributeAddedCallback = function (mutationsList) {
    // For Chrome
    if (document.documentElement.className.match('translated-ltr')) {
        // Translated
        dotranslations();
    } else {
        // For Edge
        var translated = false;
        for (const mutation of mutationsList) {
            if (mutation.type === 'attributes' && mutation.attributeName === '_msttexthash') {
                translated = true;
            }
        }
        if (translated) {
            // Translated
            dotranslations();
        }
    }
};
// Observe for changes on translate
const observer = new MutationObserver(attributeAddedCallback);
observer.observe(langspan, { attributes: true, subtree: true, attributeFilter: ['class', '_msttexthash'] });

Now we can detect page translated into which language with using a control text -If "language" translated into "dil" then page translated into Turkish -If "language" translated into "Γλώσσα" then page translated into Greek ...

langs = { 'dil': 'tr', 'language': 'en', 'Γλώσσα': 'el' }; // Add as you need

var langspan = document.createElement("span");
langspan.innerText = "dil";
langspan.lang = "tr";
langspan.translate = "yes";

function dotranslations() {
    var lang = langs[langspan.innerText];
    document.querySelectorAll("*").forEach(element => {
        if (element.hasAttribute('translate-suggestion-' + lang)) {
            element.innerText = element.getAttribute('translate-suggestion-' + lang);
        }
    });
}

Now construct the code:

translationsuggests.js

langs = { 'dil': 'tr', 'language': 'en', 'Γλώσσα': 'el' };

// Language control span that hidden
var langspan = document.createElement("span");
langspan.style.position = "fixed";
langspan.style.opacity = "0";
langspan.style.pointerEvents = "none";
langspan.innerText = "dil";
langspan.lang = "tr";
langspan.translate = "yes";
document.body.appendChild(langspan);

function dotranslations() {
    var lang = langs[langspan.innerText];
    document.querySelectorAll("*").forEach(element => {
        if (element.hasAttribute('translate-suggestion-' + lang)) {
            element.innerText = element.getAttribute('translate-suggestion-' + lang);
        }
    });
}

const attributeAddedCallback = function (mutationsList) {
    // For Chrome
    if (document.documentElement.className.match('translated-ltr')) {
        // Translated
        dotranslations();
    } else {
        // For Edge
        for (const mutation of mutationsList) {
            if (mutation.type === 'attributes' && mutation.attributeName === '_msttexthash') {
                // Translated
                dotranslations();
            }
        }
    }
};
// Observe for changes on translate
const observer = new MutationObserver(attributeAddedCallback);
observer.observe(langspan, { attributes: true, subtree: true, attributeFilter: ['class', '_msttexthash'] });

Usage

<html lang="tr">
<body>
    <script src="path/to/translationsuggests.js"></script>
    <p translate="yes" translate-suggestion-el="Κάμερα:" translate-suggestion-en="Cam:">Kamera:</p>
    <span translate="no">XYZ</span>
</body>
</html>

EDIT

I said "Chrome adds translated class to document" but it was adding translated-ltr, sorry, my mistake.

0
FedKad On

Although still not exactly what in my original question I was asking about, I tried to improve the answer from @IłyaBursov as follows:

<!DOCTYPE html>
<html lang="tr">
<head>
<title>test</title>
<style>
/* by default display only "tr" and nothing else: */
[class^="lang_"] {  display: none;  }
.lang_tr {  display: inline;  }

/* Now enable only the relevant language content: */
:lang(el) > .lang_el {  display: inline;  }
:lang(el) > .lang_tr {  display: none;  }

:lang(en) > .lang_en {  display: inline;  }
:lang(en) > .lang_tr {  display: none;  }
</style>
</head>
<body>
<p>
 <span class="lang_tr">Kamera</span>
 <span class="lang_el">Κάμερα</span>
 <span class="lang_en">Cam</span>
 <span translate="no">XYZ</span>
</p>
</body>

This way, I got rid of putting "content" inside CSS, the CSS code is "static" now, and the HTML code is more easy to understand.