Uh oh!
There was an error while loading. Please reload this page.
Supply plurals forms header to Gettext.Plural callbacks - #343
Conversation
Pull Request Test Coverage Report for Build aeac2189c347a744226966f37750f7f56ab3a25d-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 |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
whatyouhide
commented
Jan 15, 2023
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? |
whatyouhide
commented
Jan 15, 2023
@maennchen also, can you elaborate on the purpose of this PR in more details? I'm not really following 😄 |
maennchen
commented
Jan 15, 2023
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. |
maennchen
commented
Jan 15, 2023
@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")defmoduleArabicdodefindex(n),do: unquote(ExpoPluralForms.compile_index(arabic))endBenchee.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: |
josevalim
commented
Jan 15, 2023
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? |
maennchen
commented
Jan 15, 2023
@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. |
josevalim
commented
Jan 15, 2023
and how do you determine which one to use? :) |
maennchen
commented
Jan 15, 2023
@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: |
whatyouhide
commented
Jan 15, 2023
Yeah, I think the |
c22ce54 to
91bb61dComparemaennchen
commented
Jan 15, 2023
@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
26427feCompare
EDIT: Moved to jm/extend_plural_interface...jm/expo-example |
26427fe to
41e16f2Compare| @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.
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
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.
Maybe we can deprecate the option and guide users towards the new solution.
There was a problem hiding this comment.
@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.
whatyouhide
left a comment
There was a problem hiding this comment.
Left a bunch of comments!
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| Fallback if not implemented: `"nplurals={nplurals};"` | ||
| """ | ||
| @callback plural_forms_header(locale()) :: String.t() | nil |
There was a problem hiding this comment.
When does this return nil, and what does that mean semantically?
There was a problem hiding this comment.
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.
Ignore my previous comment, that is not factually correct. That's what's supposed to happen though. I'll have a look.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
12df317 to
8d701d8Compare8d701d8 to
e7bbf36CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
e7bbf36 to
7377b2dCompareCloses#318 This makes it possible to react precisely to the header instead of using predefined formats.
7377b2d to
352117bComparemaennchen
commented
Jan 20, 2023
@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. |
whatyouhide
left a comment
There was a problem hiding this comment.
This is great for now, we can deprecate the --plural-forms option later. 💯
maennchen
commented
Jan 20, 2023
@whatyouhide / @josevalim |
whatyouhide
commented
Jan 20, 2023
@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!! 💟 |
maennchen
commented
Jan 20, 2023
@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) Closeselixir-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.