i18n Django国际化和数据库对象

时间:2010-09-06 19:57:31

标签: django django-models internationalization

我正在从事双语项目(es / en);对于这个项目,我选择使用django的i18n国际化系统(我开始后悔了......)

今天的问题如下:
对于某些模型,我的数据库存储descriptiones_description,或english_common_namespanish_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 个答案:

答案 0 :(得分:5)

你真的应该使用像django-multilingual这样的东西(如果你使用的是Django 1.2,请参阅Django 1.2 compatible branch)。

为您的示例(基于documentation

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检测到它的方式相同。

答案 1 :(得分:4)

你可以写一个custom template tag,基本上是

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

但没有那么难看:

def get_lang(object, property, lang):
    if lang=='en':
        return object.__getattribute__(property) # TODO: deal with AttributeError
    try: # assuming other lang is 'es'
        return object.__getattribute__("es_%s" % property) # try first option of spanish property
    except AttributeError: # try other option of spanish property
        return object.__getattribute__("spanish_%s" % property) # TODO: deal with AttributeError again.
    return ""

然后你可以通过

从模板中调用它
{% get_lang obj common_name lang %}

答案 2 :(得分:1)

如果还不晚,您可以考虑重新设计数据模型,以便模拟核心实体与其语言特定表示之间的一对多关系。这样你的模型就会更加规范化 - 你不会在你的字段名称中隐藏元数据 - 你会发现它更容易使用。

类似的东西:

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,
})

答案 3 :(得分:1)

  

我遇到了同样的问题,看到了您的帖子。但是,没有一个答案足以满足我的口味。 (并且因为这个问题很老,所以链接库也已经过时了)

2019年最佳选择(IMHO)django-modeltranslation

经过一些挖掘和基准测试之后,以下是我(个人)对最近的Django项目的建议:

https://django-modeltranslation.readthedocs.io

它适合OP的问题:保持模型不变,并处理现有的I18n DB字段。

OP情况是一个特殊的情况,因为数据库已经包含一些转换字段(需要以某种方式迁移),这与我自己的设置不同(从头开始)。

但是图书馆也解决了这个问题,请参见https://django-modeltranslation.readthedocs.io/en/latest/commands.html#the-update-translation-fields-command

Official features

  • 添加翻译而不更改现有模型或视图
  • 翻译字段存储在同一表中(没有昂贵的连接)
  • 支持继承的模型(抽象和多表继承)
  • 处理不仅仅是文本字段Django管理员集成灵活 后备,自动填充等等!

图书馆比较

我迅速比较了以下库:

我找到了这个比较表,可以帮助我找到public class Main extends Application { public Stage window = new Stage(); (在那儿获得最高评价)https://djangopackages.org/grids/g/i18n/


其他良好资源

请注意,https://github.com/WeblateOrg/weblate也很受欢迎,但不能解决OP问题。但这看起来很有趣!

此外,https://django-modeltranslation.readthedocs.io/en/latest/related_projects.html列出了其他一些项目,但大多数看起来相似或不够成熟。