Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API usecase #21

Open
char0n opened this issue Dec 17, 2019 · 1 comment
Open

API usecase #21

char0n opened this issue Dec 17, 2019 · 1 comment

Comments

@char0n
Copy link

char0n commented Dec 17, 2019

This library is great, but doesn't support API usecase. I have an API and want to use set_locale as a simple mechanism to read the Accept-Language header and setting the locale without any redirects and reading cookies etc. Have you thought about supporting API usecases ?

@char0n
Copy link
Author

char0n commented Dec 17, 2019

I've create a Plug specifically for API usecase for anybody looking for API only solution:

defmodule SetLocale.Api do
  @moduledoc """
  Module for setting locale from Accept-Language header.

  This implementation is appropriate for API use-cases only.
  The only thing this plug does is determining the locale from
  the `Accept-Language` header and setting the locale to gettext.

  The options for the plugs are
   - gettext: mandatory
   - default_locale: mandatory, used as last step in fallback chain
   - additional_locales: optional, if given it allows to whitelist locales that are not defined via Gettext. Possible scenario: You want to use Gettext and some SaaS localization service (e.g. http://bablic.com/) in parallel. Whitelisting these additional languages allows you to have proper routing for the locales and trigger the wanted JS behaviour depending on the assigned locale in your templates.
  """

  import Plug.Conn

  defmodule Config do
    @moduledoc "Struct for SetLocale config."
    @enforce_keys [:gettext, :default_locale]
    defstruct [:gettext, :default_locale, additional_locales: []]
  end

  def init(opts) when is_tuple(hd(opts)), do: struct!(Config, opts)

  def call(%Plug.Conn{} = conn, config) do
    requested_locale = determine_locale(conn, config)

    if supported_locale?(requested_locale, config) do
      if Enum.member?(config.additional_locales, requested_locale) do
        Gettext.put_locale(config.gettext, config.default_locale)
      else
        Gettext.put_locale(config.gettext, requested_locale)
      end
    else
      Gettext.put_locale(config.gettext, config.default_locale)
    end

    assign(conn, :locale, requested_locale)
  end

  defp determine_locale(conn, config) do
    determined_locale = get_locale_from_header(conn, config)

    if supported_locale?(determined_locale, config),
      do: determined_locale,
      else: config.default_locale
  end

  defp get_locale_from_header(conn, gettext) do
    conn
    |> SetLocale.Headers.extract_accept_language()
    |> Enum.find(nil, fn accepted_locale -> supported_locale?(accepted_locale, gettext) end)
  end

  defp supported_locale?(locale, config), do: Enum.member?(supported_locales(config), locale)

  defp supported_locales(config),
    do: Gettext.known_locales(config.gettext) ++ config.additional_locales
end

Would you be interested in PR ? To merge this we'd need to consolidate some code to be able to reuse as much as possible from the original implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant