1 | /* This file is part of the KDE project |
2 | Copyright (C) 2010 Luigi Toscano <luigi.toscano@tiscali.it> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) version 3, or any |
8 | later version accepted by the membership of KDE e.V. (or its |
9 | successor approved by the membership of KDE e.V.), which shall |
10 | act as a proxy defined in Section 6 of version 3 of the license. |
11 | |
12 | This library is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | Lesser General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU Lesser General Public |
18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. |
19 | */ |
20 | |
21 | #include <QCoreApplication> |
22 | #include <QDebug> |
23 | #include <QDir> |
24 | #include <QFile> |
25 | #include <QIODevice> |
26 | #include <QList> |
27 | #include <QPair> |
28 | #include <QRegExp> |
29 | #include <QStringList> |
30 | #include <QTextStream> |
31 | |
32 | |
33 | class LangListType: public QList<QPair<QString,QString> > |
34 | { |
35 | public: |
36 | int searchLang( QString el ) { |
37 | |
38 | for ( int i = 0; i < size(); ++i ) { |
39 | if ( at( i ).first == el ) |
40 | return i; |
41 | } |
42 | return -1; |
43 | } |
44 | }; |
45 | |
46 | int writeLangFile( const QString &fname, const QString &dtdPath, |
47 | const LangListType &langMap ) { |
48 | |
49 | QFile outFile( fname ); |
50 | if ( ! outFile.open( QIODevice::WriteOnly ) ) { |
51 | qCritical() << QString( "Could not write %1" ) |
52 | .arg( outFile.fileName() ); |
53 | return( 1 ); |
54 | } |
55 | |
56 | QTextStream outStream( &outFile ); |
57 | outStream << "<?xml version='1.0'?>" << endl; |
58 | outStream << QString( "<!DOCTYPE l:i18n SYSTEM \"%1\" [" ) |
59 | .arg( dtdPath ) << endl; |
60 | |
61 | LangListType::const_iterator i = langMap.constBegin(); |
62 | while ( i != langMap.constEnd() ) { |
63 | //qDebug() << (*i).first << ": " << (*i).second; |
64 | outStream << QString( "<!ENTITY %1 SYSTEM \"%2\">" ) |
65 | .arg( (*i).first ).arg( (*i).second ) << endl; |
66 | ++i; |
67 | } |
68 | outStream << "]>" << endl; |
69 | |
70 | if ( langMap.size() > 0 ) { |
71 | outStream |
72 | << "<l:i18n xmlns:l=\"http://docbook.sourceforge.net/xmlns/l10n/1.0\">" |
73 | << endl; |
74 | i = langMap.constBegin(); |
75 | while ( i != langMap.constEnd() ) { |
76 | outStream << QString( "&%1;" ) |
77 | .arg( (*i).first ) << endl; |
78 | ++i; |
79 | } |
80 | outStream << "</l:i18n>" << endl; |
81 | } |
82 | |
83 | outFile.close(); |
84 | |
85 | return( 0 ); |
86 | } |
87 | |
88 | int writeLangFileNew( const QString &fname, const QString &dtdPath, |
89 | const LangListType &langMap ) { |
90 | |
91 | QFile outFile( fname ); |
92 | if ( ! outFile.open( QIODevice::WriteOnly ) ) { |
93 | qCritical() << QString( "Could not write %1" ) |
94 | .arg( outFile.fileName() ); |
95 | return( 1 ); |
96 | } |
97 | |
98 | QTextStream outStream( &outFile ); |
99 | outStream << "<?xml version='1.0'?>" << endl; |
100 | outStream << QString( "<!DOCTYPE l:i18n SYSTEM \"%1\">" ) |
101 | .arg( dtdPath ) << endl; |
102 | |
103 | if ( langMap.size() > 0 ) { |
104 | outStream |
105 | << "<l:i18n xmlns:l=\"http://docbook.sourceforge.net/xmlns/l10n/1.0\">" |
106 | << endl; |
107 | LangListType::const_iterator i = langMap.constBegin(); |
108 | while ( i != langMap.constEnd() ) { |
109 | outStream << QString( "<l:l10n language=\"%1\" href=\"%2\"/>" ) |
110 | .arg( (*i).first ).arg( (*i).second ) << endl; |
111 | ++i; |
112 | } |
113 | outStream << "</l:i18n>" << endl; |
114 | } |
115 | |
116 | outFile.close(); |
117 | |
118 | return( 0 ); |
119 | } |
120 | |
121 | inline const QString addTrailingSlash( const QString &p ) { |
122 | return p.endsWith( "/" ) ? p : p + "/" ; |
123 | } |
124 | |
125 | int main( int argc, char **argv ) { |
126 | QCoreApplication app( argc, argv ); |
127 | |
128 | const QStringList arguments = app.arguments(); |
129 | if ( arguments.count() != 4 ) { |
130 | qCritical() << "wrong argument count" ; |
131 | return ( 1 ); |
132 | } |
133 | |
134 | const QString l10nDir = addTrailingSlash( arguments[1] ); |
135 | const QString l10nCustomDir = addTrailingSlash( arguments[2] ); |
136 | const QString destDir = addTrailingSlash( arguments[3] ); |
137 | |
138 | QFile i18nFile( l10nDir + "common/l10n.xml" ); |
139 | |
140 | if ( ! i18nFile.open( QIODevice::ReadOnly ) ) { |
141 | qCritical() << i18nFile.fileName() << " not found" ; |
142 | return( 1 ); |
143 | } |
144 | |
145 | const QString all10nFName = destDir + "all-l10n.xml" ; |
146 | const QString customl10nFName = destDir + "kde-custom-l10n.xml" ; |
147 | |
148 | /* |
149 | * for each language defined in the original l10n.xml, copy |
150 | * it into all-l10n.xml and store it in a list; |
151 | **/ |
152 | QRegExp rxEntity, rxEntity2, rxDocType, rxDocType2; |
153 | rxDocType.setPattern("^\\s*<!DOCTYPE\\s+l:i18n\\s+SYSTEM\\s+\"l10n\\.dtd\"\\s+\\[\\s*$" ); |
154 | rxDocType2.setPattern("^\\s*<!DOCTYPE\\s+l:i18n\\s+SYSTEM\\s+\"l10n\\.dtd\"\\s*>$" ); |
155 | rxEntity.setPattern("^\\s*<!ENTITY\\s+([^\\s]+)\\s+SYSTEM\\s+\"([^\\s]+)\">\\s*$" ); |
156 | rxEntity2.setPattern("^\\s*<l:l10n language=\"([^\\s]+)\"\\s+href=\"([^\\s]+)\"/>\\s*$" ); |
157 | QTextStream inStream( &i18nFile ); |
158 | int parsingState = 0; |
159 | |
160 | LangListType allLangs, customLangs; |
161 | |
162 | bool foundRxEntity = false; |
163 | bool foundRxEntity2 = false; |
164 | while ( ! inStream.atEnd() ) { |
165 | QString line = inStream.readLine(); |
166 | |
167 | switch ( parsingState ) { |
168 | case 0: |
169 | if ( rxDocType.indexIn( line ) != -1 ) { |
170 | parsingState = 1; |
171 | //qDebug() << "DTD found"; |
172 | } else if ( rxDocType2.indexIn( line ) != -1 ) { |
173 | parsingState = 1; |
174 | //qDebug() << "DTD found"; |
175 | } |
176 | break; |
177 | case 1: |
178 | QString langCode, langFile; |
179 | if ( rxEntity.indexIn( line ) != -1 && !foundRxEntity2 ) { |
180 | foundRxEntity = true; |
181 | langCode = rxEntity.cap( 1 ); |
182 | langFile = l10nDir + "common/" + rxEntity.cap( 2 ); |
183 | allLangs += qMakePair( langCode, langFile ); |
184 | //qDebug() << langCode << " - " << langFile; |
185 | } else if ( rxEntity2.indexIn( line ) != -1 && !foundRxEntity ) { |
186 | foundRxEntity2 = true; |
187 | langCode = rxEntity2.cap( 1 ); |
188 | langFile = l10nDir + "common/" + rxEntity2.cap( 2 ); |
189 | allLangs += qMakePair( langCode, langFile ); |
190 | //qDebug() << langCode << " - " << langFile; |
191 | } |
192 | break; |
193 | } |
194 | |
195 | } |
196 | i18nFile.close(); |
197 | |
198 | /* read the list of locally-available custom languages */ |
199 | QDir outDir( l10nCustomDir ); |
200 | |
201 | QStringList dirFileFilters; |
202 | dirFileFilters << "*.xml" ; |
203 | QStringList customLangFiles = outDir.entryList( dirFileFilters, |
204 | QDir::Files|QDir::NoSymLinks, QDir::Name ); |
205 | /* the following two calls to removeOne should not be needed, as |
206 | * the customization directory from the sources should not contain |
207 | * those files |
208 | */ |
209 | customLangFiles.removeOne( "all-l10n.xml" ); |
210 | customLangFiles.removeOne( "kde-custom-l10n.xml" ); |
211 | //qDebug() << "customLangFiles:" << customLangFiles; |
212 | |
213 | /* |
214 | * for each custom language (from directory listing), if it is not |
215 | * in the list of upstream languages, add it to all-l10n.xml, |
216 | * otherwise add it to kde-custom-l10n.xml |
217 | */ |
218 | QStringList::const_iterator i = customLangFiles.constBegin(); |
219 | while ( i != customLangFiles.constEnd() ) { |
220 | QString langFile = (*i); |
221 | /* remove trailing .xml */ |
222 | QString langCode = langFile.left( langFile.length() - 4 ); |
223 | |
224 | QPair<QString,QString> cl = qMakePair( langCode, langFile ); |
225 | if ( ( allLangs.searchLang( langCode ) ) > 0 ) { |
226 | /* custom language found in upstream list */ |
227 | customLangs += cl; |
228 | } else { |
229 | /* custom language not found in upstream list */ |
230 | allLangs += cl; |
231 | } |
232 | ++i; |
233 | } |
234 | |
235 | int res = 0; |
236 | |
237 | if ( foundRxEntity ) { |
238 | /* old style (docbook-xsl<=1.75) */ |
239 | res = writeLangFile( all10nFName, l10nDir + "common/l10n.dtd" , |
240 | allLangs ); |
241 | } else { |
242 | res = writeLangFileNew( all10nFName, l10nDir + "common/l10n.dtd" , |
243 | allLangs ); |
244 | } |
245 | |
246 | return( res ); |
247 | } |
248 | |