2 * This file is part of LyX, the document processor.
3 * Licence details can be found in the file COPYING.
5 * \author Lars Gullik Bjønnes
7 * Full author contact details are available in file CREDITS.
12 #include "support/Messages.h"
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"
20 #include "support/lassert.h"
29 using lyx::from_ascii;
31 void cleanTranslation(docstring & trans)
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.
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);
61 # include <libintl.h> // use the header already in the system *EK*
63 # include "../../intl/libintl.h"
66 using namespace lyx::support;
70 // This version use the traditional gettext.
71 Messages::Messages(string const & l)
72 : lang_(l), warned_(false)
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::DEBUG, "language(" << lang_ << ")");
84 string const locale_dir = package().locale_dir().toFilesystemEncoding();
85 char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
88 LYXERR(Debug::DEBUG, "Error code: " << errno << '\n'
89 << "Directory : " << package().locale_dir().absFilename() << '\n'
90 << "Rtn value : " << c);
93 if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
94 LYXERR(Debug::DEBUG, "Error code: " << errno << '\n'
95 << "Codeset : " << ucs4_codeset);
102 docstring const Messages::get(string const & m) const
107 // Look for the translated string in the cache.
108 TranslationCache::iterator it = cache_.find(m);
109 if (it != cache_.end())
112 // The string was not found, use gettext to generate it
114 static string const oldLANGUAGE = getEnv("LANGUAGE");
115 static string const oldLC_ALL = getEnv("LC_ALL");
116 if (!lang_.empty()) {
117 // This GNU extension overrides any language locale
119 setEnv("LANGUAGE", lang_);
120 // However, setting LANGUAGE does nothing when the
121 // locale is "C". Therefore we set the locale to
122 // something that is believed to exist on most
123 // systems. The idea is that one should be able to
124 // load German documents even without having de_DE
126 setEnv("LC_ALL", "en_US");
127 #ifdef HAVE_LC_MESSAGES
128 setlocale(LC_MESSAGES, "");
132 char const * m_c = m.c_str();
133 char const * trans_c = gettext(m_c);
136 LYXERR0("Undefined result from gettext");
137 else if (trans_c == m_c) {
138 LYXERR(Debug::DEBUG, "Same as entered returned");
139 trans = from_ascii(m);
141 LYXERR(Debug::DEBUG, "We got a translation");
142 // m is actually not a char const * but ucs4 data
143 trans = reinterpret_cast<char_type const *>(trans_c);
146 cleanTranslation(trans);
148 // Reset environment variables as they were.
149 if (!lang_.empty()) {
150 // Reset everything as it was.
151 setEnv("LANGUAGE", oldLANGUAGE);
152 setEnv("LC_ALL", oldLC_ALL);
153 #ifdef HAVE_LC_MESSAGES
154 setlocale(LC_MESSAGES, "");
158 pair<TranslationCache::iterator, bool> result =
159 cache_.insert(make_pair(m, trans));
161 LASSERT(result.second, /**/);
163 return result.first->second;
169 // This is the dummy variant.
173 Messages::Messages(string const & l) {}
175 void Messages::init()
180 docstring const Messages::get(string const & m) const
182 docstring trans = from_ascii(m);
183 cleanTranslation(trans);
197 // This version of the Pimpl utilizes the message capability of
198 // libstdc++ that is distributed with GNU G++.
199 class Messages::Pimpl {
201 typedef messages<char>::catalog catalog;
203 Pimpl(string const & l)
205 loc_gl(lang_.c_str()),
206 mssg_gl(use_facet<messages<char> >(loc_gl))
208 //LYXERR("Messages: language(" << l << ") in dir(" << dir << ")");
210 string const locale_dir = package().locale_dir().toFilesystemEncoding();
211 cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
217 mssg_gl.close(cat_gl);
220 docstring const get(string const & msg) const
222 return mssg_gl.get(cat_gl, 0, 0, msg);
230 messages<char> const & mssg_gl;