I18n with Phoenix LiveView

16082 단어 liveviewelixirphoenix
Phoenix LiveView에서 I81n을 사용하시겠습니까? 저도 그랬습니다. 하지만 Phoenix LiveView에서 gettext/1를 즉시 사용할 수는 없습니다. 그것을하는 방법을 알아내는 데 몇 시간이 걸렸습니다. 레시피는 다음과 같습니다. 모두 복사 붙여넣기 하시면 됩니다. exampleExample 를 검색하고 바꾸십시오.

설정



mix phx.new example --live
cd example

내 예제 응용 프로그램은 영어(en)와 독일어(de)를 특징으로 하며 기본적으로 영어로 설정되어 있습니다. 따라서 config/config.ex 끝에 이것을 추가해야 합니다.

config :example, ExampleWeb.Gettext,
  default_locale: "en",
  locales: ~w(en de)


브라우저에 묻기



사용할 언어를 결정하는 몇 가지 방법이 있습니다. 제 생각에는 브라우저의 "accept-language" 헤더가 좋은 방법입니다. 다른 방향으로 가고 싶다면 이 플러그가 좋은 출발점입니다. "accept-language"를 사용하고 사용된 언어를 설정하기 위해 새 플러그를 생성합니다.

lib/example_web/plug/local_plug.ex

defmodule ExampleWeb.Plugs.Locale do
  import Plug.Conn

  def init(_opts), do: nil

  def call(conn, _opts) do
    accepted_languages = extract_accept_language(conn)
    known_locales = Gettext.known_locales(ExampleWeb.Gettext)

    accepted_languages =
      known_locales --
        (known_locales -- accepted_languages)

    case accepted_languages do
      [locale | _] ->
        Gettext.put_locale(ExampleWeb.Gettext, locale)

        conn
        |> put_session(:locale, locale)

      _ ->
        conn
    end
  end

  # Copied from
  # https://raw.githubusercontent.com/smeevil/set_locale/fd35624e25d79d61e70742e42ade955e5ff857b8/lib/headers.ex
  def extract_accept_language(conn) do
    case Plug.Conn.get_req_header(conn, "accept-language") do
      [value | _] ->
        value
        |> String.split(",")
        |> Enum.map(&parse_language_option/1)
        |> Enum.sort(&(&1.quality > &2.quality))
        |> Enum.map(& &1.tag)
        |> Enum.reject(&is_nil/1)
        |> ensure_language_fallbacks()

      _ ->
        []
    end
  end

  defp parse_language_option(string) do
    captures = Regex.named_captures(~r/^\s?(?<tag>[\w\-]+)(?:;q=(?<quality>[\d\.]+))?$/i, string)

    quality =
      case Float.parse(captures["quality"] || "1.0") do
        {val, _} -> val
        _ -> 1.0
      end

    %{tag: captures["tag"], quality: quality}
  end

  defp ensure_language_fallbacks(tags) do
    Enum.flat_map(tags, fn tag ->
      case String.split(tag, "-") do
        [language, _country_variant] ->
          if Enum.member?(tags, language), do: [tag], else: [tag, language]

        [_language] ->
          [tag]
      end
    end)
  end
end


이 플러그를 파이프라인에 포함시켜야 합니다.

lib/example_web/router.ex

defmodule ExampleWeb.Router do
  use ExampleWeb, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_live_flash
    plug :put_root_layout, {ExampleWeb.LayoutView, :root}
    plug :protect_from_forgery
    plug :put_secure_browser_headers
    plug ExampleWeb.Plugs.Locale # <-----
  end
  [...]


I18n이 포함된 LiveView Hello World



좋은 헬로 월드! 예시:

lib/example_web/live/page_live.ex

defmodule ExampleWeb.PageLive do
  use ExampleWeb, :live_view
  import Gettext, only: [with_locale: 2]

  @impl true
  def mount(_params, session, socket) do
    locale = case session do
      %{"locale" => locale} -> locale
      _ -> "en"
    end

    socket =
      socket
      |> assign(locale: locale)

    {:ok, socket}
  end

  def render(assigns) do
    ~L"""
    <%= with_locale(@locale, fn -> %>
      <%= gettext "Hello World!" %></h2>
    <% end) %>
    """
  end
end


번역


gettext 번역을 위한 구성 파일을 생성해야 합니다.
  • mix gettext.extract --merge
  • mix gettext.merge priv/gettext --locale de

  • 다음은 번역에 사용해야 하는 파일입니다.

    priv/gettext
    ├── de
    │   └── LC_MESSAGES
    │       ├── default.po
    │       └── errors.po
    ├── default.pot
    └── errors.pot
    
    priv/gettext/de/LC_MESSAGES/default.po(독일어 번역)의 내용은 다음과 같습니다.

    ## "msgid"s in this file come from POT (.pot) files.
    ##
    ## Do not add, change, or remove "msgid"s manually here as
    ## they're tied to the ones in the corresponding POT file
    ## (with the same domain).
    ##
    ## Use "mix gettext.extract --merge" or "mix gettext.merge"
    ## to merge POT files into PO files.
    msgid ""
    msgstr ""
    "Language: de\n"
    "Plural-Forms: nplurals=2\n"
    
    #, elixir-format
    #: lib/example_web/live/page_live.ex:17
    msgid "Hello World!"
    msgstr "Hallo Welt!"
    

    다음은 Gettext 사용에 대한 추가 문서입니다.
  • https://phrase.com/blog/posts/i18n-for-phoenix-applications-with-gettext/
  • http://blog.plataformatec.com.br/2016/03/using-gettext-to-internationalize-a-phoenix-application/

  • 이 모든 작업 후에 애플리케이션을 시작할 수 있습니다.

    mix phx.server
    

    그게 다야!



    내 트위터 계정:

    추신: LiveView 구성 요소를 다루려는 경우 https://www.paulfioravanti.com/blog/internationalisation-phoenix-live-components/https://www.paulfioravanti.com/blog/internationalisation-phoenix-live-components/을 살펴보십시오.

    좋은 웹페이지 즐겨찾기