fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / l10ntools / source / pocheck.cxx
blobbdd3ad86a3387b8870d84c738423a0af2bf25ac3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <iostream>
11 #include <map>
12 #include <list>
13 #include <vector>
14 #include <rtl/string.hxx>
15 #include <rtl/ustring.hxx>
16 #include <osl/file.hxx>
17 #include "po.hxx"
19 // Translated style names must be unique
20 static void checkStyleNames(const OString& aLanguage)
22 std::map<OString,sal_uInt16> aLocalizedStyleNames;
23 std::map<OString,sal_uInt16> aLocalizedNumStyleNames;
24 std::list<PoEntry> repeatedEntries;
26 OString aPoPath = OString(getenv("SRC_ROOT")) +
27 "/translations/source/" +
28 aLanguage + "/sw/source/ui/utlui.po";
29 PoIfstream aPoInput;
30 aPoInput.open(aPoPath);
31 if( !aPoInput.isOpen() )
32 std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
34 for(;;)
36 PoEntry aPoEntry;
37 aPoInput.readEntry(aPoEntry);
38 bool bRepeated = false;
39 if( aPoInput.eof() )
41 break;
44 if( !aPoEntry.isFuzzy() && aPoEntry.getSourceFile() == "poolfmt.src" &&
45 aPoEntry.getGroupId().startsWith("STR_POOLCOLL") )
47 OString aMsgStr = aPoEntry.getMsgStr();
48 if( aMsgStr.isEmpty() )
49 continue;
50 if( aLocalizedStyleNames.find(aMsgStr) == aLocalizedStyleNames.end() )
51 aLocalizedStyleNames[aMsgStr] = 1;
52 else {
53 aLocalizedStyleNames[aMsgStr]++;
54 bRepeated = true;
57 if( !aPoEntry.isFuzzy() && aPoEntry.getSourceFile() == "poolfmt.src" &&
58 aPoEntry.getGroupId().startsWith("STR_POOLNUMRULE") )
60 OString aMsgStr = aPoEntry.getMsgStr();
61 if( aMsgStr.isEmpty() )
62 continue;
63 if( aLocalizedNumStyleNames.find(aMsgStr) == aLocalizedNumStyleNames.end() )
64 aLocalizedNumStyleNames[aMsgStr] = 1;
65 else {
66 aLocalizedNumStyleNames[aMsgStr]++;
67 bRepeated = true;
70 if (bRepeated)
71 repeatedEntries.push_back(aPoEntry);
73 aPoInput.close();
75 for( std::map<OString,sal_uInt16>::iterator it=aLocalizedStyleNames.begin(); it!=aLocalizedStyleNames.end(); ++it)
77 if( it->second > 1 )
79 std::cout << "ERROR: Style name translations must be unique in:\n" <<
80 aPoPath << "\nLanguage: " << aLanguage << "\nDuplicated translation is: " << it->first <<
81 "\nSee STR_POOLCOLL_*\n\n";
84 for( std::map<OString,sal_uInt16>::iterator it=aLocalizedNumStyleNames.begin(); it!=aLocalizedNumStyleNames.end(); ++it)
86 if( it->second > 1 )
88 std::cout << "ERROR: Style name translations must be unique in:\n" <<
89 aPoPath << "\nLanguage: " << aLanguage << "\nDuplicated translation is: " << it->first <<
90 "\nSee STR_POOLNUMRULE_*\n\n";
93 aPoInput.open(aPoPath);
94 if( !aPoInput.isOpen() )
95 std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
96 PoOfstream aPoOutput;
97 aPoOutput.open(aPoPath+".new");
98 PoHeader aTmp("sw/source/ui/utlui");
99 aPoOutput.writeHeader(aTmp);
100 bool bAnyError = false;
102 for(;;)
104 PoEntry aPoEntry;
105 bool bError = false;
106 aPoInput.readEntry(aPoEntry);
107 if( aPoInput.eof() )
108 break;
109 for ( std::list<PoEntry>::iterator it=repeatedEntries.begin(); it!=repeatedEntries.end(); ++it) {
110 if (it->getMsgId() == aPoEntry.getMsgId() && it->getGroupId() == aPoEntry.getGroupId()) {
111 bError = true;
112 break;
115 if (bError) {
116 bAnyError = true;
117 } else {
118 aPoOutput.writeEntry(aPoEntry);
121 aPoInput.close();
122 aPoOutput.close();
123 OUString aPoPathURL;
124 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPath, RTL_TEXTENCODING_UTF8), aPoPathURL);
125 if( bAnyError )
126 osl::File::move(aPoPathURL + ".new", aPoPathURL);
127 else
128 osl::File::remove(aPoPathURL + ".new");
132 // Translated spreadsheet function names must be unique
133 static void checkFunctionNames(const OString& aLanguage)
135 std::map<OString,sal_uInt16> aLocalizedFunctionNames;
136 std::map<OString,sal_uInt16> aLocalizedCoreFunctionNames;
138 std::list<PoEntry> repeatedEntries;
140 OString aPoPaths[4];
141 OUString aPoPathURL;
143 aPoPaths[0] = OString(getenv("SRC_ROOT")) +
144 "/translations/source/" +
145 aLanguage +
146 "/formula/source/core/resource.po";
147 PoIfstream aPoInput;
148 aPoInput.open(aPoPaths[0]);
149 if( !aPoInput.isOpen() )
150 std::cerr << "Warning: Cannot open " << aPoPaths[0] << std::endl;
152 for(;;)
154 PoEntry aPoEntry;
155 aPoInput.readEntry(aPoEntry);
156 if( aPoInput.eof() )
157 break;
158 if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_STRLIST_FUNCTION_NAMES" )
160 OString aMsgStr = aPoEntry.getMsgStr();
161 if( aMsgStr.isEmpty() )
162 continue;
163 if( aLocalizedCoreFunctionNames.find(aMsgStr) == aLocalizedCoreFunctionNames.end() )
164 aLocalizedCoreFunctionNames[aMsgStr] = 1;
165 if( aLocalizedFunctionNames.find(aMsgStr) == aLocalizedFunctionNames.end() ) {
166 aLocalizedFunctionNames[aMsgStr] = 1;
167 } else {
168 aLocalizedFunctionNames[aMsgStr]++;
169 repeatedEntries.push_back(aPoEntry);
173 aPoInput.close();
175 aPoPaths[1] = OString(getenv("SRC_ROOT")) +
176 "/translations/source/" +
177 aLanguage +
178 "/scaddins/source/analysis.po";
179 aPoInput.open(aPoPaths[1]);
180 if( !aPoInput.isOpen() )
181 std::cerr << "Warning: Cannot open " << aPoPaths[1] << std::endl;
183 for(;;)
185 PoEntry aPoEntry;
186 aPoInput.readEntry(aPoEntry);
187 if( aPoInput.eof() )
188 break;
189 if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_ANALYSIS_FUNCTION_NAMES" )
191 OString aMsgStr = aPoEntry.getMsgStr();
192 if( aMsgStr.isEmpty() )
193 continue;
194 if( aLocalizedCoreFunctionNames.find(aMsgStr) != aLocalizedCoreFunctionNames.end() )
195 aMsgStr += "_ADD";
196 if( aLocalizedFunctionNames.find(aMsgStr) == aLocalizedFunctionNames.end() ) {
197 aLocalizedFunctionNames[aMsgStr] = 1;
198 } else {
199 aLocalizedFunctionNames[aMsgStr]++;
200 repeatedEntries.push_back(aPoEntry);
204 aPoInput.close();
207 aPoPaths[2] = OString(getenv("SRC_ROOT")) +
208 "/translations/source/" +
209 aLanguage +
210 "/scaddins/source/datefunc.po";
211 aPoInput.open(aPoPaths[2]);
212 if( !aPoInput.isOpen() )
213 std::cerr << "Warning: Cannot open " << aPoPaths[2] << std::endl;
215 for(;;)
217 PoEntry aPoEntry;
218 aPoInput.readEntry(aPoEntry);
219 if( aPoInput.eof() )
220 break;
221 if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_DATE_FUNCTION_NAMES" )
223 OString aMsgStr = aPoEntry.getMsgStr();
224 if( aMsgStr.isEmpty() )
225 continue;
226 if( aLocalizedCoreFunctionNames.find(aMsgStr) != aLocalizedCoreFunctionNames.end() )
227 aMsgStr += "_ADD";
228 if( aLocalizedFunctionNames.find(aMsgStr) == aLocalizedFunctionNames.end() ) {
229 aLocalizedFunctionNames[aMsgStr] = 1;
230 } else {
231 aLocalizedFunctionNames[aMsgStr]++;
232 repeatedEntries.push_back(aPoEntry);
236 aPoInput.close();
238 aPoPaths[3] = OString(getenv("SRC_ROOT")) +
239 "/translations/source/" +
240 aLanguage +
241 "/scaddins/source/pricing.po";
242 aPoInput.open(aPoPaths[3]);
243 if( !aPoInput.isOpen() )
244 std::cerr << "Warning: Cannot open " << aPoPaths[3] << std::endl;
246 for(;;)
248 PoEntry aPoEntry;
249 aPoInput.readEntry(aPoEntry);
250 if( aPoInput.eof() )
252 break;
255 if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_PRICING_FUNCTION_NAMES" )
257 OString aMsgStr = aPoEntry.getMsgStr();
258 if( aMsgStr.isEmpty() )
259 continue;
260 if( aLocalizedCoreFunctionNames.find(aMsgStr) != aLocalizedCoreFunctionNames.end() )
261 aMsgStr += "_ADD";
262 if( aLocalizedFunctionNames.find(aMsgStr) == aLocalizedFunctionNames.end() ) {
263 aLocalizedFunctionNames[aMsgStr] = 1;
264 } else {
265 aLocalizedFunctionNames[aMsgStr]++;
266 repeatedEntries.push_back(aPoEntry);
270 aPoInput.close();
271 for( std::map<OString,sal_uInt16>::iterator it=aLocalizedFunctionNames.begin(); it!=aLocalizedFunctionNames.end(); ++it)
273 if( it->second > 1 )
275 std::cout
276 << ("ERROR: Spreadsheet function name translations must be"
277 " unique.\nLanguage: ")
278 << aLanguage << "\nDuplicated translation is: " << it->first
279 << "\n\n";
283 for (int i=0;i<4;i++)
285 aPoInput.open(aPoPaths[i]);
286 if( !aPoInput.isOpen() )
287 std::cerr << "Warning: Cannot open " << aPoPaths[i] << std::endl;
288 PoOfstream aPoOutput;
289 aPoOutput.open(aPoPaths[i]+".new");
291 switch (i)
293 case 0:
295 PoHeader hd(OString("formula/source/core/resource"));
296 aPoOutput.writeHeader(hd);
297 break;
299 case 1:
301 PoHeader hd(OString("scaddins/source/analysis"));
302 aPoOutput.writeHeader(hd);
303 break;
305 case 2:
307 PoHeader hd(OString("scaddins/source/datefunc"));
308 aPoOutput.writeHeader(hd);
309 break;
311 case 3:
313 PoHeader hd(OString("scaddins/source/pricing"));
314 aPoOutput.writeHeader(hd);
315 break;
318 bool bAnyError = false;
320 for(;;)
322 PoEntry aPoEntry;
323 bool bError = false;
324 aPoInput.readEntry(aPoEntry);
325 if( aPoInput.eof() )
326 break;
327 for ( std::list<PoEntry>::iterator it=repeatedEntries.begin(); it!=repeatedEntries.end(); ++it)
329 if (it->getMsgId() == aPoEntry.getMsgId() && it->getGroupId() == aPoEntry.getGroupId())
331 bError = true;
332 break;
335 if (bError)
337 bAnyError = true;
339 else
341 aPoOutput.writeEntry(aPoEntry);
344 aPoInput.close();
345 aPoOutput.close();
346 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPaths[i], RTL_TEXTENCODING_UTF8), aPoPathURL);
347 if( bAnyError )
348 osl::File::move(aPoPathURL + ".new", aPoPathURL);
349 else
350 osl::File::remove(aPoPathURL + ".new");
354 // In instsetoo_native/inc_openoffice/windows/msi_languages.po
355 // where an en-US string ends with '|', translation must end
356 // with '|', too.
357 static void checkVerticalBar(const OString& aLanguage)
359 OString aPoPath = OString(getenv("SRC_ROOT")) +
360 "/translations/source/" +
361 aLanguage +
362 "/instsetoo_native/inc_openoffice/windows/msi_languages.po";
363 PoIfstream aPoInput;
364 aPoInput.open(aPoPath);
365 PoOfstream aPoOutput;
366 aPoOutput.open(aPoPath+".new");
367 if( !aPoInput.isOpen() )
368 std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
369 PoHeader aTmp("instsetoo_native/inc_openoffice/windows/msi_languages");
370 aPoOutput.writeHeader(aTmp);
371 bool bError = false;
373 for(;;)
375 PoEntry aPoEntry;
376 aPoInput.readEntry(aPoEntry);
377 if( aPoInput.eof() )
378 break;
379 if( !aPoEntry.isFuzzy() && aPoEntry.getMsgId().endsWith("|") &&
380 !aPoEntry.getMsgStr().isEmpty() && !aPoEntry.getMsgStr().endsWith("|") )
382 std::cout
383 << ("ERROR: Missing '|' character at the end of translated"
384 " string.\nIt causes runtime error in installer.\nFile: ")
385 << aPoPath << std::endl
386 << "Language: " << aLanguage << std::endl
387 << "English: " << aPoEntry.getMsgId() << std::endl
388 << "Localized: " << aPoEntry.getMsgStr() << std::endl
389 << std::endl;
390 bError = true;
392 else
393 aPoOutput.writeEntry(aPoEntry);
395 aPoInput.close();
396 aPoOutput.close();
397 OUString aPoPathURL;
398 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPath, RTL_TEXTENCODING_UTF8), aPoPathURL);
399 if( bError )
400 osl::File::move(aPoPathURL + ".new", aPoPathURL);
401 else
402 osl::File::remove(aPoPathURL + ".new");
405 // In starmath/source.po Math symbol names (from symbol.src)
406 // must not contain spaces
407 static void checkMathSymbolNames(const OString& aLanguage)
409 OString aPoPath = OString(getenv("SRC_ROOT")) +
410 "/translations/source/" +
411 aLanguage +
412 "/starmath/source.po";
413 PoIfstream aPoInput;
414 aPoInput.open(aPoPath);
415 PoOfstream aPoOutput;
416 aPoOutput.open(aPoPath+".new");
417 if( !aPoInput.isOpen() )
418 std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
419 PoHeader aTmp("starmath/source");
420 aPoOutput.writeHeader(aTmp);
421 bool bError = false;
423 for(;;)
425 PoEntry aPoEntry;
426 aPoInput.readEntry(aPoEntry);
427 if( aPoInput.eof() )
428 break;
429 if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_UI_SYMBOL_NAMES" &&
430 !aPoEntry.getMsgStr().isEmpty() && (aPoEntry.getMsgStr().indexOf(" ") != -1) )
432 std::cout
433 << "ERROR: Math symbol names must not contain spaces.\nFile: "
434 << aPoPath << std::endl
435 << "Language: " << aLanguage << std::endl
436 << "English: " << aPoEntry.getMsgId() << std::endl
437 << "Localized: " << aPoEntry.getMsgStr() << std::endl
438 << std::endl;
439 bError = true;
441 else
442 aPoOutput.writeEntry(aPoEntry);
444 aPoInput.close();
445 aPoOutput.close();
446 OUString aPoPathURL;
447 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPath, RTL_TEXTENCODING_UTF8), aPoPathURL);
448 if( bError )
449 osl::File::move(aPoPathURL + ".new", aPoPathURL);
450 else
451 osl::File::remove(aPoPathURL + ".new");
454 int main()
456 OString aLanguages(getenv("ALL_LANGS"));
457 if( aLanguages.isEmpty() )
459 std::cerr << "Usage: bin/run pocheck\n";
460 return 1;
462 for(sal_Int32 i = 1;;++i) // skip en-US
464 OString aLanguage = aLanguages.getToken(i,' ');
465 if( aLanguage.isEmpty() )
466 break;
467 if( aLanguage == "qtz" )
468 continue;
469 checkStyleNames(aLanguage);
470 checkFunctionNames(aLanguage);
471 checkVerticalBar(aLanguage);
472 checkMathSymbolNames(aLanguage);
474 return 0;
477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */