d33d592801
and cid#1554819 COPY_INSTEAD_OF_MOVE cid#1554837 COPY_INSTEAD_OF_MOVE cid#1554881 COPY_INSTEAD_OF_MOVE cid#1554882 COPY_INSTEAD_OF_MOVE cid#1554884 COPY_INSTEAD_OF_MOVE cid#1554891 COPY_INSTEAD_OF_MOVE cid#1554892 COPY_INSTEAD_OF_MOVE cid#1554897 COPY_INSTEAD_OF_MOVE cid#1554904 COPY_INSTEAD_OF_MOVE cid#1554918 COPY_INSTEAD_OF_MOVE cid#1554928 COPY_INSTEAD_OF_MOVE cid#1554931 COPY_INSTEAD_OF_MOVE cid#1554944 COPY_INSTEAD_OF_MOVE cid#1554945 COPY_INSTEAD_OF_MOVE cid#1554959 COPY_INSTEAD_OF_MOVE cid#1554960 COPY_INSTEAD_OF_MOVE cid#1554963 COPY_INSTEAD_OF_MOVE cid#1554966 COPY_INSTEAD_OF_MOVE cid#1554969 COPY_INSTEAD_OF_MOVE cid#1554973 COPY_INSTEAD_OF_MOVE cid#1555011 COPY_INSTEAD_OF_MOVE cid#1555012 COPY_INSTEAD_OF_MOVE cid#1555015 COPY_INSTEAD_OF_MOVE cid#1555044 COPY_INSTEAD_OF_MOVE cid#1555051 COPY_INSTEAD_OF_MOVE cid#1555055 COPY_INSTEAD_OF_MOVE cid#1555063 COPY_INSTEAD_OF_MOVE cid#1555068 COPY_INSTEAD_OF_MOVE cid#1555073 COPY_INSTEAD_OF_MOVE cid#1555074 COPY_INSTEAD_OF_MOVE cid#1555078 COPY_INSTEAD_OF_MOVE cid#1555080 COPY_INSTEAD_OF_MOVE cid#1555091 COPY_INSTEAD_OF_MOVE cid#1555099 COPY_INSTEAD_OF_MOVE cid#1555101 COPY_INSTEAD_OF_MOVE cid#1555121 COPY_INSTEAD_OF_MOVE cid#1610739 COPY_INSTEAD_OF_MOVE cid#1608424 COPY_INSTEAD_OF_MOVE cid#1608059 COPY_INSTEAD_OF_MOVE cid#1607952 COPY_INSTEAD_OF_MOVE cid#1607653 COPY_INSTEAD_OF_MOVE cid#1607614 COPY_INSTEAD_OF_MOVE cid#1607592 COPY_INSTEAD_OF_MOVE Change-Id: Ie9f922a9fe1b8001dfab31e2741fe8bd5558e442 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170802 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
644 lines
18 KiB
C++
644 lines
18 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include <rtl/ustring.hxx>
|
|
#include <rtl/strbuf.hxx>
|
|
#include <rtl/crc.h>
|
|
#include <sal/log.hxx>
|
|
|
|
#include <cstring>
|
|
#include <ctime>
|
|
#include <cassert>
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
#include <po.hxx>
|
|
#include <helper.hxx>
|
|
|
|
/** Container of po entry
|
|
|
|
Provide all file operations related to LibreOffice specific
|
|
po entry and store it's attributes.
|
|
*/
|
|
class GenPoEntry
|
|
{
|
|
private:
|
|
OStringBuffer m_sExtractCom;
|
|
std::vector<OString> m_sReferences;
|
|
OString m_sMsgCtxt;
|
|
OString m_sMsgId;
|
|
OString m_sMsgIdPlural;
|
|
OString m_sMsgStr;
|
|
std::vector<OString> m_sMsgStrPlural;
|
|
bool m_bFuzzy;
|
|
bool m_bCFormat;
|
|
bool m_bNull;
|
|
|
|
public:
|
|
GenPoEntry();
|
|
|
|
const std::vector<OString>& getReference() const { return m_sReferences; }
|
|
const OString& getMsgCtxt() const { return m_sMsgCtxt; }
|
|
const OString& getMsgId() const { return m_sMsgId; }
|
|
const OString& getMsgStr() const { return m_sMsgStr; }
|
|
bool isFuzzy() const { return m_bFuzzy; }
|
|
bool isNull() const { return m_bNull; }
|
|
|
|
void setExtractCom(std::string_view rExtractCom)
|
|
{
|
|
m_sExtractCom = rExtractCom;
|
|
}
|
|
void setReference(const OString& rReference)
|
|
{
|
|
m_sReferences.push_back(rReference);
|
|
}
|
|
void setMsgCtxt(const OString& rMsgCtxt)
|
|
{
|
|
m_sMsgCtxt = rMsgCtxt;
|
|
}
|
|
void setMsgId(const OString& rMsgId)
|
|
{
|
|
m_sMsgId = rMsgId;
|
|
}
|
|
void setMsgStr(const OString& rMsgStr)
|
|
{
|
|
m_sMsgStr = rMsgStr;
|
|
}
|
|
|
|
void writeToFile(std::ofstream& rOFStream) const;
|
|
void readFromFile(std::ifstream& rIFStream);
|
|
};
|
|
|
|
namespace
|
|
{
|
|
// Convert a normal string to msg/po output string
|
|
OString lcl_GenMsgString(std::string_view rString)
|
|
{
|
|
if ( rString.empty() )
|
|
return "\"\""_ostr;
|
|
|
|
OString sResult =
|
|
"\"" +
|
|
helper::escapeAll(rString,"\n""\t""\r""\\""\"","\\n""\\t""\\r""\\\\""\\\"") +
|
|
"\"";
|
|
sal_Int32 nIndex = 0;
|
|
while((nIndex=sResult.indexOf("\\n",nIndex))!=-1)
|
|
{
|
|
if( !sResult.match("\\\\n", nIndex-1) &&
|
|
nIndex!=sResult.getLength()-3)
|
|
{
|
|
sResult = sResult.replaceAt(nIndex,2,"\\n\"\n\"");
|
|
}
|
|
++nIndex;
|
|
}
|
|
|
|
if ( sResult.indexOf('\n') != -1 )
|
|
return "\"\"\n" + sResult;
|
|
|
|
return sResult;
|
|
}
|
|
|
|
// Convert msg string to normal form
|
|
OString lcl_GenNormString(std::string_view rString)
|
|
{
|
|
return
|
|
helper::unEscapeAll(
|
|
rString.substr(1,rString.size()-2),
|
|
"\\n""\\t""\\r""\\\\""\\\"",
|
|
"\n""\t""\r""\\""\"");
|
|
}
|
|
}
|
|
|
|
GenPoEntry::GenPoEntry()
|
|
: m_bFuzzy( false )
|
|
, m_bCFormat( false )
|
|
, m_bNull( false )
|
|
{
|
|
}
|
|
|
|
void GenPoEntry::writeToFile(std::ofstream& rOFStream) const
|
|
{
|
|
if ( rOFStream.tellp() != std::ofstream::pos_type( 0 ))
|
|
rOFStream << std::endl;
|
|
if ( !m_sExtractCom.isEmpty() )
|
|
rOFStream
|
|
<< "#. "
|
|
<< m_sExtractCom.toString().replaceAll("\n"_ostr,"\n#. "_ostr) << std::endl;
|
|
for(const auto& rReference : m_sReferences)
|
|
rOFStream << "#: " << rReference << std::endl;
|
|
if ( m_bFuzzy )
|
|
rOFStream << "#, fuzzy" << std::endl;
|
|
if ( m_bCFormat )
|
|
rOFStream << "#, c-format" << std::endl;
|
|
if ( !m_sMsgCtxt.isEmpty() )
|
|
rOFStream << "msgctxt "
|
|
<< lcl_GenMsgString(m_sMsgCtxt)
|
|
<< std::endl;
|
|
rOFStream << "msgid "
|
|
<< lcl_GenMsgString(m_sMsgId) << std::endl;
|
|
if ( !m_sMsgIdPlural.isEmpty() )
|
|
rOFStream << "msgid_plural "
|
|
<< lcl_GenMsgString(m_sMsgIdPlural)
|
|
<< std::endl;
|
|
if ( !m_sMsgStrPlural.empty() )
|
|
for(auto & line : m_sMsgStrPlural)
|
|
rOFStream << line.copy(0,10) << lcl_GenMsgString(line.subView(10)) << std::endl;
|
|
else
|
|
rOFStream << "msgstr "
|
|
<< lcl_GenMsgString(m_sMsgStr) << std::endl;
|
|
}
|
|
|
|
void GenPoEntry::readFromFile(std::ifstream& rIFStream)
|
|
{
|
|
*this = GenPoEntry();
|
|
OString* pLastMsg = nullptr;
|
|
std::string sTemp;
|
|
getline(rIFStream,sTemp);
|
|
if( rIFStream.eof() || sTemp.empty() )
|
|
{
|
|
m_bNull = true;
|
|
return;
|
|
}
|
|
while(!rIFStream.eof())
|
|
{
|
|
OString sLine(sTemp.data(),sTemp.length());
|
|
if (sLine.startsWith("#. "))
|
|
{
|
|
if( !m_sExtractCom.isEmpty() )
|
|
{
|
|
m_sExtractCom.append("\n");
|
|
}
|
|
m_sExtractCom.append(sLine.subView(3));
|
|
}
|
|
else if (sLine.startsWith("#: "))
|
|
{
|
|
m_sReferences.push_back(sLine.copy(3));
|
|
}
|
|
else if (sLine.startsWith("#, fuzzy"))
|
|
{
|
|
m_bFuzzy = true;
|
|
}
|
|
else if (sLine.startsWith("#, c-format"))
|
|
{
|
|
m_bCFormat = true;
|
|
}
|
|
else if (sLine.startsWith("msgctxt "))
|
|
{
|
|
m_sMsgCtxt = lcl_GenNormString(sLine.subView(8));
|
|
pLastMsg = &m_sMsgCtxt;
|
|
}
|
|
else if (sLine.startsWith("msgid "))
|
|
{
|
|
m_sMsgId = lcl_GenNormString(sLine.subView(6));
|
|
pLastMsg = &m_sMsgId;
|
|
}
|
|
else if (sLine.startsWith("msgid_plural "))
|
|
{
|
|
m_sMsgIdPlural = lcl_GenNormString(sLine.subView(13));
|
|
pLastMsg = &m_sMsgIdPlural;
|
|
}
|
|
else if (sLine.startsWith("msgstr "))
|
|
{
|
|
m_sMsgStr = lcl_GenNormString(sLine.subView(7));
|
|
pLastMsg = &m_sMsgStr;
|
|
}
|
|
else if (sLine.startsWith("msgstr["))
|
|
{
|
|
// assume there are no more than 10 plural forms...
|
|
// and that plural strings are never split to multi-line in po
|
|
m_sMsgStrPlural.push_back(sLine.subView(0,10) + lcl_GenNormString(sLine.subView(10)));
|
|
}
|
|
else if (sLine.startsWith("\"") && pLastMsg)
|
|
{
|
|
OString sReference;
|
|
if (!m_sReferences.empty())
|
|
{
|
|
sReference = m_sReferences.front();
|
|
}
|
|
if (pLastMsg != &m_sMsgCtxt || sLine != Concat2View("\"" + sReference + "\\n\""))
|
|
{
|
|
*pLastMsg += lcl_GenNormString(sLine);
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
getline(rIFStream,sTemp);
|
|
}
|
|
}
|
|
|
|
PoEntry::PoEntry()
|
|
: m_bIsInitialized( false )
|
|
{
|
|
}
|
|
|
|
PoEntry::PoEntry(
|
|
std::string_view rSourceFile, std::string_view rResType, std::string_view rGroupId,
|
|
std::string_view rLocalId, std::string_view rHelpText,
|
|
const OString& rText, const TYPE eType )
|
|
: m_bIsInitialized( false )
|
|
{
|
|
if( rSourceFile.empty() )
|
|
throw NOSOURCFILE;
|
|
else if ( rResType.empty() )
|
|
throw NORESTYPE;
|
|
else if ( rGroupId.empty() )
|
|
throw NOGROUPID;
|
|
else if ( rText.isEmpty() )
|
|
throw NOSTRING;
|
|
else if ( rHelpText.size() == 5 )
|
|
throw WRONGHELPTEXT;
|
|
|
|
m_pGenPo.reset( new GenPoEntry() );
|
|
size_t idx = rSourceFile.rfind('/');
|
|
if (idx == std::string_view::npos)
|
|
idx = 0;
|
|
OString sReference(rSourceFile.substr(idx+1));
|
|
m_pGenPo->setReference(sReference);
|
|
|
|
OString sMsgCtxt =
|
|
sReference + "\n" +
|
|
rGroupId + "\n" +
|
|
(rLocalId.empty() ? OString() : OString::Concat(rLocalId) + "\n") +
|
|
rResType;
|
|
switch(eType){
|
|
case TTEXT:
|
|
sMsgCtxt += ".text"; break;
|
|
case TQUICKHELPTEXT:
|
|
sMsgCtxt += ".quickhelptext"; break;
|
|
case TTITLE:
|
|
sMsgCtxt += ".title"; break;
|
|
// Default case is unneeded because the type of eType has only three element
|
|
}
|
|
m_pGenPo->setMsgCtxt(sMsgCtxt);
|
|
m_pGenPo->setMsgId(rText);
|
|
m_pGenPo->setExtractCom(Concat2View(
|
|
( !rHelpText.empty() ? OString::Concat(rHelpText) + "\n" : OString()) +
|
|
genKeyId( m_pGenPo->getReference().front() + rGroupId + rLocalId + rResType + rText ) ));
|
|
m_bIsInitialized = true;
|
|
}
|
|
|
|
PoEntry::~PoEntry()
|
|
{
|
|
}
|
|
|
|
PoEntry::PoEntry( const PoEntry& rPo )
|
|
: m_pGenPo( rPo.m_pGenPo ? new GenPoEntry( *(rPo.m_pGenPo) ) : nullptr )
|
|
, m_bIsInitialized( rPo.m_bIsInitialized )
|
|
{
|
|
}
|
|
|
|
PoEntry& PoEntry::operator=(const PoEntry& rPo)
|
|
{
|
|
if( this == &rPo )
|
|
{
|
|
return *this;
|
|
}
|
|
if( rPo.m_pGenPo )
|
|
{
|
|
if( m_pGenPo )
|
|
{
|
|
*m_pGenPo = *(rPo.m_pGenPo);
|
|
}
|
|
else
|
|
{
|
|
m_pGenPo.reset( new GenPoEntry( *(rPo.m_pGenPo) ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pGenPo.reset();
|
|
}
|
|
m_bIsInitialized = rPo.m_bIsInitialized;
|
|
return *this;
|
|
}
|
|
|
|
PoEntry& PoEntry::operator=(PoEntry&& rPo) noexcept
|
|
{
|
|
m_pGenPo = std::move(rPo.m_pGenPo);
|
|
m_bIsInitialized = std::move(rPo.m_bIsInitialized);
|
|
return *this;
|
|
}
|
|
|
|
OString const & PoEntry::getSourceFile() const
|
|
{
|
|
assert( m_bIsInitialized );
|
|
return m_pGenPo->getReference().front();
|
|
}
|
|
|
|
OString PoEntry::getGroupId() const
|
|
{
|
|
assert( m_bIsInitialized );
|
|
return m_pGenPo->getMsgCtxt().getToken(0,'\n');
|
|
}
|
|
|
|
OString PoEntry::getLocalId() const
|
|
{
|
|
assert( m_bIsInitialized );
|
|
const OString sMsgCtxt = m_pGenPo->getMsgCtxt();
|
|
if (sMsgCtxt.indexOf('\n')==sMsgCtxt.lastIndexOf('\n'))
|
|
return OString();
|
|
else
|
|
return sMsgCtxt.getToken(1,'\n');
|
|
}
|
|
|
|
OString PoEntry::getResourceType() const
|
|
{
|
|
assert( m_bIsInitialized );
|
|
const OString sMsgCtxt = m_pGenPo->getMsgCtxt();
|
|
if (sMsgCtxt.indexOf('\n')==sMsgCtxt.lastIndexOf('\n'))
|
|
return sMsgCtxt.getToken(1,'\n').getToken(0,'.');
|
|
else
|
|
return sMsgCtxt.getToken(2,'\n').getToken(0,'.');
|
|
}
|
|
|
|
PoEntry::TYPE PoEntry::getType() const
|
|
{
|
|
assert( m_bIsInitialized );
|
|
const OString sMsgCtxt = m_pGenPo->getMsgCtxt();
|
|
const OString sType = sMsgCtxt.copy( sMsgCtxt.lastIndexOf('.') + 1 );
|
|
assert(
|
|
(sType == "text" || sType == "quickhelptext" || sType == "title") );
|
|
if ( sType == "text" )
|
|
return TTEXT;
|
|
else if ( sType == "quickhelptext" )
|
|
return TQUICKHELPTEXT;
|
|
else
|
|
return TTITLE;
|
|
}
|
|
|
|
bool PoEntry::isFuzzy() const
|
|
{
|
|
assert( m_bIsInitialized );
|
|
return m_pGenPo->isFuzzy();
|
|
}
|
|
|
|
// Get message context
|
|
const OString& PoEntry::getMsgCtxt() const
|
|
{
|
|
assert( m_bIsInitialized );
|
|
return m_pGenPo->getMsgCtxt();
|
|
|
|
}
|
|
|
|
// Get translation string in merge format
|
|
OString const & PoEntry::getMsgId() const
|
|
{
|
|
assert( m_bIsInitialized );
|
|
return m_pGenPo->getMsgId();
|
|
}
|
|
|
|
// Get translated string in merge format
|
|
const OString& PoEntry::getMsgStr() const
|
|
{
|
|
assert( m_bIsInitialized );
|
|
return m_pGenPo->getMsgStr();
|
|
|
|
}
|
|
|
|
bool PoEntry::IsInSameComp(const PoEntry& rPo1,const PoEntry& rPo2)
|
|
{
|
|
assert( rPo1.m_bIsInitialized && rPo2.m_bIsInitialized );
|
|
return ( rPo1.getSourceFile() == rPo2.getSourceFile() &&
|
|
rPo1.getGroupId() == rPo2.getGroupId() &&
|
|
rPo1.getLocalId() == rPo2.getLocalId() &&
|
|
rPo1.getResourceType() == rPo2.getResourceType() );
|
|
}
|
|
|
|
OString PoEntry::genKeyId(const OString& rGenerator)
|
|
{
|
|
sal_uInt32 nCRC = rtl_crc32(0, rGenerator.getStr(), rGenerator.getLength());
|
|
// Use simple ASCII characters, exclude I, l, 1 and O, 0 to avoid confusing IDs
|
|
static const char sSymbols[] =
|
|
"ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789";
|
|
char sKeyId[6];
|
|
for( short nKeyInd = 0; nKeyInd < 5; ++nKeyInd )
|
|
{
|
|
sKeyId[nKeyInd] = sSymbols[(nCRC & 63) % strlen(sSymbols)];
|
|
nCRC >>= 6;
|
|
}
|
|
sKeyId[5] = '\0';
|
|
return sKeyId;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
// Get actual time in "YEAR-MO-DA HO:MI+ZONE" form
|
|
OString lcl_GetTime()
|
|
{
|
|
time_t aNow = time(nullptr);
|
|
struct tm* pNow = localtime(&aNow);
|
|
char pBuff[50];
|
|
strftime( pBuff, sizeof pBuff, "%Y-%m-%d %H:%M%z", pNow );
|
|
return pBuff;
|
|
}
|
|
}
|
|
|
|
// when updating existing files (pocheck), reuse provided po-header
|
|
PoHeader::PoHeader( std::string_view rExtSrc, const OString& rPoHeaderMsgStr )
|
|
: m_pGenPo( new GenPoEntry() )
|
|
, m_bIsInitialized( false )
|
|
{
|
|
m_pGenPo->setExtractCom(Concat2View(OString::Concat("extracted from ") + rExtSrc));
|
|
m_pGenPo->setMsgStr(rPoHeaderMsgStr);
|
|
m_bIsInitialized = true;
|
|
}
|
|
|
|
PoHeader::PoHeader( std::string_view rExtSrc )
|
|
: m_pGenPo( new GenPoEntry() )
|
|
, m_bIsInitialized( false )
|
|
{
|
|
m_pGenPo->setExtractCom(Concat2View(OString::Concat("extracted from ") + rExtSrc));
|
|
m_pGenPo->setMsgStr(
|
|
"Project-Id-Version: PACKAGE VERSION\n"
|
|
"Report-Msgid-Bugs-To: https://bugs.libreoffice.org/enter_bug.cgi?"
|
|
"product=LibreOffice&bug_status=UNCONFIRMED&component=UI\n"
|
|
"POT-Creation-Date: " + lcl_GetTime() +
|
|
"\nPO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
"MIME-Version: 1.0\n"
|
|
"Content-Type: text/plain; charset=UTF-8\n"
|
|
"Content-Transfer-Encoding: 8bit\n"
|
|
"X-Accelerator-Marker: ~\n"
|
|
"X-Generator: LibreOffice\n");
|
|
m_bIsInitialized = true;
|
|
}
|
|
|
|
PoHeader::~PoHeader()
|
|
{
|
|
}
|
|
|
|
PoOfstream::PoOfstream()
|
|
: m_bIsAfterHeader( false )
|
|
{
|
|
}
|
|
|
|
PoOfstream::PoOfstream(const OString& rFileName, OpenMode aMode )
|
|
: m_bIsAfterHeader( false )
|
|
{
|
|
open( rFileName, aMode );
|
|
}
|
|
|
|
PoOfstream::~PoOfstream()
|
|
{
|
|
if( isOpen() )
|
|
{
|
|
close();
|
|
}
|
|
}
|
|
|
|
void PoOfstream::open(const OString& rFileName, OpenMode aMode )
|
|
{
|
|
assert( !isOpen() );
|
|
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()
|
|
{
|
|
assert( isOpen() );
|
|
m_aOutPut.close();
|
|
}
|
|
|
|
void PoOfstream::writeHeader(const PoHeader& rPoHeader)
|
|
{
|
|
assert( isOpen() && !m_bIsAfterHeader && rPoHeader.m_bIsInitialized );
|
|
rPoHeader.m_pGenPo->writeToFile( m_aOutPut );
|
|
m_bIsAfterHeader = true;
|
|
}
|
|
|
|
void PoOfstream::writeEntry( const PoEntry& rPoEntry )
|
|
{
|
|
assert( isOpen() && m_bIsAfterHeader && rPoEntry.m_bIsInitialized );
|
|
rPoEntry.m_pGenPo->writeToFile( m_aOutPut );
|
|
}
|
|
|
|
namespace
|
|
{
|
|
|
|
// Check the validity of read entry
|
|
bool lcl_CheckInputEntry(const GenPoEntry& rEntry)
|
|
{
|
|
// stock button labels don't have a reference/sourcefile - they are not extracted from ui files
|
|
// (explicitly skipped by solenv/bin/uiex) but instead inserted by l10ntools/source/localize.cxx
|
|
// into all module templates (see d5d905b480c2a9b1db982f2867e87b5c230d1ab9)
|
|
return !rEntry.getMsgCtxt().isEmpty() &&
|
|
(rEntry.getMsgCtxt() == "stock" || !rEntry.getReference().empty()) &&
|
|
!rEntry.getMsgId().isEmpty();
|
|
}
|
|
|
|
}
|
|
|
|
PoIfstream::PoIfstream()
|
|
: m_bEof( false )
|
|
{
|
|
}
|
|
|
|
PoIfstream::PoIfstream(const OString& rFileName)
|
|
: m_bEof( false )
|
|
{
|
|
open( rFileName );
|
|
}
|
|
|
|
PoIfstream::~PoIfstream()
|
|
{
|
|
if( isOpen() )
|
|
{
|
|
close();
|
|
}
|
|
}
|
|
|
|
void PoIfstream::open( const OString& rFileName, OString& rPoHeader )
|
|
{
|
|
assert( !isOpen() );
|
|
m_aInPut.open( rFileName.getStr(), std::ios_base::in );
|
|
|
|
// capture header, updating timestamp and generator
|
|
std::string sTemp;
|
|
std::getline(m_aInPut,sTemp);
|
|
while( !sTemp.empty() && !m_aInPut.eof() )
|
|
{
|
|
std::getline(m_aInPut,sTemp);
|
|
OString sLine(sTemp.data(),sTemp.length());
|
|
if (sLine.startsWith("\"PO-Revision-Date"))
|
|
rPoHeader += "PO-Revision-Date: " + lcl_GetTime() + "\n";
|
|
else if (sLine.startsWith("\"X-Generator"))
|
|
rPoHeader += "X-Generator: LibreOffice\n";
|
|
else if (sLine.startsWith("\""))
|
|
rPoHeader += lcl_GenNormString(sLine);
|
|
}
|
|
m_bEof = false;
|
|
}
|
|
|
|
void PoIfstream::open( const OString& rFileName )
|
|
{
|
|
assert( !isOpen() );
|
|
m_aInPut.open( rFileName.getStr(), std::ios_base::in );
|
|
|
|
// Skip header
|
|
std::string sTemp;
|
|
std::getline(m_aInPut,sTemp);
|
|
while( !sTemp.empty() && !m_aInPut.eof() )
|
|
{
|
|
std::getline(m_aInPut,sTemp);
|
|
}
|
|
m_bEof = false;
|
|
}
|
|
|
|
void PoIfstream::close()
|
|
{
|
|
assert( isOpen() );
|
|
m_aInPut.close();
|
|
}
|
|
|
|
void PoIfstream::readEntry( PoEntry& rPoEntry )
|
|
{
|
|
assert( isOpen() && !eof() );
|
|
GenPoEntry aGenPo;
|
|
aGenPo.readFromFile( m_aInPut );
|
|
if( aGenPo.isNull() )
|
|
{
|
|
m_bEof = true;
|
|
rPoEntry = PoEntry();
|
|
}
|
|
else
|
|
{
|
|
if( lcl_CheckInputEntry(aGenPo) )
|
|
{
|
|
if( rPoEntry.m_pGenPo )
|
|
{
|
|
*(rPoEntry.m_pGenPo) = std::move(aGenPo);
|
|
}
|
|
else
|
|
{
|
|
rPoEntry.m_pGenPo.reset( new GenPoEntry(std::move(aGenPo)) );
|
|
}
|
|
rPoEntry.m_bIsInitialized = true;
|
|
}
|
|
else
|
|
{
|
|
SAL_WARN("l10ntools", "Parse problem with entry: " << aGenPo.getMsgStr());
|
|
throw PoIfstream::Exception();
|
|
}
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|