Многоязычные модели Django для начинающих

    Вводная


    Работаю я, как и все адекватные программисты, над социальным порталом который покорит всех от грудничков до маразматиков. И так как цели наполеоновские — нужно учесть возможность использования сервиса даже теми представителями человечества, которые не владеют великим и могучим. Знаю, что многие долго боролись с вопросом локализации именно контента (перевод отдельных полей модели на разные языки), т.к. локализация интерфейса, в пределах общепринятых, в Django решена. Суть проблемы в том, чтобы одна и та же модель (это важно! к примеру пункты единого для всех языков каталога) имела переводы своих полей на разные языки. Те кто давно «на игле» этого фреймворка уже наверняка нашли для себя наиболее подходящую методу решения этой проблемы, я же хочу предложить способ решения и набросать порядок действий для начинающих, чтобы они не сбежали по рельсам на рубиновые копи.

    Отмазка


    Совсем недавно мне подвернулся счастливый случай начать превращение из личинки-PHP'шника в жука-Python'оида. Так что сразу ногами не бейте. Эта заметка (не статья) представляет из себя HowTo для таких же начинающих.

    Используемые материалы


    Для локализации моделей мы будем использовать приложение для Django — django-modeltranslation. Я выбрал именно его среди прочих по следующим причинам:
    • работает с Django 1.3
    • добавляет переводимые поля для языков в ту же таблицу, т.е. не будет лишних JOIN'ов
    • не требует внесения никакого кода в уже существующие модели
    • почти безболезненно включается и отключается
    • в админке локализованная модель интегрируется с другими модулями (меня волновал mptt)

    Ещё понадобится South — установленный и работающий.
    Собственно всё (не считая рабочего/разрабатываемого сайта на django).

    HowTo


    Устанавливаем modeltranslation командой pip install django-modeltranslation.

    Или качаем последнюю версию django-modeltranslation. Распаковываем, заходим в распакованный каталог и устанавливаем python setup.py install. Можно сразу из распакованного каталога руками закинуть в папку для статических файлов директорию modeltranslation/static/modeltranslation.

    Далее работаем уже с нашим проектом

    Добавляем 'modeltranslation' в INSTALLED_APPS файла настроек settings.py.

    В тот же файл добавляем описание необходимых локализаций, язык по-умолчанию и импортируемый файл регистрации локализуемых моделей. В последнем MYPROJECT — нужно заменить на имя вашего проекта (оно же имя папки в которой он размещается), а translation — на имя самого .py файла без расширения, по умолчанию это translation.py. Этот файл один на весь проект и кладётся, соответственно, в корень проекта.

    LANGUAGES = (
        ('ru', 'Russian'),
        ('en', 'English'),
    )
    
    MODELTRANSLATION_DEFAULT_LANGUAGE = 'ru'
    MODELTRANSLATION_TRANSLATION_REGISTRY = 'MYPROJECT.translation'
    


    В этом самом файле нам нужно создать классы содержащие указание какие поля (здесь это 'name' и 'description') нужно переводить и привязать эти классы к переводимым моделям (здесь это 'Modelka') Ваших приложений (здесь это 'app') сответствтенно:

    # -*- coding: utf-8 -*-
    
    from modeltranslation.translator import translator, TranslationOptions
    from app.models import Modelka
    
    
    class ModelkaTranslationOptions(TranslationOptions):
        """
        Класс настроек интернационализации полей модели Modelka.
        """
        
        fields = ('name', 'description',)
    
    translator.register(Modelka, ModelkaTranslationOptions)
    


    В этом месте можно сгенерировать миграцию python manage.py schemamigration app --auto.

    South обнаружит новые поля для локализации и сгенерирует миграцию для их добавления. К слову если отключить приложение 'modeltranslation' — то также можно сгенерировать и миграцию для их удаления. Кроме того отдельное удобство в том, что modeltranslation привязывает язык по-умолчанию к оригинальным полям модели, т.е. это поле локализации и переводимое оригинальное поле модели будут идентичны.

    Не забудьте потом применить миграцию: python manage.py migrate app.

    И, наконец, настраиваем админку.

    Очень важно чтобы админка описывалась в отдельном файле admin.py для каждого приложения!!! А не в файле моделей, как, признаюсь честно, по-началу пытался сделать я.

    Для образца сразу приведу пример использования локализованной админки с админкой mptt:

    # -*- coding: utf-8 -*-
    
    from django.contrib import admin
    from mptt.admin import MPTTModelAdmin
    from modeltranslation.admin import TranslationAdmin
    from models import Modelka
    
    class ModelkaAdmin(MPTTModelAdmin, TranslationAdmin):
        """
        Настройка админки для Modelka.
        """
        
        list_display = ('name',)
    
        class Media:
            js = (
                '/static/modeltranslation/js/force_jquery.js',
                'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js',
                '/static/modeltranslation/js/tabbed_translation_fields.js',
            )
            css = {
                'screen': ('/static/modeltranslation/css/tabbed_translation_fields.css',),
            }
    
        fieldsets = [
            (None, {
                'fields': [
                    'name',
                    'slug',
                    'type',
                    'description',
                    'parent',
                ]
            }),
            (u'Лог', {
                'fields': [
                    'author',
                    'editor',
                ],
                'classes': ['collapse']
            })
        ]
    
    
    admin.site.register(Modelka, ModelkaAdmin)
    


    Обращаю Ваше внимание, что в примере сразу же включены скрипты для отображения переводов на разных вкладках. Это как раз те файлы которые я в начале предлагал скопировать в каталог для статического контента. Если Вы установили modeltranslation через pip — не забудьте собрать статические фалы командой python manage.py collectstatic (подробнее о статических файлах). Соответсвенно не забудьте подправить пути во вложенном Meta классе, если они у Вас отличаются.



    На скриншоте видны вкладки языков для переводимых полей модели (скриншот с разрабатываемого приложения, потому языков больше чем в примере)

    Работа с локализованной моделью

    Собственно сама работа абсолютно прозрачна и также не затрагивает уже существующий код (наилучший язык отображения сайта может определяться как самим фреймворком, так и сторонними модулями, но это отдельная тема), если не понадобится где-то руками объявлять используемый язык через set_language. Т.е. модель будет возвращать значения полей на текущем языке приложения возвращаемом get_lang.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 28

      –5
      Что вы все возитесь с этими соц. порталами/сетями, это не ново, нужно двигаться дальше.
        0
        Спрошу тут, может кто путное подскажет:
        сейчас пишу систему и вот вот подойду к поиску, хочется использовать haystack + xapian по ряду причин,
        но контент у меня мультиязычен (используется этот самый modeltranslation)
        предварительно протестировав как-то я ума не приложу как разделить индексы по языкам… пока языков 2, в перспективе будет больше, по всем языкам нужно искать отдельно (т.е. один мешаный индекс не канает).
        Может есть у кого саксес стори или какой опыт в вопросе?
        (в гугле не забанен, но таки ничего внятного не нашлось)
          0
          а haystack второй не поможет? там вроде как поддержка нескольких индексов одновременно есть
            0
            Да я читал где-то, но 2.0 в стадии альфы, что там у него со стабильностью и насколько будет меняться апи?
              0
              Вы меня об этом спрашиваете?) Если «стабильность» — это отсутствие багов, то, думаю, с ней примерно так же, как и в 1.2.4. Баги могут быть, но и без «альфа» они могут быть. Насчет API — API у фиксированного коммита из репозитория меняться не будет) Если там есть нужная фича, то брать и использовать, делать-то что. Ставьте версию из репозитория и вперед, если что-то не так — обновляетесь до последней ревизии, правите и pull request. По опыту, «житье» на последних ревизиях софта с учетом того, что что-то, возможно, придется поправить — вполне рабочий подход, да и код, который используешь, в любом случае читать полезно (для маленьких штук — всегда весь читаю, вдруг там фигня какая-то, для больших — основной хотя бы). В проекте сейчас где-то 80 сторонних пакетов используется, из них десяток — это фиксированные ревизии из репозиториев на битбакете и гитхабе — для тех, где есть незарелизенные багфиксы или улучшения какие-то, важные для конкретного проекта.
            0
            > как разделить индексы по языкам
            Если для каждого языка исплользуется отдельное поле в модели, то созадавайт на каждое поле отдельный индекс. В чём именно проблема?
              0
              Проблема «то созадавайт на каждое поле отдельный индекс»…
                0
                Что вам мешает создавать эти индексы?
                  0
                  каким образом это можно сделать гибко и не костыляво?
            +3
            Качаем последнюю версию django-modeltranslation.

            Распаковываем, заходим в распакованный каталог и устанавливаем python setup.py install.

            Можно сразу из распакованного каталога руками закинуть в папку для статических файлов директорию modeltranslation/static/modeltranslation.


            Лучше ставить через pip и использовать django.contrib.staticfiles.
              +2
              И использовать virtualenv
                +1
                Это вопрос не относящийся к теме HowTo. Можно много разных нюансов придумать и написать несколько томов в результате. Моя цель была написать небольшое конкретное HowTo которого хватило бы лично мне в тот момент когда я начал искать решение проблем мультиязычности моделей в django.
                0
                возможно у меня криво поставлен pip или как-то не настроен, но он не знает такого модуля.
                  +1
                  А быть может в вашу строку «pip install django-modeltranslation» просто закралась ошибка?
                    0
                    это, конечно, тоже не исключено :)
                      0
                      и правда, работает. поправил в howto
                    +1
                    pip сработал, поправил заметку согласно Вашему совету. спасибо!
                    –1
                    > Работаю я, как и все адекватные программисты, над социальным порталом который покорит…

                    Кхм… не хочу ничего сказать плохого про вёб-кодеров, но это уж как-то чересчур. Программисты-системщики смотрят на вас с укоризной.
                      +3
                      Я думаю, программисты-системщики смотрят без укора т.к. у них с чувством юмора всё в порядке :)
                        –2
                        Как-то не чувствуется юмора в том абзаце) Впрочем, я не настаиваю. Может и правда я туплю)
                          +1
                          а как же «от грудничков до маразматиков»?
                            0
                            Не, тоже не подействовало)

                            Наверное, надо или работать меньше, или спать больше. В общем, что-то из этого.
                      0
                      В примере админки используется функция _l — откуда она взялась?
                        0
                        И ещё в статье скриншота админки не хватает.
                          +1
                          добавил
                          +1
                          прошу прощения, копировал из рабочего кода забыл убрать. сейчас исправлю.
                          0
                          сейчас мне сольют карму, но зачем каждый новичек пишет туториалы??
                            0
                            может потому, что они им нужны, а старички их писать не хотят?

                          Only users with full accounts can post comments. Log in, please.