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  from translate.storage import base
     55  from translate.misc import wStringIO
     56  import re
     57  import datetime
     58
     59 -class TikiUnit(base.TranslationUnit):
     60      """A tiki unit entry."""
     61 -    def __init__(self, source=None, encoding="UTF-8"):
     62          self.location = []
     63          super(TikiUnit, self).__init__(source)
     64
     65 -    def __unicode__(self):
     66          """Returns a string formatted to be inserted into a tiki language.php file."""
     67          ret = u'"%s" => "%s",' % (self.source, self.target)
     68          if self.location == ["untranslated"]:
     69              ret = u'// ' + ret
     70          return ret + "\n"
     71
     72 -    def addlocation(self, location):
     73          """Location is defined by the comments in the file. This function will only
     74          set valid locations.
     75
     76          @param location: Where the string is located in the file.  Must be a valid location.
     77          """
     78          if location in ['unused', 'untranslated', 'possiblyuntranslated', 'translated']:
     79              self.location.append(location)
     80
     81 -    def getlocations(self):
     82          """Returns the a list of the location(s) of the string."""
     83          return self.location
     84
     85 -class TikiStore(base.TranslationStore):
     86      """Represents a tiki language.php file."""
     87 -    def __init__(self, inputfile=None):
     88          """If an inputfile is specified it will be parsed.
     89
     90          @param inputfile: Either a string or a filehandle of the source file
     91          """
     92          base.TranslationStore.__init__(self, TikiUnit)
     93          self.units = []
     94          self.filename = getattr(inputfile, 'name', '')
     95          if inputfile is not None:
     96              self.parse(inputfile)
     97
     98 -    def __str__(self):
     99          """Will return a formatted tiki-style language.php file."""
    100          _unused = []
    101          _untranslated = []
    102          _possiblyuntranslated = []
    103          _translated = []
    104
    105          output = self._tiki_header()
    106
    107          # Reorder all the units into their groups
    108          for unit in self.units:
    109              if unit.getlocations() == ["unused"]:
    110                  _unused.append(unit)
    111              elif unit.getlocations() == ["untranslated"]:
    112                  _untranslated.append(unit)
    113              elif unit.getlocations() == ["possiblyuntranslated"]:
    114                  _possiblyuntranslated.append(unit)
    115              else:
    116                  _translated.append(unit)
    117
    118          output += "// ### Start of unused words\n"
    119          for unit in _unused:
    120              output += unicode(unit)
    121          output += "// ### end of unused words\n\n"
    122          output += "// ### start of untranslated words\n"
    123          for unit in _untranslated:
    124              output += unicode(unit)
    125          output += "// ### end of untranslated words\n\n"
    126          output += "// ### start of possibly untranslated words\n"
    127          for unit in _possiblyuntranslated:
    128              output += unicode(unit)
    129          output += "// ### end of possibly untranslated words\n\n"
    130          for unit in _translated:
    131              output += unicode(unit)
    132
    133          output += self._tiki_footer()
    134          return output.encode('UTF-8')
    135
    136 -    def _tiki_header(self):
    137          """Returns a tiki-file header string."""
    138          return u"<?php // -*- coding:utf-8 -*-\n// Generated from po2tiki on %s\n\n$lang=Array(\n" % datetime.datetime.now()
    139
    143
    144 -    def parse(self, input):
    145          """Parse the given input into source units.
    146
    147          @param input: the source, either a string or filehandle
    148          """
    149          if hasattr(input, "name"):
    150              self.filename = input.name
    151
    152          if isinstance(input, str):
    153              input = wStringIO.StringIO(input)
    154
    155          _split_regex = re.compile(r"^(?:// )?\"(.*)\" => \"(.*)\",$", re.UNICODE)
    156
    157          try:
    158              _location = "translated"
    159
    160              for line in input:
    161                  # The tiki file fails to identify each section so we have to look for start and end
    162                  # points and if we're outside of them we assume the string is translated
    163                  if line.count("### Start of unused words"):
    164                      _location = "unused"
    165                  elif line.count("### start of untranslated words"):
    166                      _location = "untranslated"
    167                  elif line.count("### start of possibly untranslated words"):
    168                      _location = "possiblyuntranslated"
    169                  elif line.count("### end of unused words"):
    170                      _location = "translated"
    171                  elif line.count("### end of untranslated words"):
    172                      _location = "translated"
    173                  elif line.count("### end of possibly untranslated words"):
    174                      _location = "translated"
    175
    176                  match = _split_regex.match(line)
    177
    178                  if match:
    179                      unit = self.addsourceunit("".join(match.group(1)))
    180                      # Untranslated words get an empty msgstr
    181                      if not _location == "untranslated":
    182                          unit.settarget(match.group(2))
    183                      unit.addlocation(_location)
    184          finally:
    185              input.close()
    186