I solved this problem in one of my own projects by introducing a special helper class holding both the original string and the translated one. Here's the rough sketch of how it looks:
class LocalizedString
{
public:
LocalizedString(const char * str) :
m_originalString(str),
m_localizedString(tr(str))
{}
const char * originalString() const { return m_originalString; }
const QString & localizedString() const { return m_localizedString; }
private:
const char * m_originalString;
QString m_localizedString;
}
Then the code using this class works like this:
// In one place within the code:
LocalizedString errorDescription = QT_TR_NOOP("Some message which should go both to the log and to the user");
qDebug() << errorDescription.originalString();
<...>
// In some other place within the code which gets errorDescription variable from somewhere and needs to show it to the user
showErrorMessage(errorDescription.localizedString());
The main part within the approach is the use of QT_TR_NOOP macro. What it does is marking the string literal enclosed into it as the one requiring extraction during qmake
step for further translation. Unlike QObject::tr
, this macro does not convert the non-translated text into the translated one. If you want to access the translated text, you need to call tr
manually later on - as I did in the above example within the constructor of LocalizedString
.
Note that QT_TR_NOOP
is designed to be used within classes i.e. the context for translation would be the name of the class inside some method of which the macro is present. If you have free standing functions or if you want to specify the context yourself, use QT_TRANSLATE_NOOP macro instead - its second argument is the translation context.
Upd.: one more tip: in my real implementation of LocalizedString
it has operator<<
which prints the original, non-localized string. It is convenient because this way you can just pass the object of LocalizedString
class to QDebug
without calling its originalString
method.