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.
16 #include "support/docstring.h"
17 #include "support/environment.h"
18 #include "support/Package.h"
19 #include "support/unicode.h"
21 #include <boost/current_function.hpp>
32 using lyx::from_ascii;
34 void cleanTranslation(docstring & trans)
37 Some english words have different translations, depending on
38 context. In these cases the original string is augmented by
39 context information (e.g. "To:[[as in 'From page x to page
40 y']]" and "To:[[as in 'From format x to format y']]". This
41 means that we need to filter out everything in double square
42 brackets at the end of the string, otherwise the user sees
43 bogus messages. If we are unable to honour the request we
44 just return what we got in.
46 docstring::size_type const pos1 = trans.find(from_ascii("[["));
47 if (pos1 != docstring::npos) {
48 docstring::size_type const pos2
49 = trans.find(from_ascii("]]"), pos1);
50 if (pos2 != docstring::npos)
51 trans.erase(pos1, pos2 - pos1 + 2);
65 # include <libintl.h> // use the header already in the system *EK*
67 # include "../intl/libintl.h"
72 using support::package;
73 using support::getEnv;
74 using support::setEnv;
77 // This version use the traditional gettext.
78 Messages::Messages(string const & l)
79 : lang_(l), warned_(false)
81 // strip off any encoding suffix, i.e., assume 8-bit po files
82 string::size_type i = lang_.find(".");
83 lang_ = lang_.substr(0, i);
84 LYXERR(Debug::DEBUG, BOOST_CURRENT_FUNCTION
85 << ": language(" << lang_ << ")");
92 string const locale_dir = package().locale_dir().toFilesystemEncoding();
93 char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
96 LYXERR(Debug::DEBUG, BOOST_CURRENT_FUNCTION << '\n'
97 << "Error code: " << errno << '\n'
98 << "Directory : " << package().locale_dir().absFilename() << '\n'
99 << "Rtn value : " << c);
102 if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
103 LYXERR(Debug::DEBUG, BOOST_CURRENT_FUNCTION << '\n'
104 << "Error code: " << errno << '\n'
105 << "Codeset : " << ucs4_codeset << '\n');
112 docstring const Messages::get(string const & m) const
117 // Look for the translated string in the cache.
118 TranslationCache::iterator it = cache_.find(m);
119 if (it != cache_.end())
122 // The string was not found, use gettext to generate it
124 string const oldLANGUAGE = getEnv("LANGUAGE");
125 string const oldLC_ALL = getEnv("LC_ALL");
126 if (!lang_.empty()) {
127 // This GNU extension overrides any language locale
129 setEnv("LANGUAGE", lang_);
130 // However, setting LANGUAGE does nothing when the
131 // locale is "C". Therefore we set the locale to
132 // something that is believed to exist on most
133 // systems. The idea is that one should be able to
134 // load German documents even without having de_DE
136 setEnv("LC_ALL", "en_US");
137 #ifdef HAVE_LC_MESSAGES
138 setlocale(LC_MESSAGES, "");
142 char const * m_c = m.c_str();
143 char const * trans_c = gettext(m_c);
146 lyxerr << "Undefined result from gettext" << endl;
147 else if (trans_c == m_c) {
148 LYXERR(Debug::DEBUG, "Same as entered returned");
149 trans = from_ascii(m);
151 LYXERR(Debug::DEBUG, "We got a translation");
152 // m is actually not a char const * but ucs4 data
153 trans = reinterpret_cast<char_type const *>(trans_c);
156 cleanTranslation(trans);
158 // Reset environment variables as they were.
159 if (!lang_.empty()) {
160 // Reset everything as it was.
161 setEnv("LANGUAGE", oldLANGUAGE);
162 setEnv("LC_ALL", oldLC_ALL);
163 #ifdef HAVE_LC_MESSAGES
164 setlocale(LC_MESSAGES, "");
168 std::pair<TranslationCache::iterator, bool> result =
169 cache_.insert(std::make_pair(m, trans));
171 BOOST_ASSERT(result.second);
173 return result.first->second;
179 // This is the dummy variant.
183 Messages::Messages(string const & l) {}
185 void Messages::init()
190 docstring const Messages::get(string const & m) const
192 docstring trans = from_ascii(m);
193 cleanTranslation(trans);
207 // This version of the Pimpl utilizes the message capability of
208 // libstdc++ that is distributed with GNU G++.
209 class Messages::Pimpl {
211 typedef std::messages<char>::catalog catalog;
213 Pimpl(string const & l)
215 loc_gl(lang_.c_str()),
216 mssg_gl(std::use_facet<std::messages<char> >(loc_gl))
218 //lyxerr << "Messages: language(" << l
219 // << ") in dir(" << dir << ")" << endl;
221 string const locale_dir = package().locale_dir().toFilesystemEncoding();
222 cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
228 mssg_gl.close(cat_gl);
231 docstring const get(string const & msg) const
233 return mssg_gl.get(cat_gl, 0, 0, msg);
241 std::messages<char> const & mssg_gl;