簡體   English   中英

Django 標簽和翻譯 - Model 設計

[英]Django labels and translations - Model Design

假設我有以下 Django model:

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

每個 label 都有一個 ID 號、label 文本和一個縮寫。 現在,我想讓這些標簽可以翻譯成其他語言。 做這個的最好方式是什么?

在我看來,我有幾個選擇:

1:將翻譯添加為 model 上的字段:

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)

這顯然不理想 - 添加語言需要編輯 model,正確的字段名稱取決於語言。

2:添加語言作為外鍵:

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)

但這里的問題是標簽 dict 是一個查找表,如下所示:

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

如果每個 label 有一行,並且單個 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)

3:將 label 文本拋出到新的 model 中:

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 是一個抽象的 model,我將其子類化以獲得針對不同領域的不同 label 集。

我想如果選項 3 /沒有/命中數據庫,這就是我會選擇的。 我相信真正的問題是過濾器text__language=1沒有緩存LabelText實例,因此當我text.get(language=1)

您對此有何看法? 誰能推薦一個更清潔的解決方案?

編輯:為了清楚起見,這些不是表單標簽,所以 Django 國際化系統沒有幫助。

當然,根據您的應用程序設計,您可能會考慮的另一個選擇是利用 Django 的國際化功能。 他們使用的方法與桌面軟件中的方法很常見。

我看到該問題已被編輯以添加對 Django 國際化的引用,所以您確實知道,但是 Django 中的國際功能不僅僅適用於 Z6450242531912981C3683CAE88A326 它涉及很多,只需要對您的應用程序設計進行一些調整。

他們的文檔在這里: http://docs.djangoproject.com/en/dev/topics/i18n/#topics-i18n

這個想法是你定義你的 model 好像只有一種語言。 換句話說,根本不提及語言,在 model 中只放英語。

所以:

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

我知道這看起來您已經完全排除了語言問題,但實際上您只是重新定位了它。 您已將其推送到視圖中,而不是數據 model 中的語言。

django 國際化功能允許您生成文本翻譯文件,並提供許多將文本從系統中提取到文件中的功能。 這實際上非常有用,因為它允許您將純文件發送給您的翻譯,這使他們的工作更容易。 添加新語言就像將文件翻譯成新語言一樣簡單。

翻譯文件定義數據庫中的 label,以及該語言的翻譯。 有一些函數可以在運行時動態處理模型、管理視圖、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)

當然,如果您的應用程序都是關於on the fly輸入新語言,那么這種方法可能不適合您。 不過,請查看 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')

我更喜歡為每種語言添加一個字段,而不是為每種語言添加一個新的 model 實例。 添加新語言時確實需要更改架構,但這並不難,您希望多久添加一次語言? 同時,它會為您提供更好的數據庫性能(沒有添加連接或索引),並且您不必用翻譯的東西弄亂您的查詢邏輯; 將其全部保存在它所屬的模板中。

更好的是,使用像django-transmetadjango-modeltranslation這樣的可重復使用的應用程序,這使得這個愚蠢的簡單並且幾乎完全透明。

雖然我會用丹尼爾的解決方案go ,但這是我從您的評論中了解到的另一種選擇:

您可以使用XMLField或 JSONField 來存儲您的語言/翻譯對。 這將允許引用標簽的對象對所有翻譯使用單個id 然后你可以有一個自定義的管理器方法來調用一個特定的翻譯:

Label.objects.get_by_language('ru', **kwargs)

或者與admin配合使用的稍微干凈和稍微復雜一點的解決方案是將 XMLField 非規范化為另一個 model 與Label Z20F35E630DAF44DBFA4C3F68F5399DC8 具有多對一關系。 相同的 API,但它可以查詢相關模型,而不是解析 XML。

對於這兩個建議,都有一個 object 的用戶將指向 label 的用戶。

我不會太擔心查詢,Django 緩存查詢,您的 DBMS 可能也有更好的緩存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM