crow-translate / QOnlineTranslator

A library for Qt5 that provides free usage of Google, Yandex and Bing translate API.
GNU General Public License v3.0
79 stars 12 forks source link

Question about translate call with return value #16

Closed Light-Wizzard closed 2 years ago

Light-Wizzard commented 2 years ago

Is there a way to call translate without having to connect to the finished thread?

I have a list of words I need to translate in a loop, and I want to handle each translation before going on to the next, currently, I would have to write a cue function to handle this, one issue is that I want to switch engines if it fails and then retry, this is easy to do if it is not threaded is my point, you can understand why, for now, I will work on the logic of a cue to handle this, but was wondering if there is another method, or function call I missed.

Sorry to pound on you with issues, they are easy to fix, but I just started to use this and found roadblocks to a threaded model, and it is mostly due to the fact I am that I am sure you have another way of doing this, but I could not find many working examples that relate to how I am using this, I have no GUI to slow down during this process, and really just want the results as fast as I can get them, I handle the GUI it does have by using system updates to show progress, I can use a one-shot timer to call the function and let it run on its own thread, letting the progress function terminate the call when it is completed, I thought about just pushing everything into an array and dealing with it with the call finishes, then resubmitting failures to another engine, but that gets ugly.

My problem is that in the loop each call ends up in its own thread, and I have no way to get progress from it, no way to have it return a value without waiting for a signal, I noticed I will have many threads running due to the way I am feeding it jobs without a proper cue controller, but I am new to this code, and that is my biggest issue, I know there is a way to write a scheduler, and use an emit to kill a wait state in the MainWindow, to keep it responsive, really what I need is a good example showing how to process a list of words, and switching engines to try to get a translation for that word.

I am working on a GitHub project that is not published yet, it translates my ts files, I parse the undefined words and make a list of them to translate, I could have them come up and give the user the option on what engine to use per word, and let them deal with failures, which would resolve this issue, but that would make it less automated, so I thought I would run this by you and see if you know of a better solution.

In my main loop, I have to inject a wait state so I am not pounding on any service with repeated calls during a specified time limit, and where my tracking threads have led me to lockouts, these delays can be long at times, in minutes to hours at times, I have to go by a quota system for usage, so this app knows upfront this will take a long time, this is a port of another program I wrote years ago and learned the hard way about asking for too many translations due a given time period, so having a non-threaded call would be a lot easier in this situation, I have seen it takes days to translate a file without getting locked out of a service, all these services have a limit, so I am more concerned with metering calls, and really do not want to make this an interactive process, just a push of a button and check it each day to see how far it has gotten, as such, it has settings for paid accounts, and free accounts.

Thanks, Flesh

Shatur commented 2 years ago

Just use QEventLoop to achieve sync translation. Something like this:

QOnlineTranslator translator;
qDebug() << "Translating...";

QEventLoop eventLoop;
connect(&translator, &QOnlineTranslator::finished, &loop, &QEventLoop::quit);
translator.translate("Hello world", QOnlineTranslator::Google);
loop.exec();

qDebug() << "Done...";

Networking is async by default Qt, this is why this library is async too.

Light-Wizzard commented 2 years ago

Thanks, QEventLoop is what I needed, without it I was get racing, I get it now, been a while since I worked with threads.

I have a question about Free and Paid Translation service accounts, not sure if you have a forum for these types of questions, I wanted to know if you use the free account for Google as well as the paid service, not sure how that varies as far as the calls go, but I know from using trans, that if you have the paid account is set up on your machine it would use it, it did not need a different API from what I have noticed anyway, not sure if Bing or Yandex has paid accounts, but I could not find any information about this, and was wondering if you knew offhand?

Thanks, Flesh

Shatur commented 2 years ago

No, we use a free public API.

Light-Wizzard commented 2 years ago

Maybe you can add a wiki and a few examples like this, it would help new users like myself.

    QOnlineTranslator translator;
    qDebug() << "Translating...";
    QEventLoop eventLoop;
    translator.translate("Hello world", QOnlineTranslator::Google);
    QObject::connect(&translator, &QOnlineTranslator::finished, &eventLoop, [&]
    {
        if (translator.error() == QOnlineTranslator::NoError)
            qInfo() << translator.translation();
        else
            qCritical() << translator.errorString();
        eventLoop.quit();
    });
    eventLoop.exec();
    qDebug() << "Done...";

Thanks, Flesh

Shatur commented 2 years ago

Using a library synchronously is a very rare case. Typically Qt applications are GUI applications and it is not a good idea to use QEventLoop for them. Therefore, I did not include this in the example so that people would not make a mistake. But if you think otherwise - send a PR to the README, I will accept.

Light-Wizzard commented 2 years ago

The last example works great, my problem was in my logic in the way I was dealing with the threads, the last example is just a combination of examples you gave that works, and the way to do it, I just needed a working example of how to use the function the right way, digging through code I might find problems, but rarely find solutions that way, maybe just add an example like this to your documentation somewhere for the next person to find it would be great, I understand this might not be the best practice, but if you need to deal with the translations one at a time, I do not see another approach, my translations strings are per tr, so very short request, and I have to add delays, I know from experience how many translations google will allow before cutting you off, which is why I need to use this approach, I got this part working last night and will publish my project soon, it is called Qt Lingo, it is a different way of localized files.

You can close all the issues I have opened, they have all be answered, just a few issues I ran into and I am sure others would have run into them eventually.

Thanks for all the help, I am getting back into programming to keep my mind off of cancer, bad enough I have, now my Santa Paws Puppy has it.

Flesh