it-roy-ru.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)

Проблема: чертовски тяжело?

54
Thiago Belem

Ваш третий пример - это способ решения проблемы. Тяжело, но выполнимо.

Удалите ссылку на продукт из таблицы перевода и поместите ссылку на перевод там, где он вам нужен (наоборот).

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

В качестве альтернативы (не особенно удачного) вы можете использовать одно поле и объединять все переводы (например, в 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.

Не так сложно, и избавляет вас от головной боли.

35
Gipsy King

Чтобы уменьшить количество JOIN, вы можете хранить отдельные переведенные и не переведенные в две отдельные таблицы:

[ products ]
id (INT)
price (DECIMAL)

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

На моем $ DAYJOB мы используем gettext для I18N. Я написал плагин для xgettext.pl , который извлекает весь английский текст из таблиц базы данных и добавляет их в мастер messages.pot.

Это работает очень хорошо - переводчики при переводе имеют дело только с одним файлом - 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 языках ... но это вопрос работы макета.

2
Tio

Как насчет четвертого решения?

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

* Translation_of * - этоFKсамо по себе. При добавлении языка по умолчанию * translation_of * устанавливается в значение Null. Но когда вы добавляете второй язык, * translation_of * принимает основной идентификатор языка продукта.

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

В этом случае мы получаем все переводы для продукта с идентификатором 1.

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

Мы получаем только продукт в польском переводе. Без второй таблицы и JOINS.

0
chf