changeset 372:d1a9c618d2d5

We no longer neglect `catalog.plurals`. Added tests for it. Fixes #120. Added tests for the plural forms checker which will all now pass due to the above fix.
author palgarvio
date Mon, 30 Jun 2008 12:23:28 +0000
parents e6b370b49d46
children ef486619c2cc
files babel/messages/frontend.py babel/messages/pofile.py babel/messages/tests/__init__.py babel/messages/tests/checkers.py babel/messages/tests/frontend.py babel/messages/tests/pofile.py
diffstat 6 files changed, 563 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/babel/messages/frontend.py
+++ b/babel/messages/frontend.py
@@ -440,7 +440,9 @@
 
         infile = open(self.input_file, 'r')
         try:
-            catalog = read_po(infile)
+            # Although reading from the catalog template, read_po must be fed
+            # the locale in order to correcly calculate plurals
+            catalog = read_po(infile, locale=self.locale)
         finally:
             infile.close()
 
--- a/babel/messages/pofile.py
+++ b/babel/messages/pofile.py
@@ -147,8 +147,14 @@
             msgid = tuple([denormalize(m) for m in messages])
         else:
             msgid = denormalize(messages[0])
-        if len(translations) > 1:
-            string = tuple([denormalize(t[1]) for t in translations])
+        if isinstance(msgid, (list, tuple)):
+            string = []
+            for idx in range(catalog.num_plurals):
+                try:
+                    string.append(translations[idx])
+                except IndexError:
+                    string.append((idx, ''))
+            string = tuple([denormalize(t[1]) for t in string])
         else:
             string = denormalize(translations[0][1])
         if context:
@@ -396,9 +402,14 @@
             _write('%smsgid_plural %s\n' % (
                 prefix, _normalize(message.id[1], prefix)
             ))
-            for i, string in enumerate(message.string):
+
+            for idx in range(catalog.num_plurals):
+                try:
+                    string = message.string[idx]
+                except IndexError:
+                    string = ''
                 _write('%smsgstr[%d] %s\n' % (
-                    prefix, i, _normalize(message.string[i], prefix)
+                    prefix, idx, _normalize(string, prefix)
                 ))
         else:
             _write('%smsgid %s\n' % (prefix, _normalize(message.id, prefix)))
--- a/babel/messages/tests/__init__.py
+++ b/babel/messages/tests/__init__.py
@@ -15,7 +15,7 @@
 
 def suite():
     from babel.messages.tests import catalog, extract, frontend, mofile, \
-                                     plurals, pofile
+                                     plurals, pofile, checkers
     suite = unittest.TestSuite()
     suite.addTest(catalog.suite())
     suite.addTest(extract.suite())
@@ -23,6 +23,7 @@
     suite.addTest(mofile.suite())
     suite.addTest(plurals.suite())
     suite.addTest(pofile.suite())
+    suite.addTest(checkers.suite())
     return suite
 
 if __name__ == '__main__':
new file mode 100644
--- /dev/null
+++ b/babel/messages/tests/checkers.py
@@ -0,0 +1,371 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2008 Edgewall Software
+# All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://babel.edgewall.org/wiki/License.
+#
+# This software consists of voluntary contributions made by many
+# individuals. For the exact contribution history, see the revision
+# history and logs, available at http://babel.edgewall.org/log/.
+
+from datetime import datetime
+import time
+import unittest
+from StringIO import StringIO
+
+from babel import __version__ as VERSION
+from babel.core import Locale, UnknownLocaleError
+from babel.dates import format_datetime
+from babel.messages import checkers
+from babel.messages.plurals import PLURALS
+from babel.messages.pofile import read_po
+from babel.util import LOCALTZ
+
+class CheckersTestCase(unittest.TestCase):
+    # the last msgstr[idx] is always missing except for singular plural forms    
+                
+    def test_1_num_plurals_checkers(self):
+        for _locale in [p for p in PLURALS if PLURALS[p][0]==1]:
+            try:
+                locale = Locale.parse(_locale)
+            except UnknownLocaleError:
+                # Just an alias? Not what we're testing here, let's continue
+                continue
+            po_file = (ur"""\
+# %(english_name)s translations for TestProject.
+# Copyright (C) 2007 FooBar, Inc.
+# This file is distributed under the same license as the TestProject
+# project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: TestProject 0.1\n"
+"Report-Msgid-Bugs-To: bugs.address@email.tld\n"
+"POT-Creation-Date: 2007-04-01 15:30+0200\n"
+"PO-Revision-Date: %(date)s\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: %(locale)s <LL@li.org>\n"
+"Plural-Forms: nplurals=%(num_plurals)s; plural=%(plural_expr)s\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel %(version)s\n"
+
+#. This will be a translator comment,
+#. that will include several lines
+#: project/file1.py:8
+msgid "bar"
+msgstr ""
+
+#: project/file2.py:9
+msgid "foobar"
+msgid_plural "foobars"
+msgstr[0] ""
+
+""" % dict(locale       = _locale,
+           english_name = locale.english_name,
+           version      = VERSION,
+           year         = time.strftime('%Y'),
+           date         = format_datetime(datetime.now(LOCALTZ),
+                                          'yyyy-MM-dd HH:mmZ',
+                                          tzinfo=LOCALTZ, locale=_locale),
+           num_plurals  = PLURALS[_locale][0],
+           plural_expr  = PLURALS[_locale][0])).encode('utf-8')
+           
+            # This test will fail for revisions <= 406 because so far
+            # catalog.num_plurals was neglected
+            catalog = read_po(StringIO(po_file), _locale)
+            message = catalog.get('foobar')
+            checkers.num_plurals(catalog, message)        
+            
+    def test_2_num_plurals_checkers(self):
+        # in this testcase we add an extra msgstr[idx], we should be
+        # disregarding it
+        for _locale in [p for p in PLURALS if PLURALS[p][0]==2]:
+            if _locale in ['nn', 'no']:
+                _locale = 'nn_NO'                
+                num_plurals  = PLURALS[_locale.split('_')[0]][0]
+                plural_expr  = PLURALS[_locale.split('_')[0]][1]
+            else:                
+                num_plurals  = PLURALS[_locale][0]
+                plural_expr  = PLURALS[_locale][1]
+            try:
+                locale = Locale(_locale)
+                date = format_datetime(datetime.now(LOCALTZ),
+                                       'yyyy-MM-dd HH:mmZ',
+                                       tzinfo=LOCALTZ, locale=_locale),
+            except UnknownLocaleError:
+                # Just an alias? Not what we're testing here, let's continue
+                continue
+            po_file = (ur"""\
+# %(english_name)s translations for TestProject.
+# Copyright (C) 2007 FooBar, Inc.
+# This file is distributed under the same license as the TestProject
+# project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: TestProject 0.1\n"
+"Report-Msgid-Bugs-To: bugs.address@email.tld\n"
+"POT-Creation-Date: 2007-04-01 15:30+0200\n"
+"PO-Revision-Date: %(date)s\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: %(locale)s <LL@li.org>\n"
+"Plural-Forms: nplurals=%(num_plurals)s; plural=%(plural_expr)s\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel %(version)s\n"
+
+#. This will be a translator comment,
+#. that will include several lines
+#: project/file1.py:8
+msgid "bar"
+msgstr ""
+
+#: project/file2.py:9
+msgid "foobar"
+msgid_plural "foobars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+""" % dict(locale       = _locale,
+           english_name = locale.english_name,
+           version      = VERSION,
+           year         = time.strftime('%Y'),
+           date         = date,
+           num_plurals  = num_plurals,
+           plural_expr  = plural_expr)).encode('utf-8')
+            # we should be adding the missing msgstr[0]
+           
+            # This test will fail for revisions <= 406 because so far
+            # catalog.num_plurals was neglected
+            catalog = read_po(StringIO(po_file), _locale)
+            message = catalog.get('foobar')
+            checkers.num_plurals(catalog, message)
+    
+    
+    def test_3_num_plurals_checkers(self):
+        for _locale in [p for p in PLURALS if PLURALS[p][0]==3]:
+            po_file = r"""\
+# %(english_name)s translations for TestProject.
+# Copyright (C) 2007 FooBar, Inc.
+# This file is distributed under the same license as the TestProject
+# project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: TestProject 0.1\n"
+"Report-Msgid-Bugs-To: bugs.address@email.tld\n"
+"POT-Creation-Date: 2007-04-01 15:30+0200\n"
+"PO-Revision-Date: %(date)s\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: %(locale)s <LL@li.org>\n"
+"Plural-Forms: nplurals=%(num_plurals)s; plural=%(plural_expr)s\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel %(version)s\n"
+
+#. This will be a translator comment,
+#. that will include several lines
+#: project/file1.py:8
+msgid "bar"
+msgstr ""
+
+#: project/file2.py:9
+msgid "foobar"
+msgid_plural "foobars"
+msgstr[0] ""
+msgstr[1] ""
+
+""" % dict(locale       = _locale,
+           english_name = Locale.parse(_locale).english_name,
+           version      = VERSION,
+           year         = time.strftime('%Y'),
+           date         = format_datetime(datetime.now(LOCALTZ),
+                                          'yyyy-MM-dd HH:mmZ',
+                                          tzinfo=LOCALTZ, locale=_locale),
+           num_plurals  = PLURALS[_locale][0],
+           plural_expr  = PLURALS[_locale][0])
+           
+            # This test will fail for revisions <= 406 because so far
+            # catalog.num_plurals was neglected
+            catalog = read_po(StringIO(po_file), _locale)
+            message = catalog.get('foobar')
+            checkers.num_plurals(catalog, message)
+            
+    def test_4_num_plurals_checkers(self):
+        for _locale in [p for p in PLURALS if PLURALS[p][0]==4]:
+            po_file = r"""\
+# %(english_name)s translations for TestProject.
+# Copyright (C) 2007 FooBar, Inc.
+# This file is distributed under the same license as the TestProject
+# project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: TestProject 0.1\n"
+"Report-Msgid-Bugs-To: bugs.address@email.tld\n"
+"POT-Creation-Date: 2007-04-01 15:30+0200\n"
+"PO-Revision-Date: %(date)s\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: %(locale)s <LL@li.org>\n"
+"Plural-Forms: nplurals=%(num_plurals)s; plural=%(plural_expr)s\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel %(version)s\n"
+
+#. This will be a translator comment,
+#. that will include several lines
+#: project/file1.py:8
+msgid "bar"
+msgstr ""
+
+#: project/file2.py:9
+msgid "foobar"
+msgid_plural "foobars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+""" % dict(locale       = _locale,
+           english_name = Locale.parse(_locale).english_name,
+           version      = VERSION,
+           year         = time.strftime('%Y'),
+           date         = format_datetime(datetime.now(LOCALTZ),
+                                          'yyyy-MM-dd HH:mmZ',
+                                          tzinfo=LOCALTZ, locale=_locale),
+           num_plurals  = PLURALS[_locale][0],
+           plural_expr  = PLURALS[_locale][0])
+           
+            # This test will fail for revisions <= 406 because so far
+            # catalog.num_plurals was neglected
+            catalog = read_po(StringIO(po_file), _locale)
+            message = catalog.get('foobar')
+            checkers.num_plurals(catalog, message)
+            
+    def test_5_num_plurals_checkers(self):
+        for _locale in [p for p in PLURALS if PLURALS[p][0]==5]:
+            po_file = r"""\
+# %(english_name)s translations for TestProject.
+# Copyright (C) 2007 FooBar, Inc.
+# This file is distributed under the same license as the TestProject
+# project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: TestProject 0.1\n"
+"Report-Msgid-Bugs-To: bugs.address@email.tld\n"
+"POT-Creation-Date: 2007-04-01 15:30+0200\n"
+"PO-Revision-Date: %(date)s\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: %(locale)s <LL@li.org>\n"
+"Plural-Forms: nplurals=%(num_plurals)s; plural=%(plural_expr)s\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel %(version)s\n"
+
+#. This will be a translator comment,
+#. that will include several lines
+#: project/file1.py:8
+msgid "bar"
+msgstr ""
+
+#: project/file2.py:9
+msgid "foobar"
+msgid_plural "foobars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+""" % dict(locale       = _locale,
+           english_name = Locale.parse(_locale).english_name,
+           version      = VERSION,
+           year         = time.strftime('%Y'),
+           date         = format_datetime(datetime.now(LOCALTZ),
+                                          'yyyy-MM-dd HH:mmZ',
+                                          tzinfo=LOCALTZ, locale=_locale),
+           num_plurals  = PLURALS[_locale][0],
+           plural_expr  = PLURALS[_locale][0])
+           
+            # This test will fail for revisions <= 406 because so far
+            # catalog.num_plurals was neglected
+            catalog = read_po(StringIO(po_file), _locale)
+            message = catalog.get('foobar')
+            checkers.num_plurals(catalog, message)
+
+    def test_6_num_plurals_checkers(self):
+        for _locale in [p for p in PLURALS if PLURALS[p][0]==6]:
+            po_file = r"""\
+# %(english_name)s translations for TestProject.
+# Copyright (C) 2007 FooBar, Inc.
+# This file is distributed under the same license as the TestProject
+# project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: TestProject 0.1\n"
+"Report-Msgid-Bugs-To: bugs.address@email.tld\n"
+"POT-Creation-Date: 2007-04-01 15:30+0200\n"
+"PO-Revision-Date: %(date)s\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: %(locale)s <LL@li.org>\n"
+"Plural-Forms: nplurals=%(num_plurals)s; plural=%(plural_expr)s\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel %(version)s\n"
+
+#. This will be a translator comment,
+#. that will include several lines
+#: project/file1.py:8
+msgid "bar"
+msgstr ""
+
+#: project/file2.py:9
+msgid "foobar"
+msgid_plural "foobars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+""" % dict(locale       = _locale,
+           english_name = Locale.parse(_locale).english_name,
+           version      = VERSION,
+           year         = time.strftime('%Y'),
+           date         = format_datetime(datetime.now(LOCALTZ),
+                                          'yyyy-MM-dd HH:mmZ',
+                                          tzinfo=LOCALTZ, locale=_locale),
+           num_plurals  = PLURALS[_locale][0],
+           plural_expr  = PLURALS[_locale][0])
+           
+            # This test will fail for revisions <= 406 because so far
+            # catalog.num_plurals was neglected
+            catalog = read_po(StringIO(po_file), _locale)
+            message = catalog.get('foobar')
+            checkers.num_plurals(catalog, message)
+    
+    
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(CheckersTestCase))
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='suite')
--- a/babel/messages/tests/frontend.py
+++ b/babel/messages/tests/frontend.py
@@ -348,8 +348,7 @@
 
 
 class InitCatalogNonFuzzyTestCase(unittest.TestCase):
-    # FIXME: what is this test case about?
-
+    # init catalog keeps the catalog non fuzzy
     def setUp(self):
         self.olddir = os.getcwd()
         self.datadir = os.path.join(os.path.dirname(__file__), 'data')
@@ -420,6 +419,151 @@
        'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ',
                                tzinfo=LOCALTZ, locale='en')},
        open(po_file, 'U').read())
+        
+class InitCatalogMoreThan2PluralForms(unittest.TestCase):
+    def setUp(self):
+        self.olddir = os.getcwd()
+        self.datadir = os.path.join(os.path.dirname(__file__), 'data')
+        os.chdir(self.datadir)
+        _global_log.threshold = 5 # shut up distutils logging
+
+        self.dist = Distribution(dict(
+            name='TestProject',
+            version='0.1',
+            packages=['project']
+        ))
+        self.cmd = frontend.init_catalog(self.dist)
+        self.cmd.initialize_options()
+
+    def tearDown(self):
+        locale_dir = os.path.join(self.datadir, 'project', 'i18n', 'lv_LV')
+        if os.path.isdir(locale_dir):
+            shutil.rmtree(locale_dir)
+
+        os.chdir(self.olddir)
+
+    def test_correct_init_plurals(self):
+        self.cmd.input_file = 'project/i18n/messages.pot'
+        self.cmd.locale = 'lv_LV'
+        self.cmd.output_dir = 'project/i18n'
+
+        self.cmd.finalize_options()
+        self.cmd.run()
+
+        po_file = os.path.join(self.datadir, 'project', 'i18n', 'lv_LV',
+                               'LC_MESSAGES', 'messages.po')
+        assert os.path.isfile(po_file)
+
+        self.assertEqual(
+r"""# Latvian (Latvia) translations for TestProject.
+# Copyright (C) 2007 FooBar, Inc.
+# This file is distributed under the same license as the TestProject
+# project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: TestProject 0.1\n"
+"Report-Msgid-Bugs-To: bugs.address@email.tld\n"
+"POT-Creation-Date: 2007-04-01 15:30+0200\n"
+"PO-Revision-Date: %(date)s\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: lv_LV <LL@li.org>\n"
+"Plural-Forms: nplurals=3; plural=(n%%10==1 && n%%100!=11 ? 0 : n != 0 ? 1 :"
+" 2)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel %(version)s\n"
+
+#. This will be a translator coment,
+#. that will include several lines
+#: project/file1.py:8
+msgid "bar"
+msgstr ""
+
+#: project/file2.py:9
+msgid "foobar"
+msgid_plural "foobars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+""" % {'version': VERSION,
+       'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ',
+                               tzinfo=LOCALTZ, locale='en')},
+       open(po_file, 'U').read())
+        
+class InitCatalogSingularPluralForms(unittest.TestCase):
+    def setUp(self):
+        self.olddir = os.getcwd()
+        self.datadir = os.path.join(os.path.dirname(__file__), 'data')
+        os.chdir(self.datadir)
+        _global_log.threshold = 5 # shut up distutils logging
+
+        self.dist = Distribution(dict(
+            name='TestProject',
+            version='0.1',
+            packages=['project']
+        ))
+        self.cmd = frontend.init_catalog(self.dist)
+        self.cmd.initialize_options()
+
+    def tearDown(self):
+        locale_dir = os.path.join(self.datadir, 'project', 'i18n', 'ja_JP')
+        if os.path.isdir(locale_dir):
+            shutil.rmtree(locale_dir)
+
+        os.chdir(self.olddir)
+
+    def test_correct_init_plurals(self):
+        self.cmd.input_file = 'project/i18n/messages.pot'
+        self.cmd.locale = 'ja_JP'
+        self.cmd.output_dir = 'project/i18n'
+
+        self.cmd.finalize_options()
+        self.cmd.run()
+
+        po_file = os.path.join(self.datadir, 'project', 'i18n', 'ja_JP',
+                               'LC_MESSAGES', 'messages.po')
+        assert os.path.isfile(po_file)
+
+        self.assertEqual(
+r"""# Japanese (Japan) translations for TestProject.
+# Copyright (C) 2007 FooBar, Inc.
+# This file is distributed under the same license as the TestProject
+# project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: TestProject 0.1\n"
+"Report-Msgid-Bugs-To: bugs.address@email.tld\n"
+"POT-Creation-Date: 2007-04-01 15:30+0200\n"
+"PO-Revision-Date: %(date)s\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: ja_JP <LL@li.org>\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel %(version)s\n"
+
+#. This will be a translator coment,
+#. that will include several lines
+#: project/file1.py:8
+msgid "bar"
+msgstr ""
+
+#: project/file2.py:9
+msgid "foobar"
+msgid_plural "foobars"
+msgstr[0] ""
+
+""" % {'version': VERSION,
+       'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ',
+                               tzinfo=LOCALTZ, locale='ja_JP')},
+       open(po_file, 'U').read())
 
 
 class CommandLineInterfaceTestCase(unittest.TestCase):
@@ -684,6 +828,8 @@
     suite.addTest(unittest.makeSuite(ExtractMessagesTestCase))
     suite.addTest(unittest.makeSuite(InitCatalogTestCase))
     suite.addTest(unittest.makeSuite(InitCatalogNonFuzzyTestCase))
+    suite.addTest(unittest.makeSuite(InitCatalogMoreThan2PluralForms))
+    suite.addTest(unittest.makeSuite(InitCatalogSingularPluralForms))
     suite.addTest(unittest.makeSuite(CommandLineInterfaceTestCase))
     return suite
 
--- a/babel/messages/tests/pofile.py
+++ b/babel/messages/tests/pofile.py
@@ -163,6 +163,30 @@
         message = catalog.get('bar', context='Menu')
         self.assertEqual('Menu', message.context)
 
+    def test_singlular_plural_form(self):
+        buf = StringIO(r'''msgid "foo"
+msgid_plural "foo"
+msgstr[0] "Voh"
+msgstr[1] "Vohs"''') # This is a bad po, ja_JP only uses msgstr[0]
+        catalog = pofile.read_po(buf, locale='ja_JP')
+        self.assertEqual(1, len(catalog))
+        self.assertEqual(1, catalog.num_plurals)
+        message = catalog.get('foo')
+        self.assertEqual(1, len(message.string))
+        
+    def test_more_than_two_plural_forms(self):
+        buf = StringIO(r'''msgid "foo"
+msgid_plural "foo"
+msgstr[0] "Voh"
+msgstr[1] "Vohs"''') # last translation form is missing
+#msgstr[2] "Vohss"''')
+        catalog = pofile.read_po(buf, locale='lv_LV')
+        self.assertEqual(1, len(catalog))
+        self.assertEqual(3, catalog.num_plurals)
+        message = catalog.get('foo')
+        self.assertEqual(3, len(message.string))
+        self.assertEqual('', message.string[2])
+
 
 class WritePoTestCase(unittest.TestCase):
 
Copyright (C) 2012-2017 Edgewall Software