i18n Django Интернационализация и объекты базы данных - PullRequest
5 голосов
/ 06 сентября 2010

Я работаю в двуязычном проекте (es / en);для этого проекта я решил использовать систему интернационализации django i18n (и я начинаю сожалеть об этом ...)

Сегодняшняя проблема заключается в следующем:
для некоторых моделей моя база данных хранит такую ​​информацию, какdescription и es_description, или english_common_name и spanish_common_name (это атрибуты моих объектов и используются во многих случаях, не только для проблем перевода страниц) .

Пример модели можно определить следующим образом:

def MyModel(models.Model):
    name = ...
    type = ...
    authors = ...
    contributors = ...
    ...
    ...
    description = models.TextField(max_length = 800, blank=True)
    es_description = models.TextField(max_length = 800, blank=True)
    ...
    english_common_name = models.CharField('name', max_length=80, unique=True)
    spanish_common_name = models.CharField('nombre', max_length=80, unique=True)
    ...




Допустим, я хочу получить эту информацию в моем шаблоне в соответствии с lang, язык, выбранный пользователем.

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

<h1>{{name}}</h1>
<h3>{{english_common_name}}</h3>
<p>{{description}}</p>
<p>{% trans "Contributors" %}: {{contributors}}</p>

Как я могу позвонить {{spanish_common_name}} вместо {{english_common_name}} или {{es_description}} вместо {{description}}, если для языка страницы установлено значение 'es'?

Я абсолютно отказываюсь делать что-то вроде

<p>{% ifequal lang 'es' %}{{descrpition}}{% else %}{{es_description}}{% endifequal %}</p>

И если я попытаюсь управлять этим в представлениях ... Я не хочу определять get_translated_content функцию, подобную этой

def get_translated_content(en_content,es_content,lang):
    if lang is 'es':
        return es_content
    else:
        return en_content

...
# MyView
...
    return render_to_response(...,
                              {'object': my_object,
                               'object_common_name': get_translated_content(english_common_name, spanish_common_name, lang),
                               'object_description': get_translated_content(description, es_description, lang), 
                                ... ,})

Это может работать (все еще ужасное решение) в простых ситуациях, но в более сложных случаях я был бы вынужден возвращать словари, которые являются локализованными копиями исходного MyModel объекта (и если в представлении мне приходится использовать множество различных экземпляровта же модель, я был бы вынужден сгенерировать biiiig список этих словарей).

Пожалуйста, скажите мне, что есть хороший, логичный способ доступа к объектным полям БД в соответствии с языком страницы, пожалуйста!

Редактировать: после прочтения полученных ответов, я думаю, что я должен добавить к своему вопросу ", оставив структуру базы данных (почти) без изменений ".

Ответы [ 4 ]

5 голосов
/ 07 сентября 2010

Вы действительно должны использовать что-то вроде django-многоязычный (если вы используете Django 1.2, см. Django 1.2-совместимая ветка ).

Для вашего примера (на основе документации )

from django.db import models
from django.utils.translation import ugettext_lazy as _
from multilingual.translation import TranslationModel

class MyModel(models.Model):
    name = ...
    type = ...
    authors = ...
    contributors = ...
    ...
    ...
    class Translation(TranslationModel):
        description = models.TextField(max_length = 800, blank=True)
        ...
        common_name = models.CharField(_(u'name'), max_length=80, unique=True)
        ...

Доступ к переводимым полям

my_model = MyModel.objects.get(id=1)
my_model.description # the description in the current language
my_model.common_name # the common name in the current language
my_model.name # the name

Текущий язык определяется так же, как его обнаруживает django.

4 голосов
/ 14 февраля 2011

Вы можете написать пользовательский шаблонный тег , который, в основном, делает

{% ifequal lang 'es' %}{{descrpition}}{% else %}{{es_description}}{% endifequal %}

, но не настолько уродлив:шаблон по

{% get_lang obj common_name lang %}
1 голос
/ 02 марта 2019

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

Лучший выбор в 2019 году (ИМХО) : django-modeltranslation

После некоторых копаний и бенчмаркинга вот что (лично) я рекомендую для недавних проектов Django:

https://django -modeltranslation.readthedocs.io

Подходит для проблем ОП : оставить модели без изменений и обработать существующие поля БД I18n.

Случай OP является частным случаем, поскольку БД уже содержит некоторые поля перевода (которые нужно будет как-то перенести), в отличие от моей собственной настройки, которая начинается с нуля.

Но библиотека также решает эту проблему, см. https://django -modeltranslation.readthedocs.io / en / latest / commands.html # the-update-translation-fields-command

Официальные функции

  • Добавление переводов без изменения существующих моделей или видов
  • Поля перевода хранятся в одной таблице (без дорогих объединений)
  • Поддерживает унаследованные модели (абстрактное и многостоловое наследование)
  • Обработка не только текстовых полей Интеграция с администратором Django Гибкая запасные варианты, автопопуляция и многое другое!

Сравнение библиотек

Я быстро сравнил следующие библиотеки:

Я нашел эту таблицу сравнения, которая помогла мне найти django-modeltranslation (что является наиболее популярным) : https://djangopackages.org/grids/g/i18n/


Другие хорошие ресурсы

Обратите внимание, что https://github.com/WeblateOrg/weblate также довольно популярен, но не решает проблему с OP. И все же это выглядит очень интересно!

Кроме того, https://django -modeltranslation.readthedocs.io / en / latest / related_projects.html перечисляет несколько других проектов, но большинство выглядит либо похожими, либо недостаточно зрелыми.

1 голос
/ 07 сентября 2010

Если еще не слишком поздно, вы можете пересмотреть свою модель данных, чтобы смоделировать отношения «один ко многим» между основными сущностями и их языковыми представлениями.Таким образом, ваша модель более нормализована - вы не включаете метаданные в имена полей - и вам будет легче с ней работать.

Что-то вроде:

class MyModel(models.Model):
    // fields that don't need translating go here
    name = ...
    type = ...

class MyModelTranslation(models.Model):
    // fields that do need translating go here
    language = models.CharField(...)
    description = models.TextField(...)
    common_name = models.TextField(...)
    parent = models.ForeignKey('MyModel', related_name="translations")

    // TODO: enforce uniqueness for any given parent/language tuple

Тогдана ваш взгляд вы можете сделать что-то вроде:

// Get the user's chosen language, default to 'en'
lang = request.session.get('django_language', 'en')


obj = MyModel.objects.get(...)
object_text = obj.translations.filter(language__exact=lang)[0]

return render_to_response(...,
{
    'object': obj,
    'object_common_name': object_text.common_name,
    'object_description': object_text.description,
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...