Cppcheck
translationhandler.cpp
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2024 Cppcheck team.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "translationhandler.h"
20 
21 #include "config.h"
22 #include "common.h"
23 
24 #include <QApplication>
25 #include <QCoreApplication>
26 #include <QFile>
27 #include <QFileInfo>
28 #include <QLocale>
29 #include <QMessageBox>
30 #include <QTranslator>
31 #include <QtGlobal>
32 
33 
34 // Provide own translations for standard buttons. This (garbage) code is needed to enforce them to appear in .ts files even after "lupdate gui.pro"
35 UNUSED static void unused()
36 {
37  Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "OK"))
38  Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Cancel"))
39  Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Close"))
40  Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Save"))
41 }
42 
44  QObject(parent),
45  mCurrentLanguage("en")
46 {
47  // Add our available languages
48  // Keep this list sorted
49  addTranslation("Chinese (Simplified)", "cppcheck_zh_CN");
50  addTranslation("Chinese (Traditional)", "cppcheck_zh_TW");
51  addTranslation("Dutch", "cppcheck_nl");
52  addTranslation("English", "cppcheck_en");
53  addTranslation("Finnish", "cppcheck_fi");
54  addTranslation("French", "cppcheck_fr");
55  addTranslation("German", "cppcheck_de");
56  addTranslation("Italian", "cppcheck_it");
57  addTranslation("Japanese", "cppcheck_ja");
58  addTranslation("Korean", "cppcheck_ko");
59  addTranslation("Russian", "cppcheck_ru");
60  addTranslation("Serbian", "cppcheck_sr");
61  addTranslation("Spanish", "cppcheck_es");
62  addTranslation("Swedish", "cppcheck_sv");
63 }
64 
65 bool TranslationHandler::setLanguage(const QString &code)
66 {
67  bool failure = false;
68  QString error;
69 
70  //If English is the language. Code can be e.g. en_US
71  if (code.indexOf("en") == 0) {
72  //Just remove all extra translators
73  if (mTranslator) {
74  qApp->removeTranslator(mTranslator);
75  delete mTranslator;
76  mTranslator = nullptr;
77  }
78 
79  mCurrentLanguage = code;
80  return true;
81  }
82 
83  //Make sure the translator is otherwise valid
84  const int index = getLanguageIndexByCode(code);
85  if (index == -1) {
86  error = QObject::tr("Unknown language specified!");
87  failure = true;
88  } else {
89  // Make sure there is a translator
90  if (!mTranslator)
91  mTranslator = new QTranslator(this);
92 
93  //Load the new language
94  const QString appPath = QFileInfo(QCoreApplication::applicationFilePath()).canonicalPath();
95 
96  QString datadir = getDataDir();
97 
98  QString translationFile;
99  if (QFile::exists(datadir + "/lang/" + mTranslations[index].mFilename + ".qm"))
100  translationFile = datadir + "/lang/" + mTranslations[index].mFilename + ".qm";
101 
102  else if (QFile::exists(datadir + "/" + mTranslations[index].mFilename + ".qm"))
103  translationFile = datadir + "/" + mTranslations[index].mFilename + ".qm";
104 
105  else
106  translationFile = appPath + "/" + mTranslations[index].mFilename + ".qm";
107 
108  if (!mTranslator->load(translationFile)) {
109  failure = true;
110  //If it failed, lets check if the default file exists
111  if (!QFile::exists(translationFile)) {
112  error = QObject::tr("Language file %1 not found!");
113  error = error.arg(translationFile);
114  }
115  else {
116  //If file exists, there's something wrong with it
117  error = QObject::tr("Failed to load translation for language %1 from file %2");
118  error = error.arg(mTranslations[index].mName);
119  error = error.arg(translationFile);
120  }
121  }
122  }
123 
124  if (failure) {
125  const QString msg(tr("Failed to change the user interface language:"
126  "\n\n%1\n\n"
127  "The user interface language has been reset to English. Open "
128  "the Preferences-dialog to select any of the available "
129  "languages.").arg(error));
130  QMessageBox msgBox(QMessageBox::Warning,
131  tr("Cppcheck"),
132  msg,
133  QMessageBox::Ok);
134  msgBox.exec();
135  return false;
136  }
137 
138  qApp->installTranslator(mTranslator);
139 
140  mCurrentLanguage = code;
141 
142  return true;
143 }
144 
146 {
147  return mCurrentLanguage;
148 }
149 
151 {
152  //Get language from system locale's name ie sv_SE or zh_CN
153  QString language = QLocale::system().name();
154  //qDebug()<<"Your language is"<<language;
155 
156  //And see if we can find it from our list of language files
157  const int index = getLanguageIndexByCode(language);
158 
159  //If nothing found, return English
160  if (index < 0) {
161  return "en";
162  }
163 
164  return language;
165 }
166 
167 void TranslationHandler::addTranslation(const char *name, const char *filename)
168 {
169  TranslationInfo info;
170  info.mName = name;
171  info.mFilename = filename;
172  const int codeLength = QString(filename).length() - QString(filename).indexOf('_') - 1;
173  info.mCode = QString(filename).right(codeLength);
174  mTranslations.append(info);
175 }
176 
177 int TranslationHandler::getLanguageIndexByCode(const QString &code) const
178 {
179  int index = -1;
180  for (int i = 0; i < mTranslations.size(); i++) {
181  if (mTranslations[i].mCode == code || mTranslations[i].mCode == code.left(2)) {
182  index = i;
183  break;
184  }
185  }
186  return index;
187 }
TranslationHandler(QObject *parent=nullptr)
int getLanguageIndexByCode(const QString &code) const
Find language in the list and return its index.
const QString & getCurrentLanguage() const
Get currently selected translation.
QTranslator * mTranslator
Translator class instance.
bool setLanguage(const QString &code)
Set active translation.
void addTranslation(const char *name, const char *filename)
Add new translation to list of available translations.
QList< TranslationInfo > mTranslations
List of available translations.
QString suggestLanguage() const
Get translation suggestion for the system.
QString mCurrentLanguage
ISO 639 language code of the currently selected translation.
#define UNUSED
Definition: config.h:102
@ error
Programming error.
QString getDataDir()
Get configured data dir.
Definition: common.cpp:75
Information for one translation.
QString mName
Readable name for the translation (e.g.
QString mCode
ISO 639 language code for the translation (e.g.
QString mFilename
Filename for the translation.
static UNUSED void unused()