2 Copyright (C) 2001-2009 Free Software Foundation, Inc.
3 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
32 #define _(str) gettext (str)
34 /* Table of all format string parsers. */
35 struct formatstring_parser *formatstring_parsers[NFORMATS] =
37 /* format_c */ &formatstring_c,
38 /* format_objc */ &formatstring_objc,
39 /* format_sh */ &formatstring_sh,
40 /* format_python */ &formatstring_python,
41 /* format_python_brace */ &formatstring_python_brace,
42 /* format_lisp */ &formatstring_lisp,
43 /* format_elisp */ &formatstring_elisp,
44 /* format_librep */ &formatstring_librep,
45 /* format_scheme */ &formatstring_scheme,
46 /* format_smalltalk */ &formatstring_smalltalk,
47 /* format_java */ &formatstring_java,
48 /* format_csharp */ &formatstring_csharp,
49 /* format_awk */ &formatstring_awk,
50 /* format_pascal */ &formatstring_pascal,
51 /* format_ycp */ &formatstring_ycp,
52 /* format_tcl */ &formatstring_tcl,
53 /* format_perl */ &formatstring_perl,
54 /* format_perl_brace */ &formatstring_perl_brace,
55 /* format_php */ &formatstring_php,
56 /* format_gcc_internal */ &formatstring_gcc_internal,
57 /* format_gfc_internal */ &formatstring_gfc_internal,
58 /* format_qt */ &formatstring_qt,
59 /* format_qt_plural */ &formatstring_qt_plural,
60 /* format_kde */ &formatstring_kde,
61 /* format_boost */ &formatstring_boost,
62 /* format_lua */ &formatstring_lua,
63 /* format_javascript */ &formatstring_javascript
66 /* Check whether both formats strings contain compatible format
67 specifications for format type i (0 <= i < NFORMATS). */
69 check_msgid_msgstr_format_i (const char *msgid, const char *msgid_plural,
70 const char *msgstr, size_t msgstr_len,
72 struct argument_range range,
73 const struct plural_distribution *distribution,
74 formatstring_error_logger_t error_logger)
78 /* At runtime, we can assume the program passes arguments that fit well for
79 msgid. We must signal an error if msgstr wants more arguments that msgid
81 If msgstr wants fewer arguments than msgid, it wouldn't lead to a crash
82 at runtime, but we nevertheless give an error because
83 1) this situation occurs typically after the programmer has added some
84 arguments to msgid, so we must make the translator specially aware
85 of it (more than just "fuzzy"),
86 2) it is generally wrong if a translation wants to ignore arguments that
87 are used by other translations. */
89 struct formatstring_parser *parser = formatstring_parsers[i];
90 char *invalid_reason = NULL;
92 parser->parse (msgid_plural != NULL ? msgid_plural : msgid, false, NULL,
95 if (msgid_descr != NULL)
97 const char *pretty_msgid =
98 (msgid_plural != NULL ? "msgid_plural" : "msgid");
100 const char *pretty_msgstr = "msgstr";
101 bool has_plural_translations = (strlen (msgstr) + 1 < msgstr_len);
102 const char *p_end = msgstr + msgstr_len;
106 for (p = msgstr, j = 0; p < p_end; p += strlen (p) + 1, j++)
110 if (msgid_plural != NULL)
112 sprintf (buf, "msgstr[%u]", j);
116 msgstr_descr = parser->parse (p, true, NULL, &invalid_reason);
118 if (msgstr_descr != NULL)
120 /* Use strict checking (require same number of format
121 directives on both sides) if the message has no plurals,
122 or if msgid_plural exists but on the msgstr[] side
123 there is only msgstr[0], or if distribution->often[j]
124 indicates that the variant applies to infinitely many
125 values of N and the N range is not restricted in a way
126 that the variant applies to only one N.
127 Use relaxed checking when there are at least two
128 msgstr[] forms and the distribution does not give more
129 precise information. */
130 bool strict_checking =
131 (msgid_plural == NULL
132 || !has_plural_translations
133 || (distribution != NULL
134 && distribution->often != NULL
135 && j < distribution->often_length
136 && distribution->often[j]
137 && !(has_range_p (range)
138 && distribution->histogram (distribution,
139 range.min, range.max, j)
142 if (parser->check (msgid_descr, msgstr_descr,
144 error_logger, pretty_msgid, pretty_msgstr))
147 parser->free (msgstr_descr);
152 '%s' is not a valid %s format string, unlike '%s'. Reason: %s"),
153 pretty_msgstr, format_language_pretty[i],
154 pretty_msgid, invalid_reason);
156 free (invalid_reason);
160 parser->free (msgid_descr);
163 free (invalid_reason);
168 /* Check whether both formats strings contain compatible format
170 Return the number of errors that were seen. */
172 check_msgid_msgstr_format (const char *msgid, const char *msgid_plural,
173 const char *msgstr, size_t msgstr_len,
174 const enum is_format is_format[NFORMATS],
175 struct argument_range range,
176 const struct plural_distribution *distribution,
177 formatstring_error_logger_t error_logger)
182 /* We check only those messages for which the msgid's is_format flag
183 is one of 'yes' or 'possible'. We don't check msgids with is_format
184 'no' or 'impossible', to obey the programmer's order. We don't check
185 msgids with is_format 'undecided' because that would introduce too
186 many checks, thus forcing the programmer to add "xgettext: no-c-format"
187 anywhere where a translator wishes to use a percent sign. */
188 for (i = 0; i < NFORMATS; i++)
189 if (possible_format_p (is_format[i]))
190 seen_errors += check_msgid_msgstr_format_i (msgid, msgid_plural,
191 msgstr, msgstr_len, i,