]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Add support for Qt 4 format strings.
authorBruno Haible <bruno@clisp.org>
Mon, 10 Sep 2007 00:27:34 +0000 (00:27 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:15:04 +0000 (12:15 +0200)
NEWS
gettext-tools/src/ChangeLog
gettext-tools/src/format-qt.c
gettext-tools/tests/ChangeLog
gettext-tools/tests/format-qt-1
gettext-tools/tests/format-qt-2

diff --git a/NEWS b/NEWS
index ff3fdcdae81bdeccd0233ece5424aad8fcb7dfef..5728582a499c671f0443ecdea19cce96742f09f9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,8 @@ Version 0.16.2 - January 2007
   be updated all together.
 
 * Programming languages support:
-  Contexts (msgctxt) are now also supported for Java and C#.
+  - Contexts (msgctxt) are now also supported for Java and C#.
+  - C# with Qt: The support for Qt format strings has been updated for Qt 4.
 
 * Documentation:
   The "Users" chapter has been completely rewritten.
index d45547fc074f2b823309f7e3b152b8b1f08109be..e6e940e450afbcc05dfe321f13214683ab445ed9 100644 (file)
@@ -1,3 +1,14 @@
+2007-09-09  Bruno Haible  <bruno@clisp.org>
+
+       Add support for Qt 4 format strings.
+       * format-qt.c (struct spec): Increase args_used field size to 100.
+       Add 'simple' field.
+       (format_parse): Update for Qt 4 syntax. Remove error message when the
+       same format argument is used more than once.
+       (format_check): Add check: If the msgid is simple, the msgstr must be
+       simple as well.
+       Reported by Chusslove Illich <caslav.ilic@gmx.net>.
+
 2007-09-02  Bruno Haible  <bruno@clisp.org>
 
        Correct handling of different libexpat ABIs.
index 75407ed64d6e2f4d3a457c77fa2014099b5d674a..49abf1a779c6d424c6eb104ca1b1053db05cd925 100644 (file)
 #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.
+   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.
+   An unterminated directive ('%' or '%L' not followed by a digit or at the
+   end) is not an error.
    The first .arg() invocation replaces the %n with the lowest numbered n,
    the next .arg() invocation then replaces the %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.  */
 
 struct spec
 {
+  /* Number of format directives.  */
   unsigned int directives;
+
+  /* True if the string supports the multi-argument .arg() methods, i.e. if it
+     contains no 'L' flags and only single-digit argument designators.  */
+  bool simple;
+
+  /* Booleans telling which %nn was seen.  */
   unsigned int arg_count;
-  bool args_used[10];
+  bool args_used[100];
 };
 
 
@@ -59,42 +74,51 @@ format_parse (const char *format, bool translated, char *fdi,
   struct spec *result;
 
   spec.directives = 0;
+  spec.simple = true;
   spec.arg_count = 0;
 
   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++;
-       }
+      {
+       const char *dir_start = format - 1;
+       bool locale_flag = false;
+
+       if (*format == 'L')
+         {
+           locale_flag = true;
+           format++;
+         }
+       if (*format >= '0' && *format <= '9')
+         {
+           /* A directive.  */
+           unsigned int number;
+
+           FDI_SET (dir_start, FMTDIR_START);
+           spec.directives++;
+           if (locale_flag)
+             spec.simple = false;
+
+           number = *format - '0';
+           if (format[1] >= '0' && format[1] <= '9')
+             {
+               number = 10 * number + (format[1] - '0');
+               spec.simple = false;
+               format++;
+             }
+
+           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;
   return result;
-
- bad_format:
-  return NULL;
 }
 
 static void
@@ -123,25 +147,34 @@ format_check (void *msgid_descr, void *msgstr_descr, bool equality,
   bool err = false;
   unsigned int i;
 
-  for (i = 0; i < spec1->arg_count || i < spec2->arg_count; i++)
+  if (spec1->simple && !spec2->simple)
     {
-      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)
-       {
-         if (error_logger)
-           error_logger (arg_used1
-                         ? _("a format specification for argument %u doesn't exist in '%s'")
-                         : _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
-                         i, pretty_msgstr);
-         err = true;
-         break;
-       }
+      if (error_logger)
+       error_logger (_("'msgid' is a simple format string, but '%s' is not: it contains an 'L' flag or a double-digit argument number"),
+                     pretty_msgstr);
+      err = true;
     }
 
+  if (!err)
+    for (i = 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)
+         {
+           if (error_logger)
+             error_logger (arg_used1
+                           ? _("a format specification for argument %u doesn't exist in '%s'")
+                           : _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
+                           i, pretty_msgstr);
+           err = true;
+           break;
+         }
+      }
+
   return err;
 }
 
index c4e908551ba18eb29da5b0023b4a1e1d9fab5c5b..5f2161aae7b304715cf73cad00133ebd4eba159e 100644 (file)
@@ -1,3 +1,10 @@
+2007-09-09  Bruno Haible  <bruno@clisp.org>
+
+       Add support for Qt 4 format strings.
+       * format-qt-1: Update for Qt 4 syntax.
+       * format-qt-2: Likewise.
+       Based on input by by Chusslove Illich <caslav.ilic@gmx.net>.
+
 2007-09-02  Bruno Haible  <bruno@clisp.org>
 
        Implement msgctxt for C# ResourceManagers.
index 74df988a1f7e24ffcf0657202c755b049d4f2251..e2207bc322cd79c3b00832b4708a945c23e9c6c4 100755 (executable)
@@ -13,16 +13,28 @@ cat <<\EOF > f-qt-1.data
 "abc%1def"
 # Valid: one argument
 "abc%9def"
+# Valid: one argument specified by two digits
+"abc%09def"
+# Valid: one argument specified by 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: zero specified by two digits
+"abc%1def%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 e0118679bd258cf8f4ef129283284cc1e97dc786..0f8005e2cdeb153eb81ec2c4d80b1fe5ff52839d 100755 (executable)
@@ -10,12 +10,27 @@ cat <<\EOF > f-qt-2.data
 # 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: same arguments, msgstr may be simpler than msgid
+msgid  "abc%L2def"
+msgstr "xyz%2"
+# Valid: same arguments, msgstr may be simpler than msgid
+msgid  "abc%02def"
+msgstr "xyz%2"
+# Invalid: msgid is simple but msgstr is not
+msgid  "abc%2def"
+msgstr "xyz%L2"
+# Invalid: msgid is simple but msgstr is not
+msgid  "abc%2def"
+msgstr "xyz%02"
+# 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: permutation
 msgid  "abc%3%1%2def"
 msgstr "xyz%2%1%3"