Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2010 Ævar Arnfjörð Bjarmason |
3 | | */ |
4 | | |
5 | | #define DISABLE_SIGN_COMPARE_WARNINGS |
6 | | |
7 | | #include "git-compat-util.h" |
8 | | #include "abspath.h" |
9 | | #include "environment.h" |
10 | | #include "exec-cmd.h" |
11 | | #include "gettext.h" |
12 | | #include "utf8.h" |
13 | | |
14 | | #ifndef NO_GETTEXT |
15 | | # include <libintl.h> |
16 | | # ifdef GIT_WINDOWS_NATIVE |
17 | | |
18 | | static const char *locale_charset(void) |
19 | | { |
20 | | const char *env = getenv("LC_ALL"), *dot; |
21 | | |
22 | | if (!env || !*env) |
23 | | env = getenv("LC_CTYPE"); |
24 | | if (!env || !*env) |
25 | | env = getenv("LANG"); |
26 | | |
27 | | if (!env) |
28 | | return "UTF-8"; |
29 | | |
30 | | dot = strchr(env, '.'); |
31 | | return !dot ? env : dot + 1; |
32 | | } |
33 | | |
34 | | # elif defined HAVE_LIBCHARSET_H |
35 | | # include <libcharset.h> |
36 | | # else |
37 | | # include <langinfo.h> |
38 | 0 | # define locale_charset() nl_langinfo(CODESET) |
39 | | # endif |
40 | | #endif |
41 | | |
42 | | static const char *charset; |
43 | | |
44 | | /* |
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. |
47 | | * |
48 | | * The result can be a colon-separated list like "ko:ja:en". |
49 | | */ |
50 | | const char *get_preferred_languages(void) |
51 | 0 | { |
52 | 0 | const char *retval; |
53 | |
|
54 | 0 | retval = getenv("LANGUAGE"); |
55 | 0 | if (retval && *retval) |
56 | 0 | return retval; |
57 | | |
58 | 0 | #ifndef NO_GETTEXT |
59 | 0 | retval = setlocale(LC_MESSAGES, NULL); |
60 | 0 | if (retval && *retval && |
61 | 0 | strcmp(retval, "C") && |
62 | 0 | strcmp(retval, "POSIX")) |
63 | 0 | return retval; |
64 | 0 | #endif |
65 | | |
66 | 0 | return NULL; |
67 | 0 | } |
68 | | |
69 | | #ifndef NO_GETTEXT |
70 | | __attribute__((format (printf, 1, 2))) |
71 | | static int test_vsnprintf(const char *fmt, ...) |
72 | 0 | { |
73 | 0 | char buf[26]; |
74 | 0 | int ret; |
75 | 0 | va_list ap; |
76 | 0 | va_start(ap, fmt); |
77 | 0 | ret = vsnprintf(buf, sizeof(buf), fmt, ap); |
78 | 0 | va_end(ap); |
79 | 0 | return ret; |
80 | 0 | } |
81 | | |
82 | | static void init_gettext_charset(const char *domain) |
83 | 0 | { |
84 | 0 | charset = locale_charset(); |
85 | 0 | bind_textdomain_codeset(domain, charset); |
86 | | |
87 | | /* |
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. |
92 | | * |
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. |
96 | | * |
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. |
100 | | */ |
101 | 0 | if (test_vsnprintf("%.*s", 13, "David_K\345gedal") < 0) |
102 | 0 | setlocale(LC_CTYPE, "C"); |
103 | 0 | } |
104 | | |
105 | | int git_gettext_enabled = 0; |
106 | | |
107 | | void git_setup_gettext(void) |
108 | 0 | { |
109 | 0 | const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT); |
110 | 0 | char *p = NULL; |
111 | |
|
112 | 0 | if (!podir) |
113 | 0 | podir = p = system_path(GIT_LOCALE_PATH); |
114 | |
|
115 | 0 | if (!is_directory(podir)) { |
116 | 0 | free(p); |
117 | 0 | return; |
118 | 0 | } |
119 | | |
120 | 0 | bindtextdomain("git", podir); |
121 | 0 | setlocale(LC_MESSAGES, ""); |
122 | 0 | setlocale(LC_TIME, ""); |
123 | 0 | init_gettext_charset("git"); |
124 | 0 | textdomain("git"); |
125 | |
|
126 | 0 | git_gettext_enabled = 1; |
127 | |
|
128 | 0 | free(p); |
129 | 0 | } |
130 | | |
131 | | /* return the number of columns of string 's' in current locale */ |
132 | | int gettext_width(const char *s) |
133 | 0 | { |
134 | 0 | static int is_utf8 = -1; |
135 | 0 | if (is_utf8 == -1) |
136 | 0 | is_utf8 = is_utf8_locale(); |
137 | |
|
138 | 0 | return is_utf8 ? utf8_strwidth(s) : strlen(s); |
139 | 0 | } |
140 | | #endif |
141 | | |
142 | | int is_utf8_locale(void) |
143 | 0 | { |
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); |
156 | | } |
157 | | #endif |
158 | 0 | return is_encoding_utf8(charset); |
159 | 0 | } |