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>
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"
68 using support::package;
69 using support::getEnv;
70 using support::setEnv;
73 // This version use the traditional gettext.
74 Messages::Messages(string const & l)
75 : lang_(l), warned_(false)
77 // strip off any encoding suffix, i.e., assume 8-bit po files
78 size_t i = lang_.find(".");
79 lang_ = lang_.substr(0, i);
80 LYXERR(Debug::DEBUG, "language(" << lang_ << ")");
87 string const locale_dir = package().locale_dir().toFilesystemEncoding();
88 char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
91 LYXERR(Debug::DEBUG, "Error code: " << errno << '\n'
92 << "Directory : " << package().locale_dir().absFilename() << '\n'
93 << "Rtn value : " << c);
96 if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
97 LYXERR(Debug::DEBUG, "Error code: " << errno << '\n'
98 << "Codeset : " << ucs4_codeset);
105 docstring const Messages::get(string const & m) const
110 // Look for the translated string in the cache.
111 TranslationCache::iterator it = cache_.find(m);
112 if (it != cache_.end())
115 // The string was not found, use gettext to generate it
117 string const oldLANGUAGE = getEnv("LANGUAGE");
118 string const oldLC_ALL = getEnv("LC_ALL");
119 if (!lang_.empty()) {
120 // This GNU extension overrides any language locale
122 setEnv("LANGUAGE", lang_);
123 // However, setting LANGUAGE does nothing when the
124 // locale is "C". Therefore we set the locale to
125 // something that is believed to exist on most
126 // systems. The idea is that one should be able to
127 // load German documents even without having de_DE
129 setEnv("LC_ALL", "en_US");
130 #ifdef HAVE_LC_MESSAGES
131 setlocale(LC_MESSAGES, "");
135 char const * m_c = m.c_str();
136 char const * trans_c = gettext(m_c);
139 LYXERR0("Undefined result from gettext");
140 else if (trans_c == m_c) {
141 LYXERR(Debug::DEBUG, "Same as entered returned");
142 trans = from_ascii(m);
144 LYXERR(Debug::DEBUG, "We got a translation");
145 // m is actually not a char const * but ucs4 data
146 trans = reinterpret_cast<char_type const *>(trans_c);
149 cleanTranslation(trans);
151 // Reset environment variables as they were.
152 if (!lang_.empty()) {
153 // Reset everything as it was.
154 setEnv("LANGUAGE", oldLANGUAGE);
155 setEnv("LC_ALL", oldLC_ALL);
156 #ifdef HAVE_LC_MESSAGES
157 setlocale(LC_MESSAGES, "");
161 std::pair<TranslationCache::iterator, bool> result =
162 cache_.insert(std::make_pair(m, trans));
164 BOOST_ASSERT(result.second);
166 return result.first->second;
172 // This is the dummy variant.
176 Messages::Messages(string const & l) {}
178 void Messages::init()
183 docstring const Messages::get(string const & m) const
185 docstring trans = from_ascii(m);
186 cleanTranslation(trans);
200 // This version of the Pimpl utilizes the message capability of
201 // libstdc++ that is distributed with GNU G++.
202 class Messages::Pimpl {
204 typedef std::messages<char>::catalog catalog;
206 Pimpl(string const & l)
208 loc_gl(lang_.c_str()),
209 mssg_gl(std::use_facet<std::messages<char> >(loc_gl))
211 //LYXERR("Messages: language(" << l << ") in dir(" << dir << ")");
213 string const locale_dir = package().locale_dir().toFilesystemEncoding();
214 cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
220 mssg_gl.close(cat_gl);
223 docstring const get(string const & msg) const
225 return mssg_gl.get(cat_gl, 0, 0, msg);
233 std::messages<char> const & mssg_gl;