Какова лучшая структура базы данных для хранения многоязычных данных? [дубликат]
Возможные Дубликаты:
схема для многоязыковой базы данных
вот пример:
[ 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)
проблема: чертовски трудно?
8 ответов:
ваш третий пример на самом деле так, как проблема обычно решается. Тяжело, но выполнимо.
удалите ссылку на продукт из таблицы перевода и поместите ссылку на перевод, где вам это нужно (наоборот).
[ 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>
аналогично методу 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
.не так сложно, и держит вас от головной боли.
чтобы уменьшить количество соединений, вы можете разделить переведенные и непереведенные в 2 отдельных таблицах:
[ products ] id (INT) price (DECIMAL) [ products_i18n ] id (INT) name (VARCHAR) description (VARCHAR) lang_code (CHAR(5))
на мой $работа мы используем gettext версии для i18n. Я написал плагин для xgettext.pl, которая извлекает все английские тексты из таблиц базы данных и добавить их в мастер-сообщения.горшок.
Он работает очень хорошо-переводчики имеют дело только с одним файлом при выполнении перевода - файл po. Там нет возиться с записями базы данных при выполнении переводов.
[языки] идентификатор (инт ПК) код (тип varchar)
[products] id (int PK) name price all other fields of product id_language ( int FK )
Я на самом деле использую этот метод, но в моем случае, это не с точки зрения продукта, для различных страниц в моей CMS, эта работа довольно хорошо.
Если у вас есть много продуктов, это может быть головная боль, чтобы обновить один из них на 5 или 6 языках... но это вопрос работы макета.
как насчет четвертого решения?
[ products ] id (INT) language (VARCHAR 2) name (VARCHAR) description (VARCHAR) price (DECIMAL) *translation_of (INT FK)*
* Translation_of* is FK это самостоятельно. При добавлении языка по умолчанию * translation_of * имеет значение Null. Но при добавлении второго языка * translation_of * принимает первичный код языка продукта.
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'
мы получаем только продукт в польском переводе. Без второй таблицы и присоединяется.
многие ко многим отношения.
У вас есть таблица данных, таблица языков и таблица data_language.
в таблице data_language у вас есть
id, data_id, language_id
Я думаю, что это может работать лучше для вас.
мы используем эту концепцию для нашего webiste (600k просмотров в день) и (возможно, удивительно) это работает. Конечно, наряду с кэшированием и оптимизацией запросов.
[attribute_names] id (INT) name (VARCHAR) [languages_names] id (INT) name (VARCHAR) [products] id (INT) attr_id (INT) value (MEDIUMTEXT) lang_id (INT)