• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • kdecore
  • localization
kcatalog.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  Copyright (c) 2001 Hans Petter Bieker <bieker@kde.org>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include "kcatalog_p.h"
21 #include "kstandarddirs.h"
22 
23 #include <config.h>
24 
25 #include <QtCore/QFile>
26 #include <QMutexLocker>
27 
28 #include <kdebug.h>
29 
30 #include <stdlib.h>
31 #include <locale.h>
32 #include "gettext.h"
33 
34 
35 static bool s_localeSet = false;
36 
37 // Initialize the locale very early during application startup
38 // This is necessary for e.g. toLocal8Bit() to work, even before
39 // a Q[Core]Application exists (David)
40 int kInitializeLocale()
41 {
42 #ifndef _WIN32_WCE
43  setlocale(LC_ALL, "");
44 #endif
45  extern Q_CORE_EXPORT bool qt_locale_initialized; // in Qt since 4.5.0
46  qt_locale_initialized = true; // as recommended by Thiago
47  s_localeSet = true;
48  return 1;
49 }
50 Q_CONSTRUCTOR_FUNCTION(kInitializeLocale)
51 
52 // not defined on win32 :(
53 #ifdef _WIN32
54 # ifndef LC_MESSAGES
55 # define LC_MESSAGES 42
56 # endif
57 #endif
58 
59 static char *langenv = 0;
60 static const int langenvMaxlen = 42;
61 // = "LANGUAGE=" + 32 chars for language code + terminating zero
62 
63 class KCatalogStaticData
64 {
65 public:
66  KCatalogStaticData() {}
67 
68  QMutex mutex;
69 };
70 
71 K_GLOBAL_STATIC(KCatalogStaticData, catalogStaticData)
72 
73 class KCatalogPrivate
74 {
75 public:
76  KCatalogPrivate()
77  : bindDone(false)
78  {}
79 
80  QByteArray language;
81  QByteArray name;
82  QByteArray localeDir;
83 
84  QByteArray systemLanguage;
85  bool bindDone;
86 
87  static QByteArray currentLanguage;
88 
89  void setupGettextEnv ();
90  void resetSystemLanguage ();
91 };
92 
93 QDebug operator<<(QDebug debug, const KCatalog &c)
94 {
95  return debug << c.d->language << " " << c.d->name << " " << c.d->localeDir;
96 }
97 
98 QByteArray KCatalogPrivate::currentLanguage;
99 
100 KCatalog::KCatalog(const QString & name, const QString & language )
101  : d( new KCatalogPrivate )
102 {
103  // Set locales if the static initializer didn't work
104  if (!s_localeSet) {
105  kInitializeLocale();
106  }
107 
108  // Find locale directory for this catalog.
109  QString localeDir = catalogLocaleDir( name, language );
110 
111  d->language = QFile::encodeName( language );
112  d->name = QFile::encodeName( name );
113  d->localeDir = QFile::encodeName( localeDir );
114 
115  // Always get translations in UTF-8, regardless of user's environment.
116  bind_textdomain_codeset( d->name, "UTF-8" );
117 
118  // Invalidate current language, to trigger binding at next translate call.
119  KCatalogPrivate::currentLanguage.clear();
120 
121  if (!langenv) {
122  // Call putenv only here, to initialize LANGUAGE variable.
123  // Later only change langenv to what is currently needed.
124  langenv = new char[langenvMaxlen];
125  QByteArray lang = qgetenv("LANGUAGE");
126  snprintf(langenv, langenvMaxlen, "LANGUAGE=%s", lang.constData());
127  putenv(langenv);
128  }
129 }
130 
131 KCatalog::KCatalog(const KCatalog & rhs)
132  : d( new KCatalogPrivate )
133 {
134  *this = rhs;
135 }
136 
137 KCatalog & KCatalog::operator=(const KCatalog & rhs)
138 {
139  *d = *rhs.d;
140 
141  return *this;
142 }
143 
144 KCatalog::~KCatalog()
145 {
146  delete d;
147 }
148 
149 QString KCatalog::catalogLocaleDir( const QString &name,
150  const QString &language )
151 {
152  QString relpath = QString::fromLatin1( "%1/LC_MESSAGES/%2.mo" )
153  .arg( language ).arg( name );
154  return KGlobal::dirs()->findResourceDir( "locale", relpath );
155 }
156 
157 QString KCatalog::name() const
158 {
159  return QFile::decodeName(d->name);
160 }
161 
162 QString KCatalog::language() const
163 {
164  return QFile::decodeName(d->language);
165 }
166 
167 QString KCatalog::localeDir() const
168 {
169  return QFile::decodeName(d->localeDir);
170 }
171 
172 #ifdef Q_WS_WIN
173  extern "C" int __declspec(dllimport) _nl_msg_cat_cntr;
174 #endif
175 
176 void KCatalogPrivate::setupGettextEnv ()
177 {
178  // Point Gettext to current language, recording system value for recovery.
179  systemLanguage = qgetenv("LANGUAGE");
180  if (systemLanguage != language) {
181  // putenv has been called in the constructor,
182  // it is enough to change the string set there.
183  snprintf(langenv, langenvMaxlen, "LANGUAGE=%s", language.constData());
184  }
185 
186  // Rebind text domain if language actually changed from the last time,
187  // as locale directories may differ for different languages of same catalog.
188  if (language != currentLanguage || !bindDone) {
189 
190  currentLanguage = language;
191  bindDone = true;
192 
193  //kDebug() << "bindtextdomain" << name << localeDir;
194  bindtextdomain(name, localeDir);
195 
196  // Magic to make sure Gettext doesn't use stale cached translation
197  // from previous language.
198 #ifndef _MSC_VER
199  extern int _nl_msg_cat_cntr;
200 #endif
201  ++_nl_msg_cat_cntr;
202  }
203 }
204 
205 void KCatalogPrivate::resetSystemLanguage ()
206 {
207  if (language != systemLanguage) {
208  snprintf(langenv, langenvMaxlen, "LANGUAGE=%s", systemLanguage.constData());
209  }
210 }
211 
212 QString KCatalog::translate(const char * msgid) const
213 {
214  QMutexLocker locker(&catalogStaticData->mutex);
215  d->setupGettextEnv();
216  const char *msgstr = dgettext(d->name, msgid);
217  d->resetSystemLanguage();
218  return QString::fromUtf8(msgstr);
219 }
220 
221 QString KCatalog::translate(const char * msgctxt, const char * msgid) const
222 {
223  QMutexLocker locker(&catalogStaticData->mutex);
224  d->setupGettextEnv();
225  const char *msgstr = dpgettext_expr(d->name, msgctxt, msgid);
226  d->resetSystemLanguage();
227  return QString::fromUtf8(msgstr);
228 }
229 
230 QString KCatalog::translate(const char * msgid, const char * msgid_plural,
231  unsigned long n) const
232 {
233  QMutexLocker locker(&catalogStaticData->mutex);
234  d->setupGettextEnv();
235  const char *msgstr = dngettext(d->name, msgid, msgid_plural, n);
236  d->resetSystemLanguage();
237  return QString::fromUtf8(msgstr);
238 }
239 
240 QString KCatalog::translate(const char * msgctxt, const char * msgid,
241  const char * msgid_plural, unsigned long n) const
242 {
243  QMutexLocker locker(&catalogStaticData->mutex);
244  d->setupGettextEnv();
245  const char *msgstr = dnpgettext_expr(d->name, msgctxt, msgid, msgid_plural, n);
246  d->resetSystemLanguage();
247  return QString::fromUtf8(msgstr);
248 }
249 
250 QString KCatalog::translateStrict(const char * msgid) const
251 {
252  QMutexLocker locker(&catalogStaticData->mutex);
253  d->setupGettextEnv();
254  const char *msgstr = dgettext(d->name, msgid);
255  d->resetSystemLanguage();
256  return msgstr != msgid ? QString::fromUtf8(msgstr) : QString();
257 }
258 
259 QString KCatalog::translateStrict(const char * msgctxt, const char * msgid) const
260 {
261  QMutexLocker locker(&catalogStaticData->mutex);
262  d->setupGettextEnv();
263  const char *msgstr = dpgettext_expr(d->name, msgctxt, msgid);
264  d->resetSystemLanguage();
265  return msgstr != msgid ? QString::fromUtf8(msgstr) : QString();
266 }
267 
268 QString KCatalog::translateStrict(const char * msgid, const char * msgid_plural,
269  unsigned long n) const
270 {
271  QMutexLocker locker(&catalogStaticData->mutex);
272  d->setupGettextEnv();
273  const char *msgstr = dngettext(d->name, msgid, msgid_plural, n);
274  d->resetSystemLanguage();
275  return msgstr != msgid && msgstr != msgid_plural ? QString::fromUtf8(msgstr) : QString();
276 }
277 
278 QString KCatalog::translateStrict(const char * msgctxt, const char * msgid,
279  const char * msgid_plural, unsigned long n) const
280 {
281  QMutexLocker locker(&catalogStaticData->mutex);
282  d->setupGettextEnv();
283  const char *msgstr = dnpgettext_expr(d->name, msgctxt, msgid, msgid_plural, n);
284  d->resetSystemLanguage();
285  return msgstr != msgid && msgstr != msgid_plural ? QString::fromUtf8(msgstr) : QString();
286 }
287 
s_localeSet
static bool s_localeSet
Definition: kcatalog.cpp:35
QMutex
QByteArray::clear
void clear()
kdebug.h
dnpgettext_expr
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N)
Definition: gettext.h:221
QByteArray
KCatalog::catalogLocaleDir
static QString catalogLocaleDir(const QString &name, const QString &language)
Finds the locale directory for the given catalog in given language.
Definition: kcatalog.cpp:149
KCatalog::translateStrict
QString translateStrict(const char *msgid) const
Retrieves a translation of the specified message id, returning empty if the translation was not found...
Definition: kcatalog.cpp:250
K_GLOBAL_STATIC
#define K_GLOBAL_STATIC(TYPE, NAME)
This macro makes it easy to use non-POD types as global statics.
Definition: kglobal.h:221
KGlobal::dirs
KStandardDirs * dirs()
Returns the application standard dirs object.
KCatalog::operator=
KCatalog & operator=(const KCatalog &rhs)
Assignment operator.
Definition: kcatalog.cpp:137
bindtextdomain
#define bindtextdomain(Domainname, Dirname)
Definition: gettext.h:77
bind_textdomain_codeset
#define bind_textdomain_codeset(Domainname, Codeset)
Definition: gettext.h:78
KCatalog::KCatalog
KCatalog(const QString &name, const QString &language)
Constructor.
Definition: kcatalog.cpp:100
__declspec
int __declspec(dllimport) _nl_msg_cat_cntr
QString::fromUtf8
QString fromUtf8(const char *str, int size)
dgettext
#define dgettext(Domainname, Msgid)
Definition: gettext.h:68
KCatalog::~KCatalog
virtual ~KCatalog()
Destructor.
Definition: kcatalog.cpp:144
KCatalog::translate
QString translate(const char *msgid) const
Retrieves a translation of the specified message id.
Definition: kcatalog.cpp:212
QByteArray::constData
const char * constData() const
QString
KCatalog::language
QString language() const
Returns the language of the catalog.
Definition: kcatalog.cpp:162
KStandardDirs::findResourceDir
QString findResourceDir(const char *type, const QString &filename) const
Tries to find the directory the file is in.
Definition: kstandarddirs.cpp:553
KCatalog::localeDir
QString localeDir() const
Returns locale directory of the catalog.
Definition: kcatalog.cpp:167
kcatalog_p.h
QDebug
langenvMaxlen
static const int langenvMaxlen
Definition: kcatalog.cpp:60
dpgettext_expr
#define dpgettext_expr(Domainname, Msgctxt, Msgid)
Definition: gettext.h:176
QMutexLocker
KCatalog::name
QString name() const
Returns the name of the catalog.
Definition: kcatalog.cpp:157
kstandarddirs.h
langenv
static char * langenv
Definition: kcatalog.cpp:59
operator<<
QDebug operator<<(QDebug debug, const KCatalog &c)
Definition: kcatalog.cpp:93
KCatalog
This class abstracts a gettext message catalog.
Definition: kcatalog_p.h:35
QString::fromLatin1
QString fromLatin1(const char *str, int size)
gettext.h
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
kInitializeLocale
int kInitializeLocale()
Definition: kcatalog.cpp:40
QFile::encodeName
QByteArray encodeName(const QString &fileName)
QFile::decodeName
QString decodeName(const QByteArray &localFileName)
dngettext
#define dngettext(Domainname, Msgid1, Msgid2, N)
Definition: gettext.h:72
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:10 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal