xref: /aosp_15_r20/external/libcups/locale/strings2po.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Convert Apple .strings file (UTF-16 BE text file) to GNU gettext .po files.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2007-2014 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  *
6*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
7*5e7646d2SAndroid Build Coastguard Worker  *
8*5e7646d2SAndroid Build Coastguard Worker  * Usage:
9*5e7646d2SAndroid Build Coastguard Worker  *
10*5e7646d2SAndroid Build Coastguard Worker  *   strings2po filename.strings filename.po
11*5e7646d2SAndroid Build Coastguard Worker  *
12*5e7646d2SAndroid Build Coastguard Worker  * Compile with:
13*5e7646d2SAndroid Build Coastguard Worker  *
14*5e7646d2SAndroid Build Coastguard Worker  *   gcc -o strings2po strings2po.c
15*5e7646d2SAndroid Build Coastguard Worker  */
16*5e7646d2SAndroid Build Coastguard Worker 
17*5e7646d2SAndroid Build Coastguard Worker #include <stdio.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <stdlib.h>
19*5e7646d2SAndroid Build Coastguard Worker 
20*5e7646d2SAndroid Build Coastguard Worker 
21*5e7646d2SAndroid Build Coastguard Worker /*
22*5e7646d2SAndroid Build Coastguard Worker  * The .strings file format is simple:
23*5e7646d2SAndroid Build Coastguard Worker  *
24*5e7646d2SAndroid Build Coastguard Worker  * // comment
25*5e7646d2SAndroid Build Coastguard Worker  * "id" = "str";
26*5e7646d2SAndroid Build Coastguard Worker  *
27*5e7646d2SAndroid Build Coastguard Worker  * Both the id and str strings use standard C quoting for special characters
28*5e7646d2SAndroid Build Coastguard Worker  * like newline and the double quote character.
29*5e7646d2SAndroid Build Coastguard Worker  */
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker /*
32*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
33*5e7646d2SAndroid Build Coastguard Worker  */
34*5e7646d2SAndroid Build Coastguard Worker 
35*5e7646d2SAndroid Build Coastguard Worker static int	read_strings(FILE *strings, char *buffer, size_t bufsize,
36*5e7646d2SAndroid Build Coastguard Worker 		             char **id, char **str);
37*5e7646d2SAndroid Build Coastguard Worker static void	write_po(FILE *po, const char *what, const char *s);
38*5e7646d2SAndroid Build Coastguard Worker 
39*5e7646d2SAndroid Build Coastguard Worker 
40*5e7646d2SAndroid Build Coastguard Worker /*
41*5e7646d2SAndroid Build Coastguard Worker  *   main() - Convert .strings file to .po.
42*5e7646d2SAndroid Build Coastguard Worker  */
43*5e7646d2SAndroid Build Coastguard Worker 
44*5e7646d2SAndroid Build Coastguard Worker int					/* O - Exit code */
main(int argc,char * argv[])45*5e7646d2SAndroid Build Coastguard Worker main(int  argc,				/* I - Number of command-line args */
46*5e7646d2SAndroid Build Coastguard Worker      char *argv[])			/* I - Command-line arguments */
47*5e7646d2SAndroid Build Coastguard Worker {
48*5e7646d2SAndroid Build Coastguard Worker   FILE	*strings,			/* .strings file */
49*5e7646d2SAndroid Build Coastguard Worker 	*po;				/* .po file */
50*5e7646d2SAndroid Build Coastguard Worker   char	iconv[1024],			/* iconv command */
51*5e7646d2SAndroid Build Coastguard Worker 	buffer[8192],			/* Line buffer */
52*5e7646d2SAndroid Build Coastguard Worker 	*id,				/* ID string */
53*5e7646d2SAndroid Build Coastguard Worker 	*str;				/* Translation string */
54*5e7646d2SAndroid Build Coastguard Worker   int	count;				/* Number of messages converted */
55*5e7646d2SAndroid Build Coastguard Worker 
56*5e7646d2SAndroid Build Coastguard Worker 
57*5e7646d2SAndroid Build Coastguard Worker   if (argc != 3)
58*5e7646d2SAndroid Build Coastguard Worker   {
59*5e7646d2SAndroid Build Coastguard Worker     puts("Usage: strings2po filename.strings filename.po");
60*5e7646d2SAndroid Build Coastguard Worker     return (1);
61*5e7646d2SAndroid Build Coastguard Worker   }
62*5e7646d2SAndroid Build Coastguard Worker 
63*5e7646d2SAndroid Build Coastguard Worker  /*
64*5e7646d2SAndroid Build Coastguard Worker   * Cheat by using iconv to convert the .strings file from UTF-16 to UTF-8
65*5e7646d2SAndroid Build Coastguard Worker   * which is what we need for the .po file (and it makes things a lot
66*5e7646d2SAndroid Build Coastguard Worker   * simpler...)
67*5e7646d2SAndroid Build Coastguard Worker   */
68*5e7646d2SAndroid Build Coastguard Worker 
69*5e7646d2SAndroid Build Coastguard Worker   snprintf(iconv, sizeof(iconv), "iconv -f utf-16 -t utf-8 '%s'", argv[1]);
70*5e7646d2SAndroid Build Coastguard Worker   if ((strings = popen(iconv, "r")) == NULL)
71*5e7646d2SAndroid Build Coastguard Worker   {
72*5e7646d2SAndroid Build Coastguard Worker     perror(argv[1]);
73*5e7646d2SAndroid Build Coastguard Worker     return (1);
74*5e7646d2SAndroid Build Coastguard Worker   }
75*5e7646d2SAndroid Build Coastguard Worker 
76*5e7646d2SAndroid Build Coastguard Worker   if ((po = fopen(argv[2], "w")) == NULL)
77*5e7646d2SAndroid Build Coastguard Worker   {
78*5e7646d2SAndroid Build Coastguard Worker     perror(argv[2]);
79*5e7646d2SAndroid Build Coastguard Worker     pclose(strings);
80*5e7646d2SAndroid Build Coastguard Worker     return (1);
81*5e7646d2SAndroid Build Coastguard Worker   }
82*5e7646d2SAndroid Build Coastguard Worker 
83*5e7646d2SAndroid Build Coastguard Worker   count = 0;
84*5e7646d2SAndroid Build Coastguard Worker 
85*5e7646d2SAndroid Build Coastguard Worker   while (read_strings(strings, buffer, sizeof(buffer), &id, &str))
86*5e7646d2SAndroid Build Coastguard Worker   {
87*5e7646d2SAndroid Build Coastguard Worker     count ++;
88*5e7646d2SAndroid Build Coastguard Worker     write_po(po, "msgid", id);
89*5e7646d2SAndroid Build Coastguard Worker     write_po(po, "msgstr", str);
90*5e7646d2SAndroid Build Coastguard Worker   }
91*5e7646d2SAndroid Build Coastguard Worker 
92*5e7646d2SAndroid Build Coastguard Worker   pclose(strings);
93*5e7646d2SAndroid Build Coastguard Worker   fclose(po);
94*5e7646d2SAndroid Build Coastguard Worker 
95*5e7646d2SAndroid Build Coastguard Worker   printf("%s: %d messages.\n", argv[2], count);
96*5e7646d2SAndroid Build Coastguard Worker 
97*5e7646d2SAndroid Build Coastguard Worker   return (0);
98*5e7646d2SAndroid Build Coastguard Worker }
99*5e7646d2SAndroid Build Coastguard Worker 
100*5e7646d2SAndroid Build Coastguard Worker 
101*5e7646d2SAndroid Build Coastguard Worker /*
102*5e7646d2SAndroid Build Coastguard Worker  * 'read_strings()' - Read a line from a .strings file.
103*5e7646d2SAndroid Build Coastguard Worker  */
104*5e7646d2SAndroid Build Coastguard Worker 
105*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 on success, 0 on failure */
read_strings(FILE * strings,char * buffer,size_t bufsize,char ** id,char ** str)106*5e7646d2SAndroid Build Coastguard Worker read_strings(FILE   *strings,		/* I - .strings file */
107*5e7646d2SAndroid Build Coastguard Worker              char   *buffer,		/* I - Line buffer */
108*5e7646d2SAndroid Build Coastguard Worker 	     size_t bufsize,		/* I - Size of line buffer */
109*5e7646d2SAndroid Build Coastguard Worker              char   **id,		/* O - Pointer to ID string */
110*5e7646d2SAndroid Build Coastguard Worker 	     char   **str)		/* O - Pointer to translation string */
111*5e7646d2SAndroid Build Coastguard Worker {
112*5e7646d2SAndroid Build Coastguard Worker   char	*bufptr;			/* Pointer into buffer */
113*5e7646d2SAndroid Build Coastguard Worker 
114*5e7646d2SAndroid Build Coastguard Worker 
115*5e7646d2SAndroid Build Coastguard Worker   while (fgets(buffer, (int)bufsize, strings))
116*5e7646d2SAndroid Build Coastguard Worker   {
117*5e7646d2SAndroid Build Coastguard Worker     if (buffer[0] != '\"')
118*5e7646d2SAndroid Build Coastguard Worker       continue;
119*5e7646d2SAndroid Build Coastguard Worker 
120*5e7646d2SAndroid Build Coastguard Worker     *id = buffer + 1;
121*5e7646d2SAndroid Build Coastguard Worker 
122*5e7646d2SAndroid Build Coastguard Worker     for (bufptr = buffer + 1; *bufptr && *bufptr != '\"'; bufptr ++)
123*5e7646d2SAndroid Build Coastguard Worker       if (*bufptr == '\\')
124*5e7646d2SAndroid Build Coastguard Worker         bufptr ++;
125*5e7646d2SAndroid Build Coastguard Worker 
126*5e7646d2SAndroid Build Coastguard Worker     if (*bufptr != '\"')
127*5e7646d2SAndroid Build Coastguard Worker       continue;
128*5e7646d2SAndroid Build Coastguard Worker 
129*5e7646d2SAndroid Build Coastguard Worker     *bufptr++ = '\0';
130*5e7646d2SAndroid Build Coastguard Worker 
131*5e7646d2SAndroid Build Coastguard Worker     while (*bufptr && *bufptr != '\"')
132*5e7646d2SAndroid Build Coastguard Worker       bufptr ++;
133*5e7646d2SAndroid Build Coastguard Worker 
134*5e7646d2SAndroid Build Coastguard Worker     if (!*bufptr)
135*5e7646d2SAndroid Build Coastguard Worker       continue;
136*5e7646d2SAndroid Build Coastguard Worker 
137*5e7646d2SAndroid Build Coastguard Worker     bufptr ++;
138*5e7646d2SAndroid Build Coastguard Worker     *str = bufptr;
139*5e7646d2SAndroid Build Coastguard Worker 
140*5e7646d2SAndroid Build Coastguard Worker     for (; *bufptr && *bufptr != '\"'; bufptr ++)
141*5e7646d2SAndroid Build Coastguard Worker       if (*bufptr == '\\')
142*5e7646d2SAndroid Build Coastguard Worker         bufptr ++;
143*5e7646d2SAndroid Build Coastguard Worker 
144*5e7646d2SAndroid Build Coastguard Worker     if (*bufptr != '\"')
145*5e7646d2SAndroid Build Coastguard Worker       continue;
146*5e7646d2SAndroid Build Coastguard Worker 
147*5e7646d2SAndroid Build Coastguard Worker     *bufptr = '\0';
148*5e7646d2SAndroid Build Coastguard Worker 
149*5e7646d2SAndroid Build Coastguard Worker     return (1);
150*5e7646d2SAndroid Build Coastguard Worker   }
151*5e7646d2SAndroid Build Coastguard Worker 
152*5e7646d2SAndroid Build Coastguard Worker   return (0);
153*5e7646d2SAndroid Build Coastguard Worker }
154*5e7646d2SAndroid Build Coastguard Worker 
155*5e7646d2SAndroid Build Coastguard Worker 
156*5e7646d2SAndroid Build Coastguard Worker /*
157*5e7646d2SAndroid Build Coastguard Worker  * 'write_po()' - Write a line to the .po file.
158*5e7646d2SAndroid Build Coastguard Worker  */
159*5e7646d2SAndroid Build Coastguard Worker 
160*5e7646d2SAndroid Build Coastguard Worker static void
write_po(FILE * po,const char * what,const char * s)161*5e7646d2SAndroid Build Coastguard Worker write_po(FILE       *po,		/* I - .po file */
162*5e7646d2SAndroid Build Coastguard Worker          const char *what,		/* I - Type of string */
163*5e7646d2SAndroid Build Coastguard Worker 	 const char *s)			/* I - String to write */
164*5e7646d2SAndroid Build Coastguard Worker {
165*5e7646d2SAndroid Build Coastguard Worker   fprintf(po, "%s \"%s\"\n", what, s);
166*5e7646d2SAndroid Build Coastguard Worker }
167