diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 4e0a6cfce..4c2a16715 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -168,7 +168,9 @@ class Builder(object): def compile_all_catalogs(self): catalogs = i18n.get_catalogs( [path.join(self.srcdir, x) for x in self.config.locale_dirs], - self.config.language, self.config.gettext_compact, True) + self.config.language, + gettext_compact=self.config.gettext_compact, + force_all=True) message = 'all of %d po files' % len(catalogs) self.compile_catalogs(catalogs, message) @@ -181,15 +183,17 @@ class Builder(object): specified_domains = set(map(to_domain, specified_files)) catalogs = i18n.get_catalogs( [path.join(self.srcdir, x) for x in self.config.locale_dirs], - self.config.language, self.config.gettext_compact, True) - catalogs = [f for f in catalogs if f.domain in specified_domains] + self.config.language, + domains=list(specified_domains), + gettext_compact=self.config.gettext_compact) message = 'targets for %d po files that are specified' % len(catalogs) self.compile_catalogs(catalogs, message) def compile_update_catalogs(self): catalogs = i18n.get_catalogs( [path.join(self.srcdir, x) for x in self.config.locale_dirs], - self.config.language, self.config.gettext_compact) + self.config.language, + gettext_compact=self.config.gettext_compact) message = 'targets for %d po files that are out of date' % len(catalogs) self.compile_catalogs(catalogs, message) diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py index acb71bf28..db8081516 100644 --- a/sphinx/locale/__init__.py +++ b/sphinx/locale/__init__.py @@ -208,6 +208,15 @@ def init(locale_dirs, language, catalog='sphinx'): translator = None # the None entry is the system's default locale path has_translation = True + + # compile mo files if po file is updated + # TODO: remove circular importing + from sphinx.util.i18n import get_catalogs + for catinfo in get_catalogs(locale_dirs, language, domains=[catalog], + force_all=False): + catinfo.write_mo(language) + + # loading for dir_ in locale_dirs: try: trans = gettext.translation(catalog, localedir=dir_, diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py index 7bd0c34ea..e83ba4052 100644 --- a/sphinx/util/i18n.py +++ b/sphinx/util/i18n.py @@ -16,6 +16,7 @@ from babel.messages.pofile import read_po from babel.messages.mofile import write_mo from sphinx.util.osutil import walk +from sphinx.util import SEP LocaleFileInfoBase = namedtuple('CatalogInfo', 'base_dir,domain') @@ -50,13 +51,16 @@ class CatalogInfo(LocaleFileInfoBase): write_mo(mo, read_po(po, locale)) -def get_catalogs(locale_dirs, locale, gettext_compact=False, force_all=False): +def get_catalogs(locale_dirs, locale, domains=None, + gettext_compact=False, force_all=False): """ :param list locale_dirs: list of path as `['locale_dir1', 'locale_dir2', ...]` to find translation catalogs. Each path contains a structure such as `/LC_MESSAGES/domain.po`. :param str locale: a language as `'en'` + :param list domains: list of domain names to get. If empty list or None + is specified, get all domain names. default is None. :param boolean gettext_compact: * False: keep domains directory structure (default). * True: domains in the sub directory will be merged into 1 file. @@ -70,6 +74,9 @@ def get_catalogs(locale_dirs, locale, gettext_compact=False, force_all=False): catalogs = set() for locale_dir in locale_dirs: + if not locale_dir: + continue # skip system locale directory + base_dir = path.join(locale_dir, locale, 'LC_MESSAGES') if not path.exists(base_dir): @@ -82,6 +89,9 @@ def get_catalogs(locale_dirs, locale, gettext_compact=False, force_all=False): domain = path.relpath(path.join(dirpath, base), base_dir) if gettext_compact and path.sep in domain: domain = path.split(domain)[0] + domain = domain.replace(path.sep, SEP) + if domains and domain not in domains: + continue cat = CatalogInfo(base_dir, domain) if force_all or cat.is_outdated(): catalogs.add(cat) diff --git a/tests/test_catalogs.py b/tests/test_catalogs.py index b06e71a57..7b1cc05e0 100644 --- a/tests/test_catalogs.py +++ b/tests/test_catalogs.py @@ -55,10 +55,13 @@ def test_compile_all_catalogs(app, status, warning): @with_app(buildername='html', testroot='intl', confoverrides={'language': 'en', 'locale_dirs': [locale_dir]}) def test_compile_specific_catalogs(app, status, warning): - app.builder.compile_specific_catalogs(['admonitions']) - catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES' - actual = set(find_files(catalog_dir, '.mo')) + def get_actual(): + return set(find_files(catalog_dir, '.mo')) + + actual_on_boot = get_actual() # sphinx.mo might be included + app.builder.compile_specific_catalogs(['admonitions']) + actual = get_actual() - actual_on_boot assert actual == set(['admonitions.mo']) diff --git a/tests/test_util_i18n.py b/tests/test_util_i18n.py index ba18026ca..d8f0cd012 100644 --- a/tests/test_util_i18n.py +++ b/tests/test_util_i18n.py @@ -77,8 +77,8 @@ def test_get_catalogs_for_xx(dir): assert domains == set([ 'test1', 'test2', - path.normpath('sub/test4'), - path.normpath('sub/test5'), + 'sub/test4', + 'sub/test5', ]) @@ -131,8 +131,8 @@ def test_get_catalogs_for_xx_without_outdated(dir): assert domains == set([ 'test1', 'test2', - path.normpath('sub/test4'), - path.normpath('sub/test5'), + 'sub/test4', + 'sub/test5', ])