1 /* Message list charset and locale charset handling.
2    Copyright (C) 2001-2003, 2005-2006 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 2, or (at your option)
8    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, write to the Free Software Foundation,
17    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
18 
19 
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23 #include <alloca.h>
24 
25 /* Specification.  */
26 #include "msgl-charset.h"
27 
28 #include <stddef.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.h"
36 #include "xallocsa.h"
37 #include "xerror.h"
38 #include "xvasprintf.h"
39 #include "message.h"
40 #include "c-strstr.h"
41 #include "exit.h"
42 #include "gettext.h"
43 
44 #define _(str) gettext (str)
45 
46 void
compare_po_locale_charsets(const msgdomain_list_ty * mdlp)47 compare_po_locale_charsets (const msgdomain_list_ty *mdlp)
48 {
49   const char *locale_code;
50   const char *canon_locale_code;
51   bool warned;
52   size_t j, k;
53 
54   /* Check whether the locale encoding and the PO file's encoding are the
55      same.  Otherwise emit a warning.  */
56   locale_code = locale_charset ();
57   canon_locale_code = po_charset_canonicalize (locale_code);
58   warned = false;
59   for (k = 0; k < mdlp->nitems; k++)
60     {
61       const message_list_ty *mlp = mdlp->item[k]->messages;
62 
63       for (j = 0; j < mlp->nitems; j++)
64 	if (mlp->item[j]->msgstr == NULL
65 	    && mlp->item[j]->msgid[0] == '\0' && !mlp->item[j]->obsolete)
66 	  {
67 	    const char *header = mlp->item[j]->msgstr;
68 
69 	    if (header != NULL)
70 	      {
71 		const char *charsetstr = c_strstr (header, "charset=");
72 
73 		if (charsetstr != NULL)
74 		  {
75 		    size_t len;
76 		    char *charset;
77 		    const char *canon_charset;
78 
79 		    charsetstr += strlen ("charset=");
80 		    len = strcspn (charsetstr, " \t\n");
81 		    charset = (char *) xallocsa (len + 1);
82 		    memcpy (charset, charsetstr, len);
83 		    charset[len] = '\0';
84 
85 		    canon_charset = po_charset_canonicalize (charset);
86 		    if (canon_charset == NULL)
87 		      error (EXIT_FAILURE, 0,
88 			     _("\
89 present charset \"%s\" is not a portable encoding name"),
90 			     charset);
91 		    freesa (charset);
92 		    if (canon_locale_code != canon_charset)
93 		      {
94 			multiline_warning (xasprintf (_("warning: ")),
95 					   xasprintf (_("\
96 Locale charset \"%s\" is different from\n\
97 input file charset \"%s\".\n\
98 Output of '%s' might be incorrect.\n\
99 Possible workarounds are:\n\
100 "), locale_code, canon_charset, basename (program_name)));
101 			multiline_warning (NULL,
102 					   xasprintf (_("\
103 - Set LC_ALL to a locale with encoding %s.\n\
104 "), canon_charset));
105 			if (canon_locale_code != NULL)
106 			  multiline_warning (NULL,
107 					     xasprintf (_("\
108 - Convert the translation catalog to %s using 'msgconv',\n\
109   then apply '%s',\n\
110   then convert back to %s using 'msgconv'.\n\
111 "), canon_locale_code, basename (program_name), canon_charset));
112 			if (strcmp (canon_charset, "UTF-8") != 0
113 			    && (canon_locale_code == NULL
114 				|| strcmp (canon_locale_code, "UTF-8") != 0))
115 			  multiline_warning (NULL,
116 					     xasprintf (_("\
117 - Set LC_ALL to a locale with encoding %s,\n\
118   convert the translation catalog to %s using 'msgconv',\n\
119   then apply '%s',\n\
120   then convert back to %s using 'msgconv'.\n\
121 "), "UTF-8", "UTF-8", basename (program_name), canon_charset));
122 			warned = true;
123 		      }
124 		  }
125 	      }
126 	  }
127       }
128   if (canon_locale_code == NULL && !warned)
129     multiline_warning (xasprintf (_("warning: ")),
130 		       xasprintf (_("\
131 Locale charset \"%s\" is not a portable encoding name.\n\
132 Output of '%s' might be incorrect.\n\
133 A possible workaround is to set LC_ALL=C.\n\
134 "), locale_code, basename (program_name)));
135 }
136