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