[Libreoffice-commits] core.git: l10ntools/Executable_pocheck.mk l10ntools/Module_l10ntools.mk l10ntools/source Repository.mk

Andras Timar atimar at suse.com
Tue Aug 20 05:24:08 PDT 2013


 Repository.mk                   |    1 
 l10ntools/Executable_pocheck.mk |   34 +++++
 l10ntools/Module_l10ntools.mk   |    1 
 l10ntools/source/pocheck.cxx    |  267 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 303 insertions(+)

New commits:
commit 72576f439ad3eebc6947a50070f1ffabe2964b32
Author: Andras Timar <atimar at suse.com>
Date:   Tue Aug 20 13:24:19 2013 +0200

    fdo#67786 pocheck tool for checking translations
    
    Pootle has many checks, but there are cases which are not covered.
    Therefore I wrote a tool which checked three types of translation
    errors:
    
    1. Unique style names.
    2. Unique spreadsheet function names.
    3. Missing trailing '|' in Windows installer translation.
    
    Usage: make cmd cmd=solver/*/bin/pocheck
    
    It checks all languages and prints the report to stdout.
    
    Change-Id: I89aad66ea41c0ebe4a6f45beaaf86afd1a6439cc

diff --git a/Repository.mk b/Repository.mk
index ba0f291..1433f1b 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -46,6 +46,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \
 	osl_process_child \
 	pdf2xml \
 	pdfunzip \
+	pocheck \
 	propex \
 	reg2unoidl \
 	regsvrex \
diff --git a/l10ntools/Executable_pocheck.mk b/l10ntools/Executable_pocheck.mk
new file mode 100644
index 0000000..2619ac6
--- /dev/null
+++ b/l10ntools/Executable_pocheck.mk
@@ -0,0 +1,34 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Executable_Executable,pocheck))
+
+$(eval $(call gb_Executable_set_include,pocheck,\
+    -I$(SRCDIR)/l10ntools/inc \
+    $$(INCLUDE) \
+))
+
+$(eval $(call gb_Executable_use_libraries,pocheck,\
+    sal \
+))
+
+$(eval $(call gb_Executable_use_static_libraries,pocheck,\
+    transex \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,pocheck,\
+    l10ntools/source/pocheck \
+))
+
+$(eval $(call gb_Executable_use_externals,pocheck,\
+    boost_headers \
+    libxml2 \
+))
+
+# vim:set noet sw=4 ts=4:
diff --git a/l10ntools/Module_l10ntools.mk b/l10ntools/Module_l10ntools.mk
index 6e637b2..771e717 100644
--- a/l10ntools/Module_l10ntools.mk
+++ b/l10ntools/Module_l10ntools.mk
@@ -18,6 +18,7 @@ $(eval $(call gb_Module_add_targets_for_build,l10ntools,\
     Executable_xrmex \
     Executable_localize \
     Executable_transex3 \
+    Executable_pocheck \
     Executable_propex \
     Executable_treex \
     Executable_stringex \
diff --git a/l10ntools/source/pocheck.cxx b/l10ntools/source/pocheck.cxx
new file mode 100644
index 0000000..b717c7d
--- /dev/null
+++ b/l10ntools/source/pocheck.cxx
@@ -0,0 +1,267 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <iostream>
+#include <map>
+#include <rtl/string.hxx>
+#include "po.hxx"
+
+// Translated style names must be unique
+static void checkStyleNames(OString aLanguage)
+{
+    std::map<OString,sal_uInt16> aLocalizedStyleNames;
+    std::map<OString,sal_uInt16> aLocalizedNumStyleNames;
+    OString aPoPath = OString(getenv("SRC_ROOT")) +
+                      "/translations/source/"
+                      aLanguage + "/sw/source/ui/utlui.po";
+    PoIfstream aPoInput;
+    aPoInput.open(aPoPath);
+    if( !aPoInput.isOpen() )
+        std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
+
+    for(;;)
+    {
+        PoEntry aPoEntry;
+        aPoInput.readEntry(aPoEntry);
+        if( aPoInput.eof() )
+            break;
+        if( !aPoEntry.isFuzzy() && aPoEntry.getSourceFile() == "poolfmt.src" &&
+            aPoEntry.getGroupId().startsWith("STR_POOLCOLL") )
+        {
+            OString aMsgStr = aPoEntry.getMsgStr();
+            if( aMsgStr.isEmpty() )
+                continue;
+            if( aLocalizedStyleNames.find(aMsgStr) == aLocalizedStyleNames.end() )
+                aLocalizedStyleNames[aMsgStr] = 1;
+            else
+                aLocalizedStyleNames[aMsgStr]++;
+        }
+        if( !aPoEntry.isFuzzy() && aPoEntry.getSourceFile() == "poolfmt.src" &&
+            aPoEntry.getGroupId().startsWith("STR_POOLNUMRULE") )
+        {
+            OString aMsgStr = aPoEntry.getMsgStr();
+            if( aMsgStr.isEmpty() )
+                continue;
+            if( aLocalizedNumStyleNames.find(aMsgStr) == aLocalizedNumStyleNames.end() )
+                aLocalizedNumStyleNames[aMsgStr] = 1;
+            else
+                aLocalizedNumStyleNames[aMsgStr]++;
+        }
+    }
+    aPoInput.close();
+
+    for( std::map<OString,sal_uInt16>::iterator it=aLocalizedStyleNames.begin(); it!=aLocalizedStyleNames.end(); ++it)
+    {
+        if( it->second > 1 )
+        {
+            std::cout << "ERROR: Style name translations must be unique in:\n" <<
+                aPoPath << "\nLanguage: " << aLanguage << "\nDuplicated translation is: " << it->first <<
+                "\nSee STR_POOLCOLL_*\n\n";
+        }
+    }
+    for( std::map<OString,sal_uInt16>::iterator it=aLocalizedNumStyleNames.begin(); it!=aLocalizedNumStyleNames.end(); ++it)
+    {
+        if( it->second > 1 )
+        {
+            std::cout << "ERROR: Style name translations must be unique in:\n" <<
+                aPoPath << "\nLanguage: " << aLanguage << "\nDuplicated translation is: " << it->first <<
+                "\nSee STR_POOLNUMRULE_*\n\n";
+        }
+    }
+}
+
+// Translated spreadsheet function names must be unique
+static void checkFunctionNames(OString aLanguage)
+{
+    std::map<OString,sal_uInt16> aLocalizedFunctionNames;
+    std::map<OString,sal_uInt16> aLocalizedCoreFunctionNames;
+    OString aPoPath = OString(getenv("SRC_ROOT")) +
+                      "/translations/source/"
+                      aLanguage
+                      "/formula/source/core/resource.po";
+    PoIfstream aPoInput;
+    aPoInput.open(aPoPath);
+    if( !aPoInput.isOpen() )
+        std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
+
+    for(;;)
+    {
+        PoEntry aPoEntry;
+        aPoInput.readEntry(aPoEntry);
+        if( aPoInput.eof() )
+            break;
+        if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_STRLIST_FUNCTION_NAMES" )
+        {
+            OString aMsgStr = aPoEntry.getMsgStr();
+            if( aMsgStr.isEmpty() )
+                continue;
+            if( aLocalizedCoreFunctionNames.find(aMsgStr) == aLocalizedCoreFunctionNames.end() )
+                aLocalizedCoreFunctionNames[aMsgStr] = 1;
+            if( aLocalizedFunctionNames.find(aMsgStr) == aLocalizedFunctionNames.end() )
+                aLocalizedFunctionNames[aMsgStr] = 1;
+            else
+                aLocalizedFunctionNames[aMsgStr]++;
+        }
+    }
+    aPoInput.close();
+
+    aPoPath = OString(getenv("SRC_ROOT")) +
+        "/translations/source/"
+        aLanguage
+        "/scaddins/source/analysis.po";
+    aPoInput.open(aPoPath);
+    if( !aPoInput.isOpen() )
+        std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
+
+    for(;;)
+    {
+        PoEntry aPoEntry;
+        aPoInput.readEntry(aPoEntry);
+        if( aPoInput.eof() )
+            break;
+        if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_ANALYSIS_FUNCTION_NAMES" )
+        {
+            OString aMsgStr = aPoEntry.getMsgStr();
+            if( aMsgStr.isEmpty() )
+                continue;
+            if( aLocalizedCoreFunctionNames.find(aMsgStr) != aLocalizedCoreFunctionNames.end() )
+                aMsgStr += "_ADD";
+            if( aLocalizedFunctionNames.find(aMsgStr) == aLocalizedFunctionNames.end() )
+                aLocalizedFunctionNames[aMsgStr] = 1;
+            else
+                aLocalizedFunctionNames[aMsgStr]++;
+        }
+    }
+    aPoInput.close();
+
+    aPoPath = OString(getenv("SRC_ROOT")) +
+              "/translations/source/"
+               aLanguage
+              "/scaddins/source/datefunc.po";
+    aPoInput.open(aPoPath);
+    if( !aPoInput.isOpen() )
+        std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
+
+    for(;;)
+    {
+        PoEntry aPoEntry;
+        aPoInput.readEntry(aPoEntry);
+        if( aPoInput.eof() )
+            break;
+        if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_DATE_FUNCTION_NAMES" )
+        {
+            OString aMsgStr = aPoEntry.getMsgStr();
+            if( aMsgStr.isEmpty() )
+                continue;
+            if( aLocalizedCoreFunctionNames.find(aMsgStr) != aLocalizedCoreFunctionNames.end() )
+                aMsgStr += "_ADD";
+            if( aLocalizedFunctionNames.find(aMsgStr) == aLocalizedFunctionNames.end() )
+                aLocalizedFunctionNames[aMsgStr] = 1;
+            else
+                aLocalizedFunctionNames[aMsgStr]++;
+        }
+    }
+    aPoInput.close();
+
+    aPoPath = OString(getenv("SRC_ROOT")) +
+              "/translations/source/"
+               aLanguage
+              "/scaddins/source/pricing.po";
+    aPoInput.open(aPoPath);
+    if( !aPoInput.isOpen() )
+        std::cerr << "Warning: Cannot open " << aPoPath << std::endl;
+
+    for(;;)
+    {
+        PoEntry aPoEntry;
+        aPoInput.readEntry(aPoEntry);
+        if( aPoInput.eof() )
+            break;
+        if( !aPoEntry.isFuzzy() && aPoEntry.getGroupId() == "RID_PRICING_FUNCTION_NAMES" )
+        {
+            OString aMsgStr = aPoEntry.getMsgStr();
+            if( aMsgStr.isEmpty() )
+                continue;
+            if( aLocalizedCoreFunctionNames.find(aMsgStr) != aLocalizedCoreFunctionNames.end() )
+                aMsgStr += "_ADD";
+            if( aLocalizedFunctionNames.find(aMsgStr) == aLocalizedFunctionNames.end() )
+                aLocalizedFunctionNames[aMsgStr] = 1;
+            else
+                aLocalizedFunctionNames[aMsgStr]++;
+        }
+    }
+    aPoInput.close();
+    for( std::map<OString,sal_uInt16>::iterator it=aLocalizedFunctionNames.begin(); it!=aLocalizedFunctionNames.end(); ++it)
+    {
+        if( it->second > 1 )
+        {
+            std::cout << "ERROR: Spreadsheet function name translations must be unique.\n" <<
+                "Language: " << aLanguage <<
+                "\nDuplicated translation is: " << it->first << "\n\n";
+        }
+    }
+}
+
+// In instsetoo_native/inc_openoffice/windows/msi_languages.po
+// where an en-US string ends with '|', translation must end
+// with '|', too.
+static void checkVerticalBar(OString aLanguage)
+{
+    OString aPoPath = OString(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;
+
+    for(;;)
+    {
+        PoEntry aPoEntry;
+        aPoInput.readEntry(aPoEntry);
+        if( aPoInput.eof() )
+            break;
+        if( !aPoEntry.isFuzzy() && aPoEntry.getMsgId().endsWith("|") &&
+            !aPoEntry.getMsgStr().isEmpty() && !aPoEntry.getMsgStr().endsWith("|") )
+        {
+            std::cout << "ERROR: Missing '|' character at the end of translated string.\n" <<
+                "It causes runtime error in installer.\n" <<
+                "File: " << aPoPath << std::endl <<
+                "Language: " << aLanguage << std::endl <<
+                "English:   " << aPoEntry.getMsgId() << std::endl <<
+                "Localized: " << aPoEntry.getMsgStr() << std::endl << std::endl;
+        }
+    }
+    aPoInput.close();
+}
+
+int main()
+{
+    OString aLanguages(getenv("ALL_LANGS"));
+    if( aLanguages.isEmpty() )
+    {
+        std::cerr << "Usage: make cmd cmd=solver/*/bin/pocheck\n";
+        return 1;
+    }
+    for(sal_Int32 i = 1;;++i) // skip en-US
+    {
+         OString aLanguage = aLanguages.getToken(i,' ');
+         if( aLanguage.isEmpty() )
+             break;
+         if( aLanguage == "qtz" )
+             continue;
+         checkStyleNames(aLanguage);
+         checkFunctionNames(aLanguage);
+         checkVerticalBar(aLanguage);
+    }
+    return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list