Fix typos
[LibreOffice.git] / l10ntools / source / merge.cxx
blob004cffacc494f45a2bd7d4f4b1992d048e212ba6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
23 #include <algorithm>
24 #include <fstream>
25 #include <string>
26 #include <vector>
28 #include <export.hxx>
29 #include <po.hxx>
31 namespace
33 OString lcl_NormalizeFilename(const OString& rFilename)
35 return rFilename.copy(
36 std::max(
37 rFilename.lastIndexOf( '\\' ),
38 rFilename.lastIndexOf( '/' ))+1);
41 bool lcl_ReadPoChecked(
42 PoEntry& o_rPoEntry, PoIfstream& rPoFile,
43 const OString& rFileName)
45 try
47 rPoFile.readEntry( o_rPoEntry );
49 catch (const PoIfstream::Exception&)
51 SAL_WARN("l10ntools", rFileName << " contains invalid entry");
52 return false;
54 return true;
61 ResData::ResData( const OString &rGId )
63 sGId( rGId )
65 sGId = sGId.replaceAll("\r", OString());
68 ResData::ResData( const OString &rGId, const OString &rFilename)
70 sGId( rGId ),
71 sFilename( rFilename )
73 sGId = sGId.replaceAll("\r", OString());
79 bool MergeEntrys::GetText( OString &rReturn,
80 const OString &nLangIndex, bool bDel )
82 bool bReturn = true;
83 rReturn = sText[ nLangIndex ];
84 if ( bDel )
85 sText[ nLangIndex ] = "";
86 bReturn = bTextFirst[ nLangIndex ];
87 bTextFirst[ nLangIndex ] = false;
88 return bReturn;
91 namespace
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 u8"\u2016";
101 OString MergeEntrys::GetQTZText(const ResData& rResData, std::string_view rOrigText)
103 const OString sFilename = rResData.sFilename.copy(rResData.sFilename.lastIndexOf('/')+1);
104 const OString sKey =
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 auto const env = getenv("ENABLE_RELEASE_BUILD");
116 OString sEnableReleaseBuild(env == nullptr ? "" : env);
118 std::ifstream aInputStream( rFileName.getStr() );
119 if ( !aInputStream.is_open() )
121 SAL_WARN("l10ntools", "Can't open po path container file for " << rFileName);
122 return;
124 std::string sPoFile;
125 aInputStream >> sPoFile;
126 bool bFirstLang = true;
127 while( !aInputStream.eof() )
129 bool bSkipCurrentPOFile = false;
130 const OString sFileName( lcl_NormalizeFilename(rFile) );
131 const bool bReadAll = sFileName.isEmpty();
132 // coverity[tainted_data] - this is a build time tool
133 const OString sPoFileName(sPoFile.data(), static_cast<sal_Int32>(sPoFile.length()));
134 PoIfstream aPoInput;
135 aPoInput.open( sPoFileName );
136 if ( !aPoInput.isOpen() )
138 SAL_WARN("l10ntools", "Can't open file: " << sPoFileName);
139 return;
142 OString sLang;
143 //Get language id from path
145 const OString sTransSource("translations/source/");
146 const sal_Int32 nStart =
147 sPoFileName.indexOf(sTransSource)+sTransSource.getLength();
148 const sal_Int32 nCount =
149 sPoFileName.indexOf('/',nStart) - nStart;
150 sLang = sPoFileName.copy(nStart,nCount);
152 aLanguageSet.insert( sLang );
153 PoEntry aNextPo;
156 if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
158 bSkipCurrentPOFile = true;
159 break;
161 } while( !aPoInput.eof() && aNextPo.getSourceFile() != sFileName && !bReadAll );
162 while( !aPoInput.eof() && (aNextPo.getSourceFile() == sFileName || bReadAll ) && !bSkipCurrentPOFile )
164 PoEntry aActPo( aNextPo );
166 bool bInSameComp = false;
167 OString sText;
168 OString sQHText;
169 OString sTitle;
170 OString sExText;
171 OString sExQHText;
172 OString sExTitle;
175 if( bInSameComp )
176 aActPo = aNextPo;
177 OString sTemp = aActPo.getMsgStr();
178 if( aActPo.isFuzzy() || sTemp.isEmpty() )
179 sTemp = aActPo.getMsgId();
180 switch( aActPo.getType() )
182 case PoEntry::TTEXT:
183 sText = sTemp;
184 sExText = aActPo.getMsgId();
185 break;
186 case PoEntry::TQUICKHELPTEXT:
187 sQHText = sTemp;
188 sExQHText = aActPo.getMsgId();
189 break;
190 case PoEntry::TTITLE:
191 sTitle = sTemp;
192 sExTitle = aActPo.getMsgId();
193 break;
195 if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
197 bSkipCurrentPOFile = true;
198 break;
200 if (aPoInput.eof())
201 break;
202 bInSameComp = PoEntry::IsInSameComp(aActPo, aNextPo);
203 } while( bInSameComp );
205 InsertEntry(
206 aActPo.getResourceType(), aActPo.getGroupId(),
207 aActPo.getLocalId(), sLang, sText,
208 sQHText, sTitle, aActPo.getSourceFile(),
209 bFirstLang, bCaseSensitive );
211 if( bFirstLang && bWithQtz &&
212 sEnableReleaseBuild != "TRUE" )
214 aLanguageSet.insert("qtz");
215 InsertEntry(
216 aActPo.getResourceType(), aActPo.getGroupId(),
217 aActPo.getLocalId(), "qtz",
218 sExText, sExQHText,
219 sExTitle, aActPo.getSourceFile(),
220 false, bCaseSensitive );
223 aPoInput.close();
224 aInputStream >> sPoFile;
225 bFirstLang = false;
227 aInputStream.close();
230 MergeDataFile::~MergeDataFile()
234 std::vector<OString> MergeDataFile::GetLanguages() const
236 return std::vector<OString>(aLanguageSet.begin(),aLanguageSet.end());
239 MergeEntrys *MergeDataFile::GetMergeData( ResData *pResData , bool bCaseSensitive )
241 OString sOldG = pResData->sGId;
242 OString sOldL = pResData->sId;
243 OString sGID = pResData->sGId;
244 OString sLID;
245 if (sGID.isEmpty())
246 sGID = pResData->sId;
247 else
248 sLID = pResData->sId;
249 pResData->sGId = sGID;
250 pResData->sId = sLID;
252 OString sKey = CreateKey( pResData->sResTyp , pResData->sGId , pResData->sId , pResData->sFilename , bCaseSensitive );
254 auto mit = aMap.find( sKey );
255 if(mit != aMap.end())
257 pResData->sGId = sOldG;
258 pResData->sId = sOldL;
259 return mit->second.get();
261 pResData->sGId = sOldG;
262 pResData->sId = sOldL;
263 return nullptr;
266 MergeEntrys *MergeDataFile::GetMergeEntrys( ResData *pResData )
268 // search for requested MergeEntrys
269 return GetMergeData( pResData );
272 MergeEntrys *MergeDataFile::GetMergeEntrysCaseSensitive( ResData *pResData )
274 // search for requested MergeEntrys
275 return GetMergeData( pResData , true );
278 void MergeDataFile::InsertEntry(
279 std::string_view rTYP, std::string_view rGID,
280 std::string_view rLID, const OString &nLANG,
281 const OString &rTEXT, const OString &rQHTEXT,
282 const OString &rTITLE, const OString &rInFilename,
283 bool bFirstLang, bool bCaseSensitive )
285 MergeEntrys *pMergeEntrys = nullptr;
287 // search for MergeData
288 OString sKey = CreateKey(rTYP , rGID , rLID , rInFilename , bCaseSensitive);
290 if( !bFirstLang )
292 auto mit = aMap.find( sKey );
293 if(mit != aMap.end())
294 pMergeEntrys = mit->second.get();
298 if( !pMergeEntrys )
300 pMergeEntrys = new MergeEntrys;
301 aMap.emplace( sKey, std::unique_ptr<MergeEntrys>(pMergeEntrys) );
305 // insert the cur string
306 if( nLANG =="qtz" )
308 const OString sTemp = rInFilename + rGID + rLID + rTYP;
309 pMergeEntrys->InsertEntry(
310 nLANG,
311 rTEXT.isEmpty()? rTEXT : PoEntry::genKeyId(sTemp + rTEXT) + GetDoubleBars() + rTEXT,
312 rQHTEXT.isEmpty()? rQHTEXT : PoEntry::genKeyId(sTemp + rQHTEXT) + GetDoubleBars() + rQHTEXT,
313 rTITLE.isEmpty()? rTITLE : PoEntry::genKeyId(sTemp + rTITLE) + GetDoubleBars() + rTITLE );
315 else
317 pMergeEntrys->InsertEntry( nLANG , rTEXT, rQHTEXT, rTITLE );
321 OString MergeDataFile::CreateKey(std::string_view rTYP, std::string_view rGID,
322 std::string_view rLID, const OString& rFilename, bool bCaseSensitive)
324 static const char sStroke[] = "-";
325 OString sKey = OString::Concat(rTYP) + sStroke + rGID + sStroke + rLID + sStroke +
326 lcl_NormalizeFilename(rFilename);
327 if(bCaseSensitive)
328 return sKey; // officecfg case sensitive identifier
329 return sKey.toAsciiUpperCase();
332 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */