Bermuda
Новичок
Многоязыковая модель данных
Известно, что используя ООП можно построить проекцию реляционной базы данных на програмный код следующим образом:
Сущность == Таблица == Класс
Кортэж = Запись (строка) == Объект класса
Атрибут == Поле (столбец) == Свойство объекта
Такое соглашение очень удобно при реализации ORM, и в некоторых случаях позволяет реализовать генерацию функционала CRUD на основе имеющейся модели данных. До этого места все вроде бы понятно.
Трудности возникают при реализации "многоязыковой" модели данных.
Пример:
Есть класс "статьи", объекты класса хранятся в одноименной таблице, по одной записи на объект. Некоторые свойства класса текстовые, например "заголовок статьи", т. е. они содержат текст на вполне определенном языке, например на русском. В многоязычном сайте такие текстовые поля могут быть представлены на нескольких языках. Например сайт сделан русском, английском и испанском. Таким образом редактор добавляя новую статью должен ввести "заголовок статьи" на данных языках, дабы в дальнейшем при запросе пользователя приложение отобразило "заголовок статьи" на языке текущего интерфейса пользователя. Т. е. на сайт заходит испанец, переключает интерфейс на испанский язык и при запросе статьи получает ее на испанском языке.
Вопрос: Как правильнее реализовать модель данных?
Вопрос не по php, скорее это академический вопрос по реализации модели данных.
На сегодняшний день я нашел несколько вариантов решения, но не один меня не удовлетворил.
1. Тривиальный
Для каждого текстового поля завести столько его дубликатов сколько языков присутствует в системе. Т. е. в таблице базы будет три отдельных поля для русского, английского и испанского названия статьи.
Достоинства:
- соответствует соглашению приведенному выше
- облегчает реализацию автогенерации CRUD функционала.
Недостатки:
- следуя соглашению описанному выше каждое поле это свойство класса, таким образом вместо отображения одного свойства потребуется выбрать из нескольких, что не совсем корректно с точки зрения ООП.
- при добавлении/удалении/изменении языка потребуется переделывать как модель данных, так и классы.
- избыточность, не для всех статей может существовать перевод на другой язык
2. Притянутый за уши
Разбить класс (сущность, таблицу) на две части. Левая часть -- языконезависимая, правая зависит от языка. На одну левую часть создается столько правых частей сколько языков присутствует в системе. Т. е. создается одна запись в таблице "статьи" и три записи в таблице "статьи-языки".
Достоинства:
- псевдореляционно
Недостатки:
- не соответсвует изначальному соглашению, что затрудняет реализацию автогенерации CRUD функционала.
- в действительности используется составной первичный ключ (идентификадор + язык) вместо простого первичного ключа (идентификатор). Т. е. для статьи с номером 5 будет:
5 + русский = содержимое на русском
5 + английский = содержимое на английском
5 + испанский = содержимое на испанском
Что в действительности суть три различных объекта с тремя составными первичными ключами.
- нереляционно
3. Избыточный.
Для каждого языка создается свой экземпляр объекта.
Достоинства:
- полностью соответсвует соглашению описанному выше.
Недостатки:
- трудности навигации. Для получения содержимого одной и той же статьи на разных языках требуется указать разные идентификаторы
Используя предыдущие методы можно говорить скорее о версиях статьи на разных языках, чем о переводе.
4. Перевод
Забыть про такое понятие как язык и просто использовать тектовые данные как есть. Также завести еще один класс/таблицу переводов. Каждому тексту будет соответствовать запись/объект в классе/таблице переводов. Первичным ключом таблицы переводов может служить оригинальный текст или его хэш. При запросе пользователя будет получен объект, после чего будет проверено предоставлены ли тескстовые данные на том языке на котором их запрашивает пользователь, в случае несоответствия будут найдены переводы текстов из таблицы переводов.
Достоинства:
- полностью исключается понятие языка для текстовых данных и вводится понятие перевода текста.
- полностью соответсвует соглашению описанному выше.
Недостатки:
- Резкое падение производительности при использовании оригинальных текстов как ключа для поиска перевода.
- В случае использования хэша текста появляется проблема разрешения коллизий и в случае если язык интерфейса пользователя не совпадает с оригинальным языком "статьи" теряется возможность поиска по текстовым полям
- отсуствует возможность "правильной" связи текста с записью в таблице переводов.
Дополнительно:
1. Может существовать несколько текстовых полей
Т. е. будет нечто похожее на
таблица_статей.поле_заголовок.значение => таблица_переводов.поле_ключа.значение
все бы хорошо, но текстовых полей может быть больше чем один, следовательно такая связь не будет иметь смысла.
2. Может существовать несколько сущностей/таблицы/классов содержащих текстовые данные.
3. Необходимо иметь возможность безболезненно добавлять/удалять языки
Не знаю, удалось ли мне объяснить проблему, но тем не менее: Как правильнее реализовать модель данных?
Известно, что используя ООП можно построить проекцию реляционной базы данных на програмный код следующим образом:
Сущность == Таблица == Класс
Кортэж = Запись (строка) == Объект класса
Атрибут == Поле (столбец) == Свойство объекта
Такое соглашение очень удобно при реализации ORM, и в некоторых случаях позволяет реализовать генерацию функционала CRUD на основе имеющейся модели данных. До этого места все вроде бы понятно.
Трудности возникают при реализации "многоязыковой" модели данных.
Пример:
Есть класс "статьи", объекты класса хранятся в одноименной таблице, по одной записи на объект. Некоторые свойства класса текстовые, например "заголовок статьи", т. е. они содержат текст на вполне определенном языке, например на русском. В многоязычном сайте такие текстовые поля могут быть представлены на нескольких языках. Например сайт сделан русском, английском и испанском. Таким образом редактор добавляя новую статью должен ввести "заголовок статьи" на данных языках, дабы в дальнейшем при запросе пользователя приложение отобразило "заголовок статьи" на языке текущего интерфейса пользователя. Т. е. на сайт заходит испанец, переключает интерфейс на испанский язык и при запросе статьи получает ее на испанском языке.
Вопрос: Как правильнее реализовать модель данных?
Вопрос не по php, скорее это академический вопрос по реализации модели данных.
На сегодняшний день я нашел несколько вариантов решения, но не один меня не удовлетворил.
1. Тривиальный
Для каждого текстового поля завести столько его дубликатов сколько языков присутствует в системе. Т. е. в таблице базы будет три отдельных поля для русского, английского и испанского названия статьи.
Достоинства:
- соответствует соглашению приведенному выше
- облегчает реализацию автогенерации CRUD функционала.
Недостатки:
- следуя соглашению описанному выше каждое поле это свойство класса, таким образом вместо отображения одного свойства потребуется выбрать из нескольких, что не совсем корректно с точки зрения ООП.
- при добавлении/удалении/изменении языка потребуется переделывать как модель данных, так и классы.
- избыточность, не для всех статей может существовать перевод на другой язык
2. Притянутый за уши
Разбить класс (сущность, таблицу) на две части. Левая часть -- языконезависимая, правая зависит от языка. На одну левую часть создается столько правых частей сколько языков присутствует в системе. Т. е. создается одна запись в таблице "статьи" и три записи в таблице "статьи-языки".
Достоинства:
- псевдореляционно
Недостатки:
- не соответсвует изначальному соглашению, что затрудняет реализацию автогенерации CRUD функционала.
- в действительности используется составной первичный ключ (идентификадор + язык) вместо простого первичного ключа (идентификатор). Т. е. для статьи с номером 5 будет:
5 + русский = содержимое на русском
5 + английский = содержимое на английском
5 + испанский = содержимое на испанском
Что в действительности суть три различных объекта с тремя составными первичными ключами.
- нереляционно
3. Избыточный.
Для каждого языка создается свой экземпляр объекта.
Достоинства:
- полностью соответсвует соглашению описанному выше.
Недостатки:
- трудности навигации. Для получения содержимого одной и той же статьи на разных языках требуется указать разные идентификаторы
Используя предыдущие методы можно говорить скорее о версиях статьи на разных языках, чем о переводе.
4. Перевод
Забыть про такое понятие как язык и просто использовать тектовые данные как есть. Также завести еще один класс/таблицу переводов. Каждому тексту будет соответствовать запись/объект в классе/таблице переводов. Первичным ключом таблицы переводов может служить оригинальный текст или его хэш. При запросе пользователя будет получен объект, после чего будет проверено предоставлены ли тескстовые данные на том языке на котором их запрашивает пользователь, в случае несоответствия будут найдены переводы текстов из таблицы переводов.
Достоинства:
- полностью исключается понятие языка для текстовых данных и вводится понятие перевода текста.
- полностью соответсвует соглашению описанному выше.
Недостатки:
- Резкое падение производительности при использовании оригинальных текстов как ключа для поиска перевода.
- В случае использования хэша текста появляется проблема разрешения коллизий и в случае если язык интерфейса пользователя не совпадает с оригинальным языком "статьи" теряется возможность поиска по текстовым полям
- отсуствует возможность "правильной" связи текста с записью в таблице переводов.
Дополнительно:
1. Может существовать несколько текстовых полей
Т. е. будет нечто похожее на
таблица_статей.поле_заголовок.значение => таблица_переводов.поле_ключа.значение
все бы хорошо, но текстовых полей может быть больше чем один, следовательно такая связь не будет иметь смысла.
2. Может существовать несколько сущностей/таблицы/классов содержащих текстовые данные.
3. Необходимо иметь возможность безболезненно добавлять/удалять языки
Не знаю, удалось ли мне объяснить проблему, но тем не менее: Как правильнее реализовать модель данных?