]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - locale/po2strings.c
Merge changes from CUPS 1.5svn-r9641
[thirdparty/cups.git] / locale / po2strings.c
index 3e766ba26fc9c1c6aaa68d15a6593c96bdd6306b..97f9cc337c2d17151c1e1596825e63fcf761c26a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * "$Id: po2strings.c 6921 2007-09-06 13:38:37Z mike $"
  *
- *   Convert GNU gettext .po files to Apple .strings file (UTF-16 BE text file).
+ *   Convert a GNU gettext .po file to an Apple .strings file.
  *
  *   Copyright 2007-2010 by Apple Inc.
  *
@@ -21,8 +21,7 @@
  *
  * Contents:
  *
- *   main()         - Convert .po file to .strings.
- *   write_string() - Write a string to the .strings file.
+ *   main() - Convert .po file to .strings.
  */
 
 #include <cups/cups-private.h>
  * The .strings file format is simple:
  *
  * // comment
- * "id" = "str";
+ * "msgid" = "msgstr";
  *
- * Both the id and str strings use standard C quoting for special characters
- * like newline and the double quote character.
- */
-
-/*
- * Local functions...
+ * The GNU gettext .po format is also fairly simple:
+ *
+ *     #. comment
+ *     msgid "some text"
+ *     msgstr "localized text"
+ *
+ * The comment, msgid, and msgstr text can span multiple lines using the form:
+ *
+ *     #. comment
+ *     #. more comments
+ *     msgid ""
+ *     "some long text"
+ *     msgstr ""
+ *     "localized text spanning "
+ *     "multiple lines"
+ *
+ * Both the msgid and msgstr strings use standard C quoting for special
+ * characters like newline and the double quote character.
  */
 
-static void    write_string(FILE *strings, const char *s);
-
-
 /*
  *   main() - Convert .po file to .strings.
  */
@@ -54,21 +62,29 @@ main(int  argc,                             /* I - Number of command-line args */
      char *argv[])                     /* I - Command-line arguments */
 {
   int                  i;              /* Looping var */
-  FILE                 *strings;       /* .strings file */
-  cups_array_t         *po;            /* .po file */
-  char                 iconv[1024];    /* iconv command */
-  _cups_message_t      *msg;           /* Current message */
-  const char           *srcfile,       /* Source file */
-                       *dstfile;       /* Destination file */
+  const char           *pofile,        /* .po filename */
+                       *stringsfile;   /* .strings filename */
+  cups_file_t          *po,            /* .po file */
+                       *strings;       /* .strings file */
+  char                 s[4096],        /* String buffer */
+                       *ptr,           /* Pointer into buffer */
+                       *temp,          /* New string */
+                       *msgid,         /* msgid string */
+                       *msgstr;        /* msgstr string */
+  int                  length;         /* Length of combined strings */
   int                  use_msgid;      /* Use msgid strings for msgstr? */
 
 
-  srcfile   = NULL;
-  dstfile   = NULL;
-  use_msgid = 0;
+ /*
+  * Process command-line arguments...
+  */
 
+  pofile      = NULL;
+  stringsfile = NULL;
+  use_msgid   = 0;
 
   for (i = 1; i < argc; i ++)
+  {
     if (!strcmp(argv[i], "-m"))
       use_msgid = 1;
     else if (argv[i][0] == '-')
@@ -76,99 +92,187 @@ main(int  argc,                            /* I - Number of command-line args */
       puts("Usage: po2strings [-m] filename.po filename.strings");
       return (1);
     }
-    else if (srcfile == NULL)
-      srcfile = argv[i];
-    else if (dstfile == NULL)
-      dstfile = argv[i];
+    else if (!pofile)
+      pofile = argv[i];
+    else if (!stringsfile)
+      stringsfile = argv[i];
     else
     {
       puts("Usage: po2strings [-m] filename.po filename.strings");
       return (1);
     }
+  }
 
-  if (!srcfile || !dstfile)
+  if (!pofile || !stringsfile)
   {
     puts("Usage: po2strings [-m] filename.po filename.strings");
     return (1);
   }
 
  /*
-  * Use the CUPS .po loader to get the message strings...
+  * Read strings from the .po file and write to the .strings file...
   */
 
-  if ((po = _cupsMessageLoad(srcfile, 1)) == NULL)
+  if ((po = cupsFileOpen(pofile, "r")) == NULL)
   {
-    perror(srcfile);
+    perror(pofile);
     return (1);
   }
 
- /*
-  * Cheat by using iconv to write the .strings file with a UTF-16 encoding.
-  * The .po file uses UTF-8...
-  */
-
-  snprintf(iconv, sizeof(iconv), "iconv -f utf-8 -t utf-16 >'%s'", dstfile);
-  if ((strings = popen(iconv, "w")) == NULL)
+  if ((strings = cupsFileOpen(stringsfile, "w")) == NULL)
   {
-    perror(argv[2]);
-    _cupsMessageFree(po);
+    perror(stringsfile);
+    cupsFileClose(po);
     return (1);
   }
 
-  for (msg = (_cups_message_t *)cupsArrayFirst(po);
-       msg;
-       msg = (_cups_message_t *)cupsArrayNext(po))
+  msgid = msgstr = NULL;
+
+  while (cupsFileGets(po, s, sizeof(s)) != NULL)
   {
-    write_string(strings, msg->id);
-    fputs(" = ", strings);
-    write_string(strings, use_msgid ? msg->id : msg->str);
-    fputs(";\n", strings);
-  }
+    if (s[0] == '#' && s[1] == '.')
+    {
+     /*
+      * Copy comment string...
+      */
 
-  printf("%s: %d messages.\n", argv[2], cupsArrayCount(po));
+      if (msgid && msgstr)
+      {
+       /*
+        * First output the last localization string...
+       */
 
-  pclose(strings);
-  _cupsMessageFree(po);
+       if (*msgid)
+         cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid,
+                        (use_msgid || !*msgstr) ? msgid : msgstr);
 
-  return (0);
-}
+       free(msgid);
+       free(msgstr);
+       msgid = msgstr = NULL;
+      }
 
+      cupsFilePrintf(strings, "//%s\n", s + 2);
+    }
+    else if (s[0] == '#' || !s[0])
+    {
+     /*
+      * Skip blank and file comment lines...
+      */
 
-/*
- * 'write_string()' - Write a string to the .strings file.
- */
+      continue;
+    }
+    else
+    {
+     /*
+      * Strip the trailing quote...
+      */
 
-static void
-write_string(FILE       *strings,      /* I - .strings file */
-             const char *s)            /* I - String to write */
-{
-  putc('\"', strings);
+      if ((ptr = strrchr(s, '\"')) == NULL)
+       continue;
 
-  while (*s)
-  {
-    switch (*s)
-    {
-      case '\n' :
-          fputs("\\n", strings);
-         break;
-      case '\t' :
-          fputs("\\t", strings);
-         break;
-      case '\\' :
-          fputs("\\\\", strings);
-         break;
-      case '\"' :
-          fputs("\\\"", strings);
-         break;
-      default :
-          putc(*s, strings);
-         break;
+      *ptr = '\0';
+
+     /*
+      * Find start of value...
+      */
+      
+      if ((ptr = strchr(s, '\"')) == NULL)
+       continue;
+
+      ptr ++;
+
+     /*
+      * Create or add to a message...
+      */
+
+      if (!strncmp(s, "msgid", 5))
+      {
+       /*
+       * Output previous message as needed...
+       */
+
+        if (msgid && msgstr)
+       {
+         if (*msgid)
+            cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid,
+                          (use_msgid || !*msgstr) ? msgid : msgstr);
+
+         free(msgid);
+         free(msgstr);
+       }
+
+        msgid  = strdup(ptr);
+       msgstr = NULL;
+      }
+      else if (s[0] == '\"' )
+      {
+       /*
+       * Append to current string...
+       */
+
+       length = (int)strlen(msgstr ? msgstr : msgid);
+
+       if ((temp = realloc(msgstr ? msgstr : msgid,
+                           length + strlen(ptr) + 1)) == NULL)
+       {
+         perror("Unable to allocate string");
+         return (1);
+       }
+
+       if (msgstr)
+       {
+        /*
+         * Copy the new portion to the end of the msgstr string - safe
+         * to use strcpy because the buffer is allocated to the correct
+         * size...
+         */
+
+         msgstr = temp;
+
+         strcpy(msgstr + length, ptr);
+       }
+       else
+       {
+        /*
+         * Copy the new portion to the end of the msgid string - safe
+         * to use strcpy because the buffer is allocated to the correct
+         * size...
+         */
+
+         msgid = temp;
+
+         strcpy(msgid + length, ptr);
+       }
+      }
+      else if (!strncmp(s, "msgstr", 6) && msgid)
+      {
+       /*
+       * Set the string...
+       */
+
+       if ((msgstr = strdup(ptr)) == NULL)
+       {
+         perror("Unable to allocate msgstr");
+         return (1);
+       }
+      }
     }
+  }
+
+  if (msgid && msgstr)
+  {
+    if (*msgid)
+      cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid,
+                    (use_msgid || !*msgstr) ? msgid : msgstr);
 
-    s ++;
+    free(msgid);
+    free(msgstr);
   }
 
-  putc('\"', strings);
+  cupsFileClose(po);
+  cupsFileClose(strings);
+
+  return (0);
 }