]>
git.ipfire.org Git - thirdparty/cups.git/blob - locale/po2strings.c
2 * Convert a GNU gettext .po file to an Apple .strings file.
4 * Copyright 2007-2017 by Apple Inc.
6 * These coded instructions, statements, and computer programs are the
7 * property of Apple Inc. and are protected by Federal copyright
8 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
9 * which should have been included with this file. If this file is
10 * missing or damaged, see the license at "http://www.cups.org/".
14 * po2strings filename.strings filename.po
18 * gcc -o po2strings po2strings.c `cups-config --libs`
21 #include <cups/cups-private.h>
25 * The .strings file format is simple:
30 * The GNU gettext .po format is also fairly simple:
34 * msgstr "localized text"
36 * The comment, msgid, and msgstr text can span multiple lines using the form:
43 * "localized text spanning "
46 * Both the msgid and msgstr strings use standard C quoting for special
47 * characters like newline and the double quote character.
50 static char *normalize_string(const char *idstr
, char *buffer
, size_t bufsize
);
54 * main() - Convert .po file to .strings.
57 int /* O - Exit code */
58 main(int argc
, /* I - Number of command-line args */
59 char *argv
[]) /* I - Command-line arguments */
61 int i
; /* Looping var */
62 const char *pofile
, /* .po filename */
63 *stringsfile
; /* .strings filename */
64 cups_file_t
*po
, /* .po file */
65 *strings
; /* .strings file */
66 char s
[4096], /* String buffer */
67 *ptr
, /* Pointer into buffer */
68 *temp
, /* New string */
69 *msgid
, /* msgid string */
70 *msgstr
, /* msgstr string */
71 normalized
[8192];/* Normalized msgid string */
72 size_t length
; /* Length of combined strings */
73 int use_msgid
; /* Use msgid strings for msgstr? */
77 * Process command-line arguments...
84 for (i
= 1; i
< argc
; i
++)
86 if (!strcmp(argv
[i
], "-m"))
88 else if (argv
[i
][0] == '-')
90 puts("Usage: po2strings [-m] filename.po filename.strings");
95 else if (!stringsfile
)
96 stringsfile
= argv
[i
];
99 puts("Usage: po2strings [-m] filename.po filename.strings");
104 if (!pofile
|| !stringsfile
)
106 puts("Usage: po2strings [-m] filename.po filename.strings");
111 * Read strings from the .po file and write to the .strings file...
114 if ((po
= cupsFileOpen(pofile
, "r")) == NULL
)
120 if ((strings
= cupsFileOpen(stringsfile
, "w")) == NULL
)
127 msgid
= msgstr
= NULL
;
129 while (cupsFileGets(po
, s
, sizeof(s
)) != NULL
)
131 if (s
[0] == '#' && s
[1] == '.')
134 * Copy comment string...
140 * First output the last localization string...
144 cupsFilePrintf(strings
, "\"%s\" = \"%s\";\n", msgid
,
145 (use_msgid
|| !*msgstr
) ? msgid
: msgstr
);
149 msgid
= msgstr
= NULL
;
152 cupsFilePrintf(strings
, "//%s\n", s
+ 2);
154 else if (s
[0] == '#' || !s
[0])
157 * Skip blank and file comment lines...
165 * Strip the trailing quote...
168 if ((ptr
= strrchr(s
, '\"')) == NULL
)
174 * Find start of value...
177 if ((ptr
= strchr(s
, '\"')) == NULL
)
183 * Create or add to a message...
186 if (!strncmp(s
, "msgid", 5))
189 * Output previous message as needed...
195 cupsFilePrintf(strings
, "\"%s\" = \"%s\";\n", msgid
, normalize_string((use_msgid
|| !*msgstr
) ? msgid
: msgstr
, normalized
, sizeof(normalized
)));
207 else if (s
[0] == '\"' && (msgid
|| msgstr
))
210 * Append to current string...
213 size_t ptrlen
= strlen(ptr
); /* Length of string */
215 length
= strlen(msgstr
? msgstr
: msgid
);
217 if ((temp
= realloc(msgstr
? msgstr
: msgid
,
218 length
+ ptrlen
+ 1)) == NULL
)
223 perror("Unable to allocate string");
230 * Copy the new portion to the end of the msgstr string - safe
231 * to use strcpy because the buffer is allocated to the correct
237 memcpy(msgstr
+ length
, ptr
, ptrlen
+ 1);
242 * Copy the new portion to the end of the msgid string - safe
243 * to use strcpy because the buffer is allocated to the correct
249 memcpy(msgid
+ length
, ptr
, ptrlen
+ 1);
252 else if (!strncmp(s
, "msgstr", 6) && msgid
)
261 if ((msgstr
= strdup(ptr
)) == NULL
)
264 perror("Unable to allocate msgstr");
274 cupsFilePrintf(strings
, "\"%s\" = \"%s\";\n", msgid
, normalize_string((use_msgid
|| !*msgstr
) ? msgid
: msgstr
, normalized
, sizeof(normalized
)));
284 cupsFileClose(strings
);
291 * 'normalize_string()' - Normalize a msgid string.
293 * This function converts ASCII ellipsis and double quotes to their Unicode
297 static char * /* O - Normalized string */
298 normalize_string(const char *idstr
, /* I - msgid string */
299 char *buffer
, /* I - Normalized string buffer */
300 size_t bufsize
) /* I - Size of string buffer */
302 char *bufptr
= buffer
, /* Pointer into buffer */
303 *bufend
= buffer
+ bufsize
- 3; /* End of buffer */
304 int quote
= 0, /* Quote direction */
305 html
= 0; /* HTML text */
308 while (*idstr
&& bufptr
< bufend
)
310 if (!strncmp(idstr
, "<A ", 3))
312 else if (html
&& *idstr
== '>')
315 if (*idstr
== '.' && idstr
[1] == '.' && idstr
[2] == '.')
318 * Convert ... to Unicode ellipsis...
321 *bufptr
++ = (char)0xE2;
322 *bufptr
++ = (char)0x80;
323 *bufptr
++ = (char)0xA6;
326 else if (!html
&& *idstr
== '\\' && idstr
[1] == '\"')
331 * Convert second \" to Unicode right (curley) double quote.
334 *bufptr
++ = (char)0xE2;
335 *bufptr
++ = (char)0x80;
336 *bufptr
++ = (char)0x9D;
339 else if (strchr(idstr
+ 2, '\"') != NULL
)
342 * Convert first \" to Unicode left (curley) double quote.
345 *bufptr
++ = (char)0xE2;
346 *bufptr
++ = (char)0x80;
347 *bufptr
++ = (char)0x9C;
353 * Convert lone \" to Unicode double prime.
356 *bufptr
++ = (char)0xE2;
357 *bufptr
++ = (char)0x80;
358 *bufptr
++ = (char)0xB3;
363 else if (*idstr
== '\'')
365 if (strchr(idstr
+ 1, '\'') == NULL
|| quote
)
368 * Convert second ' (or ' used for a contraction) to Unicode right
369 * (curley) single quote.
372 *bufptr
++ = (char)0xE2;
373 *bufptr
++ = (char)0x80;
374 *bufptr
++ = (char)0x99;
380 * Convert first ' to Unicode left (curley) single quote.
383 *bufptr
++ = (char)0xE2;
384 *bufptr
++ = (char)0x80;
385 *bufptr
++ = (char)0x98;