git
/
gettext.c
157 строк · 3.2 Кб
1/*
2* Copyright (c) 2010 Ævar Arnfjörð Bjarmason
3*/
4
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 "utf8.h"11
12#ifndef NO_GETTEXT13# include <libintl.h>14# ifdef GIT_WINDOWS_NATIVE15
16static const char *locale_charset(void)17{
18const char *env = getenv("LC_ALL"), *dot;19
20if (!env || !*env)21env = getenv("LC_CTYPE");22if (!env || !*env)23env = getenv("LANG");24
25if (!env)26return "UTF-8";27
28dot = strchr(env, '.');29return !dot ? env : dot + 1;30}
31
32# elif defined HAVE_LIBCHARSET_H33# include <libcharset.h>34# else35# include <langinfo.h>36# define locale_charset() nl_langinfo(CODESET)37# endif38#endif39
40static const char *charset;41
42/*
43* Guess the user's preferred languages from the value in LANGUAGE environment
44* variable and LC_MESSAGES locale category if NO_GETTEXT is not defined.
45*
46* The result can be a colon-separated list like "ko:ja:en".
47*/
48const char *get_preferred_languages(void)49{
50const char *retval;51
52retval = getenv("LANGUAGE");53if (retval && *retval)54return retval;55
56#ifndef NO_GETTEXT57retval = setlocale(LC_MESSAGES, NULL);58if (retval && *retval &&59strcmp(retval, "C") &&60strcmp(retval, "POSIX"))61return retval;62#endif63
64return NULL;65}
66
67#ifndef NO_GETTEXT68__attribute__((format (printf, 1, 2)))69static int test_vsnprintf(const char *fmt, ...)70{
71char buf[26];72int ret;73va_list ap;74va_start(ap, fmt);75ret = vsnprintf(buf, sizeof(buf), fmt, ap);76va_end(ap);77return ret;78}
79
80static void init_gettext_charset(const char *domain)81{
82charset = locale_charset();83bind_textdomain_codeset(domain, charset);84
85/*86* Work around an old bug fixed in glibc 2.17 (released on
87* 2012-12-24), at the cost of potentially making translated
88* messages from external functions like perror() emitted in
89* the wrong encoding.
90*
91* The bug affected e.g. git.git's own 7eb93c89651 ([PATCH]
92* Simplify git script, 2005-09-07), which is the origin of
93* the "David_K\345gedal" test string.
94*
95* See a much longer comment added to this file in 5e9637c6297
96* (i18n: add infrastructure for translating Git with gettext,
97* 2011-11-18) for more details.
98*/
99if (test_vsnprintf("%.*s", 13, "David_K\345gedal") < 0)100setlocale(LC_CTYPE, "C");101}
102
103int git_gettext_enabled = 0;104
105void git_setup_gettext(void)106{
107const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT);108char *p = NULL;109
110if (!podir)111podir = p = system_path(GIT_LOCALE_PATH);112
113if (!is_directory(podir)) {114free(p);115return;116}117
118bindtextdomain("git", podir);119setlocale(LC_MESSAGES, "");120setlocale(LC_TIME, "");121init_gettext_charset("git");122textdomain("git");123
124git_gettext_enabled = 1;125
126free(p);127}
128
129/* return the number of columns of string 's' in current locale */
130int gettext_width(const char *s)131{
132static int is_utf8 = -1;133if (is_utf8 == -1)134is_utf8 = is_utf8_locale();135
136return is_utf8 ? utf8_strwidth(s) : strlen(s);137}
138#endif139
140int is_utf8_locale(void)141{
142#ifdef NO_GETTEXT143if (!charset) {144const char *env = getenv("LC_ALL");145if (!env || !*env)146env = getenv("LC_CTYPE");147if (!env || !*env)148env = getenv("LANG");149if (!env)150env = "";151if (strchr(env, '.'))152env = strchr(env, '.') + 1;153charset = xstrdup(env);154}155#endif156return is_encoding_utf8(charset);157}
158