]>
git.ipfire.org Git - thirdparty/cups.git/blob - locale/checkpo.c
2ac66273346702680d4e1bac5cb8ea8765be17ac
2 * "$Id: checkpo.c 6926 2007-09-06 14:34:31Z mike $"
4 * Verify that translations in the .po file have the same number and type of
5 * printf-style format strings.
9 * checkpo filename.po [... filenameN.po]
13 * gcc -o checkpo checkpo.c `cups-config --libs`
17 * main() - Validate .po files.
18 * abbreviate() - Abbreviate a message string as needed.
19 * collect_formats() - Collect all of the format strings in the msgid.
20 * free_formats() - Free all of the format strings.
25 #include <cups/string.h>
26 #include <cups/i18n.h>
33 static char *abbreviate(const char *s
, char *buf
, int bufsize
);
34 static cups_array_t
*collect_formats(const char *id
);
35 static void free_formats(cups_array_t
*fmts
);
39 * 'main()' - Validate .po files.
42 int /* O - Exit code */
43 main(int argc
, /* I - Number of command-line args */
44 char *argv
[]) /* I - Command-line arguments */
46 int i
; /* Looping var */
47 cups_array_t
*po
; /* .po file */
48 _cups_message_t
*msg
; /* Current message */
49 cups_array_t
*idfmts
, /* Format strings in msgid */
50 *strfmts
; /* Format strings in msgstr */
51 char *idfmt
, /* Current msgid format string */
52 *strfmt
; /* Current msgstr format string */
53 int fmtidx
, /* Format index */
54 fmtcount
; /* Format count */
55 int status
, /* Exit status */
56 pass
, /* Pass/fail status */
57 untranslated
; /* Untranslated messages */
58 char idbuf
[80], /* Abbreviated msgid */
59 strbuf
[80]; /* Abbreviated msgstr */
64 puts("Usage: checkpo filename.po [... filenameN.po]");
69 * Check every .po file on the command-line...
72 for (i
= 1, status
= 0; i
< argc
; i
++)
75 * Use the CUPS .po loader to get the message strings...
78 if ((po
= _cupsMessageLoad(argv
[i
])) == NULL
)
84 printf("%s: ", argv
[i
]);
88 * Scan every message for a % string and then match them up with
89 * the corresponding string in the translation...
95 for (msg
= (_cups_message_t
*)cupsArrayFirst(po
);
97 msg
= (_cups_message_t
*)cupsArrayNext(po
))
99 if (!msg
->str
|| !msg
->str
[0])
104 else if (strchr(msg
->id
, '%'))
106 idfmts
= collect_formats(msg
->id
);
107 strfmts
= collect_formats(msg
->str
);
110 for (strfmt
= (char *)cupsArrayFirst(strfmts
);
112 strfmt
= (char *)cupsArrayNext(strfmts
))
114 if (isdigit(strfmt
[1] & 255) && strfmt
[2] == '$')
117 * Handle positioned format stuff...
120 fmtidx
= strfmt
[1] - '1';
122 if ((idfmt
= (char *)cupsArrayIndex(idfmts
, fmtidx
)) != NULL
)
128 * Compare against the current format...
131 idfmt
= (char *)cupsArrayIndex(idfmts
, fmtidx
);
136 if (!idfmt
|| strcmp(strfmt
, idfmt
))
142 if (cupsArrayCount(strfmts
) != cupsArrayCount(idfmts
) || strfmt
)
150 printf(" Bad translation string \"%s\"\n for \"%s\"\n",
151 abbreviate(msg
->str
, strbuf
, sizeof(strbuf
)),
152 abbreviate(msg
->id
, idbuf
, sizeof(idbuf
)));
153 fputs(" Translation formats:", stdout
);
154 for (strfmt
= (char *)cupsArrayFirst(strfmts
);
156 strfmt
= (char *)cupsArrayNext(strfmts
))
157 printf(" %s", strfmt
);
158 fputs("\n Original formats:", stdout
);
159 for (idfmt
= (char *)cupsArrayFirst(idfmts
);
161 idfmt
= (char *)cupsArrayNext(idfmts
))
162 printf(" %s", idfmt
);
166 free_formats(idfmts
);
167 free_formats(strfmts
);
170 if ((!strncmp(msg
->id
, "ALERT:", 6) && strncmp(msg
->str
, "ALERT:", 6)) ||
171 (!strncmp(msg
->id
, "CRIT:", 5) && strncmp(msg
->str
, "CRIT:", 5)) ||
172 (!strncmp(msg
->id
, "DEBUG:", 6) && strncmp(msg
->str
, "DEBUG:", 6)) ||
173 (!strncmp(msg
->id
, "DEBUG2:", 7) && strncmp(msg
->str
, "DEBUG2:", 7)) ||
174 (!strncmp(msg
->id
, "EMERG:", 6) && strncmp(msg
->str
, "EMERG:", 6)) ||
175 (!strncmp(msg
->id
, "ERROR:", 6) && strncmp(msg
->str
, "ERROR:", 6)) ||
176 (!strncmp(msg
->id
, "INFO:", 5) && strncmp(msg
->str
, "INFO:", 5)) ||
177 (!strncmp(msg
->id
, "NOTICE:", 7) && strncmp(msg
->str
, "NOTICE:", 7)) ||
178 (!strncmp(msg
->id
, "WARNING:", 8) && strncmp(msg
->str
, "WARNING:", 8)))
186 printf(" Bad prefix on filter message \"%s\"\n for \"%s\"\n",
187 abbreviate(msg
->str
, strbuf
, sizeof(strbuf
)),
188 abbreviate(msg
->id
, idbuf
, sizeof(idbuf
)));
194 if ((untranslated
* 10) >= cupsArrayCount(po
))
197 * Only allow 10% of messages to be untranslated before we fail...
202 printf(" Too many untranslated messages (%d of %d)\n", untranslated
,
205 else if (untranslated
> 0)
206 printf("PASS (%d of %d untranslated)\n", untranslated
,
215 _cupsMessageFree(po
);
223 * 'abbreviate()' - Abbreviate a message string as needed.
226 static char * /* O - Abbreviated string */
227 abbreviate(const char *s
, /* I - String to abbreviate */
228 char *buf
, /* I - Buffer */
229 int bufsize
) /* I - Size of buffer */
231 char *bufptr
; /* Pointer into buffer */
234 for (bufptr
= buf
, bufsize
-= 4; *s
&& bufsize
> 0; s
++)
254 else if (*s
>= 0 && *s
< ' ')
259 sprintf(bufptr
, "\\%03o", *s
);
271 strcpy(bufptr
, "...");
280 * 'collect_formats()' - Collect all of the format strings in the msgid.
283 static cups_array_t
* /* O - Array of format strings */
284 collect_formats(const char *id
) /* I - msgid string */
286 cups_array_t
*fmts
; /* Array of format strings */
287 char buf
[255], /* Format string buffer */
288 *bufptr
; /* Pointer into format string */
291 fmts
= cupsArrayNew(NULL
, NULL
);
293 while ((id
= strchr(id
, '%')) != NULL
)
305 for (bufptr
= buf
; *id
&& bufptr
< (buf
+ sizeof(buf
) - 1); id
++)
309 if (strchr("CDEFGIOSUXcdeifgopsux", *id
))
317 cupsArrayAdd(fmts
, strdup(buf
));
325 * 'free_formats()' - Free all of the format strings.
329 free_formats(cups_array_t
*fmts
) /* I - Array of format strings */
331 char *s
; /* Current string */
334 for (s
= (char *)cupsArrayFirst(fmts
); s
; s
= (char *)cupsArrayNext(fmts
))
337 cupsArrayDelete(fmts
);
342 * End of "$Id: checkpo.c 6926 2007-09-06 14:34:31Z mike $".