Cldr locale name not known while trying to download

I’m trying to setup Cldr for a project, and I want to set Cldr locales as the locales we have for Gettext. So I am doing this

defmodule MyApp.Cldr do
  use Cldr,
    default_locale: "en",
    locales: Gettext.known_locales(MyApp.Gettext) ,
    gettext: MyApp.Gettext,
end

but then Cldr complains with

note: The locale "pt_BR" is configured in the MyApp.Gettext gettext backend but is unknown to CLDR. It will not be used to configure CLDR but it will still be used to match CLDR locales to Gettext locales at runtime.

== Compilation error in file lib/my_app/cldr.ex ==
** (Cldr.UnknownLocaleError) Failed to install the locale named :pt_BR. The locale name is not known.
    (ex_cldr 2.40.1) lib/cldr/install.ex:93: Cldr.Install.do_install_locale_name/3
    (elixir 1.17.2) lib/enum.ex:987: Enum."-each/2-lists^foreach/1-0-"/2
    (ex_cldr 2.40.1) lib/cldr/install.ex:29: Cldr.Install.install_known_locale_names/1
    (ex_cldr 2.40.1) lib/cldr.ex:102: Cldr.install_locales/1
    (ex_cldr 2.40.1) expanding macro: Cldr.Backend.Compiler.__before_compile__/1
    lib/my_app/cldr.ex:1: MyApp.Cldr (module)

So it just raises because of pt_BR, which is not an available locale in Cldr as far as I understand, also this answer helped understand it better. Also these are the available locales in ex_cldr.

However, this is handled in code when you want to validate the locale pt-BR or pt_BR.

iex(9)> MyApp.Cldr.validate_locale "pt_BR"
{:ok, MyApp.Cldr.Locale.new!("pt-BR")}
  1. Should this also be handled by ex_cldr when downloading locales?
  2. So in this case, should I just be doing something like :point_down:
defmodule MyApp.Cldr do
  use Cldr,
    default_locale: "en",
    # Though I think this wouldn't work if I didn't have both `pt.po` and `pt_BR.po`
    # i.e. `pt` wouldn't be in known locales
    locales: Gettext.known_locales(MyApp.Gettext) -- ["pt_BR"] ,
    gettext: MyApp.Gettext,
end
  1. or is there a better way to handle this? Well, another way is to basically just rename the translation file I guess.

Edit: Seems like you don’t even need to mention locales when you pass gettext backend. (source)

:gettext: specifies the name of a Gettext module that informs ex_cldr to use that module as an additional source of locales you want to configure.

As you found, CLDR doesn’t have locale data for pt-BR. In the same way it doesn’t have locale data for en-US. The region of the world that has the highest population of speakers of a given language is the default for that language. Therefore the language tags are en and pt - since Brazil has the largest number of Portuguese speakers.

Knowing this, the ex_cldr configuration would be:

defmodule MyApp.Cldr do
  use Cldr,
    default_locale: "en",
    # Add the "pt" locale, whose data is applicable to Portuguese in Brazil
    locales: ["pt"],
    gettext: MyApp.Gettext
end

However, this is handled in code when you want to validate the locale…

Yes, the code tries to play nicely even when not everything lines up perfectly as you discovered. With “pt” configured in you Cldr backend you would see:

iex> {:ok, locale} = MyApp.Cldr.put_locale "pt"
{:ok, MyApp.Cldr.Locale.new!("pt-BR")}
iex> locale.requested_locale_name
"pt"
iex> locale.gettext_locale_name
"pt_BR"
iex> locale.cldr_locale_name
:pt

And the same results for requesting pt-BR:

iex> {:ok, locale} = MyApp.Cldr.put_locale "pt-BR"
{:ok, MyApp.Cldr.Locale.new!("pt-BR")}
iex> locale.requested_locale_name
"pt-BR"
iex> locale.gettext_locale_name
"pt_BR"
iex> locale.cldr_locale_name
:pt
2 Likes