I'm trying to use Django-ModelTranslation (0.12.2) to provide translation fields for products in Django-Oscar (1.5.2). It uses Django 1.10.8. I followed the documentation on Registering Models for Translation but keep getting this in response: No new translatable fields detected
.
I don't know if this might be part of the problem but I first started a Mezzanine (4.2.3) project and then integrated Oscar into it using Oscar's docs. Translation fields were added to Mezzanine perfectly. (EDIT: added Oscar with ModelTranslation to a new Django project, same response, so it's not Mezzanine.)
Below, I show how I forked Oscar's catalogue app and added it to settings.py.
project/settings.py:
from oscar import get_core_apps
# Django-ModelTranslation settings
USE_MODELTRANSLATION = True
MODELTRANSLATION_FALLBACK_LANGUAGES = ('en',)
LANGUAGES = (
('en', _('English')),
('de', _('German')),
)
INSTALLED_APPS = [
...,
] + get_core_apps(['forked_apps.catalogue'])
project/forked_apps/catalogue/translation.py:
from modeltranslation.translator import translator, TranslationOptions
from oscar.apps.catalogue.abstract_models import AbstractProduct
class AbstractProductTranslationOptions(TranslationOptions):
fields = ('title', 'description',)
translator.register(AbstractProduct, AbstractProductTranslationOptions)
I then ran sync_translation_fields
to no avail. What have I missed?
So, I pressed CTRL+SHIFT+R on PyCharm, entered the No new translatable fields detected
response into it and searched the ModelTranslation package for where it comes from. I found it in modeltranslation.management.commands.sync_translation_fields.Command. This is a class containing a handle() with this line: models = translator.get_registered_models(abstract=False)
.
I thought, ok, maybe it's not working because oscar.apps.catalogue.abstract_models.AbstractProduct has abstract=True
. I guess the dead giveaway is in the name of the module itself.
So, if it's not AbstractProduct, where's the right model? I decided to try triggering another error to figure it out. I overrode Oscar's abstract_models.AbstractProduct with my own in project.catalogue.abstract_models:
from django.db import models
from django.utils.translation import get_language, pgettext_lazy
from django.utils.translation import ugettext_lazy as _
from oscar.apps.catalogue.abstract_models import AbstractProduct
class AbstractProduct(AbstractProduct):
title = models.CharField(pgettext_lazy(u'Product title', u'Title'),
max_length=255, blank=True)
description = models.TextField(_('Description'), blank=True)
from oscar.apps.catalogue.models import *
It produced this error:
ERRORS:
catalogue.AbstractProduct.product_class: (fields.E304) Reverse accessor for 'AbstractProduct.product_class' clashes with reverse accessor for 'Product.product_class'.
...
It goes on for 20+ lines but the first was enough. The correct model was Product. So, I went hunting again and found it in oscar.apps.catalogue.models.Product. No surprise, it looked like this: Product(AbstractProduct)
.
Only two things left to do. First, I edited my translation.py in project.forked_apps.catalogue:
from modeltranslation.translator import register, translator, TranslationOptions
# DELETED: from oscar.apps.catalogue.abstract_models import AbstractProduct
from oscar.apps.catalogue.models import Product
# Updated the following accordingly.
class ProductTranslationOptions(TranslationOptions):
fields = ('title', 'description',)
translator.register(Product, ProductTranslationOptions)
Second, I ran python manage.py sync_translation_fields
. It worked!
Now, on to whatever the next problem is.