Updated: Comment #0
Problem/Motivation
When we add a language entity the logic behind (marking site as multilingual if needed, changing default language if needed and clearing language caches) is never called because it resides in language_save().
This is particularly painful with migrate, where we are storing entities directly.
Proposed resolution
Move this logic to the Entity/Language::postSave().
I'm not sure if this circular reference Entity/Language=>LanguageManager=>Entity/Language is desired.
Remaining tasks
Discuss if this is the way to go.
User interface changes
None.
API changes
None.
Follow-ups
- (needs to be opened) an @todo: fix type hint, should be postponed on #2246665: Typehint with Drupal\Core\Language\LanguageInterface instead Drupal\Core\Language\Language and #2246679: Make Language module's LanguageInterface (to be ConfigurableLanguageInterface) extend Core's LanguageInterface
Comment | File | Size | Author |
---|---|---|---|
#32 | 2234623.32.patch | 11.08 KB | alexpott |
#32 | 28-32-interdiff.txt | 2.07 KB | alexpott |
#28 | 2234623.28.patch | 10.97 KB | alexpott |
#28 | 22-28-interdiff.txt | 7.26 KB | alexpott |
#22 | 16-22.txt | 1.09 KB | penyaskito |
Comments
Comment #1
penyaskitoComment #2
penyaskitoFirst attempt, just moving code around.
Comment #4
penyaskitoPassing the $language->default property and fixed usage statements. This should fix most of the failures.
Comment #6
penyaskitoEven more fixes. We should try to resolve the dicotomy between Entity/Language and Core/Language, but it is out of scope of this issue.
Comment #8
penyaskitoRemoved passing $language->default to the entity.
Restored the language default logic into language_save().
Changed the language default form handling to use the language.default service instead of language_save().
This should make most tests pass, but some negotiation tests are failing locally still.
Comment #10
Anonymous (not verified) CreditAttribution: Anonymous commentedComment #11
Gábor HojtsyWhy do we need to change the submit function?
Comment #12
penyaskitoWe shouldn't, but actually it fixed some tests. I'm reverting that in the attached patch.
About the attached patch, I've been looking at it and cannot find why it's breaking negotiation.
Drupal\language\LanguageNegotiationMethodBase::setCurrentUser() is being called with NULL in LanguageNegotiator::getNegotiationMethodInstance() with language-url method id, so an exception is thrown and I think it's the root of every other failure. This is only a guess, as I don't know why phpstorm is not being able of debug this on my machine, but I can assure that it was never called with a NULL before this patch.
I lost track of what's going on at LanguageRequestSubscriber::onKernelRequestLanguage(), I will try to get help on IRC.
Comment #14
alexpottisNew()
is no longer TRUE inpostSave()
and the multilingual check needs to be done in preSave since we're trying to determine if the site is becoming multilingual.Comment #16
alexpottSo the order in which the default is set matters too
Comment #17
Gábor HojtsyThis is tagged as an IMP blocker. Is this also blocking deploying languages through config deploy? Since all the additional actions should happen on the entity being saved instead of global functions, right? Does that make this a bug, beta target, beta blocker or what? :)
Comment #18
alexpott@Gábor Hojtsy good point - it don't think it is a beta blocker because it does not change an API or data model - but it certainly would prevent a comprehensive test for #2224887: Language configuration overrides should have their own storage being written. That is one that tests a configuration sync that makes a site multilingual and overrides config in the same process..
Comment #19
Gábor HojtsyThis is confusing but due to the value vs. entity object differences. Not sure if possible to fix without further (unrelated) refactoring.
Should also say not saved on the language entity, right?
Also the variable names are not unified?! Does this even work? :)
Comment #20
xjm@alexpott and @Gábor Hojtsy discussed this issue today and both suggested that it should actually be beta-blocking.
Comment #21
Gábor Hojtsy@alexpott explained #19/3 to me in IRC. The default behavior for saving config entities is only public property values are saved. So by defining $multilingual and $default as protected, they are not saved back. So that is fine. The variable name mismatch in #19/2 though makes the $preSaveMultilingual property public (runtime created), so it will be saved. So once that is fixed the use the right variable, it should be fine. Looks like this is very close, only needs that variable name fixed.
Comment #22
penyaskitoRenamed the property and improved docs.
Comment #23
penyaskitoShouldn't this call the \Drupal::service('language.default') for getting if this is the default language, as this could be called when the instance has not been saved, and the value could be a wrong one?
Comment #24
alexpott#23 good point - perhaps the best thing to here will be actually save the default value to the entity - the problem we have then is keeping it in sync. hmm....
Comment #25
Gábor HojtsyWell, we can make the default language service be dynamic like the configurable language manager, when the language module is enabled it would derive this value from looking at which language is default by looking at all of them. Then we still need to ensure multiples are not defaults. Either way there is some coordination required.
Comment #26
Gábor HojtsyLooks like needs work.
Comment #27
tstoecklerDon't have better suggestions but this variable name and the documentation is not very clear.
Since this is a beta blocker this is fine for now but we should add a @todo to remove this again after #2246665: Typehint with Drupal\Core\Language\LanguageInterface instead Drupal\Core\Language\Language and #2246679: Make Language module's LanguageInterface (to be ConfigurableLanguageInterface) extend Core's LanguageInterface.
Instead of hardcoding the class name here we could move the second if into the first.
Note that its perfectly valid to call static methods non-statically. I.e. we could do
inside of the first if.
Reading this code again, shouldn't ConfigurableLanguageManager simply override reset() to do that stuff itself?
On the other hand this is just moving stuff around and this issue is a beta blocker, so feel free to leave to a follow-up.
Comment #28
alexpottAdded code to ensure Language::$default is always correct after loading or creating and added a test. I don't think we should save the default value to the entity - maintaining this will be very messy.
Comment #29
tstoecklerActually I'm pretty sure the entire method can be removed after those, but as long as we have the todo we won't forget.
This is actually not true. I tried this locally and there is no warning. PhpStorm does not complain either.
Comment #31
Gábor HojtsyThis looks like a classic example where return *thecondition* would have done the same?
A higher level comment above would be great. This is for the case when this language was made the default but the global default is not yet up to date.
Comment #32
alexpottFixed tests and nits reported in #31
Comment #33
Gábor HojtsyLooks good to be. RTBC assuming it passes now :)
Comment #34
penyaskitoTests for #2166875: Migrate D6 languages are green too, thanks :D
Comment #35
YesCT CreditAttribution: YesCT commentedonly one @todo, and it already mentions issues.
updated summary with that info.
Comment #36
effulgentsia CreditAttribution: effulgentsia commentedThis doesn't need to block commit, but I'm curious why we need to support callers calling
->get('default')
instead of requiring them to call->isDefault()
. Unless it's quick to do here, I'm fine with that being discussed and/or removed in a follow up.Comment #38
webchickAlex's quoted code also stuck out to me. It'd be great to get a code comment explaining why this method is overridden. Fine with that being a follow-up though; not worth holding a beta blocker up over this.
Committed and pushed to 8.x. Thanks!
Comment #39
penyaskitoThanks all!
Created follow-up: #2247497: Clean up overriden Entity/Language::get()
Comment #40
Gábor HojtsyYay, superb, thanks all!