cmlenz@12: # -*- coding: utf-8 -*- cmlenz@12: # jruigrok@530: # Copyright (C) 2007-2011 Edgewall Software cmlenz@12: # All rights reserved. cmlenz@12: # cmlenz@12: # This software is licensed as described in the file COPYING, which cmlenz@12: # you should have received as part of this distribution. The terms cmlenz@12: # are also available at http://babel.edgewall.org/wiki/License. cmlenz@12: # cmlenz@12: # This software consists of voluntary contributions made by many cmlenz@12: # individuals. For the exact contribution history, see the revision cmlenz@12: # history and logs, available at http://babel.edgewall.org/log/. cmlenz@12: cmlenz@134: from datetime import datetime cmlenz@117: from distutils.dist import Distribution palgarvio@372: from distutils.errors import DistutilsOptionError cmlenz@117: from distutils.log import _global_log cmlenz@12: import doctest fschwarz@521: import logging cmlenz@117: import os cmlenz@120: import shutil cmlenz@127: from StringIO import StringIO cmlenz@127: import sys cmlenz@117: import time cmlenz@12: import unittest cmlenz@12: palgarvio@114: from babel import __version__ as VERSION cmlenz@134: from babel.dates import format_datetime palgarvio@372: from babel.messages import frontend cmlenz@134: from babel.util import LOCALTZ palgarvio@114: cmlenz@117: fschwarz@573: this_dir = os.path.abspath(os.path.dirname(__file__)) fschwarz@573: cmlenz@160: class CompileCatalogTestCase(unittest.TestCase): cmlenz@160: cmlenz@160: def setUp(self): cmlenz@160: self.olddir = os.getcwd() fschwarz@573: self.datadir = os.path.join(this_dir, 'data') cmlenz@160: os.chdir(self.datadir) cmlenz@160: _global_log.threshold = 5 # shut up distutils logging cmlenz@160: cmlenz@160: self.dist = Distribution(dict( cmlenz@160: name='TestProject', cmlenz@160: version='0.1', cmlenz@160: packages=['project'] cmlenz@160: )) cmlenz@160: self.cmd = frontend.compile_catalog(self.dist) cmlenz@160: self.cmd.initialize_options() cmlenz@160: cmlenz@160: def tearDown(self): cmlenz@160: os.chdir(self.olddir) cmlenz@160: cmlenz@160: def test_no_directory_or_output_file_specified(self): cmlenz@160: self.cmd.locale = 'en_US' cmlenz@160: self.cmd.input_file = 'dummy' cmlenz@160: self.assertRaises(DistutilsOptionError, self.cmd.finalize_options) cmlenz@160: cmlenz@160: def test_no_directory_or_input_file_specified(self): cmlenz@160: self.cmd.locale = 'en_US' cmlenz@160: self.cmd.output_file = 'dummy' cmlenz@160: self.assertRaises(DistutilsOptionError, self.cmd.finalize_options) cmlenz@160: cmlenz@160: cmlenz@117: class ExtractMessagesTestCase(unittest.TestCase): cmlenz@117: palgarvio@114: def setUp(self): palgarvio@114: self.olddir = os.getcwd() fschwarz@573: self.datadir = os.path.join(this_dir, 'data') palgarvio@114: os.chdir(self.datadir) cmlenz@117: _global_log.threshold = 5 # shut up distutils logging cmlenz@117: cmlenz@117: self.dist = Distribution(dict( cmlenz@117: name='TestProject', cmlenz@117: version='0.1', cmlenz@117: packages=['project'] cmlenz@117: )) cmlenz@117: self.cmd = frontend.extract_messages(self.dist) cmlenz@117: self.cmd.initialize_options() cmlenz@117: cmlenz@117: def tearDown(self): fschwarz@566: pot_file = self._pot_file() cmlenz@117: if os.path.isfile(pot_file): cmlenz@117: os.unlink(pot_file) cmlenz@117: cmlenz@117: os.chdir(self.olddir) cmlenz@117: fschwarz@566: def _i18n_dir(self): fschwarz@566: return os.path.join(self.datadir, 'project', 'i18n') fschwarz@566: fschwarz@566: def _pot_file(self): fschwarz@566: return os.path.join(self._i18n_dir(), 'temp.pot') fschwarz@566: fschwarz@566: def assert_pot_file_exists(self): fschwarz@566: assert os.path.isfile(self._pot_file()) fschwarz@566: cmlenz@117: def test_neither_default_nor_custom_keywords(self): cmlenz@120: self.cmd.output_file = 'dummy' cmlenz@117: self.cmd.no_default_keywords = True cmlenz@117: self.assertRaises(DistutilsOptionError, self.cmd.finalize_options) cmlenz@117: cmlenz@117: def test_no_output_file_specified(self): cmlenz@117: self.assertRaises(DistutilsOptionError, self.cmd.finalize_options) cmlenz@117: cmlenz@117: def test_both_sort_output_and_sort_by_file(self): cmlenz@120: self.cmd.output_file = 'dummy' cmlenz@117: self.cmd.sort_output = True cmlenz@117: self.cmd.sort_by_file = True cmlenz@117: self.assertRaises(DistutilsOptionError, self.cmd.finalize_options) cmlenz@117: cmlenz@117: def test_extraction_with_default_mapping(self): cmlenz@117: self.cmd.copyright_holder = 'FooBar, Inc.' cmlenz@117: self.cmd.msgid_bugs_address = 'bugs.address@email.tld' cmlenz@120: self.cmd.output_file = 'project/i18n/temp.pot' cmlenz@117: self.cmd.add_comments = 'TRANSLATOR:,TRANSLATORS:' cmlenz@117: cmlenz@117: self.cmd.finalize_options() cmlenz@117: self.cmd.run() cmlenz@120: fschwarz@566: self.assert_pot_file_exists() cmlenz@120: cmlenz@120: self.assertEqual( palgarvio@114: r"""# Translations template for TestProject. cmlenz@117: # Copyright (C) %(year)s FooBar, Inc. palgarvio@114: # This file is distributed under the same license as the TestProject palgarvio@114: # project. palgarvio@114: # FIRST AUTHOR , %(year)s. palgarvio@114: # palgarvio@114: #, fuzzy palgarvio@114: msgid "" palgarvio@114: msgstr "" palgarvio@114: "Project-Id-Version: TestProject 0.1\n" palgarvio@114: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" palgarvio@114: "POT-Creation-Date: %(date)s\n" palgarvio@114: "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" palgarvio@114: "Last-Translator: FULL NAME \n" palgarvio@114: "Language-Team: LANGUAGE \n" palgarvio@114: "MIME-Version: 1.0\n" palgarvio@114: "Content-Type: text/plain; charset=utf-8\n" palgarvio@114: "Content-Transfer-Encoding: 8bit\n" palgarvio@114: "Generated-By: Babel %(version)s\n" palgarvio@114: aronacher@338: #. TRANSLATOR: This will be a translator coment, palgarvio@114: #. that will include several lines palgarvio@114: #: project/file1.py:8 palgarvio@114: msgid "bar" palgarvio@114: msgstr "" palgarvio@114: palgarvio@114: #: project/file2.py:9 palgarvio@114: msgid "foobar" palgarvio@114: msgid_plural "foobars" palgarvio@114: msgstr[0] "" palgarvio@114: msgstr[1] "" palgarvio@114: cmlenz@458: #: project/ignored/this_wont_normally_be_here.py:11 palgarvio@114: msgid "FooBar" palgarvio@114: msgid_plural "FooBars" palgarvio@114: msgstr[0] "" palgarvio@114: msgstr[1] "" palgarvio@114: palgarvio@114: """ % {'version': VERSION, palgarvio@114: 'year': time.strftime('%Y'), cmlenz@134: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', cmlenz@134: tzinfo=LOCALTZ, locale='en')}, fschwarz@566: open(self._pot_file(), 'U').read()) cmlenz@117: cmlenz@117: def test_extraction_with_mapping_file(self): cmlenz@117: self.cmd.copyright_holder = 'FooBar, Inc.' cmlenz@117: self.cmd.msgid_bugs_address = 'bugs.address@email.tld' cmlenz@117: self.cmd.mapping_file = 'mapping.cfg' cmlenz@120: self.cmd.output_file = 'project/i18n/temp.pot' cmlenz@117: self.cmd.add_comments = 'TRANSLATOR:,TRANSLATORS:' cmlenz@117: cmlenz@117: self.cmd.finalize_options() cmlenz@117: self.cmd.run() cmlenz@120: fschwarz@566: self.assert_pot_file_exists() cmlenz@120: cmlenz@120: self.assertEqual( palgarvio@114: r"""# Translations template for TestProject. cmlenz@117: # Copyright (C) %(year)s FooBar, Inc. palgarvio@114: # This file is distributed under the same license as the TestProject palgarvio@114: # project. palgarvio@114: # FIRST AUTHOR , %(year)s. palgarvio@114: # palgarvio@114: #, fuzzy palgarvio@114: msgid "" palgarvio@114: msgstr "" palgarvio@114: "Project-Id-Version: TestProject 0.1\n" palgarvio@114: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" palgarvio@114: "POT-Creation-Date: %(date)s\n" palgarvio@114: "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" palgarvio@114: "Last-Translator: FULL NAME \n" palgarvio@114: "Language-Team: LANGUAGE \n" palgarvio@114: "MIME-Version: 1.0\n" palgarvio@114: "Content-Type: text/plain; charset=utf-8\n" palgarvio@114: "Content-Transfer-Encoding: 8bit\n" palgarvio@114: "Generated-By: Babel %(version)s\n" palgarvio@114: aronacher@338: #. TRANSLATOR: This will be a translator coment, palgarvio@114: #. that will include several lines palgarvio@114: #: project/file1.py:8 palgarvio@114: msgid "bar" palgarvio@114: msgstr "" palgarvio@114: palgarvio@114: #: project/file2.py:9 palgarvio@114: msgid "foobar" palgarvio@114: msgid_plural "foobars" palgarvio@114: msgstr[0] "" palgarvio@114: msgstr[1] "" palgarvio@114: palgarvio@114: """ % {'version': VERSION, palgarvio@114: 'year': time.strftime('%Y'), cmlenz@134: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', cmlenz@134: tzinfo=LOCALTZ, locale='en')}, fschwarz@566: open(self._pot_file(), 'U').read()) cmlenz@117: cmlenz@117: def test_extraction_with_mapping_dict(self): cmlenz@117: self.dist.message_extractors = { cmlenz@117: 'project': [ cmlenz@458: ('**/ignored/**.*', 'ignore', None), cmlenz@458: ('**.py', 'python', None), cmlenz@117: ] cmlenz@117: } cmlenz@117: self.cmd.copyright_holder = 'FooBar, Inc.' cmlenz@117: self.cmd.msgid_bugs_address = 'bugs.address@email.tld' cmlenz@120: self.cmd.output_file = 'project/i18n/temp.pot' cmlenz@117: self.cmd.add_comments = 'TRANSLATOR:,TRANSLATORS:' cmlenz@117: cmlenz@117: self.cmd.finalize_options() cmlenz@117: self.cmd.run() cmlenz@120: fschwarz@566: self.assert_pot_file_exists() cmlenz@120: cmlenz@120: self.assertEqual( cmlenz@117: r"""# Translations template for TestProject. cmlenz@117: # Copyright (C) %(year)s FooBar, Inc. cmlenz@117: # This file is distributed under the same license as the TestProject cmlenz@117: # project. cmlenz@117: # FIRST AUTHOR , %(year)s. cmlenz@117: # cmlenz@117: #, fuzzy cmlenz@117: msgid "" cmlenz@117: msgstr "" cmlenz@117: "Project-Id-Version: TestProject 0.1\n" cmlenz@117: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" cmlenz@117: "POT-Creation-Date: %(date)s\n" cmlenz@117: "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" cmlenz@117: "Last-Translator: FULL NAME \n" cmlenz@117: "Language-Team: LANGUAGE \n" cmlenz@117: "MIME-Version: 1.0\n" cmlenz@117: "Content-Type: text/plain; charset=utf-8\n" cmlenz@117: "Content-Transfer-Encoding: 8bit\n" cmlenz@117: "Generated-By: Babel %(version)s\n" cmlenz@117: aronacher@338: #. TRANSLATOR: This will be a translator coment, cmlenz@117: #. that will include several lines cmlenz@117: #: project/file1.py:8 cmlenz@117: msgid "bar" cmlenz@117: msgstr "" cmlenz@117: cmlenz@117: #: project/file2.py:9 cmlenz@117: msgid "foobar" cmlenz@117: msgid_plural "foobars" cmlenz@117: msgstr[0] "" cmlenz@117: msgstr[1] "" cmlenz@117: cmlenz@117: """ % {'version': VERSION, cmlenz@117: 'year': time.strftime('%Y'), cmlenz@134: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', cmlenz@134: tzinfo=LOCALTZ, locale='en')}, fschwarz@566: open(self._pot_file(), 'U').read()) cmlenz@120: cmlenz@120: cmlenz@181: class InitCatalogTestCase(unittest.TestCase): cmlenz@120: cmlenz@120: def setUp(self): cmlenz@120: self.olddir = os.getcwd() fschwarz@573: self.datadir = os.path.join(this_dir, 'data') cmlenz@120: os.chdir(self.datadir) cmlenz@120: _global_log.threshold = 5 # shut up distutils logging cmlenz@120: cmlenz@120: self.dist = Distribution(dict( cmlenz@120: name='TestProject', cmlenz@120: version='0.1', cmlenz@120: packages=['project'] cmlenz@120: )) cmlenz@181: self.cmd = frontend.init_catalog(self.dist) cmlenz@120: self.cmd.initialize_options() cmlenz@120: cmlenz@120: def tearDown(self): palgarvio@371: for dirname in ['en_US', 'ja_JP', 'lv_LV']: fschwarz@566: locale_dir = os.path.join(self._i18n_dir(), dirname) palgarvio@371: if os.path.isdir(locale_dir): palgarvio@371: shutil.rmtree(locale_dir) cmlenz@120: cmlenz@120: os.chdir(self.olddir) cmlenz@120: fschwarz@566: def _i18n_dir(self): fschwarz@566: return os.path.join(self.datadir, 'project', 'i18n') fschwarz@566: fschwarz@566: def _po_file(self, locale): fschwarz@566: return os.path.join(self._i18n_dir(), locale, 'LC_MESSAGES', fschwarz@566: 'messages.po') fschwarz@566: cmlenz@120: def test_no_input_file(self): cmlenz@120: self.cmd.locale = 'en_US' cmlenz@120: self.cmd.output_file = 'dummy' cmlenz@120: self.assertRaises(DistutilsOptionError, self.cmd.finalize_options) cmlenz@120: cmlenz@120: def test_no_locale(self): cmlenz@120: self.cmd.input_file = 'dummy' cmlenz@120: self.cmd.output_file = 'dummy' cmlenz@120: self.assertRaises(DistutilsOptionError, self.cmd.finalize_options) cmlenz@120: cmlenz@121: def test_with_output_dir(self): cmlenz@120: self.cmd.input_file = 'project/i18n/messages.pot' cmlenz@120: self.cmd.locale = 'en_US' cmlenz@120: self.cmd.output_dir = 'project/i18n' cmlenz@120: cmlenz@120: self.cmd.finalize_options() cmlenz@120: self.cmd.run() cmlenz@120: fschwarz@566: po_file = self._po_file('en_US') cmlenz@120: assert os.path.isfile(po_file) cmlenz@120: cmlenz@120: self.assertEqual( cmlenz@120: r"""# English (United States) translations for TestProject. cmlenz@120: # Copyright (C) 2007 FooBar, Inc. cmlenz@120: # This file is distributed under the same license as the TestProject cmlenz@120: # project. cmlenz@120: # FIRST AUTHOR , 2007. cmlenz@120: # cmlenz@120: msgid "" cmlenz@120: msgstr "" cmlenz@120: "Project-Id-Version: TestProject 0.1\n" cmlenz@120: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" cmlenz@120: "POT-Creation-Date: 2007-04-01 15:30+0200\n" cmlenz@120: "PO-Revision-Date: %(date)s\n" cmlenz@120: "Last-Translator: FULL NAME \n" cmlenz@120: "Language-Team: en_US \n" cmlenz@120: "Plural-Forms: nplurals=2; plural=(n != 1)\n" cmlenz@120: "MIME-Version: 1.0\n" cmlenz@120: "Content-Type: text/plain; charset=utf-8\n" cmlenz@120: "Content-Transfer-Encoding: 8bit\n" cmlenz@120: "Generated-By: Babel %(version)s\n" cmlenz@120: cmlenz@120: #. This will be a translator coment, cmlenz@120: #. that will include several lines cmlenz@120: #: project/file1.py:8 cmlenz@120: msgid "bar" cmlenz@120: msgstr "" cmlenz@120: cmlenz@120: #: project/file2.py:9 cmlenz@120: msgid "foobar" cmlenz@120: msgid_plural "foobars" cmlenz@120: msgstr[0] "" cmlenz@120: msgstr[1] "" cmlenz@120: cmlenz@120: """ % {'version': VERSION, cmlenz@134: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', cmlenz@134: tzinfo=LOCALTZ, locale='en')}, cmlenz@120: open(po_file, 'U').read()) cmlenz@12: palgarvio@371: def test_keeps_catalog_non_fuzzy(self): palgarvio@176: self.cmd.input_file = 'project/i18n/messages_non_fuzzy.pot' palgarvio@176: self.cmd.locale = 'en_US' palgarvio@176: self.cmd.output_dir = 'project/i18n' palgarvio@176: palgarvio@176: self.cmd.finalize_options() palgarvio@176: self.cmd.run() palgarvio@176: fschwarz@566: po_file = self._po_file('en_US') palgarvio@176: assert os.path.isfile(po_file) palgarvio@176: palgarvio@176: self.assertEqual( palgarvio@176: r"""# English (United States) translations for TestProject. palgarvio@176: # Copyright (C) 2007 FooBar, Inc. palgarvio@176: # This file is distributed under the same license as the TestProject palgarvio@176: # project. palgarvio@176: # FIRST AUTHOR , 2007. palgarvio@176: # palgarvio@176: msgid "" palgarvio@176: msgstr "" palgarvio@176: "Project-Id-Version: TestProject 0.1\n" palgarvio@176: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" palgarvio@176: "POT-Creation-Date: 2007-04-01 15:30+0200\n" palgarvio@176: "PO-Revision-Date: %(date)s\n" palgarvio@176: "Last-Translator: FULL NAME \n" palgarvio@176: "Language-Team: en_US \n" palgarvio@176: "Plural-Forms: nplurals=2; plural=(n != 1)\n" palgarvio@176: "MIME-Version: 1.0\n" palgarvio@176: "Content-Type: text/plain; charset=utf-8\n" palgarvio@176: "Content-Transfer-Encoding: 8bit\n" palgarvio@176: "Generated-By: Babel %(version)s\n" palgarvio@176: palgarvio@176: #. This will be a translator coment, palgarvio@176: #. that will include several lines palgarvio@176: #: project/file1.py:8 palgarvio@176: msgid "bar" palgarvio@176: msgstr "" palgarvio@176: palgarvio@176: #: project/file2.py:9 palgarvio@176: msgid "foobar" palgarvio@176: msgid_plural "foobars" palgarvio@176: msgstr[0] "" palgarvio@176: msgstr[1] "" palgarvio@176: palgarvio@176: """ % {'version': VERSION, palgarvio@176: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', palgarvio@176: tzinfo=LOCALTZ, locale='en')}, palgarvio@176: open(po_file, 'U').read()) palgarvio@370: palgarvio@371: def test_correct_init_more_than_2_plurals(self): palgarvio@370: self.cmd.input_file = 'project/i18n/messages.pot' palgarvio@370: self.cmd.locale = 'lv_LV' palgarvio@370: self.cmd.output_dir = 'project/i18n' palgarvio@370: palgarvio@370: self.cmd.finalize_options() palgarvio@370: self.cmd.run() palgarvio@370: fschwarz@566: po_file = self._po_file('lv_LV') palgarvio@370: assert os.path.isfile(po_file) palgarvio@370: palgarvio@370: self.assertEqual( palgarvio@370: r"""# Latvian (Latvia) translations for TestProject. palgarvio@370: # Copyright (C) 2007 FooBar, Inc. palgarvio@370: # This file is distributed under the same license as the TestProject palgarvio@370: # project. palgarvio@370: # FIRST AUTHOR , 2007. palgarvio@370: # palgarvio@370: msgid "" palgarvio@370: msgstr "" palgarvio@370: "Project-Id-Version: TestProject 0.1\n" palgarvio@370: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" palgarvio@370: "POT-Creation-Date: 2007-04-01 15:30+0200\n" palgarvio@370: "PO-Revision-Date: %(date)s\n" palgarvio@370: "Last-Translator: FULL NAME \n" palgarvio@370: "Language-Team: lv_LV \n" palgarvio@370: "Plural-Forms: nplurals=3; plural=(n%%10==1 && n%%100!=11 ? 0 : n != 0 ? 1 :" palgarvio@370: " 2)\n" palgarvio@370: "MIME-Version: 1.0\n" palgarvio@370: "Content-Type: text/plain; charset=utf-8\n" palgarvio@370: "Content-Transfer-Encoding: 8bit\n" palgarvio@370: "Generated-By: Babel %(version)s\n" palgarvio@370: palgarvio@370: #. This will be a translator coment, palgarvio@370: #. that will include several lines palgarvio@370: #: project/file1.py:8 palgarvio@370: msgid "bar" palgarvio@370: msgstr "" palgarvio@370: palgarvio@370: #: project/file2.py:9 palgarvio@370: msgid "foobar" palgarvio@370: msgid_plural "foobars" palgarvio@370: msgstr[0] "" palgarvio@370: msgstr[1] "" palgarvio@370: msgstr[2] "" palgarvio@370: palgarvio@370: """ % {'version': VERSION, palgarvio@370: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', palgarvio@370: tzinfo=LOCALTZ, locale='en')}, palgarvio@370: open(po_file, 'U').read()) palgarvio@370: palgarvio@371: def test_correct_init_singular_plural_forms(self): palgarvio@370: self.cmd.input_file = 'project/i18n/messages.pot' palgarvio@370: self.cmd.locale = 'ja_JP' palgarvio@370: self.cmd.output_dir = 'project/i18n' palgarvio@370: palgarvio@370: self.cmd.finalize_options() palgarvio@370: self.cmd.run() palgarvio@370: fschwarz@566: po_file = self._po_file('ja_JP') palgarvio@370: assert os.path.isfile(po_file) palgarvio@370: palgarvio@370: self.assertEqual( palgarvio@370: r"""# Japanese (Japan) translations for TestProject. palgarvio@370: # Copyright (C) 2007 FooBar, Inc. palgarvio@370: # This file is distributed under the same license as the TestProject palgarvio@370: # project. palgarvio@370: # FIRST AUTHOR , 2007. palgarvio@370: # palgarvio@370: msgid "" palgarvio@370: msgstr "" palgarvio@370: "Project-Id-Version: TestProject 0.1\n" palgarvio@370: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" palgarvio@370: "POT-Creation-Date: 2007-04-01 15:30+0200\n" palgarvio@370: "PO-Revision-Date: %(date)s\n" palgarvio@370: "Last-Translator: FULL NAME \n" palgarvio@370: "Language-Team: ja_JP \n" palgarvio@370: "Plural-Forms: nplurals=1; plural=0\n" palgarvio@370: "MIME-Version: 1.0\n" palgarvio@370: "Content-Type: text/plain; charset=utf-8\n" palgarvio@370: "Content-Transfer-Encoding: 8bit\n" palgarvio@370: "Generated-By: Babel %(version)s\n" palgarvio@370: palgarvio@370: #. This will be a translator coment, palgarvio@370: #. that will include several lines palgarvio@370: #: project/file1.py:8 palgarvio@370: msgid "bar" palgarvio@370: msgstr "" palgarvio@370: palgarvio@370: #: project/file2.py:9 palgarvio@370: msgid "foobar" palgarvio@370: msgid_plural "foobars" palgarvio@370: msgstr[0] "" palgarvio@370: palgarvio@370: """ % {'version': VERSION, palgarvio@370: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', palgarvio@370: tzinfo=LOCALTZ, locale='ja_JP')}, palgarvio@370: open(po_file, 'U').read()) cmlenz@115: cmlenz@181: cmlenz@127: class CommandLineInterfaceTestCase(unittest.TestCase): cmlenz@127: cmlenz@127: def setUp(self): fschwarz@573: self.datadir = os.path.join(this_dir, 'data') fschwarz@541: self.orig_working_dir = os.getcwd() cmlenz@128: self.orig_argv = sys.argv cmlenz@127: self.orig_stdout = sys.stdout cmlenz@127: self.orig_stderr = sys.stderr cmlenz@232: sys.argv = ['pybabel'] cmlenz@127: sys.stdout = StringIO() cmlenz@127: sys.stderr = StringIO() fschwarz@541: os.chdir(self.datadir) fschwarz@521: fschwarz@548: self._remove_log_handlers() cmlenz@127: self.cli = frontend.CommandLineInterface() cmlenz@127: cmlenz@127: def tearDown(self): fschwarz@541: os.chdir(self.orig_working_dir) cmlenz@128: sys.argv = self.orig_argv cmlenz@127: sys.stdout = self.orig_stdout cmlenz@127: sys.stderr = self.orig_stderr palgarvio@371: for dirname in ['lv_LV', 'ja_JP']: fschwarz@566: locale_dir = os.path.join(self._i18n_dir(), dirname) palgarvio@371: if os.path.isdir(locale_dir): palgarvio@371: shutil.rmtree(locale_dir) fschwarz@548: self._remove_log_handlers() fschwarz@548: fschwarz@548: def _remove_log_handlers(self): fschwarz@548: # Logging handlers will be reused if possible (#227). This breaks the fschwarz@548: # implicit assumption that our newly created StringIO for sys.stderr fschwarz@548: # contains the console output. Removing the old handler ensures that a fschwarz@548: # new handler with our new StringIO instance will be used. fschwarz@548: log = logging.getLogger('babel') fschwarz@548: for handler in log.handlers: fschwarz@548: log.removeHandler(handler) cmlenz@127: cmlenz@127: def test_usage(self): cmlenz@127: try: cmlenz@128: self.cli.run(sys.argv) cmlenz@127: self.fail('Expected SystemExit') cmlenz@127: except SystemExit, e: cmlenz@127: self.assertEqual(2, e.code) cmlenz@127: self.assertEqual("""\ cmlenz@232: usage: pybabel command [options] [args] cmlenz@127: palgarvio@424: pybabel: error: no valid command or option passed. try the -h/--help option for more information. cmlenz@135: """, sys.stderr.getvalue().lower()) cmlenz@127: fschwarz@539: def _run_init_catalog(self): fschwarz@539: i18n_dir = os.path.join(self.datadir, 'project', 'i18n') fschwarz@539: pot_path = os.path.join(self.datadir, 'project', 'i18n', 'messages.pot') fschwarz@539: init_argv = sys.argv + ['init', '--locale', 'en_US', '-d', i18n_dir, fschwarz@539: '-i', pot_path] fschwarz@539: self.cli.run(init_argv) fschwarz@539: fschwarz@539: def test_no_duplicated_output_for_multiple_runs(self): fschwarz@539: self._run_init_catalog() fschwarz@539: first_output = sys.stderr.getvalue() fschwarz@539: self._run_init_catalog() fschwarz@539: second_output = sys.stderr.getvalue()[len(first_output):] fschwarz@539: fschwarz@539: # in case the log message is not duplicated we should get the same fschwarz@539: # output as before fschwarz@539: self.assertEqual(first_output, second_output) fschwarz@539: fschwarz@539: def test_frontend_can_log_to_predefined_handler(self): fschwarz@539: custom_stream = StringIO() fschwarz@539: log = logging.getLogger('babel') fschwarz@539: log.addHandler(logging.StreamHandler(custom_stream)) fschwarz@539: fschwarz@539: self._run_init_catalog() fschwarz@539: self.assertNotEqual(id(sys.stderr), id(custom_stream)) fschwarz@539: self.assertEqual('', sys.stderr.getvalue()) fschwarz@539: assert len(custom_stream.getvalue()) > 0 fschwarz@539: cmlenz@127: def test_help(self): cmlenz@127: try: cmlenz@128: self.cli.run(sys.argv + ['--help']) cmlenz@127: self.fail('Expected SystemExit') cmlenz@127: except SystemExit, e: cmlenz@127: self.assertEqual(0, e.code) cmlenz@127: self.assertEqual("""\ cmlenz@232: usage: pybabel command [options] [args] cmlenz@127: cmlenz@127: options: cmlenz@185: --version show program's version number and exit cmlenz@185: -h, --help show this help message and exit cmlenz@185: --list-locales print all known locales and exit cmlenz@232: -v, --verbose print as much as possible cmlenz@232: -q, --quiet print as little as possible cmlenz@127: cmlenz@127: commands: cmlenz@185: compile compile message catalogs to mo files cmlenz@185: extract extract messages from source files and generate a pot file cmlenz@185: init create new message catalogs from a pot file cmlenz@185: update update existing message catalogs from a pot file cmlenz@135: """, sys.stdout.getvalue().lower()) cmlenz@127: fschwarz@566: def _pot_file(self): fschwarz@566: return os.path.join(self._i18n_dir(), 'temp.pot') fschwarz@566: fschwarz@566: def assert_pot_file_exists(self): fschwarz@566: assert os.path.isfile(self._pot_file()) fschwarz@566: cmlenz@127: def test_extract_with_default_mapping(self): fschwarz@566: pot_file = self._pot_file() fschwarz@541: self.cli.run(sys.argv + ['extract', fschwarz@541: '--copyright-holder', 'FooBar, Inc.', fschwarz@541: '--project', 'TestProject', '--version', '0.1', fschwarz@541: '--msgid-bugs-address', 'bugs.address@email.tld', fschwarz@541: '-c', 'TRANSLATOR', '-c', 'TRANSLATORS:', fschwarz@541: '-o', pot_file, 'project']) fschwarz@566: self.assert_pot_file_exists() fschwarz@541: self.assertEqual( cmlenz@127: r"""# Translations template for TestProject. cmlenz@127: # Copyright (C) %(year)s FooBar, Inc. cmlenz@127: # This file is distributed under the same license as the TestProject cmlenz@127: # project. cmlenz@127: # FIRST AUTHOR , %(year)s. cmlenz@127: # cmlenz@127: #, fuzzy cmlenz@127: msgid "" cmlenz@127: msgstr "" cmlenz@127: "Project-Id-Version: TestProject 0.1\n" cmlenz@127: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" cmlenz@127: "POT-Creation-Date: %(date)s\n" cmlenz@127: "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" cmlenz@127: "Last-Translator: FULL NAME \n" cmlenz@127: "Language-Team: LANGUAGE \n" cmlenz@127: "MIME-Version: 1.0\n" cmlenz@127: "Content-Type: text/plain; charset=utf-8\n" cmlenz@127: "Content-Transfer-Encoding: 8bit\n" cmlenz@127: "Generated-By: Babel %(version)s\n" cmlenz@127: fschwarz@541: #. TRANSLATOR: This will be a translator coment, cmlenz@127: #. that will include several lines cmlenz@127: #: project/file1.py:8 cmlenz@127: msgid "bar" cmlenz@127: msgstr "" cmlenz@127: cmlenz@127: #: project/file2.py:9 cmlenz@127: msgid "foobar" cmlenz@127: msgid_plural "foobars" cmlenz@127: msgstr[0] "" cmlenz@127: msgstr[1] "" cmlenz@127: cmlenz@458: #: project/ignored/this_wont_normally_be_here.py:11 cmlenz@127: msgid "FooBar" cmlenz@127: msgid_plural "FooBars" cmlenz@127: msgstr[0] "" cmlenz@127: msgstr[1] "" cmlenz@127: cmlenz@127: """ % {'version': VERSION, cmlenz@127: 'year': time.strftime('%Y'), cmlenz@134: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', cmlenz@134: tzinfo=LOCALTZ, locale='en')}, cmlenz@134: open(pot_file, 'U').read()) cmlenz@127: cmlenz@127: def test_extract_with_mapping_file(self): fschwarz@566: pot_file = self._pot_file() fschwarz@541: self.cli.run(sys.argv + ['extract', fschwarz@541: '--copyright-holder', 'FooBar, Inc.', fschwarz@541: '--project', 'TestProject', '--version', '0.1', fschwarz@541: '--msgid-bugs-address', 'bugs.address@email.tld', fschwarz@541: '--mapping', os.path.join(self.datadir, 'mapping.cfg'), fschwarz@541: '-c', 'TRANSLATOR', '-c', 'TRANSLATORS:', fschwarz@541: '-o', pot_file, 'project']) fschwarz@566: self.assert_pot_file_exists() fschwarz@541: self.assertEqual( cmlenz@127: r"""# Translations template for TestProject. cmlenz@127: # Copyright (C) %(year)s FooBar, Inc. cmlenz@127: # This file is distributed under the same license as the TestProject cmlenz@127: # project. cmlenz@127: # FIRST AUTHOR , %(year)s. cmlenz@127: # cmlenz@127: #, fuzzy cmlenz@127: msgid "" cmlenz@127: msgstr "" cmlenz@127: "Project-Id-Version: TestProject 0.1\n" cmlenz@127: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" cmlenz@127: "POT-Creation-Date: %(date)s\n" cmlenz@127: "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" cmlenz@127: "Last-Translator: FULL NAME \n" cmlenz@127: "Language-Team: LANGUAGE \n" cmlenz@127: "MIME-Version: 1.0\n" cmlenz@127: "Content-Type: text/plain; charset=utf-8\n" cmlenz@127: "Content-Transfer-Encoding: 8bit\n" cmlenz@127: "Generated-By: Babel %(version)s\n" cmlenz@127: fschwarz@541: #. TRANSLATOR: This will be a translator coment, cmlenz@127: #. that will include several lines cmlenz@127: #: project/file1.py:8 cmlenz@127: msgid "bar" cmlenz@127: msgstr "" cmlenz@127: cmlenz@127: #: project/file2.py:9 cmlenz@127: msgid "foobar" cmlenz@127: msgid_plural "foobars" cmlenz@127: msgstr[0] "" cmlenz@127: msgstr[1] "" cmlenz@127: cmlenz@127: """ % {'version': VERSION, cmlenz@127: 'year': time.strftime('%Y'), cmlenz@134: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', cmlenz@134: tzinfo=LOCALTZ, locale='en')}, cmlenz@134: open(pot_file, 'U').read()) cmlenz@127: cmlenz@127: def test_init_with_output_dir(self): fschwarz@566: po_file = self._po_file('en_US') fschwarz@541: self.cli.run(sys.argv + ['init', fschwarz@541: '--locale', 'en_US', fschwarz@566: '-d', os.path.join(self._i18n_dir()), fschwarz@566: '-i', os.path.join(self._i18n_dir(), 'messages.pot')]) fschwarz@541: assert os.path.isfile(po_file) fschwarz@541: self.assertEqual( cmlenz@127: r"""# English (United States) translations for TestProject. cmlenz@127: # Copyright (C) 2007 FooBar, Inc. cmlenz@127: # This file is distributed under the same license as the TestProject cmlenz@127: # project. cmlenz@127: # FIRST AUTHOR , 2007. cmlenz@127: # cmlenz@127: #, fuzzy cmlenz@127: msgid "" cmlenz@127: msgstr "" cmlenz@127: "Project-Id-Version: TestProject 0.1\n" cmlenz@127: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" cmlenz@127: "POT-Creation-Date: 2007-04-01 15:30+0200\n" cmlenz@127: "PO-Revision-Date: %(date)s\n" cmlenz@127: "Last-Translator: FULL NAME \n" cmlenz@127: "Language-Team: en_US \n" cmlenz@127: "Plural-Forms: nplurals=2; plural=(n != 1)\n" cmlenz@127: "MIME-Version: 1.0\n" cmlenz@127: "Content-Type: text/plain; charset=utf-8\n" cmlenz@127: "Content-Transfer-Encoding: 8bit\n" cmlenz@127: "Generated-By: Babel %(version)s\n" cmlenz@127: cmlenz@127: #. This will be a translator coment, cmlenz@127: #. that will include several lines cmlenz@127: #: project/file1.py:8 cmlenz@127: msgid "bar" cmlenz@127: msgstr "" cmlenz@127: cmlenz@127: #: project/file2.py:9 cmlenz@127: msgid "foobar" cmlenz@127: msgid_plural "foobars" cmlenz@127: msgstr[0] "" cmlenz@127: msgstr[1] "" cmlenz@127: cmlenz@127: """ % {'version': VERSION, cmlenz@134: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', cmlenz@134: tzinfo=LOCALTZ, locale='en')}, cmlenz@127: open(po_file, 'U').read()) fschwarz@566: fschwarz@566: def _i18n_dir(self): fschwarz@566: return os.path.join(self.datadir, 'project', 'i18n') fschwarz@566: palgarvio@371: def test_init_singular_plural_forms(self): fschwarz@566: po_file = self._po_file('ja_JP') fschwarz@541: self.cli.run(sys.argv + ['init', fschwarz@541: '--locale', 'ja_JP', fschwarz@566: '-d', os.path.join(self._i18n_dir()), fschwarz@566: '-i', os.path.join(self._i18n_dir(), 'messages.pot')]) palgarvio@371: assert os.path.isfile(po_file) palgarvio@371: self.assertEqual( palgarvio@371: r"""# Japanese (Japan) translations for TestProject. palgarvio@371: # Copyright (C) 2007 FooBar, Inc. palgarvio@371: # This file is distributed under the same license as the TestProject palgarvio@371: # project. palgarvio@371: # FIRST AUTHOR , 2007. palgarvio@371: # palgarvio@371: #, fuzzy palgarvio@371: msgid "" palgarvio@371: msgstr "" palgarvio@371: "Project-Id-Version: TestProject 0.1\n" palgarvio@371: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" palgarvio@371: "POT-Creation-Date: 2007-04-01 15:30+0200\n" palgarvio@371: "PO-Revision-Date: %(date)s\n" palgarvio@371: "Last-Translator: FULL NAME \n" palgarvio@371: "Language-Team: ja_JP \n" palgarvio@371: "Plural-Forms: nplurals=1; plural=0\n" palgarvio@371: "MIME-Version: 1.0\n" palgarvio@371: "Content-Type: text/plain; charset=utf-8\n" palgarvio@371: "Content-Transfer-Encoding: 8bit\n" palgarvio@371: "Generated-By: Babel %(version)s\n" palgarvio@371: palgarvio@371: #. This will be a translator coment, palgarvio@371: #. that will include several lines palgarvio@371: #: project/file1.py:8 palgarvio@371: msgid "bar" palgarvio@371: msgstr "" palgarvio@371: palgarvio@371: #: project/file2.py:9 palgarvio@371: msgid "foobar" palgarvio@371: msgid_plural "foobars" palgarvio@371: msgstr[0] "" palgarvio@371: palgarvio@371: """ % {'version': VERSION, palgarvio@371: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', palgarvio@371: tzinfo=LOCALTZ, locale='en')}, palgarvio@371: open(po_file, 'U').read()) palgarvio@371: palgarvio@371: def test_init_more_than_2_plural_forms(self): fschwarz@566: po_file = self._po_file('lv_LV') fschwarz@541: self.cli.run(sys.argv + ['init', fschwarz@541: '--locale', 'lv_LV', fschwarz@566: '-d', self._i18n_dir(), fschwarz@566: '-i', os.path.join(self._i18n_dir(), 'messages.pot')]) palgarvio@371: assert os.path.isfile(po_file) palgarvio@371: self.assertEqual( palgarvio@371: r"""# Latvian (Latvia) translations for TestProject. palgarvio@371: # Copyright (C) 2007 FooBar, Inc. palgarvio@371: # This file is distributed under the same license as the TestProject palgarvio@371: # project. palgarvio@371: # FIRST AUTHOR , 2007. palgarvio@371: # palgarvio@371: #, fuzzy palgarvio@371: msgid "" palgarvio@371: msgstr "" palgarvio@371: "Project-Id-Version: TestProject 0.1\n" palgarvio@371: "Report-Msgid-Bugs-To: bugs.address@email.tld\n" palgarvio@371: "POT-Creation-Date: 2007-04-01 15:30+0200\n" palgarvio@371: "PO-Revision-Date: %(date)s\n" palgarvio@371: "Last-Translator: FULL NAME \n" palgarvio@371: "Language-Team: lv_LV \n" palgarvio@371: "Plural-Forms: nplurals=3; plural=(n%%10==1 && n%%100!=11 ? 0 : n != 0 ? 1 :" palgarvio@371: " 2)\n" palgarvio@371: "MIME-Version: 1.0\n" palgarvio@371: "Content-Type: text/plain; charset=utf-8\n" palgarvio@371: "Content-Transfer-Encoding: 8bit\n" palgarvio@371: "Generated-By: Babel %(version)s\n" palgarvio@371: palgarvio@371: #. This will be a translator coment, palgarvio@371: #. that will include several lines palgarvio@371: #: project/file1.py:8 palgarvio@371: msgid "bar" palgarvio@371: msgstr "" palgarvio@371: palgarvio@371: #: project/file2.py:9 palgarvio@371: msgid "foobar" palgarvio@371: msgid_plural "foobars" palgarvio@371: msgstr[0] "" palgarvio@371: msgstr[1] "" palgarvio@371: msgstr[2] "" palgarvio@371: palgarvio@371: """ % {'version': VERSION, palgarvio@371: 'date': format_datetime(datetime.now(LOCALTZ), 'yyyy-MM-dd HH:mmZ', palgarvio@371: tzinfo=LOCALTZ, locale='en')}, palgarvio@371: open(po_file, 'U').read()) cmlenz@177: palgarvio@176: def test_compile_catalog(self): fschwarz@566: po_file = self._po_file('de_DE') cmlenz@232: mo_file = po_file.replace('.po', '.mo') cmlenz@232: self.cli.run(sys.argv + ['compile', cmlenz@232: '--locale', 'de_DE', fschwarz@566: '-d', self._i18n_dir()]) cmlenz@232: assert not os.path.isfile(mo_file), 'Expected no file at %r' % mo_file cmlenz@232: self.assertEqual("""\ cmlenz@232: catalog %r is marked as fuzzy, skipping cmlenz@232: """ % (po_file), sys.stderr.getvalue()) cmlenz@232: cmlenz@232: def test_compile_fuzzy_catalog(self): fschwarz@566: po_file = self._po_file('de_DE') cmlenz@232: mo_file = po_file.replace('.po', '.mo') palgarvio@176: try: palgarvio@176: self.cli.run(sys.argv + ['compile', cmlenz@232: '--locale', 'de_DE', '--use-fuzzy', fschwarz@566: '-d', self._i18n_dir()]) cmlenz@232: assert os.path.isfile(mo_file) palgarvio@176: self.assertEqual("""\ cmlenz@177: compiling catalog %r to %r cmlenz@232: """ % (po_file, mo_file), sys.stderr.getvalue()) cmlenz@232: finally: cmlenz@232: if os.path.isfile(mo_file): cmlenz@232: os.unlink(mo_file) cmlenz@127: fschwarz@566: def _po_file(self, locale): fschwarz@566: return os.path.join(self._i18n_dir(), locale, 'LC_MESSAGES', fschwarz@566: 'messages.po') fschwarz@566: cmlenz@331: def test_compile_catalog_with_more_than_2_plural_forms(self): fschwarz@566: po_file = self._po_file('ru_RU') cmlenz@331: mo_file = po_file.replace('.po', '.mo') cmlenz@331: try: cmlenz@331: self.cli.run(sys.argv + ['compile', cmlenz@331: '--locale', 'ru_RU', '--use-fuzzy', fschwarz@566: '-d', self._i18n_dir()]) cmlenz@331: assert os.path.isfile(mo_file) cmlenz@331: self.assertEqual("""\ cmlenz@331: compiling catalog %r to %r cmlenz@331: """ % (po_file, mo_file), sys.stderr.getvalue()) cmlenz@331: finally: cmlenz@331: if os.path.isfile(mo_file): cmlenz@331: os.unlink(mo_file) cmlenz@331: cmlenz@177: cmlenz@12: def suite(): cmlenz@12: suite = unittest.TestSuite() cmlenz@12: suite.addTest(doctest.DocTestSuite(frontend)) cmlenz@160: suite.addTest(unittest.makeSuite(CompileCatalogTestCase)) cmlenz@117: suite.addTest(unittest.makeSuite(ExtractMessagesTestCase)) cmlenz@181: suite.addTest(unittest.makeSuite(InitCatalogTestCase)) cmlenz@127: suite.addTest(unittest.makeSuite(CommandLineInterfaceTestCase)) cmlenz@12: return suite cmlenz@12: cmlenz@12: if __name__ == '__main__': cmlenz@12: unittest.main(defaultTest='suite')