Přeložit React Public HTML soubory

Nedávno jsem dostal za úkol přeložit soubory html ve veřejné složce v naší aplikaci Reagovat a to, co jsem považoval za přímočarý úkol, trvalo déle, než jsem čekal.

Můj výzkum mě přivedl k několika knihovnám, jako je google api, translater.js, linguminum atd. Ale nakonec jsem se spokojil s Transalator.js. Zde je odkaz na původní příspěvek, který mě s tím seznámil.

Co jsem hledal

Potřeboval jsem službu, která

  • Bude hostováno online
  • Bylo snadné jej nastavit a bylo lehké
  • Úložiště bylo pravidelně udržováno
  • Bude schopen správně vykreslit vložené značky HTML

Dostal jsem pouze 2 z možností, a to byla možnost 2 a 3. K použití jste museli stáhnout repo lokálně a nevykreslovalo správně vložené html značky. Absence možnosti jedna byla dobrá věc, protože mi dala možnost projít kód, vidět, jak to funguje, a dala mi příležitost provést změny, které potřebuji, abych získal to, co jsem chtěl. Pokud vás tolik nezajímají vložené html tagy, pak si stačí stáhnout knihovnu a hostit ji kdekoli si vyberete.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title eo-translator="title"></title>
  </head>
  <body>
    <div class="container">
     <h1 eo-translator="greeting"></h1>
     <h2 eo-translator="question"></h2>
    </div>

    <script src="/path/to/translate.min.js"></script>
    <script type="text/javascript">
        // Construct your dictionary
        const dictionary = {
          en: {
            greeting: 'Hello',
            question: 'How are you doing?',
            title: 'Test title'
          },
          es: { 
            greeting: 'Hola',
            question: '¿Como estas?',
            title: 'Título de la prueba'
          }
        };

        // Get the user's preferred language from the browser
        let language = (window.navigator.userLanguage || window.navigator.language).split('-')[0]
        const displayLanguage = language === 'es' ? 'es' : 'en';
        let translator = new EOTranslator(dictionary, displayLanguage);

        // The translator takes care of everything else
        translator.translateDOM();       
    </script>
  </body>
</html>

Moje řešení

Vzhledem k tomu, že výše uvedené nevyřešilo zobrazení vložených html značek, musel jsem trochu extrahovat část obsaženou v souboru translator.js, trochu ji vyladit a přidat javascript do svého html souboru. Tady byl můj konečný výsledek.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title eo-translator="title"></title>
  </head>
  <body>
    <div class="container">
     <h1 eo-translator="greeting"></h1>
     <h2 eo-translator="question"></h2>
    </div>

    <script src="/path/to/translate.min.js"></script>
    <script type="text/javascript">
      (function () {
        // Construct your dictionary
        const dictionary = {
          en: {
            greeting: 'Hello',
            question: 'How are you doing?',
            title: 'Test title'
          },
          es: { 
            greeting: 'Hola',
            question: '¿Como estas?',
            title: 'Título de la prueba'
          }
        };

        // Get the user's preferred language from the browser
        let language = (window.navigator.userLanguage || window.navigator.language).split('-')[0]
        const displayLanguage = language === 'es' ? 'es' : 'en';
        translateDOM();

        function translateDOM(DOMContainer) {
          const language = displayLanguage;
          const container = DOMContainer || typeof document === 'object' ? document : null;

          if (container) {
            const elements = container.querySelectorAll('[eo-translator]');
            elements.forEach((element) => translateElement(element, language));
          }
        }

        function translateElement(DOMElement, lang) {
          if (DOMElement) {
            const input = DOMElement.attributes['eo-translator'].value || DOMElement.textContent || DOMElement.innerText || DOMElement.innerHTML;

            // Here was where i made the change to display the embedded html tags. In the translator.js file, this line was DOMElement.innerText = translate(input);
            DOMElement.innerHTML = translate(input);
          }
        }

        function translate(input = '') {
          const language = displayLanguage;
          const fallback = input;
          const params = {};
          const frags = input.split('.').filter(frag => frag.length > 0);

          let output = dictionary.hasOwnProperty(displayLanguage);

          if (output) {
            if (frags.length > 1) {
              output = extractValue(dictionary, language, frags);
            } else {
              output = dictionary[language][input];
            }
          }

          return output ? assignParams(output, params) : fallback;
        }

        function assignParams(raw, params) {
          Object.keys(params).forEach(key => {
            const pattern = new RegExp(`{${key}}`, 'g');
            raw = raw.replace(pattern, params[key]);
          });
          return raw;
        };

        function extractValue(dictionary, language, frags) {
          let temp = dictionary[language];
          for (const frag of frags) {
            temp = temp[frag] || undefined

            if (!temp) {
              break;
            }
          }
          return temp;
        }
      })((typeof window !== 'undefined') ? window : this);
    </script>
  </body>
</html>

Těsně předtím, než skončím, byla další dobrá volba Translater.js, pokud vás nezajímají vložené značky html. Když o tom teď přemýšlím, mohl jsem to obejít. Boom, tady je to, co jsem mohl udělat. Nemůžu uvěřit, že mi to uniklo, protože jsem hledal něco přímočarého. Tady to máte. Toto níže je lepší varianta...

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title eo-translator="title">
      Test title
      <!--{es} Título de la prueba -->
    </title>
  </head>
  <body>
    <div class="container">
      <h2>
        Hello
        <!--{es}Hola! -->
        <a href="https://www.google.com/chrome/">
          Link to Google Chrome
          <!--{es}Enlace a Google Chrome -->
        </a>
      </h2>
    </div>

    <script src="https://unpkg.com/translater.js/dist/translater.js" type="text/javascript"></script>
    <script type="text/javascript">

    // You can still get the user's language with the example above and pass it to the lang option here. 
      var tran = new Translater({
        lang:"es"
      });
    </script>
 </body>
</html>

Pokud někdy narazíte na problémy bez mezery mezi slovy s vnořenými prvky, stačí, když za definici jazyka přidáte dvojité mezery

   <!--{es}  Enlace a Google Chrome-->

Závěrem, druhá možnost vám poskytuje větší kontrolu, protože se nemusíte starat o to, zda je balíček aktualizován nebo ne. Je to docela jednoduché a objemnější, ale smířil jsem se s tím.

Promiň, jestli je to dezorientované. Jen se snažím napsat svůj myšlenkový proces, který řeší problém. Neváhejte zanechat komentáře