diff options
author | Zolnai Tamás <zolnaitamas2000@gmail.com> | 2012-08-29 09:47:26 +0200 |
---|---|---|
committer | Andras Timar <atimar@suse.com> | 2012-08-29 07:59:36 +0000 |
commit | 437ae002185a81802cb31b00fa777a7b5d8f9847 (patch) | |
tree | cc117bb7725202b1764dacb174e224e22ff91ebd | |
parent | 42688495edac102b18014a02072ba081870059db (diff) |
Renew localization and kill sdf 1.step
Extract strings from source directly to pot files
Implement PoHeader and PoEntry classes
Renew fomrat of pot/po files
Implement conversion from old po to new po
Change-Id: I411b6041f7d525e76b189d7f31adc5b9ab60f6d6
Reviewed-on: https://gerrit.libreoffice.org/506
Reviewed-by: Andras Timar <atimar@suse.com>
Tested-by: Andras Timar <atimar@suse.com>
-rw-r--r-- | Repository.mk | 1 | ||||
-rw-r--r-- | l10ntools/Executable_localize.mk | 9 | ||||
-rw-r--r-- | l10ntools/Executable_renewpo.mk | 36 | ||||
-rw-r--r-- | l10ntools/Module_l10ntools.mk | 1 | ||||
-rw-r--r-- | l10ntools/StaticLibrary_transex.mk | 1 | ||||
-rw-r--r-- | l10ntools/inc/po.hxx | 97 | ||||
-rw-r--r-- | l10ntools/source/localize.cxx | 135 | ||||
-rw-r--r-- | l10ntools/source/po.cxx | 309 | ||||
-rw-r--r-- | l10ntools/source/renewpo.cxx | 168 |
9 files changed, 718 insertions, 39 deletions
diff --git a/Repository.mk b/Repository.mk index cadf342562d3..8e5847418533 100644 --- a/Repository.mk +++ b/Repository.mk @@ -50,6 +50,7 @@ $(eval $(call gb_Helper_register_executables,NONE, \ rdbmaker \ regsingleton \ regsvrex \ + renewpo \ rsc \ rscdep \ saxparser \ diff --git a/l10ntools/Executable_localize.mk b/l10ntools/Executable_localize.mk index 511604ac74d2..6184a8982bd5 100644 --- a/l10ntools/Executable_localize.mk +++ b/l10ntools/Executable_localize.mk @@ -26,10 +26,19 @@ $(eval $(call gb_Executable_Executable,localize)) +$(eval $(call gb_Executable_set_include,localize,\ + -I$(SRCDIR)/l10ntools/inc \ + $$(INCLUDE) \ +)) + $(eval $(call gb_Executable_use_libraries,localize,\ sal \ )) +$(eval $(call gb_Executable_use_static_libraries,localize,\ + transex \ +)) + $(eval $(call gb_Executable_add_exception_objects,localize,\ l10ntools/source/localize \ )) diff --git a/l10ntools/Executable_renewpo.mk b/l10ntools/Executable_renewpo.mk new file mode 100644 index 000000000000..33e38b22751f --- /dev/null +++ b/l10ntools/Executable_renewpo.mk @@ -0,0 +1,36 @@ +# for the specific language governing rights and limitations under the +# License. +# +# Major Contributor(s): +# Copyright (C) 2012 David Ostrovsky <d.ostrovsky@gmx.de> (initial developer) +# +# All Rights Reserved. +# +# For minor contributions see the git repository. +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 3 or later (the "GPLv3+"), or +# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +# instead of those above. + +$(eval $(call gb_Executable_Executable,renewpo)) + +$(eval $(call gb_Executable_set_include,renewpo,\ + -I$(SRCDIR)/l10ntools/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_Executable_use_libraries,renewpo,\ + sal \ +)) + +$(eval $(call gb_Executable_use_static_libraries,renewpo,\ + transex \ +)) + +$(eval $(call gb_Executable_add_exception_objects,renewpo,\ + l10ntools/source/renewpo \ +)) + +# vim:set shiftwidth=4 softtabstop=4 expandtab: diff --git a/l10ntools/Module_l10ntools.mk b/l10ntools/Module_l10ntools.mk index e3c11344a0c9..fb2a3b3289e5 100644 --- a/l10ntools/Module_l10ntools.mk +++ b/l10ntools/Module_l10ntools.mk @@ -38,6 +38,7 @@ $(eval $(call gb_Module_add_targets,l10ntools,\ Executable_transex3 \ Executable_helpindexer \ Executable_helplinker \ + Executable_renewpo \ StaticLibrary_transex \ Library_helplinker \ Package_inc \ diff --git a/l10ntools/StaticLibrary_transex.mk b/l10ntools/StaticLibrary_transex.mk index e8c84b7d3662..21f50e572ef6 100644 --- a/l10ntools/StaticLibrary_transex.mk +++ b/l10ntools/StaticLibrary_transex.mk @@ -37,6 +37,7 @@ $(eval $(call gb_StaticLibrary_add_exception_objects,transex,\ l10ntools/source/merge \ l10ntools/source/file \ l10ntools/source/directory \ + l10ntools/source/po \ )) # vim: set noet sw=4 ts=4: diff --git a/l10ntools/inc/po.hxx b/l10ntools/inc/po.hxx new file mode 100644 index 000000000000..de01053ba217 --- /dev/null +++ b/l10ntools/inc/po.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PO_INCLUDED +#define _PO_INCLUDED + +#include <fstream> +#include <rtl/string.hxx> + +class PoEntry +{ + +private: + + OString m_sWhiteSpace; + OString m_sExtractCom; + OString m_sReference; + OString m_sContext; + OString m_sUnTransStr; + OString m_sTransStr; + + OString m_sKeyId; + +protected: + void setExtractCom(const OString& rExtCom) + { m_sExtractCom = rExtCom; } + +public: + PoEntry(); + PoEntry(const OString& i_rSDFLine, + const sal_uInt16 eType = TEXT); + virtual ~PoEntry(); + + virtual void writeToFile(std::ofstream& io_rOFStream); + + void setTransStr(const OString& rTransStr); + + enum SDFPARTS { PROJECT, SOURCEFILE, DUMMY, RESOURCETYPE, GROUPID, + LOCALID, HELPID, PLATFORM, WIDTH, LANGUAGEID, + TEXT, HELPTEXT, QUICKHELPTEXT, TITLE, TIMESTAMP }; +}; + + + + +class PoHeader: public PoEntry +{ + +private: + OString m_sExtractionSource; + OString m_sProjectIdVersion; + OString m_sReportMsgidBugsTo; + OString m_sPotCreationDate; + OString m_sPoRevisionDate; + OString m_sLastTranslator; + OString m_sLanguageTeam; + OString m_sMimeVersion; + OString m_sPluralForms; + OString m_sContentType; + OString m_sCharset; + OString m_sEncoding; + OString m_sXGenerator; + OString m_sXAcceleratorMarker; + +public: + PoHeader( const OString& rExtSrc ); + ~PoHeader(); +}; + +#endif // _PO_INCLUDED + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/source/localize.cxx b/l10ntools/source/localize.cxx index a54d096503df..c10c3f515c0f 100644 --- a/l10ntools/source/localize.cxx +++ b/l10ntools/source/localize.cxx @@ -50,16 +50,12 @@ #include "sal/main.h" #include "sal/types.h" +#include "po.hxx" + using namespace std; namespace { -namespace global { - -std::ofstream output; - -} - rtl::OUString getEnvironment(rtl::OUString const & variable) { rtl::OUString value; if (osl_getEnvironment(variable.pData, &value.pData) != osl_Process_E_None) @@ -174,7 +170,8 @@ bool passesPositiveList(rtl::OUString const & url) { void handleCommand( rtl::OUString const & project, rtl::OUString const & projectRoot, - rtl::OUString const & url, rtl::OUString const & executable, bool positive) + rtl::OUString const & url, rtl::OUString const & actualDir, + std::ofstream & outPut, rtl::OUString const & executable, bool positive) { if (positive ? passesPositiveList(url) : passesNegativeList(url)) { rtl::OUString inPath; @@ -197,13 +194,13 @@ void handleCommand( throw false; //TODO } rtl::OUStringBuffer buf( - getEnvironment( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SOLARVER")))); - buf.append('/'); - buf.append( - getEnvironment( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("INPATH_FOR_BUILD")))); + //getEnvironment( + //rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SOLARVER")))); + //buf.append('/'); + //buf.append( + //getEnvironment( + rtl::OUString("/home/zolnai/git/libo/solver/unxlngi6.pro")); + // RTL_CONSTASCII_USTRINGPARAM("INPATH_FOR_BUILD")))); buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/bin/")); buf.append(executable); buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -e -p ")); @@ -239,23 +236,70 @@ void handleCommand( } std::ifstream in(outPath8.getStr()); if (!in.is_open()) { - std::cerr << "Error: Cannot open " << outPath.getStr() << "\n"; + std::cerr << "Error: Cannot open " << outPath8.getStr() << "\n"; throw false; //TODO } + + std::string s; + std::getline(in, s); + if (!in.eof() && !outPut.is_open()) + { + rtl::OUString outDirUrl; + if (osl::FileBase::getFileURLFromSystemPath(actualDir. + copy(0,actualDir.lastIndexOf('/')), outDirUrl) + != osl::FileBase::E_None) + { + std::cerr << "Error: Cannot convert pathname to URL\n"; + throw false; //TODO + } + osl::Directory::createPath(outDirUrl); + + rtl::OString outFilePath; + if (!actualDir.concat(".pot"). + convertToString( + &outFilePath, osl_getThreadTextEncoding(), + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + std::cerr << "Error: Cannot convert pathname from UTF-16\n"; + throw false; //TODO + } + outPut.open(outFilePath.getStr(), + std::ios_base::out | std::ios_base::trunc); + rtl::OString relativPath; + if (!inPath.copy(inPath.indexOf(project), + inPath.lastIndexOf('/')-inPath.indexOf(project)). + convertToString(&relativPath, osl_getThreadTextEncoding(), + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + std::cerr << "Error: Cannot convert pathname from UTF-16\n"; + throw false; //TODO + } + PoHeader(relativPath).writeToFile(outPut); + } while (!in.eof()) { - std::string s; + OString sLine = OString(s.data(),s.length()); + if (!sLine.isEmpty()) + { + if (!sLine.getToken(PoEntry::TEXT,'\t').isEmpty()) + PoEntry(sLine).writeToFile(outPut); + if (!sLine.getToken(PoEntry::QUICKHELPTEXT,'\t').isEmpty()) + PoEntry(sLine,PoEntry::QUICKHELPTEXT).writeToFile(outPut); + if (!sLine.getToken(PoEntry::TITLE,'\t').isEmpty()) + PoEntry(sLine,PoEntry::TITLE).writeToFile(outPut); + } std::getline(in, s); - if (!s.empty()) - global::output << s << '\n'; - } + }; in.close(); } } void handleFile( rtl::OUString const & project, rtl::OUString const & projectRoot, - rtl::OUString const & url) + rtl::OUString const & url, rtl::OUString const & actualDir, + std::ofstream & outPut) { struct Command { char const * extension; @@ -277,7 +321,7 @@ void handleFile( commands[i].extension, commands[i].extensionLength)) { handleCommand( - project, projectRoot, url, + project, projectRoot, url, actualDir, outPut, rtl::OUString::createFromAscii(commands[i].executable), commands[i].positive); break; @@ -386,8 +430,9 @@ bool excludeDirectory(rtl::OUString const & directory) { /// level <= 0) void handleDirectory( rtl::OUString const & url, int level, rtl::OUString const & project, - rtl::OUString const & projectRoot) + rtl::OUString const & projectRoot, rtl::OUString const & actualDir) { + std::ofstream output; osl::Directory dir(url); if (dir.open() != osl::FileBase::E_None) { std::cerr @@ -417,7 +462,8 @@ void handleDirectory( case -1: // the clone or src directory if (stat.getFileType() == osl::FileStatus::Directory) { handleDirectory( - stat.getFileURL(), 0, rtl::OUString(), rtl::OUString()); + stat.getFileURL(), 0, rtl::OUString(), + rtl::OUString(), actualDir); } break; case 0: // a root directory @@ -425,12 +471,14 @@ void handleDirectory( if (includeProject(stat.getFileName())) { handleDirectory( stat.getFileURL(), 1, stat.getFileName(), - rtl::OUString()); - } else if ( stat.getFileName() == "clone" || stat.getFileName() == "src" ) + rtl::OUString(), actualDir.concat("/"). + concat(stat.getFileName())); + } else if ( stat.getFileName() == "clone" || + stat.getFileName() == "src" ) { handleDirectory( stat.getFileURL(), -1, rtl::OUString(), - rtl::OUString()); + rtl::OUString(), actualDir); } } break; @@ -442,24 +490,29 @@ void handleDirectory( pr += rtl::OUString('/'); } pr += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("..")); - handleDirectory(stat.getFileURL(), 2, project, pr); + handleDirectory(stat.getFileURL(), 2, project, pr, + actualDir.concat("/"). + concat(stat.getFileName())); } } else { - handleFile(project, projectRoot, stat.getFileURL()); + handleFile(project, projectRoot, + stat.getFileURL(), actualDir, output); } break; } } + if (output.is_open()) + output.close(); if (dir.close() != osl::FileBase::E_None) { std::cerr << "Error: Cannot close directory\n"; throw false; //TODO } } -void handleProjects(char const * root) { +void handleProjects(char const * sourceRoot, char const * destRoot) { rtl::OUString root16; if (!rtl_convertStringToUString( - &root16.pData, root, rtl_str_getLength(root), + &root16.pData, sourceRoot, rtl_str_getLength(sourceRoot), osl_getThreadTextEncoding(), (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR @@ -475,9 +528,19 @@ void handleProjects(char const * root) { std::cerr << "Error: Cannot convert pathname to URL\n"; throw false; //TODO } - handleDirectory(rootUrl, 0, rtl::OUString(), rtl::OUString()); + rtl::OUString outPutRoot; + if (!rtl_convertStringToUString( + &outPutRoot.pData, destRoot, rtl_str_getLength(destRoot), + osl_getThreadTextEncoding(), + (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR + | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR + | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) + { + std::cerr << "Error: Cannot convert pathname to UTF-16\n"; + throw false; //TODO + } + handleDirectory(rootUrl, 0, rtl::OUString(), rtl::OUString(), outPutRoot); } - } SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) { @@ -490,17 +553,11 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) { "Syntax: localize <source-root> <outfile>\n"); std::exit(EXIT_FAILURE); } - global::output.open(argv[2], std::ios_base::out | std::ios_base::trunc); - if (!global::output.is_open()) { - std::cerr << "Error: Cannot append to " << argv[2] << '\n'; - std::exit(EXIT_FAILURE); - } try { - handleProjects(argv[1]); + handleProjects(argv[1],argv[2]); } catch (bool) { //TODO return EXIT_FAILURE; } - global::output.close(); return EXIT_SUCCESS; } diff --git a/l10ntools/source/po.cxx b/l10ntools/source/po.cxx new file mode 100644 index 000000000000..ab926792f70d --- /dev/null +++ b/l10ntools/source/po.cxx @@ -0,0 +1,309 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "po.hxx" +#include <ctime> +#include <vector> + +#define ESCAPED OString("\\n\\t\\r\\\\\\\"") +#define UNESCAPED OString("\n\t\r\\\"") + + +//Get actual time in "YEAR-MO-DA HO:MI+ZONE" form +OString ImplGetTime() +{ + time_t aNow(time(NULL)); + struct tm* pNow(localtime(&aNow)); + char pBuff[50]; + strftime( pBuff, sizeof pBuff, "%Y-%m-%d %H:%M%z", pNow ); + return pBuff; +} + +//Split string at the delimiter char +void ImplSplitAt(const OString& rSource, const sal_Int32 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)); +} + +//Escape text +OString ImplEscapeText(const OString& rText, const OString& rUnEscaped, + const OString& rEscaped) +{ + if(rEscaped.getLength()!=2*rUnEscaped.getLength()) throw; + OString sResult = rText; + sal_Int32 nCount = 0; + for(sal_Int32 nIndex=0; nIndex<rText.getLength(); ++nIndex) + { + sal_Int32 nActChar = rUnEscaped.indexOf(rText[nIndex]); + if(nActChar!=-1) + sResult = sResult.replaceAt((nIndex)+(nCount++),1, + rEscaped.copy(2*nActChar,2)); + } + return sResult; +} + + +//Escape text to write to po files +OString ImplEscapeText(const OString& rText) +{ + return ImplEscapeText(rText,UNESCAPED,ESCAPED); +} + +//Unescape text +OString ImplUnEscapeText(const OString& rText,const OString& rEscaped, + const OString& rUnEscaped) +{ + if(rEscaped.getLength()!=2*rUnEscaped.getLength()) throw; + OString sResult = rText; + sal_Int32 nCount = 0; + for(sal_Int32 nIndex=0; nIndex<rText.getLength()-1; ++nIndex) + { + sal_Int32 nActChar = rEscaped.indexOf(rText.copy(nIndex,2)); + if(nActChar % 2 == 0) + sResult = sResult.replaceAt((nIndex++)-(nCount++),2, + rUnEscaped.copy(nActChar/2,1)); + } + return sResult; +} + +//Unescape text from po files +OString ImplUnEscapeText(const OString& rText) +{ + return ImplUnEscapeText(rText,ESCAPED,UNESCAPED); +} + +//Unescape extracted helptext +OString ImplFromSDFHelpText(const OString& rText) +{ + return ImplUnEscapeText(rText,"\\<\\>\\\"\\\\","<>\"\\"); +} + +//Unescape extracted text +OString ImplFromSDFText(const OString& rText) +{ + return ImplUnEscapeText(rText,"\\n\\t\\r","\n\t\r"); +} + + +//Generate msgctxt, msgid and msgstr strings +OString ImplGenMsgString(const OString& rSource) +{ + if ( rSource.isEmpty() ) + return "\"\""; + + OString sResult = "\"" + rSource + "\""; + sal_Int32 nIndex = 0; + while((nIndex=sResult.indexOf("\\n",nIndex))!=-1) + { + if( sResult.copy(nIndex-1,3) != "\\\\n" ) + sResult = sResult.replaceAt(nIndex,2,"\\n\"\n\""); + ++nIndex; + } + + if ( sResult.indexOf('\n') != -1 ) + return "\"\"\n" + sResult; + + return sResult; +} + +//Generate crc24 +sal_Int32 ImplGenCRC24(const OString& rKey) +{ + const sal_Int32 CRC24_INIT = 0x00b704ce; + const sal_Int32 CRC24_POLY = 0x00864cfb; + sal_Int32 nCRC = CRC24_INIT; + sal_Int32 nPosition = 0; + + while ( nPosition < rKey.getLength() ) + { + nCRC ^= sal_Int32(rKey[nPosition]) << 16; + for (sal_uInt16 i = 0; i < 8; ++i) + { + nCRC <<= 1; + if (nCRC & 0x01000000) + nCRC ^= CRC24_POLY; + } + ++nPosition; + } + return nCRC & 0x00ffffff; +} + +//Generate KeyId +OString ImplGenKeyId(const OString& rSourcePath, const OString& rContext) +{ + std::vector<OString> vPathParts; + ImplSplitAt(rSourcePath,'\\',vPathParts); + if ( vPathParts.size()<3 ) throw; + + sal_Int32 nCRC = ImplGenCRC24( vPathParts[vPathParts.size()-3] + "_" + + vPathParts[vPathParts.size()-2] + "_" + + vPathParts[vPathParts.size()-1] + "_" + + rContext); + const OString sSymbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#_"; + OString sKeyId = ""; + while ( sKeyId.getLength() < 4 ) + { + sKeyId += sSymbols.copy(nCRC & 63, 1); + nCRC >>= 6; + } + return sKeyId; +} + +//Default constructor +PoEntry::PoEntry() + : m_sWhiteSpace( OString() ) + , m_sExtractCom( OString() ) + , m_sReference( OString() ) + , m_sContext( OString() ) + , m_sUnTransStr( OString() ) + , m_sTransStr( OString() ) + , m_sKeyId( OString() ) +{ +} + +//Construct PoEntry from sdfline +PoEntry::PoEntry(const OString& rSDFLine, const sal_uInt16 eType) + : m_sWhiteSpace( "\n" ) + , m_sExtractCom( OString() ) + , m_sTransStr( OString() ) + , m_sKeyId( OString() ) +{ + std::vector<OString> vParts; + ImplSplitAt(rSDFLine,'\t',vParts); + if(vParts.size()!=15) throw; + + m_sReference = vParts[SOURCEFILE]. + copy(vParts[SOURCEFILE].lastIndexOf("\\")+1); + m_sContext = vParts[GROUPID] + "\\n" + + (vParts[LOCALID].isEmpty()? "" : vParts[LOCALID] + "\\n") + + vParts[RESOURCETYPE]; + + switch(eType){ + case TEXT: + m_sContext += ".text"; break; + case QUICKHELPTEXT: + m_sContext += ".quickhelptext"; break; + case TITLE: + m_sContext += ".title"; break; + default: + throw; break; + } + if (m_sReference.endsWith(".xhp")) + m_sUnTransStr = ImplFromSDFHelpText(vParts[eType]); + else + m_sUnTransStr = ImplFromSDFText(vParts[eType]); + + m_sExtractCom = vParts[HELPTEXT]; + m_sKeyId = ImplGenKeyId(vParts[PROJECT] + + "\\" + vParts[SOURCEFILE],m_sContext); +} + +PoEntry::~PoEntry() +{ +} + +//Write out +void PoEntry::writeToFile(std::ofstream& io_rOFStream) +{ + if ( !m_sWhiteSpace.isEmpty() ) + io_rOFStream << m_sWhiteSpace.getStr(); + if ( !m_sExtractCom.isEmpty() ) + io_rOFStream << "#. " << m_sExtractCom.getStr() << std::endl; + if ( !m_sKeyId.isEmpty() ) + io_rOFStream << "#. " << m_sKeyId.getStr() << std::endl; + if ( !m_sReference.isEmpty() ) + io_rOFStream << "#: " << m_sReference.getStr() << std::endl; + if ( !m_sContext.isEmpty() ) + io_rOFStream << "msgctxt " + << ImplGenMsgString(m_sContext).getStr() << std::endl; + io_rOFStream << "msgid " + << ImplGenMsgString( + ImplEscapeText(m_sUnTransStr)).getStr() + << std::endl; + io_rOFStream << "msgstr " + << ImplGenMsgString( + ImplEscapeText(m_sTransStr)).getStr() + << std::endl; +} + +void PoEntry::setTransStr(const OString& rTransStr) +{ + m_sTransStr = ImplUnEscapeText(rTransStr); +} + +//Constructor +PoHeader::PoHeader( const OString& rExtSrc ) + : m_sExtractionSource( rExtSrc ) + , m_sProjectIdVersion( "PACKAGE VERSION" ) + , m_sReportMsgidBugsTo( OString("https://bugs.freedesktop.org/") + + "enter_bug.cgi?product=LibreOffice&" + + "bug_status=UNCONFIRMED&component=UI" ) + , m_sPotCreationDate( ImplGetTime() ) + , m_sPoRevisionDate( "YEAR-MO-DA HO:MI+ZONE" ) + , m_sLastTranslator( "FULL NAME <EMAIL@ADDRESS>" ) + , m_sLanguageTeam( "LANGUAGE <LL@li.org>" ) + , m_sMimeVersion( "1.0" ) + , m_sContentType( "text/plain" ) + , m_sCharset( "UTF-8" ) + , m_sEncoding( "8bit" ) + , m_sXGenerator( "LibreOffice" ) + , m_sXAcceleratorMarker( "~" ) +{ + setExtractCom("extracted from " + rExtSrc); + setTransStr("Project-Id-Version: " + m_sProjectIdVersion + "\n" + + "Report-Msgid-Bugs-To: " + m_sReportMsgidBugsTo + "\n" + + "POT-Creation-Date: " + m_sPotCreationDate + "\n" + + "PO-Revision-Date: " + m_sPoRevisionDate + "\n" + + "Last-Translator: " + m_sLastTranslator + "\n" + + "Language-Team: " + m_sLanguageTeam + "\n" + + "MIME-Version: " + m_sMimeVersion + "\n" + + "Content-Type: " + m_sContentType + "; " + + "charset=" + m_sCharset + "\n" + + "Content-Transfer-Encoding: " + m_sEncoding + "\n" + + "X-Genarator: " + m_sXGenerator + "\n" + + "X-Accelerator_Marker: " + m_sXAcceleratorMarker + "\n"); +} + +PoHeader::~PoHeader() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/source/renewpo.cxx b/l10ntools/source/renewpo.cxx new file mode 100644 index 000000000000..c9fad34a99f3 --- /dev/null +++ b/l10ntools/source/renewpo.cxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <iostream> +#include <fstream> +#include <dirent.h> +#include <string> +#include <rtl/string.hxx> +#include "po.hxx" + +using namespace std; + +//Check wheather the two entry are the same but in different languages +bool IsSameEntry(const OString& rFirstEntry,const OString& rSecEntry) +{ + for(int i = PoEntry::PROJECT; i<=PoEntry::LOCALID;++i) + { + if ( rFirstEntry.getToken(i,'\t') != rSecEntry.getToken(i,'\t')) + return false; + } + return true; +} + +//Get path of po file +OString GetPath(const OString& rPath, const OString& rLine) +{ + OString sSourceFile = rLine.getToken(PoEntry::SOURCEFILE,'\t'); + OString sSourcePath = rPath + "/" + + rLine.getToken(PoEntry::PROJECT,'\t') + "/" + + sSourceFile.copy(0,sSourceFile.lastIndexOf("\\")). + replaceAll("\\","/"); + return sSourcePath; +} + +//Renew po files of the actual language +void HandleLanguage(struct dirent* pLangEntry, const OString& rPath, + const OString& rpo2ooPath, const OString& rSDFPath) +{ + const OString LangEntryName = pLangEntry->d_name; + const OString SDFFileName = LangEntryName + ".sdf"; + + //Generate and open sdf + cout << "Start process with language: " << LangEntryName.getStr() << endl; + system( (rpo2ooPath + " -t " + rSDFPath + + " -l " + LangEntryName + " " + + rPath.getStr() + LangEntryName + " " + + SDFFileName).getStr()); + + ofstream aOutPut; + ifstream aSDFInput(SDFFileName.getStr()); + string s; + getline(aSDFInput,s); + OString sLine = OString(s.data(),s.length()); + while(!aSDFInput.eof()) + { + OString sActUnTrans = sLine; + OString sPath = rPath + LangEntryName; + OString sActSourcePath = GetPath(sPath,sActUnTrans); + //Make new po file, copy header with some changes + if (!aOutPut.is_open()) + { + aOutPut.open((sActSourcePath + ".po_tmp").getStr(), + std::ios_base::out | std::ios_base::trunc); + ifstream aPOInput((sActSourcePath + ".po").getStr()); + getline(aPOInput,s); + while(s!="") + { + if (s.find("#. extracted from")!=string::npos) + s = string(s,0,s.length()-3); + if (s.find("Report-Msgid-Bugs-To")!=string::npos) + s = string("\"Report-Msgid-Bugs-To: ") + + "https://bugs.freedesktop.org/enter_bug.cgi?product=" + + "LibreOffice&bug_status=UNCONFIRMED&component=UI\\n\""; + if (s.find("X-Generator")!=string::npos) + s = "\"X-Generator: LibreOffice\\n\""; + aOutPut << s << endl; + getline(aPOInput,s); + }; + aPOInput.close(); + } + + //Set PoEntry and write out + getline(aSDFInput,s); + sLine = OString(s.data(),s.length()); + OString sActTrans; + if (IsSameEntry(sActUnTrans,sLine)) + { + sActTrans = sLine; + getline(aSDFInput,s); + sLine = OString(s.data(),s.length()); + } + else + { + sActTrans =""; + } + PoEntry aPE(sActUnTrans); + aPE.setTransStr(sActTrans.getToken(PoEntry::TEXT,'\t')); + aPE.writeToFile(aOutPut); + + //Check wheather next entry is in the same po file + OString sNextSourcePath = GetPath(sPath,sLine); + if (sNextSourcePath!=sActSourcePath) + { + aOutPut.close(); + system(("rm " + sActSourcePath +".po").getStr()); + system(("mv "+ sActSourcePath +".po_tmp " + + sActSourcePath +".po").getStr()); + } + } + + //Close and remove sdf file + aSDFInput.close(); + system(("rm " + SDFFileName).getStr()); + aOutPut.close(); +} + + +int main(int argc, char* argv[]) +{ + //Usage + if (argc < 4) + { + cout << "Use: renewpot translationsdir po2oo en-us.sdf" << endl; + cout << "translationsdir: in this dir there are language" << endl; + cout << "directories which contain the po files. These" << endl; + cout << "directories have named by the languageid" << endl; + cout << "po2oo: the path withwhich po2oo can be call" << endl; + cout << "en-us.sdf: the path to call po2oo with this sdf" << endl; + return 1; + } + + //Call processing function with all language directories + DIR* pTranslations = opendir(argv[1]); + while ( struct dirent* pActEntry = readdir(pTranslations) ) + { + if ( OString(pActEntry->d_name).indexOf('.')==-1 ) + HandleLanguage(pActEntry,OString(argv[1]), + OString(argv[2]),OString(argv[3])); + } + closedir(pTranslations); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |