]>
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 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
10 * po2strings filename.strings filename.po
14 * gcc -o po2strings po2strings.c `cups-config --libs`
17 #include <cups/cups-private.h>
21 * The .strings file format is simple:
26 * The GNU gettext .po format is also fairly simple:
30 * msgstr "localized text"
32 * The comment, msgid, and msgstr text can span multiple lines using the form:
39 * "localized text spanning "
42 * Both the msgid and msgstr strings use standard C quoting for special
43 * characters like newline and the double quote character.
46 static char *normalize_string(const char *idstr
, char *buffer
, size_t bufsize
);
50 * main() - Convert .po file to .strings.
53 int /* O - Exit code */
54 main(int argc
, /* I - Number of command-line args */
55 char *argv
[]) /* I - Command-line arguments */
57 int i
; /* Looping var */
58 const char *pofile
, /* .po filename */
59 *stringsfile
; /* .strings filename */
60 cups_file_t
*po
, /* .po file */
61 *strings
; /* .strings file */
62 char s
[4096], /* String buffer */
63 *ptr
, /* Pointer into buffer */
64 *temp
, /* New string */
65 *msgid
, /* msgid string */
66 *msgstr
, /* msgstr string */
67 normalized
[8192];/* Normalized msgid string */
68 size_t length
; /* Length of combined strings */
69 int use_msgid
; /* Use msgid strings for msgstr? */
73 * Process command-line arguments...
80 for (i
= 1; i
< argc
; i
++)
82 if (!strcmp(argv
[i
], "-m"))
84 else if (argv
[i
][0] == '-')
86 puts("Usage: po2strings [-m] filename.po filename.strings");
91 else if (!stringsfile
)
92 stringsfile
= argv
[i
];
95 puts("Usage: po2strings [-m] filename.po filename.strings");
100 if (!pofile
|| !stringsfile
)
102 puts("Usage: po2strings [-m] filename.po filename.strings");
107 * Read strings from the .po file and write to the .strings file...
110 if ((po
= cupsFileOpen(pofile
, "r")) == NULL
)
116 if ((strings
= cupsFileOpen(stringsfile
, "w")) == NULL
)
123 msgid
= msgstr
= NULL
;
125 while (cupsFileGets(po
, s
, sizeof(s
)) != NULL
)
127 if (s
[0] == '#' && s
[1] == '.')
130 * Copy comment string...
136 * First output the last localization string...
140 cupsFilePrintf(strings
, "\"%s\" = \"%s\";\n", msgid
,
141 (use_msgid
|| !*msgstr
) ? msgid
: msgstr
);
145 msgid
= msgstr
= NULL
;
148 cupsFilePrintf(strings
, "//%s\n", s
+ 2);
150 else if (s
[0] == '#' || !s
[0])
153 * Skip blank and file comment lines...
161 * Strip the trailing quote...
164 if ((ptr
= strrchr(s
, '\"')) == NULL
)
170 * Find start of value...
173 if ((ptr
= strchr(s
, '\"')) == NULL
)
179 * Create or add to a message...
182 if (!strncmp(s
, "msgid", 5))
185 * Output previous message as needed...
191 cupsFilePrintf(strings
, "\"%s\" = \"%s\";\n", msgid
, normalize_string((use_msgid
|| !*msgstr
) ? msgid
: msgstr
, normalized
, sizeof(normalized
)));
203 else if (s
[0] == '\"' && (msgid
|| msgstr
))
206 * Append to current string...
209 size_t ptrlen
= strlen(ptr
); /* Length of string */
211 length
= strlen(msgstr
? msgstr
: msgid
);
213 if ((temp
= realloc(msgstr
? msgstr
: msgid
,
214 length
+ ptrlen
+ 1)) == NULL
)
219 perror("Unable to allocate string");
226 * Copy the new portion to the end of the msgstr string - safe
227 * to use strcpy because the buffer is allocated to the correct
233 memcpy(msgstr
+ length
, ptr
, ptrlen
+ 1);
238 * Copy the new portion to the end of the msgid string - safe
239 * to use strcpy because the buffer is allocated to the correct
245 memcpy(msgid
+ length
, ptr
, ptrlen
+ 1);
248 else if (!strncmp(s
, "msgstr", 6) && msgid
)
257 if ((msgstr
= strdup(ptr
)) == NULL
)
260 perror("Unable to allocate msgstr");
270 cupsFilePrintf(strings
, "\"%s\" = \"%s\";\n", msgid
, normalize_string((use_msgid
|| !*msgstr
) ? msgid
: msgstr
, normalized
, sizeof(normalized
)));
280 cupsFileClose(strings
);
287 * 'normalize_string()' - Normalize a msgid string.
289 * This function converts ASCII ellipsis and double quotes to their Unicode
293 static char * /* O - Normalized string */
294 normalize_string(const char *idstr
, /* I - msgid string */
295 char *buffer
, /* I - Normalized string buffer */
296 size_t bufsize
) /* I - Size of string buffer */
298 char *bufptr
= buffer
, /* Pointer into buffer */
299 *bufend
= buffer
+ bufsize
- 3; /* End of buffer */
300 int quote
= 0, /* Quote direction */
301 html
= 0; /* HTML text */
304 while (*idstr
&& bufptr
< bufend
)
306 if (!strncmp(idstr
, "<A ", 3))
308 else if (html
&& *idstr
== '>')
311 if (*idstr
== '.' && idstr
[1] == '.' && idstr
[2] == '.')
314 * Convert ... to Unicode ellipsis...
317 *bufptr
++ = (char)0xE2;
318 *bufptr
++ = (char)0x80;
319 *bufptr
++ = (char)0xA6;
322 else if (!html
&& *idstr
== '\\' && idstr
[1] == '\"')
327 * Convert second \" to Unicode right (curley) double quote.
330 *bufptr
++ = (char)0xE2;
331 *bufptr
++ = (char)0x80;
332 *bufptr
++ = (char)0x9D;
335 else if (strchr(idstr
+ 2, '\"') != NULL
)
338 * Convert first \" to Unicode left (curley) double quote.
341 *bufptr
++ = (char)0xE2;
342 *bufptr
++ = (char)0x80;
343 *bufptr
++ = (char)0x9C;
349 * Convert lone \" to Unicode double prime.
352 *bufptr
++ = (char)0xE2;
353 *bufptr
++ = (char)0x80;
354 *bufptr
++ = (char)0xB3;
359 else if (*idstr
== '\'')
361 if (strchr(idstr
+ 1, '\'') == NULL
|| quote
)
364 * Convert second ' (or ' used for a contraction) to Unicode right
365 * (curley) single quote.
368 *bufptr
++ = (char)0xE2;
369 *bufptr
++ = (char)0x80;
370 *bufptr
++ = (char)0x99;
376 * Convert first ' to Unicode left (curley) single quote.
379 *bufptr
++ = (char)0xE2;
380 *bufptr
++ = (char)0x80;
381 *bufptr
++ = (char)0x98;