1 /*
2 * i18n.c -
3 * $Id: i18n.c,v 1.26.4.12 2008-03-06 15:38:09 opengl2772 Exp $
4 *
5 * Copyright (C) 1997-1999 Satoru Takabayashi All rights reserved.
6 * Copyright (C) 2000-2008 Namazu Project All rights reserved.
7 * This is free software with ABSOLUTELY NO WARRANTY.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 * 02111-1307, USA
23 *
24 *
25 */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 #ifdef HAVE_SUPPORT_H
31 # include "support.h"
32 #endif
33
34 #include <stdio.h>
35 #ifdef HAVE_STDLIB_H
36 # include <stdlib.h>
37 #endif
38
39 #ifdef HAVE_STRING_H
40 # include <string.h>
41 #else
42 # include <strings.h>
43 #endif
44
45 #ifdef HAVE_LOCALE_H
46 # include <locale.h>
47 #endif
48
49 #include "libnamazu.h"
50 #include "util.h"
51 #include "i18n.h"
52
53 /*
54 *
55 * Private functions
56 *
57 */
58
59 static const char *guess_category_value ( const char *categoryname );
60 static char *get_lang_by_category ( const char *categoryname );
61 static int _purification_lang( char *lang, size_t n );
62
63
64 /* The following is (partly) taken from the gettext package.
65 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. */
66
67 static const char *
guess_category_value(const char * categoryname)68 guess_category_value (const char *categoryname)
69 {
70 const char *retval;
71
72 if (!strcmp(categoryname, "LC_MESSAGES")) {
73
74 /* The highest priority value is the `LANGUAGE' environment
75 variable. This is a GNU extension. */
76 retval = getenv ("LANGUAGE");
77 if (retval != NULL && retval[0] != '\0')
78 return retval;
79 }
80
81 /* `LANGUAGE' is not set. So we have to proceed with the POSIX
82 methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some
83 systems this can be done by the `setlocale' function itself. */
84
85 /* Setting of LC_ALL overwrites all other. */
86 retval = getenv ("LC_ALL");
87 if (retval != NULL && retval[0] != '\0')
88 return retval;
89
90 /* Next comes the name of the desired category. */
91 retval = getenv (categoryname);
92 if (retval != NULL && retval[0] != '\0')
93 return retval;
94
95 /* Last possibility is the LANG environment variable. */
96 retval = getenv ("LANG");
97 if (retval != NULL && retval[0] != '\0')
98 return retval;
99
100 return NULL;
101 }
102
103 static char *
get_lang_by_category(const char * categoryname)104 get_lang_by_category(const char *categoryname)
105 {
106 static char lang[BUFSIZE] = "";
107 char *value;
108
109 value = (char *)guess_category_value(categoryname);
110 if (value == NULL) {
111 return "C";
112 } else {
113 strncpy(lang, value, BUFSIZE - 1);
114 lang[BUFSIZE - 1] = '\0';
115 _purification_lang(lang, BUFSIZE);
116 if (lang[0] == '\0') {
117 return "C";
118 }
119 return lang;
120 }
121 }
122
123 /*
124 *
125 * Public functions
126 *
127 */
128
129 char *
nmz_set_lang(const char * value)130 nmz_set_lang(const char *value)
131 {
132 static char lang[BUFSIZE] = "";
133 const char* env;
134
135 strncpy(lang, value, BUFSIZE - 1);
136 _purification_lang(lang, BUFSIZE);
137
138 env = guess_category_value("LC_MESSAGES");
139 if (env == NULL && *lang != '\0') {
140 #ifdef HAVE_SETENV
141 setenv("LANG", lang, 1);
142 #else
143 # ifdef HAVE_PUTENV
144 {
145 static char *store = NULL;
146
147 if (store != NULL)
148 free(store);
149 store = (char *)malloc(strlen(lang) + 6); /* do *not* free */
150 if (store == NULL)
151 return NULL; /* FIXME: should be fatal error */
152 strcpy(store, "LANG=");
153 strcat(store, lang);
154 putenv(store);
155 }
156 # endif
157 #endif
158 }
159
160 #ifdef HAVE_SETLOCALE
161 /* Set locale via LC_ALL. */
162 setlocale (LC_ALL, "");
163 #endif
164
165 return (char *)lang;
166 }
167
168 char *
nmz_get_lang(void)169 nmz_get_lang(void)
170 {
171 return get_lang_by_category("LC_MESSAGES");
172 }
173
174 char *
nmz_get_lang_ctype(void)175 nmz_get_lang_ctype(void)
176 {
177 return get_lang_by_category("LC_CTYPE");
178 }
179
180 /*
181 * Choose suffix of message files such as ".ja_JP", ".ja", "", etc.
182 * lang
183 */
184 enum nmz_stat
nmz_choose_msgfile_suffix(const char * pfname,char * lang_suffix)185 nmz_choose_msgfile_suffix(const char *pfname, char *lang_suffix)
186 {
187 FILE *fp;
188 size_t baselen;
189 char fname[BUFSIZE] = "";
190 char suffix[BUFSIZE] = "";
191
192 strncpy(fname, pfname, BUFSIZE - 1);
193 baselen = strlen(fname);
194 strncat(fname, ".", BUFSIZE - strlen(fname) - 1);
195 nmz_delete_since_path_delimitation(suffix, nmz_get_lang(), BUFSIZE);
196 strncat(fname, suffix, BUFSIZE - strlen(fname) - 1);
197
198 /*
199 * Trial example:
200 * 1. NMZ.tips.ja_JP.ISO-2022-JP
201 * 2. NMZ.tips.ja_JP
202 * 3. NMZ.tips.ja
203 * 4. NMZ.tips
204 */
205
206 do {
207 int i;
208
209 fp = fopen(fname, "rb");
210 if (fp != NULL) { /* fopen success */
211 nmz_debug_printf("choose_msgfile: %s open SUCCESS.\n", fname);
212 fclose(fp);
213 strcpy(lang_suffix, fname + baselen); /* it shouldn't be flood */
214 return SUCCESS;
215 }
216 nmz_debug_printf("choose_msgfile: %s open failed.\n", fname);
217
218 for (i = (int)strlen(fname) - 1; i >= 0; i--) {
219 if (fname[i] == '.' ||
220 fname[i] == '_')
221 {
222 fname[i] = '\0';
223 break;
224 }
225 }
226 if (strlen(fname) < baselen) {
227 break;
228 }
229 } while (1);
230 return FAILURE;
231 }
232
233 /*
234 * purification language.
235 * [A-Za-z][A-Za-z0-9_,+@\-\.=]*
236 * (ex. ja_JP.eucJP, ja_JP.SJIS, C)
237 */
_purification_lang(char * lang,size_t n)238 static int _purification_lang(char *lang, size_t n)
239 {
240 char *p;
241
242 p = lang;
243
244 /* [A-Za-z][A-Za-z0-9_,+@\-\.=]* */
245 if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z')) {
246 p++;
247 while(*p) {
248 if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z')
249 || (*p >= '0' && *p <= '9')
250 || *p == '_' || *p == ',' || *p == '+' || *p == '@'
251 || *p == '-' || *p == '.' || *p == '='
252 ) {
253 } else {
254 *p = '\0';
255 break;
256 }
257 p++;
258 }
259 } else {
260 *p = '\0';
261 }
262
263 return 1;
264 }
265