Problem

When setting language detection method, the checkbox Customize Content language detection to differ from User interface text language detection settings is not applied, only the interface configuration.

This leads to two critical issues with translating content:

  1. It is not possible to edit translated version of a node. All "Edit" urls on node's "Translate" tab are the same and lead to main editing form. See edit.png.
  2. Translated content is never shown to the user. Default language is always displayed.

Steps to reproduce

On a fresh D8 install:

  1. Enable content translation and language modules
  2. Add another language
  3. Set Detection and selection method to session and browser (tested both, both are broken)
  4. Configure content type "Article" to be translatable (Administration >> Configuration >> Regional and language)
  5. Add a node and set it's language to default one (I used article with image. All fields were filled including image)
  6. Translate node to a second language and save.
  7. Go to "Translate" tab and investigate "Edit" links. Both lead to the same page.
  8. Go to the newly create node and try switching language using "session" parameter. You will still see the node in default language.
  9. Do the same with a browser running second language (or just spoof the browser string to change language). You will still see the node in default language.

Remaining tasks

  1. Investigate why the checkbox Customize Content language detection to differ from User interface text language detection settings is ignored. The source of the issue lies probably inside Drupal\language\Form\NegotiationConfigureForm::submitForm() function. - the configuration is correctly saved
  2. Create patch - Patch is provided

User interface changes

No changes to the UI are required for the fix.

API changes

The protected variable type which indicates whether a given type of language usage (language_content, language_interface, language_url) changes to an array to allow different types to initialize during the initialization of another.

CommentFileSizeAuthor
#101 2189267-100.patch8.67 KBalexpott
#101 98-100-interdiff.txt1015 bytesalexpott
#98 2189267-98.patch8.64 KBalexpott
#98 88-98-interdiff.txt1.23 KBalexpott
edit.png79.95 KBSiliconMind
detection.png55.27 KBSiliconMind
#13 content_language-2189267-13.patch1.29 KBsnufkin
#14 content_language-2189267-13.patch1.11 KBsnufkin
#15 content_language-2189267-13.patch1.33 KBsnufkin
#19 content_language-2189267-13.patch1.47 KBsnufkin
#19 content_language-2189267-13.patch1.47 KBsnufkin
#22 content_language-2189267-13.patch1.57 KBsnufkin
#24 content_language-2189267-24.patch1.66 KBsnufkin
#29 content_language-2189267-29-test-only.patch3.22 KBmaxocub
#29 content_language-2189267-29.patch4.87 KBmaxocub
#40 node-translations-d8_2_1.png45.37 KBmirsoft
#40 node-translations-d8_2_1.png48.94 KBmirsoft
#40 invalid-settings.png117.46 KBmirsoft
#40 no-link.png37.13 KBmirsoft
#41 config.png89.99 KBAnonymous (not verified)
#42 failing_language_detection.png100.52 KBblazey
#43 same-stuff.png137.21 KBAnonymous (not verified)
#43 what-to-do.png113.78 KBAnonymous (not verified)
#51 Screen Shot 2017-02-08 at 16.30.32.png416.33 KBwannesdr
#53 2189267-53-without-24.patch7.17 KBnuez
#53 2189267-53.patch8.83 KBnuez
#60 2189267-60.patch2.86 KBAndriy Khomych
#62 ui-configuration-lang.png62.52 KBmErilainen
#63 block_multilingual_issue.patch3.3 KBa3hill
#69 2189267-69-test-only.patch7.17 KBManuel Garcia
#69 2189267-69.patch8.83 KBManuel Garcia
#72 2189267-72.patch8.91 KBManuel Garcia
#72 interdiff-2189267-69-72.txt8.25 KBManuel Garcia
#73 2189267-73.patch8.9 KBManuel Garcia
#73 interdiff-2189267-72-73.txt648 bytesManuel Garcia
#75 2189267-75.patch8.89 KBManuel Garcia
#75 interdiff-2189267-73-75.txt768 bytesManuel Garcia
#78 2189267-78-test-only.patch7.25 KBManuel Garcia
#78 2189267-78.patch8.48 KBManuel Garcia
#78 interdiff-2189267-75-78.txt6.76 KBManuel Garcia
#79 2189267-79-test-only.patch6.95 KBManuel Garcia
#88 2189267-88.patch8.52 KBManuel Garcia
#88 interdiff-2189267-78-88.txt754 bytesManuel Garcia
#88 2189267-88-test-only.patch6.98 KBManuel Garcia
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

SiliconMind’s picture

Issue summary: View changes

Added steps to reproduce.

SiliconMind’s picture

Irrelevant.

SiliconMind’s picture

Project: Content translation » Drupal core
Version: » 8.x-dev
Component: Code » content_translation.module

OK, this is embarrassing - I posted this to the wrong project :)

SiliconMind’s picture

Priority: Major » Critical
Issue summary: View changes

I'm changing this to critical. The site is unusable with this bug if you want to use more than one language.
The issue might be related to this: #2214697: Invalid argument supplied for foreach() in Drupal\content_translation\ContentTranslationController->entityFormAlter()

Also updated "steps to reproduce" as it missed one important step.

SiliconMind’s picture

My investigation led me to the Drupal\language\Entity\Language::preSave method that explicitly sets "en" langcode for EVERY language that is being saved. So no matter what language is chosen on "Add language" form (admin/config/regional/language/add), the langcode is always set to "en".

  public function preSave(EntityStorageControllerInterface $storage_controller) {
    parent::preSave($storage_controller);
    // Languages are picked from a predefined list which is given in English.
    // For the uncommon case of custom languages the label should be given in
    // English.
    $this->langcode = 'en';
  }

No wonder that each language.entity.*.yml file has "langcode" set to "en".
Why this is hardcoded?

SiliconMind’s picture

Argh, Ignore my last comment. It seems that language.entity.*.yml is a dead end. The langcode in these files are for label purpose only. It looks like this is langcode of the language entity, not the language itself. This is very misleading.

SiliconMind’s picture

Upon more digging I've found that despite setting language detection for interface to browser and session AND un-checking Customize Content language detection to differ from User interface text language detection settings, language negotiation for content was always set to default, which is 'URL'.

As soon as I've checked Customize Content language detection to differ from User interface text language detection settings and set detection method for content to browser and session explicitly, I was able to see translated content properly.

So it seems that option Customize Content language detection to differ from User interface text language detection settings is ignored.

SiliconMind’s picture

Title: Content translation not working » Content language detection must be set explicitly to work correctly
Component: content_translation.module » language system
Issue summary: View changes

Updated issue to reflect recent findings.
It seems that Drupal\language\Form\NegotiationConfigureForm::submitForm() needs fixing.

It would be nice to be able to delete comments that are now irrelevant (#2, #5, #6).

catch’s picture

Priority: Critical » Major
Issue tags: +D8MI

Tagging with D8MI. This looks like just the configuration form itself is broken rather than negotiation, so moving to major.

meyertox’s picture

Same problem in D 8.0.0-beta; even if Customize Content language detection to differ from User interface text language detection settings-checkbox is on or off, the links in the admin-interface for editing and translating a page/content are resulting in same links

Bearbeiten

Bearbeiten

matsbla’s picture

I also see same issue no matter if the "Customize Content language detection to differ from User interface text language detection settings"-checkbox is on or off.

Maybe this is related?
#2476563: Entity operations links tied to original entity language, ignore everything else

snufkin’s picture

This can be reproduced on the latest dev as well. I've looked into the previously mentioned submitForm() method, but it seems that negotiations are saved just fine as they appear in the config object:

all:
  - language_interface
  - language_content
  - language_url
configurable:
  - language_interface
  - language_content
negotiation:
  language_content:
    enabled:
      language-url: -8
      language-selected: 12
    method_weights:
      language-content-entity: -9
      language-url: -8
      language-session: -6
      language-user: -4
      language-browser: -2
      language-interface: 9
      language-selected: 12
  language_url:
    enabled:
      language-url: 0
      language-url-fallback: 1
  language_interface:
    enabled:
      language-user-admin: -10
      language-url: -8
      language-selected: 12
    method_weights:
      language-user-admin: -10
      language-url: -8
      language-session: -6
      language-user: -4
      language-browser: -2
      language-selected: 12
_core:
  default_config_hash: dqouFqVseNJNvEjsoYKxbinFOITuCxYhi4y2OTNQP_8

Regardless of what language detection I set for content language detection it always defaults to the source node (in this case english).

In comparison here is the config when i disable the Content language customization:

all:
  - language_interface
  - language_content
  - language_url
configurable:
  - language_interface
negotiation:
  language_content:
    enabled:
      language-url: -8
    method_weights:
      language-content-entity: -9
      language-url: -8
      language-session: -6
      language-user: -4
      language-browser: -2
      language-interface: 9
      language-selected: 12
  language_url:
    enabled:
      language-url: 0
      language-url-fallback: 1
  language_interface:
    enabled:
      language-user-admin: -10
      language-selected: 12
    method_weights:
      language-user-admin: -10
      language-url: -8
      language-session: -6
      language-user: -4
      language-browser: -2
      language-selected: 12
_core:
  default_config_hash: dqouFqVseNJNvEjsoYKxbinFOITuCxYhi4y2OTNQP_8
snufkin’s picture

Status: Active » Needs review
FileSize
1.29 KB

So it seems that \Drupal\language\ConfigurableLanguageManager::getCurrentLanguage somehow gets called while it is initialising, and due to the check on $this->initializing it will not process the next query.

If I change this to an array where the key is the type, then the content translation picks up from the URL fine and I see a translated content with english interface.

snufkin’s picture

Oops, random whitespace change crept in.

snufkin’s picture

Updating the type of the protected variable as well.

The last submitted patch, 13: content_language-2189267-13.patch, failed testing.

The last submitted patch, 14: content_language-2189267-13.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 15: content_language-2189267-13.patch, failed testing.

snufkin’s picture

Let's see if we initialise the $initializing array with all possible types to FALSE solves the notice errors.

edit: due to a form error I have duplicate patches uploaded, ignore one please.

The last submitted patch, 19: content_language-2189267-13.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 19: content_language-2189267-13.patch, failed testing.

snufkin’s picture

Status: Needs work » Needs review
FileSize
1.57 KB

Initializing the array on the first request to avoid the undefined index notices.

Gábor Hojtsy’s picture

Yay, thanks! Issue title and summary needs to be updated to current state. Also needs tests for the bug. Finally:

+++ b/core/modules/language/src/ConfigurableLanguageManager.php
@@ -99,7 +99,7 @@ class ConfigurableLanguageManager extends LanguageManager implements Configurabl
    * @var bool
    */
-  protected $initializing = FALSE;
+  protected $initializing = [];

Type phpdoc should be updated too.

Also, this is protected, so any classes inheriting from this language manager would now get a new type for this variable. Is that a BC change or not? :) How do we consider that now. https://www.drupal.org/core/d8-allowed-changes does not spell out protected members.

snufkin’s picture

Title: Content language detection must be set explicitly to work correctly » When content language detection is different from interface language detection, the detected language is not applied to the rendered content
Issue summary: View changes
FileSize
1.66 KB
  • Fixing the phpdoc annotation for the variable type.
  • Updating issue summary and issue title
timmillwood’s picture

Version: 8.0.x-dev » 8.1.x-dev
Gábor Hojtsy’s picture

Status: Needs review » Needs work
Issue tags: -Needs issue summary update +Needs tests

As I wrote in #27, this needs test coverage for the bug to prove its fixed. Sorry forgot to add the tag.

fran seva’s picture

Assigned: Unassigned » fran seva
pbonnefoi’s picture

Applying the patch fixed the problem for me. Thanks for the good work !

The last submitted patch, 29: content_language-2189267-29-test-only.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 29: content_language-2189267-29.patch, failed testing.

jjcarrion’s picture

Patch #24 works fine for me.

@maxocub, you said that didn't work for you, could it be that you have another order in the 'Content language detection'? I have used something like this:

Language detection

Great work all!

maxocub’s picture

Hi @jjcarrion, the settings you show on your screen capture work well even without the patch. What I tried and what I reproduced in the test is what is mentioned in the step to reproduce of the issue summary:

3. Set Detection and selection method to session and browser (tested both, both are broken)

Maybe the issue summary or title should be updated, they are not perfectly clear to me.

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.

spoit’s picture

Patch #24 fixed it for me too (on 8.2.x)

Without the patch combining Account administration pages language setting (in Interface text) with Content language (in Content language detection ) just does not work.

Gábor Hojtsy’s picture

I think #24 is clearly fixing a bug, since if you call getCurrentLanguage() for the content language, it depends on the interface language, so if the later is not yet negotiated, that is called again, which then is not initialized properly because another language type is already being initialized. So to avoid a recursion, that is not negotiated. But its a different type, so it should be negotiated to be used for the content language. Does that help outline the purpose of #24 @maxocub? Your test does not test that scenario because it disabled the interface language detection on the content language, so the "recursion" of negotiation does not even happen. Not surprising that the patch does not make a difference for your scenario.

dubcanada’s picture

Patch #24 fixes my translation issues as well.

Mojtaba Reyhani’s picture

I added a RTL Language translation File (Like: Persian, Farsi) to my drupal 8 site and What I simply want is to All "Administration Pages language" (or backend Language) in english only and all admin menu Always in left side and frontend pages of the site(Site Language) in another language (Like: persian, Farsi)
I do below setting:

1- I enabled the Language module, and set-up one additional language. Install was done in En (english), and I added Fa (Persian) language.
Language Module Configuration
Language Module Configuration

2- I configure the administration language separate to the content language by below setting:

/admin/config/regional/language/detection:
Account administration pages: enabled

Interface text language Configuration
Interface text language Configuration

3-Admin -> Edit Profile -> Edit(Tab)
Configuration of Administration Language
Configuration of Administration Language

This work properly for all administration page and those are English and in left side (LTR) except the "home page" and "user/1/" and admin/structure/block/demo/'Theme Name' of the site that the administration menu is in Persian Language and in right side (RTL) yet.

Administration Pages
Administration Pages

Home Page
Home Page

Gábor Hojtsy’s picture

@Mojtaba Reyhani: looks like your problem is not related to which language is selected for the page, but how the admin menu is rendered? We have #2313309: Admin toolbar and contextual links should always be rendered in the admin language (if set) for that, which did not see to have much interest from users so far unfortunately :/

mirsoft’s picture

I was going to write tests for this to proceed further, however during getting through whole story I wasn't able to reproduce the issue anymore (Drupal 8.2.1).

The setting from screenshot #32 provides already correct language translation query parameter "language_content_entity" that determines the correct translation paths to each node's translation:

correct behavior

The issue I found was in case we only select browser and/or session in either settings:

invalid settings

In that case, the "translate" page does not differentiate with any URL:

no link

That actually corresponds with the original ticket description, however does not correspond with the patch in #24 (it actually does not fix this issue).

In a summary, could please somebody explain and/or summarize and update the ticket description and provide clear testing path with exact previous state, exact working patch and exact state that the patch fixes?

Anonymous’s picture

FileSize
89.99 KB

yes. I do have this issue too! This is hilarious!
asd

it is critical bug, we cannot edit translated content at all! Only language switch helps

blazey’s picture

FileSize
100.52 KB

@yurii_2016 Have you tried checking the box at the bottom of the form and enabling Content Language detection method?

@mirsoft I have also been trying to write a test and my results are similar.

When content language detection is enabled and Content language detection method is chosen everything works fine. Translation forms can be reached via edit links on both /node/{nid}/translations and /admin/content.

The problem starts when all detection methods other than Browser and Session are disabled. This is the case described in #40 but also the one pictured below, when content language detection is disabled completely.

Only Browser and Session detection methods enabled

In this setup translations' Edit buttons are pointing to /node/{nid}/edit and show the node in wrong (default) language. Patch from #24 doesn't help.

I think what we need here is something like Content language detection method enabled all the time under the hood for edit links. There is no way to determine language of edited entity based on Accept-language header sent by editor's browser.

Anonymous’s picture

FileSize
137.21 KB
113.78 KB

blazey,

same stuff. maybe it is bug of autopath module.. we're on 8.2.0, maybe it was fixed? I don't know.

sa

Another stuff. Tried to change manually language of alias to 'none' - then it shows page in currently selected language for any alias.. other way one of alias'ed page is 'not' found'.

what

regards!

p.s.
I was switched to another project, so I'm not able to dig to D8 for now, but this stuff is critical

Gábor Hojtsy’s picture

@yurii_2016: let's not use this issue as a general support forum, what does the language of path aliases has to do with what language does Drupal pick for editing a node?

Anonymous’s picture

Gábor Hojtsy,

so far only bug reports are active on useful response (at least for me), drupal answers has no use too. but ok, i'll try to be quiet

about path alias - i think this is related issue, because path alias has this 'language' distinction which MUST be used to load appropriate content, and not be overlapped by user language selection. Or not?! This is what happens in admin panel too (i think).

*e-em, or should try to change order of language negotiation options somehow?

spoit’s picture

While using the patch in #24 is working well for editing entities, it seems to mess up ajax file uploads in an evil way:

Normal ajax callback url:
/nl/node/370/edit?element_parents=gt_main_photo/widget/0&ajax_form=1&_wrapper_format=drupal_ajax

When using the language_content_entity parameter:

/nl/node/370/edit?language_content_entity=nl?element_parents=gt_main_photo/widget/0&language_content_entity=nl&ajax_form=1&_wrapper_format=drupal_ajax

Mind the double"?" which make the ajaxCallback function fail. On the UI side this makes the full widget disappear (since the ajax callback fails to deliver a new one)

danquah’s picture

Seems https://www.drupal.org/node/2772891 is a duplicate of this issue, can anyone confirm, and does it make sense to incorporate any of the work from that issue in to this, or should it just be closed?

mogio_hh’s picture

I also have the problem that twig templates t() function and other elements like yml forms pick up the UI language rather than the content defined or url defined language.

Its so funny that nobody fixes this problem. Seems to me like the whole backend / content language feature makes no sense like this.

Also I recognized that the lang attribute of the html tag shows the default admin language instead of the language that is defined through the url prefix.

Crazy stuff.

mogio_hh’s picture

Can smb confirm issue #46?

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.

wannesdr’s picture

Issue summary: View changes
FileSize
416.33 KB

@mogio_hh I can't confirm the file upload issue. Any image uploading works fine with me.

I can also confirm patch #24 solves the issue as described. When detection & selection settings is set as shown in the attached screenshot and content is added, adding translations doesn't work as it should. With the patch it does.
Wat needs to be done to get this committed in core? Should any tests be updated/written?
screenshot

stella’s picture

I can confirm the file upload issue.

It's interesting to note though, that I am using the Media module on the site and so am uploading my images via the media entity. While I have nodes marked as translatable, and media entities are translatable, the file fields are not. Even if I go to add a media item directly (ie not via the inline entity form on the node) i still can not upload new images.

No errors in the logs, no errors in the console, it just sits and spins.

nuez’s picture

Version: 8.3.x-dev » 8.4.x-dev
Assigned: fran seva » Unassigned
Status: Needs work » Needs review
FileSize
7.17 KB
8.83 KB

I can confirm that #24 works for me. I've written a browsertest to validate the patch. The test includes:

  • Content and Interface language negotiation based on URL and the Preferred Administration language of the user.
  • Content and Interface language negotiation based on URL and the Session variable

I'm adding two patches, one including #24 which should pass, one without #24 which should fail. I hope we can book some progress on this since it's quite a critical bug imho.

The last submitted patch, 53: 2189267-53-without-24.patch, failed testing.

nuez’s picture

Status: Needs review » Needs work

I overlooked the Ajax upload issue, sorry about that, I'll see if I can find the time to add a test for the ajax file as well.

nuez’s picture

I have been trying to reproduce the image upload issue (no media module, just core) but I cannot reproduce it after going through the following steps and applying patch #24.

Steps:

  1. Installing a standard installation
  2. Enabling content translation and interface translation
  3. Enabling Spanish and english
  4. Setting both article and basic page content types as translatable)
  5. Setting interface language negotiation to
    1. Account administration pages
    2. URL
  6. Enabling content language negotiation and setting it to
    1. URL
  7. Setting preferred administration language to english of user 1.
  8. Creating article with language english and upload an image.
  9. Translating that same article to spanish and change the image.
  10. Making the file field translatable too and change the image of both translations.

I found no issue with the upload widget.

Maybe spoit and stella can provide us with the exact steps to reproduce this issue?

Another issue

I did however find an issue with the toolbar and the administration language negotiator switched on, following the exact same steps, but I'm assuming that the issue is unrelated:

It happens when viewing the full page node: The access callback that collects the cached subtrees of the toolbar returns an Access Denied, breaking the toolbar. The issue only occurs when activating caches. When disabling them using settings.local.php the issue does not occur:

http://localhost/<<drupal8>>/toolbar/subtrees/nAMBTIOqWe13vT5ZIhj_JroJ1d-FcDGfVKyhzq6wpFA?_wrapper_format=drupal_ajax Failed to load resource: the server responded with a status of 403 (Forbidden)

I'm going to try and find the issue, and if it doesn't exist already create it.

nuez’s picture

Status: Needs work » Needs review
nuez’s picture

stella’s picture

Still an issue for me, though maybe it's something to do with the fact that i'm using an entity browser to pull in the image, but then again, that's because i'm using a media field, so wouldn't be an option on regular image fields iirc.

Andriy Khomych’s picture

Hi, guys, I found other problem, after I enabled this patch, when I added it to the site and created custom block type with field paragraph reference, it doesn't render this block with correct language under admin user with predefined language. May be this will need separate issue. Nevertheless, I created a patch for this.

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

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now 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.

mErilainen’s picture

FileSize
62.52 KB

Patch in #24 (and #53) works when I select non-default language (Finnish) as "Administration pages language" and move it over URL in interface detection method.
No need to change "Content language detection" to differ, but then when viewing content in other language UI will change too. This is acceptable for now as long as admin pages stick to user selection.

Edit: It seems that "Content language detection" has to be enabled after all, maybe there was some caching issue why it behaved like that. But the the issue below still exists.

But I noticed that users will need a "Bypass content access control" permission for this to work. Without that permission user will see a mix of UI strings in the selected admin language and configuration (for example field labels) in the default language of the site. Check the attached image.

a3hill’s picture

Updating #60 patch for 8.4.x.

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

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now 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.

douggreen’s picture

I ran across this problem in 8.4.x, debugged the issue to the recursion in language detection and the initializing variable, found #2772891: Wrong url-language negotiated when the user has an admin-language which directed to here, and see that the solution in #53 is the same solution we've had for at least a year and a half. I'm unaware of the second issue fixed here.

Should there be two issues, one for the initialization recursion, and one for the block UI, so that we can get them each RTBM and committed? The initialization issue has been around with a fix for almost 2 years now.

swentel’s picture

So the patch in #53 seems to work fine for editing (don't forget to configure Content language detection though).
I still need to confirm whether uploading works fine as #46 reports something might be wrong.

- edit - uploading seems to work fine for me

Also it's very confusing to start uploading different patches like in #60 and #63
Either merge them or create different issues which link to each other.

Rob230’s picture

The original problem elaborated in #40 and #42 seems to have been forgotten about, and the ticket rewritten to fix something else, that isn't even broken.

For me, if I enable content language detection then it works, with or without #24 / #53. The patch changes nothing. But if I don't have it enabled, it is impossible to edit translations because all edit links simply point to node/[nid]/edit, as discussed earlier in the ticket.

So basically, you must use either URL or content language detection, otherwise you will never be able to edit translated nodes.

GiorgosK’s picture

#53 patch does not apply in 8.5.x version

Checking patch core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php...
error: while searching for:
      $temp_view = $this->getTemporaryView();

      // Add the sort from the options to the default display.
      // This is broken, in that the sort order field also gets added as a
      // select field. See https://www.drupal.org/node/844910.
      // We work around this further down.
      $sort = $options['subquery_sort'];
      list($sort_table, $sort_field) = explode('.', $sort);
      $sort_options = ['order' => $options['subquery_order']];
      $temp_view->addHandler('default', 'sort', $sort_table, $sort_field, $sort_options);
    }

error: patch failed: core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php:192
error: core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php: patch does not apply

the original issue mentioned by @rob230 at #67 seems to have been neglected even though its Major

Manuel Garcia’s picture

@GiorgosK Patch #53 does apply cleanly against 8.5.x - It looks like you tried to apply a different patch, becasue #53 is not trying to modify the file core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php

@Andriy Khomych re #60 Feels like a different problem, please do open a new issue with the patch attached - thanks!

I am re-uploading both patches from #53 here for clarity. If anyone wants to add to the solution being proposed here, please continue from this patch as it already has tests.

The last submitted patch, 69: 2189267-69-test-only.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

borisson_’s picture

Status: Needs review » Needs work

I have some comments on the latest patch, it's great to see that the patch passes and the tests fail when it's not there, so that's a great thing!

I think apart from these nitpicks + a documentation update this is good to go.

Great work!

  1. +++ b/core/modules/language/src/ConfigurableLanguageManager.php
    @@ -212,13 +212,18 @@ public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) {
    +      // Ensure that the initalizing array is properly set up for any keys.
    +      if (!isset($this->initializing[$type])) {
    +        $this->initializing[$type] = FALSE;
    +      }
    

    This comment doesn't make me any wiser about what this line is actually doing, can we document the why here?

  2. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,207 @@
    +  public static $modules = [
    

    Needs a docblock. {@inheritdoc} should suffice.

  3. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,207 @@
    +   * @var LanguageNegotiatorInterface
    ...
    +   * @var User
    ...
    +   * @var ConfigFactory
    ...
    +   * @var StringStorage
    

    The documentation standards say that this should be the FQN, not the short version. So this needs to change, it should also have a single line of what the thing is.

  4. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,207 @@
    +  protected function setUp() {
    

    This also needs a docblock.

  5. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,207 @@
    +
    +
    

    Should be only one blank line.

  6. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,207 @@
    +    $this->assertSession()->responseContains('English');
    +    $this->assertSession()->responseContains('Powered by');
    

    Should probably use pageTextContains() instead of responseContains

  7. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,207 @@
    +    $this->assertSession()->responseContains('Español');
    +    $this->assertSession()->responseContains('Funciona con');
    +    $this->assertSession()->responseNotContains('Powered by');
    

    ^

Manuel Garcia’s picture

Status: Needs work » Needs review
FileSize
8.91 KB
8.25 KB

Thanks for the review @borisson_!

Re #71.1 -

+      // Ensure that the initalizing array is properly set up for any keys.
+      if (!isset($this->initializing[$type])) {
+        $this->initializing[$type] = FALSE;
+      }

Not entirely sure what this should say, which kinda proves the point that we actually need to explain the reasoning here :D - any suggestions?

All other points on #71 addressed, also cleaned up a few other CS issues, cached the assert session, and removed a few unused use statements on ConfigurableLanguageManagerTest.

Still needs work for #71.1 - setting this to needs review for the cleaned up test to run.

Manuel Garcia’s picture

Crap, made a mistake on the docblock for protected $configFactory; - sorry for the noise.

borisson_’s picture

As a suggestion, I think this is probably something like: Make sure that all types of languages (interface, content, ...) can be statically cached.?

Manuel Garcia’s picture

Thanks, went with Ensure all language types can be statically cached., hopefully it makes sense.

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

That makes sense. All the nitpicks I had were fixed. Thanks!

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/language/src/ConfigurableLanguageManager.php
    @@ -92,9 +92,9 @@ class ConfigurableLanguageManager extends LanguageManager implements Configurabl
       /**
        * Whether already in the process of language initialization.
        *
    -   * @var bool
    +   * @var array
        */
    -  protected $initializing = FALSE;
    +  protected $initializing = [];
    

    Let's document that this is an array of bools. So @var bool[] and keyed by language type. Also the description could be updated to reflect this is now per language type.

  2. +++ b/core/modules/language/src/ConfigurableLanguageManager.php
    @@ -212,13 +212,18 @@ public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) {
    +      // Ensure all language types can be statically cached.
    +      if (!isset($this->initializing[$type])) {
    +        $this->initializing[$type] = FALSE;
    +      }
    

    We're not statically caching a language type. I think we could only store the list of things we are initializing here. So we don't need this code.

  3. +++ b/core/modules/language/src/ConfigurableLanguageManager.php
    @@ -212,13 +212,18 @@ public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) {
    +        if (!$this->initializing[$type]) {
    

    We can change this to if (!isset($this->initializing[$type])) { and then we don't need the code to check the isset-ness before.

  4. +++ b/core/modules/language/src/ConfigurableLanguageManager.php
    @@ -212,13 +212,18 @@ public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) {
    +          $this->initializing[$type] = FALSE;
    

    This could be

    unset($this->initializing[$type])<code> as I think the whole point of this is to prevent recursion.
    </li>
    
    <li>
    <code>
    +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,212 @@
    +  /**
    +   * The language negotiator.
    +   *
    +   * @var \Drupal\language\LanguageNegotiatorInterface
    +   */
    +  protected $languageNegotiator;
    

    Let's not stick this on the test class. The moment drupal_flush_all_caches() rebuilds the container this is out of date.

  5. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,212 @@
    +  /**
    +   * The config factory.
    +   *
    +   * @var \Drupal\Core\Config\ConfigFactoryInterface
    +   */
    +  protected $configFactory;
    ...
    +    // Make sure node edit pages are administration pages.
    +    $this->configFactory = \Drupal::getContainer()->get('config.factory');
    +    $this->configFactory->getEditable('node.settings')->set('use_admin_theme', '1')->save();
    

    No need for this - you can use $this->config('node.settings')-> instead.

  6. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,212 @@
    +  /**
    +   * The locale storage.
    +   *
    +   * @var \Drupal\locale\StringStorageInterface
    +   */
    +  protected $stringStorage;
    ...
    +    // Translate the Powered by string.
    +    $this->stringStorage = \Drupal::getContainer()->get('locale.storage');
    +
    +    $source = $this->stringStorage->findString(['source' => 'Powered by <a href=":poweredby">Drupal</a>']);
    +
    +    $this->stringStorage->createTranslation([
    +      'lid' => $source->lid,
    +      'language' => 'es',
    +      'translation' => 'Funciona con ...',
    +    ])->save();
    

    Let's not store this as a class property. In general in browser tests we should avoid them because they can get out-of-sync with the site under test.

  7. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,212 @@
    +    $this->container->get('router.builder')->rebuild();
    

    It'd be nice to not have to do this - I opened https://www.drupal.org/project/drupal/issues/2980237

  8. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,212 @@
    +    drupal_flush_all_caches();
    

    Why is this needed?

Manuel Garcia’s picture

Thanks @alexpott!
Addressing #77 here.
Took the liberty of also removing the user from the class since it's only used during setup.
Re #77.8 - I don't know, this was introduced on #53. Removing it since I don't see why we'd need to do this. I'm uploading a test-only patch to see if it still demonstrates the bug.

Manuel Garcia’s picture

Messed up the test-only patch on #78 - sorry, here is the good one with the changes from #78.

Manuel Garcia’s picture

The last submitted patch, 78: 2189267-78.patch, failed testing. View results

The last submitted patch, 78: 2189267-78-test-only.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 79: 2189267-79-test-only.patch, failed testing. View results

matthiasm11’s picture

Thank you for the patch in #78. I tested this in many different situation on the "Detection and selection"-page and did not encounter any more issues.

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.

dwkitchen’s picture

Also using patch #78 on 8.6.x

cestmoi’s picture

using patch #78 on 8.6.1
and patch #44 from the issue Admin toolbar should always be rendered in the admin language (if set)

I hope these patches would be committed to next core

Manuel Garcia’s picture

So it looks like we need to use drupal_flush_all_caches() in the test.

The last submitted patch, 88: 2189267-88-test-only.patch, failed testing. View results

LaravZ’s picture

The last submitted patch, 88: 2189267-88-test-only.patch, failed testing. View results

Dubs’s picture

So glad I found this issue. It would be good to get this tested successfully and committed. Thanks for the work on this.

Manuel Garcia’s picture

Next steps here are for someone to review my changes on #78/ #88, and setting the status back to RTBC if see fit.

Upchuk’s picture

Status: Needs review » Reviewed & tested by the community

I reviewed the changes done in #78/#88. They address the comments in #77.

I also tested the patch, it applies properly and does what it is supposed to.

samerali’s picture

I tried 2189267-88.patch against 8.5 and it works very well

a.milkovsky’s picture

#88 works with Drupal 8.6.

Nitebreed’s picture

Yes, #88 is working nicely (I'm on 8.5 aswell)

alexpott’s picture

@Manuel Garcia it's not necessary to use drupal_flush_all_caches() here - it clears everything. What we can do is simulate what happens when you save a translation. See \Drupal\locale\EventSubscriber\LocaleTranslationCacheTag::saveTranslation()

alexpott’s picture

borisson_’s picture

I found 2 more nitpicks. Otherwise this looks great.

  1. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,188 @@
    +  public static $modules = [
    

    Needs {@inheritdoc}

  2. +++ b/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php
    @@ -0,0 +1,188 @@
    +    // Translate the Powered by string.
    +    /** @var \Drupal\locale\StringStorageInterface $string_storage */
    +    $string_storage = \Drupal::getContainer()->get('locale.storage');
    +
    +    $source = $string_storage->findString(['source' => 'Powered by <a href=":poweredby">Drupal</a>']);
    

    The newline here before $source makes it seem like the comment doesn't belong to it. I think that should be removed.

alexpott’s picture

@borisson_ thanks!

borisson_’s picture

Awesome. That's probably the quickest I've ever seen a new patch :) Thanks Alex!

RTBC++

alexpott’s picture

I've tried to give credit to all the people who commented on the issue with feedback that either improved the patch, addressed other people's comments or provided good evidence that the patch is working.

alexpott credited Xano.

alexpott credited lauriii.

alexpott’s picture

Crediting @Xano, @danquah and @lauriii for work on #2772891: Wrong url-language negotiated when the user has an admin-language

alexpott’s picture

It would be great if someone could go through this issue and spotted the unrelated & unaddressed issues raised in the comments and ensure we have issues for them. For example #60.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed edfebee539 to 8.7.x and 3788f65ad4 to 8.6.x. Thanks!

  • alexpott committed edfebee on 8.7.x
    Issue #2189267 by Manuel Garcia, snufkin, alexpott, nuez, maxocub,...

  • alexpott committed 3788f65 on 8.6.x
    Issue #2189267 by Manuel Garcia, snufkin, alexpott, nuez, maxocub,...
Manuel Garcia’s picture

@Manuel Garcia it's not necessary to use drupal_flush_all_caches() here - it clears everything. What we can do is simulate what happens when you save a translation. See \Drupal\locale\EventSubscriber\LocaleTranslationCacheTag::saveTranslation()
Ah I get it now, thanks for the explanation @alexpott!

Also, great to see this committed - thanks all!!

Status: Fixed » Closed (fixed)

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

rgpublic’s picture

Hm. It doesn't work for me. I did:

1) A fresh Drupal install 8.6.7 in German with config_translation and content_translation modules both enabled.
2) Under "admin/config/regional/language" I added English as a second language but German remains the default.
3) Under "admin/config/regional/language/detection" I have checked the checkbox [x] Customize Content language detection to differ from Interface text language detection settings. For interface language detection only "Selected language" is checked - nothing else. I want the interface to be in German only. For content language detection "URL" is selected because I want to use URL prefixes (/de,/en). As a fallback also "Select language" is checked which I cannot uncheck because it's grayed out. Well, that's okay for me.
4) I create a new content type "person" with a string field "phone". I give it the German label "Telefon". I translate that label into English and give it the label "Phone".
5) Under "admin/config/regional/content-language" I set that Content-Type and its fields to be translatable.
6) I create a new node of that content type and translate it.
7) I have now two different pages: /de/node/1 and /en/node/1
8) I would expect to have my phone field with the label in the appropriate language. But it doesn't work :-( It works without a problem when I switch off [x] Customize Content language detection to differ from Interface text language detection settings.

huzooka’s picture

The label of a field is not content, its the part of the user interface.

maryedith’s picture

Hello,
I have a multilingual site to which I had applied the patch in #24 in drupal 8.6.2. Content editing, and detection on the url was working well.

Yesterday I updated to 8.6 13. Suddenly I can no longer edit my translated nodes. Switching to a url with a language prefix does not show the translated content. In other words, I am back to the state before applying patch#24 !
I have confirmed that 8.6.13 includes the correct code in ConfigurableLanguageManager.php (ie the patch is now in core).

Has anyone else had this problem? Does anyone have ideas as to what happened? Many thanks for any help.

More details:
Interface language detection: Account Admin pages first, then URL
Customize Content language detection to differ from Interface text language detection settings is checked.
Content language detection: URL

Site language: English
my Admin Pages language: English
Site has Spanish, Chinese Traditional, Filipino.

WakeDrup’s picture

I have the same issue. Can't update the site anymore with 8.6.15

botanic_spark’s picture

I have an issue with the list (text) fields.
The node itself is displayed on correct language (French), but the value (option) of the list field is on English.

If I turn off `Account administration pages` option, the field translation is displayed correctly.

Dubs’s picture

We saw the same issue here after a test update to D 8.6.13. Hopefully we'll solve and report back any fixes.

octopus1’s picture

tested with drupal 8.8.4 and I think there is still a prob:
this is what i tested:
Having URL(prefixes) language detection and negociation method, I create a node with the default site language (en), when trying to acces the translated node in frensh (prefix fr-FR) I got an URL with no prefix, and it shows the default site language's node content. Is there any fix to this prob ?

mariusdiacu’s picture

I think this issue is bigger than that. Here's what I found:

- Install a fresh instance of Drupal (I installed with composer).
- Install drush.
- Enable Language, Interface Translation and Configuration Translation (do not enable Content Translation) modules.
- Add a new language (e.g. German)
- Keep default language EN
- On detection settings, enable URL and Selected language (set German as default fallback on Selected language)
- Add a new page (article, basic page)

Now, run this command with drush:
- ./vendor/bin/drush cc plugin && ./vendor/bin/drush eval "node_load(1)->save();"

Go to /de/node/add/article and check the field labels. Most of the labels are in English.

This is also happening on web interface (if a cache is cleared while someone creates a new node). But it is easier to reproduce with drush. I think clearing plugin cache is clearing the "discovery" bin, which stores configuration translations for fields.

nikitas’s picture

Hi, for Drupal 8.8.5 i can confirm that #44 (https://www.drupal.org/project/drupal/issues/2313309#comment-13616765) works as expected but i can not apply the #78 or any other (most recent) patch (2189267-100.patch or 2189267-98.patch) for drupal core 8.8.5.
Any suggestions?
Thank you

introfini’s picture

I confirm that if you turn off `Account administration pages` option this issue disappears.

Something strange that I noticed was that no language selector was show. After disabling Account administration pages` it also appeared as expected.

ducktape’s picture

I have the same issue with 'Account administration pages'.

Enabling 'Content language' and turning off 'Language from interface' does not work.
But enabling "URL - Language from the URL (Path prefix or domain)" does seem to work. I haven't tested extensively yet, so more is coming.

gaboo’s picture

Multilingual Drupal 9.3.3 site here, bug still present.
Turning off "Account administration pages" fixes it.

TwoD’s picture

I believe this is caused by having a single field definition cache, see #3114824: Add multilingual support for caching basefield definitions.

I can reliably reproduce it by clearing cache via Drush and having the site default language as English, a URL language negotiator as the first step (en/sv prefix), and a fallback to Swedish.
When using Drush the URL language negotiator does not make a decision and the fallback is always Swedish.

When the cache is reset with Drush the ConfigFactory is using English when first caching the discovered field definitions, as LanguageConfigFactoryOverride was created before language negotiation has taken place, and thus has that 'en' set - which it hands up to ConfigFactory as a cache key.

Then the EntityFieldManager comes around and wants to load fields with the default interface language (Swedish). The desired language is not passed down when loading config so ConfigFactory returns data cached in English. EntityFieldManager goes about and applies field overrides, also loading in English definitions via ConfigFactory. Then EntityFieldManager does its own caching, using the interface langcode (Swedish).

When clearing cache via the GUI it will fire the `KernelEvents::REQUEST` event, which LanguageRequestSubscriber picks up, negotiates languages, and then informs LanguageConfigOverride of the correct language to use, before any field definitions have been loaded.

achap’s picture

For the comments in #40, #42 and #67 I agree that the original idea of the issue has been forgotten about so I created a new issue to deal specifically with the fact that you can't edit a node if only session negotiation is enabled. https://www.drupal.org/project/drupal/issues/3349579

honyik’s picture

Had the same problem on Drupal 10.1, solved it NOT by turning off the "Account administration pages" option on the detection page, but by pushing this option further down, so my detection order is "Chosen language", "URL" and then "Account administration pages" and the translations are accessible. Just in case this helps anybody.

joseph.olstad’s picture

joseph.olstad’s picture

@honyik, I just noticed your suggestion, I'll try that later.
Regarding comment #127 above