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