1 /* locale.c - Miscellaneous internationalization functions. */
3 /* Copyright (C) 1996 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
23 #include "bashtypes.h"
25 #if defined (HAVE_UNISTD_H)
32 #include "chartypes.h"
35 #include "input.h" /* For bash_input */
37 extern int dump_translatable_strings
, dump_po_strings
;
39 /* The current locale when the program begins */
40 static char *default_locale
;
42 /* The current domain for textdomain(3). */
43 static char *default_domain
;
44 static char *default_dir
;
46 /* tracks the value of LC_ALL; used to override values for other locale
50 /* Set the value of default_locale and make the current locale the
51 system default locale. This should be called very early in main(). */
55 #if defined (HAVE_SETLOCALE)
56 default_locale
= setlocale (LC_ALL
, "");
58 default_locale
= savestring (default_locale
);
59 #endif /* HAVE_SETLOCALE */
62 /* Set default values for LC_CTYPE, LC_COLLATE, and LC_MESSAGES if they
63 are not specified in the environment, but LANG or LC_ALL is. This
64 should be called from main() after parsing the environment. */
66 set_default_locale_vars ()
70 #if defined (HAVE_SETLOCALE)
71 val
= get_string_value ("LC_CTYPE");
72 if (val
== 0 && lc_all
&& *lc_all
)
73 setlocale (LC_CTYPE
, lc_all
);
75 # if defined (LC_COLLATE)
76 val
= get_string_value ("LC_COLLATE");
77 if (val
== 0 && lc_all
&& *lc_all
)
78 setlocale (LC_COLLATE
, lc_all
);
79 # endif /* LC_COLLATE */
81 # if defined (LC_MESSAGES)
82 val
= get_string_value ("LC_MESSAGES");
83 if (val
== 0 && lc_all
&& *lc_all
)
84 setlocale (LC_MESSAGES
, lc_all
);
85 # endif /* LC_MESSAGES */
87 # if defined (LC_NUMERIC)
88 val
= get_string_value ("LC_NUMERIC");
89 if (val
== 0 && lc_all
&& *lc_all
)
90 setlocale (LC_NUMERIC
, lc_all
);
91 # endif /* LC_NUMERIC */
93 #endif /* HAVE_SETLOCALE */
95 val
= get_string_value ("TEXTDOMAIN");
98 FREE (default_domain
);
99 default_domain
= savestring (val
);
100 textdomain (default_domain
);
103 val
= get_string_value ("TEXTDOMAINDIR");
107 default_dir
= savestring (val
);
108 bindtextdomain (default_domain
, default_dir
);
112 /* Set one of the locale categories (specified by VAR) to VALUE. Returns 1
113 if successful, 0 otherwise. */
115 set_locale_var (var
, value
)
118 if (var
[0] == 'T' && var
[10] == 0) /* TEXTDOMAIN */
120 FREE (default_domain
);
121 default_domain
= value
? savestring (value
) : (char *)NULL
;
122 textdomain (default_domain
);
125 else if (var
[0] == 'T') /* TEXTDOMAINDIR */
128 default_dir
= value
? savestring (value
) : (char *)NULL
;
129 bindtextdomain (default_domain
, default_dir
);
133 /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
135 else if (var
[3] == 'A') /* LC_ALL */
139 lc_all
= savestring (value
);
140 else if (default_locale
)
141 lc_all
= savestring (default_locale
);
144 lc_all
= (char *)xmalloc (1);
147 #if defined (HAVE_SETLOCALE)
148 return (setlocale (LC_ALL
, lc_all
) != 0);
154 #if defined (HAVE_SETLOCALE)
155 else if (var
[3] == 'C' && var
[4] == 'T') /* LC_CTYPE */
157 if (lc_all
== 0 || *lc_all
== '\0')
158 return (setlocale (LC_CTYPE
, value
? value
: "") != 0);
160 else if (var
[3] == 'C' && var
[4] == 'O') /* LC_COLLATE */
162 # if defined (LC_COLLATE)
163 if (lc_all
== 0 || *lc_all
== '\0')
164 return (setlocale (LC_COLLATE
, value
? value
: "") != 0);
165 # endif /* LC_COLLATE */
167 else if (var
[3] == 'M' && var
[4] == 'E') /* LC_MESSAGES */
169 # if defined (LC_MESSAGES)
170 if (lc_all
== 0 || *lc_all
== '\0')
171 return (setlocale (LC_MESSAGES
, value
? value
: "") != 0);
172 # endif /* LC_MESSAGES */
174 else if (var
[3] == 'N' && var
[4] == 'U') /* LC_NUMERIC */
176 # if defined (LC_NUMERIC)
177 if (lc_all
== 0 || *lc_all
== '\0')
178 return (setlocale (LC_NUMERIC
, value
? value
: "") != 0);
179 # endif /* LC_NUMERIC */
181 #endif /* HAVE_SETLOCALE */
186 /* Called when LANG is assigned a value. Sets LC_ALL category with
187 setlocale(3) if that has not already been set. Doesn't change any
190 set_lang (var
, value
)
193 return ((lc_all
== 0 || *lc_all
== 0) ? setlocale (LC_ALL
, value
?value
:"") != NULL
: 0);
196 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE) */
206 locale
= get_string_value (var
);
208 locale
= default_locale
;
213 /* Translate the contents of STRING, a $"..." quoted string, according
214 to the current locale. In the `C' or `POSIX' locale, or if gettext()
215 is not available, the passed string is returned unchanged. The
216 length of the translated string is returned in LENP, if non-null. */
218 localetrans (string
, len
, lenp
)
223 #if defined (HAVE_GETTEXT)
228 /* Don't try to translate null strings. */
229 if (string
== 0 || *string
== 0)
233 return ((char *)NULL
);
236 locale
= get_locale_var ("LC_MESSAGES");
238 /* If we don't have setlocale() or the current locale is `C' or `POSIX',
239 just return the string. If we don't have gettext(), there's no use
240 doing anything else. */
241 #if defined (HAVE_GETTEXT)
242 if (locale
== 0 || locale
[0] == '\0' ||
243 (locale
[0] == 'C' && locale
[1] == '\0') || STREQ (locale
, "POSIX"))
246 t
= (char *)xmalloc (len
+ 1);
253 #if defined (HAVE_GETTEXT)
254 /* Now try to translate it. */
255 translated
= gettext (string
);
256 if (translated
== string
) /* gettext returns its argument if untranslatable */
258 t
= (char *)xmalloc (len
+ 1);
265 tlen
= strlen (translated
);
266 t
= (char *)xmalloc (tlen
+ 1);
267 strcpy (t
, translated
);
272 #endif /* HAVE_GETTEXT */
275 /* Change a bash string into a string suitable for inclusion in a `po' file.
276 This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
278 mk_msgstr (string
, foundnlp
)
283 char *result
, *r
, *s
;
285 for (len
= 0, s
= string
; s
&& *s
; s
++)
288 if (*s
== '"' || *s
== '\\')
294 r
= result
= (char *)xmalloc (len
+ 3);
297 for (s
= string
; s
&& (c
= *s
); s
++)
299 if (c
== '\n') /* <NL> -> \n"<NL>" */
310 if (c
== '"' || c
== '\\')
321 /* $"..." -- Translate the portion of STRING between START and END
322 according to current locale using gettext (if available) and return
323 the result. The caller will take care of leaving the quotes intact.
324 The string will be left without the leading `$' by the caller.
325 If translation is performed, the translated string will be double-quoted
326 by the caller. The length of the translated string is returned in LENP,
329 localeexpand (string
, start
, end
, lineno
, lenp
)
331 int start
, end
, lineno
, *lenp
;
333 int len
, tlen
, foundnl
;
336 temp
= (char *)xmalloc (end
- start
+ 1);
337 for (tlen
= 0, len
= start
; len
< end
; )
338 temp
[tlen
++] = string
[len
++];
341 /* If we're just dumping translatable strings, don't do anything with the
342 string itself, but if we're dumping in `po' file format, convert it into a form more palatable to gettext(3)
343 and friends by quoting `"' and `\' with backslashes and converting <NL>
344 into `\n"<NL>"'. If we find a newline in TEMP, we first output a
345 `msgid ""' line and then the translated string; otherwise we output the
346 `msgid' and translated string all on one line. */
347 if (dump_translatable_strings
)
352 t
= mk_msgstr (temp
, &foundnl
);
353 t2
= foundnl
? "\"\"\n" : "";
355 printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
356 yy_input_name (), lineno
, t2
, t
);
360 printf ("\"%s\"\n", temp
);
368 t
= localetrans (temp
, tlen
, &len
);