Подтвердить что ты не робот

Какая лучшая структура базы данных для хранения многоязычных данных?

Возможный дубликат:
Схема для мультиязычной базы данных

Вот пример:

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

Проблема: сложно?

4b9b3361

Ответ 1

Ваш третий пример на самом деле является способом решения проблемы. Жесткий, но выполнимый.

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

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

Ответ 2

Аналогично методу 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.

Не так сложно и держит вас свободными от головных болей.

Ответ 3

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

[ products ]
id (INT)
price (DECIMAL)

[ products_i18n ]
id (INT)
name (VARCHAR)
description (VARCHAR)
lang_code (CHAR(5))

Ответ 4

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

Он работает очень хорошо - переводчики обрабатывают только один файл при выполнении перевода - файл po. При выполнении переводов не возится с записями базы данных.

Ответ 5

[языки]   id (int PK)   код (varchar)

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

Я действительно использую этот метод, но в моем случае это не с точки зрения продукта, для разных страниц в моей CMS, это работает довольно хорошо.

Если у вас много продуктов, может возникнуть головная боль для обновления одного на 5 или 6 языках... но это вопрос работы с макетом.

Ответ 6

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

[ 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

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

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

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

Ответ 7

У многих отношений много.

У вас есть таблица данных, таблица языков и таблица data_language.

В таблице data_language есть

id, data_id, language_id

Я думаю, что это может сработать лучше всего для вас.

Ответ 8

Мы используем эту концепцию для нашего webiste (600 тыс. просмотров в день) и (возможно, удивительно), это работает. Разумеется, наряду с кешированием и оптимизацией запросов.

[attribute_names]
id (INT)
name (VARCHAR)

[languages_names]
id (INT)
name (VARCHAR)

[products]
id (INT)
attr_id (INT)
value (MEDIUMTEXT)
lang_id (INT)