[Libreoffice-commits] core.git: l10ntools/inc l10ntools/source translations

Zolnai Tamás zolnaitamas2000 at gmail.com
Sat Mar 16 04:28:52 PDT 2013


 l10ntools/inc/cfgmerge.hxx       |   23 --
 l10ntools/inc/export.hxx         |   12 +
 l10ntools/inc/helpmerge.hxx      |   10 -
 l10ntools/inc/lngmerge.hxx       |   12 -
 l10ntools/inc/po.hxx             |   29 +--
 l10ntools/inc/propmerge.hxx      |    3 
 l10ntools/inc/stringmerge.hxx    |    3 
 l10ntools/inc/treemerge.hxx      |    3 
 l10ntools/inc/xrmmerge.hxx       |   28 ---
 l10ntools/source/cfgmerge.cxx    |   65 ++-----
 l10ntools/source/common.hxx      |   49 -----
 l10ntools/source/export.cxx      |   73 +++-----
 l10ntools/source/export2.cxx     |   50 +++++
 l10ntools/source/helpex.cxx      |    6 
 l10ntools/source/helpmerge.cxx   |   68 ++-----
 l10ntools/source/lngex.cxx       |    3 
 l10ntools/source/lngmerge.cxx    |   38 +---
 l10ntools/source/localize.cxx    |  353 ++++++++++++++++-----------------------
 l10ntools/source/po.cxx          |  122 ++++++-------
 l10ntools/source/propex.cxx      |    5 
 l10ntools/source/propmerge.cxx   |   40 +---
 l10ntools/source/stringex.cxx    |    3 
 l10ntools/source/stringmerge.cxx |   42 +---
 l10ntools/source/treemerge.cxx   |   47 +----
 l10ntools/source/treex.cxx       |    3 
 l10ntools/source/uimerge.cxx     |   33 ++-
 l10ntools/source/xrmmerge.cxx    |   76 ++------
 translations                     |    2 
 28 files changed, 496 insertions(+), 705 deletions(-)

New commits:
commit 15a13bafccb96e6ab0cc5a23af6dd46715fa22c5
Author: Zolnai Tamás <zolnaitamas2000 at gmail.com>
Date:   Fri Mar 15 15:42:05 2013 +0100

    Get rid of generating temporary sdf file
    
    Working:
    1. Localize add header to po files.
    2. Executables append po entries to po files.
    3. Localize delete entryless po files and empty directories
    
    Plus a bunch of clean up.
    
    Change-Id: I58e300eaee4cee948203cc9d3e642ca9462d0d26

diff --git a/l10ntools/inc/cfgmerge.hxx b/l10ntools/inc/cfgmerge.hxx
index 316c9de..0598728 100644
--- a/l10ntools/inc/cfgmerge.hxx
+++ b/l10ntools/inc/cfgmerge.hxx
@@ -26,6 +26,7 @@
 #include <vector>
 
 #include "boost/unordered_map.hpp"
+#include "po.hxx"
 
 typedef boost::unordered_map<rtl::OString, rtl::OString, rtl::OStringHash> OStringHashMap;
 
@@ -137,28 +138,18 @@ public:
 };
 
 //
-// class CfgOutputParser
-//
-
-class CfgOutputParser : public CfgParser
-{
-protected:
-    std::ofstream pOutputStream;
-public:
-    CfgOutputParser(const rtl::OString &rOutputFile);
-    virtual ~CfgOutputParser();
-};
-
-//
 // class CfgExport
 //
 
-class CfgExport : public CfgOutputParser
+class CfgExport : public CfgParser
 {
 private:
     rtl::OString sPrj;
     rtl::OString sPath;
     std::vector<rtl::OString> aLanguages;
+
+    PoOfstream pOutputStream;
+
 protected:
     virtual void WorkOnText(
         rtl::OString &rText,
@@ -180,7 +171,7 @@ public:
 // class CfgMerge
 //
 
-class CfgMerge : public CfgOutputParser
+class CfgMerge : public CfgParser
 {
 private:
     MergeDataFile *pMergeDataFile;
@@ -190,6 +181,8 @@ private:
     rtl::OString sFilename;
     sal_Bool bEnglish;
 
+    std::ofstream pOutputStream;
+
 protected:
     virtual void WorkOnText(rtl::OString &rText, const rtl::OString &rLangIndex);
 
diff --git a/l10ntools/inc/export.hxx b/l10ntools/inc/export.hxx
index 409e616..050ded5 100644
--- a/l10ntools/inc/export.hxx
+++ b/l10ntools/inc/export.hxx
@@ -21,6 +21,7 @@
 #define _EXPORT_HXX
 
 #include "sal/config.h"
+#include "po.hxx"
 
 #include <cstddef>
 #include <fstream>
@@ -274,7 +275,12 @@ class Export
 private:
     WordTransformer *pWordTransformer;
 
-    std::ofstream aOutput;
+    union
+    {
+        std::ofstream* mSimple;
+        PoOfstream* mPo;
+
+    } aOutput;
 
     ResStack aResStack;                 // stack for parsing recursive
 
@@ -307,6 +313,10 @@ public:
 
     static bool handleArguments(int argc, char * argv[], HandledArgs& o_aHandledArgs);
     static void writeUsage(const OString& rName, const OString& rFileType);
+    static void writePoEntry(const OString& rExecutable, PoOfstream& rPoStream, const OString& rSourceFile,
+                             const OString& rResType, const OString& rGroupId, const OString& rLocalId,
+                             const OString& rHelpText, const OString& rText,
+                             const PoEntry::TYPE eType = PoEntry::TTEXT);
 
     static void InitLanguages( bool bMergeMode = false );
     static void InitForcedLanguages( bool bMergeMode = false );
diff --git a/l10ntools/inc/helpmerge.hxx b/l10ntools/inc/helpmerge.hxx
index 77f1dd8..d248d9c 100644
--- a/l10ntools/inc/helpmerge.hxx
+++ b/l10ntools/inc/helpmerge.hxx
@@ -42,14 +42,14 @@ public:
     HelpParser( const rtl::OString &rHelpFile );
     ~HelpParser(){};
 
-/// Method creates/append a SDF file with the content of a parsed XML file
+/// Method append a PO file with the content of a parsed XML file
 /// @PRECOND rHelpFile is valid
-    static bool CreateSDF( const rtl::OString &rSDFFile_in, const rtl::OString &rPrj_in, const rtl::OString &rRoot_in,
-                           const rtl::OString &sHelpFile, XMLFile *pXmlFile, const rtl::OString &rGsi1 );
+    static bool CreatePO( const rtl::OString &rPOFile_in, const rtl::OString &sHelpFile,
+                          XMLFile *pXmlFile, const rtl::OString &rGsi1 );
 
-/// Method merges the String from the SDFfile into XMLfile. Both Strings must
+/// Method merges the String from the POfile into XMLfile. Both Strings must
 /// point to existing files.
-    bool Merge( const rtl::OString &rSDFFile_in, const rtl::OString &rDestinationFile_in ,
+    bool Merge( const rtl::OString &rPOFile_in, const rtl::OString &rDestinationFile_in ,
         const rtl::OString& sLanguage , MergeDataFile& aMergeDataFile );
 
 private:
diff --git a/l10ntools/inc/lngmerge.hxx b/l10ntools/inc/lngmerge.hxx
index 3995bd7..d18bce3 100644
--- a/l10ntools/inc/lngmerge.hxx
+++ b/l10ntools/inc/lngmerge.hxx
@@ -23,13 +23,12 @@
 #include <vector>
 
 #include "export.hxx"
+#include "po.hxx"
 
 typedef std::vector< rtl::OString* > LngLineList;
 
 #define LNG_OK              0x0000
 #define LNG_COULD_NOT_OPEN  0x0001
-#define SDF_OK              0x0002
-#define SDF_COULD_NOT_OPEN  0x0003
 
 //
 // class LngParser
@@ -47,18 +46,15 @@ private:
     bool isNextGroup(rtl::OString &sGroup_out, const rtl::OString &sLine_in);
     void ReadLine(const rtl::OString &rLine_in,
         OStringHashMap &rText_inout);
-    void WriteSDF(std::ofstream &aSDFStream, OStringHashMap &rText_inout,
-        const rtl::OString &rPrj, const rtl::OString &rRoot,
+    void WritePO(PoOfstream &aPOStream, OStringHashMap &rText_inout,
         const rtl::OString &rActFileName, const rtl::OString &rID);
 public:
     LngParser(const rtl::OString &rLngFile,
         sal_Bool bULFFormat);
     ~LngParser();
 
-    sal_Bool CreateSDF(const rtl::OString &rSDFFile,
-        const rtl::OString &rPrj,
-        const rtl::OString &rRoot);
-    sal_Bool Merge(const rtl::OString &rSDFFile,
+    sal_Bool CreatePO( const rtl::OString &rPOFile );
+    sal_Bool Merge(const rtl::OString &rPOFile,
         const rtl::OString &rDestinationFile);
 };
 
diff --git a/l10ntools/inc/po.hxx b/l10ntools/inc/po.hxx
index f2edb06..5ffad8e 100755
--- a/l10ntools/inc/po.hxx
+++ b/l10ntools/inc/po.hxx
@@ -40,15 +40,13 @@ public:
     friend class PoOfstream;
     friend class PoIfstream;
 
-    enum SDFPART { PROJECT, SOURCEFILE, DUMMY, RESOURCETYPE, GROUPID,
-                    LOCALID, HELPID, PLATFORM, WIDTH, LANGUAGEID,
-                    TEXT, HELPTEXT, QUICKHELPTEXT, TITLE, TIMESTAMP };
-    enum TYPE { TTEXT=TEXT, TQUICKHELPTEXT=QUICKHELPTEXT, TTITLE=TITLE };
-    enum Exception { INVALIDSDFLINE };
+    enum TYPE { TTEXT, TQUICKHELPTEXT, TTITLE };
+    enum Exception { NOSOURCFILE, NORESTYPE, NOGROUPID, NOSTRING, WRONGHELPTEXT };
 
                     PoEntry();
-                    PoEntry(const OString& rSDFLine,
-                            const TYPE eType = TTEXT);
+                    PoEntry( const OString& rSourceFile, const OString& rResType, const OString& rGroupId,
+                             const OString& rLocalId, const OString& rHelpText, const OString& rText,
+                             const TYPE eType = TTEXT );
                     ~PoEntry();
 
                     PoEntry( const PoEntry& rPo );
@@ -63,8 +61,8 @@ public:
     OString         getMsgStr() const;
     bool            isFuzzy() const;
     OString         getKeyId() const;
-    void            setMsgId(const OString& rUnTransStr);
-    void            setMsgStr(const OString& rTransStr);
+    void            setMsgId(const OString& rMsgId);
+    void            setMsgStr(const OString& rMsgStr);
     void            setFuzzy(const bool bFuzzy);
 
     static bool     IsInSameComp(const PoEntry& rPo1,const PoEntry& rPo2);
@@ -93,8 +91,7 @@ public:
                     ~PoHeader();
 };
 
-/** Interface to write po entry to files as output streams
-*/
+/// Interface to write po entry to files as output streams
 class PoOfstream: private boost::noncopyable
 {
 private:
@@ -103,18 +100,21 @@ private:
     bool            m_bIsAfterHeader;
 
 public:
+
+    enum OpenMode { TRUNC, APP };
+
             PoOfstream();
+            PoOfstream(const OString& rFileName, OpenMode aMode = TRUNC );
             ~PoOfstream();
     bool    isOpen() const  { return m_aOutPut.is_open(); }
 
-    void    open(const OString& rFileName);
+    void    open(const OString& rFileName, OpenMode aMode = TRUNC );
     void    close();
     void    writeHeader(const PoHeader& rHeader);
     void    writeEntry(const PoEntry& rPo);
 };
 
-/** Interface to read po entry from files as input streams
-*/
+/// Interface to read po entry from files as input streams
 class PoIfstream: private boost::noncopyable
 {
 private:
@@ -127,6 +127,7 @@ public:
     enum Exception { INVALIDENTRY };
 
             PoIfstream();
+            PoIfstream( const OString& rFileName );
             ~PoIfstream();
     bool    isOpen() const  { return m_aInPut.is_open(); }
     bool    eof() const     { return m_bEof; }
diff --git a/l10ntools/inc/propmerge.hxx b/l10ntools/inc/propmerge.hxx
index a44649c..b6e2a0b 100644
--- a/l10ntools/inc/propmerge.hxx
+++ b/l10ntools/inc/propmerge.hxx
@@ -33,8 +33,7 @@ public:
     ~PropParser();
 
     bool isInitialized() const { return m_bIsInitialized; }
-    void Extract(
-        const OString& rSDFFile, const OString& rPrj, const OString& rRoot );
+    void Extract( const OString& rPOFile );
     void Merge( const OString &rMergeSrc, const OString &rDestinationFile );
 };
 
diff --git a/l10ntools/inc/stringmerge.hxx b/l10ntools/inc/stringmerge.hxx
index 01a7b9b..be18904 100644
--- a/l10ntools/inc/stringmerge.hxx
+++ b/l10ntools/inc/stringmerge.hxx
@@ -32,8 +32,7 @@ public:
     ~StringParser();
 
     bool isInitialized() const { return m_bIsInitialized; }
-    void Extract(
-        const OString& rSDFFile, const OString& rPrj, const OString& rRoot );
+    void Extract( const OString& rPOFile );
     void Merge(
         const OString &rMergeSrc, const OString &rDestinationFile );
 };
diff --git a/l10ntools/inc/treemerge.hxx b/l10ntools/inc/treemerge.hxx
index 98f5a02..d3d15af 100644
--- a/l10ntools/inc/treemerge.hxx
+++ b/l10ntools/inc/treemerge.hxx
@@ -33,8 +33,7 @@ public:
     ~TreeParser();
 
     bool isInitialized() const { return m_bIsInitialized; }
-    void Extract(
-        const OString& rSDFFile, const OString& rPrj, const OString& rRoot );
+    void Extract( const OString& rPOFile );
     void Merge(
         const OString &rMergeSrc, const OString &rDestinationFile,
         const OString &rXhpRoot );
diff --git a/l10ntools/inc/xrmmerge.hxx b/l10ntools/inc/xrmmerge.hxx
index e9839ce..c5671eb 100644
--- a/l10ntools/inc/xrmmerge.hxx
+++ b/l10ntools/inc/xrmmerge.hxx
@@ -20,6 +20,7 @@
 #include "sal/config.h"
 
 #include <fstream>
+#include "po.hxx"
 
 //
 // XRMResParser
@@ -37,9 +38,8 @@ private:
     rtl::OString sCurrentOpenTag;
     rtl::OString sCurrentCloseTag;
     rtl::OString sCurrentText;
-    std::vector<rtl::OString> aLanguages;
-
 protected:
+    std::vector<rtl::OString> aLanguages;
     rtl::OString GetAttribute( const rtl::OString &rToken, const rtl::OString &rAttribute );
     void Error( const rtl::OString &rError );
 
@@ -74,32 +74,16 @@ public:
 };
 
 //
-// class XRMResOutputParser
-//
-
-class XRMResOutputParser : public XRMResParser
-{
-private:
-    std::vector<rtl::OString> aLanguages;
-protected:
-    std::ofstream pOutputStream;
-public:
-    XRMResOutputParser ( const rtl::OString &rOutputFile );
-    virtual ~XRMResOutputParser();
-};
-
-//
 // XRMResExport
 //
 
-class XRMResExport : public XRMResOutputParser
+class XRMResExport : public XRMResParser
 {
 private:
     ResData *pResData;
     rtl::OString sPrj;
     rtl::OString sPath;
-    std::vector<rtl::OString> aLanguages;
-
+    PoOfstream pOutputStream;
 protected:
     void WorkOnDesc(
         const rtl::OString &rOpenTag,
@@ -128,13 +112,13 @@ public:
 // class XRMResMerge
 //
 
-class XRMResMerge : public XRMResOutputParser
+class XRMResMerge : public XRMResParser
 {
 private:
     MergeDataFile *pMergeDataFile;
     rtl::OString sFilename;
     ResData *pResData;
-    std::vector<rtl::OString> aLanguages;
+    std::ofstream pOutputStream;
 
 protected:
     void WorkOnDesc(
diff --git a/l10ntools/source/cfgmerge.cxx b/l10ntools/source/cfgmerge.cxx
index e380b223..50329fa 100644
--- a/l10ntools/source/cfgmerge.cxx
+++ b/l10ntools/source/cfgmerge.cxx
@@ -73,8 +73,7 @@ FILE * init(int argc, char ** argv) {
         global::parser.reset(
             new CfgExport(
                 aArgs.m_sOutputFile.getStr(), aArgs.m_sPrj.getStr(),
-                common::pathnameToken(global::inputPathname.getStr(),
-                aArgs.m_sPrjRoot.getStr())));
+                global::inputPathname ));
     }
 
     return pFile;
@@ -355,30 +354,6 @@ void CfgParser::Error(const rtl::OString& rError)
 }
 
 //
-// class CfgOutputParser
-//
-
-CfgOutputParser::CfgOutputParser(const rtl::OString &rOutputFile)
-{
-    pOutputStream.open(
-        rOutputFile.getStr(), std::ios_base::out | std::ios_base::trunc);
-    if (!pOutputStream.is_open())
-    {
-        rtl::OStringBuffer sError(RTL_CONSTASCII_STRINGPARAM("ERROR: Unable to open output file: "));
-        sError.append(rOutputFile);
-        Error(sError.makeStringAndClear());
-        std::exit(EXIT_FAILURE);
-    }
-}
-
-/*****************************************************************************/
-CfgOutputParser::~CfgOutputParser()
-/*****************************************************************************/
-{
-    pOutputStream.close();
-}
-
-//
 // class CfgExport
 //
 
@@ -389,10 +364,15 @@ CfgExport::CfgExport(
         const rtl::OString &rFilePath
 )
 /*****************************************************************************/
-                : CfgOutputParser( rOutputFile ),
-                sPrj( rProject ),
+                : sPrj( rProject ),
                 sPath( rFilePath )
 {
+    pOutputStream.open( rOutputFile, PoOfstream::APP );
+    if (!pOutputStream.isOpen())
+    {
+        std::cerr << "ERROR: Unable to open output file: " << rOutputFile << "\n";
+        std::exit(EXIT_FAILURE);
+    }
     Export::InitLanguages( false );
     aLanguages = Export::GetLanguages();
 }
@@ -401,6 +381,7 @@ CfgExport::CfgExport(
 CfgExport::~CfgExport()
 /*****************************************************************************/
 {
+    pOutputStream.close();
 }
 
 /*****************************************************************************/
@@ -432,19 +413,9 @@ void CfgExport::WorkOnResourceEnd()
 
                 sText = Export::UnquoteHTML( sText );
 
-                rtl::OString sOutput( sPrj ); sOutput += "\t";
-                sOutput += sPath;
-                sOutput += "\t0\t";
-                sOutput += pStackData->sResTyp; sOutput += "\t";
-                sOutput += sGroupId; sOutput += "\t";
-                sOutput += sLocalId; sOutput += "\t\t\t0\t";
-                sOutput += sCur;
-                sOutput += "\t";
-
-                sOutput += sText; sOutput += "\t";
-                sOutput += sXComment; sOutput += "\t\t\t";
-
-                pOutputStream << sOutput.getStr() << '\n';
+                Export::writePoEntry(
+                    "Cfgex", pOutputStream, sPath, pStackData->sResTyp,
+                    sGroupId, sLocalId, sXComment, sText);
             }
         }
     }
@@ -466,12 +437,19 @@ void CfgExport::WorkOnText(
 CfgMerge::CfgMerge(
     const rtl::OString &rMergeSource, const rtl::OString &rOutputFile,
     const rtl::OString &rFilename)
-                : CfgOutputParser( rOutputFile ),
-                pMergeDataFile( NULL ),
+                : pMergeDataFile( NULL ),
                 pResData( NULL ),
                 sFilename( rFilename ),
                 bEnglish( sal_False )
 {
+    pOutputStream.open(
+        rOutputFile.getStr(), std::ios_base::out | std::ios_base::trunc);
+    if (!pOutputStream.is_open())
+    {
+        std::cerr << "ERROR: Unable to open output file: " << rOutputFile << "\n";
+        std::exit(EXIT_FAILURE);
+    }
+
     if (rMergeSource.getLength())
     {
         pMergeDataFile = new MergeDataFile(
@@ -491,6 +469,7 @@ CfgMerge::CfgMerge(
 CfgMerge::~CfgMerge()
 /*****************************************************************************/
 {
+    pOutputStream.close();
     delete pMergeDataFile;
     delete pResData;
 }
diff --git a/l10ntools/source/common.hxx b/l10ntools/source/common.hxx
index 0129c6a..6c2d2c7 100644
--- a/l10ntools/source/common.hxx
+++ b/l10ntools/source/common.hxx
@@ -69,55 +69,6 @@ inline rtl::OUString pathnameToAbsoluteUrl(rtl::OUString const & pathname) {
     return url;
 }
 
-inline rtl::OString pathnameToken(char const * pathname, char const * root) {
-    rtl::OUString full;
-    if (!rtl_convertStringToUString(
-            &full.pData, pathname, rtl_str_getLength(pathname),
-            osl_getThreadTextEncoding(),
-            (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
-             | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
-             | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
-    {
-        std::cerr << "Error: Cannot convert input pathname to UTF-16\n";
-        std::exit(EXIT_FAILURE);
-    }
-    full = pathnameToAbsoluteUrl(full);
-    if (root == 0) {
-        std::cerr << "Error: No project root argument\n";
-        std::exit(EXIT_FAILURE);
-    }
-    rtl::OUString base;
-    if (!rtl_convertStringToUString(
-            &base.pData, root, rtl_str_getLength(root),
-            osl_getThreadTextEncoding(),
-            (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
-             | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
-             | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
-    {
-        std::cerr << "Error: Cannot convert project root to UTF-16\n";
-        std::exit(EXIT_FAILURE);
-    }
-    base = rtl::Uri::convertRelToAbs(full, base);
-    if (full.getLength() <= base.getLength() || base.isEmpty()
-        || base[base.getLength() - 1] != '/'
-        || full[base.getLength() - 1] != '/')
-    {
-        std::cerr << "Error: Cannot extract suffix from input pathname\n";
-        std::exit(EXIT_FAILURE);
-    }
-    full = full.copy(base.getLength()).replace('/', '\\');
-    rtl::OString suffix;
-    if (!full.convertToString(
-            &suffix, osl_getThreadTextEncoding(),
-            (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
-             | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
-    {
-        std::cerr << "Error: Cannot convert suffix from UTF-16\n";
-        std::exit(EXIT_FAILURE);
-    }
-    return suffix;
-}
-
 }
 
 #endif
diff --git a/l10ntools/source/export.cxx b/l10ntools/source/export.cxx
index bb6e1c5..259bdd2 100644
--- a/l10ntools/source/export.cxx
+++ b/l10ntools/source/export.cxx
@@ -37,7 +37,6 @@ void YYWarning( const char * );
 
 namespace {
 
-rtl::OString sActFileName; //TODO
 MergeDataFile * pMergeDataFile = 0; //TODO
 
 namespace global {
@@ -77,9 +76,6 @@ FILE * init(int argc, char ** argv) {
         global::exporter.reset(
             new Export(aArgs.m_sMergeSrc.getStr(), aArgs.m_sOutputFile.getStr()));
     } else {
-        sActFileName =
-            common::pathnameToken(
-                global::inputPathname.getStr(), global::prjRoot.getStr());
         global::exporter.reset(new Export(aArgs.m_sOutputFile.getStr()));
     }
 
@@ -190,8 +186,8 @@ Export::Export(const rtl::OString &rOutput)
     // used when export is enabled
 
     // open output stream
-    aOutput.open(rOutput.getStr(), std::ios_base::out | std::ios_base::trunc);
-    if (!aOutput.is_open()) {
+    aOutput.mPo = new PoOfstream( rOutput, PoOfstream::APP );
+    if (!aOutput.mPo->isOpen()) {
         fprintf(stderr, "ERROR : Can't open file %s\n", rOutput.getStr());
         exit ( -1 );
     }
@@ -221,7 +217,8 @@ Export::Export(const rtl::OString &rMergeSource, const rtl::OString &rOutput)
     // used when merge is enabled
 
     // open output stream
-    aOutput.open(rOutput.getStr(), std::ios_base::out | std::ios_base::trunc);
+    aOutput.mSimple = new std::ofstream();
+    aOutput.mSimple->open(rOutput.getStr(), std::ios_base::out | std::ios_base::trunc);
 }
 
 /*****************************************************************************/
@@ -247,7 +244,16 @@ Export::~Export()
 {
     if( pParseQueue )
         delete pParseQueue;
-    aOutput.close();
+    if ( bMergeMode )
+    {
+        aOutput.mSimple->close();
+        delete aOutput.mSimple;
+    }
+    else
+    {
+        aOutput.mPo->close();
+        delete aOutput.mPo;
+    }
     for ( size_t i = 0, n = aResStack.size(); i < n;  ++i )
         delete aResStack[ i ];
     aResStack.clear();
@@ -936,25 +942,18 @@ sal_Bool Export::WriteData( ResData *pResData, sal_Bool bCreateNew )
         if (sXText.isEmpty())
             sXText = "-";
 
-        rtl::OString sOutput( sProject ); sOutput += "\t";
-        if ( !sRoot.isEmpty())
-            sOutput += sActFileName;
-        sOutput += "\t0\t";
-        sOutput += pResData->sResTyp; sOutput += "\t";
-        sOutput += sGID; sOutput += "\t";
-        sOutput += sLID; sOutput += "\t";
-        sOutput += pResData->sHelpId; sOutput   += "\t";
-        sOutput += pResData->sPForm; sOutput    += "\t";
-        sOutput += rtl::OString::valueOf(pResData->nWidth); sOutput += "\t";
-        sOutput += "en-US"; sOutput += "\t";
+        writePoEntry(
+            "Transex3", *aOutput.mPo, global::inputPathname,
+            pResData->sResTyp, sGID, sLID, sXHText, sXText);
+        if( !sXQHText.isEmpty() )
+            writePoEntry(
+                "Transex3", *aOutput.mPo, global::inputPathname, pResData->sResTyp,
+                sGID, sLID, OString(), sXQHText, PoEntry::TQUICKHELPTEXT );
 
-
-        sOutput += sXText; sOutput  += "\t";
-        sOutput += sXHText; sOutput += "\t";
-        sOutput += sXQHText; sOutput+= "\t";
-        sOutput += sXTitle; sOutput += "\t";
-
-        aOutput << sOutput.getStr() << '\n';
+        if( !sXTitle.isEmpty() )
+            writePoEntry(
+                "Transex3", *aOutput.mPo, global::inputPathname, pResData->sResTyp,
+                sGID, sLID, OString(), sXTitle, PoEntry::TTITLE );
 
         if ( bCreateNew ) {
             pResData->sText[ SOURCE_LANGUAGE ]         = "";
@@ -1059,21 +1058,9 @@ sal_Bool Export::WriteExportList(ResData *pResData, ExportList *pExportList,
                     if( sText == "\\\"" )
                         sText = "\"";
                 }
-
-                rtl::OStringBuffer sOutput(sProject);
-                sOutput.append('\t');
-                if ( !sRoot.isEmpty())
-                    sOutput.append(sActFileName);
-                sOutput.append("\t0\t");
-                sOutput.append(rTyp).append('\t');
-                sOutput.append(sGID).append('\t');
-                sOutput.append(sLID).append("\t\t");
-                sOutput.append(pResData->sPForm).append("\t0\t");
-                sOutput.append(sCur).append('\t');
-
-                sOutput.append(sText).append("\t\t\t\t");
-
-                aOutput << sOutput.makeStringAndClear().getStr() << '\n';
+                writePoEntry(
+                    "Transex3", *aOutput.mPo, global::inputPathname,
+                    rTyp, sGID, sLID, OString(), sText);
             }
         }
         if ( bCreateNew )
@@ -1305,10 +1292,10 @@ void Export::WriteToMerged(const rtl::OString &rText , bool bSDFContent)
         }
     } for (sal_Int32 i = 0; i < sText.getLength(); ++i) {
         if (sText[i] == '\n') {
-            aOutput << '\n';
+            *aOutput.mSimple << '\n';
         } else {
             char cChar = sText[i];
-            aOutput << cChar;
+            *aOutput.mSimple << cChar;
         }
     }
 }
diff --git a/l10ntools/source/export2.cxx b/l10ntools/source/export2.cxx
index 0ef5ca4..7d2257d 100644
--- a/l10ntools/source/export2.cxx
+++ b/l10ntools/source/export2.cxx
@@ -192,6 +192,56 @@ void Export::writeUsage(const OString& rName, const OString& rFileType)
         << " (de, en-US, ...)\n";
 }
 
+void Export::writePoEntry(
+    const OString& rExecutable, PoOfstream& rPoStream, const OString& rSourceFile,
+    const OString& rResType, const OString& rGroupId, const OString& rLocalId,
+    const OString& rHelpText, const OString& rText, const PoEntry::TYPE eType )
+{
+    try
+    {
+        PoEntry aPO(rSourceFile, rResType, rGroupId, rLocalId, rHelpText, rText, eType);
+        rPoStream.writeEntry( aPO );
+    }
+    catch( PoEntry::Exception& aException )
+    {
+        if(aException == PoEntry::NOSOURCFILE)
+        {
+            std::cerr << rExecutable << " warning: no sourcefile specified for po entry\n";
+        }
+        else
+        {
+            std::cerr << rExecutable << " warning: inavlid po attributes extracted from " <<  rSourceFile << "\n";
+            if(aException == PoEntry::NOGROUPID)
+            {
+                std::cerr << "No groupID specified!\n";
+                std::cerr << "String: " << rText << "\n";
+            }
+            else if (aException == PoEntry::NOSTRING)
+            {
+                std::cerr << "No string specified!\n";
+                std::cerr << "GroupID: " << rGroupId << "\n";
+                if( !rLocalId.isEmpty() ) std::cerr << "LocalID: " << rLocalId << "\n";
+            }
+            else
+            {
+                if (aException == PoEntry::NORESTYPE)
+                {
+                    std::cerr << "No resource type specified!\n";
+                }
+                else if (aException == PoEntry::WRONGHELPTEXT)
+                {
+                    std::cerr << "x-comment length is 5 characters:" << rHelpText << "\n";
+                }
+
+                std::cerr << "GroupID: " << rGroupId << "\n";
+                if( !rLocalId.isEmpty() ) std::cerr << "LocalID: " << rLocalId << "\n";
+                std::cerr << "String: " << rText << "\n";
+            }
+        }
+    }
+}
+
+
 /*****************************************************************************/
 void Export::SetLanguages( std::vector<rtl::OString> val ){
 /*****************************************************************************/
diff --git a/l10ntools/source/helpex.cxx b/l10ntools/source/helpex.cxx
index 3224324..1cd7dce 100644
--- a/l10ntools/source/helpex.cxx
+++ b/l10ntools/source/helpex.cxx
@@ -116,9 +116,9 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
     {
         HelpParser aParser( aArgs.m_sInputFile );
         hasNoError =
-            aParser.CreateSDF(
-                aArgs.m_sOutputFile, aArgs.m_sPrj, aArgs.m_sPrjRoot,
-                aArgs.m_sInputFile, new XMLFile( OUString('0') ), "help" );
+            aParser.CreatePO(
+                aArgs.m_sOutputFile, aArgs.m_sInputFile,
+                new XMLFile( OUString('0') ), "help" );
     }
 
     if( hasNoError )
diff --git a/l10ntools/source/helpmerge.cxx b/l10ntools/source/helpmerge.cxx
index 787458b..0ec6231 100644
--- a/l10ntools/source/helpmerge.cxx
+++ b/l10ntools/source/helpmerge.cxx
@@ -42,6 +42,7 @@
 
 #include "common.hxx"
 #include "helper.hxx"
+#include "po.hxx"
 
 #if OSL_DEBUG_LEVEL > 2
 void HelpParser::Dump(XMLHashMap* rElem_in)
@@ -72,10 +73,10 @@ HelpParser::HelpParser( const rtl::OString &rHelpFile )
           {};
 
 /*****************************************************************************/
-bool HelpParser::CreateSDF(
+bool HelpParser::CreatePO(
 /*****************************************************************************/
-    const rtl::OString &rSDFFile_in, const rtl::OString &rPrj_in,const rtl::OString &rRoot_in,
-    const rtl::OString &sHelpFile, XMLFile *pXmlFile, const rtl::OString &rGsi1){
+    const rtl::OString &rPOFile_in, const rtl::OString &sHelpFile,
+    XMLFile *pXmlFile, const rtl::OString &rGsi1){
     SimpleXMLParser aParser;
     rtl::OUString sXmlFile(
         rtl::OStringToOUString(sHelpFile, RTL_TEXTENCODING_ASCII_US));
@@ -97,26 +98,18 @@ bool HelpParser::CreateSDF(
     if( !file->CheckExportStatus() ){
         return true;
     }
-    std::ofstream aSDFStream(
-        rSDFFile_in.getStr(), std::ios_base::out | std::ios_base::trunc);
 
-    if (!aSDFStream.is_open()) {
-        fprintf(stdout,"Can't open file %s\n",rSDFFile_in.getStr());
+    PoOfstream aPoOutput( rPOFile_in, PoOfstream::APP );
+
+    if (!aPoOutput.isOpen()) {
+        fprintf(stdout,"Can't open file %s\n",rPOFile_in.getStr());
         return false;
     }
 
-    rtl::OString sActFileName(
-        common::pathnameToken(sHelpFile.getStr(), rRoot_in.getStr()));
-
     XMLHashMap*  aXMLStrHM   = file->GetStrings();
     LangHashMap* pElem;
     XMLElement*  pXMLElement  = NULL;
 
-    OUStringBuffer sBuffer;
-    const OUString sOUPrj( rPrj_in.getStr() , rPrj_in.getLength() , RTL_TEXTENCODING_ASCII_US );
-    const OUString sOUActFileName(sActFileName.getStr() , sActFileName.getLength() , RTL_TEXTENCODING_ASCII_US );
-    const OUString sOUGsi1( rGsi1.getStr() , rGsi1.getLength() , RTL_TEXTENCODING_ASCII_US );
-
     Export::InitLanguages( false );
     std::vector<rtl::OString> aLanguages = Export::GetLanguages();
 
@@ -137,52 +130,33 @@ bool HelpParser::CreateSDF(
 
             if( pXMLElement != NULL )
             {
-                OUString data(
-                    pXMLElement->ToOUString().
-                    replaceAll(
-                        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\n")),
-                        rtl::OUString()).
-                    replaceAll(
-                        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\t")),
-                        rtl::OUString()).trim());
-                sBuffer.append( sOUPrj );
-                sBuffer.append('\t');
-                if ( !rRoot_in.isEmpty())
-                    sBuffer.append( sOUActFileName );
-                   sBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("\t0\t"));
-                   sBuffer.append( sOUGsi1 );               //"help";
-                   sBuffer.append('\t');
-                   rtl::OString sID = posm->first;           // ID
-                   sBuffer.append( rtl::OStringToOUString( sID, RTL_TEXTENCODING_UTF8 ) );
-                   sBuffer.append('\t');
-                rtl::OString sOldRef = pXMLElement->GetOldref(); // oldref
-                sBuffer.append( rtl::OStringToOUString(sOldRef, RTL_TEXTENCODING_UTF8 ) );
-                sBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("\t\t\t0\t"));
-                   sBuffer.append( rtl::OStringToOUString( sCur, RTL_TEXTENCODING_UTF8 ) );
-                   sBuffer.append('\t');
-                sBuffer.append( data );
-                sBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("\t\t\t\t"));
-                rtl::OString sOut(rtl::OUStringToOString(sBuffer.makeStringAndClear().getStr() , RTL_TEXTENCODING_UTF8));
-                if( !data.isEmpty() )
-                    aSDFStream << sOut.getStr() << '\n';
+                OString data(
+                    OUStringToOString( pXMLElement->ToOUString(), RTL_TEXTENCODING_UTF8 ).
+                        replaceAll("\n",OString()).
+                        replaceAll("\t",OString()).trim());
+
+                Export::writePoEntry(
+                    "Helpex", aPoOutput, sHelpFile, rGsi1,
+                    posm->first, pXMLElement->GetOldref(), OString(), data);
+
                 pXMLElement=NULL;
             }
             else
             {
-                fprintf(stdout,"\nDBG: NullPointer in HelpParser::CreateSDF, Language %s, File %s\n", sCur.getStr(), sHelpFile.getStr());
+                fprintf(stdout,"\nDBG: NullPointer in HelpParser::CreatePO, Language %s, File %s\n", sCur.getStr(), sHelpFile.getStr());
             }
         }
     }
-    aSDFStream.close();
+    aPoOutput.close();
 
     return sal_True;
 }
 
-bool HelpParser::Merge( const rtl::OString &rSDFFile, const rtl::OString &rDestinationFile  ,
+bool HelpParser::Merge( const rtl::OString &rPOFile, const rtl::OString &rDestinationFile  ,
     const rtl::OString& rLanguage , MergeDataFile& aMergeDataFile )
 {
 
-    (void) rSDFFile;
+    (void) rPOFile;
 
     SimpleXMLParser aParser;
 
diff --git a/l10ntools/source/lngex.cxx b/l10ntools/source/lngex.cxx
index eb5cccc..9f63b89 100644
--- a/l10ntools/source/lngex.cxx
+++ b/l10ntools/source/lngex.cxx
@@ -38,8 +38,7 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
     if ( aArgs.m_bMergeMode )
         aParser.Merge(aArgs.m_sMergeSrc, aArgs.m_sOutputFile);
     else
-        aParser.CreateSDF(
-            aArgs.m_sOutputFile, aArgs.m_sPrj, aArgs.m_sPrjRoot );
+        aParser.CreatePO( aArgs.m_sOutputFile );
 
     return 0;
 }
diff --git a/l10ntools/source/lngmerge.cxx b/l10ntools/source/lngmerge.cxx
index 71f68ef..001ff83 100644
--- a/l10ntools/source/lngmerge.cxx
+++ b/l10ntools/source/lngmerge.cxx
@@ -80,20 +80,15 @@ LngParser::~LngParser()
     delete pLines;
 }
 
-sal_Bool LngParser::CreateSDF(const rtl::OString &rSDFFile,
-    const rtl::OString &rPrj, const rtl::OString &rRoot)
+sal_Bool LngParser::CreatePO( const rtl::OString &rPOFile )
 {
 
     Export::InitLanguages( false );
     aLanguages = Export::GetLanguages();
-    std::ofstream aSDFStream(
-        rSDFFile.getStr(), std::ios_base::out | std::ios_base::trunc);
-    if (!aSDFStream.is_open()) {
-        nError = SDF_COULD_NOT_OPEN;
+    PoOfstream aPOStream( rPOFile, PoOfstream::APP );
+    if (!aPOStream.isOpen()) {
+        std::cerr << "Ulfex error: Can't open po file:" << rPOFile.getStr() << "\n";
     }
-    nError = SDF_OK;
-    rtl::OString sActFileName(
-        common::pathnameToken(sSource.getStr(), rRoot.getStr()));
 
     size_t nPos  = 0;
     sal_Bool bStart = true;
@@ -113,16 +108,15 @@ sal_Bool LngParser::CreateSDF(const rtl::OString &rSDFFile,
             sID = sGroup;
         }
         else {
-            WriteSDF( aSDFStream , Text , rPrj , rRoot , sActFileName , sID );
+            WritePO( aPOStream , Text , sSource , sID );
         }
     }
-    aSDFStream.close();
+    aPOStream.close();
     return true;
 }
 
-void LngParser::WriteSDF(std::ofstream &aSDFStream,
-    OStringHashMap &rText_inout, const rtl::OString &rPrj,
-    const rtl::OString &rRoot, const rtl::OString &rActFileName,
+void LngParser::WritePO(PoOfstream &aPOStream,
+    OStringHashMap &rText_inout, const rtl::OString &rActFileName,
     const rtl::OString &rID)
 {
 
@@ -135,15 +129,9 @@ void LngParser::WriteSDF(std::ofstream &aSDFStream,
            if ( sAct.isEmpty() && !sCur.isEmpty() )
                sAct = rText_inout[ rtl::OString("en-US") ];
 
-           rtl::OString sOutput( rPrj ); sOutput += "\t";
-           if (rRoot.getLength())
-               sOutput += rActFileName;
-           sOutput += "\t0\t";
-           sOutput += "LngText\t";
-           sOutput += rID; sOutput += "\t\t\t\t0\t";
-           sOutput += sCur; sOutput += "\t";
-           sOutput += sAct; sOutput += "\t\t\t\t";
-           aSDFStream << sOutput.getStr() << '\n';
+           Export::writePoEntry(
+                "Ulfex", aPOStream, rActFileName, "LngText",
+                rID, OString(), OString(), sAct);
        }
    }
 }
@@ -173,7 +161,7 @@ void LngParser::ReadLine(const rtl::OString &rLine_in,
 }
 
 sal_Bool LngParser::Merge(
-    const rtl::OString &rSDFFile,
+    const rtl::OString &rPOFile,
     const rtl::OString &rDestinationFile)
 {
     Export::InitLanguages( true );
@@ -184,7 +172,7 @@ sal_Bool LngParser::Merge(
     }
     nError = LNG_OK;
 
-    MergeDataFile aMergeDataFile( rSDFFile, sSource, false, true );
+    MergeDataFile aMergeDataFile( rPOFile, sSource, false, true );
     rtl::OString sTmp( Export::sLanguages );
     if( sTmp.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("ALL")) )
         Export::SetLanguages( aMergeDataFile.GetLanguages() );
diff --git a/l10ntools/source/localize.cxx b/l10ntools/source/localize.cxx
index 55dcda2..e0c22f7 100644
--- a/l10ntools/source/localize.cxx
+++ b/l10ntools/source/localize.cxx
@@ -21,11 +21,9 @@
 
 #include <cstddef>
 #include <cstdlib>
-#include <fstream>
 #include <iostream>
 #include <string>
 
-#include "boost/noncopyable.hpp"
 #include "osl/file.h"
 #include "osl/file.hxx"
 #include "osl/thread.h"
@@ -45,46 +43,24 @@ using namespace std;
 
 namespace {
 
-class TempFile: private boost::noncopyable {
-public:
-    TempFile() {
-        if (osl::FileBase::createTempFile(0, 0, &url_) != osl::FileBase::E_None)
-        {
-            cerr << "osl::FileBase::createTempFile() failed\n";
-            throw false; //TODO
-        }
-    }
-
-    ~TempFile() {
-        if (osl::File::remove(url_) != osl::FileBase::E_None) {
-            cerr << "Warning: failure removing temporary " << url_ << '\n';
-        }
-    }
-
-    OUString getUrl() const { return url_; }
-
-private:
-    OUString url_;
-};
-
 struct AsciiString {
     char const * string;
     sal_Int32 length;
 };
 
 bool matchList(
-    OUString const & url, AsciiString const * list, size_t length)
+    const OUString& rUrl, const AsciiString* pList, size_t nLength)
 {
-    for (size_t i = 0; i != length; ++i) {
-        if (url.endsWithAsciiL(list[i].string, list[i].length)) {
+    for (size_t i = 0; i != nLength; ++i) {
+        if (rUrl.endsWithAsciiL(pList[i].string, pList[i].length)) {
             return true;
         }
     }
     return false;
 }
 
-bool passesNegativeList(OUString const & url) {
-    static AsciiString const list[] = {
+bool passesNegativeList(const OUString& rUrl) {
+    static const AsciiString list[] = {
         { RTL_CONSTASCII_STRINGPARAM("/dictionaries.xcu") },
         { RTL_CONSTASCII_STRINGPARAM(
             "/dictionaries/da_DK/help/da/help.tree") },
@@ -105,11 +81,11 @@ bool passesNegativeList(OUString const & url) {
         { RTL_CONSTASCII_STRINGPARAM(
             "/officecfg/registry/data/org/openoffice/Office/SFX.xcu") }
     };
-    return !matchList(url, list, SAL_N_ELEMENTS(list));
+    return !matchList(rUrl, list, SAL_N_ELEMENTS(list));
 }
 
-bool passesPositiveList(OUString const & url) {
-    static AsciiString const list[] = {
+bool passesPositiveList(const OUString& rUrl) {
+    static const AsciiString list[] = {
         { RTL_CONSTASCII_STRINGPARAM(
             "/chart2/source/controller/dialogs/res_DataLabel_tmpl.hrc") },
         { RTL_CONSTASCII_STRINGPARAM(
@@ -145,155 +121,81 @@ bool passesPositiveList(OUString const & url) {
         { RTL_CONSTASCII_STRINGPARAM("/sw/source/ui/inc/swmn_tmpl.hrc") },
         { RTL_CONSTASCII_STRINGPARAM("/sw/source/ui/inc/toolbox_tmpl.hrc") }
     };
-    return matchList(url, list, SAL_N_ELEMENTS(list));
+    return matchList(rUrl, list, SAL_N_ELEMENTS(list));
 }
 
 void handleCommand(
-    OString const & project, OString const & projectRoot,
-    OUString const & url, OString const & actualPotDir,
-    PoOfstream & rPoOutPut, OString const & executable, bool positive)
+    const OString& rProject, const OString& rProjectRoot,
+    const OString& rInPath, const OString& rOutPath,
+    const OString& rExecutable)
 {
-    if (positive ? passesPositiveList(url) : passesNegativeList(url)) {
-
-        //Get input file path
-        OString inPath;
-        {
-            OUString inPathTmp;
-            if (osl::FileBase::getSystemPathFromFileURL(url, inPathTmp) !=
-                osl::FileBase::E_None)
-            {
-                cerr
-                    << "osl::FileBase::getSystemPathFromFileURL(" << url
-                    << ") failed\n";
-                throw false; //TODO
-            }
-            inPath = OUStringToOString( inPathTmp, RTL_TEXTENCODING_UTF8 );
-        }
+    OStringBuffer buf(OString(getenv("SOLARVER")));
+    buf.append('/');
+    buf.append(OString(getenv("INPATH_FOR_BUILD")));
+    buf.append("/bin/");
+    buf.append(rExecutable);
+    buf.append(" -p ");
+    buf.append(rProject);
+    buf.append(" -r ");
+    buf.append(rProjectRoot);
+    buf.append(" -i ");
+    buf.append(rInPath);
+    buf.append(" -o ");
+    buf.append(rOutPath);
+    buf.append(" -l en-US");
 
-        //Get output file path
-        TempFile temp;
-        OString outPath;
-        {
-            OUString outPathTmp;
-            if (osl::FileBase::getSystemPathFromFileURL(temp.getUrl(),outPathTmp)
-                != osl::FileBase::E_None)
-            {
-                cerr
-                    << "osl::FileBase::getSystemPathFromFileURL("
-                    << temp.getUrl() << ") failed\n";
-                throw false; //TODO
-            }
-            outPath = OUStringToOString( outPathTmp, RTL_TEXTENCODING_UTF8 );
-        }
+    const OString cmd = buf.makeStringAndClear();
+    if (system(cmd.getStr()) != 0)
+    {
+        cerr << "Error: Failed to execute " << cmd.getStr() << '\n';
+        throw false; //TODO
+    }
+}
 
-        //Call the executable
+void InitPoFile(
+    const OString& rProject, const OString& rInPath,
+    const OString& rPotDir, const OString& rOutPath )
+{
+    //Create directory for po file
+    {
+        OUString outDir =
+            OStringToOUString(
+                rPotDir.copy(0,rPotDir.lastIndexOf('/')), RTL_TEXTENCODING_UTF8);
+        OUString outDirUrl;
+        if (osl::FileBase::getFileURLFromSystemPath(outDir, outDirUrl)
+            != osl::FileBase::E_None)
         {
-            OStringBuffer buf(OString(getenv("SOLARVER")));
-            buf.append('/');
-            buf.append(OString(getenv("INPATH_FOR_BUILD")));
-            buf.append("/bin/");
-            buf.append(executable);
-            buf.append(" -p ");
-            buf.append(project);
-            buf.append(" -r ");
-            buf.append(projectRoot);
-            buf.append(" -i ");
-            buf.append(inPath);
-            buf.append(" -o ");
-            buf.append(outPath);
-            buf.append(" -l en-US");
-
-            const OString cmd = buf.makeStringAndClear();
-            if (system(cmd.getStr()) != 0) {
-                cerr << "Error: Failed to execute " << cmd.getStr() << '\n';
-                throw false; //TODO
-            }
-        }
-
-        ifstream in(outPath.getStr());
-        if (!in.is_open()) {
-            cerr << "Error: Cannot open " << outPath.getStr() << "\n";
+            cerr << "Error: Cannot convert pathname to URL in " << __FILE__ << ", in line " << __LINE__ << "\n"
+            << "       outDir: " << OUStringToOString(outDir, RTL_TEXTENCODING_ASCII_US).getStr() << "\n";
             throw false; //TODO
         }
+        osl::Directory::createPath(outDirUrl);
+    }
 
-        string s;
-        getline(in, s);
-        if (!in.eof() && !rPoOutPut.isOpen())
-        {
-            //Create directory for po file
-            {
-                OUString outDir =
-                    OStringToOUString(
-                        actualPotDir.copy(0,actualPotDir.lastIndexOf('/')),
-                        RTL_TEXTENCODING_UTF8);
-                OUString outDirUrl;
-                if (osl::FileBase::getFileURLFromSystemPath(outDir, outDirUrl)
-                    != osl::FileBase::E_None)
-                {
-                    cerr << "Error: Cannot convert pathname to URL in " << __FILE__ << ", in line " << __LINE__ << "\n"
-                         << "       outDir: " << OUStringToOString(outDir, RTL_TEXTENCODING_ASCII_US).getStr() << "\n";
-                    throw false; //TODO
-                }
-                osl::Directory::createPath(outDirUrl);
-            }
-
-            //Open po file
-            {
-                OString outFilePath = actualPotDir.concat(".pot");
-                rPoOutPut.open(outFilePath.getStr());
-                if (!rPoOutPut.isOpen())
-                {
-                    cerr
-                        << "Error: Cannot open po file "
-                        << outFilePath.getStr() << "\n";
-                    throw false; //TODO
-                }
-            }
+    //Add header to the po file
+    PoOfstream aPoOutPut;
+    aPoOutPut.open(rOutPath.getStr());
+    if (!aPoOutPut.isOpen())
+    {
+        cerr
+            << "Error: Cannot open po file "
+            << rOutPath.getStr() << "\n";
+        throw false; //TODO
+    }
 
-            //Add header to po file
-            {
-                const sal_Int32 nProjectInd = inPath.indexOf(project);
-                const OString relativPath =
-                    inPath.copy(
-                        nProjectInd, inPath.lastIndexOf('/')- nProjectInd);
+    const sal_Int32 nProjectInd = rInPath.indexOf(rProject);
+    const OString relativPath =
+        rInPath.copy(nProjectInd, rInPath.lastIndexOf('/')- nProjectInd);
 
-                PoHeader aTmp(relativPath);
-                rPoOutPut.writeHeader(aTmp);
-            }
-        }
-        while (!in.eof())
-        {
-            OString sLine = OString(s.data(),s.length());
-            try
-            {
-                if (!sLine.getToken(PoEntry::TEXT,'\t').isEmpty())
-                    rPoOutPut.writeEntry(PoEntry(sLine));
-                if (!sLine.getToken(PoEntry::QUICKHELPTEXT,'\t').isEmpty())
-                    rPoOutPut.writeEntry(PoEntry(sLine,PoEntry::TQUICKHELPTEXT));
-                if (!sLine.getToken(PoEntry::TITLE,'\t').isEmpty())
-                    rPoOutPut.writeEntry(PoEntry(sLine,PoEntry::TTITLE));
-            }
-            catch(PoEntry::Exception& aException)
-            {
-                if(aException == PoEntry::INVALIDSDFLINE)
-                {
-                    cerr
-                        << executable.getStr()
-                        << "'s output is invalid:\n"
-                        << sLine.replaceAll("\t","\\t").getStr()
-                        << endl;
-                }
-            }
-            getline(in, s);
-        };
-        in.close();
-    }
+    PoHeader aTmp(relativPath);
+    aPoOutPut.writeHeader(aTmp);
+    aPoOutPut.close();
 }
 
-void handleFile(
-    OString const & project, OString const & projectRoot,
-    OUString const & url, OString const & actualPotDir,
-    PoOfstream & rPoOutPut)
+bool handleFile(
+    const OString& rProject, const OString& rProjectRoot,
+    const OUString& rUrl, const OString& rPotDir,
+    bool bInitPoFile )
 {
     struct Command {
         char const * extension;
@@ -315,20 +217,42 @@ void handleFile(
         { RTL_CONSTASCII_STRINGPARAM(".tree"), "treex", false } };
     for (size_t i = 0; i != SAL_N_ELEMENTS(commands); ++i)
     {
-        if (url.endsWithAsciiL(
+        if (rUrl.endsWithAsciiL(
                 commands[i].extension, commands[i].extensionLength) &&
-            (commands[i].executable != "propex" || url.indexOf("en_US") != -1)
-)
+            (commands[i].executable != "propex" || rUrl.indexOf("en_US") != -1))
         {
-            handleCommand(
-                project, projectRoot, url, actualPotDir, rPoOutPut,
-                commands[i].executable, commands[i].positive);
+            if (commands[i].positive ? passesPositiveList(rUrl) : passesNegativeList(rUrl))
+            {
+                //Get input file path
+                OString sInPath;
+                {
+                    OUString sInPathTmp;
+                    if (osl::FileBase::getSystemPathFromFileURL(rUrl, sInPathTmp) !=
+                        osl::FileBase::E_None)
+                    {
+                        cerr << "osl::FileBase::getSystemPathFromFileURL(" << rUrl << ") failed\n";
+                        throw false; //TODO
+                    }
+                    sInPath = OUStringToOString( sInPathTmp, RTL_TEXTENCODING_UTF8 );
+                }
+                OString sOutPath = rPotDir.concat(".pot");
+
+                if ( bInitPoFile )
+                {
+                    InitPoFile(rProject, sInPath, rPotDir, sOutPath);
+                }
+                handleCommand(
+                    rProject, rProjectRoot, sInPath,
+                    sOutPath, commands[i].executable);
+                return true;
+            }
             break;
         }
     }
+    return false;
 }
 
-bool includeProject(OString const & project) {
+bool includeProject(const OString& rProject) {
     static OString projects[] = {
         "accessibility",
         "android",
@@ -380,7 +304,7 @@ bool includeProject(OString const & project) {
         "wizards",
         "xmlsecurity" };
     for (size_t i = 0; i != SAL_N_ELEMENTS(projects); ++i) {
-        if (project == projects[i]) {
+        if (rProject == projects[i]) {
             return true;
         }
     }
@@ -392,29 +316,29 @@ bool includeProject(OString const & project) {
 /// Ignores symlinks and instead explicitly descends into clone/* or src/*,
 /// as the Cygwin symlinks are not supported by osl::Directory on Windows.
 ///
-/// @param url the absolute file URL of this directory
+/// @param rUrl the absolute file URL of this directory
 ///
-/// @param level 0 if this is either the root directory that contains the
+/// @param nLevel 0 if this is either the root directory that contains the
 /// projects or one of the clone/* or src/* directories that contain the
 /// additional projects; -1 if this is the clone directory; 1 if this
 /// is a project directory; 2 if this is a directory inside a project
 ///
-/// @param project the name of the project (empty and ignored if level <= 0)
+/// @param rProject the name of the project (empty and ignored if nLevel <= 0)
 ///
-/// @param the relative path back to the project root (empty and ignored if
-/// level <= 0)
-/// @param actualPotDir the path of pot directory
+/// @param rProjectRoo the relative path back to the project root (empty and ignored if
+/// nLevel <= 0)
+/// @param rPotDir the path of pot directory
 void handleDirectory(
-    OUString const & url, int level, OString const & project,
-    OString const & projectRoot, OString const & actualPotDir)
+    const OUString& rUrl, int nLevel, const OString& rProject,
+    const OString& rProjectRoot, const OString& rPotDir)
 {
-    PoOfstream aPoOutPut;
-    osl::Directory dir(url);
+    osl::Directory dir(rUrl);
     if (dir.open() != osl::FileBase::E_None) {
         cerr
-            << "Error: Cannot open directory: " << url << '\n';
+            << "Error: Cannot open directory: " << rUrl << '\n';
         throw false; //TODO
     }
+    bool bFirstLocFile = true;
     for (;;) {
         osl::DirectoryItem item;
         osl::FileBase::RC e = dir.getNextItem(item);
@@ -434,12 +358,12 @@ void handleDirectory(
         }
         const OString sFileName =
             OUStringToOString(stat.getFileName(),RTL_TEXTENCODING_UTF8);
-        switch (level) {
+        switch (nLevel) {
         case -1: // the clone or src directory
             if (stat.getFileType() == osl::FileStatus::Directory) {
                 handleDirectory(
                     stat.getFileURL(), 0, OString(),
-                    OString(), actualPotDir);
+                    OString(), rPotDir);
             }
             break;
         case 0: // a root directory
@@ -447,46 +371,71 @@ void handleDirectory(
                 if (includeProject(sFileName)) {
                     handleDirectory(
                         stat.getFileURL(), 1, sFileName,
-                        OString(), actualPotDir.concat("/").
-                        concat(sFileName));
+                        OString(), rPotDir.concat("/").concat(sFileName));
                 } else if ( sFileName == "clone" ||
                             sFileName == "src" )
                 {
                     handleDirectory(
-                        stat.getFileURL(), -1, OString(),
-                        OString(), actualPotDir);
+                        stat.getFileURL(), -1, OString(), OString(), rPotDir);
                 }
             }
             break;
         default:
             if (stat.getFileType() == osl::FileStatus::Directory) {
-                OString pr(projectRoot);
+                OString pr(rProjectRoot);
                 if (!pr.isEmpty()) {
                     pr += OString('/');
                 }
                 pr += OString("..");
-                handleDirectory(stat.getFileURL(), 2, project, pr,
-                                actualPotDir.concat("/").concat(sFileName));
+                handleDirectory(
+                    stat.getFileURL(), 2, rProject, pr, rPotDir.concat("/").concat(sFileName));
             } else {
-                handleFile(project, projectRoot,
-                           stat.getFileURL(), actualPotDir, aPoOutPut);
+                if( handleFile( rProject, rProjectRoot, stat.getFileURL(),
+                                rPotDir, bFirstLocFile) )
+                    bFirstLocFile = false;
             }
             break;
         }
     }
-    if (aPoOutPut.isOpen())
-        aPoOutPut.close();
+
     if (dir.close() != osl::FileBase::E_None) {
         cerr << "Error: Cannot close directory\n";
         throw false; //TODO
     }
+    if( bFirstLocFile == false )
+    {
+        //Delete pot file if it contain only the header
+        OString sPotFile = rPotDir.concat(".pot");
+        PoIfstream aPOStream( sPotFile );
+        PoEntry aPO;
+        aPOStream.readEntry( aPO );
+        bool bDel = aPOStream.eof();
+        aPOStream.close();
+        if( bDel )
+        {
+            system(OString("rm " + sPotFile).getStr());
+        }
+    }
+    //Remove empty pot directories
+    OUString sPoPath =
+        OStringToOUString(
+            rPotDir.copy(0,rPotDir.lastIndexOf('/')), RTL_TEXTENCODING_UTF8);
+    OUString sPoUrl;
+    if (osl::FileBase::getFileURLFromSystemPath(sPoPath, sPoUrl)
+        != osl::FileBase::E_None)
+    {
+        cerr << "Error: Cannot convert pathname to URL in " << __FILE__ << ", in line " << __LINE__ << "\n"
+             << OUStringToOString(sPoPath, RTL_TEXTENCODING_UTF8).getStr() << "\n";
+        throw false; //TODO
+    }
+    osl::Directory::remove(sPoUrl);
 }
 
-void handleProjects(char * sourceRoot, char const * destRoot)
+void handleProjects(char * sSourceRoot, char const * sDestRoot)
 {
     OUString root16;
     if (!rtl_convertStringToUString(
-            &root16.pData, sourceRoot, rtl_str_getLength(sourceRoot),
+            &root16.pData, sSourceRoot, rtl_str_getLength(sSourceRoot),
             osl_getThreadTextEncoding(),
             (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
              | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
@@ -503,7 +452,7 @@ void handleProjects(char * sourceRoot, char const * destRoot)
              << "       root16: " << OUStringToOString(root16, RTL_TEXTENCODING_ASCII_US).getStr() << "\n";
         throw false; //TODO
     }
-    handleDirectory(rootUrl, 0, OString(), OString(), OString(destRoot));
+    handleDirectory(rootUrl, 0, OString(), OString(), OString(sDestRoot));
 }
 }
 
diff --git a/l10ntools/source/po.cxx b/l10ntools/source/po.cxx
index cdb5fb4..36e6ebb 100755
--- a/l10ntools/source/po.cxx
+++ b/l10ntools/source/po.cxx
@@ -199,14 +199,14 @@ void GenPoEntry::writeToFile(std::ofstream& rOFStream) const
 void GenPoEntry::readFromFile(std::ifstream& rIFStream)
 {
     *this = GenPoEntry();
-    if( rIFStream.eof() )
+    OString* pLastMsg = 0;
+    std::string sTemp;
+    getline(rIFStream,sTemp);
+    if( rIFStream.eof() || sTemp.empty() )
     {
         m_bNull = true;
         return;
     }
-    OString* pLastMsg = 0;
-    std::string sTemp;
-    getline(rIFStream,sTemp);
     while(!rIFStream.eof())
     {
         OString sLine = OString(sTemp.data(),sTemp.length());
@@ -277,28 +277,8 @@ namespace
         return OString(sKeyId);
     }
 
-    //Split string at the delimiter character
-    static void lcl_SplitAt(const OString& rSource, const sal_Char nDelimiter,
-                     std::vector<OString>& o_vParts)
-    {
-        o_vParts.resize( 0 );
-        sal_Int32 nActIndex = 0;
-        sal_Int32 nLastSplit = 0;
-        while( nActIndex < rSource.getLength() )
-        {
-            if ( rSource[nActIndex] == nDelimiter )
-            {
-                o_vParts.push_back(
-                    rSource.copy(nLastSplit,nActIndex-nLastSplit));
-                nLastSplit = nActIndex+1;
-            }
-            ++nActIndex;
-        }
-        o_vParts.push_back(rSource.copy(nLastSplit));
-    }
-
-    //Unescape sdf string
-    static OString lcl_UnEscapeSDFText(
+    //Unescape merge string
+    static OString lcl_UnEscapeMergeText(
         const OString& rText,const bool bHelpText = false )
     {
         if ( bHelpText )
@@ -382,8 +362,8 @@ namespace
         return sResult;
     }
 
-    //Escape to get sdf/merge string
-    static OString lcl_EscapeSDFText(
+    //Escape to get merge string
+    static OString lcl_EscapeMergeText(
         const OString& rText,const bool bHelpText = false )
     {
         if ( bHelpText )
@@ -400,31 +380,31 @@ PoEntry::PoEntry()
 {
 }
 
-//Construct PoEntry from sdfline
-PoEntry::PoEntry(const OString& rSDFLine, const TYPE eType)
+PoEntry::PoEntry(
+    const OString& rSourceFile, const OString& rResType, const OString& rGroupId,
+    const OString& rLocalId, const OString& rHelpText,
+    const OString& rText, const TYPE eType )
     : m_pGenPo( 0 )
     , m_bIsInitialized( false )
 {
-    std::vector<OString> vParts;
-    lcl_SplitAt(rSDFLine,'\t',vParts);
-    if( vParts.size()!=15 ||
-        vParts[SOURCEFILE].isEmpty() ||
-        vParts[GROUPID].isEmpty() ||
-        vParts[RESOURCETYPE].isEmpty() ||
-        vParts[eType].isEmpty() ||
-        vParts[HELPTEXT].getLength() == 4 )
-    {
-        throw INVALIDSDFLINE;
-    }
+    if( rSourceFile.isEmpty() )
+        throw NOSOURCFILE;
+    else if ( rResType.isEmpty() )
+        throw NORESTYPE;
+    else if ( rGroupId.isEmpty() )
+        throw NOGROUPID;
+    else if ( rText.isEmpty() )
+        throw NOSTRING;
+    else if ( rHelpText.getLength() == 5 )
+        throw WRONGHELPTEXT;
 
     m_pGenPo = new GenPoEntry();
-    m_pGenPo->setReference(vParts[SOURCEFILE].
-        copy(vParts[SOURCEFILE].lastIndexOf("\\")+1));
+    m_pGenPo->setReference(rSourceFile.copy(rSourceFile.lastIndexOf("/")+1));
 
     OString sMsgCtxt =
-        vParts[GROUPID] + "\n" +
-        (vParts[LOCALID].isEmpty() ? OString( "" ) : vParts[LOCALID] + "\n") +
-        vParts[RESOURCETYPE];
+        rGroupId + "\n" +
+        (rLocalId.isEmpty() ? OString( "" ) : rLocalId + "\n") +
+        rResType;
     switch(eType){
     case TTEXT:
         sMsgCtxt += ".text"; break;
@@ -437,13 +417,14 @@ PoEntry::PoEntry(const OString& rSDFLine, const TYPE eType)
     }
     m_pGenPo->setMsgCtxt(sMsgCtxt);
     m_pGenPo->setMsgId(
-        lcl_UnEscapeSDFText(
-            vParts[eType],vParts[SOURCEFILE].endsWith(".xhp")));
+        lcl_UnEscapeMergeText(
+            rText,rSourceFile.endsWith(".xhp")));
     m_pGenPo->setExtractCom(
-        ( !vParts[HELPTEXT].isEmpty() ?  vParts[HELPTEXT] + "\n" : OString( "" )) +
+        ( !rHelpText.isEmpty() ?  rHelpText + "\n" : OString( "" )) +
         lcl_GenKeyId(
             m_pGenPo->getReference() + sMsgCtxt + m_pGenPo->getMsgId() ) );
     m_bIsInitialized = true;
+
 }
 
 //Destructor
@@ -561,31 +542,31 @@ OString PoEntry::getKeyId() const
 }
 
 
-//Get translation string in sdf/merge format
+//Get translation string in merge format
 OString PoEntry::getMsgId() const
 {
     assert( m_bIsInitialized );
     return
-        lcl_EscapeSDFText(
+        lcl_EscapeMergeText(
             m_pGenPo->getMsgId(), getSourceFile().endsWith(".xhp") );
 }
 
-//Get translated string in sdf/merge format
+//Get translated string in merge format
 OString PoEntry::getMsgStr() const
 {
     assert( m_bIsInitialized );
     return
-        lcl_EscapeSDFText(
+        lcl_EscapeMergeText(
             m_pGenPo->getMsgStr(), getSourceFile().endsWith(".xhp") );
 
 }
 
-//Set translated string when input is in sdf format
+//Set translated string when input is in merge format
 void PoEntry::setMsgStr(const OString& rMsgStr)
 {
     assert( m_bIsInitialized );
     m_pGenPo->setMsgStr(
-                lcl_UnEscapeSDFText(
+                lcl_UnEscapeMergeText(
                     rMsgStr,getSourceFile().endsWith(".xhp")));
 }
 
@@ -656,6 +637,13 @@ PoOfstream::PoOfstream()
 {
 }
 
+PoOfstream::PoOfstream(const OString& rFileName, OpenMode aMode )
+    : m_aOutPut()
+    , m_bIsAfterHeader( false )
+{
+    open( rFileName, aMode );
+}
+
 PoOfstream::~PoOfstream()
 {
     if( isOpen() )
@@ -664,12 +652,21 @@ PoOfstream::~PoOfstream()
     }
 }
 
-void PoOfstream::open(const OString& rFileName)
+void PoOfstream::open(const OString& rFileName, OpenMode aMode )
 {
     assert( !isOpen() );
-    m_aOutPut.open( rFileName.getStr(),
-        std::ios_base::out | std::ios_base::trunc );
-    m_bIsAfterHeader = false;
+    if( aMode == TRUNC )
+    {
+        m_aOutPut.open( rFileName.getStr(),
+            std::ios_base::out | std::ios_base::trunc );
+        m_bIsAfterHeader = false;
+    }
+    else if( aMode == APP )
+    {
+        m_aOutPut.open( rFileName.getStr(),
+            std::ios_base::out | std::ios_base::app );
+        m_bIsAfterHeader = m_aOutPut.tellp() != std::ofstream::pos_type( 0 );
+    }
 }
 
 void PoOfstream::close()
@@ -699,6 +696,13 @@ PoIfstream::PoIfstream()
 {
 }
 
+PoIfstream::PoIfstream(const OString& rFileName)
+    : m_aInPut()
+    , m_bEof( false )
+{
+    open( rFileName );
+}
+
 PoIfstream::~PoIfstream()
 {
     if( isOpen() )
diff --git a/l10ntools/source/propex.cxx b/l10ntools/source/propex.cxx
index 0538580..0c2e7da 100644
--- a/l10ntools/source/propex.cxx
+++ b/l10ntools/source/propex.cxx
@@ -29,12 +29,11 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
     }
     if( aArgs.m_bMergeMode )
     {
-        aParser.Merge(aArgs.m_sMergeSrc, aArgs.m_sOutputFile);
+        aParser.Merge( aArgs.m_sMergeSrc, aArgs.m_sOutputFile );
     }
     else
     {
-        aParser.Extract(
-            aArgs.m_sOutputFile, aArgs.m_sPrj, aArgs.m_sPrjRoot );
+        aParser.Extract( aArgs.m_sOutputFile );
     }
     return 0;
 }
diff --git a/l10ntools/source/propmerge.cxx b/l10ntools/source/propmerge.cxx
index 8c2b97b..6f87a4e 100644
--- a/l10ntools/source/propmerge.cxx
+++ b/l10ntools/source/propmerge.cxx
@@ -19,19 +19,6 @@
 
 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 )
-    {
-           OString sOutput( rPrj ); sOutput += "\t";
-           sOutput += rActFileName;
-           sOutput += "\t0\tproperty\t";
-           sOutput += rID; sOutput += "\t\t\t\t0\ten-US\t";
-           sOutput += rText; sOutput += "\t\t\t\t";
-           aSDFStream << sOutput.getStr() << std::endl;
-    }
-
     //Find ascii escaped unicode
     static sal_Int32 lcl_IndexOfUnicode(
         const OString& rSource, const sal_Int32 nFrom = 0 )
@@ -136,17 +123,15 @@ PropParser::~PropParser()
 }
 
 //Extract strings form source file
-void PropParser::Extract(
-    const OString& rSDFFile, const OString& rPrj, const OString& rRoot )
+void PropParser::Extract( const OString& rPOFile )
 {
     assert( m_bIsInitialized );
-    std::ofstream aSDFStream(
-        rSDFFile.getStr(), std::ios_base::out | std::ios_base::trunc );
-    if( !aSDFStream.is_open() )
+    PoOfstream aPOStream( rPOFile, PoOfstream::APP );
+    if( !aPOStream.isOpen() )
     {
         std::cerr
-            << "Propex error: Cannot open sdffile for extract: "
-            << rSDFFile.getStr() << std::endl;
+            << "Propex error: Cannot open pofile for extract: "
+            << rPOFile.getStr() << std::endl;
         return;
     }
 
@@ -156,17 +141,16 @@ void PropParser::Extract(
         const sal_Int32 nEqualSign = sLine.indexOf('=');
         if( nEqualSign != -1 )
         {
-            lcl_WriteSDF(
-                aSDFStream,
-                lcl_ConvertToUTF8( sLine.copy( nEqualSign + 1 ).trim() ),//Text
-                rPrj,
-                common::pathnameToken(
-                    m_sSource.getStr(), rRoot.getStr()), //FileName
-                sLine.copy( 0, nEqualSign ).trim() );   //ID
+            OString sID = sLine.copy( 0, nEqualSign ).trim();
+            OString sText = lcl_ConvertToUTF8( sLine.copy( nEqualSign + 1 ).trim() );
+
+            Export::writePoEntry(
+                "Propex", aPOStream, m_sSource, "property",
+                sID, OString(), OString(), sText);
         }
     }
 
-    aSDFStream.close();
+    aPOStream.close();
 }
 
 //Merge strings to source file
diff --git a/l10ntools/source/stringex.cxx b/l10ntools/source/stringex.cxx
index ed2a935..3050538 100644
--- a/l10ntools/source/stringex.cxx
+++ b/l10ntools/source/stringex.cxx
@@ -50,8 +50,7 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
         }
         else
         {
-            aParser.Extract(
-                aArgs.m_sOutputFile, aArgs.m_sPrj, aArgs.m_sPrjRoot );
+            aParser.Extract( aArgs.m_sOutputFile );
         }
     return 0;
 }
diff --git a/l10ntools/source/stringmerge.cxx b/l10ntools/source/stringmerge.cxx
index 133a5bf..bc7417d 100644
--- a/l10ntools/source/stringmerge.cxx
+++ b/l10ntools/source/stringmerge.cxx
@@ -19,25 +19,12 @@
 
 #include "export.hxx"
 #include "common.hxx"
+#include "po.hxx"
 #include "stringmerge.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 )
     {
@@ -76,17 +63,15 @@ StringParser::~StringParser()
 }
 
 //Extract strings form source file
-void StringParser::Extract(
-    const OString& rSDFFile, const OString& rPrj, const OString& rRoot )
+void StringParser::Extract( const OString& rPOFile )
 {
     assert( m_bIsInitialized );
-    std::ofstream aSDFStream(
-        rSDFFile.getStr(), std::ios_base::out | std::ios_base::trunc );
-    if( !aSDFStream.is_open() )
+    PoOfstream aPOStream( rPOFile, PoOfstream::APP );
+    if( !aPOStream.isOpen() )
     {
         std::cerr
-            << "stringex error: Cannot open sdffile for extract: "
-            << rSDFFile.getStr() << std::endl;
+            << "stringex error: Cannot open po file for extract: "
+            << rPOFile.getStr() << std::endl;
         return;
     }
 
@@ -98,14 +83,11 @@ void StringParser::Extract(
         {
             xmlChar* pID = xmlGetProp(pCurrent, (const xmlChar*)("name"));
             xmlChar* pText = xmlNodeGetContent(pCurrent);
-            lcl_WriteSDF(
-                aSDFStream,
-                lcl_xmlStrToOString( pText ),
-                rPrj,
-                common::pathnameToken(
-                m_pSource->name, rRoot.getStr()),
-                lcl_xmlStrToOString( pID ),
-                OString( "string" ));
+
+            Export::writePoEntry(
+                "Stringex", aPOStream, m_pSource->name, "string",
+                lcl_xmlStrToOString( pID ), OString(), OString(),
+                lcl_xmlStrToOString( pText ));
 
             xmlFree( pID );
             xmlFree( pText );
@@ -114,7 +96,7 @@ void StringParser::Extract(
 
     xmlFreeDoc( m_pSource );
     xmlCleanupParser();
-    aSDFStream.close();
+    aPOStream.close();
     m_bIsInitialized = false;
 }
 
diff --git a/l10ntools/source/treemerge.cxx b/l10ntools/source/treemerge.cxx
index 6529a10..d259efc 100644
--- a/l10ntools/source/treemerge.cxx
+++ b/l10ntools/source/treemerge.cxx
@@ -24,20 +24,6 @@
 
 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 )
     {
@@ -51,8 +37,7 @@ namespace
     //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 )
+        const xmlChar* pNodeName, PoOfstream& rPOStream )
     {
         if( !pRoot->children )
         {
@@ -66,21 +51,17 @@ namespace
                 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 ));
+
+                Export::writePoEntry(
+                    "Treex", rPOStream, pSource->name, lcl_xmlStrToOString( pNodeName ),
+                    lcl_xmlStrToOString( pID ), OString(), OString(), lcl_xmlStrToOString( pText ));
 
                 xmlFree( pID );
                 xmlFree( pText );
 
                 lcl_ExtractLevel(
                     pSource, pCurrent, (const xmlChar *)("node"),
-                    rSDFStream, rPrj, rRoot );
+                    rPOStream );
             }
         }
     }
@@ -238,28 +219,26 @@ TreeParser::~TreeParser()
 }
 
 //Extract strings form source file
-void TreeParser::Extract(
-    const OString& rSDFFile, const OString& rPrj, const OString& rRoot )
+void TreeParser::Extract( const OString& rPOFile )
 {
     assert( m_bIsInitialized );
-    std::ofstream aSDFStream(
-        rSDFFile.getStr(), std::ios_base::out | std::ios_base::trunc );
-    if( !aSDFStream.is_open() )
+    PoOfstream aPOStream( rPOFile, PoOfstream::APP );
+    if( !aPOStream.isOpen() )
     {
         std::cerr
-            << "Treex error: Cannot open sdffile for extract: "
-            << rSDFFile.getStr() << std::endl;
+            << "Treex error: Cannot open po file for extract: "
+            << rPOFile.getStr() << std::endl;
         return;
     }
 
     xmlNodePtr pRootNode = xmlDocGetRootElement( m_pSource );
     lcl_ExtractLevel(
         m_pSource, pRootNode, (const xmlChar *)("help_section"),
-        aSDFStream, rPrj, rRoot );
+        aPOStream );
 
     xmlFreeDoc( m_pSource );
     xmlCleanupParser();
-    aSDFStream.close();
+    aPOStream.close();
     m_bIsInitialized = false;
 }
 
diff --git a/l10ntools/source/treex.cxx b/l10ntools/source/treex.cxx
index 65807b1..d8565f8 100644
--- a/l10ntools/source/treex.cxx
+++ b/l10ntools/source/treex.cxx
@@ -51,8 +51,7 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
         }
         else
         {
-            aParser.Extract(
-                aArgs.m_sOutputFile, aArgs.m_sPrj, aArgs.m_sPrjRoot );
+            aParser.Extract( aArgs.m_sOutputFile );
         }
     return 0;
 }
diff --git a/l10ntools/source/uimerge.cxx b/l10ntools/source/uimerge.cxx
index 7b7d315..63b0808 100644
--- a/l10ntools/source/uimerge.cxx
+++ b/l10ntools/source/uimerge.cxx
@@ -23,6 +23,7 @@
 #include "common.hxx"
 #include "export.hxx"
 #include "tokens.h"
+#include "po.hxx"
 #include <iostream>
 #include <fstream>
 #include <vector>
@@ -32,10 +33,23 @@ rtl::OString sPrjRoot;
 rtl::OString sInputFileName;
 rtl::OString sOutputFile;
 
+namespace
+{
+    //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;
+    }
+}
+
 int extractTranslations()
 {
-    FILE *pOutFile = fopen(sOutputFile.getStr(), "w");
-    if (!pOutFile)
+    PoOfstream aPOStream( sOutputFile, PoOfstream::APP);
+    if (!aPOStream.isOpen())
     {
         fprintf(stderr, "cannot open %s\n", sOutputFile.getStr());
         return 1;
@@ -43,8 +57,6 @@ int extractTranslations()
 
     exsltRegisterAll();
 
-    rtl::OString sActFileName = common::pathnameToken(sInputFileName.getStr(), sPrjRoot.getStr());
-
     rtl::OString sStyleSheet = rtl::OString(getenv("SRC_ROOT"))  + rtl::OString("/solenv/bin/uilangfilter.xslt");
 
     xsltStylesheetPtr stylesheet = xsltParseStylesheetFile ((const xmlChar *)sStyleSheet.getStr());
@@ -59,14 +71,19 @@ int extractTranslations()
         {
             if (nodeLevel2->type == XML_ELEMENT_NODE)
             {
-                fprintf(pOutFile, "%s\t%s\t0\t",sPrj.getStr(), sActFileName.getStr());
+                std::vector<OString> vIDs;
                 for(xmlAttrPtr attribute = nodeLevel2->properties; attribute != NULL; attribute = attribute->next)
                 {
                     xmlChar *content = xmlNodeListGetString(res, attribute->children, 1);
-                    fprintf(pOutFile, "%s\t", content);
+                    vIDs.push_back(lcl_xmlStrToOString(content));
                     xmlFree(content);
                 }
-                fprintf(pOutFile, "\t\t0\ten-US\t%s\t\t\t\t\n", xmlNodeGetContent(nodeLevel2));
+                OString sText = lcl_xmlStrToOString(xmlNodeGetContent(nodeLevel2));
+                Export::writePoEntry(
+                    "Uiex", aPOStream, sInputFileName, vIDs[0],
+                    (vIDs.size()>=2) ? vIDs[1] : OString(),
+                    (vIDs.size()>=3) ? vIDs[2] : OString(),
+                    OString(), sText);
             }
         }
     }
@@ -77,7 +94,7 @@ int extractTranslations()
 
     xsltFreeStylesheet(stylesheet);
 
-    fclose(pOutFile);
+    aPOStream.close();
 
     return 0;
 }
diff --git a/l10ntools/source/xrmmerge.cxx b/l10ntools/source/xrmmerge.cxx
index 2b02bce..e231b5d8 100644
--- a/l10ntools/source/xrmmerge.cxx
+++ b/l10ntools/source/xrmmerge.cxx
@@ -44,7 +44,6 @@ sal_Bool bExtensionDescription;
 rtl::OString sPrj;
 rtl::OString sPrjRoot;
 rtl::OString sInputFileName;
-rtl::OString sActFileName;
 rtl::OString sOutputFile;
 rtl::OString sMergeSrc;
 rtl::OString sLangAttribute;
@@ -60,7 +59,6 @@ extern char *GetOutputFile( int argc, char* argv[])
 {
     bDisplayName = sal_False;
     bExtensionDescription = sal_False;
-    sActFileName = "";
 
     HandledArgs aArgs;
     if ( Export::handleArguments(argc, argv, aArgs) )
@@ -95,7 +93,7 @@ int InitXrmExport( char*, char* pFilename)
     if ( bMergeMode )
         pParser = new XRMResMerge( sMergeSrc, sOutputFile, sFilename );
       else if (!sOutputFile.isEmpty()) {
-        pParser = new XRMResExport( sOutputFile, sPrj, sActFileName );
+        pParser = new XRMResExport( sOutputFile, sPrj, sInputFileName );
     }
 
     return 1;
@@ -125,10 +123,6 @@ extern FILE *GetXrmFile()
                 sInputFileName.getStr());
         }
         else {
-            if (!bMergeMode) {
-                sActFileName = common::pathnameToken(
-                    sInputFileName.getStr(), sPrjRoot.getStr());
-            }
             return pFile;
         }
     }
@@ -175,7 +169,6 @@ XRMResParser::XRMResParser()
                 : bError( sal_False ),
                 bText( sal_False )
 {
-    aLanguages = Export::GetLanguages();
 }
 
 /*****************************************************************************/
@@ -336,33 +329,6 @@ void XRMResParser::ConvertStringToXMLFormat( rtl::OString &rString )
     rString = rString.replaceAll("\\t", "\t");
 }
 
-
-
-//
-// class XRMResOutputParser
-//
-
-/*****************************************************************************/
-XRMResOutputParser::XRMResOutputParser ( const rtl::OString &rOutputFile )
-/*****************************************************************************/
-{
-    aLanguages = Export::GetLanguages();
-    pOutputStream.open(
-        rOutputFile.getStr(), std::ios_base::out | std::ios_base::trunc);
-    if (!pOutputStream.is_open()) {
-        rtl::OString sError( "Unable to open output file: " );
-        sError += rOutputFile;
-        Error( sError );
-    }
-}
-
-/*****************************************************************************/
-XRMResOutputParser::~XRMResOutputParser()
-/*****************************************************************************/
-{
-    pOutputStream.close();
-}
-
 //
 // class XMLResExport
 //
@@ -372,18 +338,26 @@ XRMResExport::XRMResExport(
     const rtl::OString &rOutputFile, const rtl::OString &rProject,
     const rtl::OString &rFilePath )
 /*****************************************************************************/
-                : XRMResOutputParser( rOutputFile ),
+                : XRMResParser(),
                 pResData( NULL ),
                 sPrj( rProject ),
                 sPath( rFilePath )
 {
     aLanguages = Export::GetLanguages();
+    pOutputStream.open( rOutputFile, PoOfstream::APP );
+    if (!pOutputStream.isOpen())
+    {
+        rtl::OString sError( "Unable to open output file: " );
+        sError += rOutputFile;
+        Error( sError );
+    }
 }
 
 /*****************************************************************************/
 XRMResExport::~XRMResExport()
 /*****************************************************************************/
 {
+    pOutputStream.close();
     delete pResData;
 }
 
@@ -451,22 +425,10 @@ void XRMResExport::EndOfText(
             rtl::OString sAct(
                 pResData->sText[sCur].replaceAll("\x0A", rtl::OString()));
 
-            rtl::OString sOutput( sPrj ); sOutput += "\t";
-            sOutput += sPath;
-            sOutput += "\t0\t";
-            sOutput += sResourceType;
-            sOutput += "\t";
-            sOutput += pResData->sGId;
-            sOutput += "\t\t\t\t0\t";
-            sOutput += sCur;
-            sOutput += "\t";
-
-            sOutput += sAct;
-            sOutput += "\t\t\t\t";
-
-            sOutput = sOutput.replace('\0', '_');
-            if( sAct.getLength() > 1 )
-                pOutputStream << sOutput.getStr() << '\n';
+            if( !sAct.isEmpty() )
+                Export::writePoEntry(
+                    "Xrmex", pOutputStream, sPath, sResourceType,
+                    pResData->sGId, OString(), OString(), sAct );
         }
     }
     delete pResData;
@@ -482,7 +444,7 @@ XRMResMerge::XRMResMerge(
     const rtl::OString &rMergeSource, const rtl::OString &rOutputFile,
     const rtl::OString &rFilename)
 /*****************************************************************************/
-                : XRMResOutputParser( rOutputFile ),
+                : XRMResParser(),
                 pMergeDataFile( NULL ),
                 sFilename( rFilename ) ,
                 pResData( NULL )
@@ -497,12 +459,20 @@ XRMResMerge::XRMResMerge(
     }
     else
         aLanguages = Export::GetLanguages();
+    pOutputStream.open(
+        rOutputFile.getStr(), std::ios_base::out | std::ios_base::trunc);
+    if (!pOutputStream.is_open()) {
+        rtl::OString sError( "Unable to open output file: " );
+        sError += rOutputFile;
+        Error( sError );
+    }
 }
 
 /*****************************************************************************/
 XRMResMerge::~XRMResMerge()
 /*****************************************************************************/
 {
+    pOutputStream.close();
     delete pMergeDataFile;
     delete pResData;
 }
diff --git a/translations b/translations
index a45c8b4b..85f724f 160000
--- a/translations
+++ b/translations
@@ -1 +1 @@
-Subproject commit a45c8b4b02ef5e45b225c0418bb378b7d332a01f
+Subproject commit 85f724f5aa1d6a59662a7d1c7ea406a641814bd2


More information about the Libreoffice-commits mailing list