0

I have created a jQuery function extending its own object $. This function translate those elements attached to the element this:

$.fn.extend({
  translate: function(sourceLang, targetLang) {
    if($(this).text().trim().length < 1 || !isNaN(parseInt($(this).text().trim())) || sourceLang == targetLang)
      return;

    let $function = this;

    $($function).each(function() {
      let $each = this;
      $.ajax({
        url: 'https://translate.yandex.net/api/v1.5/tr.json/translate',
        method: 'GET',
        dataType: 'JSONP',
        crossDomain: true,
        data: {
          key: /* my-secret-key */,
          text: $($each).text(),
          lang: sourceLang + '-' + targetLang
        },
        success: function(response) {
          try {
            if(response.code !== 200)
              throw "Response: " + response.code;
            $($each).text(response.text[0])
          } catch(error) {
            console.error('Translation error on element: ', $($function).text());
            console.error('Message returned by the server:', error);
          }
        },
        error: function(xhr, status, error) {
          console.error('Translation error on element: ', $($function).text());
          console.error('Message returned by the server:', xhr.responseText);
        }
      });
    });
  }
});

After loading the code I do this:

$(document).ready(function() {
    let lang = $('html').attr('lang').split('-')[0];
    $('td td:visible').translate(lang, "en");
}); 

Note: the HTML tag looks like this <html lang="es-ES"> depending on the logged user language.

The issue I have is the table loads after a couple of seconds (since we are not in Production environment they could be more than 30). Therefore the previous code block is not useful.

Note: the <tbody> tag is created when the data is added.

What I have tried is:

1. Create a setInterval() and clearInterval() when the $('td:visible').length is greater than 0:

let iv = setInterval(function() {
    let lang = $('html').attr('lang').split('-')[0];
    let rows = $('tbody td:visible');
    if(rows.length > 0) {
        rows.translate(lang, "en");
        clearInterval(iv);
    }
}, 1000);

2. Set a .delay() before the translation:

let isTranslated = false;
while(!isTranslated) {
    let lang = $('html').attr('lang').split('-')[0];
    let rows = $('tbody td:visible');
    if(rows.length > 0) {
        rows.delay(1000).translate(lang, "en");
        isTranslated = true;
    }
}

The memory consumed by the browser is greater than 200MB. I also tried with $('table').on('DOMSubstreeModified', 'tbody', function() {}) but it didn't work.

So, what approach would you recommend to use this translation plugin on this table after it loads its tbody?

Edit 1:

I have changed my code so I perform less API requests, thanks to the recommendation of @lucifer63:

let $function = this;
let collection = [];
let translation = '';
$(this).each(function() {
  collection.push($(this).text());
});
let text = collection.join('::');

$.ajax({
  url: 'https://translate.yandex.net/api/v1.5/tr.json/translate',
  method: 'GET',
  dataType: 'JSONP',
  crossDomain: true,
  data: {
    key: /* my-secret-key */,
    text: text,
    lang: sourceLang + '-' + targetLang
  },
  success: function(response) {
    try {
      if(response.code !== 200) {
        throw "Response: " + response.code;
      }
      translation = response.text[0].split('::');
      $($function).each(function() {
        $(this).text(translation.shift());
      });
    } catch(error) {
      console.error('Message returned by the server:', error);
    }
  },
  error: function(xhr, status, error) {
    console.error('Message returned by the server:', xhr.responseText);
  }
});

But still, I need to figure out how to print after data has loaded.

Martin Fernandez
  • 368
  • 5
  • 16
  • How do you inject the table in your document? If you use some framework for it you can always use some event that you can listen to. If you do it manually, just call your translation service after the injection. And by the way you better accomodate the text that needs translation in one query instead of many; afaik yandex has some queries limitations – lucifer63 Dec 07 '18 at 13:13
  • Thanks @lucifer63 for the comment. I am not sure how the table is inserted, but I am pretty sure it is loaded with [Liquid templating engine](https://help.shopify.com/en/themes/liquid/basics) with C#. Also, I will try to do less requests. – Martin Fernandez Dec 07 '18 at 13:22
  • maybe you can look ... "when" method of jQuery..its wait to one or mutiple ajax calls is fully complete before to perform an action – Sk. Dec 07 '18 at 14:23
  • @Martin Fernandez, lol, i just had some experience working with Yandex translation API, so it was a little "fyi" about the requests; sure it's offtop. As for Liquid templating engine: i suppose it runs under some kind of framework, therefore you can still listen to some events. But anyway, if you dont give a damn about how your project work, so just use a timeout, no need to search for another doors – lucifer63 Dec 07 '18 at 14:42
  • @lucifer63, lol, I do care about how "my" project works. But... now you "asked" I can investigate, read, ask, learn on how my project is deeply working but I don't have that time to do it. Thanks anyway for worrying about this project... – Martin Fernandez Dec 07 '18 at 14:47

1 Answers1

0

Well... I think I found the answer I was seeking:

$('body').on('DOMNodeInserted', 'table', function() {
    $('td:visible').translate('es', 'en');
});

It seems it is working correctly.

Martin Fernandez
  • 368
  • 5
  • 16