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/current_function.hpp>
30 using lyx::from_ascii;
32 void cleanTranslation(docstring & trans)
35 Some english words have different translations, depending on
36 context. In these cases the original string is augmented by
37 context information (e.g. "To:[[as in 'From page x to page
38 y']]" and "To:[[as in 'From format x to format y']]". This
39 means that we need to filter out everything in double square
40 brackets at the end of the string, otherwise the user sees
41 bogus messages. If we are unable to honour the request we
42 just return what we got in.
44 size_t const pos1 = trans.find(from_ascii("[["));
45 if (pos1 != docstring::npos) {
46 size_t const pos2 = trans.find(from_ascii("]]"), pos1);
47 if (pos2 != docstring::npos)
48 trans.erase(pos1, pos2 - pos1 + 2);
62 # include <libintl.h> // use the header already in the system *EK*
64 # include "../../intl/libintl.h"
69 using support::package;
70 using support::getEnv;
71 using support::setEnv;
74 // This version use the traditional gettext.
75 Messages::Messages(string const & l)
76 : lang_(l), warned_(false)
78 // strip off any encoding suffix, i.e., assume 8-bit po files
79 string::size_type i = lang_.find(".");
80 lang_ = lang_.substr(0, i);
81 LYXERR(Debug::DEBUG, BOOST_CURRENT_FUNCTION
82 << ": language(" << lang_ << ")");
89 string const locale_dir = package().locale_dir().toFilesystemEncoding();
90 char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
93 LYXERR(Debug::DEBUG, BOOST_CURRENT_FUNCTION << '\n'
94 << "Error code: " << errno << '\n'
95 << "Directory : " << package().locale_dir().absFilename() << '\n'
96 << "Rtn value : " << c);
99 if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
100 LYXERR(Debug::DEBUG, BOOST_CURRENT_FUNCTION << '\n'
101 << "Error code: " << errno << '\n'
102 << "Codeset : " << ucs4_codeset << '\n');
109 docstring const Messages::get(string const & m) const
114 // Look for the translated string in the cache.
115 TranslationCache::iterator it = cache_.find(m);
116 if (it != cache_.end())
119 // The string was not found, use gettext to generate it
121 string const oldLANGUAGE = getEnv("LANGUAGE");
122 string const oldLC_ALL = getEnv("LC_ALL");
123 if (!lang_.empty()) {
124 // This GNU extension overrides any language locale
126 setEnv("LANGUAGE", lang_);
127 // However, setting LANGUAGE does nothing when the
128 // locale is "C". Therefore we set the locale to
129 // something that is believed to exist on most
130 // systems. The idea is that one should be able to
131 // load German documents even without having de_DE
133 setEnv("LC_ALL", "en_US");
134 #ifdef HAVE_LC_MESSAGES
135 setlocale(LC_MESSAGES, "");
139 char const * m_c = m.c_str();
140 char const * trans_c = gettext(m_c);
143 LYXERR0("Undefined result from gettext");
144 else if (trans_c == m_c) {
145 LYXERR(Debug::DEBUG, "Same as entered returned");
146 trans = from_ascii(m);
148 LYXERR(Debug::DEBUG, "We got a translation");
149 // m is actually not a char const * but ucs4 data
150 trans = reinterpret_cast<char_type const *>(trans_c);
153 cleanTranslation(trans);
155 // Reset environment variables as they were.
156 if (!lang_.empty()) {
157 // Reset everything as it was.
158 setEnv("LANGUAGE", oldLANGUAGE);
159 setEnv("LC_ALL", oldLC_ALL);
160 #ifdef HAVE_LC_MESSAGES
161 setlocale(LC_MESSAGES, "");
165 std::pair<TranslationCache::iterator, bool> result =
166 cache_.insert(std::make_pair(m, trans));
168 BOOST_ASSERT(result.second);
170 return result.first->second;
176 // This is the dummy variant.
180 Messages::Messages(string const & l) {}
182 void Messages::init()
187 docstring const Messages::get(string const & m) const
189 docstring trans = from_ascii(m);
190 cleanTranslation(trans);
204 // This version of the Pimpl utilizes the message capability of
205 // libstdc++ that is distributed with GNU G++.
206 class Messages::Pimpl {
208 typedef std::messages<char>::catalog catalog;
210 Pimpl(string const & l)
212 loc_gl(lang_.c_str()),
213 mssg_gl(std::use_facet<std::messages<char> >(loc_gl))
215 //LYXERR("Messages: language(" << l << ") in dir(" << dir << ")");
217 string const locale_dir = package().locale_dir().toFilesystemEncoding();
218 cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
224 mssg_gl.close(cat_gl);
227 docstring const get(string const & msg) const
229 return mssg_gl.get(cat_gl, 0, 0, msg);
237 std::messages<char> const & mssg_gl;