Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Interesting effect with tr().arg()

Interesting effect with tr().arg()

Scheduled Pinned Locked Moved Solved General and Desktop
14 Posts 5 Posters 6.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    ChrisVT
    wrote on last edited by
    #1

    Hi all,

    I observed an interesting issue with tr().arg() a minute ago - I do have a work-around but wonder if this is actually a bug. Opinions of course welcome.

    Suppose you do the following:

    tr("%1%2%3").arg("A").arg("%2A").arg("B")

    The expected outcome is "A%2AB", right? Well, the "%" in the second arg() seems to throw the replacement algorithm off, because the actual result is "ABA%3".

    My workaround is to put the "%"-containing text as the last arg(), then it works:

    tr("%1%3%2").arg("A").arg("B").arg("%2A").

    It seem to me that the text in an arg should not affect how the args are treated for tr().

    Best,
    Chris

    JonBJ joeQJ 2 Replies Last reply
    0
    • C ChrisVT

      Hi all,

      I observed an interesting issue with tr().arg() a minute ago - I do have a work-around but wonder if this is actually a bug. Opinions of course welcome.

      Suppose you do the following:

      tr("%1%2%3").arg("A").arg("%2A").arg("B")

      The expected outcome is "A%2AB", right? Well, the "%" in the second arg() seems to throw the replacement algorithm off, because the actual result is "ABA%3".

      My workaround is to put the "%"-containing text as the last arg(), then it works:

      tr("%1%3%2").arg("A").arg("B").arg("%2A").

      It seem to me that the text in an arg should not affect how the args are treated for tr().

      Best,
      Chris

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @ChrisVT
      Firstly, I can't see how this can have anything to do with tr() function. As per http://doc.qt.io/qt-5/qobject.html#tr, QObject::tr() simply returns a QString, only then does it evaluate the .arg()s, so the whole thing is simply QString::arg() calls, forget about tr().

      • Check what plain tr("%1%2%3") returns?
      • Check what QString("%1%2%3").arg("A").arg("%2A").arg("B") returns?
      C 1 Reply Last reply
      1
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        There's a warning about that in QString's documentation

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        1
        • C ChrisVT

          Hi all,

          I observed an interesting issue with tr().arg() a minute ago - I do have a work-around but wonder if this is actually a bug. Opinions of course welcome.

          Suppose you do the following:

          tr("%1%2%3").arg("A").arg("%2A").arg("B")

          The expected outcome is "A%2AB", right? Well, the "%" in the second arg() seems to throw the replacement algorithm off, because the actual result is "ABA%3".

          My workaround is to put the "%"-containing text as the last arg(), then it works:

          tr("%1%3%2").arg("A").arg("B").arg("%2A").

          It seem to me that the text in an arg should not affect how the args are treated for tr().

          Best,
          Chris

          joeQJ Offline
          joeQJ Offline
          joeQ
          wrote on last edited by joeQ
          #4

          @ChrisVT Hi,Friend,Welcome.

          You can write some test code, to find why. It is interesting.

          Do not omit Intermediate results.

          You will clear well from following snippet:

          #include <QCoreApplication>
          
          #include <QtCore/QDebug>
          
          int main(int argc, char *argv[])
          {
              QCoreApplication a(argc, argv);
              qDebug() << QObject::tr("%1%2%3"); /// %1%2%3
              qDebug() << QObject::tr("%1%2%3").arg("A"); /// A%2%3
          
              qDebug() << QObject::tr("%2%3").arg("A"); ///A%3
          
              qDebug() << QObject::tr("%1%2%3").arg("A").arg("%2A"); /// A%2A%3
              qDebug() << QObject::tr("%1%2%3").arg("A").arg("%2A").arg("B"); /// ABA%3
              // To replace First %, is %1=>A, result is tr(A%2%3).arg(%2A).arg(B) 
              // In Result To replace First %, is %2=>%2, result is (A%2A%3).arg(B)
              // In Result To replace First %, is %2=>B, result is ABA%3
          
              return a.exec();
          }
          
          

          Just do it!

          JonBJ 1 Reply Last reply
          0
          • VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by
            #5

            I discussed in the past this and also the season why you should only use arg(QString) and not the other overloads

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            C 1 Reply Last reply
            2
            • joeQJ joeQ

              @ChrisVT Hi,Friend,Welcome.

              You can write some test code, to find why. It is interesting.

              Do not omit Intermediate results.

              You will clear well from following snippet:

              #include <QCoreApplication>
              
              #include <QtCore/QDebug>
              
              int main(int argc, char *argv[])
              {
                  QCoreApplication a(argc, argv);
                  qDebug() << QObject::tr("%1%2%3"); /// %1%2%3
                  qDebug() << QObject::tr("%1%2%3").arg("A"); /// A%2%3
              
                  qDebug() << QObject::tr("%2%3").arg("A"); ///A%3
              
                  qDebug() << QObject::tr("%1%2%3").arg("A").arg("%2A"); /// A%2A%3
                  qDebug() << QObject::tr("%1%2%3").arg("A").arg("%2A").arg("B"); /// ABA%3
                  // To replace First %, is %1=>A, result is tr(A%2%3).arg(%2A).arg(B) 
                  // In Result To replace First %, is %2=>%2, result is (A%2A%3).arg(B)
                  // In Result To replace First %, is %2=>B, result is ABA%3
              
                  return a.exec();
              }
              
              
              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #6

              @joeQ
              I still don't get how this behaviour is anything to do with using QObject::tr(), in your examples and this thread title? I can't test because I don't use C++, but wouldn't your examples behave just the same if you used QString in place of QObject::tr? The arg()s are evaluated after the tr(), not before, aren't they?

              1 Reply Last reply
              1
              • JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by JonB
                #7

                Further to what I have written above, and to @VRonin 's post:

                ISTM that you should never use qString.arg().arg(). The chained args, which work on the substituted result from the previous arg() calls, are far too dangerous. [You wouldn't use C's sprint(format) with a non-literal format string for the same kind of reason, would you?]

                Like with sprintf, or repeated replaces or regular expression substitutions, you can only afford to use a substituter which works from a single, original string specifying what to do, not one affected by a previous substitution. You need a function which does multiple substitutions at the same time, not one after the other, to be safe.

                So I don't see/where is Qt's QString::argList() function, so you can go like: QString("%1%2%3")::argList(arg1, arg2, arg3), which is what you need to do?

                VRoninV 1 Reply Last reply
                0
                • JonBJ JonB

                  @ChrisVT
                  Firstly, I can't see how this can have anything to do with tr() function. As per http://doc.qt.io/qt-5/qobject.html#tr, QObject::tr() simply returns a QString, only then does it evaluate the .arg()s, so the whole thing is simply QString::arg() calls, forget about tr().

                  • Check what plain tr("%1%2%3") returns?
                  • Check what QString("%1%2%3").arg("A").arg("%2A").arg("B") returns?
                  C Offline
                  C Offline
                  ChrisVT
                  wrote on last edited by
                  #8

                  @JonB Correct, this has nothing to do with tr(). This was just the way I used it in my original code, and I didn't remove it. Sorry. The problem also occurs with QString.

                  1 Reply Last reply
                  1
                  • JonBJ JonB

                    Further to what I have written above, and to @VRonin 's post:

                    ISTM that you should never use qString.arg().arg(). The chained args, which work on the substituted result from the previous arg() calls, are far too dangerous. [You wouldn't use C's sprint(format) with a non-literal format string for the same kind of reason, would you?]

                    Like with sprintf, or repeated replaces or regular expression substitutions, you can only afford to use a substituter which works from a single, original string specifying what to do, not one affected by a previous substitution. You need a function which does multiple substitutions at the same time, not one after the other, to be safe.

                    So I don't see/where is Qt's QString::argList() function, so you can go like: QString("%1%2%3")::argList(arg1, arg2, arg3), which is what you need to do?

                    VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #9

                    @JonB said in Interesting effect with tr().arg():

                    You need a function which does multiple substitutions at the same time, not one after the other, to be safe.

                    πŸ‘πŸ‘πŸ‘πŸ‘πŸ‘πŸ‘πŸ‘πŸ‘

                    @JonB said in Interesting effect with tr().arg():

                    which is what you need to do?

                    Actually it's very easy to solve the problem at hand: tr("%1%2%3").arg(QStringLiteral("A"),QStringLiteral("%2A"),QStringLiteral("B"))

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    JonBJ 1 Reply Last reply
                    2
                    • VRoninV VRonin

                      @JonB said in Interesting effect with tr().arg():

                      You need a function which does multiple substitutions at the same time, not one after the other, to be safe.

                      πŸ‘πŸ‘πŸ‘πŸ‘πŸ‘πŸ‘πŸ‘πŸ‘

                      @JonB said in Interesting effect with tr().arg():

                      which is what you need to do?

                      Actually it's very easy to solve the problem at hand: tr("%1%2%3").arg(QStringLiteral("A"),QStringLiteral("%2A"),QStringLiteral("B"))

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #10

                      @VRonin
                      .arg() takes a list of arguments?

                      VRoninV 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @VRonin
                        .arg() takes a list of arguments?

                        VRoninV Offline
                        VRoninV Offline
                        VRonin
                        wrote on last edited by
                        #11

                        Yes, up to 9: http://doc.qt.io/qt-5/qstring.html#arg-21

                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                        ~Napoleon Bonaparte

                        On a crusade to banish setIndexWidget() from the holy land of Qt

                        JonBJ 1 Reply Last reply
                        2
                        • VRoninV VRonin

                          Yes, up to 9: http://doc.qt.io/qt-5/qstring.html#arg-21

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by
                          #12

                          @VRonin
                          Yeah, I just saw that, that's what I call "cheating" :)
                          Are the %numbers limited to 9 in the format string?
                          Where is QString::argv(arrayOfArgs) ? ;-)

                          1 Reply Last reply
                          0
                          • VRoninV VRonin

                            I discussed in the past this and also the season why you should only use arg(QString) and not the other overloads

                            C Offline
                            C Offline
                            ChrisVT
                            wrote on last edited by
                            #13

                            Thanks for all the responses - very insightful!

                            @VRonin This also happens with QStrings:
                            qDebug() << QString("%1%2%3").arg("A").arg("%2A").arg("B"); -> "ABA%3"
                            qDebug() << QString("%1%2%3").arg(QString("A")).arg(QString("%2A")).arg(QString("B")); -> "ABA%3"
                            But yes, implicit type conversion can be very hard to figure out. Been there!

                            @joeB Good advice about using the arglist instead, but
                            (a) this only works for QStrings, not for numerical formats, and
                            (b) Qt offers the ability to use chained args which MOSTLY work.
                            I was incorrectly assuming that arg(a).arg(b) should be the same as .arg(a,b) for constant QStrings a and b. I'll still say it's not all that intuitive that it isn't.

                            JonBJ 1 Reply Last reply
                            1
                            • C ChrisVT

                              Thanks for all the responses - very insightful!

                              @VRonin This also happens with QStrings:
                              qDebug() << QString("%1%2%3").arg("A").arg("%2A").arg("B"); -> "ABA%3"
                              qDebug() << QString("%1%2%3").arg(QString("A")).arg(QString("%2A")).arg(QString("B")); -> "ABA%3"
                              But yes, implicit type conversion can be very hard to figure out. Been there!

                              @joeB Good advice about using the arglist instead, but
                              (a) this only works for QStrings, not for numerical formats, and
                              (b) Qt offers the ability to use chained args which MOSTLY work.
                              I was incorrectly assuming that arg(a).arg(b) should be the same as .arg(a,b) for constant QStrings a and b. I'll still say it's not all that intuitive that it isn't.

                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by
                              #14

                              @ChrisVT
                              I love things which "MOSTLY" work :)

                              Be aware, if you are going to use "numerical formats" as you say then, as @VRonin pointed out in the post he referred to, these will not be localed. If you care about that, you must format them to localed strings in the first place, then you can pass them to the list-arg() because they are now strings.

                              1 Reply Last reply
                              0

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved