Web Development

Parsing text with a translation function – JavaScript – SitePoint Forums


I’m working on a plugin. I have two basic types of options that developers can use

toggleButtonHTML: '<button aria-controls="weglot-list" aria-expanded="false" aria-haspopup="listbox" role="combobox" class="fs-weglot-toggle">{language}</button>', 
//toggleButtonHTML: '<button aria-controls="weglot-list" aria-expanded="false" aria-haspopup="listbox" role="combobox" class="fs-weglot-toggle">Translate<span class="fsStyleSROnly"> this page</span></button>',

They can only pick one or the other. The commented out option is fully taken care of. In other words, I have my plugin properly discerning the text of the button + any hidden spans (fsStyleSROnly is a screen-reader only class – so it hides text visually). Translation is perfect. This use case is if the design has a button called “Translate” and it opens a dropdown of languages you can click to translate.

The other design pattern is what I’m trying to focus on. There may be situations where instead of “Translate” as a button, it shows the active language the user is on. So if you loaded up the page to English, you could show the 2 character code “EN” (which the data point will be {lang}) or “English” which should generate if {language} is used. I have a few problems. E.g. I have this function which I was using to replace {lang} and {language} BUT this function alone isn’t enough because upon initial rendering, it will replace {lang} and {language} which means future translations cannot translate it properly. E.g. maybe it translates English to “Ingles” instead of “Espanol”. So this function needed to be updated to check for spans or the {lang}/{language}

getUpdatedToggleButtonHTML() {
    const { toggleButtonHTML } = this;

    // Replace {lang} and {language} with the appropriate values
    const updatedHTML = toggleButtonHTML
      .replace(/{lang}/g, Weglot.getCurrentLang())
      .replace(/{language}/g, () => {
        const currentLang = Weglot.getCurrentLang();
        return Weglot.getLanguageName(currentLang);
      });

    return updatedHTML;
  }

So the new attempt

getUpdatedToggleButtonHTML() {
  const { toggleButtonHTML } = this;
  const currentLang = Weglot.getCurrentLang();
  const translatedLanguageName = Weglot.getLanguageName(currentLang);

  // Check for the existence of {lang} or {language}
  const hasLangOrLanguage = /{lang}|{language}/.test(toggleButtonHTML);

  // Replace either {lang}/{language} or the spans with the appropriate values
  let updatedHTML = toggleButtonHTML;
  if (hasLangOrLanguage) {
    updatedHTML = updatedHTML
      .replace(/{lang}/g, `<span data-translation-type="lang">${currentLang}</span>`)
      .replace(/{language}/g, `<span data-translation-type="language">${translatedLanguageName}</span>`);
  }

  return updatedHTML;
}

This new code has 2 problems though: the toggleButton actually won’t click to open my dropdown menu. I see in inspector that something is happening to the attributes, but even if I manually open the dropdown (disabling some CSS), the text of the button stays as “english”

The only other function which is relevant, is addToggleButton() which runs if you’ve elected to output the toggleButton (I have it as a boolean). So, function gets called, addToggleButton runs, and off to the races…The accessibility function is irrelevant IMO. It does stuff like arrow support, escape, attributes work, etc

addToggleButton() {
    const toggleButton = $(this.target).prepend(this.getUpdatedToggleButtonHTML()).find('.fs-weglot-toggle');
    const dropdownList = $(this.target).find(".weglot-list");

    // Accessibility function
    this.toggleButtonAccessibility(toggleButton, dropdownList);

    // Store the original text and inner span text separately
    const originalButtonText = toggleButton.contents().filter(function () {
      return this.nodeType === 3; // Text node
    }).text().trim();

    const originalInnerSpanText = toggleButton.find("span.fsStyleSROnly").text().trim();

    // Update the toggle button text when the language changes
    Weglot.on("languageChanged", (newLang, prevLang) => {
      // Strip the inner span if it exists
      const innerSpan = toggleButton.find("span.fsStyleSROnly");
      if (innerSpan.length) {
        this.translateText(innerSpan.text(), newLang, (translatedText) => {
          innerSpan.text(`${translatedText}`);
        });
      }

      // Translate the button text using the stored original text
      this.translateText(originalButtonText, newLang, (translatedText) => {
        toggleButton.contents().filter(function () {
          return this.nodeType === 3; // Remove existing text nodes
        }).remove();

        // Insert the translated text as a new text node
        toggleButton.prepend(document.createTextNode(`${translatedText}`));

        // Translate the original inner span text
        this.translateText(originalInnerSpanText, newLang, (translatedInnerSpanText) => {
          // Remove existing inner span
          innerSpan.remove();

          // Append the translated inner span after translation only if it's not empty
          if (translatedInnerSpanText) {
            toggleButton.append(` <span class="fsStyleSROnly">${translatedInnerSpanText}</span>`);
          }
        });
        
      });
    });

    // Close dropdown when clicking outside
    $(document).on("click", (event) => {
      const isDropdownClick = dropdownList.is(event.target) || dropdownList.has(event.target).length > 0;
      const isToggleButtonClick = toggleButton.is(event.target);

      if (!isDropdownClick && !isToggleButtonClick) {
        dropdownList.removeClass("weglot-list-open");
        toggleButton.removeClass("active").attr('aria-expanded', 'false').focus();
      }
    });
  }

How can I get this working so that if {lang} (“EN”) or {language} (“English”) is used, it works? In my head, if toggleButtonHTML has either of those, it should replace it with a with some sort of data-language-type attribute which we can then use to say “hey, this should not translate normally, like to Ingles, but rather update it with the new {lang} or {language} (I have functions which can get me this info – I just need to detect it)

Thank you.



Source

Related Articles

Back to top button