Salome HOME
Improve coverage for Model and Config packages
[modules/shaper.git] / src / Config / Config_Translator.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "Config_Translator.h"
22 #include "Config_XMLReader.h"
23 #include "Config_Common.h"
24
25 #include <fstream>
26 #include <ostream>
27
28 #ifdef WIN32
29 #pragma warning(disable : 4996) // for sprintf
30 #endif
31
32 // LCOV_EXCL_START
33 /**
34  * \class Config_TSReader
35  * \ingroup Config
36  * \brief Class for reading translations from TS files (an XML format).
37  */
38 class Config_TSReader : public Config_XMLReader
39 {
40 public:
41   /// Constructor
42   /// \param theTSFile name of TS file
43   Config_TSReader(const std::string& theTSFile) : Config_XMLReader(theTSFile) {}
44
45   /// Returns content of TS file
46   const Config_Translator::Translator& translator() const { return myTranslator; }
47
48   /// Returns codecs defined in TS files
49   const Config_Translator::Dictionary& codecs() const { return myCodecs; }
50
51 protected:
52   /// Overloaded method. Defines how to process each node
53   virtual void processNode(xmlNodePtr theNode);
54 private:
55   Config_Translator::Translator myTranslator;
56   Config_Translator::Dictionary myCodecs;
57 };
58
59 void Config_TSReader::processNode(xmlNodePtr theNode)
60 {
61   static std::string aName;
62   static std::string aSource;
63   std::string aTranslat;
64
65   if (isNode(theNode, "context", NULL)) {
66     aName = "";
67   } else if (isNode(theNode, "name", NULL)) {
68     aName = getContent(theNode);
69     myCodecs[aName] = encoding();
70   } else if (isNode(theNode, "message", NULL)) {
71     aSource = "";
72   } else if (isNode(theNode, "source", NULL)) {
73     aSource = getContent(theNode);
74   } else if (isNode(theNode, "translation", NULL)) {
75     aTranslat = getContent(theNode);
76     if ((aName.size() > 0) && (aSource.size() > 0))
77       myTranslator[aName][aSource] = aTranslat;
78   }
79 }
80
81 //******************************************************************************
82 //******************************************************************************
83 //******************************************************************************
84 Config_Translator::Translator Config_Translator::myTranslator;
85 Config_Translator::Dictionary Config_Translator::myCodecs;
86
87 #ifdef _DEBUG
88 #ifdef MISSED_TRANSLATION
89 Config_Translator::Translator Config_Translator::myMissed;
90 #endif
91 #endif
92
93 bool Config_Translator::load(const std::string& theFileName)
94 {
95   Config_TSReader aReader(theFileName);
96   aReader.readAll();
97
98   const Translator& aTranslator = aReader.translator();
99   Translator::const_iterator aIt;
100   std::string aContext;
101   Dictionary aDictionary;
102   for (aIt = aTranslator.cbegin(); aIt != aTranslator.cend(); aIt++) {
103     aContext = (*aIt).first;
104     aDictionary = (*aIt).second;
105     if (myTranslator.count(aContext) == 0) {
106       myTranslator[aContext] = aDictionary;
107     } else {
108       Dictionary::const_iterator aDictIt;
109       for (aDictIt = aDictionary.cbegin(); aDictIt != aDictionary.cend(); aDictIt++) {
110         myTranslator[aContext][(*aDictIt).first] = (*aDictIt).second;
111       }
112     }
113   }
114
115   const Dictionary aCodecs = aReader.codecs();
116   Dictionary::const_iterator aDictIt;
117   for (aDictIt = aCodecs.cbegin(); aDictIt != aCodecs.cend(); aDictIt++) {
118     myCodecs[aDictIt->first] = aDictIt->second;
119   }
120   return true;
121 }
122 // LCOV_EXCL_STOP
123
124 std::string Config_Translator::translate(const Events_InfoMessage& theInfo)
125 {
126   std::string aContext = theInfo.context();
127   std::string aMessage = theInfo.messageString();
128   std::list<std::string> aParameters = theInfo.parameters();
129   return translate(aContext, aMessage, aParameters);
130 }
131
132 std::string insertParameters(const std::string& theString, const std::list<std::string>& theParams)
133 {
134   std::string aResult = theString;
135   std::list<std::string>::const_iterator aIt;
136   int i;
137   char aBuf[20];
138   std::string aParam;
139   for (i=1, aIt = theParams.cbegin(); aIt != theParams.cend(); aIt++, i++) {
140     aParam = (*aIt);
141     sprintf(aBuf, "%d", i);
142     std::string aCode = std::string("%") + std::string(aBuf);
143     size_t aPos = aResult.find(aCode);
144     if (aPos != std::string::npos) {
145       std::string aFirst = aResult.substr(0, aPos);
146       std::string aLast = aResult.substr(aPos + aCode.length(), std::string::npos);
147       aResult = aFirst + aParam + aLast;
148     }
149   }
150   return aResult;
151 }
152
153 std::string Config_Translator::translate(const std::string& theContext,
154                                          const std::string& theMessage,
155                                          const std::list<std::string>& theParams)
156 {
157   if (myTranslator.count(theContext) > 0) {
158     if (myTranslator[theContext].count(theMessage) > 0) {
159       std::string aTranslation = myTranslator[theContext][theMessage];
160       if (theParams.size() > 0) {
161         aTranslation = insertParameters(aTranslation, theParams);
162       }
163       if (aTranslation.size() > 0)
164         return aTranslation;
165     }
166   }
167   std::string aMsg = theMessage;
168   if (theParams.size() > 0) {
169     aMsg = insertParameters(aMsg, theParams);
170   }
171 #ifdef _DEBUG
172 #ifdef MISSED_TRANSLATION
173   myMissed[theContext][theMessage] = "";
174 #endif
175 #endif
176   return aMsg;
177 }
178
179 // LCOV_EXCL_START
180 std::string Config_Translator::codec(const std::string& theContext)
181 {
182   return (myCodecs.count(theContext) > 0)? myCodecs[theContext] : "UTF-8";
183 }
184
185 std::string Config_Translator::codec(const Events_InfoMessage& theInfo)
186 {
187   return codec(theInfo.context());
188 }
189 // LCOV_EXCL_STOP
190
191 #ifdef _DEBUG
192 #ifdef MISSED_TRANSLATION
193 void Config_Translator::saveMissedTranslations()
194 {
195   if (myMissed.size() == 0)
196     return;
197
198   char* aPath = getenv("ROOT_DIR");
199 #ifdef WIN32
200   std::string aFile = aPath + std::string("\\MissedTranslation.ts");
201 #else
202   std::string aFile = aPath + std::string("/MissedTranslation.ts");
203 #endif
204   std::ofstream oFStream;
205
206   // Delete old file
207   remove(aFile.c_str());
208
209   oFStream.open(aFile, std::ofstream::out | std::ofstream::app);
210   if (oFStream.is_open()) {
211     Translator::const_iterator aContIt;
212     Dictionary::const_iterator aDictIt;
213     std::string aContext;
214     std::string aSrc;
215     Dictionary aDict;
216
217     oFStream << "<TS version=\"2.0\">" << std::endl;
218     for(aContIt = myMissed.cbegin(); aContIt != myMissed.cend(); aContIt++) {
219       oFStream << "<context>" << std::endl;
220
221       aContext = aContIt->first;
222       oFStream << "  <name>" << aContext << "</name>" << std::endl;
223
224       aDict = aContIt->second;
225       for(aDictIt = aDict.cbegin(); aDictIt != aDict.cend(); aDictIt++) {
226         oFStream << "  <message>" << std::endl;
227         aSrc = aDictIt->first;
228
229         oFStream << "    <source>" << aSrc << "</source>" << std::endl;
230         oFStream << "    <translation>" << "</translation>" << std::endl;
231
232         oFStream << "  </message>" << std::endl;
233       }
234       oFStream << "</context>" << std::endl;
235     }
236
237     oFStream << "</TS>" << std::endl;
238     oFStream.close();
239   }
240 }
241 #endif
242 #endif