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 <boost/assert.hpp>
21 #include <boost/current_function.hpp>
31 using lyx::from_ascii;
33 void cleanTranslation(docstring & trans)
36 Some english words have different translations, depending on
37 context. In these cases the original string is augmented by
38 context information (e.g. "To:[[as in 'From page x to page
39 y']]" and "To:[[as in 'From format x to format y']]". This
40 means that we need to filter out everything in double square
41 brackets at the end of the string, otherwise the user sees
42 bogus messages. If we are unable to honour the request we
43 just return what we got in.
45 size_t const pos1 = trans.find(from_ascii("[["));
46 if (pos1 != docstring::npos) {
47 size_t const pos2 = trans.find(from_ascii("]]"), pos1);
48 if (pos2 != docstring::npos)
49 trans.erase(pos1, pos2 - pos1 + 2);
63 # include <libintl.h> // use the header already in the system *EK*
65 # include "../../intl/libintl.h"
70 using support::package;
71 using support::getEnv;
72 using support::setEnv;
75 // This version use the traditional gettext.
76 Messages::Messages(string const & l)
77 : lang_(l), warned_(false)
79 // strip off any encoding suffix, i.e., assume 8-bit po files
80 string::size_type i = lang_.find(".");
81 lang_ = lang_.substr(0, i);
82 LYXERR(Debug::DEBUG, BOOST_CURRENT_FUNCTION
83 << ": language(" << lang_ << ")");
90 string const locale_dir = package().locale_dir().toFilesystemEncoding();
91 char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
94 LYXERR(Debug::DEBUG, BOOST_CURRENT_FUNCTION << '\n'
95 << "Error code: " << errno << '\n'
96 << "Directory : " << package().locale_dir().absFilename() << '\n'
97 << "Rtn value : " << c);
100 if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
101 LYXERR(Debug::DEBUG, BOOST_CURRENT_FUNCTION << '\n'
102 << "Error code: " << errno << '\n'
103 << "Codeset : " << ucs4_codeset << '\n');
110 docstring const Messages::get(string const & m) const
115 // Look for the translated string in the cache.
116 TranslationCache::iterator it = cache_.find(m);
117 if (it != cache_.end())
120 // The string was not found, use gettext to generate it
122 string const oldLANGUAGE = getEnv("LANGUAGE");
123 string const oldLC_ALL = getEnv("LC_ALL");
124 if (!lang_.empty()) {
125 // This GNU extension overrides any language locale
127 setEnv("LANGUAGE", lang_);
128 // However, setting LANGUAGE does nothing when the
129 // locale is "C". Therefore we set the locale to
130 // something that is believed to exist on most
131 // systems. The idea is that one should be able to
132 // load German documents even without having de_DE
134 setEnv("LC_ALL", "en_US");
135 #ifdef HAVE_LC_MESSAGES
136 setlocale(LC_MESSAGES, "");
140 char const * m_c = m.c_str();
141 char const * trans_c = gettext(m_c);
144 LYXERR0("Undefined result from gettext");
145 else if (trans_c == m_c) {
146 LYXERR(Debug::DEBUG, "Same as entered returned");
147 trans = from_ascii(m);
149 LYXERR(Debug::DEBUG, "We got a translation");
150 // m is actually not a char const * but ucs4 data
151 trans = reinterpret_cast<char_type const *>(trans_c);
154 cleanTranslation(trans);
156 // Reset environment variables as they were.
157 if (!lang_.empty()) {
158 // Reset everything as it was.
159 setEnv("LANGUAGE", oldLANGUAGE);
160 setEnv("LC_ALL", oldLC_ALL);
161 #ifdef HAVE_LC_MESSAGES
162 setlocale(LC_MESSAGES, "");
166 std::pair<TranslationCache::iterator, bool> result =
167 cache_.insert(std::make_pair(m, trans));
169 BOOST_ASSERT(result.second);
171 return result.first->second;
177 // This is the dummy variant.
181 Messages::Messages(string const & l) {}
183 void Messages::init()
188 docstring const Messages::get(string const & m) const
190 docstring trans = from_ascii(m);
191 cleanTranslation(trans);
205 // This version of the Pimpl utilizes the message capability of
206 // libstdc++ that is distributed with GNU G++.
207 class Messages::Pimpl {
209 typedef std::messages<char>::catalog catalog;
211 Pimpl(string const & l)
213 loc_gl(lang_.c_str()),
214 mssg_gl(std::use_facet<std::messages<char> >(loc_gl))
216 //LYXERR("Messages: language(" << l << ") in dir(" << dir << ")");
218 string const locale_dir = package().locale_dir().toFilesystemEncoding();
219 cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
225 mssg_gl.close(cat_gl);
228 docstring const get(string const & msg) const
230 return mssg_gl.get(cat_gl, 0, 0, msg);
238 std::messages<char> const & mssg_gl;