- 複数言語あるかもしれないのでフィールド追加ではなくリレーションモデルで保持させる
settings.py
- 持ちたい言語一覧を設定できるようにする
OTHER_LANGUAGE_CODES = ['en', ]
models.py
- 国際データを持ちたいモデルと、フィールドの一覧を指定して動的にモデルを定義する
I18N_LANG_CHOICES = tuple(
ln for ln in settings.LANGUAGES if ln[0] in settings.OTHER_LANGUAGE_CODES)
def i18n(cls, *field_names):
postfix = _('Translation')
meta = type(
'Meta', (object, ),
dict(
verbose_name="{} {}".format(cls._meta.verbose_name, postfix),
verbose_name_plural="{} {}".format(cls._meta.verbose_name_plural, postfix),
unique_together=(('original', 'lang',),),
)
)
fields = dict(
(name, cls._meta.get_field(name).clone()) for name in field_names)
fields['__module__'] = cls.__module__
fields['Meta'] = meta
fields['original'] = models.ForeignKey(
cls, verbose_name=cls._meta.verbose_name)
fields['lang'] = models.CharField(
_('Language'), choices=I18N_LANG_CHOICES, max_length=10)
return type(cls._meta.object_name + "Trans", (models.Model,), fields)
例
class Community(models.Model):
area = models.CharField(
_('Community Area'), max_length=10, null=True, default=None, blank=True,)
name = models.CharField( _('Community Name'), max_length=50,)
...
CommunityTrans = i18n(Community, 'area', 'name')
admin.py
- インラインで編集できるようにする
from django.utils.safestring import mark_safe as _S
from django import template
def _T(src, **ctx):
return _S(template.Template(src).render(template.Context(ctx)))
def _CHANGE(instance):
url = 'admin:{0}_change'.format(instance._meta.db_table)
return _T('''<a href="{% url u o.id %}">{{o}}</a>''', u=url, o=instance)
class TransAdmin(admin.ModelAdmin):
raw_id_fields = ('original', )
def original_link(self, obj):
return _CHANGE(obj.original)
original_link.short_description = _('Original Model')
original_link.allow_tags = True
class CommunityTransAdmin(TransAdmin):
pass
class CommunityTransAdminInline(admin.StackedInline):
model = models.CommunityTrans
extra = 0
class CommunityAdmin(admin.ModelAdmin):
inlines = [CommunityTransAdminInline, ]
...
テンプレートタグ
- 指定したモデルに Trans モデルがあったら、現在の言語で探す
- 見つかったら 指定されたフィールドの値を返す
- なかったら元のモデルのフィールドの値を返す
from django import template
from django.utils import translation
register = template.Library()
@register.simple_tag
def trans_field(instance, field_name):
lang = translation.get_language()
name = instance._meta.object_name + "Trans"
rels = [
r for r in instance._meta.get_all_related_objects()
if r.related_model._meta.object_name == name]
if rels and lang:
instance = rels[0].related_model.objects.filter(
original=instance, lang=lang).first() or instance
res = getattr(instance, field_name, None)
return res or ''
テンプレート
<a href="{{ community.get_absolute_url }}">{% trans_field community 'name' %}</a>