Локализация базы данных - PullRequest
       17

Локализация базы данных

8 голосов
/ 24 августа 2009

У меня есть несколько таблиц базы данных, которые содержат name и description столбцы, которые необходимо локализовать. Моя первая попытка разработать схему БД, которая бы поддерживала это, была что-то вроде:

product
-------
id
name
description


local_product
-------
id
product_id
local_name
local_description
locale_id


locale
------
id
locale

Однако для этого решения требуется новая таблица local_ для каждой таблицы, содержащей name, и столбцы описания, для которых требуется localization. Пытаясь избежать этих издержек, я переработал схему так, чтобы была нужна только одна localization таблица

product
-------
id
localization_id


localization    
-------
id    
local_name
local_description
locale_id


locale
------
id
locale

Вот пример данных, которые будут храниться в этой схеме, когда есть 2 таблицы (продукт и страна), требующие локализации:

страна

id,     localization_id
-----------------------
1,      5

продукт

id,     localization_id
-----------------------
1,      2

локализация

id,     local_name,   local_description,     locale_id
------------------------------------------------------
2,      apple,        a delicious fruit,     2
2,      pomme,        un fruit délicieux,    3
2,      apfel,        ein köstliches Obst,   4
5,      ireland,      a small country,       2
5,      irlande,      un petite pay,         3

язык

id,     locale
--------------
2,      en
3,      fr
4,      de

Обратите внимание, что составной первичный ключ таблицы localization равен (id, locale_id), но внешний ключ в таблице product относится только к первому элементу этого составного PK. Это похоже на «плохую вещь» от POV нормализации.

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

Обновление: Ряд респондентов предложили решение, которое требует создания отдельной таблицы для каждой локализуемой таблицы. Однако это именно то, чего я пытаюсь избежать. Схема, которую я предложил выше, почти решает проблему к моему удовлетворению, но я недоволен тем фактом, что внешние ключи localization_id относятся только к части соответствующего первичного ключа в таблице localization.

Спасибо, Дон

Ответы [ 4 ]

3 голосов
/ 24 августа 2009

Я думаю, что все в порядке. Вы описываете отношение «один ко многим» между продуктом и текстом его локализации.

Мне интересно, следует ли вам также локализовать английский вместо денормализации его в таблице продуктов.

2 голосов
/ 11 мая 2010

Мне нравится идея, но я бы пошёл в другом направлении и имел бы запись локализации для каждого переводимого столбца:

страна

id,     localization_id
-----------------------
1,      5

продукт

id,     name_locale_id,  description_locale_id
----------------------------------------------
1,      2,               8

локализация

id,     locale_id,    value
------------------------------------------------------
2,      2             apple
2,      3             pomme
2,      4             apfel
5,      2             ireland
5,      3             irlande
8,      2             a delicious fruit
8,      3             un fruit délicieux
8,      4             ein köstliches Obst
9,      2             a small country
9,      3             un petite pay

локаль

id,     locale
--------------
2,      en
3,      fr
4,      de

PK локализации - это (id, locale_id). Это не проблема, что id также является ссылкой FK в нескольких других таблицах. Вы можете добавить заменитель PK, если хотите, если у вас все еще есть уникальный индекс (id, locale_id).

Хорошая вещь об этом - это одна таблица локализации, и она работает для любой таблицы в вашей схеме, независимо от того, какие поля у нее есть (вы не ограничены ни именем, ни описанием чего-либо, что локализуется). Недостатком является потенциальное снижение производительности при использовании таблицы локализации - хотя потенциально вы можете просто кешировать все для заданного locale_id, поэтому, когда вы просматриваете записи, вам просто нужно искать заданный идентификатор (так как ваш кеш является ключ на основе уже языка).

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

1 голос
/ 24 августа 2009

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

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

Продукт (ID, имя, описание, tanslation_row_id)

Переводы продукта (идентификатор, имя, описание, lang_id, translation_id)

translation_row_id будет внешним ключом, указывающим на Product_translations.ID Однако translation_id будет указывать родительскую запись в той же таблице, которая будет служить общей записью для всех записей, относящихся к конкретному языку.

Пример записей

Продукт

(ID, name, description, translation_row_id)
(p1, apples,a red fruit, tr1)
(p2, mango, a yellow fruit, tr2)

Product_translations

(ID, name, description, lang_id, translation_id)
(tr1, apples, a red fruit, ENU, null)
(tr2, mango, a yellow fruit, null)
(tr3, pomme,un fruit rouge, FRA,tr1)
(tr4, mangue,a yellow fruit, SPA,tr2)

Учитывая код языка, вы можете извлечь значения имени и описания, используя следующий SQL-запрос

select T.name, T.description
from product_translations T 
where T.translation_id = 
     (select T2.ID 
      from Product P,Product_translations T2 
      where P.translation_row_id = t2.ID
      ) 
     and T.lang_id = '&langID';

Важное примечание. Я предполагаю, что таблица продуктов имеет гораздо больше атрибутов, которые не нуждаются в этом переводе. '& langID' - это параметр для запроса SQL, который запрашивает у пользователя выбранный код языка

1 голос
/ 24 августа 2009

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

Итак, у вас будет:

продукт

id 
-name removed
-description removed

локализация продукта

productid, locale_id, name,   description
------------------------------------------------------
1,         3,         pomme,  un fruit délicieux
1,         4,         apfel,  ein köstliches Obst
1,         1,         apple,  a delicious fruit

локаль

id,     locale
--------------
1,      en
3,      fr
4,      de
...