Suggestions for using tr() with variables



  • Hi,

    I'm rewriting my story editor (screenshots: [url=http://mkoskim.drivehq.com/moe/screenshot.moepm.jpg]project manager[/url] and [url=http://mkoskim.drivehq.com/moe/screenshot.moe.jpg]editor[/url]) from Python & GTK to C++ & Qt. It uses XML format and when I read in the file, I store the element content (e.g. attributes and elements named like "title", "content", "synopsis", ...) to a string-addressable hash (following the Python implementation):

    [code]
    class Record
    {
    ...
    QHash<QString, QString> fields;
    ...
    void setField(QString name, QString value) { fields[name] = value; }
    QString getField(QString name) { return fields[name].value(); }
    }
    [/code]

    When I show story elements in GUI widgets, I use directly the field names. For example, my custom ItemModel stores the field names to show in views, and uses the names to retrieve data:

    [code]
    class ItemModel
    {
    ...
    addColumn(QString name) { columns.append(name); }
    ...
    QVariant data(...) { ... return item->getField(columns[index.column()]); }
    ...
    };
    [/code]

    Now the question: I already use tr(), and I would like to use it to translate the field names to "human-readable" form, e.g. "title" -> "Title" (en), "Otsikko" (fi):

    [code]
    QVariant ItemModel::headerData(...) { ...return tr(columns.value(section)); }
    [/code]

    What would you think, what would be the best way to implement this kind of translation? I have thought to use some sort of "fake" translations to be able to use Qt linguist, something like this:

    [code]
    ItemModel::ItemModel()
    {
    ...
    // Fake translations for Qt Linguist
    tr("title");
    tr("subtitle");
    ...
    }

    QVariant ItemModel::headerData(...) { ...return tr(columns.value(section)); }
    [/code]

    Is there any other way? Can I add some comments to tell the linguist to add translations even if they are not directly present in source code?


  • Moderators

    Have a look at "this thread":http://developer.qt.nokia.com/forums/viewthread/7396. It's similar.

    Basically you use a qstring with %1 %2 .... placeholders which you can fill in with parameters using the arg member.



  • [quote author="Eddy" date="1319199226"]
    Basically you use a qstring with %1 %2 .... placeholders which you can fill in with parameters using the arg member.
    [/quote]

    Hmmh, I don't get it. I thought that args are used to add variable content to translations (e.g. QString(tr("Count: %1")).arg(count)), but how can I add translations to dynamic content?

    I was probably not describing my aim very clearly. I try it again. I load an XML document, and I would like to translate attributes and their content:

    [code]
    // Load XML document
    QDomDocument doc;
    doc.setContent(QFile("file.xml"));

    ...
    // Get some node from document
    QDomElement node;

    // Translate node attribute names (and values) to GUI
    QDomNamedNodeMap attrs = node.attributes();

    for(int i = 0; i < attr.size(); i++)
    {
    cout << QObject::tr(attr.nodeName())
    << " = "
    << QObject::tr(attr.nodeValue());
    }
    [/code]

    For example, one element is "TitleItem", containing the title of the story, and type of it:

    [code]
    <TitleItem type="shortstory" ...> ... </TitleItem>
    [/code]

    I would like to add translations to those with Qt Linguist, so one way is to add "fake" translations to source, like below?

    [code]
    ...
    QObject::tr("type"); // Translation for type attribute name
    QObject::tr("shortstory"); // Translation for one type attribute value
    QObject::tr("longstory"); // Translation for another type attribute value
    ...
    [/code]

    Is there any better way to do this?



  • You want to be able to dynamically translate a word taken from this xml file. So this could be any word, right? Then how do you want lupdate to populate the language file correctly? lupdate cannot guess the words that will come out of your xml.



  • In general, that is possible.
    The only thing is, you have to manage the ts files by hand :-(
    So if you create the ts files by hand, you can call tr with variables :-)



  • [quote author="neFAST" date="1319202492"]You want to be able to dynamically translate a word taken from this xml file. So this could be any word, right?[/quote]

    Yes and yes.

    [quote author="neFAST" date="1319202492"]Then how do you want lupdate to populate the language file correctly? lupdate cannot guess the words that will come out of your xml.[/quote]

    No, but I can - so that's why I thought that I could write those "fake" translations (unused translations, with some suitable context, possibly placed in some dead code sections) to make lupdate to know the words.



  • [quote author="Gerolf" date="1319202765"]In general, that is possible.
    The only thing is, you have to manage the ts files by hand :-([/quote]

    Oh, no, that's something I would not like to do :(

    [quote author="Gerolf" date="1319202765"]So if you create the ts files by hand, you can call tr with variables :-)[/quote]

    There is no some comment fields for lupdate/linguist to tell the possibly content of variables? If not, then I try to make that fake translation method work...



  • Did anyone solve this?? I have a massive amount of strings to be translated for a big menu structure and would prefer them not to be hard coded - prefer to read them from an XML file - managing the ts file by hand would be a huge task prone to error.



  • [quote author="Dolphin" date="1338472810"]Did anyone solve this?? I have a massive amount of strings to be translated for a big menu structure and would prefer them not to be hard coded - prefer to read them from an XML file - managing the ts file by hand would be a huge task prone to error.[/quote]
    Why don't you do the translations directly in your XML then?

    Otherwise, the only option I can see is that you write a kind of pre-compiler that parses your XML, and generates code for it that contains the strings to be translated using of the methods that can be picked up by lupdate.



  • Using the Menu XML is an option but it would be preferable not to give such a key file out to all and sundry (this system has to cope with lots of languages, braille, speech and hands free so a LOT of things can go wrong if the menu xml is messed up).

    According to the documentation QT_TR_NOOP should work but I have not managed that yet.

    Thanks for your thoughts, hope you had a good loooooooooong weekend.



  • QT_TR_NOOP can only be used with static texts. Text that have a value during the pass that lupdate does over your source code. At that point the XML is not loaded of course.

    So, if you really want this, the custom compiler to create a source file from the XML is the only viable solution.



  • I have just now got this code:

    @
    QString text = QT_TR_NOOP("test, test!");

    QPushButton hello(QPushButton::tr(text.toStdString().c_str()));
    QPushButton hello2(QPushButton::tr("Hello from Nicola"));
    

    @

    giving me this TS file:
    @
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE TS>
    <TS version="2.0" language="en_US">
    <context>
    <name>QPushButton</name>
    <message>
    <source>Hello from Nicola</source>
    <translation type="unfinished"></translation>
    </message>
    </context>
    <context>
    <name>TranslationObject</name>
    <message>
    <source>test, test!</source>
    <translation type="unfinished"></translation>
    </message>
    </context>
    </TS>
    @
    Which is exactly what I need - woop! My code was not in a QObject, doh! ( Little things :-S )
    Thank you :-)

    Edit: Please use @ tags to surround code sections; Andre



  • If your code is not a QObject, you can use QObject::tr. It is a static method after all...



  • Well, that is what I thought but my code did not work until I put it in a QObject (a frustrated experiment) but I have just moved it back out of the QObject (deleted the TS) and it works. Must have been something funky about the update of the TS). Either way, it works, yay!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.