Ticket #18731: makemessages.patch

File makemessages.patch, 10.8 KB (added by diabeteman, 2 years ago)

Adds --extra-keyword to the makemessages command. (with docs and tests)

  • django/core/management/commands/makemessages.py

    diff --git a/django/core/management/commands/makemessages.py b/django/core/management/commands/makemessages.py
    index 606cbe0..55b9ee1 100644
    a b def write_pot_file(potfile, msgs, file, work_file, is_templatized): 
    126126        fp.write(msgs)
    127127
    128128def process_file(file, dirpath, potfile, domain, verbosity,
    129                  extensions, wrap, location, stdout=sys.stdout):
     129                 extensions, wrap, location, stdout=sys.stdout,
     130                 extra_keywords=None):
    130131    """
    131132    Extract translatable literals from :param file: for :param domain:
    132133    creating or updating the :param potfile: POT file.
    def process_file(file, dirpath, potfile, domain, verbosity, 
    149150        work_file = os.path.join(dirpath, thefile)
    150151        with open(work_file, "w") as fp:
    151152            fp.write(src_data)
    152         cmd = (
    153             'xgettext -d %s -L C %s %s --keyword=gettext_noop '
    154             '--keyword=gettext_lazy --keyword=ngettext_lazy:1,2 '
    155             '--keyword=pgettext:1c,2 --keyword=npgettext:1c,2,3 '
    156             '--from-code UTF-8 --add-comments=Translators -o - "%s"' %
    157             (domain, wrap, location, work_file))
     153
     154        keywords = ['gettext_noop',
     155                    'gettext_lazy',
     156                    'ngettext_lazy:1,2',
     157                    'pgettext:1c,2',
     158                    'npgettext:1c,2,3',
     159                    ]
     160        if extra_keywords:
     161            keywords.extend(extra_keywords)
     162
     163        cmd = 'xgettext -d %s -L C %s %s'
     164        for kw in keywords:
     165            cmd += ' --keyword=%s' % kw
     166        cmd += ' --from-code UTF-8 --add-comments=Translators -o - "%s"'
     167        cmd %= (domain, wrap, location, work_file)
     168
    158169    elif domain == 'django' and (file_ext == '.py' or file_ext in extensions):
    159170        thefile = file
    160171        orig_file = os.path.join(dirpath, file)
    def process_file(file, dirpath, potfile, domain, verbosity, 
    167178            with open(os.path.join(dirpath, thefile), "w") as fp:
    168179                fp.write(content)
    169180        work_file = os.path.join(dirpath, thefile)
    170         cmd = (
    171             'xgettext -d %s -L Python %s %s --keyword=gettext_noop '
    172             '--keyword=gettext_lazy --keyword=ngettext_lazy:1,2 '
    173             '--keyword=ugettext_noop --keyword=ugettext_lazy '
    174             '--keyword=ungettext_lazy:1,2 --keyword=pgettext:1c,2 '
    175             '--keyword=npgettext:1c,2,3 --keyword=pgettext_lazy:1c,2 '
    176             '--keyword=npgettext_lazy:1c,2,3 --from-code UTF-8 '
    177             '--add-comments=Translators -o - "%s"' %
    178             (domain, wrap, location, work_file))
     181
     182        keywords = ['gettext_lazy',
     183                    'ngettext_lazy:1,2',
     184                    'ugettext_noop',
     185                    'ugettext_lazy',
     186                    'ungettext_lazy:1,2',
     187                    'pgettext:1c,2',
     188                    'npgettext:1c,2,3',
     189                    'pgettext_lazy:1c,2',
     190                    'npgettext_lazy:1c,2,3',
     191                    ]
     192        if extra_keywords:
     193            keywords.extend(extra_keywords)
     194
     195        cmd = 'xgettext -d %s -L Python %s %s'
     196        for kw in keywords:
     197            cmd += ' --keyword=%s' % kw
     198        cmd += ' --from-code UTF-8 --add-comments=Translators -o - "%s"'
     199        cmd %= (domain, wrap, location, work_file)
    179200    else:
    180201        return
    181202    msgs, errors, status = _popen(cmd)
    def write_po_file(pofile, potfile, domain, locale, verbosity, stdout, 
    246267
    247268def make_messages(locale=None, domain='django', verbosity=1, all=False,
    248269        extensions=None, symlinks=False, ignore_patterns=None, no_wrap=False,
    249         no_location=False, no_obsolete=False, stdout=sys.stdout):
     270        no_location=False, no_obsolete=False, stdout=sys.stdout,
     271        extra_keywords=None):
    250272    """
    251273    Uses the ``locale/`` directory from the Django Git tree or an
    252274    application/project to process all files with translatable literals for
    def make_messages(locale=None, domain='django', verbosity=1, all=False, 
    325347        for dirpath, file in find_files(".", ignore_patterns, verbosity,
    326348                stdout, symlinks=symlinks):
    327349            process_file(file, dirpath, potfile, domain, verbosity, extensions,
    328                     wrap, location, stdout)
     350                    wrap, location, stdout, extra_keywords)
    329351
    330352        if os.path.exists(potfile):
    331353            write_po_file(pofile, potfile, domain, locale, verbosity, stdout,
    class Command(NoArgsCommand): 
    355377            default=False, help="Don't write '#: filename:line' lines"),
    356378        make_option('--no-obsolete', action='store_true', dest='no_obsolete',
    357379            default=False, help="Remove obsolete message strings"),
     380        make_option('--extra-keyword', dest='extra_keywords',
     381                    help='If you use import aliases for ugettext and its variations, '
     382                    'you can specify it here to make sure that xgettext will find '
     383                    'your translatable strings.',
     384                    action='append')
    358385    )
    359386    help = ("Runs over the entire source tree of the current directory and "
    360387"pulls out all strings marked for translation. It creates (or updates) a message "
    class Command(NoArgsCommand): 
    379406        no_wrap = options.get('no_wrap')
    380407        no_location = options.get('no_location')
    381408        no_obsolete = options.get('no_obsolete')
     409        extra_keywords = options.get('extra_keywords')
    382410        if domain == 'djangojs':
    383411            exts = extensions if extensions else ['js']
    384412        else:
    class Command(NoArgsCommand): 
    390418                             % get_text_list(list(extensions), 'and'))
    391419
    392420        make_messages(locale, domain, verbosity, process_all, extensions,
    393             symlinks, ignore_patterns, no_wrap, no_location, no_obsolete, self.stdout)
     421            symlinks, ignore_patterns, no_wrap, no_location, no_obsolete,
     422            self.stdout, extra_keywords)
  • docs/man/django-admin.1

    diff --git a/docs/man/django-admin.1 b/docs/man/django-admin.1
    index 4d937b4..7e9200c 100644
    a b Executes 
    6060.B sqlall
    6161for the given app(s) in the current database.
    6262.TP
    63 .BI "makemessages [" "\-\-locale=LOCALE" "] [" "\-\-domain=DOMAIN" "] [" "\-\-extension=EXTENSION" "] [" "\-\-all" "] [" "\-\-symlinks" "] [" "\-\-ignore=PATTERN" "] [" "\-\-no\-default\-ignore" "] [" "\-\-no\-wrap" "] [" "\-\-no\-location" "]"
     63.BI "makemessages [" "\-\-locale=LOCALE" "] [" "\-\-domain=DOMAIN" "] [" "\-\-extension=EXTENSION" "] [" "\-\-all" "] [" "\-\-symlinks" "] [" "\-\-ignore=PATTERN" "] [" "\-\-no\-default\-ignore" "] [" "\-\-no\-wrap" "] [" "\-\-no\-location" "] [" "\-\-extra-keyword=KEYWORD" "]"
    6464Runs over the entire source tree of the current directory and pulls out all
    6565strings marked for translation. It creates (or updates) a message file in the
    6666conf/locale (in the django tree) or locale (for project and application) directory.
  • docs/ref/django-admin.txt

    diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
    index d471b59..70a748d 100644
    a b Use the ``--no-location`` option to not write '``#: filename:line``' 
    474474comment lines in language files. Note that using this option makes it harder
    475475for technically skilled translators to understand each message's context.
    476476
     477.. django-admin-option:: --extra-keyword
     478
     479.. versionadded:: 1.6
     480
     481When you import the ``ugettext`` and ``ugettext_lazy`` functions as aliases,
     482``makemessages`` may not find translatable strings in your python source code.
     483With the ``--extra-keyword`` option, you can force it to look for other aliases
     484you may choose.
     485
     486Example usage:
     487
     488If you want ``makemessages`` to find translatable strings in the following
     489python code.
     490
     491.. code-block:: python
     492
     493   from django.utils.translation import ugettext as tr, ugettext_lazy as tr_lazy
     494
     495   tr('some translatable string')
     496   tr_lazy('some lazy translatable string')
     497
     498You will need to add the option ``--extra-keyword`` twice::
     499
     500    django-admin.py makemessages --locale=fr_FR --extra-keyword=tr --extra-keyword=tr_lazy
     501
     502.. note:: The default alias ``'_'`` will allways be detected by ``makemessages``
     503   whether you use the ``--extra-keyword`` option or not.
     504
     505
    477506runfcgi [options]
    478507-----------------
    479508
  • tests/regressiontests/i18n/commands/extraction.py

    diff --git a/setup.py b/setup.py
    old mode 100644
    new mode 100755
    diff --git a/tests/regressiontests/i18n/commands/extraction.py b/tests/regressiontests/i18n/commands/extraction.py
    index aa5efe1..61720f5 100644
    a b class NoLocationExtractorTests(ExtractorTests): 
    293293        with open(self.PO_FILE, 'r') as fp:
    294294            po_contents = force_text(fp.read())
    295295            self.assertTrue('#: templates/test.html:55' in po_contents)
     296
     297
     298class UgettextAliasesTests(ExtractorTests):
     299
     300    def test_missing_keyword(self):
     301        os.chdir(self.test_dir)
     302        shutil.copyfile('./ugettext-aliases.sample', './ugettext_aliases.py')
     303        management.call_command('makemessages', locale=LOCALE, verbosity=0)
     304        self.assertTrue(os.path.exists(self.PO_FILE))
     305        with open(self.PO_FILE, 'r') as fp:
     306            po_contents = force_text(fp.read())
     307            self.assertNotMsgId('Should be found only with the --extra-keyword option', po_contents)
     308            self.assertNotMsgId('Lazy, should be found only with the --extra-keyword option', po_contents)
     309        os.remove('./ugettext_aliases.py')
     310
     311    def test_added_keywords(self):
     312        os.chdir(self.test_dir)
     313        shutil.copyfile('./ugettext-aliases.sample', './ugettext_aliases.py')
     314        management.call_command('makemessages', locale=LOCALE, verbosity=0, extra_keywords=['tr', 'tr_lazy'])
     315        self.assertTrue(os.path.exists(self.PO_FILE))
     316        with open(self.PO_FILE, 'r') as fp:
     317            po_contents = force_text(fp.read())
     318            self.assertMsgId('Should be found only with the --extra-keyword option', po_contents)
     319            self.assertMsgId('Lazy, should be found only with the --extra-keyword option', po_contents)
     320        os.remove('./ugettext_aliases.py')
     321
  • tests/regressiontests/i18n/tests.py

    diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
    index d8af6f1..28dd4e7 100644
    a b if can_run_extraction_tests: 
    3232    from .commands.extraction import (ExtractorTests, BasicExtractorTests,
    3333        JavascriptExtractorTests, IgnoredExtractorTests, SymlinkExtractorTests,
    3434        CopyPluralFormsExtractorTests, NoWrapExtractorTests,
    35         NoLocationExtractorTests)
     35        NoLocationExtractorTests, UgettextAliasesTests)
    3636if can_run_compilation_tests:
    3737    from .commands.compilation import (PoFileTests, PoFileContentsTests,
    3838        PercentRenderingTests)
Back to Top