Updated: Comment #7

Problem/Motivation

Follow-up from #2111349: Move format_plural to the string translation service and format_interval to the date service.. Implementation of #2111349: Move format_plural to the string translation service and format_interval to the date service. is not applied side-wide.

Proposed resolution

Implement #2111349: Move format_plural to the string translation service and format_interval to the date service. by

1. Inject translation service in Base classes (ControllerBase, FormBase and PluginBase) and create a helper method.
2. Use static \Drupal::translation()->formatPlural() call on procedural and test methods.

Remaining tasks

Patch - In progress

User interface changes

N/A

API changes

N/A

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

vijaycs85’s picture

Title: Replace format_plural with format_plural with \Drupal::translation()->formatPlural() » Replace format_plural with \Drupal::translation()->formatPlural()
vijaycs85’s picture

Initial patch...

vijaycs85’s picture

Status: Active » Needs review
penyaskito’s picture

Shouldn't we inject the translation service?

dawehner’s picture

Shouldn't we inject the translation service?

My thoughts!

tim.plunkett’s picture

We should consider adding it to FormBase.

Gábor Hojtsy’s picture

Status: Needs review » Needs work

Exactly, we should not just simply replace the global function calls with global static method calls.

vijaycs85’s picture

Status: Needs work » Needs review
FileSize
78.71 KB
31.63 KB

Ok, injected and created helpers FormBase, ControllerBase and PluginBase and all classes extending them just use by calling $this->formatPlural(). Tests and procedural functions using Drupal::translation()->formatPlural()

vijaycs85’s picture

Issue summary: View changes

Updating issue summary with more details.

The last submitted patch, 8: 2149195-convert-format_plural-8.patch, failed testing.

penyaskito’s picture

FileSize
611 bytes
78.71 KB

Status: Needs review » Needs work

The last submitted patch, 11: 2149195-convert-format_plural-10.patch, failed testing.

penyaskito’s picture

Status: Needs work » Needs review
FileSize
1.11 KB
78.72 KB

I must do the same in FormBase and PluginBase...

Gábor Hojtsy’s picture

BTW we have #2151527: Support for formatPlural() in PHP as format_plural() is deprecated open in potx to track this change in the parser.

vijaycs85’s picture

arrrgh!!! sorry for that copy-paste error and thanks for fixing @penyaskito. So we got below instance of current code base which we may still need to keep:

    // Start writing with the function to be called.
    $compiler->write('echo ' . (empty($plural) ? 't' : 'format_plural') . '(');
penyaskito’s picture

FileSize
79.36 KB
661 bytes

Let's try to change it.

ParisLiakos’s picture

Issue tags: -PHPUnit +PHPUnit Blocker

i dont see any phpunit tests for reviews, so i guess the correct tag is this one

ParisLiakos’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

And since i am here

+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockCreationTest.php
@@ -188,7 +188,7 @@ public function testBlockDelete() {
-    $this->assertText(format_plural(1, 'This will also remove 1 placed block instance.', 'This will also remove @count placed block instance.'));
+    $this->assertText(\Drupal::translation()->formatPlural(1, 'This will also remove 1 placed block instance.', 'This will also remove @count placed block instance.'));

+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentNonNodeTest.php
@@ -197,7 +197,7 @@ function performCommentOperation($comment, $operation, $approval = FALSE) {
-      $this->assertRaw(format_plural(1, 'Deleted 1 comment.', 'Deleted @count comments.'), format_string('Operation "@operation" was performed on comment.', array('@operation' => $operation)));
+      $this->assertRaw(\Drupal::translation()->formatPlural(1, 'Deleted 1 comment.', 'Deleted @count comments.'), format_string('Operation "@operation" was performed on comment.', array('@operation' => $operation)));

+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php
@@ -311,7 +311,7 @@ function performCommentOperation(CommentInterface $comment, $operation, $approva
-      $this->assertRaw(format_plural(1, 'Deleted 1 comment.', 'Deleted @count comments.'), format_string('Operation "@operation" was performed on comment.', array('@operation' => $operation)));
+      $this->assertRaw(\Drupal::translation()->formatPlural(1, 'Deleted 1 comment.', 'Deleted @count comments.'), format_string('Operation "@operation" was performed on comment.', array('@operation' => $operation)));

+++ b/core/modules/file/lib/Drupal/file/Tests/FileManagedTestBase.php
@@ -78,7 +78,7 @@ function assertFileHookCalled($hook, $expected_count = 1, $message = NULL) {
-        $message = format_plural($actual_count, 'hook_file_@name was not expected to be called but was actually called once.', 'hook_file_@name was not expected to be called but was actually called @count times.', array('@name' => $hook, '@count' => $actual_count));
+        $message = \Drupal::translation()->formatPlural($actual_count, 'hook_file_@name was not expected to be called but was actually called once.', 'hook_file_@name was not expected to be called but was actually called @count times.', array('@name' => $hook, '@count' => $actual_count));

+++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php
@@ -167,7 +167,7 @@ function testForum() {
-    $unread_topics = format_plural($unread_topics, '1 new post', '@count new posts');
+    $unread_topics = \Drupal::translation()->formatPlural($unread_topics, '1 new post', '@count new posts');

+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocalePluralFormatTest.php
@@ -126,7 +126,7 @@ function testGetPluralFormat() {
-        $this->assertIdentical(format_plural($count, '1 hour', '@count hours', array(), array('langcode' => $langcode)), $expected_plural_string, 'Plural translation of 1 hours / @count hours for count ' . $count . ' in ' . $langcode . ' is ' . $expected_plural_string);
+        $this->assertIdentical(\Drupal::translation()->formatPlural($count, '1 hour', '@count hours', array(), array('langcode' => $langcode)), $expected_plural_string, 'Plural translation of 1 hours / @count hours for count ' . $count . ' in ' . $langcode . ' is ' . $expected_plural_string);

@@ -214,7 +214,7 @@ function testPluralEditExport() {
-    format_plural(1, '1 day', '@count days', array(), array('langcode' => 'fr'));
+    \Drupal::translation()->formatPlural(1, '1 day', '@count days', array(), array('langcode' => 'fr'));

+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -1078,7 +1078,7 @@ protected function tearDown() {
-        $message = format_plural($emailCount, '1 e-mail was sent during this test.', '@count e-mails were sent during this test.');
+        $message = \Drupal::translation()->formatPlural($emailCount, '1 e-mail was sent during this test.', '@count e-mails were sent during this test.');

+++ b/core/modules/user/lib/Drupal/user/Tests/UserLoginTest.php
@@ -149,7 +149,7 @@ function assertFailedLogin($account, $flood_trigger = NULL) {
-        $this->assertRaw(format_plural(\Drupal::config('user.flood')->get('user_limit'), 'Sorry, there has been more than one failed login attempt for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', 'Sorry, there have been more than @count failed login attempts for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password'))));
+        $this->assertRaw(\Drupal::translation()->formatPlural(\Drupal::config('user.flood')->get('user_limit'), 'Sorry, there has been more than one failed login attempt for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', 'Sorry, there have been more than @count failed login attempts for this account. It is temporarily blocked. Try again later or <a href="@url">request a new password</a>.', array('@url' => url('user/password'))));

+++ b/core/modules/user/lib/Drupal/user/Tests/Views/HandlerFilterUserNameTest.php
@@ -108,7 +108,7 @@ public function testAdminUserInterface() {
-    $message = format_plural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));
+    $message = \Drupal::translation()->formatPlural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));

@@ -120,7 +120,7 @@ public function testAdminUserInterface() {
-    $message = format_plural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));
+    $message = \Drupal::translation()->formatPlural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));

@@ -130,7 +130,7 @@ public function testAdminUserInterface() {
-    $message = format_plural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));
+    $message = \Drupal::translation()->formatPlural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));

@@ -147,7 +147,7 @@ public function testExposedFilter() {
-    $message = format_plural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));
+    $message = \Drupal::translation()->formatPlural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));

@@ -157,7 +157,7 @@ public function testExposedFilter() {
-    $message = format_plural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));
+    $message = \Drupal::translation()->formatPlural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));

we are supposed to use $this->container->get() inside simpletests instead of \Drupal

Also a reroll

penyaskito’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
15.03 KB
78.44 KB

Rerolled and used $this->container->get('string_translation')->formatPlural() in tests. Thanks for the review, Paris!

tim.plunkett’s picture

penyaskito’s picture

Plain reroll of #16 per #20.

Status: Needs review » Needs work

The last submitted patch, 21: 2149195-formatPlural-21.patch, failed testing.

penyaskito’s picture

Status: Needs work » Needs review

21: 2149195-formatPlural-21.patch queued for re-testing.

penyaskito’s picture

21: 2149195-formatPlural-21.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, 21: 2149195-formatPlural-21.patch, failed testing.

The last submitted patch, 21: 2149195-formatPlural-21.patch, failed testing.

vijaycs85’s picture

Status: Needs work » Needs review
FileSize
78.13 KB

Re-roll...

penyaskito’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll
herom’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
78.12 KB
dawehner’s picture

Status: Needs review » Reviewed & tested by the community

There aren't any out of scope changes and the patch is green.

webchick’s picture

Status: Reviewed & tested by the community » Needs review
+++ b/core/includes/common.inc
@@ -862,12 +862,12 @@ function format_xml_elements($array) {
- *   $output = format_plural($node->comment_count, '1 comment', '@count comments');
+ *   $output = \Drupal::translation()->formatPlural($node->comment_count, '1 comment', '@count comments');

+++ b/core/lib/Drupal/Core/Update/Form/UpdateScriptSelectionForm.php
@@ -105,7 +105,7 @@ public function buildForm(array $form, array &$form_state) {
-        $form['start']['#title'] = format_plural(
+        $form['start']['#title'] = $this->formatPlural(

Hm. We've gone from "always call format_plural()" to sometimes call $this->formatPlural() and other times call \Drupal::translation()->formatPlural(). This does not seem to be a huge DX win for me. :\

t() is a bit different because in either case you're calling (whatever OO crap)->t() as opposed to sometimes (but not always) needing to know it's buried underneath a top-level "translation()" object instead.

In other words, I think we should either make it a top-level method on Drupal, or we should make the base classes mock translation() as well, so calls to this can be consistent throughout the code base.

vijaycs85’s picture

Ok we have injected to OO so $this->formatPlural works whereas procedural code we have no option except to use \Drupal::translation()->formatPlural(). IMHO, this is only better way until get all OO.

reg: t() we haven't done t() for procedural. So t() is 1 step behind what we have for formatPlural(). - We have the implementation in place, but not deprecated t() calls.

function t($string, array $args = array(), array $options = array()) {
  return \Drupal::translation()->translate($string, $args, $options);
}

ideally we should use \Drupal::translation()->translate() instead of t().

webchick’s picture

Why..? That is exposing super unimportant implementation details to someone who just. wants. to. freaking. print. a. string. :)

dawehner’s picture

Why..? That is exposing super unimportant implementation details to someone who just. wants. to. freaking. print. a. string. :)

Wait for traits, which will add t()\formatPlural() to every possible class.

tim.plunkett’s picture

deally we should use \Drupal::translation()->translate() instead of t().

Nope, because that would break localize.d.o, which is the entire reason t() exists.

Wait for traits, which will add t()\formatPlural() to every possible class.

Yep, this. See #2079797: Provide a trait for $this->t() and $this->formatPlural(), we need an equivalent.

webchick’s picture

Yeah, traits are where we ultimately want to go, but there are a pile of dependencies between here and there, starting with #2135199-35: Provide php 5.4 testing on testbots for D8 code without breaking everything else.

My concerns for the purposes of committing this particular patch can be addressed by merely adding a formatPlural() method straight onto the Drupal class, so it retains parity with t(). If we can't or won't do that for some reason, I'd love to understand why, and also how we plan to explain to module developers why sometimes they need an extra ->translate() indirection prior to calling the function they have in mind.

sun’s picture

Issue tags: +API clean-up, +@deprecated
dawehner’s picture

My concerns for the purposes of committing this particular patch can be addressed by merely adding a formatPlural() method straight onto the Drupal class, so it retains parity with t(). If we can't or won't do that for some reason, I'd love to understand why, and also how we plan to explain to module developers why sometimes they need an extra ->translate() indirection prior to calling the function they have in mind.

We don't have a t() method on the \Drupal class as well for a good reason. We need to encourage people to write proper code/inject dependencies instead of writing sort of procedural code. People will understand that they need a method on a class or a dependency before they can do anything.

dawehner’s picture

FileSize
78.28 KB

Just in case, here is also a reroll.

naveko’s picture

FileSize
34.23 KB

Reworked the latest patch, leaving out the static method call \Drupal::translation()->formatPlural(). There is no agreement on whether to use the static method instead of format_plural, but on the implementation of formatPlural in the Base Classes there is.

Status: Needs review » Needs work

The last submitted patch, 40: format_plural-2149195.patch, failed testing.

rych’s picture

Status: Needs work » Needs review
FileSize
33.13 KB

Status: Needs review » Needs work

The last submitted patch, 42: format_plural-2149195_42.patch, failed testing.

Gábor Hojtsy’s picture

The forum block tests fail. Is that using views already? :) No direct forum changes are in this patch.

Gábor Hojtsy’s picture

Status: Needs work » Needs review

42: format_plural-2149195_42.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, 42: format_plural-2149195_42.patch, failed testing.

Gábor Hojtsy’s picture

Issue tags: -sprint

Remove from sprint.

herom’s picture

reroll. let's see what's failing, then I'll try fixing it.

herom’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 48: format_plural-2149195_48.patch, failed testing.

herom’s picture

Assigned: herom » Unassigned
Status: Needs work » Needs review
FileSize
29.36 KB
2.23 KB

reverted a couple of $this->formatPlural()s in procedural code.

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +DX (Developer Experience)

This now sets up formatPlural() on base classes like t() and uses it as appropriate. This looks sane from a DX point of view so there is no difference between t() and format_plural() for calling a local method vs. a global function.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Looks like this is covered in the change record at https://drupal.org/node/2173787

Committed and pushed to 8.x. Thanks!

Gábor Hojtsy’s picture

Yay, thanks all!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.