2009-03-05 14 views
2

私は、次の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番号、ラベルテキスト、および略語があります。今、これらのラベルを他の言語に翻訳できるようにしたいと思います。これを行う最善の方法は何ですか?

私はそれを見るように、私はいくつかのオプションがあります。

1:モデルのフィールドとして翻訳を追加します。

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) 

これは明らかに理想的ではありません - 言語を追加モデルを編集する必要があり、正しいフィールド名は言語によって異なります。

2:

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

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') 

これは、今、私は特定の言語でのすべてのラベルを求める、と辞書にそれらを投げることができる、はるかに優れている:外部キーなどの言語を追加します。

しかし、ここでの問題は、ラベルの辞書はそうのようなルックアップテーブル、であることを意味するということである:DOE

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

1つのラベルに複数の言語がある場合は、ラベルごとに行がある場合は機能しません。新しいモデルに投げラベルテキストアウト:

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:1つを解決するために、私は別のフィールドを必要とする

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=1LabelTextインスタンスをキャッシュしないため、DBがヒットした場合です。text.get(language=1)

これについてのご意見はありますか?誰もクリーナーソリューションをお勧めできますか?

:これはフォームラベルではないので、Django Internationalizationシステムは役に立ちません。

答えて

1

言語ごとに新しいモデルインスタンスよりも言語ごとにフィールドを追加する方がはるかに好きです。新しい言語を追加するときにスキーマの変更が必要ですが、それは難しくありませんし、言語を追加する頻度はどれくらいですか?その間、より良いデータベースパフォーマンス(ジョインやインデックスは追加されません)が得られます。また、クエリロジックに翻訳作業を煩わせる必要はありません。それが所属するテンプレート内にすべて保持してください。

django-transmetadjango-modeltranslationのような再利用可能なアプリを使用すると、この単純でほぼ完全な透明性が得られます。

+0

ありがとうございました!これらの2つのアプリは非常に有望に見える - 今私は使用するかを決定する必要があります:) –

+0

ええ、それは厳しい呼び出しです。個人的に私はdjango-transmetaについていくつかのことを好んでいます(元のフィールドを取り除く方法のように複雑なロジックは必要ありません)。しかし、私はdjango-modeltranslationを使ってコードに触れることなくモデルを翻訳できます。 –

2

できるだけシンプルにします。

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') 
+0

私はむしろDBに1回だけヒットするために、すべてのラベルをメモリにロードします。これらのラベルを参照するID番号のオブジェクトがいくつかあります。もし私ができればラベルには外来キーを使用したいが、それでもDBに当てはまるオプション3を使わない限り、それは言語でロックされる。 –

+0

私はあなたが物事を思っていると思う。データをキャッシュする必要がある場合は、 'StandardLabel.objects.all()。values()'を実行してください。追加のデータベースクエリが心配な場合は、 'select_related'パラメータを使用してください。 –

+0

+1。シンプルな方法を行く必要があります。翻訳はすでに複雑な作業です。 – muhuk

3

あなたはもちろんのアプリケーションの設計に応じて、検討するかもしれない別のオプション、 Djangoの国際化機能を利用することです。彼らが使用するアプローチは、デスクトップソフトウェアに見られるアプローチに非常に共通しています。

Djangoの国際化への参照を追加するために編集されたので、あなたはそれについて知っていますが、Djangoのintlの機能はFormsだけでなく、それはかなりたくさん触れ、あなたのアプリデザインにわずかな調整が必要です。

彼らのドキュメントはここにある: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、およびテンプレートの実行時に言語翻訳を動的に処理する機能があります。あなたのアプリが入っすべてについてであれば、もちろん

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

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

またはビューコードで

は、あなたができる:

たとえば、テンプレートでは、あなたのような何かをするかもしれません新しい言語on the flyの場合、この方法はうまくいかない場合があります。それでも、「現状のまま」使用することができますか、またはあなたのドメインで動作するdjangoに適したソリューションに触発されるように、Internationalizationプロジェクトをご覧ください。

+0

私はこれを見ましたが、残念ながらそれは私がしたいことではありません。いろいろな理由から、私はむしろ翻訳をデータベースに保存しています。とにかく助けてくれてありがとう! –

+1

-1適度に動的なウェブサイトでは、データベースコンテンツの翻訳にgettextを使用することはできません。それはあまりにも頻繁に変化します。 –

0

私はここに、Daniel's solutionとなるだろうが、私はあなたのコメントから理解してきたことから、代替です:

あなたはあなたの言語/翻訳ペアを格納するXMLFieldまたはJSONFieldを使用することができます。これにより、ラベルを参照するオブジェクトですべての翻訳に単一のidを使用できるようになります。そして、あなたは特定の変換を呼び出すために、カスタム管理方法を持つことができます。

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

それともadminとよく果たして少しクリーナーと少し複雑ソリューションは、多対して別のモデルにXMLFieldを非正規化することであろうLabelモデルとの1つの関係。同じAPIですが、XMLを解析する代わりに関連するモデルをクエリできます。

両方の提案には、ラベルのユーザーが指す単一のオブジェクトがあります。

私はクエリをあまりにも心配することはありません、Djangoはクエリをキャッシュし、おそらくあなたのDBMSも同様に優れたキャッシュを持つでしょう。

+0

これはまともな解決策ですが、私は管理UIに統合したいのですが(私が知っている、私は台無しです:))。 –