/* * Stellarium * Copyright (C) 2005 Fabien Chereau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include "StelUtils.hpp" #include "StelTranslator.hpp" #include "StelFileMgr.hpp" // Init static members StelTranslator* StelTranslator::lastUsed = NULL; QMap StelTranslator::iso639codes; QString StelTranslator::systemLangName; // Use system locale language by default StelTranslator StelTranslator::globalTranslator = StelTranslator("stellarium", "./locale/", "system"); #ifdef Q_OS_WIN # include # include #define putenv(x) _putenv((x)) #endif //! Initialize Translation //! @param fileName file containing the list of language codes void StelTranslator::init(const QString& fileName) { StelTranslator::initSystemLanguage(); StelTranslator::initIso639_1LanguageCodes(fileName); } //! Try to determine system language from system configuration void StelTranslator::initSystemLanguage(void) { char* lang = getenv("LANGUAGE"); if (lang) systemLangName = lang; else { lang = getenv("LANG"); if (lang) systemLangName = lang; else { #ifdef Q_OS_WIN char cc[3]; if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, cc, 3)) { cc[2] = '\0'; systemLangName = cc; } else { systemLangName = "C"; } #else systemLangName = "C"; #endif } } //change systemLangName to ISO 639 / ISO 3166. int pos = systemLangName.indexOf(':', 0); if (pos != -1) systemLangName.resize(pos); pos = systemLangName.indexOf('.', 0); if (pos != -1) systemLangName.resize(pos); } void StelTranslator::reload() { if (StelTranslator::lastUsed == this) return; // Find out what the system language is if not defined yet if (systemLangName.isEmpty()) initSystemLanguage(); // Apply that // This needs to be static as it is used a each gettext call... It tooks me quite a while before I got that :( static char envstr[128]; if (langName=="system" || langName=="system_default") #ifdef Q_OS_MAC { qsnprintf(envstr, 128, "LANG=%s", StelTranslator::systemLangName.toUtf8().constData()); } else { qsnprintf(envstr, 128, "LANG=%s", langName.toUtf8().constData()); } #elif defined (Q_OS_WIN) //MSCVER { qsnprintf(envstr, 128, "LANGUAGE=%s", StelTranslator::systemLangName.toUtf8().constData()); } else { qsnprintf(envstr, 128, "LANGUAGE=%s", langName.toUtf8().constData()); } #else // UNIX { qsnprintf(envstr, 128, "LANGUAGE=%s", StelTranslator::systemLangName.toUtf8().constData()); } else { qsnprintf(envstr, 128, "LANGUAGE=%s", langName.toUtf8().constData()); } #endif putenv(envstr); #ifndef Q_OS_WIN setlocale(LC_MESSAGES, ""); #else setlocale(LC_CTYPE,""); #endif QString result = bind_textdomain_codeset(domain.toUtf8().constData(), "UTF-8"); Q_ASSERT(result=="UTF-8"); bindtextdomain (domain.toUtf8().constData(), QFile::encodeName(moDirectory).constData()); textdomain (domain.toUtf8().constData()); StelTranslator::lastUsed = this; } //! Convert from ISO639-1 2 letters langage code to native language name QString StelTranslator::iso639_1CodeToNativeName(const QString& languageCode) { if (languageCode=="C") return "English"; QLocale loc(languageCode); QString l = loc.name(); // There is a QLocale for this code. This should be the case for most // language codes, but there are a few without QLocales, e.g. Interlingua if (l.contains('_')) l.truncate(l.indexOf('_')); if (iso639codes.find(l)!=iso639codes.end()) return iso639codes[l]+ (languageCode.size()==2 ? "" : QString(" (")+QLocale::countryToString(loc.country())+")"); // For codes which return the locale C, use the language code to do the lookup if (iso639codes.contains(languageCode)) return iso639codes[languageCode]; // qWarning() << "WARNING: Cannot determine name of language for code" << languageCode; return languageCode; } //! Convert from native language name to ISO639-1 2(+3) letters langage code QString StelTranslator::nativeNameToIso639_1Code(const QString& languageName) { QMap::iterator iter; for (iter=iso639codes.begin();iter!=iso639codes.end();++iter) if (iter.value() == languageName) return iter.key(); return languageName; } //! Get available native language names from directory tree QStringList StelTranslator::getAvailableLanguagesNamesNative(const QString& localeDir) const { QString tmpDir = localeDir; if (tmpDir.isEmpty()) tmpDir = moDirectory; QStringList codeList = getAvailableIso639_1Codes(tmpDir); QStringList output; foreach (QString lang, codeList) { output += iso639_1CodeToNativeName(lang); } return output; } //! Get available language codes from directory tree QStringList StelTranslator::getAvailableIso639_1Codes(const QString& localeDir) const { QString locDir = localeDir; if (locDir.isEmpty()) locDir = moDirectory; struct dirent *entryp; DIR *dp; QStringList result; if ((dp = opendir(QFile::encodeName(locDir).constData())) == NULL) { qWarning() << "Unable to find locale directory containing translations:" << localeDir; return result; } while ((entryp = readdir(dp)) != NULL) { QString tmp = entryp->d_name; QString tmpdir = locDir+"/"+tmp+"/LC_MESSAGES/stellarium.mo"; FILE* fic = fopen(QFile::encodeName(tmpdir).constData(), "r"); if (fic) { result.push_back(tmp); fclose(fic); } } closedir(dp); // Sort the language names by alphabetic order result.sort(); return result; } //! Initialize the languages code list from the passed file //! @param fileName file containing the list of language codes void StelTranslator::initIso639_1LanguageCodes(const QString& fileName) { QFile inf(fileName); if (!inf.open(QIODevice::ReadOnly)) { qWarning() << "Can't open ISO639 codes file " << fileName; Q_ASSERT(0); } if (!iso639codes.empty()) iso639codes.clear(); while (!inf.atEnd()) { QString record = QString::fromUtf8(inf.readLine()); record.remove(QRegExp("[\\n\\r]*$")); // chomp new lines const QStringList& fields = record.split("\t", QString::SkipEmptyParts); iso639codes.insert(fields.at(0), fields.at(2)); } }