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