Salome HOME
Add copyright header according to request of CEA from 06.06.2017
[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 email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
18 //
19
20 #include "Config_Translator.h"
21 #include "Config_XMLReader.h"
22 #include "Config_Common.h"
23
24 #include <fstream>
25 #include <ostream>
26
27 #ifdef WIN32
28 #pragma warning(disable : 4996) // for sprintf
29 #endif
30
31 /**
32  * \class Config_TSReader
33  * \ingroup Config
34  * \brief Class for reading translations from TS files (an XML format).
35  */
36 class Config_TSReader : public Config_XMLReader
37 {
38 public:
39   /// Constructor
40   /// \param theTSFile name of TS file
41   Config_TSReader(const std::string& theTSFile) : Config_XMLReader(theTSFile) {}
42
43   /// Returns content of TS file
44   const Config_Translator::Translator& translator() const { return myTranslator; }
45
46   /// Returns codecs defined in TS files
47   const Config_Translator::Dictionary& codecs() const { return myCodecs; }
48
49 protected:
50   /// Overloaded method. Defines how to process each node
51   virtual void processNode(xmlNodePtr theNode);
52 private:
53   Config_Translator::Translator myTranslator;
54   Config_Translator::Dictionary myCodecs;
55 };
56
57 void Config_TSReader::processNode(xmlNodePtr theNode)
58 {
59   static std::string aName;
60   static std::string aSource;
61   std::string aTranslat;
62
63   if (isNode(theNode, "context", NULL)) {
64     aName = "";
65   } else if (isNode(theNode, "name", NULL)) {
66     aName = getContent(theNode);
67     myCodecs[aName] = encoding();
68   } else if (isNode(theNode, "message", NULL)) {
69     aSource = "";
70   } else if (isNode(theNode, "source", NULL)) {
71     aSource = getContent(theNode);
72   } else if (isNode(theNode, "translation", NULL)) {
73     aTranslat = getContent(theNode);
74     if ((aName.size() > 0) && (aSource.size() > 0))
75       myTranslator[aName][aSource] = aTranslat;
76   }
77 }
78
79 //******************************************************************************
80 //******************************************************************************
81 //******************************************************************************
82 Config_Translator::Translator Config_Translator::myTranslator;
83 Config_Translator::Dictionary Config_Translator::myCodecs;
84
85 #ifdef _DEBUG
86 #ifdef MISSED_TRANSLATION
87 Config_Translator::Translator Config_Translator::myMissed;
88 #endif
89 #endif
90
91 bool Config_Translator::load(const std::string& theFileName)
92 {
93   Config_TSReader aReader(theFileName);
94   aReader.readAll();
95
96   const Translator& aTranslator = aReader.translator();
97   Translator::const_iterator aIt;
98   std::string aContext;
99   Dictionary aDictionary;
100   for (aIt = aTranslator.cbegin(); aIt != aTranslator.cend(); aIt++) {
101     aContext = (*aIt).first;
102     aDictionary = (*aIt).second;
103     if (myTranslator.count(aContext) == 0) {
104       myTranslator[aContext] = aDictionary;
105     } else {
106       Dictionary::const_iterator aDictIt;
107       for (aDictIt = aDictionary.cbegin(); aDictIt != aDictionary.cend(); aDictIt++) {
108         myTranslator[aContext][(*aDictIt).first] = (*aDictIt).second;
109       }
110     }
111   }
112
113   const Dictionary aCodecs = aReader.codecs();
114   Dictionary::const_iterator aDictIt;
115   for (aDictIt = aCodecs.cbegin(); aDictIt != aCodecs.cend(); aDictIt++) {
116     myCodecs[aDictIt->first] = aDictIt->second;
117   }
118   return true;
119 }
120
121 std::string Config_Translator::translate(const Events_InfoMessage& theInfo)
122 {
123   std::string aContext = theInfo.context();
124   std::string aMessage = theInfo.messageString();
125   std::list<std::string> aParameters = theInfo.parameters();
126   return translate(aContext, aMessage, aParameters);
127 }
128
129 std::string insertParameters(const std::string& theString, const std::list<std::string>& theParams)
130 {
131   std::string aResult = theString;
132   std::list<std::string>::const_iterator aIt;
133   int i;
134   char aBuf[20];
135   std::string aParam;
136   for (i=1, aIt = theParams.cbegin(); aIt != theParams.cend(); aIt++, i++) {
137     aParam = (*aIt);
138     sprintf(aBuf, "%d", i);
139     std::string aCode = std::string("%") + std::string(aBuf);
140     size_t aPos = aResult.find(aCode);
141     if (aPos != std::string::npos) {
142       std::string aFirst = aResult.substr(0, aPos);
143       std::string aLast = aResult.substr(aPos + aCode.length(), std::string::npos);
144       aResult = aFirst + aParam + aLast;
145     }
146   }
147   return aResult;
148 }
149
150 std::string Config_Translator::translate(const std::string& theContext,
151                                          const std::string& theMessage,
152                                          const std::list<std::string>& theParams)
153 {
154   if (myTranslator.count(theContext) > 0) {
155     if (myTranslator[theContext].count(theMessage) > 0) {
156       std::string aTranslation = myTranslator[theContext][theMessage];
157       if (theParams.size() > 0) {
158         aTranslation = insertParameters(aTranslation, theParams);
159       }
160       if (aTranslation.size() > 0)
161         return aTranslation;
162     }
163   }
164   std::string aMsg = theMessage;
165   if (theParams.size() > 0) {
166     aMsg = insertParameters(aMsg, theParams);
167   }
168 #ifdef _DEBUG
169 #ifdef MISSED_TRANSLATION
170   myMissed[theContext][theMessage] = "";
171 #endif
172 #endif
173   return aMsg;
174 }
175
176
177 std::string Config_Translator::codec(const std::string& theContext)
178 {
179   return (myCodecs.count(theContext) > 0)? myCodecs[theContext] : "UTF-8";
180 }
181
182 std::string Config_Translator::codec(const Events_InfoMessage& theInfo)
183 {
184   return codec(theInfo.context());
185 }
186
187 #ifdef _DEBUG
188 #ifdef MISSED_TRANSLATION
189 void Config_Translator::saveMissedTranslations()
190 {
191   if (myMissed.size() == 0)
192     return;
193
194   char* aPath = getenv("ROOT_DIR");
195 #ifdef WIN32
196   std::string aFile = aPath + std::string("\\MissedTranslation.ts");
197 #else
198   std::string aFile = aPath + std::string("/MissedTranslation.ts");
199 #endif
200   std::ofstream oFStream;
201
202   // Delete old file
203   int aa = remove(aFile.c_str());
204
205   oFStream.open(aFile, std::ofstream::out | std::ofstream::app);
206   if (oFStream.is_open()) {
207     Translator::const_iterator aContIt;
208     Dictionary::const_iterator aDictIt;
209     std::string aContext;
210     std::string aSrc;
211     Dictionary aDict;
212
213     oFStream << "<TS version=\"2.0\">" << std::endl;
214     for(aContIt = myMissed.cbegin(); aContIt != myMissed.cend(); aContIt++) {
215       oFStream << "<context>" << std::endl;
216
217       aContext = aContIt->first;
218       oFStream << "  <name>" << aContext << "</name>" << std::endl;
219
220       aDict = aContIt->second;
221       for(aDictIt = aDict.cbegin(); aDictIt != aDict.cend(); aDictIt++) {
222         oFStream << "  <message>" << std::endl;
223         aSrc = aDictIt->first;
224
225         oFStream << "    <source>" << aSrc << "</source>" << std::endl;
226         oFStream << "    <translation>" << "</translation>" << std::endl;
227
228         oFStream << "  </message>" << std::endl;
229       }
230       oFStream << "</context>" << std::endl;
231     }
232
233     oFStream << "</TS>" << std::endl;
234     oFStream.close();
235   }
236 }
237 #endif
238 #endif