Package translate :: Package storage :: Module php

[hide private]
[frames] | no frames]

# Source Code for Module translate.storage.php

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2004-2008 Zuza Software Foundation
      5  #
      6  # This file is part of translate.
      7  #
      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.
     12  #
     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.
     17  #
     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
     21
     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
     24
     25  """
     26
     27  from translate.storage import base
     28  from translate.misc import quote
     29  import re
     30
     31 -def phpencode(text, quotechar="'"):
     32      """convert Python string to PHP escaping"""
     33      if not text:
     34          return text
     35      return text.replace("%s" % quotechar, "\\%s" % quotechar).replace("\n", "\\n")
     36
     37 -def phpdecode(text):
     38      """convert PHP escaped string to a Python string"""
     39      if not text:
     40          return text
     41      return text.replace("\\'", "'").replace('\\"', '"').replace("\\n", "\n")
     42
     43 -class phpunit(base.TranslationUnit):
     44      """a unit of a PHP file i.e. a name and value, and any comments
     45      associated"""
     46 -    def __init__(self, source=""):
     47          """construct a blank phpunit"""
     48          super(phpunit, self).__init__(source)
     49          self.name = ""
     50          self.value = ""
     51          self._comments = []
     52          self.source = source
     53
     54 -    def setsource(self, source):
     55          """Sets the source AND the target to be equal"""
     56          self.value = phpencode(source)
     57
     58 -    def getsource(self):
     59          return phpdecode(self.value)
     60      source = property(getsource, setsource)
     61
     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...
     65          self.source = target
     66
     67 -    def gettarget(self):
     68          return self.source
     69      target = property(gettarget, settarget)
     70
     71 -    def __str__(self):
     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"))
     76          return source
     77
     78 -    def getoutput(self):
     79          """convert the unit back into formatted lines for a php file"""
     80          return "".join(self._comments + ["%s='%s';\n" % (self.name, self.value)])
     81
     82 -    def addlocation(self, location):
     83          self.name = location
     84
     85 -    def getlocations(self):
     86          return [self.name]
     87
     88 -    def addnote(self, note, origin=None):
     89          self._comments.append(note)
     90
     91 -    def getnotes(self, origin=None):
     92          return '\n'.join(self._comments)
     93
     94 -    def removenotes(self):
     95          self._comments = []
     96
     97 -    def isblank(self):
     98          """returns whether this is a blank element, containing only comments..."""
     99          return not (self.name or self.value)
    100
    101 -class phpfile(base.TranslationStore):
    102      """this class represents a php file, made up of phpunits"""
    103      UnitClass = phpunit
    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()
    111              inputfile.close()
    112              self.parse(phpsrc)
    113
    114 -    def parse(self, phpsrc):
    115          """read the source of a php file in and include them as units"""
    116          newunit = phpunit()
    117          lastvalue = ""
    118          value = ""
    119          comment = []
    120          invalue = False
    121          incomment = False
    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:
    128                  incomment = True
    129                  if commentendpos != -1:
    130                      newunit.addnote(line[commentstartpos+2:commentendpos].strip(), "developer")
    131                      incomment = False
    132                  if incomment:
    133                      newunit.addnote(line[commentstartpos+2:].strip(), "developer")
    134              if commentendpos != -1 and incomment:
    135                  newunit.addnote(line[:commentendpos].strip(), "developer")
    136                  incomment = False
    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]
    144                  lastvalue = ""
    145                  invalue = True
    146              else:
    147                  if invalue:
    148                      value = line
    149              colonpos = value.rfind(";")
    150              while colonpos != -1:
    151                  if value[colonpos-1] == valuequote:
    152                      newunit.value = lastvalue + value[:colonpos-1]
    153                      lastvalue = ""
    154                      invalue = False
    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")
    159                  if not invalue:
    160                      self.addunit(newunit)
    161                      value = ""
    162                      newunit = phpunit()
    163                  colonpos = value.rfind(";", 0, colonpos)
    164              if invalue:
    165                  lastvalue = lastvalue + value
    166
    167 -    def __str__(self):
    168          """convert the units back to lines"""
    169          lines = []
    170          for unit in self.units:
    171              lines.append(str(unit))
    172          return "".join(lines)
    173
    174  if __name__ == '__main__':
    175      import sys
    176      pf = phpfile(sys.stdin)
    177      sys.stdout.write(str(pf))
    178