diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py index dbb97af76c..8205a4f957 100644 --- a/django/utils/translation/__init__.py +++ b/django/utils/translation/__init__.py @@ -7,7 +7,8 @@ __all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext', 'ngettext_lazy', 'string_concat', 'activate', 'deactivate', 'get_language', 'get_language_bidi', 'get_date_formats', 'get_partial_date_formats', 'check_for_language', 'to_locale', - 'get_language_from_request', 'install', 'templatize'] + 'get_language_from_request', 'install', 'templatize', 'ugettext', + 'ungettext'] # Here be dragons, so a short explanation of the logic won't hurt: # We are trying to solve two problems: (1) access settings, in particular @@ -48,18 +49,27 @@ del g, delayed_loader def gettext_noop(message): return real_gettext_noop(message) +ugettext_noop = gettext_noop + def gettext(message): return real_gettext(message) - def ngettext(singular, plural, number): return real_ngettext(singular, plural, number) +def ugettext(message): + return real_ugettext(message) + +def ungettext(singular, plural, number): + return real_ungettext(singular, plural, number) + def string_concat(*strings): return real_string_concat(*strings) -ngettext_lazy = lazy(ngettext, str, unicode) -gettext_lazy = lazy(gettext, str, unicode) +ngettext_lazy = lazy(ngettext, str) +gettext_lazy = lazy(gettext, str) +ungettext_lazy = lazy(ungettext, unicode) +ugettext_lazy = lazy(ugettext, unicode) string_concat = lazy(string_concat, str, unicode) def activate(language): diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py index 10b07529e3..a4b30737ca 100644 --- a/django/utils/translation/trans_null.py +++ b/django/utils/translation/trans_null.py @@ -3,12 +3,16 @@ # settings.USE_I18N = False can use this module rather than trans_real.py. from django.conf import settings +from django.utils.encoding import smart_unicode def ngettext(singular, plural, number): if number == 1: return singular return plural ngettext_lazy = ngettext +def ungettext(singular, plural, number): + return smart_unicode(ngettext(singular, plural, number)) + string_concat = lambda *strings: ''.join([str(el) for el in strings]) activate = lambda x: None deactivate = install = lambda: None @@ -30,6 +34,9 @@ TECHNICAL_ID_MAP = { def gettext(message): return TECHNICAL_ID_MAP.get(message, message) +def ugettext(message): + return smart_unicode(gettext(message)) + gettext_noop = gettext_lazy = _ = gettext def to_locale(language): diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index 0c8dcd540f..2878d9ad0a 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -3,6 +3,7 @@ import os, re, sys import gettext as gettext_module from cStringIO import StringIO +from django.utils.encoding import smart_str, smart_unicode try: import threading @@ -57,10 +58,10 @@ class DjangoTranslation(gettext_module.GNUTranslations): # the output charset. Before 2.4, the output charset is # identical with the translation file charset. try: - self.set_output_charset(settings.DEFAULT_CHARSET) + self.set_output_charset('utf-8') except AttributeError: pass - self.django_output_charset = settings.DEFAULT_CHARSET + self.django_output_charset = 'utf-8' self.__language = '??' def merge(self, other): @@ -238,6 +239,20 @@ def catalog(): _default = translation(settings.LANGUAGE_CODE) return _default +def do_translate(message, translation_function): + """ + Translate 'message' using the given 'translation_function' name -- which + will be either gettext or ugettext. + """ + global _default, _active + t = _active.get(currentThread(), None) + if t is not None: + return getattr(t, translation_function)(message) + if _default is None: + from django.conf import settings + _default = translation(settings.LANGUAGE_CODE) + return getattr(_default, translation_function)(message) + def gettext(message): """ This function will be patched into the builtins module to provide the _ @@ -245,42 +260,51 @@ def gettext(message): the translation object to use. If no current translation is activated, the message will be run through the default translation object. """ - global _default, _active - t = _active.get(currentThread(), None) - if t is not None: - return t.gettext(message) - if _default is None: - from django.conf import settings - _default = translation(settings.LANGUAGE_CODE) - return _default.gettext(message) + return do_translate(message, 'gettext') + +def ugettext(message): + return do_translate(message, 'ugettext') def gettext_noop(message): """ Marks strings for translation but doesn't translate them now. This can be used to store strings in global variables that should stay in the base - language (because they might be used externally) and will be translated later. + language (because they might be used externally) and will be translated + later. """ return message -def ngettext(singular, plural, number): - """ - Returns the translation of either the singular or plural, based on the number. - """ +def do_ntranslate(singular, plural, number, translation_function): global _default, _active t = _active.get(currentThread(), None) if t is not None: - return t.ngettext(singular, plural, number) + return getattr(t, translation_function)(singular, plural, number) if _default is None: from django.conf import settings _default = translation(settings.LANGUAGE_CODE) - return _default.ngettext(singular, plural, number) + return getattr(_default, translation_function)(singular, plural, number) + +def ngettext(singular, plural, number): + """ + Returns a UTF-8 bytestring of the translation of either the singular or + plural, based on the number. + """ + return do_ntranslate(singular, plural, number, 'ngettext') + +def ungettext(singular, plural, number): + """ + Returns a unicode strings of the translation of either the singular or + plural, based on the number. + """ + return do_ntranslate(singular, plural, number, 'ungettext') def check_for_language(lang_code): """ - Checks whether there is a global language file for the given language code. - This is used to decide whether a user-provided language is available. This is - only used for language codes from either the cookies or session. + Checks whether there is a global language file for the given language + code. This is used to decide whether a user-provided language is + available. This is only used for language codes from either the cookies or + session. """ from django.conf import settings globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale') @@ -291,9 +315,10 @@ def check_for_language(lang_code): def get_language_from_request(request): """ - Analyzes the request to find what language the user wants the system to show. - Only languages listed in settings.LANGUAGES are taken into account. If the user - requests a sublanguage where we have a main language, we send out the main language. + Analyzes the request to find what language the user wants the system to + show. Only languages listed in settings.LANGUAGES are taken into account. + If the user requests a sublanguage where we have a main language, we send + out the main language. """ global _accepted from django.conf import settings