Дизайн базы данных: как поддерживать многоязычный сайт? - PullRequest
3 голосов
/ 06 апреля 2011

Предположим, у меня есть таблица:

TABLE: product
=================================================================
| product_id | name           | description                     |
=================================================================
| 1          | Widget 1       | Really nice widget. Buy it now! |
-----------------------------------------------------------------

Если я хочу предоставить многоязычную поддержку, каков наилучший подход для этого?

Возможные решения:

  1. Добавить столбец «языка» в таблицу выше; это будет указывать на язык конкретной записи. (Я не думаю, что это вариант для меня, так как другие таблицы будут использовать product.product_id в качестве FK.)
  2. Удалите все переводимые столбцы в таблице продуктов (в приведенном выше примере product.name и product.description) и поместите их в отдельную таблицу со столбцом «language». Эта новая таблица будет использовать product.product_id в качестве FK. (Я не буду поддерживать многоязычность в первой версии моего приложения. Это решение означает, что мне нужно будет выполнить дополнительный JOIN только для того, чтобы получить значения изначально поддерживаемого языка.)
  3. Что-то еще, что я не учел?

Ответы [ 5 ]

4 голосов
/ 06 апреля 2011

Я бы выбрал третий вариант, представляющий собой гибрид существующего дизайна и решения № 2.Столбцы, которые существуют в вашей таблице, теперь представляют ваш «нейтральный» или язык по умолчанию.Затем вы должны добавить таблицу для каждого объекта, для которого нужны переведенные значения, которые будут содержать PK основной таблицы, ключ для кода языка и столбец для каждого значения в родительской таблице, для которого требуется перевод. Так что у нас может быть

Create Table product_translations
    (
    product_id int not null References product( id )
    , language_code varchar(5) not null
    , name ...
    , description ...
    , Primary Key ( product_id, language_code )
    ...
    )

Тогда ваши запросы будут выглядеть следующим образом:

Select P.product_id
    , Coalesce( PT.name, P.name ) As Name
From product As P
    Left Join product_translations As PT
        On PT.product_id = P.product_id
            And PT.language_code = 'en-UK'

Это означает, что для каждого запроса, для которого вы запрашиваете информацию о продукте, потребуется Левое соединение с таблицей переводов, а затем решите, что делать, еслинет значения перевода: верните языковой термин по умолчанию (как в моем примере выше) или верните ноль.

4 голосов
/ 06 апреля 2011

Я бы пошел с решением 2.

Эта опция уменьшит вашу работу с первой версией и уменьшит повторение между столбцами, которые не изменяются.

Требуется дополнительный JOIN, но это простое соединение клавиш, поэтому оно не сильно повлияет на вашу производительность.

1 голос
/ 06 апреля 2011

Я бы использовал немного измененную версию (2).Я думаю, что не стоит удалять ваши столбцы name и description из таблицы продуктов - в этом случае вы всегда будете иметь значения по умолчанию для продукта, если локализованная версия не существует.

0 голосов
/ 06 апреля 2011

Вы уверены, что всегда будете иметь весь контент хотя бы на английском? Количество переводов достаточно мало? Если это так, я бы сказал, оставьте product как есть и добавьте аналогичную таблицу для каждого перевода:

TABLE: product_fi
=================================================================
| product_id | name           | description                     |
=================================================================
| 1          | Vimpain 1      | Tosi kiva vimpain. Osta heti!   |
-----------------------------------------------------------------

Затем вы можете OUTER JOIN и COALESCE, чтобы получить конкретные языковые версии, когда они существуют, но использовать английские версии:

SELECT
  coalesce(fi.name, en.name) AS name,
  coalesce(fi.description, en.description) AS description
FROM product en
LEFT OUTER JOIN product_fi fi ON en.product_id = fi.product_id
WHERE en.product_id = 1
0 голосов
/ 06 апреля 2011

Я думаю, что вариант № 2 создает отношение 1: M в неправильном направлении. Теперь вам нужна таблица перевода для любой базовой таблицы, которая требует перевода.

Последнее использованное мной решение, примененное к вашему образцу:

language
--------------
language_id
language_name

language_key
-------------
language_key_id
lang_key_name (or description)

translation
-------------------
translation_id
language_id
language_key_id
translation_text

product
--------------
product_id
product_name_key_id
product_description_key_id

Вы также можете добавить что-то вроде «перевода по умолчанию» в таблицу ключей, так что добавление перевода не является обязательным и имеет запасное значение.

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

...