We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
po2prop is not working as expected
I've spend some days by now and I can't seem to find any solution.

I have a strings file from my ios app and I'm able to convert it successfully to a po using prop2po using this command.

`prop2po --encoding utf8 -t ../en.lproj/Localizable.strings  Localizable.strings es.po`

I'm executing this command inside the `/Strings/es.lproj` where the Localizables.strings is the one having the Spanish translations.

So it creates a es.po file with the msgid form the template and the translations from the Localizables.strings from the current path.

Then when I try to convert back my es.po to a new Localizables.strings with the new translations I'm getting always the template.

I'm using this command:
`po2prop --encoding utf8 -i es.po -o new.strings -t ../en.lproj/Localizable.strings`

new.strings is always the same as the template that I'm using instead of having the translation from the es.po.

Also I think there is something wrong with the gettext file parser as I have to delete this two lines from the es.po generated file in order to work.
`#, fuzzy`
`msgid ""` <--
`msgstr ""` <--

I've added the commented fuzzy but that line does not creates trouble.

If I don't delete theese two lines when I try to use the po2prop command I get this error:
`template ../en.lproj/Localizable.strings: 'NoneType' object has no attribute 'istranslated'`

Is quite misleading as it seems that is has a problem with the template but after many tries I manage to figure that the problem was in the po file.(Or maybe not and I'm missing something).

I'm using the 2.0.0b2 version.

I hope someone can tell me what I'm doing wrong..or if this is actually a bug since I've tried many ways to convert from po2prop using all the settings available and I'm not able to do it right.

Supposedly this should work...

http://stackoverflow.com/questions/13939766/are-there-any-good-tools-for-ios-pseudo-localization

Or this : 

`po2prop -t some.properties some.po some-other.properties` from http://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/prop2po.html

Thanks,
Rubén.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `translate/convert/po2prop.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # Copyright 2002-2006 Zuza Software Foundation
5 #
6 # This file is part of translate.
7 #
8 # translate is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
12 #
13 # translate is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, see <http://www.gnu.org/licenses/>.
20 
21 """Convert Gettext PO localization files to Java/Mozilla .properties files.
22 
23 See: http://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/prop2po.html
24 for examples and usage instructions.
25 """
26 
27 import six
28 import warnings
29 
30 from translate.convert import accesskey, convert
31 from translate.misc import quote
32 from translate.storage import po, properties
33 
34 
35 eol = u"\n"
36 
37 
38 def applytranslation(key, propunit, inunit, mixedkeys):
39     """applies the translation for key in the po unit to the prop unit"""
40     # this converts the po-style string to a prop-style string
41     value = inunit.target
42     # handle mixed keys
43     for labelsuffix in properties.labelsuffixes:
44         if key.endswith(labelsuffix):
45             if key in mixedkeys:
46                 value, akey = accesskey.extract(value)
47                 break
48     else:
49         for akeysuffix in properties.accesskeysuffixes:
50             if key.endswith(akeysuffix):
51                 if key in mixedkeys:
52                     label, value = accesskey.extract(value)
53                     if not value:
54                         warnings.warn("Could not find accesskey for %s" % key)
55                         # Use the source language accesskey
56                         label, value = accesskey.extract(inunit.source)
57                     else:
58                         original = propunit.source
59                         # For the sake of diffs we keep the case of the
60                         # accesskey the same if we know the translation didn't
61                         # change. Casing matters in XUL.
62                         if value == propunit.source and original.lower() == value.lower():
63                             if original.isupper():
64                                 value = value.upper()
65                             elif original.islower():
66                                 value = value.lower()
67     return value
68 
69 
70 class reprop(object):
71 
72     def __init__(self, templatefile, inputstore, personality, encoding=None,
73                  remove_untranslated=False):
74         self.templatefile = templatefile
75         self.inputstore = inputstore
76         self.personality = properties.get_dialect(personality)
77         self.encoding = encoding
78         if self.encoding is None:
79             self.encoding = self.personality.default_encoding
80         self.remove_untranslated = remove_untranslated
81         self.mixer = accesskey.UnitMixer(properties.labelsuffixes,
82                                          properties.accesskeysuffixes)
83 
84     def convertstore(self, includefuzzy=False):
85         self.includefuzzy = includefuzzy
86         self.inmultilinemsgid = False
87         self.inecho = False
88         self.inputstore.makeindex()
89         if self.personality.name == "gaia":
90             self._explode_gaia_plurals()
91         outputlines = []
92         # Readlines doesn't work for UTF-16, we read() and splitlines(keepends) instead
93         content = self.templatefile.read().decode(self.encoding)
94         for line in content.splitlines(True):
95             outputstr = self.convertline(line)
96             outputlines.append(outputstr)
97         return u"".join(outputlines).encode(self.encoding)
98 
99     def _handle_accesskeys(self, inunit, currkey):
100         value = inunit.target
101         if self.personality.name == "mozilla":
102             keys = inunit.getlocations()
103             mixedkeys = self.mixer.match_entities(keys)
104             for key in keys:
105                 if key == currkey and key in self.inputstore.locationindex:
106                     propunit = self.inputstore.locationindex[key]  # find the prop
107                     value = applytranslation(key, propunit, inunit, mixedkeys)
108                     break
109 
110         return value
111 
112     def _explode_gaia_plurals(self):
113         """Explode the gaia plurals."""
114         from translate.lang import data
115         for unit in self.inputstore.units:
116             if not unit.hasplural():
117                 continue
118             if unit.isfuzzy() and not self.includefuzzy or not unit.istranslated():
119                 continue
120 
121             names = data.cldr_plural_categories
122             location = unit.getlocations()[0]
123             for category, text in zip(names, unit.target.strings):
124                 # TODO: for now we assume all forms are present. We need to
125                 # fill in the rest after mapping things to the proper CLDR names.
126                 if category == 'zero':
127                     # [zero] cases are translated as separate units
128                     continue
129                 new_unit = self.inputstore.addsourceunit(u"fish")  # not used
130                 new_location = '%s[%s]' % (location, category)
131                 new_unit.addlocation(new_location)
132                 new_unit.target = text
133                 self.inputstore.locationindex[new_location] = new_unit
134 
135             # We don't want the plural marker to be translated:
136             del self.inputstore.locationindex[location]
137 
138     def convertline(self, line):
139         returnline = u""
140         # handle multiline msgid if we're in one
141         if self.inmultilinemsgid:
142             msgid = quote.rstripeol(line).strip()
143             # see if there's more
144             self.inmultilinemsgid = (msgid[-1:] == '\\')
145             # if we're echoing...
146             if self.inecho:
147                 returnline = line
148         # otherwise, this could be a comment
149         elif line.strip()[:1] == '#':
150             returnline = quote.rstripeol(line) + eol
151         else:
152             line = quote.rstripeol(line)
153             delimiter_char, delimiter_pos = self.personality.find_delimiter(line)
154             if quote.rstripeol(line)[-1:] == '\\':
155                 self.inmultilinemsgid = True
156             if delimiter_pos == -1:
157                 key = self.personality.key_strip(line)
158                 delimiter = " %s " % self.personality.delimiters[0]
159             else:
160                 key = self.personality.key_strip(line[:delimiter_pos])
161                 # Calculate space around the equal sign
162                 prespace = line[line.find(' ', len(key)):delimiter_pos]
163                 postspacestart = len(line[delimiter_pos+1:])
164                 postspaceend = len(line[delimiter_pos+1:].lstrip())
165                 postspace = line[delimiter_pos+1:delimiter_pos+(postspacestart-postspaceend)+1]
166                 delimiter = prespace + delimiter_char + postspace
167             if key in self.inputstore.locationindex:
168                 unit = self.inputstore.locationindex[key]
169                 if not unit.istranslated() and bool(unit.source) and self.remove_untranslated:
170                     returnline = u""
171                     self.inecho = False
172                 else:
173                     if unit.isfuzzy() and not self.includefuzzy or len(unit.target) == 0:
174                         value = unit.source
175                     else:
176                         value = self._handle_accesskeys(unit, key)
177                     self.inecho = False
178                     assert isinstance(value, six.text_type)
179                     returnline = "%(key)s%(del)s%(value)s%(term)s%(eol)s" % {
180                         "key": "%s%s%s" % (self.personality.key_wrap_char,
181                                            key,
182                                            self.personality.key_wrap_char),
183                         "del": delimiter,
184                         "value": "%s%s%s" % (self.personality.value_wrap_char,
185                                              self.personality.encode(value),
186                                              self.personality.value_wrap_char),
187                         "term": self.personality.pair_terminator,
188                         "eol": eol,
189                     }
190             else:
191                 self.inecho = True
192                 returnline = line + eol
193         assert isinstance(returnline, six.text_type)
194         return returnline
195 
196 
197 def convertstrings(inputfile, outputfile, templatefile, personality="strings",
198                    includefuzzy=False, encoding=None, outputthreshold=None,
199                    remove_untranslated=False):
200     """.strings specific convertor function"""
201     return convertprop(inputfile, outputfile, templatefile,
202                        personality="strings", includefuzzy=includefuzzy,
203                        encoding=encoding, outputthreshold=outputthreshold,
204                        remove_untranslated=remove_untranslated)
205 
206 
207 def convertmozillaprop(inputfile, outputfile, templatefile,
208                        includefuzzy=False, remove_untranslated=False,
209                        outputthreshold=None):
210     """Mozilla specific convertor function"""
211     return convertprop(inputfile, outputfile, templatefile,
212                        personality="mozilla", includefuzzy=includefuzzy,
213                        remove_untranslated=remove_untranslated,
214                        outputthreshold=outputthreshold)
215 
216 
217 def convertprop(inputfile, outputfile, templatefile, personality="java",
218                 includefuzzy=False, encoding=None, remove_untranslated=False,
219                 outputthreshold=None):
220     inputstore = po.pofile(inputfile)
221 
222     if not convert.should_output_store(inputstore, outputthreshold):
223         return False
224 
225     if templatefile is None:
226         raise ValueError("must have template file for properties files")
227         # convertor = po2prop()
228     else:
229         convertor = reprop(templatefile, inputstore, personality, encoding,
230                            remove_untranslated)
231     outputprop = convertor.convertstore(includefuzzy)
232     outputfile.write(outputprop)
233     return True
234 
235 
236 formats = {
237     ("po", "properties"): ("properties", convertprop),
238     ("po", "lang"): ("lang", convertprop),
239     ("po", "strings"): ("strings", convertstrings),
240 }
241 
242 
243 def main(argv=None):
244     # handle command line options
245     parser = convert.ConvertOptionParser(formats, usetemplates=True,
246                                          description=__doc__)
247     parser.add_option(
248         "", "--personality", dest="personality",
249         default=properties.default_dialect, type="choice",
250         choices=list(properties.dialects.keys()),
251         help="override the input file format: %s (for .properties files, default: %s)" % (
252             ", ".join(six.iterkeys(properties.dialects)), properties.default_dialect),
253         metavar="TYPE")
254     parser.add_option(
255         "", "--encoding", dest="encoding", default=None,
256         help="override the encoding set by the personality",
257         metavar="ENCODING")
258     parser.add_option(
259         "", "--removeuntranslated", dest="remove_untranslated",
260         default=False, action="store_true",
261         help="remove key value from output if it is untranslated")
262     parser.add_threshold_option()
263     parser.add_fuzzy_option()
264     parser.passthrough.append("personality")
265     parser.passthrough.append("encoding")
266     parser.passthrough.append("remove_untranslated")
267     parser.run(argv)
268 
269 if __name__ == '__main__':
270     main()
271
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/translate/convert/po2prop.py b/translate/convert/po2prop.py
--- a/translate/convert/po2prop.py
+++ b/translate/convert/po2prop.py
@@ -166,7 +166,7 @@
                 delimiter = prespace + delimiter_char + postspace
             if key in self.inputstore.locationindex:
                 unit = self.inputstore.locationindex[key]
-                if not unit.istranslated() and bool(unit.source) and self.remove_untranslated:
+                if unit is None or not unit.istranslated() and bool(unit.source) and self.remove_untranslated:
                     returnline = u""
                     self.inecho = False
                 else:

{"golden_diff": "diff --git a/translate/convert/po2prop.py b/translate/convert/po2prop.py\n--- a/translate/convert/po2prop.py\n+++ b/translate/convert/po2prop.py\n@@ -166,7 +166,7 @@\n                 delimiter = prespace + delimiter_char + postspace\n             if key in self.inputstore.locationindex:\n                 unit = self.inputstore.locationindex[key]\n-                if not unit.istranslated() and bool(unit.source) and self.remove_untranslated:\n+                if unit is None or not unit.istranslated() and bool(unit.source) and self.remove_untranslated:\n                     returnline = u\"\"\n                     self.inecho = False\n                 else:\n", "issue": "po2prop is not working as expected\nI've spend some days by now and I can't seem to find any solution.\n\nI have a strings file from my ios app and I'm able to convert it successfully to a po using prop2po using this command.\n\n`prop2po --encoding utf8 -t ../en.lproj/Localizable.strings  Localizable.strings es.po`\n\nI'm executing this command inside the `/Strings/es.lproj` where the Localizables.strings is the one having the Spanish translations.\n\nSo it creates a es.po file with the msgid form the template and the translations from the Localizables.strings from the current path.\n\nThen when I try to convert back my es.po to a new Localizables.strings with the new translations I'm getting always the template.\n\nI'm using this command:\n`po2prop --encoding utf8 -i es.po -o new.strings -t ../en.lproj/Localizable.strings`\n\nnew.strings is always the same as the template that I'm using instead of having the translation from the es.po.\n\nAlso I think there is something wrong with the gettext file parser as I have to delete this two lines from the es.po generated file in order to work.\n`#, fuzzy`\n`msgid \"\"` <--\n`msgstr \"\"` <--\n\nI've added the commented fuzzy but that line does not creates trouble.\n\nIf I don't delete theese two lines when I try to use the po2prop command I get this error:\n`template ../en.lproj/Localizable.strings: 'NoneType' object has no attribute 'istranslated'`\n\nIs quite misleading as it seems that is has a problem with the template but after many tries I manage to figure that the problem was in the po file.(Or maybe not and I'm missing something).\n\nI'm using the 2.0.0b2 version.\n\nI hope someone can tell me what I'm doing wrong..or if this is actually a bug since I've tried many ways to convert from po2prop using all the settings available and I'm not able to do it right.\n\nSupposedly this should work...\n\nhttp://stackoverflow.com/questions/13939766/are-there-any-good-tools-for-ios-pseudo-localization\n\nOr this : \n\n`po2prop -t some.properties some.po some-other.properties` from http://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/prop2po.html\n\nThanks,\nRub\u00e9n.\n\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#\n# Copyright 2002-2006 Zuza Software Foundation\n#\n# This file is part of translate.\n#\n# translate is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# translate is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"Convert Gettext PO localization files to Java/Mozilla .properties files.\n\nSee: http://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/prop2po.html\nfor examples and usage instructions.\n\"\"\"\n\nimport six\nimport warnings\n\nfrom translate.convert import accesskey, convert\nfrom translate.misc import quote\nfrom translate.storage import po, properties\n\n\neol = u\"\\n\"\n\n\ndef applytranslation(key, propunit, inunit, mixedkeys):\n    \"\"\"applies the translation for key in the po unit to the prop unit\"\"\"\n    # this converts the po-style string to a prop-style string\n    value = inunit.target\n    # handle mixed keys\n    for labelsuffix in properties.labelsuffixes:\n        if key.endswith(labelsuffix):\n            if key in mixedkeys:\n                value, akey = accesskey.extract(value)\n                break\n    else:\n        for akeysuffix in properties.accesskeysuffixes:\n            if key.endswith(akeysuffix):\n                if key in mixedkeys:\n                    label, value = accesskey.extract(value)\n                    if not value:\n                        warnings.warn(\"Could not find accesskey for %s\" % key)\n                        # Use the source language accesskey\n                        label, value = accesskey.extract(inunit.source)\n                    else:\n                        original = propunit.source\n                        # For the sake of diffs we keep the case of the\n                        # accesskey the same if we know the translation didn't\n                        # change. Casing matters in XUL.\n                        if value == propunit.source and original.lower() == value.lower():\n                            if original.isupper():\n                                value = value.upper()\n                            elif original.islower():\n                                value = value.lower()\n    return value\n\n\nclass reprop(object):\n\n    def __init__(self, templatefile, inputstore, personality, encoding=None,\n                 remove_untranslated=False):\n        self.templatefile = templatefile\n        self.inputstore = inputstore\n        self.personality = properties.get_dialect(personality)\n        self.encoding = encoding\n        if self.encoding is None:\n            self.encoding = self.personality.default_encoding\n        self.remove_untranslated = remove_untranslated\n        self.mixer = accesskey.UnitMixer(properties.labelsuffixes,\n                                         properties.accesskeysuffixes)\n\n    def convertstore(self, includefuzzy=False):\n        self.includefuzzy = includefuzzy\n        self.inmultilinemsgid = False\n        self.inecho = False\n        self.inputstore.makeindex()\n        if self.personality.name == \"gaia\":\n            self._explode_gaia_plurals()\n        outputlines = []\n        # Readlines doesn't work for UTF-16, we read() and splitlines(keepends) instead\n        content = self.templatefile.read().decode(self.encoding)\n        for line in content.splitlines(True):\n            outputstr = self.convertline(line)\n            outputlines.append(outputstr)\n        return u\"\".join(outputlines).encode(self.encoding)\n\n    def _handle_accesskeys(self, inunit, currkey):\n        value = inunit.target\n        if self.personality.name == \"mozilla\":\n            keys = inunit.getlocations()\n            mixedkeys = self.mixer.match_entities(keys)\n            for key in keys:\n                if key == currkey and key in self.inputstore.locationindex:\n                    propunit = self.inputstore.locationindex[key]  # find the prop\n                    value = applytranslation(key, propunit, inunit, mixedkeys)\n                    break\n\n        return value\n\n    def _explode_gaia_plurals(self):\n        \"\"\"Explode the gaia plurals.\"\"\"\n        from translate.lang import data\n        for unit in self.inputstore.units:\n            if not unit.hasplural():\n                continue\n            if unit.isfuzzy() and not self.includefuzzy or not unit.istranslated():\n                continue\n\n            names = data.cldr_plural_categories\n            location = unit.getlocations()[0]\n            for category, text in zip(names, unit.target.strings):\n                # TODO: for now we assume all forms are present. We need to\n                # fill in the rest after mapping things to the proper CLDR names.\n                if category == 'zero':\n                    # [zero] cases are translated as separate units\n                    continue\n                new_unit = self.inputstore.addsourceunit(u\"fish\")  # not used\n                new_location = '%s[%s]' % (location, category)\n                new_unit.addlocation(new_location)\n                new_unit.target = text\n                self.inputstore.locationindex[new_location] = new_unit\n\n            # We don't want the plural marker to be translated:\n            del self.inputstore.locationindex[location]\n\n    def convertline(self, line):\n        returnline = u\"\"\n        # handle multiline msgid if we're in one\n        if self.inmultilinemsgid:\n            msgid = quote.rstripeol(line).strip()\n            # see if there's more\n            self.inmultilinemsgid = (msgid[-1:] == '\\\\')\n            # if we're echoing...\n            if self.inecho:\n                returnline = line\n        # otherwise, this could be a comment\n        elif line.strip()[:1] == '#':\n            returnline = quote.rstripeol(line) + eol\n        else:\n            line = quote.rstripeol(line)\n            delimiter_char, delimiter_pos = self.personality.find_delimiter(line)\n            if quote.rstripeol(line)[-1:] == '\\\\':\n                self.inmultilinemsgid = True\n            if delimiter_pos == -1:\n                key = self.personality.key_strip(line)\n                delimiter = \" %s \" % self.personality.delimiters[0]\n            else:\n                key = self.personality.key_strip(line[:delimiter_pos])\n                # Calculate space around the equal sign\n                prespace = line[line.find(' ', len(key)):delimiter_pos]\n                postspacestart = len(line[delimiter_pos+1:])\n                postspaceend = len(line[delimiter_pos+1:].lstrip())\n                postspace = line[delimiter_pos+1:delimiter_pos+(postspacestart-postspaceend)+1]\n                delimiter = prespace + delimiter_char + postspace\n            if key in self.inputstore.locationindex:\n                unit = self.inputstore.locationindex[key]\n                if not unit.istranslated() and bool(unit.source) and self.remove_untranslated:\n                    returnline = u\"\"\n                    self.inecho = False\n                else:\n                    if unit.isfuzzy() and not self.includefuzzy or len(unit.target) == 0:\n                        value = unit.source\n                    else:\n                        value = self._handle_accesskeys(unit, key)\n                    self.inecho = False\n                    assert isinstance(value, six.text_type)\n                    returnline = \"%(key)s%(del)s%(value)s%(term)s%(eol)s\" % {\n                        \"key\": \"%s%s%s\" % (self.personality.key_wrap_char,\n                                           key,\n                                           self.personality.key_wrap_char),\n                        \"del\": delimiter,\n                        \"value\": \"%s%s%s\" % (self.personality.value_wrap_char,\n                                             self.personality.encode(value),\n                                             self.personality.value_wrap_char),\n                        \"term\": self.personality.pair_terminator,\n                        \"eol\": eol,\n                    }\n            else:\n                self.inecho = True\n                returnline = line + eol\n        assert isinstance(returnline, six.text_type)\n        return returnline\n\n\ndef convertstrings(inputfile, outputfile, templatefile, personality=\"strings\",\n                   includefuzzy=False, encoding=None, outputthreshold=None,\n                   remove_untranslated=False):\n    \"\"\".strings specific convertor function\"\"\"\n    return convertprop(inputfile, outputfile, templatefile,\n                       personality=\"strings\", includefuzzy=includefuzzy,\n                       encoding=encoding, outputthreshold=outputthreshold,\n                       remove_untranslated=remove_untranslated)\n\n\ndef convertmozillaprop(inputfile, outputfile, templatefile,\n                       includefuzzy=False, remove_untranslated=False,\n                       outputthreshold=None):\n    \"\"\"Mozilla specific convertor function\"\"\"\n    return convertprop(inputfile, outputfile, templatefile,\n                       personality=\"mozilla\", includefuzzy=includefuzzy,\n                       remove_untranslated=remove_untranslated,\n                       outputthreshold=outputthreshold)\n\n\ndef convertprop(inputfile, outputfile, templatefile, personality=\"java\",\n                includefuzzy=False, encoding=None, remove_untranslated=False,\n                outputthreshold=None):\n    inputstore = po.pofile(inputfile)\n\n    if not convert.should_output_store(inputstore, outputthreshold):\n        return False\n\n    if templatefile is None:\n        raise ValueError(\"must have template file for properties files\")\n        # convertor = po2prop()\n    else:\n        convertor = reprop(templatefile, inputstore, personality, encoding,\n                           remove_untranslated)\n    outputprop = convertor.convertstore(includefuzzy)\n    outputfile.write(outputprop)\n    return True\n\n\nformats = {\n    (\"po\", \"properties\"): (\"properties\", convertprop),\n    (\"po\", \"lang\"): (\"lang\", convertprop),\n    (\"po\", \"strings\"): (\"strings\", convertstrings),\n}\n\n\ndef main(argv=None):\n    # handle command line options\n    parser = convert.ConvertOptionParser(formats, usetemplates=True,\n                                         description=__doc__)\n    parser.add_option(\n        \"\", \"--personality\", dest=\"personality\",\n        default=properties.default_dialect, type=\"choice\",\n        choices=list(properties.dialects.keys()),\n        help=\"override the input file format: %s (for .properties files, default: %s)\" % (\n            \", \".join(six.iterkeys(properties.dialects)), properties.default_dialect),\n        metavar=\"TYPE\")\n    parser.add_option(\n        \"\", \"--encoding\", dest=\"encoding\", default=None,\n        help=\"override the encoding set by the personality\",\n        metavar=\"ENCODING\")\n    parser.add_option(\n        \"\", \"--removeuntranslated\", dest=\"remove_untranslated\",\n        default=False, action=\"store_true\",\n        help=\"remove key value from output if it is untranslated\")\n    parser.add_threshold_option()\n    parser.add_fuzzy_option()\n    parser.passthrough.append(\"personality\")\n    parser.passthrough.append(\"encoding\")\n    parser.passthrough.append(\"remove_untranslated\")\n    parser.run(argv)\n\nif __name__ == '__main__':\n    main()\n", "path": "translate/convert/po2prop.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#\n# Copyright 2002-2006 Zuza Software Foundation\n#\n# This file is part of translate.\n#\n# translate is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# translate is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"Convert Gettext PO localization files to Java/Mozilla .properties files.\n\nSee: http://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/prop2po.html\nfor examples and usage instructions.\n\"\"\"\n\nimport six\nimport warnings\n\nfrom translate.convert import accesskey, convert\nfrom translate.misc import quote\nfrom translate.storage import po, properties\n\n\neol = u\"\\n\"\n\n\ndef applytranslation(key, propunit, inunit, mixedkeys):\n    \"\"\"applies the translation for key in the po unit to the prop unit\"\"\"\n    # this converts the po-style string to a prop-style string\n    value = inunit.target\n    # handle mixed keys\n    for labelsuffix in properties.labelsuffixes:\n        if key.endswith(labelsuffix):\n            if key in mixedkeys:\n                value, akey = accesskey.extract(value)\n                break\n    else:\n        for akeysuffix in properties.accesskeysuffixes:\n            if key.endswith(akeysuffix):\n                if key in mixedkeys:\n                    label, value = accesskey.extract(value)\n                    if not value:\n                        warnings.warn(\"Could not find accesskey for %s\" % key)\n                        # Use the source language accesskey\n                        label, value = accesskey.extract(inunit.source)\n                    else:\n                        original = propunit.source\n                        # For the sake of diffs we keep the case of the\n                        # accesskey the same if we know the translation didn't\n                        # change. Casing matters in XUL.\n                        if value == propunit.source and original.lower() == value.lower():\n                            if original.isupper():\n                                value = value.upper()\n                            elif original.islower():\n                                value = value.lower()\n    return value\n\n\nclass reprop(object):\n\n    def __init__(self, templatefile, inputstore, personality, encoding=None,\n                 remove_untranslated=False):\n        self.templatefile = templatefile\n        self.inputstore = inputstore\n        self.personality = properties.get_dialect(personality)\n        self.encoding = encoding\n        if self.encoding is None:\n            self.encoding = self.personality.default_encoding\n        self.remove_untranslated = remove_untranslated\n        self.mixer = accesskey.UnitMixer(properties.labelsuffixes,\n                                         properties.accesskeysuffixes)\n\n    def convertstore(self, includefuzzy=False):\n        self.includefuzzy = includefuzzy\n        self.inmultilinemsgid = False\n        self.inecho = False\n        self.inputstore.makeindex()\n        if self.personality.name == \"gaia\":\n            self._explode_gaia_plurals()\n        outputlines = []\n        # Readlines doesn't work for UTF-16, we read() and splitlines(keepends) instead\n        content = self.templatefile.read().decode(self.encoding)\n        for line in content.splitlines(True):\n            outputstr = self.convertline(line)\n            outputlines.append(outputstr)\n        return u\"\".join(outputlines).encode(self.encoding)\n\n    def _handle_accesskeys(self, inunit, currkey):\n        value = inunit.target\n        if self.personality.name == \"mozilla\":\n            keys = inunit.getlocations()\n            mixedkeys = self.mixer.match_entities(keys)\n            for key in keys:\n                if key == currkey and key in self.inputstore.locationindex:\n                    propunit = self.inputstore.locationindex[key]  # find the prop\n                    value = applytranslation(key, propunit, inunit, mixedkeys)\n                    break\n\n        return value\n\n    def _explode_gaia_plurals(self):\n        \"\"\"Explode the gaia plurals.\"\"\"\n        from translate.lang import data\n        for unit in self.inputstore.units:\n            if not unit.hasplural():\n                continue\n            if unit.isfuzzy() and not self.includefuzzy or not unit.istranslated():\n                continue\n\n            names = data.cldr_plural_categories\n            location = unit.getlocations()[0]\n            for category, text in zip(names, unit.target.strings):\n                # TODO: for now we assume all forms are present. We need to\n                # fill in the rest after mapping things to the proper CLDR names.\n                if category == 'zero':\n                    # [zero] cases are translated as separate units\n                    continue\n                new_unit = self.inputstore.addsourceunit(u\"fish\")  # not used\n                new_location = '%s[%s]' % (location, category)\n                new_unit.addlocation(new_location)\n                new_unit.target = text\n                self.inputstore.locationindex[new_location] = new_unit\n\n            # We don't want the plural marker to be translated:\n            del self.inputstore.locationindex[location]\n\n    def convertline(self, line):\n        returnline = u\"\"\n        # handle multiline msgid if we're in one\n        if self.inmultilinemsgid:\n            msgid = quote.rstripeol(line).strip()\n            # see if there's more\n            self.inmultilinemsgid = (msgid[-1:] == '\\\\')\n            # if we're echoing...\n            if self.inecho:\n                returnline = line\n        # otherwise, this could be a comment\n        elif line.strip()[:1] == '#':\n            returnline = quote.rstripeol(line) + eol\n        else:\n            line = quote.rstripeol(line)\n            delimiter_char, delimiter_pos = self.personality.find_delimiter(line)\n            if quote.rstripeol(line)[-1:] == '\\\\':\n                self.inmultilinemsgid = True\n            if delimiter_pos == -1:\n                key = self.personality.key_strip(line)\n                delimiter = \" %s \" % self.personality.delimiters[0]\n            else:\n                key = self.personality.key_strip(line[:delimiter_pos])\n                # Calculate space around the equal sign\n                prespace = line[line.find(' ', len(key)):delimiter_pos]\n                postspacestart = len(line[delimiter_pos+1:])\n                postspaceend = len(line[delimiter_pos+1:].lstrip())\n                postspace = line[delimiter_pos+1:delimiter_pos+(postspacestart-postspaceend)+1]\n                delimiter = prespace + delimiter_char + postspace\n            if key in self.inputstore.locationindex:\n                unit = self.inputstore.locationindex[key]\n                if unit is None or not unit.istranslated() and bool(unit.source) and self.remove_untranslated:\n                    returnline = u\"\"\n                    self.inecho = False\n                else:\n                    if unit.isfuzzy() and not self.includefuzzy or len(unit.target) == 0:\n                        value = unit.source\n                    else:\n                        value = self._handle_accesskeys(unit, key)\n                    self.inecho = False\n                    assert isinstance(value, six.text_type)\n                    returnline = \"%(key)s%(del)s%(value)s%(term)s%(eol)s\" % {\n                        \"key\": \"%s%s%s\" % (self.personality.key_wrap_char,\n                                           key,\n                                           self.personality.key_wrap_char),\n                        \"del\": delimiter,\n                        \"value\": \"%s%s%s\" % (self.personality.value_wrap_char,\n                                             self.personality.encode(value),\n                                             self.personality.value_wrap_char),\n                        \"term\": self.personality.pair_terminator,\n                        \"eol\": eol,\n                    }\n            else:\n                self.inecho = True\n                returnline = line + eol\n        assert isinstance(returnline, six.text_type)\n        return returnline\n\n\ndef convertstrings(inputfile, outputfile, templatefile, personality=\"strings\",\n                   includefuzzy=False, encoding=None, outputthreshold=None,\n                   remove_untranslated=False):\n    \"\"\".strings specific convertor function\"\"\"\n    return convertprop(inputfile, outputfile, templatefile,\n                       personality=\"strings\", includefuzzy=includefuzzy,\n                       encoding=encoding, outputthreshold=outputthreshold,\n                       remove_untranslated=remove_untranslated)\n\n\ndef convertmozillaprop(inputfile, outputfile, templatefile,\n                       includefuzzy=False, remove_untranslated=False,\n                       outputthreshold=None):\n    \"\"\"Mozilla specific convertor function\"\"\"\n    return convertprop(inputfile, outputfile, templatefile,\n                       personality=\"mozilla\", includefuzzy=includefuzzy,\n                       remove_untranslated=remove_untranslated,\n                       outputthreshold=outputthreshold)\n\n\ndef convertprop(inputfile, outputfile, templatefile, personality=\"java\",\n                includefuzzy=False, encoding=None, remove_untranslated=False,\n                outputthreshold=None):\n    inputstore = po.pofile(inputfile)\n\n    if not convert.should_output_store(inputstore, outputthreshold):\n        return False\n\n    if templatefile is None:\n        raise ValueError(\"must have template file for properties files\")\n        # convertor = po2prop()\n    else:\n        convertor = reprop(templatefile, inputstore, personality, encoding,\n                           remove_untranslated)\n    outputprop = convertor.convertstore(includefuzzy)\n    outputfile.write(outputprop)\n    return True\n\n\nformats = {\n    (\"po\", \"properties\"): (\"properties\", convertprop),\n    (\"po\", \"lang\"): (\"lang\", convertprop),\n    (\"po\", \"strings\"): (\"strings\", convertstrings),\n}\n\n\ndef main(argv=None):\n    # handle command line options\n    parser = convert.ConvertOptionParser(formats, usetemplates=True,\n                                         description=__doc__)\n    parser.add_option(\n        \"\", \"--personality\", dest=\"personality\",\n        default=properties.default_dialect, type=\"choice\",\n        choices=list(properties.dialects.keys()),\n        help=\"override the input file format: %s (for .properties files, default: %s)\" % (\n            \", \".join(six.iterkeys(properties.dialects)), properties.default_dialect),\n        metavar=\"TYPE\")\n    parser.add_option(\n        \"\", \"--encoding\", dest=\"encoding\", default=None,\n        help=\"override the encoding set by the personality\",\n        metavar=\"ENCODING\")\n    parser.add_option(\n        \"\", \"--removeuntranslated\", dest=\"remove_untranslated\",\n        default=False, action=\"store_true\",\n        help=\"remove key value from output if it is untranslated\")\n    parser.add_threshold_option()\n    parser.add_fuzzy_option()\n    parser.passthrough.append(\"personality\")\n    parser.passthrough.append(\"encoding\")\n    parser.passthrough.append(\"remove_untranslated\")\n    parser.run(argv)\n\nif __name__ == '__main__':\n    main()\n", "path": "translate/convert/po2prop.py"}]}