File indexing completed on 2025-02-16 13:03:31
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2010 Luigi Toscano <luigi.toscano@tiscali.it> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include "loggingcategory.h" 0009 0010 #include <QCoreApplication> 0011 #include <QDir> 0012 #include <QFile> 0013 #include <QIODevice> 0014 #include <QList> 0015 #include <QPair> 0016 #include <QRegularExpression> 0017 #include <QStringList> 0018 #include <QTextStream> 0019 0020 class LangListType : public QList<QPair<QString, QString>> 0021 { 0022 public: 0023 int searchLang(const QString &el) 0024 { 0025 for (int i = 0; i < size(); ++i) { 0026 if (at(i).first == el) { 0027 return i; 0028 } 0029 } 0030 return -1; 0031 } 0032 }; 0033 0034 int writeLangFile(const QString &fname, const QString &dtdPath, const LangListType &langMap) 0035 { 0036 QFile outFile(fname); 0037 if (!outFile.open(QIODevice::WriteOnly)) { 0038 qCCritical(KDocToolsLog) << QStringLiteral("Could not write %1").arg(outFile.fileName()); 0039 return (1); 0040 } 0041 0042 QTextStream outStream(&outFile); 0043 outStream << "<?xml version='1.0'?>\n"; 0044 outStream << QStringLiteral("<!DOCTYPE l:i18n SYSTEM \"%1\" [").arg(dtdPath) << QLatin1Char('\n'); 0045 0046 LangListType::const_iterator i = langMap.constBegin(); 0047 while (i != langMap.constEnd()) { 0048 // qCDebug(KDocToolsLog) << (*i).first << ": " << (*i).second; 0049 outStream << QStringLiteral("<!ENTITY %1 SYSTEM \"%2\">").arg((*i).first).arg((*i).second) << QLatin1Char('\n'); 0050 ++i; 0051 } 0052 outStream << "]>\n"; 0053 0054 if (!langMap.isEmpty()) { 0055 outStream << "<l:i18n xmlns:l=\"http://docbook.sourceforge.net/xmlns/l10n/1.0\">\n"; 0056 i = langMap.constBegin(); 0057 while (i != langMap.constEnd()) { 0058 outStream << QStringLiteral("&%1;").arg((*i).first) << QLatin1Char('\n'); 0059 ++i; 0060 } 0061 outStream << "</l:i18n>\n"; 0062 } 0063 0064 outFile.close(); 0065 0066 return (0); 0067 } 0068 0069 int writeLangFileNew(const QString &fname, const QString &dtdPath, const LangListType &langMap) 0070 { 0071 QFile outFile(fname); 0072 if (!outFile.open(QIODevice::WriteOnly)) { 0073 qCCritical(KDocToolsLog) << QStringLiteral("Could not write %1").arg(outFile.fileName()); 0074 return (1); 0075 } 0076 0077 QTextStream outStream(&outFile); 0078 outStream << "<?xml version='1.0'?>\n"; 0079 outStream << QStringLiteral("<!DOCTYPE l:i18n SYSTEM \"%1\">").arg(dtdPath) << QLatin1Char('\n'); 0080 0081 if (!langMap.isEmpty()) { 0082 outStream << "<l:i18n xmlns:l=\"http://docbook.sourceforge.net/xmlns/l10n/1.0\">" << QLatin1Char('\n'); 0083 LangListType::const_iterator i = langMap.constBegin(); 0084 while (i != langMap.constEnd()) { 0085 outStream << QStringLiteral("<l:l10n language=\"%1\" href=\"%2\"/>").arg((*i).first).arg((*i).second) << QLatin1Char('\n'); 0086 ++i; 0087 } 0088 outStream << "</l:i18n>\n"; 0089 } 0090 0091 outFile.close(); 0092 0093 return (0); 0094 } 0095 0096 inline const QString addTrailingSlash(const QString &p) 0097 { 0098 return p.endsWith(QStringLiteral("/")) ? p : p + QStringLiteral("/"); 0099 } 0100 0101 int main(int argc, char **argv) 0102 { 0103 QCoreApplication app(argc, argv); 0104 0105 const QStringList arguments = app.arguments(); 0106 if (arguments.count() != 4) { 0107 qCCritical(KDocToolsLog) << "wrong argument count"; 0108 return (1); 0109 } 0110 0111 const QString l10nDir = addTrailingSlash(arguments[1]); 0112 const QString l10nCustomDir = addTrailingSlash(arguments[2]); 0113 const QString destDir = addTrailingSlash(arguments[3]); 0114 0115 QFile i18nFile(l10nDir + QStringLiteral("common/l10n.xml")); 0116 0117 if (!i18nFile.open(QIODevice::ReadOnly)) { 0118 qCCritical(KDocToolsLog) << i18nFile.fileName() << " not found"; 0119 return (1); 0120 } 0121 0122 const QString all10nFName = destDir + QStringLiteral("all-l10n.xml"); 0123 const QString customl10nFName = destDir + QStringLiteral("kde-custom-l10n.xml"); 0124 0125 /* 0126 * for each language defined in the original l10n.xml, copy 0127 * it into all-l10n.xml and store it in a list; 0128 **/ 0129 const QRegularExpression rxDocType(QStringLiteral("^\\s*<!DOCTYPE\\s+l:i18n\\s+SYSTEM\\s+\"l10n\\.dtd\"\\s+\\[\\s*$")); 0130 const QRegularExpression rxDocType2(QStringLiteral("^\\s*<!DOCTYPE\\s+l:i18n\\s+SYSTEM\\s+\"l10n\\.dtd\"\\s*>$")); 0131 const QRegularExpression rxEntity(QStringLiteral("^\\s*<!ENTITY\\s+([^\\s]+)\\s+SYSTEM\\s+\"([^\\s]+)\">\\s*$")); 0132 const QRegularExpression rxEntity2(QStringLiteral("^\\s*<l:l10n language=\"([^\\s]+)\"\\s+href=\"([^\\s]+)\"/>\\s*$")); 0133 QTextStream inStream(&i18nFile); 0134 int parsingState = 0; 0135 0136 LangListType allLangs; 0137 LangListType customLangs; 0138 0139 bool foundRxEntity = false; 0140 bool foundRxEntity2 = false; 0141 while (!inStream.atEnd()) { 0142 QString line = inStream.readLine(); 0143 0144 switch (parsingState) { 0145 case 0: 0146 if (rxDocType.match(line).hasMatch()) { 0147 parsingState = 1; 0148 // qCDebug(KDocToolsLog) << "DTD found"; 0149 } else if (rxDocType2.match(line).hasMatch()) { 0150 parsingState = 1; 0151 // qCDebug(KDocToolsLog) << "DTD found"; 0152 } 0153 break; 0154 case 1: 0155 QString langCode, langFile; 0156 QRegularExpressionMatch match = rxEntity.match(line); 0157 if (match.hasMatch() && !foundRxEntity2) { 0158 foundRxEntity = true; 0159 langCode = match.captured(1); 0160 langFile = l10nDir + QStringLiteral("common/") + match.captured(2); 0161 allLangs += qMakePair(langCode, langFile); 0162 // qCDebug(KDocToolsLog) << langCode << " - " << langFile; 0163 } else if (!foundRxEntity) { 0164 match = rxEntity2.match(line); 0165 if (match.hasMatch()) { 0166 foundRxEntity2 = true; 0167 langCode = match.captured(1); 0168 langFile = l10nDir + QStringLiteral("common/") + match.captured(2); 0169 allLangs += qMakePair(langCode, langFile); 0170 // qCDebug(KDocToolsLog) << langCode << " - " << langFile; 0171 } 0172 } 0173 break; 0174 } 0175 } 0176 i18nFile.close(); 0177 0178 /* read the list of locally-available custom languages */ 0179 QDir outDir(l10nCustomDir); 0180 0181 QStringList dirFileFilters; 0182 dirFileFilters << QStringLiteral("*.xml"); 0183 QStringList customLangFiles = outDir.entryList(dirFileFilters, QDir::Files, QDir::Name); 0184 /* the following two calls to removeOne should not be needed, as 0185 * the customization directory from the sources should not contain 0186 * those files 0187 */ 0188 customLangFiles.removeOne(QStringLiteral("all-l10n.xml")); 0189 customLangFiles.removeOne(QStringLiteral("kde-custom-l10n.xml")); 0190 // qCDebug(KDocToolsLog) << "customLangFiles:" << customLangFiles; 0191 0192 /* 0193 * for each custom language (from directory listing), if it is not 0194 * in the list of upstream languages, add it to all-l10n.xml, 0195 * otherwise add it to kde-custom-l10n.xml 0196 */ 0197 QStringList::const_iterator i = customLangFiles.constBegin(); 0198 while (i != customLangFiles.constEnd()) { 0199 QString langFile = (*i); 0200 /* remove trailing .xml */ 0201 QString langCode = langFile.left(langFile.length() - 4); 0202 0203 QPair<QString, QString> cl = qMakePair(langCode, langFile); 0204 if ((allLangs.searchLang(langCode)) > 0) { 0205 /* custom language found in upstream list */ 0206 customLangs += cl; 0207 } else { 0208 /* custom language not found in upstream list */ 0209 allLangs += cl; 0210 } 0211 ++i; 0212 } 0213 0214 int res = 0; 0215 0216 if (foundRxEntity) { 0217 /* old style (docbook-xsl<=1.75) */ 0218 res = writeLangFile(all10nFName, l10nDir + QStringLiteral("common/l10n.dtd"), allLangs); 0219 } else { 0220 res = writeLangFileNew(all10nFName, l10nDir + QStringLiteral("common/l10n.dtd"), allLangs); 0221 } 0222 0223 return (res); 0224 }