[Debian-l10n-commits] r1813 - in /translate-toolkit/branches/upstream/current: ./ tools/ translate/ translate/convert/ translate/doc/user/ translate/filters/ translate/lang/ translate/misc/ translate/search/ translate/search/indexing/ translate/services/ translate/storage/ translate/storage/placeables/ translate/storage/versioncontrol/ translate/storage/xml_extract/ translate/tools/

nekral-guest at users.alioth.debian.org nekral-guest at users.alioth.debian.org
Fri Jul 24 16:25:53 UTC 2009


Author: nekral-guest
Date: Fri Jul 24 16:25:46 2009
New Revision: 1813

URL: http://svn.debian.org/wsvn/?sc=1&rev=1813
Log:
[svn-upgrade] Integrating new upstream version, translate-toolkit (1.4.0-rc1)

Added:
    translate-toolkit/branches/upstream/current/translate/convert/po2sub   (with props)
    translate-toolkit/branches/upstream/current/translate/convert/po2sub.py
    translate-toolkit/branches/upstream/current/translate/convert/po2web2py   (with props)
    translate-toolkit/branches/upstream/current/translate/convert/po2web2py.py
    translate-toolkit/branches/upstream/current/translate/convert/sub2po   (with props)
    translate-toolkit/branches/upstream/current/translate/convert/sub2po.py
    translate-toolkit/branches/upstream/current/translate/convert/web2py2po   (with props)
    translate-toolkit/branches/upstream/current/translate/convert/web2py2po.py
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-odf.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po2sub.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-py2web2po.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-sub2po.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-subtitles.html
    translate-toolkit/branches/upstream/current/translate/lang/de.py
    translate-toolkit/branches/upstream/current/translate/lang/identify.py
    translate-toolkit/branches/upstream/current/translate/lang/ne.py
    translate-toolkit/branches/upstream/current/translate/lang/test_ne.py
    translate-toolkit/branches/upstream/current/translate/misc/xml_helpers.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/general.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/interfaces.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/parse.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/strelem.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/terminology.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/test_base.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/test_general.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/test_terminology.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/xliff.py
    translate-toolkit/branches/upstream/current/translate/storage/subtitles.py
Removed:
    translate-toolkit/branches/upstream/current/translate/misc/rich.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/misc.py
Modified:
    translate-toolkit/branches/upstream/current/PKG-INFO
    translate-toolkit/branches/upstream/current/setup.py
    translate-toolkit/branches/upstream/current/tools/pomigrate2
    translate-toolkit/branches/upstream/current/translate/README
    translate-toolkit/branches/upstream/current/translate/__version__.py
    translate-toolkit/branches/upstream/current/translate/convert/accesskey.py
    translate-toolkit/branches/upstream/current/translate/convert/moz2po.py
    translate-toolkit/branches/upstream/current/translate/convert/mozfunny2prop.py
    translate-toolkit/branches/upstream/current/translate/convert/odf2xliff.py
    translate-toolkit/branches/upstream/current/translate/convert/po2csv.py
    translate-toolkit/branches/upstream/current/translate/convert/po2dtd.py
    translate-toolkit/branches/upstream/current/translate/convert/po2ical.py
    translate-toolkit/branches/upstream/current/translate/convert/po2moz.py
    translate-toolkit/branches/upstream/current/translate/convert/po2php.py
    translate-toolkit/branches/upstream/current/translate/convert/po2rc.py
    translate-toolkit/branches/upstream/current/translate/convert/po2symb.py
    translate-toolkit/branches/upstream/current/translate/convert/pot2po.py
    translate-toolkit/branches/upstream/current/translate/convert/prop2mozfunny.py
    translate-toolkit/branches/upstream/current/translate/convert/prop2po.py
    translate-toolkit/branches/upstream/current/translate/convert/rc2po.py
    translate-toolkit/branches/upstream/current/translate/convert/symb2po.py
    translate-toolkit/branches/upstream/current/translate/convert/test_convert.py
    translate-toolkit/branches/upstream/current/translate/convert/test_dtd2po.py
    translate-toolkit/branches/upstream/current/translate/convert/test_html2po.py
    translate-toolkit/branches/upstream/current/translate/convert/test_po2dtd.py
    translate-toolkit/branches/upstream/current/translate/convert/test_po2html.py
    translate-toolkit/branches/upstream/current/translate/convert/test_po2php.py
    translate-toolkit/branches/upstream/current/translate/convert/test_pot2po.py
    translate-toolkit/branches/upstream/current/translate/convert/test_prop2po.py
    translate-toolkit/branches/upstream/current/translate/convert/test_xliff2po.py
    translate-toolkit/branches/upstream/current/translate/convert/xliff2odf.py
    translate-toolkit/branches/upstream/current/translate/convert/xliff2po.py
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-contributing.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-creating_a_terminology_list_from_your_existing_translations.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-creating_mozilla_pot_files.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv2po.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv2tbx.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-developers.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-dtd.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-duplicates_duplicatestyle.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-formats.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-html.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-important_changes.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-index.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-ini2po.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-migrating_to_firefox.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-mozilla_l10n_scripts.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-odf2xliff.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-personality_type.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-php.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po2wordfast.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pocount.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-podebug.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pofilter.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pofilter_tests.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-poglossary.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pogrep.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pomerge.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-posegment.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-poterminology.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-progress_progress.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-prop2po.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-properties.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-qm.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rc.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rc2po.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rewrite_style.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-symb2po.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-tbx.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-ts.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-using_csv2po.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-using_pofilter.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-wordfast.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-xliff.html
    translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-xliff2po.html
    translate-toolkit/branches/upstream/current/translate/filters/autocorrect.py
    translate-toolkit/branches/upstream/current/translate/filters/checks.py
    translate-toolkit/branches/upstream/current/translate/filters/decoration.py
    translate-toolkit/branches/upstream/current/translate/filters/pofilter.py
    translate-toolkit/branches/upstream/current/translate/filters/spelling.py
    translate-toolkit/branches/upstream/current/translate/filters/test_checks.py
    translate-toolkit/branches/upstream/current/translate/lang/af.py
    translate-toolkit/branches/upstream/current/translate/lang/common.py
    translate-toolkit/branches/upstream/current/translate/lang/data.py
    translate-toolkit/branches/upstream/current/translate/lang/el.py
    translate-toolkit/branches/upstream/current/translate/lang/fa.py
    translate-toolkit/branches/upstream/current/translate/lang/test_common.py
    translate-toolkit/branches/upstream/current/translate/lang/test_zh.py
    translate-toolkit/branches/upstream/current/translate/lang/ur.py
    translate-toolkit/branches/upstream/current/translate/misc/file_discovery.py
    translate-toolkit/branches/upstream/current/translate/misc/multistring.py
    translate-toolkit/branches/upstream/current/translate/misc/quote.py
    translate-toolkit/branches/upstream/current/translate/misc/test_optrecurse.py
    translate-toolkit/branches/upstream/current/translate/search/indexing/PyLuceneIndexer.py
    translate-toolkit/branches/upstream/current/translate/search/indexing/XapianIndexer.py
    translate-toolkit/branches/upstream/current/translate/search/match.py
    translate-toolkit/branches/upstream/current/translate/search/terminology.py
    translate-toolkit/branches/upstream/current/translate/search/test_match.py
    translate-toolkit/branches/upstream/current/translate/search/test_terminology.py
    translate-toolkit/branches/upstream/current/translate/services/tmserver.py
    translate-toolkit/branches/upstream/current/translate/storage/base.py
    translate-toolkit/branches/upstream/current/translate/storage/cpo.py
    translate-toolkit/branches/upstream/current/translate/storage/csvl10n.py
    translate-toolkit/branches/upstream/current/translate/storage/ini.py
    translate-toolkit/branches/upstream/current/translate/storage/lisa.py
    translate-toolkit/branches/upstream/current/translate/storage/php.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/__init__.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/base.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/lisa.py
    translate-toolkit/branches/upstream/current/translate/storage/placeables/test_lisa.py
    translate-toolkit/branches/upstream/current/translate/storage/pocommon.py
    translate-toolkit/branches/upstream/current/translate/storage/poheader.py
    translate-toolkit/branches/upstream/current/translate/storage/poparser.py
    translate-toolkit/branches/upstream/current/translate/storage/poxliff.py
    translate-toolkit/branches/upstream/current/translate/storage/properties.py
    translate-toolkit/branches/upstream/current/translate/storage/pypo.py
    translate-toolkit/branches/upstream/current/translate/storage/qm.py
    translate-toolkit/branches/upstream/current/translate/storage/qph.py
    translate-toolkit/branches/upstream/current/translate/storage/rc.py
    translate-toolkit/branches/upstream/current/translate/storage/statsdb.py
    translate-toolkit/branches/upstream/current/translate/storage/tbx.py
    translate-toolkit/branches/upstream/current/translate/storage/test_base.py
    translate-toolkit/branches/upstream/current/translate/storage/test_cpo.py
    translate-toolkit/branches/upstream/current/translate/storage/test_dtd.py
    translate-toolkit/branches/upstream/current/translate/storage/test_monolingual.py
    translate-toolkit/branches/upstream/current/translate/storage/test_po.py
    translate-toolkit/branches/upstream/current/translate/storage/test_poheader.py
    translate-toolkit/branches/upstream/current/translate/storage/test_properties.py
    translate-toolkit/branches/upstream/current/translate/storage/test_pypo.py
    translate-toolkit/branches/upstream/current/translate/storage/test_tmx.py
    translate-toolkit/branches/upstream/current/translate/storage/test_ts2.py
    translate-toolkit/branches/upstream/current/translate/storage/test_wordfast.py
    translate-toolkit/branches/upstream/current/translate/storage/test_xliff.py
    translate-toolkit/branches/upstream/current/translate/storage/tmdb.py
    translate-toolkit/branches/upstream/current/translate/storage/tmx.py
    translate-toolkit/branches/upstream/current/translate/storage/ts2.py
    translate-toolkit/branches/upstream/current/translate/storage/versioncontrol/__init__.py
    translate-toolkit/branches/upstream/current/translate/storage/wordfast.py
    translate-toolkit/branches/upstream/current/translate/storage/xliff.py
    translate-toolkit/branches/upstream/current/translate/storage/xml_extract/extract.py
    translate-toolkit/branches/upstream/current/translate/storage/xml_extract/misc.py
    translate-toolkit/branches/upstream/current/translate/tools/build_tmdb.py
    translate-toolkit/branches/upstream/current/translate/tools/pocount.py
    translate-toolkit/branches/upstream/current/translate/tools/podebug.py
    translate-toolkit/branches/upstream/current/translate/tools/pomerge.py
    translate-toolkit/branches/upstream/current/translate/tools/posegment.py
    translate-toolkit/branches/upstream/current/translate/tools/pretranslate.py
    translate-toolkit/branches/upstream/current/translate/tools/test_podebug.py
    translate-toolkit/branches/upstream/current/translate/tools/test_pomerge.py

Modified: translate-toolkit/branches/upstream/current/PKG-INFO
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/PKG-INFO?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/PKG-INFO (original)
+++ translate-toolkit/branches/upstream/current/PKG-INFO Fri Jul 24 16:25:46 2009
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: translate-toolkit
-Version: 1.3.0
+Version: 1.4.0-rc1
 Summary: The Translate Toolkit is a Python package that assists in localization of software.
 Home-page: http://translate.sourceforge.net/wiki/toolkit/index
 Author: Translate.org.za

Modified: translate-toolkit/branches/upstream/current/setup.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/setup.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/setup.py (original)
+++ translate-toolkit/branches/upstream/current/setup.py Fri Jul 24 16:25:46 2009
@@ -29,10 +29,21 @@
              [join('translate',filename) for filename in 'ChangeLog', 'COPYING', 'LICENSE', 'README'])]
 initfiles = [(join(sitepackages,'translate'),[join('translate','__init__.py')])]
 
-subpackages = ["convert", "misc", "storage", join("storage", "versioncontrol"), 
-        join("storage", "xml_extract"), join("storage", "placeables"),
-        "filters", "tools", "services", "search", join("search", "indexing"), 
-        "lang", join("misc", "typecheck")]
+subpackages = [
+        "convert",
+        "filters",
+        "lang",
+        "misc",
+        join("misc", "typecheck"),
+        "storage",
+        join("storage", "placeables"),
+        join("storage", "versioncontrol"),
+        join("storage", "xml_extract"),
+        "search",
+        join("search", "indexing"),
+        "services",
+        "tools",
+        ]
 # TODO: elementtree doesn't work in sdist, fix this
 packages = ["translate"]
 
@@ -52,11 +63,13 @@
                   ('convert', 'php2po'), ('convert', 'po2php'),
                   ('convert', 'rc2po'), ('convert', 'po2rc'),
                   ('convert', 'xliff2po'), ('convert', 'po2xliff'),
+                  ('convert', 'sub2po'), ('convert', 'po2sub'),
                   ('convert', 'symb2po'), ('convert', 'po2symb'),
                   ('convert', 'po2tmx'),
                   ('convert', 'po2wordfast'),
                   ('convert', 'csv2tbx'),
                   ('convert', 'odf2xliff'), ('convert', 'xliff2odf'),
+                  ('convert', 'web2py2po'), ('convert', 'po2web2py'),
                   ('filters', 'pofilter'),
                   ('tools', 'pocompile'),
                   ('tools', 'poconflicts'),

Modified: translate-toolkit/branches/upstream/current/tools/pomigrate2
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/tools/pomigrate2?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/tools/pomigrate2 (original)
+++ translate-toolkit/branches/upstream/current/tools/pomigrate2 Fri Jul 24 16:25:46 2009
@@ -126,7 +126,10 @@
 
 if [ "$option_use_compendium" != "" ]; then
 	echo "** Creating compendium from old files... **"
-	compendium=`mktemp tmp.XXXXXXXXXX`.po
+	compendium=`mktemp tmp.compendium.XXXXXXXXXX`
+	# Move and rename to work around inability of mktemp TEMPLATE to end on anything but X's
+        mv $compendium ${compendium}.po
+        compendium=${compendium}.po
 	`dirname $0`/pocompendium --correct $compendium -d $old
 	option_use_compendium=" --compendium=$compendium "
 	option_pot2po_use_compendium=" --tm=$compendium "

Modified: translate-toolkit/branches/upstream/current/translate/README
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/README?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/README (original)
+++ translate-toolkit/branches/upstream/current/translate/README Fri Jul 24 16:25:46 2009
@@ -76,11 +76,23 @@
 reporting it as a bug.
 
 The package lxml is needed for XML file processing. Version 1.3.4 and upwards 
-should work, but lxml 2.1.0 or later is recommended.
+should work, but lxml 2.1.0 or later is strongly recommended.
 http://codespeak.net/lxml/
+Depending on your platform, the easiest way to install might be through your
+system's package management. Alternatively you can try
+  easy_install lxml
+which should install the newest version from the web. See the easy_install
+documentation for more details on how to force installation of a certain
+version, or to specify upgrade options, etc.
+
+For Mac OSX, the following pages might be of help:
+http://codespeak.net/lxml/build.html#providing-newer-library-versions-on-mac-os-x
+http://codespeak.net/lxml/installation.html#macos-x
 
 The package lxml has dependencies on libxml2 and libxslt. Please check the lxml
-site for the recommended versions of these libraries.
+site for the recommended versions of these libraries if you need to install
+them separately at all. Most packaged versions of lxml will already contain
+these dependencies.
 
 Python 2.5 includes pysqlite, but pysqlite2 needs to be installed if you are 
 using an older version of Python.
@@ -118,9 +130,16 @@
 http://packages.debian.org/unstable/source/iso-codes
 
 The package vobject is needed for ical2po and po2ical.  Versions from
-0.6.0 have been tested, 0.6.5 is required to fix a Lotus Notes related
-calendars.
+0.6.0 have been tested, 0.6.5 is required to fix an issue related to
+Lotus Notes calendars.
 http://vobject.skyhouseconsulting.com/
+
+The subtitle editing program Gaupol is needed for sub2po and
+po2sub. Some Unicode encoded files (including most files from
+http://dotsub.com) require latest development version of Gaupol.
+http://home.gna.org/gaupol/
+You will also need the 'Universal Encoding Detector'
+http://chardet.feedparser.org/
 
 The programs have been tested on Linux and Windows.
 
@@ -167,7 +186,7 @@
   http://translate.sourceforge.net/wiki/developers/reporting_bugs
 
 Documentation
------------
+-------------
 Please read our documentation online at 
   http://translate.sourceforge.net/wiki/toolkit/index
 There they are constantly being updated. Please feel free to contribute new 
@@ -205,6 +224,7 @@
 csv2tbx  - Create TBX (TermBase eXchange) files from Comma Separated Value (CSV) files
 ini2po   - convert .ini files to to PO
 ical2po  - Convert iCalendar files (*.ics) to PO
+sub2po   - Convert many subtitle files to PO
 
 * Tools (Quality Assurance)
 pofilter - run any of the 40+ checks on your PO files
@@ -223,6 +243,6 @@
             for creating a segmented translation memory.
 poswap    - uses a translation of another language that you would rather use 
             than English as source language
-poterminology - analise PO or POT files to build a list of frequently occuring
+poterminology - analyse PO or POT files to build a list of frequently occurring
                 words and phrases
 

Modified: translate-toolkit/branches/upstream/current/translate/__version__.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/__version__.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/__version__.py (original)
+++ translate-toolkit/branches/upstream/current/translate/__version__.py Fri Jul 24 16:25:46 2009
@@ -20,6 +20,6 @@
 
 """This file contains the version of the Translate Toolkit."""
 
-build = 12001
-sver = "1.3.0"
-ver = (1, 3, 0)
+build = 12002
+sver = "1.4.0-rc1"
+ver = (1, 4, 0)

Modified: translate-toolkit/branches/upstream/current/translate/convert/accesskey.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/accesskey.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/accesskey.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/accesskey.py Fri Jul 24 16:25:46 2009
@@ -21,10 +21,12 @@
 
 """functions used to manipulate access keys in strings"""
 
+from translate.storage.placeables.general import XMLEntityPlaceable
+
 DEFAULT_ACCESSKEY_MARKER = u"&"
 
 def extract(string, accesskey_marker=DEFAULT_ACCESSKEY_MARKER):
-    """Extract the label and accesskey form a label+accesskey string
+    """Extract the label and accesskey from a label+accesskey string
 
     The function will also try to ignore &entities; which would obviously not
     contain accesskeys.
@@ -46,10 +48,8 @@
         marker_pos = string.find(accesskey_marker, marker_pos)
         if marker_pos != -1:
             marker_pos += 1
-            semicolon_pos = string.find(";", marker_pos)
-            if semicolon_pos != -1:
-                if string[marker_pos:semicolon_pos].isalnum():
-                    continue
+            if accesskey_marker == '&' and XMLEntityPlaceable.regex.match(string[marker_pos-1:]):
+                continue
             label = string[:marker_pos-1] + string[marker_pos:]
             accesskey = string[marker_pos]
             break
@@ -59,8 +59,8 @@
             accesskey_marker=DEFAULT_ACCESSKEY_MARKER):
     """Combine a label and and accesskey to form a label+accesskey string
 
-    We place an accesskey marker before the accesskey in the label and this create a string
-    with the two combined e.g. "File" + "F" = "&File"
+    We place an accesskey marker before the accesskey in the label and this creates a 
+    string with the two combined e.g. "File" + "F" = "&File"
 
     @type label: unicode
     @param label: a label

Modified: translate-toolkit/branches/upstream/current/translate/convert/moz2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/moz2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/moz2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/moz2po.py Fri Jul 24 16:25:46 2009
@@ -27,7 +27,6 @@
 
 from translate.convert import dtd2po
 from translate.convert import prop2po
-from translate.convert import html2po
 from translate.convert import mozfunny2prop
 from translate.storage import xpi
 from translate.convert import convert
@@ -37,7 +36,7 @@
             ("*", "*"): ("*", convert.copyinput),
             "*": ("*", convert.copyinput)}
     # handle formats that convert to .po files
-    converters = [("dtd", dtd2po.convertdtd), ("properties", prop2po.convertprop), ("xhtml", html2po.converthtml), ("html", html2po.converthtml),
+    converters = [("dtd", dtd2po.convertdtd), ("properties", prop2po.convertmozillaprop),
             ("it", mozfunny2prop.it2po), ("ini", mozfunny2prop.ini2po), ("inc", mozfunny2prop.inc2po)]
     for format, converter in converters:
         formats[(format, format)] = (format + ".po", converter)

Modified: translate-toolkit/branches/upstream/current/translate/convert/mozfunny2prop.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/mozfunny2prop.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/mozfunny2prop.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/mozfunny2prop.py Fri Jul 24 16:25:46 2009
@@ -25,15 +25,6 @@
 from translate.misc import quote
 from translate.convert import prop2po
 from translate.misc.wStringIO import StringIO
-
-def encodepropline(line):
-    """helper which strips off any end of line, encodes for properties file, and adds on the end of line"""
-    strippedline = line.rstrip("\n")
-    if line == strippedline:
-        ending = ""
-    else:
-        ending = line[len(strippedline)-len(line):]
-    return quote.mozillapropertiesencode(strippedline) + ending
 
 def inc2prop(lines):
     """convert a .inc file with #defines in it to a properties file"""
@@ -86,36 +77,36 @@
     hashstarts = len([line for line in lines if line.startswith("#")])
     if hashstarts:
         for line in inc2prop(lines):
-            yield encodepropline(line)
+            yield line
     else:
         for line in it2prop(lines, encoding=itencoding):
-            yield encodepropline(line)
+            yield line
 
 def inc2po(inputfile, outputfile, templatefile, encoding=None, pot=False, duplicatestyle="msgctxt"):
     """wraps prop2po but converts input/template files to properties first"""
     inputlines = inputfile.readlines()
-    inputproplines = [encodepropline(line) for line in inc2prop(inputlines)]
+    inputproplines = [line for line in inc2prop(inputlines)]
     inputpropfile = StringIO("".join(inputproplines))
     if templatefile is not None:
         templatelines = templatefile.readlines()
-        templateproplines = [encodepropline(line) for line in inc2prop(templatelines)]
+        templateproplines = [line for line in inc2prop(templatelines)]
         templatepropfile = StringIO("".join(templateproplines))
     else:
         templatepropfile = None
-    return prop2po.convertprop(inputpropfile, outputfile, templatepropfile, pot=pot, duplicatestyle=duplicatestyle)
+    return prop2po.convertprop(inputpropfile, outputfile, templatepropfile, personality="mozilla", pot=pot, duplicatestyle=duplicatestyle)
 
 def it2po(inputfile, outputfile, templatefile, encoding="cp1252", pot=False, duplicatestyle="msgctxt"):
     """wraps prop2po but converts input/template files to properties first"""
     inputlines = inputfile.readlines()
-    inputproplines = [encodepropline(line) for line in it2prop(inputlines, encoding=encoding)]
+    inputproplines = [line for line in it2prop(inputlines, encoding=encoding)]
     inputpropfile = StringIO("".join(inputproplines))
     if templatefile is not None:
         templatelines = templatefile.readlines()
-        templateproplines = [encodepropline(line) for line in it2prop(templatelines, encoding=encoding)]
+        templateproplines = [line for line in it2prop(templatelines, encoding=encoding)]
         templatepropfile = StringIO("".join(templateproplines))
     else:
         templatepropfile = None
-    return prop2po.convertprop(inputpropfile, outputfile, templatepropfile, pot=pot, duplicatestyle=duplicatestyle)
+    return prop2po.convertprop(inputpropfile, outputfile, templatepropfile, personality="mozilla", pot=pot, duplicatestyle=duplicatestyle)
 
 def ini2po(inputfile, outputfile, templatefile, encoding="UTF-8", pot=False, duplicatestyle="msgctxt"):
     return it2po(inputfile=inputfile, outputfile=outputfile, templatefile=templatefile, encoding=encoding, pot=pot, duplicatestyle=duplicatestyle)

Modified: translate-toolkit/branches/upstream/current/translate/convert/odf2xliff.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/odf2xliff.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/odf2xliff.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/odf2xliff.py Fri Jul 24 16:25:46 2009
@@ -70,6 +70,10 @@
     @contextmanager
     def store_context():
         store = factory.getobject(outputfile)
+        try:
+            store.setfilename(store.getfilenode('NoName'), inputfile.name)
+        except:
+            print "couldn't set origin filename"
         yield store
         store.save()
 
@@ -78,7 +82,12 @@
             translate_toolkit_implementation(store)
         else:
             itools_implementation(store)
-    
+
+    # Since the convertoptionsparser will give us an open file, we risk that
+    # it could have been opened in non-binary mode on Windows, and then we'll
+    # have problems, so let's make sure we have what we want.
+    inputfile.close()
+    inputfile = file(inputfile.name, mode='rb')
     with_(store_context(), with_block)
     return True
 

Modified: translate-toolkit/branches/upstream/current/translate/convert/po2csv.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2csv.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2csv.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2csv.py Fri Jul 24 16:25:46 2009
@@ -42,8 +42,8 @@
             return None
         else:
             csvunit.comment = self.convertcomments(inputunit)
-            csvunit.source = inputunit.source.strings[0]
-            csvunit.target = inputunit.target.strings[0]
+            csvunit.source = inputunit.source
+            csvunit.target = inputunit.target
         return csvunit
 
     def convertplurals(self, inputunit):

Modified: translate-toolkit/branches/upstream/current/translate/convert/po2dtd.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2dtd.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2dtd.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2dtd.py Fri Jul 24 16:25:46 2009
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 # 
-# Copyright 2002-2008 Zuza Software Foundation
+# Copyright 2002-2009 Zuza Software Foundation
 # 
 # This file is part of translate.
 #
@@ -65,10 +65,14 @@
                         warnings.warn("Could not find accesskey for %s" % entity)
                     else:
                         original = dtd.unquotefromdtd(dtdunit.definition)
-                        if original.isupper() and unquotedstr.islower():
-                            unquotedstr = unquotedstr.upper()
-                        elif original.islower() and unquotedstr.isupper():
-                            unquotedstr = unquotedstr.lower()
+                        # For the sake of diffs we keep the case of the
+                        # accesskey the same if we know the translation didn't
+                        # change. Casing matters in XUL.
+                        if unquotedstr == dtdunit.source and original.lower() == unquotedstr.lower():
+                            if original.isupper():
+                                unquotedstr = unquotedstr.upper()
+                            elif original.islower():
+                                unquotedstr = unquotedstr.lower()
     if len(unquotedstr) > 0:
         dtdunit.definition = dtd.quotefordtd(dtd.removeinvalidamps(entity, unquotedstr))
 
@@ -121,7 +125,7 @@
         if msgidcomment:
             locnote = quote.unstripcomment("LOCALIZATION NOTE ("+dtdunit.entity+"): "+msgidcomment)
             dtdunit.comments.append(("locnote", locnote))
-             
+
 
     def convertstrings(self, inputunit, dtdunit):
         if inputunit.istranslated():

Modified: translate-toolkit/branches/upstream/current/translate/convert/po2ical.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2ical.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2ical.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2ical.py Fri Jul 24 16:25:46 2009
@@ -35,7 +35,10 @@
         self.makestoredict(inputstore, includefuzzy)
         for unit in self.templatestore.units:
             for location in unit.getlocations():
-                unit.target = self.inputdict[location]
+                if self.inputdict.has_key(location):
+                    unit.target = self.inputdict[location]
+                else:
+                    unit.target = unit.source
         return str(self.templatestore)
 
     def makestoredict(self, store, includefuzzy=False):

Modified: translate-toolkit/branches/upstream/current/translate/convert/po2moz.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2moz.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2moz.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2moz.py Fri Jul 24 16:25:46 2009
@@ -28,7 +28,6 @@
 import os.path
 from translate.convert import po2dtd
 from translate.convert import po2prop
-from translate.convert import po2html
 from translate.convert import prop2mozfunny
 from translate.storage import xpi
 from translate.convert import convert
@@ -66,7 +65,7 @@
         # TODO: not sure if this should be here, was in po2moz
         d, n = os.path.dirname(inputpath), os.path.basename(inputpath)
         s = n.find(".")
-        if s == '-1':
+        if s == -1:
             return (inputpath, "")
         root = os.path.join(d, n[:s])
         ext = n[s+1:]
@@ -86,8 +85,6 @@
     # handle command line options
     formats = {("dtd.po", "dtd"): ("dtd", po2dtd.convertdtd),
                ("properties.po", "properties"): ("properties", po2prop.convertmozillaprop),
-               ("xhtml.po", "xhtml"): ("xhtml", po2html.converthtml),
-               ("html.po", "html"): ("html", po2html.converthtml),
                ("it.po", "it"): ("it", prop2mozfunny.po2it),
                ("ini.po", "ini"): ("ini", prop2mozfunny.po2ini),
                ("inc.po", "inc"): ("inc", prop2mozfunny.po2inc),

Modified: translate-toolkit/branches/upstream/current/translate/convert/po2php.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2php.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2php.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2php.py Fri Jul 24 16:25:46 2009
@@ -58,6 +58,7 @@
                     self.inputdict[location] = inputstring
 
     def convertline(self, line):
+        line = unicode(line, 'utf-8')
         returnline = ""
         # handle multiline msgid if we're in one
         if self.inmultilinemsgid:
@@ -84,7 +85,7 @@
                 key = line[:equalspos].strip()
                 lookupkey = key.replace(" ", "")
                 # Calculate space around the equal sign
-                prespace = line.lstrip()[line.lstrip().find(']')+1:equalspos]
+                prespace = line[len(line[:equalspos].rstrip()):equalspos]
                 postspacestart = len(line[equalspos+1:])
                 postspaceend = len(line[equalspos+1:].lstrip())
                 postspace = line[equalspos+1:equalspos+(postspacestart-postspaceend)+1]

Modified: translate-toolkit/branches/upstream/current/translate/convert/po2rc.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2rc.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2rc.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2rc.py Fri Jul 24 16:25:46 2009
@@ -1,36 +1,31 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2002-2006 Zuza Software Foundation
-# 
-# This file is part of translate.
 #
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2002-2006,2008-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
+"""Convert Gettext PO localization files back to Windows Resource (.rc) files
 
-"""convert Gettext PO localization files to Windows Resource (.rc) files
-
-see: http://translate.sourceforge.net/wiki/toolkit/po2rc for examples and 
-usage instructions
+See: http://translate.sourceforge.net/wiki/toolkit/po2rc for examples and
+usage instructions.
 """
 
-from translate.misc import quote
 from translate.storage import po
 from translate.storage import rc
-
-eol = "\n"
 
 class rerc:
     def __init__(self, templatefile, charset="utf-8", lang=None, sublang=None):
@@ -59,7 +54,7 @@
                     rcstring = unit.target
                     if len(rcstring.strip()) == 0:
                         rcstring = unit.source
-                    self.inputdict[location] = rc.escape_to_rc(rcstring)
+                    self.inputdict[location] = rc.escape_to_rc(rcstring).encode(self.charset)
 
     def convertblock(self, block):
         newblock = block
@@ -111,4 +106,3 @@
 
 if __name__ == '__main__':
     main()
-

Added: translate-toolkit/branches/upstream/current/translate/convert/po2sub
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2sub?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2sub (added)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2sub Fri Jul 24 16:25:46 2009
@@ -1,0 +1,27 @@
+#!/usr/bin/env python
+# 
+# Copyright 2008 Zuza Software Foundation
+# 
+# This file is part of translate.
+#
+# translate is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# translate is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with translate; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""simple script to convert a gettext .po localization file to a supported subtitle file"""
+
+from translate.convert import po2sub
+
+if __name__ == '__main__':
+    po2sub.main()
+

Propchange: translate-toolkit/branches/upstream/current/translate/convert/po2sub
------------------------------------------------------------------------------
    svn:executable = *

Added: translate-toolkit/branches/upstream/current/translate/convert/po2sub.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2sub.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2sub.py (added)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2sub.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,75 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# 
+# Copyright 2008-2009 Zuza Software Foundation
+# 
+# This file is part of translate.
+#
+# translate is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# translate is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with translate; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+"""Convert Gettext PO localization files to subtitle files"""
+
+from translate.storage import factory
+from translate.storage import subtitles
+
+class resub:
+    def __init__(self, templatefile):
+        self.templatefile = templatefile
+        self.templatestore = subtitles.SubtitleFile(templatefile)
+        self._inputdict = {}
+
+    def convertstore(self, inputstore, includefuzzy=False):
+        self._makestoredict(inputstore, includefuzzy)
+        for unit in self.templatestore.units:
+            for location in unit.getlocations():
+                if location in self._inputdict:
+                    unit.target = self._inputdict[location]
+                else:
+                    unit.target = unit.source
+        return str(self.templatestore)
+
+    def _makestoredict(self, store, includefuzzy=False):
+        # make a dictionary of the translations
+        for unit in store.units:
+            if includefuzzy or not unit.isfuzzy():
+                # there may be more than one entity due to msguniq merge
+                for location in unit.getlocations():
+                    substring = unit.target
+                    if len(substring.strip()) == 0:
+                        substring = unit.source
+                    self._inputdict[location] = substring
+
+def convertsub(inputfile, outputfile, templatefile, includefuzzy=False):
+    inputstore = factory.getobject(inputfile)
+    if templatefile is None:
+        raise ValueError("must have template file for subtitle files")
+    else:
+        convertor = resub(templatefile)
+    outputstring = convertor.convertstore(inputstore, includefuzzy)
+    outputfile.write(outputstring)
+    return 1
+
+def main(argv=None):
+    # handle command line options
+    from translate.convert import convert
+    formats = {("po", "srt"): ("srt", convertsub)}
+    parser = convert.ConvertOptionParser(formats, usetemplates=True, description=__doc__)
+    parser.add_fuzzy_option()
+    parser.run(argv)
+
+if __name__ == '__main__':
+    main()
+

Modified: translate-toolkit/branches/upstream/current/translate/convert/po2symb.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2symb.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2symb.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2symb.py Fri Jul 24 16:25:46 2009
@@ -3,7 +3,7 @@
 #
 # Copyright 2008 Zuza Software Foundation
 #
-# This file is part of Virtaal.
+# This file is part of the Translate Toolkit.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

Added: translate-toolkit/branches/upstream/current/translate/convert/po2web2py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2web2py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2web2py (added)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2web2py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,27 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of translate.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""convert GNU/gettext PO files to web2py translation dictionaries (.py)"""
+
+from translate.convert import po2web2py
+
+if __name__ == '__main__':
+    po2web2py.main()
+

Propchange: translate-toolkit/branches/upstream/current/translate/convert/po2web2py
------------------------------------------------------------------------------
    svn:executable = *

Added: translate-toolkit/branches/upstream/current/translate/convert/po2web2py.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/po2web2py.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/po2web2py.py (added)
+++ translate-toolkit/branches/upstream/current/translate/convert/po2web2py.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,70 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of translate.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# (c) 2009 Dominic König (dominic at nursix.org)
+#
+
+"""convert GNU/gettext PO files to web2py translation dictionaries (.py)"""
+
+from translate.storage import factory
+
+class po2pydict:
+    def __init__(self):
+        return
+
+    def convertstore(self, inputstore, includefuzzy):
+        from StringIO import StringIO
+        str_obj = StringIO()
+        
+        mydict = dict()
+        for unit in inputstore.units:
+            if unit.isheader():
+                continue
+            if unit.istranslated() or (includefuzzy and unit.isfuzzy()):
+                mydict[unit.source] = unit.target
+            else:
+                mydict[unit.source] = '*** ' + unit.source
+        
+        str_obj.write('{\n')
+        for source_str in mydict:
+            str_obj.write("%s:%s,\n" % (repr(str(source_str)),repr(str(mydict[source_str]))))
+        str_obj.write('}\n')
+        str_obj.seek(0)
+        return str_obj
+
+def convertpy(inputfile, outputfile, templatefile=None, includefuzzy=False):
+    inputstore = factory.getobject(inputfile)
+    convertor = po2pydict()
+    outputstring = convertor.convertstore(inputstore, includefuzzy)
+    outputfile.write(outputstring.read())
+    return 1
+
+def main(argv=None):
+    from translate.convert import convert
+    from translate.misc import stdiotell
+    import sys
+    sys.stdout = stdiotell.StdIOWrapper(sys.stdout)
+    formats = {("po", "py"):("py", convertpy), ("po"):("py", convertpy)}
+    parser = convert.ConvertOptionParser(formats, usetemplates=False, description=__doc__)
+    parser.add_fuzzy_option()
+    parser.run(argv)
+
+if __name__ == '__main__':
+    main()

Modified: translate-toolkit/branches/upstream/current/translate/convert/pot2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/pot2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/pot2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/pot2po.py Fri Jul 24 16:25:46 2009
@@ -1,28 +1,28 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2004-2007 Zuza Software Foundation
-# 
+#
+# Copyright 2004-2009 Zuza Software Foundation
+#
 # This file is part of translate.
 #
-# translate is free software; you can redistribute it and/or modify
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-"""convert Gettext PO templates (.pot) to PO localization files, preserving existing translations
-
-See: http://translate.sourceforge.net/wiki/toolkit/pot2po for examples and 
-usage instructions
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""Convert template files (like .pot or template .xlf files) translation files,
+preserving existing translations.
+
+See: http://translate.sourceforge.net/wiki/toolkit/pot2po for examples and
+usage instructions.
 """
 
 from translate.storage import factory
@@ -34,7 +34,7 @@
 
 def convertpot(input_file, output_file, template_file, tm=None, min_similarity=75, fuzzymatching=True, **kwargs):
     """Main conversion function"""
-    
+
     input_store = factory.getobject(input_file)
     template_store = None
     if template_file is not None:
@@ -51,8 +51,9 @@
 
     #prepare for merging
     output_store = type(input_store)()
-    #create fuzzy matchers to be used by pretrnaslate.pretranslate_unit
+    #create fuzzy matchers to be used by pretranslate.pretranslate_unit
     matchers = []
+    _prepare_merge(input_store, output_store, template_store)
     if fuzzymatching:
         if template_store:
             matcher = match.matcher(template_store, max_candidates=1, min_similarity=min_similarity, max_length=3000, usefuzzy=True)
@@ -62,7 +63,6 @@
             matcher = pretranslate.memory(tm, max_candidates=1, min_similarity=min_similarity, max_length=1000)
             matcher.addpercentage = False
             matchers.append(matcher)
-    _prepare_merge(input_store, output_store, template_store)
 
     #initialize store
     _store_pre_merge(input_store, output_store, template_store)
@@ -82,7 +82,7 @@
 
 ##dispatchers
 def _prepare_merge(input_store, output_store, template_store, **kwargs):
-    """prepare stores & TM matchers before merging"""       
+    """Prepare stores & TM matchers before merging."""
     #dispatch to format specific functions
     prepare_merge_hook = "_prepare_merge_%s" % input_store.__class__.__name__
     if  globals().has_key(prepare_merge_hook):
@@ -95,7 +95,7 @@
 
 
 def _store_pre_merge(input_store, output_store, template_store, **kwargs) :
-    """initialize the new file with things like headers and metadata"""
+    """Initialize the new file with things like headers and metadata."""
     #formats that implement poheader interface are a special case
     if isinstance(input_store, poheader.poheader):
         _do_poheaders(input_store, output_store, template_store)
@@ -107,25 +107,25 @@
 
 
 def _store_post_merge(input_store, output_store, template_store, **kwargs) :
-    """close file after merging all translations, used for adding
-    statistics, obselete messages and similar wrapup tasks"""
+    """Close file after merging all translations, used for adding
+    statistics, obselete messages and similar wrapup tasks."""
     #dispatch to format specific functions
     store_post_merge_hook = "_store_post_merge_%s" % input_store.__class__.__name__
     if  globals().has_key(store_post_merge_hook):
         globals()[store_post_merge_hook](input_store, output_store, template_store, **kwargs)
 
 def _unit_post_merge(input_unit, input_store, output_store, template_store, **kwargs):
-    """handle any unit level cleanup and situations not handled by the merge()
-    function"""
+    """Handle any unit level cleanup and situations not handled by the merge()
+    function."""
     #dispatch to format specific functions
     unit_post_merge_hook = "_unit_post_merge_%s" % input_unit.__class__.__name__
     if  globals().has_key(unit_post_merge_hook):
         globals()[unit_post_merge_hook](input_unit, input_store, output_store, template_store, **kwargs)
-    
+
 
 ##format specific functions
 def _prepare_merge_pofile(input_store, output_store, template_store):
-    """po format specific template preparation logic"""
+    """PO format specific template preparation logic."""
     #we need to revive obselete units to be able to consider
     #their translation when matching
     if template_store:
@@ -135,7 +135,7 @@
 
 
 def _unit_post_merge_pounit(input_unit, input_store, output_store, template_store):
-    """po format specific plural string initializtion logic"""
+    """PO format specific plural string initializtion logic."""
     #FIXME: do we want to do that for poxliff also?
     if input_unit.hasplural() and len(input_unit.target) == 0:
         # untranslated plural unit; Let's ensure that we have the correct number of plural forms:
@@ -145,7 +145,7 @@
 
 
 def _store_post_merge_pofile(input_store, output_store, template_store):
-    """po format specific, adds newly obseleted messages to end of store"""
+    """PO format specific: adds newly obseleted messages to end of store."""
     #Let's take care of obsoleted messages
     if template_store:
         newlyobsoleted = []
@@ -163,7 +163,7 @@
 
 
 def _do_poheaders(input_store, output_store, template_store):
-    """adds initialized ph headers to output store"""
+    """Adds initialized PO headers to output store."""
     # header values
     charset = "UTF-8"
     encoding = "8bit"
@@ -176,7 +176,7 @@
     plural_forms = None
     kwargs = {}
 
-    if template_store is not None:
+    if template_store is not None and isinstance(template_store, poheader.poheader):
         templateheadervalues = template_store.parseheader()
         for key, value in templateheadervalues.iteritems():
             if key == "Project-Id-Version":
@@ -210,11 +210,11 @@
             mime_version = value
         else:
             kwargs[key] = value
-            
+
     output_header = output_store.makeheader(charset=charset, encoding=encoding, project_id_version=project_id_version,
         pot_creation_date=pot_creation_date, po_revision_date=po_revision_date, last_translator=last_translator,
         language_team=language_team, mime_version=mime_version, plural_forms=plural_forms, **kwargs)
-    
+
     # Get the header comments and fuzziness state
     if template_store is not None and len(template_store.units) > 0:
         if template_store.units[0].isheader():
@@ -225,7 +225,7 @@
             output_header.markfuzzy(template_store.units[0].isfuzzy())
     elif len(input_store.units) > 0 and input_store.units[0].isheader():
         output_header.addnote(input_store.units[0].getnotes())
-        
+
     output_store.addunit(output_header)
 
 

Modified: translate-toolkit/branches/upstream/current/translate/convert/prop2mozfunny.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/prop2mozfunny.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/prop2mozfunny.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/prop2mozfunny.py Fri Jul 24 16:25:46 2009
@@ -56,11 +56,11 @@
             if comment.startswith("# converted from") and "pseudo-properties" in comment:
                 pass
             elif comment.startswith("# section: "):
-                yield comment.replace("# section: ", "", 1)
+                yield comment.replace("# section: ", "", 1) + "\n"
             else:
-                yield comment.replace("#", ";", 1)
+                yield comment.replace("#", ";", 1) + "\n"
         if unit.isblank():
-            yield "\n"
+            yield ""
         else:
             definition = "%s=%s\n" % (unit.name, unit.value)
             if isinstance(definition, unicode):
@@ -79,7 +79,7 @@
         lines = lines[1:]
     if not (waspseudoprops ^ wasdefines):
         raise ValueError("could not determine file type as pseudo-properties or defines file")
-    pf = properties.propfile()
+    pf = properties.propfile(personality="mozilla")
     pf.parse("\n".join(lines))
     if wasdefines:
         for line in prop2inc(pf):
@@ -93,14 +93,14 @@
     outputpropfile = StringIO()
     if templatefile is not None:
         templatelines = templatefile.readlines()
-        templateproplines = [mozfunny2prop.encodepropline(line) for line in mozfunny2prop.inc2prop(templatelines)]
+        templateproplines = [line for line in mozfunny2prop.inc2prop(templatelines)]
         templatepropfile = StringIO("".join(templateproplines))
     else:
         templatepropfile = None
     result = po2prop.convertmozillaprop(inputfile, outputpropfile, templatepropfile, includefuzzy=includefuzzy)
     if result:
         outputpropfile.seek(0)
-        pf = properties.propfile(outputpropfile)
+        pf = properties.propfile(outputpropfile, personality="mozilla")
         outputlines = prop2inc(pf)
         outputfile.writelines(outputlines)
     return result
@@ -110,14 +110,14 @@
     outputpropfile = StringIO()
     if templatefile is not None:
         templatelines = templatefile.readlines()
-        templateproplines = [mozfunny2prop.encodepropline(line) for line in mozfunny2prop.it2prop(templatelines, encoding=encoding)]
+        templateproplines = [line for line in mozfunny2prop.it2prop(templatelines, encoding=encoding)]
         templatepropfile = StringIO("".join(templateproplines))
     else:
         templatepropfile = None
     result = po2prop.convertmozillaprop(inputfile, outputpropfile, templatepropfile, includefuzzy=includefuzzy)
     if result:
         outputpropfile.seek(0)
-        pf = properties.propfile(outputpropfile)
+        pf = properties.propfile(outputpropfile, personality="mozilla")
         outputlines = prop2it(pf)
         for line in outputlines:
             line = line.decode("utf-8").encode(encoding)

Modified: translate-toolkit/branches/upstream/current/translate/convert/prop2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/prop2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/prop2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/prop2po.py Fri Jul 24 16:25:46 2009
@@ -31,10 +31,14 @@
 
 class prop2po:
     """convert a .properties file to a .po file for handling the translation..."""
-    def convertstore(self, thepropfile, duplicatestyle="msgctxt"):
+    def convertstore(self, thepropfile, personality="java", duplicatestyle="msgctxt"):
         """converts a .properties file to a .po file..."""
+        self.personality = personality
         thetargetfile = po.pofile()
-        targetheader = thetargetfile.makeheader(charset="UTF-8", encoding="8bit", x_accelerator_marker="&")
+        if self.personality == "mozilla":
+            targetheader = thetargetfile.makeheader(charset="UTF-8", encoding="8bit", x_accelerator_marker="&")
+        else:
+            targetheader = thetargetfile.makeheader(charset="UTF-8", encoding="8bit")
         targetheader.addnote("extracted from %s" % thepropfile.filename, "developer")
         # we try and merge the header po with any comments at the start of the properties file
         appendedheader = False
@@ -59,10 +63,14 @@
         thetargetfile.removeduplicates(duplicatestyle)
         return thetargetfile
 
-    def mergestore(self, origpropfile, translatedpropfile, blankmsgstr=False, duplicatestyle="msgctxt"):
+    def mergestore(self, origpropfile, translatedpropfile, personality="java", blankmsgstr=False, duplicatestyle="msgctxt"):
         """converts two .properties files to a .po file..."""
+        self.personality = personality
         thetargetfile = po.pofile()
-        targetheader = thetargetfile.makeheader(charset="UTF-8", encoding="8bit")
+        if self.personality == "mozilla":
+            targetheader = thetargetfile.makeheader(charset="UTF-8", encoding="8bit", x_accelerator_marker="&")
+        else:
+            targetheader = thetargetfile.makeheader(charset="UTF-8", encoding="8bit")
         targetheader.addnote("extracted from %s, %s" % (origpropfile.filename, translatedpropfile.filename), "developer")
         translatedpropfile.makeindex()
         # we try and merge the header po with any comments at the start of the properties file
@@ -96,7 +104,7 @@
             if origpo is not None:
                 if translatedpo is not None and not blankmsgstr:
                     origpo.target = translatedpo.source
-                origpo.addnote("".join(waitingcomments).rstrip(), "developer", position="prepend")
+                origpo.addnote(u"".join(waitingcomments).rstrip(), "developer", position="prepend")
                 waitingcomments = []
                 thetargetfile.addunit(origpo)
             elif translatedpo is not None:
@@ -115,24 +123,28 @@
             for comment in propunit.comments:
                 if "DONT_TRANSLATE" in comment:
                     return "discard"
-            pounit.addnote("".join(propunit.comments).rstrip(), commenttype)
+            pounit.addnote(u"".join(propunit.getnotes()).rstrip(), commenttype)
         # TODO: handle multiline msgid
         if propunit.isblank():
             return None
         pounit.addlocation(propunit.name)
         pounit.source = propunit.source
-        pounit.target = ""
+        pounit.target = u""
         return pounit
 
-def convertprop(inputfile, outputfile, templatefile, pot=False, duplicatestyle="msgctxt"):
+def convertmozillaprop(inputfile, outputfile, templatefile, pot=False, duplicatestyle="msgctxt"):
+    """Mozilla specific convertor function"""
+    return convertprop(inputfile, outputfile, templatefile, personality="mozilla", pot=pot, duplicatestyle=duplicatestyle)
+
+def convertprop(inputfile, outputfile, templatefile, personality="java", pot=False, duplicatestyle="msgctxt"):
     """reads in inputfile using properties, converts using prop2po, writes to outputfile"""
-    inputstore = properties.propfile(inputfile)
+    inputstore = properties.propfile(inputfile, personality)
     convertor = prop2po()
     if templatefile is None:
-        outputstore = convertor.convertstore(inputstore, duplicatestyle=duplicatestyle)
+        outputstore = convertor.convertstore(inputstore, personality, duplicatestyle=duplicatestyle)
     else:
-        templatestore = properties.propfile(templatefile)
-        outputstore = convertor.mergestore(templatestore, inputstore, blankmsgstr=pot, duplicatestyle=duplicatestyle)
+        templatestore = properties.propfile(templatefile, personality)
+        outputstore = convertor.mergestore(templatestore, inputstore, personality, blankmsgstr=pot, duplicatestyle=duplicatestyle)
     if outputstore.isempty():
         return 0
     outputfile.write(str(outputstore))
@@ -142,8 +154,12 @@
     from translate.convert import convert
     formats = {"properties": ("po", convertprop), ("properties", "properties"): ("po", convertprop)}
     parser = convert.ConvertOptionParser(formats, usetemplates=True, usepots=True, description=__doc__)
+    parser.add_option("", "--personality", dest="personality", default="java", type="choice",
+            choices=["java", "mozilla"],
+            help="set the input behaviour: java (default), mozilla", metavar="TYPE")
     parser.add_duplicates_option()
     parser.passthrough.append("pot")
+    parser.passthrough.append("personality")
     parser.run(argv)
 
 if __name__ == '__main__':

Modified: translate-toolkit/branches/upstream/current/translate/convert/rc2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/rc2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/rc2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/rc2po.py Fri Jul 24 16:25:46 2009
@@ -1,23 +1,22 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2007-2008 Zuza Software Foundation
-# 
-# This file is part of translate.
 #
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2007-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """convert .rc files to Gettext PO localization files"""
 
@@ -26,7 +25,7 @@
 from translate.storage import rc
 
 class rc2po:
-    """convert a .rc file to a .po file for handling the translation..."""
+    """Convert a .rc file to a .po file for handling the translation."""
     def __init__(self, charset=None):
         self.charset = charset
 
@@ -81,14 +80,14 @@
         output_unit.target = ""
         return output_unit
 
-def convertrc(input_file, output_file, template_file, pot=False, duplicatestyle="msgctxt", charset=None):
+def convertrc(input_file, output_file, template_file, pot=False, duplicatestyle="msgctxt", charset=None, lang=None, sublang=None):
     """reads in input_file using rc, converts using rc2po, writes to output_file"""
-    input_store = rc.rcfile(input_file)
+    input_store = rc.rcfile(input_file, lang, sublang)
     convertor = rc2po(charset=charset)
     if template_file is None:
         output_store = convertor.convert_store(input_store, duplicatestyle=duplicatestyle)
     else:
-        template_store = rc.rcfile(template_file)
+        template_store = rc.rcfile(template_file, lang, sublang)
         output_store = convertor.merge_store(template_store, input_store, blankmsgstr=pot, duplicatestyle=duplicatestyle)
     if output_store.isempty():
         return 0
@@ -97,17 +96,24 @@
 
 def main(argv=None):
     from translate.convert import convert
-    formats = {"rc": ("po", convertrc), ("rc", "rc"): ("po", convertrc), 
+    formats = {"rc": ("po", convertrc), ("rc", "rc"): ("po", convertrc),
                "nls": ("po", convertrc), ("nls", "nls"): ("po", convertrc)}
     parser = convert.ConvertOptionParser(formats, usetemplates=True, usepots=True, description=__doc__)
     DEFAULTCHARSET = "cp1252"
     parser.add_option("", "--charset", dest="charset", default=DEFAULTCHARSET,
         help="charset to use to decode the RC files (default: %s)" % DEFAULTCHARSET, metavar="CHARSET")
+    DEFAULTLANG = "LANG_ENGLISH"
+    parser.add_option("-l", "--lang", dest="lang", default=DEFAULTLANG,
+        help="LANG entry (default: %s)" % DEFAULTLANG, metavar="LANG")
+    DEFAULTSUBLANG = "SUBLANG_DEFAULT"
+    parser.add_option("", "--sublang", dest="sublang", default=DEFAULTSUBLANG,
+        help="SUBLANG entry (default: %s)" % DEFAULTSUBLANG, metavar="SUBLANG")
     parser.add_duplicates_option()
     parser.passthrough.append("pot")
     parser.passthrough.append("charset")
+    parser.passthrough.append("lang")
+    parser.passthrough.append("sublang")
     parser.run(argv)
 
 if __name__ == '__main__':
     main()
-

Added: translate-toolkit/branches/upstream/current/translate/convert/sub2po
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/sub2po?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/sub2po (added)
+++ translate-toolkit/branches/upstream/current/translate/convert/sub2po Fri Jul 24 16:25:46 2009
@@ -1,0 +1,27 @@
+#!/usr/bin/env python
+# 
+# Copyright 2008 Zuza Software Foundation
+# 
+# This file is part of translate.
+#
+# translate is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# translate is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with translate; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""simple script to convert a supported subtitle file to a Gettext PO localization file"""
+
+from translate.convert import sub2po
+
+if __name__ == '__main__':
+    sub2po.main()
+

Propchange: translate-toolkit/branches/upstream/current/translate/convert/sub2po
------------------------------------------------------------------------------
    svn:executable = *

Added: translate-toolkit/branches/upstream/current/translate/convert/sub2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/sub2po.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/sub2po.py (added)
+++ translate-toolkit/branches/upstream/current/translate/convert/sub2po.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,102 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# 
+# Copyright 2008-2009 Zuza Software Foundation
+# 
+# This file is part of translate.
+#
+# translate is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# translate is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with translate; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""convert subtitle files to Gettext PO localization files"""
+
+import sys
+from translate.storage import po
+from translate.storage import subtitles
+
+def convert_store(input_store, duplicatestyle="msgctxt"):
+    """converts a subtitle file to a .po file..."""
+    output_store = po.pofile()
+    output_header = output_store.makeheader(charset="UTF-8", encoding="8bit")
+    output_header.addnote("extracted from %s" % input_store.filename, "developer")
+    output_store.addunit(output_header)
+    for input_unit in input_store.units:
+        output_unit = convert_unit(input_unit, "developer")
+        if output_unit is not None:
+            output_store.addunit(output_unit)
+    output_store.removeduplicates(duplicatestyle)
+    return output_store
+
+def merge_store(template_store, input_store, blankmsgstr=False, duplicatestyle="msgctxt"):
+    """converts two subtitle files to a .po file..."""
+    output_store = po.pofile()
+    output_header = output_store.makeheader(charset="UTF-8", encoding="8bit")
+    output_header.addnote("extracted from %s, %s" % (template_store.filename, input_store.filename), "developer")
+    output_store.addunit(output_header)
+    input_store.makeindex()
+    for template_unit in template_store.units:
+        origpo = convert_unit(template_unit, "developer")
+        # try and find a translation of the same name...
+        template_unit_name = "".join(template_unit.getlocations())
+        if template_unit_name in input_store.locationindex:
+            translatedini = input_store.locationindex[template_unit_name]
+            translatedpo = convert_unit(translatedini, "translator")
+        else:
+            translatedpo = None
+        # if we have a valid po unit, get the translation and add it...
+        if origpo is not None:
+            if translatedpo is not None and not blankmsgstr:
+                origpo.target = translatedpo.source
+            output_store.addunit(origpo)
+        elif translatedpo is not None:
+            print >> sys.stderr, "error converting original subtitle definition %s" % origini.name
+    output_store.removeduplicates(duplicatestyle)
+    return output_store
+
+def convert_unit(input_unit, commenttype):
+    """Converts a subtitle unit to a .po unit. Returns None if empty
+    or not for translation."""
+    if input_unit is None:
+        return None
+    # escape unicode
+    output_unit = po.pounit(encoding="UTF-8")
+    output_unit.addlocation("".join(input_unit.getlocations()))
+    output_unit.addnote(input_unit.getnotes("developer"), "developer")
+    output_unit.source = input_unit.source
+    output_unit.target = ""
+    return output_unit
+
+def convertsub(input_file, output_file, template_file=None, pot=False, duplicatestyle="msgctxt"):
+    """Reads in L{input_file} using translate.subtitles, converts using L{sub2po}, writes to L{output_file}"""
+    input_store = subtitles.SubtitleFile(input_file)
+    if template_file is None:
+        output_store = convert_store(input_store, duplicatestyle=duplicatestyle)
+    else:
+        template_store = subtitles.SubtitleFile(template_file)
+        output_store = merge_store(template_store, input_store, blankmsgstr=pot, duplicatestyle=duplicatestyle)
+    if output_store.isempty():
+        return 0
+    output_file.write(str(output_store))
+    return 1
+
+def main(argv=None):
+    from translate.convert import convert
+    formats = {"srt": ("po", convertsub), ("srt", "srt"): ("po", convertsub)}
+    parser = convert.ConvertOptionParser(formats, usetemplates=True, usepots=True, description=__doc__)
+    parser.add_duplicates_option()
+    parser.passthrough.append("pot")
+    parser.run(argv)
+
+if __name__ == '__main__':
+    main()

Modified: translate-toolkit/branches/upstream/current/translate/convert/symb2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/symb2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/symb2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/symb2po.py Fri Jul 24 16:25:46 2009
@@ -1,9 +1,9 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2008 Zuza Software Foundation
+# Copyright 2008-2009 Zuza Software Foundation
 #
-# This file is part of Virtaal.
+# This file is part of the Translate Toolkit.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -20,8 +20,6 @@
 
 """Convert Symbian localisation files to Gettext PO localization files."""
 
-import sys
-import re
 from translate.storage import factory
 from translate.storage.pypo import extractpoline
 from translate.storage.symbian import *
@@ -74,10 +72,11 @@
     ignore = set(['r_string_languagegroup_name'])
     header_entries = {
         'Last-Translator': template_header.get('Author', ''),
-        'Language-Team': template_dict.get('r_string_languagegroup_name', '')
+        'Language-Team': template_dict.get('r_string_languagegroup_name', ''),
+        'Content-Transfer-Encoding': '8bit',
+        'Content-Type': 'text/plain; charset=UTF-8',
         }
     output_store.updateheader(add=True, **header_entries)
-    output_store.changeencoding('UTF-8')
     for id, source in units:
         if id in ignore:
             continue

Modified: translate-toolkit/branches/upstream/current/translate/convert/test_convert.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/test_convert.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/test_convert.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/test_convert.py Fri Jul 24 16:25:46 2009
@@ -5,11 +5,17 @@
 import os
 import sys
 from py import test
+try:
+    import psyco
+except Exception:
+    psyco = None
 
 class TestConvertCommand:
     """Tests running actual commands on files"""
     convertmodule = convert
-    defaultoptions = {"progress": "none", "psyco": "none"}
+    defaultoptions = {"progress": "none"}
+    if psyco:
+        defaultoptions["psyco"] = "none"
 
     def setup_method(self, method):
         """creates a clean test directory for the given method"""
@@ -117,11 +123,8 @@
         options = self.help_check(options, "-h, --help")
         options = self.help_check(options, "--manpage")
         options = self.help_check(options, "--errorlevel=ERRORLEVEL")
-        try:
-            import psyco
+        if psyco:
             options = self.help_check(options, "--psyco=MODE")
-        except Exception:
-            pass
         options = self.help_check(options, "-i INPUT, --input=INPUT")
         options = self.help_check(options, "-x EXCLUDE, --exclude=EXCLUDE")
         options = self.help_check(options, "-o OUTPUT, --output=OUTPUT")

Modified: translate-toolkit/branches/upstream/current/translate/convert/test_dtd2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/test_dtd2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/test_dtd2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/test_dtd2po.py Fri Jul 24 16:25:46 2009
@@ -88,6 +88,7 @@
         pofile = self.dtd2po(dtdsource)
         pounit = self.singleelement(pofile)
         assert "credit.translation" in str(pounit)
+        assert 'msgctxt "credit.translation"' in str(pounit)
 
     def test_emptyentity_translated(self):
         """checks that if we translate an empty entity it makes it into the PO, bug 101"""

Modified: translate-toolkit/branches/upstream/current/translate/convert/test_html2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/test_html2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/test_html2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/test_html2po.py Fri Jul 24 16:25:46 2009
@@ -34,7 +34,7 @@
         """helper to validate a PO message"""
         if not pofile.units[0].isheader():
             unitnumber = unitnumber - 1
-        print 'unit source: ' + str(pofile.units[unitnumber].source) + '|'
+        print 'unit source: ' + pofile.units[unitnumber].source.encode('utf-8') + '|'
         print 'expected: ' + expected.encode('utf-8') + '|'
         assert unicode(pofile.units[unitnumber].source) == unicode(expected)
 

Modified: translate-toolkit/branches/upstream/current/translate/convert/test_po2dtd.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/test_po2dtd.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/test_po2dtd.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/test_po2dtd.py Fri Jul 24 16:25:46 2009
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
 
 from translate.convert import po2dtd
 from translate.convert import dtd2po
@@ -92,18 +93,27 @@
 
     def test_accesskeycase(self):
         """tests that access keys come out with the same case as the original, regardless"""
-        simplepo_template = '''#: simple.label\n#: simple.accesskey\nmsgid "Simple &%s"\nmsgstr "Dimpled &%s"\n'''
+        simplepo_template = '''#: simple.label\n#: simple.accesskey\nmsgid "%s"\nmsgstr "%s"\n'''
         simpledtd_template = '''<!ENTITY simple.label "Simple %s">\n<!ENTITY simple.accesskey "%s">'''
-        # we test each combination of label case and accelerator case
-        for srcword in ("String", "string"):
-            for destword in ("Ring", "ring"):
-                for srcaccel, destaccel in ("SR", "sr"):
-                    simplepo = simplepo_template % (srcword, destword)
-                    simpledtd = simpledtd_template % (srcword, srcaccel)
-                    dtdfile = self.merge2dtd(simpledtd, simplepo)
-                    dtdfile.makeindex()
-                    accel = dtd.unquotefromdtd(dtdfile.index["simple.accesskey"].definition)
-                    assert accel == destaccel
+        possibilities = [
+                #(en label, en akey, en po, af po, af label, expected af akey)
+                ("Sis", "S", "&Sis", "&Sies", "Sies", "S"),
+                ("Sis", "s", "Si&s", "&Sies", "Sies", "S"),
+                ("Sis", "S", "&Sis", "Sie&s", "Sies", "s"),
+                ("Sis", "s", "Si&s", "Sie&s", "Sies", "s"),
+                # untranslated strings should have the casing of the source
+                ("Sis", "S", "&Sis", "", "Sis", "S"),
+                ("Sis", "s", "Si&s", "", "Sis", "s"),
+                ("Suck", "S", "&Suck", "", "Suck", "S"),
+                ("Suck", "s", "&Suck", "", "Suck", "s"),
+                ]
+        for (en_label, en_akey, po_source, po_target, target_label, target_akey) in possibilities:
+            simplepo = simplepo_template % (po_source, po_target)
+            simpledtd = simpledtd_template % (en_label, en_akey)
+            dtdfile = self.merge2dtd(simpledtd, simplepo)
+            dtdfile.makeindex()
+            accel = dtd.unquotefromdtd(dtdfile.index["simple.accesskey"].definition)
+            assert accel == target_akey
 
     def test_accesskey_types(self):
         """tests that we can detect the various styles of accesskey"""
@@ -123,6 +133,18 @@
         dtdfile = self.po2dtd(simplestring)
         dtdsource = str(dtdfile)
         assert "Dimpled Ring" in dtdsource
+
+        po_snippet = r'''#: searchIntegration.label
+#: searchIntegration.accesskey
+msgid "Allow &searchIntegration.engineName; to &search messages"
+msgstr "&searchIntegration.engineName; &ileti aramasına izin ver"
+'''
+        dtd_snippet = r'''<!ENTITY searchIntegration.accesskey      "s">
+<!ENTITY searchIntegration.label       "Allow &searchIntegration.engineName; to search messages">'''
+        dtdfile = self.merge2dtd(dtd_snippet, po_snippet)
+        dtdsource = str(dtdfile)
+        print dtdsource
+        assert '"&searchIntegration.engineName; ileti aramasına izin ver"' in dtdsource
 
     def test_entities_two(self):
         """test the error ouput when we find two entities"""

Modified: translate-toolkit/branches/upstream/current/translate/convert/test_po2html.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/test_po2html.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/test_po2html.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/test_po2html.py Fri Jul 24 16:25:46 2009
@@ -56,7 +56,7 @@
 </body>'''
         assert htmlexpected.replace("\n", " ") in self.converthtml(posource, htmlsource).replace("\n", " ")
 
-    def test_entities(self):
+    def xtest_entities(self):
         """Tests that entities are handled correctly"""
         htmlsource = '<p>5 less than 6</p>'
         posource = '#:html:3\nmsgid "5 less than 6"\nmsgstr "5 < 6"\n'
@@ -68,7 +68,7 @@
         htmlexpected = '<p>Vis & skyfies</p>'
         assert htmlexpected in self.converthtml(posource, htmlsource)
 
-    def test_escapes(self):
+    def xtest_escapes(self):
         """Tests that PO escapes are correctly handled"""
         htmlsource = '<div>Row 1<br />Row 2</div>'
         posource = '#: html:3\nmsgid "Row 1\\n"\n"Row 2"\nmsgstr "Ry 1\\n"\n"Ry 2"\n'

Modified: translate-toolkit/branches/upstream/current/translate/convert/test_po2php.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/test_po2php.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/test_po2php.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/test_po2php.py Fri Jul 24 16:25:46 2009
@@ -84,6 +84,18 @@
         print phpfile
         assert phpfile == [phpexpected]
 
+    def test_named_variables(self):
+        """check that we convert correctly if using named variables."""
+        posource = '''#: $dictYear
+msgid "Year"
+msgstr "Jaar"
+'''
+        phptemplate = '''$dictYear = 'Year';\n'''
+        phpexpected = '''$dictYear = 'Jaar';\n'''
+        phpfile = self.merge2php(phptemplate, posource)
+        print phpfile
+        assert phpfile == [phpexpected]
+
 #    def test_merging_propertyless_template(self):
 #        """check that when merging with a template with no property values that we copy the template"""
 #        posource = ""

Modified: translate-toolkit/branches/upstream/current/translate/convert/test_pot2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/test_pot2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/test_pot2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/test_pot2po.py Fri Jul 24 16:25:46 2009
@@ -133,8 +133,8 @@
         potsource = '''#: location.c:1\nmsgid ""\n"_: location.c:1\\n"\n"Source"\nmsgstr ""\n\n''' + \
                     '''#: location.c:10\nmsgid ""\n"_: location.c:10\\n"\n"Source"\nmsgstr ""\n'''
         posource = '''#: location.c:1\n#: location.c:10\nmsgid "Source"\nmsgstr "Target"\n\n'''
-        poexpected1 = '''#: location.c:1\nmsgid ""\n"_: location.c:1\\n"\n"Source"\nmsgstr "Target"\n'''
-        poexpected2 = '''#: location.c:10\nmsgid ""\n"_: location.c:10\\n"\n"Source"\nmsgstr "Target"\n'''
+        poexpected1 = '''#: location.c:1\n#, fuzzy\nmsgid ""\n"_: location.c:1\\n"\n"Source"\nmsgstr "Target"\n'''
+        poexpected2 = '''#: location.c:10\n#, fuzzy\nmsgid ""\n"_: location.c:10\\n"\n"Source"\nmsgstr "Target"\n'''
         newpo = self.convertpot(potsource, posource)
         print "Expected:\n", poexpected1, "Actual:\n", newpo.units[1]
         assert str(newpo.units[1]) == poexpected1
@@ -250,6 +250,7 @@
 msgstr "Sertifikate"
 '''
         expected = r'''#: pref.certs.title
+#, fuzzy
 msgid ""
 "_: pref.certs.title\n"
 "Certificates"
@@ -323,11 +324,11 @@
 
     def test_merging_resurect_obsolete_messages_into_msgidcomment(self):
         """check that we can reuse old obsolete messages even if the recipient has a msgidcomment"""
-        potsource = '''#: resurect1.c\nmsgid ""\n"_: resurect1.c\\n"\n"About"\nmsgstr ""\n\n''' + \
+        potsource = '''#: resurect1.c\nmsgid "About"\nmsgstr ""\n\n''' + \
                     '''#: resurect2.c\nmsgid ""\n"_: resurect2.c\\n"\n"About"\nmsgstr ""\n'''
         posource = '''#~ msgid "About"\n#~ msgstr "Omtrent"\n'''
-        expected1 = '''#: resurect1.c\nmsgid ""\n"_: resurect1.c\\n"\n"About"\nmsgstr "Omtrent"\n'''
-        expected2 = '''#: resurect2.c\nmsgid ""\n"_: resurect2.c\\n"\n"About"\nmsgstr "Omtrent"\n'''
+        expected1 = '''#: resurect1.c\nmsgid "About"\nmsgstr "Omtrent"\n'''
+        expected2 = '''#: resurect2.c\n#, fuzzy\nmsgid ""\n"_: resurect2.c\\n"\n"About"\nmsgstr "Omtrent"\n'''
         newpo = self.convertpot(potsource, posource)
         print newpo
         assert len(newpo.units) == 3
@@ -394,7 +395,7 @@
         print newpo
         newpounit = self.singleunit(newpo)
         assert str(newpounit) == poexpected
-        
+
     def test_merging_typecomments(self):
         """Test that we can merge with typecomments"""
         potsource = '''#: file.c:1\n#, c-format\nmsgid "%d pipes"\nmsgstr ""\n''' 
@@ -412,6 +413,95 @@
         newpounit = self.singleunit(newpo)
         assert newpounit.isfuzzy()
         assert newpounit.hastypecomment("c-format")
+
+    def test_msgctxt(self):
+        """Test that msgctxt is migrated correctly"""
+        potsource = """
+#: something.h:5
+msgctxt "context1"
+msgid "text"
+msgstr ""
+
+#: something.h:6
+msgctxt "context2"
+msgid "text"
+msgstr ""
+"""
+        posource = """
+#: something.h:3
+msgctxt "context0"
+msgid "text"
+msgstr "teks"
+
+#: something.h:4
+msgctxt "context1"
+msgid "text"
+msgstr "sms"
+"""
+        poexpected = """
+#: something.h:5
+msgctxt "context1"
+msgid "text"
+msgstr "sms"
+
+#: something.h:6
+#, fuzzy
+msgctxt "context2"
+msgid "text"
+msgstr "teks"
+"""
+        newpo = self.convertpot(potsource, posource)
+        print newpo
+        assert poexpected in str(newpo)
+
+    def test_empty_msgid(self):
+        """Test that we handle empty msgids correctly."""
+        #TODO: this test will fail if we don't have the gettext location
+        # comment in the pot file
+        potsource = '#: file:1\nmsgctxt "bla"\nmsgid ""\nmsgstr ""\n'
+        posource = r"""
+msgid ""
+"Project-Id-Version: Pootle 0.10\n"
+msgstr ""
+
+msgctxt "bla"
+msgid ""
+msgstr "trans"
+"""
+        newpo = self.convertpot(potsource, posource)
+        print newpo
+        assert len(newpo.units) == 2
+        assert newpo.units[0].isheader()
+        unit = newpo.units[1]
+        assert unit.source == u""
+        assert unit.getid() == u"bla\04"
+        assert unit.target == "trans"
+        assert not unit.isfuzzy()
+
+    def test_migrate_msgidcomment_to_msgctxt(self):
+        """Test that we migrate correctly from msgidcomments to msgctxt.
+
+        This is needed for our move away from using msgidcomments for mozilla."""
+        potsource = '#: bla\nmsgctxt "bla"\nmsgid ""\nmsgstr ""'
+        posource = r"""
+msgid ""
+"Project-Id-Version: Pootle 0.10\n"
+msgstr ""
+
+#: bla
+msgid ""
+"_: bla\n"
+msgstr "trans"
+"""
+        newpo = self.convertpot(potsource, posource)
+        print newpo
+        assert len(newpo.units) == 2
+        assert newpo.units[0].isheader()
+        unit = newpo.units[1]
+        assert unit.source == u""
+        assert unit.getid() == u"bla\04"
+        assert unit.target == "trans"
+        assert not unit.isfuzzy()
 
     def test_obsolete_msgctxt(self):
         """Test that obsolete units' msgctxt is preserved."""
@@ -439,6 +529,69 @@
         # Search in unit string, because obsolete units can't return a context
         assert 'msgctxt "context"' in str(newpo.units[2])
         assert 'msgctxt "context2"' in str(newpo.units[3])
+
+    def test_small_strings(self):
+        """Test that units with small source strings are not incorrectly
+        populated by means of fuzzy matching."""
+        potsource = r'''#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: new at example.com\n"
+"POT-Creation-Date: 2006-11-11 11:11+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+"X-Generator: Translate Toolkit 0.10rc2\n"
+
+#: new_disassociated_mozilla_accesskey
+msgid "R"
+msgstr ""
+'''
+        posource = r'''msgid ""
+msgstr ""
+"Project-Id-Version: Pootle 0.10\n"
+"Report-Msgid-Bugs-To: old at example.com\n"
+"POT-Creation-Date: 2006-01-01 01:01+0100\n"
+"PO-Revision-Date: 2006-09-09 09:09+0900\n"
+"Last-Translator: Joe Translate <joe at example.com>\n"
+"Language-Team: Pig Latin <piglatin at example.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Translate Toolkit 0.9\n"
+
+#: old_disassociated_mozilla_accesskey
+msgid "R"
+msgstr "S"
+'''
+        expected = r'''msgid ""
+msgstr ""
+"Project-Id-Version: Pootle 0.10\n"
+"Report-Msgid-Bugs-To: new at example.com\n"
+"POT-Creation-Date: 2006-11-11 11:11+0000\n"
+"PO-Revision-Date: 2006-09-09 09:09+0900\n"
+"Last-Translator: Joe Translate <joe at example.com>\n"
+"Language-Team: Pig Latin <piglatin at example.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Translate Toolkit 0.10rc2\n"
+
+#: new_disassociated_mozilla_accesskey
+msgid "R"
+msgstr ""
+'''
+        newpo = self.convertpot(potsource, posource)
+        print 'Output:\n%s' % newpo
+        print 'Expected:\n%s' % expected
+        assert str(newpo) == expected
 
 
 class TestPOT2POCommand(test_convert.TestConvertCommand, TestPOT2PO):

Modified: translate-toolkit/branches/upstream/current/translate/convert/test_prop2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/test_prop2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/test_prop2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/test_prop2po.py Fri Jul 24 16:25:46 2009
@@ -71,10 +71,10 @@
         pounit = self.singleelement(pofile)
         assert pounit.source == "This setence has a space then tab at the end. \t"
         
-        propsource = r"SPACE_AT_END=This setence will lose its 4 spaces at the end.    "
+        propsource = r"SPACE_AT_END=This setence will keep its 4 spaces at the end.    "
         pofile = self.prop2po(propsource)
         pounit = self.singleelement(pofile)
-        assert pounit.source == "This setence will lose its 4 spaces at the end."
+        assert pounit.source == "This setence will keep its 4 spaces at the end.    "
         
         propsource = r"SPACE_AT_END_NO_TRIM=This setence will keep its 4 spaces at the end.\\    "
         pofile = self.prop2po(propsource)
@@ -140,6 +140,7 @@
         pounit = self.singleelement(pofile)
         assert pounit.getlocations() == ["credit"]
         assert pounit.getcontext() == "credit"
+        assert 'msgctxt "credit"' in str(pounit)
         assert "#. # comment" in str(pofile)
         assert pounit.source == ""
 
@@ -188,5 +189,6 @@
         options = test_convert.TestConvertCommand.test_help(self)
         options = self.help_check(options, "-P, --pot")
         options = self.help_check(options, "-t TEMPLATE, --template=TEMPLATE")
+        options = self.help_check(options, "--personality=TYPE")
         options = self.help_check(options, "--duplicates=DUPLICATESTYLE", last=True)
 

Modified: translate-toolkit/branches/upstream/current/translate/convert/test_xliff2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/test_xliff2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/test_xliff2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/test_xliff2po.py Fri Jul 24 16:25:46 2009
@@ -80,6 +80,24 @@
         assert pofile.translate("nonsense") == "matlhapolosa"
         assert pofile.translate("bla") is None
         unit = pofile.units[0]
+        assert unit.getnotes("translator") == "Couldn't do it"
+        potext = str(pofile)
+        assert potext.index("# Couldn't do it\n") >= 0
+
+        minixlf = self.xliffskeleton % '''<trans-unit xml:space="preserve">
+        <source>nonsense</source>
+        <target>matlhapolosa</target>
+        <context-group name="po-entry" purpose="information">
+            <context context-type="x-po-trancomment">Couldn't do
+it</context>
+        </context-group>
+        <note from="po-translator">Couldn't do
+it</note>
+</trans-unit>'''
+        pofile = self.xliff2po(minixlf)
+        assert pofile.translate("nonsense") == "matlhapolosa"
+        assert pofile.translate("bla") is None
+        unit = pofile.units[0]
         assert unit.getnotes("translator") == "Couldn't do\nit"
         potext = str(pofile)
         assert potext.index("# Couldn't do\n# it\n") >= 0
@@ -87,6 +105,24 @@
     def test_autocomment(self):
         """Tests automatic comments"""
         minixlf = self.xliffskeleton % '''<trans-unit>
+        <source>nonsense</source>
+        <target>matlhapolosa</target>
+        <context-group name="po-entry" purpose="information">
+            <context context-type="x-po-autocomment">Note that this is
+garbage</context>
+        </context-group>
+        <note from="developer">Note that this is
+garbage</note>
+</trans-unit>'''
+        pofile = self.xliff2po(minixlf)
+        assert pofile.translate("nonsense") == "matlhapolosa"
+        assert pofile.translate("bla") is None
+        unit = pofile.units[0]
+        assert unit.getnotes("developer") == "Note that this is garbage"
+        potext = str(pofile)
+        assert potext.index("#. Note that this is garbage\n") >= 0
+
+        minixlf = self.xliffskeleton % '''<trans-unit xml:space="preserve">
         <source>nonsense</source>
         <target>matlhapolosa</target>
         <context-group name="po-entry" purpose="information">

Added: translate-toolkit/branches/upstream/current/translate/convert/web2py2po
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/web2py2po?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/web2py2po (added)
+++ translate-toolkit/branches/upstream/current/translate/convert/web2py2po Fri Jul 24 16:25:46 2009
@@ -1,0 +1,26 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of translate.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""convert web2py translation dictionaries (.py) to GNU/gettext PO files"""
+
+from translate.convert import web2py2po
+
+if __name__ == '__main__':
+    web2py2po.main()

Propchange: translate-toolkit/branches/upstream/current/translate/convert/web2py2po
------------------------------------------------------------------------------
    svn:executable = *

Added: translate-toolkit/branches/upstream/current/translate/convert/web2py2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/web2py2po.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/web2py2po.py (added)
+++ translate-toolkit/branches/upstream/current/translate/convert/web2py2po.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,80 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of translate.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# (c) 2009 Dominic König (dominic at nursix.org)
+#
+
+"""convert web2py translation dictionaries (.py) to GNU/gettext PO files"""
+
+import sys
+from translate.storage import po
+
+class web2py2po:
+    def __init__(self, pofile=None):
+        self.mypofile = pofile
+
+    def convertunit(self, source_str, target_str):
+        pounit = po.pounit(encoding="UTF-8")
+        pounit.setsource( source_str )
+        if target_str:
+            pounit.settarget( target_str )
+        return pounit
+
+    def convertstore(self, mydict):
+
+        targetheader = self.mypofile.makeheader(charset="UTF-8", encoding="8bit")
+        targetheader.addnote("extracted from web2py", "developer")
+
+        self.mypofile.addunit(targetheader)
+
+        for source_str in mydict.keys():
+            target_str = mydict[source_str]
+            if target_str.startswith('*** '):
+                target_str = ''
+            pounit = self.convertunit(source_str, target_str)
+            self.mypofile.addunit(pounit)
+
+        return self.mypofile
+
+def convertpy(inputfile, outputfile, encoding="UTF-8"):
+
+    new_pofile = po.pofile()
+    convertor = web2py2po(new_pofile)
+
+    mydict = eval(inputfile.read())
+    if not isinstance(mydict, dict):
+        return 0
+
+    outputstore = convertor.convertstore(mydict)
+
+    if outputstore.isempty():
+        return 0
+
+    outputfile.write(str(outputstore))
+    return 1
+
+def main(argv=None):
+    from translate.convert import convert
+    formats = {("py", "po"): ("po", convertpy), ("py", None): ("po", convertpy)}
+    parser = convert.ConvertOptionParser(formats, usetemplates=False, description=__doc__)
+    parser.run(argv)
+
+if __name__ == '__main__':
+    main()

Modified: translate-toolkit/branches/upstream/current/translate/convert/xliff2odf.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/xliff2odf.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/xliff2odf.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/xliff2odf.py Fri Jul 24 16:25:46 2009
@@ -66,6 +66,11 @@
             generate.apply_translations(dom_tree.getroot(), file_unit_tree, generate.replace_dom_text(make_parse_state))
         return dom_trees
 
+    # Since the convertoptionsparser will give us an open file, we risk that
+    # it could have been opened in non-binary mode on Windows, and then we'll
+    # have problems, so let's make sure we have what we want.
+    template.close()
+    template = file(template.name, mode='rb')
     dom_trees = load_dom_trees(template)
     unit_trees = load_unit_tree(input_file, dom_trees)
     return translate_dom_trees(unit_trees, dom_trees)
@@ -75,6 +80,11 @@
         for filename, dom_tree in dom_trees.iteritems():
             output_zip.writestr(filename, etree.tostring(dom_tree, encoding='UTF-8', xml_declaration=True))
 
+    # Since the convertoptionsparser will give us an open file, we risk that
+    # it could have been opened in non-binary mode on Windows, and then we'll
+    # have problems, so let's make sure we have what we want.
+    template.close()
+    template = file(template.name, mode='rb')
     template_zip = zipfile.ZipFile(template,  'r')
     output_zip   = zipfile.ZipFile(output_file, 'w', compression=zipfile.ZIP_DEFLATED)
     output_zip   = odf_io.copy_odf(template_zip, output_zip, dom_trees.keys() + ['META-INF/manifest.xml'])
@@ -86,6 +96,7 @@
     xlf_data = input_file.read()
     dom_trees = translate_odf(template, cStringIO.StringIO(xlf_data))
     write_odf(xlf_data, template, output_file, dom_trees)
+    output_file.close()
     return True
 
 def main(argv=None):

Modified: translate-toolkit/branches/upstream/current/translate/convert/xliff2po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/convert/xliff2po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/convert/xliff2po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/convert/xliff2po.py Fri Jul 24 16:25:46 2009
@@ -1,29 +1,27 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2002-2006 Zuza Software Foundation
-# 
-# This file is part of translate.
+# Copyright 2002-2009 Zuza Software Foundation
 #
-# translate is free software; you can redistribute it and/or modify
+# This file is part of Virtaal.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
-"""convert XLIFF localization files to Gettext PO localization files
+"""Convert XLIFF localization files to Gettext PO localization files.
 
-see: http://translate.sourceforge.net/wiki/toolkit/xliff2po for examples and 
-usage instructions
+see: http://translate.sourceforge.net/wiki/toolkit/xliff2po for examples and
+usage instructions.
 """
 
 from translate.storage import po
@@ -45,14 +43,14 @@
         #Location comments
         locations = transunit.getlocations()
         if locations:
-            thepo.addlocation("%s" % " ".join(locations))
+            thepo.addlocations(locations)
 
         #NOTE: Supporting both <context> and <note> tags in xliff files for comments
         #Translator comments
         trancomments = transunit.getnotes("translator")
         if trancomments:
             thepo.addnote(trancomments, origin="translator")
-        
+
         #Automatic and Developer comments
         autocomments = transunit.getnotes("developer")
         if autocomments:
@@ -61,11 +59,11 @@
         #See 5.6.1 of the spec. We should not check fuzzyness, but approved attribute
         if transunit.isfuzzy():
             thepo.markfuzzy(True)
-        
+
         return thepo
 
     def convertstore(self, inputfile):
-        """converts a .xliff file to .po format"""
+        """Converts a .xliff file to .po format"""
         # XXX: The inputfile is converted to string because Pootle supplies
         # XXX: a PootleFile object as input which cannot be sent to PoXliffFile.
         # XXX: The better way would be to have a consistent conversion API.
@@ -94,4 +92,3 @@
     formats = {"xlf":("po", convertxliff)}
     parser = convert.ConvertOptionParser(formats, usepots=True, description=__doc__)
     parser.run(argv)
-

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-contributing.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-contributing.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-contributing.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-contributing.html Fri Jul 24 16:25:46 2009
@@ -270,7 +270,7 @@
 
 <p>
 
-An aligner would be nice.  At the moment, po2tmx can create a <acronym title="Translation Memory eXchange">TMX</acronym> file, but the TUs in the <acronym title="Translation Memory eXchange">TMX</acronym> often contain more than one sentence.  A TM is more useful to translators if it contains sentences, not paragraphs.  So, how about a tool that takes such a <acronym title="Translation Memory eXchange">TMX</acronym> and attempts to converts each one into sentences (source and target).  The output can be <acronym title="Comma Seperated Value">CSV</acronym>, so that a translator can open it in a graphical <acronym title="Comma Seperated Value">CSV</acronym> editor and correct misalignments.  The output can even be a plaintext tab delimited file so that one can open it as a table in OpenOffice and use shortcuts to correct the alignment.
+An aligner would be nice.  At the moment, po2tmx can create a <acronym title="Translation Memory eXchange">TMX</acronym> file, but the TUs in the <acronym title="Translation Memory eXchange">TMX</acronym> often contain more than one sentence.  A TM is more useful to translators if it contains sentences, not paragraphs.  So, how about a tool that takes such a <acronym title="Translation Memory eXchange">TMX</acronym> and attempts to converts each one into sentences (source and target).  The output can be <acronym title="Comma Separated Value">CSV</acronym>, so that a translator can open it in a graphical <acronym title="Comma Separated Value">CSV</acronym> editor and correct misalignments.  The output can even be a plaintext tab delimited file so that one can open it as a table in OpenOffice and use shortcuts to correct the alignment.
 </p>
 
 <p>
@@ -302,11 +302,11 @@
 </p>
 
 <p>
-po2csv isn't really feasible because different programs have different <acronym title="Comma Seperated Value">CSV</acronym> definitions.  Excel and Calc interpret a <acronym title="Comma Seperated Value">CSV</acronym> file in two different ways.  So exporting the <acronym title="Gettext Portable Object">PO</acronym> to <acronym title="Comma Seperated Value">CSV</acronym> only works for tools that can correctly interpret the Toolkit's chosen dialect of <acronym title="Comma Seperated Value">CSV</acronym>.
+po2csv isn't really feasible because different programs have different <acronym title="Comma Separated Value">CSV</acronym> definitions.  Excel and Calc interpret a <acronym title="Comma Separated Value">CSV</acronym> file in two different ways.  So exporting the <acronym title="Gettext Portable Object">PO</acronym> to <acronym title="Comma Separated Value">CSV</acronym> only works for tools that can correctly interpret the Toolkit's chosen dialect of <acronym title="Comma Separated Value">CSV</acronym>.
 
 </p>
 <blockquote><div class="no">
- The underlying toolkit <acronym title="Comma Seperated Value">CSV</acronym> module supports various flavours of <acronym title="Comma Seperated Value">CSV</acronym>.  It currently uses the Excel flavour.  So it is possible to output for different spreadsheets if needed.  It might be better to understand what exactly fails, I know we had to hack things to prevent the loss of leading single quotes which in most word processors are interpreted as meaning 'treat this as text'  --- <em><a href="mailto:&#x64;&#x77;&#x61;&#x79;&#x6e;&#x65;&#x40;&#x74;&#x72;&#x61;&#x6e;&#x73;&#x6c;&#x61;&#x74;&#x65;&#x2e;&#x6f;&#x72;&#x67;&#x2e;&#x7a;&#x61;" class="mail JSnocheck" title="&#x64;&#x77;&#x61;&#x79;&#x6e;&#x65;&#x40;&#x74;&#x72;&#x61;&#x6e;&#x73;&#x6c;&#x61;&#x74;&#x65;&#x2e;&#x6f;&#x72;&#x67;&#x2e;&#x7a;&#x61;">Dwayne Bailey</a> 2007/10/18 03:13</em></div></blockquote>
+ The underlying toolkit <acronym title="Comma Separated Value">CSV</acronym> module supports various flavours of <acronym title="Comma Separated Value">CSV</acronym>.  It currently uses the Excel flavour.  So it is possible to output for different spreadsheets if needed.  It might be better to understand what exactly fails, I know we had to hack things to prevent the loss of leading single quotes which in most word processors are interpreted as meaning 'treat this as text'  --- <em><a href="mailto:&#x64;&#x77;&#x61;&#x79;&#x6e;&#x65;&#x40;&#x74;&#x72;&#x61;&#x6e;&#x73;&#x6c;&#x61;&#x74;&#x65;&#x2e;&#x6f;&#x72;&#x67;&#x2e;&#x7a;&#x61;" class="mail JSnocheck" title="&#x64;&#x77;&#x61;&#x79;&#x6e;&#x65;&#x40;&#x74;&#x72;&#x61;&#x6e;&#x73;&#x6c;&#x61;&#x74;&#x65;&#x2e;&#x6f;&#x72;&#x67;&#x2e;&#x7a;&#x61;">Dwayne Bailey</a> 2007/10/18 03:13</em></div></blockquote>
 <blockquote><div class="no">
 <blockquote><div class="no">
  Well, Excel doesn't convert cleanly to a word processing format and back.  Excel wasn't designed as a text editing tool anyway.  The “normal” program to edit text in, surely, is a word processor. -- Samuel</div></blockquote>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-creating_a_terminology_list_from_your_existing_translations.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-creating_a_terminology_list_from_your_existing_translations.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-creating_a_terminology_list_from_your_existing_translations.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-creating_a_terminology_list_from_your_existing_translations.html Fri Jul 24 16:25:46 2009
@@ -49,7 +49,7 @@
 </li>
 <li class="level1"><div class="li"> Extract and review items that are fuzzy and drop untranslated items</div>
 </li>
-<li class="level1"><div class="li"> Create a new <acronym title="Gettext Portable Object">PO</acronym> files and process into <acronym title="Comma Seperated Value">CSV</acronym> and <acronym title="Translation Memory eXchange">TMX</acronym> format</div>
+<li class="level1"><div class="li"> Create a new <acronym title="Gettext Portable Object">PO</acronym> files and process into <acronym title="Comma Separated Value">CSV</acronym> and <acronym title="Translation Memory eXchange">TMX</acronym> format</div>
 </li>
 </ol>
 
@@ -212,7 +212,7 @@
 
 <p>
 
-It is probably good to make your terminology available in other formats.  You can create <acronym title="Comma Seperated Value">CSV</acronym> and <acronym title="Translation Memory eXchange">TMX</acronym> files from your <acronym title="Gettext Portable Object">PO</acronym>.
+It is probably good to make your terminology available in other formats.  You can create <acronym title="Comma Separated Value">CSV</acronym> and <acronym title="Translation Memory eXchange">TMX</acronym> files from your <acronym title="Gettext Portable Object">PO</acronym>.
 
 </p>
 <pre class="code">po2csv zulu-gnome-glossary.po zulu-gnome-glossary.csv

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-creating_mozilla_pot_files.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-creating_mozilla_pot_files.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-creating_mozilla_pot_files.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-creating_mozilla_pot_files.html Fri Jul 24 16:25:46 2009
@@ -57,8 +57,12 @@
 that you can use for translation or updating your existing <acronym title="Gettext Portable Object">PO</acronym> files.
 </p>
 
+<p>
+There are also <a href="toolkit-mozilla_l10n_scripts.html" class="wikilink1" title="toolkit-mozilla_l10n_scripts.html">other scripts</a> that can help with creating and updating <acronym title="Gettext Portable Object Template">POT</acronym> and <acronym title="Gettext Portable Object">PO</acronym> files for <a href="toolkit-mozilla.html" class="wikilink2" title="toolkit-mozilla.html">Mozilla</a> localisation.
+</p>
+
 </div>
-<!-- SECTION "Using Mercurial" [148-973] -->
+<!-- SECTION "Using Mercurial" [148-1115] -->
 <h2><a name="using_cvs" id="using_cvs">Using CVS</a></h2>
 <div class="level2">
 
@@ -94,7 +98,7 @@
 </p>
 
 </div>
-<!-- SECTION "Using CVS" [974-1910] -->
+<!-- SECTION "Using CVS" [1116-2052] -->
 <h2><a name="using_an_en-us_xpi_file" id="using_an_en-us_xpi_file">Using an en-US XPI file</a></h2>
 <div class="level2">
 
@@ -112,5 +116,5 @@
 </p>
 
 </div>
-<!-- SECTION "Using an en-US XPI file" [1911-] --></body>
+<!-- SECTION "Using an en-US XPI file" [2053-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv.html Fri Jul 24 16:25:46 2009
@@ -18,7 +18,7 @@
 <div class="level1">
 
 <p>
-<acronym title="Comma Seperated Value">CSV</acronym> (Comma Separated Values) is a simple file format for general data interchange. It can be used in the toolkit for simple data interchange, and can be edited with most spreadsheet programs. There is no formal specification for the <acronym title="Comma Seperated Value">CSV</acronym> file format, but more information can be acquired from <a href="http://en.wikipedia.org/wiki/Comma-separated%20values" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/Comma-separated%20values">Comma-separated values</a>
+<acronym title="Comma Separated Value">CSV</acronym> (Comma Separated Values) is a simple file format for general data interchange. It can be used in the toolkit for simple data interchange, and can be edited with most spreadsheet programs. There is no formal specification for the <acronym title="Comma Separated Value">CSV</acronym> file format, but more information can be acquired from <a href="http://en.wikipedia.org/wiki/Comma-separated%20values" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/Comma-separated%20values">Comma-separated values</a>
 </p>
 
 <p>
@@ -31,7 +31,7 @@
 <div class="level2">
 
 <p>
-<acronym title="Comma Seperated Value">CSV</acronym> files were initially used to convert from and to <a href="toolkit-po.html" class="wikilink1" title="toolkit-po.html">PO</a> files, and therefore contained three columns as follows:
+<acronym title="Comma Separated Value">CSV</acronym> files were initially used to convert from and to <a href="toolkit-po.html" class="wikilink1" title="toolkit-po.html">PO</a> files, and therefore contained three columns as follows:
 </p>
 <ul>
 <li class="level1"><div class="li"> A column with the location of the original msgid (in other words, a line in a programming source file, as indicated in the #: comments of <acronym title="Gettext Portable Object">PO</acronym> files).</div>
@@ -48,7 +48,7 @@
 </p>
 
 <p>
-Quoting is a problem, because the different spreadsheet programs handle these things differently. Notably, Microsoft's excel handles single quotes slightly differently. In future, it might be worthwhile to handle excel <acronym title="Comma Seperated Value">CSV</acronym> as a different format from other <acronym title="Comma Seperated Value">CSV</acronym> files. An entry like 'mono' is ambiguous as it is not sure whether this refers simply to the word <em>mono</em> or to the entry <em>'mono'</em> quoted with single quotes. (Example from Audacity pot file)
+Quoting is a problem, because the different spreadsheet programs handle these things differently. Notably, Microsoft's excel handles single quotes slightly differently. In future, it might be worthwhile to handle excel <acronym title="Comma Separated Value">CSV</acronym> as a different format from other <acronym title="Comma Separated Value">CSV</acronym> files. An entry like 'mono' is ambiguous as it is not sure whether this refers simply to the word <em>mono</em> or to the entry <em>'mono'</em> quoted with single quotes. (Example from Audacity pot file)
 </p>
 
 </div>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv2po.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv2po.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv2po.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv2po.html Fri Jul 24 16:25:46 2009
@@ -19,11 +19,15 @@
 
 <p>
 
-Convert between <acronym title="Comma Seperated Value">CSV</acronym> (Comma Separated Value) files and the <acronym title="Gettext Portable Object">PO</acronym> format.  This is useful for those translators who can only use a Spreadsheet, a modern spreadsheet can open <acronym title="Comma Seperated Value">CSV</acronym> files for editing.  It is also useful if you have other data such as translation memory in <acronym title="Comma Seperated Value">CSV</acronym> format and you wish to use it with your <acronym title="Gettext Portable Object">PO</acronym> translations.
-</p>
-
-</div>
-<!-- SECTION "csv2po and po2csv" [1-359] -->
+Convert between <acronym title="Comma Separated Value">CSV</acronym> (Comma Separated Value) files and the <acronym title="Gettext Portable Object">PO</acronym> format.  This is useful for those translators who can only use a Spreadsheet, a modern spreadsheet can open <acronym title="Comma Separated Value">CSV</acronym> files for editing.  It is also useful if you have other data such as translation memory in <acronym title="Comma Separated Value">CSV</acronym> format and you wish to use it with your <acronym title="Gettext Portable Object">PO</acronym> translations.
+</p>
+
+<p>
+If you are starting out with your own <acronym title="Comma Separated Value">CSV</acronym> files (not created by po2csv), take note of the assumptions of the column layout explained below.
+</p>
+
+</div>
+<!-- SECTION "csv2po and po2csv" [1-500] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
 <pre class="code">csv2po [options] <csv> <po>
@@ -36,7 +40,7 @@
 </p>
 <table class="inline">
 	<tr class="row0">
-		<td class="col0 leftalign"> <csv>  </td><td class="col1 leftalign"> is a file or directory containing <acronym title="Comma Seperated Value">CSV</acronym> files  </td>
+		<td class="col0 leftalign"> <csv>  </td><td class="col1 leftalign"> is a file or directory containing <acronym title="Comma Separated Value">CSV</acronym> files  </td>
 	</tr>
 	<tr class="row1">
 		<td class="col0 leftalign"> <po>   </td><td class="col1 leftalign"> is a file or directory containing <acronym title="Gettext Portable Object">PO</acronym> files  </td>
@@ -129,13 +133,13 @@
 </table>
 
 </div>
-<!-- SECTION "Usage" [360-2433] -->
+<!-- SECTION "Usage" [501-2574] -->
 <h2><a name="csv_file_layout" id="csv_file_layout">CSV file layout</a></h2>
 <div class="level2">
 
 <p>
 
-The resultant <acronym title="Comma Seperated Value">CSV</acronym> file has the following layout
+The resultant <acronym title="Comma Separated Value">CSV</acronym> file has the following layout
 
 </p>
 <table class="inline">
@@ -143,7 +147,7 @@
 		<th class="col0 leftalign"> Column  </th><th class="col1 leftalign"> Data  </th><th class="col2 leftalign"> Description  </th>
 	</tr>
 	<tr class="row1">
-		<td class="col0 centeralign">  A  </td><td class="col1 leftalign"> Location              </td><td class="col2 leftalign"> All the <acronym title="Gettext Portable Object">PO</acronym> #: location comments.  These are needed to reconstruct or merge the <acronym title="Comma Seperated Value">CSV</acronym> back into the <acronym title="Gettext Portable Object">PO</acronym> file  </td>
+		<td class="col0 centeralign">  A  </td><td class="col1 leftalign"> Location              </td><td class="col2 leftalign"> All the <acronym title="Gettext Portable Object">PO</acronym> #: location comments.  These are needed to reconstruct or merge the <acronym title="Comma Separated Value">CSV</acronym> back into the <acronym title="Gettext Portable Object">PO</acronym> file  </td>
 	</tr>
 	<tr class="row2">
 		<td class="col0 centeralign">  B  </td><td class="col1"> Source Language (English) </td><td class="col2 leftalign"> The msgid or source string  </td>
@@ -154,7 +158,7 @@
 </table>
 
 </div>
-<!-- SECTION "CSV file layout" [2434-2814] -->
+<!-- SECTION "CSV file layout" [2575-2955] -->
 <h2><a name="examples" id="examples">Examples</a></h2>
 <div class="level2">
 
@@ -167,14 +171,14 @@
 
 <p>
 
-We use the <em>-P</em> option to recognise <acronym title="Gettext Portable Object Template">POT</acronym> files found in <em>pot</em> and convert them to <acronym title="Comma Seperated Value">CSV</acronym> files placed in <em>csv</em>
+We use the <em>-P</em> option to recognise <acronym title="Gettext Portable Object Template">POT</acronym> files found in <em>pot</em> and convert them to <acronym title="Comma Separated Value">CSV</acronym> files placed in <em>csv</em>
 
 </p>
 <pre class="code">csv2po csv po</pre>
 
 <p>
 
-Convert <acronym title="Comma Seperated Value">CSV</acronym> files in <em>csv</em> to <acronym title="Gettext Portable Object">PO</acronym> files placed in <em>po</em>
+Convert <acronym title="Comma Separated Value">CSV</acronym> files in <em>csv</em> to <acronym title="Gettext Portable Object">PO</acronym> files placed in <em>po</em>
 
 </p>
 <pre class="code">csv2po --charset=windows-1250 -t pot csv po</pre>
@@ -182,22 +186,22 @@
 <p>
 
 User working on Windows will often return files encoded in everything but Unicode.  In this case we convert
-<acronym title="Comma Seperated Value">CSV</acronym> files found in <em>csv</em> from <em>windows-1250</em> to UTF-8 and place the correctly encoded files in <em>po</em>.  We use
+<acronym title="Comma Separated Value">CSV</acronym> files found in <em>csv</em> from <em>windows-1250</em> to UTF-8 and place the correctly encoded files in <em>po</em>.  We use
 the templates found in <em>pot</em> to ensure that we preserve formatting and other data.  Note that 
 UTF-8 is the only available destination encoding.
 </p>
 
 </div>
-<!-- SECTION "Examples" [2815-3512] -->
+<!-- SECTION "Examples" [2956-3653] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 <ul>
-<li class="level1"><div class="li"> Translation comments #[space] and KDE comments _: are not available in <acronym title="Comma Seperated Value">CSV</acronym> mode which effects the translators effectiveness</div>
+<li class="level1"><div class="li"> Translation comments #[space] and KDE comments _: are not available in <acronym title="Comma Separated Value">CSV</acronym> mode which effects the translators effectiveness</div>
 </li>
 <li class="level1"><div class="li"> Locations #: that are not conformant to <acronym title="Gettext Portable Object">PO</acronym> (i.e. have spaces) will get messed up by <acronym title="Gettext Portable Object">PO</acronym> tools.</div>
 </li>
 </ul>
 
 </div>
-<!-- SECTION "Bugs" [3513-] --></body>
+<!-- SECTION "Bugs" [3654-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv2tbx.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv2tbx.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv2tbx.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-csv2tbx.html Fri Jul 24 16:25:46 2009
@@ -19,7 +19,7 @@
 
 <p>
 
-Convert between <acronym title="Comma Seperated Value">CSV</acronym> (Comma Separated Value) files and the <a href="toolkit-tbx.html" class="wikilink1" title="toolkit-tbx.html">TBX</a> format for terminology exchange.
+Convert between <acronym title="Comma Separated Value">CSV</acronym> (Comma Separated Value) files and the <a href="toolkit-tbx.html" class="wikilink1" title="toolkit-tbx.html">TBX</a> format for terminology exchange.
 </p>
 
 </div>
@@ -35,7 +35,7 @@
 </p>
 <table class="inline">
 	<tr class="row0">
-		<td class="col0 leftalign"> <csv>  </td><td class="col1 leftalign"> is a <acronym title="Comma Seperated Value">CSV</acronym> file  </td>
+		<td class="col0 leftalign"> <csv>  </td><td class="col1 leftalign"> is a <acronym title="Comma Separated Value">CSV</acronym> file  </td>
 	</tr>
 	<tr class="row1">
 		<td class="col0 leftalign"> <tbx>   </td><td class="col1"> is the target <acronym title="TermBase eXchange">TBX</acronym> file </td>
@@ -90,7 +90,7 @@
 
 <p>
 
-The <acronym title="Comma Seperated Value">CSV</acronym> file is expected in to have three columns, of which the default layout is
+The <acronym title="Comma Separated Value">CSV</acronym> file is expected in to have three columns, of which the default layout is
 
 </p>
 <table class="inline">
@@ -133,7 +133,7 @@
 
 <p>
 
-This will convert <acronym title="Comma Seperated Value">CSV</acronym> files in <em>csv-dir</em> to <acronym title="TermBase eXchange">TBX</acronym> files placed in <em>tbx-target-dir</em>.
+This will convert <acronym title="Comma Separated Value">CSV</acronym> files in <em>csv-dir</em> to <acronym title="TermBase eXchange">TBX</acronym> files placed in <em>tbx-target-dir</em>.
 
 </p>
 <pre class="code">csv2tbx --charset=windows-1250 csv tbx</pre>
@@ -141,7 +141,7 @@
 <p>
 
 Users working on Windows will often return files in encoding other the Unicode based encodings.  In this case we convert
-<acronym title="Comma Seperated Value">CSV</acronym> files found in <em>csv</em> from <em>windows-1250</em> to UTF-8 and place the correctly encoded files in <em>tbx</em>. Note that 
+<acronym title="Comma Separated Value">CSV</acronym> files found in <em>csv</em> from <em>windows-1250</em> to UTF-8 and place the correctly encoded files in <em>tbx</em>. Note that 
 UTF-8 is the only available destination encoding.
 </p>
 

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-developers.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-developers.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-developers.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-developers.html Fri Jul 24 16:25:46 2009
@@ -148,7 +148,7 @@
 </p>
 
 <p>
-To run / test things without installing, see the <a href="pootle-no_install.html" class="wikilink1" title="pootle-no_install.html">instructions for Pootle</a>. Those instructions sets your environment for both Pootle and the toolkit
+To run / test things without installing, see the <a href="pootle-no_install.html" class="wikilink2" title="pootle-no_install.html">instructions for Pootle</a>. Those instructions sets your environment for both Pootle and the toolkit
 </p>
 
 </div>
@@ -282,9 +282,9 @@
 
 </p>
 <ul>
-<li class="level1"><div class="li"> XXelement -- handles the low level individual elements of the file format.  e.g. <acronym title="Gettext Portable Object">PO</acronym> message, <acronym title="Comma Seperated Value">CSV</acronym> records, <acronym title="Document Type Definition">DTD</acronym> elements</div>
-</li>
-<li class="level1"><div class="li"> XXfile -- handles the document or file level of the format.  Eg a <acronym title="Gettext Portable Object">PO</acronym> file, a <acronym title="Comma Seperated Value">CSV</acronym> file a <acronym title="Document Type Definition">DTD</acronym> file</div>
+<li class="level1"><div class="li"> XXelement -- handles the low level individual elements of the file format.  e.g. <acronym title="Gettext Portable Object">PO</acronym> message, <acronym title="Comma Separated Value">CSV</acronym> records, <acronym title="Document Type Definition">DTD</acronym> elements</div>
+</li>
+<li class="level1"><div class="li"> XXfile -- handles the document or file level of the format.  Eg a <acronym title="Gettext Portable Object">PO</acronym> file, a <acronym title="Comma Separated Value">CSV</acronym> file a <acronym title="Document Type Definition">DTD</acronym> file</div>
 <ul>
 <li class="level2"><div class="li"> fromlines -- read in a file and initialise the various elements</div>
 </li>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-dtd.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-dtd.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-dtd.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-dtd.html Fri Jul 24 16:25:46 2009
@@ -49,7 +49,7 @@
 <h2><a name="issues" id="issues">Issues</a></h2>
 <div class="level2">
 <ul>
-<li class="level1"><div class="li"> We don't escape character entities like &lt;, &#38; - this doesn't break anything but it would be nicer to see © rather then &copy;</div>
+<li class="level1"><div class="li"> We don't escape character entities like &lt;, &#38; - this doesn't break anything but it would be nicer to see © rather than &copy;</div>
 </li>
 </ul>
 

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-duplicates_duplicatestyle.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-duplicates_duplicatestyle.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-duplicates_duplicatestyle.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-duplicates_duplicatestyle.html Fri Jul 24 16:25:46 2009
@@ -39,20 +39,20 @@
 
 This is the traditional Gettext approach.  All messages with the same source string or English string are merged into one <acronym title="Gettext Portable Object">PO</acronym> message.
 </p>
-<pre class="code po"><pre class="code po">#: file1.dtd:instruction_manual
+<pre class="code po">#: file1.dtd:instruction_manual
 #: file1.dtd:manual_process
 msgid "Manual"
-msgstr ""</pre></pre>
+msgstr ""</pre>
 <p>
 If however the source text is blank (these are often configuration options in Mozilla) then the <em>merge</em> style will use KDE comments as used in the <em>msgid_comment</em> style in order to create unambiquous entries that can still be used for configuration.
 </p>
-<pre class="code po"><pre class="code po">#: file1.dtd:translators_name
+<pre class="code po">#: file1.dtd:translators_name
 msgid "_: file1.dtd:translators_name\n"
 msgstr ""
  
 #: file1.dtd:translators_email
 msgid "_: file1.dtd:translators_email\n"
-msgstr ""</pre></pre>
+msgstr ""</pre>
 </div>
 <!-- SECTION "merge" [1096-1790] -->
 <h2><a name="keep" id="keep">keep</a></h2>
@@ -62,13 +62,13 @@
 
 Duplictes are not merged and each appear in their own message.  This type of <acronym title="Gettext Portable Object">PO</acronym> file will not work with the Gettext tools.
 </p>
-<pre class="code po"><pre class="code po">#: file1.dtd:instruction_manual
+<pre class="code po">#: file1.dtd:instruction_manual
 msgid "Manual"
 msgstr ""
  
 #: file1.dtd:manual_process
 msgid "Manual"
-msgstr ""</pre></pre>
+msgstr ""</pre>
 </div>
 <!-- SECTION "keep" [1791-2062] -->
 <h2><a name="msgid_comment" id="msgid_comment">msgid_comment</a></h2>
@@ -78,7 +78,7 @@
 
 If a duplicates is discovered then we make use of the KDE style comments to make them unique.
 </p>
-<pre class="code po"><pre class="code po">#: file1.dtd:instruction_manual
+<pre class="code po">#: file1.dtd:instruction_manual
 msgid "_: instruction_manual\n"
 "Manual"
 msgstr ""
@@ -86,7 +86,7 @@
 #: file1.dtd:manual_process
 msgid "_: manual_process\n"
 "Manual"
-msgstr ""</pre></pre>
+msgstr ""</pre>
 <p>
 You can see that both the entries <em>instruction_manual</em> and <em>manual_process</em> have source strings of <em>“Manual”</em>.  By adding 
 the KDE style comment we make the messages unique.  This is helful for many people but isn't quite perfect in that in many cases 
@@ -112,7 +112,7 @@
 
 This uses the new feature of gettext that was introduced with gettext 0.15. Several tools might not support it 100%. This option for duplicatestyle was added in version 1.0 of the translate toolkit.
 </p>
-<pre class="code po"><pre class="code po">#: file1.dtd:instruction_manual
+<pre class="code po">#: file1.dtd:instruction_manual
 msgctxt "instruction_manual"
 msgid "Manual"
 msgstr ""
@@ -120,7 +120,7 @@
 #: file1.dtd:manual_process
 msgctxt "manual_process"
 msgid "Manual"
-msgstr ""</pre></pre>
+msgstr ""</pre>
 </div>
 <!-- SECTION "msgctxt" [2896-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-formats.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-formats.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-formats.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-formats.html Fri Jul 24 16:25:46 2009
@@ -99,10 +99,12 @@
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-wiki.html" class="wikilink1" title="toolkit-wiki.html">Wiki</a> - <a href="http://en.wikipedia.org/wiki/dokuwiki" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/dokuwiki">dokuwiki</a> and <a href="http://en.wikipedia.org/wiki/MediaWiki" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/MediaWiki">MediaWiki</a> supported</div>
 </li>
-</ul>
-
-</div>
-<!-- SECTION "Formats of translatable documents" [1012-1279] -->
+<li class="level1"><div class="li"> <a href="toolkit-subtitles.html" class="wikilink1" title="toolkit-subtitles.html">Subtitles</a> - various formats (v1.4)</div>
+</li>
+</ul>
+
+</div>
+<!-- SECTION "Formats of translatable documents" [1012-1322] -->
 <h2><a name="machine_readable_formats" id="machine_readable_formats">Machine readable formats</a></h2>
 <div class="level2">
 <ul>
@@ -113,18 +115,16 @@
 </ul>
 
 </div>
-<!-- SECTION "Machine readable formats" [1280-1364] -->
+<!-- SECTION "Machine readable formats" [1323-1407] -->
 <h2><a name="in_development" id="in_development">In development</a></h2>
 <div class="level2">
 <ul>
 <li class="level1"><div class="li"> <a href="toolkit-wml.html" class="wikilink1" title="toolkit-wml.html">WML</a></div>
 </li>
-<li class="level1"><div class="li"> <a href="http://bugs.locamotion.org/show_bug.cgi?id=703" class="interwiki iw_bug" title="http://bugs.locamotion.org/show_bug.cgi?id=703">Subtitles</a></div>
-</li>
-</ul>
-
-</div>
-<!-- SECTION "In development" [1365-1431] -->
+</ul>
+
+</div>
+<!-- SECTION "In development" [1408-1448] -->
 <h2><a name="unsupported_formats" id="unsupported_formats">Unsupported formats</a></h2>
 <div class="level2">
 
@@ -188,26 +188,22 @@
 </li>
 <li class="level1"><div class="li"> <a href="http://en.wikipedia.org/wiki/Android%20%28mobile%20device%20platform%29" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/Android%20%28mobile%20device%20platform%29">Android</a> <a href="http://code.google.com/android/devel/resources-i18n.html" class="urlextern" title="http://code.google.com/android/devel/resources-i18n.html">resource files</a> specifically <a href="http://code.google.com/android/reference/available-resources.html#stringresources" class="urlextern" title="http://code.google.com/android/reference/available-resources.html#stringresources">string resources</a></div>
 </li>
-<li class="level1"><div class="li"> Subtitling</div>
-<ul>
-<li class="level2"><div class="li"> Both .sub and .srt are the main formats <a href="http://help.youtube.com/support/youtube/bin/answer.py?answer=100077" class="urlextern" title="http://help.youtube.com/support/youtube/bin/answer.py?answer=100077">supported by YouTube</a></div>
-</li>
-<li class="level2"><div class="li"> <a href="http://en.wikipedia.org/wiki/SubViewer" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/SubViewer">SubViewer</a> .sub - the format is outline on the youtube wupport page above.</div>
-</li>
-<li class="level2"><div class="li"> <a href="http://en.wikipedia.org/wiki/SubRip" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/SubRip">SubRip</a> .srt</div>
-</li>
-<li class="level2"><div class="li"> <a href="http://home.gna.org/gaupol/" class="urlextern" title="http://home.gna.org/gaupol/">Gaupol</a> an PyGTK based subtitling tool looks like a good option to get format readers.</div>
-</li>
-</ul>
-</li>
 <li class="level1"><div class="li"> Tcl: .msg files.  <a href="http://www.google.com/codesearch?hl=en&q=show:XvsRBDCljVk:M2kzUbm70Ts:D5EHICz0aaQ&sa=N&ct=rd&cs_p=http://www.scilab.org/download/4.0/scilab-4.0-src.tar.gz&cs_f=scilab-4.0/tcl/scipadsources/msg_files/AddingTranslations.txt" class="urlextern" title="http://www.google.com/codesearch?hl=en&q=show:XvsRBDCljVk:M2kzUbm70Ts:D5EHICz0aaQ&sa=N&ct=rd&cs_p=http://www.scilab.org/download/4.0/scilab-4.0-src.tar.gz&cs_f=scilab-4.0/tcl/scipadsources/msg_files/AddingTranslations.txt">Good documentation</a></div>
 </li>
-<li class="level1"><div class="li"> NSIS installer: <a href="http://trac.vidalia-project.net/browser/vidalia/trunk/src/tools" class="urlextern" title="http://trac.vidalia-project.net/browser/vidalia/trunk/src/tools">Existing C++ implementation</a></div>
-</li>
-</ul>
-
-</div>
-<!-- SECTION "Unsupported formats" [1432-4358] -->
+<li class="level1"><div class="li"> Installers:</div>
+<ul>
+<li class="level2"><div class="li"> NSIS installer: <a href="http://trac.vidalia-project.net/browser/vidalia/trunk/src/tools" class="urlextern" title="http://trac.vidalia-project.net/browser/vidalia/trunk/src/tools">Existing C++ implementation</a></div>
+</li>
+<li class="level2"><div class="li"> WiX - MSI (Microsoft Installer) creator.  <a href="http://wix.mindcapers.com/wiki/Localization" class="urlextern" title="http://wix.mindcapers.com/wiki/Localization">Localization instructions</a>, <a href="http://www.mail-archive.com/wix-users@lists.sourceforge.net/msg15489.html" class="urlextern" title="http://www.mail-archive.com/wix-users@lists.sourceforge.net/msg15489.html">more notes on localisation</a>. This is a custom <acronym title="Extensible Markup Language">XML</acronym> format, another one!</div>
+</li>
+</ul>
+</li>
+<li class="level1"><div class="li"> <a href="http://www.opengroup.org/onlinepubs/009695399/utilities/gencat.html" class="urlextern" title="http://www.opengroup.org/onlinepubs/009695399/utilities/gencat.html">gencat</a>: precedes gettext, looking in man packages is the best information I could find.  Also <a href="http://dev.linuxfoundation.org/navigator/browse/cmd_single.php?cmd=list-by-name&Cname=gencat" class="urlextern" title="http://dev.linuxfoundation.org/navigator/browse/cmd_single.php?cmd=list-by-name&Cname=gencat">LSB requires it</a>.</div>
+</li>
+</ul>
+
+</div>
+<!-- SECTION "Unsupported formats" [1449-4558] -->
 <h2><a name="unlikely_to_be_supported" id="unlikely_to_be_supported">Unlikely to be supported</a></h2>
 <div class="level2">
 
@@ -222,5 +218,5 @@
 </ul>
 
 </div>
-<!-- SECTION "Unlikely to be supported" [4359-] --></body>
+<!-- SECTION "Unlikely to be supported" [4559-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-html.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-html.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-html.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-html.html Fri Jul 24 16:25:46 2009
@@ -23,11 +23,11 @@
 </p>
 
 <p>
-The <acronym title="HyperText Markup Language">HTML</acronym> support is basic so please be aware of that
+The <acronym title="HyperText Markup Language">HTML</acronym> support is basic, so please be aware of that.
 </p>
 
 </div>
-<!-- SECTION "HTML" [1-160] -->
+<!-- SECTION "HTML" [1-162] -->
 <h2><a name="conformance" id="conformance">Conformance</a></h2>
 <div class="level2">
 <ul>
@@ -40,7 +40,7 @@
 </ul>
 
 </div>
-<!-- SECTION "Conformance" [161-444] -->
+<!-- SECTION "Conformance" [163-446] -->
 <h2><a name="references" id="references">References</a></h2>
 <div class="level2">
 <ul>
@@ -49,5 +49,5 @@
 </ul>
 
 </div>
-<!-- SECTION "References" [445-] --></body>
+<!-- SECTION "References" [447-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-important_changes.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-important_changes.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-important_changes.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-important_changes.html Fri Jul 24 16:25:46 2009
@@ -38,11 +38,20 @@
 
 </div>
 <!-- SECTION "trunk" [287-540] -->
-<h2><a name="section" id="section">1.2</a></h2>
-<div class="level2">
-
-</div>
-<!-- SECTION "1.2" [541-557] -->
+<h2><a name="section" id="section">1.3.0</a></h2>
+<div class="level2">
+
+<p>
+Several duplicate styles were removed as has been warned about long before. Please check the recommendations posted at the time that msgctxt was added on how to migrate.
+</p>
+
+</div>
+<!-- SECTION "1.3.0" [541-729] -->
+<h2><a name="section1" id="section1">1.2</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "1.2" [730-746] -->
 <h3><a name="new_formats" id="new_formats">New formats</a></h3>
 <div class="level3">
 
@@ -64,7 +73,7 @@
 </p>
 
 </div>
-<!-- SECTION "New formats" [558-921] -->
+<!-- SECTION "New formats" [747-1110] -->
 <h3><a name="stats_database_change" id="stats_database_change">Stats database change</a></h3>
 <div class="level3">
 
@@ -73,7 +82,7 @@
 </p>
 
 </div>
-<!-- SECTION "Stats database change" [922-1277] -->
+<!-- SECTION "Stats database change" [1111-1466] -->
 <h3><a name="valid_accelerators" id="valid_accelerators">Valid accelerators</a></h3>
 <div class="level3">
 
@@ -83,7 +92,7 @@
 </p>
 
 </div>
-<!-- SECTION "Valid accelerators" [1278-1788] -->
+<!-- SECTION "Valid accelerators" [1467-1977] -->
 <h2><a name="branches" id="branches">branches</a></h2>
 <div class="level2">
 
@@ -93,7 +102,7 @@
 </p>
 
 </div>
-<!-- SECTION "branches" [1789-1965] -->
+<!-- SECTION "branches" [1978-2154] -->
 <h3><a name="toolkit-c-po" id="toolkit-c-po">toolkit-C-po</a></h3>
 <div class="level3">
 
@@ -103,12 +112,12 @@
 </p>
 
 </div>
-<!-- SECTION "toolkit-C-po" [1966-2404] -->
-<h2><a name="section1" id="section1">1.1.1</a></h2>
-<div class="level2">
-
-</div>
-<!-- SECTION "1.1.1" [2405-2423] -->
+<!-- SECTION "toolkit-C-po" [2155-2593] -->
+<h2><a name="section2" id="section2">1.1.1</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "1.1.1" [2594-2612] -->
 <h3><a name="premature_termination_of_dtd_entities" id="premature_termination_of_dtd_entities">Premature termination of DTD entities</a></h3>
 <div class="level3">
 
@@ -122,12 +131,12 @@
 </p>
 
 </div>
-<!-- SECTION "Premature termination of DTD entities" [2424-2929] -->
-<h2><a name="section2" id="section2">1.1</a></h2>
-<div class="level2">
-
-</div>
-<!-- SECTION "1.1" [2930-2947] -->
+<!-- SECTION "Premature termination of DTD entities" [2613-3118] -->
+<h2><a name="section3" id="section3">1.1</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "1.1" [3119-3136] -->
 <h3><a name="oo2po_help_helpcontent2_escaping_fixed" id="oo2po_help_helpcontent2_escaping_fixed">oo2po Help (helpcontent2) escaping fixed</a></h3>
 <div class="level3">
 
@@ -161,7 +170,7 @@
 </p>
 
 </div>
-<!-- SECTION "oo2po Help (helpcontent2) escaping fixed" [2948-4197] -->
+<!-- SECTION "oo2po Help (helpcontent2) escaping fixed" [3137-4386] -->
 <h3><a name="prop2po_uses_developer_comments" id="prop2po_uses_developer_comments">prop2po uses developer comments</a></h3>
 <div class="level3">
 
@@ -175,7 +184,7 @@
 </p>
 
 </div>
-<!-- SECTION "prop2po uses developer comments" [4198-4855] -->
+<!-- SECTION "prop2po uses developer comments" [4387-5044] -->
 <h3><a name="moz2po_no_longer_uses_kde_comments" id="moz2po_no_longer_uses_kde_comments">moz2po no longer uses KDE comments</a></h3>
 <div class="level3">
 
@@ -193,7 +202,7 @@
 </p>
 
 </div>
-<!-- SECTION "moz2po no longer uses KDE comments" [4856-6041] -->
+<!-- SECTION "moz2po no longer uses KDE comments" [5045-6230] -->
 <h3><a name="read_and_write_mo_files" id="read_and_write_mo_files">Read and Write MO files</a></h3>
 <div class="level3">
 
@@ -207,7 +216,7 @@
 </p>
 
 </div>
-<!-- SECTION "Read and Write MO files" [6042-6390] -->
+<!-- SECTION "Read and Write MO files" [6231-6579] -->
 <h3><a name="read_qt_.qm_files" id="read_qt_.qm_files">Read Qt .qm files</a></h3>
 <div class="level3">
 
@@ -217,12 +226,12 @@
 </p>
 
 </div>
-<!-- SECTION "Read Qt .qm files" [6391-6555] -->
-<h2><a name="section3" id="section3">1.0.1</a></h2>
-<div class="level2">
-
-</div>
-<!-- SECTION "1.0.1" [6556-6574] -->
+<!-- SECTION "Read Qt .qm files" [6580-6744] -->
+<h2><a name="section4" id="section4">1.0.1</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "1.0.1" [6745-6763] -->
 <h3><a name="pot2po_will_create_new_empty_po_files_if_needed" id="pot2po_will_create_new_empty_po_files_if_needed">pot2po will create new empty PO files if needed</a></h3>
 <div class="level3">
 
@@ -232,12 +241,12 @@
 </p>
 
 </div>
-<!-- SECTION "pot2po will create new empty PO files if needed" [6575-7029] -->
-<h2><a name="section4" id="section4">1.0</a></h2>
-<div class="level2">
-
-</div>
-<!-- SECTION "1.0" [7030-7046] -->
+<!-- SECTION "pot2po will create new empty PO files if needed" [6764-7218] -->
+<h2><a name="section5" id="section5">1.0</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "1.0" [7219-7235] -->
 <h3><a name="improved_xliff_support" id="improved_xliff_support">Improved XLIFF support</a></h3>
 <div class="level3">
 
@@ -246,7 +255,7 @@
 </p>
 
 </div>
-<!-- SECTION "Improved XLIFF support" [7047-7247] -->
+<!-- SECTION "Improved XLIFF support" [7236-7436] -->
 <h3><a name="pretty_xml_output" id="pretty_xml_output">Pretty XML output</a></h3>
 <div class="level3">
 
@@ -255,7 +264,7 @@
 </p>
 
 </div>
-<!-- SECTION "Pretty XML output" [7248-7391] -->
+<!-- SECTION "Pretty XML output" [7437-7580] -->
 <h3><a name="fuzzy_matching_in_pot2po_is_optional" id="fuzzy_matching_in_pot2po_is_optional">Fuzzy matching in pot2po is optional</a></h3>
 <div class="level3">
 
@@ -264,7 +273,7 @@
 </p>
 
 </div>
-<!-- SECTION "Fuzzy matching in pot2po is optional" [7392-7708] -->
+<!-- SECTION "Fuzzy matching in pot2po is optional" [7581-7897] -->
 <h3><a name="old_matchlevenshtein.py_can_cause_name_clash" id="old_matchlevenshtein.py_can_cause_name_clash">Old match/Levenshtein.py* can cause name clash</a></h3>
 <div class="level3">
 
@@ -273,7 +282,7 @@
 </p>
 
 </div>
-<!-- SECTION "Old match/Levenshtein.py* can cause name clash" [7709-8236] -->
+<!-- SECTION "Old match/Levenshtein.py* can cause name clash" [7898-8425] -->
 <h3><a name="po_file_layout_now_follows_gettext_more_closely" id="po_file_layout_now_follows_gettext_more_closely">PO file layout now follows Gettext more closely</a></h3>
 <div class="level3">
 
@@ -319,7 +328,7 @@
 </p>
 
 </div>
-<!-- SECTION "PO file layout now follows Gettext more closely" [8237-9899] -->
+<!-- SECTION "PO file layout now follows Gettext more closely" [8426-10088] -->
 <h3><a name="language_awareness" id="language_awareness">Language awareness</a></h3>
 <div class="level3">
 
@@ -328,7 +337,7 @@
 </p>
 
 </div>
-<!-- SECTION "Language awareness" [9900-10443] -->
+<!-- SECTION "Language awareness" [10089-10632] -->
 <h3><a name="new_pofilter_testsnewlines_and_tabs" id="new_pofilter_testsnewlines_and_tabs">New pofilter tests: newlines and tabs</a></h3>
 <div class="level3">
 
@@ -338,7 +347,7 @@
 </p>
 
 </div>
-<!-- SECTION "New pofilter tests: newlines and tabs" [10444-10738] -->
+<!-- SECTION "New pofilter tests: newlines and tabs" [10633-10927] -->
 <h3><a name="merging_can_change_fuzzy_status" id="merging_can_change_fuzzy_status">Merging can change fuzzy status</a></h3>
 <div class="level3">
 
@@ -359,7 +368,7 @@
 </p>
 
 </div>
-<!-- SECTION "Merging can change fuzzy status" [10739-11102] -->
+<!-- SECTION "Merging can change fuzzy status" [10928-11291] -->
 <h3><a name="pofilter_will_make_mozilla_accelerators_a_serious_failure" id="pofilter_will_make_mozilla_accelerators_a_serious_failure">pofilter will make Mozilla accelerators a serious failure</a></h3>
 <div class="level3">
 
@@ -369,7 +378,7 @@
 </p>
 
 </div>
-<!-- SECTION "pofilter will make Mozilla accelerators a serious failure" [11103-11455] -->
+<!-- SECTION "pofilter will make Mozilla accelerators a serious failure" [11292-11644] -->
 <h3><a name="po2prop_can_output_mozilla_or_java_style_properties" id="po2prop_can_output_mozilla_or_java_style_properties">po2prop can output Mozilla or Java style properties</a></h3>
 <div class="level3">
 
@@ -401,7 +410,7 @@
 </p>
 
 </div>
-<!-- SECTION "po2prop can output Mozilla or Java style properties" [11456-12500] -->
+<!-- SECTION "po2prop can output Mozilla or Java style properties" [11645-12689] -->
 <h3><a name="support_for_compressed_files" id="support_for_compressed_files">Support for compressed files</a></h3>
 <div class="level3">
 
@@ -410,12 +419,12 @@
 </p>
 
 </div>
-<!-- SECTION "Support for compressed files" [12501-12922] -->
-<h2><a name="section5" id="section5">0.11</a></h2>
-<div class="level2">
-
-</div>
-<!-- SECTION "0.11" [12923-12940] -->
+<!-- SECTION "Support for compressed files" [12690-13111] -->
+<h2><a name="section6" id="section6">0.11</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "0.11" [13112-13129] -->
 <h3><a name="po2oo_defaults_to_not_check_for_errors" id="po2oo_defaults_to_not_check_for_errors">po2oo defaults to not check for errors</a></h3>
 <div class="level3">
 
@@ -425,7 +434,7 @@
 </p>
 
 </div>
-<!-- SECTION "po2oo defaults to not check for errors" [12941-13350] -->
+<!-- SECTION "po2oo defaults to not check for errors" [13130-13539] -->
 <h3><a name="pofilter_xmltags_produces_less_false_positives" id="pofilter_xmltags_produces_less_false_positives">pofilter xmltags produces less false positives</a></h3>
 <div class="level3">
 
@@ -441,12 +450,12 @@
 </ol>
 
 </div>
-<!-- SECTION "pofilter xmltags produces less false positives" [13351-13823] -->
-<h2><a name="section6" id="section6">0.10</a></h2>
-<div class="level2">
-
-</div>
-<!-- SECTION "0.10" [13824-13841] -->
+<!-- SECTION "pofilter xmltags produces less false positives" [13540-14012] -->
+<h2><a name="section7" id="section7">0.10</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "0.10" [14013-14030] -->
 <h3><a name="po_to_xliff_conversion" id="po_to_xliff_conversion">PO to XLIFF conversion</a></h3>
 <div class="level3">
 
@@ -456,7 +465,7 @@
 </p>
 
 </div>
-<!-- SECTION "PO to XLIFF conversion" [13842-14098] -->
+<!-- SECTION "PO to XLIFF conversion" [14031-14287] -->
 <h3><a name="pot2po_can_replace_msgmerge" id="pot2po_can_replace_msgmerge">pot2po can replace msgmerge</a></h3>
 <div class="level3">
 
@@ -475,7 +484,7 @@
 </p>
 
 </div>
-<!-- SECTION "pot2po can replace msgmerge" [14099-14941] -->
+<!-- SECTION "pot2po can replace msgmerge" [14288-15130] -->
 <h3><a name="properties_pretty_formatting" id="properties_pretty_formatting">.properties pretty formatting</a></h3>
 <div class="level3">
 
@@ -497,12 +506,12 @@
 </p>
 
 </div>
-<!-- SECTION ".properties pretty formatting" [14942-15616] -->
-<h2><a name="section7" id="section7">0.9</a></h2>
-<div class="level2">
-
-</div>
-<!-- SECTION "0.9" [15617-15634] -->
+<!-- SECTION ".properties pretty formatting" [15131-15805] -->
+<h2><a name="section8" id="section8">0.9</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "0.9" [15806-15823] -->
 <h3><a name="escaping_-_dtd_files_are_no_longer_escaped" id="escaping_-_dtd_files_are_no_longer_escaped">Escaping - DTD files are no longer escaped</a></h3>
 <div class="level3">
 
@@ -529,17 +538,17 @@
 We did not make this backward compatible as the fix is relatively simple and is one 
 you would have done for any migration of your <acronym title="Gettext Portable Object">PO</acronym> files.
 </p>
-<pre class="code bash"><pre class="code bash"><span class="re3"># <span class="nu0">1</span>. Create a new <span class="kw3">set</span> of POT files</span>
+<pre class="code bash"><span class="co0"># 1. Create a new set of POT files</span>
 moz2po -P mozilla pot 
-<span class="re3"># <span class="nu0">2</span>. Migrate your old PO files</span>
+<span class="co0"># 2. Migrate your old PO files</span>
 pomigrate2 old new pot
-<span class="re3"># 3a. Fix all the fuzzy translations by editing your PO files</span>
-<span class="re3"># 3b. Use pofilter to check <span class="kw1">for</span> escaping problems and fix them</span>
+<span class="co0"># 3a. Fix all the fuzzy translations by editing your PO files</span>
+<span class="co0"># 3b. Use pofilter to check for escaping problems and fix them</span>
 pofilter -t escapes new new-check
-<span class="re3"># Edit file <span class="kw1">in</span> new-check <span class="kw1">in</span> your PO editor</span>
-pomerge -t new -i new-check -o new-check</pre></pre>
-</div>
-<!-- SECTION "Escaping - DTD files are no longer escaped" [15635-16889] -->
+<span class="co0"># Edit file in new-check in your PO editor</span>
+pomerge -t new -i new-check -o new-check</pre>
+</div>
+<!-- SECTION "Escaping - DTD files are no longer escaped" [15824-17078] -->
 <h3><a name="migration_to_base_class" id="migration_to_base_class">Migration to base class</a></h3>
 <div class="level3">
 
@@ -566,7 +575,7 @@
 </p>
 
 </div>
-<!-- SECTION "Migration to base class" [16890-18004] -->
+<!-- SECTION "Migration to base class" [17079-18193] -->
 <h3><a name="duplicate_merging_in_po_files_-_merge_now_the_default" id="duplicate_merging_in_po_files_-_merge_now_the_default">Duplicate Merging in PO files - merge now the default</a></h3>
 <div class="level3">
 
@@ -588,7 +597,7 @@
 </p>
 
 </div>
-<!-- SECTION "Duplicate Merging in PO files - merge now the default" [18005-18949] -->
+<!-- SECTION "Duplicate Merging in PO files - merge now the default" [18194-19138] -->
 <h3><a name="properties_files_no_longer_use_escaped_unicode" id="properties_files_no_longer_use_escaped_unicode">.properties files no longer use escaped Unicode</a></h3>
 <div class="level3">
 
@@ -600,10 +609,10 @@
 </p>
 
 </div>
-<!-- SECTION ".properties files no longer use escaped Unicode" [18950-19573] -->
-<h2><a name="section8" id="section8">0.8</a></h2>
-<div class="level2">
-
-</div>
-<!-- SECTION "0.8" [19574-] --></body>
+<!-- SECTION ".properties files no longer use escaped Unicode" [19139-19762] -->
+<h2><a name="section9" id="section9">0.8</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "0.8" [19763-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-index.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-index.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-index.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-index.html Fri Jul 24 16:25:46 2009
@@ -72,14 +72,12 @@
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-using_pofilter.html" class="wikilink1" title="toolkit-using_pofilter.html">Checking for technical errors in your translations</a></div>
 </li>
-<li class="level1"><div class="li"> <a href="toolkit-using_csv2po.html" class="wikilink1" title="toolkit-using_csv2po.html">Translating using only a spreadsheet</a> (a look at the whole roundtrip from <acronym title="Gettext Portable Object">PO</acronym> to <acronym title="Comma Seperated Value">CSV</acronym> and back)</div>
+<li class="level1"><div class="li"> <a href="toolkit-using_csv2po.html" class="wikilink1" title="toolkit-using_csv2po.html">Translating using only a spreadsheet</a> (a look at the whole roundtrip from <acronym title="Gettext Portable Object">PO</acronym> to <acronym title="Comma Separated Value">CSV</acronym> and back)</div>
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-using_oo2po.html" class="wikilink1" title="toolkit-using_oo2po.html">Creating OpenOffice.org POT files</a></div>
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-creating_mozilla_pot_files.html" class="wikilink1" title="toolkit-creating_mozilla_pot_files.html">Creating Mozilla POT files</a></div>
 </li>
-<li class="level1"><div class="li"> <a href="toolkit-migrating_to_firefox.html" class="wikilink1" title="toolkit-migrating_to_firefox.html">Migrating Mozilla translations to Firefox</a></div>
-</li>
 <li class="level1"><div class="li"> <a href="toolkit-checking_for_inconsistencies.html" class="wikilink1" title="toolkit-checking_for_inconsistencies.html">Checking for inconsistencies in your translations</a></div>
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-creating_a_terminology_list_from_your_existing_translations.html" class="wikilink1" title="toolkit-creating_a_terminology_list_from_your_existing_translations.html">Creating a terminology list from your existing translations</a></div>
@@ -93,7 +91,7 @@
 </ul>
 
 </div>
-<!-- SECTION "Use Cases" [1777-2617] -->
+<!-- SECTION "Use Cases" [1777-2538] -->
 <h1><a name="converters" id="converters">Converters</a></h1>
 <div class="level1">
 
@@ -107,15 +105,15 @@
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-oo2po.html" class="wikilink1" title="toolkit-oo2po.html">oo2po</a> - OpenOffice.org SDF converter (See also <a href="toolkit-oo2xliff.html" class="wikilink1" title="toolkit-oo2xliff.html">oo2xliff</a>).</div>
 </li>
-<li class="level1"><div class="li"> <a href="toolkit-csv2po.html" class="wikilink1" title="toolkit-csv2po.html">csv2po</a> - Comma Separated Value (<acronym title="Comma Seperated Value">CSV</acronym>) converter. Useful for doing translations using a spreadsheet.</div>
-</li>
-<li class="level1"><div class="li"> <a href="toolkit-csv2tbx.html" class="wikilink1" title="toolkit-csv2tbx.html">csv2tbx</a> - Create <acronym title="TermBase eXchange">TBX</acronym> (TermBase eXchange) files from Comma Separated Value (<acronym title="Comma Seperated Value">CSV</acronym>) files</div>
+<li class="level1"><div class="li"> <a href="toolkit-csv2po.html" class="wikilink1" title="toolkit-csv2po.html">csv2po</a> - Comma Separated Value (<acronym title="Comma Separated Value">CSV</acronym>) converter. Useful for doing translations using a spreadsheet.</div>
+</li>
+<li class="level1"><div class="li"> <a href="toolkit-csv2tbx.html" class="wikilink1" title="toolkit-csv2tbx.html">csv2tbx</a> - Create <acronym title="TermBase eXchange">TBX</acronym> (TermBase eXchange) files from Comma Separated Value (<acronym title="Comma Separated Value">CSV</acronym>) files</div>
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-html2po.html" class="wikilink1" title="toolkit-html2po.html">html2po</a> - <acronym title="HyperText Markup Language">HTML</acronym> converter</div>
 </li>
-<li class="level1"><div class="li"> <a href="toolkit-ical2po.html" class="wikilink1" title="toolkit-ical2po.html">ical2po</a> - iCalendar file converter (v1.2)</div>
-</li>
-<li class="level1"><div class="li"> <a href="toolkit-ini2po.html" class="wikilink1" title="toolkit-ini2po.html">ini2po</a> - Windows INI file converter (v1.1.1)</div>
+<li class="level1"><div class="li"> <a href="toolkit-ical2po.html" class="wikilink1" title="toolkit-ical2po.html">ical2po</a> - iCalendar file converter</div>
+</li>
+<li class="level1"><div class="li"> <a href="toolkit-ini2po.html" class="wikilink1" title="toolkit-ini2po.html">ini2po</a> - Windows INI file converter</div>
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-odf2xliff.html" class="wikilink1" title="toolkit-odf2xliff.html">odf2xliff</a> - Convert OpenDocument (ODF) documents to <acronym title="XML Localization Interchange File Format">XLIFF</acronym> and vice-versa.</div>
 </li>
@@ -129,7 +127,13 @@
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-prop2po.html" class="wikilink1" title="toolkit-prop2po.html">prop2po</a> - Java property file (.properties) converter</div>
 </li>
-<li class="level1"><div class="li"> <a href="toolkit-rc2po.html" class="wikilink1" title="toolkit-rc2po.html">rc2po</a> - Windows Resource .rc (C++ Resource Compiler) converter (v1.2)</div>
+<li class="level1"><div class="li"> <a href="toolkit-py2web2po.html" class="wikilink1" title="toolkit-py2web2po.html">web2py2po</a> - web2py translation to <acronym title="Gettext Portable Object">PO</acronym> converter</div>
+</li>
+<li class="level1"><div class="li"> <a href="toolkit-rc2po.html" class="wikilink1" title="toolkit-rc2po.html">rc2po</a> - Windows Resource .rc (C++ Resource Compiler) converter</div>
+</li>
+<li class="level1"><div class="li"> <a href="toolkit-sub2po.html" class="wikilink1" title="toolkit-sub2po.html">sub2po</a> - Converter for various subtitle files</div>
+</li>
+<li class="level1"><div class="li"> <a href="toolkit-symb2po.html" class="wikilink1" title="toolkit-symb2po.html">symb2po</a> - Symbian-style translation to <acronym title="Gettext Portable Object">PO</acronym> converter</div>
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-tiki2po.html" class="wikilink1" title="toolkit-tiki2po.html">tiki2po</a> - <a href="http://tikiwiki.org/" class="urlextern" title="http://tikiwiki.org/">TikiWiki</a> language.php converter</div>
 </li>
@@ -139,12 +143,10 @@
 </li>
 <li class="level1"><div class="li"> <a href="toolkit-xliff2po.html" class="wikilink1" title="toolkit-xliff2po.html">xliff2po</a> - <acronym title="XML Localization Interchange File Format">XLIFF</acronym> (<acronym title="Extensible Markup Language">XML</acronym> Localisation Interchange File Format) converter</div>
 </li>
-<li class="level1"><div class="li"> <a href="toolkit-symb2po.html" class="wikilink1" title="toolkit-symb2po.html">symb2po</a> - Symbian-style translation to <acronym title="Gettext Portable Object">PO</acronym> converter (not in an official release yet)</div>
-</li>
-</ul>
-
-</div>
-<!-- SECTION "Converters" [2618-4087] -->
+</ul>
+
+</div>
+<!-- SECTION "Converters" [2539-4071] -->
 <h1><a name="tools" id="tools">Tools</a></h1>
 <div class="level1">
 
@@ -154,7 +156,7 @@
 </p>
 
 </div>
-<!-- SECTION "Tools" [4088-4170] -->
+<!-- SECTION "Tools" [4072-4154] -->
 <h3><a name="quality_assurance" id="quality_assurance">Quality Assurance</a></h3>
 <div class="level3">
 
@@ -176,7 +178,7 @@
 </ul>
 
 </div>
-<!-- SECTION "Quality Assurance" [4171-4672] -->
+<!-- SECTION "Quality Assurance" [4155-4656] -->
 <h3><a name="other_tools" id="other_tools">Other tools</a></h3>
 <div class="level3">
 <ul>
@@ -201,7 +203,7 @@
 </ul>
 
 </div>
-<!-- SECTION "Other tools" [4673-5592] -->
+<!-- SECTION "Other tools" [4657-5576] -->
 <h1><a name="scripts" id="scripts">Scripts</a></h1>
 <div class="level1">
 
@@ -235,5 +237,5 @@
 </ul>
 
 </div>
-<!-- SECTION "Scripts" [5593-] --></body>
+<!-- SECTION "Scripts" [5577-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-ini2po.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-ini2po.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-ini2po.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-ini2po.html Fri Jul 24 16:25:46 2009
@@ -22,13 +22,8 @@
 Converts .ini files to Gettext <acronym title="Gettext Portable Object">PO</acronym> format.
 </p>
 
-<p>
-<p><div class="noteclassic">New in v1.1.1
-</div></p>
-</p>
-
-</div>
-<!-- SECTION "ini2po" [1-93] -->
+</div>
+<!-- SECTION "ini2po" [1-65] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
 <pre class="code">ini2po [options] <ini> <po>
@@ -134,7 +129,7 @@
 </table>
 
 </div>
-<!-- SECTION "Usage" [94-2277] -->
+<!-- SECTION "Usage" [66-2249] -->
 <h2><a name="examples" id="examples">Examples</a></h2>
 <div class="level2">
 
@@ -185,7 +180,7 @@
 </p>
 
 </div>
-<!-- SECTION "Examples" [2278-3609] -->
+<!-- SECTION "Examples" [2250-3581] -->
 <h2><a name="issues" id="issues">Issues</a></h2>
 <div class="level2">
 
@@ -195,7 +190,7 @@
 </p>
 
 </div>
-<!-- SECTION "Issues" [3610-3767] -->
+<!-- SECTION "Issues" [3582-3739] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 
@@ -206,5 +201,5 @@
 </p>
 
 </div>
-<!-- SECTION "Bugs" [3768-] --></body>
+<!-- SECTION "Bugs" [3740-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-migrating_to_firefox.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-migrating_to_firefox.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-migrating_to_firefox.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-migrating_to_firefox.html Fri Jul 24 16:25:46 2009
@@ -29,7 +29,7 @@
 </p>
 
 <p>
-<img src="images/smileys/fixme.gif" align="middle" alt="FIXME" /> this page needs to be rewriten now that Mozilla is using <acronym title="Comma Seperated Value">CSV</acronym>.  The steps are more or less the same.  Look at <a href="toolkit-creating_mozilla_pot_files.html" class="wikilink1" title="toolkit-creating_mozilla_pot_files.html">creating mozilla POT files</a> which talks about creating <acronym title="Gettext Portable Object Template">POT</acronym> file from <acronym title="Concurrent Versions System">CVS</acronym>. Then the process is mostly the same except swap any reference to <acronym title="Cross Platform Installer">XPI</acronym> to be the translations in Mozilla <acronym title="Concurrent Versions System">CVS</acronym>.
+<img src="images/smileys/fixme.gif" align="middle" alt="FIXME" /> this page needs to be rewriten now that Mozilla is using <acronym title="Comma Separated Value">CSV</acronym>.  The steps are more or less the same.  Look at <a href="toolkit-creating_mozilla_pot_files.html" class="wikilink1" title="toolkit-creating_mozilla_pot_files.html">creating mozilla POT files</a> which talks about creating <acronym title="Gettext Portable Object Template">POT</acronym> file from <acronym title="Concurrent Versions System">CVS</acronym>. Then the process is mostly the same except swap any reference to <acronym title="Cross Platform Installer">XPI</acronym> to be the translations in Mozilla <acronym title="Concurrent Versions System">CVS</acronym>.
 </p>
 
 </div>
@@ -93,7 +93,7 @@
 Now create the Mozilla <acronym title="Gettext Portable Object">PO</acronym> files for your language using your existing <acronym title="Cross Platform Installer">XPI</acronym> and
 the en-US <acronym title="Cross Platform Installer">XPI</acronym>.
 </p>
-<pre class="code bash"><pre class="code bash">moz2po -t mozilla<span class="nu0">-1.7</span><span class="nu0">.3</span>-langenus.xpi langXXYY.xpi xxYY<span class="nu0">-1.7</span><span class="nu0">.3</span></pre></pre>
+<pre class="code bash">moz2po -t mozilla<span class="nu0">-1.7</span><span class="nu0">.3</span>-langenus.xpi langXXYY.xpi xxYY<span class="nu0">-1.7</span><span class="nu0">.3</span></pre>
 <p>
 Where:
 </p>
@@ -138,7 +138,7 @@
 
 <h4><a name="create_the_pot_files" id="create_the_pot_files">Create the POT files</a></h4>
 <div class="level4">
-<pre class="code bash"><pre class="code bash">moz2po -P firefox<span class="nu0">-1.0</span>-en-US.xpi templates-ff<span class="nu0">-1.0</span></pre></pre>
+<pre class="code bash">moz2po -P firefox<span class="nu0">-1.0</span>-en-US.xpi templates-ff<span class="nu0">-1.0</span></pre>
 <p>
 Where:
 </p>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-mozilla_l10n_scripts.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-mozilla_l10n_scripts.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-mozilla_l10n_scripts.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-mozilla_l10n_scripts.html Fri Jul 24 16:25:46 2009
@@ -34,24 +34,33 @@
 All of these scripts are available on Subversion from <a href="https://translate.svn.sourceforge.net/svnroot/translate/src/trunk/tools/mozilla/" class="urlextern" title="https://translate.svn.sourceforge.net/svnroot/translate/src/trunk/tools/mozilla/">here</a>.
 </p>
 
-</div>
-<!-- SECTION "Introduction" [36-526] -->
+<p>
+We are currently generating <acronym title="Gettext Portable Object Template">POT</acronym> files for most major betas, RCs and releases of Firefox and Thunderbird. They are available here:
+<a href="http://l10n.mozilla.org/pootle/pot/" class="urlextern" title="http://l10n.mozilla.org/pootle/pot/">http://l10n.mozilla.org/pootle/pot/</a>
+</p>
+
+<p>
+As a start you might want to just use these <acronym title="Gettext Portable Object Template">POT</acronym> files and gradually learn more about the processes described below. Contact us for more help on using these.
+</p>
+
+</div>
+<!-- SECTION "Introduction" [36-850] -->
 <h2><a name="requirements" id="requirements">Requirements</a></h2>
 <div class="level2">
 <ul>
-<li class="level1"><div class="li"> The <a href="toolkit-index.html" class="wikilink1" title="toolkit-index.html">Translate Toolkit</a></div>
+<li class="level1"><div class="li"> The <a href="toolkit-index.html" class="wikilink1" title="toolkit-index.html">Translate Toolkit</a> (>=1.3)</div>
 </li>
 <li class="level1"><div class="li"> All scripts in the <code>tools/mozilla</code> directory (from the project sources) should be executable and in your <code>PATH</code>.</div>
 </li>
 </ul>
 
 </div>
-<!-- SECTION "Requirements" [527-718] -->
+<!-- SECTION "Requirements" [851-1050] -->
 <h2><a name="build_ff3.1_langs.sh" id="build_ff3.1_langs.sh">build_ff3.1_langs.sh</a></h2>
 <div class="level2">
 
 </div>
-<!-- SECTION "build_ff3.1_langs.sh" [719-751] -->
+<!-- SECTION "build_ff3.1_langs.sh" [1051-1083] -->
 <h3><a name="description" id="description">Description</a></h3>
 <div class="level3">
 
@@ -88,10 +97,11 @@
 <p>
 
 This script is used on the l10n.mozilla.org server to create most (if not all) of the files available from <a href="http://l10n.mozilla.org/pootle/" class="urlextern" title="http://l10n.mozilla.org/pootle/">http://l10n.mozilla.org/pootle/</a>. It was originally written as a stable way to provide these files and as such making it as general as possible was not the biggest requirement. This is evident in the script's very narrow focus.
-</p>
-
-</div>
-<!-- SECTION "Description" [752-1942] -->
+
+</p>
+
+</div>
+<!-- SECTION "Description" [1084-2273] -->
 <h3><a name="usage" id="usage">Usage</a></h3>
 <div class="level3">
 
@@ -110,10 +120,10 @@
 		<td class="col0"><code>MOZCENTRAL_DIR</code></td><td class="col1"> The directory containing a checkout of the Mozilla source tree (from <a href="http://hg.mozilla.org/mozilla-central/" class="urlextern" title="http://hg.mozilla.org/mozilla-central/">http://hg.mozilla.org/mozilla-central/</a>). </td>
 	</tr>
 	<tr class="row2">
-		<td class="col0"><code>HG_LANGS</code></td><td class="col1"> A space-seperated list of language codes to build for. </td>
+		<td class="col0"><code>HG_LANGS</code></td><td class="col1"> A space-separated list of language codes to build for. </td>
 	</tr>
 	<tr class="row3">
-		<td class="col0"><code>L10N_DIR</code></td><td class="col1"> The directory where Mozilla l10n files should be collected. </td>
+		<td class="col0"><code>L10N_DIR</code></td><td class="col1"> The directory where Mozilla l10n files (from l10n-central) should be collected. </td>
 	</tr>
 	<tr class="row4">
 		<td class="col0"><code><acronym title="Gettext Portable Object">PO</acronym>_DIR</code></td><td class="col1"> The directory containing the externally-hosted or previously available source <acronym title="Gettext Portable Object">PO</acronym> files (ex. <acronym title="Gettext Portable Object">PO</acronym> files managed in another VCS repository). It contains a sub-directory for each language. </td>
@@ -125,7 +135,7 @@
 		<td class="col0"><code>PORECOVER_DIR</code></td><td class="col1"> The directory to put recovered <acronym title="Gettext Portable Object">PO</acronym> files in. It contains a sub-directory for each language. </td>
 	</tr>
 	<tr class="row7">
-		<td class="col0"><code><acronym title="Gettext Portable Object Template">POT</acronym>_INCLUDES</code></td><td class="col1"> A space-seperated list of files to be included in <acronym title="Gettext Portable Object Template">POT</acronym> archives. </td>
+		<td class="col0"><code><acronym title="Gettext Portable Object Template">POT</acronym>_INCLUDES</code></td><td class="col1"> A space-separated list of files to be included in <acronym title="Gettext Portable Object Template">POT</acronym> archives. </td>
 	</tr>
 	<tr class="row8">
 		<td class="col0"><code>POTPACK_DIR</code></td><td class="col1"> The output directory for <acronym title="Gettext Portable Object Template">POT</acronym> archives. </td>
@@ -141,22 +151,32 @@
 	</tr>
 </table>
 
-</div>
-<!-- SECTION "Usage" [1943-3308] -->
+<p>
+
+<p><div class="noteclassic">It is <strong>strongly</strong> recommended that you mirror the directory structure specified by the default values of the <code>*_DIR</code> variables. For example the default value for <code>L10N_DIR</code> is <code>${BUILD_DIR}/l10n</code>, then you should put your l10n-central check-outs in the <code>l10n</code> directory under your main build directory (<code>BUILD_DIR</code>).
+</p>
+
+<p>
+Basically, you should have an ideally separate build directory containing the following sub-directories: <code>l10n</code>, <code>mozilla-central</code>, <code>po</code>, <code>popacks</code>, <code>potpacks</code>, <code>po-updated</code> and <code>xpi</code> (if used). This way the only variable that need to be changed is <code>BUILD_DIR</code>.
+</div></p>
+</p>
+
+</div>
+<!-- SECTION "Usage" [2274-4280] -->
 <h2><a name="build_tb3_langs.sh" id="build_tb3_langs.sh">build_tb3_langs.sh</a></h2>
 <div class="level2">
 
 <p>
-This is the script that the <code>build_ff3.1_langs.sh</code> script above was actually adapted from. It is 90% similar with the obvious exception that it is aimed at building Thunderbird 3.0 packages in stead of Firefox 3.1.
-</p>
-
-</div>
-<!-- SECTION "build_tb3_langs.sh" [3309-3558] -->
+This is the script that the <code>build_ff3.1_langs.sh</code> script above was actually adapted from. It is 90% similar with the obvious exception that it is aimed at building Thunderbird 3.0 packages in stead of Firefox 3.1. Also note that this script uses the comm-central repository in stead of mozilla-central.
+</p>
+
+</div>
+<!-- SECTION "build_tb3_langs.sh" [4281-4619] -->
 <h2><a name="buildxpi.py" id="buildxpi.py">buildxpi.py</a></h2>
 <div class="level2">
 
 </div>
-<!-- SECTION "buildxpi.py" [3559-3582] -->
+<!-- SECTION "buildxpi.py" [4620-4643] -->
 <h3><a name="description1" id="description1">Description</a></h3>
 <div class="level3">
 
@@ -177,7 +197,7 @@
 </p>
 
 </div>
-<!-- SECTION "Description" [3583-4189] -->
+<!-- SECTION "Description" [4644-5250] -->
 <h3><a name="usage1" id="usage1">Usage</a></h3>
 <div class="level3">
 <pre class="code">buildxpi.py -L /path/to/l10n -s /path/to/mozilla-central -o /path/to/xpi_output af</pre>
@@ -198,12 +218,12 @@
 </table>
 
 </div>
-<!-- SECTION "Usage" [4190-4931] -->
+<!-- SECTION "Usage" [5251-5992] -->
 <h2><a name="get_moz_enus.py" id="get_moz_enus.py">get_moz_enUS.py</a></h2>
 <div class="level2">
 
 </div>
-<!-- SECTION "get_moz_enUS.py" [4932-4959] -->
+<!-- SECTION "get_moz_enUS.py" [5993-6020] -->
 <h3><a name="description2" id="description2">Description</a></h3>
 <div class="level3">
 
@@ -212,7 +232,7 @@
 </p>
 
 </div>
-<!-- SECTION "Description" [4960-5150] -->
+<!-- SECTION "Description" [6021-6211] -->
 <h3><a name="usage2" id="usage2">Usage</a></h3>
 <div class="level3">
 <pre class="code">get_moz_enUS.py [options]</pre>
@@ -243,7 +263,7 @@
 </table>
 
 </div>
-<!-- SECTION "Usage" [5151-5700] -->
+<!-- SECTION "Usage" [6212-6761] -->
 <h2><a name="moz-l10n-builder" id="moz-l10n-builder">moz-l10n-builder</a></h2>
 <div class="level2">
 
@@ -260,7 +280,7 @@
 </p>
 
 </div>
-<!-- SECTION "moz-l10n-builder" [5701-6111] -->
+<!-- SECTION "moz-l10n-builder" [6762-7172] -->
 <h2><a name="moz_l10n_builder.py" id="moz_l10n_builder.py">moz_l10n_builder.py</a></h2>
 <div class="level2">
 
@@ -270,5 +290,5 @@
 </p>
 
 </div>
-<!-- SECTION "moz_l10n_builder.py" [6112-] --></body>
+<!-- SECTION "moz_l10n_builder.py" [7173-] --></body>
 </html>

Added: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-odf.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-odf.html?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-odf.html (added)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-odf.html Fri Jul 24 16:25:46 2009
@@ -1,0 +1,47 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+  <title></title>
+  <link rel="stylesheet" media="screen" type="text/css" href="./style.css" />
+  <link rel="stylesheet" media="screen" type="text/css" href="./design.css" />
+  <link rel="stylesheet" media="print" type="text/css" href="./print.css" />
+
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+</head>
+<body>
+<a href=.>start</a></br>
+
+
+
+<h1><a name="opendocument_format" id="opendocument_format">OpenDocument Format</a></h1>
+<div class="level1">
+
+<p>
+This page summarises the support for the <a href="http://en.wikipedia.org/wiki/OpenDocument" class="urlextern" title="http://en.wikipedia.org/wiki/OpenDocument">OpenDocument format</a> (ODF) in the Translate Toolkit. This currently involves only the <a href="toolkit-odf2xliff.html" class="wikilink1" title="toolkit-odf2xliff.html">odf2xliff</a> and xliff2odf converters.
+</p>
+
+<p>
+The Translate Toolkit aims to support version 1.1 of the ODF standard, although it should work reasonably well with older or newer files to the extent that they are similar.
+</p>
+
+<p>
+Our support is implemented to classify tags as not containing translatable text, or as being inline tags inside translatable tags. This approach means that new fields added in future versions will automatically be seen as translatable and should still be extracted successfully, even if the currently released versions of the Translate Toolkit are not aware of their existence.
+</p>
+
+<p>
+The current list of classified tags used, can be viewed here: 
+</p>
+
+<p>
+<a href="http://translate.svn.sourceforge.net/viewvc/translate/src/trunk/translate/storage/odf_shared.py?view=log" class="urlextern" title="http://translate.svn.sourceforge.net/viewvc/translate/src/trunk/translate/storage/odf_shared.py?view=log">http://translate.svn.sourceforge.net/viewvc/translate/src/trunk/translate/storage/odf_shared.py?view=log</a>
+</p>
+
+<p>
+More complex tag uses are still needed to extract 100% correctly in some complex cases. For more information, see the list of <a href="odf-testing.html" class="wikilink2" title="odf-testing.html">issues from testing</a>. 
+
+</p>
+
+</div>
+</body>
+</html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-odf2xliff.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-odf2xliff.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-odf2xliff.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-odf2xliff.html Fri Jul 24 16:25:46 2009
@@ -24,7 +24,7 @@
 
 <p>
 <acronym title="XML Localization Interchange File Format">XLIFF</acronym> is the <acronym title="Extensible Markup Language">XML</acronym> Localization Interchange File Format 
-developed by <a href="http://lisa.org/" class="urlextern" title="http://lisa.org/">LISA</a> (The Localization Industry Standards Authority) to allow translation
+developed by <a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xliff" class="urlextern" title="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xliff">OASIS</a> (The Organization for the Advancement of Structured Information Standards) to allow translation
 work to be standardised no matter what the source format and to allow the work to be freely moved from tool to
 tool.
 </p>
@@ -34,7 +34,7 @@
 </p>
 
 </div>
-<!-- SECTION "odf2xliff and xliff2odf" [1-719] -->
+<!-- SECTION "odf2xliff and xliff2odf" [1-795] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
 <pre class="code">odf2xliff [options] <original_odf> <xliff>
@@ -124,7 +124,7 @@
 </table>
 
 </div>
-<!-- SECTION "Usage" [720-2453] -->
+<!-- SECTION "Usage" [796-2529] -->
 <h2><a name="examples" id="examples">Examples</a></h2>
 <div class="level2">
 <pre class="code">odf2xliff english.odt english_français.xlf</pre>
@@ -142,16 +142,16 @@
 </p>
 
 </div>
-<!-- SECTION "Examples" [2454-2856] -->
+<!-- SECTION "Examples" [2530-2932] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 
 <p>
 
-This filter is not yet extensively used - we appreciate your feedback.  See <a href="toolkit-xliff.html" class="wikilink1" title="toolkit-xliff.html">xliff</a> to see how well our implementation conforms to the <acronym title="XML Localization Interchange File Format">XLIFF</acronym> standard. Possible issues were listed during <a href="odf-testing.html" class="wikilink1" title="odf-testing.html">testing</a>.
+This filter is not yet extensively used - we appreciate your feedback.  For more information on conformance to standards, see the <a href="toolkit-xliff.html" class="wikilink1" title="toolkit-xliff.html">xliff</a> or <a href="toolkit-odf.html" class="wikilink1" title="toolkit-odf.html">odf</a> pages. Possible issues were listed during <a href="odf-testing.html" class="wikilink2" title="odf-testing.html">testing</a>.
 
 </p>
 
 </div>
-<!-- SECTION "Bugs" [2857-] --></body>
+<!-- SECTION "Bugs" [2933-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-personality_type.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-personality_type.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-personality_type.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-personality_type.html Fri Jul 24 16:25:46 2009
@@ -43,7 +43,7 @@
 
 <p>
 
-Mozilla has made slight adjustments to the Java .properties <acronym title="specification">spec</acronym>.  Mozilla will accept UTF-8 encoded strings in the property file and thus does not need escaped Unicode.  Thus the string above string - ṽḁḽṻḝ - will not be escaped.  Mozilla property files are thus more useful for non-Latin languages in that they are actually readable.
+Mozilla has made slight adjustments to the Java .properties <acronym title="specification">spec</acronym>.  Mozilla will accept UTF-8 encoded strings in the property file and thus does not need escaped Unicode.  Thus the above string - ṽḁḽṻḝ - will not be escaped.  Mozilla property files are thus more useful for non-Latin languages in that they are actually readable.
 </p>
 
 <p>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-php.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-php.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-php.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-php.html Fri Jul 24 16:25:46 2009
@@ -19,11 +19,11 @@
 
 <p>
 
-Many <a href="http://en.wikipedia.org/wiki/PHP" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/PHP">PHP</a> programs make use of a localisable string array.  The toolkit support the full localisation of such files.
+Many <a href="http://en.wikipedia.org/wiki/PHP" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/PHP">PHP</a> programs make use of a localisable string array.  The toolkit support the full localisation of such files with <a href="toolkit-php2po.html" class="wikilink1" title="toolkit-php2po.html">php2po</a> and po2php.
 </p>
 
 </div>
-<!-- SECTION "PHP" [1-143] -->
+<!-- SECTION "PHP" [1-170] -->
 <h2><a name="example" id="example">Example</a></h2>
 <div class="level2">
 
@@ -31,10 +31,10 @@
 
 The localisable string arrays appear like this:
 </p>
-<pre class="code php"><pre class="code php"><span class="kw2"><?php</span>
-<span class="re0">$string</span><span class="br0">[</span><span class="st0">'name'</span><span class="br0">]</span> = <span class="st0">'value'</span></pre></pre>
+<pre class="code php"><span class="kw2"><?php</span>
+<span class="re1">$string</span><span class="br0">[</span><span class="st0">'name'</span><span class="br0">]</span> <span class="sy0">=</span> <span class="st0">'value'</span></pre>
 </div>
-<!-- SECTION "Example" [144-265] -->
+<!-- SECTION "Example" [171-292] -->
 <h2><a name="conformance" id="conformance">Conformance</a></h2>
 <div class="level2">
 
@@ -54,7 +54,7 @@
 <span class="re1">$string</span><span class="br0">[</span>name<span class="br0">]</span>
 <span class="re1">$string</span><span class="br0">[</span> <span class="st0">'name'</span> <span class="br0">]</span></pre>
 </div>
-<!-- SECTION "Conformance" [266-690] -->
+<!-- SECTION "Conformance" [293-717] -->
 <h2><a name="non-conformance" id="non-conformance">Non-Conformance</a></h2>
 <div class="level2">
 
@@ -75,5 +75,5 @@
 </ul>
 
 </div>
-<!-- SECTION "Non-Conformance" [691-] --></body>
+<!-- SECTION "Non-Conformance" [718-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po.html Fri Jul 24 16:25:46 2009
@@ -38,10 +38,14 @@
 </li>
 <li class="level1"><div class="li"> Message Context (msgctxt)</div>
 </li>
+<li class="level1"><div class="li"> Language header (since gettext version 0.17)</div>
+</li>
+<li class="level1"><div class="li"> Previous message ID and context (#| msgid and #| msgctxt)</div>
+</li>
 </ul>
 
 </div>
-<!-- SECTION "Supported Features" [220-359] -->
+<!-- SECTION "Supported Features" [220-469] -->
 <h2><a name="supported_comments" id="supported_comments">Supported comments</a></h2>
 <div class="level2">
 <ul>
@@ -57,17 +61,10 @@
 <li class="level1"><div class="li"> typecomments <pre class="code">#, fuzzy</pre>
 </div>
 </li>
-<li class="level1"><div class="li"> visiblecomments <pre class="code">#_ note to translator  (this is nonsense)</pre>
-
-<p>
-This style is no longer used by tools like pofilter, they use normal comments to ensure that they work with Gettext tools.  Handling of these will be removed in the future.
-</p>
-</div>
-</li>
 <li class="level1"><div class="li"> msgidcomments <pre class="code">magid "_: within msgid\n"</pre>
 
 <p>
-Also know as KDE style comments as they are used by KDE for message disambiguation and comments to translators.
+Also know as KDE style comments as they are used by KDE for message disambiguation and comments to translators. (support for this is being phased out)
 </p>
 </div>
 </li>
@@ -76,25 +73,19 @@
 </div>
 </li>
 </ul>
+<ul>
+<li class="level1"><div class="li"> previous msgid and msgctxt <pre class="code"> #| msgid "previous message"</pre>
+</div>
+</li>
+</ul>
 
 </div>
-<!-- SECTION "Supported comments" [360-1114] -->
+<!-- SECTION "Supported comments" [470-1091] -->
 <h2><a name="unsupported_features" id="unsupported_features">Unsupported Features</a></h2>
 <div class="level2">
 
 </div>
-<!-- SECTION "Unsupported Features" [1115-1149] -->
-<h3><a name="previous_msgid" id="previous_msgid">Previous msgid</a></h3>
-<div class="level3">
-<pre class="code">#| msgid "previous message"</pre>
-
-<p>
-
-In Gettext 0.16
-</p>
-
-</div>
-<!-- SECTION "Previous msgid" [1150-1223] -->
+<!-- SECTION "Unsupported Features" [1092-1125] -->
 <h3><a name="alternate_language" id="alternate_language">Alternate language</a></h3>
 <div class="level3">
 <pre class="code">msgid "English"
@@ -102,10 +93,10 @@
 
 <p>
 
-Unsure of when or if this was added to Gettext.
+(This was proposed but not yet accepted in a released version of Gettext.)
 
 </p>
 
 </div>
-<!-- SECTION "Alternate language" [1224-] --></body>
+<!-- SECTION "Alternate language" [1126-] --></body>
 </html>

Added: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po2sub.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po2sub.html?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po2sub.html (added)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po2sub.html Fri Jul 24 16:25:46 2009
@@ -1,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+  <title></title>
+  <link rel="stylesheet" media="screen" type="text/css" href="./style.css" />
+  <link rel="stylesheet" media="screen" type="text/css" href="./design.css" />
+  <link rel="stylesheet" media="print" type="text/css" href="./print.css" />
+
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+</head>
+<body>
+<a href=.>start</a></br>
+<div class="noteredirect">This page has been moved, the new location is <a href="/opt/sf/software/offline-doku-0.1.1/toolkit/sub2po" class="wikilink1" title="toolkit:sub2po">sub2po</a>.</div></body>
+</html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po2wordfast.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po2wordfast.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po2wordfast.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-po2wordfast.html Fri Jul 24 16:25:46 2009
@@ -19,11 +19,6 @@
 
 <p>
 
-<p><div class="noteclassic">Only in v1.1 of the Translate Toolkit
-</div></p>
-</p>
-
-<p>
 Convert Gettext <acronym title="Gettext Portable Object">PO</acronym> files to a <a href="toolkit-wordfast.html" class="wikilink1" title="toolkit-wordfast.html">Wordfast</a> translation memory file.  
 </p>
 
@@ -32,7 +27,7 @@
 </p>
 
 </div>
-<!-- SECTION "po2wordfast" [1-230] -->
+<!-- SECTION "po2wordfast" [1-178] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
 <pre class="code">po2wordfast [options] --language <target> <po> <wordfast></pre>
@@ -91,7 +86,7 @@
 </table>
 
 </div>
-<!-- SECTION "Usage" [231-1260] -->
+<!-- SECTION "Usage" [179-1208] -->
 <h2><a name="examples" id="examples">Examples</a></h2>
 <div class="level2">
 <pre class="code">po2wordfast -l xh-ZA browser.po browser.txt</pre>
@@ -102,5 +97,5 @@
 </p>
 
 </div>
-<!-- SECTION "Examples" [1261-] --></body>
+<!-- SECTION "Examples" [1209-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pocount.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pocount.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pocount.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pocount.html Fri Jul 24 16:25:46 2009
@@ -34,7 +34,7 @@
 <!-- SECTION "pocount" [1-522] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
-<pre class="code">pocount [--csv] [directory|file(s)]</pre>
+<pre class="code">pocount [options] <directory|file(s)></pre>
 
 <p>
 
@@ -43,12 +43,9 @@
 </p>
 <table class="inline">
 	<tr class="row0">
-		<td class="col0 leftalign"> <blank>    </td><td class="col1 leftalign"> will recurse through all files from the current directory  </td>
+		<td class="col0 leftalign"> directory  </td><td class="col1 leftalign"> will recurse and count all files in the specified directory  </td>
 	</tr>
 	<tr class="row1">
-		<td class="col0 leftalign"> directory  </td><td class="col1 leftalign"> will recurse and count all files in the specified directory  </td>
-	</tr>
-	<tr class="row2">
 		<td class="col0 leftalign"> file(s)    </td><td class="col1 leftalign"> will count all files specified  </td>
 	</tr>
 </table>
@@ -60,48 +57,187 @@
 </p>
 <table class="inline">
 	<tr class="row0">
-		<td class="col0 leftalign"> --csv   </td><td class="col1 leftalign"> changes the output format to <acronym title="Comma Seperated Value">CSV</acronym> (Comma Separated Values) for import into a spreadsheet   </td>
+		<td class="col0 leftalign"> -h, --help      </td><td class="col1 leftalign"> show this help message and exit  </td>
+	</tr>
+	<tr class="row1">
+		<td class="col0 leftalign"> --incomplete    </td><td class="col1 leftalign"> skip 100% translated files  </td>
+	</tr>
+	<tr class="row2">
+		<td class="col0 leftalign"> --full          </td><td class="col1 leftalign"> (default) statistics in full, verbose format  </td>
+	</tr>
+	<tr class="row3">
+		<td class="col0 leftalign"> --csv           </td><td class="col1 leftalign"> statistics in <acronym title="Comma Separated Value">CSV</acronym> format  </td>
+	</tr>
+	<tr class="row4">
+		<td class="col0 leftalign"> --short         </td><td class="col1 leftalign"> same as --short-strings  </td>
+	</tr>
+	<tr class="row5">
+		<td class="col0"> --short-strings </td><td class="col1 leftalign"> statistics of strings in short format - one line per file  </td>
+	</tr>
+	<tr class="row6">
+		<td class="col0 leftalign"> --short-words   </td><td class="col1 leftalign"> statistics of words in short format - one line per file  </td>
 	</tr>
 </table>
 
 </div>
-<!-- SECTION "Usage" [523-907] -->
-<h2><a name="output" id="output">Output</a></h2>
-<div class="level2">
-
-<p>
-
-In normal mode the following output is given:
+<!-- SECTION "Usage" [523-1158] -->
+<h2><a name="examples" id="examples">Examples</a></h2>
+<div class="level2">
+
+<p>
+
+pocount makes it easy to count the current state of a body of translations. The most interesting options are those that adjust the output style and decide what to count.
+</p>
+
+</div>
+<!-- SECTION "Examples" [1159-1351] -->
+<h3><a name="easy_counting" id="easy_counting">Easy counting</a></h3>
+<div class="level3">
+
+<p>
+
+To count how much work is to be done in you project:
+
+</p>
+<pre class="code">pocount project/</pre>
+
+<p>
+
+This will count all translatable files found in the directory <em>project</em>/ and output the results in <code>--full</code> format.
+</p>
+
+<p>
+You might want to be more specific and only count certain files
+
+</p>
+<pre class="code">pocount *.po</pre>
+
+<p>
+
+This will count all <acronym title="Gettext Portable Object">PO</acronym> files in the current directory but will ignore any other files that 'pocount' can count.
+</p>
+
+<p>
+You can have full control of the files to count by using some of the abilities of the Unix commandline, these may work on Mac <acronym title="Operating System">OS</acronym> X but are unlikely to work on Windows.
+
+</p>
+<pre class="code">pocount $(find . -name "*.properties.po")</pre>
+
+<p>
+
+This will first find all files that match <code>*.properties.po</code> and then count them.  That would make it easy to count the state of your Mozilla translations of .properties files.
+</p>
+
+</div>
+<!-- SECTION "Easy counting" [1352-2158] -->
+<h3><a name="incomplete_work" id="incomplete_work">Incomplete work</a></h3>
+<div class="level3">
+
+<p>
+
+To count what still needs to be done, ignoring what is 100% complete you can use the <code>--incomplete</code> option.
+
+</p>
+<pre class="code">pocount --incomplete --short *.xlf</pre>
+
+<p>
+
+We are now counting all <acronym title="XML Localization Interchange File Format">XLIFF</acronym> files by using the <code>*.xlf</code> expansion.  We are only counting files that are not 100% complete and we're outputing string counts using the <code>--short</code> option.
+</p>
+
+</div>
+<!-- SECTION "Incomplete work" [2159-2524] -->
+<h2><a name="output_formats" id="output_formats">Output formats</a></h2>
+<div class="level2">
+
+<p>
+
+The output options provide the following types of output
+</p>
+
+</div>
+<!-- SECTION "Output formats" [2525-2610] -->
+<h3><a name="full" id="full">--full</a></h3>
+<div class="level3">
+
+<p>
+
+This is the normal, or default, mode.  It produces the most comprehensive and easy to read data, although the amount of data may overwhelm the user. It produces the following output:
 </p>
 <pre class="code">avmedia/source/viewer.po 
-type           strings words (source) words (translation)
-translated:       1          3               3
-fuzzy:            0          0             n/a
-untranslated:     4         22             n/a
-Total:            5         25               3
-review            1          3             n/a</pre>
-
-<p>
-
-In <acronym title="Comma Seperated Value">CSV</acronym> mode the following output is shown:
+type              strings      words (source)    words (translation)
+translated:   73465 ( 99%)     538598 ( 99%)          513296
+fuzzy:           13 (  0%)        141 (  0%)             n/a
+untranslated:    53 (  0%)        602 (  0%)             n/a
+Total:        73531            539341                 513296</pre>
+
+<p>
+
+A grand total and file count is provided if the number of files is greater than one.
+</p>
+
+</div>
+<!-- SECTION "--full" [2611-3249] -->
+<h3><a name="csv" id="csv">--csv</a></h3>
+<div class="level3">
+
+<p>
+
+This format is useful if you want to reuse the data in a spreadsheet.  In <acronym title="Comma Separated Value">CSV</acronym> mode the following output is shown:
 </p>
 <pre class="code">Filename, Translated Messages, Translated Source Words, Translated Target Words, Fuzzy Messages, Fuzzy Source Words, Untranslated Messages, Untranslated Source Words, Review Messages, Review Source Words
 avmedia/source/viewer.po,  1, 3, 3, 0, 0, 4, 22, 1, 3</pre>
 
 <p>
 
-Totals are not provided in <acronym title="Comma Seperated Value">CSV</acronym> mode.  In normal mode a grand total and file count is provided if the number of files is greater than one.
-</p>
-
-</div>
-<!-- SECTION "Output" [908-1752] -->
+Totals are not provided in <acronym title="Comma Separated Value">CSV</acronym> mode.  
+</p>
+
+</div>
+<!-- SECTION "--csv" [3250-3684] -->
+<h3><a name="short-strings_alias_--short" id="short-strings_alias_--short">--short-strings (alias --short)</a></h3>
+<div class="level3">
+
+<p>
+
+The focus is on easily accessible data in a compact form.  This will only count strings and uses a short syntax to make it easy for an experienced localiser to read.
+
+</p>
+<pre class="code">test-po/fuzzy.po strings: total: 1	| 0t	1f	0u	| 0%t	100%f	0%u</pre>
+
+<p>
+
+The filename is followed by a word indicating the type of count, here we are counting strings.  The total give the total string count.  While the letters t, f and u represent 'translated', 'fuzzy' and 'untranslated' and here indicate the string counts for each of those categories.  The counts are followed by a percentage representation of the same categories.
+</p>
+
+</div>
+<!-- SECTION "--short-strings (alias --short)" [3685-4322] -->
+<h3><a name="short-words" id="short-words">--short-words</a></h3>
+<div class="level3">
+
+<p>
+
+The output is very similar to --short-strings above:
+
+</p>
+<pre class="code">test-po/fuzzy.po source words: total: 3	| 0t	3f	0u	| 0%t	100%f	0%u</pre>
+
+<p>
+
+But instead of counting string we are now counting words as indicated by the term 'source words'
+</p>
+
+</div>
+<!-- SECTION "--short-words" [4323-4569] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 <ul>
 <li class="level1"><div class="li"> There are some miscounts related to word breaks.</div>
 </li>
+<li class="level1"><div class="li"> When using the short output formats the columns may not be exactly aligned. This is because the number of digits in different columns is unknown before all input files are processed. The chosen tradeoff here was instanteous output (after each processed file) instead of waiting for the last file to be processed.</div>
+</li>
 </ul>
 
 </div>
-<!-- SECTION "Bugs" [1753-] --></body>
+<!-- SECTION "Bugs" [4570-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-podebug.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-podebug.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-podebug.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-podebug.html Fri Jul 24 16:25:46 2009
@@ -23,7 +23,7 @@
 </p>
 
 <p>
-The pseudo translation or debig markers make it easy to reference and locate strings when your translated application is running.
+The pseudo translation or debug markers make it easy to reference and locate strings when your translated application is running.
 </p>
 
 <p>
@@ -41,7 +41,7 @@
 </ul>
 
 </div>
-<!-- SECTION "podebug" [1-839] -->
+<!-- SECTION "podebug" [1-833] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
 <pre class="code">podebug [options] [-f format] <in> <out></pre>
@@ -105,15 +105,15 @@
 		<td class="col0 leftalign"> <a href="toolkit-rewrite_style.html" class="wikilink1" title="toolkit-rewrite_style.html">--rewrite=STYLE</a>      </td><td class="col1"> the translation rewrite style: xxx, en, blank, chef  (v1.2), unicode (v1.2) </td>
 	</tr>
 	<tr class="row12">
-		<td class="col0 leftalign"> --ignore=APPLICATION  </td><td class="col1 leftalign"> apply tagging ignore rules for the given application: kde, gtk, openoffice, mozilla (v1.1.1)  </td>
+		<td class="col0 leftalign"> --ignore=APPLICATION  </td><td class="col1 leftalign"> apply tagging ignore rules for the given application: kde, gtk, openoffice, mozilla  </td>
 	</tr>
 	<tr class="row13">
-		<td class="col0 leftalign"> --hash=LENGTH        </td><td class="col1"> add an md5 hash to translations  (v1.1) </td>
+		<td class="col0 leftalign"> --hash=LENGTH        </td><td class="col1"> add an md5 hash to translations </td>
 	</tr>
 </table>
 
 </div>
-<!-- SECTION "Usage" [840-2274] -->
+<!-- SECTION "Usage" [834-2251] -->
 <h2><a name="formats" id="formats">Formats</a></h2>
 <div class="level2">
 
@@ -169,7 +169,7 @@
 </p>
 
 </div>
-<!-- SECTION "Formats" [2275-3252] -->
+<!-- SECTION "Formats" [2252-3229] -->
 <h2><a name="rewriting_style" id="rewriting_style">Rewriting (style)</a></h2>
 <div class="level2">
 
@@ -183,7 +183,7 @@
 </p>
 
 </div>
-<!-- SECTION "Rewriting (style)" [3253-3892] -->
+<!-- SECTION "Rewriting (style)" [3230-3869] -->
 <h2><a name="ignoring_messages" id="ignoring_messages">Ignoring messages</a></h2>
 <div class="level2">
 
@@ -201,7 +201,7 @@
 </p>
 
 </div>
-<!-- SECTION "Ignoring messages" [3893-4447] -->
+<!-- SECTION "Ignoring messages" [3870-4424] -->
 <h2><a name="hashing" id="hashing">Hashing</a></h2>
 <div class="level2">
 
@@ -214,16 +214,16 @@
 </p>
 
 </div>
-<!-- SECTION "Hashing" [4448-4938] -->
+<!-- SECTION "Hashing" [4425-4915] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 
 <p>
 
-Marking exceptions are hard coded for OpenOffice.org.  They should be configurable for any application.
-
-</p>
-
-</div>
-<!-- SECTION "Bugs" [4939-] --></body>
+None known
+
+</p>
+
+</div>
+<!-- SECTION "Bugs" [4916-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pofilter.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pofilter.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pofilter.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pofilter.html Fri Jul 24 16:25:46 2009
@@ -19,9 +19,7 @@
 
 <p>
 
-Pofilter allows you to run a <a href="toolkit-pofilter_tests.html" class="wikilink1" title="toolkit-pofilter_tests.html">number of checks</a> against your <acronym title="Gettext Portable Object">PO</acronym> files.  These checks
-are designed to pick up problems with capitalisation, accelerators, variables, etc.  Those messages
-that fail any of the checks are output and marked so that you can correct them.
+Pofilter allows you to run a <a href="toolkit-pofilter_tests.html" class="wikilink1" title="toolkit-pofilter_tests.html">number of checks</a> against your <acronym title="Gettext Portable Object">PO</acronym>, <acronym title="XML Localization Interchange File Format">XLIFF</acronym> or <acronym title="Translation Memory eXchange">TMX</acronym> files.  These checks are designed to pick up problems with capitalisation, accelerators, variables, etc.  Those messages that fail any of the checks are output and marked so that you can correct them.
 </p>
 
 <p>
@@ -33,7 +31,7 @@
 </p>
 
 </div>
-<!-- SECTION "pofilter" [1-500] -->
+<!-- SECTION "pofilter" [1-514] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
 <pre class="code">pofilter [options] <in> <out></pre>
@@ -74,13 +72,13 @@
 		<td class="col0 leftalign"> <a href="toolkit-errorlevel_errorlevel.html" class="wikilink1" title="toolkit-errorlevel_errorlevel.html">--errorlevel=ERRORLEVEL</a>  </td><td class="col1 leftalign"> show errorlevel as: none, message, exception, traceback  </td>
 	</tr>
 	<tr class="row5">
-		<td class="col0 leftalign"> -iINPUT, --input=INPUT   </td><td class="col1"> read from INPUT in pot, po, xlf formats (<acronym title="XML Localization Interchange File Format">XLIFF</acronym> since version 1.0) </td>
+		<td class="col0 leftalign"> -iINPUT, --input=INPUT   </td><td class="col1"> read from INPUT in pot, po, xlf, tmx formats </td>
 	</tr>
 	<tr class="row6">
 		<td class="col0 leftalign"> -xEXCLUDE, --exclude=EXCLUDE  </td><td class="col1 leftalign"> exclude names matching EXCLUDE from input paths  </td>
 	</tr>
 	<tr class="row7">
-		<td class="col0 leftalign"> -oOUTPUT, --output=OUTPUT  </td><td class="col1"> write to OUTPUT in po, pot, xlf formats (<acronym title="XML Localization Interchange File Format">XLIFF</acronym> since version 1.0) </td>
+		<td class="col0 leftalign"> -oOUTPUT, --output=OUTPUT  </td><td class="col1"> write to OUTPUT in po, pot, xlf, tmx formats </td>
 	</tr>
 	<tr class="row8">
 		<td class="col0 leftalign"> <a href="toolkit-psyco_mode.html" class="wikilink1" title="toolkit-psyco_mode.html">--psyco=MODE</a>        </td><td class="col1 leftalign"> use psyco to speed up the operation (set mode)  </td>
@@ -119,33 +117,36 @@
 		<td class="col0 leftalign"> --mozilla            </td><td class="col1 leftalign"> use the standard checks for Mozilla translations  </td>
 	</tr>
 	<tr class="row20">
+		<td class="col0 leftalign"> --drupal            </td><td class="col1 leftalign"> use the standard checks for Drupal translations  </td>
+	</tr>
+	<tr class="row21">
 		<td class="col0 leftalign"> --gnome              </td><td class="col1 leftalign"> use the standard checks for Gnome translations  </td>
 	</tr>
-	<tr class="row21">
+	<tr class="row22">
 		<td class="col0 leftalign"> --kde                </td><td class="col1 leftalign"> use the standard checks for KDE translations  </td>
 	</tr>
-	<tr class="row22">
-		<td class="col0 leftalign"> --wx                 </td><td class="col1"> use the standard checks for wxWidgets translations (since version 1.1) - identical to --kde </td>
-	</tr>
 	<tr class="row23">
+		<td class="col0 leftalign"> --wx                 </td><td class="col1"> use the standard checks for wxWidgets translations - identical to --kde </td>
+	</tr>
+	<tr class="row24">
 		<td class="col0 leftalign"> --excludefilter=FILTER  </td><td class="col1 leftalign"> don't use FILTER when filtering  </td>
 	</tr>
-	<tr class="row24">
+	<tr class="row25">
 		<td class="col0 leftalign"> -tFILTER, --test=FILTER  </td><td class="col1 leftalign"> only use test FILTERs specified with this option when filtering  </td>
 	</tr>
-	<tr class="row25">
+	<tr class="row26">
 		<td class="col0 leftalign"> --notranslatefile=FILE   </td><td class="col1 leftalign"> read list of untranslatable words from FILE (must not be translated)  </td>
 	</tr>
-	<tr class="row26">
+	<tr class="row27">
 		<td class="col0 leftalign"> --musttranslatefile=FILE  </td><td class="col1 leftalign"> read list of translatable words from FILE (must be translated)  </td>
 	</tr>
-	<tr class="row27">
+	<tr class="row28">
 		<td class="col0 leftalign"> --validcharsfile=FILE  </td><td class="col1 leftalign"> read list of all valid characters from FILE (must be in UTF-8)  </td>
 	</tr>
 </table>
 
 </div>
-<!-- SECTION "Usage" [501-3080] -->
+<!-- SECTION "Usage" [515-3107] -->
 <h2><a name="example" id="example">Example</a></h2>
 <div class="level2">
 
@@ -186,6 +187,13 @@
 Tell pofilter that you are checking French translations so that it can take the conventions of the language into account (for things like punctuation, spacing, quoting, etc.) It will also disable some tests that are not meaningful for your language, like capitalisation checks for languages that don't have capital letters.
 
 </p>
+<pre class="code">pofilter --excludefilter=untranslated</pre>
+
+<p>
+
+Tell pofilter not to complain about your untranslated units.
+
+</p>
 <pre class="code">pofilter -l</pre>
 
 <p>
@@ -194,7 +202,7 @@
 </p>
 
 </div>
-<!-- SECTION "Example" [3081-4492] -->
+<!-- SECTION "Example" [3108-4622] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 
@@ -205,5 +213,5 @@
 </p>
 
 </div>
-<!-- SECTION "Bugs" [4493-] --></body>
+<!-- SECTION "Bugs" [4623-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pofilter_tests.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pofilter_tests.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pofilter_tests.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pofilter_tests.html Fri Jul 24 16:25:46 2009
@@ -76,7 +76,7 @@
 <ul>
 <li class="level1"><div class="li"> Functional -- may confuse the user</div>
 <ul>
-<li class="level2"><div class="li"> <a href="toolkit-pofilter_tests.html#acronyms" class="wikilink1" title="toolkit-pofilter_tests.html">acronyms</a>, <a href="toolkit-pofilter_tests.html#blank" class="wikilink1" title="toolkit-pofilter_tests.html">blank</a>, <a href="toolkit-pofilter_tests.html#emails" class="wikilink1" title="toolkit-pofilter_tests.html">emails</a>, <a href="toolkit-pofilter_tests.html#filepaths" class="wikilink1" title="toolkit-pofilter_tests.html">filepaths</a>, <a href="toolkit-pofilter_tests.html#functions" class="wikilink1" title="toolkit-pofilter_tests.html">functions</a>, <a href="toolkit-pofilter_tests.html#gconf" class="wikilink1" title="toolkit-pofilter_tests.html">gconf</a>, <a href="toolkit-pofilter_tests.html#kdecomments" class="wikilink1" title="toolkit-pofilter_tests.html">kdecomments</a>, <a href="toolkit-pofilter_tests.html#long" class="wikilink1" title="toolkit-pofilter_tests.html">long</a>, <a href="toolkit-pofilter_tests.html#musttranslatewords" class="wikilink1" title="toolkit-pofilter_tests.html">musttranslatewords</a>, <a href="toolkit-pofilter_tests.html#notranslatewords" class="wikilink1" title="toolkit-pofilter_tests.html">notranslatewords</a>, <a href="toolkit-pofilter_tests.html#numbers" class="wikilink1" title="toolkit-pofilter_tests.html">numbers</a>, <a href="toolkit-pofilter_tests.html#options" class="wikilink1" title="toolkit-pofilter_tests.html">options</a> (v1.1), <a href="toolkit-pofilter_tests.html#purepunc" class="wikilink1" title="toolkit-pofilter_tests.html">purepunc</a>, <a href="toolkit-pofilter_tests.html#sentencecount" class="wikilink1" title="toolkit-pofilter_tests.html">sentencecount</a>, <a href="toolkit-pofilter_tests.html#short" class="wikilink1" title="toolkit-pofilter_tests.html">short</a>, <a href="toolkit-pofilter_tests.html#spellcheck" class="wikilink1" title="toolkit-pofilter_tests.html">spellcheck</a>, <a href="toolkit-pofilter_tests.html#urls" class="wikilink1" title="toolkit-pofilter_tests.html">urls</a>, <a href="toolkit-pofilter_tests.html#unchanged" class="wikilink1" title="toolkit-pofilter_tests.html">unchanged</a></div>
+<li class="level2"><div class="li"> <a href="toolkit-pofilter_tests.html#acronyms" class="wikilink1" title="toolkit-pofilter_tests.html">acronyms</a>, <a href="toolkit-pofilter_tests.html#blank" class="wikilink1" title="toolkit-pofilter_tests.html">blank</a>, <a href="toolkit-pofilter_tests.html#emails" class="wikilink1" title="toolkit-pofilter_tests.html">emails</a>, <a href="toolkit-pofilter_tests.html#filepaths" class="wikilink1" title="toolkit-pofilter_tests.html">filepaths</a>, <a href="toolkit-pofilter_tests.html#functions" class="wikilink1" title="toolkit-pofilter_tests.html">functions</a>, <a href="toolkit-pofilter_tests.html#gconf" class="wikilink1" title="toolkit-pofilter_tests.html">gconf</a>, <a href="toolkit-pofilter_tests.html#kdecomments" class="wikilink1" title="toolkit-pofilter_tests.html">kdecomments</a>, <a href="toolkit-pofilter_tests.html#long" class="wikilink1" title="toolkit-pofilter_tests.html">long</a>, <a href="toolkit-pofilter_tests.html#musttranslatewords" class="wikilink1" title="toolkit-pofilter_tests.html">musttranslatewords</a>, <a href="toolkit-pofilter_tests.html#notranslatewords" class="wikilink1" title="toolkit-pofilter_tests.html">notranslatewords</a>, <a href="toolkit-pofilter_tests.html#numbers" class="wikilink1" title="toolkit-pofilter_tests.html">numbers</a>, <a href="toolkit-pofilter_tests.html#options" class="wikilink1" title="toolkit-pofilter_tests.html">options</a>, <a href="toolkit-pofilter_tests.html#purepunc" class="wikilink1" title="toolkit-pofilter_tests.html">purepunc</a>, <a href="toolkit-pofilter_tests.html#sentencecount" class="wikilink1" title="toolkit-pofilter_tests.html">sentencecount</a>, <a href="toolkit-pofilter_tests.html#short" class="wikilink1" title="toolkit-pofilter_tests.html">short</a>, <a href="toolkit-pofilter_tests.html#spellcheck" class="wikilink1" title="toolkit-pofilter_tests.html">spellcheck</a>, <a href="toolkit-pofilter_tests.html#urls" class="wikilink1" title="toolkit-pofilter_tests.html">urls</a>, <a href="toolkit-pofilter_tests.html#unchanged" class="wikilink1" title="toolkit-pofilter_tests.html">unchanged</a></div>
 </li>
 </ul>
 </li>
@@ -92,19 +92,19 @@
 <ul>
 <li class="level1"><div class="li"> Extraction -- useful mainly for extracting certain types of string</div>
 <ul>
-<li class="level2"><div class="li"> <a href="toolkit-pofilter_tests.html#compendiumconflicts" class="wikilink1" title="toolkit-pofilter_tests.html">compendiumconflicts</a>, <a href="toolkit-pofilter_tests.html#credits" class="wikilink1" title="toolkit-pofilter_tests.html">credits</a> (v1.1), <a href="toolkit-pofilter_tests.html#hassuggestion" class="wikilink1" title="toolkit-pofilter_tests.html">hassuggestion</a> (v1.1), <a href="toolkit-pofilter_tests.html#isfuzzy" class="wikilink1" title="toolkit-pofilter_tests.html">isfuzzy</a>, <a href="toolkit-pofilter_tests.html#isreview" class="wikilink1" title="toolkit-pofilter_tests.html">isreview</a>, <a href="toolkit-pofilter_tests.html#untranslated" class="wikilink1" title="toolkit-pofilter_tests.html">untranslated</a></div>
+<li class="level2"><div class="li"> <a href="toolkit-pofilter_tests.html#compendiumconflicts" class="wikilink1" title="toolkit-pofilter_tests.html">compendiumconflicts</a>, <a href="toolkit-pofilter_tests.html#credits" class="wikilink1" title="toolkit-pofilter_tests.html">credits</a>, <a href="toolkit-pofilter_tests.html#hassuggestion" class="wikilink1" title="toolkit-pofilter_tests.html">hassuggestion</a>, <a href="toolkit-pofilter_tests.html#isfuzzy" class="wikilink1" title="toolkit-pofilter_tests.html">isfuzzy</a>, <a href="toolkit-pofilter_tests.html#isreview" class="wikilink1" title="toolkit-pofilter_tests.html">isreview</a>, <a href="toolkit-pofilter_tests.html#untranslated" class="wikilink1" title="toolkit-pofilter_tests.html">untranslated</a></div>
 </li>
 </ul>
 </li>
 </ul>
 
 </div>
-<!-- SECTION "Test Classification" [830-2603] -->
+<!-- SECTION "Test Classification" [830-2582] -->
 <h2><a name="test_description" id="test_description">Test Description</a></h2>
 <div class="level2">
 
 </div>
-<!-- SECTION "Test Description" [2604-2633] -->
+<!-- SECTION "Test Description" [2583-2612] -->
 <h3><a name="accelerators" id="accelerators">accelerators</a></h3>
 <div class="level3">
 
@@ -118,7 +118,7 @@
 </p>
 
 </div>
-<!-- SECTION "accelerators" [2634-2934] -->
+<!-- SECTION "accelerators" [2613-2913] -->
 <h3><a name="acronyms" id="acronyms">acronyms</a></h3>
 <div class="level3">
 
@@ -132,7 +132,7 @@
 </p>
 
 </div>
-<!-- SECTION "acronyms" [2935-3288] -->
+<!-- SECTION "acronyms" [2914-3267] -->
 <h3><a name="blank" id="blank">blank</a></h3>
 <div class="level3">
 
@@ -146,7 +146,7 @@
 </p>
 
 </div>
-<!-- SECTION "blank" [3289-3632] -->
+<!-- SECTION "blank" [3268-3611] -->
 <h3><a name="brackets" id="brackets">brackets</a></h3>
 <div class="level3">
 
@@ -160,7 +160,7 @@
 </p>
 
 </div>
-<!-- SECTION "brackets" [3633-3812] -->
+<!-- SECTION "brackets" [3612-3791] -->
 <h3><a name="compendiumconflicts" id="compendiumconflicts">compendiumconflicts</a></h3>
 <div class="level3">
 
@@ -175,7 +175,7 @@
 </p>
 
 </div>
-<!-- SECTION "compendiumconflicts" [3813-4163] -->
+<!-- SECTION "compendiumconflicts" [3792-4142] -->
 <h3><a name="credits" id="credits">credits</a></h3>
 <div class="level3">
 
@@ -189,7 +189,7 @@
 </p>
 
 </div>
-<!-- SECTION "credits" [4164-4638] -->
+<!-- SECTION "credits" [4143-4617] -->
 <h3><a name="doublequoting" id="doublequoting">doublequoting</a></h3>
 <div class="level3">
 
@@ -199,11 +199,11 @@
 </p>
 
 <p>
-Checks on double quotes ” to ensure that you have the same number in both the original and the translated string.
-</p>
-
-</div>
-<!-- SECTION "doublequoting" [4639-4846] -->
+Checks on double quotes ” to ensure that you have the same number in both the original and the translated string. This tests takes into account that several languages use different quoting characters, and will test for them instead.
+</p>
+
+</div>
+<!-- SECTION "doublequoting" [4618-4944] -->
 <h3><a name="doublespacing" id="doublespacing">doublespacing</a></h3>
 <div class="level3">
 
@@ -217,7 +217,7 @@
 </p>
 
 </div>
-<!-- SECTION "doublespacing" [4847-5171] -->
+<!-- SECTION "doublespacing" [4945-5269] -->
 <h3><a name="doublewords" id="doublewords">doublewords</a></h3>
 <div class="level3">
 
@@ -231,7 +231,7 @@
 </p>
 
 </div>
-<!-- SECTION "doublewords" [5172-5564] -->
+<!-- SECTION "doublewords" [5270-5662] -->
 <h3><a name="emails" id="emails">emails</a></h3>
 <div class="level3">
 
@@ -245,7 +245,7 @@
 </p>
 
 </div>
-<!-- SECTION "emails" [5565-5865] -->
+<!-- SECTION "emails" [5663-5963] -->
 <h3><a name="endpunc" id="endpunc">endpunc</a></h3>
 <div class="level3">
 
@@ -262,8 +262,12 @@
 It must be noted that if you are tempted to leave out [full-stop] or [colon] or add [full-stop] to a sentence, that often these have been done for a reason, e.g. a list where fullstops make it look cluttered.  So, initially match them with the English, and make changes once the program is being used.
 </p>
 
-</div>
-<!-- SECTION "endpunc" [5866-6951] -->
+<p>
+This check is aware of several language conventions for punctuation characters, such as the custom question marks for Greek and Arabic, Devenagari Danda, full-width punctuation for CJK languages, etc.  Support for your language can be added easily if it is not there yet.
+</p>
+
+</div>
+<!-- SECTION "endpunc" [5964-7322] -->
 <h3><a name="endwhitespace" id="endwhitespace">endwhitespace</a></h3>
 <div class="level3">
 
@@ -276,8 +280,12 @@
 Operates the same as endpunc but is only concerned with whitespace. This filter is particularly useful for those strings which will evidently be followed by another string in the program, e.g. [Password: ] or [Enter your username: ]. The whitespace is an inherent part of the string. This filter makes sure you don't miss those important but otherwise invisible spaces!
 </p>
 
-</div>
-<!-- SECTION "endwhitespace" [6952-7408] -->
+<p>
+If your language uses full-width punctuation (like Chinese), the visual spacing in the character might be enough without an added extra space.
+</p>
+
+</div>
+<!-- SECTION "endwhitespace" [7323-7923] -->
 <h3><a name="escapes" id="escapes">escapes</a></h3>
 <div class="level3">
 
@@ -291,7 +299,7 @@
 </p>
 
 </div>
-<!-- SECTION "escapes" [7409-7616] -->
+<!-- SECTION "escapes" [7924-8131] -->
 <h3><a name="filepaths" id="filepaths">filepaths</a></h3>
 <div class="level3">
 
@@ -305,7 +313,7 @@
 </p>
 
 </div>
-<!-- SECTION "filepaths" [7617-7884] -->
+<!-- SECTION "filepaths" [8132-8399] -->
 <h3><a name="functions" id="functions">functions</a></h3>
 <div class="level3">
 
@@ -319,7 +327,7 @@
 </p>
 
 </div>
-<!-- SECTION "functions" [7885-8045] -->
+<!-- SECTION "functions" [8400-8560] -->
 <h3><a name="gconf" id="gconf">gconf</a></h3>
 <div class="level3">
 
@@ -333,7 +341,7 @@
 </p>
 
 </div>
-<!-- SECTION "gconf" [8046-8386] -->
+<!-- SECTION "gconf" [8561-8901] -->
 <h3><a name="hassuggestion" id="hassuggestion">hassuggestion</a></h3>
 <div class="level3">
 
@@ -347,7 +355,7 @@
 </p>
 
 </div>
-<!-- SECTION "hassuggestion" [8387-8716] -->
+<!-- SECTION "hassuggestion" [8902-9231] -->
 <h3><a name="isfuzzy" id="isfuzzy">isfuzzy</a></h3>
 <div class="level3">
 
@@ -361,7 +369,7 @@
 </p>
 
 </div>
-<!-- SECTION "isfuzzy" [8717-8986] -->
+<!-- SECTION "isfuzzy" [9232-9501] -->
 <h3><a name="isreview" id="isreview">isreview</a></h3>
 <div class="level3">
 
@@ -383,7 +391,7 @@
 </p>
 
 </div>
-<!-- SECTION "isreview" [8987-9438] -->
+<!-- SECTION "isreview" [9502-9953] -->
 <h3><a name="kdecomments" id="kdecomments">kdecomments</a></h3>
 <div class="level3">
 
@@ -397,7 +405,7 @@
 </p>
 
 </div>
-<!-- SECTION "kdecomments" [9439-9724] -->
+<!-- SECTION "kdecomments" [9954-10239] -->
 <h3><a name="long" id="long">long</a></h3>
 <div class="level3">
 
@@ -413,7 +421,7 @@
 </p>
 
 </div>
-<!-- SECTION "long" [9725-10088] -->
+<!-- SECTION "long" [10240-10603] -->
 <h3><a name="musttranslatewords" id="musttranslatewords">musttranslatewords</a></h3>
 <div class="level3">
 
@@ -429,7 +437,7 @@
 </p>
 
 </div>
-<!-- SECTION "musttranslatewords" [10089-10489] -->
+<!-- SECTION "musttranslatewords" [10604-11004] -->
 <h3><a name="newlines" id="newlines">newlines</a></h3>
 <div class="level3">
 
@@ -443,7 +451,7 @@
 </p>
 
 </div>
-<!-- SECTION "newlines" [10490-10673] -->
+<!-- SECTION "newlines" [11005-11188] -->
 <h3><a name="nplurals" id="nplurals">nplurals</a></h3>
 <div class="level3">
 
@@ -457,7 +465,7 @@
 </p>
 
 </div>
-<!-- SECTION "nplurals" [10674-10991] -->
+<!-- SECTION "nplurals" [11189-11506] -->
 <h3><a name="notranslatewords" id="notranslatewords">notranslatewords</a></h3>
 <div class="level3">
 
@@ -472,7 +480,7 @@
 </p>
 
 </div>
-<!-- SECTION "notranslatewords" [10992-11352] -->
+<!-- SECTION "notranslatewords" [11507-11867] -->
 <h3><a name="numbers" id="numbers">numbers</a></h3>
 <div class="level3">
 
@@ -486,13 +494,13 @@
 </p>
 
 </div>
-<!-- SECTION "numbers" [11353-11625] -->
+<!-- SECTION "numbers" [11868-12140] -->
 <h3><a name="options" id="options">options</a></h3>
 <div class="level3">
 
 <p>
 
-checks that options are not translated
+checks that command line options are not translated
 </p>
 
 <p>
@@ -500,7 +508,7 @@
 </p>
 
 </div>
-<!-- SECTION "options" [11626-12052] -->
+<!-- SECTION "options" [12141-12580] -->
 <h3><a name="printf" id="printf">printf</a></h3>
 <div class="level3">
 
@@ -514,7 +522,7 @@
 </p>
 
 </div>
-<!-- SECTION "printf" [12053-12729] -->
+<!-- SECTION "printf" [12581-13257] -->
 <h3><a name="puncspacing" id="puncspacing">puncspacing</a></h3>
 <div class="level3">
 
@@ -527,8 +535,12 @@
 In the case of [full-stop][space] in the original, this test checks that your translation does not remove the space.  It checks also for [comma], [colon], etc.
 </p>
 
-</div>
-<!-- SECTION "puncspacing" [12730-12955] -->
+<p>
+Some languages don't use spaces after common punctuation marks, especially where full-width punctuation marks are used. This check will take that into account.
+</p>
+
+</div>
+<!-- SECTION "puncspacing" [13258-13644] -->
 <h3><a name="purepunc" id="purepunc">purepunc</a></h3>
 <div class="level3">
 
@@ -542,7 +554,7 @@
 </p>
 
 </div>
-<!-- SECTION "purepunc" [12956-13119] -->
+<!-- SECTION "purepunc" [13645-13808] -->
 <h3><a name="sentencecount" id="sentencecount">sentencecount</a></h3>
 <div class="level3">
 
@@ -552,11 +564,11 @@
 </p>
 
 <p>
-Adds the number of fullstops to see that the sentence count is the same between the original and translated string. You may not always want to use this test, if you find you often need to reformat your translation, because the original is badly-expressed, or because the structure of your language works better that way. Do what works best for your language: it's the sense of the original you want to convey, not every dot and p or q.
-</p>
-
-</div>
-<!-- SECTION "sentencecount" [13120-13640] -->
+Adds the number of sentences to see that the sentence count is the same between the original and translated string. You may not always want to use this test, if you find you often need to reformat your translation, because the original is badly-expressed, or because the structure of your language works better that way. Do what works best for your language: it's the meaning of the original you want to convey, not the exact way it was written in the English.
+</p>
+
+</div>
+<!-- SECTION "sentencecount" [13809-14354] -->
 <h3><a name="short" id="short">short</a></h3>
 <div class="level3">
 
@@ -572,7 +584,7 @@
 </p>
 
 </div>
-<!-- SECTION "short" [13641-14002] -->
+<!-- SECTION "short" [14355-14716] -->
 <h3><a name="simplecaps" id="simplecaps">simplecaps</a></h3>
 <div class="level3">
 
@@ -586,7 +598,7 @@
 </p>
 
 </div>
-<!-- SECTION "simplecaps" [14003-14526] -->
+<!-- SECTION "simplecaps" [14717-15240] -->
 <h3><a name="simpleplurals" id="simpleplurals">simpleplurals</a></h3>
 <div class="level3">
 
@@ -602,8 +614,12 @@
 This test allows an editor to check that the plurals used are correct.  Be aware that this test may create a number of false positives.
 </p>
 
-</div>
-<!-- SECTION "simpleplurals" [14527-15128] -->
+<p>
+For languages with no plural forms (only one noun form) this test will simply test that nothing like ”(s)” was used in the translation.
+</p>
+
+</div>
+<!-- SECTION "simpleplurals" [15241-15979] -->
 <h3><a name="singlequoting" id="singlequoting">singlequoting</a></h3>
 <div class="level3">
 
@@ -617,7 +633,7 @@
 </p>
 
 </div>
-<!-- SECTION "singlequoting" [15129-15577] -->
+<!-- SECTION "singlequoting" [15980-16428] -->
 <h3><a name="spellcheck" id="spellcheck">spellcheck</a></h3>
 <div class="level3">
 
@@ -627,22 +643,19 @@
 </p>
 
 <p>
-This test will check for for misspelled words in your translation.  The test first checks for misspelled words in the original (usually English) text, and adds those to an
-exclusion list. The advantage of this exclusion is that many words that are specific to the application will not raise errors e.g. program names, brand names, function names.
-</p>
-
-<p>
-The checker works with <a href="http://pyenchant.sourceforge.net/" class="urlextern" title="http://pyenchant.sourceforge.net/">PyEnchant</a>, failing that it works with <a href="http://jtoolkit.sourceforge.net/" class="urlextern" title="http://jtoolkit.sourceforge.net/">jToolkit's</a> spelling module.  You will need to have one of these
-installed for the checker to work.  Plus, of course, a spell checker dictionary for your language (for example, one of <a href="http://ftp.gnu.org/gnu/aspell/dict/" class="urlextern" title="http://ftp.gnu.org/gnu/aspell/dict/">the aspell dictionaries</a>).  This test will only work if you have specified the <em>--language</em> option.
-</p>
-
-<p>
-The pofilter error that is created lists the misspelled word, plus all the suggestions returned from the spell checker.  That makes it easy for you to
-identify the word and select a suggestion.
-</p>
-
-</div>
-<!-- SECTION "spellcheck" [15578-16651] -->
+This test will check for misspelled words in your translation.  The test first checks for misspelled words in the original (usually English) text, and adds those to an exclusion list. The advantage of this exclusion is that many words that are specific to the application will not raise errors e.g. program names, brand names, function names.
+</p>
+
+<p>
+The checker works with <a href="http://pyenchant.sourceforge.net/" class="urlextern" title="http://pyenchant.sourceforge.net/">PyEnchant</a>. You need to have PyEnchant installed as well as a dictionary for your language (for example, one of the <a href="http://wiki.services.openoffice.org/wiki/Dictionaries" class="urlextern" title="http://wiki.services.openoffice.org/wiki/Dictionaries">Hunspell</a> or <a href="http://ftp.gnu.org/gnu/aspell/dict/" class="urlextern" title="http://ftp.gnu.org/gnu/aspell/dict/">aspell</a> dictionaries).  This test will only work if you have specified the <em>--language</em> option.
+</p>
+
+<p>
+The pofilter error that is created, lists the misspelled word, plus  suggestions returned from the spell checker.  That makes it easy for you to identify the word and select a replacement.
+</p>
+
+</div>
+<!-- SECTION "spellcheck" [16429-17416] -->
 <h3><a name="startcaps" id="startcaps">startcaps</a></h3>
 <div class="level3">
 
@@ -652,11 +665,15 @@
 </p>
 
 <p>
-After stripping whitespace and common punctuation characters, it then checks to see that the first remaining character is correctly capitalised.  So, if the sentence starts with an upper-case letter, and the translation does not, an error is produced.  This check does not <em>yet</em> consider locale information to determine which characters are considered to be upper-case in your locale.
-</p>
-
-</div>
-<!-- SECTION "startcaps" [16652-17124] -->
+After stripping whitespace and common punctuation characters, it then checks to see that the first remaining character is correctly capitalised.  So, if the sentence starts with an upper-case letter, and the translation does not, an error is produced.
+</p>
+
+<p>
+This check is entirely disabled for many languages that don't make a distinction between upper and lower case. Contact us if this is not yet disabled for your language.
+</p>
+
+</div>
+<!-- SECTION "startcaps" [17417-17924] -->
 <h3><a name="startpunc" id="startpunc">startpunc</a></h3>
 <div class="level3">
 
@@ -670,7 +687,7 @@
 </p>
 
 </div>
-<!-- SECTION "startpunc" [17125-17272] -->
+<!-- SECTION "startpunc" [17925-18072] -->
 <h3><a name="startwhitespace" id="startwhitespace">startwhitespace</a></h3>
 <div class="level3">
 
@@ -684,7 +701,7 @@
 </p>
 
 </div>
-<!-- SECTION "startwhitespace" [17273-17418] -->
+<!-- SECTION "startwhitespace" [18073-18218] -->
 <h3><a name="tabs" id="tabs">tabs</a></h3>
 <div class="level3">
 
@@ -698,7 +715,7 @@
 </p>
 
 </div>
-<!-- SECTION "tabs" [17419-17568] -->
+<!-- SECTION "tabs" [18219-18368] -->
 <h3><a name="unchanged" id="unchanged">unchanged</a></h3>
 <div class="level3">
 
@@ -712,7 +729,7 @@
 </p>
 
 </div>
-<!-- SECTION "unchanged" [17569-17854] -->
+<!-- SECTION "unchanged" [18369-18654] -->
 <h3><a name="untranslated" id="untranslated">untranslated</a></h3>
 <div class="level3">
 
@@ -726,7 +743,7 @@
 </p>
 
 </div>
-<!-- SECTION "untranslated" [17855-18071] -->
+<!-- SECTION "untranslated" [18655-18871] -->
 <h3><a name="urls" id="urls">urls</a></h3>
 <div class="level3">
 
@@ -736,11 +753,11 @@
 </p>
 
 <p>
-This checks only basic URLs (http, ftp, mailto etc.) not all URIs (e.g. afp, smb, file).  Generally, you don't want to translate URLs, unless they are example URLs (<a href="http://your_server.com/filename.html" class="urlextern" title="http://your_server.com/filename.html">http://your_server.com/filename.html</a>).  If the <acronym title="Uniform Resource Locator">URL</acronym> is for configuration information, then you need to query the developers about placing config. information in <acronym title="Gettext Portable Object">PO</acronym> files.  It shouldn't really be there, unless it is very clearly marked: such information should go into a configuration file.
-</p>
-
-</div>
-<!-- SECTION "urls" [18072-18586] -->
+This checks only basic URLs (http, ftp, mailto etc.) not all URIs (e.g. afp, smb, file).  Generally, you don't want to translate URLs, unless they are example URLs (<a href="http://your_server.com/filename.html" class="urlextern" title="http://your_server.com/filename.html">http://your_server.com/filename.html</a>).  If the <acronym title="Uniform Resource Locator">URL</acronym> is for configuration information, then you need to query the developers about placing configuration information in <acronym title="Gettext Portable Object">PO</acronym> files.  It shouldn't really be there, unless it is very clearly marked: such information should go into a configuration file.
+</p>
+
+</div>
+<!-- SECTION "urls" [18872-19392] -->
 <h3><a name="validchars" id="validchars">validchars</a></h3>
 <div class="level3">
 
@@ -763,7 +780,7 @@
 </p>
 
 </div>
-<!-- SECTION "validchars" [18587-19235] -->
+<!-- SECTION "validchars" [19393-20041] -->
 <h3><a name="variables" id="variables">variables</a></h3>
 <div class="level3">
 
@@ -777,7 +794,7 @@
 </p>
 
 </div>
-<!-- SECTION "variables" [19236-19646] -->
+<!-- SECTION "variables" [20042-20452] -->
 <h3><a name="xmltags" id="xmltags">xmltags</a></h3>
 <div class="level3">
 
@@ -791,10 +808,10 @@
 </p>
 
 <p>
-The check ignores tags or things that look like tags that cover the whole string eg ”<Error>” but will produce false positives for things like “An <Error> occurred” as here “Error” should be translated.  It also will detect a translated alt tag in e.g. <img src=bob.png alt=“blah”> as an error when in fact it is correct.
-
-</p>
-
-</div>
-<!-- SECTION "xmltags" [19647-] --></body>
+The check ignores tags or things that look like tags that cover the whole string eg ”<Error>” but will produce false positives for things like “An <Error> occurred” as here “Error” should be translated.  It also will allow translation of the alt attribute in e.g. <img src=bob.png alt=“Image description”> or similar translatable attributes in OpenOffice.org help files. 
+
+</p>
+
+</div>
+<!-- SECTION "xmltags" [20453-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-poglossary.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-poglossary.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-poglossary.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-poglossary.html Fri Jul 24 16:25:46 2009
@@ -24,7 +24,7 @@
 
 <p>
 
-This tool takes a directory of translated <acronym title="Gettext Portable Object">PO</acronym> files and creates a single <acronym title="Gettext Portable Object">PO</acronym> file containing terms and / or phrases that can be used as a glossary.  This compendium can be used to review word choice of a subset of words, and can be a useful start for a your <a href="pootle-terminology_matching.html" class="wikilink1" title="pootle-terminology_matching.html">terminology</a> in Pootle or many other offline editors.
+This tool takes a directory of translated <acronym title="Gettext Portable Object">PO</acronym> files and creates a single <acronym title="Gettext Portable Object">PO</acronym> file containing terms and / or phrases that can be used as a glossary.  This compendium can be used to review word choice of a subset of words, and can be a useful start for a your <a href="pootle-terminology_matching.html" class="wikilink2" title="pootle-terminology_matching.html">terminology</a> in Pootle or many other offline editors.
 </p>
 
 </div>
@@ -87,7 +87,7 @@
 
 <p>
 
-poglossary makes use of <a href="toolkit-pocompendium.html" class="wikilink1" title="toolkit-pocompendium.html">pocompendium</a> and some tools of the translate toolkit. It searches for all short terms and phrases in the <acronym title="Gettext Portable Object">PO</acronym> files from the input directory and combines it into one file. Output is given in <acronym title="Gettext Portable Object">PO</acronym>, <acronym title="Comma Seperated Value">CSV</acronym> and <acronym title="TermBase eXchange">TBX</acronym> formats.
+poglossary makes use of <a href="toolkit-pocompendium.html" class="wikilink1" title="toolkit-pocompendium.html">pocompendium</a> and some tools of the translate toolkit. It searches for all short terms and phrases in the <acronym title="Gettext Portable Object">PO</acronym> files from the input directory and combines it into one file. Output is given in <acronym title="Gettext Portable Object">PO</acronym>, <acronym title="Comma Separated Value">CSV</acronym> and <acronym title="TermBase eXchange">TBX</acronym> formats.
 
 </p>
 

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pogrep.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pogrep.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pogrep.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pogrep.html Fri Jul 24 16:25:46 2009
@@ -135,11 +135,11 @@
 
 <p>
 
-pogrep will normalize Unicode strings (from v1.1).  This allows you to search for strings that contain the same character but that are using precomposed Unicode characters or which are composed using another composition recipe.  While an individual user will in all likelihood only compose characters in one way, normalization ensures that data created in a team setting can be shared.
+pogrep will normalize Unicode strings.  This allows you to search for strings that contain the same character but that are using precomposed Unicode characters or which are composed using another composition recipe.  While an individual user will in all likelihood only compose characters in one way, normalization ensures that data created in a team setting can be shared.
 </p>
 
 </div>
-<!-- SECTION "Unicode normalization" [2757-3176] -->
+<!-- SECTION "Unicode normalization" [2757-3164] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 
@@ -150,5 +150,5 @@
 </p>
 
 </div>
-<!-- SECTION "Bugs" [3177-] --></body>
+<!-- SECTION "Bugs" [3165-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pomerge.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pomerge.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pomerge.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-pomerge.html Fri Jul 24 16:25:46 2009
@@ -19,24 +19,20 @@
 
 <p>
 
-Pomerge will merge corrected <acronym title="Gettext Portable Object">PO</acronym>/<acronym title="XML Localization Interchange File Format">XLIFF</acronym> files (or snippets) into your existing <acronym title="Gettext Portable Object">PO</acronym>/<acronym title="XML Localization Interchange File Format">XLIFF</acronym> files.  Usually you would extract
-errors using <a href="toolkit-pofilter.html" class="wikilink1" title="toolkit-pofilter.html">pofilter</a>, make corrections to these <acronym title="Gettext Portable Object">PO</acronym> (or <acronym title="XML Localization Interchange File Format">XLIFF</acronym>) snippets then merge them back using pomerge.  You
-could also use <a href="toolkit-pogrep.html" class="wikilink1" title="toolkit-pogrep.html">pogrep</a> to extract a number of messages matching a certain string, make corrections then merge
-the correction back using pomerge.
+Pomerge will merge corrected <acronym title="Gettext Portable Object">PO</acronym>, <acronym title="XML Localization Interchange File Format">XLIFF</acronym>, or <acronym title="Translation Memory eXchange">TMX</acronym> files (or snippets) into your existing <acronym title="Gettext Portable Object">PO</acronym>, <acronym title="XML Localization Interchange File Format">XLIFF</acronym>, <acronym title="Translation Memory eXchange">TMX</acronym> files.  Usually you would extract
+errors using <a href="toolkit-pofilter.html" class="wikilink1" title="toolkit-pofilter.html">pofilter</a>, make corrections to these <acronym title="Gettext Portable Object">PO</acronym> (or <acronym title="XML Localization Interchange File Format">XLIFF</acronym>, <acronym title="Translation Memory eXchange">TMX</acronym>) snippets then merge them back using pomerge.  You could also use <a href="toolkit-pogrep.html" class="wikilink1" title="toolkit-pogrep.html">pogrep</a> to extract a number of messages matching a certain string, make corrections then merge the correction back using pomerge.
 </p>
 
 <p>
-It is probably best to run pomerge against files stored in some kind of version control system so that
-you can monitor what changes were made.
+It is probably best to run pomerge against files stored in some kind of version control system so that you can monitor what changes were made.
 </p>
 
 <p>
-Pomerge will also attempt to make as small a change as possible to the text, making it easier to 
-see the changes using your version control system.
+Pomerge will also attempt to make as small a change as possible to the text, making it easier to see the changes using your version control system.
 </p>
 
 </div>
-<!-- SECTION "pomerge" [1-705] -->
+<!-- SECTION "pomerge" [1-724] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
 <pre class="code">pomerge [options] [-t <template>] -i <input> -o <output></pre>
@@ -48,7 +44,7 @@
 </p>
 <table class="inline">
 	<tr class="row0">
-		<td class="col0 leftalign"> <template>  </td><td class="col1 leftalign"> is a set of reference <acronym title="Gettext Portable Object">PO</acronym>/<acronym title="XML Localization Interchange File Format">XLIFF</acronym> files, either the originals or a set of <acronym title="Gettext Portable Object Template">POT</acronym> files  </td>
+		<td class="col0 leftalign"> <template>  </td><td class="col1 leftalign"> is a set of reference <acronym title="Gettext Portable Object">PO</acronym>, <acronym title="XML Localization Interchange File Format">XLIFF</acronym>, <acronym title="Translation Memory eXchange">TMX</acronym> files, either the originals or a set of <acronym title="Gettext Portable Object Template">POT</acronym> files  </td>
 	</tr>
 	<tr class="row1">
 		<td class="col0 leftalign"> <input>     </td><td class="col1 leftalign"> contains the corrected files that are to override content in <output>  </td>
@@ -80,30 +76,30 @@
 		<td class="col0 leftalign"> <a href="toolkit-errorlevel_errorlevel.html" class="wikilink1" title="toolkit-errorlevel_errorlevel.html">--errorlevel=ERRORLEVEL</a>  </td><td class="col1 leftalign"> show errorlevel as: none, message, exception, traceback  </td>
 	</tr>
 	<tr class="row5">
-		<td class="col0 leftalign"> -iINPUT, --input=INPUT   </td><td class="col1 leftalign"> read from INPUT in po, pot and xlf formats  </td>
+		<td class="col0 leftalign"> -iINPUT, --input=INPUT   </td><td class="col1 leftalign"> read from INPUT in po, pot, xlf, tmx formats  </td>
 	</tr>
 	<tr class="row6">
 		<td class="col0 leftalign"> -xEXCLUDE, --exclude=EXCLUDE   </td><td class="col1 leftalign"> exclude names matching EXCLUDE from input paths  </td>
 	</tr>
 	<tr class="row7">
-		<td class="col0 leftalign"> -oOUTPUT, --output=OUTPUT   </td><td class="col1 leftalign"> write to OUTPUT in po, pot and xlf formats  </td>
+		<td class="col0 leftalign"> -oOUTPUT, --output=OUTPUT   </td><td class="col1 leftalign"> write to OUTPUT in po, pot, xlf, tmx formats  </td>
 	</tr>
 	<tr class="row8">
-		<td class="col0 leftalign"> -tTEMPLATE, --template=TEMPLATE   </td><td class="col1 leftalign"> read from TEMPLATE in po, pot and xlf formats  </td>
+		<td class="col0 leftalign"> -tTEMPLATE, --template=TEMPLATE   </td><td class="col1 leftalign"> read from TEMPLATE in po, pot, xlf, tmx formats  </td>
 	</tr>
 	<tr class="row9">
 		<td class="col0 leftalign"> <a href="toolkit-psyco_mode.html" class="wikilink1" title="toolkit-psyco_mode.html">--psyco=MODE</a>        </td><td class="col1 leftalign"> use psyco to speed up the operation (set mode)  </td>
 	</tr>
 	<tr class="row10">
-		<td class="col0 leftalign"> --mergeblanks=MERGEBLANKS  </td><td class="col1 leftalign"> whether to overwrite existing translations with blank translations (yes/no)  </td>
+		<td class="col0 leftalign"> --mergeblanks=MERGEBLANKS  </td><td class="col1 leftalign"> whether to overwrite existing translations with blank translations (yes/no). Default is yes.  </td>
 	</tr>
 	<tr class="row11">
-		<td class="col0 leftalign"> --mergecomments=MERGECOMMENTS  </td><td class="col1 leftalign"> whether to merge comments as well as translations (yes/no)  </td>
+		<td class="col0 leftalign"> --mergecomments=MERGECOMMENTS  </td><td class="col1 leftalign"> whether to merge comments as well as translations (yes/no). Default is yes.  </td>
 	</tr>
 </table>
 
 </div>
-<!-- SECTION "Usage" [706-2108] -->
+<!-- SECTION "Usage" [725-2173] -->
 <h2><a name="examples" id="examples">Examples</a></h2>
 <div class="level2">
 
@@ -127,16 +123,16 @@
 </p>
 
 </div>
-<!-- SECTION "Examples" [2109-2762] -->
-<h2><a name="bugs" id="bugs">Bugs</a></h2>
+<!-- SECTION "Examples" [2174-2827] -->
+<h2><a name="issues" id="issues">Issues</a></h2>
 <div class="level2">
-
-<p>
-
-Seems to have trouble merging KDE style comments back.
-
-</p>
+<ul>
+<li class="level1"><div class="li"> Seems to have trouble merging KDE style comments back. (Probably not relevant with newest versions any more.)</div>
+</li>
+<li class="level1"><div class="li"> Only files found in the input directory will be copied to the output. The template directory is not searched for extra files to copy to the output. Therefore it is always best to have your input directory in version control, and use the same directory as output. This will allow you to use the diff function of the version control system to double check changes made, with all the files of the input still present.</div>
+</li>
+</ul>
 
 </div>
-<!-- SECTION "Bugs" [2763-] --></body>
+<!-- SECTION "Issues" [2828-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-posegment.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-posegment.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-posegment.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-posegment.html Fri Jul 24 16:25:46 2009
@@ -23,7 +23,7 @@
 </p>
 
 <p>
-This is useful for the creation of a file that can be used as a Translation Memory (e.g. when using <a href="pootle-updatetm.html" class="wikilink1" title="pootle-updatetm.html">updatetm</a> to create translation memory for Pootle) as you should get better matching after you have exposed translated sentences that might occur elsewhere in your work.
+This is useful for the creation of a file that can be used as a Translation Memory (e.g. when using <a href="pootle-updatetm.html" class="wikilink2" title="pootle-updatetm.html">updatetm</a> to create translation memory for Pootle) as you should get better matching after you have exposed translated sentences that might occur elsewhere in your work.
 </p>
 
 <p>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-poterminology.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-poterminology.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-poterminology.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-poterminology.html Fri Jul 24 16:25:46 2009
@@ -153,7 +153,7 @@
 </p>
 
 <p>
-The default output file can be added to a Pootle project to provide <a href="pootle-terminology_matching.html" class="wikilink1" title="pootle-terminology_matching.html">terminology matching</a> suggestions for that project; alternately a special Terminology project can be used and it will provide terminology suggestions for all projects that do not have a pootle-terminology.po file.
+The default output file can be added to a Pootle project to provide <a href="pootle-terminology_matching.html" class="wikilink2" title="pootle-terminology_matching.html">terminology matching</a> suggestions for that project; alternately a special Terminology project can be used and it will provide terminology suggestions for all projects that do not have a pootle-terminology.po file.
 </p>
 
 <p>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-progress_progress.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-progress_progress.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-progress_progress.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-progress_progress.html Fri Jul 24 16:25:46 2009
@@ -36,8 +36,8 @@
 No visual feedback, this is useful if you want to use any of the scripts as part of another script and don't
 want feedback to interfere with the operation.
 </p>
-<pre class="code bash"><pre class="code bash"><span class="br0">[</span>dwayne at laptop OOo20<span class="br0">]</span>$ oo2po -P --<span class="re2">progress=</span>none en-US.sdf pot
-<span class="br0">[</span>dwayne at laptop OOo20<span class="br0">]</span>$</pre></pre>
+<pre class="code bash"><span class="br0">[</span>dwayne<span class="sy0">@</span>laptop OOo20<span class="br0">]</span>$ oo2po -P --<span class="re2">progress=</span>none en-US.sdf pot
+<span class="br0">[</span>dwayne<span class="sy0">@</span>laptop OOo20<span class="br0">]</span>$</pre>
 </div>
 <!-- SECTION "none" [249-529] -->
 <h2><a name="dots" id="dots">dots</a></h2>
@@ -47,11 +47,11 @@
 
 Use visual dots to represent progress.  Each dot represent a file that has been processed.
 </p>
-<pre class="code bash"><pre class="code bash"><span class="br0">[</span>dwayne at laptop OOo20<span class="br0">]</span>$ oo2po -P --<span class="re2">progress=</span>dots en-US.sdf pot
+<pre class="code bash"><span class="br0">[</span>dwayne<span class="sy0">@</span>laptop OOo20<span class="br0">]</span>$ oo2po -P --<span class="re2">progress=</span>dots en-US.sdf pot
 .............................................................................................
 .............................................................................................
 .........................................
-<span class="br0">[</span>dwayne at laptop OOo20<span class="br0">]</span>$</pre></pre>
+<span class="br0">[</span>dwayne<span class="sy0">@</span>laptop OOo20<span class="br0">]</span>$</pre>
 </div>
 <!-- SECTION "dots" [530-975] -->
 <h2><a name="bar_default" id="bar_default">bar (default)</a></h2>
@@ -61,13 +61,13 @@
 
 Use a progress bar consisting of hashes (#) to show progress.  
 </p>
-<pre class="code bash"><pre class="code bash"><span class="br0">[</span>dwayne at laptop OOo20<span class="br0">]</span>$ oo2po -P --<span class="re2">progress=</span>bar en-US.sdf pot
+<pre class="code bash"><span class="br0">[</span>dwayne<span class="sy0">@</span>laptop OOo20<span class="br0">]</span>$ oo2po -P --<span class="re2">progress=</span>bar en-US.sdf pot
 processing <span class="nu0">227</span> files...
-<span class="br0">[</span><span class="re3">##############################             <span class="br0">]</span>  <span class="nu0">69</span>%</span></pre></pre>
+<span class="br0">[</span><span class="co0">##############################             ]  69%</span></pre>
 <p>
 This is the default mode of operation, therefore this command would create the same output.
 </p>
-<pre class="code bash"><pre class="code bash"><span class="br0">[</span>dwayne at laptop OOo20<span class="br0">]</span>$ oo2po -P en-US.sdf pot</pre></pre>
+<pre class="code bash"><span class="br0">[</span>dwayne<span class="sy0">@</span>laptop OOo20<span class="br0">]</span>$ oo2po -P en-US.sdf pot</pre>
 </div>
 <!-- SECTION "bar (default)" [976-1385] -->
 <h2><a name="verbose" id="verbose">verbose</a></h2>
@@ -77,20 +77,20 @@
 
 Combine the hash (#) progress bar form the <em>bar</em> option with the actual names of files that have been processed.
 </p>
-<pre class="code bash"><pre class="code bash"><span class="br0">[</span>dwayne at laptop OOo20<span class="br0">]</span>$ oo2po -P --<span class="re2">progress=</span>verbose en-US.sdf pot
+<pre class="code bash"><span class="br0">[</span>dwayne<span class="sy0">@</span>laptop OOo20<span class="br0">]</span>$ oo2po -P --<span class="re2">progress=</span>verbose en-US.sdf pot
 processing <span class="nu0">227</span> files...
-so3/src.oo
-dbaccess/<span class="kw3">source</span>/ui/uno.oo
-helpcontent2/<span class="kw3">source</span>/text/shared.oo
-wizards/<span class="kw3">source</span>/formwizard.oo
-sch/<span class="kw3">source</span>/ui/dlg.oo
-helpcontent2/<span class="kw3">source</span>/text/sbasic/shared/<span class="nu0">01</span>.oo
-dbaccess/<span class="kw3">source</span>/core/resource.oo
-svtools/<span class="kw3">source</span>/sbx.oo
-dbaccess/<span class="kw3">source</span>/ui/relationdesign.oo
-scp2/<span class="kw3">source</span>/writer.oo
-filter/<span class="kw3">source</span>/xsltdialog.oo
-<span class="br0">[</span><span class="re3">##                                         <span class="br0">]</span>   <span class="nu0">5</span>%</span></pre></pre>
+so3<span class="sy0">/</span>src.oo
+dbaccess<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>ui<span class="sy0">/</span>uno.oo
+helpcontent2<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>text<span class="sy0">/</span>shared.oo
+wizards<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>formwizard.oo
+sch<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>ui<span class="sy0">/</span>dlg.oo
+helpcontent2<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>text<span class="sy0">/</span>sbasic<span class="sy0">/</span>shared<span class="sy0">/</span><span class="nu0">01</span>.oo
+dbaccess<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>core<span class="sy0">/</span>resource.oo
+svtools<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>sbx.oo
+dbaccess<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>ui<span class="sy0">/</span>relationdesign.oo
+scp2<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>writer.oo
+filter<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>xsltdialog.oo
+<span class="br0">[</span><span class="co0">##                                         ]   5%</span></pre>
 </div>
 <!-- SECTION "verbose" [1386-1992] -->
 <h2><a name="names" id="names">names</a></h2>
@@ -101,18 +101,18 @@
 Prints out only the filenames without any other progress indicator.  This is
 a good option when outputting to a log file rather than a terminal.
 </p>
-<pre class="code bash"><pre class="code bash"><span class="br0">[</span>dwayne at laptop OOo20<span class="br0">]</span>$ oo2po -P --<span class="re2">progress=</span>names en-US.sdf pot
-so3/src.oo
-dbaccess/<span class="kw3">source</span>/ui/uno.oo
-helpcontent2/<span class="kw3">source</span>/text/shared.oo
-wizards/<span class="kw3">source</span>/formwizard.oo
-sch/<span class="kw3">source</span>/ui/dlg.oo
-helpcontent2/<span class="kw3">source</span>/text/sbasic/shared/<span class="nu0">01</span>.oo
-dbaccess/<span class="kw3">source</span>/core/resource.oo
-svtools/<span class="kw3">source</span>/sbx.oo
-dbaccess/<span class="kw3">source</span>/ui/relationdesign.oo
-scp2/<span class="kw3">source</span>/writer.oo
-filter/<span class="kw3">source</span>/xsltdialog.oo</pre></pre>
+<pre class="code bash"><span class="br0">[</span>dwayne<span class="sy0">@</span>laptop OOo20<span class="br0">]</span>$ oo2po -P --<span class="re2">progress=</span>names en-US.sdf pot
+so3<span class="sy0">/</span>src.oo
+dbaccess<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>ui<span class="sy0">/</span>uno.oo
+helpcontent2<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>text<span class="sy0">/</span>shared.oo
+wizards<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>formwizard.oo
+sch<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>ui<span class="sy0">/</span>dlg.oo
+helpcontent2<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>text<span class="sy0">/</span>sbasic<span class="sy0">/</span>shared<span class="sy0">/</span><span class="nu0">01</span>.oo
+dbaccess<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>core<span class="sy0">/</span>resource.oo
+svtools<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>sbx.oo
+dbaccess<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>ui<span class="sy0">/</span>relationdesign.oo
+scp2<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>writer.oo
+filter<span class="sy0">/</span><span class="kw3">source</span><span class="sy0">/</span>xsltdialog.oo</pre>
 </div>
 <!-- SECTION "names" [1993-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-prop2po.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-prop2po.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-prop2po.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-prop2po.html Fri Jul 24 16:25:46 2009
@@ -88,6 +88,9 @@
 		<td class="col0 leftalign"> -P, --pot            </td><td class="col1 leftalign"> output <acronym title="Gettext Portable Object">PO</acronym> Templates (.pot) rather than <acronym title="Gettext Portable Object">PO</acronym> files (.po)  </td>
 	</tr>
 	<tr class="row11">
+		<td class="col0 leftalign"> <a href="toolkit-personality_type.html" class="wikilink1" title="toolkit-personality_type.html">--personality=TYPE</a>   </td><td class="col1 leftalign"> set the input behaviour: java (default), mozilla  </td>
+	</tr>
+	<tr class="row12">
 		<td class="col0 leftalign"> <a href="toolkit-duplicates_duplicatestyle.html" class="wikilink1" title="toolkit-duplicates_duplicatestyle.html">--duplicates=DUPLICATESTYLE</a>  </td><td class="col1 leftalign"> what to do with duplicate strings (identical source text): merge (default), msgid_comment, msgctxt, keep, msgid_comment_all  </td>
 	</tr>
 </table>
@@ -139,7 +142,7 @@
 </table>
 
 </div>
-<!-- SECTION "Usage" [301-2740] -->
+<!-- SECTION "Usage" [301-2821] -->
 <h2><a name="examples" id="examples">Examples</a></h2>
 <div class="level2">
 
@@ -149,7 +152,7 @@
 </p>
 
 </div>
-<!-- SECTION "Examples" [2741-2833] -->
+<!-- SECTION "Examples" [2822-2914] -->
 <h3><a name="creating_pot_files" id="creating_pot_files">Creating POT files</a></h3>
 <div class="level3">
 <pre class="code">prop2po -P properties pot</pre>
@@ -167,7 +170,7 @@
 </p>
 
 </div>
-<!-- SECTION "Creating POT files" [2834-3169] -->
+<!-- SECTION "Creating POT files" [2915-3250] -->
 <h3><a name="creating_po_files_from_existing_work" id="creating_po_files_from_existing_work">Creating PO files from existing work</a></h3>
 <div class="level3">
 <pre class="code">prop2po --duplicates=msgctxt -t reference zu zu-po</pre>
@@ -178,7 +181,7 @@
 </p>
 
 </div>
-<!-- SECTION "Creating PO files from existing work" [3170-3739] -->
+<!-- SECTION "Creating PO files from existing work" [3251-3820] -->
 <h3><a name="creating_.properties_files_from_your_translations" id="creating_.properties_files_from_your_translations">Creating .properties files from your translations</a></h3>
 <div class="level3">
 <pre class="code">po2prop -t reference zu-po zu</pre>
@@ -210,7 +213,7 @@
 </p>
 
 </div>
-<!-- SECTION "Creating .properties files from your translations" [3740-4644] -->
+<!-- SECTION "Creating .properties files from your translations" [3821-4725] -->
 <h2><a name="doing_away_with_native2ascii" id="doing_away_with_native2ascii">Doing away with native2ascii</a></h2>
 <div class="level2">
 
@@ -249,7 +252,7 @@
 </p>
 
 </div>
-<!-- SECTION "Doing away with native2ascii" [4645-5873] -->
+<!-- SECTION "Doing away with native2ascii" [4726-5954] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 
@@ -260,5 +263,5 @@
 </p>
 
 </div>
-<!-- SECTION "Bugs" [5874-] --></body>
+<!-- SECTION "Bugs" [5955-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-properties.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-properties.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-properties.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-properties.html Fri Jul 24 16:25:46 2009
@@ -19,11 +19,11 @@
 
 <p>
 
-The Translate Toolkit can manage Java .properties files
+The Translate Toolkit can manage Java .properties files with the <a href="toolkit-prop2po.html" class="wikilink1" title="toolkit-prop2po.html">prop2po</a> and po2prop tool. As part of the Mozilla localisation process, the <a href="toolkit-moz2po.html" class="wikilink1" title="toolkit-moz2po.html">moz2po</a> tool handles the properties files along with the other files.
 </p>
 
 </div>
-<!-- SECTION "Mozilla and Java properties files" [1-106] -->
+<!-- SECTION "Mozilla and Java properties files" [1-267] -->
 <h2><a name="features" id="features">Features</a></h2>
 <div class="level2">
 <ul>
@@ -34,7 +34,7 @@
 </ul>
 
 </div>
-<!-- SECTION "Features" [107-282] -->
+<!-- SECTION "Features" [268-443] -->
 <h2><a name="not_implemented" id="not_implemented">Not implemented</a></h2>
 <div class="level2">
 <ul>
@@ -43,14 +43,14 @@
 </ul>
 
 </div>
-<!-- SECTION "Not implemented" [283-391] -->
+<!-- SECTION "Not implemented" [444-552] -->
 <h2><a name="examples" id="examples">Examples</a></h2>
 <div class="level2">
 <pre class="code">editmenu.label = "Edit" 
 saveas.label = "Save As"</pre>
 
 </div>
-<!-- SECTION "Examples" [392-468] -->
+<!-- SECTION "Examples" [553-629] -->
 <h2><a name="references" id="references">References</a></h2>
 <div class="level2">
 <ul>
@@ -61,5 +61,5 @@
 </ul>
 
 </div>
-<!-- SECTION "References" [469-] --></body>
+<!-- SECTION "References" [630-] --></body>
 </html>

Added: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-py2web2po.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-py2web2po.html?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-py2web2po.html (added)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-py2web2po.html Fri Jul 24 16:25:46 2009
@@ -1,0 +1,173 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+  <title></title>
+  <link rel="stylesheet" media="screen" type="text/css" href="./style.css" />
+  <link rel="stylesheet" media="screen" type="text/css" href="./design.css" />
+  <link rel="stylesheet" media="print" type="text/css" href="./print.css" />
+
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+</head>
+<body>
+<a href=.>start</a></br>
+
+
+
+<h1><a name="web2py2po" id="web2py2po">web2py2po</a></h1>
+<div class="level1">
+
+<p>
+
+Converts web2py translation files to <acronym title="Gettext Portable Object">PO</acronym> files and vice versa.
+</p>
+
+<p>
+Web2py (<a href="http://mdp.cti.depaul.edu" class="urlextern" title="http://mdp.cti.depaul.edu">http://mdp.cti.depaul.edu</a>, formerly known as Gluon) is an open-source, Python-based web application framework by Massimo Di Pierro (inspired by Django and Rails).
+</p>
+
+<p>
+Web2py uses an internal localization engine based on Python dictionaries, which is applied with the T() lookup function. Web2py provides a built-in translation interface for the T()-engine, which is excellent for rapid application development.
+</p>
+
+<p>
+On the other hand, for collaboration and workflow control in a wider community you might probably rather want to use Pootle, Launchpad or similar facilities for translation, thus need to transform the web2py dictionaries into <acronym title="Gettext Portable Object">PO</acronym> files and vice versa. And exactly that is what the web2py2po converters are good for.
+</p>
+
+<p>
+<p><div class="noteclassic">Current this is only available in the SVN trunk version of the toolkit.
+</div></p>
+</p>
+
+</div>
+<!-- SECTION "web2py2po" [1-911] -->
+<h2><a name="usage" id="usage">Usage</a></h2>
+<div class="level2">
+<pre class="code">web2py2po [options] <web2py> <po>
+po2web2py [options] <po> <web2py></pre>
+
+<p>
+
+Where:
+</p>
+<table class="inline">
+	<tr class="row0">
+		<td class="col0"> <web2py> </td><td class="col1"> is a valid web2py translation file </td>
+	</tr>
+	<tr class="row1">
+		<td class="col0 leftalign"> <po>   </td><td class="col1 leftalign"> is a <acronym title="Gettext Portable Object">PO</acronym> or <acronym title="Gettext Portable Object Template">POT</acronym> file or a directory of <acronym title="Gettext Portable Object">PO</acronym> or <acronym title="Gettext Portable Object Template">POT</acronym> files  </td>
+	</tr>
+</table>
+
+<p>
+
+Options (web2py2po):
+</p>
+<table class="inline">
+	<tr class="row0">
+		<td class="col0 leftalign"> --version           </td><td class="col1 leftalign"> show program's version number and exit  </td>
+	</tr>
+	<tr class="row1">
+		<td class="col0 leftalign"> -h, --help          </td><td class="col1 leftalign"> show this help message and exit  </td>
+	</tr>
+	<tr class="row2">
+		<td class="col0 leftalign"> --manpage           </td><td class="col1 leftalign"> output a manpage based on the help  </td>
+	</tr>
+	<tr class="row3">
+		<td class="col0 leftalign"> <a href="toolkit-progress_progress.html" class="wikilink1" title="toolkit-progress_progress.html">--progress=PROGRESS</a>  </td><td class="col1 leftalign"> show progress as: dots, none, bar, names, verbose  </td>
+	</tr>
+	<tr class="row4">
+		<td class="col0 leftalign"> <a href="toolkit-errorlevel_errorlevel.html" class="wikilink1" title="toolkit-errorlevel_errorlevel.html">--errorlevel=ERRORLEVEL</a>  </td><td class="col1 leftalign"> show errorlevel as: none, message, exception, traceback   </td>
+	</tr>
+	<tr class="row5">
+		<td class="col0 leftalign"> -i INPUT, --input=INPUT      </td><td class="col1 leftalign"> read from INPUT in php format  </td>
+	</tr>
+	<tr class="row6">
+		<td class="col0 leftalign"> -x EXCLUDE, --exclude=EXCLUDE  </td><td class="col1 leftalign"> exclude names matching EXCLUDE from input paths   </td>
+	</tr>
+	<tr class="row7">
+		<td class="col0 leftalign"> -o OUTPUT, --output=OUTPUT     </td><td class="col1 leftalign"> write to OUTPUT in po, pot formats  </td>
+	</tr>
+	<tr class="row8">
+		<td class="col0 leftalign"> <a href="toolkit-psyco_mode.html" class="wikilink1" title="toolkit-psyco_mode.html">--psyco=MODE</a>  </td><td class="col1 leftalign"> use psyco to speed up the operation, modes: none,                        full, profile  </td>
+	</tr>
+</table>
+
+<p>
+
+Options (po2web2py):
+</p>
+<table class="inline">
+	<tr class="row0">
+		<td class="col0 leftalign"> --version            </td><td class="col1 leftalign"> show program's version number and exit  </td>
+	</tr>
+	<tr class="row1">
+		<td class="col0 leftalign"> -h, --help           </td><td class="col1 leftalign"> show this help message and exit  </td>
+	</tr>
+	<tr class="row2">
+		<td class="col0 leftalign"> --manpage            </td><td class="col1 leftalign"> output a manpage based on the help  </td>
+	</tr>
+	<tr class="row3">
+		<td class="col0 leftalign"> <a href="toolkit-progress_progress.html" class="wikilink1" title="toolkit-progress_progress.html">--progress=PROGRESS</a>  </td><td class="col1 leftalign"> show progress as: dots, none, bar, names, verbose  </td>
+	</tr>
+	<tr class="row4">
+		<td class="col0 leftalign"> <a href="toolkit-errorlevel_errorlevel.html" class="wikilink1" title="toolkit-errorlevel_errorlevel.html">--errorlevel=ERRORLEVEL</a>    </td><td class="col1 leftalign"> show errorlevel as: none, message, exception, traceback  </td>
+	</tr>
+	<tr class="row5">
+		<td class="col0 leftalign"> -i INPUT, --input=INPUT  </td><td class="col1 leftalign"> read from INPUT in po, pot formats  </td>
+	</tr>
+	<tr class="row6">
+		<td class="col0 leftalign"> -x EXCLUDE, --exclude=EXCLUDE   </td><td class="col1 leftalign"> exclude names matching EXCLUDE from input paths  </td>
+	</tr>
+	<tr class="row7">
+		<td class="col0 leftalign"> -o OUTPUT, --output=OUTPUT      </td><td class="col1 leftalign"> write to OUTPUT in php format  </td>
+	</tr>
+	<tr class="row8">
+		<td class="col0 leftalign"> <a href="toolkit-psyco_mode.html" class="wikilink1" title="toolkit-psyco_mode.html">--psyco=MODE</a>         </td><td class="col1 leftalign"> use psyco to speed up the operation, modes: none, full, profile  </td>
+	</tr>
+	<tr class="row9">
+		<td class="col0 leftalign"> --fuzzy | --nofuzzy     </td><td class="col1 leftalign"> include|exclude fuzzy translations  </td>
+	</tr>
+</table>
+
+</div>
+<!-- SECTION "Usage" [912-2632] -->
+<h2><a name="examples" id="examples">Examples</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "Examples" [2633-2654] -->
+<h2><a name="notes" id="notes">Notes</a></h2>
+<div class="level2">
+
+<p>
+
+<strong>Handling of blanks/untranslated messages:</strong>
+</p>
+
+<p>
+Untranslated messages in the web2py translation files are usually marked with a leading "*** ", so:
+
+</p>
+<ul>
+<li class="level1"><div class="li"> all target strings from the web2py sources with a leading "*** " are inserted as blank msgstr's into the <acronym title="Gettext Portable Object">PO</acronym> result (web2py2po)</div>
+</li>
+</ul>
+<ul>
+<li class="level1"><div class="li"> blank msgstr's from the <acronym title="Gettext Portable Object">PO</acronym> file will get the msgid string with a leading "*** " as target string in the web2py result (po2web2py)</div>
+</li>
+</ul>
+
+</div>
+<!-- SECTION "Notes" [2655-3100] -->
+<h2><a name="issues" id="issues">Issues</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "Issues" [3101-3120] -->
+<h2><a name="bugs" id="bugs">Bugs</a></h2>
+<div class="level2">
+
+</div>
+<!-- SECTION "Bugs" [3121-] --></body>
+</html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-qm.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-qm.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-qm.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-qm.html Fri Jul 24 16:25:46 2009
@@ -19,15 +19,11 @@
 
 <p>
 
-NOTE: In still to be released 1.1 of the toolkit
-</p>
-
-<p>
 A .qm file is a compiled Qt <a href="toolkit-ts.html" class="wikilink1" title="toolkit-ts.html">.ts</a> file.  In many ways it is similar to Gettext, in that it uses a hashing table to lookup the translated text.  In older version they store only the hash and the translation which doesn't make the format useful for recovering translated text.
 </p>
 
 </div>
-<!-- SECTION "Qt .qm" [1-351] -->
+<!-- SECTION "Qt .qm" [1-301] -->
 <h2><a name="conformance" id="conformance">Conformance</a></h2>
 <div class="level2">
 
@@ -41,7 +37,7 @@
 </p>
 
 </div>
-<!-- SECTION "Conformance" [352-837] -->
+<!-- SECTION "Conformance" [302-787] -->
 <h2><a name="todo" id="todo">TODO</a></h2>
 <div class="level2">
 <ul>
@@ -54,5 +50,5 @@
 </ul>
 
 </div>
-<!-- SECTION "TODO" [838-] --></body>
+<!-- SECTION "TODO" [788-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rc.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rc.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rc.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rc.html Fri Jul 24 16:25:46 2009
@@ -19,7 +19,7 @@
 
 <p>
 
-Windows .rc files, or resource files, are used to store translatable text, dialogs, menu, etc. for Windows application.
+Windows .rc files, or resource files, are used to store translatable text, dialogs, menu, etc. for Windows applications.  The format can be handled by the Translate Toolkit <a href="toolkit-rc2po.html" class="wikilink1" title="toolkit-rc2po.html">rc2po</a> and po2rc.
 </p>
 
 <p>
@@ -28,7 +28,7 @@
 </p>
 
 </div>
-<!-- SECTION "Windows RC files" [1-180] -->
+<!-- SECTION "Windows RC files" [1-254] -->
 <h2><a name="conformance" id="conformance">Conformance</a></h2>
 <div class="level2">
 
@@ -38,7 +38,7 @@
 </p>
 
 </div>
-<!-- SECTION "Conformance" [181-494] -->
+<!-- SECTION "Conformance" [255-568] -->
 <h2><a name="useful_resource" id="useful_resource">Useful resource</a></h2>
 <div class="level2">
 <ul>
@@ -49,7 +49,7 @@
 </ul>
 
 </div>
-<!-- SECTION "Useful resource" [495-699] -->
+<!-- SECTION "Useful resource" [569-773] -->
 <h2><a name="supported_elements" id="supported_elements">Supported elements</a></h2>
 <div class="level2">
 <ul>
@@ -64,7 +64,7 @@
 </ul>
 
 </div>
-<!-- SECTION "Supported elements" [700-904] -->
+<!-- SECTION "Supported elements" [774-978] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 <ul>
@@ -75,5 +75,5 @@
 </ul>
 
 </div>
-<!-- SECTION "Bugs" [905-] --></body>
+<!-- SECTION "Bugs" [979-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rc2po.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rc2po.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rc2po.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rc2po.html Fri Jul 24 16:25:46 2009
@@ -22,13 +22,8 @@
 Converts Windows Resource .rc files to Gettext <acronym title="Gettext Portable Object">PO</acronym> format.
 </p>
 
-<p>
-<p><div class="noteclassic">New in v1.2
-</div></p>
-</p>
-
-</div>
-<!-- SECTION "rc2po" [1-106] -->
+</div>
+<!-- SECTION "rc2po" [1-80] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
 <pre class="code">rc2po [options] <rc> <po>
@@ -132,15 +127,21 @@
 		<td class="col0 leftalign"> --charset=CHARSET    </td><td class="col1 leftalign"> charset to use to decode the RC files (default: utf-8)  </td>
 	</tr>
 	<tr class="row11">
+		<td class="col0 leftalign"> --lang=LANG  </td><td class="col1 leftalign"> LANG entry  </td>
+	</tr>
+	<tr class="row12">
+		<td class="col0"> --sublang=SUBLANG </td><td class="col1"> SUBLANG entry (default: SUBLANG_DEFAULT) </td>
+	</tr>
+	<tr class="row13">
 		<td class="col0 leftalign"> --fuzzy              </td><td class="col1 leftalign"> use translations marked fuzzy  </td>
 	</tr>
-	<tr class="row12">
+	<tr class="row14">
 		<td class="col0 leftalign"> --nofuzzy            </td><td class="col1 leftalign"> don't use translations marked fuzzy (default)  </td>
 	</tr>
 </table>
 
 </div>
-<!-- SECTION "Usage" [107-2484] -->
+<!-- SECTION "Usage" [81-2554] -->
 <h2><a name="examples" id="examples">Examples</a></h2>
 <div class="level2">
 
@@ -191,7 +192,7 @@
 </p>
 
 </div>
-<!-- SECTION "Examples" [2485-3971] -->
+<!-- SECTION "Examples" [2555-4041] -->
 <h2><a name="issues" id="issues">Issues</a></h2>
 <div class="level2">
 
@@ -205,7 +206,7 @@
 </p>
 
 </div>
-<!-- SECTION "Issues" [3972-4182] -->
+<!-- SECTION "Issues" [4042-4252] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 
@@ -216,5 +217,5 @@
 </p>
 
 </div>
-<!-- SECTION "Bugs" [4183-] --></body>
+<!-- SECTION "Bugs" [4253-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rewrite_style.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rewrite_style.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rewrite_style.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-rewrite_style.html Fri Jul 24 16:25:46 2009
@@ -77,7 +77,29 @@
 </p>
 
 </div>
-<!-- SECTION "blank" [790-1064] -->
+<!-- SECTION "blank" [790-1063] -->
+<h2><a name="bracket" id="bracket">bracket</a></h2>
+<div class="level2">
+
+<p>
+
+New in 1.4
+</p>
+
+<p>
+Places brackets around the translated text.
+
+</p>
+<pre class="code">msgid "English"
+msgstr "[English]"</pre>
+
+<p>
+
+This can be used in the same way as <code>xxx</code> to check for translatability.  It is also useful with very long strings as it allows you to check that the full string in rendered and has not been cutoff by the application.
+</p>
+
+</div>
+<!-- SECTION "bracket" [1064-1401] -->
 <h2><a name="chef" id="chef">chef</a></h2>
 <div class="level2">
 
@@ -99,7 +121,29 @@
 </p>
 
 </div>
-<!-- SECTION "chef" [1065-1431] -->
+<!-- SECTION "chef" [1402-1768] -->
+<h2><a name="flipped" id="flipped">flipped</a></h2>
+<div class="level2">
+
+<p>
+
+New in version 1.4
+</p>
+
+<p>
+Change the text into a version that uses equivalent latin characters that are upside down.
+
+</p>
+<pre class="code">msgid "English"
+msgstr "‮ƎuƃÊ
ısɥ"</pre>
+
+<p>
+
+<code>flipped</code> can give an output that simulates RTL languages.  It inserts RTL characters to try to achieve RTL like results.  Its not perfect but will give you some sense of whether your application can do RTL.  Or just use it for fun!
+</p>
+
+</div>
+<!-- SECTION "flipped" [1769-2183] -->
 <h2><a name="unicode" id="unicode">unicode</a></h2>
 <div class="level2">
 
@@ -126,5 +170,5 @@
 </p>
 
 </div>
-<!-- SECTION "unicode" [1432-] --></body>
+<!-- SECTION "unicode" [2184-] --></body>
 </html>

Added: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-sub2po.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-sub2po.html?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-sub2po.html (added)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-sub2po.html Fri Jul 24 16:25:46 2009
@@ -1,0 +1,180 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+  <title></title>
+  <link rel="stylesheet" media="screen" type="text/css" href="./style.css" />
+  <link rel="stylesheet" media="screen" type="text/css" href="./design.css" />
+  <link rel="stylesheet" media="print" type="text/css" href="./print.css" />
+
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+</head>
+<body>
+<a href=.>start</a></br>
+
+
+
+<h1><a name="sub2po_and_po2sub" id="sub2po_and_po2sub">sub2po and po2sub</a></h1>
+<div class="level1">
+
+<p>
+
+sub2po allows you to use the same principles of <acronym title="Gettext Portable Object">PO</acronym> files with <a href="toolkit-subtitles.html" class="wikilink1" title="toolkit-subtitles.html">subtitles</a>. In <acronym title="Gettext Portable Object">PO</acronym> only items that change are marked fuzzy and only new items need to be translated, unchanged items remain unchanged for the translation.
+</p>
+
+</div>
+<!-- SECTION "sub2po and po2sub" [1-254] -->
+<h2><a name="usage" id="usage">Usage</a></h2>
+<div class="level2">
+<pre class="code">sub2po [options] <foo.srt> <foo.po>
+po2sub [options] [-t <foo.srt>] <XX.po> <foo-XX.srt></pre>
+
+<p>
+
+Where:
+</p>
+<table class="inline">
+	<tr class="row0">
+		<td class="col0 leftalign"> foo.srt    </td><td class="col1 leftalign"> is the input subtitle file   </td>
+	</tr>
+	<tr class="row1">
+		<td class="col0 leftalign"> foo.po     </td><td class="col1 leftalign"> is an empty <acronym title="Gettext Portable Object">PO</acronym> file that may be translated   </td>
+	</tr>
+	<tr class="row2">
+		<td class="col0 leftalign"> XX.po      </td><td class="col1 leftalign"> is a <acronym title="Gettext Portable Object">PO</acronym> file translated into the XX language   </td>
+	</tr>
+	<tr class="row3">
+		<td class="col0"> foo-XX.srt </td><td class="col1 leftalign"> is the foo.srt file translated into language XX   </td>
+	</tr>
+</table>
+
+<p>
+
+Options (sub2po):
+
+</p>
+<table class="inline">
+	<tr class="row0">
+		<td class="col0 leftalign"> --version            </td><td class="col1 leftalign"> show program's version number and exit   </td>
+	</tr>
+	<tr class="row1">
+		<td class="col0 leftalign"> -h, --help           </td><td class="col1 leftalign"> show this help message and exit   </td>
+	</tr>
+	<tr class="row2">
+		<td class="col0 leftalign"> --manpage            </td><td class="col1 leftalign"> output a manpage based on the help   </td>
+	</tr>
+	<tr class="row3">
+		<td class="col0 leftalign"> <a href="toolkit-progress_progress.html" class="wikilink1" title="toolkit-progress_progress.html">--progress=PROGRESS</a>  </td><td class="col1 leftalign"> show progress as: dots, none, bar, names, verbose   </td>
+	</tr>
+	<tr class="row4">
+		<td class="col0 leftalign"> <a href="toolkit-errorlevel_errorlevel.html" class="wikilink1" title="toolkit-errorlevel_errorlevel.html">--errorlevel=ERRORLEVEL</a>   </td><td class="col1 leftalign"> show errorlevel as: none, message, exception, traceback   </td>
+	</tr>
+	<tr class="row5">
+		<td class="col0 leftalign"> -iINPUT, --input=INPUT    </td><td class="col1 leftalign"> read from INPUT in .srt format   </td>
+	</tr>
+	<tr class="row6">
+		<td class="col0 leftalign"> -xEXCLUDE, --exclude=EXCLUDE   </td><td class="col1 leftalign"> exclude names matching EXCLUDE from input paths   </td>
+	</tr>
+	<tr class="row7">
+		<td class="col0 leftalign"> -oOUTPUT, --output=OUTPUT  </td><td class="col1 leftalign"> write to OUTPUT in po, pot formats   </td>
+	</tr>
+	<tr class="row8">
+		<td class="col0 leftalign"> <a href="toolkit-psyco_mode.html" class="wikilink1" title="toolkit-psyco_mode.html">--psyco=MODE</a>         </td><td class="col1 leftalign"> use psyco to speed up the operation, modes: none, full, profile   </td>
+	</tr>
+	<tr class="row9">
+		<td class="col0 leftalign"> -P, --pot            </td><td class="col1 leftalign"> output <acronym title="Gettext Portable Object">PO</acronym> Templates (.pot) rather than <acronym title="Gettext Portable Object">PO</acronym> files (.po)   </td>
+	</tr>
+	<tr class="row10">
+		<td class="col0 leftalign"> <a href="toolkit-duplicates_duplicatestyle.html" class="wikilink1" title="toolkit-duplicates_duplicatestyle.html">--duplicates=DUPLICATESTYLE</a>  </td><td class="col1"> what to do with duplicate strings (identical source text): merge, msgctxt (default) </td>
+	</tr>
+</table>
+
+<p>
+
+Options (po2sub):
+
+</p>
+<table class="inline">
+	<tr class="row0">
+		<td class="col0 leftalign"> --version            </td><td class="col1 leftalign"> show program's version number and exit   </td>
+	</tr>
+	<tr class="row1">
+		<td class="col0 leftalign"> -h, --help           </td><td class="col1 leftalign"> show this help message and exit   </td>
+	</tr>
+	<tr class="row2">
+		<td class="col0 leftalign"> --manpage            </td><td class="col1 leftalign"> output a manpage based on the help   </td>
+	</tr>
+	<tr class="row3">
+		<td class="col0 leftalign"> <a href="toolkit-progress_progress.html" class="wikilink1" title="toolkit-progress_progress.html">--progress=PROGRESS</a>  </td><td class="col1 leftalign"> show progress as: dots, none, bar, names, verbose   </td>
+	</tr>
+	<tr class="row4">
+		<td class="col0 leftalign"> <a href="toolkit-errorlevel_errorlevel.html" class="wikilink1" title="toolkit-errorlevel_errorlevel.html">--errorlevel=ERRORLEVEL</a>   </td><td class="col1 leftalign"> show errorlevel as: none, message, exception, traceback   </td>
+	</tr>
+	<tr class="row5">
+		<td class="col0 leftalign"> -iINPUT, --input=INPUT    </td><td class="col1 leftalign"> read from INPUT in po, pot formats   </td>
+	</tr>
+	<tr class="row6">
+		<td class="col0 leftalign"> -xEXCLUDE, --exclude=EXCLUDE   </td><td class="col1 leftalign"> exclude names matching EXCLUDE from input paths   </td>
+	</tr>
+	<tr class="row7">
+		<td class="col0 leftalign"> -oOUTPUT, --output=OUTPUT   </td><td class="col1 leftalign"> write to OUTPUT in srt format   </td>
+	</tr>
+	<tr class="row8">
+		<td class="col0 leftalign"> -tTEMPLATE, --template=TEMPLATE   </td><td class="col1 leftalign"> read from TEMPLATE in txt format   </td>
+	</tr>
+	<tr class="row9">
+		<td class="col0 leftalign"> <a href="toolkit-psyco_mode.html" class="wikilink1" title="toolkit-psyco_mode.html">--psyco=MODE</a>         </td><td class="col1 leftalign"> use psyco to speed up the operation, modes: none, full, profile   </td>
+	</tr>
+	<tr class="row10">
+		<td class="col0 leftalign"> --fuzzy              </td><td class="col1 leftalign"> use translations marked fuzzy  </td>
+	</tr>
+	<tr class="row11">
+		<td class="col0 leftalign"> --nofuzzy            </td><td class="col1 leftalign"> don't use translations marked fuzzy (default)  </td>
+	</tr>
+</table>
+
+</div>
+<!-- SECTION "Usage" [255-2467] -->
+<h3><a name="examples" id="examples">Examples</a></h3>
+<div class="level3">
+
+<p>
+
+To create the <acronym title="Gettext Portable Object Template">POT</acronym> files is simple:
+
+</p>
+<pre class="code">sub2po -P SUBTITLE_FILE subtitles.pot</pre>
+
+<p>
+
+A translator would copy the <acronym title="Gettext Portable Object Template">POT</acronym> file to their own <acronym title="Gettext Portable Object">PO</acronym> file and then create translations of the entries. If you wish to create a <acronym title="Gettext Portable Object">PO</acronym> file and not a <acronym title="Gettext Portable Object Template">POT</acronym> file then leave off the <em>-P</em> option.
+</p>
+
+<p>
+To convert back:
+
+</p>
+<pre class="code">po2sub -t SUBTITLE_FILE   subtitles-XX.po  subtitles-XX.srt</pre>
+
+</div>
+<!-- SECTION "Examples" [2468-2835] -->
+<h3><a name="translating" id="translating">Translating</a></h3>
+<div class="level3">
+
+<p>
+
+Translate as normal. However, see the issues mentioned at <a href="toolkit-subtitles.html" class="wikilink1" title="toolkit-subtitles.html">subtitles</a>.
+</p>
+
+</div>
+<!-- SECTION "Translating" [2836-2932] -->
+<h3><a name="bugs" id="bugs">Bugs</a></h3>
+<div class="level3">
+
+<p>
+There might be some issues with encodings, since the srt files don't specify them. We assume files to be encoded in UTF-8, so a conversion should solve this easily. Note that most of the handling of the srt files come from gaupol.
+</p>
+
+</div>
+<!-- SECTION "Bugs" [2933-] --></body>
+</html>

Added: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-subtitles.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-subtitles.html?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-subtitles.html (added)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-subtitles.html Fri Jul 24 16:25:46 2009
@@ -1,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+  <title></title>
+  <link rel="stylesheet" media="screen" type="text/css" href="./style.css" />
+  <link rel="stylesheet" media="screen" type="text/css" href="./design.css" />
+  <link rel="stylesheet" media="print" type="text/css" href="./print.css" />
+
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+</head>
+<body>
+<a href=.>start</a></br>
+
+
+
+<h1><a name="subtitles" id="subtitles">Subtitles</a></h1>
+<div class="level1">
+
+<p>
+
+The translation of subtitles are supported in the toolkit with the commands <a href="toolkit-sub2po.html" class="wikilink1" title="toolkit-sub2po.html">sub2po</a> and po2sub.
+</p>
+
+<p>
+The following formats are supported for subtitles:
+</p>
+<ul>
+<li class="level1"><div class="li"> MicroDVD</div>
+</li>
+<li class="level1"><div class="li"> MPL2</div>
+</li>
+<li class="level1"><div class="li"> MPsub</div>
+</li>
+<li class="level1"><div class="li"> <a href="http://en.wikipedia.org/wiki/SubRip" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/SubRip">SubRip</a> (.srt)</div>
+</li>
+<li class="level1"><div class="li"> <a href="http://en.wikipedia.org/wiki/SubViewer" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/SubViewer">SubViewer</a> 2.0 (.sub)</div>
+</li>
+<li class="level1"><div class="li"> TMPlayer</div>
+</li>
+<li class="level1"><div class="li"> Sub Station Alpha</div>
+</li>
+<li class="level1"><div class="li"> Advanced Sub Station Alpha</div>
+</li>
+</ul>
+
+<p>
+
+Both .sub and .srt are the main formats <a href="http://help.youtube.com/support/youtube/bin/answer.py?answer=100077" class="urlextern" title="http://help.youtube.com/support/youtube/bin/answer.py?answer=100077">supported by YouTube</a>
+</p>
+
+</div>
+<!-- SECTION "Subtitles" [1-466] -->
+<h2><a name="implementation_details" id="implementation_details">Implementation details</a></h2>
+<div class="level2">
+
+<p>
+
+Format support is provided <a href="http://home.gna.org/gaupol/" class="urlextern" title="http://home.gna.org/gaupol/">Gaupol</a> a subtitling tool.  Further enhancement of format support in Gaupol will directly benefit our conversion ability.
+</p>
+
+</div>
+<!-- SECTION "Implementation details" [467-683] -->
+<h2><a name="usage" id="usage">Usage</a></h2>
+<div class="level2">
+
+<p>
+
+It must be noted that our tools provide the ability to localise the subtitles. This in itself is useful and allows a translator to use their existing localisation tools.  But this is pure localisation and users should be aware that they might still need to post edit their work to account for timing, limited text space, limits in the ability of viewers to keep up with the text.
+</p>
+
+<p>
+For most cases simply localising will be good enough.  But in some cases the translated work might need to be reviewed to fix any such issues.  You can use Gaupol to perform those reviews.
+
+</p>
+
+</div>
+<!-- SECTION "Usage" [684-] --></body>
+</html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-symb2po.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-symb2po.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-symb2po.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-symb2po.html Fri Jul 24 16:25:46 2009
@@ -23,12 +23,12 @@
 </p>
 
 <p>
-<p><div class="noteclassic">These tools currently only appear in the development version of the toolkit. You can get it by <a href="toolkit-installation.html" class="wikilink1" title="toolkit-installation.html">checking out the code from Subverion</a>
+<p><div class="noteclassic">Appears in version 1.3 of the toolkit.
 </div></p>
 </p>
 
 </div>
-<!-- SECTION "symb2po" [1-398] -->
+<!-- SECTION "symb2po" [1-280] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
 <pre class="code">symb2po [options] [-t <target_lang_symb>] <source_lang_symb> <po>
@@ -128,12 +128,12 @@
 </table>
 
 </div>
-<!-- SECTION "Usage" [399-2499] -->
+<!-- SECTION "Usage" [281-2381] -->
 <h2><a name="examples" id="examples">Examples</a></h2>
 <div class="level2">
 
 </div>
-<!-- SECTION "Examples" [2500-2521] -->
+<!-- SECTION "Examples" [2382-2403] -->
 <h3><a name="symb2po1" id="symb2po1">symb2po</a></h3>
 <div class="level3">
 
@@ -166,7 +166,7 @@
 </p>
 
 </div>
-<!-- SECTION "symb2po" [2522-3764] -->
+<!-- SECTION "symb2po" [2404-3646] -->
 <h3><a name="po2symb" id="po2symb">po2symb</a></h3>
 <div class="level3">
 
@@ -182,7 +182,7 @@
 <pre class="code">po2symb -t my_project.r01 my_project-en-fr.po my_project.r02</pre>
 
 </div>
-<!-- SECTION "po2symb" [3765-4314] -->
+<!-- SECTION "po2symb" [3647-4196] -->
 <h2><a name="notes" id="notes">Notes</a></h2>
 <div class="level2">
 
@@ -203,7 +203,7 @@
 </p>
 
 </div>
-<!-- SECTION "Notes" [4315-4625] -->
+<!-- SECTION "Notes" [4197-4507] -->
 <h2><a name="issues" id="issues">Issues</a></h2>
 <div class="level2">
 
@@ -224,7 +224,7 @@
 </p>
 
 </div>
-<!-- SECTION "Issues" [4626-5003] -->
+<!-- SECTION "Issues" [4508-4885] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 
@@ -234,5 +234,5 @@
 </p>
 
 </div>
-<!-- SECTION "Bugs" [5004-] --></body>
+<!-- SECTION "Bugs" [4886-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-tbx.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-tbx.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-tbx.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-tbx.html Fri Jul 24 16:25:46 2009
@@ -30,7 +30,7 @@
 <h2><a name="references" id="references">References</a></h2>
 <div class="level2">
 <ul>
-<li class="level1"><div class="li"> <a href="http://www.lisa.org/standards/tbx/" class="urlextern" title="http://www.lisa.org/standards/tbx/">Standard home page</a></div>
+<li class="level1"><div class="li"> <a href="http://www.lisa.org/Term-Base-eXchange.32.0.html" class="urlextern" title="http://www.lisa.org/Term-Base-eXchange.32.0.html">Standard home page</a></div>
 </li>
 <li class="level1"><div class="li"> <a href="http://www.lisa.org/TBX-Specification.33.0.html" class="urlextern" title="http://www.lisa.org/TBX-Specification.33.0.html">Specification</a></div>
 </li>
@@ -38,26 +38,31 @@
 </li>
 </ul>
 
-</div>
-<!-- SECTION "References" [140-434] -->
+<p>
+
+You might also be interested in reading about <acronym title="TermBase eXchange">TBX</acronym>-Basic - a simpler, reduced version of <acronym title="TermBase eXchange">TBX</acronym> with most of the useful features included.
+</p>
+
+</div>
+<!-- SECTION "References" [140-584] -->
 <h2><a name="standard_conformance" id="standard_conformance">Standard conformance</a></h2>
 <div class="level2">
 
 </div>
-<!-- SECTION "Standard conformance" [435-467] -->
+<!-- SECTION "Standard conformance" [585-617] -->
 <h3><a name="done" id="done">Done</a></h3>
 <div class="level3">
 <ul>
 <li class="level1"><div class="li"> Basic file creation</div>
 </li>
-<li class="level1"><div class="li"> Creating a bilingual list from <acronym title="Comma Seperated Value">CSV</acronym> with <a href="toolkit-csv2tbx.html" class="wikilink1" title="toolkit-csv2tbx.html">csv2tbx</a></div>
+<li class="level1"><div class="li"> Creating a bilingual list from <acronym title="Comma Separated Value">CSV</acronym> with <a href="toolkit-csv2tbx.html" class="wikilink1" title="toolkit-csv2tbx.html">csv2tbx</a></div>
 </li>
 <li class="level1"><div class="li"> Using <tig> tags, not ntig</div>
 </li>
 </ul>
 
 </div>
-<!-- SECTION "Done" [468-594] -->
+<!-- SECTION "Done" [618-744] -->
 <h3><a name="todo" id="todo">Todo</a></h3>
 <div class="level3">
 <ul>
@@ -82,7 +87,7 @@
 </ul>
 
 </div>
-<!-- SECTION "Todo" [595-795] -->
+<!-- SECTION "Todo" [745-945] -->
 <h2><a name="implementation_notes_for_missing_features" id="implementation_notes_for_missing_features">Implementation notes for missing features</a></h2>
 <div class="level2">
 
@@ -97,7 +102,7 @@
 </ul>
 
 </div>
-<!-- SECTION "Implementation notes for missing features" [796-946] -->
+<!-- SECTION "Implementation notes for missing features" [946-1096] -->
 <h3><a name="synonyms" id="synonyms">Synonyms</a></h3>
 <div class="level3">
 
@@ -107,17 +112,17 @@
 <acronym title="TermBase eXchange">TBX</acronym>:
 
 </p>
-<pre class="code xml"><pre class="code xml"><span class="sc3"><span class="re1"><termNote</span> <span class="re0">type</span>=<span class="st0">"termNote"</span><span class="re2">></span></span>synonym<span class="sc3"><span class="re1"></termNote<span class="re2">></span></span></span></pre></pre>
+<pre class="code xml"><span class="sc3"><span class="re1"><termNote</span> <span class="re0">type</span>=<span class="st0">"termNote"</span><span class="re2">></span></span>synonym<span class="sc3"><span class="re1"></termNote<span class="re2">></span></span></span></pre>
 <p>
 according to this <acronym title="TermBase eXchange">TBX</acronym> documentation. In another place:
 </p>
-<pre class="code xml"><pre class="code xml"><span class="sc3"><span class="re1"><termNote</span> <span class="re0">type</span>=<span class="st0">"termType"</span><span class="re2">></span></span>synonym<span class="sc3"><span class="re1"></termNote<span class="re2">></span></span></span></pre></pre>
+<pre class="code xml"><span class="sc3"><span class="re1"><termNote</span> <span class="re0">type</span>=<span class="st0">"termType"</span><span class="re2">></span></span>synonym<span class="sc3"><span class="re1"></termNote<span class="re2">></span></span></span></pre>
 <p>
 inside a <termGrp>, following <term>
 </p>
 
 </div>
-<!-- SECTION "Synonyms" [947-1215] -->
+<!-- SECTION "Synonyms" [1097-1365] -->
 <h3><a name="definition" id="definition">Definition</a></h3>
 <div class="level3">
 
@@ -127,16 +132,16 @@
 <acronym title="TermBase eXchange">TBX</acronym>
 
 </p>
-<pre class="code xml"><pre class="code xml"><span class="sc3"><span class="re1"><descripGrp<span class="re2">></span></span></span>
+<pre class="code xml"><span class="sc3"><span class="re1"><descripGrp<span class="re2">></span></span></span>
    <span class="sc3"><span class="re1"><descrip</span> <span class="re0">type</span>=<span class="st0">"definition"</span><span class="re2">></span></span>The longish definition of the term<span class="sc3"><span class="re1"></descrip<span class="re2">></span></span></span>
-<span class="sc3"><span class="re1"></descripGrp<span class="re2">></span></span></span></pre></pre>
+<span class="sc3"><span class="re1"></descripGrp<span class="re2">></span></span></span></pre>
 <p>
 inside langSet
 <descript> can probably be used directly under langSet
 </p>
 
 </div>
-<!-- SECTION "Definition" [1216-1481] -->
+<!-- SECTION "Definition" [1366-1631] -->
 <h3><a name="context" id="context">Context</a></h3>
 <div class="level3">
 
@@ -146,13 +151,13 @@
 <acronym title="TermBase eXchange">TBX</acronym>:
 
 </p>
-<pre class="code xml"><pre class="code xml"><span class="sc3"><span class="re1"><descrip</span> <span class="re0">type</span>=<span class="st0">"context"</span><span class="re2">></span></span>A usually somewhat longer contextual sentence.<span class="sc3"><span class="re1"></descrip<span class="re2">></span></span></span></pre></pre>
+<pre class="code xml"><span class="sc3"><span class="re1"><descrip</span> <span class="re0">type</span>=<span class="st0">"context"</span><span class="re2">></span></span>A usually somewhat longer contextual sentence.<span class="sc3"><span class="re1"></descrip<span class="re2">></span></span></span></pre>
 <p>
 inside <ntig>
 </p>
 
 </div>
-<!-- SECTION "Context" [1482-1680] -->
+<!-- SECTION "Context" [1632-1830] -->
 <h3><a name="parts_of_speech" id="parts_of_speech">Parts of speech</a></h3>
 <div class="level3">
 
@@ -162,13 +167,13 @@
 <acronym title="TermBase eXchange">TBX</acronym>:
 
 </p>
-<pre class="code xml"><pre class="code xml"><span class="sc3"><span class="re1"><termNote</span> <span class="re0">type</span>=<span class="st0">"partOfSpeech"</span> <span class="re2">></span></span>noun<span class="sc3"><span class="re1"></termNote<span class="re2">></span></span></span></pre></pre>
+<pre class="code xml"><span class="sc3"><span class="re1"><termNote</span> <span class="re0">type</span>=<span class="st0">"partOfSpeech"</span> <span class="re2">></span></span>noun<span class="sc3"><span class="re1"></termNote<span class="re2">></span></span></span></pre>
 <p>
 following <term>
 </p>
 
 </div>
-<!-- SECTION "Parts of speech" [1681-1828] -->
+<!-- SECTION "Parts of speech" [1831-1978] -->
 <h3><a name="cross_reference" id="cross_reference">Cross reference</a></h3>
 <div class="level3">
 
@@ -179,7 +184,7 @@
 </p>
 
 </div>
-<!-- SECTION "Cross reference" [1829-1907] -->
+<!-- SECTION "Cross reference" [1979-2057] -->
 <h3><a name="abbreviations" id="abbreviations">Abbreviations</a></h3>
 <div class="level3">
 
@@ -187,9 +192,63 @@
 NLS: same as alternate term: a.m. → before noon<br/>
 
 <acronym title="TermBase eXchange">TBX</acronym>: TODO
-
-</p>
-
-</div>
-<!-- SECTION "Abbreviations" [1908-] --></body>
+</p>
+
+</div>
+<!-- SECTION "Abbreviations" [2058-2144] -->
+<h2><a name="tbx_cheat_sheet" id="tbx_cheat_sheet">TBX cheat sheet</a></h2>
+<div class="level2">
+<ol>
+<li class="level1"><div class="li"> source word in English</div>
+</li>
+<li class="level1"><div class="li"> definition in English</div>
+</li>
+<li class="level1"><div class="li"> translation of source word to XX</div>
+</li>
+<li class="level1"><div class="li"> definition in XX</div>
+</li>
+<li class="level1"><div class="li"> comment</div>
+</li>
+<li class="level1"><div class="li"> syntactic group</div>
+</li>
+<li class="level1"><div class="li"> one or more tags</div>
+</li>
+<li class="level1"><div class="li"> a reference number</div>
+</li>
+</ol>
+<pre class="code xml"><span class="sc3"><span class="re1"><termEntry</span> <span class="re0">id</span>=<span class="st0">"4324 (8)"</span><span class="re2">></span></span>
+    <span class="sc3"><span class="re1"><note<span class="re2">></span></span></span>tag1, tag2, tag3 (7) -
+(Actually not clear what the best mapping to TBX is in this case.)<span class="sc3"><span class="re1"></note<span class="re2">></span></span></span>
+    <span class="sc3"><span class="re1"><langSet</span> <span class="re0">xml:lang</span>=<span class="st0">"en"</span><span class="re2">></span></span>
+        <span class="sc3"><span class="re1"><tig<span class="re2">></span></span></span>
+            <span class="sc3"><span class="re1"><term<span class="re2">></span></span></span>sound (1)<span class="sc3"><span class="re1"></term<span class="re2">></span></span></span>
+            <span class="sc3"><span class="re1"><termNote</span> <span class="re0">type</span>=<span class="st0">"partOfSpeech"</span><span class="re2">></span></span>noun (6)<span class="sc3"><span class="re1"></termNote<span class="re2">></span></span></span>
+        <span class="sc3"><span class="re1"></tig<span class="re2">></span></span></span>
+        <span class="sc3"><span class="re1"><descripGrp<span class="re2">></span></span></span>
+            <span class="sc3"><span class="re1"><descrip</span> <span class="re0">type</span>=<span class="st0">"definition"</span><span class="re2">></span></span>Something you can hear (2) -
+definition with an associated external source)<span class="sc3"><span class="re1"></descrip<span class="re2">></span></span></span>
+            <span class="sc3"><span class="re1"><xref</span> <span class="re0">type</span>=<span class="st0">"xSource"</span> <span class="re0">target</span>=<span class="st0">"http://www.something.org/?id=234"</span><span class="re2">></span></span>Glossmaster<span class="sc3"><span class="re1"></xref<span class="re2">></span></span></span>
+        <span class="sc3"><span class="re1"></descripGrp<span class="re2">></span></span></span>
+        <span class="sc3"><span class="re1"><note<span class="re2">></span></span></span>Any random note about the term. (5)
+(Actually there are ways of storing pretty specific stuff in specific spaces,
+but while it seems the comment could be a more verbose definition, examples,
+usage notes or anything else, we'll use this generic way.)
+        <span class="sc3"><span class="re1"></note<span class="re2">></span></span></span>
+    <span class="sc3"><span class="re1"></langSet<span class="re2">></span></span></span>
+    <span class="sc3"><span class="re1"><langSet</span> <span class="re0">xml:lang</span>=<span class="st0">"af"</span><span class="re2">></span></span>
+        <span class="sc3"><span class="re1"><tig<span class="re2">></span></span></span>
+            <span class="sc3"><span class="re1"><term<span class="re2">></span></span></span>klank (3)<span class="sc3"><span class="re1"></term<span class="re2">></span></span></span>
+        <span class="sc3"><span class="re1"></tig<span class="re2">></span></span></span>
+        <span class="sc3"><span class="re1"><descrip</span> <span class="re0">type</span>=<span class="st0">"definition"</span><span class="re2">></span></span>Iets wat jy kan hoor (4) -
+definition without an external source)<span class="sc3"><span class="re1"></descrip<span class="re2">></span></span></span>
+        <span class="sc3"><span class="re1"><note<span class="re2">></span></span></span>A note in the target language (5).<span class="sc3"><span class="re1"></note<span class="re2">></span></span></span>
+    <span class="sc3"><span class="re1"></langSet<span class="re2">></span></span></span>
+<span class="sc3"><span class="re1"></termEntry<span class="re2">></span></span></span></pre>
+<p>
+Note that the <xref> tags are optional (as are just about everything except termEntry, langSet and tig). They allow to link to an external source. An internal source can also be specified, or the definition can be specified without a source as shown for the term “klank”.
+
+</p>
+
+</div>
+<!-- SECTION "TBX cheat sheet" [2145-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-ts.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-ts.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-ts.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-ts.html Fri Jul 24 16:25:46 2009
@@ -22,36 +22,50 @@
 The Qt toolkit uses a .ts file format to store translations which are traditionally edited using Qt Linguist.
 </p>
 
+</div>
+<!-- SECTION "Qt .ts" [1-133] -->
+<h2><a name="references" id="references">References</a></h2>
+<div class="level2">
+
 <p>
+
 The format is <acronym title="Extensible Markup Language">XML</acronym> and seems to only have been documented properly in Qt 4.3
 
 </p>
 <ul>
-<li class="level1"><div class="li"> <a href="http://doc.trolltech.com/4.3/linguist-ts-file-format.html" class="urlextern" title="http://doc.trolltech.com/4.3/linguist-ts-file-format.html">DTD Specification</a>: Qt 4.3</div>
+<li class="level1"><div class="li"> <a href="http://doc.trolltech.com/4.5/linguist-ts-file-format.html" class="urlextern" title="http://doc.trolltech.com/4.5/linguist-ts-file-format.html">Current DTD Specification</a> for Qt 4.5, older versions; <a href="http://doc.trolltech.com/4.3/linguist-ts-file-format.html" class="urlextern" title="http://doc.trolltech.com/4.3/linguist-ts-file-format.html">Qt 4.3</a></div>
 </li>
 <li class="level1"><div class="li"> <a href="http://svn.ez.no/svn/ezcomponents/trunk/Translation/docs/linguist-format.txt" class="urlextern" title="http://svn.ez.no/svn/ezcomponents/trunk/Translation/docs/linguist-format.txt">http://svn.ez.no/svn/ezcomponents/trunk/Translation/docs/linguist-format.txt</a></div>
 </li>
 </ul>
 
 </div>
-<!-- SECTION "Qt .ts" [1-388] -->
+<!-- SECTION "References" [134-509] -->
 <h2><a name="complete" id="complete">Complete</a></h2>
 <div class="level2">
+
+<p>
+
+Note that <a href="toolkit-ts2po.html" class="wikilink1" title="toolkit-ts2po.html">ts2po</a> uses and older version and does not support all of these features.  <a href="virtaal-index.html" class="wikilink2" title="virtaal-index.html">Virtaal</a> and other users of the new ts class support the following:
+
+</p>
 <ul>
 <li class="level1"><div class="li"> Context</div>
 </li>
 <li class="level1"><div class="li"> Message: status (unfinished, finished), source, translation</div>
 </li>
+<li class="level1"><div class="li"> Plurals: numerusform</div>
+</li>
 </ul>
 
 </div>
-<!-- SECTION "Complete" [389-487] -->
+<!-- SECTION "Complete" [510-807] -->
 <h2><a name="todo" id="todo">TODO</a></h2>
 <div class="level2">
 
 <p>
 
-<p><div class="noteclassic">A new parser has been added to the toolkit in v1.2. This allows pocount and other users to work with v1.1 of the .ts format.  This corrects almost all of the issues listed below.  The converters po2ts and ts2po continue to use the older storage class and thus continue to experience some of these problems.
+<p><div class="noteclassic">A new parser has been added to the toolkit in v1.2. This allows <a href="virtaal-index.html" class="wikilink2" title="virtaal-index.html">Virtaal</a>, <a href="toolkit-pocount.html" class="wikilink1" title="toolkit-pocount.html">pocount</a> and other users to work with v1.1 of the .ts format.  This corrects almost all of the issues listed below.  The converters po2ts and ts2po continue to use the older storage class and thus continue to experience some of these problems.
 </div></p>
 
 </p>
@@ -62,10 +76,16 @@
 </li>
 <li class="level1"><div class="li"> translation: obsolete (currently handled with comments in conversion to <acronym title="Gettext Portable Object">PO</acronym>.  But should be able to convert Obsolete <acronym title="Gettext Portable Object">PO</acronym> back into obsolete TS.  This might mean moving this format properly onto the base class).</div>
 </li>
+<li class="level1"><div class="li"> lengthvariants</div>
+</li>
+<li class="level1"><div class="li"> *comment: various new comment fields</div>
+</li>
+<li class="level1"><div class="li"> old*: ability to store previous source and comments</div>
+</li>
 </ul>
 
 </div>
-<!-- SECTION "TODO" [488-1106] -->
+<!-- SECTION "TODO" [808-1573] -->
 <h2><a name="validate" id="validate">Validate</a></h2>
 <div class="level2">
 
@@ -80,5 +100,5 @@
 </ul>
 
 </div>
-<!-- SECTION "Validate" [1107-] --></body>
+<!-- SECTION "Validate" [1574-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-using_csv2po.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-using_csv2po.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-using_csv2po.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-using_csv2po.html Fri Jul 24 16:25:46 2009
@@ -19,7 +19,7 @@
 
 <p>
 
-<a href="toolkit-csv2po.html" class="wikilink1" title="toolkit-csv2po.html">csv2po</a> allows you to create <acronym title="Comma Seperated Value">CSV</acronym> files from <acronym title="Gettext Portable Object">PO</acronym> files.  This allows you to
+<a href="toolkit-csv2po.html" class="wikilink1" title="toolkit-csv2po.html">csv2po</a> allows you to create <acronym title="Comma Separated Value">CSV</acronym> files from <acronym title="Gettext Portable Object">PO</acronym> files.  This allows you to
 send translation work to translators who do not or cannot use <acronym title="Gettext Portable Object">PO</acronym> Editors but who
 can use a Spreadsheet.
 </p>
@@ -56,9 +56,9 @@
 
 <p>
 
-po2csv allows you to send <acronym title="Comma Seperated Value">CSV</acronym> files, which can be edited in any spreadsheet, to
+po2csv allows you to send <acronym title="Comma Separated Value">CSV</acronym> files, which can be edited in any spreadsheet, to
 a translator.  This document outlines the process to follow from the raw po
-files → <acronym title="Comma Seperated Value">CSV</acronym> files → back to <acronym title="Gettext Portable Object">PO</acronym>.  We also look at a case where you may have
+files → <acronym title="Comma Separated Value">CSV</acronym> files → back to <acronym title="Gettext Portable Object">PO</acronym>.  We also look at a case where you may have
 submitted a subset of the <acronym title="Gettext Portable Object">PO</acronym> files for translation and you need to integrate
 these.
 </p>
@@ -104,7 +104,7 @@
 </p>
 
 <p>
-Now continue as normal and convert to <acronym title="Comma Seperated Value">CSV</acronym> and perform word counts for each
+Now continue as normal and convert to <acronym title="Comma Separated Value">CSV</acronym> and perform word counts for each
 separate directory.
 </p>
 
@@ -116,7 +116,7 @@
 
 <p>
 
-This will create a set of <acronym title="Comma Seperated Value">CSV</acronym> files in <em>csv-out</em> which you can compress using zip
+This will create a set of <acronym title="Comma Separated Value">CSV</acronym> files in <em>csv-out</em> which you can compress using zip
 (we use zip because most people are Windows users)
 </p>
 
@@ -140,7 +140,7 @@
 </p>
 
 <p>
-Place the word count file in both the <acronym title="Gettext Portable Object">PO</acronym> and <acronym title="Comma Seperated Value">CSV</acronym> directory to avoid the problem
+Place the word count file in both the <acronym title="Gettext Portable Object">PO</acronym> and <acronym title="Comma Separated Value">CSV</acronym> directory to avoid the problem
 of finding it later.  Check the number to make sure you haven't inadvertently
 including something that you didn't want in.
 </p>
@@ -182,7 +182,7 @@
 
 <p>
 
-You can, and should, keep your files as <acronym title="Comma Seperated Value">CSV</acronym> files.  However, many translators are not the best wizzes at using their spreadsheet.  In this case
+You can, and should, keep your files as <acronym title="Comma Separated Value">CSV</acronym> files.  However, many translators are not the best wizzes at using their spreadsheet.  In this case
 many files will have been changed to XLS files.  To convert them by hand is tedious and error prone.  Rather make use of <a href="http://freshmeat.net/projects/xlhtml/" class="urlextern" title="http://freshmeat.net/projects/xlhtml/">xlHtml</a> which can do all the work for you.
 
 </p>
@@ -195,14 +195,14 @@
 
 <p>
 
-Extract the <acronym title="Comma Seperated Value">CSV</acronym> files here we assume they are in <em>csv-in</em>.
+Extract the <acronym title="Comma Separated Value">CSV</acronym> files here we assume they are in <em>csv-in</em>.
 
 </p>
 <pre class="code">csv2po --charset=windows-1250 -t <templates> <csv-in> <po-in></pre>
 
 <p>
 
-This will create new <acronym title="Gettext Portable Object">PO</acronym> files in <em>po-in</em> based on the <acronym title="Comma Seperated Value">CSV</acronym> files in the
+This will create new <acronym title="Gettext Portable Object">PO</acronym> files in <em>po-in</em> based on the <acronym title="Comma Separated Value">CSV</acronym> files in the
 <em>csv-in</em> and the template <acronym title="Gettext Portable Object">PO</acronym> files in <em>templates</em>.  You shouldn't run
 the csv2po command without templates as this allows you to preserve the original file layout.
 Only run it without -t if you are dealing with a partial part of the <acronym title="Gettext Portable Object">PO</acronym> that you will 
@@ -246,14 +246,14 @@
 <p>
 This is best performed against <acronym title="Concurrent Versions System">CVS</acronym> otherwise who knows what changed.
 </p>
-<pre class="code bash"><pre class="code bash">po-in-<span class="re2">dir=</span>your-incomming-po-files
+<pre class="code bash">po-in-<span class="re2">dir=</span>your-incomming-po-files
 po-<span class="re2">dir=</span>your-existing-po-files
  
-<span class="kw1">for</span> pofile <span class="kw1">in</span> `<span class="kw3">cd</span> <span class="re1">$po</span>-in-dir; find . -name <span class="st0">"*.po"</span>`
+<span class="kw1">for</span> pofile <span class="kw1">in</span> `<span class="kw3">cd</span> <span class="re1">$po</span>-in-<span class="kw2">dir</span>; <span class="kw2">find</span> . -name <span class="st0">"*.po"</span>`
 <span class="kw1">do</span>
-       egrep -v <span class="st0">"^#, fuzzy"</span> < <span class="re1">$po</span>-dir/<span class="re1">$pofile</span> > <span class="re1">$po</span>-dir/<span class="re0">$<span class="br0">{</span>pofile<span class="br0">}</span></span>.unfuzzy && \
-       mv <span class="re1">$po</span>-dir/<span class="re0">$<span class="br0">{</span>pofile<span class="br0">}</span></span>.unfuzzy <span class="re1">$po</span>-dir/<span class="re1">$pofile</span>
-<span class="kw1">done</span></pre></pre>
+       <span class="kw2">egrep</span> -v <span class="st0">"^#, fuzzy"</span> <span class="sy0"><</span> <span class="re1">$po</span>-<span class="kw2">dir</span><span class="sy0">/</span><span class="re1">$pofile</span> <span class="sy0">></span> <span class="re1">$po</span>-<span class="kw2">dir</span><span class="sy0">/</span><span class="re0">$<span class="br0">{</span>pofile<span class="br0">}</span><span class="sy0">|</span>>.unfuzzy <span class="sy0">&&</span> \
+       <span class="kw2">mv</span> <span class="re1">$po</span>-<span class="kw2">dir</span><span class="sy0">/</span><span class="re0">$<span class="br0">{</span>pofile<span class="br0">}</span><span class="sy0">|</span>>.unfuzzy <span class="re1">$po</span>-<span class="kw2">dir</span><span class="sy0">/</span><span class="re1">$pofile</span>
+<span class="kw1">done</span></pre>
 </div>
 <!-- SECTION "Removing fuzzies" [5216-5787] -->
 <h3><a name="merging_po_files_into_the_main_po_files" id="merging_po_files_into_the_main_po_files">Merging PO files into the main PO files</a></h3>
@@ -261,7 +261,7 @@
 
 <p>
 
-This step would not be necessary if the <acronym title="Comma Seperated Value">CSV</acronym> contained the complete <acronym title="Gettext Portable Object">PO</acronym> file.  It
+This step would not be necessary if the <acronym title="Comma Separated Value">CSV</acronym> contained the complete <acronym title="Gettext Portable Object">PO</acronym> file.  It
 is only needed when the translator has been editing a subset of the whole <acronym title="Gettext Portable Object">PO</acronym>
 file.
 

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-using_pofilter.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-using_pofilter.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-using_pofilter.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-using_pofilter.html Fri Jul 24 16:25:46 2009
@@ -19,7 +19,7 @@
 
 <p>
 
-<a href="toolkit-pofilter.html" class="wikilink1" title="toolkit-pofilter.html">pofilter</a> allows you to check your <acronym title="Gettext Portable Object">PO</acronym> or <acronym title="XML Localization Interchange File Format">XLIFF</acronym> files for certain common errors.  This quickstart guide takes 
+<a href="toolkit-pofilter.html" class="wikilink1" title="toolkit-pofilter.html">pofilter</a> allows you to check your <acronym title="Gettext Portable Object">PO</acronym> or <acronym title="XML Localization Interchange File Format">XLIFF</acronym> files for certain common errors.  This quick-start guide takes 
 you through the process of using this tool, making corrections and merging your correction back into your translations.
 </p>
 
@@ -28,28 +28,32 @@
 </p>
 
 </div>
-<!-- SECTION "Checking your files with PO filter" [1-379] -->
+<!-- SECTION "Checking your files with PO filter" [1-380] -->
 <h2><a name="quickstart" id="quickstart">Quickstart</a></h2>
 <div class="level2">
+
+<p>
+<em>Use any preferred text editor wherever <code>vim</code> is used.</em>
+</p>
 <ol>
-<li class="level1"><div class="li"> pofilter -l (select a filter)</div>
-</li>
-<li class="level1"><div class="li"> pofilter -i existing_files/ -o errors/ [-t specific tests] [--excludefilter don't perform specific tests]</div>
-</li>
-<li class="level1"><div class="li"> vim errors/*.po (delete items you don't want changed, set fuzzy if needed, delete if not needed)</div>
-</li>
-<li class="level1"><div class="li"> pomerge -i errors/ -o existing_files/ -t existing_files/ (will overwrite existing files)</div>
-</li>
-<li class="level1"><div class="li"> cvs diff -u existing_files/ > x.diff</div>
-</li>
-<li class="level1"><div class="li"> vim x.diff (check to see that the updates are what you want)</div>
-</li>
-<li class="level1"><div class="li"> cvs ci existing_files/</div>
+<li class="level1"><div class="li"> Select filter(s): <code>pofilter -l</code></div>
+</li>
+<li class="level1"><div class="li"> Run filter(s): <code>pofilter -i existing_files/ -o errors/ [-t specific tests] [--excludefilter don't perform specific tests]</code></div>
+</li>
+<li class="level1"><div class="li"> Delete items you don't want changed, set fuzzy if needed, delete if not needed: <code>vim errors/*.po</code></div>
+</li>
+<li class="level1"><div class="li"> Merge changes back: <code>pomerge -i errors/ -o existing_files/ -t existing_files/</code> (will overwrite existing files)</div>
+</li>
+<li class="level1"><div class="li"> Create a patch for the changes: <code>cvs diff -u existing_files/ > x.diff</code></div>
+</li>
+<li class="level1"><div class="li"> Check to see that the updates are what you want: <code>vim x.diff</code></div>
+</li>
+<li class="level1"><div class="li"> Commit changes: <code>cvs ci existing_files/</code></div>
 </li>
 </ol>
 
 </div>
-<!-- SECTION "Quickstart" [380-875] -->
+<!-- SECTION "Quickstart" [381-1044] -->
 <h2><a name="detailed_description" id="detailed_description">Detailed Description</a></h2>
 <div class="level2">
 
@@ -59,7 +63,7 @@
 </p>
 
 </div>
-<!-- SECTION "Detailed Description" [876-1280] -->
+<!-- SECTION "Detailed Description" [1045-1449] -->
 <h3><a name="extracting_errors" id="extracting_errors">Extracting Errors</a></h3>
 <div class="level3">
 
@@ -112,7 +116,7 @@
 </p>
 
 </div>
-<!-- SECTION "Extracting Errors" [1281-3516] -->
+<!-- SECTION "Extracting Errors" [1450-3685] -->
 <h3><a name="edit_the_files" id="edit_the_files">Edit the files</a></h3>
 <div class="level3">
 
@@ -160,7 +164,7 @@
 </p>
 
 </div>
-<!-- SECTION "Edit the files" [3517-5202] -->
+<!-- SECTION "Edit the files" [3686-5371] -->
 <h3><a name="merging_your_corrections_back_into_the_originals" id="merging_your_corrections_back_into_the_originals">Merging your corrections back into the originals</a></h3>
 <div class="level3">
 
@@ -180,7 +184,7 @@
 </p>
 
 </div>
-<!-- SECTION "Merging your corrections back into the originals" [5203-5666] -->
+<!-- SECTION "Merging your corrections back into the originals" [5372-5835] -->
 <h3><a name="checking_the_corrections" id="checking_the_corrections">Checking the corrections</a></h3>
 <div class="level3">
 
@@ -233,5 +237,5 @@
 </p>
 
 </div>
-<!-- SECTION "Checking the corrections" [5667-] --></body>
+<!-- SECTION "Checking the corrections" [5836-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-wordfast.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-wordfast.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-wordfast.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-wordfast.html Fri Jul 24 16:25:46 2009
@@ -19,10 +19,6 @@
 
 <p>
 
-(Only in v1.1)
-</p>
-
-<p>
 The Wordfast format, as used by the <a href="http://en.wikipedia.org/wiki/Wordfast" class="interwiki iw_wp" title="http://en.wikipedia.org/wiki/Wordfast">Wordfast</a> translation tool, is a simple tab delimited file.
 </p>
 
@@ -31,7 +27,7 @@
 </p>
 
 </div>
-<!-- SECTION "Wordfast Translation Memory" [1-221] -->
+<!-- SECTION "Wordfast Translation Memory" [1-205] -->
 <h2><a name="conformance" id="conformance">Conformance</a></h2>
 <div class="level2">
 <ul>
@@ -48,5 +44,5 @@
 </ul>
 
 </div>
-<!-- SECTION "Conformance" [222-] --></body>
+<!-- SECTION "Conformance" [206-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-xliff.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-xliff.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-xliff.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-xliff.html Fri Jul 24 16:25:46 2009
@@ -106,11 +106,7 @@
 
 <p>
 
-Here is a small report on <acronym title="XML Localization Interchange File Format">XLIFF</acronym> and <acronym title="Microsoft">MS</acronym> Windows tools:
-</p>
-
-<p>
-<a href="http://translate.sourceforge.net/wiki/guide/tools/xliff_support_by_ms_windows_programs" class="urlextern" title="http://translate.sourceforge.net/wiki/guide/tools/xliff_support_by_ms_windows_programs">http://translate.sourceforge.net/wiki/guide/tools/xliff_support_by_ms_windows_programs</a>
+Here is a small report on the <a href="guide-tools-xliff_support_by_ms_windows_programs.html" class="wikilink1" title="guide-tools-xliff_support_by_ms_windows_programs.html">XLIFF support by MS Windows programs</a>.
 </p>
 
 </div>

Modified: translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-xliff2po.html
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-xliff2po.html?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-xliff2po.html (original)
+++ translate-toolkit/branches/upstream/current/translate/doc/user/toolkit-xliff2po.html Fri Jul 24 16:25:46 2009
@@ -20,13 +20,13 @@
 <p>
 
 Converts <acronym title="XML Localization Interchange File Format">XLIFF</acronym> localization files to Gettext <acronym title="Gettext Portable Object">PO</acronym> files.  <acronym title="XML Localization Interchange File Format">XLIFF</acronym> is the <acronym title="Extensible Markup Language">XML</acronym> Localization Interchange File Format 
-developed by <a href="http://lisa.org/" class="urlextern" title="http://lisa.org/">LISA</a> (The Localization Industry Standards Authority) to allow translation
+developed by <a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xliff" class="urlextern" title="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xliff">OASIS</a> (Organization for the Advancement of Structured Information Standards) to allow translation
 work to be standardised no matter what the source format and to allow the work to be freely moved from tool to
 tool.
 </p>
 
 </div>
-<!-- SECTION "xliff2po and po2xliff" [1-374] -->
+<!-- SECTION "xliff2po and po2xliff" [1-446] -->
 <h2><a name="usage" id="usage">Usage</a></h2>
 <div class="level2">
 <pre class="code">po2xliff [options] <po> <xliff>
@@ -125,7 +125,7 @@
 </table>
 
 </div>
-<!-- SECTION "Usage" [375-2276] -->
+<!-- SECTION "Usage" [447-2348] -->
 <h2><a name="examples" id="examples">Examples</a></h2>
 <div class="level2">
 <pre class="code">xliff2po -P xliff pot</pre>
@@ -143,7 +143,7 @@
 </p>
 
 </div>
-<!-- SECTION "Examples" [2277-2530] -->
+<!-- SECTION "Examples" [2349-2602] -->
 <h2><a name="bugs" id="bugs">Bugs</a></h2>
 <div class="level2">
 
@@ -158,5 +158,5 @@
 </p>
 
 </div>
-<!-- SECTION "Bugs" [2531-] --></body>
+<!-- SECTION "Bugs" [2603-] --></body>
 </html>

Modified: translate-toolkit/branches/upstream/current/translate/filters/autocorrect.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/filters/autocorrect.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/filters/autocorrect.py (original)
+++ translate-toolkit/branches/upstream/current/translate/filters/autocorrect.py Fri Jul 24 16:25:46 2009
@@ -1,47 +1,54 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 # 
-# Copyright 2005, 2006 Zuza Software Foundation
+# Copyright 2005, 2006, 2009 Zuza Software Foundation
 # 
-# This file is part of translate.
+# This file is part of the Translate Toolkit.
 #
-# translate is free software; you can redistribute it and/or modify
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
-"""a set of autocorrect functions that make resolving common problems more automatic..."""
+"""A set of autocorrect functions that fix common punctuation and space problems automatically"""
 
 from translate.filters import decoration
 
-def correct(msgid, msgstr):
-    """runs a set of easy automatic corrections"""
-    assert isinstance(msgid, unicode)
-    assert isinstance(msgstr, unicode)
-    if msgstr == "":
-        return msgstr
-    if "..." in msgid and u"…" in msgstr:
-        return msgstr.replace(u"…", "...")
-    if decoration.spacestart(msgid) != decoration.spacestart(msgstr) or decoration.spaceend(msgid) != decoration.spaceend(msgstr):
-        return decoration.spacestart(msgid) + msgstr.strip() + decoration.spaceend(msgid)
+def correct(source, target):
+    """Runs a set of easy and automatic corrections
+
+    Current corrections include:
+      - Ellipses - align target to use source form of ellipses (either three dots or the Unicode ellipses characters)
+      - Missing whitespace and start or end of the target
+      - Missing punction (.:?) at the end of the target
+    """
+    assert isinstance(source, unicode)
+    assert isinstance(target, unicode)
+    if target == "":
+        return target
+    if "..." in source and u"…" in target:
+        return target.replace(u"…", "...")
+    if u"…" in source and "..." in target:
+        return target.replace("...", u"…")
+    if decoration.spacestart(source) != decoration.spacestart(target) or decoration.spaceend(source) != decoration.spaceend(target):
+        return decoration.spacestart(source) + target.strip() + decoration.spaceend(source)
     punctuation = (".", ":", ". ", ": ", "?")
-    puncendid = decoration.puncend(msgid, punctuation)
-    puncendstr = decoration.puncend(msgstr, punctuation)
+    puncendid = decoration.puncend(source, punctuation)
+    puncendstr = decoration.puncend(target, punctuation)
     if puncendid != puncendstr:
         if not puncendstr:
-            return msgstr + puncendid
-    if msgid[:1].isalpha() and msgstr[:1].isalpha():
-        if msgid[:1].isupper() and msgstr[:1].islower():
-            return msgstr[:1].upper() + msgstr[1:]
-        elif msgid[:1].islower() and msgstr[:1].isupper():
-            return msgstr[:1].lower() + msgstr[1:]
+            return target + puncendid
+    if source[:1].isalpha() and target[:1].isalpha():
+        if source[:1].isupper() and target[:1].islower():
+            return target[:1].upper() + target[1:]
+        elif source[:1].islower() and target[:1].isupper():
+            return target[:1].lower() + target[1:]
     return None

Modified: translate-toolkit/branches/upstream/current/translate/filters/checks.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/filters/checks.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/filters/checks.py (original)
+++ translate-toolkit/branches/upstream/current/translate/filters/checks.py Fri Jul 24 16:25:46 2009
@@ -450,11 +450,14 @@
 
     def unchanged(self, str1, str2):
         """checks whether a translation is basically identical to the original string"""
-        str1 = self.removevariables(self.filteraccelerators(str1)).strip()
-        str2 = self.removevariables(self.filteraccelerators(str2)).strip()
+        str1 = self.filteraccelerators(self.removevariables(str1)).strip()
+        str2 = self.filteraccelerators(self.removevariables(str2)).strip()
         if len(str1) < 2:
             return True
-        if str1.isupper() and str1 == str2:
+        # If the whole string is upperase, or nothing in the string can go
+        # towards uppercase, let's assume there is nothing translatable
+        # TODO: reconsider
+        if (str1.isupper() or str1.upper() == str1) and str1 == str2:
             return True
         if self.config.notranslatewords:
             words1 = str1.split()
@@ -463,7 +466,9 @@
             #   if len(words1) == 1 and words1[0] in self.config.notranslatewords:
             #why do we only test for one notranslate word?
                 return True
-        if str1.isalpha() and str1.lower() == str2.lower():
+        # we could also check for things like str1.isnumeric(), but the test
+        # above (str1.upper() == str1) makes this unnecessary
+        if str1.lower() == str2.lower():
             raise FilterFailure(u"please translate")
         return True
 
@@ -508,7 +513,6 @@
         else:
             return True
 
-
     def singlequoting(self, str1, str2):
         """checks whether singlequoting is consistent between the two strings"""
         str1 = self.filterwordswithpunctuation(self.filteraccelerators(self.filtervariables(str1)))
@@ -522,7 +526,7 @@
         str1 = self.config.lang.punctranslate(str1)
         str2 = self.filteraccelerators(self.filtervariables(str2))
         str2 = self.filterxml(str2)
-        return helpers.countsmatch(str1, str2, (u'"', u'""', u'\\"', u"«", u"»"))
+        return helpers.countsmatch(str1, str2, (u'"', u'""', u'\\"', u"«", u"»", u"“", u"”"))
 
     def doublespacing(self, str1, str2):
         """checks for bad double-spaces by comparing to original"""
@@ -699,14 +703,11 @@
 
     def startwhitespace(self, str1, str2):
         """checks whether whitespace at the beginning of the strings matches"""
-        str1 = self.filteraccelerators(self.filtervariables(str1))
-        str2 = self.filteraccelerators(self.filtervariables(str2))
         return helpers.funcmatch(str1, str2, decoration.spacestart)
 
     def endwhitespace(self, str1, str2):
         """checks whether whitespace at the end of the strings matches"""
-        str1 = self.filteraccelerators(self.filtervariables(str1))
-        str2 = self.filteraccelerators(self.filtervariables(str2))
+        str1 = self.config.lang.punctranslate(str1)
         return helpers.funcmatch(str1, str2, decoration.spaceend)
 
     def startpunc(self, str1, str2):
@@ -757,6 +758,8 @@
 
     def sentencecount(self, str1, str2):
         """checks that the number of sentences in both strings match"""
+        str1 = self.filteraccelerators(str1)
+        str2 = self.filteraccelerators(str2)
         sentences1 = len(self.config.sourcelang.sentences(str1))
         sentences2 = len(self.config.lang.sentences(str2))
         if not sentences1 == sentences2:
@@ -974,7 +977,7 @@
             # hack to ignore hyphenisation rules
             if word in suggestions:
                 continue
-            messages.append(u"check spelling of %s (could be %s)" % (word, u" / ".join(suggestions)))
+            messages.append(u"check spelling of %s (could be %s)" % (word, u" / ".join(suggestions[:5])))
         if messages:
             raise FilterFailure(messages)
         return True
@@ -1015,7 +1018,14 @@
                                     "emails", "simpleplurals", "urls", "printf",
                                     "tabs", "newlines", "functions", "options"),
                    "purepunc":      ("startcaps", "options"),
-                   "startcaps":     ("simplecaps",),
+                   # This is causing some problems since Python 2.6, as
+                   # startcaps is now seen as an important one to always execute
+                   # and could now be done before it is blocked by a failing
+                   # "untranslated" or "blank" test. This is probably happening
+                   # due to slightly different implementation of the internal
+                   # dict handling since Python 2.6. We should never have relied
+                   # on this ordering anyway.
+                   #"startcaps":     ("simplecaps",),
                    "endwhitespace": ("endpunc",),
                    "startwhitespace":("startpunc",),
                    "unchanged":     ("doublewords",), 
@@ -1059,6 +1069,13 @@
             kwargs["checkerconfig"] = checkerconfig
         checkerconfig.update(mozillaconfig)
         StandardChecker.__init__(self, **kwargs)
+
+    def credits(self, str1, str2):
+        """checks for messages containing translation credits instead of normal translations."""
+        for location in self.locations:
+            if location in ['MOZ_LANGPACK_CONTRIBUTORS', 'credit.translation']:
+                return False
+        return True
 
 drupalconfig = CheckerConfig(
     varmatches = [("%", None), ("@", None)],

Modified: translate-toolkit/branches/upstream/current/translate/filters/decoration.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/filters/decoration.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/filters/decoration.py (original)
+++ translate-toolkit/branches/upstream/current/translate/filters/decoration.py Fri Jul 24 16:25:46 2009
@@ -88,6 +88,8 @@
     else:
         # Old code path - ensures that we don't get a large number of regressions
         accelerator = accelerator.replace("_","")
+        if accelerator in u"-?":
+            return True
         if not accelerator.isalnum():
             return False
 

Modified: translate-toolkit/branches/upstream/current/translate/filters/pofilter.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/filters/pofilter.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/filters/pofilter.py (original)
+++ translate-toolkit/branches/upstream/current/translate/filters/pofilter.py Fri Jul 24 16:25:46 2009
@@ -79,8 +79,8 @@
         Return value:
             - A new translation store object with the results of the filter included."""
         newtransfile = type(transfile)()
-        newtransfile.setsourcelanguage(transfile.sourcelanguage)
-        newtransfile.settargetlanguage(transfile.targetlanguage)
+        if self.options.includeheader and newtransfile.units > 0:
+            newtransfile.addunit(transfile.header())
         for unit in transfile.units:
             filterresult = self.filterunit(unit)
             if filterresult:
@@ -91,9 +91,6 @@
                         if isinstance(filtermessage, checks.SeriousFilterFailure):
                             unit.markfuzzy()
                 newtransfile.addunit(unit)
-        if self.options.includeheader and newtransfile.units > 0:
-            newtransfile.units.insert(0, newtransfile.makeheader())
-            newtransfile.changeencoding("UTF-8")
         return newtransfile
 
 class FilterOptionParser(optrecurse.RecursiveOptionParser):

Modified: translate-toolkit/branches/upstream/current/translate/filters/spelling.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/filters/spelling.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/filters/spelling.py (original)
+++ translate-toolkit/branches/upstream/current/translate/filters/spelling.py Fri Jul 24 16:25:46 2009
@@ -25,17 +25,19 @@
 
 available = False
 
-# Let us see what is available in our preferred order
 try:
     # Enchant
-    from enchant import checker, DictNotFoundError
+    from enchant import checker, DictNotFoundError, Error as EnchantError
     available = True
     checkers = {}
     def check(text, lang):
         if not lang in checkers:
             try:
                 checkers[lang] = checker.SpellChecker(lang)
-            except DictNotFoundError, e:
+                # some versions only report an error when checking something
+                checkers[lang].check('')
+            except EnchantError, e:
+                # sometimes this is raised instead of DictNotFoundError
                 print >> sys.stderr, str(e)
                 checkers[lang] = None
 
@@ -47,14 +49,6 @@
             yield err.word, err.wordpos, err.suggest()
 
 except ImportError:
-    try:
-        # jToolkit might be installed and might give access to aspell, for 
-        # example
-        from jToolkit import spellcheck
-        available = True
-        check = spellcheck.check
-    except ImportError:
+    def check(text, lang):
+        return []
 
-        def check(text, lang):
-            return []
-

Modified: translate-toolkit/branches/upstream/current/translate/filters/test_checks.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/filters/test_checks.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/filters/test_checks.py (original)
+++ translate-toolkit/branches/upstream/current/translate/filters/test_checks.py Fri Jul 24 16:25:46 2009
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from translate.filters import checks
 from translate.lang import data
-from translate.storage import po 
+from translate.storage import po
 
 def strprep(str1, str2, message=None):
     return data.normalized_unicode(str1), data.normalized_unicode(str2), data.normalized_unicode(message)
@@ -81,37 +81,38 @@
     assert fails(stdchecker.validchars, "Some unexpected characters", "©", "invalid chars: '©' (\\u00a9)")
     stdchecker = checks.StandardChecker()
     assert fails_serious(stdchecker.escapes, r"A tab", r"'n á¹°ab\t", r"""escapes in original () don't match escapes in translation ('á¹°ab\t')""")
-    
+
 def test_accelerators():
     """tests accelerators"""
     stdchecker = checks.StandardChecker(checks.CheckerConfig(accelmarkers="&"))
-    assert passes(stdchecker.accelerators, "&File", "&Fayile") 
-    assert fails(stdchecker.accelerators, "&File", "Fayile") 
-    assert fails(stdchecker.accelerators, "File", "&Fayile") 
-    assert passes(stdchecker.accelerators, "Mail && News", "Pos en Nuus") 
-    assert fails(stdchecker.accelerators, "Mail & News", "Pos en Nuus") 
+    assert passes(stdchecker.accelerators, "&File", "&Fayile")
+    assert fails(stdchecker.accelerators, "&File", "Fayile")
+    assert fails(stdchecker.accelerators, "File", "&Fayile")
+    assert passes(stdchecker.accelerators, "Mail && News", "Pos en Nuus")
+    assert fails(stdchecker.accelerators, "Mail & News", "Pos en Nuus")
     assert passes(stdchecker.accelerators, "&Allow", u'&\ufeb2\ufee3\ufe8e\ufea3')
-    assert fails(stdchecker.accelerators, "Open &File", "Vula& Ifayile") 
+    assert fails(stdchecker.accelerators, "Open &File", "Vula& Ifayile")
     kdechecker = checks.KdeChecker()
-    assert passes(kdechecker.accelerators, "&File", "&Fayile") 
-    assert fails(kdechecker.accelerators, "&File", "Fayile") 
-    assert fails(kdechecker.accelerators, "File", "&Fayile") 
+    assert passes(kdechecker.accelerators, "&File", "&Fayile")
+    assert fails(kdechecker.accelerators, "&File", "Fayile")
+    assert fails(kdechecker.accelerators, "File", "&Fayile")
     gnomechecker = checks.GnomeChecker()
-    assert passes(gnomechecker.accelerators, "_File", "_Fayile") 
-    assert fails(gnomechecker.accelerators, "_File", "Fayile") 
-    assert fails(gnomechecker.accelerators, "File", "_Fayile") 
-    assert fails(gnomechecker.accelerators, "_File", "_Fayil_e") 
+    assert passes(gnomechecker.accelerators, "_File", "_Fayile")
+    assert fails(gnomechecker.accelerators, "_File", "Fayile")
+    assert fails(gnomechecker.accelerators, "File", "_Fayile")
+    assert fails(gnomechecker.accelerators, "_File", "_Fayil_e")
     mozillachecker = checks.MozillaChecker()
-    assert passes(mozillachecker.accelerators, "&File", "&Fayile") 
-    assert fails_serious(mozillachecker.accelerators, "&File", "Fayile") 
-    assert fails_serious(mozillachecker.accelerators, "File", "&Fayile") 
-    assert passes(mozillachecker.accelerators, "Mail & News", "Pos en Nuus") 
-    assert fails_serious(mozillachecker.accelerators, "Mail & News", "Pos en &Nuus") 
-    assert fails_serious(mozillachecker.accelerators, "&File", "Fayile") 
-    ooochecker = checks.OpenOfficeChecker()
-    assert passes(ooochecker.accelerators, "~File", "~Fayile") 
-    assert fails(ooochecker.accelerators, "~File", "Fayile") 
-    assert fails(ooochecker.accelerators, "File", "~Fayile") 
+    assert passes(mozillachecker.accelerators, "&File", "&Fayile")
+    assert passes(mozillachecker.accelerators, "Warn me if this will disable any of my add&-ons", "&Waarsku my as dit enige van my byvoegings sal deaktiveer")
+    assert fails_serious(mozillachecker.accelerators, "&File", "Fayile")
+    assert fails_serious(mozillachecker.accelerators, "File", "&Fayile")
+    assert passes(mozillachecker.accelerators, "Mail & News", "Pos en Nuus")
+    assert fails_serious(mozillachecker.accelerators, "Mail & News", "Pos en &Nuus")
+    assert fails_serious(mozillachecker.accelerators, "&File", "Fayile")
+    ooochecker = checks.OpenOfficeChecker()
+    assert passes(ooochecker.accelerators, "~File", "~Fayile")
+    assert fails(ooochecker.accelerators, "~File", "Fayile")
+    assert fails(ooochecker.accelerators, "File", "~Fayile")
 
     # We don't want an accelerator for letters with a diacritic
     assert fails(ooochecker.accelerators, "F~ile", "L~êer")
@@ -130,7 +131,6 @@
     ooochecker = checks.OpenOfficeChecker()
     assert fails(ooochecker.acceleratedvariables, "%PRODUCTNAME% ~Options", "~%PRODUCTNAME% Ikhetho")
     assert passes(ooochecker.acceleratedvariables, "%PRODUCTNAME% ~Options", "%PRODUCTNAME% ~Ikhetho")
-    
 
 def test_acronyms():
     """tests acronyms"""
@@ -186,10 +186,10 @@
     assert fails(frchecker.doublequoting, "Do \"this\"", "Do \"this\"")
     assert passes(frchecker.doublequoting, "Do \"this\"", "Do « this »")
     assert fails(frchecker.doublequoting, "Do \"this\"", "Do « this » « this »")
-    
+
     vichecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage="vi"))
     assert passes(vichecker.doublequoting, 'Save "File"', u"Lưu « Tập tin »")
-    
+
 def test_doublespacing():
     """tests double spacing"""
     stdchecker = checks.StandardChecker()
@@ -234,11 +234,18 @@
     stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage='vi'))
     assert passes(stdchecker.endpunc, "Do you want to delete the XX dialog?", u"Bạn có muốn xoá hộp thoại XX không?")
 
+    stdchecker = checks.StandardChecker(checks.CheckerConfig(targetlanguage='fr'))
+    assert passes(stdchecker.endpunc, "Header:", u"En-tête :")
+
 def test_endwhitespace():
     """tests endwhitespace"""
     stdchecker = checks.StandardChecker()
     assert passes(stdchecker.endwhitespace, "A setence. ", "I'm correct. ")
     assert fails(stdchecker.endwhitespace, "A setence. ", "'I'm incorrect.")
+
+    zh_checker = checks.StandardChecker(checks.CheckerConfig(targetlanguage='zh'))
+    # This should pass since the space is not needed in Chinese
+    assert passes(zh_checker.endwhitespace, "Init. Limit: ", "起始时间限制:")
 
 def test_escapes():
     """tests escapes"""
@@ -293,7 +300,7 @@
     stdchecker = checks.StandardChecker()
     assert passes(stdchecker.filepaths, "%s to the file /etc/hosts on your system.", "%s na die leer /etc/hosts op jou systeem.")
     assert fails(stdchecker.filepaths, "%s to the file /etc/hosts on your system.", "%s na die leer /etc/gasheer op jou systeem.")
-    
+
 def test_kdecomments():
     """tests kdecomments"""
     stdchecker = checks.StandardChecker()
@@ -610,21 +617,27 @@
 def test_unchanged():
     """tests unchanged entries"""
     stdchecker = checks.StandardChecker(checks.CheckerConfig(accelmarkers="&"))
-    assert fails(stdchecker.unchanged, "Unchanged", "Unchanged") 
-    assert fails(stdchecker.unchanged, "&Unchanged", "Un&changed") 
-    assert passes(stdchecker.unchanged, "Unchanged", "Changed") 
-    assert passes(stdchecker.unchanged, "1234", "1234") 
+    assert fails(stdchecker.unchanged, "Unchanged", "Unchanged")
+    assert fails(stdchecker.unchanged, "&Unchanged", "Un&changed")
+    assert passes(stdchecker.unchanged, "Unchanged", "Changed")
+    assert passes(stdchecker.unchanged, "1234", "1234")
     assert passes(stdchecker.unchanged, "2×2", "2×2") # bug 178, description item 14
-    assert passes(stdchecker.unchanged, "I", "I") 
+    assert passes(stdchecker.unchanged, "I", "I")
     assert passes(stdchecker.unchanged, "   ", "   ")  # bug 178, description item 5
     assert passes(stdchecker.unchanged, "???", "???")  # bug 178, description item 15
     assert passes(stdchecker.unchanged, "&ACRONYM", "&ACRONYM") # bug 178, description item 7
     assert passes(stdchecker.unchanged, "F1", "F1") # bug 178, description item 20
+    assert fails(stdchecker.unchanged, "Two words", "Two words")
+    #TODO: this still fails
+#    assert passes(stdchecker.unchanged, "NOMINAL", "NOMÄ°NAL")
+    gnomechecker = checks.GnomeChecker()
+    assert fails(gnomechecker.unchanged, "Entity references, such as & and ©", "Entity references, such as & and ©")
     # Variable only and variable plus punctuation messages should be ignored
     mozillachecker = checks.MozillaChecker()
-    assert passes(mozillachecker.unchanged, "$ProgramName$", "$ProgramName$") 
+    assert passes(mozillachecker.unchanged, "$ProgramName$", "$ProgramName$")
     assert passes(mozillachecker.unchanged, "$file$ : $dir$", "$file$ : $dir$") # bug 178, description item 13
-    assert fails(mozillachecker.unchanged, "$file$ in $dir$", "$file$ in $dir$") 
+    assert fails(mozillachecker.unchanged, "$file$ in $dir$", "$file$ in $dir$")
+    assert passes(mozillachecker.unchanged, "&brandShortName;", "&brandShortName;")
     # Don't translate words should be ignored
     stdchecker = checks.StandardChecker(checks.CheckerConfig(notranslatewords=["Mozilla"]))
     assert passes(stdchecker.unchanged, "Mozilla", "Mozilla") # bug 178, description item 10
@@ -871,20 +884,27 @@
 def test_credits():
     """tests credits"""
     stdchecker = checks.StandardChecker()
-    assert passes(stdchecker.credits, "File", "iFayile") 
-    assert passes(stdchecker.credits, "&File", "&Fayile") 
-    assert passes(stdchecker.credits, "translator-credits", "Ekke, ekke!") 
-    assert passes(stdchecker.credits, "Your names", "Ekke, ekke!") 
-    assert passes(stdchecker.credits, "ROLES_OF_TRANSLATORS", "Ekke, ekke!") 
+    assert passes(stdchecker.credits, "File", "iFayile")
+    assert passes(stdchecker.credits, "&File", "&Fayile")
+    assert passes(stdchecker.credits, "translator-credits", "Ekke, ekke!")
+    assert passes(stdchecker.credits, "Your names", "Ekke, ekke!")
+    assert passes(stdchecker.credits, "ROLES_OF_TRANSLATORS", "Ekke, ekke!")
     kdechecker = checks.KdeChecker()
-    assert passes(kdechecker.credits, "File", "iFayile") 
-    assert passes(kdechecker.credits, "&File", "&Fayile") 
-    assert passes(kdechecker.credits, "translator-credits", "Ekke, ekke!") 
-    assert fails(kdechecker.credits, "Your names", "Ekke, ekke!") 
-    assert fails(kdechecker.credits, "ROLES_OF_TRANSLATORS", "Ekke, ekke!") 
+    assert passes(kdechecker.credits, "File", "iFayile")
+    assert passes(kdechecker.credits, "&File", "&Fayile")
+    assert passes(kdechecker.credits, "translator-credits", "Ekke, ekke!")
+    assert fails(kdechecker.credits, "Your names", "Ekke, ekke!")
+    assert fails(kdechecker.credits, "ROLES_OF_TRANSLATORS", "Ekke, ekke!")
     gnomechecker = checks.GnomeChecker()
-    assert passes(gnomechecker.credits, "File", "iFayile") 
-    assert passes(gnomechecker.credits, "&File", "&Fayile") 
-    assert fails(gnomechecker.credits, "translator-credits", "Ekke, ekke!") 
-    assert passes(gnomechecker.credits, "Your names", "Ekke, ekke!") 
-    assert passes(gnomechecker.credits, "ROLES_OF_TRANSLATORS", "Ekke, ekke!") 
+    assert passes(gnomechecker.credits, "File", "iFayile")
+    assert passes(gnomechecker.credits, "&File", "&Fayile")
+    assert fails(gnomechecker.credits, "translator-credits", "Ekke, ekke!")
+    assert passes(gnomechecker.credits, "Your names", "Ekke, ekke!")
+    assert passes(gnomechecker.credits, "ROLES_OF_TRANSLATORS", "Ekke, ekke!")
+
+def test_gconf():
+    """test GNOME gconf errors"""
+    gnomechecker = checks.GnomeChecker()
+    assert passes(gnomechecker.gconf, 'Blah "gconf_setting"', 'Bleh "gconf_setting"')
+    assert fails(gnomechecker.gconf, 'Blah "gconf_setting"', 'Bleh "gconf_steling"')
+

Modified: translate-toolkit/branches/upstream/current/translate/lang/af.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/af.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/af.py (original)
+++ translate-toolkit/branches/upstream/current/translate/lang/af.py Fri Jul 24 16:25:46 2009
@@ -38,7 +38,7 @@
                             .*?         #anything, but match non-greedy
                             [%s]        #the puntuation for sentence ending
                             \s+         #the spacing after the puntuation
-                            (?='n\s[A-Z\d]|[^'a-z]|'[^n])
+                            (?='n\s[A-Z]|[^'a-z\d]|'[^n])
                             #lookahead that next part starts with caps or 'n followed by caps
                             """ % sentenceend, re.VERBOSE)
 
@@ -47,7 +47,7 @@
         match = articlere.search(text, 0, 20)
         if match:
             #construct a list of non-apostrophe punctuation:
-            nonapos = "".join(cls.punctuation.split("'"))
+            nonapos = u"".join(cls.punctuation.split(u"'"))
             stripped = text.lstrip().lstrip(nonapos)
             match = articlere.match(stripped)
             if match:

Modified: translate-toolkit/branches/upstream/current/translate/lang/common.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/common.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/common.py (original)
+++ translate-toolkit/branches/upstream/current/translate/lang/common.py Fri Jul 24 16:25:46 2009
@@ -101,7 +101,7 @@
     # some code probably depends on these for unrecognised languages
     
     listseperator = u", "
-    """This string is used to seperate lists of textual elements. Most 
+    """This string is used to separate lists of textual elements. Most 
     languages probably can stick with the default comma, but Arabic and some
     Asian languages might want to override this."""
     
@@ -197,6 +197,10 @@
             pass
         return language
 
+    def __deepcopy__(self, memo={}):
+        memo[id(self)] = self
+        return self
+
     def __repr__(self):
         """Give a simple string representation without address information to 
         be able to store it in text for comparison later."""
@@ -211,13 +215,22 @@
 #        TODO: look at po::escapeforpo() for performance idea
         if not text:
             return text
+        ellipses_end = text.endswith(u"...")
+        if ellipses_end:
+            text = text[:-3]
         for source, target in cls.puncdict.iteritems():
             text = text.replace(source, target)
+        if ellipses_end:
+            if u"..." in cls.puncdict:
+                text += cls.puncdict[u"..."]
+            else:
+                text += u"..."
         # Let's account for cases where a punctuation symbol plus a space is 
         # replaced, but the space won't exist at the end of a message.
         # As a simple improvement for messages ending in ellipses (...), we
         # test that the last character is different from the second last
-        if (text[-1] + u" " in cls.puncdict) and (text[-2] != text[-1]):
+        # This is only relevant if the string has two characters or more
+        if (text[-1] + u" " in cls.puncdict) and (len(text) < 2 or text[-2] != text[-1]):
             text = text[:-1] + cls.puncdict[text[-1] + u" "].rstrip()
         return text
     punctranslate = classmethod(punctranslate)
@@ -254,9 +267,9 @@
                     text = text[-extra:]
             return text
         expanded = []
-        for subtext in text.split("\n\n"):
+        for subtext in text.split(u"\n\n"):
             expanded.append(alter_it(subtext))
-        text = "\n\n".join(expanded)
+        text = u"\n\n".join(expanded)
         return text
 
     def character_iter(cls, text):
@@ -304,7 +317,7 @@
         if strip: remainder = remainder.strip()
         if remainder: yield remainder
     sentence_iter = classmethod(sentence_iter)
-            
+
     def sentences(cls, text, strip=True):
         """Returns a list of senteces in text."""
         return [s for s in cls.sentence_iter(text, strip=strip)]

Modified: translate-toolkit/branches/upstream/current/translate/lang/data.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/data.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/data.py (original)
+++ translate-toolkit/branches/upstream/current/translate/lang/data.py Fri Jul 24 16:25:46 2009
@@ -23,16 +23,20 @@
 
 import unicodedata
 
+from translate.storage.placeables import StringElem
+
+
 languages = {
 'af': ('Afrikaans', 2, '(n != 1)'),
 'ak': ('Akan', 2, 'n > 1'),
 'am': ('Amharic', 2, 'n > 1'),
-'ar': ('Arabic', 6, 'n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n>=3 && n<=10 ? 3 : n>=11 && n<=99 ? 4 : 5'),
+'ar': ('Arabic', 6, 'n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5'),
 'arn': ('Mapudungun; Mapuche', 2, 'n > 1'),
 'az': ('Azerbaijani', 2, '(n != 1)'),
 'be': ('Belarusian', 3, 'n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2'),
 'bg': ('Bulgarian', 2, '(n != 1)'),
 'bn': ('Bengali', 2, '(n != 1)'),
+'bn_IN': ('Bengali (India)', 2, '(n != 1)'),
 'bo': ('Tibetan', 1, '0'),
 'bs': ('Bosnian', 3, 'n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2'),
 'ca': ('Catalan; Valencian', 2, '(n != 1)'),
@@ -81,6 +85,7 @@
 'ky': ('Kirghiz; Kyrgyz', 1, '0'),
 'lb': ('Luxembourgish; Letzeburgesch', 2, '(n != 1)'),
 'ln': ('Lingala', 2, '(n > 1)'),
+'lo': ('Lao', 1, '0'),
 'lt': ('Lithuanian', 3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)'),
 'lv': ('Latvian', 3, '(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)'),
 'mg': ('Malagasy', 2, '(n > 1)'),
@@ -92,15 +97,18 @@
 'ms': ('Malay', 1, '0'),
 'mt': ('Maltese', 4, '(n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3)'),
 'nah': ('Nahuatl languages', 2, '(n != 1)'),
+'nap': ('Neapolitan', 2, '(n != 1)'),
 'nb': ('Norwegian Bokmal', 2, '(n != 1)'),
 'ne': ('Nepali', 2, '(n != 1)'),
 'nl': ('Dutch; Flemish', 2, '(n != 1)'),
 'nn': ('Norwegian Nynorsk', 2, '(n != 1)'),
-'nso': ('Northern Sotho', 2, '(n > 1)'),
+'nso': ('Pedi; Sepedi; Northern Sotho', 2, '(n > 1)'),
 'or': ('Oriya', 2, '(n != 1)'),
 'pa': ('Panjabi; Punjabi', 2, '(n != 1)'),
 'pap': ('Papiamento', 2, '(n != 1)'),
 'pl': ('Polish', 3, '(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
+'pms': ('Piemontese', 2, '(n != 1)'),
+'ps': ('Pushto; Pashto', 2, '(n != 1)'),
 'pt': ('Portuguese', 2, '(n != 1)'),
 'pt_BR': ('Portuguese (Brazil)', 2, '(n > 1)'),
 'ro': ('Romanian', 3, '(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);'),
@@ -165,7 +173,9 @@
 """Source to target string length expansion factors."""
 
 import gettext
+import locale
 import re
+import os
 
 iso639 = {}
 """ISO 639 language codes"""
@@ -182,10 +192,10 @@
     return languagecode == otherlanguagecode or \
       (otherlanguagecode.startswith(languagecode) and variant_re.match(otherlanguagecode[len(languagecode):]))
 
-dialect_name_re = re.compile(r"([^(\s]+)\s*\(([^)]+)\)")
+dialect_name_re = re.compile(r"(.+)\s\(([^)]+)\)$")
 
 def tr_lang(langcode=None):
-    """Gives a function that can translate a language name, even in the form::
+    """Gives a function that can translate a language name, even in the form:
            "language (country)"
        into the language with iso code langcode, or the system language if no
        language is specified."""
@@ -208,7 +218,11 @@
     if not langcode in iso639:
         if not langcode:
             langcode = ""
-            t = gettext.translation('iso_639', fallback=True)
+            if os.name == "nt":
+                # On Windows the default locale is not used for some reason
+                t = gettext.translation('iso_639', languages=[locale.getdefaultlocale()[0]], fallback=True)
+            else:
+                t = gettext.translation('iso_639', fallback=True)
         else:
             t = gettext.translation('iso_639', languages=[langcode], fallback=True)
         iso639[langcode] = t.ugettext
@@ -220,7 +234,11 @@
     if not langcode in iso3166:
         if not langcode:
             langcode = ""
-            t = gettext.translation('iso_3166', fallback=True)
+            if os.name == "nt":
+                # On Windows the default locale is not used for some reason
+                t = gettext.translation('iso_3166', languages=[locale.getdefaultlocale()[0]], fallback=True)
+            else:
+                t = gettext.translation('iso_3166', fallback=True)
         else:
             t = gettext.translation('iso_3166', languages=[langcode], fallback=True)
         iso3166[langcode] = t.ugettext
@@ -251,6 +269,8 @@
     if isinstance(string, str):
         encoding = getattr(string, "encoding", "utf-8")
         string = string.decode(encoding)
+    elif isinstance(string, StringElem):
+        string = unicode(string)
     return string
 
 def normalized_unicode(string):
@@ -259,15 +279,14 @@
 
 def normalize_code(code):
     return code.replace("_", "-").replace("@", "-").lower()
-
 
 def simplify_to_common(language_code, languages=languages):
     """Simplify language code to the most commonly used form for the
     language, stripping country information for languages that tend
     not to be localized differently for different countries"""
     simpler = simplercode(language_code)
-    if normalize_code(language_code) in [normalize_code(key) for key in languages.keys()] or simpler =="":
+    if normalize_code(language_code) in [normalize_code(key) for key in languages.keys()] or simpler == "":
         return language_code
     else:
         return simplify_to_common(simpler)
-    
+

Added: translate-toolkit/branches/upstream/current/translate/lang/de.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/de.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/de.py (added)
+++ translate-toolkit/branches/upstream/current/translate/lang/de.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,31 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""This module represents German language.
+
+For more information, see U{http://en.wikipedia.org/wiki/German_language}
+"""
+
+from translate.lang import common
+
+class de(common.Common):
+    """This class represents German."""
+
+    ignoretests = ["simplecaps"]

Modified: translate-toolkit/branches/upstream/current/translate/lang/el.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/el.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/el.py (original)
+++ translate-toolkit/branches/upstream/current/translate/lang/el.py Fri Jul 24 16:25:46 2009
@@ -40,9 +40,17 @@
                             \s+         #the spacing after the puntuation
                             (?=[^a-z\d])#lookahead that next part starts with caps
                             """ % sentenceend, re.VERBOSE)
-    
+
     puncdict = {
         u"?": u";",
         u";": u"·",
     }
 
+    # Valid latin characters for use as accelerators
+    valid_latin_accel = u"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
+
+    # Valid greek characters for use as accelerators (accented characters and "Ï‚" omitted)
+    valid_greek_accel = u"αβγδεζηθικλμνξοπρστÏ
φχψωΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"
+
+    # Valid accelerators
+    validaccel =  u"".join([valid_latin_accel, valid_greek_accel])

Modified: translate-toolkit/branches/upstream/current/translate/lang/fa.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/fa.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/fa.py (original)
+++ translate-toolkit/branches/upstream/current/translate/lang/fa.py Fri Jul 24 16:25:46 2009
@@ -35,7 +35,8 @@
         u",": u"،",
         u";": u"Ø›",
         u"?": u"ØŸ",
-        u"%": u"Ùª",
+        #This causes problems with variables, so commented out for now:
+        #u"%": u"Ùª",
     }
 
     ignoretests = ["startcaps", "simplecaps"]

Added: translate-toolkit/branches/upstream/current/translate/lang/identify.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/identify.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/identify.py (added)
+++ translate-toolkit/branches/upstream/current/translate/lang/identify.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,124 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# 
+# Copyright 2009 Zuza Software Foundation
+# 
+# This file is part of translate.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""This module contains functions for identifying languages based on language models.
+
+   It wraps U{libtextcat<http://software.wise-guys.nl/libtextcat/>} to get the language
+   identification functionality.
+
+   To use first create an instance of I{LanguageIdentifier} and then use the methods 
+   I{identify} or I{identify_store} to detect the language in a string or in a translation
+   store respectively.
+"""
+
+from ctypes import *
+import ctypes.util
+
+from translate.lang.data import *
+
+# Load libtextcat
+textcat = None
+# 'textcat' is recognised on Unix, while only 'libtextcat' is recognised on
+# windows. Therefore we test both.
+names = ['textcat', 'libtextcat']
+for name in names:
+    lib_location = ctypes.util.find_library(name)
+    if lib_location:
+        textcat = cdll.LoadLibrary(lib_location)
+        if textcat:
+            break
+else:
+    # Now we are getting desperate, so let's guess a unix type DLL that might 
+    # be in LD_LIBRARY_PATH or loaded with LD_PRELOAD
+    try:
+        textcat = cdll.LoadLibrary('libtextcat.so')
+    except OSError, e:
+        raise ImportError("textcat library not found")
+
+# Original initialisation
+textcat.textcat_Init.argtypes = [c_char_p]
+textcat.textcat_Init.retype = c_int
+
+# Initialisation used in OpenOffice.org modification which allows the models to be in a different directory
+textcat.special_textcat_Init.argtypes = [c_char_p, c_char_p]
+textcat.special_textcat_Init.restype = c_int
+
+# Cleans up textcat
+textcat.textcat_Done.argtypes = [c_int]
+
+# Perform language guessing
+textcat.textcat_Classify.argtypes = [c_int, c_char_p, c_int]
+textcat.textcat_Classify.restype = c_char_p
+
+class LanguageIdentifier(object):
+
+    def __init__(self, config, model_dir):
+        """
+        @param config: path to .conf for textcat
+        @type config: String
+        @param model_dir: path to language models
+        @type model_dir: String
+        """
+        if textcat is None:
+            return None
+        self._handle = textcat.special_textcat_Init(config, model_dir)
+
+    lang_list_re = re.compile("\[(.+?)\]+")
+
+    def _lang_result_to_list(self, lang_result):
+        """Converts a text result of '[lang][lang]' into a Python list of language codes"""
+        if lang_result in ('SHORT', 'UNKNOWN'):
+            return []
+        return self.lang_list_re.findall(lang_result)
+
+    def identify(self, text, sample_length=None):
+        """Identify the language in I{text} by sampling I{sample_length}
+
+        @param text: Text to be identified
+        @type text: String
+        @param sample_length: The amount of I{text} to be analysed
+        @type sample_length: Int
+        @return: list of language codes
+        """
+        if sample_length is None or sample_length > len(text):
+            sample_length = len(text)
+        if isinstance(text, unicode):
+            text = text.encode('utf-8')
+        matches = self._lang_result_to_list(textcat.textcat_Classify(self._handle, text, sample_length))
+        return [(simplify_to_common(match, languages), 0.8) for match in matches]
+
+    def identify_store(self, store, sample_length=None):
+        """Identify the language of a translation store
+
+        @param store: Store to be identified
+        @type text: L{TranslationStore <sorage.base.TranslatonStore>}
+        @param sample_length: The amount of text to be analysed
+        @type sample_length: Int
+        @return: list of language codes
+        """
+        text = ""
+        for unit in store.units:
+            text = text + unit.target
+            if sample_length is not None and len(text) >= sample:
+                break
+        return self.identify(text, sample_length)
+
+    def __del__(self):
+        textcat.textcat_Done(self._handle)

Added: translate-toolkit/branches/upstream/current/translate/lang/ne.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/ne.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/ne.py (added)
+++ translate-toolkit/branches/upstream/current/translate/lang/ne.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,49 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# 
+# Copyright 2009 Zuza Software Foundation
+# 
+# This file is part of translate.
+#
+# translate is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# translate is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with translate; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""This module represents Nepali language.
+
+For more information, see U{http://en.wikipedia.org/wiki/Nepali_language}
+"""
+
+import re
+
+from translate.lang import common
+
+class ne(common.Common):
+    """This class represents Nepali."""
+
+    sentenceend = u"।!?…"
+
+    sentencere = re.compile(r"""(?s)    #make . also match newlines
+                            .*?         #anything, but match non-greedy
+                            \s?         #the single space before the punctuation
+                            [%s]        #the puntuation for sentence ending
+                            \s+         #the spacing after the puntuation
+                            (?=[^a-z\d])#lookahead that next part starts with caps
+                            """ % sentenceend, re.VERBOSE)
+
+    puncdict = {
+        u".": u" ।",
+        u"?": u" ?",
+    }
+
+    ignoretests = ["startcaps", "simplecaps", "accelerators"]

Modified: translate-toolkit/branches/upstream/current/translate/lang/test_common.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/test_common.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/test_common.py (original)
+++ translate-toolkit/branches/upstream/current/translate/lang/test_common.py Fri Jul 24 16:25:46 2009
@@ -45,6 +45,13 @@
     assert sentences == [u"Apples, bananas, etc.", u"Next part"]
     sentences = language.sentences(u"No font for displaying text in encoding '%s' found,\nbut an alternative encoding '%s' is available.\nDo you want to use this encoding (otherwise you will have to choose another one)?")
     assert sentences == [u"No font for displaying text in encoding '%s' found,\nbut an alternative encoding '%s' is available.", u"Do you want to use this encoding (otherwise you will have to choose another one)?"]
+    # Test that a newline at the end won't confuse us
+    sentences = language.sentences(u"The first sentence. The second sentence.\n")
+    assert sentences == [u"The first sentence.", u"The second sentence."]
+    sentences = language.sentences(u"P.O. box")
+    assert sentences == [u"P.O. box"]
+    sentences = language.sentences(u"Doen dit d.m.v. koeie.")
+    assert sentences == [u"Doen dit d.m.v. koeie."]
 
 def test_capsstart():
     """Tests that the indefinite article ('n) doesn't confuse startcaps()."""

Added: translate-toolkit/branches/upstream/current/translate/lang/test_ne.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/test_ne.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/test_ne.py (added)
+++ translate-toolkit/branches/upstream/current/translate/lang/test_ne.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,24 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from translate.lang import factory
+
+def test_punctranslate():
+    """Tests that we can translate punctuation."""
+    language = factory.getlanguage('ne')
+    assert language.punctranslate(u"abc efg") == u"abc efg"
+    assert language.punctranslate(u"abc efg.") == u"abc efg ।"
+    assert language.punctranslate(u"(abc efg).") == u"(abc efg) ।"
+    assert language.punctranslate(u"abc efg...") == u"abc efg..."
+    assert language.punctranslate(u"abc efg?") == u"abc efg ?"
+
+def test_sentences():
+    """Tests basic functionality of sentence segmentation."""
+    language = factory.getlanguage('ne')
+    # Without spaces before the punctuation
+    sentences = language.sentences(u"यसको भौगोलिक à¤
क्षांश २६ डिग्री २२ मिनेट देखि ३० डिग्री २७ मिनेट उत्तर र ८० डिग्री ४ मिनेट देखि ८८ डिग्री १२ मिनेट पूर्वी देशान्तर सम्म फैलिएको छ। यसको कूल क्षेत्रफल १,४७,१८१ वर्ग कि.मि छ।\n")
+    assert sentences == [u"यसको भौगोलिक à¤
क्षांश २६ डिग्री २२ मिनेट देखि ३० डिग्री २७ मिनेट उत्तर र ८० डिग्री ४ मिनेट देखि ८८ डिग्री १२ मिनेट पूर्वी देशान्तर सम्म फैलिएको छ।", u"यसको कूल क्षेत्रफल १,४७,१८१ वर्ग कि.मि छ।"]
+    # With spaces before the punctuation
+    sentences = language.sentences(u"यसको भौगोलिक à¤
क्षांश २६ डिग्री २२ मिनेट देखि ३० डिग्री २७ मिनेट उत्तर र ८० डिग्री ४ मिनेट देखि ८८ डिग्री १२ मिनेट पूर्वी देशान्तर सम्म फैलिएको छ । यसको कूल क्षेत्रफल १,४७,१८१ वर्ग कि.मि छ ।\n")
+    assert sentences == [u"यसको भौगोलिक à¤
क्षांश २६ डिग्री २२ मिनेट देखि ३० डिग्री २७ मिनेट उत्तर र ८० डिग्री ४ मिनेट देखि ८८ डिग्री १२ मिनेट पूर्वी देशान्तर सम्म फैलिएको छ ।", u"यसको कूल क्षेत्रफल १,४७,१८१ वर्ग कि.मि छ ।"]
+

Modified: translate-toolkit/branches/upstream/current/translate/lang/test_zh.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/test_zh.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/test_zh.py (original)
+++ translate-toolkit/branches/upstream/current/translate/lang/test_zh.py Fri Jul 24 16:25:46 2009
@@ -9,6 +9,8 @@
     assert language.punctranslate(u"abc efg") == u"abc efg"
     assert language.punctranslate(u"abc efg.") == u"abc efg。"
     assert language.punctranslate(u"(abc efg).") == u"(abc efg)。"
+    assert language.punctranslate(u"(abc efg). hijk") == u"(abc efg)。hijk"
+    assert language.punctranslate(u".") == u"。"
     assert language.punctranslate(u"abc efg...") == u"abc efg..."
 
 def test_sentences():

Modified: translate-toolkit/branches/upstream/current/translate/lang/ur.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/lang/ur.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/lang/ur.py (original)
+++ translate-toolkit/branches/upstream/current/translate/lang/ur.py Fri Jul 24 16:25:46 2009
@@ -36,7 +36,8 @@
         u",": u"،",
         u";": u"Ø›",
         u"?": u"ØŸ",
-        u"%": u"Ùª",
+        #This causes problems with variables, so commented out for now:
+        #u"%": u"Ùª",
     }
 
     ignoretests = ["startcaps", "simplecaps"]

Modified: translate-toolkit/branches/upstream/current/translate/misc/file_discovery.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/misc/file_discovery.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/misc/file_discovery.py (original)
+++ translate-toolkit/branches/upstream/current/translate/misc/file_discovery.py Fri Jul 24 16:25:46 2009
@@ -25,13 +25,15 @@
 import sys
 import os
 
-def get_abs_data_filename(path_parts, basedirs=[]):
+def get_abs_data_filename(path_parts, basedirs=None):
     """Get the absolute path to the given file- or directory name in the current
         running application's data directory.
 
         @type  path_parts: list
         @param path_parts: The path parts that can be joined by os.path.join().
         """
+    if basedirs is None:
+        basedirs = []
 
     if isinstance(path_parts, str):
         path_parts = [path_parts]

Modified: translate-toolkit/branches/upstream/current/translate/misc/multistring.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/misc/multistring.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/misc/multistring.py (original)
+++ translate-toolkit/branches/upstream/current/translate/misc/multistring.py Fri Jul 24 16:25:46 2009
@@ -37,9 +37,9 @@
         return newstring
 
     def __init__(self, *args, **kwargs):
-        super(multistring, self).__init__(*args, **kwargs)
+        super(multistring, self).__init__()
         if not hasattr(self, "strings"):
-            self.strings = []    
+            self.strings = []
 
     def __cmp__(self, otherstring):
         if isinstance(otherstring, multistring):

Modified: translate-toolkit/branches/upstream/current/translate/misc/quote.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/misc/quote.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/misc/quote.py (original)
+++ translate-toolkit/branches/upstream/current/translate/misc/quote.py Fri Jul 24 16:25:46 2009
@@ -119,6 +119,7 @@
         enddelim_places = startdelim_places[:]
     else:
         enddelim_places = find_all(source, enddelim)
+    #hell slow because it is called far too often
     if escape is not None:
         lenescape = len(escape)
         escape_places = find_all(source, escape)
@@ -241,7 +242,7 @@
 
 def javapropertiesencode(source):
     """encodes source in the escaped-unicode encoding used by Java .properties files"""
-    output = ""
+    output = u""
     for char in source:
         charnum = ord(char)
         if char in controlchars:
@@ -249,12 +250,12 @@
         elif 0 <= charnum < 128:
             output += str(char)
         else:
-            output += "\\u%04X" % charnum
+            output += u"\\u%04X" % charnum
     return output
 
 def mozillapropertiesencode(source):
     """encodes source in the escaped-unicode encoding used by Mozilla .properties files"""
-    output = ""
+    output = u""
     for char in source:
         charnum = ord(char)
         if char in controlchars:
@@ -267,12 +268,13 @@
     # escapes that are self-escaping
     "\\": "\\", "'": "'", '"': '"',
     # control characters that we keep
-    "b": "\b", "f": "\f", "t": "\t", "n": "\n", "v": "\v", "a": "\a"
+    "f": "\f", "n": "\n", "r": "\r", "t": "\t",
     }
 
 controlchars = {
     # the reverse of the above...
-    "\b": "\\b", "\f": "\\f", "\t": "\\t", "\n": "\\n", "\v": "\\v"
+    "\\": "\\\\",
+    "\f": "\\f", "\n": "\\n", "\r": "\\r", "\t": "\\t"
     }
 
 def escapecontrols(source):
@@ -281,15 +283,17 @@
         source = source.replace(key, value)
     return source
 
-def mozillapropertiesdecode(source):
-    """decodes source from the escaped-unicode encoding used by mozilla .properties files"""
+def propertiesdecode(source):
+    """Decodes source from the escaped-unicode encoding used by .properties files.
+
+    Java uses Latin1 by default, and Mozilla uses UTF-8 by default."""
     # since the .decode("unicode-escape") routine decodes everything, and we don't want to
     # we reimplemented the algorithm from Python Objects/unicode.c in Python here
     # and modified it to retain escaped control characters
     output = u""
     s = 0
     if isinstance(source, str):
-        source = source.decode("utf-8")
+        source = source.decode(encoding)
     def unichr2(i):
         """Returns a Unicode string of one character with ordinal 32 <= i, otherwise an escaped control character"""
         if 32 <= i:
@@ -352,7 +356,7 @@
             output += unicodedata.lookup(name)
             s = e + 1
         else:
-            output += "\\" + c
+            output += c # Drop any \ that we don't specifically handle
     return output
 
 def quotestr(source, escapeescapes=0):

Modified: translate-toolkit/branches/upstream/current/translate/misc/test_optrecurse.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/misc/test_optrecurse.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/misc/test_optrecurse.py (original)
+++ translate-toolkit/branches/upstream/current/translate/misc/test_optrecurse.py Fri Jul 24 16:25:46 2009
@@ -3,7 +3,7 @@
 from translate.misc import optrecurse
 import os
 
-class TestRecursiveOptionParser():
+class TestRecursiveOptionParser:
 
     def __init__(self):
         self.parser = optrecurse.RecursiveOptionParser({"txt":("po", None)})

Added: translate-toolkit/branches/upstream/current/translate/misc/xml_helpers.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/misc/xml_helpers.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/misc/xml_helpers.py (added)
+++ translate-toolkit/branches/upstream/current/translate/misc/xml_helpers.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,119 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2006-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""Helper functions for working with XML."""
+
+import re
+from lxml import etree
+
+# some useful xpath expressions
+xml_preserve_ancestors = etree.XPath("ancestor-or-self::*[attribute::xml:space='preserve']")
+"""All ancestors with xml:space='preserve'"""
+
+xml_space_ancestors= etree.XPath("ancestor-or-self::*/attribute::xml:space")
+"""All xml:space attributes in the ancestors"""
+
+string_xpath = etree.XPath("string()")
+"""Return a non-normalized string in the node subtree"""
+
+string_xpath_normalized = etree.XPath("normalize-space()")
+"""Return a (space) normalized string in the node subtree"""
+
+def getText(node, xml_space="preserve"):
+    """Extracts the plain text content out of the given node.
+
+    This method checks the xml:space attribute of the given node, and takes
+    an optional default to use in case nothing is specified in this node."""
+    xml_space = getXMLspace(node, xml_space)
+    if xml_space == "default":
+        return unicode(string_xpath_normalized(node)) # specific to lxml.etree
+    else:
+        return unicode(string_xpath(node)) # specific to lxml.etree
+
+    # If we want to normalise space and only preserve it when the directive
+    # xml:space="preserve" is given in node or in parents, consider this code:
+    #xml_preserves = xml_preserve_ancestors(node)
+    #if xml_preserves and xml_preserves[-1] == "preserve":
+    #    return unicode(string_xpath(node)) # specific to lxml.etree
+    #else:
+    #    return unicode(string_xpath_normalized(node)) # specific to lxml.etree
+
+
+XML_NS = 'http://www.w3.org/XML/1998/namespace'
+
+def getXMLlang(node):
+    """Gets the xml:lang attribute on node"""
+    return node.get("{%s}lang" % XML_NS)
+
+def setXMLlang(node, lang):
+    """Sets the xml:lang attribute on node"""
+    node.set("{%s}lang" % XML_NS, lang)
+
+def getXMLspace(node, default=None):
+    """Gets the xml:space attribute on node"""
+    value = node.get("{%s}space" % XML_NS)
+    if value is None:
+        value = default
+    return value
+
+def setXMLspace(node, value):
+    """Sets the xml:space attribute on node"""
+    node.set("{%s}space" % XML_NS, value)
+
+def namespaced(namespace, name):
+    """Returns name in Clark notation within the given namespace.
+
+       For example namespaced("source") in an XLIFF document might return::
+           {urn:oasis:names:tc:xliff:document:1.1}source
+       This is needed throughout lxml.
+    """
+    if namespace:
+        return "{%s}%s" % (namespace, name)
+    else:
+        return name
+
+MULTIWHITESPACE_PATTERN = r"[\n\r\t ]+"
+MULTIWHITESPACE_RE = re.compile(MULTIWHITESPACE_PATTERN, re.MULTILINE)
+
+def normalize_space(text):
+    """Normalize the given text for implimentation of xml:space="default"."""
+    text = MULTIWHITESPACE_RE.sub(u" ", text)
+    return text
+
+def normalize_xml_space(node, xml_space, remove_start=False):
+    """normalize spaces following the nodes xml:space, or alternatively the 
+    given xml_space parameter."""
+    xml_space = getXMLspace(node) or xml_space
+    if xml_space == 'preserve':
+        return
+    if node.text:
+        node.text = normalize_space(node.text)
+        if remove_start and node.text[0] == u" ":
+            node.text = node.text.lstrip()
+            remove_start = False
+        if len(node.text) > 0 and node.text.endswith(u" "):
+            remove_start = True
+        if len(node) == 0:
+            node.text = node.text.rstrip()
+    if node.tail:
+        node.tail = normalize_space(node.tail)
+
+    for child in node:
+        normalize_xml_space(child, remove_start)

Modified: translate-toolkit/branches/upstream/current/translate/search/indexing/PyLuceneIndexer.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/search/indexing/PyLuceneIndexer.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/search/indexing/PyLuceneIndexer.py (original)
+++ translate-toolkit/branches/upstream/current/translate/search/indexing/PyLuceneIndexer.py Fri Jul 24 16:25:46 2009
@@ -26,11 +26,11 @@
 take a look at PyLuceneIndexer1.py for the PyLucene v1.x interface
 """
 
-__revision__ = "$Id: PyLuceneIndexer.py 8506 2008-09-27 09:11:32Z dwaynebailey $"
+__revision__ = "$Id: PyLuceneIndexer.py 11946 2009-07-19 23:59:10Z alaaosh $"
 
 import CommonIndexer
 # TODO: replace this dependency on the jToolkit
-import jToolkit.glock
+#import jToolkit.glock
 import tempfile
 import re
 import os
@@ -40,14 +40,14 @@
 # remember the type of the detected package (compiled with jcc (>=v2.3) or
 # with gcj (<=v2.2)
 try:
-	import PyLucene
-        _COMPILER = 'gcj'
+    import PyLucene
+    _COMPILER = 'gcj'
 except ImportError:
-	# if this fails, then there is no pylucene installed
-	import lucene
-	PyLucene = lucene
-	PyLucene.initVM(PyLucene.CLASSPATH)
-        _COMPILER = 'jcc'
+    # if this fails, then there is no pylucene installed
+    import lucene
+    PyLucene = lucene
+    PyLucene.initVM(PyLucene.CLASSPATH)
+    _COMPILER = 'jcc'
 
 
 UNNAMED_FIELD_NAME = "FieldWithoutAName"
@@ -122,30 +122,31 @@
         # create a lock for the database directory - to be used later
         lockname = os.path.join(tempfile.gettempdir(),
                 re.sub("\W", "_", self.location))
-        self.dir_lock = jToolkit.glock.GlobalLock(lockname)
+        #self.dir_lock = jToolkit.glock.GlobalLock(lockname)
         # windows file locking seems inconsistent, so we try 10 times
         numtries = 0
-        self.dir_lock.acquire(blocking=True)
+        #self.dir_lock.acquire(blocking=True)
         # read "self.reader", "self.indexVersion" and "self.searcher"
         try:
             while numtries < 10:
                 try:
                     self.reader = PyLucene.IndexReader.open(self.location)
                     self.indexVersion = self.reader.getCurrentVersion(
-                            self.location)
+                        self.location)
                     self.searcher = PyLucene.IndexSearcher(self.reader)
                     break
                 except PyLucene.JavaError, e:
                     # store error message for possible later re-raise (below)
                     lock_error_msg = e
                     time.sleep(0.01)
-                numtries += 1
+                    numtries += 1
             else:
                 # locking failed for 10 times
                 raise OSError("Indexer: failed to lock index database" \
-                        + " (%s)" % lock_error_msg)
+                              + " (%s)" % lock_error_msg)
         finally:
-            self.dir_lock.release()
+            pass
+        #    self.dir_lock.release()
         # initialize the searcher and the reader
         self._index_refresh()
 
@@ -417,7 +418,7 @@
         exclusive lock
         """
         if not self._writer_is_open():
-            self.dir_lock.acquire()
+            #self.dir_lock.acquire()
             self.writer = PyLucene.IndexWriter(self.location, self.pyl_analyzer,
                     False)
             # "setMaxFieldLength" is available since PyLucene v2
@@ -433,7 +434,7 @@
             self.writer.close()
             self.writer = None
         # make sure that the lock is removed
-        self.dir_lock.forcerelease()
+        #self.dir_lock.forcerelease()
 
     def _writer_is_open(self):
         """check if the indexing write access is currently open"""
@@ -441,12 +442,12 @@
 
     def _index_refresh(self):
         """re-read the indexer database"""
-        try:
-            self.dir_lock.acquire(blocking=False)
-        except jToolkit.glock.GlobalLockError, e:
+        #try:
+            #self.dir_lock.acquire(blocking=False)
+        #except jToolkit.glock.GlobalLockError, e:
             # if this fails the index is being rewritten, so we continue with
             # our old version
-            return
+        #    return
         try:
             if self.reader is None or self.searcher is None:
                 self.reader = PyLucene.IndexReader.open(self.location)
@@ -462,7 +463,7 @@
             # TODO: add some debugging output?
             #self.errorhandler.logerror("Error attempting to read index - try reindexing: "+str(e))
             pass
-        self.dir_lock.release()
+        #self.dir_lock.release()
 
 
 

Modified: translate-toolkit/branches/upstream/current/translate/search/indexing/XapianIndexer.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/search/indexing/XapianIndexer.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/search/indexing/XapianIndexer.py (original)
+++ translate-toolkit/branches/upstream/current/translate/search/indexing/XapianIndexer.py Fri Jul 24 16:25:46 2009
@@ -31,8 +31,13 @@
 It is not completely working, but it should give you a good start.
 """
 
-__revision__ = "$Id: XapianIndexer.py 8504 2008-09-27 09:02:29Z dwaynebailey $"
-
+__revision__ = "$Id: XapianIndexer.py 10834 2009-04-09 14:40:06Z alaaosh $"
+
+# xapian module hangs apache under mod_python
+# detect if running under apache and fail immediatly
+import sys
+if 'apache' in sys.modules or '_apache' in sys.modules:
+    raise ImportError("Running under mod_python, can't load xapian")
 
 import CommonIndexer
 import xapian

Modified: translate-toolkit/branches/upstream/current/translate/search/match.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/search/match.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/search/match.py (original)
+++ translate-toolkit/branches/upstream/current/translate/search/match.py Fri Jul 24 16:25:46 2009
@@ -1,26 +1,26 @@
+#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2006-2007 Zuza Software Foundation
-# 
-# This file is part of translate.
-#
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2006-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """Class to perform translation memory matching from a store of translation units"""
 
+import heapq
 import re
 
 from translate.search import lshtein
@@ -28,21 +28,18 @@
 from translate.storage import base
 from translate.storage import po
 from translate.misc.multistring import multistring
-import heapq
+
 
 def sourcelen(unit):
     """Returns the length of the source string"""
     return len(unit.source)
 
-def sourcelencmp(x, y):
-    """Compares using sourcelen"""
-    # This is mostly useful for Python 2.3
-    xlen = sourcelen(x)
-    ylen = sourcelen(y)
-    return cmp(xlen, ylen)
 
 class matcher(object):
     """A class that will do matching and store configuration for the matching process"""
+
+    sort_reverse = False
+
     def __init__(self, store, max_candidates=10, min_similarity=75, max_length=70, comparer=None, usefuzzy=False):
         """max_candidates is the maximum number of candidates that should be assembled,
         min_similarity is the minimum similarity that must be attained to be included in
@@ -54,13 +51,15 @@
         self.usefuzzy = usefuzzy
         self.inittm(store)
         self.addpercentage = True
-        
+
     def usable(self, unit):
         """Returns whether this translation unit is usable for TM"""
         #TODO: We might want to consider more attributes, such as approved, reviewed, etc.
         source = unit.source
         target = unit.target
         if source and target and (self.usefuzzy or not unit.isfuzzy()):
+            if len(source) < 2:
+                return False
             if source in self.existingunits and self.existingunits[source] == target:
                 return False
             else:
@@ -68,28 +67,29 @@
                 return True
         return False
 
-    def inittm(self, stores):
-        """Initialises the memory for later use. We use simple base units for 
+    def inittm(self, stores, reverse=False):
+        """Initialises the memory for later use. We use simple base units for
         speedup."""
+        # reverse is deprectated - just use self.sort_reverse
         self.existingunits = {}
         self.candidates = base.TranslationStore()
-        
+
         if not isinstance(stores, list):
             stores = [stores]
         for store in stores:
             self.extendtm(store.units, store=store, sort=False)
-        self.candidates.units.sort(sourcelencmp)
+        self.candidates.units.sort(key=sourcelen, reverse=self.sort_reverse)
         # print "TM initialised with %d candidates (%d to %d characters long)" % \
         #        (len(self.candidates.units), len(self.candidates.units[0].source), len(self.candidates.units[-1].source))
 
     def extendtm(self, units, store=None, sort=True):
         """Extends the memory with extra unit(s).
-        
+
         @param units: The units to add to the TM.
         @param store: Optional store from where some metadata can be retrieved
         and associated with each unit.
-        @param sort:  Optional parameter that can be set to False to supress 
-        sorting of the candidates list. This should probably only be used in 
+        @param sort:  Optional parameter that can be set to False to supress
+        sorting of the candidates list. This should probably only be used in
         inittm().
         """
         if not isinstance(units, list):
@@ -108,7 +108,7 @@
             else:
                 simpleunit.source = candidate.source
                 simpleunit.target = candidate.target
-            # If we now only get translator comments, we don't get programmer 
+            # If we now only get translator comments, we don't get programmer
             # comments in TM suggestions (in Pootle, for example). If we get all
             # notes, pot2po adds all previous comments as translator comments
             # in the new po file
@@ -116,15 +116,15 @@
             simpleunit.fuzzy = candidate.isfuzzy()
             self.candidates.units.append(simpleunit)
         if sort:
-            self.candidates.units.sort(sourcelencmp)
+            self.candidates.units.sort(key=sourcelen, reverse=self.sort_reverse)
 
     def setparameters(self, max_candidates=10, min_similarity=75, max_length=70):
-        """Sets the parameters without reinitialising the tm. If a parameter 
+        """Sets the parameters without reinitialising the tm. If a parameter
         is not specified, it is set to the default, not ignored"""
         self.MAX_CANDIDATES = max_candidates
         self.MIN_SIMILARITY = min_similarity
         self.MAX_LENGTH = max_length
-         
+
     def getstoplength(self, min_similarity, text):
         """Calculates a length beyond which we are not interested.
         The extra fat is because we don't use plain character distance only."""
@@ -134,22 +134,22 @@
         """Calculates the minimum length we are interested in.
         The extra fat is because we don't use plain character distance only."""
         return max(len(text) * (min_similarity/100.0), 1)
-    
+
     def matches(self, text):
         """Returns a list of possible matches for given source text.
-        
+
         @type text: String
         @param text: The text that will be search for in the translation memory
         @rtype: list
-        @return: a list of units with the source and target strings from the 
-        translation memory. If self.addpercentage is true (default) the match 
+        @return: a list of units with the source and target strings from the
+        translation memory. If self.addpercentage is true (default) the match
         quality is given as a percentage in the notes.
         """
         bestcandidates = [(0.0, None)]*self.MAX_CANDIDATES
         #We use self.MIN_SIMILARITY, but if we already know we have max_candidates
         #that are better, we can adjust min_similarity upwards for speedup
         min_similarity = self.MIN_SIMILARITY
-        
+
         # We want to limit our search in self.candidates, so we want to ignore
         # all units with a source string that is too short or too long. We use
         # a binary search to find the shortest string, from where we start our
@@ -165,9 +165,9 @@
                 startindex = mid + 1
             else:
                 endindex = mid
-        
+
         # maximum source string length to be considered
-        stoplength = self.getstoplength(min_similarity, text) 
+        stoplength = self.getstoplength(min_similarity, text)
         lowestscore = 0
 
         for candidate in self.candidates.units[startindex:]:
@@ -184,17 +184,15 @@
                     break
                 if min_similarity < lowestscore:
                     min_similarity = lowestscore
-                    stoplength = self.getstoplength(min_similarity, text) 
-        
+                    stoplength = self.getstoplength(min_similarity, text)
+
         #Remove the empty ones:
         def notzero(item):
             score = item[0]
             return score != 0
         bestcandidates = filter(notzero, bestcandidates)
         #Sort for use as a general list, and reverse so the best one is at index 0
-        bestcandidates.sort()
-        # We reverse as separate step for compatibility with Python 2.3
-        bestcandidates.reverse()
+        bestcandidates.sort(reverse=True)
         return self.buildunits(bestcandidates)
 
     def buildunits(self, candidates):
@@ -215,42 +213,91 @@
             units.append(newunit)
         return units
 
+
+# We don't want to miss certain forms of words that only change a little
+# at the end. Now we are tying this code to English, but it should serve
+# us well. For example "category" should be found in "categories",
+# "copy" should be found in "copied"
+#
+# The tuples define a regular expression to search for, and with what it
+# should be replaced.
+ignorepatterns = [
+    ("y\s*$", "ie"),          #category/categories, identify/identifies, apply/applied
+    ("[\s-]+", ""),           #down time / downtime, pre-order / preorder
+    ("-", " "),               #pre-order / pre order
+    (" ", "-"),               #pre order / pre-order
+]
+
+context_re = re.compile("\s+\(.*\)\s*$")
+
 class terminologymatcher(matcher):
     """A matcher with settings specifically for terminology matching"""
+
+    sort_reverse = True
+
     def __init__(self, store, max_candidates=10, min_similarity=75, max_length=500, comparer=None):
         if comparer is None:
             comparer = terminology.TerminologyComparer(max_length)
         matcher.__init__(self, store, max_candidates, min_similarity=10, max_length=max_length, comparer=comparer)
         self.addpercentage = False
+        self.match_info = {}
 
     def inittm(self, store):
         """Normal initialisation, but convert all source strings to lower case"""
         matcher.inittm(self, store)
+        extras = []
         for unit in self.candidates.units:
-            unit.source = unit.source.lower()
+            source = unit.source = context_re.sub("", unit.source).lower()
+            for ignorepattern in ignorepatterns:
+                (newterm, occurrences) = re.subn(ignorepattern[0], ignorepattern[1], source)
+                if occurrences:
+                    new_unit = type(unit).buildfromunit(unit)
+                    new_unit.source = newterm
+                    # We mark it fuzzy to indicate that it isn't pristine
+                    unit.markfuzzy()
+                    extras.append(new_unit)
+        self.candidates.units.sort(key=sourcelen, reverse=self.sort_reverse)
+        if extras:
+            # We don't sort, so that the altered forms are at the back and
+            # considered last.
+            self.extendtm(extras, sort=False)
 
     def getstartlength(self, min_similarity, text):
-        # Let's number false matches by not working with terms of two 
+        # Let's number false matches by not working with terms of two
         # characters or less
         return 3
-            
+
     def getstoplength(self, min_similarity, text):
         # Let's ignore terms with more than 30 characters. Perhaps someone
         # gave a file with normal (long) translations
         return 30
-            
+
+    def usable(self, unit):
+        """Returns whether this translation unit is usable for terminology."""
+        if not unit.istranslated():
+            return False
+        l = len(context_re.sub("", unit.source))
+        return l <= self.MAX_LENGTH and l >= self.getstartlength(None, None)
+
     def matches(self, text):
         """Normal matching after converting text to lower case. Then replace
         with the original unit to retain comments, etc."""
         text = text.lower()
-        matches = matcher.matches(self, text)
+        comparer = self.comparer
+        comparer.match_info = {}
+        matches = []
+        for cand in self.candidates.units:
+            source = cand.source
+            if comparer.similarity(text, source, self.MIN_SIMILARITY):
+                self.match_info[source] = {'pos': comparer.match_info[source]['pos']}
+                matches.append(cand)
         return matches
 
 
 # utility functions used by virtaal and tmserver to convert matching units in easily marshallable dictionaries
 def unit2dict(unit):
     """converts a pounit to a simple dict structure for use over the web"""
-    return {"source": unit.source, "target": unit.target, 
+    return {"source": unit.source, "target": unit.target,
             "quality": _parse_quality(unit.getnotes()), "context": unit.getcontext()}
 
 def _parse_quality(comment):

Modified: translate-toolkit/branches/upstream/current/translate/search/terminology.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/search/terminology.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/search/terminology.py (original)
+++ translate-toolkit/branches/upstream/current/translate/search/terminology.py Fri Jul 24 16:25:46 2009
@@ -1,71 +1,46 @@
+#!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2006 Zuza Software Foundation
-# 
-# This file is part of translate.
 #
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2006-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """A class that does terminology matching"""
 
-import re
-
-# We don't want to miss certain forms of words that only change a little
-# at the end. Now we are tying this code to English, but it should serve
-# us well. For example "category" should be found in "categories", 
-# "copy" should be found in "copied"
-#
-# The tuples define a regular expression to search for, and what with
-# what it should be replaced.
-ignorepatterns = [("y\s*$", "ie"),          #category/categories, identify/identifies, apply/applied
-                  ("[\s-]*", ""),           #down time / downtime, pre-order / preorder
-                  ("-", " "),               #pre-order / pre order
-                  (" ", "-"),               #pre order / pre-order
-                 ]
-
-#TODO: compile regexes
-
 class TerminologyComparer:
     def __init__(self, max_len=500):
+        self.match_info = {}
         self.MAX_LEN = max_len
 
-    def similarity(self, a, b, stoppercentage=40):
-        """returns the match quality of term b in the text a"""
-        # We could segment the words, but mostly it will give less ideal 
+    def similarity(self, text, term, stoppercentage=40):
+        """Returns the match quality of C{term} in the C{text}"""
+        # We could segment the words, but mostly it will give less ideal
         # results, since we'll miss plurals, etc. Then we also can't search for
-        # multiword terms, such as "Free Software". Ideally we should use a 
+        # multiword terms, such as "Free Software". Ideally we should use a
         # stemmer, like the Porter stemmer.
-        
+
         # So we just see if the word occurs anywhere. This is not perfect since
         # we might get more than we bargained for. The term "form" will be found
         # in the word "format", for example. A word like "at" will trigger too
-        # many false positives. 
+        # many false positives.
 
-        # First remove a possible disambiguating bracket at the end
-        b = re.sub("\s+\(.*\)\s*$", "", b)
+        text = text[:self.MAX_LEN]
 
-        if len(b) <= 2:
-            return 0
-            
-        pos = a[:self.MAX_LEN].find(b)
+        pos = text.find(term)
         if pos >= 0:
-            return 100 - pos * 10 / len(a[:self.MAX_LEN])
-
-        for ignorepattern in ignorepatterns:
-            newb = re.sub(ignorepattern[0], ignorepattern[1], b)
-            if newb in a[:self.MAX_LEN]:
-                return 80
+            self.match_info[term] = { 'pos': pos }
+            return 100
         return 0
-    

Modified: translate-toolkit/branches/upstream/current/translate/search/test_match.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/search/test_match.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/search/test_match.py (original)
+++ translate-toolkit/branches/upstream/current/translate/search/test_match.py Fri Jul 24 16:25:46 2009
@@ -85,3 +85,44 @@
         candidates.sort()
         assert candidates == ["computer", "file"]
 
+    def test_brackets(self):
+        """Tests that brackets at the end of a term are ignored"""
+        csvfile = self.buildcsv(["file (noun)", "ISP (Internet Service Provider)"])
+        matcher = match.terminologymatcher(csvfile)
+        candidates = self.candidatestrings(matcher.matches("Open File"))
+        assert candidates == ["file"]
+        candidates = self.candidatestrings(matcher.matches("Contact your ISP"))
+        # we lowercase everything - that is why we get it back differerntly.
+        # we don't change the target text, though
+        assert candidates == ["isp"]
+
+    def test_past_tences(self):
+        """Tests matching of some past tenses"""
+        csvfile = self.buildcsv(["submit", "certify"])
+        matcher = match.terminologymatcher(csvfile)
+        candidates = self.candidatestrings(matcher.matches("The bug was submitted"))
+        assert candidates == ["submit"]
+        candidates = self.candidatestrings(matcher.matches("The site is certified"))
+
+    def test_space_mismatch(self):
+        """Tests that we can match with some spacing mismatch"""
+        csvfile = self.buildcsv(["down time"])
+        matcher = match.terminologymatcher(csvfile)
+        candidates = self.candidatestrings(matcher.matches("%d minutes downtime"))
+        assert candidates == ["downtime"]
+
+    def test_hyphen_mismatch(self):
+        """Tests that we can match with some spacing mismatch"""
+        csvfile = self.buildcsv(["pre-order"])
+        matcher = match.terminologymatcher(csvfile)
+        candidates = self.candidatestrings(matcher.matches("You can preorder"))
+        assert candidates == ["preorder"]
+        candidates = self.candidatestrings(matcher.matches("You can pre order"))
+        assert candidates == ["pre order"]
+
+        csvfile = self.buildcsv(["pre order"])
+        matcher = match.terminologymatcher(csvfile)
+        candidates = self.candidatestrings(matcher.matches("You can preorder"))
+        assert candidates == ["preorder"]
+        candidates = self.candidatestrings(matcher.matches("You can pre order"))
+        assert candidates == ["pre order"]

Modified: translate-toolkit/branches/upstream/current/translate/search/test_terminology.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/search/test_terminology.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/search/test_terminology.py (original)
+++ translate-toolkit/branches/upstream/current/translate/search/test_terminology.py Fri Jul 24 16:25:46 2009
@@ -2,33 +2,9 @@
 
 class TestTerminology:
     """Test terminology matching"""
+
     def test_basic(self):
         """Tests basic functionality"""
         termmatcher = terminology.TerminologyComparer()
         assert termmatcher.similarity("Open the file", "file") > 75
-    
-    def test_brackets(self):
-        """Tests that brackets at the end of a term are ignored"""
-        termmatcher = terminology.TerminologyComparer()
-        assert termmatcher.similarity("Open file", "file (noun)") > 75
-        assert termmatcher.similarity("Contact your ISP", "ISP (Internet Service Provider)") > 75
 
-    def test_past_tences(self):
-        """Tests matching of some past tenses"""
-        termmatcher = terminology.TerminologyComparer()
-        assert termmatcher.similarity("The bug was submitted", "submit") > 75
-        assert termmatcher.similarity("The site is certified", "certify") > 75
-        
-    def test_space_mismatch(self):
-        """Tests that we can match with some spacing mismatch"""
-        termmatcher = terminology.TerminologyComparer()
-        assert termmatcher.similarity("%d minutes downtime", "down time") > 75
-
-    def test_hyphen_mismatch(self):
-        """Tests that we can match with some spacing mismatch"""
-        termmatcher = terminology.TerminologyComparer()
-        assert termmatcher.similarity("You can preorder", "pre-order") > 75
-        assert termmatcher.similarity("You can pre-order", "pre order") > 75
-        assert termmatcher.similarity("You can preorder", "pre order") > 75
-        assert termmatcher.similarity("You can pre order", "pre-order") > 75
-

Modified: translate-toolkit/branches/upstream/current/translate/services/tmserver.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/services/tmserver.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/services/tmserver.py (original)
+++ translate-toolkit/branches/upstream/current/translate/services/tmserver.py Fri Jul 24 16:25:46 2009
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2008 Zuza Software Foundation
+# Copyright 2008-2009 Zuza Software Foundation
 #
 # This file is part of translate.
 #
@@ -27,37 +27,40 @@
 import sys
 from optparse import OptionParser
 import simplejson as json
-from wsgiref import simple_server 
+from wsgiref import simple_server
 
 from translate.misc import selector
-from translate.search import match
 from translate.storage import factory
 from translate.storage import base
 from translate.storage import tmdb
 
 class TMServer(object):
+    """A RESTful JSON TM server."""
+
     class RequestHandler(simple_server.WSGIRequestHandler):
-        """custom request handler, disables some inefficient defaults"""
+        """Custom request handler, disables some inefficient defaults"""
+
         def address_string(self):
-            """disable client reverse dns lookup"""
+            """Disable client reverse dns lookup."""
             return  self.client_address[0]
 
         def log_message(self, format, *args):
-            """log requests using logging instead of printing to
-            stderror"""
+            """Log requests using logging instead of printing to
+            stderror."""
             logging.info("%s - - [%s] %s" %
                          (self.address_string(),
                           self.log_date_time_string(),
-                          format%args))
-        
-    """a RESTful JSON TM server"""
-    def __init__(self, tmdbfile, tmfiles, max_candidates=3, min_similarity=75, max_length=1000, prefix="", source_lang=None, target_lang=None):
+                          format % args))
+
+    def __init__(self, tmdbfile, tmfiles, max_candidates=3, min_similarity=75,
+            max_length=1000, prefix="", source_lang=None, target_lang=None):
 
         self.tmdb = tmdb.TMDB(tmdbfile, max_candidates, min_similarity, max_length)
 
         #load files into db
         if isinstance(tmfiles, list):
-            [self.tmdb.add_store(factory.getobject(tmfile), source_lang, target_lang) for tmfile in tmfiles]
+            [self.tmdb.add_store(factory.getobject(tmfile), source_lang, target_lang) \
+                    for tmfile in tmfiles]
         elif tmfiles:
             self.tmdb.add_store(factory.getobject(tmfiles), source_lang, target_lang)
 
@@ -79,15 +82,15 @@
     @selector.opliant
     def translate_unit(self, environ, start_response, uid, slang, tlang):
         start_response("200 OK", [('Content-type', 'text/plain')])
-        uid = unicode(urllib.unquote_plus(uid),"utf-8")
         candidates = self.tmdb.translate_unit(uid, slang, tlang)
+        logging.debug("candidates: %s", unicode(candidates))
         response =  json.dumps(candidates, indent=4)
         return [response]
 
     @selector.opliant
     def add_unit(self, environ, start_response, uid, slang, tlang):
         start_response("200 OK", [('Content-type', 'text/plain')])
-        uid = unicode(urllib.unquote_plus(uid),"utf-8")
+        uid = unicode(urllib.unquote_plus(uid), "utf-8")
         data = json.loads(environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])))
         unit = base.TranslationUnit(data['source'])
         unit.target = data['target']
@@ -97,7 +100,7 @@
     @selector.opliant
     def update_unit(self, environ, start_response, uid, slang, tlang):
         start_response("200 OK", [('Content-type', 'text/plain')])
-        uid = unicode(urllib.unquote_plus(uid),"utf-8")
+        uid = unicode(urllib.unquote_plus(uid), "utf-8")
         data = json.loads(environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])))
         unit = base.TranslationUnit(data['source'])
         unit.target = data['target']
@@ -108,7 +111,7 @@
     def forget_unit(self, environ, start_response, uid):
         #FIXME: implement me
         start_response("200 OK", [('Content-type', 'text/plain')])
-        uid = unicode(urllib.unquote_plus(uid),"utf-8")
+        uid = unicode(urllib.unquote_plus(uid), "utf-8")
 
         return [response]
 
@@ -116,7 +119,7 @@
     def get_store_stats(self, environ, start_response, sid):
         #FIXME: implement me
         start_response("200 OK", [('Content-type', 'text/plain')])
-        sid = unicode(urllib.unquote_plus(sid),"utf-8")
+        sid = unicode(urllib.unquote_plus(sid), "utf-8")
 
         return [response]
 
@@ -133,7 +136,7 @@
 
     @selector.opliant
     def add_store(self, environ, start_response, sid, slang, tlang):
-        """add unit from POST data to tmdb"""
+        """Add unit from POST data to tmdb."""
         start_response("200 OK", [('Content-type', 'text/plain')])
         units = json.loads(environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])))
         count = self.tmdb.add_list(units, slang, tlang)
@@ -144,7 +147,7 @@
     def forget_store(self, environ, start_response, sid):
         #FIXME: implement me
         start_response("200 OK", [('Content-type', 'text/plain')])
-        sid = unicode(urllib.unquote_plus(sid),"utf-8")
+        sid = unicode(urllib.unquote_plus(sid), "utf-8")
 
         return [response]
 
@@ -159,10 +162,16 @@
                       help="target language of translation files")
     parser.add_option("-s", "--import-source-lang", dest="source_lang",
                       help="source language of translation files")
-    parser.add_option("-b", "--bind", dest="bind",
-                      help="adress to bind server to")
-    parser.add_option("-p", "--port", dest="port", type="int",
-                      help="port to listen on")
+    parser.add_option("-b", "--bind", dest="bind", default="localhost",
+                      help="adress to bind server to (default: localhost)")
+    parser.add_option("-p", "--port", dest="port", type="int", default=8888,
+                      help="port to listen on (default: 8888)")
+    parser.add_option("--max-candidates", dest="max_candidates", type="int", default=3,
+                      help="Maximum number of candidates")
+    parser.add_option("--min-similarity", dest="min_similarity", type="int", default=75,
+                      help="minimum similarity")
+    parser.add_option("--max-length", dest="max_length", type="int", default=1000,
+                      help="Maxmimum string length")
     parser.add_option("--debug", action="store_true", dest="debug", default=False,
                       help="enable debugging features")
 
@@ -170,7 +179,7 @@
 
     #setup debugging
     format = '%(asctime)s %(levelname)s %(message)s'
-    level = options.debug and logging.DEBUG or logging.INFO
+    level = options.debug and logging.DEBUG or logging.WARNING
     if options.debug:
         format = '%(levelname)7s %(module)s.%(funcName)s:%(lineno)d: %(message)s'
         if sys.version_info[:2] < (2, 5):
@@ -184,8 +193,11 @@
 
     logging.basicConfig(level=level, format=format)
 
-    application = TMServer(options.tmdbfile, options.tmfiles, prefix="/tmserver", source_lang=options.source_lang, target_lang=options.target_lang)
-    httpd = simple_server.make_server(options.bind, options.port, application.rest, handler_class=TMServer.RequestHandler)
+    application = TMServer(options.tmdbfile, options.tmfiles, max_candidates=options.max_candidates,
+                           min_similarity=options.min_similarity, max_length=options.max_length,
+                           prefix="/tmserver", source_lang=options.source_lang, target_lang=options.target_lang)
+    httpd = simple_server.make_server(options.bind, options.port,
+            application.rest, handler_class=TMServer.RequestHandler)
     httpd.serve_forever()
 
 

Modified: translate-toolkit/branches/upstream/current/translate/storage/base.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/base.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/base.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/base.py Fri Jul 24 16:25:46 2009
@@ -1,28 +1,27 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2006-2008 Zuza Software Foundation
-# 
-# This file is part of translate.
 #
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2006-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """Base classes for storage interfaces.
 
 @organization: Zuza Software Foundation
- at copyright: 2006-2007 Zuza Software Foundation
+ at copyright: 2006-2009 Zuza Software Foundation
 @license: U{GPL <http://www.fsf.org/licensing/licenses/gpl.html>}
 """
 
@@ -32,7 +31,7 @@
     import pickle
 from exceptions import NotImplementedError
 import translate.i18n
-from translate.storage.placeables.base import Placeable, as_string
+from translate.storage.placeables import StringElem, general, parse as rich_parse
 from translate.misc.typecheck import accepts, Self, IsOneOf
 from translate.misc.multistring import multistring
 
@@ -45,7 +44,11 @@
     else:
         actualclass = method.im_class
     if actualclass != baseclass:
-        raise NotImplementedError("%s does not reimplement %s as required by %s" % (actualclass.__name__, method.__name__, baseclass.__name__))
+        raise NotImplementedError(
+            "%s does not reimplement %s as required by %s" % \
+            (actualclass.__name__, method.__name__, baseclass.__name__)
+        )
+
 
 class ParseError(Exception):
     def __init__(self, inner_exc):
@@ -54,9 +57,10 @@
     def __str__(self):
         return repr(self.inner_exc)
 
+
 class TranslationUnit(object):
     """Base class for translation units.
-    
+
     Our concept of a I{translation unit} is influenced heavily by XLIFF:
     U{http://www.oasis-open.org/committees/xliff/documents/xliff-specification.htm}
 
@@ -80,39 +84,102 @@
     @group Errors: *error*
     """
 
+    rich_parsers = []
+    """A list of functions to use for parsing a string into a rich string tree."""
+
     def __init__(self, source):
         """Constructs a TranslationUnit containing the given source string."""
-
+        self.notes = ""
         self._store = None
         self.source = source
-        self.target = None
-        self.notes = ""
+        self._target = None
+        self._rich_source = None
+        self._rich_target = None
 
     def __eq__(self, other):
         """Compares two TranslationUnits.
-        
+
         @type other: L{TranslationUnit}
         @param other: Another L{TranslationUnit}
         @rtype: Boolean
         @return: Returns True if the supplied TranslationUnit equals this unit.
-        
-        """
-
+        """
         return self.source == other.source and self.target == other.target
+
+    def rich_to_multistring(cls, elem_list):
+        """Convert a "rich" string tree to a C{multistring}.
+        >>> from translate.storage.placeables.interfaces import X
+        >>> rich = [StringElem(['foo', X(id='xxx', sub=[' ']), 'bar'])]
+        >>> TranslationUnit.rich_to_multistring(rich)
+        multistring(u'foo bar')
+        """
+        return multistring([unicode(elem) for elem in elem_list])
+    rich_to_multistring = classmethod(rich_to_multistring)
+
+    def multistring_to_rich(cls, mulstring):
+        """Convert a multistring to a list of "rich" string trees.
+        >>> target = multistring([u'foo', u'bar', u'baz'])
+        >>> TranslationUnit.multistring_to_rich(target)
+        [<StringElem([<StringElem([u'foo'])>])>,
+         <StringElem([<StringElem([u'bar'])>])>,
+         <StringElem([<StringElem([u'baz'])>])>]
+        """
+        if isinstance(mulstring, multistring):
+            return [rich_parse(s, cls.rich_parsers) for s in mulstring.strings]
+        return [rich_parse(mulstring, cls.rich_parsers)]
+
+    def setsource(self, source):
+        """Sets the source string to the given value."""
+        self._rich_source = None
+        self._source = source
+    source = property(lambda self: self._source, setsource)
 
     def settarget(self, target):
         """Sets the target string to the given value."""
-
-        self.target = target
+        self._rich_target = None
+        self._target = target
+    target = property(lambda self: self._target, settarget)
+
+    def _get_rich_source(self):
+        if self._rich_source is None:
+            self._rich_source = self.multistring_to_rich(self.source)
+        return self._rich_source
+    def _set_rich_source(self, value):
+        if not hasattr(value, '__iter__'):
+            raise ValueError('value must be iterable')
+        if len(value) < 1:
+            raise ValueError('value must have at least one element.')
+        if not isinstance(value[0], StringElem):
+            raise ValueError('value[0] must be of type StringElem.')
+        self._rich_source = list(value)
+        self.source = self.rich_to_multistring(value)
+    rich_source = property(_get_rich_source, _set_rich_source)
+    """ @see: rich_to_multistring
+        @see: multistring_to_rich"""
+
+    def _get_rich_target(self):
+        if self._rich_target is None:
+            self._rich_target = self.multistring_to_rich(self.target)
+        return self._rich_target
+    def _set_rich_target(self, value):
+        if not hasattr(value, '__iter__'):
+            raise ValueError('value must be iterable')
+        if len(value) < 1:
+            raise ValueError('value must have at least one element.')
+        if not isinstance(value[0], StringElem):
+            raise ValueError('value[0] must be of type StringElem.')
+        self._rich_target = list(value)
+        self.target = self.rich_to_multistring(value)
+    rich_target = property(_get_rich_target, _set_rich_target)
+    """ @see: rich_to_multistring
+        @see: multistring_to_rich"""
 
     def gettargetlen(self):
         """Returns the length of the target string.
-        
+
         @note: Plural forms might be combined.
         @rtype: Integer
-        
-        """
-
+        """
         length = len(self.target or "")
         strings = getattr(self.target, "strings", [])
         if strings:
@@ -132,31 +199,26 @@
 
     def getlocations(self):
         """A list of source code locations.
-        
+
         @note: Shouldn't be implemented if the format doesn't support it.
         @rtype: List
-        
-        """
-
+        """
         return []
-    
+
     def addlocation(self, location):
         """Add one location to the list of locations.
-        
+
         @note: Shouldn't be implemented if the format doesn't support it.
-        
         """
         pass
 
     def addlocations(self, location):
         """Add a location or a list of locations.
-        
+
         @note: Most classes shouldn't need to implement this,
                but should rather implement L{addlocation()}.
         @warning: This method might be removed in future.
-        
-        """
-
+        """
         if isinstance(location, list):
             for item in location:
                 self.addlocation(item)
@@ -166,19 +228,18 @@
     def getcontext(self):
         """Get the message context."""
         return ""
-    
+
     def getnotes(self, origin=None):
         """Returns all notes about this unit.
-        
+
         It will probably be freeform text or something reasonable that can be
         synthesised by the format.
         It should not include location comments (see L{getlocations()}).
-        
         """
         return getattr(self, "notes", "")
 
     def addnote(self, text, origin=None):
-        """Adds a note (comment). 
+        """Adds a note (comment).
 
         @type text: string
         @param text: Usually just a sentence or two.
@@ -187,7 +248,6 @@
                        Origin can be one of the following text strings:
                          - 'translator'
                          - 'developer', 'programmer', 'source code' (synonyms)
-
         """
         if getattr(self, "notes", None):
             self.notes += '\n'+text
@@ -196,49 +256,40 @@
 
     def removenotes(self):
         """Remove all the translator's notes."""
-
         self.notes = u''
 
     def adderror(self, errorname, errortext):
         """Adds an error message to this unit.
-        
-          @type errorname: string
-          @param errorname: A single word to id the error.
-          @type errortext: string
-          @param errortext: The text describing the error.
-        
-        """
-
+
+        @type errorname: string
+        @param errorname: A single word to id the error.
+        @type errortext: string
+        @param errortext: The text describing the error.
+        """
         pass
 
     def geterrors(self):
         """Get all error messages.
-        
+
         @rtype: Dictionary
-        
-        """
-
+        """
         return {}
 
     def markreviewneeded(self, needsreview=True, explanation=None):
         """Marks the unit to indicate whether it needs review.
-        
+
         @keyword needsreview: Defaults to True.
         @keyword explanation: Adds an optional explanation as a note.
-        
-        """
-
+        """
         pass
 
     def istranslated(self):
         """Indicates whether this unit is translated.
-        
+
         This should be used rather than deducing it from .target,
         to ensure that other classes can implement more functionality
         (as XLIFF does).
-        
-        """
-
+        """
         return bool(self.target) and not self.isfuzzy()
 
     def istranslatable(self):
@@ -251,7 +302,6 @@
 
     def isfuzzy(self):
         """Indicates whether this unit is fuzzy."""
-
         return False
 
     def markfuzzy(self, value=True):
@@ -260,27 +310,22 @@
 
     def isheader(self):
         """Indicates whether this unit is a header."""
-
         return False
 
     def isreview(self):
         """Indicates whether this unit needs review."""
         return False
 
-
     def isblank(self):
         """Used to see if this unit has no source or target string.
-        
+
         @note: This is probably used more to find translatable units,
         and we might want to move in that direction rather and get rid of this.
-        
-        """
-
+        """
         return not (self.source or self.target)
 
     def hasplural(self):
         """Tells whether or not this specific unit has plural strings."""
-
         #TODO: Reconsider
         return False
 
@@ -292,9 +337,8 @@
 
     def merge(self, otherunit, overwrite=False, comments=True):
         """Do basic format agnostic merging."""
-
         if self.target == "" or overwrite:
-            self.target = otherunit.target
+            self.rich_target = otherunit.rich_target
 
     def unit_iter(self):
         """Iterator that only returns this unit."""
@@ -305,63 +349,25 @@
         return [self]
 
     def buildfromunit(cls, unit):
-        """Build a native unit from a foreign unit, preserving as much  
+        """Build a native unit from a foreign unit, preserving as much
         information as possible."""
-
         if type(unit) == cls and hasattr(unit, "copy") and callable(unit.copy):
             return unit.copy()
         newunit = cls(unit.source)
         newunit.target = unit.target
         newunit.markfuzzy(unit.isfuzzy())
         locations = unit.getlocations()
-        if locations: 
+        if locations:
             newunit.addlocations(locations)
         notes = unit.getnotes()
-        if notes: 
+        if notes:
             newunit.addnote(notes)
         return newunit
     buildfromunit = classmethod(buildfromunit)
 
-    def _rich_to_multistring(cls, value):
-        """Convert a placeables representation to a multistring.
-        >>> rich_string = [['a', X('42'), 'b'], ['foo', G('7', ['bar'])]]
-        >>> TranslationUnit._rich_to_multistring(rich_string)
-        multistring('a*b', 'foobar')
-        """
-        return multistring([as_string(chunk_seq) for chunk_seq in value])
-    _rich_to_multistring = classmethod(_rich_to_multistring)
-
-    def _multistring_to_rich(cls, value):
-        """Convert a multistring or unicode to a placeables presentation.
-        >>> TranslationUnit._multistring_to_rich(multistring('a', 'b'))
-        [['a'], ['b']]
-        """
-        if isinstance(value, (unicode, str)):
-            return [[unicode(value)]]
-        else:
-            return [[string] for string in value.strings]
-    _multistring_to_rich = classmethod(_multistring_to_rich)
-
-    @accepts(Self(), [[IsOneOf(Placeable, unicode)]])
-    def _set_rich_source(self, value):
-        self.source = self._rich_to_multistring(value)
-
-    def _get_rich_source(self):
-        return self._multistring_to_rich(self.source)
-
-    rich_source = property(_get_rich_source, _set_rich_source)
-
-    @accepts(Self(), [[IsOneOf(Placeable, unicode)]])
-    def _set_rich_target(self, value):
-        self.target = self._rich_to_multistring(value)
-
-    def _get_rich_target(self):
-        return self._multistring_to_rich(self.target)
-
-    rich_target = property(_get_rich_target, _set_rich_target)
-
     xid = property(lambda self: None, lambda self, value: None)
     rid = property(lambda self: None, lambda self, value: None)
+
 
 class TranslationStore(object):
     """Base class for stores for multiple translation units of type UnitClass."""
@@ -376,10 +382,11 @@
     """A list of file extentions associated with this store type"""
     _binary = False
     """Indicates whether a file should be accessed as a binary file."""
+    suggestions_in_format = False
+    """Indicates if format can store suggestions and alternative translation for a unit"""
 
     def __init__(self, unitclass=None):
         """Constructs a blank TranslationStore."""
-
         self.units = []
         self.sourcelanguage = None
         self.targetlanguage = None
@@ -387,9 +394,17 @@
             self.UnitClass = unitclass
         super(TranslationStore, self).__init__()
 
+    def getsourcelanguage(self):
+        """Gets the target language for this store"""
+        return self.sourcelanguage
+
     def setsourcelanguage(self, sourcelanguage):
         """Sets the source language for this store"""
         self.sourcelanguage = sourcelanguage
+
+    def gettargetlanguage(self):
+        """Gets the target language for this store"""
+        return self.targetlanguage
 
     def settargetlanguage(self, targetlanguage):
         """Sets the target language for this store"""
@@ -406,78 +421,140 @@
 
     def addunit(self, unit):
         """Appends the given unit to the object's list of units.
-        
+
         This method should always be used rather than trying to modify the
         list manually.
 
         @type unit: L{TranslationUnit}
         @param unit: The unit that will be added.
-        
         """
         unit._store = self
         self.units.append(unit)
 
     def addsourceunit(self, source):
         """Adds and returns a new unit with the given source string.
-        
+
         @rtype: L{TranslationUnit}
-
-        """
-
+        """
         unit = self.UnitClass(source)
         self.addunit(unit)
         return unit
 
     def findunit(self, source):
         """Finds the unit with the given source string.
-        
+
         @rtype: L{TranslationUnit} or None
-
-        """
-
+        """
         if len(getattr(self, "sourceindex", [])):
             if source in self.sourceindex:
-                return self.sourceindex[source]
+                return self.sourceindex[source][0]
         else:
             for unit in self.units:
                 if unit.source == source:
                     return unit
         return None
 
+
+    def findunits(self, source):
+        """Finds the unit with the given source string.
+
+        @rtype: L{TranslationUnit} or None
+        """
+        if len(getattr(self, "sourceindex", [])):
+            if source in self.sourceindex:
+                return self.sourceindex[source]
+        else:
+            #FIXME: maybe we should generate index here instead since
+            #we'll scan all units anyway
+            result = []
+            for unit in self.units:
+                if unit.source == source:
+                    result.append(unit)
+            return result
+        return None
+
     def translate(self, source):
         """Returns the translated string for a given source string.
-        
+
         @rtype: String or None
-
-        """
-
+        """
         unit = self.findunit(source)
         if unit and unit.target:
             return unit.target
         else:
             return None
 
+    def remove_unit_from_index(self, unit):
+        """Remove a unit from source and locaton indexes"""
+        def remove_unit(source):
+            if source in self.sourceindex:
+                try:
+                    self.sourceindex[source].remove(unit)
+                    if len(self.sourceindex[source]) == 0:
+                        del(self.sourceindex[source])
+                except ValueError:
+                    pass
+
+        if unit.hasplural():
+            for source in unit.source.strings:
+                remove_unit(source)
+        else:
+            remove_unit(unit.source)
+
+        for location in unit.getlocations():
+            if location in self.locationindex and self.locationindex[location] is not None \
+                   and self.locationindex[location] == unit:
+                del(self.locationindex[location])
+                
+                                           
+    def add_unit_to_index(self, unit):
+        """Add a unit to source and location idexes"""
+        def insert_unit(source):
+            if not source in self.sourceindex:
+                self.sourceindex[source] = [unit]
+            else:
+                self.sourceindex[source].append(unit)
+                
+        if unit.hasplural():
+            for source in unit.source.strings:
+                insert_unit(source)
+        else:
+            insert_unit(unit.source)
+
+        for location in unit.getlocations():
+            if location in self.locationindex:
+                # if sources aren't unique, don't use them
+                #FIXME: maybe better store a list of units like sourceindex
+                self.locationindex[location] = None
+            else:
+                self.locationindex[location] = unit
+
     def makeindex(self):
         """Indexes the items in this store. At least .sourceindex should be usefull."""
-
         self.locationindex = {}
         self.sourceindex = {}
         for unit in self.units:
             # Do we need to test if unit.source exists?
-            self.sourceindex[unit.source] = unit
-            if unit.hasplural():
-                for nounform in unit.source.strings[1:]:
-                    self.sourceindex[nounform] = unit
-            for location in unit.getlocations():
-                if location in self.locationindex:
-                    # if sources aren't unique, don't use them
-                    self.locationindex[location] = None
-                else:
-                    self.locationindex[location] = unit
+            self.add_unit_to_index(unit)
+
+    def require_index(self):
+        """make sure source index exists"""
+        if not hasattr(self, "sourceindex"):
+            self.makeindex()
+
+            
+    def __getstate__(self):
+        odict = self.__dict__.copy()
+        odict['fileobj'] = None
+        return odict
+
+    def __setstate__(self, dict):
+        self.__dict__.update(dict)
+        if getattr(self, "filename", False):
+            self.fileobj=open(self.filename)
 
     def __str__(self):
         """Converts to a string representation that can be parsed back using L{parsestring()}."""
-
         # We can't pickle fileobj if it is there, so let's hide it for a while.
         fileobj = getattr(self, "fileobj", None)
         self.fileobj = None
@@ -487,16 +564,15 @@
 
     def isempty(self):
         """Returns True if the object doesn't contain any translation units."""
-
         if len(self.units) == 0:
             return True
         for unit in self.units:
-            if not (unit.isblank() or unit.isheader()):
+            if unit.istranslatable():
                 return False
         return True
 
     def _assignname(self):
-        """Tries to work out what the name of the filesystem file is and 
+        """Tries to work out what the name of the filesystem file is and
         assigns it to .filename."""
         fileobj = getattr(self, "fileobj", None)
         if fileobj:
@@ -549,7 +625,6 @@
 
     def parsefile(cls, storefile):
         """Reads the given file (or opens the given filename) and parses back to an object."""
-
         mode = 'r'
         if cls._binary:
             mode = 'rb'
@@ -567,4 +642,3 @@
         newstore._assignname()
         return newstore
     parsefile = classmethod(parsefile)
-

Modified: translate-toolkit/branches/upstream/current/translate/storage/cpo.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/cpo.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/cpo.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/cpo.py Fri Jul 24 16:25:46 2009
@@ -129,6 +129,8 @@
 gpo.po_message_prev_msgid.restype = STRING
 gpo.po_message_prev_msgid_plural.restype = STRING
 gpo.po_message_is_format.restype = c_int
+gpo.po_message_is_format.argtypes = [c_int, STRING]
+gpo.po_message_set_format.argtypes = [c_int, STRING, c_int]
 gpo.po_message_msgctxt.restype = STRING
 gpo.po_message_msgid.restype = STRING
 gpo.po_message_msgid_plural.restype = STRING
@@ -174,6 +176,8 @@
 
 class pounit(pocommon.pounit):
     def __init__(self, source=None, encoding='utf-8', gpo_message=None):
+        self._rich_source = None
+        self._rich_target = None
         self._encoding = encoding
         if not gpo_message:
             self._gpo_message = gpo.po_message_create()
@@ -182,12 +186,6 @@
             self.target = ""
         elif gpo_message:
             self._gpo_message = gpo_message
-
-    def setmsgidcomment(self, msgidcomment):
-        if msgidcomment:
-            newsource = "_: " + msgidcomment + "\n" + self.source
-            self.source = newsource
-    msgidcomment = property(None, setmsgidcomment)
 
     def setmsgid_plural(self, msgid_plural): 
         if isinstance(msgid_plural, list):
@@ -207,15 +205,15 @@
                     return u""
             else:
                 return text
-        singular = remove_msgid_comments(gpo.po_message_msgid(self._gpo_message))
+        singular = remove_msgid_comments(gpo.po_message_msgid(self._gpo_message).decode(self._encoding))
         if singular:
-            multi = multistring(singular, self._encoding)
             if self.hasplural():
-                pluralform = gpo.po_message_msgid_plural(self._gpo_message)
-                if isinstance(pluralform, str):
-                    pluralform = pluralform.decode(self._encoding)
+                multi = multistring(singular, self._encoding)
+                pluralform = gpo.po_message_msgid_plural(self._gpo_message).decode(self._encoding)
                 multi.strings.append(pluralform)
-            return multi
+                return multi
+            else:
+                return singular
         else:
             return u""
 
@@ -225,9 +223,9 @@
         if isinstance(source, unicode):
             source = source.encode(self._encoding)
         if isinstance(source, list):
-            gpo.po_message_set_msgid(self._gpo_message, str(source[0]))
+            gpo.po_message_set_msgid(self._gpo_message, source[0].encode(self._encoding))
             if len(source) > 1:
-                gpo.po_message_set_msgid_plural(self._gpo_message, str(source[1]))
+                gpo.po_message_set_msgid_plural(self._gpo_message, source[1].encode(self._encoding))
         else:
             gpo.po_message_set_msgid(self._gpo_message, source)
             gpo.po_message_set_msgid_plural(self._gpo_message, None)
@@ -240,7 +238,7 @@
             nplural = 0
             plural = gpo.po_message_msgstr_plural(self._gpo_message, nplural)
             while plural:
-                plurals.append(plural)
+                plurals.append(plural.decode(self._encoding))
                 nplural += 1
                 plural = gpo.po_message_msgstr_plural(self._gpo_message, nplural)
             if plurals:
@@ -248,7 +246,7 @@
             else:
                 multi = multistring(u"")
         else:
-            multi = multistring(gpo.po_message_msgstr(self._gpo_message) or u"", encoding=self._encoding)
+            multi = (gpo.po_message_msgstr(self._gpo_message) or "").decode(self._encoding)
         return multi
 
     def settarget(self, target):
@@ -380,7 +378,6 @@
 
         Overwrite non-blank self.msgstr only if overwrite is True
         merge comments only if comments is True
-        
         """
 
         if not isinstance(otherpo, pounit):
@@ -400,7 +397,7 @@
             if self._extract_msgidcomments(otherpo.target):
                 otherpo.target = otherpo.target.replace('_: ' + otherpo._extract_msgidcomments()+ '\n', '')
             self.target = otherpo.target
-            if self.source != otherpo.source:
+            if self.source != otherpo.source or self.getcontext() != otherpo.getcontext():
                 self.markfuzzy()
             else:
                 self.markfuzzy(otherpo.isfuzzy())
@@ -417,10 +414,13 @@
         return self.getid() == "" and len(self.target) > 0
 
     def isblank(self):
-        return len(self.source) == 0 and len(self.target) == 0
+        return len(self.source) == len(self.target) == len(self.getcontext()) == 0
 
     def hastypecomment(self, typecomment):
         return gpo.po_message_is_format(self._gpo_message, typecomment)
+
+    def settypecomment(self, typecomment, present=True):
+        gpo.po_message_set_format(self._gpo_message, typecomment, present)
 
     def hasmarkedcomment(self, commentmarker):
         commentmarker = "(%s)" % commentmarker
@@ -469,10 +469,14 @@
         if not text:
             text = gpo.po_message_msgid(self._gpo_message)
         if text:
-            msgidcomment = re.search("_: (.*)\n", text)
-            if msgidcomment:
-                return msgidcomment.group(1).decode(self._encoding)
+            return pocommon.extract_msgid_comment(text)
         return u""
+
+    def setmsgidcomment(self, msgidcomment):
+        if msgidcomment:
+            newsource = "_: " + msgidcomment + "\n" + self.source
+            self.source = newsource
+    msgidcomment = property(_extract_msgidcomments, setmsgidcomment)
 
     def __str__(self):
         pf = pofile()
@@ -507,11 +511,47 @@
 
     def getcontext(self):
         msgctxt = gpo.po_message_msgctxt(self._gpo_message)
-        msgidcomment = self._extract_msgidcomments()
         if msgctxt:
-            return msgctxt + msgidcomment
-        else:
+            return msgctxt.decode(self._encoding)
+        else:
+            msgidcomment = self._extract_msgidcomments()
             return msgidcomment
+
+    def buildfromunit(cls, unit):
+        """Build a native unit from a foreign unit, preserving as much
+        information as possible."""
+        if type(unit) == cls and hasattr(unit, "copy") and callable(unit.copy):
+            return unit.copy()
+        elif isinstance(unit, pocommon.pounit):
+            newunit = cls(unit.source)
+            newunit.target = unit.target
+            #context
+            newunit.msgidcomment = unit._extract_msgidcomments()
+            context = unit.getcontext()
+            if not newunit.msgidcomment and context:
+                gpo.po_message_set_msgctxt(newunit._gpo_message, context)
+
+            locations = unit.getlocations()
+            if locations:
+                newunit.addlocations(locations)
+            notes = unit.getnotes("developer")
+            if notes:
+                newunit.addnote(notes, "developer")
+            notes = unit.getnotes("translator")
+            if notes:
+                newunit.addnote(notes, "translator")
+            if unit.isobsolete():
+                newunit.makeobsolete()
+            newunit.markfuzzy(unit.isfuzzy())
+            for tc in ['python-format', 'c-format', 'php-format']:
+                if unit.hastypecomment(tc):
+                    newunit.settypecomment(tc)
+                    # We assume/guess/hope that there will only be one
+                    break
+            return newunit
+        else:
+            return base.buildfromunit(unit)
+    buildfromunit = classmethod(buildfromunit)
 
 class pofile(pocommon.pofile):
     UnitClass = pounit
@@ -534,51 +574,42 @@
 
     def removeduplicates(self, duplicatestyle="merge"):
         """make sure each msgid is unique ; merge comments etc from duplicates into original"""
-        msgiddict = {}
+        # TODO: can we handle consecutive calls to removeduplicates()? What
+        # about files already containing msgctxt? - test
+        id_dict = {}
         uniqueunits = []
-        # we sometimes need to keep track of what has been marked
-        # TODO: this is using a list as the pos aren't hashable, but this is slow...
+        # TODO: this is using a list as the pos aren't hashable, but this is slow.
+        # probably not used frequently enough to worry about it, though.
         markedpos = []
         def addcomment(thepo):
             thepo.msgidcomment = " ".join(thepo.getlocations())
             markedpos.append(thepo)
         for thepo in self.units:
-            if thepo.isheader():
+            id = thepo.getid()
+            if thepo.isheader() and not thepo.getlocations():
+                # header msgids shouldn't be merged...
                 uniqueunits.append(thepo)
-                continue
-            if duplicatestyle.startswith("msgid_comment"):
-                msgid = thepo._extract_msgidcomments() + thepo.source
-            else:
-                msgid = thepo.source
-            if duplicatestyle == "msgid_comment_all":
-                addcomment(thepo)
-                uniqueunits.append(thepo)
-            elif msgid in msgiddict:
+            elif id in id_dict:
                 if duplicatestyle == "merge":
-                    if msgid:
-                        msgiddict[msgid].merge(thepo)
+                    if id:
+                        id_dict[id].merge(thepo)
                     else:
                         addcomment(thepo)
                         uniqueunits.append(thepo)
-                elif duplicatestyle == "keep":
-                    uniqueunits.append(thepo)
-                elif duplicatestyle == "msgid_comment":
-                    origpo = msgiddict[msgid]
-                    if origpo not in markedpos:
-                        addcomment(origpo)
-                    addcomment(thepo)
-                    uniqueunits.append(thepo)
                 elif duplicatestyle == "msgctxt":
-                    origpo = msgiddict[msgid]
+                    origpo = id_dict[id]
                     if origpo not in markedpos:
                         gpo.po_message_set_msgctxt(origpo._gpo_message, " ".join(origpo.getlocations()))
                         markedpos.append(thepo)
                     gpo.po_message_set_msgctxt(thepo._gpo_message, " ".join(thepo.getlocations()))
                     uniqueunits.append(thepo)
             else:
-                if not msgid and duplicatestyle != "keep":
-                    addcomment(thepo)
-                msgiddict[msgid] = thepo
+                if not id:
+                    if duplicatestyle == "merge":
+                        addcomment(thepo)
+                    else:
+                        gpo.po_message_set_msgctxt(thepo._gpo_message, " ".join(thepo.getlocations()))
+                id_dict[id] = thepo
                 uniqueunits.append(thepo)
         new_gpo_memory_file = gpo.po_file_create()
         new_gpo_message_iterator = gpo.po_message_iterator(new_gpo_memory_file, None)
@@ -604,11 +635,13 @@
         outputstring = ""
         if self._gpo_memory_file:
             obsolete_workaround()
-            f = tempfile.NamedTemporaryFile(prefix='translate', suffix='.po')
-            self._gpo_memory_file = gpo.po_file_write_v2(self._gpo_memory_file, f.name, xerror_handler)
-            f.seek(0)
+            f, fname = tempfile.mkstemp(prefix='translate', suffix='.po')
+            os.close(f)
+            self._gpo_memory_file = gpo.po_file_write_v2(self._gpo_memory_file, fname, xerror_handler)
+            f = open(fname)
             outputstring = f.read()
             f.close()
+            os.remove(fname)
         return outputstring
 
     def isempty(self):

Modified: translate-toolkit/branches/upstream/current/translate/storage/csvl10n.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/csvl10n.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/csvl10n.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/csvl10n.py Fri Jul 24 16:25:46 2009
@@ -138,7 +138,7 @@
     """This class represents a .csv file with various lines. 
     The default format contains three columns: comments, source, target"""
     UnitClass = csvunit
-    Name = _("Comma Seperated Value")
+    Name = _("Comma Separated Value")
     Mimetypes  = ['text/comma-separated-values', 'text/csv']
     Extensions = ["csv"]
     def __init__(self, inputfile=None, fieldnames=None):

Modified: translate-toolkit/branches/upstream/current/translate/storage/ini.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/ini.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/ini.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/ini.py Fri Jul 24 16:25:46 2009
@@ -1,23 +1,22 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2007 Zuza Software Foundation
-# 
-# This file is part of translate.
 #
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2007,2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """Class that manages .ini files for translation
 
@@ -25,14 +24,14 @@
 
 # a comment
 ; a comment
-    
+
 [Section]
 a = a string
 b : a string
+"""
 
-"""
 from translate.storage import base
-from translate.misc.ini import INIConfig 
+from translate.misc.ini import INIConfig
 from StringIO import StringIO
 import re
 

Modified: translate-toolkit/branches/upstream/current/translate/storage/lisa.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/lisa.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/lisa.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/lisa.py Fri Jul 24 16:25:46 2009
@@ -1,42 +1,35 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2006-2007 Zuza Software Foundation
-# 
-# This file is part of translate.
-#
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2006-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """Parent class for LISA standards (TMX, TBX, XLIFF)"""
 
 import re
 
 from translate.storage import base
-from translate.storage.placeables import lisa
 from translate.lang import data
 try:
     from lxml import etree
+    from translate.misc.xml_helpers import *
 except ImportError, e:
     raise ImportError("lxml is not installed. It might be possible to continue without support for XML formats.")
 
-string_xpath = etree.XPath("string()")
-
-def getText(node):
-    """joins together the text from all the text nodes in the nodelist and their children"""
-    return unicode(string_xpath(node)) # specific to lxml.etree
 
 def _findAllMatches(text, re_obj):
     """generate match objects for all L{re_obj} matches in L{text}."""
@@ -48,6 +41,7 @@
         yield m
         start = m.end()
 
+#TODO: we can now do better with our proper placeables support
 placeholders = ['(%[diouxXeEfFgGcrs])', r'(\\+.?)', '(%[0-9]$lx)', '(%[0-9]\$[a-z])', '(<.+?>)']
 re_placeholders = [re.compile(ph) for ph in placeholders]
 def _getPhMatches(text):
@@ -60,35 +54,12 @@
     matches.sort(lambda a, b: cmp(a.start(), b.start()))
     return matches
 
-XML_NS = 'http://www.w3.org/XML/1998/namespace'
-
-def getXMLlang(node):
-    """Sets the xml:lang attribute on node"""
-    return node.get("{%s}lang" % XML_NS)
-
-def setXMLlang(node, lang):
-    """Sets the xml:lang attribute on node"""
-    node.set("{%s}lang" % XML_NS, lang)
-
-def setXMLspace(node, value):
-    """Sets the xml:space attribute on node"""
-    node.set("{%s}space" % XML_NS, value)
-
-def namespaced(namespace, name):
-    """Returns name in Clark notation within the given namespace.
-
-       For example namespaced("source") in an XLIFF document might return::
-           {urn:oasis:names:tc:xliff:document:1.1}source
-       This is needed throughout lxml.
+
+class LISAunit(base.TranslationUnit):
     """
-    if namespace:
-        return "{%s}%s" % (namespace, name)
-    else:
-        return name
-
-class LISAunit(base.TranslationUnit):
-    """A single unit in the file. 
-Provisional work is done to make several languages possible."""
+    A single unit in the file.  Provisional work is done to make several
+    languages possible.
+    """
 
     #The name of the root element of this unit type:(termEntry, tu, trans-unit)
     rootNode = ""
@@ -98,10 +69,16 @@
     textNode = ""
 
     namespace = None
+    _default_xml_space = "preserve"
+    """The default handling of spacing in the absense of an xml:space attribute.
+
+    This is mostly for correcting XLIFF behaviour."""
 
     def __init__(self, source, empty=False, **kwargs):
         """Constructs a unit containing the given source string"""
         if empty:
+            self._rich_source = None
+            self._rich_target = None
             return
         self.xmlelement = etree.Element(self.rootNode)
         #add descrip, note, etc.
@@ -109,13 +86,15 @@
 
     def __eq__(self, other):
         """Compares two units"""
+        if not isinstance(other, LISAunit):
+             return super(LISAunit, self).__eq__(other)
         languageNodes = self.getlanguageNodes()
         otherlanguageNodes = other.getlanguageNodes()
         if len(languageNodes) != len(otherlanguageNodes):
             return False
         for i in range(len(languageNodes)):
-            mytext = self.getNodeText(languageNodes[i])
-            othertext = other.getNodeText(otherlanguageNodes[i])
+            mytext = self.getNodeText(languageNodes[i], getXMLspace(self.xmlelement, self._default_xml_space))
+            othertext = other.getNodeText(otherlanguageNodes[i], getXMLspace(self.xmlelement, self._default_xml_space))
             if mytext != othertext:
                 #TODO:^ maybe we want to take children and notes into account
                 return False
@@ -136,31 +115,17 @@
             self.xmlelement[0] = dom_node
         else:
             self.xmlelement.append(dom_node)
-    
+
     def get_source_dom(self):
         return self.getlanguageNode(lang=None, index=0)
     source_dom = property(get_source_dom, set_source_dom)
 
-    def _ensure_singular(cls, value):
-        if value is not None and len(value) > 1:
-            raise Exception("XLIFF cannot handle plurals by default")
-    _ensure_singular = classmethod(_ensure_singular)
-
-    def set_rich_source(self, value, sourcelang='en'):
-        self._ensure_singular(value)
-        sourcelanguageNode = self.createlanguageNode(sourcelang, u'', "source")        
-        self.source_dom = lisa.insert_into_dom(sourcelanguageNode, value[0])
-
-    def get_rich_source(self):
-        return [lisa.extract_chunks(self.source_dom)]
-    rich_source = property(get_rich_source, set_rich_source)
-
     def setsource(self, text, sourcelang='en'):
         text = data.forceunicode(text)
         self.source_dom = self.createlanguageNode(sourcelang, text, "source")
 
     def getsource(self):
-        return self.getNodeText(self.source_dom)
+        return self.getNodeText(self.source_dom, getXMLspace(self.xmlelement, self._default_xml_space))
     source = property(getsource, setsource)
 
     def set_target_dom(self, dom_node, append=False):
@@ -180,20 +145,6 @@
         else:
             return self.getlanguageNode(lang=None, index=1)
     target_dom = property(get_target_dom)
-
-    def set_rich_target(self, value, lang='xx', append=False):
-        self._ensure_singular(value)
-        languageNode = None
-        if not value is None:
-            languageNode = self.createlanguageNode(lang, u'', "target")
-            lisa.insert_into_dom(languageNode, value[0])
-        self.set_target_dom(languageNode, append)
-
-    def get_rich_target(self, lang=None):
-        """retrieves the "target" text (second entry), or the entry in the 
-        specified language, if it exists"""
-        return [lisa.extract_chunks(self.get_target_dom(lang))]
-    rich_target = property(get_rich_target, set_rich_target)
 
     def settarget(self, text, lang='xx', append=False):
         #XXX: we really need the language - can't really be optional, and we
@@ -220,13 +171,13 @@
             self.set_target_dom(None, False)
 
     def gettarget(self, lang=None):
-        """retrieves the "target" text (second entry), or the entry in the 
+        """retrieves the "target" text (second entry), or the entry in the
         specified language, if it exists"""
-        return self.getNodeText(self.get_target_dom(lang))
+        return self.getNodeText(self.get_target_dom(lang), getXMLspace(self.xmlelement, self._default_xml_space))
     target = property(gettarget, settarget)
 
     def createlanguageNode(self, lang, text, purpose=None):
-        """Returns a xml Element setup with given parameters to represent a 
+        """Returns a xml Element setup with given parameters to represent a
         single language entry. Has to be overridden."""
         return None
 
@@ -279,7 +230,7 @@
                 return languageNodes[index]
         return None
 
-    def getNodeText(self, languageNode):
+    def getNodeText(self, languageNode, xml_space="preserve"):
         """Retrieves the term from the given languageNode"""
         if languageNode is None:
             return None
@@ -288,9 +239,9 @@
             if terms is None:
                 return None
             else:
-                return getText(terms.next())
-        else:
-            return getText(languageNode)
+                return getText(terms.next(), xml_space)
+        else:
+            return getText(languageNode, xml_space)
 
     def __str__(self):
         return etree.tostring(self.xmlelement, pretty_print=True, encoding='utf-8')
@@ -324,8 +275,6 @@
 
     def __init__(self, inputfile=None, sourcelanguage='en', targetlanguage=None, unitclass=None):
         super(LISAfile, self).__init__(unitclass=unitclass)
-        self.setsourcelanguage(sourcelanguage)
-        self.settargetlanguage(targetlanguage)
         if inputfile is not None:
             self.parse(inputfile)
             assert self.document.getroot().tag == self.namespaced(self.rootNode)
@@ -333,6 +282,8 @@
             # We strip out newlines to ensure that spaces in the skeleton doesn't
             # interfere with the the pretty printing of lxml
             self.parse(self.XMLskeleton.replace("\n", ""))
+            self.setsourcelanguage(sourcelanguage)
+            self.settargetlanguage(targetlanguage)
             self.addheader()
         self._encoding = "UTF-8"
 
@@ -380,7 +331,7 @@
             posrc = xml.read()
             xml = posrc
         if etree.LXML_VERSION > (2, 1, 0):
-            #Since version 2.1.0 we can pass the strip_cdata parameter to 
+            #Since version 2.1.0 we can pass the strip_cdata parameter to
             #indicate that we don't want cdata to be converted to raw XML
             parser = etree.XMLParser(strip_cdata=False)
         else:

Modified: translate-toolkit/branches/upstream/current/translate/storage/php.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/php.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/php.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/php.py Fri Jul 24 16:25:46 2009
@@ -1,28 +1,27 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
+#
 # Copyright 2004-2008 Zuza Software Foundation
-# 
-# This file is part of translate.
-#
-# translate is free software; you can redistribute it and/or modify
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-"""classes that hold units of PHP localisation files L{phpunit} or entire files
-   L{phpfile} these files are used in translating many PHP based applications.
-
-   Only PHP files written with these conventtions are supported::
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""Classes that hold units of PHP localisation files L{phpunit} or entire files
+   L{phpfile}. These files are used in translating many PHP based applications.
+
+   Only PHP files written with these conventions are supported::
       $lang['item'] = "vale";  # Array of values
       $some_entity = "value";  # Named variables
 
@@ -38,7 +37,6 @@
 """
 
 from translate.storage import base
-from translate.misc import quote
 import re
 
 def phpencode(text, quotechar="'"):
@@ -143,11 +141,11 @@
         self._comments = []
 
     def isblank(self):
-        """returns whether this is a blank element, containing only comments..."""
+        """Returns whether this is a blank element, containing only comments."""
         return not (self.name or self.value)
 
 class phpfile(base.TranslationStore):
-    """this class represents a php file, made up of phpunits"""
+    """This class represents a PHP file, made up of phpunits"""
     UnitClass = phpunit
     def __init__(self, inputfile=None, encoding='utf-8'):
         """construct a phpfile, optionally reading in from inputfile"""
@@ -160,7 +158,7 @@
             self.parse(phpsrc)
 
     def parse(self, phpsrc):
-        """read the source of a php file in and include them as units"""
+        """Read the source of a PHP file in and include them as units"""
         newunit = phpunit()
         lastvalue = ""
         value = ""
@@ -170,7 +168,7 @@
         valuequote = "" # either ' or "
         for line in phpsrc.decode(self._encoding).split("\n"):
             commentstartpos = line.find("/*")
-            commentendpos = line.rfind("*/")            
+            commentendpos = line.rfind("*/")
             if commentstartpos != -1:
                 incomment = True
                 if commentendpos != -1:
@@ -204,7 +202,7 @@
                 if not invalue and colonpos != len(value)-1:
                     commentinlinepos = value.find("//", colonpos)
                     if commentinlinepos != -1:
-                        newunit.addnote(value[commentinlinepos+2:].strip(), "developer") 
+                        newunit.addnote(value[commentinlinepos+2:].strip(), "developer")
                 if not invalue:
                     self.addunit(newunit)
                     value = ""
@@ -214,7 +212,7 @@
                 lastvalue = lastvalue + value + "\n"
 
     def __str__(self):
-        """convert the units back to lines"""
+        """Convert the units back to lines."""
         lines = []
         for unit in self.units:
             lines.append(str(unit))

Modified: translate-toolkit/branches/upstream/current/translate/storage/placeables/__init__.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/__init__.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/__init__.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/__init__.py Fri Jul 24 16:25:46 2009
@@ -1,26 +1,52 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2008 Zuza Software Foundation
-# 
-# This file is part of translate.
 #
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2008-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
-"""translate.storage.placeables is part of the translate package
-It contains classes that represent placeables (non-translatable inline 
-elements as native codes and variable markups)"""
+"""
+This module implements basic functionality to support placeables.
 
+A placeable is used to represent things like:
+1. Substitutions
+     For example, in ODF, footnotes appear in the ODF XML
+     where they are defined; so if we extract a paragraph with some
+     footnotes, the translator will have a lot of additional XML to with;
+     so we separate the footnotes out into separate translation units and
+     mark their positions in the original text with placeables.
+2. Hiding of inline formatting data
+     The translator doesn't want to have to deal with all the weird
+     formatting conventions of wherever the text came from.
+3. Marking variables
+     This is an old issue - translators translate variable names which
+     should remain untranslated. We can wrap placeables around variable
+     names to avoid this.
+
+The placeables model follows the XLIFF standard's list of placeables.
+Please refer to the XLIFF specification to get a better understanding.
+"""
+
+import base
+import interfaces
+import general
+import xliff
 from base import *
+from base import __all__ as all_your_base
+from strelem import StringElem
+from parse import parse
+
+__all__ = ['base', 'interfaces', 'general', 'parse', 'StringElem', 'xliff'] + all_your_base

Modified: translate-toolkit/branches/upstream/current/translate/storage/placeables/base.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/base.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/base.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/base.py Fri Jul 24 16:25:46 2009
@@ -1,132 +1,107 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2008 Zuza Software Foundation
-# 
-# This file is part of translate.
+# Copyright 2008-2009 Zuza Software Foundation
 #
-# translate is free software; you can redistribute it and/or modify
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
-"""This module implements basic functionality to support placeables.
-
-A placeable is used to represent things like:
-1. substitutions
-     for example, in ODF, footnotes appear in the ODF xml
-     where they are defined; so if we extract a paragraph with some
-     footnotes, the translator will have a lot of additional XML to with;
-     so we separate the footnotes out into separate translation units and
-     mark their positions in the original text with placeables.
-2. hiding of inline formatting data
-     the translator doesn't want to have to deal with all the weird
-     formatting conventions of wherever the text came from.
-3. marking variables
-     This is an old issue - translators translate variable names which
-     should remain untranslated. We can wrap placeables around variable
-     names to avoid this.
-
-The placeables model follows the XLIFF standard's list of placeables.
-Please refer to the XLIFF specification to get a better understanding.
+"""
+Contains base placeable classes with names based on XLIFF placeables. See the
+XLIFF standard for more information about what the names mean.
 """
 
-__all__ = ['Placeable', 'Bpt', 'Ept', 'X', 'Bx', 'Ex', 'G', 'It', 'Sub', 'Ph']
+from strelem import StringElem
+from interfaces import *
 
-def as_string(chunk_seq):
-    return u''.join([unicode(chunk) for chunk in chunk_seq])
-    
-class Placeable(object):
+
+__all__ = ['Bpt', 'Ept', 'Ph', 'It', 'G', 'Bx', 'Ex', 'X', 'Sub', 'to_base_placeables']
+
+
+# Basic placeable types.
+class Bpt(MaskingPlaceable, PairedDelimiter):
     has_content = True
-    
-    def __init__(self, id, content=None, xid=None, rid=None):
-        self.id      = id
-        self.xid     = xid
-        self.rid     = rid
-        self.content = content
 
-    def __unicode__(self):
-        if self.has_content:
-            return as_string(self.content)
-        else:
-            return u'\ufffc'
-        
-    def __repr__(self):
-        if self.has_content:
-            return u'<%(tagname)s id=%(id)s>%(content)s</%(tagname)s>' % \
-                {'tagname': self.__class__.__name__,
-                 'id':      self.id,
-                 'content': as_string(self.content)}
-        else:
-            return u'<%(tagname)s id=%(id)s />' % {'tagname': self.__class__.__name__, 
-                                                   'id': self.id }
-        
-    def __eq__(self, other):
-        return self.id        == other.id        and \
-               self.content   == other.content   and \
-               self.xid       == other.xid       and \
-               self.rid       == other.rid       and \
-               self.__class__ == other.__class__
-
-class Delimiter(object):
-    pass
-
-class PairedDelimiter(object):
-    pass
-
-class MaskingPlaceable(Placeable):
-    def __init__(self, id, content, masked_code):
-        raise NotImplementedError
-
-class Bpt(MaskingPlaceable, PairedDelimiter):
-    pass
 
 class Ept(MaskingPlaceable, PairedDelimiter):
-    pass
+    has_content = True
+
 
 class Ph(MaskingPlaceable):
-    pass
+    has_content = True
+    istranslatable = False
+
 
 class It(MaskingPlaceable, Delimiter):
-    pass
-        
-class ReplacementPlaceable(Placeable):
-    pass
+    has_content = True
+
 
 class G(ReplacementPlaceable):
-    pass
+    has_content = True
+
 
 class Bx(ReplacementPlaceable, PairedDelimiter):
     has_content = False
+    istranslatable = False
 
-    def __init__(self, id, xid = None):
-        ReplacementPlaceable.__init__(self, id, content = None, xid = xid)
+    def __init__(self, id=None, xid=None, **kwargs):
+        # kwargs is ignored
+        ReplacementPlaceable.__init__(self, id=id, xid=xid, **kwargs)
+
 
 class Ex(ReplacementPlaceable, PairedDelimiter):
     has_content = False
+    istranslatable = False
 
-    def __init__(self, id, xid = None):
-        ReplacementPlaceable.__init__(self, id, content = None, xid = xid)
+    def __init__(self, id=None, xid=None, **kwargs):
+        # kwargs is ignored
+        ReplacementPlaceable.__init__(self, id=id, xid=xid, **kwargs)
+
 
 class X(ReplacementPlaceable, Delimiter):
     has_content = False
+    iseditable = False
+    istranslatable = False
 
-    def __init__(self, id, xid = None):
-        ReplacementPlaceable.__init__(self, id, content = None, xid = xid)
+    def __init__(self, id=None, xid=None, **kwargs):
+        ReplacementPlaceable.__init__(self, id=id, xid=xid, **kwargs)
 
-class SubflowPlaceable(Placeable):
-    pass
 
 class Sub(SubflowPlaceable):
-    pass
+    has_content = True
 
+
+def to_base_placeables(tree):
+    if not isinstance(tree, StringElem):
+        return tree
+
+    base_class = [klass for klass in tree.__class__.__bases__ \
+                  if klass in [Bpt, Ept, Ph, It, G, Bx, Ex, X, Sub]]
+
+    if not base_class:
+        base_class = tree.__class__
+    else:
+        base_class = base_class[0]
+
+    newtree = base_class()
+    newtree.id = tree.id
+    newtree.rid = tree.rid
+    newtree.xid = tree.xid
+    newtree.sub = []
+
+    for subtree in tree.sub:
+        newtree.sub.append(to_base_placeables(subtree))
+
+    return newtree

Added: translate-toolkit/branches/upstream/current/translate/storage/placeables/general.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/general.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/general.py (added)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/general.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,329 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""
+Contains general placeable implementations. That is placeables that does not
+fit into any other sub-category.
+"""
+
+import re
+
+__all__ = ['AltAttrPlaceable', 'XMLEntityPlaceable', 'XMLTagPlaceable', 'parsers', 'to_general_placeables']
+
+from translate.storage.placeables.base import G, Ph, StringElem
+
+
+def regex_parse(cls, pstr):
+    """A parser method to extract placeables from a string based on a regular
+        expression. Use this function as the C{@parse()} method of a placeable
+        class."""
+    if cls.regex is None:
+        return None
+    matches = []
+    oldend = 0
+    for match in cls.regex.finditer(pstr):
+        start, end = match.start(), match.end()
+        if oldend != start:
+            matches.append(StringElem(pstr[oldend:start]))
+        matches.append(cls([pstr[start:end]]))
+        oldend = end
+    if oldend != len(pstr) and matches:
+        matches.append(StringElem(pstr[oldend:]))
+    return matches or None
+
+
+class AltAttrPlaceable(G):
+    """Placeable for the "alt=..." attributes inside XML tags."""
+
+    regex = re.compile(r'alt=".*?"')
+    parse = classmethod(regex_parse)
+
+
+class NewlinePlaceable(Ph):
+    """Matches new-lines."""
+
+    iseditable = False
+    istranslatable = False
+    regex = re.compile(r'\n')
+    parse = classmethod(regex_parse)
+
+
+class NumberPlaceable(Ph):
+    """Placeable for numbers."""
+
+    istranslatable = False
+    regex = re.compile(ur"[-+]?[0-9]+([\u00a0.,][0-9]+)*")
+    parse = classmethod(regex_parse)
+
+
+class QtFormattingPlaceable(Ph):
+    """Placeable representing a Qt string formatting variable.
+
+    Implemented following Qt documentation on
+    L{QString::arg<http://doc.trolltech.com/4.5/qstring.html#arg>} where
+    the placeables are refered to as 'place markers'
+
+    Notes::
+      - Place markers can be reordered
+      - Place markers may be repeated
+      - 'L' use a localised representation e.g. in a number
+      - %% some in the wild to escape real %, not documented (not in regex)
+    """
+    iseditable = False
+    istranslatable = False
+    regex = re.compile(r"""(?x)
+                       %                 # Start of a place marker
+                       L?                # The sequence is replaced with a localized representation (optional)
+                       [1-9]\d{0,1}      # Place marker numbers must be in the range 1 to 99.
+                       (?=([^\d]|$))     # Double check that we aren't matching %100+ (non consuming match)
+                       """)
+    parse = classmethod(regex_parse)
+
+
+class PythonFormattingPlaceable(Ph):
+    """Placeable representing a Python string formatting variable.
+
+    Implemented following Python documentation on
+    L{String Formatting Operations<http://docs.python.org/library/stdtypes.html#string-formatting-operations>}"""
+
+    iseditable = False
+    istranslatable = False
+    # Need to correctly define a python identifier.
+    regex = re.compile(r"""(?x)
+                       %                     # Start of formatting specifier
+                       (%|                   # No argument converted %% creates a %
+                       (\([a-z_]+\)){0,1}    # Mapping key value (optional)
+                       [\-\+0\s\#]{0,1}      # Conversion flags (optional)
+                       (\d+|\*){0,1}         # Minimum field width (optional)
+                       (\.(\d+|\*)){0,1}     # Precision (optional)
+                       [hlL]{0,1}            # Length modifier (optional)
+                       [diouxXeEfFgGcrs]{1}) # Conversion type""")
+    parse = classmethod(regex_parse)
+
+
+class JavaMessageFormatPlaceable(Ph):
+    """Placeable representing a Java MessageFormat formatting variable.
+
+    Implemented according to the Java U{MessageFormat 
+    documentation<http://java.sun.com/j2se/1.4.2/docs/api/java/text/MessageFormat.html>}.
+
+    Information about custom formats::
+      - number - U{DecimalFormat<http://java.sun.com/j2se/1.4.2/docs/api/java/text/DecimalFormat.html>}
+      - date/time - U{SimpleDateFormat<http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html>}
+      - choice - U{ChoiceFormat<http://java.sun.com/j2se/1.4.2/docs/api/java/text/ChoiceFormat.html>}
+    """
+
+    iseditable = False  # TODO: Technically incorrect as you need to change
+    istranslatable = False
+    # things in a choice entry
+    regex = re.compile(r"""(?x)
+      {                      # Start of MessageFormat
+      [0-9]+                 # Number, positive array reference
+      (,\s*                  # FormatType (optional) one of number,date,time,choice
+        (number(,\s*(integer|currency|percent|[-0#.,E;%\u2030\u00a4']+)?)?|  # number FormatStyle (optional)
+         (date|time)(,\s*(short|medium|long|full|.+?))?|                  # date/time FormatStyle (optional)
+         choice,([^{]+({.+})?)+)?                                      # choice with format, format required
+      )?                     # END: (optional) FormatType
+      }                      # END: MessageFormat""")
+    parse = classmethod(regex_parse)
+
+
+class FormattingPlaceable(Ph):
+    """Placeable representing string formatting variables."""
+
+    iseditable = False
+    istranslatable = False
+    regex = re.compile(r"%[\-\+0\s\#]{0,1}(\d+){0,1}(\.\d+){0,1}[hlI]{0,1}[cCdiouxXeEfgGnpsS]{1}")
+    parse = classmethod(regex_parse)
+
+
+class UrlPlaceable(Ph):
+    """Placeable handling URI."""
+
+    istranslatable = False
+    regex = re.compile(r"""
+    ((((news|nttp|file|https?|ftp|irc)://)       # has to start with a protocol
+    |((www|ftp)[-A-Za-z0-9]*\.))                 # or www... or ftp... hostname
+    ([-A-Za-z0-9]+(\.[-A-Za-z0-9]+)*)            # hostname
+    |(\d{1,3}(\.\d{1,3}){3,3}))                  # or IP address
+    (:[0-9]{1,5})?                               # optional port
+    (/[-A-Za-z0-9_\$\.\+\!\*\(\),;:@&=\?/~\#\%]*)?     # optional trailing path
+    (?=$|\s|([]'}>\),\"]))
+    """, re.VERBOSE)
+    parse = classmethod(regex_parse)
+
+
+class FilePlaceable(Ph):
+    """Placeable handling file locations."""
+
+    istranslatable = False
+    regex = re.compile(r"(~/|/|\./)([-A-Za-z0-9_\$\.\+\!\*\(\),;:@&=\?/~\#\%]|\\){3,}")
+    #TODO: Handle Windows drive letters. Some common Windows paths won't be
+    # handled correctly while note allowing spaces, such as
+    #     "C:\Documents and Settings"
+    #     "C:\Program Files"
+    parse = classmethod(regex_parse)
+
+
+class EmailPlaceable(Ph):
+    """Placeable handling emails."""
+
+    istranslatable = False
+    regex = re.compile(r"((mailto:)|)[A-Za-z0-9]+[-a-zA-Z0-9._%]*@(([-A-Za-z0-9]+)\.)+[a-zA-Z]{2,4}")
+    # TODO: What about internationalised domain names? ;-)
+    parse = classmethod(regex_parse)
+
+
+class PunctuationPlaceable(Ph):
+    """Placeable handling punctuation."""
+
+    iseditable = False
+    istranslatable = False
+    # FIXME this should really be a list created as being the inverse of what
+    # is available on the translators keyboard.  Or easily expanded by their
+    # configuration.
+    regex = re.compile(ur'[™℃℉©®£¥°±‘’‚‛“”„‟…—– ]+') #last space is NBSP
+    parse = classmethod(regex_parse)
+
+
+class XMLEntityPlaceable(Ph):
+    """Placeable handling XML entities (C{&xxxxx;}-style entities)."""
+
+    iseditable = False
+    istranslatable = False
+    regex = re.compile(r'''&(
+        ([a-zA-Z][a-zA-Z0-9\.-]*)            #named entity
+         |([#](\d{1,5}|x[a-fA-F0-9]{1,5})+)  #numeric entity
+        );''', re.VERBOSE)
+    parse = classmethod(regex_parse)
+
+
+class CapsPlaceable(Ph):
+    """Placeable handling long all-caps strings."""
+
+    iseditable = True
+    regex = re.compile(r'\b[A-Z][A-Z/\-:*0-9]{2,}\b')
+    parse = classmethod(regex_parse)
+
+
+class CamelCasePlaceable(Ph):
+    """Placeable handling camel case strings."""
+
+    iseditable = True
+    regex = re.compile(r'''(?x)
+            \b(
+               [a-z]+[A-Z]|         #Not that strict if we start with lower (iPod)
+               [A-Z]+[a-z]+[A-Z]|   #One capital at the start is not enough (OpenTran)
+               [A-Z]{2,}[a-z]       #Two capitals at the start is enough    (KBabel)
+            )[a-zA-Z0-9]*           #Let's allow any final lower/upper/digit
+            \b''')
+    parse = classmethod(regex_parse)
+
+
+class SpacesPlaceable(Ph):
+    """Placeable handling unusual spaces in strings."""
+
+    iseditable = True
+    istranslatable = False
+    regex = re.compile(r"""(?m)  #Multiline expression
+        [ ]{2,}|     #More than two consecutive
+        ^[ ]+|       #At start of a line
+        [ ]+$        #At end of line""", re.VERBOSE)
+
+    parse = classmethod(regex_parse)
+
+
+class XMLTagPlaceable(Ph):
+    """Placeable handling XML tags."""
+
+    iseditable = False
+    istranslatable = False
+    regex = re.compile(r'<(\w+)(\s(\w*=".*?")?)*>|</(\w+)>')
+    parse = classmethod(regex_parse)
+
+
+class OptionPlaceable(Ph):
+    """Placeble handling command line options e.g. --help"""
+
+    istranslatable = False
+    regex = re.compile(r'''(?x)
+                      \B(             # Empty string at the start of a non-word, ensures [space]-
+                        -[a-zA-Z]|    # Single letter options: -i, -I
+                        --[a-z\-]+    # Word options: --help
+                      )\b''')
+    #regex = re.compile(r'''(-[a-zA-Z]|--[-a-z]+)\b''')
+    parse = classmethod(regex_parse)
+
+
+def to_general_placeables(tree, classmap={
+        G:      (AltAttrPlaceable,),
+        Ph:     (
+            NumberPlaceable,
+            XMLEntityPlaceable,
+            XMLTagPlaceable,
+            UrlPlaceable,
+            FilePlaceable,
+            EmailPlaceable,
+            OptionPlaceable,
+            PunctuationPlaceable,
+                )
+        }):
+    if not isinstance(tree, StringElem):
+        return tree
+
+    newtree = None
+
+    for baseclass, gclasslist in classmap.items():
+        if isinstance(tree, baseclass):
+            gclass = [c for c in gclasslist if c.parse(unicode(tree))]
+            if gclass:
+                newtree = gclass[0]()
+
+    if newtree is None:
+        newtree = tree.__class__()
+
+    newtree.id = tree.id
+    newtree.rid = tree.rid
+    newtree.xid = tree.xid
+    newtree.sub = []
+
+    for subtree in tree.sub:
+        newtree.sub.append(to_general_placeables(subtree))
+
+    return newtree
+
+parsers = [
+    NewlinePlaceable.parse,
+    XMLTagPlaceable.parse,
+    AltAttrPlaceable.parse,
+    XMLEntityPlaceable.parse,
+    QtFormattingPlaceable.parse,
+    PythonFormattingPlaceable.parse,
+    JavaMessageFormatPlaceable.parse,
+    FormattingPlaceable.parse,
+    UrlPlaceable.parse,
+    FilePlaceable.parse,
+    EmailPlaceable.parse,
+    CapsPlaceable.parse,
+    CamelCasePlaceable.parse,
+    OptionPlaceable.parse,
+    PunctuationPlaceable.parse,
+    NumberPlaceable.parse,
+]

Added: translate-toolkit/branches/upstream/current/translate/storage/placeables/interfaces.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/interfaces.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/interfaces.py (added)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/interfaces.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,49 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""
+This file contains abstract (semantic) interfaces for placeable implementations.
+"""
+
+from strelem import StringElem
+
+
+class InvisiblePlaceable(StringElem):
+    parse = None
+
+
+class MaskingPlaceable(StringElem):
+    parse = None
+
+
+class ReplacementPlaceable(StringElem):
+    parse = None
+
+
+class SubflowPlaceable(StringElem):
+    parse = None
+
+
+class Delimiter(object):
+    pass
+
+
+class PairedDelimiter(object):
+    pass

Modified: translate-toolkit/branches/upstream/current/translate/storage/placeables/lisa.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/lisa.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/lisa.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/lisa.py Fri Jul 24 16:25:46 2009
@@ -1,125 +1,198 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2008 Zuza Software Foundation
-# 
-# This file is part of translate.
+# Copyright 2008-2009 Zuza Software Foundation
 #
-# translate is free software; you can redistribute it and/or modify
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 from lxml import etree
 
-from translate.storage.placeables import base
-import translate.storage.placeables.misc as placeables_misc
+from translate.misc.xml_helpers import *
+from translate.storage.placeables import base, xliff, StringElem
 from translate.storage.xml_extract import misc
 
-def make_empty_replacement_placeable(klass, node):
-    return klass(node.attrib[u'id'])
+__all__ = ['xml_to_strelem', 'strelem_to_xml']
+# Use the above functions as entry points into this module. The rest are used by these functions.
 
-def make_g_placeable(klass, node):
-    return klass(node.attrib[u'id'], extract_chunks(node))
 
-def not_yet_implemented(klass, node):
+def make_empty_replacement_placeable(klass, node, xml_space="preserve"):
+    try:
+        return klass(
+            id=node.attrib[u'id'],
+            rid=node.attrib.get('rid', None),
+            xid=node.attrib.get('xid', None),
+            xml_attrib=node.attrib
+        )
+    except KeyError:
+        pass
+    return klass()
+
+def make_g_placeable(klass, node, xml_space="default"):
+    return klass(
+        id=node.attrib[u'id'],
+        sub=xml_to_strelem(node, xml_space).sub,
+        xml_attrib=node.attrib
+    )
+
+def not_yet_implemented(klass, node, xml_space="preserve"):
     raise NotImplementedError
 
-_class_dictionary = { u'bpt': (base.Bpt, not_yet_implemented), 
-                      u'bx' : (base.Bx,  make_empty_replacement_placeable), 
-                      u'ept': (base.Ept, not_yet_implemented),
-                      u'ex' : (base.Ex,  make_empty_replacement_placeable),
-                      u'g'  : (base.G,   make_g_placeable), 
-                      u'it' : (base.It,  not_yet_implemented),
-                      u'ph' : (base.Ph,  not_yet_implemented), 
-                      u'sub': (base.Sub, not_yet_implemented),
-                      u'x'  : (base.X,   make_empty_replacement_placeable) }
+def make_unknown(klass, node, xml_space="preserve"):
+    assert klass is xliff.UnknownXML
 
-def make_placeable(node):
+    sub = xml_to_strelem(node, xml_space).sub
+    id =  node.get('id',  None)
+    rid = node.get('rid', None)
+    xid = node.get('xid', None)
+
+    return klass(sub=sub, id=id, rid=rid, xid=xid, xml_node=node)
+
+_class_dictionary = {
+    #u'bpt': (xliff.Bpt, not_yet_implemented),
+    u'bx' : (xliff.Bx,  make_empty_replacement_placeable),
+    #u'ept': (xliff.Ept, not_yet_implemented),
+    u'ex' : (xliff.Ex,  make_empty_replacement_placeable),
+    u'g'  : (xliff.G,   make_g_placeable),
+    #u'it' : (xliff.It,  not_yet_implemented),
+    #u'ph' : (xliff.Ph,  not_yet_implemented),
+    #u'sub': (xliff.Sub, not_yet_implemented),
+    u'x'  : (xliff.X,   make_empty_replacement_placeable)
+}
+
+def make_placeable(node, xml_space):
     _namespace, tag = misc.parse_tag(node.tag)
-    klass, maker = _class_dictionary[tag]
-    return maker(klass, node)
+    if tag in _class_dictionary:
+        klass, maker = _class_dictionary[tag]
+    else:
+        klass, maker = xliff.UnknownXML, make_unknown
+    return maker(klass, node, xml_space)
 
-def extract_chunks(dom_node):
-    result = []
+def as_unicode(string):
+    if isinstance(string, unicode):
+        return string
+    elif isinstance(string, StringElem):
+        return unicode(string)
+    else:
+        return unicode(string.decode('utf-8'))
+
+def xml_to_strelem(dom_node, xml_space="preserve"):
+    if dom_node is None:
+        return StringElem()
+    if isinstance(dom_node, basestring):
+        dom_node = etree.fromstring(dom_node)
+    normalize_xml_space(dom_node, xml_space, remove_start=True)
+    result = StringElem()
     if dom_node.text:
-        result.append(placeables_misc.as_unicode(dom_node.text))
+        result.sub.append(StringElem(unicode(dom_node.text)))
     for child_dom_node in dom_node:
-        result.append(make_placeable(child_dom_node))
+        result.sub.append(make_placeable(child_dom_node, xml_space))
         if child_dom_node.tail:
-            result.append(placeables_misc.as_unicode(child_dom_node.tail))
+            result.sub.append(StringElem(unicode(child_dom_node.tail)))
+    result.prune()
     return result
 
 # ==========================================================
 
 def placeable_as_dom_node(placeable, tagname):
     dom_node = etree.Element(tagname)
-    dom_node.attrib['id'] = placeable.id
+    if placeable.id is not None:
+        dom_node.attrib['id'] = placeable.id
     if placeable.xid is not None:
         dom_node.attrib['xid'] = placeable.xid
     if placeable.rid is not None:
         dom_node.attrib['rid'] = placeable.rid
+
+    if hasattr(placeable, 'xml_attrib'):
+        for attrib, value in placeable.xml_attrib.items():
+            dom_node.set(attrib, value)
+
     return dom_node
 
-_placeable_dictionary = { base.Bpt: lambda placeable: placeable_as_dom_node(placeable, 'bpt'), 
-                          base.Bx : lambda placeable: placeable_as_dom_node(placeable, 'bx'), 
-                          base.Ept: lambda placeable: placeable_as_dom_node(placeable, 'ept'),
-                          base.Ex : lambda placeable: placeable_as_dom_node(placeable, 'ex'),
-                          base.G  : lambda placeable: placeable_as_dom_node(placeable, 'g'), 
-                          base.It : lambda placeable: placeable_as_dom_node(placeable, 'it'),
-                          base.Ph : lambda placeable: placeable_as_dom_node(placeable, 'ph'), 
-                          base.Sub: lambda placeable: placeable_as_dom_node(placeable, 'sub'),
-                          base.X  : lambda placeable: placeable_as_dom_node(placeable, 'x') }
+def unknown_placeable_as_dom_node(placeable):
+    assert type(placeable) is xliff.UnknownXML
 
-class EOF: pass
+    from copy import copy
+    node = copy(placeable.xml_node)
+    for i in range(len(node)):
+        del node[0]
+    node.tail = None
+    node.text = None
 
-def end_with_eof(seq):
-    for item in seq:
-        yield item
-    while True:
-        yield EOF
+    return node
 
-def collect_text(text, next, itr):
-    text = placeables_misc.as_unicode(text)
-    if isinstance(next, (unicode, str)):
-        return collect_text(text + placeables_misc.as_unicode(next), itr.next(), itr)
+_placeable_dictionary = {
+    xliff.Bpt: lambda placeable: placeable_as_dom_node(placeable, 'bpt'),
+    xliff.Bx : lambda placeable: placeable_as_dom_node(placeable, 'bx'),
+    xliff.Ept: lambda placeable: placeable_as_dom_node(placeable, 'ept'),
+    xliff.Ex : lambda placeable: placeable_as_dom_node(placeable, 'ex'),
+    xliff.G  : lambda placeable: placeable_as_dom_node(placeable, 'g'),
+    xliff.It : lambda placeable: placeable_as_dom_node(placeable, 'it'),
+    xliff.Ph : lambda placeable: placeable_as_dom_node(placeable, 'ph'),
+    xliff.Sub: lambda placeable: placeable_as_dom_node(placeable, 'sub'),
+    xliff.X  : lambda placeable: placeable_as_dom_node(placeable, 'x'),
+    xliff.UnknownXML: unknown_placeable_as_dom_node,
+    base.Bpt:  lambda placeable: placeable_as_dom_node(placeable, 'bpt'),
+    base.Bx :  lambda placeable: placeable_as_dom_node(placeable, 'bx'),
+    base.Ept:  lambda placeable: placeable_as_dom_node(placeable, 'ept'),
+    base.Ex :  lambda placeable: placeable_as_dom_node(placeable, 'ex'),
+    base.G  :  lambda placeable: placeable_as_dom_node(placeable, 'g'),
+    base.It :  lambda placeable: placeable_as_dom_node(placeable, 'it'),
+    base.Ph :  lambda placeable: placeable_as_dom_node(placeable, 'ph'),
+    base.Sub:  lambda placeable: placeable_as_dom_node(placeable, 'sub'),
+    base.X  :  lambda placeable: placeable_as_dom_node(placeable, 'x')
+}
+
+def xml_append_string(node, string):
+    if not len(node):
+        if not node.text:
+            node.text = unicode(string)
+        else:
+            node.text += unicode(string)
     else:
-        return text, next
-    
-def get_placeable(result, next, itr):
-    if isinstance(next, base.Placeable):
-        return next, itr.next()
+        lastchild = node.getchildren()[-1]
+        if lastchild.tail is None:
+            lastchild.tail = ''
+        lastchild.tail += unicode(string)
+    return node
+
+def strelem_to_xml(parent_node, elem):
+    if isinstance(elem, (str, unicode)):
+        return xml_append_string(parent_node, elem)
+    if not isinstance(elem, StringElem):
+        return parent_node
+
+    if type(elem) is StringElem and elem.isleaf():
+        return xml_append_string(parent_node, elem)
+
+    if elem.__class__ in _placeable_dictionary:
+        node = _placeable_dictionary[elem.__class__](elem)
+        parent_node.append(node)
     else:
-        return result, next
+        node = parent_node
 
-def process_placeable(placeable, next, chunk_seq):
-    """Get all text appearing after """
-    text, next          = collect_text(u'', next, chunk_seq)
-    child_dom_node      = _placeable_dictionary[placeable.__class__](placeable)
-    child_dom_node.tail = text
-    if placeable.content is not None:
-        insert_into_dom(child_dom_node, placeable.content)
-    return child_dom_node, next
+    for sub in elem.sub:
+        strelem_to_xml(node, sub)
 
-def insert_into_dom(dom_node, chunk_seq):
-    """Enumerate the elements of chunk_seq, adding text and placeable
-    nodes to dom_node."""
-    
-    chunk_seq = end_with_eof(chunk_seq)
-    dom_node.text, next = collect_text(u'', chunk_seq.next(), chunk_seq)
-    while next != EOF:
-        placeable, next = get_placeable(None, next, chunk_seq)
-        if placeable is not None:
-            child_dom_node, next = process_placeable(placeable, next, chunk_seq)
-            dom_node.append(child_dom_node)
-    return dom_node
+    return parent_node
+
+
+def parse_xliff(pstr):
+    try:
+        return xml_to_strelem(etree.fromstring('<source>%s</source>' % (pstr)))
+    except Exception, exc:
+        raise
+        return None
+xliff.parsers = [parse_xliff]

Added: translate-toolkit/branches/upstream/current/translate/storage/placeables/parse.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/parse.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/parse.py (added)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/parse.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,85 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2008-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""
+Contains the C{parse} function that parses normal strings into StringElem-
+based "rich" string element trees.
+"""
+
+from translate.storage.placeables import base, StringElem
+
+def parse(tree, parse_funcs):
+    """Parse placeables from the given string or sub-tree by using the
+        parsing functions provided.
+
+        The output of this function is B{heavily} dependent on the order of the
+        parsing functions. This is because of the algorithm used.
+
+        An over-simplification of the algorithm: the leaves in the C{StringElem}
+        tree are expanded to the output of the first parsing function in
+        C{parse_funcs}. The next level of recursion is then started on the new
+        set of leaves with the used parsing function removed from
+        C{parse_funcs}.
+
+        @type  tree: unicode|StringElem
+        @param tree: The string or string element sub-tree to parse.
+        @type  parse_funcs: A list of parsing functions. It must take exactly
+            one argument (a C{unicode} string to parse) and return a list of
+            C{StringElem}s which, together, form the original string. If nothing
+            could be parsed, it should return C{None}."""
+    if isinstance(tree, unicode):
+        tree = StringElem(tree)
+    if not parse_funcs:
+        return tree
+
+    parse_func = parse_funcs[0]
+
+    for leaf in tree.flatten():
+        #FIXME: we might rather want to test for editability, but for now this
+        # works better
+        if not leaf.istranslatable:
+            continue
+
+        unileaf = unicode(leaf)
+        if not unileaf:
+            continue
+
+        subleaves = parse_func(unileaf)
+        if subleaves is not None:
+            if len(subleaves) == 1 and type(leaf) is type(subleaves[0]) and leaf == subleaves[0]:
+                pass
+            elif isinstance(leaf, unicode):
+                parent = tree.get_parent_elem(leaf)
+                if parent is not None:
+                    if len(parent.sub) == 1:
+                        parent.sub = subleaves
+                        leaf = parent
+                    else:
+                        leafindex = parent.sub.index(leaf)
+                        parent.sub[leafindex] = StringElem(subleaves)
+                        leaf = parent.sub[leafindex]
+            else:
+                leaf.sub = subleaves
+
+        parse(leaf, parse_funcs[1:])
+
+        if isinstance(leaf, StringElem):
+            leaf.prune()
+    return tree

Added: translate-toolkit/branches/upstream/current/translate/storage/placeables/strelem.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/strelem.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/strelem.py (added)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/strelem.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,824 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""
+Contains the base L{StringElem} class that represents a node in a parsed rich-
+string tree. It is the base class of all placeables.
+"""
+
+import logging
+import sys
+
+
+class ElementNotFoundError(ValueError):
+    pass
+
+
+class StringElem(object):
+    """
+    This class represents a sub-tree of a string parsed into a rich structure.
+    It is also the base class of all placeables.
+    """
+
+    renderer = None
+    """An optional function that returns the Unicode representation of the string."""
+    sub = []
+    """The sub-elements that make up this this string."""
+    has_content = True
+    """Whether this string can have sub-elements."""
+    iseditable = True
+    """Whether this string should be changable by the user. Not used at the moment."""
+    istranslatable = True
+    """Whether this string is translatable into other languages."""
+    isvisible = True
+    """Whether this string should be visible to the user. Not used at the moment."""
+
+    # INITIALIZERS #
+    def __init__(self, sub=None, id=None, rid=None, xid=None, **kwargs):
+        if sub is None:
+            sub = []
+        if isinstance(sub, (unicode, StringElem)):
+            sub = [sub]
+
+        for elem in sub:
+            if not isinstance(elem, (unicode, StringElem)):
+                raise ValueError(elem)
+
+        self.sub   = sub
+        self.id    = id
+        self.rid   = rid
+        self.xid   = xid
+
+        for key, value in kwargs.items():
+            if hasattr(self, key):
+                raise ValueError('attribute already exists: %s' % (key))
+            setattr(self, key, value)
+
+        self.prune()
+
+    # SPECIAL METHODS #
+    def __add__(self, rhs):
+        """Emulate the C{unicode} class."""
+        return unicode(self) + rhs
+
+    def __contains__(self, item):
+        """Emulate the C{unicode} class."""
+        return item in unicode(self)
+
+    def __eq__(self, rhs):
+        """@returns: C{True} if (and only if) all members as well as sub-trees
+            are equal. False otherwise."""
+        if not isinstance(rhs, StringElem):
+            return False
+
+        return  self.id             == rhs.id             and \
+                self.iseditable     == rhs.iseditable     and \
+                self.istranslatable == rhs.istranslatable and \
+                self.isvisible      == rhs.isvisible      and \
+                self.rid            == rhs.rid            and \
+                self.xid            == rhs.xid            and \
+                len(self.sub) == len(rhs.sub) and \
+                not [i for i in range(len(self.sub)) if self.sub[i] != rhs.sub[i]]
+
+    def __ge__(self, rhs):
+        """Emulate the C{unicode} class."""
+        return unicode(self) >= rhs
+
+    def __getitem__(self, i):
+        """Emulate the C{unicode} class."""
+        return unicode(self)[i]
+
+    def __getslice__(self, i, j):
+        """Emulate the C{unicode} class."""
+        return unicode(self)[i:j]
+
+    def __gt__(self, rhs):
+        """Emulate the C{unicode} class."""
+        return unicode(self) > rhs
+
+    def __iter__(self):
+        """Create an iterator of this element's sub-elements."""
+        for elem in self.sub:
+            yield elem
+
+    def __le__(self, rhs):
+        """Emulate the C{unicode} class."""
+        return unicode(self) <= rhs
+
+    def __len__(self):
+        """Emulate the C{unicode} class."""
+        return len(unicode(self))
+
+    def __lt__(self, rhs):
+        """Emulate the C{unicode} class."""
+        return unicode(self) < rhs
+
+    def __mul__(self, rhs):
+        """Emulate the C{unicode} class."""
+        return unicode(self) * rhs
+
+    def __ne__(self, rhs):
+        return not self.__eq__(rhs)
+
+    def __radd__(self, lhs):
+        """Emulate the C{unicode} class."""
+        return self + lhs
+
+    def __rmul__(self, lhs):
+        """Emulate the C{unicode} class."""
+        return self * lhs
+
+    def __repr__(self):
+        elemstr = ', '.join([repr(elem) for elem in self.sub])
+        return '<%(class)s(%(id)s%(rid)s%(xid)s[%(subs)s])>' % {
+            'class': self.__class__.__name__,
+            'id':  self.id  is not None and 'id="%s" '  % (self.id) or '',
+            'rid': self.rid is not None and 'rid="%s" ' % (self.rid) or '',
+            'xid': self.xid is not None and 'xid="%s" ' % (self.xid) or '',
+            'subs': elemstr
+        }
+
+    def __str__(self):
+        if not self.isvisible:
+            return ''
+        return ''.join([unicode(elem).encode('utf-8') for elem in self.sub])
+
+    def __unicode__(self):
+        if callable(self.renderer):
+            return self.renderer(self)
+        if not self.isvisible:
+            return u''
+        return u''.join([unicode(elem) for elem in self.sub])
+
+    # METHODS #
+    def apply_to_strings(self, f):
+        """Apply C{f} to all actual strings in the tree.
+            @param f: Must take one (str or unicode) argument and return a
+                string or unicode."""
+        for elem in self.flatten():
+            for i in range(len(elem.sub)):
+                if isinstance(elem.sub[i], basestring):
+                    elem.sub[i] = f(elem.sub[i])
+
+    def copy(self):
+        """Returns a copy of the sub-tree.
+            This should be overridden in sub-classes with more data.
+
+            NOTE: C{self.renderer} is B{not} copied."""
+        #logging.debug('Copying instance of class %s' % (self.__class__.__name__))
+        cp = self.__class__(id=self.id, xid=self.xid, rid=self.rid)
+        for sub in self.sub:
+            if isinstance(sub, StringElem):
+                cp.sub.append(sub.copy())
+            else:
+                cp.sub.append(sub.__class__(sub))
+        return cp
+
+    def delete_elem(self, elem):
+        if elem is self:
+            self.sub = []
+            return
+        parent = self.get_parent_elem(elem)
+        if parent is None:
+            raise ElementNotFoundError(repr(elem))
+        subidx = -1
+        for i in range(len(parent.sub)):
+            if parent.sub[i] is elem:
+                subidx = i
+                break
+        if subidx < 0:
+            raise ElementNotFoundError(repr(elem))
+        del parent.sub[subidx]
+
+    def delete_range(self, start_index, end_index):
+        """Delete the text in the range given by the string-indexes
+            C{start_index} and C{end_index}.
+            Partial nodes will only be removed if they are editable.
+            @returns: A C{StringElem} representing the removed sub-string as
+                well as the parent node from which it was deleted. C{None} is
+                returned for the parent value if the root was deleted."""
+        if start_index == end_index:
+            return StringElem(), self
+        if start_index > end_index:
+            raise IndexError('start_index > end_index: %d > %d' % (start_index, end_index))
+        if start_index < 0 or start_index > len(self):
+            raise IndexError('start_index: %d' % (start_index))
+        if end_index < 1 or end_index > len(self) + 1:
+            raise IndexError('end_index: %d' % (end_index))
+
+        start = self.get_index_data(start_index)
+        if isinstance(start['elem'], tuple):
+            # If {start} is "between" elements, we use the one on the "right"
+            start['elem']   = start['elem'][-1]
+            start['offset'] = start['offset'][-1]
+        end = self.get_index_data(end_index)
+        if isinstance(end['elem'], tuple):
+            # If {end} is "between" elements, we use the one on the "left"
+            end['elem']   = end['elem'][0]
+            end['offset'] = end['offset'][0]
+        assert start['elem'].isleaf() and end['elem'].isleaf()
+
+        #logging.debug('FROM %s TO %s' % (start, end))
+
+        # Ranges can be one of 3 types:
+        # 1) The entire string.
+        # 2) An entire element.
+        # 3) Restricted to a single element.
+        # 4) Spans multiple elements (start- and ending elements are not the same).
+
+        # Case 1: Entire string #
+        if start_index == 0 and end_index == len(self):
+            #logging.debug('Case 1: [%s]' % (unicode(self)))
+            removed = self.copy()
+            self.sub = []
+            return removed, None
+
+        # Case 2: An entire element #
+        if start['elem'] is end['elem'] and start['offset'] == 0 and end['offset'] == len(start['elem']):
+            ##### FOR DEBUGGING #####
+            #s = ''
+            #for e in self.flatten():
+            #    if e is start['elem']:
+            #        s += '[' + unicode(e) + ']'
+            #    else:
+            #        s += unicode(e)
+            #logging.debug('Case 2: %s' % (s))
+            #########################
+
+            if start['elem'] is self and self.__class__ is StringElem:
+                removed = self.copy()
+                self.sub = []
+                return removed, None
+            removed = list(start['elem'].sub)
+            parent = start['elem']
+            parent.sub = []
+            return removed, parent
+
+        # Case 3: Within a single element #
+        if start['elem'] is end['elem'] and start['elem'].iseditable:
+            ##### FOR DEBUGGING #####
+            #s = ''
+            #for e in self.flatten():
+            #    if e is start['elem']:
+            #        s += '%s[%s]%s' % (
+            #            e[:start['offset']],
+            #            e[start['offset']:end['offset']],
+            #            e[end['offset']:]
+            #        )
+            #    else:
+            #        s += unicode(e)
+            #logging.debug('Case 3: %s' % (s))
+            #########################
+
+            # XXX: This might not have the expected result if start['elem'] is a StringElem sub-class instance.
+            newstr = u''.join(start['elem'].sub)
+            removed = StringElem(newstr[start['offset']:end['offset']])
+            newstr = newstr[:start['offset']] + newstr[end['offset']:]
+            parent = self.get_parent_elem(start['elem'])
+            if parent is None and start['elem'] is self:
+                parent = self
+            start['elem'].sub = [newstr]
+            self.prune()
+            return removed, parent
+
+        # Case 4: Across multiple elements #
+        range_nodes = self.depth_first()
+        startidx = 0
+        endidx = -1
+        for i in range(len(range_nodes)):
+            if range_nodes[i] is start['elem']:
+                startidx = i
+            elif range_nodes[i] is end['elem']:
+                endidx = i
+                break
+        range_nodes = range_nodes[startidx:endidx+1]
+        #assert range_nodes[0] is start['elem'] and range_nodes[-1] is end['elem']
+
+        marked_nodes = [] # Contains nodes that have been marked for deletion (directly or inderectly (via parent)).
+        for node in range_nodes[1:-1]:
+            if node in marked_nodes:
+                continue
+            subtree = node.depth_first()
+            if end['elem'] not in subtree:
+                marked_nodes.extend(subtree) # "subtree" does not include "node"
+
+        ##### FOR DEBUGGING #####
+        #s = ''
+        #for e in self.flatten():
+        #    if e is start['elem']:
+        #        s += '%s[%s' % (e[:start['offset']], e[start['offset']:])
+        #    elif e is end['elem']:
+        #        s += '%s]%s' % (e[:end['offset']], e[end['offset']:])
+        #    else:
+        #        s += unicode(e)
+        #logging.debug('Case 4: %s' % (s))
+        #########################
+
+        removed = self.copy()
+
+        # Save offsets before we start changing the tree
+        start_offset = self.elem_offset(start['elem'])
+        end_offset = self.elem_offset(end['elem'])
+
+        for node in marked_nodes:
+            self.delete_elem(node)
+        self.prune()
+
+        if start_offset == start['index']:
+            self.delete_elem(start['elem'])
+        elif start['elem'].iseditable:
+            start['elem'].sub = [ u''.join(start['elem'].sub)[:start['offset']] ]
+
+        if end_offset + len(end['elem']) == end['index']:
+            self.delete_elem(end['elem'])
+        elif end['elem'].iseditable:
+            end['elem'].sub = [ u''.join(end['elem'].sub)[end['offset']:] ]
+
+        return removed, None
+
+    def depth_first(self, filter=None):
+        """Returns a list of the nodes in the tree in depth-first order."""
+        if filter is None or not callable(filter):
+            filter = lambda e: True
+        elems = []
+        if filter(self):
+            elems.append(self)
+
+        for sub in self.sub:
+            if not isinstance(sub, StringElem):
+                continue
+            if sub.isleaf() and filter(sub):
+                elems.append(sub)
+            else:
+                elems.extend(sub.depth_first())
+        return elems
+
+    def encode(self, encoding=sys.getdefaultencoding()):
+        """More C{unicode} class emulation."""
+        return unicode(self).encode(encoding)
+
+    def elem_offset(self, elem):
+        """Find the offset of C{elem} in the current tree.
+            This cannot be reliably used if C{self.renderer} is used and even
+            less so if the rendering function renders the string differently
+            upon different calls. In Virtaal the C{StringElemGUI.index()} method
+            is used as replacement for this one.
+            @returns: The string index where element C{e} starts, or -1 if C{e}
+                was not found."""
+        offset = 0
+        for e in self.iter_depth_first():
+            if e is elem:
+                return offset
+            if e.isleaf():
+                offset += len(e)
+
+        # If we can't find the same instance element, settle for one that looks like it
+        offset = 0
+        for e in self.iter_depth_first():
+            if e.isleaf():
+                leafoffset = 0
+                for s in e.sub:
+                    if unicode(s) == unicode(elem):
+                        return offset + leafoffset
+                    else:
+                        leafoffset += len(unicode(s))
+                offset += len(e)
+        return -1
+
+    def elem_at_offset(self, offset):
+        """Get the C{StringElem} in the tree that contains the string rendered
+            at the given offset."""
+        if offset < 0 or offset > len(self):
+            return None
+
+        length = 0
+        elem = None
+        for elem in self.flatten():
+            elem_len = len(elem)
+            if length <= offset < length+elem_len:
+                return elem
+            length += elem_len
+        return elem
+
+    def find(self, x):
+        """Find sub-string C{x} in this string tree and return the position
+            at which it starts."""
+        if isinstance(x, basestring):
+            return unicode(self).find(x)
+        if isinstance(x, StringElem):
+            return unicode(self).find(unicode(x))
+        return None
+
+    def find_elems_with(self, x):
+        """Find all elements in the current sub-tree containing C{x}."""
+        return [elem for elem in self.flatten() if x in unicode(elem)]
+
+    def flatten(self, filter=None):
+        """Flatten the tree by returning a depth-first search over the tree's leaves."""
+        if filter is None or not callable(filter):
+            filter = lambda e: True
+        return [elem for elem in self.iter_depth_first(lambda e: e.isleaf() and filter(e))]
+
+    def get_ancestor_where(self, child, criteria):
+        parent = self.get_parent_elem(child)
+        if parent is None or criteria(parent):
+            return parent
+        return self.get_ancestor_where(parent, criteria)
+
+    def get_index_data(self, index):
+        """Get info about the specified range in the tree.
+            @returns: A dictionary with the following items:
+                * I{elem}: The element in which C{index} resides.
+                * I{index}: Copy of the C{index} parameter
+                * I{offset}: The offset of C{index} into C{'elem'}."""
+        info = {
+            'elem':  self.elem_at_offset(index),
+            'index': index,
+        }
+        info['offset'] = info['index'] - self.elem_offset(info['elem'])
+
+        # Check if there "index" is actually between elements
+        leftelem = self.elem_at_offset(index - 1)
+        if leftelem is not None and leftelem is not info['elem']:
+            info['elem'] = (leftelem, info['elem'])
+            info['offset'] = (len(leftelem), 0)
+
+        return info
+
+    def get_parent_elem(self, child):
+        """Searches the current sub-tree for and returns the parent of the
+            C{child} element."""
+        for elem in self.iter_depth_first():
+            if not isinstance(elem, StringElem):
+                continue
+            for sub in elem.sub:
+                if sub is child:
+                    return elem
+        return None
+
+    def insert(self, offset, text):
+        """Insert the given text at the specified offset of this string-tree's
+            string (Unicode) representation."""
+        if offset < 0 or offset > len(self) + 1:
+            raise IndexError('Index out of range: %d' % (offset))
+        if isinstance(text, (str, unicode)):
+            text = StringElem(text)
+        if not isinstance(text, StringElem):
+            raise ValueError('text must be of type StringElem')
+
+        def checkleaf(elem, text):
+            if elem.isleaf() and type(text) is StringElem and text.isleaf():
+                return unicode(text)
+            return text
+
+        # There are 4 general cases (including specific cases) where text can be inserted:
+        # 1) At the beginning of the string (self)
+        # 1.1) self.sub[0] is editable
+        # 1.2) self.sub[0] is not editable
+        # 2) At the end of the string (self)
+        # 3) In the middle of a node
+        # 4) Between two nodes
+        # 4.1) Neither of the nodes are editable
+        # 4.2) Both nodes are editable
+        # 4.3) Node at offset-1 is editable, node at offset is not
+        # 4.4) Node at offset is editable, node at offset-1 is not
+
+        oelem = self.elem_at_offset(offset)
+
+        # Case 1 #
+        if offset == 0:
+            # 1.1 #
+            if oelem.iseditable:
+                #logging.debug('Case 1.1')
+                oelem.sub.insert(0, checkleaf(oelem, text))
+                oelem.prune()
+                return True
+            # 1.2 #
+            else:
+                #logging.debug('Case 1.2')
+                oparent = self.get_ancestor_where(oelem, lambda x: x.iseditable)
+                if oparent is not None:
+                    oparent.sub.insert(0, checkleaf(oparent, text))
+                    return True
+                else:
+                    self.sub.insert(0, checkleaf(self, text))
+                    return True
+            return False
+
+        # Case 2 #
+        if offset >= len(self):
+            #logging.debug('Case 2')
+            last = self.flatten()[-1]
+            parent = self.get_ancestor_where(last, lambda x: x.iseditable)
+            if parent is None:
+                parent = self
+            parent.sub.append(checkleaf(parent, text))
+            return True
+
+        before = self.elem_at_offset(offset-1)
+
+        # Case 3 #
+        if oelem is before:
+            if oelem.iseditable:
+                #logging.debug('Case 3')
+                eoffset = offset - self.elem_offset(oelem)
+                if oelem.isleaf():
+                    s = unicode(oelem) # Collapse all sibling strings into one
+                    head = s[:eoffset]
+                    tail = s[eoffset:]
+                    if type(text) is StringElem and text.isleaf():
+                        oelem.sub = [head + unicode(text) + tail]
+                    else:
+                        oelem.sub = [StringElem(head), text, StringElem(tail)]
+                    return True
+                else:
+                    return oelem.insert(eoffset, text)
+            return False
+
+        # And the only case left: Case 4 #
+        # 4.1 #
+        if not before.iseditable and not oelem.iseditable:
+            #logging.debug('Case 4.1')
+            # Neither are editable, so we add it as a sibling (to the right) of before
+            bparent = self.get_parent_elem(before)
+            # bparent cannot be a leaf (because it has before as a child), so we
+            # insert the text as StringElem(text)
+            bindex = bparent.sub.index(before)
+            bparent.sub.insert(bindex + 1, text)
+            return True
+
+        # 4.2 #
+        elif before.iseditable and oelem.iseditable:
+            #logging.debug('Case 4.2')
+            return before.insert(len(before)+1, text) # Reinterpret as a case 2
+
+        # 4.3 #
+        elif before.iseditable and not oelem.iseditable:
+            #logging.debug('Case 4.3')
+            return before.insert(len(before)+1, text) # Reinterpret as a case 2
+
+        # 4.4 #
+        elif not before.iseditable and oelem.iseditable:
+            #logging.debug('Case 4.4')
+            return oelem.insert(0, text) # Reinterpret as a case 1
+
+        return False
+
+    def insert_between(self, left, right, text):
+        """Insert the given text between the two parameter C{StringElem}s."""
+        if not isinstance(left, StringElem) and left is not None:
+            raise ValueError('"left" is not a StringElem or None')
+        if not isinstance(right, StringElem) and right is not None:
+            raise ValueError('"right" is not a StringElem or None')
+        if left is right:
+            if left.sub:
+                # This is an error because the cursor cannot be inside an element ("left is right"),
+                # if it has any other content. If an element has content, it will be at least directly
+                # left or directly right of the current cursor position.
+                raise ValueError('"left" and "right" refer to the same element and is not empty.')
+            if not left.iseditable:
+                return False
+        if isinstance(text, unicode):
+            text = StringElem(text)
+
+        if left is right:
+            #logging.debug('left%s.sub.append(%s)' % (repr(left), repr(text)))
+            left.sub.append(text)
+            return True
+        # XXX: The "in" keyword is *not* used below, because the "in" tests
+        # with __eq__ and not "is", as we do below. Testing for identity is
+        # intentional and required.
+
+        if left is None:
+            if self is right:
+                #logging.debug('self%s.sub.insert(0, %s)' % (repr(self), repr(text)))
+                self.sub.insert(0, text)
+                return True
+            parent = self.get_parent_elem(right)
+            if parent is not None:
+                #logging.debug('parent%s.sub.insert(0, %s)' % (repr(parent), repr(text)))
+                parent.sub.insert(0, text)
+                return True
+            return False
+
+        if right is None:
+            if self is left:
+                #logging.debug('self%s.sub.append(%s)' % (repr(self), repr(text)))
+                self.sub.append(text)
+                return True
+            parent = self.get_parent_elem(left)
+            if parent is not None:
+                #logging.debug('parent%s.sub.append(%s)' % (repr(parent), repr(text)))
+                parent.sub.append(text)
+                return True
+            return False
+
+        # The following two blocks handle the cases where one element
+        # "surrounds" another as its parent. In that way the parent would be
+        # "left" of its first child, like in the first case.
+        ischild = False
+        for sub in left.sub:
+            if right is sub:
+                ischild = True
+                break
+        if ischild:
+            #logging.debug('left%s.sub.insert(0, %s)' % (repr(left), repr(text)))
+            left.sub.insert(0, text)
+            return True
+
+        ischild = False
+        for sub in right.sub:
+            if left is sub:
+                ischild = True
+                break
+        if ischild:
+            #logging.debug('right%s.sub.append(%s)' % (repr(right), repr(text)))
+            right.sub.append(text)
+            return True
+
+        parent = self.get_parent_elem(left)
+        if parent.iseditable:
+            idx = 1
+            for child in parent.sub:
+                if child is left:
+                    break
+                idx += 1
+            #logging.debug('parent%s.sub.insert(%d, %s)' % (repr(parent), idx, repr(text)))
+            parent.sub.insert(idx, text)
+            return True
+
+        parent = self.get_parent_elem(right)
+        if parent.iseditable:
+            idx = 0
+            for child in parent.sub:
+                if child is right:
+                    break
+                idx += 1
+            #logging.debug('parent%s.sub.insert(%d, %s)' % (repr(parent), idx, repr(text)))
+            parent.sub.insert(0, text)
+            return True
+
+        logging.debug('Could not insert between %s and %s... odd.' % (repr(left), repr(right)))
+        return False
+
+    def isleaf(self):
+        """
+        Whether or not this instance is a leaf node in the C{StringElem} tree.
+
+        A node is a leaf node if it is a C{StringElem} (not a sub-class) and
+        contains only sub-elements of type C{str} or C{unicode}.
+
+        @rtype: bool
+        """
+        for e in self.sub:
+            if not isinstance(e, (str, unicode)):
+                return False
+        return True
+
+    def iter_depth_first(self, filter=None):
+        """Iterate through the nodes in the tree in dept-first order."""
+        if filter is None or not callable(filter):
+            filter = lambda e: True
+        if filter(self):
+            yield self
+        for sub in self.sub:
+            if not isinstance(sub, StringElem):
+                continue
+            if sub.isleaf() and filter(sub):
+                yield sub
+            else:
+                for node in sub.iter_depth_first():
+                    if filter(node):
+                        yield node
+
+    def map(self, f, filter=None):
+        """Apply C{f} to all nodes for which C{filter} returned C{True} (optional)."""
+        if filter is not None and not callable(filter):
+            raise ValueError('filter is not callable or None')
+        if filter is None:
+            filter = lambda e: True
+
+        for elem in self.depth_first():
+            if filter(elem):
+                f(elem)
+
+    @classmethod
+    def parse(cls, pstr):
+        """Parse an instance of this class from the start of the given string.
+            This method should be implemented by any sub-class that wants to
+            parseable by L{translate.storage.placeables.parse}.
+
+            @type  pstr: unicode
+            @param pstr: The string to parse into an instance of this class.
+            @returns: An instance of the current class, or C{None} if the
+                string not parseable by this class."""
+        return cls(pstr)
+
+    def print_tree(self, indent=0, verbose=False):
+        """Print the tree from the current instance's point in an indented
+            manner."""
+        indent_prefix = " " * indent * 2
+        out = (u"%s%s [%s]" % (indent_prefix, self.__class__.__name__, unicode(self))).encode('utf-8')
+        if verbose:
+            out += u' ' + repr(self)
+
+        print out
+
+        for elem in self.sub:
+            if isinstance(elem, StringElem):
+                elem.print_tree(indent+1, verbose=verbose)
+            else:
+                print (u'%s%s[%s]' % (indent_prefix, indent_prefix, elem)).encode('utf-8')
+
+    def prune(self):
+        """Remove unnecessary nodes to make the tree optimal."""
+        for elem in self.iter_depth_first():
+            if len(elem.sub) == 1:
+                child = elem.sub[0]
+                # Symbolically: X->StringElem(leaf) => X(leaf)
+                #   (where X is any sub-class of StringElem, but not StringElem)
+                if type(child) is StringElem and child.isleaf():
+                    elem.sub = child.sub
+
+                # Symbolically: StringElem->StringElem2->(leaves) => StringElem->(leaves)
+                if type(elem) is StringElem and type(child) is StringElem:
+                    elem.sub = child.sub
+
+                # Symbolically: StringElem->X(leaf) => X(leaf)
+                #   (where X is any sub-class of StringElem, but not StringElem)
+                if type(elem) is StringElem and isinstance(child, StringElem) and type(child) is not StringElem:
+                    parent = self.get_parent_elem(elem)
+                    if parent is not None:
+                        parent.sub[parent.sub.index(elem)] = child
+
+            if type(elem) is StringElem and elem.isleaf():
+                # Collapse all strings in this leaf into one string.
+                elem.sub = [u''.join(elem.sub)]
+
+            for i in reversed(range(len(elem.sub))):
+                # Remove empty strings or StringElem nodes
+                # (but not StringElem sub-class instances, because they might contain important (non-rendered) data.
+                if type(elem.sub[i]) in (StringElem, str, unicode) and len(elem.sub[i]) == 0:
+                    del elem.sub[i]
+                    continue
+
+                if type(elem.sub[i]) in (str, unicode) and not elem.isleaf():
+                    elem.sub[i] = StringElem(elem.sub[i])
+
+            # Merge sibling StringElem leaves
+            if not elem.isleaf():
+                changed = True
+                while changed:
+                    changed = False
+
+                    for i in range(len(elem.sub)-1):
+                        lsub = elem.sub[i]
+                        rsub = elem.sub[i+1]
+
+                        if type(lsub) is StringElem and type(rsub) is StringElem:
+                            lsub.sub.extend(rsub.sub)
+                            del elem.sub[i+1]
+                            changed = True
+                            break
+
+    # TODO: Write unit test for this method
+    def remove_type(self, ptype):
+        """Replace nodes with type C{ptype} with base C{StringElem}s, containing
+            the same sub-elements. This is only applicable to elements below the
+            element tree root node."""
+        for elem in self.iter_depth_first():
+            if type(elem) is ptype:
+                parent = self.get_parent_elem(elem)
+                pindex = parent.sub.index(elem)
+                parent.sub[pindex] = StringElem(
+                    sub=elem.sub,
+                    id=elem.id,
+                    xid=elem.xid,
+                    rid=elem.rid
+                )
+
+    def translate(self):
+        """Transform the sub-tree according to some class-specific needs.
+            This method should be either overridden in implementing sub-classes
+            or dynamically replaced by specific applications.
+
+            @returns: The transformed Unicode string representing the sub-tree.
+            """
+        return self.copy()

Added: translate-toolkit/branches/upstream/current/translate/storage/placeables/terminology.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/terminology.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/terminology.py (added)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/terminology.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,99 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""
+Contains the placeable that represents a terminology term.
+"""
+
+__all__ = ['TerminologyPlaceable', 'parsers']
+
+from translate.storage.placeables import base, StringElem
+
+
+class TerminologyPlaceable(base.Ph):
+    """Terminology distinguished from the rest of a string by being a placeable."""
+
+    matchers = []
+    """A list of matcher objects to use to identify terminology."""
+    translations = []
+    """The available translations for this placeable."""
+
+    def __init__(self, *args, **kwargs):
+        self.translations = []
+        super(TerminologyPlaceable, self).__init__(*args, **kwargs)
+
+    @classmethod
+    def parse(cls, pstr):
+        parts = []
+        matches = []
+        match_info = {}
+
+        for matcher in cls.matchers:
+            matches.extend(matcher.matches(pstr))
+            match_info.update(matcher.match_info)
+
+        lastend = 0
+        def sort_matches(x, y):
+            # This function will sort a list of matches according to the match's starting
+            # position, putting the one with the longer source text first, if two are the same.
+            c = cmp(match_info[x.source]['pos'], match_info[y.source]['pos'])
+            return c and c or cmp(len(y.source), len(x.source))
+        matches.sort(sort_matches)
+
+        for match in matches:
+            info = match_info[match.source]
+            if info['pos'] < lastend:
+                continue
+            end = info['pos'] + len(match.source)
+            if 'newtermlen' in info:
+                end = info['pos'] + info['newtermlen']
+
+            if lastend < info['pos']:
+                parts.append(StringElem(pstr[lastend:info['pos']]))
+
+            term_string = pstr[info['pos']:end]
+            term_placeable = cls([term_string])
+            parts.append(term_placeable)
+
+            # Get translations for the placeable
+            for m in matches:
+                m_info = match_info[m.source]
+                m_end = m_info['pos']
+                if 'newtermlen' in m_info:
+                    m_end += m_info['newtermlen']
+                else:
+                    m_end += len(m.source)
+                if info['pos'] == m_info['pos'] and end == m_end:
+                    term_placeable.translations.append(m.target)
+
+            # remove duplicates:
+            term_placeable.translations = list(set(term_placeable.translations))
+
+            lastend = end
+        if lastend != len(pstr):
+            parts.append(StringElem(pstr[lastend:]))
+
+        return parts or None
+
+    def translate(self):
+        return self.translations and self.translations[0] or super(TerminologyPlaceable, self).translate()
+
+
+parsers = [TerminologyPlaceable.parse]

Added: translate-toolkit/branches/upstream/current/translate/storage/placeables/test_base.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/test_base.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/test_base.py (added)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/test_base.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,168 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from translate.storage.placeables import base, general, parse, xliff, StringElem
+
+
+class TestStringElem:
+    ORIGSTR = u'Ģët <a href="http://www.example.com" alt="Ģët &brand;!">&brandLong;</a>'
+
+    def __init__(self):
+        self.elem = parse(self.ORIGSTR, general.parsers)
+
+    def test_parse(self):
+        assert unicode(self.elem) == self.ORIGSTR
+
+    def test_tree(self):
+        assert len(self.elem.sub) == 4
+        assert unicode(self.elem.sub[0]) == u'Ģët '
+        assert unicode(self.elem.sub[1]) == u'<a href="http://www.example.com" alt="Ģët &brand;!">'
+        assert unicode(self.elem.sub[2]) == u'&brandLong;'
+        assert unicode(self.elem.sub[3]) == u'</a>'
+
+        assert len(self.elem.sub[0].sub) == 1 and self.elem.sub[0].sub[0] == u'Ģët '
+        assert len(self.elem.sub[1].sub) == 3
+        assert len(self.elem.sub[2].sub) == 2 and unicode(self.elem.sub[2]) == u'&brandLong;'
+        assert len(self.elem.sub[3].sub) == 1 and self.elem.sub[3].sub[0] == u'</a>'
+
+        sub = self.elem.sub[1].sub # That's the "<a href... >" part
+        assert unicode(sub[0]) == u'<a href="http://www.example.com" '
+        assert unicode(sub[1]) == u'alt="Ģët &brand;!"'
+        assert unicode(sub[2]) == u'>'
+
+        sub = self.elem.sub[1].sub[1].sub # The 'alt="Ģët &brand;!"' part
+        assert len(sub) == 3
+        assert unicode(sub[0]) == u'alt="Ģët '
+        assert unicode(sub[1]) == u'&brand;'
+        assert unicode(sub[2]) == u'!"'
+
+    def test_add(self):
+        assert self.elem + ' ' == self.ORIGSTR + ' '
+        # ... and __radd__() ... doesn't work
+        #assert ' ' + self.elem == ' ' + self.ORIGSTR
+
+    def test_contains(self):
+        assert 'href' in self.elem
+        assert u'hrȩf' not in self.elem
+
+    def test_getitem(self):
+        assert self.elem[0] == u'Ä¢'
+        assert self.elem[2] == 't'
+
+    def test_getslice(self):
+        assert self.elem[0:3] == u'Ģët'
+
+    def test_iter(self):
+        for chunk in self.elem:
+            assert issubclass(chunk.__class__, StringElem)
+
+    def test_len(self):
+        assert len(self.elem) == len(self.ORIGSTR)
+
+    def test_mul(self):
+        assert self.elem * 2 == self.ORIGSTR * 2
+        # ... and __rmul__()
+        assert 2 * self.elem == 2 * self.ORIGSTR
+
+    def test_elem_offset(self):
+        assert self.elem.elem_offset(self.elem.sub[0]) == 0
+        assert self.elem.elem_offset(self.elem.sub[1].sub[0].sub[0]) == 4
+
+    def test_elem_at_offset(self):
+        assert self.elem.elem_at_offset(0) is self.elem.sub[0]
+        assert self.elem.elem_at_offset(self.elem.find('!')) is self.elem.sub[1].sub[1].sub[2]
+
+    def test_find(self):
+        assert self.elem.find('example') == 24
+        assert self.elem.find(u'example') == 24
+        searchelem = parse('&brand;', general.parsers)
+        assert self.elem.find(searchelem) == 46
+
+    def test_find_elems_with(self):
+        assert self.elem.find_elems_with(u'Ģët') == [ StringElem(u'Ģët '), StringElem(u'Ģët ') ]
+        assert len(self.elem.find_elems_with('a')) == 6
+
+    def test_flatten(self):
+        assert u''.join([unicode(i) for i in self.elem.flatten()]) == self.ORIGSTR
+
+    def test_insert(self):
+        # Test inserting at the beginning
+        elem = self.elem.copy()
+        elem.insert(0, 'xxx')
+        assert unicode(elem.sub[0]) == 'xxx' + unicode(self.elem.sub[0])
+
+        # Test inserting at the end
+        elem = self.elem.copy()
+        elem.insert(len(elem) + 1, 'xxx')
+        assert elem.flatten()[-1] == StringElem('xxx')
+
+        # Test inserting in the middle of an existing string
+        elem = self.elem.copy()
+        elem.insert(2, 'xxx')
+        assert unicode(elem.sub[0]) == u'Ģëxxxt '
+
+        # Test inserting between elements
+        elem = self.elem.copy()
+        elem.insert(56, 'xxx')
+        assert unicode(elem)[56:59] == u'xxx'
+
+    def test_isleaf(self):
+        assert self.elem.sub[0].isleaf()
+        assert not self.elem.sub[1].isleaf()
+
+
+class TestConverters:
+    def __init__(self):
+        self.elem = parse(TestStringElem.ORIGSTR, general.parsers)
+
+    def test_to_base_placeables(self):
+        basetree = base.to_base_placeables(self.elem)
+        # The following asserts say that, even though tree and newtree represent the same string
+        # (the unicode() results are the same), they are composed of different classes (and so
+        # their repr()s are different
+        assert unicode(self.elem) == unicode(basetree)
+        assert repr(self.elem) != repr(basetree)
+
+    def test_to_general_placeables(self):
+        basetree = base.to_base_placeables(self.elem)
+        gentree = general.to_general_placeables(basetree)
+        assert gentree == self.elem
+
+    def test_to_xliff_placeables(self):
+        basetree = base.to_base_placeables(self.elem)
+        xliff_from_base = xliff.to_xliff_placeables(basetree)
+        assert unicode(xliff_from_base) != unicode(self.elem)
+        assert repr(xliff_from_base) != repr(self.elem)
+
+        xliff_from_gen = xliff.to_xliff_placeables(self.elem)
+        assert unicode(xliff_from_gen) != unicode(self.elem)
+        assert repr(xliff_from_gen) != repr(self.elem)
+
+        assert unicode(xliff_from_base) == unicode(xliff_from_gen)
+        assert repr(xliff_from_base) == repr(xliff_from_gen)
+
+
+if __name__ == '__main__':
+    for test in [TestStringElem(), TestConverters()]:
+        for method in dir(test):
+            if method.startswith('test_') and callable(getattr(test, method)):
+                getattr(test, method)()
+
+    test.elem.print_tree()

Added: translate-toolkit/branches/upstream/current/translate/storage/placeables/test_general.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/test_general.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/test_general.py (added)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/test_general.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,52 @@
+# -*- coding: utf-8 -*-
+
+from translate.storage.placeables import general
+
+def test_placeable_numbers():
+    """Check the correct functioning of number placeables"""
+    assert general.NumberPlaceable([u"25"]) in general.NumberPlaceable.parse(u"Here is a 25 number")
+    assert general.NumberPlaceable([u"-25"]) in general.NumberPlaceable.parse(u"Here is a -25 number")
+    assert general.NumberPlaceable([u"+25"]) in general.NumberPlaceable.parse(u"Here is a +25 number")
+    assert general.NumberPlaceable([u"25.00"]) in general.NumberPlaceable.parse(u"Here is a 25.00 number")
+    assert general.NumberPlaceable([u"2,500.00"]) in general.NumberPlaceable.parse(u"Here is a 2,500.00 number")
+    assert general.NumberPlaceable([u"1\u00a0000,99"]) in general.NumberPlaceable.parse(u"Here is a 1\u00a0000,99 number")
+
+def test_placeable_newline():
+    assert general.NewlinePlaceable.parse(u"A newline\n")[1] == general.NewlinePlaceable([u"\n"])
+    assert general.NewlinePlaceable.parse(u"First\nSecond")[1] == general.NewlinePlaceable([u"\n"])
+
+def test_placeable_alt_attr():
+    assert general.AltAttrPlaceable.parse(u'Click on the <img src="image.jpg" alt="Image">')[1] == general.AltAttrPlaceable([u'alt="Image"'])
+
+def test_placeable_qt_formatting():
+    assert general.QtFormattingPlaceable.parse(u'One %1 %99 %L1 are all valid')[1] == general.QtFormattingPlaceable([u'%1'])
+    assert general.QtFormattingPlaceable.parse(u'One %1 %99 %L1 are all valid')[3] == general.QtFormattingPlaceable([u'%99'])
+    assert general.QtFormattingPlaceable.parse(u'One %1 %99 %L1 are all valid')[5] == general.QtFormattingPlaceable([u'%L1'])
+
+def test_placeable_camelcase():
+    assert general.CamelCasePlaceable.parse(u'CamelCase')[0] == general.CamelCasePlaceable([u'CamelCase'])
+    assert general.CamelCasePlaceable.parse(u'iPod')[0] == general.CamelCasePlaceable([u'iPod'])
+    assert general.CamelCasePlaceable.parse(u'DokuWiki')[0] == general.CamelCasePlaceable([u'DokuWiki'])
+    assert general.CamelCasePlaceable.parse(u'KBabel')[0] == general.CamelCasePlaceable([u'KBabel'])
+    assert general.CamelCasePlaceable.parse(u'_Bug') is None
+    assert general.CamelCasePlaceable.parse(u'NOTCAMEL') is None
+
+def test_placeable_space():
+    assert general.SpacesPlaceable.parse(u' Space at start')[0] == general.SpacesPlaceable([u' '])
+    assert general.SpacesPlaceable.parse(u'Space at end ')[1] == general.SpacesPlaceable([u' '])
+    assert general.SpacesPlaceable.parse(u'Double  space')[1] == general.SpacesPlaceable([u'  '])
+
+def test_placeable_punctuation():
+    assert general.PunctuationPlaceable.parse(u'These, are not. Special: punctuation; marks! Or are "they"?') is None
+    assert general.PunctuationPlaceable.parse(u'Downloading…')[1] == general.PunctuationPlaceable([u'…'])
+
+def test_placeable_xml_entity():
+    assert general.XMLEntityPlaceable.parse(u'&brandShortName;')[0] == general.XMLEntityPlaceable([u'&brandShortName;'])
+    assert general.XMLEntityPlaceable.parse(u'Ӓ')[0] == general.XMLEntityPlaceable([u'Ӓ'])
+    assert general.XMLEntityPlaceable.parse(u'&xDEAD;')[0] == general.XMLEntityPlaceable([u'&xDEAD;'])
+
+def test_placeable_option():
+    assert general.OptionPlaceable.parse(u'Type --help for this help')[1] == general.OptionPlaceable([u'--help'])
+    assert general.OptionPlaceable.parse(u'Short -S ones also')[1] == general.OptionPlaceable([u'-S'])
+
+# TODO: PythonFormattingPlaceable, JavaMessageFormatPlaceable, FormattingPlaceable (printf), UrlPlaceable, FilePlaceable, EmailPlaceable, CapsPlaceable, XMLTagPlaceable

Modified: translate-toolkit/branches/upstream/current/translate/storage/placeables/test_lisa.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/test_lisa.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/test_lisa.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/test_lisa.py Fri Jul 24 16:25:46 2009
@@ -2,14 +2,14 @@
 # -*- coding: utf-8 -*-
 #
 # Copyright 2006-2007 Zuza Software Foundation
-# 
+#
 # This file is part of translate.
 #
 # translate is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
+#
 # translate is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -21,54 +21,107 @@
 #
 
 from lxml import etree
-from translate.storage.placeables import lisa
-from translate.storage.placeables import X, Bx, Ex, G, Bpt, Ept, Ph, It, Sub
+from translate.storage.placeables import lisa, StringElem
+from translate.storage.placeables.xliff import Bx, Ex, G, UnknownXML, X
 
-def test_extract_chunks():
+def test_xml_to_strelem():
     source = etree.fromstring(u'<source>a<x id="foo[1]/bar[1]/baz[1]"/></source>')
-    chunks = lisa.extract_chunks(source)
-    assert chunks == [u'a', X(u'foo[1]/bar[1]/baz[1]')]
+    elem = lisa.xml_to_strelem(source)
+    assert elem.sub == [ StringElem(u'a'), X(id=u'foo[1]/bar[1]/baz[1]') ]
 
     source = etree.fromstring(u'<source>a<x id="foo[1]/bar[1]/baz[1]"/>é</source>')
-    chunks = lisa.extract_chunks(source)
-    assert chunks == [u'a', X(u'foo[1]/bar[1]/baz[1]'), u'é']
+    elem = lisa.xml_to_strelem(source)
+    assert elem.sub == [ StringElem(u'a'), X(id=u'foo[1]/bar[1]/baz[1]'), StringElem(u'é') ]
 
     source = etree.fromstring(u'<source>a<g id="foo[2]/bar[2]/baz[2]">b<x id="foo[1]/bar[1]/baz[1]"/>c</g>é</source>')
-    chunks = lisa.extract_chunks(source)
-    assert chunks == [u'a', G(u'foo[2]/bar[2]/baz[2]', [u'b', X(id = u'foo[1]/bar[1]/baz[1]'), u'c']), u'é']
+    elem = lisa.xml_to_strelem(source)
+    assert elem.sub == [ StringElem(u'a'), G(id=u'foo[2]/bar[2]/baz[2]', sub=[StringElem(u'b'), X(id=u'foo[1]/bar[1]/baz[1]'), StringElem(u'c')]), StringElem(u'é') ]
+
+def test_xml_space():
+    source = etree.fromstring(u'<source xml:space="default"> a <x id="foo[1]/bar[1]/baz[1]"/> </source>')
+    elem = lisa.xml_to_strelem(source)
+    print elem.sub
+    assert elem.sub == [ StringElem(u'a '), X(id=u'foo[1]/bar[1]/baz[1]'), StringElem(u' ')]
 
 def test_chunk_list():
-    left  = ['a', G('foo[2]/bar[2]/baz[2]', ['b', X(id = 'foo[1]/bar[1]/baz[1]'), 'c']), 'é']
-    right = ['a', G('foo[2]/bar[2]/baz[2]', ['b', X(id = 'foo[1]/bar[1]/baz[1]'), 'c']), 'é']
+    left  = StringElem([u'a', G(id='foo[2]/bar[2]/baz[2]', sub=[u'b', X(id='foo[1]/bar[1]/baz[1]'), u'c']), u'é'])
+    right = StringElem([u'a', G(id='foo[2]/bar[2]/baz[2]', sub=[u'b', X(id='foo[1]/bar[1]/baz[1]'), u'c']), u'é'])
     assert left == right
 
-def test_set_insert_into_dom():
+def test_set_strelem_to_xml():
     source = etree.Element(u'source')
-    lisa.insert_into_dom(source, ['a'])
+    lisa.strelem_to_xml(source, StringElem(u'a'))
     assert etree.tostring(source, encoding = 'UTF-8') == '<source>a</source>'
 
     source = etree.Element(u'source')
-    lisa.insert_into_dom(source, ['a', 'é'])
+    lisa.strelem_to_xml(source, StringElem([u'a', u'é']))
     assert etree.tostring(source, encoding = 'UTF-8') == '<source>aé</source>'
 
     source = etree.Element(u'source')
-    lisa.insert_into_dom(source, [X('foo[1]/bar[1]/baz[1]')])
+    lisa.strelem_to_xml(source, StringElem(X(id='foo[1]/bar[1]/baz[1]')))
     assert etree.tostring(source, encoding = 'UTF-8') == '<source><x id="foo[1]/bar[1]/baz[1]"/></source>'
 
     source = etree.Element(u'source')
-    lisa.insert_into_dom(source, ['a', X('foo[1]/bar[1]/baz[1]')])
+    lisa.strelem_to_xml(source, StringElem([u'a', X(id='foo[1]/bar[1]/baz[1]')]))
     assert etree.tostring(source, encoding = 'UTF-8') == '<source>a<x id="foo[1]/bar[1]/baz[1]"/></source>'
-    
+
     source = etree.Element(u'source')
-    lisa.insert_into_dom(source, ['a', X('foo[1]/bar[1]/baz[1]'), 'é'])
+    lisa.strelem_to_xml(source, StringElem([u'a', X(id='foo[1]/bar[1]/baz[1]'), u'é']))
     assert etree.tostring(source, encoding = 'UTF-8') == '<source>a<x id="foo[1]/bar[1]/baz[1]"/>é</source>'
 
     source = etree.Element(u'source')
-    lisa.insert_into_dom(source, ['a', G('foo[2]/bar[2]/baz[2]', ['b', X(id = 'foo[1]/bar[1]/baz[1]'), 'c']), 'é'])
+    lisa.strelem_to_xml(source, StringElem([u'a', G(id='foo[2]/bar[2]/baz[2]', sub=[u'b', X(id='foo[1]/bar[1]/baz[1]'), u'c']), u'é']))
     assert etree.tostring(source, encoding = 'UTF-8') == '<source>a<g id="foo[2]/bar[2]/baz[2]">b<x id="foo[1]/bar[1]/baz[1]"/>c</g>é</source>'
+
+def test_unknown_xml_placeable():
+    # The XML below is (modified) from the official XLIFF example file Sample_AlmostEverything_1.2_strict.xlf
+    source = etree.fromstring(u"""<source xml:lang="en-us">Text <g id="_1_ski_040">g</g>TEXT<bpt id="_1_ski_139">bpt<sub>sub</sub>
+               </bpt>TEXT<ept id="_1_ski_238">ept</ept>TEXT<ph id="_1_ski_337"/>TEXT<it id="_1_ski_436" pos="open">it</it>TEXT<mrk mtype="x-test">mrk</mrk>
+               <x id="_1_ski_535"/>TEXT<bx id="_1_ski_634"/>TEXT<ex id="_1_ski_733"/>TEXT.</source>""")
+    elem = lisa.xml_to_strelem(source)
+
+    from copy import copy
+    custom = StringElem([
+        StringElem(u'Text '),
+        G(u'g', id='_1_ski_040'),
+        StringElem(u'TEXT'),
+        UnknownXML(
+            [
+                StringElem(u'bpt'),
+                UnknownXML(u'sub', xml_node=copy(source[1][0])),
+                StringElem(u'\n               ')
+            ],
+            id='_1_ski_139',
+            xml_node=copy(source[3])
+        ),
+        StringElem(u'TEXT'),
+        UnknownXML(u'ept', id=u'_1_ski_238', xml_node=copy(source[2])),
+        StringElem(u'TEXT'),
+        UnknownXML(id='_1_ski_337', xml_node=copy(source[3])), # ph-tag
+        StringElem(u'TEXT'),
+        UnknownXML(u'it', id='_1_ski_436', xml_node=copy(source[4])),
+        StringElem(u'TEXT'),
+        UnknownXML(u'mrk', xml_node=copy(source[5])),
+        StringElem(u'\n               '),
+        X(id='_1_ski_535'),
+        StringElem(u'TEXT'),
+        Bx(id='_1_ski_634'),
+        StringElem(u'TEXT'),
+        Ex(id='_1_ski_733'),
+        StringElem(u'TEXT.')
+    ])
+    assert elem == custom
+
+    xml = copy(source)
+    for i in range(len(xml)):
+        del xml[0]
+    xml.text = None
+    xml.tail = None
+    lisa.strelem_to_xml(xml, elem)
+    assert etree.tostring(xml) == etree.tostring(source)
 
 if __name__ == '__main__':
     test_chunk_list()
-    test_extract_chunks()
-    test_set_insert_into_dom()
-    
+    test_xml_to_strelem()
+    test_set_strelem_to_xml()
+    test_unknown_xml_placeable()

Added: translate-toolkit/branches/upstream/current/translate/storage/placeables/test_terminology.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/test_terminology.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/test_terminology.py (added)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/test_terminology.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,70 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from StringIO import StringIO
+
+from translate.search.match import terminologymatcher
+from translate.storage.pypo import pofile
+from translate.storage.placeables import base, general, parse, StringElem
+from translate.storage.placeables.terminology import parsers as term_parsers, TerminologyPlaceable
+
+
+class TestTerminologyPlaceable:
+    TERMINOLOGY = """
+msgid "name"
+msgstr "naam"
+
+msgid "file"
+msgstr "lêer"
+
+msgid "file name th"
+msgstr "lêernaam wat?"
+
+msgid "file name"
+msgstr "lêernaam"
+"""
+
+    def setup_method(self, method):
+        self.term_po = pofile(StringIO(self.TERMINOLOGY))
+        self.matcher = terminologymatcher(self.term_po)
+        self.test_string = u'<b>Inpüt</b> file name thingy.'
+
+    def test_simple_terminology(self):
+        TerminologyPlaceable.matchers = [self.matcher]
+        tree = parse(self.test_string, general.parsers + term_parsers)
+
+        assert isinstance(tree.sub[0], general.XMLTagPlaceable)
+        assert isinstance(tree.sub[2], general.XMLTagPlaceable)
+
+        tree.print_tree()
+        term = tree.sub[3].sub[1]
+
+        assert isinstance(term, TerminologyPlaceable)
+        assert unicode(term) == self.term_po.getunits()[2].source
+        assert term.translate() == unicode(self.term_po.getunits()[2].target)
+
+
+if __name__ == '__main__':
+    for test in [TestTerminologyPlaceable()]:
+        for method in dir(test):
+            if method.startswith('test_') and callable(getattr(test, method)):
+                if hasattr(test, 'setup_method'):
+                    getattr(test, 'setup_method')(getattr(test, method))
+                getattr(test, method)()

Added: translate-toolkit/branches/upstream/current/translate/storage/placeables/xliff.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/placeables/xliff.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/placeables/xliff.py (added)
+++ translate-toolkit/branches/upstream/current/translate/storage/placeables/xliff.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,154 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2008-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""Contains XLIFF-specific placeables."""
+
+from translate.storage.placeables import base
+from translate.storage.placeables.strelem import StringElem
+
+__all__ = ['Bpt', 'Ept', 'X', 'Bx', 'Ex', 'G', 'It', 'Sub', 'Ph', 'UnknownXML', 'parsers', 'to_xliff_placeables']
+
+
+class Bpt(base.Bpt):
+    pass
+
+
+class Ept(base.Ept):
+    pass
+
+
+class Ph(base.Ph):
+    pass
+
+
+class It(base.It):
+    pass
+
+
+class G(base.G):
+    pass
+
+
+class Bx(base.Bx):
+    pass
+
+
+class Ex(base.Ex):
+    pass
+
+
+class X(base.X):
+    pass
+
+
+class Sub(base.Sub):
+    pass
+
+
+class UnknownXML(StringElem):
+    """Placeable for unrecognized or umimplemented XML nodes. It's main
+        purpose is to preserve all associated XML data."""
+    iseditable = True
+
+    # INITIALIZERS #
+    def __init__(self, sub=None, id=None, rid=None, xid=None, xml_node=None, **kwargs):
+        super(UnknownXML, self).__init__(sub=sub, id=id, rid=rid, xid=xid, **kwargs)
+        if xml_node is None:
+            raise ValueError('xml_node must be a lxml node')
+        self.xml_node = xml_node
+
+        if sub:
+            self.has_content = True
+
+
+    # SPECIAL METHODS #
+    def __repr__(self):
+        """String representation of the sub-tree with the current node as the
+            root.
+
+            Copied from L{StringElem.__repr__), but includes C{self.xml_node.tag}."""
+        tag = self.xml_node.tag
+        if tag.startswith('{'):
+            tag = tag[tag.index('}')+1:]
+
+        elemstr = ', '.join([repr(elem) for elem in self.sub])
+
+        return '<%(class)s{%(tag)s}(%(id)s%(rid)s%(xid)s[%(subs)s])>' % {
+            'class': self.__class__.__name__,
+            'tag': tag,
+            'id':  self.id  is not None and 'id="%s" '  % (self.id) or '',
+            'rid': self.rid is not None and 'rid="%s" ' % (self.rid) or '',
+            'xid': self.xid is not None and 'xid="%s" ' % (self.xid) or '',
+            'subs': elemstr
+        }
+
+
+    # METHODS #
+    def copy(self):
+        """Returns a copy of the sub-tree.
+            This should be overridden in sub-classes with more data.
+
+            NOTE: C{self.renderer} is B{not} copied."""
+        from copy import copy
+        cp = self.__class__(id=self.id, rid=self.rid, xid=self.xid, xml_node=copy(self.xml_node))
+        for sub in self.sub:
+            if isinstance(sub, StringElem):
+                cp.sub.append(sub.copy())
+            else:
+                cp.sub.append(sub.__class__(sub))
+        return cp
+
+
+def to_xliff_placeables(tree):
+    if not isinstance(tree, StringElem):
+        return tree
+
+    newtree = None
+
+    classmap = {
+        base.Bpt: Bpt,
+        base.Ept: Ept,
+        base.Ph:  Ph,
+        base.It:  It,
+        base.G:   G,
+        base.Bx:  Bx,
+        base.Ex:  Ex,
+        base.X:   X,
+        base.Sub: Sub
+    }
+    for baseclass, xliffclass in classmap.items():
+        if isinstance(tree, baseclass):
+            newtree = xliffclass()
+
+    if newtree is None:
+        newtree = tree.__class__()
+
+    newtree.id = tree.id
+    newtree.rid = tree.rid
+    newtree.xid = tree.xid
+    newtree.sub = []
+
+    for subtree in tree.sub:
+        newtree.sub.append(to_xliff_placeables(subtree))
+
+    return newtree
+
+
+parsers = []

Modified: translate-toolkit/branches/upstream/current/translate/storage/pocommon.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/pocommon.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/pocommon.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/pocommon.py Fri Jul 24 16:25:46 2009
@@ -21,6 +21,21 @@
 
 from translate.storage import base
 from translate.storage import poheader
+
+import re
+
+msgid_comment_re = re.compile("_: (.*?)\n")
+
+def extract_msgid_comment(text):
+    """The one definitive way to extract a msgid comment out of an unescaped
+    unicode string that might contain it.
+
+    @rtype: unicode"""
+    msgidcomment = msgid_comment_re.match(text)
+    if msgidcomment:
+        return msgidcomment.group(1)
+    return u""
+
 
 class pounit(base.TranslationUnit):
 

Modified: translate-toolkit/branches/upstream/current/translate/storage/poheader.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/poheader.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/poheader.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/poheader.py Fri Jul 24 16:25:46 2009
@@ -1,23 +1,22 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2002-2006 Zuza Software Foundation
-# 
-# This file is part of translate.
-#
-# translate is free software; you can redistribute it and/or modify
+#
+# Copyright 2002-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """class that handles all header functions for a header in a po file"""
 
@@ -29,8 +28,8 @@
 author_re = re.compile(r".*<\S+@\S+>.*\d{4,4}")
 
 def parseheaderstring(input):
-    """Parses an input string with the definition of a PO header and returns 
-    the interpreted values as a dictionary"""
+    """Parses an input string with the definition of a PO header and returns
+    the interpreted values as a dictionary."""
     headervalues = dictutils.ordereddict()
     for line in input.split("\n"):
         if not line or ":" not in line:
@@ -42,7 +41,9 @@
     return headervalues
 
 def tzstring():
-    """Returns the timezone as a string in the format [+-]0000, eg +0200."""
+    """Returns the timezone as a string in the format [+-]0000, eg +0200.
+
+    @rtype: str"""
     if time.daylight:
         tzoffset = time.altzone
     else:
@@ -55,8 +56,8 @@
     return tz
 
 def update(existing, add=False, **kwargs):
-    """Update an existing header dictionary with the values in kwargs, adding new values 
-    only if add is true. 
+    """Update an existing header dictionary with the values in kwargs, adding new values
+    only if add is true.
 
     @return: Updated dictionary of header entries
     @rtype: dict
@@ -109,11 +110,23 @@
         "X-Generator",
         ]
 
-
-    def makeheaderdict(self, charset="CHARSET", encoding="ENCODING", project_id_version=None, pot_creation_date=None, po_revision_date=None, last_translator=None, language_team=None, mime_version=None, plural_forms=None, report_msgid_bugs_to=None, **kwargs):
-        """create a header for the given filename. arguments are specially handled, kwargs added as key: value
+    def makeheaderdict(self,
+            charset="CHARSET",
+            encoding="ENCODING",
+            project_id_version=None,
+            pot_creation_date=None,
+            po_revision_date=None,
+            last_translator=None,
+            language_team=None,
+            mime_version=None,
+            plural_forms=None,
+            report_msgid_bugs_to=None,
+            **kwargs):
+        """Create a header dictionary with useful defaults.
+
         pot_creation_date can be None (current date) or a value (datetime or string)
-        po_revision_date can be None (form), False (=pot_creation_date), True (=now), or a value (datetime or string)
+        po_revision_date can be None (form), False (=pot_creation_date), True (=now),
+        or a value (datetime or string)
 
         @return: Dictionary with the header items
         @rtype: dict
@@ -170,21 +183,26 @@
             return None
 
     def parseheader(self):
-        """Parses the PO header and returns 
-        the interpreted values as a dictionary"""
+        """Parses the PO header and returns the interpreted values as a
+        dictionary."""
         header = self.header()
         if not header:
             return {}
         return parseheaderstring(header.target)
 
     def updateheader(self, add=False, **kwargs):
-        """Updates the fields in the PO style header. 
-        This will create a header if add == True"""
+        """Updates the fields in the PO style header.
+
+        This will create a header if add == True."""
         header = self.header()
         if not header:
-            # FIXME: does not work for xliff files yet
-            if add and callable(getattr(self, "makeheader", None)):
+            if add:
                 header = self.makeheader(**kwargs)
+                # we should be using .addunit() or some equivalent in case the
+                # unit needs to refer back to the store, etc. This might be
+                # subtly broken for POXLIFF, since we don't dupliate the code
+                # from lisa::addunit().
+                header._store = self
                 self.units.insert(0, header)
         else:
             headeritems = update(self.parseheader(), add, **kwargs)
@@ -202,7 +220,7 @@
         return header
 
     def getheaderplural(self):
-        """returns the nplural and plural values from the header"""
+        """Returns the nplural and plural values from the header."""
         header = self.parseheader()
         pluralformvalue = header.get('Plural-Forms', None)
         if pluralformvalue is None:
@@ -220,12 +238,15 @@
         return nplural, plural
 
     def updateheaderplural(self, nplurals, plural):
-        """update the Plural-Form PO header"""
+        """Update the Plural-Form PO header."""
         if isinstance(nplurals, basestring):
             nplurals = int(nplurals)
         self.updateheader(add=True, Plural_Forms = "nplurals=%d; plural=%s;" % (nplurals, plural) )
 
     def gettargetlanguage(self):
+        """Return the target language if specified in the header.
+
+        Some attempt at understanding Poedit's custom headers is done."""
         header = self.parseheader()
         if 'X-Poedit-Language' in header:
             from translate.lang import poedit
@@ -235,16 +256,22 @@
         return header.get('Language')
 
     def settargetlanguage(self, lang):
+        """Set the target language in the header.
+
+        This removes any custom Poedit headers if they exist.
+
+        @param lang: the new target language code
+        @type lang: str
+        """
         if isinstance(lang, basestring) and len(lang) > 1:
             self.updateheader(add=True, Language=lang, X_Poedit_Language=None, X_Poedit_Country=None)
 
     def mergeheaders(self, otherstore):
         """Merges another header with this header.
-        
+
         This header is assumed to be the template.
-        
+
         @type otherstore: L{base.TranslationStore}
-        
         """
 
         newvalues = otherstore.parseheader()
@@ -295,33 +322,32 @@
         for i in range(len(contriblines)):
             line = contriblines[i]
             if name in line and (email is None or email in line):
+                contribexists = True
                 if year in line:
-                    contribexists = True
                     break
                 else:
                     #The contributor is there, but not for this year
-                    contriblines[i] = "%s,%s" % (line, year)
+                    if line[-1] == '.':
+                        line = line[:-1]
+                    contriblines[i] = "%s, %s." % (line, year)
 
         if not contribexists:
             # Add a new contributor
             if email:
-                contriblines.append("%s <%s>, %s" % (name, email, year))
+                contriblines.append("%s <%s>, %s." % (name, email, year))
             else:
-                contriblines.append("%s, %s" % (name, year))
+                contriblines.append("%s, %s." % (name, year))
 
         header.removenotes()
         header.addnote("\n".join(prelines))
         header.addnote("\n".join(contriblines))
         header.addnote("\n".join(postlines))
 
-
     def makeheader(self, **kwargs):
-        """create a header for the given filename. arguments are specially handled, kwargs added as key: value
-        pot_creation_date can be None (current date) or a value (datetime or string)
-        po_revision_date can be None (form), False (=pot_creation_date), True (=now), or a value (datetime or string)"""
-
+        """Create a header for the given filename.
+
+        Check .makeheaderdict() for information on parameters."""
         headerpo = self.UnitClass(encoding=self._encoding)
-            
         headerpo.markfuzzy()
         headerpo.source = ""
         headeritems = self.makeheaderdict(**kwargs)

Modified: translate-toolkit/branches/upstream/current/translate/storage/poparser.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/poparser.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/poparser.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/poparser.py Fri Jul 24 16:25:46 2009
@@ -99,9 +99,7 @@
     next_line = parse_state.next_line
     if len(next_line) > 0 and next_line[0] == '#':
         next_char = next_line[1] 
-        if isspace(next_char):
-            append(unit.othercomments, parse_state.decode(next_line))
-        elif next_char == '.':
+        if next_char == '.':
             append(unit.automaticcomments, parse_state.decode(next_line))
         elif next_char == '|':
             # Read all the lines starting with #|
@@ -124,7 +122,7 @@
             # elsewhere to ensure we reuse the normal unit parsing code
             return None
         else:
-            return None
+            append(unit.othercomments, parse_state.decode(next_line))
         return parse_state.read_line()
     else:
         return None
@@ -169,9 +167,9 @@
     left = find(line, '"', start_pos)
     if left == start_pos or isspace(line[start_pos:left]):
         right = rfind(line, '"')
-        if left != right and line[right - 1] != '\\': # If we found a terminating quote
+        if left != right:
             return parse_state.read_line()[left:right+1]
-        else: # If there is no terminating quote 
+        else: # If there is no terminating quote
             return parse_state.read_line()[left:] + '"'
     return None
 
@@ -192,7 +190,9 @@
         else:
             string = parse_msg_comment(parse_state, msg_comment_list, string)
 
-def parse_message(parse_state, start_of_string, start_of_string_len, msg_list, msg_comment_list = []):
+def parse_message(parse_state, start_of_string, start_of_string_len, msg_list, msg_comment_list=None):
+    if msg_comment_list is None:
+        msg_comment_list = []
     if startswith(parse_state.next_line, start_of_string):
         return parse_multiple_quoted(parse_state, msg_list, msg_comment_list, start_of_string_len)
 

Modified: translate-toolkit/branches/upstream/current/translate/storage/poxliff.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/poxliff.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/poxliff.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/poxliff.py Fri Jul 24 16:25:46 2009
@@ -1,31 +1,31 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2006-2007 Zuza Software Foundation
-# 
-# This file is part of translate.
-#
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2006-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
-
-"""An xliff file specifically suited for handling the po representation of 
-xliff. """
-
-from translate.storage import xliff
-from translate.storage import lisa 
-from translate.storage import poheader
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""XLIFF classes specifically suited for handling the PO representation in
+XLIFF.
+
+This way the API supports plurals as if it was a PO file, for example.
+"""
+
+from translate.storage import base, lisa, poheader, xliff
+from translate.storage.placeables import general
 from translate.misc.multistring import multistring
 from lxml import etree
 import re
@@ -37,9 +37,14 @@
 
 class PoXliffUnit(xliff.xliffunit):
     """A class to specifically handle the plural units created from a po file."""
+
+    rich_parsers = general.parsers
+
     def __init__(self, source=None, empty=False, encoding="UTF-8"):
+        self._rich_source = None
+        self._rich_target = None
         self.units = []
-            
+
         if empty:
             return
 
@@ -55,8 +60,6 @@
         if isinstance(other, PoXliffUnit):
             if len(self.units) != len(other.units):
                 return False
-            if len(self.units) == 0:
-                return True
             if not super(PoXliffUnit, self).__eq__(other):
                 return False
             for i in range(len(self.units)-1):
@@ -89,12 +92,15 @@
                 self.xmlelement.append(newunit.xmlelement)
             self.target = target
 
+    multistring_to_rich = base.TranslationUnit.multistring_to_rich
+    rich_to_multistring = base.TranslationUnit.rich_to_multistring
+
     def getsource(self):
         strings = [super(PoXliffUnit, self).getsource()]
         strings.extend([unit.source for unit in self.units[1:]])
         return multistring(strings)
     source = property(getsource, setsource)
-    
+
     def settarget(self, text, lang='xx', append=False):
         if self.gettarget() == text:
             return
@@ -116,7 +122,7 @@
             targets = text.strings + [""] * (sourcel - targetl)
         else:
             targets = text.strings
-        
+
         for i in range(len(self.units)):
             self.units[i].target = targets[i]
 
@@ -213,8 +219,8 @@
             for (type, text) in commentpairs:
                 comments.append(text)
         return "\n".join(comments)
-    
-    def gettranslatorcomments(self):       
+
+    def gettranslatorcomments(self):
         """Returns the translator comments (x-po-trancomment), which corresponds
         to the # style po comments."""
         def hastrancomment((type, text)):
@@ -308,7 +314,7 @@
                 pluralnum += 1
                 group.append(unit.xmlelement)
                 self.units.append(unit)
-        
+
         return self.units[-pluralnum]
 
     def parse(self, xml):
@@ -317,10 +323,10 @@
         def ispluralgroup(node):
             """determines whether the xml node refers to a getttext plural"""
             return node.get("restype") == "x-gettext-plurals"
-        
+
         def isnonpluralunit(node):
             """determindes whether the xml node contains a plural like id.
-            
+
             We want to filter out all the plural nodes, except the very first
             one in each group.
             """
@@ -329,7 +335,7 @@
         def pluralunits(pluralgroups):
             for pluralgroup in pluralgroups:
                 yield self.UnitClass.createfromxmlElement(pluralgroup, namespace=self.namespace)
-        
+
         self.filename = getattr(xml, 'name', '')
         if hasattr(xml, "read"):
             xml.seek(0)

Modified: translate-toolkit/branches/upstream/current/translate/storage/properties.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/properties.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/properties.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/properties.py Fri Jul 24 16:25:46 2009
@@ -23,9 +23,14 @@
    (propfile) these files are used in translating Mozilla and other software
    
    The following U{.properties file
-   description<http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.Reader)>}
+   description<http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.InputStream)>}
    and U{example <http://www.exampledepot.com/egs/java.util/Props.html>} give some
    good references to the .properties specification.
+
+   Properties file may also hold Java
+   U{MessageFormat<http://java.sun.com/j2se/1.4.2/docs/api/java/text/MessageFormat.html>} 
+   messages.  No special handling is provided in this storage class for MessageFormat,
+   but this may be implemented in future.
 
    Implementation
    ==============
@@ -46,43 +51,126 @@
 
 from translate.storage import base
 from translate.misc import quote
+from translate.lang import data
 import re
 
 # the rstripeols convert dos <-> unix nicely as well
 # output will be appropriate for the platform
 
 eol = "\n"
+
+def find_delimeter(line):
+    """Find the type and position of the delimeter in a property line.
+
+    Property files can be delimeted by "=", ":" or whitespace (space for now).
+    We find the position of each delimeter, then find the one that appears 
+    first.
+
+    @param line: A properties line
+    @type line: str
+    @return: Delimeter character and offset within L{line}
+    @rtype: Tuple (Delimeter char, Offset Integer)
+    """
+    delimeters = {"=": -1, ":": -1, " ": -1}
+    # Find the position of each delimeter type
+    for delimeter, pos in delimeters.iteritems():
+        prewhitespace = len(line) - len(line.lstrip())
+        pos = line.find(delimeter,prewhitespace)
+        while pos != -1:
+            if delimeters[delimeter] == -1 and line[pos-1] != "\\":
+                delimeters[delimeter] = pos
+                break
+            pos = line.find(delimeter,pos+1)
+    # Find the first "=" or ":" delimeter
+    mindelimeter = None
+    minpos = -1
+    for delimeter, pos in delimeters.iteritems():
+        if pos == -1 or delimeter == " ":
+            continue
+        if minpos == -1 or pos < minpos:
+            minpos = pos
+            mindelimeter = delimeter
+    if mindelimeter is None and delimeters[" "] != -1:
+        # Use space delimeter if we found nothing else
+        return (" ", delimeters[" "])
+    if mindelimeter is not None and delimeters[" "] < delimeters[mindelimeter]:
+        # If space delimeter occurs earlier then ":" or "=" then it is the 
+        # delimeter only if there are non-whitespace characters between it and
+        # the other detected delimeter.
+        if len(line[delimeters[" "]:delimeters[mindelimeter]].strip()) > 0:
+            return (" ", delimeters[" "])
+    return (mindelimeter, minpos)
+
+def is_line_continuation(line):
+    """Determine whether L{line} has a line continuation marker.
+
+    .properties files can be terminated with a backslash (\\) indicating
+    that the 'value' continues on the next line.  Continuation is only 
+    valid if there are an odd number of backslashses (an even number
+    would result in a set of N/2 slashes not an escape)
+
+    @param line: A properties line
+    @type line: str
+    @return: Does L{line} end with a line continuation
+    @rtype: Boolean
+    """
+    pos = -1
+    count = 0
+    if len(line) == 0:
+        return False
+    # Count the slashes from the end of the line. Ensure we don't
+    # go into infinite loop.
+    while len(line) >= -pos and line[pos:][0] == "\\":
+        pos -= 1
+        count += 1
+    return (count % 2) == 1  # Odd is a line continuation, even is not
+
+def key_strip(key):
+    """Cleanup whitespace found around a key
+
+    @param key: A properties key
+    @type key: str
+    @return: Key without any uneeded whitespace
+    @rtype: str
+    """
+    newkey = key.rstrip()
+    # If line now end in \ we put back the whitespace that was escaped
+    if newkey[-1:] == "\\":
+        newkey += key[len(newkey):len(newkey)+1]
+    return newkey.lstrip()
+
+default_encoding = {"java": "latin1", "mozilla": "utf-8"}
 
 class propunit(base.TranslationUnit):
     """an element of a properties file i.e. a name and value, and any comments
     associated"""
-    def __init__(self, source=""):
+    def __init__(self, source="", personality="java"):
         """construct a blank propunit"""
+        self.personality = personality
         super(propunit, self).__init__(source)
         self.name = ""
-        self.value = ""
+        self.value = u""
+        self.delimeter = u"="
         self.comments = []
         self.source = source
 
     def setsource(self, source):
         """Sets the source AND the target to be equal"""
-        self.value = quote.mozillapropertiesencode(source or "")
+        source = data.forceunicode(source)
+        if self.personality == "mozilla":
+            self.value = quote.mozillapropertiesencode(source or u"")
+        else:
+            self.value = quote.javapropertiesencode(source or u"")
 
     def getsource(self):
-        value = quote.mozillapropertiesdecode(self.value)
-        value = value.lstrip(" ")
-        rstriped = value.rstrip(" ")
-        if rstriped and rstriped[-1] != "\\":
-            value = rstriped
-
-        value = re.sub("\\\\ ", " ", value)
+        value = quote.propertiesdecode(self.value)
+        value = re.sub(u"\\\\ ", u" ", value)
         return value
 
     source = property(getsource, setsource)
 
     def settarget(self, target):
         """Note: this also sets the .source attribute!"""
-        # TODO: shouldn't this just call the .source property? no quoting done here...
         self.source = target
 
     def gettarget(self):
@@ -93,26 +181,30 @@
         """convert to a string. double check that unicode is handled somehow here"""
         source = self.getoutput()
         if isinstance(source, unicode):
-            return source.encode(getattr(self, "encoding", "UTF-8"))
+            return source.encode(default_encoding[self.personality])
         return source
 
     def getoutput(self):
         """convert the element back into formatted lines for a .properties file"""
+        notes = self.getnotes()
+        if notes:
+            notes += u"\n"
         if self.isblank():
-            return "".join(self.comments + ["\n"])
+            return notes
         else:
-            if "\\u" in self.value:
-                self.value = quote.mozillapropertiesencode(quote.mozillapropertiesdecode(self.value))
-            return "".join(self.comments + ["%s=%s\n" % (self.name, self.value)])
+            if "\\u" in self.value and self.personality == "mozilla":
+                self.value = quote.mozillapropertiesencode(self.source)
+            return u"%s%s%s%s\n" % (notes, self.name, self.delimeter, self.value)
 
     def getlocations(self):
         return [self.name]
 
     def addnote(self, note, origin=None):
+        note = data.forceunicode(note)
         self.comments.append(note)
 
     def getnotes(self, origin=None):
-        return '\n'.join(self.comments)
+        return u'\n'.join(self.comments)
 
     def removenotes(self):
         self.comments = []
@@ -124,26 +216,30 @@
 class propfile(base.TranslationStore):
     """this class represents a .properties file, made up of propunits"""
     UnitClass = propunit
-    def __init__(self, inputfile=None):
+    def __init__(self, inputfile=None, personality="java"):
         """construct a propfile, optionally reading in from inputfile"""
         super(propfile, self).__init__(unitclass = self.UnitClass)
         self.filename = getattr(inputfile, 'name', '')
         if inputfile is not None:
             propsrc = inputfile.read()
             inputfile.close()
-            self.parse(propsrc)
-
-    def parse(self, propsrc):
+            self.parse(propsrc, personality)
+
+    def parse(self, propsrc, personality="java"):
         """read the source of a properties file in and include them as units"""
-        newunit = propunit()
+        newunit = propunit("", personality)
         inmultilinevalue = False
-        for line in propsrc.split("\n"):
+        if personality == "mozilla":
+            propsrc = unicode(propsrc, 'utf-8')
+        else:
+            propsrc = unicode(propsrc, 'latin1')
+        for line in propsrc.split(u"\n"):
             # handle multiline value if we're in one
             line = quote.rstripeol(line)
             if inmultilinevalue:
                 newunit.value += line.lstrip()
                 # see if there's more
-                inmultilinevalue = (newunit.value[-1:] == '\\')
+                inmultilinevalue = is_line_continuation(newunit.value)
                 # if we're still waiting for more...
                 if inmultilinevalue:
                     # strip the backslash
@@ -151,33 +247,32 @@
                 if not inmultilinevalue:
                     # we're finished, add it to the list...
                     self.addunit(newunit)
-                    newunit = propunit()
+                    newunit = propunit("", personality)
             # otherwise, this could be a comment
-            elif line.strip()[:1] == '#':
+            elif line.strip()[:1] in (u'#', u'!'):
                 # add a comment
-                line = quote.escapecontrols(line)
-                newunit.comments.append(line+"\n")
+                newunit.comments.append(line)
             elif not line.strip():
                 # this is a blank line...
                 if str(newunit).strip():
                     self.addunit(newunit)
-                    newunit = propunit()
+                    newunit = propunit("", personality)
             else:
-                equalspos = line.find('=')
-                # if no equals, just ignore it
-                if equalspos == -1:
+                delimeter_char, delimeter_pos = find_delimeter(line)
+                if delimeter_pos == -1:
                     continue
                 # otherwise, this is a definition
                 else:
-                    newunit.name = line[:equalspos].strip()
-                    newunit.value = line[equalspos+1:].lstrip()
+                    newunit.delimeter = delimeter_char
+                    newunit.name = key_strip(line[:delimeter_pos])
+                    newunit.value = line[delimeter_pos+1:].lstrip()
                     # backslash at end means carry string on to next line
-                    if newunit.value[-1:] == '\\':
+                    if is_line_continuation(newunit.value):
                         inmultilinevalue = True
                         newunit.value = newunit.value[:-1]
                     else:
                         self.addunit(newunit)
-                        newunit = propunit()
+                        newunit = propunit("", personality)
         # see if there is a leftover one...
         if inmultilinevalue or len(newunit.comments) > 0:
             self.addunit(newunit)

Modified: translate-toolkit/branches/upstream/current/translate/storage/pypo.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/pypo.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/pypo.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/pypo.py Fri Jul 24 16:25:46 2009
@@ -1,23 +1,22 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2002-2007 Zuza Software Foundation
-# 
-# This file is part of translate.
 #
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2002-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """classes that hold units of .po files (pounit) or entire files (pofile)
 gettext-style .po (or .pot) files are used in translations for KDE et al (see kbabel)"""
@@ -43,7 +42,7 @@
 
 def escapeforpo(line):
     """Escapes a line for po format. assumes no \n occurs in the line.
-    
+
     @param line: unescaped text
     """
     special_locations = []
@@ -104,7 +103,7 @@
 
 def extractpoline(line):
     """Remove quote and unescape line from po file.
-     
+
     @param line: a quoted line from a po file (msgid or msgstr)
     """
     extracted = quote.extractwithoutquotes(line, '"', '"', '\\', includeescapes=unescapehandler)[0]
@@ -149,6 +148,10 @@
     # msgctxt
     # msgid = []
     # msgstr = []
+
+    # Our homegrown way to indicate what must be copied in a shallow
+    # fashion
+    __shallow__ = ['_store']
 
     def __init__(self, source=None, encoding="UTF-8"):
         self._encoding = encodingToUse(encoding)
@@ -180,10 +183,10 @@
             self.obsoletemsgidcomments = []
 
     def _get_all_comments(self):
-        return [self.othercomments, 
-                self.automaticcomments, 
-                self.sourcecomments, 
-                self.typecomments, 
+        return [self.othercomments,
+                self.automaticcomments,
+                self.sourcecomments,
+                self.typecomments,
                 self.msgidcomments,
                 self.obsoletemsgidcomments]
 
@@ -222,7 +225,7 @@
 
     def setsource(self, source):
         """Sets the msgid to the given (unescaped) value.
-        
+
         @param source: an unescaped source string.
         """
         self.msgid, self.msgid_plural = self._set_source_vars(source)
@@ -234,7 +237,7 @@
 
     def _set_prev_source(self, source):
         """Sets the msgid to the given (unescaped) value.
-        
+
         @param source: an unescaped source string.
         """
         self.prev_msgid, self.prev_msgid_plural = self._set_source_vars(source)
@@ -250,6 +253,7 @@
 
     def settarget(self, target):
         """Sets the msgstr to the given (unescaped) value"""
+        self._rich_target = None
         if isinstance(target, str):
             target = target.decode(self._encoding)
         if self.hasplural():
@@ -309,10 +313,29 @@
                 self.automaticcomments = newcomments
             else:
                 self.othercomments = newcomments
-        
+
     def removenotes(self):
         """Remove all the translator's notes (other comments)"""
         self.othercomments = []
+
+    def __deepcopy__(self, memo={}):
+        # Make an instance to serve as the copy
+        new_unit = self.__class__()
+        # We'll be testing membership frequently, so make a set from
+        # self.__shallow__
+        shallow = set(self.__shallow__)
+        # Make deep copies of all members which are not in shallow
+        for key, value in self.__dict__.iteritems():
+            if key not in shallow:
+                setattr(new_unit, key, copy.deepcopy(value))
+        # Make shallow copies of all members which are in shallow
+        for key in set(shallow):
+            setattr(new_unit, key, getattr(self, key))
+        # Mark memo with ourself, so that we won't get deep copied
+        # again
+        memo[id(self)] = self
+        # Return our copied unit
+        return new_unit
 
     def copy(self):
         return copy.deepcopy(self)
@@ -335,7 +358,6 @@
 
         Overwrite non-blank self.msgstr only if overwrite is True
         merge comments only if comments is True
-        
         """
 
         def mergelists(list1, list2, split=False):
@@ -347,7 +369,7 @@
                 for position, item in enumerate(list2):
                     if isinstance(item, str):
                         list2[position] = item.decode("utf-8")
-                        
+
             #Determine the newline style of list1
             lineend = ""
             if list1 and list1[0]:
@@ -358,7 +380,7 @@
                     lineend = ""
             else:
                 lineend = "\n"
-            
+
             #Split if directed to do so:
             if split:
                 splitlist1 = []
@@ -397,7 +419,7 @@
             if self._extract_msgidcomments(otherpo.target):
                 otherpo.target = otherpo.target.replace('_: ' + otherpo._extract_msgidcomments()+ '\n', '')
             self.target = otherpo.target
-            if self.source != otherpo.source:
+            if self.source != otherpo.source or self.getcontext() != otherpo.getcontext():
                 self.markfuzzy()
             else:
                 self.markfuzzy(otherpo.isfuzzy())
@@ -410,9 +432,9 @@
 
     def isheader(self):
         #return (self._msgidlen() == 0) and (self._msgstrlen() > 0) and (len(self.msgidcomments) == 0)
-        #rewritten here for performance:        
-        return (is_null(self.msgid) 
-                        and not is_null(self.msgstr) 
+        #rewritten here for performance:
+        return (is_null(self.msgid)
+                        and not is_null(self.msgstr)
                         and self.msgidcomments == []
                         and is_null(self.msgctxt)
         )
@@ -420,7 +442,7 @@
     def isblank(self):
         if self.isheader() or len(self.msgidcomments):
             return False
-        if (self._msgidlen() == 0) and (self._msgstrlen() == 0):
+        if (self._msgidlen() == 0) and (self._msgstrlen() == 0) and (is_null(self.msgctxt)):
             return True
         return False
         # TODO: remove:
@@ -601,12 +623,12 @@
         # if there's no msgid don't do msgid and string, unless we're the header
         # this will also discard any comments other than plain othercomments...
         if is_null(self.msgid):
-            if not (self.isheader() or self.msgidcomments or self.sourcecomments):
+            if not (self.isheader() or self.getcontext() or self.sourcecomments):
                 return "".join(lines)
         lines.extend(self.automaticcomments)
         lines.extend(self.sourcecomments)
+        lines.extend(self.typecomments)
         add_prev_msgid_info(lines)
-        lines.extend(self.typecomments)
         if self.msgctxt:
             lines.append(self._getmsgpartstr("msgctxt", self.msgctxt))
         lines.append(self._getmsgpartstr("msgid", self.msgid, self.msgidcomments))
@@ -640,10 +662,9 @@
 
     def _extract_msgidcomments(self, text=None):
         """Extract KDE style msgid comments from the unit.
-        
+
         @rtype: String
         @return: Returns the extracted msgidcomments found in this unit's msgid.
-        
         """
 
         if not text:
@@ -684,7 +705,12 @@
             self.parse(inputfile)
 
     def changeencoding(self, newencoding):
-        """changes the encoding on the file"""
+        """Deprecated: changes the encoding on the file."""
+        # This should not be here but in poheader. It also shouldn't mangle the
+        # header itself, but use poheader methods. All users are removed, so
+        # we can deprecate after one release.
+        raise DeprecationWarning
+
         self._encoding = encodingToUse(newencoding)
         if not self.units:
             return
@@ -728,51 +754,42 @@
 
     def removeduplicates(self, duplicatestyle="merge"):
         """make sure each msgid is unique ; merge comments etc from duplicates into original"""
-        msgiddict = {}
+        # TODO: can we handle consecutive calls to removeduplicates()? What
+        # about files already containing msgctxt? - test
+        id_dict = {}
         uniqueunits = []
-        # we sometimes need to keep track of what has been marked
-        # TODO: this is using a list as the pos aren't hashable, but this is slow...
+        # TODO: this is using a list as the pos aren't hashable, but this is slow.
+        # probably not used frequently enough to worry about it, though.
         markedpos = []
         def addcomment(thepo):
             thepo.msgidcomments.append('"_: %s\\n"' % " ".join(thepo.getlocations()))
             markedpos.append(thepo)
         for thepo in self.units:
-            if duplicatestyle.startswith("msgid_comment"):
-                msgid = unquotefrompo(thepo.msgidcomments) + unquotefrompo(thepo.msgid)
-            else:
-                msgid = unquotefrompo(thepo.msgid)
+            id = thepo.getid()
             if thepo.isheader() and not thepo.getlocations():
                 # header msgids shouldn't be merged...
                 uniqueunits.append(thepo)
-            elif duplicatestyle == "msgid_comment_all":
-                addcomment(thepo)
-                uniqueunits.append(thepo)
-            elif msgid in msgiddict:
+            elif id in id_dict:
                 if duplicatestyle == "merge":
-                    if msgid:
-                        msgiddict[msgid].merge(thepo)
+                    if id:
+                        id_dict[id].merge(thepo)
                     else:
                         addcomment(thepo)
                         uniqueunits.append(thepo)
-                elif duplicatestyle == "keep":
+                elif duplicatestyle == "msgctxt":
+                    origpo = id_dict[id]
+                    if origpo not in markedpos:
+                        origpo.msgctxt.append('"%s"' % escapeforpo(" ".join(origpo.getlocations())))
+                        markedpos.append(thepo)
+                    thepo.msgctxt.append('"%s"' % escapeforpo(" ".join(thepo.getlocations())))
                     uniqueunits.append(thepo)
-                elif duplicatestyle == "msgid_comment":
-                    origpo = msgiddict[msgid]
-                    if origpo not in markedpos:
-                        addcomment(origpo)
-                    addcomment(thepo)
-                    uniqueunits.append(thepo)
-                elif duplicatestyle == "msgctxt":
-                    origpo = msgiddict[msgid]
-                    if origpo not in markedpos:
-                        origpo.msgctxt.append('"%s"' % " ".join(origpo.getlocations()))
-                        markedpos.append(thepo)
-                    thepo.msgctxt.append('"%s"' % " ".join(thepo.getlocations()))
-                    uniqueunits.append(thepo)
-            else:
-                if not msgid and duplicatestyle != "keep":
-                    addcomment(thepo)
-                msgiddict[msgid] = thepo
+            else:
+                if not id:
+                    if duplicatestyle == "merge":
+                        addcomment(thepo)
+                    else:
+                        thepo.msgctxt.append('"%s"' % escapeforpo(" ".join(thepo.getlocations())))
+                id_dict[id] = thepo
                 uniqueunits.append(thepo)
         self.units = uniqueunits
 
@@ -822,4 +839,3 @@
         for unit in self.units:
             if not (unit.isheader() or unit.isobsolete()):
                 yield unit
-

Modified: translate-toolkit/branches/upstream/current/translate/storage/qm.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/qm.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/qm.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/qm.py Fri Jul 24 16:25:46 2009
@@ -89,7 +89,7 @@
             input.close()
             input = qmsrc
         if len(input) < 16:
-            raise ValueError("This is not a .qm file: file empty or to small")
+            raise ValueError("This is not a .qm file: file empty or too small")
         magic = struct.unpack(">4L", input[:16])
         if magic != QM_MAGIC_NUMBER:
             raise ValueError("This is not a .qm file: invalid magic number")

Modified: translate-toolkit/branches/upstream/current/translate/storage/qph.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/qph.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/qph.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/qph.py Fri Jul 24 16:25:46 2009
@@ -89,7 +89,7 @@
 class QphFile(lisa.LISAfile):
     """Class representing a QPH file store."""
     UnitClass = QphUnit
-    Name = _("Qt Phrase Book File")
+    Name = _("Qt Phrase Book")
     Mimetypes  = ["application/x-qph"]
     Extensions = ["qph"]
     rootNode = "QPH"

Modified: translate-toolkit/branches/upstream/current/translate/storage/rc.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/rc.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/rc.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/rc.py Fri Jul 24 16:25:46 2009
@@ -1,26 +1,25 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2004-2006, 2008 Zuza Software Foundation
-# 
-# This file is part of translate.
-#
-# translate is free software; you can redistribute it and/or modify
+#
+# Copyright 2004-2006,2008-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-"""classes that hold units of .rc files (rcunit) or entire files
-(rcfile) these files are used in translating Windows Resources
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+"""Classes that hold units of .rc files (rcunit) or entire files
+(rcfile) used in translating Windows Resources.
 
 @note: This implementation is based mostly on observing WINE .rc files,
 these should mimic other non-WINE .rc files.
@@ -28,7 +27,6 @@
 
 from translate.storage import base
 import re
-import sys
 
 def escape_to_python(string):
     """escape a given .rc string into a valid Python string"""
@@ -40,16 +38,16 @@
     return pystring
 
 def escape_to_rc(string):
-    """escape a given Python string into a valid .rc string"""
+    """Escape a given Python string into a valid .rc string."""
     rcstring = re.sub("\\\\", "\\\\\\\\", string)
     rcstring = re.sub("\t", "\\\\t", rcstring)
     rcstring = re.sub("\n", "\\\\n", rcstring)
     return rcstring
 
 class rcunit(base.TranslationUnit):
-    """a unit of an rc file"""
+    """A unit of an rc file"""
     def __init__(self, source=""):
-        """construct a blank rcunit"""
+        """Construct a blank rcunit."""
         super(rcunit, self).__init__(source)
         self.name = ""
         self._value = ""
@@ -75,14 +73,14 @@
     target = property(gettarget, settarget)
 
     def __str__(self):
-        """convert to a string. double check that unicode is handled somehow here"""
+        """Convert to a string. Double check that unicode is handled somehow here."""
         source = self.getoutput()
         if isinstance(source, unicode):
             return source.encode(getattr(self, "encoding", "UTF-8"))
         return source
 
     def getoutput(self):
-        """convert the element back into formatted lines for a .rc file"""
+        """Convert the element back into formatted lines for a .rc file."""
         if self.isblank():
             return "".join(self.comments + ["\n"])
         else:
@@ -101,23 +99,25 @@
         self.comments = []
 
     def isblank(self):
-        """returns whether this is a blank element, containing only comments..."""
+        """Returns whether this is a blank element, containing only comments."""
         return not (self.name or self.value)
 
 class rcfile(base.TranslationStore):
-    """this class represents a .rc file, made up of rcunits"""
+    """This class represents a .rc file, made up of rcunits."""
     UnitClass = rcunit
-    def __init__(self, inputfile=None):
-        """construct an rcfile, optionally reading in from inputfile"""
+    def __init__(self, inputfile=None, lang=None, sublang=None):
+        """Construct an rcfile, optionally reading in from inputfile."""
         super(rcfile, self).__init__(unitclass = self.UnitClass)
         self.filename = getattr(inputfile, 'name', '')
+        self.lang = lang
+        self.sublang = sublang
         if inputfile is not None:
             rcsrc = inputfile.read()
             inputfile.close()
             self.parse(rcsrc)
 
     def parse(self, rcsrc):
-        """read the source of a .rc file in and include them as units"""
+        """Read the source of a .rc file in and include them as units."""
         BLOCKS_RE = re.compile("""
                          (?:
                          LANGUAGE\s+[^\n]*|                              # Language details
@@ -150,29 +150,36 @@
                          (?:\s*,?\s*)?
                          (?P<name>[^\s]+).*?[\n]
                          """, re.DOTALL + re.VERBOSE)
-        languagesection = False
-
+
+        processsection = False
         self.blocks = BLOCKS_RE.findall(rcsrc)
-
         for blocknum, block in enumerate(self.blocks):
             #print block.split("\n")[0]
+            processblock = None
+            if block.startswith("LANGUAGE"):
+                if self.lang == None or self.sublang == None or re.match("LANGUAGE\s+%s,\s*%s\s*$" % (self.lang, self.sublang), block) is not None:
+                    processsection = True
+                else:
+                    processsection = False
+            else:
+                if re.match(".+LANGUAGE\s+[0-9A-Za-z_]+,\s*[0-9A-Za-z_]+\s*[\n]", block, re.DOTALL) is not None:
+                    if re.match(".+LANGUAGE\s+%s,\s*%s\s*[\n]" % (self.lang, self.sublang), block, re.DOTALL) is not None:
+                        processblock = True
+                    else:
+                        processblock = False
+
+            if not (processblock == True or (processsection == True and processblock != False)):
+                continue
+
             if block.startswith("STRINGTABLE"):
                 #print "stringtable:\n %s------\n" % block
-                for match in STRINGTABLE_RE.finditer(block): 
+                for match in STRINGTABLE_RE.finditer(block):
                     if not match.groupdict()['value']:
                         continue
                     newunit = rcunit(escape_to_python(match.groupdict()['value']))
                     newunit.name = "STRINGTABLE." + match.groupdict()['name']
-                    newunit.match = match 
+                    newunit.match = match
                     self.addunit(newunit)
-            if block.startswith("LANGUAGE"):
-                #print "language"
-                if not languagesection:
-                    languagesection = True
-                else:
-                    print >> sys.stderr, "Can only process one language section"
-                    self.blocks = self.blocks[:blocknum]
-                    break
             if block.startswith("/*"):  # Comments
                 #print "comment"
                 pass
@@ -194,12 +201,12 @@
                         newunit.name = "%s.%s.%s.%s" % (dialogtype, dialogname, type, value.replace(" ", "_"))
                     else:
                         newunit.name = "%s.%s.%s.%s" % (dialogtype, dialogname, type, name)
-                    newunit.match = match 
+                    newunit.match = match
                     self.addunit(newunit)
             if re.match("[0-9A-Z_]+\s+MENU", block) is not None:
                 menuname = re.match("(?P<menuname>[0-9A-Z_]+)\s+MENU", block).groupdict()["menuname"]
                 #print "menu: %s" % menuname
-                for match in DIALOG_RE.finditer(block):
+                for match in MENU_RE.finditer(block):
                     if not match.groupdict()['value']:
                         continue
                     type = match.groupdict()['type']
@@ -212,10 +219,9 @@
                         newunit.name = "MENU.%s.%s.%s" % (menuname, type, value.replace(" ", "_"))
                     else:
                         newunit.name = "MENU.%s.%s.%s" % (menuname, type, name)
-                    newunit.match = match 
+                    newunit.match = match
                     self.addunit(newunit)
-         
+
     def __str__(self):
         """convert the units back to lines"""
         return "".join(self.blocks)
-

Modified: translate-toolkit/branches/upstream/current/translate/storage/statsdb.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/statsdb.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/statsdb.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/statsdb.py Fri Jul 24 16:25:46 2009
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2007 Zuza Software Foundation
+# Copyright 2007-2009 Zuza Software Foundation
 #
 # This file is part of translate.
 #
@@ -110,11 +110,11 @@
 def transaction(f):
     """Modifies f to commit database changes if it executes without exceptions.
     Otherwise it rolls back the database.
-    
+
     ALL publicly accessible methods in StatsCache MUST be decorated with this
     decorator.
     """
-    
+
     def decorated_f(self, *args, **kwargs):
         try:
             result = f(self, *args, **kwargs)
@@ -124,7 +124,8 @@
             # If ANY exception is raised, we're left in an
             # uncertain state and we MUST roll back any changes to avoid getting
             # stuck in an inconsistent state.
-            self.con.rollback()
+            if self.con:
+                self.con.rollback()
             raise
     return decorated_f
 
@@ -171,12 +172,12 @@
             if state_for_db is TRANSLATED:
                 record['translated'] = 1
                 record['translatedsourcewords'] = sourcewords
-                record['translatedtargetwords'] = targetwords                
+                record['translatedtargetwords'] = targetwords
             elif state_for_db is FUZZY:
                 record['fuzzy'] = 1
                 record['fuzzysourcewords'] = sourcewords
         return record
-        
+
     new_record = classmethod(new_record)
 
     def _compute_derived_values(cls, record):
@@ -254,7 +255,7 @@
             def connect(cache):
                 cache.con = dbapi2.connect(statsfile)
                 cache.cur = cache.con.cursor()
-            
+
             def clear_old_data(cache):
                 try:
                     cache.cur.execute("""SELECT toolkitbuild FROM files""")
@@ -268,7 +269,7 @@
                     return False
                 except dbapi2.OperationalError:
                     return False
-            
+
             cache = cls._caches[statsfile] = object.__new__(cls)
             connect(cache)
             if clear_old_data(cache):
@@ -293,11 +294,11 @@
         # First see if a cache for this file already exists:
         if statsfile in cls._caches:
             return cls._caches[statsfile]
-        # No existing cache. Let's build a new one and keep a copy        
+        # No existing cache. Let's build a new one and keep a copy
         return make_database(statsfile)
 
     def create(self):
-        """Create all tables and indexes."""        
+        """Create all tables and indexes."""
         self.file_totals = FileTotals(self.cur)
 
         self.cur.execute("""CREATE TABLE IF NOT EXISTS files(
@@ -344,14 +345,15 @@
     create = transaction(create)
 
     def _getfileid(self, filename, check_mod_info=True, store=None):
-        """Attempt to find the fileid of the given file, if it hasn't been
-           updated since the last record update.
-
-           None is returned if either the file's record is not found, or if it is
-           not up to date.
-
-           @param filename: the filename to retrieve the id for
-           @rtype: String or None
+        """return fileid representing the given file in the statscache.
+
+        if file not in cache or has been updated since last record
+        update, recalculate stats.
+
+        optional argument store can be used to avoid unnessecary
+        reparsing of already loaded translation files.
+
+        store can be a TranslationFile object or a callback that returns one.
         """
         realpath = os.path.realpath(filename)
         self.cur.execute("""SELECT fileid, st_mtime, st_size FROM files
@@ -370,7 +372,11 @@
                 return fileid
         # We can only ignore the mod_info if the row already exists:
         assert check_mod_info
-        store = store or factory.getobject(realpath)
+        if callable(store):
+            store = store()
+        else:
+            store = store or factory.getobject(realpath)
+            
         return self._cachestore(store, realpath, mod_info)
 
     def _getstoredcheckerconfig(self, checker):
@@ -422,10 +428,10 @@
         self._cacheunitstats(store.units, fileid)
         return fileid
 
-    def filetotals(self, filename):
+    def filetotals(self, filename, store=None):
         """Retrieves the statistics for the given file if possible, otherwise
         delegates to cachestore()."""
-        return self.file_totals[self._getfileid(filename)]
+        return self.file_totals[self._getfileid(filename, store=store)]
     filetotals = transaction(filetotals)
 
     def _cacheunitschecks(self, units, fileid, configid, checker, unitindex=None):
@@ -495,7 +501,7 @@
         This method assumes that everything was up to date before (file totals,
         checks, checker config, etc."""
         fileid = self._getfileid(filename, check_mod_info=False)
-        configid = self._getstoredcheckerconfig(checker)
+        configid = self._get_config_id(fileid, checker)
         unitid = unit.getid()
         # get the unit index
         totals_without_unit = self.file_totals[fileid] - \
@@ -527,10 +533,14 @@
         first, cur = geterrors()
         if first is not None:
             return first, cur
-        
+
         # This could happen if we haven't done the checks before, or the
         # file changed, or we are using a different configuration
-        store = store or factory.getobject(filename)
+        if callable(store):
+            store = store()
+        else:
+            store = store or factory.getobject(filename)
+            
         if os.path.exists(suggestion_filename(filename)):
             checker.setsuggestionstore(factory.getobject(suggestion_filename(filename), ignore=suggestion_extension()))
         self._cachestorechecks(fileid, store, checker, configid)
@@ -582,25 +592,32 @@
             WHERE fileid=? and configid=? and name=?;""", (fileid, configid, name))
         return self.cur.fetchone() is not None
     file_fails_test = transaction(file_fails_test)
-        
+
+    def filestatestats(self, filename, store=None):
+        """Return a dictionary of unit stats mapping sets of unit
+        undices with those states"""
+        stats = emptyfilestats()
+        fileid = self._getfileid(filename, store=store)
+
+        self.cur.execute("""SELECT
+            state,
+            unitindex
+            FROM units WHERE fileid=?
+            ORDER BY unitindex;""", (fileid,))
+        values = self.cur.fetchall()
+
+        for value in values:
+            stats[state_strings[value[0]]].append(value[1])
+            stats["total"].append(value[1])
+
+        return stats
+
     def filestats(self, filename, checker, store=None):
         """Return a dictionary of property names mapping sets of unit
         indices with those properties."""
         stats = emptyfilestats()
         stats.update(self.filechecks(filename, checker, store))
-        fileid = self._getfileid(filename, store=store)
-
-        self.cur.execute("""SELECT
-            state,
-            unitindex
-            FROM units WHERE fileid=?
-            ORDER BY unitindex;""", (fileid,))
-
-        values = self.cur.fetchall()
-        for value in values:
-            stats[state_strings[value[0]]].append(value[1])
-            stats["total"].append(value[1])
-
+        stats.update(self.filestatestats(filename, store))
         return stats
     filestats = transaction(filestats)
 

Added: translate-toolkit/branches/upstream/current/translate/storage/subtitles.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/subtitles.py?rev=1813&op=file
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/subtitles.py (added)
+++ translate-toolkit/branches/upstream/current/translate/storage/subtitles.py Fri Jul 24 16:25:46 2009
@@ -1,0 +1,89 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# 
+# Copyright 2008-2009 Zuza Software Foundation
+# 
+# This file is part of translate.
+#
+# translate is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# translate is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with translate; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""Class that manages subtitle files for translation
+
+   This class makes use of the subtitle functionality of L{gaupol}
+   @see: gaupo/agents/open.py::open_main
+
+   a patch to gaupol is required to open utf-8 files successfully
+"""
+from translate.storage import base
+from StringIO import StringIO
+import gaupol
+
+class SubtitleUnit(base.TranslationUnit):
+    """A subtitle entry that is translatable"""
+
+    def __init__(self, source=None, encoding="utf-8"):
+        self._start = None
+        self._end = None
+        if source:
+            self.source = source
+        super(SubtitleUnit, self).__init__(source)
+
+    def getlocations(self):
+        return ["%s-->%s" % (self._start, self._end)]
+
+class SubtitleFile(base.TranslationStore):
+    """A subtitle file"""
+    UnitClass = SubtitleUnit
+    def __init__(self, inputfile=None, unitclass=UnitClass):
+        """construct an Subtitle file, optionally reading in from inputfile."""
+        self.UnitClass = unitclass
+        base.TranslationStore.__init__(self, unitclass=unitclass)
+        self.units = []
+        self.filename = ''
+        self._subtitlefile = None
+        self._encoding = 'utf-8'
+        if inputfile is not None:
+            self.parse(inputfile)
+
+    def __str__(self):
+        subtitles = []
+        for unit in self.units:
+            subtitle = gaupol.subtitle.Subtitle()
+            subtitle.main_text = unit.target or unit.source
+            subtitle.start = unit._start
+            subtitle.end = unit._end
+            subtitles.append(subtitle)
+        output = StringIO()
+        self._subtitlefile.write_to_file(subtitles, gaupol.documents.MAIN, output)
+        return output.getvalue().encode(self._subtitlefile.encoding)
+
+
+    def parse(self, input):
+        """parse the given file"""
+        if hasattr(input, 'name'):
+            self.filename = input.name
+        elif not getattr(self, 'filename', ''):
+            self.filename = ''
+        input.close()
+        self._encoding = gaupol.encodings.detect(self.filename)
+        if self._encoding == 'ascii':
+            self._encoding = 'utf-8'
+        self._format = gaupol.FormatDeterminer().determine(self.filename, self._encoding)
+        self._subtitlefile = gaupol.files.new(self._format, self.filename, self._encoding)
+        for subtitle in self._subtitlefile.read():
+            newunit = self.addsourceunit(subtitle.main_text)
+            newunit._start = subtitle.start
+            newunit._end =  subtitle.end
+            newunit.addnote("visible for %d seconds" % subtitle.duration_seconds, "developer")

Modified: translate-toolkit/branches/upstream/current/translate/storage/tbx.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/tbx.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/tbx.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/tbx.py Fri Jul 24 16:25:46 2009
@@ -31,7 +31,7 @@
     rootNode = "termEntry"
     languageNode = "langSet"
     textNode = "term"
-                   
+
     def createlanguageNode(self, lang, text, purpose):
         """returns a langset xml Element setup with given parameters"""
         if isinstance(text, str):
@@ -47,7 +47,7 @@
 class tbxfile(lisa.LISAfile):
     """Class representing a TBX file store."""
     UnitClass = tbxunit
-    Name = _("TBX file")
+    Name = _("TBX Glossary")
     Mimetypes  = ["application/x-tbx"]
     Extensions = ["tbx"]
     rootNode = "martif"

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_base.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_base.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_base.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_base.py Fri Jul 24 16:25:46 2009
@@ -1,9 +1,28 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
+#
+# Copyright 2008-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """tests for storage base classes"""
 
+from translate.misc.multistring import multistring
 from translate.storage import base
+from translate.storage.placeables import general, parse as rich_parse
 from py import test
 import os
 import warnings
@@ -127,6 +146,44 @@
         actual_notes = unit.getnotes()
         assert actual_notes == expected_notes
 
+    def test_rich_get(self):
+        """Basic test for converting from multistrings to StringElem trees."""
+        target_mstr = multistring([u'tÄ—st', u'<b>string</b>'])
+        unit = self.UnitClass(multistring([u'a', u'b']))
+        unit.rich_parsers = general.parsers
+        unit.target = target_mstr
+        elems = unit.rich_target
+
+        if unit.hasplural():
+            assert len(elems) == 2
+            assert len(elems[0].sub) == 1
+            assert len(elems[1].sub) == 3
+
+            assert unicode(elems[0]) == target_mstr.strings[0]
+            assert unicode(elems[1]) == target_mstr.strings[1]
+
+            assert unicode(elems[1].sub[0]) == u'<b>'
+            assert unicode(elems[1].sub[1]) == u'string'
+            assert unicode(elems[1].sub[2]) == u'</b>'
+        else:
+            assert len(elems[0].sub) == 1
+            assert unicode(elems[0]) == target_mstr.strings[0]
+
+    def test_rich_set(self):
+        """Basic test for converting from multistrings to StringElem trees."""
+        elems = [
+            rich_parse(u'Tëst <x>string</x>', general.parsers),
+            rich_parse(u'Another test string.', general.parsers),
+        ]
+        unit = self.UnitClass(multistring([u'a', u'b']))
+        unit.rich_target = elems
+
+        if unit.hasplural():
+            assert unit.target.strings[0] == u'Tëst <x>string</x>'
+            assert unit.target.strings[1] == u'Another test string.'
+        else:
+            assert unit.target == u'Tëst <x>string</x>'
+
 class TestTranslationStore(object):
     """Tests a TranslationStore.
     Derived classes can reuse these tests by pointing StoreClass to a derived Store"""

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_cpo.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_cpo.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_cpo.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_cpo.py Fri Jul 24 16:25:46 2009
@@ -48,7 +48,7 @@
         unit.target = "Boom"
         # FIXME: currently assigning the target to the same as the first string won't change anything
         # we need to verify that this is the desired behaviour...
-        assert unit.target.strings == ["Boom", "Bome"]
+        assert unit.target.strings[0] == "Boom"
         unit.target = "Een Boom"
         assert unit.target.strings == ["Een Boom"]
 

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_dtd.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_dtd.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_dtd.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_dtd.py Fri Jul 24 16:25:46 2009
@@ -33,6 +33,12 @@
 
 class TestDTDUnit(test_monolingual.TestMonolingualUnit):
     UnitClass = dtd.dtdunit
+
+    def test_rich_get(self):
+        pass
+
+    def test_rich_set(self):
+        pass
 
     
 class TestDTD(test_monolingual.TestMonolingualStore):

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_monolingual.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_monolingual.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_monolingual.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_monolingual.py Fri Jul 24 16:25:46 2009
@@ -14,6 +14,12 @@
     def test_target(self):
         pass
 
+    def test_rich_get(self):
+        pass
+
+    def test_rich_set(self):
+        pass
+
 
 class TestMonolingualStore(test_base.TestTranslationStore):
     StoreClass = base.TranslationStore

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_po.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_po.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_po.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_po.py Fri Jul 24 16:25:46 2009
@@ -2,10 +2,10 @@
 # -*- coding: utf-8 -*-
 
 from translate.storage import po
+from translate.storage import pypo
 from translate.storage import test_base
 from translate.misc import wStringIO
 from translate.misc.multistring import multistring
-from translate.storage.placeables import X, G
 from py.test import raises
 
 def test_roundtrip_quoting():
@@ -15,8 +15,8 @@
                 '\n', '\t', '\r', 
                 '\\n', '\\t', '\\r', '\\"', '\r\n', '\\r\\n', '\\']
     for special in specials:
-        quoted_special = po.quoteforpo(special)
-        unquoted_special = po.unquotefrompo(quoted_special)
+        quoted_special = pypo.quoteforpo(special)
+        unquoted_special = pypo.unquotefrompo(quoted_special)
         print "special: %r\nquoted: %r\nunquoted: %r\n" % (special, quoted_special, unquoted_special)
         assert special == unquoted_special
 
@@ -90,17 +90,15 @@
         # plain text, no plural test
         unit = self.UnitClass("Tree")
         unit.target = "ki"
-        assert unit.target.strings == ["ki"]
-        assert unit.source.strings == ["Tree"]
         assert unit.hasplural() == False
-        
+
         # plural test with multistring
         unit.setsource(["Tree", "Trees"])
         assert unit.source.strings == ["Tree", "Trees"]
         assert unit.hasplural()
         unit.target = multistring(["ki", "ni ki"])
         assert unit.target.strings == ["ki", "ni ki"]
-        
+
         # test of msgid with no plural and msgstr with plural
         unit = self.UnitClass("Tree")
         assert raises(ValueError, unit.settarget, [u"ki", u"ni ki"])
@@ -166,6 +164,18 @@
         print oldunit
         return str(oldunit)
 
+    def test_context_only(self):
+        """Checks that an empty msgid with msgctxt is handled correctly."""
+        posource = '''msgctxt "CONTEXT"
+msgid ""
+msgstr ""
+'''
+        pofile = self.poparse(posource)
+        assert pofile.units[0].istranslatable()
+        assert not pofile.units[0].isheader()
+        # we were not generating output for thse at some stage
+        assert str(pofile)
+
     def test_simpleentry(self):
         """checks that a simple po entry is parsed correctly"""
         posource = '#: test.c:100 test.c:101\nmsgid "test"\nmsgstr "rest"\n'
@@ -378,6 +388,7 @@
         unit = pofile.units[1]
         assert unit.isobsolete()
 
+        print str(pofile)
         assert str(pofile) == posource
         unit.resurrect()
         assert unit.hasplural()

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_poheader.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_poheader.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_poheader.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_poheader.py Fri Jul 24 16:25:46 2009
@@ -243,3 +243,21 @@
     assert nplural == "3"
     assert plural == "(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)"
 ##    TODO: add the same test for PoXliffFile
+
+def test_updatecontributor():
+    """Test that we can update contributor information in the header comments."""
+    posource = r'''msgid ""
+msgstr ""
+"MIME-Version: 1.0"
+'''
+    pofile = poparse(posource)
+    pofile.updatecontributor("Grasvreter")
+    assert "# Grasvreter, 20" in str(pofile)
+
+    pofile.updatecontributor("Koeivreter", "monster at grasveld.moe")
+    assert "# Koeivreter <monster at grasveld.moe>, 20" in str(pofile)
+
+    pofile.header().addnote("Khaled Hosny <khaledhosny at domain.org>, 2006, 2007, 2008.")
+    pofile.updatecontributor("Khaled Hosny", "khaledhosny at domain.org")
+    print str(pofile)
+    assert "# Khaled Hosny <khaledhosny at domain.org>, 2006, 2007, 2008, %s." % time.strftime("%Y") in str(pofile)

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_properties.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_properties.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_properties.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_properties.py Fri Jul 24 16:25:46 2009
@@ -4,6 +4,42 @@
 from translate.storage import properties
 from translate.storage import test_monolingual
 from translate.misc import wStringIO
+
+def test_find_delimeter_pos_simple():
+    assert properties.find_delimeter("key=value") == ('=', 3)
+    assert properties.find_delimeter("key:value") == (':', 3)
+    assert properties.find_delimeter("key value") == (' ', 3)
+    assert properties.find_delimeter("= value") == ('=', 0)
+
+def test_find_delimeter_pos_whitespace():
+    assert properties.find_delimeter("key = value") == ('=', 4)
+    assert properties.find_delimeter("key : value") == (':', 4)
+    assert properties.find_delimeter("key   value") == (' ', 3)
+    assert properties.find_delimeter("key key = value") == (' ', 3)
+    assert properties.find_delimeter("key value value") == (' ', 3)
+    assert properties.find_delimeter(" key = value") == ('=', 5)
+
+def test_find_delimeter_pos_escapes():
+    assert properties.find_delimeter("key\:=value") == ('=', 5)
+    assert properties.find_delimeter("key\=: value") == (':', 5)
+    assert properties.find_delimeter("key\   value") == (' ', 5)
+    assert properties.find_delimeter("key\ key\ key\: = value") == ('=', 16)
+
+def test_is_line_continuation():
+    assert properties.is_line_continuation("") == False
+    assert properties.is_line_continuation("some text") == False
+    assert properties.is_line_continuation("""some text\\""") == True
+    assert properties.is_line_continuation("""some text\\\\""") == False  # Escaped \
+    assert properties.is_line_continuation("""some text\\\\\\""") == True  # Odd num. \ is line continuation
+    assert properties.is_line_continuation("""\\\\\\""") == True
+
+def test_key_strip():
+    assert properties.key_strip("key") == "key"
+    assert properties.key_strip(" key") == "key"
+    assert properties.key_strip("\ key") == "\ key"
+    assert properties.key_strip("key ") == "key"
+    assert properties.key_strip("key\ ") == "key\ "
+
 
 class TestPropUnit(test_monolingual.TestMonolingualUnit):
     UnitClass = properties.propunit
@@ -18,13 +54,19 @@
         """
         pass
 
+    def test_rich_get(self):
+        pass
+
+    def test_rich_set(self):
+        pass
+
 class TestProp(test_monolingual.TestMonolingualStore):
     StoreClass = properties.propfile
     
-    def propparse(self, propsource):
+    def propparse(self, propsource, personality="java"):
         """helper that parses properties source without requiring files"""
         dummyfile = wStringIO.StringIO(propsource)
-        propfile = properties.propfile(dummyfile)
+        propfile = properties.propfile(dummyfile, personality)
         return propfile
 
     def propregen(self, propsource):
@@ -50,7 +92,7 @@
         """check that escapes unicode is converted properly"""
         propsource = "unicode=\u0411\u0416\u0419\u0428"
         messagevalue = u'\u0411\u0416\u0419\u0428'.encode("UTF-8")
-        propfile = self.propparse(propsource)
+        propfile = self.propparse(propsource, personality="mozilla")
         assert len(propfile.units) == 1
         propunit = propfile.units[0]
         assert propunit.name == "unicode"
@@ -60,16 +102,56 @@
         assert "\\u" not in regensource
 
     def test_newlines_startend(self):
-        """check that we preserver \n that appear at start and end of properties"""
+        """check that we preserve \n that appear at start and end of properties"""
         propsource = "newlines=\\ntext\\n"
         propregen = self.propregen(propsource)
         assert propsource + '\n' == propregen
 
-    def test_whitespace_removal(self):
+    def test_whitespace_handling(self):
         """check that we remove extra whitespace around property"""
-        propsource = '''  whitespace  =  Start \n'''
-        propfile = self.propparse(propsource)
-        propunit = propfile.units[0]
-        assert propunit.name == "whitespace"
-        assert propunit.source == "Start"
+        whitespaces = (('key = value', 'key', 'value'),      # Standard for baseline
+                       (' key =  value', 'key', 'value'),    # Extra \s before key and value
+                       ('\ key\ = value', '\ key\ ', 'value'), # extra space at start and end of key
+                       ('key = \ value ', 'key', ' value '), # extra space at start end end of value
+                      )
+        for propsource, key, value in whitespaces:
+            propfile = self.propparse(propsource)
+            propunit = propfile.units[0]
+            print repr(propsource), repr(propunit.name), repr(propunit.source)
+            assert propunit.name == key
+            assert propunit.source == value
      
+    def test_key_value_delimeters_simple(self):
+        """test that we can handle colon, equals and space delimeter
+        between key and value.  We don't test any space removal or escaping"""
+        delimeters = [":", "=", " "]
+        for delimeter in delimeters:
+            propsource = "key%svalue" % delimeter
+            print "source: '%s'\ndelimeter: '%s'" % (propsource, delimeter)
+            propfile = self.propparse(propsource)
+            assert len(propfile.units) == 1
+            propunit = propfile.units[0]
+            assert propunit.name == "key"
+            assert propunit.source == "value"
+
+    def test_comments(self):
+        """checks that we handle # and ! comments"""
+        markers = ['#', '!']
+        for comment_marker in markers:
+            propsource = '''%s A comment
+key=value
+''' % comment_marker
+            propfile = self.propparse(propsource)
+            print repr(propsource)
+            print "Comment marker: '%s'" % comment_marker
+            assert len(propfile.units) == 1
+            propunit = propfile.units[0]
+            assert propunit.comments == ['%s A comment' % comment_marker]
+
+    def test_latin1(self):
+        """checks that we handle non-escaped latin1 text"""
+        prop_source = u"key=valú".encode('latin1')
+        prop_store = self.propparse(prop_source)
+        assert len(prop_store.units) == 1
+        unit = prop_store.units[0]
+        assert unit.source == u"valú"

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_pypo.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_pypo.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_pypo.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_pypo.py Fri Jul 24 16:25:46 2009
@@ -175,31 +175,6 @@
         print pofile.units[1].msgidcomments
         assert pypo.unquotefrompo(pofile.units[0].msgidcomments) == "_: source1\n"
         assert pypo.unquotefrompo(pofile.units[1].msgidcomments) == "_: source2\n"
-
-    def test_msgid_comment(self):
-        """checks that when adding msgid_comments we place them on a newline"""
-        posource = '#: source0\nmsgid "Same"\nmsgstr ""\n\n#: source1\nmsgid "Same"\nmsgstr ""\n'
-        pofile = self.poparse(posource)
-        assert len(pofile.units) == 2
-        pofile.removeduplicates("msgid_comment")
-        assert len(pofile.units) == 2
-        assert pypo.unquotefrompo(pofile.units[0].msgidcomments) == "_: source0\n"
-        assert pypo.unquotefrompo(pofile.units[1].msgidcomments) == "_: source1\n"
-        # Now lets check for formating
-        for i in (0, 1):
-            expected = '''#: source%d\nmsgid ""\n"_: source%d\\n"\n"Same"\nmsgstr ""\n''' % (i, i)
-            assert pofile.units[i].__str__() == expected
-
-    def test_keep_blanks(self):
-        """checks that keeping keeps blanks and doesn't add msgid_comments"""
-        posource = '#: source1\nmsgid ""\nmsgstr ""\n\n#: source2\nmsgid ""\nmsgstr ""\n'
-        pofile = self.poparse(posource)
-        assert len(pofile.units) == 2
-        pofile.removeduplicates("keep")
-        assert len(pofile.units) == 2
-        # check we don't add msgidcomments
-        assert pypo.unquotefrompo(pofile.units[0].msgidcomments) == ""
-        assert pypo.unquotefrompo(pofile.units[1].msgidcomments) == ""
 
     def test_output_str_unicode(self):
         """checks that we can str(element) which is in unicode"""
@@ -248,6 +223,7 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8-bit\n"
 
+#, fuzzy
 #| msgid "trea"
 msgid "tree"
 msgstr "boom"

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_tmx.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_tmx.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_tmx.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_tmx.py Fri Jul 24 16:25:46 2009
@@ -6,6 +6,7 @@
 
 class TestTMXUnit(test_base.TestTranslationUnit):
     UnitClass = tmx.tmxunit
+
 
 class TestTMXUnitFromParsedString(TestTMXUnit):
     tmxsource = '''<?xml version="1.0" encoding="utf-8"?>

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_ts2.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_ts2.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_ts2.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_ts2.py Fri Jul 24 16:25:46 2009
@@ -1,11 +1,45 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2008-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
+from lxml import etree
+
+from translate.misc.multistring import multistring
 from translate.storage import ts2 as ts
 from translate.storage import test_base
+from translate.storage.placeables import parse
+from translate.storage.placeables import xliff
+from translate.storage.placeables.lisa import xml_to_strelem
+
+
+xliffparsers = []
+for attrname in dir(xliff):
+    attr = getattr(xliff, attrname)
+    if  type(attr) is type and attrname not in ('XLIFFPlaceable') and hasattr(attr, 'parse') and attr.parse is not None:
+        xliffparsers.append(attr.parse)
+
+def rich_parse(s):
+    return parse(s, xliffparsers)
+
 
 class TestTSUnit(test_base.TestTranslationUnit):
     UnitClass = ts.tsunit
-
 
 class TestTSfile(test_base.TestTranslationStore):
     StoreClass = ts.tsfile

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_wordfast.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_wordfast.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_wordfast.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_wordfast.py Fri Jul 24 16:25:46 2009
@@ -74,5 +74,6 @@
         unit.target = "Rest"
         assert unit.istranslated()
 
+
 class TestWFFile(test_base.TestTranslationStore):
     StoreClass = wf.WordfastTMFile

Modified: translate-toolkit/branches/upstream/current/translate/storage/test_xliff.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/test_xliff.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/test_xliff.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/test_xliff.py Fri Jul 24 16:25:46 2009
@@ -1,12 +1,13 @@
 #!/usr/bin/env python
 
-from translate.storage import xliff
+from translate.storage import xliff, lisa
 from translate.storage import test_base
-from translate.storage.placeables import X, G
+from translate.storage.placeables import StringElem
+from translate.storage.placeables.xliff import X, G
 
 class TestXLIFFUnit(test_base.TestTranslationUnit):
     UnitClass = xliff.xliffunit
-   
+
     def test_isfuzzy(self):
         """The default behaviour for XLIFF is different, so we adapt the test
         from test_base.py"""
@@ -50,6 +51,7 @@
         unit.adderror(errorname='test1', errortext='New error 1.')
         assert unit.geterrors()['test1'] == 'New error 1.'
 
+
 class TestXLIFFfile(test_base.TestTranslationStore):
     StoreClass = xliff.xlifffile
     skeleton = '''<?xml version="1.0" encoding="utf-8"?>
@@ -78,72 +80,77 @@
         xliffunit = xlifffile.addsourceunit(u'')
 
         # Test 1
-        xliffunit.rich_source = [['foo', X('bar'), 'baz']]
+        xliffunit.rich_source = [StringElem([u'foo', X(id='bar'), u'baz'])]
         source_dom_node = xliffunit.getlanguageNode(None, 0)
         x_placeable = source_dom_node[0]
 
         assert source_dom_node.text == 'foo'
-        
+
         assert x_placeable.tag == u'x'
         assert x_placeable.attrib['id'] == 'bar'
         assert x_placeable.tail == 'baz'
-        
-        assert xliffunit.rich_source == [['foo', X('bar'), 'baz']]
+
+        xliffunit.rich_source[0].print_tree(2)
+        print xliffunit.rich_source
+        assert xliffunit.rich_source == [StringElem([StringElem(u'foo'), X(id='bar'), StringElem(u'baz')])]
 
         # Test 2
-        xliffunit.rich_source = [['foo', 'baz', G('oof', [G('zab', ['bar', 'rab'])])]]
+        xliffunit.rich_source = [StringElem([u'foo', u'baz', G(id='oof', sub=[G(id='zab', sub=[u'bar', u'rab'])])])]
         source_dom_node = xliffunit.getlanguageNode(None, 0)
         g_placeable = source_dom_node[0]
         nested_g_placeable = g_placeable[0]
 
         assert source_dom_node.text == u'foobaz'
-        
+
         assert g_placeable.tag == u'g'
-        assert g_placeable.text == u''
+        assert g_placeable.text is None
         assert g_placeable.attrib[u'id'] == u'oof'
-        assert g_placeable.tail == u''
-        
+        assert g_placeable.tail is None
+
         assert nested_g_placeable.tag == u'g'
         assert nested_g_placeable.text == u'barrab'
         assert nested_g_placeable.attrib[u'id'] == u'zab'
-        assert nested_g_placeable.tail == u''
-        
+        assert nested_g_placeable.tail is None
+
         rich_source = xliffunit.rich_source
-        assert rich_source == [['foobaz', G('oof', [G('zab', ['barrab'])])]]
+        rich_source[0].print_tree(2)
+        assert rich_source == [StringElem([u'foobaz', G(id='oof', sub=[G(id='zab', sub=[u'barrab'])])])]
 
     def test_rich_target(self):
         xlifffile = xliff.xlifffile()
         xliffunit = xlifffile.addsourceunit(u'')
 
         # Test 1
-        xliffunit.set_rich_target([['foo', X('bar'), 'baz']], 'fr')
+        xliffunit.set_rich_target([StringElem([u'foo', X(id='bar'), u'baz'])], u'fr')
         target_dom_node = xliffunit.getlanguageNode(None, 1)
         x_placeable = target_dom_node[0]
-        
+
         assert target_dom_node.text == 'foo'
         assert x_placeable.tag == u'x'
         assert x_placeable.attrib['id'] == 'bar'
         assert x_placeable.tail == 'baz'
 
         # Test 2
-        xliffunit.set_rich_target([['foo', 'baz', G('oof', [G('zab', ['bar', 'rab'])])]], 'fr')
+        xliffunit.set_rich_target([StringElem([u'foo', u'baz', G(id='oof', sub=[G(id='zab', sub=[u'bar', u'rab'])])])], u'fr')
         target_dom_node = xliffunit.getlanguageNode(None, 1)
         g_placeable = target_dom_node[0]
         nested_g_placeable = g_placeable[0]
 
         assert target_dom_node.text == u'foobaz'
-        
+
         assert g_placeable.tag == u'g'
-        assert g_placeable.text == u''
+        print 'g_placeable.text: %s (%s)' % (g_placeable.text, type(g_placeable.text))
+        assert g_placeable.text is None
         assert g_placeable.attrib[u'id'] == u'oof'
-        assert g_placeable.tail == u''
-        
+        assert g_placeable.tail is None
+
         assert nested_g_placeable.tag == u'g'
         assert nested_g_placeable.text == u'barrab'
         assert nested_g_placeable.attrib[u'id'] == u'zab'
-        assert nested_g_placeable.tail == u''
-        
-        assert xliffunit.rich_target == [['foobaz', G('oof', [G('zab', ['barrab'])])]]
+        assert nested_g_placeable.tail is None
+
+        xliffunit.rich_target[0].print_tree(2)
+        assert xliffunit.rich_target == [StringElem([u'foobaz', G(id='oof', sub=[G(id='zab', sub=[u'barrab'])])])]
 
     def test_source(self):
         xlifffile = xliff.xlifffile()
@@ -153,7 +160,7 @@
         print str(xlifffile)
         assert newfile.findunit("Concept") is None
         assert newfile.findunit("Term") is not None
-    
+
     def test_target(self):
         xlifffile = xliff.xlifffile()
         xliffunit = xlifffile.addsourceunit("Concept")
@@ -166,16 +173,16 @@
         xlifffile = xliff.xlifffile(sourcelanguage="xh")
         xmltext = str(xlifffile)
         print xmltext
-        assert xmltext.find('source-language="xh"')> 0  
+        assert xmltext.find('source-language="xh"')> 0
         #TODO: test that it also works for new files.
 
     def test_targetlanguage(self):
         xlifffile = xliff.xlifffile(sourcelanguage="zu", targetlanguage="af")
         xmltext = str(xlifffile)
         print xmltext
-        assert xmltext.find('source-language="zu"')> 0  
-        assert xmltext.find('target-language="af"')> 0  
-            
+        assert xmltext.find('source-language="zu"')> 0
+        assert xmltext.find('target-language="af"')> 0
+
     def test_notes(self):
         xlifffile = xliff.xlifffile()
         unit = xlifffile.addsourceunit("Concept")
@@ -255,6 +262,59 @@
         assert 'approved="no"' in str(unit)
         #assert unit.isfuzzy()
 
+    def test_xml_space(self):
+        """Test for the correct handling of xml:space attributes."""
+        xlfsource = self.skeleton \
+          % '''<trans-unit id="1" xml:space="preserve">
+                   <source> File  1 </source>
+               </trans-unit>'''
+        xlifffile = xliff.xlifffile.parsestring(xlfsource)
+        assert xlifffile.units[0].source == " File  1 "
+        root_node = xlifffile.document.getroot()
+        lisa.setXMLspace(root_node, "preserve")
+        assert xlifffile.units[0].source == " File  1 "
+        lisa.setXMLspace(root_node, "default")
+        assert xlifffile.units[0].source == " File  1 "
+
+        xlfsource = self.skeleton \
+          % '''<trans-unit id="1" xml:space="default">
+                   <source> File  1 </source>
+               </trans-unit>'''
+        xlifffile = xliff.xlifffile.parsestring(xlfsource)
+        assert xlifffile.units[0].source == "File 1"
+        root_node = xlifffile.document.getroot()
+        lisa.setXMLspace(root_node, "preserve")
+        assert xlifffile.units[0].source == "File 1"
+        lisa.setXMLspace(root_node, "default")
+        assert xlifffile.units[0].source == "File 1"
+
+        xlfsource = self.skeleton \
+          % '''<trans-unit id="1">
+                   <source> File  1 </source>
+               </trans-unit>'''
+        # we currently always normalize as default behaviour for xliff
+        xlifffile = xliff.xlifffile.parsestring(xlfsource)
+        assert xlifffile.units[0].source == "File 1"
+        root_node = xlifffile.document.getroot()
+        lisa.setXMLspace(root_node, "preserve")
+        assert xlifffile.units[0].source == "File 1"
+        lisa.setXMLspace(root_node, "default")
+        assert xlifffile.units[0].source == "File 1"
+
+        xlfsource = self.skeleton \
+          % '''<trans-unit id="1">
+                   <source> File  1
+</source>
+               </trans-unit>'''
+        # we currently always normalize as default behaviour for xliff
+        xlifffile = xliff.xlifffile.parsestring(xlfsource)
+        assert xlifffile.units[0].source == "File 1"
+        root_node = xlifffile.document.getroot()
+        lisa.setXMLspace(root_node, "preserve")
+        assert xlifffile.units[0].source == "File 1"
+        lisa.setXMLspace(root_node, "default")
+        assert xlifffile.units[0].source == "File 1"
+
     def test_parsing(self):
         xlfsource = self.skeleton \
           % '''<trans-unit id="1" xml:space="preserve">
@@ -279,5 +339,3 @@
                </trans-unit>'''
         xlifffile = xliff.xlifffile.parsestring(xlfsource)
         assert xlifffile.units[0].istranslatable()
-
-

Modified: translate-toolkit/branches/upstream/current/translate/storage/tmdb.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/tmdb.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/tmdb.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/tmdb.py Fri Jul 24 16:25:46 2009
@@ -23,6 +23,7 @@
 import math
 import time
 import logging
+import re
 try:
     from sqlite3 import dbapi2
 except ImportError:
@@ -31,6 +32,8 @@
 from translate.search.lshtein import LevenshteinComparer
 from translate.lang import data
 
+
+STRIP_REGEXP = re.compile("\W", re.UNICODE)
 
 class LanguageError(Exception):
     def __init__(self, value):
@@ -270,7 +273,11 @@
         minlen = min_levenshtein_length(len(unit_source), self.min_similarity)
         maxlen = max_levenshtein_length(len(unit_source), self.min_similarity, self.max_length)
 
-        unit_words = unit_source.split()
+        # split source into words, remove punctuation and special
+        # chars, keep words that are at least 3 chars long
+        unit_words = STRIP_REGEXP.sub(' ', unit_source).split()
+        unit_words = filter(lambda word: len(word) > 2, unit_words)
+
         if self.fulltext and len(unit_words) > 3:
             logging.debug("fulltext matching")
             query = """SELECT s.text, t.text, s.context, s.lang, t.lang FROM sources s JOIN targets t ON s.sid = t.sid JOIN fulltext f ON s.sid = f.docid
@@ -296,6 +303,7 @@
                 results.append(result)
         results.sort(key=lambda match: match['quality'], reverse=True)
         results = results[:self.max_candidates]
+        logging.debug("results: %s", unicode(results))
         return results
 
 

Modified: translate-toolkit/branches/upstream/current/translate/storage/tmx.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/tmx.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/tmx.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/tmx.py Fri Jul 24 16:25:46 2009
@@ -1,24 +1,22 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2005-2007 Zuza Software Foundation
-# 
-# This file is part of translate.
+# Copyright 2005-2009 Zuza Software Foundation
 #
-# translate is free software; you can redistribute it and/or modify
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """module for parsing TMX translation memeory files"""
 
@@ -32,7 +30,7 @@
     rootNode = "tu"
     languageNode = "tuv"
     textNode = "seg"
-                   
+
     def createlanguageNode(self, lang, text, purpose):
         """returns a langset xml Element setup with given parameters"""
         if isinstance(text, str):
@@ -40,12 +38,14 @@
         langset = etree.Element(self.languageNode)
         lisa.setXMLlang(langset, lang)
         seg = etree.SubElement(langset, self.textNode)
+        # implied by the standard:
+        # lisa.setXMLspace(seg, "preserve")
         seg.text = text
         return langset
 
     def getid(self):
-        """Returns the identifier for this unit. The optional tuid property is 
-        used if available, otherwise we inherit .getid(). Note that the tuid 
+        """Returns the identifier for this unit. The optional tuid property is
+        used if available, otherwise we inherit .getid(). Note that the tuid
         property is only mandated to be unique from TMX 2.0."""
         id = self.xmlelement.get("tuid", "")
         return id or super(tmxunit, self).getid()
@@ -55,21 +55,21 @@
 
     def addnote(self, text, origin=None):
         """Add a note specifically in a "note" tag.
-        
+
         The origin parameter is ignored"""
         if isinstance(text, str):
             text = text.decode("utf-8")
         note = etree.SubElement(self.xmlelement, self.namespaced("note"))
         note.text = text.strip()
- 
+
     def getnotelist(self, origin=None):
         """Private method that returns the text from notes.
-        
+
         The origin parameter is ignored.."""
         note_nodes = self.xmlelement.iterdescendants(self.namespaced("note"))
         note_list = [lisa.getText(note) for note in note_nodes]
 
-        return note_list 
+        return note_list
 
     def getnotes(self, origin=None):
         return '\n'.join(self.getnotelist(origin=origin))
@@ -99,7 +99,7 @@
     def copy(self):
         """Make a copy of the translation unit.
 
-        We don't want to make a deep copy - this could duplicate the whole XML 
+        We don't want to make a deep copy - this could duplicate the whole XML
         tree. For now we just serialise and reparse the unit's XML."""
         #TODO: check performance
         new_unit = self.__class__(None, empty=True)
@@ -110,7 +110,7 @@
 class tmxfile(lisa.LISAfile):
     """Class representing a TMX file store."""
     UnitClass = tmxunit
-    Name = _("TMX file")
+    Name = _("TMX Translation Memory")
     Mimetypes  = ["application/x-tmx"]
     Extensions = ["tmx"]
     rootNode = "tmx"
@@ -121,7 +121,7 @@
 <header></header>
 <body></body>
 </tmx>'''
-    
+
     def addheader(self):
         headernode = self.document.getroot().iterchildren(self.namespaced("header")).next()
         headernode.set("creationtool", "Translate Toolkit - po2tmx")
@@ -146,4 +146,3 @@
     def translate(self, sourcetext, sourcelang=None, targetlang=None):
         """method to test old unit tests"""
         return getattr(self.findunit(sourcetext), "target", None)
-

Modified: translate-toolkit/branches/upstream/current/translate/storage/ts2.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/ts2.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/ts2.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/ts2.py Fri Jul 24 16:25:46 2009
@@ -1,24 +1,22 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2008 Zuza Software Foundation
-# 
-# This file is part of translate.
-#
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2008-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """Module for handling Qt linguist (.ts) files.
 
@@ -27,6 +25,7 @@
 both.
 
 U{TS file format 4.3<http://doc.trolltech.com/4.3/linguist-ts-file-format.html>}, 
+U{http://doc.trolltech.com/4.5/linguist-ts-file-format.html>},
 U{Example<http://svn.ez.no/svn/ezcomponents/trunk/Translation/docs/linguist-format.txt>}, 
 U{Plurals forms<http://www.koders.com/cpp/fidE7B7E83C54B9036EB7FA0F27BC56BCCFC4B9DF34.aspx#L200>}
 
@@ -34,7 +33,8 @@
 U{2 <http://doc.trolltech.com/4.3/qstring.html#arg-2>}
 """
 
-from translate.storage import lisa
+from translate.storage import base, lisa
+from translate.storage.placeables import general, StringElem
 from translate.misc.multistring import multistring
 from translate.lang import data
 from lxml import etree
@@ -67,6 +67,7 @@
     languageNode = "source"
     textNode = ""
     namespace = ''
+    rich_parsers = general.parsers
 
     def createlanguageNode(self, lang, text, purpose):
         """Returns an xml Element setup with given parameters."""
@@ -101,6 +102,7 @@
         else:
             return data.forceunicode(sourcenode.text)
     source = property(getsource, lisa.LISAunit.setsource)
+    rich_source = property(base.TranslationUnit._get_rich_source, base.TranslationUnit._set_rich_source)
 
     def settarget(self, text):
         # This is a fairly destructive implementation. Don't assume that this
@@ -121,7 +123,8 @@
         targetnode.clear()
         if type:
             targetnode.set("type", type)
-        if self.hasplural():
+        if self.hasplural() or len(strings) > 1:
+            self.xmlelement.set("numerus", "yes")
             for string in strings:
                 numerus = etree.SubElement(targetnode, self.namespaced("numerusform"))
                 numerus.text = data.forceunicode(string) or u""
@@ -139,6 +142,7 @@
         else:
             return data.forceunicode(targetnode.text) or u""
     target = property(gettarget, settarget)
+    rich_target = property(base.TranslationUnit._get_rich_target, base.TranslationUnit._set_rich_target)
 
     def hasplural(self):
         return self.xmlelement.get("numerus") == "yes"
@@ -168,7 +172,10 @@
 
     def _gettype(self):
         """Returns the type of this translation."""
-        return self._gettargetnode().get("type")
+        targetnode = self._gettargetnode()
+        if targetnode is not None:
+            return targetnode.get("type")
+        return None
 
     def _settype(self, value=None):
         """Set the type of this translation."""

Modified: translate-toolkit/branches/upstream/current/translate/storage/versioncontrol/__init__.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/versioncontrol/__init__.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/versioncontrol/__init__.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/versioncontrol/__init__.py Fri Jul 24 16:25:46 2009
@@ -191,7 +191,11 @@
           - the absolute path of the RCS object
           - the relative path of the RCS object based on the directory above
         """
-        rcs_obj_dir = os.path.dirname(os.path.abspath(rcs_obj))
+        if os.path.isdir(os.path.abspath(rcs_obj)):
+            rcs_obj_dir = os.path.abspath(rcs_obj)
+        else:
+            rcs_obj_dir = os.path.dirname(os.path.abspath(rcs_obj))
+            
         if os.path.isdir(os.path.join(rcs_obj_dir, self.RCS_METADIR)):
             # is there a metadir next to the rcs_obj?
             # (for Subversion, CVS, ...)

Modified: translate-toolkit/branches/upstream/current/translate/storage/wordfast.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/wordfast.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/wordfast.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/wordfast.py Fri Jul 24 16:25:46 2009
@@ -38,7 +38,7 @@
    Implementation
    ==============
    The implementation covers the full requirements of a Wordfast TM file.
-   The files are simple Tab Seperated Value (TSV) files that can be read 
+   The files are simple Tab Separated Value (TSV) files that can be read 
    by Microsoft Excel and other spreadsheet programs.  They use the .txt 
    extension which does make it more difficult to automatically identify 
    such files.
@@ -51,7 +51,7 @@
    are most likely because Microsoft Word is the base editing tool for
    Wordfast.
 
-   The format is tab seperated so We are able to detect UTF-16 vs Latin1 
+   The format is tab separated so we are able to detect UTF-16 vs Latin-1 
    by searching for the occurance of a UTF-16 tab character and then
    continuing with the parsing.
 
@@ -304,7 +304,7 @@
     dict = property(getdict, setdict)
 
     def _get_source_or_target(self, key):
-        if self._dict[key] is None:
+        if self._dict.get(key, None) is None:
             return None
         elif self._dict[key]:
             return _wf_to_char(self._dict[key]).decode('utf-8')
@@ -350,7 +350,7 @@
 
 class WordfastTMFile(base.TranslationStore):
     """A Wordfast translation memory file"""
-    Name = _("Wordfast TM file")
+    Name = _("Wordfast Translation Memory")
     Mimetypes  = ["application/x-wordfast"]
     Extensions = ["txt"]
     def __init__(self, inputfile=None, unitclass=WordfastUnit):

Modified: translate-toolkit/branches/upstream/current/translate/storage/xliff.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/xliff.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/xliff.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/xliff.py Fri Jul 24 16:25:46 2009
@@ -1,33 +1,35 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2005-2007 Zuza Software Foundation
-# 
-# This file is part of translate.
+# Copyright 2005-2009 Zuza Software Foundation
 #
-# translate is free software; you can redistribute it and/or modify
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """Module for handling XLIFF files for translation.
 
 The official recommendation is to use the extention .xlf for XLIFF files.
 """
 
-from translate.storage import base
-from translate.storage import lisa
 from lxml import etree
+
+from translate.misc.multistring import multistring
+from translate.misc.xml_helpers import *
+from translate.storage import base, lisa
+from translate.storage.lisa import getXMLspace
+from translate.storage.placeables.lisa import xml_to_strelem, strelem_to_xml
 
 # TODO: handle translation types
 
@@ -39,7 +41,16 @@
     textNode = ""
     namespace = 'urn:oasis:names:tc:xliff:document:1.1'
 
+    _default_xml_space = "default"
+
     #TODO: id and all the trans-unit level stuff
+
+    def __init__(self, source, empty=False, **kwargs):
+        """Override the constructor to set xml:space="preserve"."""
+        if empty:
+            return
+        super(xliffunit, self).__init__(source, empty, **kwargs)
+        lisa.setXMLspace(self.xmlelement, "preserve")
 
     def createlanguageNode(self, lang, text, purpose):
         """Returns an xml Element setup with given parameters."""
@@ -55,7 +66,7 @@
 #        self.createPHnodes(langset, text)
         langset.text = text
         return langset
-    
+
     def getlanguageNodes(self):
         """We override this to get source and target nodes."""
         sources = list(self.xmlelement.iterdescendants(self.namespaced(self.languageNode)))
@@ -69,9 +80,53 @@
             nodes.extend(sources[- (sourcesl - targetsl):])
         return nodes
 
+    def set_rich_source(self, value, sourcelang='en'):
+        sourcelanguageNode = self.get_source_dom()
+        if sourcelanguageNode is None:
+            sourcelanguageNode = self.createlanguageNode(sourcelang, u'', "source")
+            self.set_source_dom(sourcelanguageNode)
+
+        # Clear sourcelanguageNode first
+        for i in range(len(sourcelanguageNode)):
+            del sourcelanguageNode[0]
+        sourcelanguageNode.text = None
+
+        strelem_to_xml(sourcelanguageNode, value[0])
+
+    def get_rich_source(self):
+        #rsrc = xml_to_strelem(self.source_dom)
+        #logging.debug('rich source: %s' % (repr(rsrc)))
+        #from dubulib.debug.misc import print_stack_funcs
+        #print_stack_funcs()
+        return [xml_to_strelem(self.source_dom, getXMLspace(self.xmlelement, self._default_xml_space))]
+    rich_source = property(get_rich_source, set_rich_source)
+
+    def set_rich_target(self, value, lang='xx', append=False):
+        if value is None:
+            self.set_target_dom(self.createlanguageNode(lang, u'', "target"))
+            return
+
+        languageNode = self.get_target_dom()
+        if languageNode is None:
+            languageNode = self.createlanguageNode(lang, u'', "target")
+            self.set_target_dom(languageNode, append)
+
+        # Clear languageNode first
+        for i in range(len(languageNode)):
+            del languageNode[0]
+        languageNode.text = None
+
+        strelem_to_xml(languageNode, value[0])
+
+    def get_rich_target(self, lang=None):
+        """retrieves the "target" text (second entry), or the entry in the
+        specified language, if it exists"""
+        return [xml_to_strelem(self.get_target_dom(lang), getXMLspace(self.xmlelement, self._default_xml_space))]
+    rich_target = property(get_rich_target, set_rich_target)
+
     def addalttrans(self, txt, origin=None, lang=None, sourcetxt=None, matchquality=None):
         """Adds an alt-trans tag and alt-trans components to the unit.
-        
+
         @type txt: String
         @param txt: Alternative translation of the source text.
         """
@@ -81,6 +136,7 @@
         if isinstance(txt, str):
             txt = txt.decode("utf-8")
         alttrans = etree.SubElement(self.xmlelement, self.namespaced("alt-trans"))
+        lisa.setXMLspace(alttrans, "preserve")
         alttarget = etree.SubElement(alttrans, self.namespaced("target"))
         alttarget.text = txt
         if sourcetxt:
@@ -108,13 +164,13 @@
                 # the source tag is optional
                 sourcenode = node.iterdescendants(self.namespaced("source"))
                 try:
-                    newunit.source = lisa.getText(sourcenode.next())
+                    newunit.source = lisa.getText(sourcenode.next(), getXMLspace(node, self._default_xml_space))
                 except StopIteration:
                     pass
 
                 # must have one or more targets
                 targetnode = node.iterdescendants(self.namespaced("target"))
-                newunit.target = lisa.getText(targetnode.next())
+                newunit.target = lisa.getText(targetnode.next(), getXMLspace(node, self._default_xml_space))
                 #TODO: support multiple targets better
                 #TODO: support notes in alt-trans
                 newunit.xmlelement = node
@@ -141,13 +197,13 @@
         # TODO: consider using xpath to construct initial_list directly
         # or to simply get the correct text from the outset (just remember to
         # check for duplication.
-        initial_list = [lisa.getText(note) for note in notenodes if self.correctorigin(note, origin)]
+        initial_list = [lisa.getText(note, getXMLspace(self.xmlelement, self._default_xml_space)) for note in notenodes if self.correctorigin(note, origin)]
 
         # Remove duplicate entries from list:
         dictset = {}
         notelist = [dictset.setdefault(note, note) for note in initial_list if note not in dictset]
 
-        return notelist 
+        return notelist
 
     def getnotes(self, origin=None):
         return '\n'.join(self.getnotelist(origin=origin))
@@ -209,7 +265,7 @@
 #                (targetnode.get("state-qualifier") == "fuzzy-match" or \
 #                targetnode.get("state") == "needs-review-translation")
         return not self.isapproved()
-                
+
     def markfuzzy(self, value=True):
         if value:
             self.markapproved(False)
@@ -290,15 +346,16 @@
         """Returns the contexts in the context groups with the specified name"""
         groups = []
         grouptags = self.xmlelement.iterdescendants(self.namespaced("context-group"))
+        #TODO: conbine name in query
         for group in grouptags:
             if group.get("name") == name:
                 contexts = group.iterdescendants(self.namespaced("context"))
                 pairs = []
                 for context in contexts:
-                    pairs.append((context.get("context-type"), lisa.getText(context)))
+                    pairs.append((context.get("context-type"), lisa.getText(context, getXMLspace(self.xmlelement, self._default_xml_space))))
                 groups.append(pairs) #not extend
         return groups
-        
+
     def getrestype(self):
         """returns the restype attribute in the trans-unit tag"""
         return self.xmlelement.get("restype")
@@ -326,10 +383,29 @@
         else:
             return False
 
+    def multistring_to_rich(self, mstr):
+        """Override L{TranslationUnit.multistring_to_rich} which is used by the
+            C{rich_source} and C{rich_target} properties."""
+        strings = mstr
+        if isinstance(mstr, multistring):
+            strings = mstr.strings
+        elif isinstance(mstr, basestring):
+            strings = [mstr]
+
+        return [xml_to_strelem(s) for s in strings]
+    multistring_to_rich = classmethod(multistring_to_rich)
+
+    def rich_to_multistring(self, elem_list):
+        """Override L{TranslationUnit.rich_to_multistring} which is used by the
+            C{rich_source} and C{rich_target} properties."""
+        return multistring([unicode(elem) for elem in elem_list])
+    rich_to_multistring = classmethod(rich_to_multistring)
+
+
 class xlifffile(lisa.LISAfile):
     """Class representing a XLIFF file store."""
     UnitClass = xliffunit
-    Name = _("XLIFF file")
+    Name = _("XLIFF Translation File")
     Mimetypes  = ["application/x-xliff", "application/x-xliff+xml"]
     Extensions = ["xlf", "xliff"]
     rootNode = "xliff"
@@ -342,13 +418,17 @@
 </file>
 </xliff>'''
     namespace = 'urn:oasis:names:tc:xliff:document:1.1'
+    suggestions_in_format = True
+    """xliff units have alttrans tags which can be used to store suggestions"""
 
     def __init__(self, *args, **kwargs):
         lisa.LISAfile.__init__(self, *args, **kwargs)
         self._filename = "NoName"
         self._messagenum = 0
 
-        # Allow the inputfile to override defaults for source and target language.
+
+    def initbody(self):
+        super(xlifffile, self).initbody()
         filenode = self.document.getroot().iterchildren(self.namespaced('file')).next()
         sourcelanguage = filenode.get('source-language')
         if sourcelanguage:
@@ -385,6 +465,10 @@
         """returns the name of the given file"""
         return filenode.get("original")
 
+    def setfilename(self, filenode, filename):
+        """set the name of the given file"""
+        return filenode.set("original", filename)
+
     def getfilenames(self):
         """returns all filenames in this XLIFF file"""
         filenodes = self.document.getroot().iterchildren(self.namespaced("file"))
@@ -473,7 +557,6 @@
         unit = super(xlifffile, self).addsourceunit(source)
         self._messagenum += 1
         unit.setid("%d" % self._messagenum)
-        lisa.setXMLspace(unit.xmlelement, "preserve")
         return unit
 
     def switchfile(self, filename, createifmissing=False):
@@ -496,7 +579,7 @@
         #instead of globally in the whole XLIFF file, but using len(self.units)
         #will be much faster
         return True
-    
+
     def creategroup(self, filename="NoName", createifmissing=False, restype=None):
         """adds a group tag into the specified file"""
         if self._filename != filename:
@@ -506,7 +589,7 @@
         if restype:
             group.set("restype", restype)
         return group
-        
+
     def __str__(self):
         self.removedefaultfile()
         return super(xlifffile, self).__str__()
@@ -523,4 +606,3 @@
                 xliff = poxliff.PoXliffFile.parsestring(storestring)
         return xliff
     parsestring = classmethod(parsestring)
-

Modified: translate-toolkit/branches/upstream/current/translate/storage/xml_extract/extract.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/xml_extract/extract.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/xml_extract/extract.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/xml_extract/extract.py Fri Jul 24 16:25:46 2009
@@ -1,24 +1,22 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2002-2006 Zuza Software Foundation
-# 
-# This file is part of translate.
-#
-# translate is free software; you can redistribute it and/or modify
+# Copyright 2008-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 from lxml import etree
 
@@ -29,7 +27,7 @@
 from translate.misc.context import with_
 from translate.storage.xml_extract import xpath_breadcrumb
 from translate.storage.xml_extract import misc
-from translate.storage.placeables import X, G
+from translate.storage.placeables import xliff, StringElem
 
 def Nullable(t):
     return IsOneOf(t, type(None))
@@ -40,7 +38,7 @@
     """A node corresponds to a translatable element. A node may
        have children, which correspond to placeables."""
     @accepts(Self(), unicode, unicode, etree._Element, [IsOneOf(TranslatableClass, unicode)])
-    def __init__(self, placeable_name, xpath, dom_node, source): 
+    def __init__(self, placeable_name, xpath, dom_node, source):
         self.placeable_name = placeable_name
         self.source = source
         self.xpath = xpath
@@ -123,7 +121,7 @@
 @accepts(etree._Element, ParseState)
 def find_translatable_dom_nodes(dom_node, state):
     # For now, we only want to deal with XML elements.
-    # And we want to avoid processing instructions, which 
+    # And we want to avoid processing instructions, which
     # are XML elements (in the inheritance hierarchy).
     if not isinstance(dom_node, etree._Element) or \
            isinstance(dom_node, etree._ProcessingInstruction):
@@ -136,14 +134,14 @@
         state.xpath_breadcrumb.start_tag(compact_tag(state.nsmap, namespace, tag))
         yield state.xpath_breadcrumb
         state.xpath_breadcrumb.end_tag()
-        
+
     @contextmanager
     def placeable_set():
         old_placeable_name = state.placeable_name
         state.placeable_name = tag
         yield state.placeable_name
         state.placeable_name = old_placeable_name
-            
+
     @contextmanager
     def inline_set():
         old_inline = state.is_inline
@@ -153,12 +151,12 @@
             state.is_inline = False
         yield state.is_inline
         state.is_inline = old_inline
-      
+
     def with_block(xpath_breadcrumb, placeable_name, is_inline):
         if (namespace, tag) not in state.no_translate_content_elements:
             return _process_translatable(dom_node, state)
         else:
-            return _process_children(dom_node, state)            
+            return _process_children(dom_node, state)
     return with_(nested(xpath_set(), placeable_set(), inline_set()), with_block)
 
 class IdMaker(object):
@@ -184,9 +182,9 @@
         else:
             id = unicode(id_maker.get_id(chunk))
             if chunk.is_inline:
-                result.append(G(id, _to_placeables(parent_translatable, chunk, id_maker)))
+                result.append(xliff.G(sub=_to_placeables(parent_translatable, chunk, id_maker), id=id))
             else:
-                result.append(X(id, xid=chunk.xpath))
+                result.append(xliff.X(id=id, xid=chunk.xpath))
     return result
 
 @accepts(base.TranslationStore, Nullable(Translatable), Translatable, IdMaker)
@@ -195,17 +193,15 @@
     information and add it to 'store'.
     """
     unit = store.UnitClass(u'')
-    unit.rich_source = [_to_placeables(parent_translatable, translatable, id_maker)]
+    unit.rich_source = [StringElem(_to_placeables(parent_translatable, translatable, id_maker))]
     unit.addlocation(translatable.xpath)
-    if parent_translatable is not None:
-        unit.xid = parent_translatable.xpath
     store.addunit(unit)
 
 @accepts(Translatable)
 def _contains_translatable_text(translatable):
     """Checks whether translatable contains any chunks of text which contain
     more than whitespace.
-    
+
     If not, then there's nothing to translate."""
     for chunk in translatable.source:
         if isinstance(chunk, unicode):
@@ -222,7 +218,7 @@
 
     def add_to_store(parent_translatable, translatable, rid):
         _add_translatable_to_store(store, parent_translatable, translatable, id_maker)
-            
+
     return add_to_store
 
 @accepts([Translatable], IsCallable(), Nullable(Translatable), Number)
@@ -242,7 +238,7 @@
 
 @accepts(lambda obj: hasattr(obj, "read"), base.TranslationStore, ParseState, Nullable(IsCallable()))
 def build_store(odf_file, store, parse_state, store_adder = None):
-    """Utility function for loading xml_filename"""    
+    """Utility function for loading xml_filename"""
     store_adder = store_adder or _make_store_adder(store)
     tree = etree.parse(odf_file)
     root = tree.getroot()

Modified: translate-toolkit/branches/upstream/current/translate/storage/xml_extract/misc.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/storage/xml_extract/misc.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/storage/xml_extract/misc.py (original)
+++ translate-toolkit/branches/upstream/current/translate/storage/xml_extract/misc.py Fri Jul 24 16:25:46 2009
@@ -1,24 +1,22 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2002-2006 Zuza Software Foundation
-# 
-# This file is part of translate.
+# Copyright 2008 Zuza Software Foundation
 #
-# translate is free software; you can redistribute it and/or modify
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 import re
 
@@ -27,10 +25,10 @@
 @accepts(IsCallable(), Any(), Any(), IsCallable(), state=[Any()])
 def reduce_tree(f, parent_unit_node, unit_node, get_children, *state):
     """Enumerate a tree, applying f to in a pre-order fashion to each node.
-    
+
     parent_unit_node contains the parent of unit_node. For the root of the tree,
     parent_unit_node == unit_node.
-    
+
     get_children is a single argument function applied to a unit_node to
     get a list/iterator to its children.
 
@@ -42,7 +40,7 @@
             return x
         else:
             return (x,)
-    
+
     state = f(parent_unit_node, unit_node, *state)
     for child_unit_node in get_children(unit_node):
         state = reduce_tree(f, unit_node, child_unit_node, get_children, *as_tuple(state))
@@ -73,4 +71,3 @@
         return unicode(match.groupdict()['namespace']), unicode(match.groupdict()['tag'])
     else:
         raise Exception('Passed an invalid tag')
-

Modified: translate-toolkit/branches/upstream/current/translate/tools/build_tmdb.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/tools/build_tmdb.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/tools/build_tmdb.py (original)
+++ translate-toolkit/branches/upstream/current/translate/tools/build_tmdb.py Fri Jul 24 16:25:46 2009
@@ -3,7 +3,7 @@
 #
 # Copyright 2008 Zuza Software Foundation
 #
-# This file is part of Virtaal.
+# This file is part of the Translate Toolkit.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by

Modified: translate-toolkit/branches/upstream/current/translate/tools/pocount.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/tools/pocount.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/tools/pocount.py (original)
+++ translate-toolkit/branches/upstream/current/translate/tools/pocount.py Fri Jul 24 16:25:46 2009
@@ -1,23 +1,22 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2003-2007 Zuza Software Foundation
-# 
-# This file is part of translate.
-#
-# translate is free software; you can redistribute it and/or modify
+#
+# Copyright 2003-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """Create string and word counts for supported localization files including:
 XLIFF, TMX, Gettex PO and MO, Qt .ts and .qm, Wordfast TM, etc
@@ -28,8 +27,16 @@
 
 from translate.storage import factory
 from translate.storage import statsdb
+from optparse import OptionParser
 import sys
 import os
+
+# define style constants
+style_full, style_csv, style_short_strings, style_short_words = range(4)
+
+# default output style
+default_style = style_full
+
 
 def calcstats_old(filename):
     """This is the previous implementation of calcstats() and is left for
@@ -72,14 +79,28 @@
     statscache = statsdb.StatsCache()
     return statscache.filetotals(filename)
 
-def summarize(title, stats, CSVstyle=False):
+def summarize(title, stats, style=style_full, indent=8, incomplete_only=False):
+    """
+    Print summary for a .po file in specified format.
+    Arguments:
+      title - name of .po file
+      stats - array with translation statistics for the file specified
+      indent - indentation of the 2nd column (length of longest filename)
+      incomplete_only - omit fully translated files
+    Return value:
+      1 if counting incomplete files (incomplete_only=True) and the file is completely translated
+      0 otherwise
+    """
     def percent(denominator, devisor):
         if devisor == 0:
             return 0
         else:
             return denominator*100/devisor
 
-    if CSVstyle:
+    if incomplete_only and (stats["total"] == stats["translated"]):
+        return 1
+
+    if (style == style_csv):
         print "%s, " % title,
         print "%d, %d, %d," % (stats["translated"], stats["translatedsourcewords"], stats["translatedtargetwords"]),
         print "%d, %d," % (stats["fuzzy"], stats["fuzzysourcewords"]),
@@ -88,7 +109,21 @@
         if stats["review"] > 0:
             print ", %d, %d" % (stats["review"], stats["reviewsourdcewords"]),
         print
-    else:
+    elif (style == style_short_strings):
+        spaces = " "*(indent - len(title))
+        print "%s%s strings: total: %d\t| %dt\t%df\t%du\t| %d%%t\t%d%%f\t%d%%u" % (title, spaces,\
+              stats["total"], stats["translated"], stats["fuzzy"], stats["untranslated"], \
+              percent(stats["translated"], stats["total"]), \
+              percent(stats["fuzzy"], stats["total"]), \
+              percent(stats["untranslated"], stats["total"]))
+    elif (style == style_short_words):
+        spaces = " "*(indent - len(title))
+        print "%s%s source words: total: %d\t| %dt\t%df\t%du\t| %d%%t\t%d%%f\t%d%%u" % (title, spaces,\
+              stats["totalsourcewords"], stats["translatedsourcewords"], stats["fuzzysourcewords"], stats["untranslatedsourcewords"], \
+              percent(stats["translatedsourcewords"], stats["totalsourcewords"]), \
+              percent(stats["fuzzysourcewords"], stats["totalsourcewords"]), \
+              percent(stats["untranslatedsourcewords"], stats["totalsourcewords"]))
+    else: # style == style_full
         print title
         print "type              strings      words (source)    words (translation)"
         print "translated:   %5d (%3d%%) %10d (%3d%%) %15d" % \
@@ -115,6 +150,7 @@
             print "review:       %5d %17d                    n/a" % \
                     (stats["review"], stats["reviewsourcewords"])
         print
+    return 0
 
 def fuzzymessages(units):
     return filter(lambda unit: unit.isfuzzy() and unit.target, units)
@@ -126,15 +162,23 @@
     return filter(lambda unit: not (unit.istranslated() or unit.isfuzzy()) and unit.source, units)
 
 class summarizer:
-    def __init__(self, filenames, CSVstyle):
+    def __init__(self, filenames, style=default_style, incomplete_only=False):
         self.totals = {}
         self.filecount = 0
-        self.CSVstyle = CSVstyle
-        if self.CSVstyle:
+        self.longestfilename = 0
+        self.style = style
+        self.incomplete_only = incomplete_only
+        self.complete_count = 0
+
+        if (self.style == style_csv):
             print "Filename, Translated Messages, Translated Source Words, Translated \
 Target Words, Fuzzy Messages, Fuzzy Source Words, Untranslated Messages, \
 Untranslated Source Words, Total Message, Total Source Words, \
 Review Messages, Review Source Words"
+        if (self.style == style_short_strings or self.style == style_short_words):
+            for filename in filenames:  # find longest filename
+                if (len(filename) > self.longestfilename):
+                    self.longestfilename = len(filename)
         for filename in filenames:
             if not os.path.exists(filename):
                 print >> sys.stderr, "cannot process %s: does not exist" % filename
@@ -143,8 +187,12 @@
                 self.handledir(filename)
             else:
                 self.handlefile(filename)
-        if self.filecount > 1 and not self.CSVstyle:
-            summarize("TOTAL:", self.totals)
+        if self.filecount > 1 and (self.style == style_full):
+            if self.incomplete_only:
+                summarize("TOTAL (incomplete only):", self.totals, incomplete_only=True)
+                print "File count (incomplete):   %5d" % (self.filecount - self.complete_count)
+            else:
+                summarize("TOTAL:", self.totals, incomplete_only=False)
             print "File count:   %5d" % (self.filecount)
             print
 
@@ -159,7 +207,7 @@
         try:
             stats = calcstats(filename)
             self.updatetotals(stats)
-            summarize(filename, stats, self.CSVstyle)
+            self.complete_count += summarize(filename, stats, self.style, self.longestfilename, self.incomplete_only)
             self.filecount += 1
         except: # This happens if we have a broken file.
             print >> sys.stderr, sys.exc_info()[1]
@@ -180,17 +228,52 @@
         self.handlefiles(dirname, entries)
 
 def main():
-    # TODO: make this handle command line options using optparse...
-    CSVstyle = False
-    if "--csv" in sys.argv:
-        sys.argv.remove("--csv")
-        CSVstyle = True
+    parser = OptionParser(usage="usage: %prog [options] po-files")
+    parser.add_option("--incomplete", action="store_const", const = True, dest = "incomplete_only",
+                      help="skip 100% translated files.")
+    # options controlling output format:
+    parser.add_option("--full", action="store_const", const = style_csv, dest = "style_full",
+                      help="(default) statistics in full, verbose format")
+    parser.add_option("--csv", action="store_const", const = style_csv, dest = "style_csv",
+                      help="statistics in CSV format")
+    parser.add_option("--short", action="store_const", const = style_csv, dest = "style_short_strings",
+                      help="same as --short-strings")
+    parser.add_option("--short-strings", action="store_const", const = style_csv, dest = "style_short_strings",
+                      help="statistics of strings in short format - one line per file")
+    parser.add_option("--short-words", action="store_const", const = style_csv, dest = "style_short_words",
+                      help="statistics of words in short format - one line per file")
+
+    (options, args) = parser.parse_args()
+
+    if (options.incomplete_only == None):
+        options.incomplete_only = False
+
+    if (options.style_full and options.style_csv) or \
+       (options.style_full and options.style_short_strings) or \
+       (options.style_full and options.style_short_words) or \
+       (options.style_csv and options.style_short_strings) or \
+       (options.style_csv and options.style_short_words) or \
+       (options.style_short_strings and options.style_short_words):
+        parser.error("options --full, --csv, --short-strings and --short-words are mutually exclusive")
+        sys.exit(2)
+
+    style = default_style   # default output style
+    if options.style_csv:
+        style = style_csv
+    if options.style_full:
+        style = style_full
+    if options.style_short_strings:
+        style = style_short_strings
+    if options.style_short_words:
+        style = style_short_words
+
     try:
         import psyco
         psyco.full()
     except Exception:
         pass
-    summarizer(sys.argv[1:], CSVstyle)
+
+    summarizer(args, style, options.incomplete_only)
 
 if __name__ == '__main__':
     main()

Modified: translate-toolkit/branches/upstream/current/translate/tools/podebug.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/tools/podebug.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/tools/podebug.py (original)
+++ translate-toolkit/branches/upstream/current/translate/tools/podebug.py Fri Jul 24 16:25:46 2009
@@ -1,40 +1,48 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
-# Copyright 2004-2006,2008 Zuza Software Foundation
-# 
-# This file is part of translate.
-#
-# translate is free software; you can redistribute it and/or modify
+#
+# Copyright 2004-2006,2008-2009 Zuza Software Foundation
+#
+# This file is part of the Translate Toolkit.
+#
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
-# 
-# translate is distributed in the hope that it will be useful,
+#
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 """Insert debug messages into XLIFF and Gettext PO localization files
 
 See: http://translate.sourceforge.net/wiki/toolkit/podebug for examples and
-usage instructions
+usage instructions.
 """
 
-from translate.storage import factory
-from translate.misc.rich import map_rich, only_strings
 import os
 import re
+
 from translate.misc import hash
-
-def add_prefix(prefix, strings):
-    for string in strings:
-        string.insert(0, prefix)
-    return strings
+from translate.storage import factory
+from translate.storage.placeables import StringElem, general
+from translate.storage.placeables import parse as rich_parse
+
+
+def add_prefix(prefix, stringelems):
+    for stringelem in stringelems:
+        for string in stringelem.flatten():
+            if len(string.sub) > 0:
+                string.sub[0] = prefix + string.sub[0]
+    return stringelems
+
+podebug_parsers = general.parsers
+podebug_parsers.remove(general.CapsPlaceable.parse)
+podebug_parsers.remove(general.CamelCasePlaceable.parse)
 
 class podebug:
     def __init__(self, format=None, rewritestyle=None, hash=None, ignoreoption=None):
@@ -46,24 +54,56 @@
         self.ignorefunc = getattr(self, "ignore_%s" % ignoreoption, None)
         self.hash = hash
 
+    def apply_to_translatables(self, string, func):
+        """Applies func to all translatable strings in string."""
+        string.map(
+            lambda e: e.apply_to_strings(func),
+            lambda e: e.isleaf() and e.istranslatable
+        )
+
     def rewritelist(cls):
         return [rewrite.replace("rewrite_", "") for rewrite in dir(cls) if rewrite.startswith("rewrite_")]
     rewritelist = classmethod(rewritelist)
 
+    def _rewrite_prepend_append(self, string, prepend, append=None):
+        if append is None:
+            append = prepend
+        if not isinstance(string, StringElem):
+            string = StringElem(string)
+        string.sub.insert(0, prepend)
+        if unicode(string).endswith(u'\n'):
+            # Try and remove the last character from the tree
+            try:
+                lastnode = string.flatten()[-1]
+                if isinstance(lastnode.sub[-1], unicode):
+                    lastnode.sub[-1] = lastnode.sub[-1].rstrip(u'\n')
+            except IndexError:
+                pass
+            string.sub.append(append + u'\n')
+        else:
+            string.sub.append(append)
+        return string
+
     def rewrite_xxx(self, string):
-        if string.endswith("\n"):
-            return "xxx%sxxx\n" % string[:-1]
-        return "xxx%sxxx" % string
+        return self._rewrite_prepend_append(string, u"xxx")
+
+    def rewrite_bracket(self, string):
+        return self._rewrite_prepend_append(string, u"[", u"]")
 
     def rewrite_en(self, string):
+        if not isinstance(string, StringElem):
+            string = StringElem(string)
         return string
 
     def rewrite_blank(self, string):
-        return ""
+        return StringElem(u"")
 
     def rewrite_chef(self, string):
         """Rewrite using Mock Swedish as made famous by Monty Python"""
-        # From Dive into Python which itself got it elsewhere http://www.renderx.com/demos/examples/diveintopython.pdf
+        if not isinstance(string, StringElem):
+            string = StringElem(string)
+        # From Dive into Python which itself got it elsewhere
+        # http://www.renderx.com/demos/examples/diveintopython.pdf
         subs = (
                (r'a([nu])', r'u\1'),
                (r'A([nu])', r'U\1'),
@@ -92,18 +132,51 @@
                (r'W', r'W'),
                (r'([a-z])[.]', r'\1. Bork Bork Bork!'))
         for a, b in subs:
-            string = re.sub(a, b, string)
+            self.apply_to_translatables(string, lambda s: re.sub(a, b, s))
         return string
 
     REWRITE_UNICODE_MAP = u"ȦƁƇḒḖƑƓĦĪĴĶĿḾȠǾƤɊŘŞŦŬṼẆẊẎẐ" + u"[\\]^_`" + u"ȧƀƈḓḗƒɠħīĵķŀḿƞǿƥɋřşŧŭṽẇẋẏẑ"
     def rewrite_unicode(self, string):
         """Convert to Unicode characters that look like the source string"""
+        if not isinstance(string, StringElem):
+            string = StringElem(string)
         def transpose(char):
             loc = ord(char)-65
             if loc < 0 or loc > 56:
                 return char
             return self.REWRITE_UNICODE_MAP[loc]
-        return "".join(map(transpose, string))
+        def transformer(s):
+            return ''.join([transpose(c) for c in s])
+        self.apply_to_translatables(string, transformer)
+        return string
+
+    REWRITE_FLIPPED_MAP = u"¡„#$%â
‹,()⁎+´-·/012Ɛᔭ59Ƚ86:;<=>?@" + \
+            u"∀ԐↃᗡƎℲâ
HIÅ¿Ó¼â
‚WNOԀÒᴚS⊥∩É
ï¼­Xâ
„Z" + u"[\\]áµ¥_," + \
+            u"ɐqÉ”pǝɟƃɥıɾʞÊ
ɯuodbɹsʇnʌʍxʎz"
+        # Brackets should be swapped if the string will be reversed in memory.
+        # If a right-to-left override is used, the brackets should be
+        # unchanged.
+        #Some alternatives:
+        # D: á—¡â—–
+        # K: Ж⋊Ӽ
+        # @: Ò¨ - Seems only related in Dejavu Sans
+        # Q: Ὄ Ό Ὀ Ὃ Ὄ Ṑ Ò Ỏ
+        # _: ‾ - left out for now for the sake of GTK accelerators
+    def rewrite_flipped(self, string):
+        """Convert the string to look flipped upside down."""
+        if not isinstance(string, StringElem):
+            string = StringElem(string)
+        def transpose(char):
+            loc = ord(char)-33
+            if loc < 0 or loc > 89:
+                return char
+            return self.REWRITE_FLIPPED_MAP[loc]
+        def transformer(s):
+            return u"\u202e" + u''.join([transpose(c) for c in s])
+            # To reverse instead of using the RTL override:
+            #return u''.join(reversed([transpose(c) for c in s]))
+        self.apply_to_translatables(string, transformer)
+        return string
 
     def ignorelist(cls):
         return [ignore.replace("ignore_", "") for ignore in dir(cls) if ignore.startswith("ignore_")]
@@ -127,7 +200,7 @@
             if location.endswith(".height") or location.endswith(".width") or \
                     location.endswith(".macWidth") or location.endswith(".unixWidth"):
                 return True
-            if location == "brandShortName" or location == "brandFullName" or location == "vendorShortName":
+            if location in ["brandShortName", "brandFullName", "vendorShortName"]:
                 return True
             if location.lower().endswith(".commandkey") or location.endswith(".key"):
                 return True
@@ -153,8 +226,13 @@
             else:
                 hashable = unit.source
             prefix = hash.md5_f(hashable).hexdigest()[:self.hash] + " "
+        rich_source = unit.rich_source
+        if not isinstance(rich_source, StringElem):
+            rich_source = [rich_parse(string, podebug_parsers) for string in rich_source]
         if self.rewritefunc:
-            unit.rich_target = map_rich(only_strings(self.rewritefunc), unit.rich_source)
+            rewritten = [self.rewritefunc(string) for string in rich_source]
+            if rewritten:
+                unit.rich_target = rewritten
         elif not unit.istranslated():
             unit.rich_target = unit.rich_source
         unit.rich_target = add_prefix(prefix, unit.rich_target)
@@ -189,7 +267,7 @@
                     formatted = formatted[:int(length)]
             prefix = prefix.replace(formatstr, formatted)
         for unit in store.units:
-            if unit.isheader() or unit.isblank():
+            if not unit.istranslatable():
                 continue
             unit = self.convertunit(unit, prefix)
         return store
@@ -211,7 +289,7 @@
         return dirshrunk + baseshrunk
 
 def convertpo(inputfile, outputfile, templatefile, format=None, rewritestyle=None, hash=None, ignoreoption=None):
-    """reads in inputfile using po, changes to have debug strings, writes to outputfile"""
+    """Reads in inputfile, changes it to have debug strings, writes to outputfile."""
     # note that templatefile is not used, but it is required by the converter...
     inputstore = factory.getobject(inputfile)
     if inputstore.isempty():
@@ -226,12 +304,16 @@
     formats = {"po":("po", convertpo), "pot":("po", convertpo), "xlf":("xlf", convertpo)}
     parser = convert.ConvertOptionParser(formats, description=__doc__)
     # TODO: add documentation on format strings...
-    parser.add_option("-f", "--format", dest="format", default="", help="specify format string")
-    parser.add_option("", "--rewrite", dest="rewritestyle", 
-        type="choice", choices=podebug.rewritelist(), metavar="STYLE", help="the translation rewrite style: %s" % ", ".join(podebug.rewritelist()))
-    parser.add_option("", "--ignore", dest="ignoreoption", 
-        type="choice", choices=podebug.ignorelist(), metavar="APPLICATION", help="apply tagging ignore rules for the given application: %s" % ", ".join(podebug.ignorelist()))
-    parser.add_option("", "--hash", dest="hash", metavar="LENGTH", type="int", help="add an md5 hash to translations")
+    parser.add_option("-f", "--format", dest="format", default="",
+        help="specify format string")
+    parser.add_option("", "--rewrite", dest="rewritestyle",
+        type="choice", choices=podebug.rewritelist(), metavar="STYLE",
+        help="the translation rewrite style: %s" % ", ".join(podebug.rewritelist()))
+    parser.add_option("", "--ignore", dest="ignoreoption",
+        type="choice", choices=podebug.ignorelist(), metavar="APPLICATION",
+        help="apply tagging ignore rules for the given application: %s" % ", ".join(podebug.ignorelist()))
+    parser.add_option("", "--hash", dest="hash", metavar="LENGTH", type="int",
+        help="add an md5 hash to translations")
     parser.passthrough.append("format")
     parser.passthrough.append("rewritestyle")
     parser.passthrough.append("ignoreoption")

Modified: translate-toolkit/branches/upstream/current/translate/tools/pomerge.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/tools/pomerge.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/tools/pomerge.py (original)
+++ translate-toolkit/branches/upstream/current/translate/tools/pomerge.py Fri Jul 24 16:25:46 2009
@@ -47,9 +47,7 @@
         entities = unit2.getlocations()
         if len(entities) == 0:
             source = unit2.source
-            unit1 = None
-            if source in store1.sourceindex:
-                unit1 = store1.sourceindex[source]
+            unit1 = store1.findunit(source)
             if unit1 is None:
                 sys.stderr.write(str(unit2) + "\n")
             else:
@@ -64,11 +62,10 @@
             if store2.locationindex.has_key(entity):
                 if store2.locationindex[entity] is None:
                     unit1 = None
-            # if locationindex was not unique, use the sourceindex
+            # if locationindex was not unique, use the source index
             if unit1 is None:
                 source = unit2.source
-                if source in store1.sourceindex:
-                    unit1 = store1.sourceindex[source]
+                unit1 = store1.findunit(source)
             # check if we found a matching po element
             if unit1 is None:
                 print >> sys.stderr, "# the following po element was not found"
@@ -130,9 +127,9 @@
                 ("xlf", "po"): pooutput, ("xlf", "pot"): pooutput,
                 ("xlf", "xlf"): xliffoutput, ("po", "xlf"): xliffoutput}
     mergeblanksoption = convert.optparse.Option("", "--mergeblanks", dest="mergeblanks",
-        action="store", default="yes", help="whether to overwrite existing translations with blank translations (yes/no)")
+        action="store", default="yes", help="whether to overwrite existing translations with blank translations (yes/no). Default is yes.")
     mergecommentsoption = convert.optparse.Option("", "--mergecomments", dest="mergecomments",
-        action="store", default="yes", help="whether to merge comments as well as translations (yes/no)")
+        action="store", default="yes", help="whether to merge comments as well as translations (yes/no). Default is yes.")
     parser = convert.ConvertOptionParser(formats, usetemplates=True, description=__doc__)
     parser.add_option(mergeblanksoption)
     parser.passthrough.append("mergeblanks")

Modified: translate-toolkit/branches/upstream/current/translate/tools/posegment.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/tools/posegment.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/tools/posegment.py (original)
+++ translate-toolkit/branches/upstream/current/translate/tools/posegment.py Fri Jul 24 16:25:46 2009
@@ -1,25 +1,24 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #
-# Copyright 2007 Zuza Software Foundation
+# Copyright 2008-2009 Zuza Software Foundation
 #
-# This file is part of translate.
+# This file is part of the Translate Toolkit.
 #
-# translate is free software; you can redistribute it and/or modify
+# This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
 #
-# translate is distributed in the hope that it will be useful,
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with translate; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
-"""Segment Gettext PO, XLIFF and TMX localization files at the sentence level
+"""Segment Gettext PO, XLIFF and TMX localization files at the sentence level.
 
 See: http://translate.sourceforge.net/wiki/toolkit/posegment for examples and
 usage instructions
@@ -27,8 +26,6 @@
 
 from translate.storage import factory
 from translate.lang import factory as lang_factory
-import os
-import re
 
 class segment:
 
@@ -44,6 +41,9 @@
         targetsegments = self.targetlang.sentences(unit.target, strip=self.stripspaces)
         if unit.istranslated() and (len(sourcesegments) != len(targetsegments)):
             return [unit]
+        # We could do more here to check if the lengths correspond more or less,
+        # certain quality checks are passed, etc.  But for now this is a good
+        # start.
         units = []
         for i in range(len(sourcesegments)):
             newunit = unit.copy()

Modified: translate-toolkit/branches/upstream/current/translate/tools/pretranslate.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/tools/pretranslate.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/tools/pretranslate.py (original)
+++ translate-toolkit/branches/upstream/current/translate/tools/pretranslate.py Fri Jul 24 16:25:46 2009
@@ -1,8 +1,8 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# 
+#
 # Copyright 2008 Zuza Software Foundation
-# 
+#
 # This file is part of translate.
 #
 # This program is free software; you can redistribute it and/or modify
@@ -18,18 +18,16 @@
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, see <http://www.gnu.org/licenses/>.
 
-"""fill localization files with suggested translations based on
-translation memory and existing translations
+"""Fill localization files with suggested translations based on
+translation memory and existing translations.
 """
 
 from translate.storage import factory
 from translate.storage import xliff
 from translate.search import match
 
-
 # We don't want to reinitialise the TM each time, so let's store it here.
 tmmatcher = None
-
 
 def memory(tmfiles, max_candidates=1, min_similarity=75, max_length=1000):
     """Returns the TM store to use. Only initialises on first call."""
@@ -45,36 +43,44 @@
 
 
 def pretranslate_file(input_file, output_file, template_file, tm=None, min_similarity=75, fuzzymatching=True):
-    """pretranslate any factory supported file with old translations and translation memory"""
+    """Pretranslate any factory supported file with old translations and translation memory."""
     input_store = factory.getobject(input_file)
     template_store = None
     if template_file is not None:
         template_store = factory.getobject(template_file)
-        
+
     output = pretranslate_store(input_store, template_store, tm, min_similarity, fuzzymatching)
     output_file.write(str(output))
     return 1
 
 
-def match_template_id (input_unit, template_store):
-    """returns a matching unit from a template"""
-    #since oo2po and moz2po use localtion as unique identifiers for strings
-    #we match against location first, then check for matching source strings
-    #FIXME: this makes absolutely no sense for other po files
-    for location in input_unit.getlocations():
-        matching_unit = template_store.locationindex.get(location, None)
-        #do we really want to discard units with matching locations but no matching source?
-        if matching_unit is not None and matching_unit.source == input_unit.source and len(matching_unit.target) > 0:
-            return matching_unit
-        else:
-            #if no match by location information search for identical source strings
-            #FIXME: need a better method for matching strings, we don't take context into account
-            #FIXME: need a better test for when not to use location info for matching
-            return template_store.findunit(input_unit.source)
+def match_template_id(input_unit, template_store):
+    """Returns a matching unit from a template."""
+    # we want to use slightly different matching strategies for PO files
+    # generated by our own moz2po and oo2po. Let's take a cheap shot at
+    # detecting them from the presence of a ':' in the first location.
+    locations = input_unit.getlocations()
+    if not locations or ":" in locations[0]:
+        # do normal gettext-like matching
+        matching_units = template_store.findunits(input_unit.source)
+        if matching_units:
+            for unit in matching_units:
+                if unit.getcontext() == input_unit.getcontext():
+                    return unit
+
+    else:
+        #since oo2po and moz2po use location as unique identifiers for strings
+        #we match against location first, then check for matching source strings
+        #this makes no sense for normal gettext files
+        for location in locations:
+            matching_unit = template_store.locationindex.get(location, None)
+            #do we really want to discard units with matching locations but no matching source?
+            if matching_unit is not None and matching_unit.source == input_unit.source and matching_unit.gettargetlen() > 0:
+                return matching_unit
 
 
 def match_fuzzy(input_unit, matchers):
-    """returns a fuzzy match from a queue of matchers"""
+    """Return a fuzzy match from a queue of matchers."""
     for matcher in matchers:
         fuzzycandidates = matcher.matches(input_unit.source)
         if fuzzycandidates:
@@ -82,19 +88,19 @@
 
 
 def pretranslate_unit(input_unit, template_store, matchers=None, mark_reused=False) :
-    """returns a pretranslated unit, if no translation was found return input unit unchanged"""
+    """Pretranslate a unit or return unchanged if no translation was found."""
 
     matching_unit = None
     #do template matching
     if template_store:
         matching_unit = match_template_id(input_unit, template_store)
 
-    if matching_unit and len(matching_unit.target) > 0:
+    if matching_unit and matching_unit.gettargetlen() > 0:
         input_unit.merge(matching_unit, authoritative=True)
     elif matchers:
         #do fuzzy matching
         matching_unit = match_fuzzy(input_unit, matchers)
-        if matching_unit and len(matching_unit.target) > 0:
+        if matching_unit and matching_unit.gettargetlen() > 0:
             #FIXME: should we dispatch here instead of this crude type check
             if isinstance(input_unit, xliff.xliffunit):
                 #FIXME: what about origin, lang and matchquality
@@ -112,15 +118,14 @@
     return input_unit
 
 def prepare_template_pofile(template_store):
-    """po format specific template preparation logic"""
+    """PO format specific template preparation logic."""
     #do we want to consider obsolete translations?
     for unit in template_store.units:
         if unit.isobsolete():
             unit.resurrect()
 
-
 def pretranslate_store(input_store, template_store, tm=None, min_similarity=75, fuzzymatching=True):
-    """does the actual pretranslation"""
+    """Do the actual pretranslation of a whole store."""
     #preperation
     matchers = []
     #prepare template
@@ -130,7 +135,7 @@
         prepare_template = "prepare_template_%s" % template_store.__class__.__name__
         if  globals().has_key(prepare_template):
             globals()[prepare_template](template_store)
-                
+
         if fuzzymatching:
             #create template matcher
             #FIXME: max_length hardcoded
@@ -138,19 +143,19 @@
             matcher.addpercentage = False
             matchers.append(matcher)
 
-    #prepare tm    
+    #prepare tm
     #create tm matcher
     if tm and fuzzymatching:
         #FIXME: max_length hardcoded
         matcher = memory(tm, max_candidates=1, min_similarity=min_similarity, max_length=1000)
         matcher.addpercentage = False
         matchers.append(matcher)
-    
+
     #main loop
     for input_unit in input_store.units:
         if  input_unit.istranslatable():
             input_unit = pretranslate_unit(input_unit, template_store, matchers)
-    
+
     return input_store
 
 
@@ -160,7 +165,7 @@
                "po": ("po", pretranslate_file), ("po", "po"): ("po", pretranslate_file),
                "xlf": ("xlf", pretranslate_file), ("xlf", "xlf"): ("xlf", pretranslate_file),
                }
-    parser = convert.ConvertOptionParser(formats, usetemplates=True, 
+    parser = convert.ConvertOptionParser(formats, usetemplates=True,
         allowmissingtemplate=True, description=__doc__)
     parser.add_option("", "--tm", dest="tm", default=None,
         help="The file to use as translation memory when fuzzy matching")
@@ -169,7 +174,7 @@
     parser.add_option("-s", "--similarity", dest="min_similarity", default=defaultsimilarity,
         type="float", help="The minimum similarity for inclusion (default: %d%%)" % defaultsimilarity)
     parser.passthrough.append("min_similarity")
-    parser.add_option("--nofuzzymatching", dest="fuzzymatching", action="store_false", 
+    parser.add_option("--nofuzzymatching", dest="fuzzymatching", action="store_false",
         default=True, help="Disable fuzzy matching")
     parser.passthrough.append("fuzzymatching")
     parser.run(argv)

Modified: translate-toolkit/branches/upstream/current/translate/tools/test_podebug.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/tools/test_podebug.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/tools/test_podebug.py (original)
+++ translate-toolkit/branches/upstream/current/translate/tools/test_podebug.py Fri Jul 24 16:25:46 2009
@@ -1,11 +1,31 @@
 # -*- coding: utf-8 -*-
 
 from translate.tools import podebug
-from translate.storage import base
+from translate.storage import base, po, xliff
+
+PO_DOC = """
+msgid "This is a %s test, hooray."
+msgstr ""
+"""
+
+XLIFF_DOC = """<?xml version='1.0' encoding='utf-8'?>
+<xliff xmlns="urn:oasis:names:tc:xliff:document:1.1" version="1.1">
+  <file original="NoName" source-language="en" datatype="plaintext">
+    <body>
+      <trans-unit id="office:document-content[0]/office:body[0]/office:text[0]/text:p[0]">
+        <source>This <g id="0">is a</g> test <x id="1" xid="office:document-content[0]/office:body[0]/office:text[0]/text:p[0]/text:note[0]"/>, hooray.</source>
+      </trans-unit>
+    </body>
+  </file>
+</xliff>
+"""
 
 class TestPODebug:
+    debug = podebug.podebug()
 
-    debug = podebug.podebug()
+    def setup_method(self, method):
+        self.postore = po.pofile(PO_DOC)
+        self.xliffstore = xliff.xlifffile(XLIFF_DOC)
 
     def test_ignore_gtk(self):
         """Test operation of GTK message ignoring"""
@@ -14,25 +34,61 @@
 
     def test_rewrite_blank(self):
         """Test the blank rewrite function"""
-        assert self.debug.rewrite_blank("Test") == ""
+        assert str(self.debug.rewrite_blank(u"Test")) == u""
 
     def test_rewrite_en(self):
         """Test the en rewrite function"""
-        assert self.debug.rewrite_en("Test") == "Test"
+        assert str(self.debug.rewrite_en(u"Test")) == u"Test"
 
     def test_rewrite_xxx(self):
         """Test the xxx rewrite function"""
-        assert self.debug.rewrite_xxx("Test") == "xxxTestxxx"
-        assert self.debug.rewrite_xxx("Newline\n") == "xxxNewlinexxx\n"
+        assert str(self.debug.rewrite_xxx(u"Test")) == u"xxxTestxxx"
+        assert str(self.debug.rewrite_xxx(u"Newline\n")) == u"xxxNewlinexxx\n"
+
+    def test_rewrite_bracket(self):
+        """Test the bracket rewrite function"""
+        assert str(self.debug.rewrite_bracket(u"Test")) == u"[Test]"
+        assert str(self.debug.rewrite_bracket(u"Newline\n")) == u"[Newline]\n"
 
     def test_rewrite_unicode(self):
         """Test the unicode rewrite function"""
-        assert self.debug.rewrite_unicode("Test") == u"Ŧḗşŧ"
+        assert unicode(self.debug.rewrite_unicode(u"Test")) == u"Ŧḗşŧ"
+
+    def test_rewrite_flipped(self):
+        """Test the unicode rewrite function"""
+        assert unicode(self.debug.rewrite_flipped(u"Test")) == u"\u202e⊥ǝsʇ"
+        #alternative with reversed string and no RTL override:
+        #assert unicode(self.debug.rewrite_flipped("Test")) == u"ʇsǝ⊥"
 
     def test_rewrite_chef(self):
         """Test the chef rewrite function
-        
+
         This is not realy critical to test but a simple tests ensures
         that it stays working.
         """
-        assert self.debug.rewrite_chef("Mock Swedish test you muppet") == "Mock Swedish test yooo mooppet"
+        assert str(self.debug.rewrite_chef(u"Mock Swedish test you muppet")) == u"Mock Swedish test yooo mooppet"
+
+    def test_po_variables(self):
+        debug = podebug.podebug(rewritestyle='unicode')
+        po_out = debug.convertstore(self.postore)
+
+        in_unit = self.postore.units[0]
+        out_unit = po_out.units[0]
+
+        assert in_unit.source == out_unit.source
+        print out_unit.target
+        print str(po_out)
+        rewrite_func = self.debug.rewrite_unicode
+        assert out_unit.target == u"%s%%s%s" % (rewrite_func(u'This is a '), rewrite_func(u' test, hooray.'))
+
+    def test_xliff_rewrite(self):
+        debug = podebug.podebug(rewritestyle='xxx')
+        xliff_out = debug.convertstore(self.xliffstore)
+
+        in_unit = self.xliffstore.units[0]
+        out_unit = xliff_out.units[0]
+
+        assert in_unit.source == out_unit.source
+        print out_unit.target
+        print str(xliff_out)
+        assert out_unit.target == u'xxx%sxxx' % (in_unit.source)

Modified: translate-toolkit/branches/upstream/current/translate/tools/test_pomerge.py
URL: http://svn.debian.org/wsvn/translate-toolkit/branches/upstream/current/translate/tools/test_pomerge.py?rev=1813&op=diff
==============================================================================
--- translate-toolkit/branches/upstream/current/translate/tools/test_pomerge.py (original)
+++ translate-toolkit/branches/upstream/current/translate/tools/test_pomerge.py Fri Jul 24 16:25:46 2009
@@ -70,7 +70,7 @@
         assert pounit.target == "Dimpled King"
 
     def test_merging_locations(self):
-        """check that locations on seperate lines are output in Gettext form of all on one line"""
+        """check that locations on separate lines are output in Gettext form of all on one line"""
         templatepo = '''#: location.c:1\n#: location.c:2\nmsgid "Simple String"\nmsgstr ""\n'''
         inputpo = '''#: location.c:1\n#: location.c:2\nmsgid "Simple String"\nmsgstr "Dimpled Ring"\n'''
         expectedpo = '''#: location.c:1%slocation.c:2\nmsgid "Simple String"\nmsgstr "Dimpled Ring"\n''' % po.lsep




More information about the Debian-l10n-commits mailing list