sphinx/utils/babel_runner.py

110 lines
3.9 KiB
Python
Raw Normal View History

from io import StringIO
from json import dump
import os
import sys
from babel.messages.frontend import compile_catalog
from babel.messages.pofile import read_po
# Provide a "compile_catalog" command that also creates the translated
# JavaScript files if Babel is available.
class Tee:
def __init__(self, stream):
self.stream = stream
self.buffer = StringIO()
def write(self, s):
self.stream.write(s)
self.buffer.write(s)
def flush(self):
self.stream.flush()
class compile_catalog_plusjs(compile_catalog):
"""
An extended command that writes all message strings that occur in
JavaScript files to a JavaScript file along with the .mo file.
Unfortunately, babel's setup command isn't built very extensible, so
most of the run() code is duplicated here.
"""
def run(self):
try:
sys.stderr = Tee(sys.stderr)
compile_catalog.run(self)
finally:
if sys.stderr.buffer.getvalue():
print("Compiling failed.")
sys.exit(1)
if isinstance(self.domain, list):
for domain in self.domain:
self._run_domain_js(domain)
else:
self._run_domain_js(self.domain)
def _run_domain_js(self, domain):
po_files = []
js_files = []
if not self.input_file:
if self.locale:
po_files.append((self.locale,
os.path.join(self.directory, self.locale,
'LC_MESSAGES',
domain + '.po')))
js_files.append(os.path.join(self.directory, self.locale,
'LC_MESSAGES',
domain + '.js'))
else:
for locale in os.listdir(self.directory):
po_file = os.path.join(self.directory, locale,
'LC_MESSAGES',
domain + '.po')
if os.path.exists(po_file):
po_files.append((locale, po_file))
js_files.append(os.path.join(self.directory, locale,
'LC_MESSAGES',
domain + '.js'))
else:
po_files.append((self.locale, self.input_file))
if self.output_file:
js_files.append(self.output_file)
else:
js_files.append(os.path.join(self.directory, self.locale,
'LC_MESSAGES',
domain + '.js'))
for js_file, (locale, po_file) in zip(js_files, po_files):
with open(po_file, encoding='utf8') as infile:
catalog = read_po(infile, locale)
if catalog.fuzzy and not self.use_fuzzy:
continue
self.log.info('writing JavaScript strings in catalog %r to %r',
po_file, js_file)
jscatalog = {}
for message in catalog:
if any(x[0].endswith(('.js', '.js_t', '.html'))
for x in message.locations):
msgid = message.id
if isinstance(msgid, (list, tuple)):
msgid = msgid[0]
jscatalog[msgid] = message.string
with open(js_file, 'wt', encoding='utf8') as outfile:
outfile.write('Documentation.addTranslations(')
dump({
'messages': jscatalog,
'plural_expr': catalog.plural_expr,
'locale': str(catalog.locale)
}, outfile, sort_keys=True, indent=4)
outfile.write(');')