Closed alaadahmed closed 3 years ago
Sorry for the inconvenience @alaadahmed. It's a documentation error which I've now fixed to read:
There is an experimental plurals module for Gettext called MyApp.Cldr.Gettext.Plural
(where MyApp.Cldr
is the name of your backend module). It is configured in Gettext
by:
defmodule MyApp.Gettext do
use Gettext, otp_app: :my_app, plural_forms: MyApp.Cldr.Gettext.Plural
end
Basically, in your case, use use Gettext, plural_forms: MyApp.Cldr.Gettext.Plural
where MyApp.Cldr
is the name of your CLDR backend module.
Please report back if that now works for you - and of course please definitely report back if it does not!
Yes I understand that MyApp.Cldr
is my CLDR backend, I did actually what you said but it didn't work either.
== Compilation error in file lib/ahram_school_web/gettext.ex ==
** (UndefinedFunctionError) function AhramSchoolWeb.Cldr.Gettext.Plural.nplurals/1 is undefined (module AhramSchoolWeb.Cldr.Gettext.Plural is not available)
AhramSchoolWeb.Cldr.Gettext.Plural.nplurals("ar")
(gettext 0.18.2) lib/gettext/compiler.ex:587: Gettext.Compiler.warn_if_missing_plural_forms/4
(gettext 0.18.2) lib/gettext/compiler.ex:539: Gettext.Compiler.compile_translation/7
(elixir 1.12.1) lib/enum.ex:1553: Enum."-map/2-lists^map/1-0-"/2
(elixir 1.12.1) lib/enum.ex:1553: Enum."-map/2-lists^map/1-0-"/2
(gettext 0.18.2) lib/gettext/compiler.ex:452: Gettext.Compiler.compile_po_file/4
(gettext 0.18.2) lib/gettext/compiler.ex:407: Gettext.Compiler.compile_serial_po_file/3
(elixir 1.12.1) lib/enum.ex:1553: Enum."-map/2-lists^map/1-0-"/2
(gettext 0.18.2) expanding macro: Gettext.Compiler.__before_compile__/1
lib/ahram_school_web/gettext.ex:1: AhramSchoolWeb.Gettext (module)
(elixir 1.12.1) lib/kernel/parallel_compiler.ex:319: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7
and here is my backend config:
defmodule AhramSchoolWeb.Cldr do
@moduledoc """
Define a backend module that will host our
Cldr configuration and public API.
Most function calls in Cldr will be calls
to functions on this module.
"""
use Cldr,
locales: Gettext.known_locales(AhramSchoolWeb.Gettext),
default_locale: "ar",
providers: [Cldr.Number, Cldr.Calendar, Cldr.DateTime],
add_fallback_locales: true,
gettext: AhramSchoolWeb.Gettext,
otp_app: :ahram_school,
data_dir: "./priv/cldr",
generate_docs: true,
precompile_transliterations: [{:latn, :arab}, {:arab, :latn}],
precompile_number_formats: ["#,##0.00 ¤", "¤#,##0.00"],
force_locale_download: Mix.env() == :prod
end
Thanks for your patience. I've been digging deeper and there is a more fundamental issue I need to resolve relating to compile time dependencies. I'm working on it now but it might take a day or so to finally resolve properly. Will that timing be ok for you?
BTW so happy to see someone working in non-Latin scripts. Please do let me know if you see any other issues!
I was shocked actually with the tremendous amount of efforts you put in these packages, I am the happy one here. Sure take your time, I really appreciate your time and efforts that you will spend or spent already. Thank you and I will report any issue if I found. I read most of documentation today at the morning and it is fascinating.
Still working on this issue. In the meantime, looking at your configuration, I think it can be a bit simpler:
defmodule AhramSchoolWeb.Cldr do
@moduledoc """
Define a backend module that will host our
Cldr configuration and public API.
Most function calls in Cldr will be calls
to functions on this module.
"""
use Cldr,
# not required, get text locales are merged here anyway
# locales: Gettext.known_locales(AhramSchoolWeb.Gettext),
default_locale: "ar",
providers: [Cldr.Number, Cldr.Calendar, Cldr.DateTime],
add_fallback_locales: true,
gettext: AhramSchoolWeb.Gettext,
otp_app: :ahram_school,
# Not required, this is the default given your :otp_app config
# data_dir: "./priv/cldr",
# Not required, this is the default
# generate_docs: true,
precompile_transliterations: [{:latn, :arab}, {:arab, :latn}],
precompile_number_formats: ["#,##0.00 ¤", "¤#,##0.00"],
# Shouldn't be required, locales are downloaded at compile time
# force_locale_download: Mix.env() == :prod
end
Thank you, I modified them now. This is the first time for me to use CLDR in any application, but will not be last.
I thought also, if I removed add_fallback_locales
or I meant set it to false
, this will remove the "root"
locale, but it doesn't!
You are right, the "root" locale is included no matter what you configure. Certain operations require data that is only stored in the "root" locale.
It's possible that I can't actually fix this issue since there is a compile time circular dependency. ex_cldr
needs the Gettext
backend to be compiled before it so that it can find out what locales are configured on it.
The Gettext
backend, when there is a custom :plural_forms
module configured, needs that module compiled before it.
Since the :plural_forms
module is part of ex_cldr
we end up in a dependency loop that can't be resolved.
I have a couple more experiments to try and will see where that leads.
Ah now I understand the reason behind that error. I hope you will reach to some solution for that.
Is it possible to tell ex_cldr
about what locales are configured without Gettext
, I mean enter them manually so it will be compiled successfully, as a workaround, then Gettext
will be also compiled because ex_cldr
already compiled!
I think you might be right. Here's what I'm thinking (not yet proven if it will work satisfactorily):
Cldr.Config.gettext_locales_from_directory/1
or some such name.I was concerned that there are other requirements to have the Gettext module name be always known. But the only requirement is in Cldr.Plug.SetLocale
and I can preserve the current semantics while making the change above.
I may not finish this change until the weekend. Until then, I wonder if you really do need a custom pluralizer in your Gettext backend? Gettext's default pluralizer does a reasonable job so perhaps thats enough and you only configured a custom pluralizer because you thought one was required?
I am not sure really, but I wanted to use it because I have the default one with Gettext doesn't convert numbers to arabic format. For example:
I have <%= ngettext("1 minute read", "%{count} minutes read", read_time(post.content)) %>
. This should be translated to 2 other languages "Arabic" and "German". For German there is no problem, but for Arabic, numbers appear in English i.e: 1,2,3
but I thought if I used the Cldr.Plural it will be in Arabic format i.e: ١،٢،٣،٤،٥
.
So for the mentioned example above, in Arabic it should be: "٣ دقائق قراءة" but what I get is: "3 دقائق قراءة"
So what do you think? Actually I am not in hurry and you can take your time, but it will be very convenient addition if you could manage to solve it, I am not sure!
msgid "1 minute read"
msgid_plural "%{count} minutes read"
msgstr[0] "ثواني قراءة"
msgstr[1] "دقيقة واحدة قراءة"
msgstr[2] "دقيقتين قراءة"
msgstr[3] "%{count} دقائق قراءة"
msgstr[4] "%{count} دقيقة قراءة"
msgstr[5] "%{count} دقيقة قراءة"
And if this is not related to Cldr.Gettext.Plural
or fixing this not related to issue that I mentioned, then I think will fallback to the default Gettext because no other solution.
As you see, I used Cldr.Date.to_string
to show date in arabic
format, and this is fantastic, but when I used ngettext
to show the reading time, numbers still appear in English.
Ah, yes, I see your point. The thing is that Gettext
doesn't know about scripts. So even a custom pluralizer won't help there. I see two approaches you might consider:
Pre-format the number before you do message formatting. For example, instead of <%= ngettext("1 minute read", "%{count} minutes read", read_time(post.content)) %>
, do (not tested!):
<%= ngettext("1 minute read", "%{minutes} minutes read", read_time(post.content), minutes: Cldr.Number.to_string(read_time(post.content), locale: "ar") %>
It may be that ex_cldr_messages fits your needs better because it is designed for I18n and formats "everything" in a localised way. Its not a full translation library but @tmbb has been working on a very very cool library called ex_i18n that is an alternative to Gettext
(and much better in my opinion).
Thanks a lot, I will check that out. I think then you can close this issue if anyway Cldr.Gettext.Plural
is experimental and not related to the issue.
I really appreciate you opening the issue. It identified a bug (and a lack of tests) that I need to fix and thats very helpful.
True that its unrelated to the original challenge you had but I hope the options above will help get you there. I will close this now, and respond to the issue you raised on ex_cldr_numbers
:-)
I was following documentation and trying to add this
use Gettext, plural_forms: Cldr.Gettext.Plural
to myMyApp.Gettext
module, but I got this error