diff options
author | Georg Brandl <georg@python.org> | 2009-07-03 13:34:08 +0200 |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2009-07-03 13:34:08 +0200 |
commit | c8e8b1bfd4d76f13b51cd86b48cb32ccbe7559e0 (patch) | |
tree | 6d2a736922487d83b6a850e26a190e2ada1e9933 | |
parent | 1f18db60a49e0fc6552bcfd11fe4b2be5153c68a (diff) | |
download | sphinx-git-c8e8b1bfd4d76f13b51cd86b48cb32ccbe7559e0.tar.gz |
Use a new "lazy" gettext function instead of using dummy _() to help text extraction.
-rw-r--r-- | sphinx/builders/__init__.py | 22 | ||||
-rw-r--r-- | sphinx/config.py | 4 | ||||
-rw-r--r-- | sphinx/directives/desc.py | 47 | ||||
-rw-r--r-- | sphinx/locale/__init__.py | 190 |
4 files changed, 193 insertions, 70 deletions
diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index a8fc8871c..348e2e8fd 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -172,32 +172,18 @@ class Builder(object): Load translated strings from the configured localedirs if enabled in the configuration. """ - self.translator = None if self.config.language is not None: self.info(bold('loading translations [%s]... ' % self.config.language), nonl=True) - # the None entry is the system's default locale path locale_dirs = [None, path.join(package_dir, 'locale')] + \ [path.join(self.srcdir, x) for x in self.config.locale_dirs] - for dir_ in locale_dirs: - try: - trans = gettext.translation('sphinx', localedir=dir_, - languages=[self.config.language]) - if self.translator is None: - self.translator = trans - else: - self.translator._catalog.update(trans.catalog) - except Exception: - # Language couldn't be found in the specified path - pass - if self.translator is not None: + self.translator, has_translation = locale.init(locale_dirs, + self.config.language) + if self.config.language is not None: + if has_translation: self.info('done') else: self.info('locale not available') - if self.translator is None: - self.translator = gettext.NullTranslations() - self.translator.install(unicode=True) - locale.init() # translate common labels def load_env(self): """Set up the build environment.""" diff --git a/sphinx/config.py b/sphinx/config.py index 912f3eb2e..dbe569fb7 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -113,6 +113,10 @@ class Config(object): latex_docclass = ({}, None), # now deprecated - use latex_elements latex_preamble = ('', None), + + # text options + text_sectionchars = ('*=-~"+`', 'text'), + text_windows_newlines = (False, 'text'), ) def __init__(self, dirname, filename, overrides, tags): diff --git a/sphinx/directives/desc.py b/sphinx/directives/desc.py index 47c640b5e..666397c39 100644 --- a/sphinx/directives/desc.py +++ b/sphinx/directives/desc.py @@ -15,6 +15,7 @@ from docutils.parsers.rst import directives from sphinx import addnodes from sphinx.domains import Domain, domains +from sphinx.locale import l_ from sphinx.util import ws_re from sphinx.util.compat import Directive, directive_dwim @@ -84,8 +85,6 @@ class DescDirective(Directive): 'module': directives.unchanged, } - _ = lambda x: x # make gettext extraction in constants possible - doc_fields_with_arg = { 'param': '%param', 'parameter': '%param', @@ -95,23 +94,23 @@ class DescDirective(Directive): 'kwarg': '%param', 'kwparam': '%param', 'type': '%type', - 'raises': _('Raises'), - 'raise': 'Raises', - 'exception': 'Raises', - 'except': 'Raises', - 'var': _('Variable'), - 'ivar': 'Variable', - 'cvar': 'Variable', - 'returns': _('Returns'), - 'return': 'Returns', + 'raises': l_('Raises'), + 'raise': l_('Raises'), + 'exception': l_('Raises'), + 'except': l_('Raises'), + 'var': l_('Variable'), + 'ivar': l_('Variable'), + 'cvar': l_('Variable'), + 'returns': l_('Returns'), + 'return': l_('Returns'), } doc_fields_with_linked_arg = ('raises', 'raise', 'exception', 'except') doc_fields_without_arg = { - 'returns': 'Returns', - 'return': 'Returns', - 'rtype': _('Return type'), + 'returns': l_('Returns'), + 'return': l_('Returns'), + 'rtype': l_('Return type'), } def handle_doc_fields(self, node): @@ -132,7 +131,7 @@ class DescDirective(Directive): fname, fbody = field try: typ, obj = fname.astext().split(None, 1) - typdesc = _(self.doc_fields_with_arg[typ]) + typdesc = self.doc_fields_with_arg[typ] if _is_only_paragraph(fbody): children = fbody.children[0].children else: @@ -176,7 +175,7 @@ class DescDirective(Directive): except (KeyError, ValueError): fnametext = fname.astext() try: - typ = _(self.doc_fields_without_arg[fnametext]) + typ = self.doc_fields_without_arg[fnametext] except KeyError: # at least capitalize the field name typ = fnametext.capitalize() @@ -499,14 +498,14 @@ class ClassmemberDesc(PythonDesc): clsname, methname = name.rsplit('.', 1) except ValueError: if modname: - return '%s() (in module %s)' % (name, modname) + return _('%s() (in module %s)') % (name, modname) else: return '%s()' % name if modname: - return '%s() (%s.%s class method)' % (methname, modname, - clsname) + return _('%s() (%s.%s class method)') % (methname, modname, + clsname) else: - return '%s() (%s class method)' % (methname, clsname) + return _('%s() (%s class method)') % (methname, clsname) elif self.desctype == 'attribute': try: clsname, attrname = name.rsplit('.', 1) @@ -692,7 +691,7 @@ class GenericDesc(DescDirective): signode['ids'].append(targetname) self.state.document.note_explicit_target(signode) if indextemplate: - indexentry = _(indextemplate) % (name,) + indexentry = indextemplate % (name,) indextype = 'single' colon = indexentry.find(':') if colon != -1: @@ -757,17 +756,13 @@ class DefaultDomain(Directive): # Note: the target directive is not registered here, it is used by the # application when registering additional xref types. -_ = lambda x: x - # Generic cross-reference types; they can be registered in the application; # the directives are either desc_directive or target_directive. additional_xref_types = { # directive name: (role name, index text, function to parse the desc node) - 'envvar': ('envvar', _('environment variable; %s'), None), + 'envvar': ('envvar', l_('environment variable; %s'), None), } -del _ - directives.register_directive('default-domain', directive_dwim(DefaultDomain)) directives.register_directive('describe', directive_dwim(DescDirective)) diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py index 36fabc615..a9abc9cb9 100644 --- a/sphinx/locale/__init__.py +++ b/sphinx/locale/__init__.py @@ -8,41 +8,179 @@ :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ +import gettext +import UserString + +from sphinx import package_dir + + +class _TranslationProxy(UserString.UserString, object): + """Class for proxy strings from gettext translations. This is a helper + for the lazy_* functions from this module. + + The proxy implementation attempts to be as complete as possible, so that + the lazy objects should mostly work as expected, for example for sorting. + + This inherits from UserString because some docutils versions use UserString + for their Text nodes, which then checks its argument for being either a + basestring or UserString, otherwise calls str() -- not unicode() -- on it. + This also inherits from object to make the __new__ method work. + """ + __slots__ = ('_func', '_args') + + def __new__(cls, func, *args): + if not args: + # not called with "function" and "arguments", but a plain string + return unicode(func) + return object.__new__(cls) + + def __init__(self, func, *args): + self._func = func + self._args = args + + data = property(lambda x: x._func(*x._args)) + + def __contains__(self, key): + return key in self.data + + def __nonzero__(self): + return bool(self.data) + + def __dir__(self): + return dir(unicode) + + def __iter__(self): + return iter(self.data) + + def __len__(self): + return len(self.data) + + def __str__(self): + return str(self.data) + + def __unicode__(self): + return unicode(self.data) + + def __add__(self, other): + return self.data + other + + def __radd__(self, other): + return other + self.data + + def __mod__(self, other): + return self.data % other + + def __rmod__(self, other): + return other % self.data + + def __mul__(self, other): + return self.data * other + + def __rmul__(self, other): + return other * self.data + + def __lt__(self, other): + return self.data < other + + def __le__(self, other): + return self.data <= other + + def __eq__(self, other): + return self.data == other + + def __ne__(self, other): + return self.data != other + + def __gt__(self, other): + return self.data > other + + def __ge__(self, other): + return self.data >= other + + def __getattr__(self, name): + if name == '__members__': + return self.__dir__() + return getattr(self.data, name) + + def __getstate__(self): + return self._func, self._args + + def __setstate__(self, tup): + self._func, self._args = tup + + def __getitem__(self, key): + return self.data[key] + + def __copy__(self): + return self + + def __repr__(self): + try: + return 'i' + repr(unicode(self.data)) + except: + return '<%s broken>' % self.__class__.__name__ + +def mygettext(string): + """Used instead of _ when creating TranslationProxies, because _ is not bound + yet at that time.""" + return _(string) + +def lazy_gettext(string): + """A lazy version of `gettext`.""" + #if isinstance(string, _TranslationProxy): + # return string + return _TranslationProxy(mygettext, string) + +l_ = lazy_gettext -_ = lambda x: x admonitionlabels = { - 'attention': _('Attention'), - 'caution': _('Caution'), - 'danger': _('Danger'), - 'error': _('Error'), - 'hint': _('Hint'), - 'important': _('Important'), - 'note': _('Note'), - 'seealso': _('See Also'), - 'tip': _('Tip'), - 'warning': _('Warning'), + 'attention': l_('Attention'), + 'caution': l_('Caution'), + 'danger': l_('Danger'), + 'error': l_('Error'), + 'hint': l_('Hint'), + 'important': l_('Important'), + 'note': l_('Note'), + 'seealso': l_('See Also'), + 'tip': l_('Tip'), + 'warning': l_('Warning'), } versionlabels = { - 'versionadded': _('New in version %s'), - 'versionchanged': _('Changed in version %s'), - 'deprecated': _('Deprecated since version %s'), + 'versionadded': l_('New in version %s'), + 'versionchanged': l_('Changed in version %s'), + 'deprecated': l_('Deprecated since version %s'), } pairindextypes = { - 'module': _('module'), - 'keyword': _('keyword'), - 'operator': _('operator'), - 'object': _('object'), - 'exception': _('exception'), - 'statement': _('statement'), - 'builtin': _('built-in function'), + 'module': l_('module'), + 'keyword': l_('keyword'), + 'operator': l_('operator'), + 'object': l_('object'), + 'exception': l_('exception'), + 'statement': l_('statement'), + 'builtin': l_('built-in function'), } -del _ -def init(): - for dct in (admonitionlabels, versionlabels, pairindextypes): - for key in dct: - dct[key] = _(dct[key]) +def init(locale_dirs, language): + # the None entry is the system's default locale path + translator = None + has_translation = True + for dir_ in locale_dirs: + try: + trans = gettext.translation('sphinx', localedir=dir_, + languages=[language]) + if translator is None: + translator = trans + else: + translator._catalog.update(trans.catalog) + except Exception: + # Language couldn't be found in the specified path + pass + if translator is None: + translator = gettext.NullTranslations() + has_translation = False + translator.install(unicode=True) + return translator, has_translation |