Многоязычные поля в таблицах БД - PullRequest
4 голосов
/ 02 июня 2009

У меня есть приложение, которое должно поддерживать многоязычный интерфейс, а точнее пять языков. Для основной части интерфейса можно использовать стандартный подход ResourceBundle.

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

Хотя я полагаю, у меня могут быть поля в каждой таблице, например

NameLang1
NameLang2
...

Мне кажется, что это приводит к значительному объему идентичного кода при написании bean-компонентов, представляющих каждую таблицу.

С чисто объектно-ориентированной точки зрения решение, однако, простое. Каждый класс просто имеет объект Text, который содержит соответствующий текст на каждом из языков. Это также полезно в том смысле, что только один из языков является обязательным, у других есть запасные правила (например, если в языке 4 отсутствует язык возврата, который возвращается к языку 1, который является обязательным).

К сожалению, сопоставление этого с реляционной базой данных означает, что я получаю одну таблицу, в которую входят около 10-12 других таблиц FK (в действительности некоторые таблицы имеют более одного FK).

Этот подход, похоже, работает, и я смог отобразить данные в POJO с помощью Hibernate. Единственное, что вы не можете сделать, это сопоставить объект Text с его родительским объектом (поскольку у вас нет возможности узнать, на какую таблицу вы должны ссылаться), но тогда вряд ли это нужно делать.

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

Если это имеет значение, я использую MySQL ...

Ответы [ 5 ]

2 голосов
/ 02 июня 2009

Стандартный подход к переводу, используемый, например, в gettext , заключается в использовании одной строки для описания концепции и вызова метода translate, который переводит на язык назначения.

Таким образом, вам нужно всего лишь сохранить в базе данных одну строку (каноническое представление), а затем вызвать в вашем приложении метод translate для получения переведенной строки. Отсутствие FK и полная гибкость за счет небольшой производительности во время выполнения (и, возможно, немного больше проблем с техническим обслуживанием, но, если подумать, нет необходимости делать обслуживание проблемным в этом сценарии).

2 голосов
/ 02 июня 2009

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

В Hibernate вы можете отобразить информацию из дочерних таблиц как Map и получить информацию для нужного вам языка, реализуя запасной вариант в вашем POJO, как вы сказали. У вас могут быть разные методы получения для многоязычных полей, которые внутренне вызывают резервный метод, чтобы получить соответствующий дочерний объект для нужного языка, а затем просто возвращают обязательное поле.

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

0 голосов
/ 07 марта 2010

Как насчет этого: http://rob.purplerockscissors.com/2009/07/24/internationalizing-websites/ ... это то, что пользователь "Chochos" говорит в ответе # 2

0 голосов
/ 02 июня 2009

В зависимости от ваших требований, может быть лучше иметь отдельную таблицу меток для каждой таблицы, которая должна быть многоязычной. например: у вас есть таблица XYZ со столбцом xyz_id и таблица XYZ_Label с кодом xyz_id, language_code, label, other_label и т. д.

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

0 голосов
/ 02 июня 2009

Подход, который я видел в приложении с похожей проблемой, заключается в том, что мы используем столбец «text id» для хранения ссылки, и у нас есть одна таблица со всеми переводами. Это обеспечивает некоторую гибкость и при повторном использовании одних и тех же ключей для уменьшения количества необходимых переводов, что является дорогостоящей частью проекта.

Он также обеспечивает хорошее разделение между данными и переводами, что, на мой взгляд, является скорее интерфейсом.

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

При таком подходе у ваших bean-компонентов не будет геттеров для каждого языка, но вы бы использовали другой объект-переводчик:

 MyTranslator.translate(myBean.getNameTextId());
...