def handle_noargs(self, **options):
        """
        Command execution.
        """
        self.interactive = options['interactive']

        models = translator.get_registered_models(abstract=False)
        found_bad_fields = False
        for model in models:
            db_table = model._meta.db_table
            model_full_name = '%s.%s' % (model._meta.app_label, model._meta.module_name)
            opts = translator.get_options_for_model(model)
            for field_name in opts.local_fields.keys():
                bad_lang_field_names = self.get_bad_lang_field_names(field_name, db_table)
                if bad_lang_field_names:
                    found_bad_fields = True
                    print_bad_langs(bad_lang_field_names, field_name, model_full_name)
                    sql_sentences = self.get_alter_sql(bad_lang_field_names, model)
                    execute_sql = ask_for_confirmation(
                        sql_sentences, model_full_name, self.interactive)
                    if execute_sql:
                        print('Executing SQL...')
                        for sentence in sql_sentences:
                            self.cursor.execute(sentence)
                        print('Done')
                    else:
                        print('SQL not executed')

        if not found_bad_fields:
            print('No new translatable fields detected')
Exemple #2
0
    def handle_noargs(self, **options):
        """
        Command execution.
        """
        self.interactive = options['interactive']

        models = translator.get_registered_models(abstract=False)
        found_bad_fields = False
        for model in models:
            db_table = model._meta.db_table
            model_full_name = '%s.%s' % (model._meta.app_label,
                                         model._meta.module_name)
            opts = translator.get_options_for_model(model)
            for field_name in opts.local_fields.keys():
                bad_lang_field_names = self.get_bad_lang_field_names(
                    field_name, db_table)
                if bad_lang_field_names:
                    found_bad_fields = True
                    print_bad_langs(bad_lang_field_names, field_name,
                                    model_full_name)
                    sql_sentences = self.get_alter_sql(bad_lang_field_names,
                                                       model)
                    execute_sql = ask_for_confirmation(sql_sentences,
                                                       model_full_name,
                                                       self.interactive)
                    if execute_sql:
                        print('Executing SQL...')
                        for sentence in sql_sentences:
                            self.cursor.execute(sentence)
                        print('Done')
                    else:
                        print('SQL not executed')

        if not found_bad_fields:
            print('No new translatable fields detected')
    def handle(self, *args, **options):
        verbosity = int(options['verbosity'])
        if verbosity > 0:
            self.stdout.write("Using default language: %s\n" %
                              DEFAULT_LANGUAGE)
        models = translator.get_registered_models(abstract=False)
        for model in models:
            if verbosity > 0:
                self.stdout.write("Updating data of model '%s'\n" % model)
            opts = translator.get_options_for_model(model)
            for field_name in opts.fields.keys():
                def_lang_fieldname = build_localized_fieldname(
                    field_name, DEFAULT_LANGUAGE)

                # We'll only update fields which do not have an existing value
                q = Q(**{def_lang_fieldname: None})
                field = model._meta.get_field(field_name)
                if field.get_internal_type(
                ) == 'JsonBField':  # support for jsonbfields
                    q |= Q(**{def_lang_fieldname: {}})
                if field.empty_strings_allowed:
                    q |= Q(**{def_lang_fieldname: ""})

                model._default_manager.filter(q).rewrite(False).update(
                    **{def_lang_fieldname: F(field_name)})
    def collect_po_file(self, lang):
        po = polib.POFile()
        po.metadata = {
            'Language': lang,
            'Content-Type': 'text/plain; charset=utf-8',
            'Content-Transfer-Encoding': '8bit',
        }

        def append_item(msgid, msgstr, occurrences):
            entry = po.find(msgid)
            if not entry:
                po.append(
                    polib.POEntry(msgid=msgid,
                                  msgstr=msgstr,
                                  occurrences=occurrences))
            else:
                entry.occurrences += occurrences

        for string in StringTranslation.objects.all():
            if string.key and len(string.key) > 0:
                append_item(
                    msgid=string.key,
                    msgstr=getattr(string, 'translation_{}'.format(lang))
                    or '',
                    occurrences=[('strings', str(string.id))])
        models = translator.get_registered_models(abstract=False)
        for model in models:

            if 'products' in str(model):
                continue

            if model is StringTranslation:
                continue
            opts = translator.get_options_for_model(model)

            fields_to_copy = []
            for field_name in opts.fields.keys():
                fields_to_copy.append(
                    (field_name, build_localized_fieldname(field_name, lang)))

            for obj in model.objects.all():
                for field_name, field_name_local in fields_to_copy:
                    try:
                        msgid = obj.__dict__[field_name]
                    except KeyError:
                        msgid = None

                    if msgid and msgid != '':
                        if len(msgid) < 300:
                            append_item(msgid=msgid,
                                        msgstr=getattr(obj, field_name_local)
                                        or '',
                                        occurrences=[('{}:{}'.format(
                                            get_model_ct(model),
                                            field_name), str(obj.id))])
                        else:
                            print(
                                "WARN: text too long for msgid. Model: {} Field: {}"
                                .format(model, field_name))
        return po
    def handle_noargs(self, **options):
        """
        Command execution.
        """
        self.cursor = connection.cursor()
        self.introspection = connection.introspection

        found_missing_fields = False
        models = translator.get_registered_models(abstract=False)
        for model in models:
            db_table = model._meta.db_table
            model_full_name = '%s.%s' % (model._meta.app_label, model._meta.module_name)
            opts = translator.get_options_for_model(model)
            for field_name in opts.local_fields.iterkeys():
                missing_langs = list(self.get_missing_languages(field_name, db_table))
                if missing_langs:
                    found_missing_fields = True
                    print_missing_langs(missing_langs, field_name, model_full_name)
                    sql_sentences = self.get_sync_sql(field_name, missing_langs, model)
                    execute_sql = ask_for_confirmation(sql_sentences, model_full_name)
                    if execute_sql:
                        print 'Executing SQL...',
                        for sentence in sql_sentences:
                            self.cursor.execute(sentence)
                        print 'Done'
                    else:
                        print 'SQL not executed'

        transaction.commit_unless_managed()

        if not found_missing_fields:
            print 'No new translatable fields detected'
    def handle(self, **options):
        verbosity = int(options['verbosity'])
        if verbosity > 0:
            self.stdout.write("Using default language: %s\n" %
                              DEFAULT_LANGUAGE)
        models = translator.get_registered_models(abstract=False)
        for model in models:
            if verbosity > 0:
                self.stdout.write("Updating data of model '%s'\n" % model)
            opts = translator.get_options_for_model(model)
            for field_name in opts.fields.keys():
                def_lang_fieldname = build_localized_fieldname(
                    field_name, DEFAULT_LANGUAGE)

                # We'll only update fields which do not have an existing value
                q = Q(**{def_lang_fieldname: None})
                field = model._meta.get_field(field_name)
                if field.empty_strings_allowed:
                    q |= Q(**{def_lang_fieldname: ''})

                if issubclass(model, Page):
                    for obj in model._default_manager.filter(q):
                        # Get table description in order to know if field is
                        # in child or parent table
                        # TODO: Tested only on PostgreSQL engine
                        db_table = model._meta.db_table
                        db_table_desc = connection.introspection. \
                            get_table_description(
                            connection.cursor(), db_table)
                        # original field in child class
                        if field_name in [x.name for x in db_table_desc]:
                            raw = model._default_manager.raw(
                                'SELECT *, %s AS original_field FROM %s \
                                 WHERE page_ptr_id=%d LIMIT 1' %
                                (field_name, db_table, obj.page_ptr_id))[0]
                            setattr(obj, def_lang_fieldname,
                                    raw.original_field)
                        # field is a foreign key
                        elif (field_name + '_id') in \
                                [x.name for x in db_table_desc]:
                            raw = model._default_manager.raw(
                                'SELECT *, %s AS original_field FROM %s \
                                 WHERE page_ptr_id=%d LIMIT 1' %
                                (field_name + '_id', db_table,
                                 obj.page_ptr_id))[0]
                            setattr(obj, def_lang_fieldname + '_id',
                                    raw.original_field)
                        # original field parent class
                        else:
                            raw = Page._default_manager.raw(
                                'SELECT *, %s AS original_field FROM \
                                 wagtailcore_page WHERE id=%d LIMIT 1' %
                                (field_name, obj.page_ptr_id))[0]
                            setattr(obj, def_lang_fieldname,
                                    raw.original_field)
                        obj.save(update_fields=[def_lang_fieldname])
                else:
                    model._default_manager.filter(q).rewrite(False).update(
                        **{def_lang_fieldname: F(field_name)})
Exemple #7
0
def get_translatable_models():
    """
    Get the translatable models according to django-modeltranslation

    !! only use to migrate from django-modeltranslation !!
    """
    _raise_if_not_django_modeltranslation()
    return translator.get_registered_models()
Exemple #8
0
 def get_translated_fields(self):
     if self._translated_fields is None:
         models = translator.get_registered_models()
         if self.model in models:
             options = translator.get_options_for_model(self.model)
             rv = [field for field in options.fields]
             self._translated_fields = rv
         else:
             self._translated_fields = []
     return self._translated_fields
Exemple #9
0
def autodiscover():
    """
    Auto-discover INSTALLED_APPS translation.py modules and fail silently when
    not present. This forces an import on them to register.
    Also import explicit modules.
    """
    import os
    import sys
    import copy
    from django.conf import settings
    from django.utils.module_loading import module_has_submodule
    from modeltranslation.translator import translator
    from modeltranslation.settings import TRANSLATION_FILES, DEBUG

    if django.VERSION < (1, 7):
        from django.utils.importlib import import_module
        mods = [(app, import_module(app)) for app in settings.INSTALLED_APPS]
    else:
        from importlib import import_module
        from django.apps import apps
        mods = [(app_config.name, app_config.module) for app_config in apps.get_app_configs()]

    for (app, mod) in mods:
        # Attempt to import the app's translation module.
        module = '%s.translation' % app
        before_import_registry = copy.copy(translator._registry)
        try:
            import_module(module)
        except:
            # Reset the model registry to the state before the last import as
            # this import will have to reoccur on the next request and this
            # could raise NotRegistered and AlreadyRegistered exceptions
            translator._registry = before_import_registry

            # Decide whether to bubble up this error. If the app just
            # doesn't have an translation module, we can ignore the error
            # attempting to import it, otherwise we want it to bubble up.
            if module_has_submodule(mod, 'translation'):
                raise

    for module in TRANSLATION_FILES:
        import_module(module)

    # In debug mode, print a list of registered models and pid to stdout.
    # Note: Differing model order is fine, we don't rely on a particular
    # order, as far as base classes are registered before subclasses.
    if DEBUG:
        try:
            if sys.argv[1] in ('runserver', 'runserver_plus'):
                models = translator.get_registered_models()
                names = ', '.join(m.__name__ for m in models)
                print('modeltranslation: Registered %d models for translation'
                      ' (%s) [pid: %d].' % (len(models), names, os.getpid()))
        except IndexError:
            pass
Exemple #10
0
    def handle(self, *args, **options):
        verbosity = options['verbosity']
        if verbosity > 0:
            self.stdout.write("Using default language: %s" % DEFAULT_LANGUAGE)

        # get all models excluding proxy- and not managed models
        models = translator.get_registered_models(abstract=False)
        models = [m for m in models if not m._meta.proxy and m._meta.managed]

        # optionally filter by given app_label
        app_label = options['app_label']
        if app_label:
            models = [m for m in models if m._meta.app_label == app_label]

        # optionally filter by given model_name
        model_name = options['model_name']
        if model_name:
            model_name = model_name.lower()
            models = [m for m in models if m._meta.model_name == model_name]

        # optionally defining the translation field language
        lang = options.get('language') or DEFAULT_LANGUAGE
        if lang not in AVAILABLE_LANGUAGES:
            raise CommandError(
                "Cannot find language '%s'. Options are %s."
                % (lang, COMMASPACE.join(AVAILABLE_LANGUAGES))
            )
        else:
            lang = lang.replace('-', '_')

        if verbosity > 0:
            self.stdout.write(
                "Working on models: %s"
                % ', '.join(
                    ["{app_label}.{object_name}".format(**m._meta.__dict__) for m in models]
                )
            )

        for model in models:
            if verbosity > 0:
                self.stdout.write("Updating data of model '%s'" % model)

            opts = translator.get_options_for_model(model)
            for field_name in opts.fields.keys():
                def_lang_fieldname = build_localized_fieldname(field_name, lang)

                # We'll only update fields which do not have an existing value
                q = Q(**{def_lang_fieldname: None})
                field = model._meta.get_field(field_name)
                if field.empty_strings_allowed:
                    q |= Q(**{def_lang_fieldname: ""})

                model._default_manager.filter(q).rewrite(False).order_by().update(
                    **{def_lang_fieldname: F(field_name)}
                )
def patch_wagtail_models():
    # After all models being registered the Page or BaseSetting subclasses and snippets are patched
    registered_models = translator.get_registered_models()

    # We need to sort the models to ensure that subclasses of a model are registered first,
    # or else if the panels are inherited all the changes on the subclass would be
    # reflected in the superclass
    registered_models.sort(key=compare_class_tree_depth)

    for model_class in registered_models:
        WagtailTranslator(model_class)
def patch_wagtail_models():
    # After all models being registered the Page or BaseSetting subclasses and snippets are patched
    registered_models = translator.get_registered_models()

    # We need to sort the models to ensure that subclasses of a model are registered first,
    # or else if the panels are inherited all the changes on the subclass would be
    # reflected in the superclass
    registered_models.sort(key=compare_class_tree_depth)

    for model_class in registered_models:
        if issubclass(model_class, Page) or model_class in get_snippet_models() or issubclass(model_class, BaseSetting):
            WagtailTranslator(model_class)
def autodiscover():
    """
    Auto-discover INSTALLED_APPS translation.py modules and fail silently when
    not present. This forces an import on them to register.
    Also import explicit modules.
    """
    import os
    import sys
    import copy
    from django.utils.module_loading import module_has_submodule
    from modeltranslation.translator import translator
    from modeltranslation.settings import TRANSLATION_FILES, DEBUG

    from importlib import import_module
    from django.apps import apps

    mods = [(app_config.name, app_config.module)
            for app_config in apps.get_app_configs()]

    for (app, mod) in mods:
        # Attempt to import the app's translation module.
        module = '%s.translation' % app
        before_import_registry = copy.copy(translator._registry)
        try:
            import_module(module)
        except:
            # Reset the model registry to the state before the last import as
            # this import will have to reoccur on the next request and this
            # could raise NotRegistered and AlreadyRegistered exceptions
            translator._registry = before_import_registry

            # Decide whether to bubble up this error. If the app just
            # doesn't have an translation module, we can ignore the error
            # attempting to import it, otherwise we want it to bubble up.
            if module_has_submodule(mod, 'translation'):
                raise

    for module in TRANSLATION_FILES:
        import_module(module)

    # In debug mode, print a list of registered models and pid to stdout.
    # Note: Differing model order is fine, we don't rely on a particular
    # order, as far as base classes are registered before subclasses.
    if DEBUG:
        try:
            if sys.argv[1] in ('runserver', 'runserver_plus'):
                models = translator.get_registered_models()
                names = ', '.join(m.__name__ for m in models)
                print('modeltranslation: Registered %d models for translation'
                      ' (%s) [pid: %d].' % (len(models), names, os.getpid()))
        except IndexError:
            pass
    def inner(klass):

        class_name = klass.__name__
        options_class_name = class_name + "TranslationOptions"

        options_class = type(options_class_name, (TranslationOptions, ),
                             {"fields": fields})

        if klass not in translator.get_registered_models(
        ):  # Workaround for AlreadyRegistered bug
            translator.register(klass, options_class)

        return klass
    def handle(self, *args, **options):

        if not hasattr(settings, 'MODELTRANSLATION_LOCALE_PATH'):
            raise CommandError(
                "Settings has no attribute 'MODELTRANSLATION_LOCALE_PATH'")

        if not hasattr(settings, 'MODELTRANSLATION_PO_FILE'):
            filename_po = "modeltranslation.po"
        else:
            filename_po = settings.MODELTRANSLATION_PO_FILE
            if not filename_po.endswith(".po"):
                filename_po += '.po'

        locale_path = settings.MODELTRANSLATION_LOCALE_PATH
        if not isdir(locale_path):
            mkdir(locale_path)

        for lang in [l[0] for l in list(settings.LANGUAGES)]:

            catalog = Catalog(locale=lang)

            for model in translator.get_registered_models():
                opts = translator.get_options_for_model(model)

                for field in opts.get_field_names():
                    if field != "url_path":
                        tr_field = "%s_%s" % (field, lang)
                        en_field = "%s_%s" % (field, "en")
                        for item in model.objects.all():
                            msgid = "%s.%s.%s" % (item._meta, item.pk, field)
                            msgstr = "%s" % getattr(item, tr_field)
                            enval = getattr(item, en_field)
                            if enval is not None:
                                enstr = "%s" % enval
                                catalog.add(id=enstr,
                                            string=msgstr,
                                            auto_comments=[
                                                msgid,
                                            ])

            # write catalog to file
            lang_path = join(locale_path, lang)
            if not isdir(lang_path):
                mkdir(lang_path)
                mkdir(join(lang_path, "LC_MESSAGES"))
            f = open(join(lang_path, "LC_MESSAGES", filename_po), "wb")
            write_po(f, catalog)
            f.close()
Exemple #16
0
 def _update_obj_index_iter(self, obj):
     klass = obj.__class__
     curr_lang = translation.get_language()
     try:
         if klass in translator.get_registered_models():
             # make sure doc in default language has highest priority
             langs = list(zip(*settings.LANGUAGES)[0])
             langs.remove(settings.LANGUAGE_CODE)
             langs.append(settings.LANGUAGE_CODE)
         else:
             langs = [curr_lang]
         for lang in langs:
             translation.activate(lang)
             for ret in super(MultiligualSearchEngine, self)._update_obj_index_iter(obj, lang):
                 yield ret
     finally:
         translation.activate(curr_lang)
Exemple #17
0
    def handle_noargs(self, **options):
        """
        Command execution.
        """
        self.cursor = connection.cursor()
        self.introspection = connection.introspection
        self.interactive = options['interactive']

        found_missing_fields = False
        models = translator.get_registered_models(abstract=False)
        for model in models:
            db_table = model._meta.db_table
            if django.VERSION < (1, 8):
                model_name = model._meta.module_name
            else:
                model_name = model._meta.model_name
            model_full_name = '%s.%s' % (model._meta.app_label, model_name)
            opts = translator.get_options_for_model(model)
            for field_name, fields in opts.local_fields.items():
                # Take `db_column` attribute into account
                field = list(fields)[0]
                column_name = field.db_column if field.db_column else field_name
                missing_langs = list(
                    self.get_missing_languages(column_name, db_table))
                if missing_langs:
                    found_missing_fields = True
                    print_missing_langs(missing_langs, field_name,
                                        model_full_name)
                    sql_sentences = self.get_sync_sql(field_name,
                                                      missing_langs, model)
                    execute_sql = ask_for_confirmation(sql_sentences,
                                                       model_full_name,
                                                       self.interactive)
                    if execute_sql:
                        print('Executing SQL...')
                        for sentence in sql_sentences:
                            self.cursor.execute(sentence)
                        print('Done')
                    else:
                        print('SQL not executed')

        if django.VERSION < (1, 6):
            transaction.commit_unless_managed()

        if not found_missing_fields:
            print('No new translatable fields detected')
    def handle(self, *args, **options):
        """
        Command execution.
        """
        self.cursor = connection.cursor()
        self.introspection = connection.introspection
        self.interactive = options['interactive']

        found_missing_fields = False
        models = translator.get_registered_models(abstract=False)
        for model in models:
            db_table = model._meta.db_table
            model_name = model._meta.model_name
            model_full_name = '%s.%s' % (model._meta.app_label, model_name)
            opts = translator.get_options_for_model(model)
            for field_name, fields in opts.local_fields.items():
                # Take `db_column` attribute into account
                try:
                    field = list(fields)[0]
                except IndexError:
                    # Ignore IndexError for ProxyModel
                    # maybe there is better way to handle this
                    continue
                column_name = field.db_column if field.db_column else field_name
                missing_langs = list(
                    self.get_missing_languages(column_name, db_table))
                if missing_langs:
                    found_missing_fields = True
                    print_missing_langs(missing_langs, field_name,
                                        model_full_name)
                    sql_sentences = self.get_sync_sql(field_name,
                                                      missing_langs, model)
                    execute_sql = ask_for_confirmation(sql_sentences,
                                                       model_full_name,
                                                       self.interactive)
                    if execute_sql:
                        print('Executing SQL...')
                        for sentence in sql_sentences:
                            self.cursor.execute(sentence)
                        print('Done')
                    else:
                        print('SQL not executed')

        if not found_missing_fields:
            print('No new translatable fields detected')
    def handle(self, *args, **options):
        verbosity = options['verbosity']
        if verbosity > 0:
            self.stdout.write("Using default language: %s" % DEFAULT_LANGUAGE)

        # get all models excluding proxy- and not managed models
        models = translator.get_registered_models(abstract=False)
        models = [m for m in models if not m._meta.proxy and m._meta.managed]

        # optionally filter by given app_label
        app_label = options['app_label']
        if app_label:
            models = [m for m in models if m._meta.app_label == app_label]

        # optionally filter by given model_name
        model_name = options['model_name']
        if model_name:
            model_name = model_name.lower()
            models = [m for m in models if m._meta.model_name == model_name]

        if verbosity > 0:
            self.stdout.write("Working on models: %s" % ', '.join([
                "{app_label}.{object_name}".format(**m._meta.__dict__)
                for m in models
            ]))

        for model in models:
            if verbosity > 0:
                self.stdout.write("Updating data of model '%s'" % model)

            opts = translator.get_options_for_model(model)
            for field_name in opts.fields.keys():
                def_lang_fieldname = build_localized_fieldname(field_name, DEFAULT_LANGUAGE)

                # We'll only update fields which do not have an existing value
                q = Q(**{def_lang_fieldname: None})
                field = model._meta.get_field(field_name)
                if field.empty_strings_allowed:
                    q |= Q(**{def_lang_fieldname: ""})

                model._default_manager.filter(q).rewrite(False).update(
                    **{def_lang_fieldname: F(field_name)}
                )
    def handle_noargs(self, **options):
        """
        Command execution.
        """
        self.cursor = connection.cursor()
        self.introspection = connection.introspection
        self.interactive = options['interactive']

        found_missing_fields = False
        models = translator.get_registered_models(abstract=False)
        for model in models:
            db_table = model._meta.db_table
            if django.VERSION < (1, 8):
                model_name = model._meta.module_name
            else:
                model_name = model._meta.model_name
            model_full_name = '%s.%s' % (model._meta.app_label, model_name)
            opts = translator.get_options_for_model(model)
            for field_name, fields in opts.local_fields.items():
                # Take `db_column` attribute into account
                field = list(fields)[0]
                column_name = field.db_column if field.db_column else field_name
                missing_langs = list(self.get_missing_languages(column_name, db_table))
                if missing_langs:
                    found_missing_fields = True
                    print_missing_langs(missing_langs, field_name, model_full_name)
                    sql_sentences = self.get_sync_sql(field_name, missing_langs, model)
                    execute_sql = ask_for_confirmation(
                        sql_sentences, model_full_name, self.interactive)
                    if execute_sql:
                        print('Executing SQL...')
                        for sentence in sql_sentences:
                            self.cursor.execute(sentence)
                        print('Done')
                    else:
                        print('SQL not executed')

        if django.VERSION < (1, 6):
            transaction.commit_unless_managed()

        if not found_missing_fields:
            print('No new translatable fields detected')
    def handle_noargs(self, **options):
        verbosity = int(options['verbosity'])
        if verbosity > 0:
            self.stdout.write("Using default language: %s\n" % DEFAULT_LANGUAGE)
        models = translator.get_registered_models(abstract=False)
        for model in models:
            if verbosity > 0:
                self.stdout.write("Updating data of model '%s'\n" % model)
            opts = translator.get_options_for_model(model)
            for field_name in opts.fields.keys():
                def_lang_fieldname = build_localized_fieldname(field_name, DEFAULT_LANGUAGE)

                # We'll only update fields which do not have an existing value
                q = Q(**{def_lang_fieldname: None})
                field = model._meta.get_field(field_name)
                if field.empty_strings_allowed:
                    q |= Q(**{def_lang_fieldname: ""})

                model._default_manager.filter(q).rewrite(False).update(
                    **{def_lang_fieldname: F(field_name)})
Exemple #22
0
    def handle(self, *args, **options):
        """Handle the save_trans command."""
        filename_po = load_translation_settings(settings)

        locale_path = settings.MODELTRANSLATION_LOCALE_PATH
        if not isdir(locale_path):
            mkdir(locale_path)

        for lang in [l[0] for l in list(settings.LANGUAGES)]:

            catalog = Catalog(locale=lang)

            for model in translator.get_registered_models():
                opts = translator.get_options_for_model(model)

                for field in opts.get_field_names():
                    tr_field = "%s_%s" % (field, lang)
                    en_field = "%s_%s" % (field, "en")
                    for item in model.objects.all():
                        msgid = "%s.%s.%s" % (item._meta, item.pk, field)
                        msgstr = "%s" % getattr(item, tr_field)
                        enval = getattr(item, en_field)
                        if enval is not None and field not in [
                                "slug", "url_path"
                        ]:
                            enstr = json.dumps(enval.stream_data) if hasattr(
                                enval, "stream_data") else "%s" % enval
                            catalog.add(id=enstr,
                                        string=msgstr,
                                        auto_comments=[
                                            msgid,
                                        ])

            # write catalog to file
            lang_path = join(locale_path, lang)
            if not isdir(lang_path):
                mkdir(lang_path)
                mkdir(join(lang_path, "LC_MESSAGES"))
            po_file = open(join(lang_path, "LC_MESSAGES", filename_po), "wb")
            write_po(po_file, catalog)
            po_file.close()
Exemple #23
0
def translated_field_list(*args):
    """
    Generates a dictionary of translatable model fields associated with the model.

    Models and fields can be specified in `args`, thus allowing for export even before
    fields are set up as translatable. If none are provided, then modeltranslation's
    `translator` instance is queried for the list of *all* models and fields that are
    registered for translation.

    Args:
        *args: optional list of fields by dotted string path

    Returns:
        a defaultdict mapping translation models to translated field names

    """
    class_and_field = OrderedDict()

    if not args:
        from modeltranslation.translator import translator
        for model_class in translator.get_registered_models(abstract=False):
            class_and_field[model_class] = translator.get_options_for_model(
                model_class).get_field_names()
        return class_and_field

    for dotted_path in args:
        module_name, class_name, field_name = dotted_path.rsplit(".", 2)

        module = importlib.import_module(module_name)

        try:
            model_class = getattr(module, class_name)
        except AttributeError:
            model_class = apps.get_model(module_name, class_name)

        try:
            class_and_field[model_class].append(field_name)
        except KeyError:
            class_and_field[model_class] = [field_name]

    return class_and_field
    def handle(self, *args, **options):
        """
        Command execution.
        """
        self.cursor = connection.cursor()
        self.introspection = connection.introspection
        self.interactive = options['interactive']

        found_missing_fields = False
        models = translator.get_registered_models(abstract=False)
        for model in models:
            db_table = model._meta.db_table
            model_name = model._meta.model_name
            model_full_name = '%s.%s' % (model._meta.app_label, model_name)
            opts = translator.get_options_for_model(model)
            for field_name, fields in opts.local_fields.items():
                # Take `db_column` attribute into account
                try:
                    field = list(fields)[0]
                except IndexError:
                    # Ignore IndexError for ProxyModel
                    # maybe there is better way to handle this
                    continue
                column_name = field.db_column if field.db_column else field_name
                missing_langs = list(self.get_missing_languages(column_name, db_table))
                if missing_langs:
                    found_missing_fields = True
                    print_missing_langs(missing_langs, field_name, model_full_name)
                    sql_sentences = self.get_sync_sql(field_name, missing_langs, model)
                    execute_sql = ask_for_confirmation(
                        sql_sentences, model_full_name, self.interactive)
                    if execute_sql:
                        print('Executing SQL...')
                        for sentence in sql_sentences:
                            self.cursor.execute(sentence)
                        print('Done')
                    else:
                        print('SQL not executed')

        if not found_missing_fields:
            print('No new translatable fields detected')
    def handle(self, *args, **options):
        """Handle the save_trans command."""
        filename_po = load_translation_settings(settings)

        locale_path = settings.MODELTRANSLATION_LOCALE_PATH
        if not isdir(locale_path):
            mkdir(locale_path)

        for lang in [lang_tup[0] for lang_tup in list(settings.LANGUAGES)]:

            word_count = 0

            lang_path = join(locale_path, lang)
            if not isdir(lang_path):
                mkdir(lang_path)
                mkdir(join(lang_path, "LC_MESSAGES"))

            po_filepath = join(lang_path, "LC_MESSAGES", filename_po)
            existing_ids = []
            existing_trans = {}
            if exists(po_filepath):
                print(po_filepath)
                po_file = open(po_filepath, "r", encoding="utf-8")
                catalog = read_po(po_file)
                po_file.close()
                for message in catalog:
                    existing_ids.append(message.id)
                    for auto_comment in message.auto_comments:
                        existing_trans[auto_comment] = message.id
            else:
                catalog = Catalog(locale=lang)

            for model in translator.get_registered_models():
                if model not in EXCLUDE_MODELS:
                    opts = translator.get_options_for_model(model)

                    for field in opts.get_field_names():
                        tr_field = "%s_%s" % (field, lang)
                        en_field = "%s_%s" % (field, "en")
                        for item in model.objects.all():
                            if hasattr(item, "specific") and isinstance(item.specific, EXCLUDE_MODELS):
                                continue
                            msgid = "%s.%s.%s" % (item._meta, item.pk, field)
                            msgval = getattr(item, tr_field)
                            enval = getattr(item, en_field)
                            if isinstance(msgval, StreamValue):
                                msgstr = json.dumps(list(msgval.raw_data))
                            else:
                                msgstr = "%s" % msgval
                            if enval is not None and field not in ["slug", "url_path"]:
                                if isinstance(enval, StreamValue):
                                    enstr = json.dumps(list(enval.raw_data))
                                else:
                                    enstr = "%s" % enval
                                # We already have a translation, just add the new comment to pick it up
                                if enstr in existing_ids:
                                    catalog.add(id=enstr, string=msgstr, auto_comments=[msgid, ])
                                # We don't have an exact translation, but we've translated the page before
                                elif msgid in existing_trans.keys():
                                    # If it's JSON, the dumped strings might not match, but the objs can
                                    if isinstance(enval, StreamValue):
                                        new_json = json.loads(enstr)
                                        old_json = json.loads(existing_trans[msgid])
                                        # If it doesn't match, delete the old and re-add with a blank translation so the vendor knows it needs re-translation. If it does match, do nothing
                                        if new_json != old_json:
                                            catalog.delete(id=existing_trans[msgid])
                                            catalog.add(id=enstr, string="", auto_comments=[msgid, ])
                                            word_count += len(enstr.split())
                                    # If it's not JSON, just add it. We can't delete because can't guarantee it's not reused later
                                    else:
                                        catalog.add(id=enstr, string=msgstr, auto_comments=[msgid, ])
                                        word_count += len(enstr.split())
                                # If we don't have a translation, and it's not in a previously translated page, it's brand new
                                else:
                                    catalog.add(id=enstr, string=msgstr, auto_comments=[msgid, ])
                                    word_count += len(enstr.split())
            # write catalog to file
            po_file = open(po_filepath, "wb")
            write_po(po_file, catalog, width=None)
            po_file.close()
            # write copy to default_storage
            stream_str = io.BytesIO()
            write_po(stream_str, catalog, width=None)
            output_path = join("po_files", lang, filename_po)
            output_dir = dirname(output_path)
            if not isdir(output_dir):
                makedirs(output_dir)
            if default_storage.exists(output_path):
                default_storage.delete(output_path)
            default_storage.save(output_path, ContentFile(stream_str.getvalue()))
            print("New {} word count: {}".format(lang, word_count))
    def handle_noargs(self, **options):
        verbosity = int(options['verbosity'])
        if verbosity > 0:
            self.stdout.write(
                "Using default language: %s\n" % DEFAULT_LANGUAGE)
        models = translator.get_registered_models(abstract=False)
        for model in models:
            if verbosity > 0:
                self.stdout.write("Updating data of model '%s'\n" % model)
            opts = translator.get_options_for_model(model)
            for field_name in opts.fields.keys():
                def_lang_fieldname = build_localized_fieldname(
                    field_name, DEFAULT_LANGUAGE)

                # We'll only update fields which do not have an existing value
                q = Q(**{def_lang_fieldname: None})
                field = model._meta.get_field(field_name)
                if field.empty_strings_allowed:
                    q |= Q(**{def_lang_fieldname: ''})

                if issubclass(model, Page):
                    for obj in model._default_manager.filter(q):
                        # Get table description in order to know if field is
                        # in child or parent table
                        # TODO: Tested only on PostgreSQL engine
                        db_table = model._meta.db_table
                        db_table_desc = connection.introspection. \
                            get_table_description(
                            connection.cursor(), db_table)
                        # original field in child class
                        if field_name in [x.name for x in db_table_desc]:
                            raw = model._default_manager.raw(
                                'SELECT *, %s AS original_field FROM %s \
                                 WHERE page_ptr_id=%d LIMIT 1' % (
                                    field_name, db_table, obj.page_ptr_id))[0]
                            setattr(
                                obj, def_lang_fieldname, raw.original_field)
                        # field is a foreign key
                        elif (field_name + '_id') in \
                                [x.name for x in db_table_desc]:
                            raw = model._default_manager.raw(
                                'SELECT *, %s AS original_field FROM %s \
                                 WHERE page_ptr_id=%d LIMIT 1' % (
                                    field_name + '_id',
                                    db_table,
                                    obj.page_ptr_id))[0]
                            setattr(
                                obj,
                                def_lang_fieldname + '_id',
                                raw.original_field)
                        # original field parent class
                        else:
                            raw = Page._default_manager.raw(
                                'SELECT *, %s AS original_field FROM \
                                 wagtailcore_page WHERE id=%d LIMIT 1' % (
                                    field_name, obj.page_ptr_id))[0]
                            setattr(
                                obj, def_lang_fieldname, raw.original_field)
                        obj.save(update_fields=[def_lang_fieldname])
                else:
                    model._default_manager.filter(q).rewrite(False).update(
                        **{def_lang_fieldname: F(field_name)})
Exemple #27
0
class TranslationAdmin(TranslationAdminMixin, O_TranslationAdmin):
    TRANSLATION_REGISTERED_MODELS = set(
        translator.get_registered_models(abstract=False))

    def get_url_namespace(self, name, absolute=True):
        meta = self.model._meta
        namespace = f'{meta.app_label}_{meta.model_name}_{name}'
        return f'admin:{namespace}' if absolute else namespace

    def get_additional_addlinks(self, request):
        url = reverse(self.get_url_namespace(
            'toggle_edit_all_language')) + f'?next={request.get_full_path()}'
        label = ugettext(
            'hide all language') if self._go__show_all_language_in_form(
            ) else ugettext('show all language')
        return [{'url': url, 'label': label}]

    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context['additional_addlinks'] = extra_context.get(
            'additional_addlinks') or []
        # extra_context['additional_addlinks'].extend(self.get_additional_addlinks(request))
        return super().change_view(request,
                                   object_id,
                                   form_url,
                                   extra_context=extra_context)

    def add_view(self, request, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context['additional_addlinks'] = extra_context.get(
            'additional_addlinks') or []
        # extra_context['additional_addlinks'].extend(self.get_additional_addlinks(request))
        return super().add_view(request, form_url, extra_context=extra_context)

    def get_urls(self):
        return [
            path('toggle-edit-all-language/',
                 self.admin_site.admin_view(self.toggle_edit_all_language),
                 name=self.get_url_namespace('toggle_edit_all_language',
                                             False)),
        ] + super().get_urls()

    def toggle_edit_all_language(self, request):
        request.session[
            self.
            SHOW_ALL_LANGUAGE_TOGGLE_SESSION_NAME] = not request.session.get(
                self.SHOW_ALL_LANGUAGE_TOGGLE_SESSION_NAME, False)
        return redirect(request.GET.get('next'))

    def save_model(self, request, obj, form, change):
        # To trigger translate
        super().save_model(request, obj, form, change)
        TranslatedModelSerializerMixin.trigger_field_translation(obj)

    def save_formset(self, request, form, formset, change):
        # To trigger translate for inline models
        instances = formset.save()
        if instances and formset.model in self.TRANSLATION_REGISTERED_MODELS:
            TranslatedModelSerializerMixin.trigger_field_translation_in_bulk(
                formset.model, instances)

    def get_search_fields(self, request):
        # Ex. 'name' is translatable - add 'name_fr', 'name_es', etc
        concated_search = (
            list(self.search_fields) +
            TranslatedModelSerializerMixin._get_translated_searchfields_list(
                self.model, self.search_fields))
        return concated_search
    def handle(self, *args, **options):
        """Handle the save_trans command."""
        filename_po = load_translation_settings(settings)

        locale_path = settings.MODELTRANSLATION_LOCALE_PATH
        if not isdir(locale_path):
            mkdir(locale_path)

        for lang in [l[0] for l in list(settings.LANGUAGES)]:

            word_count = 0

            lang_path = join(locale_path, lang)
            if not isdir(lang_path):
                mkdir(lang_path)
                mkdir(join(lang_path, "LC_MESSAGES"))

            po_filepath = join(lang_path, "LC_MESSAGES", filename_po)
            existing_ids = []
            existing_trans = {}
            if exists(po_filepath):
                po_file = open(po_filepath, "r")
                catalog = read_po(po_file)
                po_file.close()
                for message in catalog:
                    existing_ids.append(message.id)
                    for auto_comment in message.auto_comments:
                        existing_trans[auto_comment] = message.id
            else:
                catalog = Catalog(locale=lang)

            for model in translator.get_registered_models():
                opts = translator.get_options_for_model(model)

                for field in opts.get_field_names():
                    tr_field = "%s_%s" % (field, lang)
                    en_field = "%s_%s" % (field, "en")
                    for item in model.objects.all():
                        msgid = "%s.%s.%s" % (item._meta, item.pk, field)
                        msgstr = "%s" % getattr(item, tr_field)
                        enval = getattr(item, en_field)
                        if enval is not None and field not in [
                                "slug", "url_path"
                        ]:
                            enstr = json.dumps(enval.stream_data) if hasattr(
                                enval, "stream_data") else "%s" % enval
                            # We already have a translation, just add the new comment to pick it up
                            if enstr in existing_ids:
                                catalog.add(id=enstr,
                                            string=msgstr,
                                            auto_comments=[
                                                msgid,
                                            ])
                            # We don't have an exact translation, but we've translated the page before
                            elif msgid in existing_trans.keys():
                                # If it's JSON, the dumped strings might not match, but the objs can
                                if hasattr(enval, "stream_data"):
                                    new_json = json.loads(enstr)
                                    old_json = json.loads(
                                        existing_trans[msgid])
                                    # If it doesn't match, delete the old and readd. If it does match, do nothing
                                    if new_json != old_json:
                                        catalog.delete(
                                            id=existing_trans[msgid])
                                        catalog.add(id=enstr,
                                                    string=msgstr,
                                                    auto_comments=[
                                                        msgid,
                                                    ])
                                        word_count += len(enstr.split())
                                # If it's not JSON, just add it. We can't delete because can't guarantee it's not reused later
                                else:
                                    catalog.add(id=enstr,
                                                string=msgstr,
                                                auto_comments=[
                                                    msgid,
                                                ])
                                    word_count += len(enstr.split())
                            # If we don't have a translation, and it's not in a previously translated page, it's brand new
                            else:
                                catalog.add(id=enstr,
                                            string=msgstr,
                                            auto_comments=[
                                                msgid,
                                            ])
                                word_count += len(enstr.split())
            # write catalog to file
            po_file = open(po_filepath, "wb")
            write_po(po_file, catalog, width=None)
            po_file.close()
            print("New {} word count: {}".format(lang, word_count))
Exemple #29
0
 def get_translatable_models(cls):
     # return all models excluding proxy- and not managed models
     return [
         m for m in translator.get_registered_models(abstract=False)
         if not m._meta.proxy and m._meta.managed
     ]
Exemple #30
0
    def apply_po_file(self, po: polib.POFile, fix_empty_db_strings=False):
        string_entries = {}
        model_entries = {}
        for entry in po:
            for kind, identity in entry.occurrences:
                if kind == 'strings':
                    string_entries[entry.msgid] = (entry.msgid, entry.msgstr)
                else:
                    model_entries['{}:{}'.format(kind,
                                                 identity)] = (entry.msgid,
                                                               entry.msgstr)

        lang = po.metadata['Language']

        strings_updated = 0
        for key, val in string_entries.items():
            for obj in StringTranslation.objects.filter(key=key):
                localized_fieldname = build_localized_fieldname(
                    'translation', lang)

                msgid, msgstr = string_entries[key]

                if not msgstr:
                    if fix_empty_db_strings:
                        msgstr = msgid
                    else:
                        continue

                if getattr(obj, localized_fieldname) != msgstr:
                    setattr(obj, localized_fieldname, msgstr)
                    strings_updated += 1
                    obj.save()

        models = translator.get_registered_models(abstract=False)

        model_entries_updated = 0
        for model in models:
            if model is StringTranslation:
                continue
            opts = translator.get_options_for_model(model)

            fields_to_copy = []
            for field_name in opts.fields.keys():
                fields_to_copy.append(
                    (field_name, build_localized_fieldname(field_name, lang)))

            for obj in model.objects.all():
                model_updated = False
                for field_name, field_name_local in fields_to_copy:
                    key = '{}:{}:{}'.format(get_model_ct(model), field_name,
                                            obj.id)

                    if key in model_entries:
                        localized_fieldname = build_localized_fieldname(
                            field_name, lang)

                        msgid, msgstr = model_entries[key]

                        if not msgstr:
                            if fix_empty_db_strings:
                                msgstr = msgid
                            else:
                                continue

                        if getattr(obj, localized_fieldname) != msgstr:
                            setattr(obj, localized_fieldname, msgstr)
                            model_updated = True
                            model_entries_updated += 1

                if model_updated:
                    obj.save()

        return {
            'lang': lang,
            'strings_updated': strings_updated,
            'model_entries_updated': model_entries_updated,
        }