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