The Book module does not fully use the new translation features we have. It doesn't translate the node titles in the different menus it generates.

Steps to reproduce:

  • Configure Book content type for translation
  • Enable a second language
  • Create a book outline in English
  • Translate each node in the outline
  • Navigate the book in the second language

The nodes get loaded correctly, in the correct language. However, the navigation in the node footer, as well as the Book block, display the node titles in English, which is incorrect.

I'm the maintainer of the Book Translation module. D8 will make much of the module obsolete (which is great). However, it misses this small part.

Release note snippet

Book navigation now displays translated titles 🎉

CommentFileSizeAuthor
#244 2470896-244.patch21.19 KBjoaoclobocar
#243 2470896-243.patch21.19 KBqusai taha
#237 2470896_237.patch35.99 KBjoseph.olstad
#234 2470896_234_Drupal_8.8.x.patch35.55 KBbserem
#233 2470896_233.patch35.99 KBghost of drupal past
#230 interdiff_2470896_223_230.txt5.29 KBghost of drupal past
#230 2470896_230.patch34.94 KBghost of drupal past
#223 2470896_223.patch33.3 KBghost of drupal past
#223 interdiff_2470896_219_223.txt1.68 KBghost of drupal past
#219 interdiff_2470896_217_219.txt10.08 KBghost of drupal past
#219 2470896_219.patch33.35 KBghost of drupal past
#217 interdiff_2470896_179_217.txt22.55 KBghost of drupal past
#217 interdiff_2470896_190_217.txt21.12 KBghost of drupal past
#217 interdiff_2470896_215_217.txt2.33 KBghost of drupal past
#217 2470896_217.patch33.18 KBghost of drupal past
#215 interdiff_2470896_190_215.txt19.83 KBghost of drupal past
#215 interdiff_2470896_179_215.txt21.26 KBghost of drupal past
#215 2470896_215.patch31.88 KBghost of drupal past
#214 2470896_179_212.txt15.07 KBghost of drupal past
#214 2470896_190_212.txt13.21 KBghost of drupal past
#214 2470896_212.patch29.38 KBghost of drupal past
#210 2470896_190_210.txt3.91 KBghost of drupal past
#210 2470896_179_210.txt8 KBghost of drupal past
#210 2470896_210.patch26.81 KBghost of drupal past
#206 D8.9.9-2470896_156_rerolled-206.patch16.65 KBjoseph.olstad
#202 interdiff_197-202.txt3.29 KBridhimaabrol24
#202 2470896-202.patch28.78 KBridhimaabrol24
#202 2470896-202-test-only-patch.patch3.29 KBridhimaabrol24
#200 D8.9.7-2470896_156_rerolled-200.patch16.64 KBjoseph.olstad
#199 D8.9x-2470896_156_rerolled-199.patch16.65 KBjoseph.olstad
#197 interdiff-190-197.txt1003 bytespaulocs
#197 2470896-197.patch25.49 KBpaulocs
#190 interdiff_189-190.txt465 bytesmindbet
#190 2470896-190.patch24.54 KBmindbet
#189 interdiff-188-189.txt1.22 KBpaulocs
#189 2470896-189.patch24.63 KBpaulocs
#188 2470896-188.patch24.77 KBayushmishra206
#188 interdiff_185-188.txt723 bytesayushmishra206
#186 interdiff_182-185.txt2.37 KBmindbet
#185 2470896_185.patch24.55 KBmindbet
#182 2470896_179_182_interdiff.txt2.26 KBpritishkumar
#182 2470896_182.patch24.54 KBpritishkumar
#179 2470896_179-interdiff.txt1.93 KBberdir
#179 2470896_179.patch24.54 KBberdir
#178 2470896_176_168_interdiff.txt2.3 KBghost of drupal past
#178 2470896_178.patch24.54 KBghost of drupal past
#176 interdiff_2470896_173_176.txt1.28 KBghost of drupal past
#176 2470896_176.patch24.44 KBghost of drupal past
#173 2470896_173.patch24.36 KBghost of drupal past
#173 interdiff_2470896_171_173.txt4.29 KBghost of drupal past
#171 2470896_171.patch24.3 KBghost of drupal past
#168 2470896_168.patch21 KBghost of drupal past
#167 2470896_167.patch20.38 KBghost of drupal past
#163 2470896-interdiff-162-163.txt3.62 KBcburschka
#163 2470896-163.patch15.69 KBcburschka
#162 2470896-162.patch16.21 KBmrinalini9
#156 2470896-156.patch16.5 KBjiong_ye
#153 interdiff.2470896.150-153.txt2.13 KBaleevas
#153 2470896-9.1-153.patch16.39 KBaleevas
#150 2470896-9.1-150.patch16.4 KBaleevas
#150 interdiff.2470896.144-150.txt8.85 KBaleevas
#144 2470896-144.patch15.85 KBswatichouhan012
#138 2470896_138.patch16.28 KBghost of drupal past
#136 book-navigation-translatable-2470896-87x-136.patch16.26 KBvidorado
#132 make-book-navigation-translatable-2470896-132.patch16.03 KBMadhura BK
#132 interdiff-2470896-130-132.txt1.75 KBMadhura BK
#130 drupal-make-book-navigation-translatable-2470896-130.patch15.97 KBavpaderno
#128 drupal-make-book-translatable-2470896-128.patch15.97 KBavpaderno
#126 book-navigation-translatable-2470896-126.patch16.24 KBMadhura BK
#126 interdiff-2470896-123-126.txt1.49 KBMadhura BK
#123 interdiff.txt998 bytesnicrodgers
#123 book_navigation_translatable-2470896-123.patch16.38 KBnicrodgers
#118 book_navigation_translatable-2470896-118.patch15.4 KBnicrodgers
#115 Screenshot from 2019-11-29 11-43-10.png34.73 KBlevmyshkin
#114 0 What’s New in Drupal 8 Drupal Book.png26.94 KBlevmyshkin
#101 book_navigation_translatable-2470896-101.patch15.59 KBsuchdavid
#99 book_navigation_translatable-2470896-75_for_8.7.x.patch.zip17.65 KBdbielke1986
#95 book_navigation_translatable-2470896-95.patch13.78 KBbrtamas
#94 book_navigation_translatable-2470896-94.patch11.03 KBbrtamas
#91 book_navigation_translatable-2470896-91.patch16.22 KBkostyashupenko
#86 book_navigation_translatable-2470896-86.patch15.66 KBandy_w
#86 book_navigation_translatable-2470896-86.patch15.66 KBandy_w
#82 book_navigation_translatable-2470896-82.patch15.65 KBerikwegner
#75 book_navigation_translatable-2470896-75.patch32.3 KBmpolishchuck
#75 interdiff-56-75.txt2.13 KBmpolishchuck
#56 book_navigation_translatable-2470896-56.patch30.67 KBerikwegner
#53 book_navigation_translatable-2470896-53.patch30.41 KBerikwegner
#51 book_navigation_translatable-2470896-51.patch30.41 KBerikwegner
#48 book_navigation_translatable-2470896-48.patch29.06 KBerikwegner
#36 book-navigation-translatable-2470896-36.patch19.31 KBsakhan
#35 book-navigation-translatable-2470896-35.patch18.51 KBsakhan
#30 User_option_and_book_navigation_translation.png61.37 KBdunebl
#29 book-navigation-translatable-2470896-29.patch17.12 KBpritishkumar
#26 book-navigation-translatable-2470896-26.patch17.14 KBerikwegner
#10 book_2470896-10.patch2.77 KBerikwegner
#17 book-navigation-translatable-2470896-16.patch17.71 KBerikwegner
#21 book-navigation-translatable-2470896-20.patch17.11 KBerikwegner
#19 book-navigation-translatable-2470896-19.patch17.11 KBerikwegner
#9 book_2470896-9.patch1.88 KBerikwegner

Issue fork drupal-2470896

Command icon 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

wadmiraal’s picture

Assigned: Unassigned » wadmiraal

Having a look at it.

wadmiraal’s picture

Assigned: wadmiraal » Unassigned

Other stuff to do for now, might get back to it later.

kattekrab’s picture

Hey @wadmiraal - are you likely to have time to circle back to this one?

Strike me it's a good idea if it's not too much work!

astra’s picture

Which version of Drupal 8 can make Book navigation translatable?

Thank you!

Matroschker’s picture

I checked this again with Drupal 8.0.1 and it does not work.
It would be very good if this could handle in standard.

Thank you.

wadmiraal’s picture

Doesn't work with Drupal 8.0.2 either. It has actually been disabled in book.module:

/**
 * Implements hook_ENTITY_TYPE_load() for node entities.
 */
function book_node_load($nodes) {
  /** @var \Drupal\book\BookManagerInterface $book_manager */
  $book_manager = \Drupal::service('book.manager');
  $links = $book_manager->loadBookLinks(array_keys($nodes), FALSE);
  ...
}

That 2nd parameter passed to loadBookLinks() (FALSE) is the $translate parameter, as seen here (src/BookManager.php):

  /**
   * {@inheritdoc}
   */
  public function loadBookLinks($nids, $translate = TRUE) {
    $result = $this->bookOutlineStorage->loadMultiple($nids, $translate);
    $links = array();
    foreach ($result as $link) {
      if ($translate) {
        $this->bookLinkTranslate($link);
      }
      $links[$link['nid']] = $link;
    }

    return $links;
  }

There are 2 things I don't understand from this code:

1. Why is $translate being passed to BookOutlineStorage::loadMultiple()? The loadMultiple() method's 2nd parameter is the $access parameter, and controls wehther a node_access tag should be added to the query. Shouldn't this always be the case? How are we checking node access in the context of the book navigation then? And why does this depend on the outline being translated or not?

2. Why was the translation specifically disabled?

Does the 2nd question have anything to do with this: when I change the code to this (meaning, I'm disabling access checks, but enabling translations):

/**
 * {@inheritdoc}
 */
public function loadBookLinks($nids, $translate = TRUE) {
  // Disable node_access tag.
  $result = $this->bookOutlineStorage->loadMultiple($nids, FALSE);
  $links = array();
  foreach ($result as $link) {
    // Enable translations on the book links.
    if (TRUE) {
      $this->bookLinkTranslate($link);
    }
    $links[$link['nid']] = $link;
  }

  return $links;
}

Apache dies with a Segmentation fault (AH00052: child pid 238 exit signal Segmentation fault (11)). Any thoughts on what could cause this? Is this the reason this was temporarily disabled?

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

erikwegner’s picture

StatusFileSize
new1.88 KB

Here is a patch that addresses the list of child pages and the bread crumb titles.

erikwegner’s picture

StatusFileSize
new2.77 KB

Here is a patch that addresses the list of child pages and the bread crumb titles.
Now the links point to the correct language.

kholloway’s picture

Status: Active » Needs review

I have have confirmed that this patch works for me. Unsure if testing is needed before this can be applied.

Just to be specific this fixes the breadcrumb, Book Navigation block as well as the (lower) link menu "next" and "previous" links.

roald’s picture

#10 appears to work fine for me as well

dawehner’s picture

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

The code looks reasonable, I'd say, but we really need test coverage to be able to sure it will be working in the future.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Leagnus’s picture

#10 works fine. Thank you, ErikWegner.

noximuz’s picture

#10, links are translated, but still point to a different language pages (in book tree section).

erikwegner’s picture

StatusFileSize
new17.71 KB

Patch including tests for:

  1. Pager links (next, previous)
  2. Breadcrumbs
  3. Outline
erikwegner’s picture

Status: Needs work » Needs review
erikwegner’s picture

StatusFileSize
new17.11 KB

Code for test reformatted

Status: Needs review » Needs work

The last submitted patch, 19: book-navigation-translatable-2470896-19.patch, failed testing.

erikwegner’s picture

Status: Needs work » Needs review
StatusFileSize
new17.11 KB

Reformatted the code

The last submitted patch, 19: book-navigation-translatable-2470896-19.patch, failed testing.

The last submitted patch, 19: book-navigation-translatable-2470896-19.patch, failed testing.

erikwegner’s picture

Issue tags: -Needs tests
dawehner’s picture

Nice test coverage!

+++ b/core/modules/book/tests/src/Functional/BookI18NTest.php
@@ -0,0 +1,422 @@
+class BookI18NTest extends BrowserTestBase {

I'd just have named it BookTranslationTest, one less abbreviation people would have to know :)

erikwegner’s picture

That's a good point. Here is the patch with the class renamed.

erikwegner’s picture

swentel’s picture

So the patch seems to be doing it's job fine.

On thing though which is important: it's entirely possible a node is not translated in a certain language, so should we then ignore this in the tree when we're showing the navigation in a different language. It's a requirement for the site I'm working on right now to hide it, so maybe this could be a setting on the block and use that as a default?

To visualize the problem. In english (default language) we have this tree

- installation (node 1)
- mac (node 2)
- linux (node 3)
- windows (node 4).

But in dutch, only the installation node is translated, the rest is not. Yet in the navigation tree in the dutch, we see the 3 children which don't make sense to be displayed there.

This behavior (a bug imho) can also be seen in the traversal links at the bottom.

Note, I'd personally consider this as a bug report (maybe even major), as multillingual book navigations are basically useless right now.

pritishkumar’s picture

Improved intendation.

But I don't know why, I am not able to create interdiff files

dunebl’s picture

#53 is doing the job... many thanks for this!!!!
Note that in "Detection and selection" page, if I check "User" to have the settings like the screencapture, the block is not translated even if I click on another language on the language switcher block...

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

sakhan’s picture

See #35.

sakhan’s picture

Priority: Normal » Major
sakhan’s picture

Category: Feature request » Bug report
sakhan’s picture

#26 (and #29 which is same as #26 but with improved indentation) work fine for me but I noticed that one issue is still there.
Along with the issues which are reported, there is an another issue which you can reproduce like this:

  • Configure Book content type for translation
  • Enable a second language
  • Create a book outline in English
  • Translate each node in the outline
  • Navigate the /admin/structure/book "Edit order and titles" in the second language
  • Edit the titles and click "Save book pages"

You will notice that the titles are saved for the English language not for the second language, which is incorrect.

Before #26 patch the Title fields in /admin/structure/book "Edit order and titles" were always loaded with the English translation.
After #26 patch, when visiting the "Edit order and titles" page, the Title fields now get loaded correctly but if you edit the Title fields and save them, the titles are saved for the default-language/English not the currently selected second language (just like without the patch). For solving this issue here is the updated patch which is same as #26 (#29 too) with additional work which addresses the above issue.

sakhan’s picture

The names/titles of the books are not correctly translated in /admin/structure/book. They are set to English/default-language in all cases.

Steps to reproduce:

  • Configure Book content type for translation
  • Enable a second language
  • Create a book outline in English
  • Translate each node in the outline including the book root page
  • Switch language to second language
  • Navigate to path /admin/structure/book

You will notice that although you have selected the second language, the book titles are displayed in English.

This patch addresses to resolves this issue too. After applying this patch you will see that the book titles are displayed in the correct translation.

erikwegner’s picture

@sakhan: I am interested in a use case where the structure of a book is different for several languages. Could you please describe one and explain the benefits? Maybe it could be an option for each book to choose whether the structure is the same for all languages?

dani3lr0se’s picture

Status: Needs review » Needs work

I've tested via simplytest.me and followed the steps to reproduce that are in #36. However, it doesn't appear to be working. I'm still seeing the book titles displayed in English. I'm pretty sure I've followed the steps correctly, but perhaps someone else could make it work.

sakhan’s picture

@Daniel_Rose Most probably your Interface text language detection settings are not properly configured. Please visit admin/config/regional/language/detection and choose a suitable detection method and then try again. I have tested on my end that if I don't set an interface language detection method then the books titles are shown in the default language.

dani3lr0se’s picture

@sakhan, no problem. I'll give it another try. Thanks for the feedback. :)

sakhan’s picture

@Daniel_Rose Please login to https://dubbr.ply.st/ as admin/admin and then visit https://dubbr.ply.st/admin/structure/book AND https://dubbr.ply.st/ur/admin/structure/book, hopefully you will notice the difference. The other language used is Urdu(ur).

dani3lr0se’s picture

@sakhan, I definitely notice there. I guess I didn't correctly setup the language translation. My apologies and thank you very much for your feedback and help. :)

Shall we mark this as RTBC since it's working?

dunebl’s picture

Hello,
I got few notices when applying #36

patching file core/modules/book/src/BookBreadcrumbBuilder.php
patching file core/modules/book/src/BookManager.php
patching file core/modules/book/src/Form/BookAdminEditForm.php
Hunk #1 succeeded at 100 (offset 2 lines).
Hunk #2 succeeded at 117 (offset 2 lines).
patching file core/modules/book/tests/src/Functional/BookTranslationTest.php

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

nesimo’s picture

Patch for Drupal 8.4.x working here too. Thanks a lot.

erikwegner’s picture

Status: Needs work » Needs review
avpaderno’s picture

Version: 8.5.x-dev » 8.6.x-dev
Status: Needs review » Needs work

The Drupal\book\BookBreadcrumbBuilder class implements a service, so using \Drupal::languageManager() in its methods is wrong.

erikwegner’s picture

Status: Needs work » Needs review
StatusFileSize
new29.06 KB

Using service for language manager. Adding translation to html export.

avpaderno’s picture

As class property, the code should use $this->languageManager, not $this->language_manager, in the same way it's used $this->viewBuilder.

Status: Needs review » Needs work

The last submitted patch, 48: book_navigation_translatable-2470896-48.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

erikwegner’s picture

Status: Needs work » Needs review
StatusFileSize
new30.41 KB

Patch: Test fix, code style

Status: Needs review » Needs work

The last submitted patch, 51: book_navigation_translatable-2470896-51.patch, failed testing. View results

erikwegner’s picture

Status: Needs work » Needs review
StatusFileSize
new30.41 KB

Typo in test

avpaderno’s picture

Status: Needs review » Needs work

There is just something more that I think needs be changed.

       // Note- access checking is already performed when building the tree.
       if ($node = $this->nodeStorage->load($data['link']['nid'])) {
+
+        // HERE
+        $langcode = $this->languageManager->getCurrentLanguage()->getId();
+        if ($node->isTranslatable()) {
+          if ($node->hasTranslation($langcode)) {
+            $node = $node->getTranslation($langcode);
+          }
+        }

It's not clear what that HERE means. If it is referring to the previous comment, then I would rather move that comment.

       if ($node = $this->nodeStorage->load($data['link']['nid'])) {
         // Access checking is already performed when building the tree.
         $langcode = $this->languageManager->getCurrentLanguage()->getId();
         if ($node->isTranslatable()) {
           if ($node->hasTranslation($langcode)) {
             $node = $node->getTranslation($langcode);
           }
         }

Note- is not using the correct punctuation. I would just leave that out, since every code comment is a note about the code.

It seems the comment is explaining why the code doesn't verify the users have permission to access the node. In that case, I would rather change the code like this.

       // Access checking is not necessary here as it is already performed when building the tree.
       if ($node = $this->nodeStorage->load($data['link']['nid'])) {
         $langcode = $this->languageManager->getCurrentLanguage()->getId();
         if ($node->isTranslatable()) {
           if ($node->hasTranslation($langcode)) {
             $node = $node->getTranslation($langcode);
           }
         }

Should not the code verify the users have access to the translation node? The existing code (i.e. the code before the patch) is not getting the translated nodes, so it is also not checking the users have access to the translation nodes.
Probably that comment should be removed, and the code verify the users have access to the translation node.

avpaderno’s picture

I was also checking if the following code could be simplified, since it is used more than once.

  if ($node->isTranslatable()) {
    if ($node->hasTranslation($langcode)) {
      $node = $node->getTranslation($langcode);
    }
  }

The only simplification I could get is the following one, which replaces two if() statements with one.

  if ($node->isTranslatable() && $node->hasTranslation($langcode)) {
    $node = $node->getTranslation($langcode);
  }

$node->isTranslatable() is necessary because it checks there is more than a language added to the site, and we don't want to show a translation that was added when the site had two or more languages, after the site is back to having a single language.

erikwegner’s picture

Status: Needs work » Needs review
StatusFileSize
new30.67 KB

That // HERE was an old marker where to insert the new code. Just forgot to remove that.

For those if-conditions: I prefer to have them as separate statements for legibility and creating diffs.

Btw: is it possible to have access to a node in one language but not in the other?

avpaderno’s picture

Since the translation is a different node, users could have access to a node, but not the other one, even if the latter is the translation of the previous.

erikwegner’s picture

Translation is not a different node in most cases, each language is a set of field values (doc). The published status is also shared across all languages.

avpaderno’s picture

They are two different node objects with the same ID, but different properties (e.g. author, creation date, active language). As such, a module implementing a content access hook could deny access to the translation. In fact, there are core tests verifying that.

avpaderno’s picture

See NodeAccessLanguageTest::testNodeAccess().

  \Drupal::state()->set('node_access_test_secret_catalan', 1);
  $node_public_ca = $this->drupalCreateNode([
    'body' => [
      [
        
      ],
    ],
    'langcode' => 'ca',
    'private' => FALSE,
  ]);
  $this->assertTrue($node_public_ca->language()->getId() == 'ca', 'Node created as Catalan.');
  
  // Tests that access is granted if requested with no language.
  $this->assertNodeAccess($expected_node_access, $node_public_no_language, $web_user);
  $this->assertNodeAccess($expected_node_access_no_access, $node_public_ca, $web_user);
  
  // Tests that Hungarian node is still accessible.
  $this->assertNodeAccess($expected_node_access, $node_public_hu, $web_user);
  $this->assertNodeAccess($expected_node_access, $node_public_hu->getTranslation('hu'), $web_user);
  
  // Tests that Catalan is still not accessible.
  $this->assertNodeAccess($expected_node_access_no_access, $node_public_ca->getTranslation('ca'), $web_user);

The code acting behind the scene is in node_access_test_node_access().

  $secret_catalan = \Drupal::state()->get('node_access_test_secret_catalan') ?: 0;
  if ($secret_catalan && $node->language()->getId() == 'ca') {
    
    // Make all Catalan content secret.
    return AccessResult::forbidden()->setCacheMaxAge(0);
  }
erikwegner’s picture

Thank you for the example, that shows what can be possible.

From my point of view, the patch we have developed so far makes at least these three assumptions:

  • Consistent hierarchy: a book page has always the same parent and the same children in all languages.
  • Consistent access: a book page is either accessible to the user or not, no matter which language is selected.
  • Partial translation: not every book page has a translation. If a translation exists, it is selected in favour of the base language version. If no translation exists, the untranslated version is used.

From my end user perspective, the issues with untranslated links and nodes can be solved easily by applying this patch. But if any of the above points is not valid, then it needs a broader approach to the problem. I am thinking of the book module's storage structure and all internals, there are many places that might need a new concept.

Perhaps it is also possible to fix this issue with the given patch and address any further concerns in a new issue that is handled by a more skilled person?

avpaderno’s picture

Using the default language, and without this patch, the Book module gives me the links only for the nodes to which I have access. If I cannot access a book page, I don't see the link to that page.

This patch introduces a difference in the behavior of the module. It could be classified as bug, since it gives me a link to a node to which I could not have access.

As side note, also the published status is translatable, which means a translation could be published, and another translation not.

danghoaiphuc’s picture

Hi,
I am not a techie guy so May I ask for your advice if I can use the patch #56 as stated for Drupal 8.6 for my Drupal 8.5? Or, should use the patch #47? Thanks a lot.

leventdal’s picture

Installing 56 on 8.5.2 gave me white screen error. "encountered error"

Currently this issue makes book navigation useless in multilingual sites. It displays only original content. And there are problems with breadcrumbs.

Here is the error I receive.

drupal __construct() must implement interface Drupal\Core\Language\LanguageManagerInterface, none given, called in /home/xxxxxx/public_html/core/lib/Drupal/Component/DependencyInjection/Container.php on line 266 in Drupal\book\BookBreadcrumbBuilder->__construct() (line 52 of core/modules/book/src/BookBreadcrumbBuilder.php).

erikwegner’s picture

After applying #56, you have to flush the caches (e.g. drush cr).

krug’s picture

#56 drupal 8.5.2
English and custom language.
Thanks @erikwegner

leventdal’s picture

Clearing the cache didn't work in 8.5.2. I've hidden the book navigation by css. Unfortunately that was the only viable option.

erikwegner’s picture

@leventdal
How did you clear the caches?
Do you get another error message now?

leventdal’s picture

@ErikWegner

I cleared cache from the performance page.
I didn't try it again with 8.5.3

dawehner’s picture

Status: Needs review » Needs work
+++ b/core/modules/book/book.services.yml
@@ -1,18 +1,18 @@
   book.breadcrumb:
     class: Drupal\book\BookBreadcrumbBuilder
-    arguments: ['@entity.manager', '@current_user']
+    arguments: ['@entity.manager', '@current_user', '@language_manager']
...
   book.manager:
     class: Drupal\book\BookManager
-    arguments: ['@entity.manager', '@string_translation', '@config.factory', '@book.outline_storage', '@renderer']
+    arguments: ['@entity.manager', '@string_translation', '@config.factory', '@book.outline_storage', '@renderer', '@language_manager']
...
   book.export:
     class: Drupal\book\BookExport
-    arguments: ['@entity.manager', '@book.manager', '@renderer']
+    arguments: ['@entity.manager', '@book.manager', '@language_manager']

+++ b/core/modules/book/src/BookBreadcrumbBuilder.php
@@ -38,10 +46,13 @@ class BookBreadcrumbBuilder implements BreadcrumbBuilderInterface {
-  public function __construct(EntityManagerInterface $entity_manager, AccountInterface $account) {
+  public function __construct(EntityManagerInterface $entity_manager, AccountInterface $account, LanguageManagerInterface $language_manager) {
     $this->nodeStorage = $entity_manager->getStorage('node');
     $this->account = $account;
+    $this->languageManager = $language_manager;
   }

+++ b/core/modules/book/src/BookExport.php
@@ -40,11 +48,14 @@ class BookExport {
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   *   The language manager.
    */
-  public function __construct(EntityManagerInterface $entityManager, BookManagerInterface $book_manager) {
+  public function __construct(EntityManagerInterface $entityManager, BookManagerInterface $book_manager, LanguageManagerInterface $language_manager) {
     $this->nodeStorage = $entityManager->getStorage('node');
     $this->viewBuilder = $entityManager->getViewBuilder('node');
     $this->bookManager = $book_manager;
+    $this->languageManager = $language_manager;

Potentially other users have subclasses this class. Given that I think you should make the constructor argument optional aka. $this->languageManager = $language_manager ?: \Drupal::service('language_manager')

Note: This would have prevented the problem described by #64

erikwegner’s picture

@dawehner Are you sure that a subclass is causing the exception? But that is actually a valid concern: how do/should subclasses handle dependencies (especially changes of constructor arguments) of their parent classes?

avpaderno’s picture

Issue tags: +Needs change record
anibal’s picture

Patch #56 works perfectly for me in drupal 8.6 dev in the following link site as example.

http://www.ergophthalmology.com

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mpolishchuck’s picture

Hello.
Patch #56 works, but I caught one more problem. When we're trying to edit book outline (change book item parent for example) - the options in "Parent item" are not translated and is being displayed in base language. I've done some investigation and solved that (more or less). Also added a test for this. Maybe it will be helpful for someone.

unknownmrb’s picture

#75 works perfectly, thank you!

godwing’s picture

I have entered the code #75 manually and have got the white screen with the message (cache was cleared before it):

"The website encountered an unexpected error. Please try again later.
Recoverable fatal error: Argument 3 passed to Drupal\book\BookBreadcrumbBuilder::__construct() must implement interface Drupal\Core\Language\LanguageManagerInterface, none given, called in /home/useraccount/mysite.org/core/lib/Drupal/Component/DependencyInjection/Container.php on line 266 and defined in Drupal\book\BookBreadcrumbBuilder->__construct() (line 52 of core/modules/book/src/BookBreadcrumbBuilder.php)."

My site version is drupal 8.6.4
Server hoster: PHP Version 5.6.35
-------------------------
Could you suggest any solution, please? (I am an ordinary user using ready-made solutions.)

erikwegner’s picture

Please try to clear the cache after applying the patch.

godwing’s picture

@ErikWegner
Unfortunately, I had no chance to do it. Any menu navigation led to this message.

erikwegner’s picture

I try to change the code, so that it works without clearing the cache.

godwing’s picture

@ErikWegner
Thanks for your support. I once again entered all the code manually. This time I previously opened the Clear Cache page. After entering the code and running the cache, I got a white screen without any messages. When I manually moved to the root of the site, everything works well, and the translation of the book is displayed correctly.
But whenever I hit ../development/performance/Clear cache I get a white screen without messages again.

Status Report informs that there are no errors. If I Run Cron - everything is OK. Recent log messages page - no any messages after Clear Cache. I optimized the database, cleared the browser's cookies, went out and went back to my site, but after Clear Cache I always get a white screen without messages.

Additionally, I inform you that initially I had settings ... Configuration> Regional and language> Russian as default. Then I decided to put finally the English as Default. After that, I entered code #75.
Perhaps an error due to the pre-change of the default language of the site?

erikwegner’s picture

If dependency injection does not know about additional required service, retrieve service from global object. This should handle the case when clearing the cache is not possible and avoid a WSOD.

godwing’s picture

@ErikWegner
Hello, Erik. Unfortunately, the new changes did not fix the WSOD error. When I restored the original files of the directory Book, the cache cleaning worked correctly.

andrii_svirin’s picture

#82 applied patch for drupal 8.6.4 - working.

embeau’s picture

I also applied patch #82, which appears to be working. Hoping this functionality can be committed to core asap.

However, one thing it does is that if I am on a French page, the book outline block still displays any English pages in the outline that were not translated. I believe this is intentional, but for what I need, it should only list the pages in the outline that are of the same language as the current page. Same with the next/previous pages at the bottom of the page.

andy_w’s picture

Not sure if this is relevant; but in the event you want to see both unpublished pages and have them show translated then this patch could be applied after the patch in [26552] - which I would assume / hope will be rolled in at some point.

< @@ -999,6 +1028,12 @@ public function bookLinkTranslate(&$link) {
<
<      // For performance, don't localize a link the user can't access.
<      if ($link['access']) {
---
> @@ -1005,6 +1034,12 @@ public function bookLinkTranslate(&$link) {
>          $node = $this->entityManager->getStorage('node')
>            ->load($link['nid']);
>        }
godwing’s picture

@ErikWegner
Haveing a new Drupal update the patch #82 is working without any problem. Thank you.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dunebl’s picture

Issue tags: +Needs reroll

#86 and #82 doesn't apply on 8.7

patching file core/modules/book/book.services.yml
Hunk #1 FAILED at 1.
1 out of 1 hunk FAILED -- saving rejects to file core/modules/book/book.services.yml.rej
patching file core/modules/book/src/BookBreadcrumbBuilder.php
Hunk #1 FAILED at 5.
Hunk #2 succeeded at 31 (offset -1 lines).
Hunk #3 FAILED at 39.
Hunk #4 succeeded at 68 (offset -4 lines).
2 out of 4 hunks FAILED -- saving rejects to file core/modules/book/src/BookBreadcrumbBuilder.php.rej
patching file core/modules/book/src/BookExport.php
Hunk #1 FAILED at 3.
Hunk #2 succeeded at 33 (offset -1 lines).
Hunk #3 FAILED at 41.
Hunk #4 succeeded at 102 (offset -4 lines).
2 out of 4 hunks FAILED -- saving rejects to file core/modules/book/src/BookExport.php.rej
patching file core/modules/book/src/BookManager.php
Hunk #1 succeeded at 7 with fuzz 2 (offset 1 line).
Hunk #2 FAILED at 67.
Hunk #3 FAILED at 108.
Hunk #4 succeeded at 433 with fuzz 2 (offset 4 lines).
Hunk #5 succeeded at 483 (offset 4 lines).
Hunk #6 succeeded at 564 (offset 4 lines).
Hunk #7 FAILED at 591.
Hunk #8 succeeded at 674 (offset -1 lines).
Hunk #9 succeeded at 1023 with fuzz 1 (offset -1 lines).
3 out of 9 hunks FAILED -- saving rejects to file core/modules/book/src/BookManager.php.rej
patching file core/modules/book/src/Form/BookAdminEditForm.php
patching file core/modules/book/tests/src/Unit/BookManagerTest.php
Hunk #1 succeeded at 40 (offset 1 line).
Hunk #2 succeeded at 63 (offset 1 line).
godwing’s picture

Patch #86 at Drupal 8.6.13 produces error, when I try to open a translated book: "The website encountered an unexpected error. Please try again later."
Patch #82 is OK.

kostyashupenko’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new16.22 KB

reroll of #86 patch

Status: Needs review » Needs work

The last submitted patch, 91: book_navigation_translatable-2470896-91.patch, failed testing. View results

avpaderno’s picture

There is an exception raised in a test.

Drupal\Tests\system\Functional\Update\UpdatePathTestBaseFilledTest::testUpdatedSite
Exception: Error: Call to a member function isTranslatable() on null
Drupal\book\BookManager->bookLinkTranslate()

brtamas’s picture

brtamas’s picture

dbielke1986’s picture

Patch #75 is working like charme for Drupal 8.7.x if you change the "EntityManagerInterface $entityManager" to "EntityTypeManagerInterface $entity_type_manager"

The other patches are fixing the export issue, but not the book navigation issue.

godwing’s picture

@JD_1
I tried your solution for Drupal 8.7.3, it doesn't work, any option. [The website encountered an unexpected error. Please try again later.]
So, finally, do we have any working patch?

dbielke1986’s picture

@godwing

I will send you my modified files tomorror, if you like.

This is working perfectly fine on our 8.7.3 installation.

dbielke1986’s picture

Attached you will find modified files for drupal 8.7.3, based on Patch 75

godwing’s picture

@JD_1
Thank you, Daniel! It began to work, really, like a miracle. I replaced the files with yours. In my inexperienced view there are no errors, but you can look at the published book.

suchdavid’s picture

@JD_1 Thank you for the files, I created a patch from them for 8.7.3.

mauriciomedeiros’s picture

Does this fixes the translation of the book tree as well? The one which shows below the content on bartik theme at least?

dbielke1986’s picture

Yes

mauriciomedeiros’s picture

@JD_1 and everyone involved, you are my heroes, thanks to all of you.

The patch works like a charm as far as I could test in the past few minutes.

This needs to be included in the next core update :D

KR
Mauricio

andrii_svirin’s picture

#101 Working for 8.7.3 for me. Thanks.

godwing’s picture

@mauriciomedeiros
I agree, it's time to include it into the next core update.

pjudge’s picture

#101 working beautifully on 8.7.4 for me.

mauriciomedeiros’s picture

What is the process for this to be included in the core? Can the community push for it in any way? :D

Apparently it is still not there...

Also, has anyone tested #101 on 8.7.5?

KR
Mauricio Medeiros

avpaderno’s picture

@mauriciomedeiros It will be included if somebody provides a correct patch. So far, the last patches failed, or failed to apply.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

sakhan’s picture

I am so much frustrated to see that still I can't work on my some projects just because they require book module :(
I am afraid that even if I use some recent working patch that may fail in the next release of the Drupal 8. Why Drupal core maintainers don't take their action to solve this problem once for all as they may know more about how to solve this issue.

sakhan’s picture

I am waiting for the working multilingual book module for 2 years as you might have noticed from my #35 and #36 patches. With my heavy heart I can say Drupal is losing my interest and loyalty day by day.
On the top of the drupal.org page, the first menu entry says "Why Drupal?" it should be "Why NOT Drupal?"!

levmyshkin’s picture

#101 Working for 8.7.10 for me. Thanks.

levmyshkin’s picture

StatusFileSize
new26.94 KB

#101 patch helps to display right language version. But it shows page from another language even if page is not translated yet:
Book translatable

levmyshkin’s picture

StatusFileSize
new34.73 KB

book translatable

nicrodgers’s picture

Issue tags: +Needs reroll

Needs re-rolling for 8.8

nicrodgers’s picture

Assigned: Unassigned » nicrodgers
nicrodgers’s picture

Assigned: nicrodgers » Unassigned
Issue tags: -Needs reroll
StatusFileSize
new15.4 KB

Re-rolled #101 for 8.8.x

avpaderno’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 118: book_navigation_translatable-2470896-118.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

avpaderno’s picture

The tests fails because of the following error.

Drupal\Tests\book\Unit\BookManagerTest::testGetBookParents with data set #1 (array(11, 12), array(11, 1, 11), array(2, 11, 12, 0, 0, 0, 0, 0, 0, 0))
Drupal\Core\DependencyInjection\ContainerNotInitializedException: \Drupal::$container is not initialized yet. \Drupal::setContainer() must be called with a real container.

It is repeated for each data set the test is using.

(The other error is test runner returned a non-zero error code.)

nicrodgers’s picture

Assigned: Unassigned » nicrodgers
nicrodgers’s picture

Assigned: nicrodgers » Unassigned
Status: Needs work » Needs review
StatusFileSize
new16.38 KB
new998 bytes

Fix for the failing tests.
Still needs work though as we need a change record.

valthebald’s picture

Status: Needs review » Needs work

Haven't checked the patch itself, but here are some code style comments:

  1. +++ b/core/modules/book/book.services.yml
    @@ -36,4 +36,4 @@ services:
    \ No newline at end of file
    

    there should be newline in the end of file

  2. +++ b/core/modules/book/src/BookBreadcrumbBuilder.php
    @@ -87,4 +104,4 @@ public function build(RouteMatchInterface $route_match) {
    \ No newline at end of file
    

    No newline

  3. +++ b/core/modules/book/src/BookExport.php
    @@ -141,4 +159,4 @@ protected function bookNodeExport(NodeInterface $node, $children = '') {
    \ No newline at end of file
    

    No newline

Madhura BK’s picture

Assigned: Unassigned » Madhura BK
Madhura BK’s picture

Have implemented the changes suggested in #124

avpaderno’s picture

Now the newlines are two. I would suggest to read what https://www.drupal.org/pift-ci-job/1506753 says about coding standards by clicking on 7 coding standards messages.

avpaderno’s picture

Status: Needs work » Needs review
StatusFileSize
new15.97 KB
Madhura BK’s picture

Assigned: Madhura BK » Unassigned
avpaderno’s picture

(This is the right patch.)

nicrodgers’s picture

Status: Needs review » Needs work

Still two remaining coding standards issues to fix:
https://www.drupal.org/pift-ci-job/1506832

And needs a change record.

Please can you remember to include an interdiff when uploading new patches, so it's easier to review the changes between versions. Thanks!

Madhura BK’s picture

Fixing the 2 coding standard issues mentioned in #131

Madhura BK’s picture

Status: Needs work » Needs review
avpaderno’s picture

Status: Needs review » Needs work

Also, since the services are getting a new dependency, the class constructors should use code similar to the one used from CssCollectionOptimizer::__construct().

public function __construct(AssetCollectionGrouperInterface $grouper, AssetOptimizerInterface $optimizer, AssetDumperInterface $dumper, StateInterface $state, FileSystemInterface $file_system = NULL) {
  $this->grouper = $grouper;
  $this->optimizer = $optimizer;
  $this->dumper = $dumper;
  $this->state = $state;
  if (!$file_system) {
    @trigger_error('The file_system service must be passed to CssCollectionOptimizer::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
    $file_system = \Drupal::service('file_system');
  }
  $this->fileSystem = $file_system;
}
avpaderno’s picture

As reference, this is the issue adding that code: #2244513: Move the unmanaged file APIs to the file_system service (file.inc).

vidorado’s picture

Rerolled patch from #132 for Drupal 8.7.x

sakhan’s picture

Any solid solution so far?

ghost of drupal past’s picture

I tried to apply this to latest stable (8.8.3) and had two rejections, rerolled. This is because of the change from entity manager to entity type manager.

swatichouhan012’s picture

Status: Needs work » Needs review

Moving this to Needs Review.

avpaderno’s picture

Status: Needs review » Needs work

There isn't yet any BC code as described in comment #134.

sakhan’s picture

@kiamlaluno Can you please discuss in detail what else is needed to solve this issue? I see many of us are just struggling to solve this issue but lacking some expertise so is it possible from your side to contribute to solve this issue once for all please?
One other way I can think of is to give monetary support to the issue resolver to expedite the process.

avpaderno’s picture

See comment #134. I quoted the code of the constructor of a class implementing a service for which the parameters have been changed. The constructor has a new parameter with a NULL default value, and it triggers a E_USER_DEPRECATED error when the default value is used for that parameter.

  if (!$file_system) {
    @trigger_error('The file_system service must be passed to CssCollectionOptimizer::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
    $file_system = \Drupal::service('file_system');
  }
  $this->fileSystem = $file_system;

Similar code needs to be used for any service which get a parameter that it didn't get in older versions.

sakhan’s picture

Drupal 9 will be released soon but yet the book module lack very basic multilingual support :(

swatichouhan012’s picture

Status: Needs work » Needs review
StatusFileSize
new15.85 KB

patch #138 failed to apply so i rerolled patch.

@kiamlaluno wrt point in comment #143. can you please provide link for language_manager service where it deprecated ?

avpaderno’s picture

@swatichouhan012 The language_manager service isn't deprecated.
Comment #142 is saying what code needs to be added when new arguments are added to a service, such as in the case of the language_manager service which is added to the book.manager service.

dbielke1986’s picture

Status: Needs review » Needs work

The patch from comment #144 does not work properly. Although the menu title is displayed correctly, the link to the pages is not correct if you use a prefix (like /de or /en in the URL)

Patch 2470896_138.patch is working for me.

levmyshkin’s picture

#144 and #138 are working fine for me with Drupal 8.9.x-dev.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

sakhan’s picture

Drupal 9 is about to be released soon but still book module is not translatable. So many developers couldn't transform their ideas into realities due to this missing translation feature.

aleevas’s picture

Status: Needs work » Needs review
StatusFileSize
new8.85 KB
new16.4 KB

Re-rolled up to 9.1
Added notice from #142 and new 'Change records'

sakhan’s picture

Patch from comment #150 working for me with drupal 9.

avpaderno’s picture

Status: Needs review » Needs work

The deprecation messages need to be updated: If the code is changed in Drupal 9.1.x, the messages cannot say Drupal 8.9.

aleevas’s picture

Status: Needs work » Needs review
StatusFileSize
new16.39 KB
new2.13 KB

@kiamlaluno thank you for review.
You warning make sense, so I changed it to 9.1

avpaderno’s picture

Status: Needs review » Reviewed & tested by the community

It's seems good to go, to me.

sakhan’s picture

Finally we have a patch that at least works with the upcoming version of Drupal that's Drupal 9! I tested it very extensively and it doesn't fail for me.

jiong_ye’s picture

StatusFileSize
new16.5 KB

#144 works for me except that it doesn't render translation's URL but origin's URL.

dbielke1986’s picture

#156 is working perfectly! Thank you so much

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/book/src/BookBreadcrumbBuilder.php
    @@ -68,11 +83,17 @@ public function build(RouteMatchInterface $route_match) {
    +          if ($parent_book->isTranslatable()) {
    +            if ($parent_book->hasTranslation($langcode)) {
    
    +++ b/core/modules/book/src/BookExport.php
    @@ -102,11 +117,18 @@ public function bookExportHtml(NodeInterface $node) {
    +        if ($node->isTranslatable()) {
    +          if ($node->hasTranslation($langcode)) {
    
    +++ b/core/modules/book/src/BookManager.php
    @@ -109,12 +122,24 @@ protected function loadBooks() {
    +          if ($nodes[$nid]->isTranslatable()) {
    +            if ($nodes[$nid]->hasTranslation($langcode)) {
    
    +++ b/core/modules/book/src/Form/BookAdminEditForm.php
    @@ -116,6 +129,11 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    +            if ($node->isTranslatable()) {
    +              if ($node->hasTranslation($langcode)) {
    

    This can be if ($parent->isTranslatable() && $parent_book->hasTranslatatioon($langcde)_ {

  2. +++ b/core/modules/book/src/BookManager.php
    @@ -109,12 +122,24 @@ protected function loadBooks() {
    +      // Load nodes with proper translation.
    +      $langcode = $this->languageManager->getCurrentLanguage()->getId();
    +      foreach ($nodes as $nid => $node) {
    +        if ($node->isTranslatable() && $node->hasTranslation($langcode)) {
    +          $nodes[$nid] = $node->getTranslation($langcode);
    +        }
    +      }
     
           // @todo: use route name for links, not system path.
           foreach ($book_links as $link) {
             $nid = $link['nid'];
             if (isset($nodes[$nid]) && $nodes[$nid]->status) {
    +          if ($nodes[$nid]->isTranslatable()) {
    +            if ($nodes[$nid]->hasTranslation($langcode)) {
    +              $nodes[$nid] = $nodes[$nid]->getTranslation($langcode);
    +            }
    +          }
    

    This looks duplicated I think only one of these code hunks is necessary.

  3. We need to add automated test coverage here. So we can prove we've fixed the bug and that we don't break it in the future. The onther test we're changing so far is an unit test but we've not added test coverage of the bug we're fixing here.
  4. +++ b/core/modules/book/book.services.yml
    @@ -36,4 +36,4 @@ services:
    -    lazy: true
    +    lazy: true
    \ No newline at end of file
    

    This change is out-of-scope - and I think incorrect.

avpaderno’s picture

Issue tags: +Needs tests
avpaderno’s picture

Issue tags: +Needs reroll

It also needs re-roll, since the patch failed to apply.

mrinalini9’s picture

Assigned: Unassigned » mrinalini9
mrinalini9’s picture

Assigned: mrinalini9 » Unassigned
StatusFileSize
new16.21 KB

Rerolled patch for 9.1.x. Still need to address #158 and #159.

cburschka’s picture

StatusFileSize
new15.69 KB
new3.62 KB

Addressing 1-2 of #158; 4 is already fixed.

Still needs tests.

avpaderno’s picture

Status: Needs work » Needs review

(Patches aren't testing, if the status isn't changed to Needs review.)

jofitz’s picture

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

No longer requires Reroll.

Setting status back to Needs Work for someone to address #158.3 - still needs tests.

dbielke1986’s picture

Status: Needs work » Needs review

#163 is working fine and has not the mentioned #158.3 issue.

ghost of drupal past’s picture

StatusFileSize
new20.38 KB

Added a kernel test. There's no interdiff: BookMultilingualTest is new, that's all. getAllBooks(), bookTreeAllData() and getTableOfContents() are covered.

ghost of drupal past’s picture

StatusFileSize
new21 KB

D'oh I always forget that @group because I run only the single file with phpunit. While at it, I have added asserts to make sure the test actually hits the code paths we want it to hit and another to make sure the current language switcher works. It's possible we want to move the current language switcher to a trait in a separate patch, it looks like it could be very useful for other such tests as well.

penyaskito’s picture

Status: Needs review » Needs work
Issue tags: -Needs tests

Removing Needs test issue tag, this has good coverage now.

+++ b/core/modules/book/src/BookBreadcrumbBuilder.php
@@ -38,10 +46,13 @@ class BookBreadcrumbBuilder implements BreadcrumbBuilderInterface {
+    $this->languageManager = $language_manager ?: \Drupal::service('language_manager');

+++ b/core/modules/book/src/BookExport.php
@@ -40,11 +48,14 @@ class BookExport {
+    $this->languageManager = $language_manager ?: \Drupal::service('language_manager');

+++ b/core/modules/book/src/BookManager.php
@@ -81,12 +89,13 @@ class BookManager implements BookManagerInterface {
+    $this->languageManager = $language_manager ?: \Drupal::service('language_manager');

+++ b/core/modules/book/src/Form/BookAdminEditForm.php
@@ -41,10 +49,13 @@ class BookAdminEditForm extends FormBase {
+    $this->languageManager = $language_manager ?: \Drupal::service('language_manager');

Seems like the request of the deprecation message for the new arguments in constructors are not taken care of yet (see #142).

Happy to RTBC afterwards as looks like this has been tested several times by several people and the latest patch is adding tests but not changing functional code.

ghost of drupal past’s picture

Assigned: Unassigned » ghost of drupal past

I have the messages added and also more tests added but please hold for now: I am having a chat with various maintainers whether the translation to the interface language is correct or not. I feel it's not and it should use content language and the EntityRepository::getTranslationFromContext method should be used. Please wait a few days while we sort this out. If I am not back in a week feel free to continue without me... but I will be.

ghost of drupal past’s picture

Assigned: ghost of drupal past » Unassigned
Status: Needs work » Needs review
StatusFileSize
new24.3 KB

There's no interdiff here because it'd be bigger than the patch as almost every line touched by the patch has been changed.

berdir’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/book/src/BookBreadcrumbBuilder.php
    @@ -38,10 +46,17 @@ class BookBreadcrumbBuilder implements BreadcrumbBuilderInterface {
    +   *   The entity repository service.
        */
    -  public function __construct(EntityTypeManagerInterface $entity_type_manager, AccountInterface $account) {
    +  public function __construct(EntityTypeManagerInterface $entity_type_manager, AccountInterface $account, EntityRepositoryInterface $entity_repository) {
         $this->nodeStorage = $entity_type_manager->getStorage('node');
         $this->account = $account;
    +    if (!$entity_repository) {
    +      @trigger_error('The entity.repository service must be passed to ' . __NAMESPACE__ . '\BookBreadcrumbBuilder::__construct(). It was added in drupal:9.1.0 and will be required before drupal:10.0.0.', E_USER_DEPRECATED);
    +      $entity_repository = \Drupal::service('entity.repository');
    +    }
    +    $this->entityRepository = $entity_repository;
       }
    

    this only works if you add = NULL to the argument, as the type otherwise doesn't allow NULL as a valid value.

  2. +++ b/core/modules/book/src/BookManager.php
    @@ -80,13 +97,27 @@ class BookManager implements BookManagerInterface {
         $this->renderer = $renderer;
    +    if (!$language_manager) {
    +      @trigger_error('The language_manager service must be passed to ' . __NAMESPACE__ . '\BookManager::__construct(). It was added in drupal:9.1.0 and will be required before drupal:10.0.0.', E_USER_DEPRECATED);
    +      $language_manager = \Drupal::service('language_manager');
    +    }
    +    $this->currentContentLangcode = $language_manager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT);
    

    I'd recommend to store the language manager, not the current language. that can in theory change during the request.

  3. +++ b/core/modules/book/src/BookManager.php
    @@ -666,14 +700,13 @@ protected function bookTreeBuild($bid, array $parameters = []) {
           sort($parameters['expanded']);
         }
    -    $tree_cid = 'book-links:' . $bid . ':tree-data:' . $language_interface->getId() . ':' . hash('sha256', serialize($parameters));
    +    $tree_cid = implode(':', ['book-links', $bid, 'tree-data', $this->currentContentLangcode, hash('sha256', serialize($parameters))]);
     
         // If we do not have this tree in the static cache, check {cache_data}.
    

    Interesting. Is there any chance the interface language _also_ affects what we cache here? I suppose not as we can expect all links to be nodes and that's all we translate?

  4. +++ b/core/modules/book/src/BookManager.php
    @@ -1015,7 +1048,7 @@ public function bookLinkTranslate(&$link) {
           }
    -      // The node label will be the value for the current user's language.
    +      $node = $this->entityRepository->getTranslationFromContext($node);
           $link['title'] = $node->label();
    

    ha, interesting case of "I wish to make the API work as I'd like it to by writing a comment saying it is so" :)

  5. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,211 @@
    +  /**
    +   * Tests various book manager methods return correct translations.
    +   *
    +   * #@dataProvider langcodesProvider
    +   */
    +  public function xtestMultilingualBookManager($langcode) {
    +    $this->setCurrentLanguage($langcode);
    +    /** @var \Drupal\book\BookManagerInterface $bm */
    

    accidentally commented out?

    I'm not a huge fan of data providers in anything but unit tests FWIW. This will do the setup() twice for each combination.

ghost of drupal past’s picture

StatusFileSize
new4.29 KB
new24.36 KB
  1. Added NULLs. (I already had a few , now we have more.)
  2. I'd recommend to store the language manager -- done. (Also fixes the test failures -- I stored the current language when I wanted the current langcode.)
  3. . Is there any chance the interface language _also_ affects what we cache here? I suppose not as we can expect all links to be nodes and that's all we translate? -- that's my understanding too. We do not do anything interface-y.
  4. accidentally commented out? -- fixed. Data providers are necessary because BookManager::$books stores translated nodes and it's not possible to reset it. I suppose we could reset the entire service but based on our chat this is cleaner.
avpaderno’s picture

Status: Needs work » Needs review
berdir’s picture

Status: Needs review » Needs work
+++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
@@ -93,7 +93,7 @@
    *
    * #@dataProvider langcodesProvider
    */
-  public function xtestMultilingualBookManager($langcode) {
+  public function testMultilingualBookManager($langcode) {
     $this->setCurrentLanguage($langcode);

the data provider is still commented out with a #, I suppose that caused an error otherwise.

ghost of drupal past’s picture

Status: Needs work » Needs review
StatusFileSize
new24.44 KB
new1.28 KB

Alright, one more then.

berdir’s picture

Status: Needs review » Needs work

Hopefully the last review.

  1. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,211 @@
    +   *
    +   * #@dataProvider langcodesProvider
    +   */
    +  public function testMultilingualBookBreadcrumbBuilder($langcode) {
    

    another #, but it seems to run and work anyway? we should remove that though.

  2. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,211 @@
    +    // Make sure the below parts of the code is actually tested.
    +    if ($top) {
    +      $this->assertTrue($below_tested);
    +    }
    

    several parts of the test seem to be basically testing/asserting itself, also the negotiation below. a bit unusual I suppose but doesn't hurt.

  3. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,211 @@
    +   * @param $langcode
    +   *   The langcode.
    

    type missing here.

  4. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,211 @@
    +   * @param $langcode
    +   *   The langcode.
    +   */
    +  protected function setCurrentLanguage($langcode) {
    +    /** @var \Drupal\language\ConfigurableLanguageManagerInterface $lm */
    +    $lm = $this->container->get('language_manager');
    +    $negotiator = $this->prophesize(LanguageNegotiatorInterface::class);
    +    foreach ($lm->getLanguages() as $candidate_langcode => $candidate) {
    +      $type = $candidate_langcode === $langcode ? LanguageInterface::TYPE_CONTENT : LanguageInterface::TYPE_INTERFACE;
    +      $negotiator->initializeType($type)->willReturn([$type => $candidate]);
    +    }
    +    $lm->setNegotiator($negotiator->reveal());
    +    $this->assertSame($lm->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId(), $langcode);
    +    $this->assertNotSame($lm->getCurrentLanguage(LanguageInterface::TYPE_INTERFACE)->getId(), $langcode);
    +  }
    +
    

    also type missing on $langcode @param.

    I know it's long, but we should use $language_manager and not $lm per our coding standards

ghost of drupal past’s picture

Status: Needs work » Needs review
StatusFileSize
new24.54 KB
new2.3 KB

Fixed as requested.

berdir’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs change record
StatusFileSize
new24.54 KB
new1.93 KB
+++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
@@ -192,20 +192,20 @@
    *   The langcode.
    */
   protected function setCurrentLanguage($langcode) {
-    /** @var \Drupal\language\ConfigurableLanguageManagerInterface $lm */
-    $lm = $this->container->get('language_manager');
+    /** @var \Drupal\language\ConfigurableLanguageManagerInterface $language_manager  */
+    $language_manager  = $this->container->get('language_manager');
     $negotiator = $this->prophesize(LanguageNegotiatorInterface::class);
-    foreach ($lm->getLanguages() as $candidate_langcode => $candidate) {
+    foreach ($language_manager ->getLanguages() as $candidate_langcode => $candidate) {

the search & replace added an extra space in several places here.

Feeling bad to set back to needs work because of that, so fixing that and RTBC'ing anyway, I think that's fine as it's just spaces and an extra comma that phpstorm phpcs also complained about.

larowlan’s picture

Thanks for this, a couple of observations / questions - setting to needs review for feedback

  1. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,211 @@
    +  /**
    +   * Modules to enable.
    +   *
    +   * @var array
    +   */
    +  protected static $modules = [
    

    ubernit: we can use inheritdoc here

  2. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,211 @@
    +  public function testMultilingualBookManager($langcode) {
    ...
    +  public function testMultilingualBookBreadcrumbBuilder($langcode) {
    ...
    +  protected function recurseTree(array $tree, $langcode, $top = TRUE) {
    ...
    +  protected function assertBookLinkIsCorrectlyTranslated(array $link, $langcode) {
    ...
    +  protected function setCurrentLanguage($langcode) {
    

    we can and should typehint this as string for new code in my opinion

  3. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,211 @@
    +    foreach ($bbb->build($route_match)->getLinks() as $link) {
    +      $parameters = $link->getUrl()->getRouteParameters();
    +      if (isset($parameters['node'])) {
    +        $nid = $parameters['node'];
    +        $node = Node::load($nid);
    +        $this->assertSame($node->getTranslation($langcode)->label(), $link->getText());
    +        $found = TRUE;
    +      }
    +    }
    +    $this->assertTrue($found);
    

    should we be more explicit here and assert the expected parent crumbs too? e.g. we're just asserting that one of the crumbs matches the child item (#2) but shouldn't we be also testing that the book parent appears in the correct language?

    I.e. rather than looping over all links to find one, assert that we have a matching set of titles in the correct language for all of the items?

larowlan’s picture

Status: Reviewed & tested by the community » Needs work

We're also missing deprecation tests here to assert the expected deprecations are raised if the constructor args are missing

pritishkumar’s picture

StatusFileSize
new24.54 KB
new2.26 KB

Addressing pointers 180.1 and 180.2

berdir’s picture

Status: Needs work » Needs review

> We're also missing deprecation tests here to assert the expected deprecations are raised if the constructor args are missing

We usually don't add tests for that unless there is special complexity, I think it's fine to skip that.

quietone’s picture

Status: Needs review » Needs work

The patch in #182 does fix the the points, #180.1 and .2.

However, 180.3 still needs to be addressed. Setting to NW.

mindbet’s picture

Status: Needs work » Needs review
StatusFileSize
new24.55 KB

This patch addresses 180.3

In the file

Kernel/BookMultilingualTest.php,

the test sets up two books for testing.

I revised the setUp function so that two books are each nine pages deep.

The test
testMultilingualBookBreadcrumbBuilder

--loads the deepest page of one of the books
--constructs the breadcrumb for that page
--tests that each element in the breadcrumb shows the correct translation

mindbet’s picture

StatusFileSize
new2.37 KB

Attached is interdiff for 182-185

My apologies.

ghost of drupal past’s picture

Status: Needs review » Needs work

Thank you so much for taking this on.

This comment "// The node label will be the value for the current user's language." does not seem correct to me. The logic is complex, let's just call it the "current language".

ayushmishra206’s picture

Status: Needs work » Needs review
StatusFileSize
new723 bytes
new24.77 KB

Made the changes requested in #187. Please Review

paulocs’s picture

StatusFileSize
new24.63 KB
new1.22 KB

Fixing drupal code standard.

mindbet’s picture

StatusFileSize
new24.54 KB
new465 bytes

Fixing an error in a comment, sorry.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

joel_osc’s picture

I have tried this patch and translated books are largely working, many thanks to everyone that has contributed to this patch. I am seeing an issue where my base language is En and the translation language is Fr - when I view a book node in Fr the book navigation block shows the link titles in Fr (properly) but they are actually linked to the En node url. I managed to (hack?) fix it like this in BookManager.php:

  protected function buildItems(array $tree) {
    
      if ($data['link']['in_active_trail']) {
        $element['in_active_trail'] = TRUE;
      }

+      $language = $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT);
      // Allow book-specific theme overrides.
      $element['attributes'] = new Attribute();
      $element['title'] = $data['link']['title'];
      $node = $this->entityTypeManager->getStorage('node')->load($data['link']['nid']);
-      $element['url'] = $node->toUrl();
+      $element['url'] = $node->toUrl('canonical', ['language' => $language]);
      $element['localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : [];
      $element['localized_options']['set_active_class'] = TRUE;
      $element['below'] = $data['below'] ? $this->buildItems($data['below']) : [];
      $element['original_link'] = $data['link'];

I am wondering (a) if anyone else is seeing this issue and (b) should I potentially open a related issue in order to not muddy up this one? Cheers.

dbielke1986’s picture

@joel_osc

I can confirm this (https://www.drupal.org/project/drupal/issues/2470896#comment-13522365). This is the reason I am using patch #163

ghost of drupal past’s picture

@joel_osc Thanks, I think it'd be great if you could add it to this patch with an appropriate test, I feel it might belong here.

paulocs’s picture

Status: Needs review » Needs work

Set back to needs work.

paulocs’s picture

Assigned: Unassigned » paulocs

I'll do the job.

paulocs’s picture

Assigned: paulocs » Unassigned
Status: Needs work » Needs review
StatusFileSize
new25.49 KB
new1003 bytes

Adding the fix pointed on comment #192.

ghost of drupal past’s picture

Thanks for adding it but don't you think it needs a test, too?

joseph.olstad’s picture

StatusFileSize
new16.65 KB

Ignore this patch, it's just because my client is on 8.9.x still

this is patch 156 rerolled for 8.9.x
sorry no interdiff

joseph.olstad’s picture

StatusFileSize
new16.64 KB

ignore this patch, it is 156 rerolled for D8.9.7

just because my client is on 8.9.x still on 8.9.7

this is patch 156 rerolled for 8.9.7
sorry no interdiff

paulocs’s picture

Status: Needs review » Needs work

Set back to needs work because we need to write tests for patch #197

ridhimaabrol24’s picture

Status: Needs work » Needs review
StatusFileSize
new3.29 KB
new28.78 KB
new3.29 KB

Adding test. Please review!

paulocs’s picture

Status: Needs review » Needs work

Hey @ridhimaabrol24, I see that you added a test.

The thing is that patch #197 already has test to cover the translation. What we need now is a test that verifies if the /book page is listing the right links with the correct language parameter. See comment #192 and #198.

ridhimaabrol24’s picture

Hey @paulocs. The test I added is verifying whether the book links and title are dispayed in the correct language. This test actually tests the bug in this issue.
It may be possible to add this method to an already existing test class rather than adding a new one but the method is actually testing the bug in this issue only.

ridhimaabrol24’s picture

The test added in #197 is a Kernel test but we will need a functional test to check the links and the node title on the browser. Please let me know your views.

joseph.olstad’s picture

StatusFileSize
new16.65 KB

Please ignore this patch, it is 156 rerolled for D8.9.9

just because my client is on 8.9.x still on 8.9.9

this is patch 156 rerolled for 8.9.9
sorry no interdiff

rachel_norfolk’s picture

hey Jospeh.olstad - if you created a child issue of this one, saying that it was a back port of this issue, you could add your patches there as they are updated here. Would keep the scope of this issue nice and tight whilst allowing you to support your client.

You never know, the back post might even prove to be a worthwhile thing to be committed...

joseph.olstad’s picture

@rachel_norfolk, patch 202 looks ready to me, we have a patch that has tests, proof that the patch is indeed fixing something, if there's a followup issue I'd ask that others open a new issue for that and provide their patches or forks for review. We could then finalize the backports for this issue.

ghost of drupal past’s picture

Assigned: Unassigned » ghost of drupal past

I will carry this patch home.

I believe we do not need a browser test -- those should be rare and either for raw functionality or for JS. Instead, we can assert the generated urls in the tree have the correct language so we can end up with a much faster kernel test.

Since this issue is extremely long and, I respectfully would like to ask everyone to just focus on getting it in and done and only after port it. Should you need intermittent patches please keep them elsewhere. Thanks.

ghost of drupal past’s picture

StatusFileSize
new26.81 KB
new8 KB
new3.91 KB

This should be it. I was able to amend the existing test with a test asserting the rendered URLs are in the correct language. The necessary config is copied from BlockUiTest, the rest is just the assert and since it is inside a conditional, making sure the assert actually ran.

I do not think there is any BC concern with replacing the book tree URL string "entity:node/$nid" with an actual Url object as this entity schema can not be printed raw, it must be passed to the link Twig function and TwigExtension::getLink converts URL strings with the exact same $url = Url::fromUri($url); code as used here. Further https://www.drupal.org/about/core/policies/core-change-policies/drupal-8...

While the Render and Form APIs themselves are stable, the exposed data structures used to build and cache pages and forms are not.

The closest ancestor to this is #190 as I have used a different fix to the problem described in #192 so an interdiff to that is attached. The previous fix is here. I also added an interdiff to #179 which was our last RTBC for the convenience of our committers.

I am keeping the issue assignment, I will see this issue home. I have the time for the foreseeable future.

This patch highlights the necessity of tranc-like functionality in core but that is most certainly a followup.

ghost of drupal past’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 210: 2470896_210.patch, failed testing. View results

daffie’s picture

The patch looks good to me. Only the added BookMultilingualTest feels more complicated then is needed. Just my perspective.

  1. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,240 @@
    +    for ($i = 0; $i < 18; $i++) {
    +      /** @var \Drupal\node\NodeInterface $node */
    +      $node = Node::create(['title' => $this->randomString(), 'type' => $node_type->id()]);
    +      $node->addTranslation(self::LANGCODE, ['title' => $this->randomString()]);
    +      $node->book['bid'] = $i < 2 ? 'new' : $this->bids[$i % 2];
    +      $node->book['pid'] = $i < 2 ? 0 : $this->bids[$i - 2];
    +      $node->book['depth'] = $i < 2 ? 1 : $this->bids[round(($i / 2), 0, PHP_ROUND_HALF_DOWN)];
    +      $node->save();
    +      $this->bids[$i] = $node->id();
    +    }
    

    We are creating a tree of nodes. Could there be a bit of documentation of this tree. Something like in core/tests/Drupal/KernelTests/Core/Menu/MenuLinkTreeTest.php or better. It is now all a bit confusing.

  2. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,240 @@
    +   * Sets the current language.
    ...
    +  protected function setCurrentLanguage(string $langcode) {
    

    This method does a little bit more then only setting the current language to the given value. Could you explain what?

  3. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,240 @@
    +   * Recurses and asserts a book tree is correctly translated.
    ...
    +  protected function recurseTree(array $tree, string $langcode, $top = TRUE) {
    

    Do we really have to use recurse tree walk to test what we want to test. We have only one tree we are testing. Can we explicit test that tree. It makes reading and understanding what we are testing a lot simpler.

  4. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,240 @@
    +      $this->assertSame(['de' => TRUE], $this->assertBookLinkIsCorrectlyTranslatedUrls);
    

    Are we are going to use SELF::LANGUAGE or 'de'. My preference would be to use 'de' everywhere.

  5. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,240 @@
    +        $this->assertRegExp('/' . preg_quote($node_label, '/') . '$/', $title);
    

    Why is there a regex assertion here instead of a assertSame()? Please add documention why.

  6. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,240 @@
    +    $nid = $this->bids[17];
    

    Why this one and only this one?

  7. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,240 @@
    +      $this->assertSame(['de' => TRUE], $this->assertBookLinkIsCorrectlyTranslatedUrls);
    

    Could you add a comment about this line. What and why?

  8. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,240 @@
    +    $this->assertTrue($found);
    

    What are we testing on this line. Could you add a comment about the variable $found.

  9. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,240 @@
    +    $this->assertNotSame($language_manager->getCurrentLanguage(LanguageInterface::TYPE_INTERFACE)->getId(), $langcode);
    

    Could you add a comment about this line.

I would very much like to help by reviewing to get this patch committed.

ghost of drupal past’s picture

Status: Needs work » Needs review
StatusFileSize
new29.38 KB
new13.21 KB
new15.07 KB

I wholeheartedly agree the BookMultilingualTest has grown overcomplicated and needed a good cleanup. I am not attaching an interdiff -- it's longer than the test itself so it's easier to read the test. The trees are explained and laid out explicitly, and all the tests are explicit instead of recursion or loops, I hope it's much more plain what's being tested.

No changes to anything else but the test. Interdiffs to 179/190 attached for the same reason as before although they are growing less and less useful with every iteration.

ghost of drupal past’s picture

StatusFileSize
new31.88 KB
new21.26 KB
new19.83 KB

I just realized we already set up the language negotiator for outgoing URLs so why not use it for determining the current language? Very little is needed, in fact, on top of what we already had. So: no more fake language negotiator. Also, I have cleaned up the testMultilingualBookBreadcrumbBuilder to use the same assert as testMultilingualBookManager and that found the bug #192 actually applies to the breadcrumb as well so I fixed that up.

daffie’s picture

@chx: The BookMultilingualTest looks great now. Just one question: where is the testing for the change to the class BookExport?

Edit: And the same for the testig of the changes to the class BookAdminEditForm.

ghost of drupal past’s picture

StatusFileSize
new33.18 KB
new2.33 KB
new21.12 KB
new22.55 KB

I have added a book export test but I am pushing back on the admin form test: there is no test for that form yet and also there are various bugs for that which all could use a test like #1184692: Unpublished books can't be reordered at admin/structure/book/[bookid] and #1169576: Book allows emptying node titles in admin/content/book/* (Notice: Trying to get property of non-object in node_page_title) so I filed an issue and linked it to all three.

As for the change in negotiation weights -- it made no sense to have a -10 weight when there's only method for each so I set them to 0 instead so the next person changing this doesn't need to wonder why it's -10.

larowlan’s picture

This is looking great, just a couple of minor changes

  1. +++ b/core/modules/book/src/BookBreadcrumbBuilder.php
    @@ -38,10 +55,24 @@ class BookBreadcrumbBuilder implements BreadcrumbBuilderInterface {
    +      @trigger_error('The entity.repository service must be passed to ' . __NAMESPACE__ . '\BookBreadcrumbBuilder::__construct(). It was added in drupal:9.1.0 and will be required before drupal:10.0.0.', E_USER_DEPRECATED);
    ...
    +      @trigger_error('The language.manager service must be passed to ' . __NAMESPACE__ . '\BookBreadcrumbBuilder::__construct(). It was added in drupal:9.1.0 and will be required before drupal:10.0.0.', E_USER_DEPRECATED);
    

    these will need to be 9.2.0 now (9.1.0 is out this week)

  2. +++ b/core/modules/book/src/BookBreadcrumbBuilder.php
    @@ -67,7 +101,9 @@ public function build(RouteMatchInterface $route_match) {
    +    /** @var NodeInterface[] $parent_books */
    

    I think we typically use the FQCN in this type of comment

  3. +++ b/core/modules/book/src/BookBreadcrumbBuilder.php
    @@ -76,7 +112,7 @@ public function build(RouteMatchInterface $route_match) {
    +            $links[] = Link::fromTextAndUrl($parent_book->label(), $parent_book->toUrl());
    

    this could even just be $parent_book->toLink()

  4. +++ b/core/modules/book/src/BookExport.php
    @@ -40,11 +48,18 @@ class BookExport {
    +   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
    

    above we used |null but not here - we should make them consistent, I think without the |null means we don't have to do future cleanup - but not sure if we have a convention around this

  5. +++ b/core/modules/book/src/BookManager.php
    @@ -80,13 +98,27 @@ class BookManager implements BookManagerInterface {
    +   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
    ...
    +   * @param \Drupal\Core\Entity\EntityRepositoryInterface|null $entity_repository
    

    we document one of these with |null but not the other.

    We should be consistent.

  6. +++ b/core/modules/book/src/BookManager.php
    @@ -476,14 +512,14 @@ public function deleteFromBook($nid) {
    -    // Generate a cache ID (cid) specific for this $bid, $link, $language, and
    +    // Generate a cache ID (cid) specific for this $bid, $link, language, and
    

    any reason for this change, out of scope? I think it should be consistent (either use the $ for all, or don't)

  7. +++ b/core/modules/book/src/BookManager.php
    @@ -476,14 +512,14 @@ public function deleteFromBook($nid) {
    -    $cid = 'book-links:' . $bid . ':all:' . $nid . ':' . $language_interface->getId() . ':' . (int) $max_depth;
    +    $langcode = $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
    +    $cid = implode(':', ['book-links', $bid, 'all', $nid, $langcode, (int) $max_depth]);
    

    so much cleaner

  8. +++ b/core/modules/book/src/Form/BookAdminEditForm.php
    @@ -41,10 +49,17 @@ class BookAdminEditForm extends FormBase {
    +    if (!$entity_repository) {
    +      @trigger_error('The entity.repository service must be passed to ' . __NAMESPACE__ . '\BookAdminEditForm::__construct(). It was added in drupal:9.1.0 and will be required before drupal:10.0.0.', E_USER_DEPRECATED);
    +      $entity_repository = \Drupal::service('entity.repository');
    

    this is dead code, because we didn't make the argument optional.

    Should we?

  9. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,319 @@
    +    // To test every possible combination of root-child / child-child, two
    +    // trees are needed. The first level below the root needs to have two
    +    // leaves and similarly a second level is needed with two-two leaves each.
    +    // The root of the first tree is node 1, the first two leaves are 2 and 3.
    +    // The third level is 4, 5, 6, 7. The node IDs are enforced.
    +    // Similarly, the second tree root is node 8, the first two leaves are
    +    // 9 and 10, the third level is 11, 12, 13, 14.
    

    this is a really helpful comment, perhaps we could also get a representation of the tree in the comment something like this to make it abundantly clear (borrowed from another project, not the actual representation):

    // Parent
    // - 1
    // -- 1.1
    // --- 1.1.1
    // --- 1.1.2
    // -- 1.2
    // --- 1.2.1
    // --- 1.2.2
    // - 2
    // -- 2.1
    // -- 2.2
    // ---- 2.2.1
    // - 3.
    
  10. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,319 @@
    +   * @param $nid
    ...
    +   * @param $title
    

    missing type-hints here

  11. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,319 @@
    +  protected function assertNodeLinkIsCorrectlyTranslated($nid, $title, Url $url, string $langcode): void {
    ...
    +   * @param $toc
    ...
    +   * @param $nid
    ...
    +   * @param $indent
    ...
    +  protected function assertToCEntryIsCorrectlyTranslated($toc, $langcode, $nid, $indent) {
    

    we can use scalar type hints here, we're doing so elsewhere so it should be consistent

ghost of drupal past’s picture

StatusFileSize
new33.35 KB
new10.08 KB
  1. fixed (I ran sed on the patch...)
  2. Fixed
  3. That's nice
  4. I have added the |null because that's what I saw elsewhere
  5. Same
  6. Yes, the full comment is Generate a cache ID (cid) specific for this $bid, $link, language, and depth -- depth was already there, there is no $depth and similarly there is no $language.
  7. :)
  8. Yes
  9. Replaced text with diagram
  10. added type hints
  11. added more type hints

I didn't reroll all the interdiffs this time.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

It all looks good to me.
For all changes there are tests added.
With the exception of the changes to the class BookAdminEditForm, there is a followup issue #3185666: Test the book admin form.
All points of @larowlan have been addressed.
For me it is RTBC.

@chx: Nice work!

joseph.olstad’s picture

Great work @Charlie ChX Negyesi and @larowlan and others.
+1 super

larowlan’s picture

Status: Reviewed & tested by the community » Needs review

Only super-nits now, feel free to self-RTBC these changes

  1. +++ b/core/modules/book/src/BookBreadcrumbBuilder.php
    @@ -31,6 +34,20 @@ class BookBreadcrumbBuilder implements BreadcrumbBuilderInterface {
    +   * @var \Drupal\Core\Language\LanguageManagerInterface|mixed|null
    

    is this ever mixed?

  2. +++ b/core/modules/book/src/BookBreadcrumbBuilder.php
    @@ -38,10 +55,24 @@ class BookBreadcrumbBuilder implements BreadcrumbBuilderInterface {
    +  public function __construct(EntityTypeManagerInterface $entity_type_manager, AccountInterface $account, EntityRepositoryInterface $entity_repository = NULL, LanguageManagerInterface  $language_manager = NULL) {
    

    nit, two spaces here

  3. +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
    @@ -0,0 +1,329 @@
    +    $this->installEntitySchema('node');
    ...
    +    $this->installEntitySchema('node');
    

    we double up here

ghost of drupal past’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new1.68 KB
new33.3 KB
  1. That's just phpstorm, it's not like I am writing these manually... removed.
  2. fixed
  3. removed

naveedahmadkhan.jadoon@gmail.com made their first commit to this issue’s fork.

naveed_jadoon’s picture

hi i got this on applying #223 patch for drupal 8.9.0, if someone can help that would be nice

Drupal\Core\Config\UnsupportedDataTypeConfigException: Invalid data type in config book.schema, found in filecore/modules/book/config/schema/book.schema.yml : A YAML file cannot contain tabs as indentation at line 36 (near " type: string"). in Drupal\Core\Config\FileStorage->read() (line 118 of core/lib/Drupal/Core/Config/FileStorage.php).

naveed_jadoon’s picture

dbielke1986’s picture

@naveedahmadkhan.jadoon@gmail.com
The patch of #223 is not compatible with D8.9.x

You need to use the following one
#206

larowlan’s picture

Adding issue credits for reviews

larowlan’s picture

Status: Reviewed & tested by the community » Needs work

Went to commit this but there's some cspell and PHPCS violations

Checking changed files...
CSPELL: checking all files
/Volumes/files/code/git/core/drupal/core/modules/book/tests/src/Kernel/BookMultilingualTest.php:29:22 - Unknown word (langcude)
CSpell: Files checked: 7, Issues found: 1 in 1 files
PHPCS: core/modules/book/book.services.yml passed

FILE: .../git/core/drupal/core/modules/book/src/BookBreadcrumbBuilder.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
 95 | ERROR | [x] Closing parenthesis of array declaration must be on
    |       |     a new line
----------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

Time: 142ms; Memory: 10MB

PHPCS: core/modules/book/src/BookExport.php passed
PHPCS: core/modules/book/src/BookManager.php passed
PHPCS: core/modules/book/src/Form/BookAdminEditForm.php passed

FILE: ...upal/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
----------------------------------------------------------------------
FOUND 12 ERRORS AND 2 WARNINGS AFFECTING 14 LINES
----------------------------------------------------------------------
  71 | WARNING | [x] A comma should follow the last multiline array
     |         |     item. Found: ]
  72 | WARNING | [x] A comma should follow the last multiline array
     |         |     item. Found: ]
 132 | ERROR   | [x] Case breaking statements must be followed by a
     |         |     single blank line
 134 | ERROR   | [x] Line indented incorrectly; expected 14 spaces,
     |         |     found 12
 135 | ERROR   | [x] Line indented incorrectly; expected 14 spaces,
     |         |     found 12
 136 | ERROR   | [x] Line indented incorrectly; expected 14 spaces,
     |         |     found 12
 137 | ERROR   | [x] Case breaking statements must be followed by a
     |         |     single blank line
 139 | ERROR   | [x] Line indented incorrectly; expected 14 spaces,
     |         |     found 12
 140 | ERROR   | [x] Line indented incorrectly; expected 14 spaces,
     |         |     found 12
 141 | ERROR   | [x] Line indented incorrectly; expected 14 spaces,
     |         |     found 12
 142 | ERROR   | [x] Case breaking statements must be followed by a
     |         |     single blank line
 144 | ERROR   | [x] Line indented incorrectly; expected 14 spaces,
     |         |     found 12
 145 | ERROR   | [x] Line indented incorrectly; expected 14 spaces,
     |         |     found 12
 146 | ERROR   | [x] Line indented incorrectly; expected 14 spaces,
     |         |     found 12
----------------------------------------------------------------------
PHPCBF CAN FIX THE 14 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

Time: 229ms; Memory: 10MB

Whilst we're at it, can we also change the typehint for language manager param on book manager to use |null like the subsequent argument, so they're consistent

ghost of drupal past’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new34.94 KB
new5.29 KB

I will self-RTBC this because after all this is just code styling (approved by larowlan). All changes are by phpcbf except for the langcude and |null as requested. However, I reverted some changes it made: case 1: case 2: should not be indented with two extra spaces. They should be indented as case 0 is and so I have opted out of those fixes.

  • larowlan committed bce4634 on 9.2.x
    Issue #2470896 by Charlie ChX Negyesi, ErikWegner, joseph.olstad,...
larowlan’s picture

Assigned: ghost of drupal past » Unassigned
Issue summary: View changes
Status: Reviewed & tested by the community » Fixed
Issue tags: +9.2.0 release highlights

Fixed on commit to resolve phpcs automated issue mentioned in #230

diff --git a/core/modules/book/tests/src/Kernel/BookMultilingualTest.php b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
index 6f895e5380..38bcdcffc3 100644
--- a/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
+++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php
@@ -131,19 +131,22 @@ protected function setUp(): void {
             $node->book['depth'] = 1;
             break;

-          case 1: case 2:
+          case 1:
+          case 2:
             $node->book['bid'] = $root;
             $node->book['pid'] = $root;
             $node->book['depth'] = 2;
             break;

-          case 3: case 4:
+          case 3:
+          case 4:
             $node->book['bid'] = $root;
             $node->book['pid'] = $root + 1;
             $node->book['depth'] = 3;
             break;

-          case 5: case 6:
+          case 5:
+          case 6:
             $node->book['bid'] = $root;
             $node->book['pid'] = $root + 2;
             $node->book['depth'] = 3;

Publishing the change record.

Congrats all.

This isn't eligible for backport because of the new deprecations.

ghost of drupal past’s picture

StatusFileSize
new35.99 KB

While not eligible for core commit, here's the patch re-rolled for 8.9.x for those who still run that -- and I suspect quite a few of us intend to do so for quite a while yet. Now is the time to do so. Conflicts were minimal.

bserem’s picture

StatusFileSize
new35.55 KB

Highly discouraged and not fully tested, but attached is a patch for Drupal 8.8.12 as requested by a site that hasn't yet updated to 8.9 (they run an older open social version).

Don't say you weren't warned, use at your own risk.

raman.b’s picture

Anyone encountered the following exception after this got committed?

"Uncaught PHP Exception Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: "You have requested a non-existent service "language.manager". Did you mean this: "language_manager"?"

Created #3188519: "Uncaught PHP Exception Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: "You have requested a non-existent service "language.manager". Did you mean this: "language_manager"?"

joseph.olstad’s picture

StatusFileSize
new35.99 KB

Reroll for 8.9.x, I have a client using this.
I took the same patch as 233 and just did a search for 'language.manager' and replaced the one instance
as per the issue noted just above

diff 2470896_233.patch 2470896_237.patch 
88c88
< +      $language_manager = \Drupal::service('language.manager');
---
> +      $language_manager = \Drupal::service('language_manager');
joseph.olstad’s picture

***EDIT*** oops comment, removing it.

joseph.olstad’s picture

Status: Fixed » Closed (fixed)

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

dbielke1986’s picture

With patch 233 we have a critical issue for D8:

  1. unpublished nodes were shown in the book navigation
  2. unpublished nodes were exported when you are using the printer friendly version

This is a huge issue when you try to create customer documentation were unpublished nodes gets exported.

dbielke1986’s picture

PS: Patch from #199 is working fine!
Hopefully Drupal 9.2 is working fine with the implemented version.

Can somebody try it out?

qusai taha’s picture

StatusFileSize
new21.19 KB

Reroll for Drupal 9.1.10.
is working fine for me.

joaoclobocar’s picture

StatusFileSize
new21.19 KB

On Drupal 9.1.10, I had to modify from language.manager to language_manager before applying the patch.

berdir’s picture

That is a bug, not related to 9.1/9.2, I assume you subclassed that class in your project and it triggers the BC layer. That part isn't tested. Please create a new issue to fix that and reference it here.

Edit: That was fixed in 9.2: #3188519: "Uncaught PHP Exception Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: "You have requested a non-existent service "language.manager". Did you mean this: "language_manager"?". And maybe you didn't actually have a subclass, more likely you just didn't clear the cache.

ahmad abbad’s picture

#244 works for me on Core 9.1.8

rachel_norfolk’s picture

Thanks for comments, Ahmad. So that the maintainers can understand in what way it "works for me", can you include a description of what you tested and, if possible, show some evidence of the change making a positive difference? Screenshots are usually the easiest way to do this - before and after applying the patch.

Have a read of https://www.drupal.org/community/contributor-guide/task/manually-test-a-... for more info.

(this is the stuff that's needed to ensure you get correctly credited for your work!)

dbielke1986’s picture

I created a new bug in the core (https://www.drupal.org/project/drupal/issues/3228274) because the issue I found in #244 is now the harsh reality... achrived/unpublished nodes gets into the htm export....