【问题标题】:I18n segments router PhoenixI18n 分段路由器 Phoenix
【发布时间】:2017-05-17 08:48:23
【问题描述】:

我有一个 Elixir / Phoenix 应用程序,它的反应因域(又名租户)而异。

租户具有特定的语言环境,例如“fr_FR”、“en_US”等。

我想根据当前语言环境翻译路由器的 URI:

# EN
get "/classifieds/new", ClassifiedController, :new

# FR
get "/annonces/ajout", ClassifiedController, :new

到目前为止,我认为可以做类似的事情(伪代码):

if locale() == :fr do

    scope "/", Awesome.App, as: :app do
        pipe_through :browser # Use the default browser stack
        get "/annonces/ajout", ClassifiedController, :new
    end

else

    scope "/", Awesome.App, as: :app do
        pipe_through :browser # Use the default browser stack
        get "/classifieds/new", ClassifiedController, :new
    end

end

它不起作用,因为路由器是在服务器启动期间编译的,所以你没有当前连接的上下文(语言环境、域、主机等)。

到目前为止,我的解决方案(可行)是创建两个具有两个别名的作用域:

scope "/", Awesome.App, as: :fr_app do
  pipe_through :browser # Use the default browser stack
  get "/annonces/ajout", ClassifiedController, :new
end

scope "/", Awesome.App, as: :app do
  pipe_through :browser # Use the default browser stack
  get "/classifieds/new", ClassifiedController, :new
end

和一个关联的助手:

localized_path(conn, path, action)

如果当前语言环境是“fr ”(例如)。如果当前语言环境不存在路径,我会回退到默认语言环境“en”)。

效果很好,但我发现了一些痛点:

  1. 每次使用“something_foo_path()”助手都必须替换为这个新的“localized_pa​​th()”

  2. 该应用程序将接受每个本地化段(fr、en、it 等),这并不是我真正想要的(我只想让 fr 段在租户“fr”上工作

  3. 我应该能够直接在路由器中获取当前的语言环境/连接信息(功能/错误修复?)并避免这样的黑客攻击。

【问题讨论】:

  • "该应用程序将接受每个本地化段(fr、en、it 等),这并不是我真正想要的(我只想让 fr 段在租户 "fr" 上工作" - 我可以创建一个插件来重定向/显示 404 错误,具体取决于当前的语言环境。
  • 如何将路由的所有变体路由到同一个控制器,但有一个检查语言和 URL 的插件,如果 URL 中的语言发送 404(或重定向到正确的)和域不匹配?
  • 因为 app_classified_pa​​th(conn, :new) 将根据在路由器中找到的第一个关联段而不是当前语言环境生成 URL。然后是的,我可以在一个插件中重定向到正确的路线,但出于 SEO 的目的,我希望根据当前的语言环境生成链接。

标签: internationalization elixir phoenix-framework


【解决方案1】:

看看这篇文章Practical i18n with Phoenix and Elixir。我相信它应该给你你所需要的。

或者,您可以使用一些宏来创建翻译路线块。下面的代码不能满足您的所有要求,因为您仍然需要在内部翻译路径。不过,它可能会给你一些想法。

defmodule LocalRoutes.Web.Router do
  use LocalRoutes.Web, :router

  @locales ~w(en fr)
  import LocalRoutes.Web.Gettext
  use LocalRoutes.LocalizedRouter

  def locale(conn, locale) do
    Plug.Conn.assign conn, :locale, locale
  end

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/", LocalRoutes.Web do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index
  end
  for locale <- @locales do
    Gettext.put_locale(LocalRoutes.Web.Gettext, locale)

    pipeline String.to_atom(locale) do
      plug :accepts, ["html"]
      plug :fetch_session
      plug :fetch_flash
      plug :protect_from_forgery
      plug :put_secure_browser_headers
      plug :locale, locale
    end

    scope "/", LocalRoutes.Web do
      pipe_through String.to_atom(locale) 
      get "/#{~g"classifieds"}", ClassifiedController, :index
      get "/#{~g"classifieds"}/#{~g"new"}", ClassifiedController, :new
      get "/#{~g"classifieds"}/:id", ClassifiedController, :show
      get "/#{~g"classifieds"}/:id/#{~g"edit"}", ClassifiedController, :edit
      post "/#{~g"classifieds"}", ClassifiedController, :create
      patch "/#{~g"classifieds"}/:id", ClassifiedController, :update
      put "/#{~g"classifieds"}/:id", ClassifiedController, :update
      delete "/#{~g"classifieds"}/:id", ClassifiedController, :delete
    end
  end
end

defmodule LocalRoutes.LocalizedRouter do

  defmacro __using__(opts) do
    quote do
      import unquote(__MODULE__)
    end
  end

  defmacro sigil_g(string, _) do
    quote do
      dgettext "routes", unquote(string) 
    end
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    • 2021-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多