l10ntools/source/pocheck.cxx | 132 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 117 insertions(+), 15 deletions(-)
New commits: commit 297dc9b6c52a9a2451c3ac7484ae484b9590fcc3 Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Wed Jul 9 01:52:57 2025 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Wed Jul 9 18:36:20 2025 +0200 tdf#166813: improve pocheck script * Check the number of opening and closing parentheses, brackets and square brackets are the same * Check {&DialogHeading} and {&DialogDefaultBold} are at the beginning of the string. the translation here * Check [ProductName] is kept. It's just a warning so pocheck doesn't remove the translation here Change-Id: Ica06e22ec547375b84ed829da12178b5976b357c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187554 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/l10ntools/source/pocheck.cxx b/l10ntools/source/pocheck.cxx index 0dcb2d0dcef9..eaf7e41a93ee 100644 --- a/l10ntools/source/pocheck.cxx +++ b/l10ntools/source/pocheck.cxx @@ -288,6 +288,16 @@ static void checkFunctionNames(const OString& aLanguage) } } +static void printError(const OString& rPoPath, const OString& rLanguage, const PoEntry& rPoEntry, const OString& rError) +{ + std::cout << "ERROR: " << rError << std::endl + << "File: " << rPoPath << std::endl + << "Language: " << rLanguage << std::endl + << "English: " << rPoEntry.getMsgId() << std::endl + << "Localized: " << rPoEntry.getMsgStr() << std::endl + << std::endl; +} + // In instsetoo_native/inc_openoffice/windows/msi_languages.po // where an en-US string ends with '|', translation must end // with '|', too. @@ -319,14 +329,9 @@ static void checkVerticalBar(const OString& aLanguage) if( !aPoEntry.isFuzzy() && aPoEntry.getMsgId().endsWith("|") && !aPoEntry.getMsgStr().isEmpty() && !aPoEntry.getMsgStr().endsWith("|") ) { - std::cout - << ("ERROR: Missing '|' character at the end of translated" - " string. It causes runtime error in installer. File: ") - << aPoPath << std::endl - << "Language: " << aLanguage << std::endl - << "English: " << aPoEntry.getMsgId() << std::endl - << "Localized: " << aPoEntry.getMsgStr() << std::endl - << std::endl; + OString aError("Missing '|' character at the end of translated" + " string. It causes runtime error in installer."_ostr); + printError(aPoPath, aLanguage, aPoEntry, aError); bError = true; } else @@ -342,6 +347,108 @@ static void checkVerticalBar(const OString& aLanguage) osl::File::remove(aPoPathURL + ".new"); } +static void checkMalformedString(const OString& aLanguage) +{ + OString aPoPath = OString::Concat(getenv("SRC_ROOT")) + + "/translations/source/" + + aLanguage + + "/instsetoo_native/inc_openoffice/windows/msi_languages.po"; + PoIfstream aPoInput; + aPoInput.open(aPoPath); + if( !aPoInput.isOpen() ) + { + std::cerr << "Warning: Cannot open " << aPoPath << std::endl; + return; + } + PoOfstream aPoOutput; + aPoOutput.open(aPoPath+".new"); + PoHeader aTmp("instsetoo_native/inc_openoffice/windows/msi_languages"); + aPoOutput.writeHeader(aTmp); + bool bError = false; + + for(;;) + { + PoEntry aPoEntry; + aPoInput.readEntry(aPoEntry); + if( aPoInput.eof() ) + break; + if(!aPoEntry.isFuzzy() && !aPoEntry.getMsgStr().isEmpty()) + { + if (aPoEntry.getMsgId().indexOf("[ProductName]") != -1 && + aPoEntry.getMsgStr().indexOf("[ProductName]") == -1) + { + // just a warning. bError = false + printError(aPoPath, aLanguage, aPoEntry, "Incorrect [ProductName]."_ostr); + } + + OString aStr = aPoEntry.getMsgStr(); + sal_Int32 nPos(0); + sal_Int32 nOpeningBracketsCount(0); + sal_Int32 nClosingBracketsCount(0); + sal_Int32 nOpeningSquareBracketsCount(0); + sal_Int32 nClosingSquareBracketsCount(0); + sal_Int32 nOpeningParenthesesCount(0); + sal_Int32 nClosingParenthesesCount(0); + + // Check the number of opening and closing characters for + // brackets, square brackets and parentheses match + while (nPos < aStr.getLength()) + { + const sal_Unicode cCurrentChar = aStr[nPos]; + if (cCurrentChar == '{') + ++nOpeningBracketsCount; + else if (cCurrentChar == '}') + ++nClosingBracketsCount; + else if (cCurrentChar == '[') + ++nOpeningSquareBracketsCount; + else if (cCurrentChar == ']') + ++nClosingSquareBracketsCount; + else if (cCurrentChar == '(') + ++nOpeningParenthesesCount; + else if (cCurrentChar == ')') + ++nClosingParenthesesCount; + ++nPos; + } + + // See instsetoo_native/inc_openoffice/windows/msi_templates/TextStyl.idt + if ((aPoEntry.getMsgId().startsWith("{&DialogDefaultBold}") && + !aPoEntry.getMsgStr().startsWith("{&DialogDefaultBold}")) || + (aPoEntry.getMsgId().startsWith("{&DialogHeading}") && + !aPoEntry.getMsgStr().startsWith("{&DialogHeading}"))) + { + printError(aPoPath, aLanguage, aPoEntry, "Incorrect TextStyle."_ostr); + bError = true; + } + else if (nOpeningBracketsCount != nClosingBracketsCount) + { + printError(aPoPath, aLanguage, aPoEntry, "Number of Opening and Closing brackets doesn't match."_ostr); + bError = true; + } + else if (nOpeningSquareBracketsCount != nClosingSquareBracketsCount) + { + printError(aPoPath, aLanguage, aPoEntry, "Number of Opening and Closing square brackets doesn't match."_ostr); + bError = true; + } + else if (nOpeningParenthesesCount != nClosingParenthesesCount) + { + printError(aPoPath, aLanguage, aPoEntry, "Number of Opening and Closing parentheses doesn't match."_ostr); + bError = true; + } + else + aPoOutput.writeEntry(aPoEntry); + } + else + aPoOutput.writeEntry(aPoEntry); + } + aPoInput.close(); + aPoOutput.close(); + OUString aPoPathURL; + osl::FileBase::getFileURLFromSystemPath(OStringToOUString(aPoPath, RTL_TEXTENCODING_UTF8), aPoPathURL); + if( bError ) + osl::File::move(aPoPathURL + ".new", aPoPathURL); + else + osl::File::remove(aPoPathURL + ".new"); +} // In starmath/source.po Math symbol names (from symbol.src) // must not contain spaces static void checkMathSymbolNames(const OString& aLanguage) @@ -372,13 +479,7 @@ static void checkMathSymbolNames(const OString& aLanguage) if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_UI_SYMBOL_NAMES" && !aPoEntry.getMsgStr().isEmpty() && (aPoEntry.getMsgStr().indexOf(" ") != -1) ) { - std::cout - << "ERROR: Math symbol names must not contain spaces. File: " - << aPoPath << std::endl - << "Language: " << aLanguage << std::endl - << "English: " << aPoEntry.getMsgId() << std::endl - << "Localized: " << aPoEntry.getMsgStr() << std::endl - << std::endl; + printError(aPoPath, aLanguage, aPoEntry, "Math symbol names must not contain spaces."_ostr); bError = true; } else @@ -417,6 +518,7 @@ int main() checkFunctionNames(aLanguage); checkVerticalBar(aLanguage); checkMathSymbolNames(aLanguage); + checkMalformedString(aLanguage); } return 0; }