i18n Django国际化和数据库对象

i18n Django国际化和数据库对象,django,django-models,internationalization,Django,Django Models,Internationalization,我在一个双语项目(es/en)中工作;对于这个项目,我选择使用django的i18n国际化系统(我开始后悔了…) 今天的问题如下: 对于某些型号,我的数据库存储信息,如description和es_description,或english_common_name和spanish_common_name(这些是我的对象的属性,在许多情况下使用,而不仅仅用于页面翻译问题)。 示例模型的定义如下: def MyModel(models.Model): name = ... type

我在一个双语项目(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>
<p>{% ifequal lang 'es' %}{{descrpition}}{% else %}{{es_description}}{% endifequal %}</p>

如果我试图在视图中管理它。。。我不想定义这样的
get\u translated\u 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列表)



请告诉我,有一个好的,逻辑的方式来访问数据库对象字段根据页面的语言,请




编辑:在阅读到目前为止收到的答案之后,我认为我应该在我的问题中添加一个“保持数据库结构(几乎)不变”的子句。

您确实应该使用类似的内容(如果您使用的是Django 1.2,请参阅)

以您的示例为例(基于)

访问可翻译字段

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

< P>如果你还不太晚,你可以考虑重新构建你的数据模型,这样你就可以在核心实体和它们的语言特定的表示之间建模一对多的关系。这样你的模型就更加规范化了——你并没有在你的字段名称中铭记元数据。你会发现这更容易合作

比如:

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,
})
然后在您看来,您可以执行以下操作:

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,
})
你可以写一个,基本上是这样的

{% 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 %}
我遇到了同一个问题,看到了你的帖子。但是,没有一个答案符合我的口味。(因为这个问题很老,链接库也过时了)

2019年最佳选择(IMHO):
django modeltranslation
在做了一些挖掘和基准测试之后,以下是我(个人)对最近Django项目的建议:

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

OP案例是一个特殊的案例,因为DB已经包含了一些翻译字段(需要进行迁移),这与我自己从头开始的设置不同

但是图书馆也解决了这个问题,参见

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

图书馆比较 我很快比较了以下库:

我找到了这个比较表,它帮助我找到了
django modeltranslation
(这是投票最多的):


其他良好资源 请注意,这也很流行,但不能解决OP问题。但它看起来非常有趣


另外,列出一些其他项目,但大多数看起来要么相似,要么不够成熟。

Ooh,我喜欢Nathan的答案-以前没有遇到过django Multilanguage!哇,谢谢你,这个解决方案非常棒,这将是一个完美的解决方案……但我不想改变我的模型结构:项目已经在运行,数据库正在运行填充了大量数据…[此外,阅读本文,django Multilanguage似乎根本不是最佳选择(i18n也是如此)]非常有趣的链接,感谢您的发布。您可以使用south()来迁移您的模型。关于django Multilanguage,有一个新的项目分支与django 1.2()我不确定,我看到了django模型的翻译,但我认为,最好为每种语言获得另一个DB,我认为这对性能更好