2014-09-21 10:17:02 -05:00
|
|
|
"""
|
|
|
|
test_util_i18n
|
|
|
|
~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Test i18n util.
|
|
|
|
|
2019-01-02 01:00:30 -06:00
|
|
|
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
2014-09-21 10:17:02 -05:00
|
|
|
:license: BSD, see LICENSE for details.
|
|
|
|
"""
|
|
|
|
|
2016-02-14 05:07:28 -06:00
|
|
|
import datetime
|
2018-02-19 07:39:14 -06:00
|
|
|
import os
|
2014-09-21 10:17:02 -05:00
|
|
|
|
2017-01-06 09:46:26 -06:00
|
|
|
import pytest
|
2014-09-21 10:17:02 -05:00
|
|
|
from babel.messages.mofile import read_mo
|
2018-02-19 07:39:14 -06:00
|
|
|
|
2016-01-26 10:36:43 -06:00
|
|
|
from sphinx.errors import SphinxError
|
2018-02-19 07:39:14 -06:00
|
|
|
from sphinx.util import i18n
|
2014-09-21 10:17:02 -05:00
|
|
|
|
|
|
|
|
|
|
|
def test_catalog_info_for_file_and_path():
|
2015-07-25 08:47:56 -05:00
|
|
|
cat = i18n.CatalogInfo('path', 'domain', 'utf-8')
|
2014-09-21 10:17:02 -05:00
|
|
|
assert cat.po_file == 'domain.po'
|
|
|
|
assert cat.mo_file == 'domain.mo'
|
2017-01-06 09:46:26 -06:00
|
|
|
assert cat.po_path == os.path.join('path', 'domain.po')
|
|
|
|
assert cat.mo_path == os.path.join('path', 'domain.mo')
|
2014-09-21 10:17:02 -05:00
|
|
|
|
|
|
|
|
|
|
|
def test_catalog_info_for_sub_domain_file_and_path():
|
2015-07-25 08:47:56 -05:00
|
|
|
cat = i18n.CatalogInfo('path', 'sub/domain', 'utf-8')
|
2014-09-21 10:17:02 -05:00
|
|
|
assert cat.po_file == 'sub/domain.po'
|
|
|
|
assert cat.mo_file == 'sub/domain.mo'
|
2017-01-06 09:46:26 -06:00
|
|
|
assert cat.po_path == os.path.join('path', 'sub/domain.po')
|
|
|
|
assert cat.mo_path == os.path.join('path', 'sub/domain.mo')
|
2014-09-21 10:17:02 -05:00
|
|
|
|
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
def test_catalog_outdated(tempdir):
|
|
|
|
(tempdir / 'test.po').write_text('#')
|
|
|
|
cat = i18n.CatalogInfo(tempdir, 'test', 'utf-8')
|
2014-09-21 10:17:02 -05:00
|
|
|
assert cat.is_outdated() # if mo is not exist
|
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
mo_file = (tempdir / 'test.mo')
|
2014-09-21 10:17:02 -05:00
|
|
|
mo_file.write_text('#')
|
|
|
|
assert not cat.is_outdated() # if mo is exist and newer than po
|
|
|
|
|
2016-06-11 10:00:52 -05:00
|
|
|
os.utime(mo_file, (os.stat(mo_file).st_mtime - 10,) * 2) # to be outdate
|
2014-09-21 10:17:02 -05:00
|
|
|
assert cat.is_outdated() # if mo is exist and older than po
|
|
|
|
|
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
def test_catalog_write_mo(tempdir):
|
|
|
|
(tempdir / 'test.po').write_text('#')
|
|
|
|
cat = i18n.CatalogInfo(tempdir, 'test', 'utf-8')
|
2014-09-21 10:17:02 -05:00
|
|
|
cat.write_mo('en')
|
2017-01-06 09:46:26 -06:00
|
|
|
assert os.path.exists(cat.mo_path)
|
2016-01-09 10:04:38 -06:00
|
|
|
with open(cat.mo_path, 'rb') as f:
|
|
|
|
assert read_mo(f) is not None
|
2014-09-21 10:17:02 -05:00
|
|
|
|
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
def test_get_catalogs_for_xx(tempdir):
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / 'test6.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_ALL').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_ALL' / 'test7.po').write_text('#')
|
|
|
|
|
|
|
|
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', force_all=False)
|
2019-03-17 14:49:36 -05:00
|
|
|
domains = {c.domain for c in catalogs}
|
|
|
|
assert domains == {
|
2014-09-21 10:17:02 -05:00
|
|
|
'test1',
|
|
|
|
'test2',
|
2015-03-16 09:01:16 -05:00
|
|
|
'sub/test4',
|
|
|
|
'sub/test5',
|
2019-03-17 14:49:36 -05:00
|
|
|
}
|
2014-09-21 10:17:02 -05:00
|
|
|
|
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
def test_get_catalogs_for_en(tempdir):
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'xx_dom.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / 'en_dom.po').write_text('#')
|
2014-09-21 10:17:02 -05:00
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'en', force_all=False)
|
2019-03-17 14:49:36 -05:00
|
|
|
domains = {c.domain for c in catalogs}
|
|
|
|
assert domains == {'en_dom'}
|
2014-09-21 10:17:02 -05:00
|
|
|
|
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
def test_get_catalogs_with_non_existent_locale(tempdir):
|
|
|
|
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx')
|
2014-09-21 10:17:02 -05:00
|
|
|
assert not catalogs
|
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], None)
|
2014-09-21 10:17:02 -05:00
|
|
|
assert not catalogs
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_catalogs_with_non_existent_locale_dirs():
|
2015-03-16 09:06:54 -05:00
|
|
|
catalogs = i18n.find_catalog_source_files(['dummy'], 'xx')
|
2014-09-21 10:17:02 -05:00
|
|
|
assert not catalogs
|
|
|
|
|
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
def test_get_catalogs_for_xx_without_outdated(tempdir):
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.mo').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.mo').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.pot').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test3.mo').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.mo').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.mo').write_text('#')
|
|
|
|
|
|
|
|
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', force_all=False)
|
2014-09-21 10:17:02 -05:00
|
|
|
assert not catalogs
|
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', force_all=True)
|
2019-03-17 14:49:36 -05:00
|
|
|
domains = {c.domain for c in catalogs}
|
|
|
|
assert domains == {
|
2014-09-21 10:17:02 -05:00
|
|
|
'test1',
|
|
|
|
'test2',
|
2015-03-16 09:01:16 -05:00
|
|
|
'sub/test4',
|
|
|
|
'sub/test5',
|
2019-03-17 14:49:36 -05:00
|
|
|
}
|
2014-09-21 10:17:02 -05:00
|
|
|
|
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
def test_get_catalogs_from_multiple_locale_dirs(tempdir):
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
|
|
|
(tempdir / 'loc2' / 'xx' / 'LC_MESSAGES').makedirs()
|
|
|
|
(tempdir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
|
|
|
(tempdir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
2014-09-21 10:17:02 -05:00
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1', tempdir / 'loc2'], 'xx')
|
2014-09-21 10:17:02 -05:00
|
|
|
domains = sorted(c.domain for c in catalogs)
|
|
|
|
assert domains == ['test1', 'test1', 'test2']
|
|
|
|
|
|
|
|
|
2018-11-11 06:44:37 -06:00
|
|
|
@pytest.mark.filterwarnings('ignore:gettext_compact argument')
|
2017-01-03 07:24:00 -06:00
|
|
|
def test_get_catalogs_with_compact(tempdir):
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#')
|
2014-09-21 10:17:02 -05:00
|
|
|
|
2017-01-03 07:24:00 -06:00
|
|
|
catalogs = i18n.find_catalog_source_files([tempdir / 'loc1'], 'xx', gettext_compact=True)
|
2019-03-17 14:49:36 -05:00
|
|
|
domains = {c.domain for c in catalogs}
|
|
|
|
assert domains == {'test1', 'test2', 'sub/test3', 'sub/test4'}
|
2016-02-14 05:07:28 -06:00
|
|
|
|
|
|
|
|
2018-05-01 15:57:32 -05:00
|
|
|
def test_get_catalogs_excluded(tempdir):
|
|
|
|
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / '.git').makedirs()
|
|
|
|
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / 'en_dom.po').write_text('#')
|
|
|
|
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / '.git' / 'no_no.po').write_text('#')
|
|
|
|
|
|
|
|
catalogs = i18n.find_catalog_source_files(
|
|
|
|
[tempdir / 'loc1'], 'en', force_all=False, excluded=lambda path: '.git' in path)
|
2019-03-17 14:49:36 -05:00
|
|
|
domains = {c.domain for c in catalogs}
|
|
|
|
assert domains == {'en_dom'}
|
2018-05-01 15:57:32 -05:00
|
|
|
|
|
|
|
|
2016-02-14 05:07:28 -06:00
|
|
|
def test_format_date():
|
|
|
|
date = datetime.date(2016, 2, 7)
|
|
|
|
|
2016-04-01 20:23:13 -05:00
|
|
|
# strftime format
|
2016-02-14 05:07:28 -06:00
|
|
|
format = '%B %d, %Y'
|
|
|
|
assert i18n.format_date(format, date=date) == 'February 07, 2016'
|
2016-02-16 10:13:00 -06:00
|
|
|
assert i18n.format_date(format, date=date, language='') == 'February 07, 2016'
|
|
|
|
assert i18n.format_date(format, date=date, language='unknown') == 'February 07, 2016'
|
2016-02-14 05:07:28 -06:00
|
|
|
assert i18n.format_date(format, date=date, language='en') == 'February 07, 2016'
|
2018-12-15 08:02:28 -06:00
|
|
|
assert i18n.format_date(format, date=date, language='ja') == '2月 07, 2016'
|
2016-02-14 05:07:28 -06:00
|
|
|
assert i18n.format_date(format, date=date, language='de') == 'Februar 07, 2016'
|
2016-01-26 10:36:43 -06:00
|
|
|
|
2016-04-01 20:23:13 -05:00
|
|
|
# raw string
|
2016-03-31 21:20:30 -05:00
|
|
|
format = 'Mon Mar 28 12:37:08 2016, commit 4367aef'
|
|
|
|
assert i18n.format_date(format, date=date) == format
|
|
|
|
|
2016-04-05 05:16:23 -05:00
|
|
|
format = '%B %d, %Y, %H:%M:%S %I %p'
|
|
|
|
datet = datetime.datetime(2016, 2, 7, 5, 11, 17, 0)
|
|
|
|
assert i18n.format_date(format, date=datet) == 'February 07, 2016, 05:11:17 05 AM'
|
|
|
|
|
2018-01-28 02:22:41 -06:00
|
|
|
format = '%B %-d, %Y, %-H:%-M:%-S %-I %p'
|
|
|
|
assert i18n.format_date(format, date=datet) == 'February 7, 2016, 5:11:17 5 AM'
|
2016-04-05 05:16:23 -05:00
|
|
|
format = '%x'
|
|
|
|
assert i18n.format_date(format, date=datet) == 'Feb 7, 2016'
|
|
|
|
format = '%X'
|
|
|
|
assert i18n.format_date(format, date=datet) == '5:11:17 AM'
|
|
|
|
assert i18n.format_date(format, date=date) == 'Feb 7, 2016'
|
|
|
|
format = '%c'
|
|
|
|
assert i18n.format_date(format, date=datet) == 'Feb 7, 2016, 5:11:17 AM'
|
|
|
|
assert i18n.format_date(format, date=date) == 'Feb 7, 2016'
|
2016-01-26 10:36:43 -06:00
|
|
|
|
2016-06-11 10:00:52 -05:00
|
|
|
|
2017-06-14 13:26:15 -05:00
|
|
|
@pytest.mark.xfail(os.name != 'posix', reason="Path separators don't match on windows")
|
2017-01-06 09:46:26 -06:00
|
|
|
def test_get_filename_for_language(app):
|
2016-01-26 10:36:43 -06:00
|
|
|
# language is None
|
|
|
|
app.env.config.language = None
|
|
|
|
assert app.env.config.language is None
|
|
|
|
assert i18n.get_image_filename_for_language('foo.png', app.env) == 'foo.png'
|
|
|
|
assert i18n.get_image_filename_for_language('foo.bar.png', app.env) == 'foo.bar.png'
|
|
|
|
assert i18n.get_image_filename_for_language('subdir/foo.png', app.env) == 'subdir/foo.png'
|
|
|
|
assert i18n.get_image_filename_for_language('../foo.png', app.env) == '../foo.png'
|
|
|
|
assert i18n.get_image_filename_for_language('foo', app.env) == 'foo'
|
|
|
|
|
|
|
|
# language is en
|
|
|
|
app.env.config.language = 'en'
|
|
|
|
assert i18n.get_image_filename_for_language('foo.png', app.env) == 'foo.en.png'
|
|
|
|
assert i18n.get_image_filename_for_language('foo.bar.png', app.env) == 'foo.bar.en.png'
|
|
|
|
assert i18n.get_image_filename_for_language('dir/foo.png', app.env) == 'dir/foo.en.png'
|
|
|
|
assert i18n.get_image_filename_for_language('../foo.png', app.env) == '../foo.en.png'
|
|
|
|
assert i18n.get_image_filename_for_language('foo', app.env) == 'foo.en'
|
|
|
|
|
|
|
|
# modify figure_language_filename and language is None
|
|
|
|
app.env.config.language = None
|
|
|
|
app.env.config.figure_language_filename = 'images/{language}/{root}{ext}'
|
|
|
|
assert i18n.get_image_filename_for_language('foo.png', app.env) == 'foo.png'
|
|
|
|
assert i18n.get_image_filename_for_language('foo.bar.png', app.env) == 'foo.bar.png'
|
|
|
|
assert i18n.get_image_filename_for_language('subdir/foo.png', app.env) == 'subdir/foo.png'
|
|
|
|
assert i18n.get_image_filename_for_language('../foo.png', app.env) == '../foo.png'
|
|
|
|
assert i18n.get_image_filename_for_language('foo', app.env) == 'foo'
|
2016-01-29 00:05:43 -06:00
|
|
|
|
|
|
|
# modify figure_language_filename and language is 'en'
|
|
|
|
app.env.config.language = 'en'
|
|
|
|
app.env.config.figure_language_filename = 'images/{language}/{root}{ext}'
|
|
|
|
assert i18n.get_image_filename_for_language('foo.png', app.env) == 'images/en/foo.png'
|
2016-03-06 06:37:04 -06:00
|
|
|
assert i18n.get_image_filename_for_language(
|
|
|
|
'foo.bar.png', app.env) == 'images/en/foo.bar.png'
|
|
|
|
assert i18n.get_image_filename_for_language(
|
|
|
|
'subdir/foo.png', app.env) == 'images/en/subdir/foo.png'
|
|
|
|
assert i18n.get_image_filename_for_language(
|
|
|
|
'../foo.png', app.env) == 'images/en/../foo.png'
|
2016-01-29 00:05:43 -06:00
|
|
|
assert i18n.get_image_filename_for_language('foo', app.env) == 'images/en/foo'
|
|
|
|
|
2016-10-12 22:34:19 -05:00
|
|
|
# new path and basename tokens
|
|
|
|
app.env.config.language = 'en'
|
|
|
|
app.env.config.figure_language_filename = '{path}{language}/{basename}{ext}'
|
|
|
|
assert i18n.get_image_filename_for_language('foo.png', app.env) == 'en/foo.png'
|
|
|
|
assert i18n.get_image_filename_for_language(
|
|
|
|
'foo.bar.png', app.env) == 'en/foo.bar.png'
|
|
|
|
assert i18n.get_image_filename_for_language(
|
|
|
|
'subdir/foo.png', app.env) == 'subdir/en/foo.png'
|
|
|
|
assert i18n.get_image_filename_for_language(
|
|
|
|
'../foo.png', app.env) == '../en/foo.png'
|
|
|
|
assert i18n.get_image_filename_for_language('foo', app.env) == 'en/foo'
|
|
|
|
|
2016-01-29 00:05:43 -06:00
|
|
|
# invalid figure_language_filename
|
|
|
|
app.env.config.figure_language_filename = '{root}.{invalid}{ext}'
|
2017-01-05 09:46:42 -06:00
|
|
|
with pytest.raises(SphinxError):
|
|
|
|
i18n.get_image_filename_for_language('foo.png', app.env)
|