Home | Trees | Indices | Help |
|
---|
|
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # 4 # Copyright 2009 Zuza Software Foundation 5 # 6 # This file is part of the Translate Toolkit. 7 # 8 # This program is free software; you can redistribute it and/or modify 9 # it under the terms of the GNU General Public License as published by 10 # the Free Software Foundation; either version 2 of the License, or 11 # (at your option) any later version. 12 # 13 # This program is distributed in the hope that it will be useful, 14 # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 # GNU General Public License for more details. 17 # 18 # You should have received a copy of the GNU General Public License 19 # along with this program; if not, see <http://www.gnu.org/licenses/>. 20 21 """ 22 Contains general placeable implementations. That is placeables that does not 23 fit into any other sub-category. 24 """ 25 26 import re 27 28 __all__ = ['AltAttrPlaceable', 'XMLEntityPlaceable', 'XMLTagPlaceable', 'parsers', 'to_general_placeables'] 29 30 from translate.storage.placeables.base import G, Ph, StringElem 31 3234 """A parser method to extract placeables from a string based on a regular 35 expression. Use this function as the C{@parse()} method of a placeable 36 class.""" 37 if cls.regex is None: 38 return None 39 matches = [] 40 oldend = 0 41 for match in cls.regex.finditer(pstr): 42 start, end = match.start(), match.end() 43 if oldend != start: 44 matches.append(StringElem(pstr[oldend:start])) 45 matches.append(cls([pstr[start:end]])) 46 oldend = end 47 if oldend != len(pstr) and matches: 48 matches.append(StringElem(pstr[oldend:])) 49 return matches or None50 5153 """Placeable for the "alt=..." attributes inside XML tags.""" 54 55 regex = re.compile(r'alt=".*?"') 56 parse = classmethod(regex_parse)57 5860 """Matches new-lines.""" 61 62 iseditable = False 63 isfragile = True 64 istranslatable = False 65 regex = re.compile(r'\n') 66 parse = classmethod(regex_parse)67 6870 """Placeable for numbers.""" 71 72 istranslatable = False 73 regex = re.compile(ur"[-+]?[0-9]+([\u00a0.,][0-9]+)*") 74 parse = classmethod(regex_parse)75 7678 """Placeable representing a Qt string formatting variable. 79 80 Implemented following Qt documentation on 81 U{QString::arg<http://doc.trolltech.com/4.5/qstring.html#arg>} where 82 the placeables are refered to as 'place markers' 83 84 Notes: 85 - Place markers can be reordered 86 - Place markers may be repeated 87 - 'L' use a localised representation e.g. in a number 88 - %% some in the wild to escape real %, not documented (not in regex) 89 """ 90 iseditable = False 91 istranslatable = False 92 regex = re.compile(r"""(?x) 93 % # Start of a place marker 94 L? # The sequence is replaced with a localized representation (optional) 95 [1-9]\d{0,1} # Place marker numbers must be in the range 1 to 99. 96 (?=([^\d]|$)) # Double check that we aren't matching %100+ (non consuming match) 97 """) 98 parse = classmethod(regex_parse)99 100102 """Placeable representing a Python string formatting variable. 103 104 Implemented following Python documentation on 105 U{String Formatting Operations<http://docs.python.org/library/stdtypes.html#string-formatting-operations>}""" 106 107 iseditable = False 108 istranslatable = False 109 # Need to correctly define a python identifier. 110 regex = re.compile(r"""(?x) 111 % # Start of formatting specifier 112 (%| # No argument converted %% creates a % 113 (\([a-z_]+\)){0,1} # Mapping key value (optional) 114 [\-\+0\s\#]{0,1} # Conversion flags (optional) 115 (\d+|\*){0,1} # Minimum field width (optional) 116 (\.(\d+|\*)){0,1} # Precision (optional) 117 [hlL]{0,1} # Length modifier (optional) 118 [diouxXeEfFgGcrs]{1}) # Conversion type""") 119 parse = classmethod(regex_parse)120 121123 """Placeable representing a Java MessageFormat formatting variable. 124 125 Implemented according to the Java U{MessageFormat 126 documentation<http://java.sun.com/j2se/1.4.2/docs/api/java/text/MessageFormat.html>}. 127 128 Information about custom formats: 129 - number - U{DecimalFormat<http://java.sun.com/j2se/1.4.2/docs/api/java/text/DecimalFormat.html>} 130 - date/time - U{SimpleDateFormat<http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html>} 131 - choice - U{ChoiceFormat<http://java.sun.com/j2se/1.4.2/docs/api/java/text/ChoiceFormat.html>} 132 """ 133 134 iseditable = False # TODO: Technically incorrect as you need to change 135 istranslatable = False 136 # things in a choice entry 137 regex = re.compile(r"""(?x) 138 { # Start of MessageFormat 139 [0-9]+ # Number, positive array reference 140 (,\s* # FormatType (optional) one of number,date,time,choice 141 (number(,\s*(integer|currency|percent|[-0#.,E;%\u2030\u00a4']+)?)?| # number FormatStyle (optional) 142 (date|time)(,\s*(short|medium|long|full|.+?))?| # date/time FormatStyle (optional) 143 choice,([^{]+({.+})?)+)? # choice with format, format required 144 )? # END: (optional) FormatType 145 } # END: MessageFormat""") 146 parse = classmethod(regex_parse)147 148150 """Placeable representing string formatting variables.""" 151 152 iseditable = False 153 istranslatable = False 154 regex = re.compile(r"%[\-\+0\s\#]{0,1}(\d+){0,1}(\.\d+){0,1}[hlI]{0,1}[cCdiouxXeEfgGnpsS]{1}") 155 parse = classmethod(regex_parse)156 157159 """Placeable handling URI.""" 160 161 istranslatable = False 162 regex = re.compile(r""" 163 ((((news|nttp|file|https?|ftp|irc)://) # has to start with a protocol 164 |((www|ftp)[-A-Za-z0-9]*\.)) # or www... or ftp... hostname 165 ([-A-Za-z0-9]+(\.[-A-Za-z0-9]+)*) # hostname 166 |(\d{1,3}(\.\d{1,3}){3,3})) # or IP address 167 (:[0-9]{1,5})? # optional port 168 (/[-A-Za-z0-9_\$\.\+\!\*\(\),;:@&=\?/~\#\%]*)? # optional trailing path 169 (?=$|\s|([]'}>\),\"])) 170 """, re.VERBOSE) 171 parse = classmethod(regex_parse)172 173175 """Placeable handling file locations.""" 176 177 istranslatable = False 178 regex = re.compile(r"(~/|/|\./)([-A-Za-z0-9_\$\.\+\!\*\(\),;:@&=\?/~\#\%]|\\){3,}") 179 #TODO: Handle Windows drive letters. Some common Windows paths won't be 180 # handled correctly while note allowing spaces, such as 181 # "C:\Documents and Settings" 182 # "C:\Program Files" 183 parse = classmethod(regex_parse)184 185187 """Placeable handling emails.""" 188 189 istranslatable = False 190 regex = re.compile(r"((mailto:)|)[A-Za-z0-9]+[-a-zA-Z0-9._%]*@(([-A-Za-z0-9]+)\.)+[a-zA-Z]{2,4}") 191 # TODO: What about internationalised domain names? ;-) 192 parse = classmethod(regex_parse)193 194196 """Placeable handling punctuation.""" 197 198 iseditable = False 199 istranslatable = False 200 # FIXME this should really be a list created as being the inverse of what 201 # is available on the translators keyboard. Or easily expanded by their 202 # configuration. 203 regex = re.compile(ur'[™℃℉©®£¥°±‘’‚‛“”„‟…—– ]+') #last space is NBSP 204 parse = classmethod(regex_parse)205 206208 """Placeable handling XML entities (C{&xxxxx;}-style entities).""" 209 210 iseditable = False 211 istranslatable = False 212 regex = re.compile(r'''&( 213 ([a-zA-Z][a-zA-Z0-9\.-]*) #named entity 214 |([#](\d{1,5}|x[a-fA-F0-9]{1,5})+) #numeric entity 215 );''', re.VERBOSE) 216 parse = classmethod(regex_parse)217 218220 """Placeable handling long all-caps strings.""" 221 222 iseditable = True 223 regex = re.compile(r'\b[A-Z][A-Z/\-:*0-9]{2,}\b') 224 parse = classmethod(regex_parse)225 226228 """Placeable handling camel case strings.""" 229 230 iseditable = True 231 regex = re.compile(r'''(?x) 232 \b( 233 [a-z]+[A-Z]| #Not that strict if we start with lower (iPod) 234 [A-Z]+[a-z]+[A-Z]| #One capital at the start is not enough (OpenTran) 235 [A-Z]{2,}[a-z] #Two capitals at the start is enough (KBabel) 236 )[a-zA-Z0-9]* #Let's allow any final lower/upper/digit 237 \b''') 238 parse = classmethod(regex_parse)239 240242 """Placeable handling unusual spaces in strings.""" 243 244 iseditable = True 245 istranslatable = False 246 regex = re.compile(r"""(?m) #Multiline expression 247 [ ]{2,}| #More than two consecutive 248 ^[ ]+| #At start of a line 249 [ ]+$ #At end of line""", re.VERBOSE) 250 251 parse = classmethod(regex_parse)252 253255 """Placeable handling XML tags.""" 256 257 iseditable = False 258 istranslatable = False 259 regex = re.compile(r'<(\w+)(\s(\w*=".*?")?)*/?>|</(\w+)>') 260 parse = classmethod(regex_parse)261 262264 """Placeble handling command line options e.g. --help""" 265 266 istranslatable = False 267 regex = re.compile(r'''(?x) 268 \B( # Empty string at the start of a non-word, ensures [space]- 269 -[a-zA-Z]| # Single letter options: -i, -I 270 --[a-z\-]+ # Word options: --help 271 )\b''') 272 #regex = re.compile(r'''(-[a-zA-Z]|--[-a-z]+)\b''') 273 parse = classmethod(regex_parse)274 275276 -def to_general_placeables(tree, classmap={ 277 G: (AltAttrPlaceable,), 278 Ph: ( 279 NumberPlaceable, 280 XMLEntityPlaceable, 281 XMLTagPlaceable, 282 UrlPlaceable, 283 FilePlaceable, 284 EmailPlaceable, 285 OptionPlaceable, 286 PunctuationPlaceable, 287 ) 288 }):289 if not isinstance(tree, StringElem): 290 return tree 291 292 newtree = None 293 294 for baseclass, gclasslist in classmap.items(): 295 if isinstance(tree, baseclass): 296 gclass = [c for c in gclasslist if c.parse(unicode(tree))] 297 if gclass: 298 newtree = gclass[0]() 299 300 if newtree is None: 301 newtree = tree.__class__() 302 303 newtree.id = tree.id 304 newtree.rid = tree.rid 305 newtree.xid = tree.xid 306 newtree.sub = [] 307 308 for subtree in tree.sub: 309 newtree.sub.append(to_general_placeables(subtree)) 310 311 return newtree312 313 parsers = [ 314 NewlinePlaceable.parse, 315 XMLTagPlaceable.parse, 316 AltAttrPlaceable.parse, 317 XMLEntityPlaceable.parse, 318 QtFormattingPlaceable.parse, 319 PythonFormattingPlaceable.parse, 320 JavaMessageFormatPlaceable.parse, 321 FormattingPlaceable.parse, 322 UrlPlaceable.parse, 323 FilePlaceable.parse, 324 EmailPlaceable.parse, 325 CapsPlaceable.parse, 326 CamelCasePlaceable.parse, 327 OptionPlaceable.parse, 328 PunctuationPlaceable.parse, 329 NumberPlaceable.parse, 330 ] 331
Home | Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Tue Aug 4 17:32:59 2009 | http://epydoc.sourceforge.net |