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