1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
33 OString
lcl_NormalizeFilename(const OString
& rFilename
)
35 return rFilename
.copy(
37 rFilename
.lastIndexOf( '\\' ),
38 rFilename
.lastIndexOf( '/' ))+1);
41 bool lcl_ReadPoChecked(
42 PoEntry
& o_rPoEntry
, PoIfstream
& rPoFile
,
43 const OString
& rFileName
)
47 rPoFile
.readEntry( o_rPoEntry
);
49 catch (const PoIfstream::Exception
&)
51 SAL_WARN("l10ntools", rFileName
<< " contains invalid entry");
61 ResData::ResData( const OString
&rGId
)
65 sGId
= sGId
.replaceAll("\r", OString());
68 ResData::ResData( const OString
&rGId
, const OString
&rFilename
)
71 sFilename( rFilename
)
73 sGId
= sGId
.replaceAll("\r", OString());
79 bool MergeEntrys::GetText( OString
&rReturn
,
80 const OString
&nLangIndex
, bool bDel
)
83 rReturn
= sText
[ nLangIndex
];
85 sText
[ nLangIndex
] = "";
86 bReturn
= bTextFirst
[ nLangIndex
];
87 bTextFirst
[ nLangIndex
] = false;
93 OString
GetDoubleBars()
95 //DOUBLE VERTICAL LINE instead of || because the translations make their
96 //way into action_names under gtk3 where || is illegal
97 return OUStringToOString(OUString(u
'\x2016'), RTL_TEXTENCODING_UTF8
);
101 OString
MergeEntrys::GetQTZText(const ResData
& rResData
, const OString
& rOrigText
)
103 const OString sFilename
= rResData
.sFilename
.copy(rResData
.sFilename
.lastIndexOf('/')+1);
105 PoEntry::genKeyId(sFilename
+ rResData
.sGId
+ rResData
.sId
+ rResData
.sResTyp
+ rOrigText
);
106 return sKey
+ GetDoubleBars() + rOrigText
;
111 MergeDataFile::MergeDataFile(
112 const OString
&rFileName
, const OString
&rFile
,
113 bool bCaseSensitive
, bool bWithQtz
)
115 OString
sEnableReleaseBuild(getenv("ENABLE_RELEASE_BUILD"));
117 std::ifstream
aInputStream( rFileName
.getStr() );
118 if ( !aInputStream
.is_open() )
120 SAL_WARN("l10ntools", "Can't open po path container file for " << rFileName
);
124 aInputStream
>> sPoFile
;
125 bool bFirstLang
= true;
126 while( !aInputStream
.eof() )
128 bool bSkipCurrentPOFile
= false;
129 const OString
sFileName( lcl_NormalizeFilename(rFile
) );
130 const bool bReadAll
= sFileName
.isEmpty();
131 // coverity[tainted_data] - this is a build time tool
132 const OString
sPoFileName(sPoFile
.data(), static_cast<sal_Int32
>(sPoFile
.length()));
134 aPoInput
.open( sPoFileName
);
135 if ( !aPoInput
.isOpen() )
137 SAL_WARN("l10ntools", "Can't open file: " << sPoFileName
);
142 //Get language id from path
144 const OString
sTransSource("translations/source/");
145 const sal_Int32 nStart
=
146 sPoFileName
.indexOf(sTransSource
)+sTransSource
.getLength();
147 const sal_Int32 nCount
=
148 sPoFileName
.indexOf('/',nStart
) - nStart
;
149 sLang
= sPoFileName
.copy(nStart
,nCount
);
151 aLanguageSet
.insert( sLang
);
155 if( !lcl_ReadPoChecked(aNextPo
, aPoInput
, sPoFileName
) )
157 bSkipCurrentPOFile
= true;
160 } while( !aPoInput
.eof() && aNextPo
.getSourceFile() != sFileName
&& !bReadAll
);
161 while( !aPoInput
.eof() && (aNextPo
.getSourceFile() == sFileName
|| bReadAll
) && !bSkipCurrentPOFile
)
163 PoEntry
aActPo( aNextPo
);
165 bool bInSameComp
= false;
176 OString sTemp
= aActPo
.getMsgStr();
177 if( aActPo
.isFuzzy() || sTemp
.isEmpty() )
178 sTemp
= aActPo
.getMsgId();
179 switch( aActPo
.getType() )
183 sExText
= aActPo
.getMsgId();
185 case PoEntry::TQUICKHELPTEXT
:
187 sExQHText
= aActPo
.getMsgId();
189 case PoEntry::TTITLE
:
191 sExTitle
= aActPo
.getMsgId();
194 if( !lcl_ReadPoChecked(aNextPo
, aPoInput
, sPoFileName
) )
196 bSkipCurrentPOFile
= true;
201 bInSameComp
= PoEntry::IsInSameComp(aActPo
, aNextPo
);
202 } while( bInSameComp
);
205 aActPo
.getResourceType(), aActPo
.getGroupId(),
206 aActPo
.getLocalId(), sLang
, sText
,
207 sQHText
, sTitle
, aActPo
.getSourceFile(),
208 bFirstLang
, bCaseSensitive
);
210 if( bFirstLang
&& bWithQtz
&&
211 sEnableReleaseBuild
!= "TRUE" )
213 aLanguageSet
.insert("qtz");
215 aActPo
.getResourceType(), aActPo
.getGroupId(),
216 aActPo
.getLocalId(), "qtz",
218 sExTitle
, aActPo
.getSourceFile(),
219 false, bCaseSensitive
);
223 aInputStream
>> sPoFile
;
226 aInputStream
.close();
229 MergeDataFile::~MergeDataFile()
233 std::vector
<OString
> MergeDataFile::GetLanguages() const
235 return std::vector
<OString
>(aLanguageSet
.begin(),aLanguageSet
.end());
238 MergeEntrys
*MergeDataFile::GetMergeData( ResData
*pResData
, bool bCaseSensitive
)
240 OString sOldG
= pResData
->sGId
;
241 OString sOldL
= pResData
->sId
;
242 OString sGID
= pResData
->sGId
;
245 sGID
= pResData
->sId
;
247 sLID
= pResData
->sId
;
248 pResData
->sGId
= sGID
;
249 pResData
->sId
= sLID
;
251 OString sKey
= CreateKey( pResData
->sResTyp
, pResData
->sGId
, pResData
->sId
, pResData
->sFilename
, bCaseSensitive
);
253 auto mit
= aMap
.find( sKey
);
254 if(mit
!= aMap
.end())
256 pResData
->sGId
= sOldG
;
257 pResData
->sId
= sOldL
;
258 return mit
->second
.get();
260 pResData
->sGId
= sOldG
;
261 pResData
->sId
= sOldL
;
265 MergeEntrys
*MergeDataFile::GetMergeEntrys( ResData
*pResData
)
267 // search for requested MergeEntrys
268 return GetMergeData( pResData
);
271 MergeEntrys
*MergeDataFile::GetMergeEntrysCaseSensitive( ResData
*pResData
)
273 // search for requested MergeEntrys
274 return GetMergeData( pResData
, true );
277 void MergeDataFile::InsertEntry(
278 const OString
&rTYP
, const OString
&rGID
,
279 const OString
&rLID
, const OString
&nLANG
,
280 const OString
&rTEXT
, const OString
&rQHTEXT
,
281 const OString
&rTITLE
, const OString
&rInFilename
,
282 bool bFirstLang
, bool bCaseSensitive
)
284 MergeEntrys
*pMergeEntrys
= nullptr;
286 // search for MergeData
287 OString sKey
= CreateKey(rTYP
, rGID
, rLID
, rInFilename
, bCaseSensitive
);
291 auto mit
= aMap
.find( sKey
);
292 if(mit
!= aMap
.end())
293 pMergeEntrys
= mit
->second
.get();
299 pMergeEntrys
= new MergeEntrys
;
300 aMap
.emplace( sKey
, std::unique_ptr
<MergeEntrys
>(pMergeEntrys
) );
304 // insert the cur string
307 const OString sTemp
= rInFilename
+ rGID
+ rLID
+ rTYP
;
308 pMergeEntrys
->InsertEntry(
310 rTEXT
.isEmpty()? rTEXT
: PoEntry::genKeyId(sTemp
+ rTEXT
) + GetDoubleBars() + rTEXT
,
311 rQHTEXT
.isEmpty()? rQHTEXT
: PoEntry::genKeyId(sTemp
+ rQHTEXT
) + GetDoubleBars() + rQHTEXT
,
312 rTITLE
.isEmpty()? rTITLE
: PoEntry::genKeyId(sTemp
+ rTITLE
) + GetDoubleBars() + rTITLE
);
316 pMergeEntrys
->InsertEntry( nLANG
, rTEXT
, rQHTEXT
, rTITLE
);
320 OString
MergeDataFile::CreateKey(const OString
& rTYP
, const OString
& rGID
,
321 const OString
& rLID
, const OString
& rFilename
, bool bCaseSensitive
)
323 static const char sStroke
[] = "-";
324 OString sKey
= rTYP
+ sStroke
+ rGID
+ sStroke
+ rLID
+ sStroke
+
325 lcl_NormalizeFilename(rFilename
);
327 return sKey
; // officecfg case sensitive identifier
328 return sKey
.toAsciiUpperCase();
331 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */