nss: upgrade to release 3.73
[LibreOffice.git] / l10ntools / source / pocheck.cxx
blob6f3252451dfa9aca23423f849b26e7ef9038fbb1
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 <vector>
13 #include <rtl/string.hxx>
14 #include <rtl/ustring.hxx>
15 #include <osl/file.hxx>
16 #include <po.hxx>
18 // Translated style names must be unique
19 static void checkStyleNames(const OString& aLanguage)
21 std::map<OString,sal_uInt16> aLocalizedStyleNames;
22 std::map<OString,sal_uInt16> aLocalizedNumStyleNames;
23 std::vector<PoEntry> repeatedEntries;
25 OString aPoPath = getenv("SRC_ROOT") +
26 OStringLiteral("/translations/source/") +
27 aLanguage + "/sw/messages.po";
28 PoIfstream aPoInput;
29 aPoInput.open(aPoPath);
30 if( !aPoInput.isOpen() )
32 std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
33 return;
36 for(;;)
38 PoEntry aPoEntry;
39 aPoInput.readEntry(aPoEntry);
40 bool bRepeated = false;
41 if( aPoInput.eof() )
43 break;
46 if( !aPoEntry.isFuzzy() && aPoEntry.getMsgCtxt().startsWith("STR_POOLCOLL") )
48 const OString& aMsgStr = aPoEntry.getMsgStr();
49 if( aMsgStr.isEmpty() )
50 continue;
51 if( aLocalizedStyleNames.find(aMsgStr) == aLocalizedStyleNames.end() )
52 aLocalizedStyleNames[aMsgStr] = 1;
53 else {
54 aLocalizedStyleNames[aMsgStr]++;
55 bRepeated = true;
58 if( !aPoEntry.isFuzzy() && aPoEntry.getMsgCtxt().startsWith("STR_POOLNUMRULE") )
60 const 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 (auto const& localizedStyleName : aLocalizedStyleNames)
77 if( localizedStyleName.second > 1 )
79 std::cout << "ERROR: Style name translations must be unique in:\n" <<
80 aPoPath << "\nLanguage: " << aLanguage << "\nDuplicated translation is: " << localizedStyleName.first <<
81 "\nSee STR_POOLCOLL_*\n\n";
84 for (auto const& localizedNumStyleName : aLocalizedNumStyleNames)
86 if( localizedNumStyleName.second > 1 )
88 std::cout << "ERROR: Style name translations must be unique in:\n" <<
89 aPoPath << "\nLanguage: " << aLanguage << "\nDuplicated translation is: " << localizedNumStyleName.first <<
90 "\nSee STR_POOLNUMRULE_*\n\n";
93 OString sPoHdrMsg;
94 aPoInput.open(aPoPath, sPoHdrMsg);
95 if( !aPoInput.isOpen() )
97 std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
98 return;
100 PoOfstream aPoOutput;
101 aPoOutput.open(aPoPath+".new");
102 PoHeader aTmp("sw/inc", sPoHdrMsg);
103 aPoOutput.writeHeader(aTmp);
104 bool bAnyError = false;
106 for(;;)
108 PoEntry aPoEntry;
109 bool bError = false;
110 aPoInput.readEntry(aPoEntry);
111 if( aPoInput.eof() )
112 break;
113 for (auto const& repeatedEntry : repeatedEntries)
115 if (repeatedEntry.getMsgId() == aPoEntry.getMsgId() && repeatedEntry.getMsgCtxt() == aPoEntry.getMsgCtxt()) {
116 bError = true;
117 break;
120 if (bError) {
121 bAnyError = true;
122 } else {
123 aPoOutput.writeEntry(aPoEntry);
126 aPoInput.close();
127 aPoOutput.close();
128 OUString aPoPathURL;
129 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPath, RTL_TEXTENCODING_UTF8), aPoPathURL);
130 if( bAnyError )
131 osl::File::move(aPoPathURL + ".new", aPoPathURL);
132 else
133 osl::File::remove(aPoPathURL + ".new");
136 // Translated spreadsheet function names must be unique
137 static void checkFunctionNames(const OString& aLanguage)
139 std::map<OString,sal_uInt16> aLocalizedFunctionNames;
140 std::map<OString,sal_uInt16> aLocalizedCoreFunctionNames;
142 std::vector<PoEntry> repeatedEntries;
144 OString aPoPaths[2];
145 OUString aPoPathURL;
147 aPoPaths[0] = getenv("SRC_ROOT") +
148 OStringLiteral("/translations/source/") +
149 aLanguage +
150 "/formula/messages.po";
151 PoIfstream aPoInput;
152 OString sPoHdrMsg;
153 aPoInput.open(aPoPaths[0], sPoHdrMsg);
154 if( !aPoInput.isOpen() )
156 std::cerr << "Warning: Cannot open " << aPoPaths[0] << std::endl;
157 return;
160 for(;;)
162 PoEntry aPoEntry;
163 aPoInput.readEntry(aPoEntry);
164 if( aPoInput.eof() )
165 break;
166 if( !aPoEntry.isFuzzy() && aPoEntry.getMsgCtxt() == "RID_STRLIST_FUNCTION_NAMES" )
168 const OString& aMsgStr = aPoEntry.getMsgStr();
169 if( aMsgStr.isEmpty() )
170 continue;
171 if( aLocalizedCoreFunctionNames.find(aMsgStr) == aLocalizedCoreFunctionNames.end() )
172 aLocalizedCoreFunctionNames[aMsgStr] = 1;
173 if( aLocalizedFunctionNames.find(aMsgStr) == aLocalizedFunctionNames.end() ) {
174 aLocalizedFunctionNames[aMsgStr] = 1;
175 } else {
176 aLocalizedFunctionNames[aMsgStr]++;
177 repeatedEntries.push_back(aPoEntry);
181 aPoInput.close();
183 aPoPaths[1] = getenv("SRC_ROOT") +
184 OStringLiteral("/translations/source/") +
185 aLanguage +
186 "/scaddins/messages.po";
187 aPoInput.open(aPoPaths[1]);
188 if( !aPoInput.isOpen() )
190 std::cerr << "Warning: Cannot open " << aPoPaths[1] << std::endl;
191 return;
194 for(;;)
196 PoEntry aPoEntry;
197 aPoInput.readEntry(aPoEntry);
198 if( aPoInput.eof() )
199 break;
200 if( !aPoEntry.isFuzzy() && aPoEntry.getMsgCtxt().startsWith("ANALYSIS_FUNCNAME") )
202 OString aMsgStr = aPoEntry.getMsgStr();
203 if( aMsgStr.isEmpty() )
204 continue;
205 if( aLocalizedCoreFunctionNames.find(aMsgStr) != aLocalizedCoreFunctionNames.end() )
206 aMsgStr += "_ADD";
207 if( aLocalizedFunctionNames.find(aMsgStr) == aLocalizedFunctionNames.end() ) {
208 aLocalizedFunctionNames[aMsgStr] = 1;
209 } else {
210 aLocalizedFunctionNames[aMsgStr]++;
211 repeatedEntries.push_back(aPoEntry);
215 aPoInput.close();
217 for (auto const& localizedFunctionName : aLocalizedFunctionNames)
219 if( localizedFunctionName.second > 1 )
221 std::cout
222 << ("ERROR: Spreadsheet function name translations must be"
223 " unique.\nLanguage: ")
224 << aLanguage << "\nDuplicated translation is: " << localizedFunctionName.first
225 << "\n\n";
229 for (int i=0;i<2;i++)
231 aPoInput.open(aPoPaths[i]);
232 if( !aPoInput.isOpen() )
233 std::cerr << "Warning: Cannot open " << aPoPaths[i] << std::endl;
234 PoOfstream aPoOutput;
235 aPoOutput.open(aPoPaths[i]+".new");
237 switch (i)
239 case 0:
241 PoHeader hd("formula/inc", sPoHdrMsg);
242 aPoOutput.writeHeader(hd);
243 break;
245 case 1:
247 PoHeader hd("scaddins/inc", sPoHdrMsg);
248 aPoOutput.writeHeader(hd);
249 break;
252 bool bAnyError = false;
254 for(;;)
256 PoEntry aPoEntry;
257 bool bError = false;
258 aPoInput.readEntry(aPoEntry);
259 if( aPoInput.eof() )
260 break;
261 for (auto const& repeatedEntry : repeatedEntries)
263 if (repeatedEntry.getMsgId() == aPoEntry.getMsgId() && repeatedEntry.getMsgCtxt() == aPoEntry.getMsgCtxt())
265 bError = true;
266 break;
269 if (bError)
271 bAnyError = true;
273 else
275 aPoOutput.writeEntry(aPoEntry);
278 aPoInput.close();
279 aPoOutput.close();
280 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPaths[i], RTL_TEXTENCODING_UTF8), aPoPathURL);
281 if( bAnyError )
282 osl::File::move(aPoPathURL + ".new", aPoPathURL);
283 else
284 osl::File::remove(aPoPathURL + ".new");
288 // In instsetoo_native/inc_openoffice/windows/msi_languages.po
289 // where an en-US string ends with '|', translation must end
290 // with '|', too.
291 static void checkVerticalBar(const OString& aLanguage)
293 OString aPoPath = getenv("SRC_ROOT") +
294 OStringLiteral("/translations/source/") +
295 aLanguage +
296 "/instsetoo_native/inc_openoffice/windows/msi_languages.po";
297 PoIfstream aPoInput;
298 aPoInput.open(aPoPath);
299 if( !aPoInput.isOpen() )
301 std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
302 return;
304 PoOfstream aPoOutput;
305 aPoOutput.open(aPoPath+".new");
306 PoHeader aTmp("instsetoo_native/inc_openoffice/windows/msi_languages");
307 aPoOutput.writeHeader(aTmp);
308 bool bError = false;
310 for(;;)
312 PoEntry aPoEntry;
313 aPoInput.readEntry(aPoEntry);
314 if( aPoInput.eof() )
315 break;
316 if( !aPoEntry.isFuzzy() && aPoEntry.getMsgId().endsWith("|") &&
317 !aPoEntry.getMsgStr().isEmpty() && !aPoEntry.getMsgStr().endsWith("|") )
319 std::cout
320 << ("ERROR: Missing '|' character at the end of translated"
321 " string.\nIt causes runtime error in installer.\nFile: ")
322 << aPoPath << std::endl
323 << "Language: " << aLanguage << std::endl
324 << "English: " << aPoEntry.getMsgId() << std::endl
325 << "Localized: " << aPoEntry.getMsgStr() << std::endl
326 << std::endl;
327 bError = true;
329 else
330 aPoOutput.writeEntry(aPoEntry);
332 aPoInput.close();
333 aPoOutput.close();
334 OUString aPoPathURL;
335 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPath, RTL_TEXTENCODING_UTF8), aPoPathURL);
336 if( bError )
337 osl::File::move(aPoPathURL + ".new", aPoPathURL);
338 else
339 osl::File::remove(aPoPathURL + ".new");
342 // In starmath/source.po Math symbol names (from symbol.src)
343 // must not contain spaces
344 static void checkMathSymbolNames(const OString& aLanguage)
346 OString aPoPath = getenv("SRC_ROOT") +
347 OStringLiteral("/translations/source/") +
348 aLanguage +
349 "/starmath/messages.po";
350 PoIfstream aPoInput;
351 aPoInput.open(aPoPath);
352 if( !aPoInput.isOpen() )
354 std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
355 return;
357 PoOfstream aPoOutput;
358 aPoOutput.open(aPoPath+".new");
359 PoHeader aTmp("starmath/inc");
360 aPoOutput.writeHeader(aTmp);
361 bool bError = false;
363 for(;;)
365 PoEntry aPoEntry;
366 aPoInput.readEntry(aPoEntry);
367 if( aPoInput.eof() )
368 break;
369 if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_UI_SYMBOL_NAMES" &&
370 !aPoEntry.getMsgStr().isEmpty() && (aPoEntry.getMsgStr().indexOf(" ") != -1) )
372 std::cout
373 << "ERROR: Math symbol names must not contain spaces.\nFile: "
374 << aPoPath << std::endl
375 << "Language: " << aLanguage << std::endl
376 << "English: " << aPoEntry.getMsgId() << std::endl
377 << "Localized: " << aPoEntry.getMsgStr() << std::endl
378 << std::endl;
379 bError = true;
381 else
382 aPoOutput.writeEntry(aPoEntry);
384 aPoInput.close();
385 aPoOutput.close();
386 OUString aPoPathURL;
387 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPath, RTL_TEXTENCODING_UTF8), aPoPathURL);
388 if( bError )
389 osl::File::move(aPoPathURL + ".new", aPoPathURL);
390 else
391 osl::File::remove(aPoPathURL + ".new");
394 int main()
398 OString aLanguages(getenv("ALL_LANGS"));
399 if( aLanguages.isEmpty() )
401 std::cerr << "Usage: LD_LIBRARY_PATH=instdir/program make cmd cmd=workdir/LinkTarget/Executable/pocheck\n";
402 return 1;
404 for(sal_Int32 i = 1;;++i) // skip en-US
406 OString aLanguage = aLanguages.getToken(i,' ');
407 if( aLanguage.isEmpty() )
408 break;
409 if( aLanguage == "qtz" )
410 continue;
411 checkStyleNames(aLanguage);
412 checkFunctionNames(aLanguage);
413 checkVerticalBar(aLanguage);
414 checkMathSymbolNames(aLanguage);
416 return 0;
418 catch (std::exception& e)
420 std::cerr << "pocheck: exception " << e.what() << std::endl;
421 return 1;
425 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */