• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Message list charset and locale charset handling.
2    Copyright (C) 2001-2003, 2005-2007, 2009, 2019-2020 Free Software Foundation, Inc.
3    Written by Bruno Haible <haible@clisp.cons.org>, 2001.
4 
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
17 
18 
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22 #include <alloca.h>
23 
24 /* Specification.  */
25 #include "msgl-charset.h"
26 
27 #include <stddef.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "po-charset.h"
32 #include "localcharset.h"
33 #include "error.h"
34 #include "progname.h"
35 #include "basename-lgpl.h"
36 #include "xmalloca.h"
37 #include "xerror.h"
38 #include "xvasprintf.h"
39 #include "message.h"
40 #include "c-strstr.h"
41 #include "gettext.h"
42 
43 #define _(str) gettext (str)
44 
45 void
compare_po_locale_charsets(const msgdomain_list_ty * mdlp)46 compare_po_locale_charsets (const msgdomain_list_ty *mdlp)
47 {
48   const char *locale_code;
49   const char *canon_locale_code;
50   bool warned;
51   size_t j, k;
52 
53   /* Check whether the locale encoding and the PO file's encoding are the
54      same.  Otherwise emit a warning.  */
55   locale_code = locale_charset ();
56   canon_locale_code = po_charset_canonicalize (locale_code);
57   warned = false;
58   for (k = 0; k < mdlp->nitems; k++)
59     {
60       const message_list_ty *mlp = mdlp->item[k]->messages;
61 
62       for (j = 0; j < mlp->nitems; j++)
63         if (is_header (mlp->item[j]) && !mlp->item[j]->obsolete)
64           {
65             const char *header = mlp->item[j]->msgstr;
66 
67             if (header != NULL)
68               {
69                 const char *charsetstr = c_strstr (header, "charset=");
70 
71                 if (charsetstr != NULL)
72                   {
73                     size_t len;
74                     char *charset;
75                     const char *canon_charset;
76 
77                     charsetstr += strlen ("charset=");
78                     len = strcspn (charsetstr, " \t\n");
79                     charset = (char *) xmalloca (len + 1);
80                     memcpy (charset, charsetstr, len);
81                     charset[len] = '\0';
82 
83                     canon_charset = po_charset_canonicalize (charset);
84                     if (canon_charset == NULL)
85                       error (EXIT_FAILURE, 0,
86                              _("present charset \"%s\" is not a portable encoding name"),
87                              charset);
88                     freea (charset);
89                     if (canon_locale_code != canon_charset)
90                       {
91                         multiline_warning (xasprintf (_("warning: ")),
92                                            xasprintf (_("\
93 Locale charset \"%s\" is different from\n\
94 input file charset \"%s\".\n\
95 Output of '%s' might be incorrect.\n\
96 Possible workarounds are:\n\
97 "), locale_code, canon_charset, last_component (program_name)));
98                         multiline_warning (NULL,
99                                            xasprintf (_("\
100 - Set LC_ALL to a locale with encoding %s.\n\
101 "), canon_charset));
102                         if (canon_locale_code != NULL)
103                           multiline_warning (NULL,
104                                              xasprintf (_("\
105 - Convert the translation catalog to %s using 'msgconv',\n\
106   then apply '%s',\n\
107   then convert back to %s using 'msgconv'.\n\
108 "), canon_locale_code, last_component (program_name), canon_charset));
109                         if (strcmp (canon_charset, "UTF-8") != 0
110                             && (canon_locale_code == NULL
111                                 || strcmp (canon_locale_code, "UTF-8") != 0))
112                           multiline_warning (NULL,
113                                              xasprintf (_("\
114 - Set LC_ALL to a locale with encoding %s,\n\
115   convert the translation catalog to %s using 'msgconv',\n\
116   then apply '%s',\n\
117   then convert back to %s using 'msgconv'.\n\
118 "), "UTF-8", "UTF-8", last_component (program_name), canon_charset));
119                         warned = true;
120                       }
121                   }
122               }
123           }
124       }
125   if (canon_locale_code == NULL && !warned)
126     multiline_warning (xasprintf (_("warning: ")),
127                        xasprintf (_("\
128 Locale charset \"%s\" is not a portable encoding name.\n\
129 Output of '%s' might be incorrect.\n\
130 A possible workaround is to set LC_ALL=C.\n\
131 "), locale_code, last_component (program_name)));
132 }
133