Package translate :: Package storage :: Module tiki

[hide private]
[frames] | no frames]

# Source Code for Module translate.storage.tiki

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2008 Mozilla Corporation, 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  """Class that manages TikiWiki files for translation.  Tiki files are <strike>ugly and
     23  inconsistent</strike> formatted as a single large PHP array with several special
     24  sections identified by comments.  Example current as of 2008-12-01::
     25
     26    <?php
     27      // Many comments at the top
     28      $lang=Array(
     29      // ### Start of unused words
     30      "aaa" => "zzz",
     31      // ### end of unused words
     32
     33      // ### start of untranslated words
     34      // "bbb" => "yyy",
     35      // ### end of untranslated words
     36
     37      // ### start of possibly untranslated words
     38      "ccc" => "xxx",
     39      // ### end of possibly untranslated words
     40
     41      "ddd" => "www",
     42      "###end###"=>"###end###");
     43    ?>
     44
     45  In addition there are several auto-generated //-style comments scattered through the
     46  page and array, some of which matter when being parsed.
     47
     48  This has all been gleaned from the
     49  U{TikiWiki source<http://tikiwiki.svn.sourceforge.net/viewvc/tikiwiki/trunk/get_strings.php?view=markup>}.
     50  As far as I know no detailed documentation exists for the tiki language.php files.
     51
     52  """
     53
     54  import datetime
     55  import re
     56
     57  from translate.misc import wStringIO
     58  from translate.storage import base
     59
     60
     61 -class TikiUnit(base.TranslationUnit):
     62      """A tiki unit entry."""
     63
     64 -    def __init__(self, source=None, encoding="UTF-8"):
     65          self.location = []
     66          super(TikiUnit, self).__init__(source)
     67
     68 -    def __unicode__(self):
     69          """Returns a string formatted to be inserted into a tiki language.php file."""
     70          ret = u'"%s" => "%s",' % (self.source, self.target)
     71          if self.location == ["untranslated"]:
     72              ret = u'// ' + ret
     73          return ret + "\n"
     74
     75 -    def addlocation(self, location):
     76          """Location is defined by the comments in the file. This function will only
     77          set valid locations.
     78
     79          @param location: Where the string is located in the file.  Must be a valid location.
     80          """
     81          if location in ['unused', 'untranslated', 'possiblyuntranslated', 'translated']:
     82              self.location.append(location)
     83
     84 -    def getlocations(self):
     85          """Returns the a list of the location(s) of the string."""
     86          return self.location
     87
     88
     89 -class TikiStore(base.TranslationStore):
     90      """Represents a tiki language.php file."""
     91
     92 -    def __init__(self, inputfile=None):
     93          """If an inputfile is specified it will be parsed.
     94
     95          @param inputfile: Either a string or a filehandle of the source file
     96          """
     97          base.TranslationStore.__init__(self, TikiUnit)
     98          self.units = []
     99          self.filename = getattr(inputfile, 'name', '')
    100          if inputfile is not None:
    101              self.parse(inputfile)
    102
    103 -    def __str__(self):
    104          """Will return a formatted tiki-style language.php file."""
    105          _unused = []
    106          _untranslated = []
    107          _possiblyuntranslated = []
    108          _translated = []
    109
    110          output = self._tiki_header()
    111
    112          # Reorder all the units into their groups
    113          for unit in self.units:
    114              if unit.getlocations() == ["unused"]:
    115                  _unused.append(unit)
    116              elif unit.getlocations() == ["untranslated"]:
    117                  _untranslated.append(unit)
    118              elif unit.getlocations() == ["possiblyuntranslated"]:
    119                  _possiblyuntranslated.append(unit)
    120              else:
    121                  _translated.append(unit)
    122
    123          output += "// ### Start of unused words\n"
    124          for unit in _unused:
    125              output += unicode(unit)
    126          output += "// ### end of unused words\n\n"
    127          output += "// ### start of untranslated words\n"
    128          for unit in _untranslated:
    129              output += unicode(unit)
    130          output += "// ### end of untranslated words\n\n"
    131          output += "// ### start of possibly untranslated words\n"
    132          for unit in _possiblyuntranslated:
    133              output += unicode(unit)
    134          output += "// ### end of possibly untranslated words\n\n"
    135          for unit in _translated:
    136              output += unicode(unit)
    137
    138          output += self._tiki_footer()
    139          return output.encode('UTF-8')
    140
    141 -    def _tiki_header(self):
    142          """Returns a tiki-file header string."""
    143          return u"<?php // -*- coding:utf-8 -*-\n// Generated from po2tiki on %s\n\n$lang=Array(\n" % datetime.datetime.now()
    144
    148
    149 -    def parse(self, input):
    150          """Parse the given input into source units.
    151
    152          @param input: the source, either a string or filehandle
    153          """
    154          if hasattr(input, "name"):
    155              self.filename = input.name
    156
    157          if isinstance(input, str):
    158              input = wStringIO.StringIO(input)
    159
    160          _split_regex = re.compile(r"^(?:// )?\"(.*)\" => \"(.*)\",$", re.UNICODE)
    161
    162          try:
    163              _location = "translated"
    164
    165              for line in input:
    166                  # The tiki file fails to identify each section so we have to look for start and end
    167                  # points and if we're outside of them we assume the string is translated
    168                  if line.count("### Start of unused words"):
    169                      _location = "unused"
    170                  elif line.count("### start of untranslated words"):
    171                      _location = "untranslated"
    172                  elif line.count("### start of possibly untranslated words"):
    173                      _location = "possiblyuntranslated"
    174                  elif line.count("### end of unused words"):
    175                      _location = "translated"
    176                  elif line.count("### end of untranslated words"):
    177                      _location = "translated"
    178                  elif line.count("### end of possibly untranslated words"):
    179                      _location = "translated"
    180
    181                  match = _split_regex.match(line)
    182
    183                  if match:
    184                      unit = self.addsourceunit("".join(match.group(1)))
    185                      # Untranslated words get an empty msgstr
    186                      if not _location == "untranslated":
    187                          unit.settarget(match.group(2))
    188                      unit.addlocation(_location)
    189          finally:
    190              input.close()
    191