1# -*- coding: utf-8 -*-
2import os
3from distutils.dist import Distribution
4from subprocess import call
5
6from django.core.management.base import LabelCommand, CommandError
7from django.conf import settings
8
9
10__all__ = ['Command']
11
12
13class Command(LabelCommand):
14
15    args = '[makemessages] [compilemessages]'
16
17    def add_arguments(self, parser):
18        super(Command, self).add_arguments(parser)
19        parser.add_argument(
20            '--locale', '-l', default=[], dest='locale', action='append',
21            help=(
22                'Creates or updates the message files for the given locale(s)'
23                ' (e.g pt_BR). Can be used multiple times.'
24            ),
25        )
26        parser.add_argument(
27            '--domain', '-d', default='django', dest='domain',
28            help='The domain of the message files (default: "django").',
29        ),
30        parser.add_argument(
31            '--mapping-file', '-F', default=None, dest='mapping_file',
32            help='Mapping file',
33        )
34
35    def handle_label(self, command, **options):
36        if command not in ('makemessages', 'compilemessages'):
37            raise CommandError(
38                "You must either apply 'makemessages' or 'compilemessages'"
39            )
40
41        if command == 'makemessages':
42            self.handle_makemessages(**options)
43        if command == 'compilemessages':
44            self.handle_compilemessages(**options)
45
46    def handle_makemessages(self, **options):
47        locale_paths = list(settings.LOCALE_PATHS)
48        domain = options.pop('domain')
49        locales = options.pop('locale')
50
51        # support for mapping file specification via setup.cfg
52        # TODO: Try to support all possible options.
53        distribution = Distribution()
54        distribution.parse_config_files(distribution.find_config_files())
55
56        mapping_file = options.pop('mapping_file', None)
57        has_extract = 'extract_messages' in distribution.command_options
58        if mapping_file is None and has_extract:
59            opts = distribution.command_options['extract_messages']
60            try:
61                mapping_file = opts['mapping_file'][1]
62            except (IndexError, KeyError):
63                mapping_file = None
64
65        for path in locale_paths:
66            potfile = os.path.join(path, '%s.pot' % domain)
67
68            if not os.path.exists(path):
69                os.makedirs(path)
70
71            if not os.path.exists(potfile):
72                with open(potfile, 'wb') as fobj:
73                    fobj.write(b'')
74
75            cmd = ['pybabel', 'extract', '-o', potfile]
76
77            if mapping_file is not None:
78                cmd.extend(['-F', mapping_file])
79
80            cmd.append(os.path.dirname(os.path.relpath(path)))
81
82            call(cmd)
83
84            for locale in locales:
85                pofile = os.path.join(
86                    os.path.dirname(potfile),
87                    locale,
88                    'LC_MESSAGES',
89                    '%s.po' % domain)
90
91                if not os.path.isdir(os.path.dirname(pofile)):
92                    os.makedirs(os.path.dirname(pofile))
93
94                if not os.path.exists(pofile):
95                    with open(pofile, 'wb') as fobj:
96                        fobj.write(b'')
97
98                cmd = ['pybabel', 'update', '-D', domain,
99                       '-i', potfile,
100                       '-d', os.path.relpath(path),
101                       '-l', locale]
102                call(cmd)
103
104    def handle_compilemessages(self, **options):
105        locale_paths = list(settings.LOCALE_PATHS)
106        domain = options.pop('domain')
107        locales = options.pop('locale')
108
109        for path in locale_paths:
110            for locale in locales:
111                po_file = os.path.join(
112                    path, locale, 'LC_MESSAGES', domain + '.po'
113                )
114                if os.path.exists(po_file):
115                    cmd = ['pybabel', 'compile', '-D', domain,
116                           '-d', path, '-l', locale]
117                    call(cmd)
118