2 # -*- coding: utf-8 -*-
4 # Copyright 2004-2008 Zuza Software Foundation
6 # This file is part of translate.
8 # translate 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.
13 # translate 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.
18 # You should have received a copy of the GNU General Public License
19 # along with translate; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 """classes that hold units of php localisation files (phpunit) or entire files
23 (phpfile) these files are used in translating many PHP based applications
27 from translate
.storage
import base
28 from translate
.misc
import quote
31 def phpencode(text
, quotechar
="'"):
32 """convert Python string to PHP escaping"""
35 return text
.replace("%s" % quotechar
, "\\%s" % quotechar
).replace("\n", "\\n")
38 """convert PHP escaped string to a Python string"""
41 return text
.replace("\\'", "'").replace('\\"', '"').replace("\\n", "\n")
43 class phpunit(base
.TranslationUnit
):
44 """a unit of a PHP file i.e. a name and value, and any comments
46 def __init__(self
, source
=""):
47 """construct a blank phpunit"""
48 super(phpunit
, self
).__init
__(source
)
54 def setsource(self
, source
):
55 """Sets the source AND the target to be equal"""
56 self
.value
= phpencode(source
)
59 return phpdecode(self
.value
)
60 source
= property(getsource
, setsource
)
62 def settarget(self
, target
):
63 """Note: this also sets the .source attribute!"""
64 # TODO: shouldn't this just call the .source property? no quoting done here...
69 target
= property(gettarget
, settarget
)
72 """convert to a string. double check that unicode is handled somehow here"""
73 source
= self
.getoutput()
74 if isinstance(source
, unicode):
75 return source
.encode(getattr(self
, "encoding", "UTF-8"))
79 """convert the unit back into formatted lines for a php file"""
80 return "".join(self
._comments
+ ["%s='%s';\n" % (self
.name
, self
.value
)])
82 def addlocation(self
, location
):
85 def getlocations(self
):
88 def addnote(self
, note
, origin
=None):
89 self
._comments
.append(note
)
91 def getnotes(self
, origin
=None):
92 return '\n'.join(self
._comments
)
94 def removenotes(self
):
98 """returns whether this is a blank element, containing only comments..."""
99 return not (self
.name
or self
.value
)
101 class phpfile(base
.TranslationStore
):
102 """this class represents a php file, made up of phpunits"""
104 def __init__(self
, inputfile
=None, encoding
='utf-8'):
105 """construct a phpfile, optionally reading in from inputfile"""
106 super(phpfile
, self
).__init
__(unitclass
= self
.UnitClass
)
107 self
.filename
= getattr(inputfile
, 'name', '')
108 self
._encoding
= encoding
109 if inputfile
is not None:
110 phpsrc
= inputfile
.read()
114 def parse(self
, phpsrc
):
115 """read the source of a php file in and include them as units"""
122 valuequote
= "" # either ' or "
123 for line
in phpsrc
.decode(self
._encoding
).split("\n"):
124 # Assuming /* comments */ are started and stopped on lines
125 commentstartpos
= line
.find("/*")
126 commentendpos
= line
.rfind("*/")
127 if commentstartpos
!= -1:
129 if commentendpos
!= -1:
130 newunit
.addnote(line
[commentstartpos
+2:commentendpos
].strip(), "developer")
133 newunit
.addnote(line
[commentstartpos
+2:].strip(), "developer")
134 if commentendpos
!= -1 and incomment
:
135 newunit
.addnote(line
[:commentendpos
].strip(), "developer")
137 if commentstartpos
== -1 and incomment
:
138 newunit
.addnote(line
.strip(), "developer")
139 equalpos
= line
.find("=")
140 if equalpos
!= -1 and not invalue
:
141 newunit
.addlocation(line
[:equalpos
].strip().replace(" ", ""))
142 value
= line
[equalpos
+1:].lstrip()[1:]
143 valuequote
= line
[equalpos
+1:].lstrip()[0]
149 colonpos
= value
.rfind(";")
150 while colonpos
!= -1:
151 if value
[colonpos
-1] == valuequote
:
152 newunit
.value
= lastvalue
+ value
[:colonpos
-1]
155 if not invalue
and colonpos
!= len(value
)-1:
156 commentinlinepos
= value
.find("//", colonpos
)
157 if commentinlinepos
!= -1:
158 newunit
.addnote(value
[commentinlinepos
+2:].strip(), "developer")
160 self
.addunit(newunit
)
163 colonpos
= value
.rfind(";", 0, colonpos
)
165 lastvalue
= lastvalue
+ value
168 """convert the units back to lines"""
170 for unit
in self
.units
:
171 lines
.append(str(unit
))
172 return "".join(lines
)
174 if __name__
== '__main__':
176 pf
= phpfile(sys
.stdin
)
177 sys
.stdout
.write(str(pf
))