Follow-up to #2573975: function_exists check in PluralTranslatableString is wrong and #2571375: Remove TranslationManager dependency from LanguageManager
Postponed on:
#3590050: Deprecate and replace locale_status related functions
#3581303: Convert locale batch callbacks
#3037156: Modernize locale history functions
Problem/Motivation
Locale module has many functions let's review and deprecate:
- locale_get_plural
Steps to reproduce
Notes about locale_get_plural
- Enabled Language and Interface Translation
- Added Romanian
- Found some text that uses plurals: Module %name has been enabled.
- Changed the plurals for these for Romanian
- Enabled some modules (1 module, 2 modules, and 3 modules)
- The messages were as expected (see screenshots below) (though I'm not sure what the 2. plural is for in Romanian)
Proposed resolution
TBD
Remaining tasks
User interface changes
API changes
Data model changes
N/A
| Comment | File | Size | Author |
|---|
Issue fork drupal-2660338
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
alexpottNo that the major issue is fixed. I think this can be treated as a normal bug.
Comment #4
claudiu.cristea#2766857: Provide a PluralTranslatableMarkup::getPluralVariantIndex() factory method is related.
Comment #5
claudiu.cristeaHere's patch.
Comment #6
claudiu.cristeaSmall improvement.
Comment #9
claudiu.cristeaAdded the missed service in unit tests container.
Comment #10
kristen polThanks for the patch. I have reviewed it and don't see any obvious issues though there are some comments that should be changed slightly.
I had not heard "zero-based positive integer" used before. I googled it and it does appear to be used but it might be better to change to something like:
...implementation should return zero, a positive integer, or...
The "he" should be changed to be gender neutral. In other places "you" is used. Or, the sentence could be restructured something like:
The implementation should return zero, a positive integer, or, to not impact the results, nothing.
Typo:
local_get_plural => locale_get_plural
Typo:
Local => Locale
I'll test the patch shortly.
Comment #11
kristen polI've tested this as follows:
Comment #12
kristen polAssigning to myself to make the comment changes. I will try to finish this today.
Comment #13
kristen polStill plan on working on this but the day got away from me. Crossing fingers for tomorrow. If I don't finish by Friday EOD, then I'll take my name off.
Comment #15
kristen polI reworded some of the comments. Here's the patch and interdiff.
Comment #16
kristen polComment #17
claudiu.cristea@Kristen Pol, thank you for your work and review. Sorry for my poor English. I think the patch looks good. I'm not very sure yet about the solution: if invoking a hook is the way to go. Also I don't find it bad. Probably in 99.99% of the cases nobody will implement such a hook and we'll live with the only implementation which is
locale_plural_variant_index(). Normally we should offer also an "alter hook" but for me that sounds a little bit over-engineering.Nit:
Compute > Computes
Comment #21
alberto56 commentedThis might be related to #2273889: Don't use one language's plural index formula with another language's string in the case of untranslated strings using format_plural()., in the sense that computing the plural index requires more information than just the target language -- we also need to know the string itself: if no translation exists for a string, we should not be using the target language plural index, but rather -1, it seems. Perhaps the string itself could be passed to hook_plural_variant_index, so that the locale_plural_variant_index could then check if the string is, in fact, translated; if it is not then the plural variant index would always be -1.
Comment #22
alexpottI don't think a new hook is a way to do this. I think PluralTranslatableMarkup should be asking the TranslationManager for the plurals and then when locale is enabled it should be wrapping the TranslationManager service and enhancing the getPluralIndex method. A new hook adds an extension a new extension point that's not needed.
Comment #23
alexpottHere's #21 implemented but not yet working. This could be becasue of how code / services are loaded.
No interdiff because a different approach.
Comment #26
claudiu.cristeaWe can also deprecate
locale_get_plural()in the scope of this issue as in #23, the procedural function became only a wrapper of the service method call.Also this approach help us also to remove usages of
drupal_static()anddrupal_static_reset()fromlocale_get_plural()and this makes this part of the #1577902: [META] Remove all usages of drupal_static() & drupal_static_reset() effort.Comment #27
andypostReroll, looks tests do a lot of mocks for services so instead of strings translatable object returns
Comment #28
andypostDebugging test
\Drupal\Tests\Core\Datetime\DateTest::testFormatInterval()shows thatcountpassed wrong somehowComment #30
andypostShould fix some tests
Comment #32
andypostDecorated service should implement all public methods
Comment #34
andypostreroll
Comment #38
ridhimaabrol24 commentedReroll patch for 9.1.x.
Comment #39
ridhimaabrol24 commentedFixing the error in patch #38.
Comment #40
kristen polThanks for the patch. I tried testing it twice (two different installs) but keep getting an error after adding the language:
When the patch is updated, here are a few nitpicks that could be addressed:
Nitpick: Character wrapping (move some words up).
Nitpick: Comment should be a sentence with starting capital and ending period.
Nitpick: More than 80 chars.
Nitpick: Extra empty line.
Comment #41
ravi.shankar commentedComment #42
ravi.shankar commentedComment #43
adityasingh commentedComment #44
adityasingh commentedUpdated patch as per the changes suggested in #40, please review.
Comment #45
kristen polThanks for the update. #44 fixes the nitpicks noted in #40.
Comment #46
kristen polTagging for manual testing. I had issues but maybe someone else can try. If you want test steps, see #11.
Comment #47
tanubansal commentedWe have followed the steps given in #11 and after adding the patch mentioned #44 (https://www.drupal.org/pift-ci-job/1751390). While enabling singular/plural modules , its showing 'Site encountered error'. When we refresh the modules page then it should that the module is enable. Please refer the attached screenshots below.
Comment #48
tanubansal commentedComment #49
kristen polOk, since @tanubansal also had an issue, moving this back to needs work.
Comment #50
andypostTests failing because of
Comment #51
andypostAttempt to fix #50
Comment #52
quietone commentedComment #54
quietone commentedPatch fails to apply to 9.2.x setting to NW for that.
The Issue summary needs to have a proposed resolution, adding tag.
Comment #55
ravi.shankar commentedAdded reroll of patch #51 on Drupal 9.2.x.
Comment #56
ravi.shankar commentedFixed custom command fails.
Comment #57
mohit_aghera commentedComment #58
andypostNew method needs CR also it could help to deprecate locale code a bit
Comment #59
mohit_aghera commentedFixing test cases.
All the test cases failing in #56 are passing on local now.
InstallerExistingConfigTesttest is something that is passing without any change. So not sure if past failure was due to other reasons.Comment #61
kristen polPulling out the failure info:
Related code:
Comment #65
andypostComment #66
ravi.shankar commentedAdded reroll of patch #59 on Drupal 9.5.x.
Comment #67
andypostLets see what will fail now
Comment #69
smustgrave commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
For the IS update and change record
Did not test or review yet.
Comment #72
nicxvan commented#3577671: Modernize locale file handling
#3037031: Convert locale.compare.inc to a service
#3037156: Modernize locale history functions
Comment #73
nicxvan commentedI think we combine a few of the remaining functions in locale.module as part of the .module elimination initiative.
There are still 8 issues remaining even if we combine these few.
Comment #74
nicxvan commentedComment #75
nicxvan commentedShould have done the file audit first, locale_get_plural is complex enough, let's just do that one here.
Comment #76
nicxvan commentedComment #79
berdirRemoving postponed status, I think this is fairly conflict-free with other issues (maybe except services.yml, but I've moved the change up and that's easy to rebase) and can be worked on. Created an MR with that. At some point changes to TranslateEditForm snuck in, those seem unrelated and I ignored them.
Comment #80
berdirI think I want to explore adding this method to a new interface + service in core, that should be much easier to overwrite. I'm not found of decorators generally and this also comes with changes to a pretty fundamental interface.
Comment #81
berdirWorking on a new service. That requires updates to a bunch of unit tests, but seems to work well and feels much cleaner.
\Drupal\Core\StringTranslation\StringTranslationTrait::getNumberOfPlurals() is somewhat related to this. That also wraps a locale service. I only identified 3 calls to that. one in locale, one in config_translation and one in views. We could consider to just deprecate that, only the views call doesn't depend on locale anyway. Alternatively we could expand the same of the new interface and add it to that as well.
I'm even wondering if we could somehow reuse the existing \Drupal\locale\PluralFormula service implement the new interface instead of a new one that calls out to it. Would nee to alias and deprecate the current service. This is already complex enough I think.
FWIW, the static/memory cache here feels overkill. what exactly is this even caching? a php calculation?
Comment #82
berdirI think this is ready for review.
Comment #83
nicxvan commentedTook a quick look and had some minor questions, I'll have a clear look in a bit.
Comment #84
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #85
andypostThis is where formula caching been added so not sure it's a good idea to remove #1273968: remove eval from locale.module
Comment #86
berdirThat's not true, locale_get_plural() was already using drupal_static() before that, those lines weren't touched in that commit. and it had been using static caching even before drupal_static(), it had been using the static keyword since that function was added in a commit in 2004 by Dries before there were issues and issue numbers.
Raw PHP execution performance changed *a tiny bit* since 2004, it doesn't look like anyone every questioned whether static caching here is worth it or not. Might not even have been back in 2004.
I did a script that called the function 100k times, it barely registered with microtime() and it made no difference whether or not the static caching is there. I verified how often it's called on the frontpage of umami with disabled render caches: zero times, on the article add form, once.
Rebased and removed it.
Comment #87
nicxvan commentedOk I did a bunch of digging, had a couple of discussions in slack and read a bunch of references.
I think we should find a way to document this here in the comments for future people.
Some of this may be obvious to other people on this thread, but I want to type it out to help ensure I understand it properly.
Different languages have different formulas for plurals: https://docs.translatehouse.org/projects/localization-guide/en/latest/l1...
English for example:
nplurals=2; plural=(n != 1);There are two plural forms and the rule for plurals is if there is 1 say the singular, if there are more or less than 1 then use the plural.
E.g 1 horse, 2 horses, 50 horses, 0 horses, -10 horses.
Other languages have other rules: https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
Polish:
nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);There is some documentation on d.o here: https://www.drupal.org/community/contributor-guide/reference-information...
My understanding is that the formula will be at the top of the .po files.
We then precalculate the plural formula in a compressed way shown here: https://www.drupal.org/project/drupal/issues/1273968#comment-7559379
A translation will look like this:
The 0 or 1 is the plural index.
I think we can fill out and link to this reference on
PluralFormula.And maybe on
LocalePluralIndex