Index: gettext-tools/src/format-qt.c =================================================================== RCS file: /sources/gettext/gettext/gettext-tools/src/format-qt.c,v retrieving revision 1.9 diff -u -r1.9 format-qt.c --- gettext-tools/src/format-qt.c 22 Aug 2007 23:11:56 -0000 1.9 +++ gettext-tools/src/format-qt.c 4 Sep 2007 14:23:16 -0000 @@ -31,14 +31,23 @@ #define _(str) gettext (str) /* Qt format strings are processed by QString::arg and are documented in - qt-3.0.5/doc/html/qstring.html. - A directive starts with '%' and is followed by a digit ('0' to '9'). - Each %n must occur only once in the given string. - The first .arg() invocation replaces the %n with the lowest numbered n, - the next .arg() invocation then replaces the %n with the second-lowest + qt-4.3.0/doc/html/qstring.html. +   A directive +     - starts with '%', +     - is optionally followed by 'L' (indicates locale-dependent processing), +     - is followed by one or two digits ('0' to '9'). %0n is equivalent to %n. +   Directives cannot be escaped, hence '%' or '%L' not followed by a digit +   is not an error, but a verbatim segment of the text. +   Same %n directive may occur more than once in the given string. + The first .arg() invocation replaces all %n with the lowest numbered n, + the next .arg() invocation then replaces all %n with the second-lowest numbered n, and so on. - (This is inherently buggy because a '%' in the first replacement confuses - the second .arg() invocation.) + This is inherently buggy because a '%' in the first replacement confuses +   the second .arg() invocation. +   To reduce this problem and introduce another one, there are also .arg() +   methods that take up to 9 strings and perform the replacements in one swoop. +   But this method works only on strings that contain no 'L' flags and only +   single-digit argument designators. Although %0 is supported, usually %1 denotes the first argument, %2 the second argument etc. */ @@ -46,7 +55,7 @@ { unsigned int directives; unsigned int arg_count; - bool args_used[10]; + bool args_used[110]; }; @@ -63,31 +72,41 @@ for (; *format != '\0';) if (*format++ == '%') - if (*format >= '0' && *format <= '9') - { - /* A directive. */ - unsigned int number; - - FDI_SET (format - 1, FMTDIR_START); - spec.directives++; - - number = *format - '0'; - - while (spec.arg_count <= number) - spec.args_used[spec.arg_count++] = false; - if (spec.args_used[number]) - { - *invalid_reason = - xasprintf (_("Multiple references to %%%c."), *format); - FDI_SET (format, FMTDIR_ERROR); - goto bad_format; - } - spec.args_used[number] = true; - - FDI_SET (format, FMTDIR_END); - - format++; - } + { + if (*format == 'L') + /* Skip the locale-dependency flag. */ + format++; + + if (*format >= '0' && *format <= '9') + { + /* A directive. */ + unsigned int number; + + FDI_SET (format - 1, FMTDIR_START); + spec.directives++; + + number = *format - '0'; + /* Check if there is also a second digit. */ + if (*(format + 1) >= '0' && *(format + 1) <= '9') + { + format++; + number = (number > 0 ? number : 10) * 10 + (*format - '0'); + /* Put the two-digit numbers starting with 0 at positions + 100-109, in order to enforce difference between e.g. + %1 and %01. This is to prevent translators from using + %0n form when directives are resolved by the multi-argument + .arg() method, which sees only one-digit directives. */ + } + + while (spec.arg_count <= number) + spec.args_used[spec.arg_count++] = false; + spec.args_used[number] = true; + + FDI_SET (format, FMTDIR_END); + + format++; + } + } result = XMALLOC (struct spec); *result = spec; @@ -122,15 +141,21 @@ struct spec *spec2 = (struct spec *) msgstr_descr; bool err = false; unsigned int i; + unsigned int ndiff; - for (i = 0; i < spec1->arg_count || i < spec2->arg_count; i++) + for (i = 0, ndiff = 0; i < spec1->arg_count || i < spec2->arg_count; i++) { bool arg_used1 = (i < spec1->arg_count && spec1->args_used[i]); bool arg_used2 = (i < spec2->arg_count && spec2->args_used[i]); /* The translator cannot omit a %n from the msgstr because that would - yield a "Argument missing" warning at runtime. */ - if (arg_used1 != arg_used2) + yield a "Argument missing" warning at runtime. + An exception is a non-strict plural form msgstr, where one of the + arguments may be missing (as handled by KDE; pure Qt in fact cannot + make proper use of gettextn call with non-strict rule). */ + if (equality + ? arg_used1 != arg_used2 + : arg_used1 != arg_used2 && i >= spec1->arg_count) { if (error_logger) error_logger (arg_used1 @@ -140,6 +165,18 @@ err = true; break; } + /* Count the number of unmatched arguments in non-strict mode. */ + if (!equality && arg_used1 != arg_used2) + ndiff++; + } + + /* Check that no more than one argument is unmatched in non-strict mode. */ + if (!equality && ndiff > 1) + { + if (error_logger) + error_logger (_("at most one unmatched argument allowed in non-strict '%s'"), + pretty_msgstr); + err = true; } return err; Index: gettext-tools/tests/format-qt-1 =================================================================== RCS file: /sources/gettext/gettext/gettext-tools/tests/format-qt-1,v retrieving revision 1.1 diff -u -r1.1 format-qt-1 --- gettext-tools/tests/format-qt-1 28 Oct 2003 16:10:35 -0000 1.1 +++ gettext-tools/tests/format-qt-1 4 Sep 2007 14:23:16 -0000 @@ -13,16 +13,26 @@ "abc%1def" # Valid: one argument "abc%9def" +# Valid: one argument with two digits +"abc%99def" # Valid: unterminated "abc%1def%" +# Valid: unterminated +"abc%1def%L" # Valid: non-digit "abc%1def%x" # Valid: zero "abc%1def%0" +# Valid: leading zero +"abc%01def%00" # Valid: permutation "abc%2def%1" -# Invalid: multiple uses of same argument +# Valid: multiple uses of same argument "abc%2def%1ghi%2" +# Valid: an argument with locale-dependency flag +"abc%L1def" +# Valid: an argument with locale-dependency flag and two digits +"abc%L12def" EOF : ${XGETTEXT=xgettext} Index: gettext-tools/tests/format-qt-2 =================================================================== RCS file: /sources/gettext/gettext/gettext-tools/tests/format-qt-2,v retrieving revision 1.1 diff -u -r1.1 format-qt-2 --- gettext-tools/tests/format-qt-2 28 Oct 2003 16:10:35 -0000 1.1 +++ gettext-tools/tests/format-qt-2 4 Sep 2007 14:23:16 -0000 @@ -10,15 +10,21 @@ # Valid: %% doesn't count msgid "abc%%def" msgstr "xyz" -# Invalid: invalid msgstr -msgid "abc%1def" -msgstr "xyz%1%1" # Valid: same arguments msgid "abc%2def" msgstr "xyz%2" # Valid: permutation msgid "abc%3%1%2def" msgstr "xyz%2%1%3" +# Valid: repetition of an argument in the translation +msgid "abc%2def" +msgstr "xyz%2uvw%2" +# Valid: removing repeated argument in the translation +msgid "abc%2def%2" +msgstr "xyz%2uvw" +# Valid: an argument with locale-dependency flag +msgid "abc%L1def" +msgstr "xyz%L1" # Invalid: too few arguments msgid "abc%2def%1" msgstr "xyz%1" @@ -31,6 +37,12 @@ # Invalid: added non-final argument msgid "abc%2def" msgstr "xyz%1%2" +# Invalid: unmatched leading zero +msgid "abc%01def" +msgstr "xyz%1" +# Invalid: extra leading zero +msgid "abc%1def" +msgstr "xyz%01" EOF : ${MSGFMT=msgfmt}