我有一个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”,则路径为(:app_classified_new_path),前缀为 fr (:fr_app_classified_new_path ) “(例如)。如果当前区域设置的路径不存在,我将回退到默认区域设置“en”。)
它运作良好,但我看到了一些痛点:
每次使用“something_foo_path()”助手必须由新的“localized_path()”替换
该应用程序将接受每个本地化细分(fr,en,it,等等)并且它不是我想要的(我想只有fr段才能在租户上工作“fr”
我应该能够直接在路由器中获取当前的locale / conn信息(feature / bugfix?)并避免出现类似黑客攻击。
答案 0 :(得分:3)
看一下这篇文章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