我正在从事双语项目(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列表。)
请告诉我,有一种很好的逻辑方法可以根据页面的语言访问数据库对象字段!
编辑:在阅读了目前为止收到的答案之后,我想我应该在我的问题中添加一个“离开数据库结构(几乎)不变的”条款。
答案 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)
我遇到了同样的问题,看到了您的帖子。但是,没有一个答案足以满足我的口味。 (并且因为这个问题很老,所以链接库也已经过时了)
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
我迅速比较了以下库:
我找到了这个比较表,可以帮助我找到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列出了其他一些项目,但大多数看起来相似或不够成熟。