Change Guile license to LGPLv3+
[bpt/guile.git] / libguile / gettext.c
1 /* Copyright (C) 2004, 2006 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
17 */
18
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include "libguile/_scm.h"
25 #include "libguile/feature.h"
26 #include "libguile/strings.h"
27 #include "libguile/dynwind.h"
28
29 #include "libguile/gettext.h"
30 #include "libgettext.h"
31 #include <locale.h>
32
33
34 int
35 scm_i_to_lc_category (SCM category, int allow_lc_all)
36 {
37 int c_category = scm_to_int (category);
38 switch (c_category)
39 {
40 #ifdef LC_CTYPE
41 case LC_CTYPE:
42 #endif
43 #ifdef LC_NUMERIC
44 case LC_NUMERIC:
45 #endif
46 #ifdef LC_COLLATE
47 case LC_COLLATE:
48 #endif
49 #ifdef LC_TIME
50 case LC_TIME:
51 #endif
52 #ifdef LC_MONETARY
53 case LC_MONETARY:
54 #endif
55 #ifdef LC_MESSAGES
56 case LC_MESSAGES:
57 #endif
58 #ifdef LC_PAPER
59 case LC_PAPER:
60 #endif
61 #ifdef LC_NAME
62 case LC_NAME:
63 #endif
64 #ifdef LC_ADDRESS
65 case LC_ADDRESS:
66 #endif
67 #ifdef LC_TELEPHONE
68 case LC_TELEPHONE:
69 #endif
70 #ifdef LC_MEASUREMENT
71 case LC_MEASUREMENT:
72 #endif
73 #ifdef LC_IDENTIFICATION
74 case LC_IDENTIFICATION:
75 #endif
76 return c_category;
77 #ifdef LC_ALL
78 case LC_ALL:
79 if (allow_lc_all)
80 return c_category;
81 #endif
82 }
83 scm_wrong_type_arg (0, 0, category);
84 }
85
86 SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
87 (SCM msgid, SCM domain, SCM category),
88 "Return the translation of @var{msgid} in the message domain "
89 "@var{domain}. @var{domain} is optional and defaults to the "
90 "domain set through (textdomain). @var{category} is optional "
91 "and defaults to LC_MESSAGES.")
92 #define FUNC_NAME s_scm_gettext
93 {
94 char *c_msgid;
95 char const *c_result;
96 SCM result;
97
98 scm_dynwind_begin (0);
99
100 c_msgid = scm_to_locale_string (msgid);
101 scm_dynwind_free (c_msgid);
102
103 if (SCM_UNBNDP (domain))
104 {
105 /* 1 argument case. */
106 c_result = gettext (c_msgid);
107 }
108 else
109 {
110 char *c_domain;
111
112 c_domain = scm_to_locale_string (domain);
113 scm_dynwind_free (c_domain);
114
115 if (SCM_UNBNDP (category))
116 {
117 /* 2 argument case. */
118 c_result = dgettext (c_domain, c_msgid);
119 }
120 else
121 {
122 /* 3 argument case. */
123 int c_category;
124
125 c_category = scm_i_to_lc_category (category, 0);
126 c_result = dcgettext (c_domain, c_msgid, c_category);
127 }
128 }
129
130 if (c_result == c_msgid)
131 result = msgid;
132 else
133 result = scm_from_locale_string (c_result);
134
135 scm_dynwind_end ();
136 return result;
137 }
138 #undef FUNC_NAME
139
140
141 SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
142 (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
143 "Return the translation of @var{msgid}/@var{msgid_plural} in the "
144 "message domain @var{domain}, with the plural form being chosen "
145 "appropriately for the number @var{n}. @var{domain} is optional "
146 "and defaults to the domain set through (textdomain). "
147 "@var{category} is optional and defaults to LC_MESSAGES.")
148 #define FUNC_NAME s_scm_ngettext
149 {
150 char *c_msgid;
151 char *c_msgid_plural;
152 unsigned long c_n;
153 const char *c_result;
154 SCM result;
155
156 scm_dynwind_begin (0);
157
158 c_msgid = scm_to_locale_string (msgid);
159 scm_dynwind_free (c_msgid);
160
161 c_msgid_plural = scm_to_locale_string (msgid_plural);
162 scm_dynwind_free (c_msgid_plural);
163
164 c_n = scm_to_ulong (n);
165
166 if (SCM_UNBNDP (domain))
167 {
168 /* 3 argument case. */
169 c_result = ngettext (c_msgid, c_msgid_plural, c_n);
170 }
171 else
172 {
173 char *c_domain;
174
175 c_domain = scm_to_locale_string (domain);
176 scm_dynwind_free (c_domain);
177
178 if (SCM_UNBNDP (category))
179 {
180 /* 4 argument case. */
181 c_result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
182 }
183 else
184 {
185 /* 5 argument case. */
186 int c_category;
187
188 c_category = scm_i_to_lc_category (category, 0);
189 c_result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
190 c_category);
191 }
192 }
193
194 if (c_result == c_msgid)
195 result = msgid;
196 else if (c_result == c_msgid_plural)
197 result = msgid_plural;
198 else
199 result = scm_from_locale_string (c_result);
200
201 scm_dynwind_end ();
202 return result;
203 }
204 #undef FUNC_NAME
205
206 SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
207 (SCM domainname),
208 "If optional parameter @var{domainname} is supplied, "
209 "set the textdomain. "
210 "Return the textdomain.")
211 #define FUNC_NAME s_scm_textdomain
212 {
213 char const *c_result;
214 char *c_domain;
215 SCM result = SCM_BOOL_F;
216
217 scm_dynwind_begin (0);
218
219 if (SCM_UNBNDP (domainname))
220 c_domain = NULL;
221 else
222 {
223 c_domain = scm_to_locale_string (domainname);
224 scm_dynwind_free (c_domain);
225 }
226
227 c_result = textdomain (c_domain);
228 if (c_result != NULL)
229 result = scm_from_locale_string (c_result);
230 else if (!SCM_UNBNDP (domainname))
231 SCM_SYSERROR;
232
233 scm_dynwind_end ();
234 return result;
235 }
236 #undef FUNC_NAME
237
238 SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
239 (SCM domainname, SCM directory),
240 "If optional parameter @var{directory} is supplied, "
241 "set message catalogs to directory @var{directory}. "
242 "Return the directory bound to @var{domainname}.")
243 #define FUNC_NAME s_scm_bindtextdomain
244 {
245 char *c_domain;
246 char *c_directory;
247 char const *c_result;
248 SCM result;
249
250 scm_dynwind_begin (0);
251
252 if (SCM_UNBNDP (directory))
253 c_directory = NULL;
254 else
255 {
256 c_directory = scm_to_locale_string (directory);
257 scm_dynwind_free (c_directory);
258 }
259
260 c_domain = scm_to_locale_string (domainname);
261 scm_dynwind_free (c_domain);
262
263 c_result = bindtextdomain (c_domain, c_directory);
264
265 if (c_result != NULL)
266 result = scm_from_locale_string (c_result);
267 else if (!SCM_UNBNDP (directory))
268 SCM_SYSERROR;
269 else
270 result = SCM_BOOL_F;
271
272 scm_dynwind_end ();
273 return result;
274 }
275 #undef FUNC_NAME
276
277 SCM_DEFINE (scm_bind_textdomain_codeset, "bind-textdomain-codeset", 1, 1, 0,
278 (SCM domainname, SCM encoding),
279 "If optional parameter @var{encoding} is supplied, "
280 "set encoding for message catalogs of @var{domainname}. "
281 "Return the encoding of @var{domainname}.")
282 #define FUNC_NAME s_scm_bind_textdomain_codeset
283 {
284 char *c_domain;
285 char *c_encoding;
286 char const *c_result;
287 SCM result;
288
289 scm_dynwind_begin (0);
290
291 if (SCM_UNBNDP (encoding))
292 c_encoding = NULL;
293 else
294 {
295 c_encoding = scm_to_locale_string (encoding);
296 scm_dynwind_free (c_encoding);
297 }
298
299 c_domain = scm_to_locale_string (domainname);
300 scm_dynwind_free (c_domain);
301
302 c_result = bind_textdomain_codeset (c_domain, c_encoding);
303
304 if (c_result != NULL)
305 result = scm_from_locale_string (c_result);
306 else if (!SCM_UNBNDP (encoding))
307 SCM_SYSERROR;
308 else
309 result = SCM_BOOL_F;
310
311 scm_dynwind_end ();
312 return result;
313 }
314 #undef FUNC_NAME
315
316 void
317 scm_init_gettext ()
318 {
319 /* When gettext support was first added (in 1.8.0), it provided feature
320 `i18n'. We keep this as is although the name is a bit misleading
321 now. */
322 scm_add_feature ("i18n");
323
324 #include "libguile/gettext.x"
325 }
326
327
328 /*
329 Local Variables:
330 c-file-style: "gnu"
331 End:
332 */