Problem/Motivation

  1. Entity based fields currently have a display setting on their own to configure language of rows to either keep the found language, reload in the page's content language or in their original language.

  2. However field based views are configured for language separately. They have different settings and may tie the field to concrete languages like the page's language, or the site default or other concrete languages. Not just the set of options are different, the options are named differently. This logic entirely lacks test coverage as well. The setting only has a UI test.
  3. Field language settings additionally have a confusing "When needed, add the field language condition to the query" which is obsolete now that base fields have language and is already handled in the entity language renderers.

  4. Base fields respect neither of these settings. That is being resolved in #2342045: Standard views base fields need to use same rendering as Field UI fields, for formatting, access checking, and translation consistency, not here.

Proposed resolution

Unify settings for 1, 2 and 3 into one setting. Include all options previously in the entity and field language settings and make them all work for fields and entities. Entities did not have fixed language rendering before, fields did not have some of the dynamic options before. Review and clean up option names.

Remaining tasks

Review. Commit.

User interface changes

See screenshots in problem and proposed resolution.

API changes

  1. The field_langcode and field_langcode_add_to_query options are removed from Views displays.
  2. The possible values for the existing rendering_language Views display option change:
    Before After
    current_language_renderer ***LANGUAGE_language_content***
    default_language_renderer ***LANGUAGE_entity_default***
    translation_language_renderer ***LANGUAGE_entity_translation***
    n/a (only available for fields earlier) ***LANGUAGE_site_default***
    n/a (only available for fields earlier) de (concrete specified language)

    While the new option values may look odd, the field_langcode setting already had dynamic values structured like this, we just follow the existing pattern established there to differentiate dynamic values from explicit language values (such as the last).

CommentFileSizeAuthor
#92 2394883-entity-language-options-92.patch197.08 KBGábor Hojtsy
#88 interdiff.txt2.82 KBGábor Hojtsy
#88 2394883-entity-language-options-88.patch197.07 KBGábor Hojtsy
#87 Content (Content) | s5226c2fa0e1af2f.s3.simplytest.me 2015-02-04 15-24-39.png85.46 KBGábor Hojtsy
#87 Content (Content) | s5226c2fa0e1af2f.s3.simplytest.me 2015-02-04 15-23-02.png52.11 KBGábor Hojtsy
#87 Content (Content) | s5b8680854ab427a.s3.simplytest.me 2015-02-04 15-18-17.png80.28 KBGábor Hojtsy
#87 Content (Content) | s5b8680854ab427a.s3.simplytest.me 2015-02-04 15-16-59.png84.49 KBGábor Hojtsy
#85 interdiff.txt2.7 KBGábor Hojtsy
#85 2394883-entity-language-options-85.patch194.25 KBGábor Hojtsy
#83 interdiff.txt1.34 KBGábor Hojtsy
#83 2394883-entity-language-options-83.patch191.55 KBGábor Hojtsy
#80 2394883-entity-language-options-80-simplified-for-review.txt42.77 KBGábor Hojtsy
#79 interdiff.txt689 bytesGábor Hojtsy
#79 2394883-entity-language-options-79.patch191.58 KBGábor Hojtsy
#78 2394883-entity-language-options-77.patch191.51 KBGábor Hojtsy
#78 interdiff.txt3.86 KBGábor Hojtsy
#76 interdiff.txt3.78 KBGábor Hojtsy
#76 2394883-entity-language-options-76.patch188.52 KBGábor Hojtsy
#74 interdiff.txt5.83 KBGábor Hojtsy
#74 2394883-entity-language-options-74.patch185.34 KBGábor Hojtsy
#72 2394883-entity-language-options-72.patch184.71 KBGábor Hojtsy
#69 2394883-entity-language-options-69.patch184.67 KBGábor Hojtsy
#68 2394883-entity-language-options-68.patch187.97 KBGábor Hojtsy
#66 interdiff.txt4.32 KBGábor Hojtsy
#66 2394883-entity-language-options-66.patch184.63 KBGábor Hojtsy
#60 interdiff.txt8.56 KBGábor Hojtsy
#60 2394883-entity-language-options-60.patch187.65 KBGábor Hojtsy
#59 interdiff.txt4.34 KBGábor Hojtsy
#59 2394883-entity-language-options-59.patch182.04 KBGábor Hojtsy
#57 interdiff.txt134.32 KBGábor Hojtsy
#57 2394883-entity-language-options-57.patch181.92 KBGábor Hojtsy
#54 2394883-entity-language-options-54.patch174.78 KBplach
#54 2394883-entity-language-options-54.interdiff.txt7.55 KBplach
#54 Fullscreen_29_01_15_01_20.png173.63 KBplach
#54 Fullscreen_29_01_15_01_16.png267.83 KBplach
#47 2394883-entity-language-options-46.interdiff-slim.txt4.58 KBplach
#46 2394883-entity-language-options-46.interdiff-slim.txt139.43 KBplach
#46 2394883-entity-language-options-46.patch173.4 KBplach
#46 2394883-entity-language-options-46.interdiff.txt143.83 KBplach
#45 2394883-entity-language-options-45.patch37.46 KBplach
#45 2394883-entity-language-options-45.interdiff.txt3.78 KBplach
#37 Home___Drupal_8_x.png96.63 KBplach
#36 2394883-entity-language-options-36.patch33.82 KBplach
#36 2394883-entity-language-options-36.interdiff.txt14.93 KBplach
#24 interdiff.txt1.34 KBGábor Hojtsy
#24 2394883-entity-language-options-24.patch25.25 KBGábor Hojtsy
#22 interdiff.txt6.88 KBGábor Hojtsy
#22 2394883-entity-language-options-22.patch25.97 KBGábor Hojtsy
#16 2394883-entity-language-options-16.patch25.34 KBjhodgdon
#14 interdiff.txt6.11 KBjhodgdon
#14 2394883-entity-language-options-14.patch25.34 KBjhodgdon
#14 languageoptions.png29.85 KBjhodgdon
#10 2394883-entity-language-options-10.patch21.58 KBGábor Hojtsy
#10 interdiff.txt13.25 KBGábor Hojtsy
#10 Content (Content) | drupal8.local 2014-12-23 17-16-34.png72.27 KBGábor Hojtsy
#8 Monosnap 2014-12-23 16-48-38.png130.71 KBGábor Hojtsy
#8 2394883-entity-language-options.patch11.29 KBGábor Hojtsy
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jhodgdon’s picture

For Field UI fields, the code for figuring out which language to use to display the field is centralized on
\Drupal\field\Plugin\views\field\Field::field_langcode()
and the method on that same class that actually does the translation of the entity is
\Drupal\field\Plugin\views\field\Field::process_entity().

field_langcode() already has a fallback for not translating, or LanguageInterface::LANGCODE_NOT_SPECIFIED, but it is not currently exposed in the UI. So that will be easy to add.

We will also need to add to the UI options for "the row's language" and "the page's language" (or whatever we want to call them in the UI in the Language settings on the View display).

For Entities, I think all we'd need to add is the static language settings from the Field Language setting options we currently have. These could use a "fixed language" renderer, with an option to tell it what language to use. That shouldn't be too difficult to manage.

Gábor Hojtsy’s picture

Is there a way to get the row's language though in some way? I see process_entity() that calls field_langcode() is called from getItems() which does get a set of $values to convert to an entity. ResultRow has an $_entity on it, but no specific way to get the row language... Where is that coming from?

Looking at the entity row plugin that works with a very different system where TranslationLanguageRenderer even modifies the query.

jhodgdon’s picture

Right, making these options actually *work* for Fields is the Hard Part of this issue, and I think you're right that the "language of the row" option is the only one that is problematic for Fields.

The language code value should be available though:
- If a view is of entities, each row is a translation, so the "row's language" would be (entity data table).langcode. All the entity data tables have this field now.
- If a view is of entity revisions, each row is a translation of a revision, so the "row's language" would be (entity revision data table).langcode. We can probably use that anyway though because if the view is not revision-based, then the data table and revision data table are presumably joined, right? Some entities don't have revisions though; in that case stick with the entity data table.

Actually, TranslationLanguageRenderer... I am not sure it is using the right logic here. It is trying, in this order: the data table, the revision table, and the base table. I think it should be using the revision data table, the data table, the revision table, and the base table, in that order. Right?

Anyway, yes fields will need to do something similar to make sure the correct langcode field is available in the query and extract it... Is it possible we can make field rendering use the existing entity renderer classes, rather than rewriting the logic?

jhodgdon’s picture

There's another discussion about changing the field rendering pipeline for Views on
#1867518: Leverage entityDisplay to provide fast rendering for fields
which I just marked as related to this issue. Not sure exactly how related, but it seems that they'd at least impact each other.

Gábor Hojtsy’s picture

Gábor Hojtsy’s picture

So let's start discussing #2357995: De-obfuscate entity row language rendering settings in views again :P I wanted this to be done with at this point, but we'll need to restart that discussion again here... So we need to merge the options to one list options.

The list of current entity language options:

  • Current language
  • Default language
  • Translation language

The list of current field language options:

  • Site's default language (English)
  • English
  • .... all other languages one by one ...
  • Not specified
  • Not applicable
  • Language negotiated for User interface text
  • Language negotiated for Content

The first of the entity options is the same as the last of the field options in behavior. So the merged list would only have one of those.

We need to decide what to name the merged options and how to make key dynamic options stand out. We also need to decide how to name the dynamic options. In entities, all our dynamic but they are lowercased underscore separated. In fields, only some are dynamic and those are wrapped in ***LANGUAGE_.....***. So we need to somehow merge them sensibly so it still makes sense.

jhodgdon’s picture

OK good, you closed the other issue.

So. Two things to fix/discuss:

a) Machine/internal names of the options. For the entities, the machine names of the options are things like
translation_language_renderer, set in

And then they are used like this, in EntityRow::getRenderer():

      $class = '\Drupal\views\Entity\Render\\' . Container::camelize($this->displayHandler->getOption('rendering_language'));
      $this->renderer = new $class($this->view, $this->languageManager, $this->entityType);

So the machine names are basically underscore-separated decamelized names of classes that need to be in the \Drupal\views\entity\Render namespace. This is really kind of ... lame? bad coding? to say the least, and this scheme for figuring out which class to use isn't going to work if we have all those other options that we have on the fields, because there's no way we're going to make a specific class for each specific-language option, for instance.

So. IMO there is no point to trying to preserve the same internal names that the entity rendering is using for the options it has now, because we're going to have to change those two lines of code anyway to do something else to figure out what class to use and how to instantiate it.

Given that, I think we should adopt the machine names that the field UI is using. Those are coming from Drupal\views\Plugin\views\PluginBase::listLanguages(), and include:

a) Specific languages - just uses the two-letter language code. Also listed here are Not specified, Not applicable, and those have their three-letter language codes.

b) ***LANGUAGE_(something)*** -- includes ***LANGUAGE_site_default*** as well as **LANGUAGE_(type ID)*** for each of the negotiated language types (content, UI text, and anything else that exists). This will take care of the option on entities that is currently called "Current language", which really means "selected Content language". Personally I think the Field labels for this are better than "Current language" -- who knows what that means. And by the way these options currently say "Language selected for ..." not "Language negotiated for..." in the language choices for Field language. See the listLanguages() method code.

c) Then we will need to add two more options here, from the entity:
- "Default language", which really means "The entity's default language"
- "Translation language", which really means "The language of this Views row"

So my opinion is that we "just" need to:

(1) Figure out good internal/machine codes for these two options -- which I think should probably be ***LANGUAGE_entity_default*** and ***LANGUAGE_entity_translation***

(2) Figure out good labels for these two options, which I really don't know... Maybe "Translated language of content" and "Default language of content", so that the complete list would be:

- Translated language of content [I think this one should be first and should be the default, because that means "the row's language"]
- Default language of content
- Site's default language (English)
- English
- .... all other languages one by one ...
- Not specified [Do we actually want this?]
- Not applicable [Do we actually want this?]
- Language selected for User interface text
- Language selected for Content

(3) Add these two new language options to the listLanguages() method (and define a new flag PluginBase::INCLUDE_ENTITY that means "include these two new entity row language options only if this flag is set to TRUE). We'll also need to look at PluginBase::queryLanguageSubstitutions() to see if we need to do something for the entity languages... which I think we would because languages and all other fields can be added as Group By and then they have to get into the query, sigh.

(4) Make the options list for the Display language call listLanguages() withPluginBase::INCLUDE_ENTITY, as well as \Drupal\Core\Language::STATE_ALL (or maybe just STATE_CONFIGURABLE -- would that get rid of Not specified and Not applicable?), \Drupal\Core\Language::STATE_SITE_DEFAULT, and \Drupal\views\Plugin\views\PluginBase::INCLUDE_NEGOTIATED, so that all the options are listed.

(5) Modify those two lines in EntityRow::getRenderer() so that it uses these new codes and gets an appropriate class, instead of assuming the machine/internal name *is* the decamelized name of the class. We may need to add a new class that does specific languages, and then in those two lines we'd instantiate the class and set the language -- that one would be used for Site Default as well as the specific language options, and maybe we could also use it for the two negotiated/selected languages, because we have a method PluginBase::queryLanguageSubstitutions() that will get the actual language to be used for the LANGUAGE_* options now.

(6) Figure out how to make the Field renderer work for those additional two options. [I think this is actually the main hard part!]

Gábor Hojtsy’s picture

Status: Active » Needs review
FileSize
11.29 KB
130.71 KB

Attached patch attempts to implement this for the entity language renderer only for now. It means it now gets arbitrary language type settings, the site default setting and specific language settings. It also does not add the not specified and not applicable (non configurable languages) because if an entity has a non-configurable language, it cannot have another language variant. So if the entity found is in that language, then it can be rendered in that language with the entity language option.

At this stage of the patch I did not attempt to merge this setting yet with the field langcode setting, but the option names now have overlapping formats.

BTW I am not flattered with out "serialization" system for this setting, but I recognize we use this ***LANGUAGE_...*** notation in language filtering as well, where it needs to be one setting (does it?), so instead of making them separate keys, we serialize them under one key.

Gábor Hojtsy’s picture

Also I am not sure the first and last options are easy to tell apart for anyone who is not a pro?! Which is why in #2357995: De-obfuscate entity row language rendering settings in views I suggested more drastic wording for these, like Language of translation of content displayed and Language selected globally for content on the page respectively for the first and last. Do people find the options clear in #8? I think it would be great to somehow explain that the first two are specific to the items displayed while the last ones are specific to the page/request they are displayed as part of.

Gábor Hojtsy’s picture

A rudimentary attempt at removing field_langcode and basing that logic off of rendering_language (with some backwards compatible defaults for the two new options). Also fixing PHP errors in previous patch. This is probably as far as I can go this year. Feel free to pick up and move forward. I did not remove any of the field_langcode settings from views yet.

The new merged UI with the options as shown in #8:

jhodgdon’s picture

RE #9 - Agreed that "Translated language of content" and "Language selected for content" are confusing from the options in #7/8.

Could we make the last two something like
Page language selected by Content methods
Page language selected by User interface text methods

And maybe the first two could be:
Content language of views row
Default language of content in views row

I think that would sufficiently disambiguate the options, and make it clearer what they really mean?

The UI words "methods" and "selected" are mentioned on the Detection and Selection admin page.

The "row" word is not shown much in the Views UI, but it is used in several places:
- The title of the row style dialog is "[display name]: How should each row in this view be styled" and the help text under the option radios is "You may also adjust the settings for the currently selected row style."
- The settings page dialog for the row style - title is "[display name]: Row style options".
- There at places like the Header text areas where you have an option like "Use replacement tokens from the first row".

So I think both of these would be decent choices. Thoughts?

I also looked through the patch. Except for making the Field renderer work for the two new special languages, which right now just has a placeholder and @todo in your patch, it all looks fairly reasonable to me.

I still think that we should consider adding the two new special languages to the centralized listLanguages method on PluginBase though -- when I set that up on another issue, I consolidated all of the list language functions there -- that was the idea of that method, so we didn't have a bunch of different places in Views all making their own ad-hoc lists of languages with different UI choices. I really do think it's better to centralize the whole thing there.

Anyway if I have some free time during the holidays or possibly later today, I might try to pick this up, but it sure looks like an excellent start!

The last submitted patch, 8: 2394883-entity-language-options.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 10: 2394883-entity-language-options-10.patch, failed testing.

jhodgdon’s picture

Status: Needs work » Needs review
FileSize
29.85 KB
25.34 KB
6.11 KB

OK. Here's a bit of work on this:

a) Added the new special languages to PluginBase::listLanguages so the listing of languages is still centralized. I added a note to the documentation that these languages are only for display options, meaning they won't work in query substitutions. This should be fine, because we don't want these options on filters and arguments (wouldn't make sense there anyway).

b) Updated the UI names for the special languages as in #11, plus or minus a typo. Screen shot:
Language options with patch

c) Fixed test failure of #10 (the problem was the default value of language had changed) and hopefully anticipated some other test failures due to (b). The test that failed in#10, ViewEditTest in Views UI module, at least passes locally now.

Hopefully this is progress. ;)

Status: Needs review » Needs work

The last submitted patch, 14: 2394883-entity-language-options-14.patch, failed testing.

jhodgdon’s picture

Status: Needs work » Needs review
FileSize
25.34 KB

Doh. I just realized that the 2nd option "Default language of content in view row" should be "Original language of content in view row".

The testbot failed on that last patch, not the patch by the way.

Anyway, no sense retesting. Here's a new patch with just that one change (it's in PluginBase::listLanguages() ).

dawehner’s picture

Thank you for working on it!

  1. +++ b/core/modules/field/src/Plugin/views/field/Field.php
    @@ -916,13 +912,9 @@ protected function addSelfTokens(&$tokens, $item) {
    -  function field_langcode(EntityInterface $entity) {
    

    Just curios, does it make sense to camelcase it at the same time?

  2. +++ b/core/modules/field/src/Plugin/views/field/Field.php
    @@ -939,6 +931,26 @@ function field_langcode(EntityInterface $entity) {
       /**
    +   * Resolve the language code to be used for fields.
    +   *
    +   * @return string
    +   *   Language code to be used.
    +   */
    +  protected function field_langcode() {
    

    What about using fieldLangcodeConfigured, so its clear where its coming from?

  3. +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
    @@ -215,11 +215,11 @@ public function initDisplay(ViewExecutable $view, array &$display, array &$optio
    -    // Convert the field_langcode and field_language_add_to_query settings.
    -    $field_langcode = $this->getOption('field_langcode');
    +    // Convert the rendering_language and field_language_add_to_query settings.
    +    $field_langcode = $this->getOption('rendering_language');
         $field_language_add_to_query = $this->getOption('field_language_add_to_query');
         if (isset($field_langcode)) {
    -      $this->setOption('field_langcode', $field_langcode);
    +      $this->setOption('rendering_language', $field_langcode);
           $this->setOption('field_langcode_add_to_query', $field_language_add_to_query);
           $changed = TRUE;
         }
    

    ... Isn't that some sort of BC code which should be better dropped?

jhodgdon’s picture

The patch still is not working for Field views.

Regarding camel case, sure.

plach’s picture

Also I am not sure the first and last options are easy to tell apart for anyone who is not a pro?!

Given that by default Content language inherits from UI language, why don't we check whether we have only one configurable language type and in that case we provide just a single option, like "Page language"? This would make the default scenario easier for non-pro. And if someone managed to provide separate configurations for those we can safely assume she is familiar with the language negotiation concepts. To sum up:

-Simple case:
Page language

-Advanced case:
Language selected for page User Interface
Language selected for page Content

Page language selected by Content methods
Page language selected by User interface text methods

These are misleading: negotiation methods can be the same for both language types, although being inspected in different order. The difference is (may be) in the negotiated languages that are assigned to the various language types.

jhodgdon’s picture

Status: Needs review » Needs work

Good ideas, although I think the logic to implement "see how many there are and modify the displayed name accordingly" would be annoying to add to the listLanguages() function? Maybe it's only a line or two though.

Anyway... Besides agreeing on the names, this patch still needs to be added to: right now it does not actually contain the code to make the new options work for field-based views.

plach’s picture

Good ideas, although I think the logic to implement "see how many there are and modify the displayed name accordingly" would be annoying to add to the listLanguages() function? Maybe it's only a line or two though.

Here it is:

$types = \Drupal::languageManager()->getLanguageTypes();
if (count($types) == 1) {
  // Simple
}
else {
  foreach ($types as $type) {
    // Pro
  }
}
Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
25.97 KB
6.88 KB

Attached patch makes the following improvements:

- renamed Field::field_langcode_available() to Field::fieldLangcodeAvailable(); this is a new method so should be fine
- renamed Field::field_langcode() to Field::fieldLangcodeConfigured() as suggested by @dawehner
- retitled options for selected languages from "Page language selected by !type methods" to "!type language selected for page", we don't lead with the scope of language selection elsewhere either and we can conveniently avoid the "methods" word
- made the option to be "Language selected for page" if there is only one named type
- removed the BC code from the display as pointed out by @dawehner

Gábor Hojtsy’s picture

Duh I realize comparing my code to @plach's suggestion in #21, that the single case will never fire. This method takes ALL named types not just configurable types with the idea that non-configurable types may equally be interesting depending on what developers use them for. Their results may still be very dynamic. So not sure we can make that shortcut with the one option or we need to cede support for non-configurable languages in this selection (including language types the site developer may have introduced for specific use cases but did not expose as configurable).

Gábor Hojtsy’s picture

So removing that extra code for the single case, that will never happen with our current logic.

jhodgdon’s picture

Looking good! So we just need to address this @todo now?

+  protected function fieldLangcodeConfigured() {
+    $langcode = $this->view->display_handler->options['rendering_language'];
+    $substitutions = static::queryLanguageSubstitutions();
+    $substitutions += array(
+      // @todo Backwards compatible fallback, needs to be implemented.
+      '***LANGUAGE_entity_translation***' => $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT),
+      '***LANGUAGE_entity_default***' => LanguageInterface::LANGCODE_DEFAULT,

now?

Gábor Hojtsy’s picture

@jhodgdon: I believe so yes. I don't know what to do for that so would refer to @dawehner or @plach if they are available in some capacity.

plach’s picture

// @todo Backwards compatible fallback, needs to be implemented.

Sorry, I'm not sure I get what this is supposed to mean. AFAICT the only way to obtain language fallback efficiently is loading a full entity and calling EntityManagerInterface::getTranslationFromContext() on it. If I'm not mistaken this is what already happens when rendering then entity in the current content language. What else do we need?

Gábor Hojtsy’s picture

Status: Needs review » Needs work

@plach: the @todo is that this line is not correct: '***LANGUAGE_entity_translation***' => $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT),. It should not take the language of the page but the language of the field as found (the language of the views row). So this would be the field view equivalent of the entity view's TranslationLanguageRenderer.

jhodgdon’s picture

Basically what that means is that Gábor put blatantly wrong placeholder code in there and it needs to be replaced by real functionality. :)

We're adding new capability here: fields will be able to be displayed in the language of the row, or in the "original" translation language of the entity. This will make field views work like entity views, so that all the language UI in Views is uniform, independent of whether you are doing a field view or an entity view. But currently fields do not know how to display using "row language" or "original language of the entity", so that part needs to be written.

Gábor Hojtsy’s picture

Well I *think* that the one line I put in for the original language SHOULD work for fields, but I did not write tests or anything, just went by the Field class defaults. The row language stuff is intentionally wrong in the patch, that is where the @todo is. We would need tests for the original language stuff of course, but I assume that one line I have there actually made that work.

Gábor Hojtsy’s picture

xjm’s picture

Issue tags: +D8 upgrade path

Looks like we are changing how we store language information in the config entities as a part of this fix, so this is an upgrade path issue.

plach’s picture

Assigned: Unassigned » plach

Working on this

plach’s picture

I have some working code reusing language renderers but the patch is not ready yet, I'll post it tomorrow.

Gábor Hojtsy’s picture

@plach: yay, that sounds fantastic!

plach’s picture

Status: Needs work » Needs review
FileSize
14.93 KB
33.82 KB

Here is the patch. It is far from complete but manual testing results are promising.

Things still missing:

  • Additional test coverage.
  • Removal of the field_langcode_add_to_query option, since it's basically applying language conditions for field tables, which now are joined to the data table and match its language. This is basically equivalent to what we are doing in the translation renderer, aside from trying to support fallback at query level which is tricky.
  • Renaming of a few methods: ::fieldLangcodeAvailable() should be called ::getFieldLangcodeAvailable() and so on.
  • Discussing the language list a bit more: I still find its options a bit confusing, I'll expand on this in a following post.

Btw, I found #2414721: EntityAdapter should be instantiated per language while testing this...

plach’s picture

FileSize
96.63 KB

Status: Needs review » Needs work

The last submitted patch, 36: 2394883-entity-language-options-36.patch, failed testing.

Gábor Hojtsy’s picture

Wow, really surprised how clean that looks like and how unified would the query handling be as far as shown in the patch at least. The trait solution with the accessor methods is interesting but adding yet one more service which would need the other services injected again may be more trouble, since we have all details and services present in the existing handlers.

I'd like to add one more thing to the list to do although I should have done it earlier (sorry). CurrentLanguageRenderer needs to be renamed to "StaticLanguageRenderer" or "PresetLanguageRenderer" or something along those lines. It basically now takes a langcode and renders with that as opposed to doing some dynamic logic. That was already true for my prior patches.

 /**
  * Renders entities in the current language.
  */
 class CurrentLanguageRenderer extends RendererBase {
plach’s picture

The trait solution with the accessor methods is interesting but adding yet one more service which would need the other services injected again may be more trouble, since we have all details and services present in the existing handlers.

Not sure I get what you mean, can you expand on this?

Gábor Hojtsy’s picture

@plach: basically the trait proposed is one method with several services required, so it has the abstract methods to access those. The same could be implemented with an entity views rendering service that has those required services / config injected, so its not built in directly to the classes. Think composition vs. extraction. Since those services we need are already in the classes you extended with the trait, it sounds like it may be more painful to extract that to its own service instead of keeping it as a trait.

plach’s picture

Ok, so you are suggesting to keep the trait, right? This is the part I'm not completely clear on :)

Gábor Hojtsy’s picture

Yeah I'm not 100% sold on the trait, but it looks better for now compared to extracting that to a service.

plach’s picture

Yep, I'm not totally convinced about it too, composition would sound as the go-to choice here, but yeah, it's easy and works so for now I guess it's ok.

plach’s picture

Status: Needs work » Needs review
FileSize
3.78 KB
37.46 KB

This should be green again.

plach’s picture

Removed the field_langcode_add_to_query option. Let's see what happens.

plach’s picture

The correct slim interdiff

jhodgdon’s picture

Just took a look at the latest patch...

A question in Entity/Render/DefaultLanguageRenderer.php:

+  public function getLangcode(ResultRow $row) {
     return $row->_entity->getUntranslated()->language()->getId();
   }

So I realize this is not a code change, since this line was the same before the patch... but ... Some view rows may have more than one entity in them (relationships! Such as a view containing fields from a node and a taxonomy term and an author). So... ???? will this work? Actually, when we have a relationship in a multilingual view, if both entities being related have translations, does the join match the languages? I guess this is a separate issue but man, that's scary code!

Hm. Took a look at the ResultRow class, and ... it's a bit lacking in details, but it looks like it's returning the main entity for the row. So if we're rendering one of the other entities in the relationships, will this be the right language? Seems wrong.

The same $row->_entity happens in the DefaultLanguageRenderer too.

Thoughts? Have we tested this with relationships?

jhodgdon’s picture

RE #48: I guess this wouldn't have come up before, because a view using Entity View Mode rendering would only have the main entity to render. So this usage of $row->_entity would work for that. But I don't think we can count on it working for Field based views, which could be displaying fields from several different entities.

Gábor Hojtsy’s picture

Issue tags: +Needs tests

@jhodgdon: so looks like this patch does not fix all the problems but only some of the problems :) Does it make the situation worse than it was before? Is it a dead end due to the multi-entity situation or not? I mean if we can make considerable progress with this one at least for basic views and we only need to go forward from here rather than rewrite it again, then I think we should keep the scope. Its already a 173k patch.

@plach: yay for removing that option (it was *confusing*), but as shown there is no test coverage for it, so not sure it still being green proves it works unfortunately... I think we need tests to prove the use case still works without that code. I am not even sure what it was meant to support honestly.

jhodgdon’s picture

I was going to suggest a fix for the case of the "untranslated" option anyway... but the more I think about it, the more I think that at least 99.999% of the time you'd want to display all entities in a row in the same language.

So actually I think that we should go with the current patch. This would mean that technically, in the case of relationships, the option "Display in language of row" or whatever it's called would really mean "Display everything in the language of the main entity of the row", and similar for the "display in base language" option.

It remains to be seen whether joins/relationships are working completely as we want them to, but that is definitely a different issue. So yes, let's move forward with this!

Gábor Hojtsy’s picture

BTW I think I can help write tests based on the language field (what was failing basically in #2384863: Translation language base field handler should use views field handler, provide unified options) if that seems suitable but I am fine if @plach has better test ideas.

Gábor Hojtsy’s picture

Assigned: plach » Gábor Hojtsy

Discussed with @plach, I'll try to bring over the failing tests from #2384863: Translation language base field handler should use views field handler, provide unified options. Tomorrow.

plach’s picture

This performs the additional code clean-up we were mentioning earlier (and some more).

As I was saying above, I'm still not happy with the language selection list. If we compare it with the one appearing in the content language settings page, we can notice various inconsistencies:

  1. Dynamic languages should be listed first, but current languages are the last options.
  2. We have different wording in the two cases (should we be using common code to generate those lists?).
  3. Only interface language is listed there.

Therefore I'd be in favor of moving current languages up, after the default language, unify wording and apply my suggestion from #19, i.e. list only configurable languages.

Gábor Hojtsy’s picture

@plach: re only including configurable languages, see my comment in #23 above. Should we introduce non-configurable language types then on the content selection page?

Gábor Hojtsy’s picture

Reviewed changes in #54 also:

+++ b/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php
@@ -0,0 +1,51 @@
+ * Renders entities in a configured language. Falls back to current language.

Erm, current language of what?

Gábor Hojtsy’s picture

Ws should also remove the field_langcode option from views files since we don't rely on that anymore (its removed in PHP in the patch for a while). We hang everything on the rendering_language option.

Status: Needs review » Needs work

The last submitted patch, 57: 2394883-entity-language-options-57.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
182.04 KB
4.34 KB

Should not leave empty display options around in views yamls.

Gábor Hojtsy’s picture

Assigned: Gábor Hojtsy » Unassigned
Issue tags: -Needs tests
FileSize
187.65 KB
8.56 KB

And here is an attempt at test coverage using the existing entity row tests, adding one more display which uses fields. Unfortunately does not pass for some of the renderers. Ha!

Status: Needs review » Needs work

The last submitted patch, 60: 2394883-entity-language-options-60.patch, failed testing.

Gábor Hojtsy’s picture

All right, what I found is if we run only one of the translation render tests on page_2 (comment out all but one in checkLanguageRenderers()), then it works perfectly. It does not matter which one, all of them work perfectly in themselves. If we run them after each other, they fail because (I assume) some cached data wins over what we want to get. While we can reorganize the test to have a lot more test methods, so they run in isolation, we should look at where it is cached and eliminate that cache. Hope to get some help on that because I was unable to track that down. The good news is the renderers all work with fields! Yay :)

Wim Leers’s picture

This is definitely not entity render caching. Views' "field views" render pipeline must be doing (static) caching somewhere and isn't keying on language as it should.

I can't dig further in this right now.

jhodgdon’s picture

I noticed this change in the patch, in that test that is failing if you run more than one of the pieces:

-  protected function assertTranslations($renderer_id, array $expected, $message = '', $group = 'Other') {
-    $view = Views::getView('test_entity_row_renderers');
+  protected function assertTranslations($view, $renderer_id, array $expected, $message = '', $group = 'Other') {
+    $view = clone $view;

The former code is calling Views::getView(), which is documented as "Loads a view from configuration and returns its executable object.". The new code is just doing a clone of an existing object -- and PHP clones (by default, in the absence of a __clone() method on the class) are shallow, so the display and other member variables on the view object would be retained, rather than cloned themselves.. Do the tests pass if you revert that change from the patch?

Gábor Hojtsy’s picture

@jhodgdon: Yeah I tried loading it again each time and setting the display each time, it did not help.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
184.63 KB
4.32 KB

Cleaning up the test view so its easier to look at. Does not fix and should not break anything with the tests.

Status: Needs review » Needs work

The last submitted patch, 66: 2394883-entity-language-options-66.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
187.97 KB

Rerolled because it did not apply anymore.

Gábor Hojtsy’s picture

Bah, unrelated LocaleTranslatedSchemaDefinitionTest.php crept in. Duh.

The last submitted patch, 68: 2394883-entity-language-options-68.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 69: 2394883-entity-language-options-69.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
184.71 KB

The user admin view changed again, rerolled once again.

Status: Needs review » Needs work

The last submitted patch, 72: 2394883-entity-language-options-72.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
185.34 KB
5.83 KB

All right, the problem is not caching, the field view still uses the 'node' plugin as if that was the plugin_id. Still investigating that but fixing the misleading pass in the meantime. The tests provided incorrect feedback because the first one returned no results and the assert defaulted to pass instead of fail, so when iterating on results, if there were no results, that assumed to be passing. Also if there were less results, but the results matched, it would also pass. Now defaulting to fail and checking from the expectation not the result for correctness. This should now fail 4 times instead of 3. It only passes for the 'row language' case, which is what the 'node' plugin would provide. Again, it does not actually use the 'field' plugin for some reason yet unknown to me.

Status: Needs review » Needs work

The last submitted patch, 74: 2394883-entity-language-options-74.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
188.52 KB
3.78 KB

Fix the new config schema fails due to two new views and remove one dead code line.

Status: Needs review » Needs work

The last submitted patch, 76: 2394883-entity-language-options-76.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
3.86 KB
191.51 KB

So the fails are due to the node field handler being used instead of the generic field handler. The reason for that is DisplayPluginBase::getHandlers('field') calls to Views::handlerManager('field')->getHandler(....) and beyond that point, its a node field handler instead of a generic field handler because the views data for the node table says so. See implementation in ViewsHandlerManager::getHandler() which takes the table data and ignores the plugin info that may be provided in the view. So we cannot just say in the view that we want a different plugin to handle it. A given row of a given table is forced to be handled by the plugin provided by the views data. That did not register with me before.

Looking at #2407801: Views generic field handler does not work with base fields it actually overrides the field data as well for the tested column, so we should do the same here. #2342045: Standard views base fields need to use same rendering as Field UI fields, for formatting, access checking, and translation consistency will make it use the field handler later.

This passes locally for the remaining 3 fails. Feedback strongly welcome.

Gábor Hojtsy’s picture

Added a @todo as well referencing #2342045: Standard views base fields need to use same rendering as Field UI fields, for formatting, access checking, and translation consistency, because once that lands, we can remove this test code, it will not be needed anymore.

Gábor Hojtsy’s picture

@dawehner asked for a simplified patch without the changed views YAML files. I kept the test file that is being tested for review but removed the rest. This will not pass obviously so uploading as txt.

plach’s picture

Makes sense to me, FWIW.

dawehner’s picture

Great work!

  1. +++ b/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php
    @@ -0,0 +1,51 @@
    +/**
    + * Renders entities in a configured language. Falls back to current language.
    + */
    

    It would be great to specific what 'current' means in this context (I guess its the content language)

  2. +++ b/core/modules/views/src/Plugin/views/PluginBase.php
    @@ -52,6 +52,13 @@
       /**
    +   * Include entity row languages when listing languages.
    +   *
    +   * @see \Drupal\views\Plugin\views\PluginBase::listLanguages()
    +   */
    +  const INCLUDE_ENTITY = 32;
    

    Its just sad that we blow up PluginBase more and more ... can't we move the languages logic into a trait? Work for a follow up?

  3. +++ b/core/modules/views/src/Plugin/views/field/Field.php
    @@ -886,16 +894,23 @@ protected function addSelfTokens(&$tokens, $item) {
        */
    -  function field_langcode(EntityInterface $entity) {
    +  public function getFieldLangcode(EntityInterface $entity, ResultRow $row) {
    

    Can we mark it as protected? I know it would be kinda an API change, but at the same time, I think it was never intended to be supported in the first place.

  4. +++ b/core/modules/views/tests/src/Unit/Plugin/field/FieldTest.php
    @@ -565,4 +576,41 @@ public function providerSortOrders() {
    +   */
    +  protected function setupLanguageRenderer(Field $handler, $definition) {
    +    $display_handler = $this->getMockBuilder('\Drupal\views\Plugin\views\display\DisplayPluginBase')
    

    Just general thoughts. Sometimes I think making dependencies / features optional in classes would be a good idea to remove complexity.

Gábor Hojtsy’s picture

@dawehner: re #82:

1. It does not actually fall back on anything. The constructor requires the langcode to be passed and getLangcode() returns that verbatim, there is no explicit fallback here. The entity rendering may fall back but that is not in control of this class. Removed that comment.

2. I looked this up and the language methods were added on PluginBase in Issue #2037979 by Gábor Hojtsy, Sweetchuck, jhodgdon, dawehner: Fixed 'Current user's language' views filter label is named very misleading where you already posed the same question and it was not really resolved.. See #2037979-54: "Current user's language" views filter label is named very misleading. Looking at the two methods, the second one is static and the first could be as well, so they could live anywhere with their current code. Opened #2419903: Consider moving the language list/replacements out of Views' PluginBase. I am not sure they should be a trait, they can also move to the Views utility class.

3. We rename it so its an API change either way. It is also not invoked from the outside and is not intended. So marked as protected.

4. I don't think that is actionable, is it?

Status: Needs review » Needs work

The last submitted patch, 83: 2394883-entity-language-options-83.patch, failed testing.

Gábor Hojtsy’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: +blocker
FileSize
194.25 KB
2.7 KB

Duh, there is of course new views being added with field_langcode all the time.

Adding blocker tag because #2384863: Translation language base field handler should use views field handler, provide unified options is postponed on this one and is part of resolving another D8 upgrade path critical.

Status: Needs review » Needs work

The last submitted patch, 85: 2394883-entity-language-options-85.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
197.07 KB
2.82 KB

There are always some field_langcodes hiding around that corner... Hope caught all and none were committed in the meantime :D

Gábor Hojtsy’s picture

Added a views API change notice draft at https://www.drupal.org/node/2420001
Added a views UI change notice draft at https://www.drupal.org/node/2420011

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Seems alright for me.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll
git ac https://www.drupal.org/files/issues/2394883-entity-language-options-88.patch
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  197k  100  197k    0     0   401k      0 --:--:-- --:--:-- --:--:--  426k
error: patch failed: core/modules/views/src/Plugin/views/field/Field.php:11
error: core/modules/views/src/Plugin/views/field/Field.php: patch does not apply
Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
197.08 KB

Rerolled.

Gábor Hojtsy’s picture

Issue summary: View changes
Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Fixed

This is a lovely change. And it's not just the diff stat :) 188 files changed, 470 insertions, 858 deletions.This issue addresses a critical bug and is allowed per https://www.drupal.org/core/beta-changes. Committed f100d94 and pushed to 8.0.x. Thanks!

  • alexpott committed f100d94 on 8.0.x
    Issue #2394883 by Gábor Hojtsy, plach, jhodgdon: Language setup for...
Gábor Hojtsy’s picture

plach’s picture

jhodgdon’s picture

WOOOOOOOOT!

lokapujya’s picture

Issue tags: -Needs reroll

Status: Fixed » Closed (fixed)

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

larowlan’s picture

+++ b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
@@ -0,0 +1,92 @@
+  abstract public function getEntityTypeId();

was there a reason this was public?