Git 2.42-rc1
[git.git] / gettext.c
blobf27e94407b4c2848eecfbd827ee85525ff8c04ed
1 /*
2 * Copyright (c) 2010 Ævar Arnfjörð Bjarmason
3 */
5 #include "git-compat-util.h"
6 #include "abspath.h"
7 #include "environment.h"
8 #include "exec-cmd.h"
9 #include "gettext.h"
10 #include "strbuf.h"
11 #include "utf8.h"
12 #include "config.h"
14 #ifndef NO_GETTEXT
15 # include <libintl.h>
16 # ifdef GIT_WINDOWS_NATIVE
18 static const char *locale_charset(void)
20 const char *env = getenv("LC_ALL"), *dot;
22 if (!env || !*env)
23 env = getenv("LC_CTYPE");
24 if (!env || !*env)
25 env = getenv("LANG");
27 if (!env)
28 return "UTF-8";
30 dot = strchr(env, '.');
31 return !dot ? env : dot + 1;
34 # elif defined HAVE_LIBCHARSET_H
35 # include <libcharset.h>
36 # else
37 # include <langinfo.h>
38 # define locale_charset() nl_langinfo(CODESET)
39 # endif
40 #endif
42 static const char *charset;
45 * Guess the user's preferred languages from the value in LANGUAGE environment
46 * variable and LC_MESSAGES locale category if NO_GETTEXT is not defined.
48 * The result can be a colon-separated list like "ko:ja:en".
50 const char *get_preferred_languages(void)
52 const char *retval;
54 retval = getenv("LANGUAGE");
55 if (retval && *retval)
56 return retval;
58 #ifndef NO_GETTEXT
59 retval = setlocale(LC_MESSAGES, NULL);
60 if (retval && *retval &&
61 strcmp(retval, "C") &&
62 strcmp(retval, "POSIX"))
63 return retval;
64 #endif
66 return NULL;
69 #ifndef NO_GETTEXT
70 __attribute__((format (printf, 1, 2)))
71 static int test_vsnprintf(const char *fmt, ...)
73 char buf[26];
74 int ret;
75 va_list ap;
76 va_start(ap, fmt);
77 ret = vsnprintf(buf, sizeof(buf), fmt, ap);
78 va_end(ap);
79 return ret;
82 static void init_gettext_charset(const char *domain)
84 charset = locale_charset();
85 bind_textdomain_codeset(domain, charset);
88 * Work around an old bug fixed in glibc 2.17 (released on
89 * 2012-12-24), at the cost of potentially making translated
90 * messages from external functions like perror() emitted in
91 * the wrong encoding.
93 * The bug affected e.g. git.git's own 7eb93c89651 ([PATCH]
94 * Simplify git script, 2005-09-07), which is the origin of
95 * the "David_K\345gedal" test string.
97 * See a much longer comment added to this file in 5e9637c6297
98 * (i18n: add infrastructure for translating Git with gettext,
99 * 2011-11-18) for more details.
101 if (test_vsnprintf("%.*s", 13, "David_K\345gedal") < 0)
102 setlocale(LC_CTYPE, "C");
105 int git_gettext_enabled = 0;
107 void git_setup_gettext(void)
109 const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT);
110 char *p = NULL;
112 if (!podir)
113 podir = p = system_path(GIT_LOCALE_PATH);
115 if (!is_directory(podir)) {
116 free(p);
117 return;
120 bindtextdomain("git", podir);
121 setlocale(LC_MESSAGES, "");
122 setlocale(LC_TIME, "");
123 init_gettext_charset("git");
124 textdomain("git");
126 git_gettext_enabled = 1;
128 free(p);
131 /* return the number of columns of string 's' in current locale */
132 int gettext_width(const char *s)
134 static int is_utf8 = -1;
135 if (is_utf8 == -1)
136 is_utf8 = is_utf8_locale();
138 return is_utf8 ? utf8_strwidth(s) : strlen(s);
140 #endif
142 int is_utf8_locale(void)
144 #ifdef NO_GETTEXT
145 if (!charset) {
146 const char *env = getenv("LC_ALL");
147 if (!env || !*env)
148 env = getenv("LC_CTYPE");
149 if (!env || !*env)
150 env = getenv("LANG");
151 if (!env)
152 env = "";
153 if (strchr(env, '.'))
154 env = strchr(env, '.') + 1;
155 charset = xstrdup(env);
157 #endif
158 return is_encoding_utf8(charset);