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;
     }

Reply via email to