Django 多语言标签和翻译 – 模型设计

假设我们有一个 Django 模型:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)

每个标签都有一个 ID 号、标签文本和缩写。现在,我们希望将这些标签翻译成其他语言。
以下是我们考虑的几种解决方案:

① 在模型上添加翻译字段:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    label_english = models.CharField(max_length=255)
    abbreviation_english = models.CharField(max_length=255)
    label_spanish = models.CharField(max_length=255)
    abbreviation_spanish = models.CharField(max_length=255)

显然这不是理想的解决方案,添加语言需要编辑模型,正确的字段名称取决于语言。

② 将语言作为外键添加:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)
    language = models.ForeignKey('languages.Language')

这种方法好得多,现在我们可以查询具有某种语言的所有标签,并将它们放到字典中:

labels = StandardLabel.objects.filter(language=1)
labels = dict((x.pk, x) for x in labels)

但问题是标签字典被用作查找表,如下所示:

x = OtherObjectWithAReferenceToTheseLabels.object.get(pk=3)
thelabel = labels[x.labelIdNumber].label

如果每条标签都有一个行,并且一个标签可能有多个语言,那么这种方法就不起作用了。为了解决这个问题,我们需要另一个字段:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    group_id = models.IntegerField(db_index=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)
    language = models.ForeignKey('languages.Language')
    class Meta:
        unique_together=(("group_id", "language"),)
#and I need to group them differently:
labels = StandardLabel.objects.filter(language=1)
labels = dict((x.group_id, x) for x in labels)

③ 将标签文本扔到一个新模型中:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    text = models.ManyToManyField('LabelText')

class LabelText(models.Model):
    id = models.AutoField(primary_key=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)
    language = models.ForeignKey('languages.Language')
labels = StandardLabel.objects.filter(text__language=1)
labels = dict((x.pk, x) for x in labels)

但是这种方法不起作用,每次引用标签的文本时都会导致数据库命中:

x = OtherObjectWithAReferenceToTheseLabels.object.get(pk=3)
thelabel = labels[x.labelIdNumber].text.get(language=1)

我们已经实现了选项 2,但我们觉得它很丑陋——我们不喜欢 group_id 字段,而且我们想不出更好的名称。此外,我们正在使用 StandardLabel 作为抽象模型,我们对它进行子类化以获取不同字段的不同标签集。
我们认为如果选项 3 不命中数据库,那么就是我们想要的。我们认为真正的问题是过滤器 text__language=1 没有缓存 LabelText 实例,因此在我们 text.get(language=1) 时命中了数据库。
您对此有何看法?谁能推荐一个更简洁的解决方案?

解决方案
① 使用 Django 国际化特性
根据你的应用程序设计,你可以考虑使用 Django 的国际化特性。他们使用的方法与桌面软件中发现的方法非常相似。
我们看到问题已经被编辑以添加对 Django 国际化的引用,因此你确实知道它,但 Django 中的 intl 特性不仅仅适用于表单;它涉及很多,并且只需要对你的应用程序设计进行一些调整。
他们的文档在这里:
http://docs.djangoproject.com/en/dev/topics/i18n/#topics-i18n
这个想法是将你的模型定义为只有一种语言。换句话说,不要在你的模型中引用任何语言,而只在你的模型中填写英语。
因此:

class StandardLabel(models.Model):
    abbreviation = models.CharField(max_length=255)
    label = models.CharField(max_length=255)

我知道这看起来像是你已经完全抛弃了语言的问题,但你实际上只是把它重新安置了。语言不再存在于你的数据模型中,你已经将它推到了视图中。
Django 的国际化特性允许你生成文本翻译文件,并提供了一些将文本从系统提取到文件中的特性。这实际上非常有用,因为它允许你将纯文件发送给你的翻译,从而使他们的工作更容易。添加新语言就像将文件翻译成一种新语言一样简单。
翻译文件定义了来自数据库的标签以及该语言的翻译。有函数可以在运行时动态处理模型、管理视图、javascript 和模板的语言翻译。
例如,在模板中,你可以做类似这样的事情:

<b>Hello {% trans "Here's the string in english" %}</b>

或者在视图代码中,你可以这样做:

# See docs on setting language, or getting Django to auto-set language
s = StandardLabel.objects.get(id=1)
lang_specific_label = ugettext(s.label)

当然,如果你的应用程序完全是关于即时输入新语言,那么这种方法可能不适合你。不过,请查看 Internationalization 项目,因为你可能能够“按原样”使用它,或者从一个确实适用于你的域的 Django 适当的解决方案中获得启发。

② 保持简单
我们希望尽可能地保持简单。使用类似这样的东西,查找速度会更快,代码也更简洁:

class StandardLabel(models.Model):
    abbreviation = models.CharField(max_length=255)
    label = models.CharField(max_length=255)
    language = models.CharField(max_length=2)
    # or, alternately, specify language as a foreign key:
    #language = models.ForeignKey(Language)

    class Meta:
        unique_together = ('language', 'abbreviation')

然后根据缩写和语言查询:

l = StandardLabel.objects.get(language='en', abbreviation='suite')

③ 使用可重用的应用程序
我更愿意为每种语言添加一个字段,而不是为每种语言添加一个新模型实例。当你添加新语言时,确实需要修改架构,但这并不难,而且你希望添加语言的频率是多少?与此同时,它将为你提供更好的数据库性能(无需添加联接或索引),并且你不需要用翻译内容来弄乱查询逻辑;保持它们全部都在属于它们的模板中。
更好的是,使用一个可重用的应用程序,如 django-transmeta 或 django-modeltranslation,它使这一切变得非常简单且几乎完全透明。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容