1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <sal/config.h>
16 #include <rtl/string.hxx>
17 #include <rtl/ustring.hxx>
18 #include <osl/file.hxx>
21 // Translated style names must be unique
22 static void checkStyleNames(const OString
& aLanguage
)
24 std::map
<OString
,sal_uInt16
> aLocalizedStyleNames
;
25 std::map
<OString
,sal_uInt16
> aLocalizedNumStyleNames
;
26 std::vector
<PoEntry
> repeatedEntries
;
28 OString aPoPath
= OString::Concat(getenv("SRC_ROOT")) +
29 "/translations/source/" +
30 aLanguage
+ "/sw/messages.po";
32 aPoInput
.open(aPoPath
);
33 if( !aPoInput
.isOpen() )
35 std::cerr
<< "Warning: Cannot open " << aPoPath
<< std::endl
;
42 aPoInput
.readEntry(aPoEntry
);
43 bool bRepeated
= false;
49 if( !aPoEntry
.isFuzzy() && aPoEntry
.getMsgCtxt().startsWith("STR_POOLCOLL") )
51 const OString
& aMsgStr
= aPoEntry
.getMsgStr();
52 if( aMsgStr
.isEmpty() )
54 if( aLocalizedStyleNames
.find(aMsgStr
) == aLocalizedStyleNames
.end() )
55 aLocalizedStyleNames
[aMsgStr
] = 1;
57 aLocalizedStyleNames
[aMsgStr
]++;
61 if( !aPoEntry
.isFuzzy() && aPoEntry
.getMsgCtxt().startsWith("STR_POOLNUMRULE") )
63 const OString
& aMsgStr
= aPoEntry
.getMsgStr();
64 if( aMsgStr
.isEmpty() )
66 if( aLocalizedNumStyleNames
.find(aMsgStr
) == aLocalizedNumStyleNames
.end() )
67 aLocalizedNumStyleNames
[aMsgStr
] = 1;
69 aLocalizedNumStyleNames
[aMsgStr
]++;
74 repeatedEntries
.push_back(aPoEntry
);
78 for (auto const& localizedStyleName
: aLocalizedStyleNames
)
80 if( localizedStyleName
.second
> 1 )
82 std::cout
<< "ERROR: Style name translations must be unique in:\n" <<
83 aPoPath
<< "\nLanguage: " << aLanguage
<< "\nDuplicated translation is: " << localizedStyleName
.first
<<
84 "\nSee STR_POOLCOLL_*\n\n";
87 for (auto const& localizedNumStyleName
: aLocalizedNumStyleNames
)
89 if( localizedNumStyleName
.second
> 1 )
91 std::cout
<< "ERROR: Style name translations must be unique in:\n" <<
92 aPoPath
<< "\nLanguage: " << aLanguage
<< "\nDuplicated translation is: " << localizedNumStyleName
.first
<<
93 "\nSee STR_POOLNUMRULE_*\n\n";
97 aPoInput
.open(aPoPath
, sPoHdrMsg
);
98 if( !aPoInput
.isOpen() )
100 std::cerr
<< "Warning: Cannot open " << aPoPath
<< std::endl
;
103 PoOfstream aPoOutput
;
104 aPoOutput
.open(aPoPath
+".new");
105 PoHeader
aTmp("sw/inc", sPoHdrMsg
);
106 aPoOutput
.writeHeader(aTmp
);
107 bool bAnyError
= false;
113 aPoInput
.readEntry(aPoEntry
);
116 for (auto const& repeatedEntry
: repeatedEntries
)
118 if (repeatedEntry
.getMsgId() == aPoEntry
.getMsgId() && repeatedEntry
.getMsgCtxt() == aPoEntry
.getMsgCtxt()) {
126 aPoOutput
.writeEntry(aPoEntry
);
132 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPath
, RTL_TEXTENCODING_UTF8
), aPoPathURL
);
134 osl::File::move(aPoPathURL
+ ".new", aPoPathURL
);
136 osl::File::remove(aPoPathURL
+ ".new");
139 // Translated spreadsheet function names must be unique
140 static void checkFunctionNames(const OString
& aLanguage
)
142 std::map
<OString
,sal_uInt16
> aLocalizedFunctionNames
;
143 std::map
<OString
,sal_uInt16
> aLocalizedCoreFunctionNames
;
145 std::vector
<PoEntry
> repeatedEntries
;
150 aPoPaths
[0] = OString::Concat(getenv("SRC_ROOT")) +
151 "/translations/source/" +
153 "/formula/messages.po";
156 aPoInput
.open(aPoPaths
[0], sPoHdrMsg
);
157 if( !aPoInput
.isOpen() )
159 std::cerr
<< "Warning: Cannot open " << aPoPaths
[0] << std::endl
;
166 aPoInput
.readEntry(aPoEntry
);
169 if( !aPoEntry
.isFuzzy() && aPoEntry
.getMsgCtxt() == "RID_STRLIST_FUNCTION_NAMES" )
171 const OString
& aMsgStr
= aPoEntry
.getMsgStr();
172 if( aMsgStr
.isEmpty() )
174 if( aLocalizedCoreFunctionNames
.find(aMsgStr
) == aLocalizedCoreFunctionNames
.end() )
175 aLocalizedCoreFunctionNames
[aMsgStr
] = 1;
176 if( aLocalizedFunctionNames
.find(aMsgStr
) == aLocalizedFunctionNames
.end() ) {
177 aLocalizedFunctionNames
[aMsgStr
] = 1;
179 aLocalizedFunctionNames
[aMsgStr
]++;
180 repeatedEntries
.push_back(aPoEntry
);
186 aPoPaths
[1] = OString::Concat(getenv("SRC_ROOT")) +
187 "/translations/source/" +
189 "/scaddins/messages.po";
190 aPoInput
.open(aPoPaths
[1]);
191 if( !aPoInput
.isOpen() )
193 std::cerr
<< "Warning: Cannot open " << aPoPaths
[1] << std::endl
;
200 aPoInput
.readEntry(aPoEntry
);
203 if( !aPoEntry
.isFuzzy() && aPoEntry
.getMsgCtxt().startsWith("ANALYSIS_FUNCNAME") )
205 OString aMsgStr
= aPoEntry
.getMsgStr();
206 if( aMsgStr
.isEmpty() )
208 if( aLocalizedCoreFunctionNames
.find(aMsgStr
) != aLocalizedCoreFunctionNames
.end() )
210 if( aLocalizedFunctionNames
.find(aMsgStr
) == aLocalizedFunctionNames
.end() ) {
211 aLocalizedFunctionNames
[aMsgStr
] = 1;
213 aLocalizedFunctionNames
[aMsgStr
]++;
214 repeatedEntries
.push_back(aPoEntry
);
220 for (auto const& localizedFunctionName
: aLocalizedFunctionNames
)
222 if( localizedFunctionName
.second
> 1 )
225 << ("ERROR: Spreadsheet function name translations must be"
226 " unique.\nLanguage: ")
227 << aLanguage
<< "\nDuplicated translation is: " << localizedFunctionName
.first
232 for (int i
=0;i
<2;i
++)
234 aPoInput
.open(aPoPaths
[i
]);
235 if( !aPoInput
.isOpen() )
236 std::cerr
<< "Warning: Cannot open " << aPoPaths
[i
] << std::endl
;
237 PoOfstream aPoOutput
;
238 aPoOutput
.open(aPoPaths
[i
]+".new");
244 PoHeader
hd("formula/inc", sPoHdrMsg
);
245 aPoOutput
.writeHeader(hd
);
250 PoHeader
hd("scaddins/inc", sPoHdrMsg
);
251 aPoOutput
.writeHeader(hd
);
255 bool bAnyError
= false;
261 aPoInput
.readEntry(aPoEntry
);
264 for (auto const& repeatedEntry
: repeatedEntries
)
266 if (repeatedEntry
.getMsgId() == aPoEntry
.getMsgId() && repeatedEntry
.getMsgCtxt() == aPoEntry
.getMsgCtxt())
278 aPoOutput
.writeEntry(aPoEntry
);
283 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPaths
[i
], RTL_TEXTENCODING_UTF8
), aPoPathURL
);
285 osl::File::move(aPoPathURL
+ ".new", aPoPathURL
);
287 osl::File::remove(aPoPathURL
+ ".new");
291 // In instsetoo_native/inc_openoffice/windows/msi_languages.po
292 // where an en-US string ends with '|', translation must end
294 static void checkVerticalBar(const OString
& aLanguage
)
296 OString aPoPath
= OString::Concat(getenv("SRC_ROOT")) +
297 "/translations/source/" +
299 "/instsetoo_native/inc_openoffice/windows/msi_languages.po";
301 aPoInput
.open(aPoPath
);
302 if( !aPoInput
.isOpen() )
304 std::cerr
<< "Warning: Cannot open " << aPoPath
<< std::endl
;
307 PoOfstream aPoOutput
;
308 aPoOutput
.open(aPoPath
+".new");
309 PoHeader
aTmp("instsetoo_native/inc_openoffice/windows/msi_languages");
310 aPoOutput
.writeHeader(aTmp
);
316 aPoInput
.readEntry(aPoEntry
);
319 if( !aPoEntry
.isFuzzy() && aPoEntry
.getMsgId().endsWith("|") &&
320 !aPoEntry
.getMsgStr().isEmpty() && !aPoEntry
.getMsgStr().endsWith("|") )
323 << ("ERROR: Missing '|' character at the end of translated"
324 " string.\nIt causes runtime error in installer.\nFile: ")
325 << aPoPath
<< std::endl
326 << "Language: " << aLanguage
<< std::endl
327 << "English: " << aPoEntry
.getMsgId() << std::endl
328 << "Localized: " << aPoEntry
.getMsgStr() << std::endl
333 aPoOutput
.writeEntry(aPoEntry
);
338 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPath
, RTL_TEXTENCODING_UTF8
), aPoPathURL
);
340 osl::File::move(aPoPathURL
+ ".new", aPoPathURL
);
342 osl::File::remove(aPoPathURL
+ ".new");
345 // In starmath/source.po Math symbol names (from symbol.src)
346 // must not contain spaces
347 static void checkMathSymbolNames(const OString
& aLanguage
)
349 OString aPoPath
= OString::Concat(getenv("SRC_ROOT")) +
350 "/translations/source/" +
352 "/starmath/messages.po";
354 aPoInput
.open(aPoPath
);
355 if( !aPoInput
.isOpen() )
357 std::cerr
<< "Warning: Cannot open " << aPoPath
<< std::endl
;
360 PoOfstream aPoOutput
;
361 aPoOutput
.open(aPoPath
+".new");
362 PoHeader
aTmp("starmath/inc");
363 aPoOutput
.writeHeader(aTmp
);
369 aPoInput
.readEntry(aPoEntry
);
372 if( !aPoEntry
.isFuzzy() && aPoEntry
.getGroupId() == "RID_UI_SYMBOL_NAMES" &&
373 !aPoEntry
.getMsgStr().isEmpty() && (aPoEntry
.getMsgStr().indexOf(" ") != -1) )
376 << "ERROR: Math symbol names must not contain spaces.\nFile: "
377 << aPoPath
<< std::endl
378 << "Language: " << aLanguage
<< std::endl
379 << "English: " << aPoEntry
.getMsgId() << std::endl
380 << "Localized: " << aPoEntry
.getMsgStr() << std::endl
385 aPoOutput
.writeEntry(aPoEntry
);
390 osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPath
, RTL_TEXTENCODING_UTF8
), aPoPathURL
);
392 osl::File::move(aPoPathURL
+ ".new", aPoPathURL
);
394 osl::File::remove(aPoPathURL
+ ".new");
401 auto const env
= getenv("ALL_LANGS");
402 assert(env
!= nullptr);
403 OString
aLanguages(env
);
404 if( aLanguages
.isEmpty() )
406 std::cerr
<< "Usage: LD_LIBRARY_PATH=instdir/program make cmd cmd=workdir/LinkTarget/Executable/pocheck\n";
409 for(sal_Int32 i
= 1;;++i
) // skip en-US
411 OString aLanguage
= aLanguages
.getToken(i
,' ');
412 if( aLanguage
.isEmpty() )
414 if( aLanguage
== "qtz" )
416 checkStyleNames(aLanguage
);
417 checkFunctionNames(aLanguage
);
418 checkVerticalBar(aLanguage
);
419 checkMathSymbolNames(aLanguage
);
423 catch (std::exception
& e
)
425 std::cerr
<< "pocheck: exception " << e
.what() << std::endl
;
430 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */