如何包装 Ecto hstore 字段以自动获取翻译?

How to wrap Ecto hstore field to get translations automatically?

Ruby 中有很多宝石可以做我想在 Elixir 中做的事情:globalize, multilang-hstore, hstore_translate

如何自动化,例如使用 Gettext.get_locale 根据 hstore 字段中的当前语言环境检索翻译?例如,如果我通过 post.tags 的相关 Post 获得它,标签将包含一个字符串列表,以防区域设置为 :en: "tags: ["climbing", "ski"]" 而不是 "tags":[{"name":{"pl":"narty","en":"ski"}},{"name":{"pl":"wspinaczka","en":"climbing"}}]?如何使用 Gettext 处理回退?

defmodule Myapp.Tag do
  use Myapp.Web, :model

  schema "tags" do
    field :name, :map
    belongs_to :post, Myapp.Post
    timestamps
  end

  def match(query, q) do
      from tag in query,
    where: fragment("?->>? ILIKE ?", tag.name, "en", ^(String.downcase(q) <> "%"))
  end
end

defmodule Myapp.TagController do
  use Myapp.Web, :controller
  alias Myapp.Tag

  def search(conn, %{"q" => q}) do
    tags = Tag |> Tag.match(q) |> Repo.all
    render(conn, "options.json", tags: tags)
  end
end

defmodule Myapp.TagView do
  use Myapp.Web, :view

  def render("options.json", %{tags: tags}) do
    %{options: render_many(tags, Myapp.TagView, "option.json")}
  end
  def render("option.json", %{tag: tag}) do
    %{id: tag.id,
      value: tag.name["en"],
      label: tag.name["en"]}
  end
end

defmodule Myapp.PostView do
  use Myapp.Web, :view

  def render("posts.json", %{posts: posts}) do
    %{data: render_many(posts, Myapp.PostView, "post.json")}
  end
  def render("post.json", %{post: post}) do
    %{id: post.id,
      title: post.title,
      tags: post.tags} # <= how to get translated keys
  end
end

Gettext.get_locale Myapp.Gettext 应该 return 根据语言环境。从地图获取值时,您可以设置默认值。例如:

Map.get(map, key, default)

所以你可以这样定义函数:

defp translated_tag_name(tag, default_lang) do
  current_lang = Gettext.get_locale Myapp.Gettext
  Map.get(tag.name, current_lang, Map.get(tag.name[default_lang])
end

您手动执行回退,但很容易使其适用于任何地图。