Coverage Report

Created: 2025-12-31 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/gettext.c
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
}