PostgreSQL, как реализовать I18n используя hstore?

Хочу написать сайт с поддержкой мультиязычности. Использую Ruby и Sequel.

Решил все переводы модели хранить в одной таблице, где мультиязычное свойство будет в формате HStore.
---
id : PK
title : {"ru"=>"Название по русски", "en"=>"Название по английски"}
info : {"ru"=>"Описание по русски", "en"=>"Описание по английски"}
---

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

В теории проблем не было, пока не задумался о количестве запросов к БД.

Есть у кого готовые SQL функции или другие решения на этот счёт?

Например было бы не плохо иметь функцию на стороне сервера БД, которой передаём массив локалей ["ru", "en", "de"] в порядке их приоритета, а она нам возвращает подходящее значение.

Обновление 1 ================


Вот что я накодил. Пока только SQL.

Допустим у нас есть такая табличка

CREATE TABLE countries
(
  id serial NOT NULL,
  name hstore NOT NULL,
  capital hstore NOT NULL,
  locale character varying(2) NOT NULL,
  CONSTRAINT countries_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE countries
  OWNER TO distrozine;

CREATE INDEX countries_name_capital_idx
  ON countries
  USING gin
  (name, capital);


Где name и capital мультиязычные свойства, а locale определяет родную локаль для объекта.

Вот содержимое этой таблички
879d83e64e6c47dabd50855476eeb8ae.png

А вот таким запросом мы вытаскиваем данные с учётом мультиязычности

SELECT
  id,
  (array_remove(name -> ARRAY['ru','en', locale], NULL))[1] AS name,
  (array_remove(capital -> ARRAY['ru','en', locale], NULL))[1] AS capital,
  locale
  FROM countries;


выполнив получим вот это

52a9ed654d7d4fbcbf57d52ab4c5c34a.png

ARRAY['ru','en', locale] в запросе указывает нужные нам локали выставленные по приоритету, при этом в конце указываем, что если ни одной подходящей нам локали нет, то берём ту, что указанна родной для объекта.

Например в случае примера предпологается, что 'ru' - текущая локаль, а 'en' локаль по умолчания
  • Вопрос задан
  • 985 просмотров
Решения вопроса 1
@xtsidx Автор вопроса
Разобрался сам с задачей.

Вот простенький плагин реализующий то, что мне нужно.
module Sequel
	module Plugins
		module I18nModel

			def self.apply(model, opts={})
				model.instance_eval do
					@i18n_columns = opts[:i18n_columns]
				end
			end
			
			module ClassMethods
			
				def i18n(options = {})
					locales = options[:locales].clone
					locales << :locale
					locales = locales.pg_array
					ds = select
					@i18n_columns.each do|c|
						ds = ds.select_append(Sequel.lit("(array_remove(? -> ?, NULL))[1]", c, locales).as(c))
					end
					return ds
				end
			
			end
			
		end
	end
end


Для модели нужно будет вызвать метод i18n, в парамере locale передать массив локалей по приоритету. Всё за один запрос.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Freika
@Freika
Senior Ruby on Rails developer
https://github.com/bithavoc/multilang-hstore не подойдет? Правда там activerecord используется вроде.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы