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

193

Каков наилучший способ создания многоязычной базы данных? Создание локализованной таблицы для каждой таблицы усложняет проектирование и выполнение запросов, в других случаях добавить столбец для каждого языка просто, но не динамично, помогите мне понять, что лучше всего выбрать для корпоративных приложений.

Арсен Мкртчян
источник

Ответы:

223

Что мы делаем, это создаем две таблицы для каждого многоязычного объекта.

Например, первая таблица содержит только независимые от языка данные (первичный ключ и т. Д.), А вторая таблица содержит одну запись для каждого языка, содержащую локализованные данные плюс код ISO языка.

В некоторых случаях мы добавляем поле DefaultLanguage, чтобы мы могли использовать этот язык, если для указанного языка нет доступных локализованных данных.

Пример:

Table "Product":
----------------
ID                 : int
<any other language-neutral fields>


Table "ProductTranslations"
---------------------------
ID                 : int      (foreign key referencing the Product)
Language           : varchar  (e.g. "en-US", "de-CH")
IsDefault          : bit
ProductDescription : nvarchar
<any other localized data>

При таком подходе вы можете обрабатывать столько языков, сколько необходимо (без необходимости добавлять дополнительные поля для каждого нового языка).


Обновление (2014-12-14): ознакомьтесь с этим ответом для получения дополнительной информации о реализации, используемой для загрузки многоязычных данных в приложение.

M4N
источник
15
Что, если единственным не зависящим от языка полем является идентификатор? и как именно вы вставляете ссылку на внешний ключ при вставке строки?
Тимо Хуовинен
4
Забавно, что я разрабатывал схему базы данных для многоязычной CMS, и у меня тоже возник этот вопрос. Я выбрал этот подход, прежде чем я даже увидел этот ответ! Спасибо за этот ответ!
Патрик Мансер
5
Здесь следует отметить, что в этой таблице не должно быть ни PK, ни ID, а язык должен быть составным PK. Либо так, либо вам нужно добавить поле ProductTranslationId, вероятно, в качестве идентификатора.
Даниэль Лоренц
1
@Luca: Я ответил на ваш вопрос, показывая, какие реализации я использую для загрузки данных.
M4N
1
@ AarónGutiérrez Ну, как ни странно, вы создаете таблицу с одним столбцом под названием id: D. Чтобы объяснить, каждый idпредставляет значение, к которому вы можете присоединить слова из любого языка в реляционной таблице, так что вы получите две таблицы, meaning(id) и word(id, sense_id), idв wordтаблице представляет слово id, idв meaningпредставляет смысл, который универсален.
Тимо Хуовинен
18

Я рекомендую ответ, опубликованный Мартином.

Но вы, похоже, обеспокоены тем, что ваши запросы становятся слишком сложными:

Создание локализованной таблицы для каждой таблицы усложняет разработку и составление запросов ...

Так что вы можете подумать, что вместо того, чтобы писать простые запросы вроде этого:

SELECT price, name, description FROM Products WHERE price < 100

... вам нужно начать писать такие запросы:

SELECT
  p.price, pt.name, pt.description
FROM
  Products p JOIN ProductTranslations pt
  ON (p.id = pt.id AND pt.lang = "en")
WHERE
  price < 100

Не очень красивая перспектива.

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

Использование этой системы может выглядеть примерно так:

db.setLocale("en");
db.query("SELECT p.price, _(p.name), _(p.description)
          FROM _(Products p) WHERE price < 100");

И я уверен, что вы можете сделать это еще лучше.

Главное, чтобы ваши таблицы и поля были названы одинаково.

Рене Саарсоо
источник
Другой вопрос, создать один бизнес-объект для продукта? или создать два ... в первом случае легко работать с этим элементом, во 2-м легко написать CMS
Арсен Мкртчян
14

Я считаю, что такой подход работает для меня:

Продукт ПродуктДеталь Страна
========= ================== =========
ProductId ProductDetailId CountryId
- и т. д. - ProductId CountryName
            CountryId Language
            ProductName - и т. Д. -
            Описание товара
            - и т.д -

В таблице ProductDetail содержатся все переводы (для названия продукта, описания и т. Д.) На языки, которые вы хотите поддерживать. В зависимости от требований вашего приложения вы можете захотеть разбить таблицу стран на использование региональных языков.

Ник
источник
Я выбрал этот же подход для проекта, над которым я сейчас работаю, потому что мои разные локали содержат очень конкретную информацию о системах единиц измерения и мерах, которые будут отображаться пользователям.
Califrench
8
Страна и язык (локали) это разные вещи. И коды языка ISO являются естественными ключами, вы исключаете ненужное объединение из страны в страну.
gavenkoa
10

Я использую следующий подход:

Товар

ProductID OrderID, ...

Информация о продукте

ProductID Название Название LanguageID

язык

LanguageID Название Культура, ....

Омото
источник
2

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

Для этого потребуется IFNULL () и другой оператор SELECT для каждого поля?

Перевод по умолчанию будет храниться в той же таблице, где флаг, такой как isDefault, указывает, является ли описание описанием по умолчанию, если для текущего языка не найдено ни одного описания.

Dóm
источник
1
@GorrillaApe: посмотрите этот ответ для примера того, как вернуться к языку по умолчанию, если нужный язык не был найден: stackoverflow.com/a/27474681/19635
M4N