-
Notifications
You must be signed in to change notification settings - Fork 90
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
Supply plurals forms header to Gettext.Plural callbacks #343
Conversation
Pull Request Test Coverage Report for Build 7377b2df5447c0d4d47b3ea46c8da3ff2a7f9220-PR-343Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
If we don't know if this improves performance, I don't think we should do it for now. Let's solve it if it ever becomes a problem? |
@maennchen also, can you elaborate on the purpose of this PR in more details? I'm not really following 😄 |
That highly depends on the implementation of that behaviour. I know that I can make it faster in ExpoPluralForms. That description should probably be worded differently.
Sure :) The purpose of this PR is that the plural form header is passed into Therefore implementations can make decisions based on that header. This will allow it to implement an ExpoPluralForms implementation of the behaviour. Current behaviourGettext has a list of known locales for which ExpoPluralForms behaviourFor various languages, there's not a single way to represent plural rules. For example for chinese there's two different rules depending on the context. ( Also in my own language (swiss german) there's some debate of how to handle Those rules & differences can be represented using the plural forms header. By supplying the plural forms header to the callbacks, the implementation can make decisions as they were intended in gettext. |
@whatyouhide Performance comparison (extended from https://github.com/elixir-gettext/expo_plural_forms/pull/33#issuecomment-1383212655) to illustrate what would happen if the header was parsed on every index call: Mix.install([{:benchee, "~> 1.1"}, {:expo_plural_forms, path: "."}])
{:ok, arabic} = ExpoPluralForms.Known.plural_form("ar")
defmodule Arabic do
def index(n), do: unquote(ExpoPluralForms.compile_index(arabic))
end
Benchee.run(
%{
"precompiled" => fn ->
Arabic.index(17)
end,
"without" => fn ->
ExpoPluralForms.index(arabic, 17)
end,
"including parse" => fn ->
{:ok, arabic} = ExpoPluralForms.parse(" nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5);")
ExpoPluralForms.index(arabic, 17)
end
},
time: 10,
memory_time: 2
) Result:
|
I think this is approaching the problem based on the current solution but, given the limitations you added, I would say the problem needs to be reworked altogether. Likely we want to compile the rules encoded in the header as part of the backend compilation? When you say the PluralForms header, is that a header for the .po file or specific to a given translation/msgid? |
@josevalim The plural forms header is in the The idea with Based on the discussion over in ExpoPluralForms (performance), I think it would make more sense to go a plug like approach. There could be some kind of I'll put the PR back into draft state and implement a cleaner solution. |
and how do you determine which one to use? :) |
@josevalim The user of the library can decide which rule to use when he sets the header in the Many tools like Poedit help a user setting up the headers as well. We have an example of that here in the source:
|
Yeah, I think the |
c22ce54
to
91bb61d
Compare
@josevalim / @whatyouhide I pushed a new version that is a lot simpler and does not cause any changes in the behaviour. Only a new callback is added. |
14a44fb
to
26427fe
Compare
EDIT: Moved to jm/extend_plural_interface...jm/expo-example |
26427fe
to
41e16f2
Compare
@@ -434,10 +467,22 @@ defmodule Gettext.Plural do | |||
"sk" | |||
] | |||
|
|||
@doc false | |||
def init(%{locale: locale, plural_forms_header: plural_forms_header}) do | |||
case read_plural_forms_from_headers(plural_forms_header) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is here to keep gettext.merge --plural-forms 7
working.
It is however not consistent internally. I could for example merge with --plural-forms 1
in a language that has 2+ plural forms.
When using ngettext
, the correct plural forms would not be defined and therefore always result in a missing translation.
As an alternate solution, we could remove the option entirely and make the Gettext.Plural
implementation only work on known formats. If a user wants to add / change a language, he would need to add his own implementation as decribed here:
Line 41 in 41e16f2
defmodule MyApp.Plural do |
Even though I personally like option 2 a lot more, I decided to go with the solution that does not cause breaking changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can deprecate the option and guide users towards the new solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@josevalim That is what I intended to do here: #343 (comment)
Based on the discussion with @whatyouhide I will probably ignore the whole topic for the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a bunch of comments!
|
||
Fallback if not implemented: `"nplurals={nplurals};"` | ||
""" | ||
@callback plural_forms_header(locale()) :: String.t() | nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When does this return nil
, and what does that mean semantically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means that it does not know a rule for that locale. The caller of the function will then just set a partial header with only nplurals defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ignore my previous comment, that is not factually correct. That's what's supposed to happen though. I'll have a look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now it is as I described.
12df317
to
8d701d8
Compare
8d701d8
to
e7bbf36
Compare
e7bbf36
to
7377b2d
Compare
Closes #318 This makes it possible to react precisely to the header instead of using predefined formats.
7377b2d
to
352117b
Compare
@whatyouhide I've adressed all the comments except #343 (comment) Are we sure that we handle the deprecation question correctly? I have removed it but find it a bit strange to keep code (and not even discourage using it) when the behaviour it causes is potentially flawed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great for now, we can deprecate the --plural-forms
option later. 💯
@whatyouhide / @josevalim |
@maennchen no worries! I have some free time, so I can give it a shot if you want. I'm working on polishing docs as well. Thanks for all the work!! 💟 |
@whatyouhide If you’d like to, I don’t mind if you pick it up from here. But otherwise I’m also fine doing myself in a few weeks. However you prefer 😊 I might be able to do some code reviews, so just let me know if I can help. |
…xt#343) Closes elixir-gettext#318 This makes it possible to react precisely to the header instead of using predefined formats.
Closes #318
This makes it possible to react precisely to the header instead of using predefined formats.