4

I am using QCoreApplication::translate() to translate text.

I am trying to understand whether a string has a translation.

Qt documentation states:

If none of the translation files contain a translation for sourceText in context, this function returns a QString equivalent of sourceText.

The problem I am facing is that I am getting results similar to this:

<message>
    <source>Side</source>
    <translation>Side</translation>
</message>

Where source and translation are the same.

In many languages, the translation is indeed same as the source. But if translate("Side") returns "Side", I can't tell whether the translation was exactly "Side" or whether the translation was empty.

How can I differentiate between the two cases?

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Kadir Erdem Demir
  • 3,531
  • 3
  • 28
  • 39
  • AFAIK there is no way. – Hatted Rooster Sep 23 '16 at 12:05
  • 1
    Why do you think you need to? What problem are you trying to solve? – Lightness Races in Orbit Sep 23 '16 at 12:07
  • 3
    @LightnessRacesinOrbit It is pretty straightforward what OP is facing. If there was no translation, the Library returns the source text. And in many languages, the translation exists but it is exactly the same as source. How to know which case the source fell in? – Khalil Khalaf Sep 23 '16 at 12:09
  • 1
    @GillBates XY in the QT-sources –  Sep 23 '16 at 12:12
  • 3
    @GillBates Also I am still not sure how did you realize that LRiO understood the Q. I think it is a disadvantage with the library. – Khalil Khalaf Sep 23 '16 at 12:15
  • There might always be solutions I believe. For example an alternative function call which takes the output string as parameter and return true or false can be my solution if exists. If such alternative does not exists it is still good to know that there is no alternative – Kadir Erdem Demir Sep 23 '16 at 12:20
  • @FirstStep: I'm asking why you ever need to know which case the source fell in. What difference does it make? – Lightness Races in Orbit Sep 23 '16 at 12:40
  • 3
    @LightnessRacesinOrbit I think it is because OP wants to know if `translate()` succeeded or failed, so he can report that ("_The translation of This is That_" **or** "_Sorry we don't have a translation for This_"). If he sent `Side` and received `Side`, what does that mean? Does it mean there exist a translation and it is `Side` or there is no translation and the library returned the source `Side` (what he sent)? – Khalil Khalaf Sep 23 '16 at 12:52
  • @FirstStep: Okay, great, that's a good reason! – Lightness Races in Orbit Sep 23 '16 at 15:09

2 Answers2

3

AFAIK there is no way to differentiate between the two cases through a QTCoreApplication::translate call.

However, QTranslator::translate returns a null QString when the key is not found (Qt 5). So one option would be to keep a container around with every QTranslator you've added through installTranslator() (since QCoreApplication doesn't have a way to get those back). Then, loop through that container, calling QTranslator::translate() on each instance in the container. When you get a non-empty result, you found a translation; if no translator succeeded, then you know the key doesn't exist in any QTranslator you have.

psuedo-code:

bool hasTranslation(const char* key)
{
  QString result;
  if(!translators.size())
    return false;

  for(const auto& translator : translators)
  {
    result = translator->translate("context", key);
    if(!result.isNull())
      break;
  }
  return !result.isNull();
}
Community
  • 1
  • 1
Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
  • The `if (translators.isEmpty())` test is unnecessary, as `result` is initially null, and the loop will execute 0 times in that case - or you could just replace the loop with `std::any_of(translators.begin(), translators.end(), [key](QTranslator *t){return !t->translate("context", key).isEmpty();});` (note: prefer `QString::isEmpty()` to `QString::isNull()`). – Toby Speight Apr 26 '17 at 16:01
2

AFAIK, there is no way. The translate function works in the following way: it iterates over all the translators that are available for the application, and tries to translate the source text with each of them. If it succeeds, it immediately breaks out of the loop and returns the translated text. If the aforementioned loop has finished, but the translation has not been found, it returns the source text in a form of a QString:

QString QCoreApplication::translate(const char *context, const char *sourceText,
                                    const char *disambiguation, Encoding encoding, int n)
{
    QString result;

    if (!sourceText)
        return result;

    if (self && !self->d_func()->translators.isEmpty()) {
        QList<QTranslator*>::ConstIterator it;
        QTranslator *translationFile;
        for (it = self->d_func()->translators.constBegin(); it != self->d_func()->translators.constEnd(); ++it) {
            translationFile = *it;
            result = translationFile->translate(context, sourceText, disambiguation, n);
            if (!result.isEmpty())
                break;
        }
    }

    if (result.isEmpty()) {
#ifdef QT_NO_TEXTCODEC
        Q_UNUSED(encoding)
#else
        if (encoding == UnicodeUTF8)
            result = QString::fromUtf8(sourceText);
        else if (QTextCodec::codecForTr() != 0)
            result = QTextCodec::codecForTr()->toUnicode(sourceText);
        else
#endif
            result = QString::fromLatin1(sourceText);
    }

    replacePercentN(&result, n);
    return result;
}

If you really need to be able to know if the translation could be found, you would have to subclass QTranslator class and override it's translate() function (since the translate() in QCoreApplication is non-virtual).

SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105