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>
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 size_t i = lang_.find(".");
80 lang_ = lang_.substr(0, i);
81 LYXERR(Debug::DEBUG, "language(" << lang_ << ")");
88 string const locale_dir = package().locale_dir().toFilesystemEncoding();
89 char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
92 LYXERR(Debug::DEBUG, "Error code: " << errno << '\n'
93 << "Directory : " << package().locale_dir().absFilename() << '\n'
94 << "Rtn value : " << c);
97 if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
98 LYXERR(Debug::DEBUG, "Error code: " << errno << '\n'
99 << "Codeset : " << ucs4_codeset);
106 docstring const Messages::get(string const & m) const
111 // Look for the translated string in the cache.
112 TranslationCache::iterator it = cache_.find(m);
113 if (it != cache_.end())
116 // The string was not found, use gettext to generate it
118 string const oldLANGUAGE = getEnv("LANGUAGE");
119 string const oldLC_ALL = getEnv("LC_ALL");
120 if (!lang_.empty()) {
121 // This GNU extension overrides any language locale
123 setEnv("LANGUAGE", lang_);
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
130 setEnv("LC_ALL", "en_US");
131 #ifdef HAVE_LC_MESSAGES
132 setlocale(LC_MESSAGES, "");
136 char const * m_c = m.c_str();
137 char const * trans_c = gettext(m_c);
140 LYXERR0("Undefined result from gettext");
141 else if (trans_c == m_c) {
142 LYXERR(Debug::DEBUG, "Same as entered returned");
143 trans = from_ascii(m);
145 LYXERR(Debug::DEBUG, "We got a translation");
146 // m is actually not a char const * but ucs4 data
147 trans = reinterpret_cast<char_type const *>(trans_c);
150 cleanTranslation(trans);
152 // Reset environment variables as they were.
153 if (!lang_.empty()) {
154 // Reset everything as it was.
155 setEnv("LANGUAGE", oldLANGUAGE);
156 setEnv("LC_ALL", oldLC_ALL);
157 #ifdef HAVE_LC_MESSAGES
158 setlocale(LC_MESSAGES, "");
162 std::pair<TranslationCache::iterator, bool> result =
163 cache_.insert(std::make_pair(m, trans));
165 BOOST_ASSERT(result.second);
167 return result.first->second;
173 // This is the dummy variant.
177 Messages::Messages(string const & l) {}
179 void Messages::init()
184 docstring const Messages::get(string const & m) const
186 docstring trans = from_ascii(m);
187 cleanTranslation(trans);
201 // This version of the Pimpl utilizes the message capability of
202 // libstdc++ that is distributed with GNU G++.
203 class Messages::Pimpl {
205 typedef std::messages<char>::catalog catalog;
207 Pimpl(string const & l)
209 loc_gl(lang_.c_str()),
210 mssg_gl(std::use_facet<std::messages<char> >(loc_gl))
212 //LYXERR("Messages: language(" << l << ") in dir(" << dir << ")");
214 string const locale_dir = package().locale_dir().toFilesystemEncoding();
215 cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
221 mssg_gl.close(cat_gl);
224 docstring const get(string const & msg) const
226 return mssg_gl.get(cat_gl, 0, 0, msg);
234 std::messages<char> const & mssg_gl;