summaryrefslogtreecommitdiff
path: root/l10ntools
diff options
context:
space:
mode:
authorZolnai Tamás <zolnaitamas2000@gmail.com>2012-11-01 13:39:43 +0100
committerZolnai Tamás <zolnaitamas2000@gmail.com>2012-11-03 23:40:30 +0100
commit0fd7f81ec6765133bc2a964afd832631cd1bbf31 (patch)
tree5766461871b043c8e4ffab58f133f7fc42feee42 /l10ntools
parentef941c6e78cbab5d9d25b1fe57e483deead03a32 (diff)
Implement new treex executable
Which localize and update help tree files instead of update_tree.pl. Use it to update extensions' help. Next step: use it with general help. Change-Id: Ife9696bdd8b973ef3cf30626533e38720408179b
Diffstat (limited to 'l10ntools')
-rw-r--r--l10ntools/Executable_treex.mk36
-rw-r--r--l10ntools/Module_l10ntools.mk1
-rw-r--r--l10ntools/inc/treemerge.hxx38
-rw-r--r--l10ntools/source/localize.cxx3
-rw-r--r--l10ntools/source/treemerge.cxx304
-rw-r--r--l10ntools/source/treex.cxx60
6 files changed, 441 insertions, 1 deletions
diff --git a/l10ntools/Executable_treex.mk b/l10ntools/Executable_treex.mk
new file mode 100644
index 000000000000..41af0a8bfbc9
--- /dev/null
+++ b/l10ntools/Executable_treex.mk
@@ -0,0 +1,36 @@
+# -*- 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,treex))
+
+$(eval $(call gb_Executable_set_include,treex,\
+ -I$(SRCDIR)/l10ntools/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_Executable_use_libraries,treex,\
+ sal \
+ i18nregexp \
+))
+
+$(eval $(call gb_Executable_use_static_libraries,treex,\
+ transex \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,treex,\
+ l10ntools/source/treemerge \
+ l10ntools/source/treex \
+))
+
+$(eval $(call gb_Executable_use_externals,treex,\
+ libxml2 \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/l10ntools/Module_l10ntools.mk b/l10ntools/Module_l10ntools.mk
index e6c0cc3a8047..6efcd7f45596 100644
--- a/l10ntools/Module_l10ntools.mk
+++ b/l10ntools/Module_l10ntools.mk
@@ -39,6 +39,7 @@ $(eval $(call gb_Module_add_targets,l10ntools,\
Executable_transex3 \
Executable_renewpo \
Executable_propex \
+ Executable_treex \
StaticLibrary_transex \
Package_inc \
Package_scripts \
diff --git a/l10ntools/inc/treemerge.hxx b/l10ntools/inc/treemerge.hxx
new file mode 100644
index 000000000000..3b681126bfab
--- /dev/null
+++ b/l10ntools/inc/treemerge.hxx
@@ -0,0 +1,38 @@
+/* -*- 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/.
+ */
+
+#ifndef _TREEMERGE_INCLUDED
+#define _TREEMERGE_INCLUDED
+
+#include <libxml/tree.h>
+#include <rtl/string.hxx>
+#include <vector>
+
+class TreeParser
+{
+private:
+ xmlDocPtr m_pSource;
+ OString m_sLang;
+ bool m_bIsInitialized;
+
+public:
+ TreeParser(
+ const OString& rInputFile, const OString& rLang );
+ ~TreeParser();
+
+ bool isInitialized() const { return m_bIsInitialized; }
+ void Extract(
+ const OString& rSDFFile, const OString& rPrj, const OString& rRoot );
+ void Merge(
+ const OString &rMergeSrc, const OString &rDestinationFile,
+ const OString &rXhpRoot );
+};
+
+#endif //_TREEMERGE_INCLUDED
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/localize.cxx b/l10ntools/source/localize.cxx
index fd1d8ca4b4d0..f808af59d6cd 100644
--- a/l10ntools/source/localize.cxx
+++ b/l10ntools/source/localize.cxx
@@ -324,7 +324,8 @@ void handleFile(
{ RTL_CONSTASCII_STRINGPARAM(".xml"), "xrmex", true },
{ RTL_CONSTASCII_STRINGPARAM(".xhp"), "helpex", false },
{ RTL_CONSTASCII_STRINGPARAM(".properties"), "propex", false },
- { RTL_CONSTASCII_STRINGPARAM(".ui"), "uiex", false } };
+ { RTL_CONSTASCII_STRINGPARAM(".ui"), "uiex", false },
+ { RTL_CONSTASCII_STRINGPARAM(".tree"), "treex", false } };
for (std::size_t i = 0; i != SAL_N_ELEMENTS(commands); ++i) {
if (url.endsWithAsciiL(
commands[i].extension, commands[i].extensionLength))
diff --git a/l10ntools/source/treemerge.cxx b/l10ntools/source/treemerge.cxx
new file mode 100644
index 000000000000..12e931c6d221
--- /dev/null
+++ b/l10ntools/source/treemerge.cxx
@@ -0,0 +1,304 @@
+/* -*- 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 <fstream>
+#include <cassert>
+#include <cstring>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlstring.h>
+
+#include "export.hxx"
+#include "common.hxx"
+#include "treemerge.hxx"
+
+
+namespace
+{
+ //Write out an sdf line
+ static void lcl_WriteSDF(
+ std::ofstream &aSDFStream, const OString& rText, const OString& rPrj,
+ const OString& rActFileName, const OString& rID, const OString& rType )
+ {
+ OString sOutput( rPrj ); sOutput += "\t";
+ sOutput += rActFileName;
+ sOutput += "\t0\t";
+ sOutput += rType; sOutput += "\t";
+ sOutput += rID; sOutput += "\t\t\t\t0\ten-US\t";
+ sOutput += rText; sOutput += "\t\t\t\t";
+ aSDFStream << sOutput.getStr() << std::endl;
+ }
+
+ //Convert xmlChar* to OString
+ static OString lcl_xmlStrToOString( const xmlChar* pString )
+ {
+ xmlChar* pTemp = xmlStrdup( pString );
+ OString sResult =
+ static_cast<OString>(reinterpret_cast<sal_Char*>( pTemp ));
+ xmlFree( pTemp );
+ return sResult;
+ }
+
+ //Extract strings from nodes on all level recursively
+ static void lcl_ExtractLevel(
+ const xmlDocPtr pSource, const xmlNodePtr pRoot,
+ const xmlChar* pNodeName, std::ofstream& rSDFStream,
+ const OString& rPrj, const OString& rRoot )
+ {
+ if( !pRoot->children )
+ {
+ return;
+ }
+ for( xmlNodePtr pCurrent = pRoot->children->next;
+ pCurrent; pCurrent = pCurrent->next)
+ {
+ if (!xmlStrcmp(pCurrent->name, pNodeName))
+ {
+ xmlChar* pID = xmlGetProp(pCurrent, (const xmlChar*)("id"));
+ xmlChar* pText =
+ xmlGetProp(pCurrent, (const xmlChar*)("title"));
+ lcl_WriteSDF(
+ rSDFStream,
+ lcl_xmlStrToOString( pText ),
+ rPrj,
+ common::pathnameToken(
+ pSource->name, rRoot.getStr()),
+ lcl_xmlStrToOString( pID ),
+ lcl_xmlStrToOString( pNodeName ));
+
+ xmlFree( pID );
+ xmlFree( pText );
+
+ lcl_ExtractLevel(
+ pSource, pCurrent, (const xmlChar *)("node"),
+ rSDFStream, rPrj, rRoot );
+ }
+ }
+ }
+
+ //Update id and content of the topic
+ static xmlNodePtr lcl_UpdateTopic(
+ const xmlNodePtr pCurrent, const OString& rXhpRoot )
+ {
+ xmlNodePtr pReturn = pCurrent;
+ xmlChar* pID = xmlGetProp(pReturn, (const xmlChar*)("id"));
+ const OString sID =
+ lcl_xmlStrToOString( pID );
+ xmlFree( pID );
+
+ const sal_Int32 nFirstSlash = sID.indexOf("/");
+ //Update id attribute of topic
+ {
+ OString sNewID =
+ sID.copy( 0, nFirstSlash + 1 ) +
+ rXhpRoot.copy( rXhpRoot.lastIndexOf("/") + 1 ) +
+ sID.copy( sID.indexOf( "/", nFirstSlash + 1 ) );
+ xmlSetProp(
+ pReturn, (const xmlChar*)("id"),
+ reinterpret_cast<const xmlChar*>(sNewID.getStr()));
+ }
+
+ const OString sXhpPath =
+ rXhpRoot +
+ sID.copy(sID.indexOf("/", nFirstSlash + 1));
+ xmlDocPtr pXhpFile = xmlParseFile( sXhpPath.getStr() );
+ //if xhpfile is missing than we put this topic into comment
+ if ( !pXhpFile )
+ {
+ xmlNodePtr pTemp = pReturn;
+ xmlChar* sNewID =
+ xmlGetProp(pReturn, (const xmlChar*)("id"));
+ xmlChar* sComment =
+ xmlStrcat( xmlCharStrdup("removed "), sNewID );
+ pReturn = xmlNewComment( sComment );
+ xmlReplaceNode( pTemp, pReturn );
+ xmlFree( pTemp );
+ xmlFree( sNewID );
+ xmlFree( sComment );
+ }
+ //update topic's content on the basis of xhpfile's title
+ else
+ {
+ xmlNodePtr pXhpNode = xmlDocGetRootElement( pXhpFile );
+ for( pXhpNode = pXhpNode->children;
+ pXhpNode; pXhpNode = pXhpNode->children )
+ {
+ while( pXhpNode->type != XML_ELEMENT_NODE )
+ {
+ pXhpNode = pXhpNode->next;
+ }
+ if(!xmlStrcmp(pXhpNode->name, (const xmlChar *)("title")))
+ {
+ xmlChar* sTitle =
+ xmlNodeListGetString(pXhpFile, pXhpNode->children, 1);
+ OString sNewTitle =
+ lcl_xmlStrToOString( sTitle ).
+ replaceAll("$[officename]","%PRODUCTNAME").
+ replaceAll("$[officeversion]","%PRODUCTVERSION");
+ xmlNodeSetContent(
+ pReturn,
+ reinterpret_cast<const xmlChar*>( sNewTitle.getStr() ));
+ xmlFree( sTitle );
+ break;
+ }
+ }
+ if( !pXhpNode )
+ {
+ std::cerr
+ << "Treex error: Cannot find title in "
+ << sXhpPath.getStr() << std::endl;
+ return 0;
+ }
+ xmlFree( pXhpFile );
+ xmlCleanupParser();
+ }
+ return pReturn;
+ }
+ //Localize title attribute of help_section and node tags
+ static void lcl_MergeLevel(
+ xmlDocPtr io_pSource, const xmlNodePtr pRoot,
+ const xmlChar * pNodeName, MergeDataFile* pMergeDataFile,
+ const OString& rLang, const OString& rXhpRoot )
+ {
+ if( !pRoot->children )
+ {
+ return;
+ }
+ for( xmlNodePtr pCurrent = pRoot->children;
+ pCurrent; pCurrent = pCurrent->next)
+ {
+ if( !xmlStrcmp(pCurrent->name, pNodeName) )
+ {
+ if( pMergeDataFile )
+ {
+ xmlChar* pID = xmlGetProp(pCurrent, (const xmlChar*)("id"));
+ ResData aResData(
+ "", lcl_xmlStrToOString( pID ),
+ static_cast<OString>(io_pSource->name) );
+ xmlFree( pID );
+ aResData.sResTyp = lcl_xmlStrToOString( pNodeName );
+ PFormEntrys* pEntrys =
+ pMergeDataFile->GetPFormEntrys( &aResData );
+ if( pEntrys )
+ {
+ OString sNewText;
+ pEntrys->GetText( sNewText, STRING_TYP_TEXT, rLang );
+ xmlSetProp(
+ pCurrent, (const xmlChar*)("title"),
+ (const xmlChar*)(sNewText.getStr()));
+ }
+ }
+ lcl_MergeLevel(
+ io_pSource, pCurrent, (const xmlChar *)("node"),
+ pMergeDataFile, rLang, rXhpRoot );
+ }
+ else if( !xmlStrcmp(pCurrent->name, (const xmlChar *)("topic")) )
+ {
+ pCurrent = lcl_UpdateTopic( pCurrent, rXhpRoot );
+ }
+ }
+ }
+}
+
+//Parse tree file
+TreeParser::TreeParser(
+ const OString& rInputFile, const OString& rLang )
+ : m_pSource( 0 )
+ , m_sLang( rLang )
+ , m_bIsInitialized( false )
+{
+ m_pSource = xmlParseFile( rInputFile.getStr() );
+ if ( !m_pSource ) {
+ std::cerr
+ << "Treex error: Cannot open source file: "
+ << rInputFile.getStr() << std::endl;
+ return;
+ }
+ if( !m_pSource->name )
+ {
+ m_pSource->name = new char[strlen(rInputFile.getStr())+1];
+ strcpy( m_pSource->name, rInputFile.getStr() );
+ }
+ m_bIsInitialized = true;
+}
+
+TreeParser::~TreeParser()
+{
+}
+
+//Extract strings form source file
+void TreeParser::Extract(
+ const OString& rSDFFile, const OString& rPrj, const OString& rRoot )
+{
+ assert( m_bIsInitialized );
+ std::ofstream aSDFStream(
+ rSDFFile.getStr(), std::ios_base::out | std::ios_base::trunc );
+ if( !aSDFStream.is_open() )
+ {
+ std::cerr
+ << "Treex error: Cannot open sdffile for extract: "
+ << rSDFFile.getStr() << std::endl;
+ return;
+ }
+
+ xmlNodePtr pRootNode = xmlDocGetRootElement( m_pSource );
+ lcl_ExtractLevel(
+ m_pSource, pRootNode, (const xmlChar *)("help_section"),
+ aSDFStream, rPrj, rRoot );
+
+ xmlFreeDoc( m_pSource );
+ xmlCleanupParser();
+ aSDFStream.close();
+ m_bIsInitialized = false;
+}
+
+//Merge strings to tree file and update reference to help files(xhp)
+void TreeParser::Merge(
+ const OString &rMergeSrc, const OString &rDestinationFile,
+ const OString &rXhpRoot )
+{
+ assert( m_bIsInitialized );
+
+ const xmlNodePtr pRootNode = xmlDocGetRootElement( m_pSource );
+ if( m_sLang == "en-US" )
+ {
+ lcl_MergeLevel(
+ m_pSource, pRootNode, (const xmlChar *)("help_section"),
+ 0, m_sLang, rXhpRoot );
+ }
+ else
+ {
+ MergeDataFile aMergeDataFile(
+ rMergeSrc, static_cast<OString>( m_pSource->name ), false );
+
+ if( aMergeDataFile.GetLanguages()[0] != m_sLang )
+ {
+ std::cerr
+ << "Treex error: given language conflicts with "
+ << "language of Mergedata file: "
+ << m_sLang.getStr() << " - " << rMergeSrc.getStr() << std::endl;
+ return;
+ }
+
+ lcl_MergeLevel(
+ m_pSource, pRootNode, (const xmlChar *)("help_section"),
+ &aMergeDataFile, m_sLang, rXhpRoot );
+ }
+
+ xmlSaveFile( rDestinationFile.getStr(), m_pSource );
+ xmlFreeDoc( m_pSource );
+ xmlCleanupParser();
+ m_bIsInitialized = false;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/treex.cxx b/l10ntools/source/treex.cxx
new file mode 100644
index 000000000000..65807b1a5c0b
--- /dev/null
+++ b/l10ntools/source/treex.cxx
@@ -0,0 +1,60 @@
+/* -*- 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 "sal/main.h"
+
+#include "export.hxx"
+#include "treemerge.hxx"
+
+void WriteUsage()
+{
+ std::cout
+ << "Syntax: Treex [-p Prj] [-r Root] -i FileIn -o FileOut"
+ << " [-m DataBase] [-l l1,l2,...]\n"
+ << " Prj: Project\n"
+ << " Root: Path to project root (../.. etc.)\n"
+ << " or path to root of localized xhp files\n"
+ << " FileIn: Source files (*.tree)\n"
+ << " FileOut: Destination file (*.*)\n"
+ << " DataBase: Mergedata (*.po)\n"
+ << " -l: Restrict the handled languages; l1, l2, ... are elements of"
+ << " (de, en-US, ...)\n";
+}
+
+
+SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
+{
+ HandledArgs aArgs;
+ if( !Export::handleArguments(argc, argv, aArgs) )
+ {
+ WriteUsage();
+ return 1;
+ }
+
+ TreeParser aParser(aArgs.m_sInputFile, Export::sLanguages);
+ if( !aParser.isInitialized() )
+ {
+ return 1;
+ }
+
+ if( aArgs.m_bMergeMode || aArgs.m_sPrj.isEmpty() )
+ {
+ aParser.Merge(
+ aArgs.m_sMergeSrc, aArgs.m_sOutputFile, aArgs.m_sPrjRoot );
+ }
+ else
+ {
+ aParser.Extract(
+ aArgs.m_sOutputFile, aArgs.m_sPrj, aArgs.m_sPrjRoot );
+ }
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */