web-dev-qa-db-ja.com

多言語データを保持するのに最適なデータベース構造は何ですか?

可能性のある複製:
多言語データベースのスキーマ

以下に例を示します。

[ products ]
id (INT)
name-en_us (VARCHAR)
name-es_es (VARCHAR)
name-pt_br (VARCHAR)
description-en_us (VARCHAR)
description-es_es (VARCHAR)
description-pt_br (VARCHAR)
price (DECIMAL)

問題:すべての新しい言語はテーブル構造を変更する必要があります。

別の例を次に示します。

[ products-en_us ]
id (INT)
name (VARCHAR)
description (VARCHAR)
price (DECIMAL)

[ products-es_es ]
id (INT)
name (VARCHAR)
description (VARCHAR)
price (DECIMAL)

問題:すべての新しい言語では新しいテーブルを作成する必要があり、「価格」フィールドはすべてのテーブルで複製されます。

別の例を次に示します。

[ languages ]
id (INT)
name (VARCHAR)

[ products ]
id (INT)
price (DECIMAL)

[ translation ]
id (INT, PK)
model (VARCHAR) // product
field (VARCHAR) // name
language_id (INT, FK) 
text (VARCHAR)

問題:ハード?

53
Thiago Belem

3番目の例は、実際に問題が通常解決される方法です。ハード、しかし実行可能。

変換テーブルから製品への参照を削除し、必要な場所に翻訳への参照を配置します(逆の場合)。

[ products ]
id (INT)
price (DECIMAL)
title_translation_id (INT, FK)

[ translation ]
id (INT, PK)
neutral_text (VARCHAR)
-- other properties that may be useful (date, creator etc.)

[ translation_text ]
translation_id (INT, FK)
language_id (INT, FK) 
text (VARCHAR)

別の方法(特に良い方法ではありません)として、1つのフィールドを持ち、そこにあるすべての翻訳を(たとえばXMLとして)マージしたままにすることができます。

<translation>
  <en>Supplier</en>
  <de>Lieferant</de>
  <fr>Fournisseur</fr>
</translation>
28
user151323

方法3と同様:

[languages]
id (int PK)
code (varchar)

[products]
id (int PK)
neutral_fields (mixed)

[products_t]
id (int FK)
language (int FK)
translated_fields (mixed)
PRIMARY KEY: id,language

そのため、各テーブルに対して、翻訳済みフィールドを保持する別のテーブル(私の場合は接尾辞「_t」)を作成します。 SELECT * FROM products、単に... LEFT JOIN products_t ON products_t.id = products.id AND products_t.language = CURRENT_LANGUAGE

それほど難しくはなく、頭痛から解放されます。

36
Gipsy King

JOINの数を減らすために、翻訳済みと未翻訳を別々の2つのテーブルに分けておくことができます。

[ products ]
id (INT)
price (DECIMAL)

[ products_i18n ]
id (INT)
name (VARCHAR)
description (VARCHAR)
lang_code (CHAR(5))
13
Clément

私の$ DAYJOBでは、I18Nにgettextを使用しています。 xgettext.pl にプラグインを作成しました。このプラグインは、すべての英語のテキストをデータベーステーブルから抽出し、それらをマスターmessages.potに追加します。

それは非常にうまく機能します-翻訳者は翻訳を行うときに1つのファイル、poファイルのみを扱います。翻訳を行う際にデータベースエントリをいじることはありません。

3
holygeek

[言語] id(int PK)コード(varchar)

[products]
id (int PK)
name
price
all other fields of product
id_language ( int FK )

私は実際にこの方法を使用しますが、私の場合は、製品の観点ではありません。CMSのさまざまなページで、この作業は非常にうまくいきます。

多数の製品がある場合、5つまたは6つの言語で1つの製品を更新するのは頭痛の種かもしれませんが、レイアウトの問題です。

2
Tio

4番目のソリューションはどうですか?

[ products ]
id (INT)
language (VARCHAR 2)
name (VARCHAR)
description (VARCHAR)
price (DECIMAL)
*translation_of (INT FK)*

* Translation_of *は[〜#〜] fk [〜#〜]それ自身です。デフォルト言語を追加すると、* translation_of *はNullに設定されます。ただし、2番目の言語を追加すると、* translation_of *はプライマリ製品の言語IDを取ります。

SELECT * FROM products WHERE id = 1 AND translation_of = 1

その場合、IDが1の製品のすべての翻訳を取得します。

SELECT * FROM products WHERE id = 1 AND translation_of = 1 AND language = 'pl'

ポーランド語の翻訳でのみ製品を取得します。 2番目のテーブルとJOINSなし。

0
chf