File indexing completed on 2024-11-24 03:56:29
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #include "translation_service.hpp" 0008 0009 #include <QLocale> 0010 #include <QTranslator> 0011 #include <QCoreApplication> 0012 #include <QRegularExpression> 0013 0014 #include "app/application.hpp" 0015 #include "app/log/log.hpp" 0016 0017 void app::TranslationService::initialize ( QString default_lang_code ) 0018 { 0019 if ( !default_lang_code.isEmpty() ) 0020 { 0021 QString name = language_name(default_lang_code); 0022 if ( !name.isEmpty() ) 0023 register_translation(name,default_lang_code, QString()); 0024 } 0025 0026 QDir translations = Application::instance()->data_file("translations"); 0027 QStringList translation_files = translations.entryList({"*.qm"}); 0028 0029 QRegularExpression re("[^_]+_([^.]+)\\.qm"); 0030 for (auto &file: std::as_const(translation_files)) 0031 { 0032 auto match = re.match(file); 0033 if ( match.hasMatch() ) 0034 { 0035 QString code = match.captured(1); 0036 QString name = language_name(code); 0037 if ( !name.isEmpty() ) 0038 register_translation(name,code,translations.absoluteFilePath(file)); 0039 } 0040 else 0041 { 0042 log::LogStream("Translations") << "Unrecognised translation file name pattern:" << file; 0043 } 0044 } 0045 0046 change_lang_code(QLocale::system().name()); 0047 } 0048 0049 QString app::TranslationService::language_name(QString lang_code) 0050 { 0051 QLocale lang_loc = QLocale(lang_code); 0052 QString name = lang_loc.nativeLanguageName(); 0053 QString specifier; 0054 0055 if ( lang_code.contains("_") ) 0056 { 0057 if ( lang_loc.script() != QLocale::AnyScript ) 0058 specifier = QLocale::scriptToString(lang_loc.script()); 0059 0060 #if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) 0061 if ( lang_loc.territory() != QLocale::AnyTerritory ) 0062 { 0063 if ( !specifier.isEmpty() ) 0064 specifier += ", "; 0065 specifier = lang_loc.nativeTerritoryName(); 0066 } 0067 #else 0068 if ( lang_loc.country() != QLocale::AnyCountry ) 0069 { 0070 if ( !specifier.isEmpty() ) 0071 specifier += ", "; 0072 specifier = lang_loc.nativeCountryName(); 0073 } 0074 #endif 0075 } 0076 0077 if ( !name.isEmpty() ) 0078 { 0079 name[0] = name[0].toUpper(); 0080 if ( !specifier.isEmpty() ) 0081 name += " (" + specifier + ")"; 0082 } 0083 0084 return name; 0085 } 0086 0087 0088 void app::TranslationService::register_translation(QString name, QString code, QString file) 0089 { 0090 lang_names[name] = code; 0091 if ( !file.isEmpty() ) 0092 { 0093 translators[code] = new QTranslator; 0094 if ( !translators[code]->load(file) ) 0095 { 0096 log::Log("Translations").log( 0097 QString("Error on loading translation file %1 for language %2 (%3)") 0098 .arg(file).arg(name).arg(code) 0099 ); 0100 } 0101 } 0102 } 0103 0104 0105 0106 QString app::TranslationService::current_language_name() 0107 { 0108 return lang_names.key(current_language); 0109 } 0110 0111 QString app::TranslationService::current_language_code() 0112 { 0113 return current_language; 0114 } 0115 0116 QTranslator *app::TranslationService::translator() 0117 { 0118 return translators[current_language]; 0119 } 0120 0121 const QMap<QString, QString>& app::TranslationService::available_languages() 0122 { 0123 return lang_names; 0124 } 0125 0126 void app::TranslationService::change_lang_code(QString code) 0127 { 0128 0129 if ( !translators.contains(code) ) 0130 { 0131 QString base_code = code.left(code.lastIndexOf('_')); // en_US -> en 0132 bool found = false; 0133 for (const auto &installed_code: translators.keys()) 0134 { 0135 if ( installed_code.left(installed_code.lastIndexOf('_')) == base_code ) 0136 { 0137 code = installed_code; 0138 found = true; 0139 break; 0140 } 0141 } 0142 if ( !found ) 0143 { 0144 log::Log("Translations").log( 0145 QString("There is no translation for language %1 (%2)") 0146 .arg(language_name(code)) 0147 .arg(code) 0148 ); 0149 return; 0150 } 0151 } 0152 0153 QCoreApplication* app = QCoreApplication::instance(); 0154 app->removeTranslator(translator()); 0155 current_language = code; 0156 app->installTranslator(translator()); 0157 }