Beispiel #1
0
    def __new__(cls, name, bases, attrs):
        ### START - Build translation model
        # At first we build translation model so we can add it to attrs
        # Purpose is to not call 'add_to_class' after model is registered

        # We have to copy attributes because they change during creation of a model
        trans_attrs = attrs.copy()

        # Make a copy of Meta, so changes in it when creating a translation model does not affect
        # creation of multilingual model
        if attrs.has_key('Meta'):
            trans_attrs['Meta'] = classobj.__new__(classobj, 'Meta', (attrs['Meta'],), attrs['Meta'].__dict__.copy())

        translation_name = name + "Translation"
        trans_attrs['multilingual_model_name'] = name
        c_trans_model = TranslationModelBase(translation_name, (TranslationModel, ), trans_attrs)
        ### END - Build translation model

        ### And some changes before we build multilingual model
        meta = attrs.get('Meta', None)
        abstract = getattr(meta, 'abstract', False)

        # Add translation model to attrs
        attrs['translation_model'] = c_trans_model

        if not abstract:
            # Add translation relations
            for language_code in [None] + get_all():
                field = TranslationRelation(c_trans_model, base_name=TRANSLATION_FIELD_NAME,
                                            language_code=language_code)
                attrs[field.name] = field

            # Add proxies for translated fields into attrs
            for field in (c_trans_model._meta.fields + c_trans_model._meta.many_to_many):
                if field.name in ('id', 'language_code', 'master'):
                    continue
                for language_code in get_all():
                    proxy = TranslationProxyField(field.name, language_code)
                    attrs[proxy.name] = proxy
                proxy = TranslationProxyField(field.name, None)
                attrs[proxy.name] = proxy
                proxy = TranslationProxyField(field.name, None, fallback=True)
                attrs[proxy.name] = proxy

        # Handle manager
        if not 'objects' in attrs:
            # If there is no manager, set MultilingualManager as manager
            attrs['objects'] = MultilingualManager()
        elif not isinstance(attrs['objects'], MultilingualManager):
            # Make sure that if the class specifies objects then it is a subclass of our Manager.

            # Don't check other managers since someone might want to have a non-multilingual manager, but assigning
            # a non-multilingual manager to objects would be a common mistake.
            raise ValueError("Model %s specifies translations, so its 'objects' manager must be a subclass of "\
                             "multilingual.Manager." % name)

        # And now just create multilingual model
        return super(MultilingualModelBase, cls).__new__(cls, name, bases, attrs)
Beispiel #2
0
    def add_select_related(self, fields):
        """
        Sets up the select_related data structure so that we only select
        certain related models (as opposed to all models, when
        self.select_related=True).
        """
        new_fields = []
        opts = self.model._meta

        # There is not actually any useful code, all this is to handle deprecated arguments.
        for field_name in fields:
            if field_name.startswith('translations'):
                new_name = None

                if field_name == 'translations':
                    new_name = '%s_%s' % (TRANSLATION_FIELD_NAME, sanitize_language_code(get_active()))
                elif '_' in field_name:
                    dummy, language_code = field_name.rsplit('_', 1)
                    if language_code in get_all():
                        new_name = '%s_%s' % (TRANSLATION_FIELD_NAME, sanitize_language_code(language_code))

                if new_name:
                    msg = "Using '%s' in select_related is deprecated, use '%s' or '%s' instead."
                    warnings.warn(msg % (field_name, TRANSLATION_FIELD_NAME, new_name), DeprecationWarning)
                    new_fields.append(TRANSLATION_FIELD_NAME)
                    new_fields.append(new_name)
                    continue

            # In all other cases use the old name
            new_fields.append(field_name)

        new_fields = set(new_fields)
        return super(MultilingualQuery, self).add_select_related(new_fields)
    def add_select_related(self, fields):
        """
        If in fields is related_field for translations, will be replaced by fields in proper languages.
        """
        new_fields = []
        extra_select = {}
        opts = self.model._meta
        trans_opts = opts.translation_model._meta
        # TODO: fix this
        #related_name = trans_opts.related_name
        related_name = 'translations'

        translation_fields = [f.name for f in trans_opts.fields if f.name not in ('master', 'language_code')]

        for field in fields:
            # usual select_related
            if not field.startswith(related_name):
                new_fields.append(field)
                continue

            # get language
            if field == related_name:
                language_code = get_active()
            else:
                field_and_lang = field.rsplit('_', 1)
                # Coincidental field name might occur if language_code is not correct, do not do anything as 
                # select_related does not raise errors if used with incorrect fields
                if len(field_and_lang) != 2 or field_and_lang[1] not in get_all():
                    new_fields.append(field)
                    continue
                field, language_code = field_and_lang

            # This is main code of this method, build extra_select that might be used by fill_translation_cache
            for trans_field in translation_fields:
                extra_select[get_field_alias(trans_field, language_code)] = '%s.%s' % (
                    get_table_alias(trans_opts.db_table, language_code),
                    connection.ops.quote_name(trans_field)
                )

            # XXX: this is not safe if translation model has no fields, can it happen??

            # join translatable model (original) table if not joined yet
            alias = self.get_initial_alias()

            # join translation table if not joined yet
            translation_fields.remove(trans_opts.pk.name)
            self.setup_joins(
                ['%s_%s' % (translation_fields[0], language_code)], # any translated_field
                opts,
                alias,
                True,
                can_reuse = set([alias])
            )

        if extra_select:
            self.add_extra(extra_select, None, None, None, None, None)
        super(MultilingualQuery, self).add_select_related(new_fields)
def multilingual(request):
    """
    Returns context variables containing information about available languages.
    """
    codes = sorted(get_all())
    return {'ML_LANGUAGE': get_active(),
            # DEPRECATED context
            #TODO: LANGUAGE_CODES, LANGUAGE_CODES_AND_NAMES available in i18n context processor
            'LANGUAGE_CODES': codes,
            'LANGUAGE_CODES_AND_NAMES': get_dict(), 
            'DEFAULT_LANGUAGE_CODE': get_settings_default()}
    def __new__(cls, name, bases, attrs):
        ### START - Build translation model
        # At first we build translation model so we can add it to attrs
        # Purpose is to not call 'add_to_class' after model is registered

        # We have to copy attributes because they change during creation of a model
        trans_attrs = attrs.copy()

        # Make a copy of Meta, so changes in it when creating a translation model does not affect
        # creation of multilingual model
        if attrs.has_key("Meta"):
            trans_attrs["Meta"] = classobj.__new__(classobj, "Meta", (attrs["Meta"],), attrs["Meta"].__dict__.copy())

        translation_name = name + "Translation"
        trans_attrs["multilingual_model_name"] = name
        c_trans_model = TranslationModelBase(translation_name, (TranslationModel,), trans_attrs)
        ### END - Build translation model

        ### And some changes before we build multilingual model
        # Add translation model to attrs
        attrs["translation_model"] = c_trans_model

        # Add proxies for translated fields into attrs
        for field in c_trans_model._meta.fields:
            if field.name in ("id", "language_code", "master"):
                continue
            for language_code in get_all():
                proxy = TranslationProxyField(field.name, language_code)
                attrs[proxy.name] = proxy
            proxy = TranslationProxyField(field.name, None)
            attrs[proxy.name] = proxy
            proxy = TranslationProxyField(field.name, None, fallback=True)
            attrs[proxy.name] = proxy

            # Handle manager
        if not "objects" in attrs:
            # If there is no manager, set MultilingualManager as manager
            attrs["objects"] = MultilingualManager()
        elif not isinstance(attrs["objects"], MultilingualManager):
            # Make sure that if the class specifies objects then it is a subclass of our Manager.

            # Don't check other managers since someone might want to have a non-multilingual manager, but assigning
            # a non-multilingual manager to objects would be a common mistake.
            raise ValueError(
                "Model %s specifies translations, so its 'objects' manager must be a subclass of "
                "multilingual.Manager." % name
            )

            # And now just create multilingual model
        return super(MultilingualModelBase, cls).__new__(cls, name, bases, attrs)
def multilingual(request):
    """
    Returns context variables containing information about available languages.
    """
    codes = sorted(get_all())
    return {
        "ML_LANGUAGE": get_active(),
        # DEPRECATED context
        # TODO: LANGUAGE_CODES, LANGUAGE_CODES_AND_NAMES available in i18n context processor
        "LANGUAGE_CODES": codes,
        "LANGUAGE_CODES_AND_NAMES": get_dict(),
        "DEFAULT_LANGUAGE_CODE": get_settings_default(),
        "ADMIN_MEDIA_URL": settings.ADMIN_MEDIA_PREFIX,
    }
 def test01_basics(self):
     self.assertEqual(languages.get_dict(), SortedDict(self.LANGUAGES))
     self.assertEqual(languages.get_all(), ['cs', 'en', 'en-us'])
     self.assertEqual(languages.get_settings_default(), 'cs')
     self.assertEqual(languages.get_active(), 'cs')
 def test_get_all(self):
     self.assertEqual(languages.get_all(), ['cs', 'en', 'en-us', 'fr'])
 def test_basics(self):
     self.assertEqual(languages.get_dict(),
                      SortedDict((('cs', u'Čeština'), ('en', u'English'), ('en-us', u'American english'))))
     self.assertEqual(languages.get_all(), ['cs', 'en', 'en-us'])
     self.assertEqual(languages.get_settings_default(), 'cs')
     self.assertEqual(languages.get_active(), 'cs')