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 "support/lassert.h"
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"
66 using namespace lyx::support;
70 // This version use the traditional gettext.
71 Messages::Messages(string const & l)
72 : lang_(l), warned_(false)
74 // strip off any encoding suffix, i.e., assume 8-bit po files
75 size_t i = lang_.find(".");
76 lang_ = lang_.substr(0, i);
77 LYXERR(Debug::LOCALE, "language(" << lang_ << ")");
84 string const locale_dir = package().locale_dir().toFilesystemEncoding();
85 char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
88 LYXERR(Debug::LOCALE, "Error code: " << errno << '\n'
89 << "Directory : " << package().locale_dir().absFilename() << '\n'
90 << "Rtn value : " << c);
93 if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
94 LYXERR(Debug::LOCALE, "Error code: " << errno << '\n'
95 << "Codeset : " << ucs4_codeset);
102 docstring const Messages::get(string const & m) const
107 // Look for the translated string in the cache.
108 TranslationCache::iterator it = cache_.find(m);
109 if (it != cache_.end())
112 // The string was not found, use gettext to generate it
114 static string oldLANGUAGE;
115 static string oldLC_ALL;
116 if (!lang_.empty()) {
117 oldLANGUAGE = getEnv("LANGUAGE");
118 oldLC_ALL = getEnv("LC_ALL");
119 // This GNU extension overrides any language locale
121 LYXERR(Debug::LOCALE, "Setting LANGUAGE to " << lang_);
122 if (!setEnv("LANGUAGE", lang_))
123 LYXERR(Debug::LOCALE, "\t... failed!");
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 LYXERR(Debug::LOCALE, "Setting LC_ALL to en_US");
131 if (!setEnv("LC_ALL", "en_US"))
132 LYXERR(Debug::LOCALE, "\t... failed!");
133 #ifdef HAVE_LC_MESSAGES
134 setlocale(LC_MESSAGES, "");
138 char const * m_c = m.c_str();
139 char const * trans_c = gettext(m_c);
142 LYXERR(Debug::LOCALE, "Undefined result from gettext");
143 else if (trans_c == m_c) {
144 LYXERR(Debug::LOCALE, "Same as entered returned");
145 trans = from_ascii(m);
147 //LYXERR(Debug::LOCALE, "We got a translation");
148 // m is actually not a char const * but ucs4 data
149 trans = reinterpret_cast<char_type const *>(trans_c);
152 cleanTranslation(trans);
154 // Reset environment variables as they were.
155 if (!lang_.empty()) {
156 // Reset everything as it was.
157 LYXERR(Debug::LOCALE, "restoring LANGUAGE from " << getEnv("LANGUAGE")
158 << " to " << oldLANGUAGE);
159 if (!setEnv("LANGUAGE", oldLANGUAGE))
160 LYXERR(Debug::LOCALE, "\t... failed!");
161 LYXERR(Debug::LOCALE, "restoring LC_ALL from " << getEnv("LC_ALL")
162 << " to " << oldLC_ALL);
163 if (!setEnv("LC_ALL", oldLC_ALL))
164 LYXERR(Debug::LOCALE, "\t... failed!");
165 #ifdef HAVE_LC_MESSAGES
166 setlocale(LC_MESSAGES, "");
170 pair<TranslationCache::iterator, bool> result =
171 cache_.insert(make_pair(m, trans));
173 LASSERT(result.second, /**/);
175 return result.first->second;
181 // This is the dummy variant.
185 Messages::Messages(string const & l) {}
187 void Messages::init()
192 docstring const Messages::get(string const & m) const
194 docstring trans = from_ascii(m);
195 cleanTranslation(trans);
209 // This version of the Pimpl utilizes the message capability of
210 // libstdc++ that is distributed with GNU G++.
211 class Messages::Pimpl {
213 typedef messages<char>::catalog catalog;
215 Pimpl(string const & l)
217 loc_gl(lang_.c_str()),
218 mssg_gl(use_facet<messages<char> >(loc_gl))
220 //LYXERR("Messages: language(" << l << ") in dir(" << dir << ")");
222 string const locale_dir = package().locale_dir().toFilesystemEncoding();
223 cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
229 mssg_gl.close(cat_gl);
232 docstring const get(string const & msg) const
234 return mssg_gl.get(cat_gl, 0, 0, msg);
242 messages<char> const & mssg_gl;