]> git.lyx.org Git - lyx.git/blob - src/support/Messages.cpp
header cleanup
[lyx.git] / src / support / Messages.cpp
1 /* \file Messages.cpp
2  * This file is part of LyX, the document processor.
3  * Licence details can be found in the file COPYING.
4  *
5  * \author Lars Gullik Bjønnes
6  *
7  * Full author contact details are available in file CREDITS.
8  */
9
10 #include <config.h>
11
12 #include "support/Messages.h"
13
14 #include "support/debug.h"
15 #include "support/docstring.h"
16 #include "support/environment.h"
17 #include "support/Package.h"
18
19 #include <boost/assert.hpp>
20
21 #include <cerrno>
22
23 using namespace std;
24
25 namespace {
26
27 using lyx::docstring;
28 using lyx::from_ascii;
29
30 void cleanTranslation(docstring & trans) 
31 {
32         /*
33           Some english words have different translations, depending on
34           context. In these cases the original string is augmented by
35           context information (e.g. "To:[[as in 'From page x to page
36           y']]" and "To:[[as in 'From format x to format y']]". This
37           means that we need to filter out everything in double square
38           brackets at the end of the string, otherwise the user sees
39           bogus messages. If we are unable to honour the request we
40           just return what we got in.
41         */
42         size_t const pos1 = trans.find(from_ascii("[["));
43         if (pos1 != docstring::npos) {
44                 size_t const pos2 = trans.find(from_ascii("]]"), pos1);
45                 if (pos2 != docstring::npos) 
46                         trans.erase(pos1, pos2 - pos1 + 2);
47         }
48 }
49
50 }
51
52
53 #ifdef ENABLE_NLS
54
55 #  ifdef HAVE_LOCALE_H
56 #    include <locale.h>
57 #  endif
58
59 #  if HAVE_GETTEXT
60 #    include <libintl.h>      // use the header already in the system *EK*
61 #  else
62 #    include "../intl/libintl.h"
63 #  endif
64
65 using namespace lyx::support;
66
67 namespace lyx {
68
69 // This version use the traditional gettext.
70 Messages::Messages(string const & l)
71         : lang_(l), warned_(false)
72 {
73         // strip off any encoding suffix, i.e., assume 8-bit po files
74         size_t i = lang_.find(".");
75         lang_ = lang_.substr(0, i);
76         LYXERR(Debug::DEBUG, "language(" << lang_ << ")");
77 }
78
79
80 void Messages::init()
81 {
82         errno = 0;
83         string const locale_dir = package().locale_dir().toFilesystemEncoding();
84         char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
85         int e = errno;
86         if (e) {
87                 LYXERR(Debug::DEBUG, "Error code: " << errno << '\n'
88                         << "Directory : " << package().locale_dir().absFilename() << '\n'
89                         << "Rtn value : " << c);
90         }
91
92         if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
93                 LYXERR(Debug::DEBUG, "Error code: " << errno << '\n'
94                         << "Codeset   : " << ucs4_codeset);
95         }
96
97         textdomain(PACKAGE);
98 }
99
100
101 docstring const Messages::get(string const & m) const
102 {
103         if (m.empty())
104                 return docstring();
105
106         // Look for the translated string in the cache.
107         TranslationCache::iterator it = cache_.find(m);
108         if (it != cache_.end())
109                 return it->second;
110
111         // The string was not found, use gettext to generate it
112
113         string const oldLANGUAGE = getEnv("LANGUAGE");
114         string const oldLC_ALL = getEnv("LC_ALL");
115         if (!lang_.empty()) {
116                 // This GNU extension overrides any language locale
117                 // wrt gettext.
118                 setEnv("LANGUAGE", lang_);
119                 // However, setting LANGUAGE does nothing when the
120                 // locale is "C". Therefore we set the locale to
121                 // something that is believed to exist on most
122                 // systems. The idea is that one should be able to
123                 // load German documents even without having de_DE
124                 // installed.
125                 setEnv("LC_ALL", "en_US");
126 #ifdef HAVE_LC_MESSAGES
127                 setlocale(LC_MESSAGES, "");
128 #endif
129         }
130
131         char const * m_c = m.c_str();
132         char const * trans_c = gettext(m_c);
133         docstring trans;
134         if (!trans_c)
135                 LYXERR0("Undefined result from gettext");
136         else if (trans_c == m_c) {
137                 LYXERR(Debug::DEBUG, "Same as entered returned");
138                 trans = from_ascii(m);
139         } else {
140                 LYXERR(Debug::DEBUG, "We got a translation");
141                 // m is actually not a char const * but ucs4 data
142                 trans = reinterpret_cast<char_type const *>(trans_c);
143         }
144
145         cleanTranslation(trans);
146
147         // Reset environment variables as they were.
148         if (!lang_.empty()) {
149                 // Reset everything as it was.
150                 setEnv("LANGUAGE", oldLANGUAGE);
151                 setEnv("LC_ALL", oldLC_ALL);
152 #ifdef HAVE_LC_MESSAGES
153                 setlocale(LC_MESSAGES, "");
154 #endif
155         }
156
157         pair<TranslationCache::iterator, bool> result =
158                 cache_.insert(make_pair(m, trans));
159
160         BOOST_ASSERT(result.second);
161
162         return result.first->second;
163 }
164
165 } // namespace lyx
166
167 #else // ENABLE_NLS
168 // This is the dummy variant.
169
170 namespace lyx {
171
172 Messages::Messages(string const & l) {}
173
174 void Messages::init()
175 {
176 }
177
178
179 docstring const Messages::get(string const & m) const
180 {
181         docstring trans = from_ascii(m);
182         cleanTranslation(trans);
183         return trans;
184 }
185
186 } // namespace lyx
187
188 #endif
189
190 #if 0
191
192 -#include <locale>
193
194 namespace lyx {
195
196 // This version of the Pimpl utilizes the message capability of
197 // libstdc++ that is distributed with GNU G++.
198 class Messages::Pimpl {
199 public:
200         typedef messages<char>::catalog catalog;
201
202         Pimpl(string const & l)
203                 : lang_(l),
204                   loc_gl(lang_.c_str()),
205                   mssg_gl(use_facet<messages<char> >(loc_gl))
206         {
207                 //LYXERR("Messages: language(" << l << ") in dir(" << dir << ")");
208
209                 string const locale_dir = package().locale_dir().toFilesystemEncoding();
210                 cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
211
212         }
213
214         ~Pimpl()
215         {
216                 mssg_gl.close(cat_gl);
217         }
218
219         docstring const get(string const & msg) const
220         {
221                 return mssg_gl.get(cat_gl, 0, 0, msg);
222         }
223 private:
224         ///
225         string lang_;
226         ///
227         locale loc_gl;
228         ///
229         messages<char> const & mssg_gl;
230         ///
231         catalog cat_gl;
232 };
233
234 } // namespace lyx
235
236 #endif