Git fork
at reftables-rust 159 lines 3.3 kB view raw
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 18static 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# define locale_charset() nl_langinfo(CODESET) 39# endif 40#endif 41 42static 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 */ 50const char *get_preferred_languages(void) 51{ 52 const char *retval; 53 54 retval = getenv("LANGUAGE"); 55 if (retval && *retval) 56 return retval; 57 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 65 66 return NULL; 67} 68 69#ifndef NO_GETTEXT 70__attribute__((format (printf, 1, 2))) 71static int test_vsnprintf(const char *fmt, ...) 72{ 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; 80} 81 82static void init_gettext_charset(const char *domain) 83{ 84 charset = locale_charset(); 85 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 if (test_vsnprintf("%.*s", 13, "David_K\345gedal") < 0) 102 setlocale(LC_CTYPE, "C"); 103} 104 105int git_gettext_enabled = 0; 106 107void git_setup_gettext(void) 108{ 109 const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT); 110 char *p = NULL; 111 112 if (!podir) 113 podir = p = system_path(GIT_LOCALE_PATH); 114 115 if (!is_directory(podir)) { 116 free(p); 117 return; 118 } 119 120 bindtextdomain("git", podir); 121 setlocale(LC_MESSAGES, ""); 122 setlocale(LC_TIME, ""); 123 init_gettext_charset("git"); 124 textdomain("git"); 125 126 git_gettext_enabled = 1; 127 128 free(p); 129} 130 131/* return the number of columns of string 's' in current locale */ 132int gettext_width(const char *s) 133{ 134 static int is_utf8 = -1; 135 if (is_utf8 == -1) 136 is_utf8 = is_utf8_locale(); 137 138 return is_utf8 ? utf8_strwidth(s) : strlen(s); 139} 140#endif 141 142int is_utf8_locale(void) 143{ 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 return is_encoding_utf8(charset); 159}