]> SALOME platform Git repositories - tools/eficas.git/blob - Extensions/translation.py
Salome HOME
pb d accent. on les enleve en français
[tools/eficas.git] / Extensions / translation.py
1 # -*- coding: utf-8 -*-
2 # copyright 2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
3 # contact http://www.logilab.fr -- mailto:contact@logilab.fr
4 #
5 # This program is free software: you can redistribute it and/or modify it under
6 # the terms of the GNU Lesser General Public License as published by the Free
7 # Software Foundation, either version 2.1 of the License, or (at your option)
8 # any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 # details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License along
16 # with this program. If not, see <http://www.gnu.org/licenses/>.
17 """
18 Main module of the ``i18n`` package, for internationalizing strings via the Qt
19 mechanism, in the ``Eficas`` application of EDF. Handles unformatted and
20 formatted strings, according to all formatting schemes: via dictionaries,
21 tuples, or atoms.
22
23 ``PyQt4`` is currently supported.
24 """
25 from Extensions.eficas_exception import EficasException
26 def _reformat_qstring_from_tuple(qstring, params):
27     """
28     _reformat_qstring_from_tuple(QString, tuple) -> QString
29
30     Module-internal method.
31     Returns a formatted QString from an unformatted QString
32     and a tuple specifying the parameters of the QString.
33     """
34     from PyQt4.QtCore import QRegExp, QString
35     reg = QRegExp("\%\.[1-9]{1,2}f")
36     for p, j in zip(params, range(len(params))):
37         try:
38             i += 1 + qstring[i + 1:].indexOf("%")
39         except NameError:
40             i = qstring.indexOf("%")
41         if i == reg.indexIn(qstring):
42             precision = reg.cap(0).split('.')[1].split('f')[0]
43             qstring = qstring[:i + 2 + len(precision)].\
44                       replace("%." + precision, "%" + unicode(1 + j)) + \
45                       qstring[i + 3 + len(precision):]
46             qstring = qstring.arg(QString.number(float(params[j]), 'f',\
47                                                  int(precision)))
48         else:
49             qstring = qstring[:i + 1].replace("%", "%" + unicode(1 + j)) + \
50                       qstring[i + 2:]
51             if isinstance(params[j], unicode):
52                 qstring = qstring.arg(params[j])
53             elif isinstance(params[j], float):
54                 qstring = qstring.arg(QString.number(params[j], 'f',\
55                                                      len(unicode(params[j]).\
56                                                          split('.')[1])))
57             elif isinstance(params[j], int):
58                 qstring = qstring.arg(QString.number(params[j], 10))
59             elif isinstance(params[j], list):
60                 qstring = qstring.arg(repr(params[j]))
61             else:
62                 raise EficasException("TypeError: i18n.translation: \
63                                       Unicode, list or number expected!")
64     return qstring
65
66 def _reformat_qstring_from_dict(qstring, params):
67     """
68     _reformat_qstring_from_dict(QString, dict) -> QString
69
70     Module-internal method.
71     Returns a formatted QString from an unformatted QString
72     and a dictionary specifying the parameters of the QString.
73     """
74     from PyQt4.QtCore import QRegExp, QString
75     for p, j in zip(params, range(len(params))):
76         p_reg = QRegExp("\%\("+ p + "\)\.[1-9]{1,2}f")
77         p_index = p_reg.indexIn(qstring)
78         if p_index != -1:
79             precision = p_reg.cap(0).split('.')[1].split('f')[0]
80             qstring = qstring.replace("%(" + p + ")." + precision + "f",\
81                                       "%" + unicode(1 + j)).\
82                                       arg(QString.number(float(params[p]), \
83                                                          'f', \
84                                                          int(precision)))
85         else:
86             qstring.remove(QRegExp("\\)[sdf]{1}"))
87             qstring = qstring.replace("%(" + p, "%" + unicode(1 + j))
88             if isinstance(params[p], unicode):
89                 qstring = qstring.arg(params[p])
90             elif isinstance(params[p], float):
91                 qstring = qstring.arg(QString.number(params[p], 'f', \
92                           len(unicode(params[p]).split('.')[1])))
93             elif isinstance(params[p], int):
94                 qstring = qstring.arg(QString.number(params[p], 10))
95             elif isinstance(params[p], list):
96                 qstring = qstring.arg(repr(params[p]))
97             else:
98                 raise EficasException("TypeError: i18n.translation: \
99                                       Improper string parameter type.")
100     return qstring
101
102 def _reformat_qstring_from_atom(qstring, params):
103     """
104     _reformat_qstring_from_atom(QString, int-or-float) -> QString
105
106     Module-internal method.
107     Returns a formatted QString from an unformatted QString
108     and an integer or a float specifying the parameter of 
109     the QString.
110     """
111     from PyQt4.QtCore import QRegExp, QString
112     reg = QRegExp("\%\.[1-9]{1,2}f")
113     if qstring.count("%") == 0:
114         qstring.append("%1")
115         try:
116             qstring = qstring.arg(unicode(params))
117         except AttributeError:
118             qstring = qstring.arg(params)
119     elif qstring.count("%") == 1:
120         i = qstring.indexOf("%")
121         if i == reg.indexIn(qstring):
122             precision = reg.cap(0).split('.')[1].split('f')[0]
123             qstring = qstring[: i + 2 + len(precision)].\
124                       replace("%." + precision, "%1") + \
125                       qstring[i + 3 + len(precision):]
126             qstring = qstring.arg(QString.number(float(params), 'f',\
127                                                  int(precision)))
128         else:
129             qstring = qstring[:i + 1].replace("%", "%1") + \
130                       qstring[i + 2:]
131             if isinstance(params, (unicode, str)):
132                 qstring = qstring.arg(_preprocess_atom(params))
133             elif isinstance(params, float):
134                 qstring = qstring.arg(QString.number(params, 'f', \
135                                                      len(unicode(params).\
136                                                          split('.')[1])))
137             elif isinstance(params, int):
138                 qstring = qstring.arg(QString.number(params, 10))
139             else:
140                 raise EficasException("TypeError: i18n.translation: Unicode, \
141                                       string or number expected!")
142     return qstring
143
144 def _reformat_qstring_from_list(qstring, params):
145     """
146     _reformat_qstring_from_list(QString, tuple) -> QString
147
148     Module-internal method.
149     Returns a formatted QString from an unformatted QString
150     and a list whose concatenation specifies the parameter 
151     of the QString.
152     """
153     # XXX to add further functionality, e.g. list processing
154     # when ``%`` not at the end.
155     if qstring.count("%") == 1 and \
156        unicode(qstring).strip()[:-1].endswith("%"):
157         qstring = qstring[:qstring.indexOf("%") + 1].append("1")
158         qstring = qstring.arg(u' '.join(map(unicode, params)))
159     elif qstring.count("%") == 0:
160         qstring.append("%1")
161         qstring = qstring.arg(u' '.join(map(unicode, params)))
162     else:
163         raise EficasException("ValueError: i18n.translation: \
164                               At most one '%' expected!")
165     return qstring
166
167 def _preprocess_atom(string):
168     """
169     _preprocess_atom(string-or-number-or-unicode) -> unicode
170     Test if input is a Unicode object or a number; if so, then return it; 
171     otherwise, test if the input is a string; if so, then try to create 
172     a Unicode object out of it. To this end, assume the string is encoded 
173     in utf-8; if this fails, then assume the string is encoded in Latin-9.
174     """
175     if isinstance(string, (unicode, int, float, complex)):
176         return string
177     elif isinstance(string, str):
178         return _str_to_unicode(string)
179     else:
180         raise EficasException("TypeError: Expected number, string or\
181                               Unicode object!")
182
183 def _str_to_unicode(string):
184     """
185     _str_to_unicode(string) -> unicode
186     Tries to create a Unicode object out of the input string; assumes 
187     the string is UTF-8 encoded; if not, then assume the string is 
188     Latin-9 encoded.
189     """
190     try:
191         string = unicode(string, "utf-8")
192     except UnicodeDecodeError:
193         try:
194             string = unicode(string, "iso-8859-15")
195         except UnicodeDecodeError:
196             raise EficasException("UnicodeDecodeError: UTF-8, Latin-1 \
197                                   or Latin-9 expected")
198     return string
199
200 def tr(string, *args):
201     """tr(string-or-unicode, iterable-or-float-or-int) -> unicode
202        tr(string-or-unicode) -> unicode
203        
204        Returns a formatted Unicode object from an unformatted 
205        string or Unicode object with formatting specifications, and, 
206        optionally, an iterable or an int or float.
207        Lets Python do the string formatting."""
208     from PyQt4.QtGui import QApplication
209     print string, args
210     string = _preprocess_atom(string)
211     if len(args) == 0:
212         r = unicode(QApplication.translate("@default", string))
213     elif len(args) == 1:
214         if isinstance(args[0], (dict, tuple)):
215             if string.count("%") == len(args[0]):
216                 r = unicode(QApplication.translate("@default", string)) % args[0]
217             elif string.count("%") == 1 and string.count("%(") == 0:
218                 r = unicode(QApplication.translate("@default", string))\
219                     % _preprocess_atom(repr(args[0]))
220             elif string.count("%") == 0:
221                 r = (unicode(QApplication.translate("@default", string)), args[0])
222             else:
223                 raise EficasException("ValueError: i18n.translate.tr: \
224                                       Improper input string formatting")
225         elif isinstance(args[0], (unicode, str, int, float, complex)):
226             if string.count("%") == 1:
227                 r = unicode(QApplication.translate("@default", string))\
228                     % _preprocess_atom(args[0])
229             else:
230                 r = unicode(QApplication.translate("@default", string)) +\
231                     unicode(_preprocess_atom(args[0]))
232         elif isinstance(args[0], list) or args[0] is None:
233             if string.count("%") == 1:
234                 r = unicode(QApplication.translate("@default", string))\
235                     % _preprocess_atom(repr(args[0]))
236             else:
237                 r = (unicode(QApplication.translate("@default", string)), args[0])
238
239         else:
240             raise EficasException("ValueError: i18n.translation.tr: \
241                                   Wrong type for formatted string \
242                                   arguments: %s" % type(args[0]))
243     else:
244         raise EficasException("ValueError: i18n.translation.tr: \
245                               Wrong formatted string arguments")
246     return r
247
248
249 def tr_qt(string, *args):
250     """tr_qt(string, iterable-or-float-or-int) -> unicode
251        t_qtr(string) -> unicode
252        
253        Returns a formatted string from an unformatted 
254        Unicode string with formatting specifications, and, 
255        optionally, an iterable or an int or float.
256        Lets PyQt4 do the string formatting. To this end,
257        a conversion from Python to Qt string formatting
258        syntax is performed."""
259     string = _preprocess_atom(string)
260     from PyQt4.QtGui import QApplication
261     if len(args) == 0:
262         r = QApplication.translate("@default", string)
263     elif len(args) == 1:
264         r = QApplication.translate("@default", string)
265         if isinstance(args[0], (dict, tuple)):
266             if r.count("%") == len(args[0]):
267                 if isinstance(args[0], dict):
268                     r = _reformat_qstring_from_dict(r, args[0])
269                 elif isinstance(args[0], tuple):
270                     r = _reformat_qstring_from_tuple(r, args[0])
271             # XXX Pay attention to this: distinguish between tuple, 
272             # dict and dict with key given in string.
273             elif r.count("%") in range(2) and r.count("%(") == 0:
274                 r = _reformat_qstring_from_atom(r, _preproces_atom(repr(args[0])))
275             else:
276                 raise EficasException("ValueError: i18n.translation.tr_qt: \
277                                       Improper formatting string parameters")
278         elif isinstance(args[0], (unicode, str, int, float, complex)):
279             r = _reformat_qstring_from_atom(r, args[0])
280         elif isinstance(args[0], list):
281             r = _reformat_qstring_from_list(r, args[0])
282         elif args[0] is None:
283             r = _reformat_qstring_from_atom(r, _preprocess_string_from_atom(repr(args[0])))
284         else:
285             raise EficasException("ValueError: i18n.translation.tr_qt: \
286                                   Wrong string formatting parameter types")
287     else:
288         raise EficasException("ValueError: i18n.translation.tr_qt: \
289                               Improper formatted string parameter set")
290     return unicode(r)
291
292
293 if __name__ == "__main__":
294     import sys
295     tr(sys.argv[1], *args)
296     tr_qt(sys.argv[1], *args)