[英]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-transmeta或django-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.