Problem/Motivation
As you create configuration on a Drupal site, it may be created in one of 4 languages:
- Current request language
- Configuration created on the UI that does not have a language selector (eg. content types, block types, etc.). This means if an admin browses the site in a foreign language, if they create a new content type, it will be created in that foreign language.
- Configuration created through config actions (eg. in recipes). This means that users of project browser will have configuration created in recipes with config actions created in the language they happened to use in their browser.
- Language explicitly selected on the UI
- Very few config entities have an explicit language selector (in core: menus, views, taxonomy vocabularies, date formats). This means that even if your request language is X, you can still create that config in Y, Z, etc. languages using the selector. This is the only way to create in "Not specified" and "Not applicable", which are two options offered.
- Configuration language directly in a YAML file, even if the language does not exist on the site at the time(!) (or if missing assumed as English)
- Configuration shipped modules, when the module is installed if locale module is not yet installed, regardless of the site default language!. This means that if your site default is German but locale module is not installed, module config will still be imported in English. Even if the English language was deleted earlier.
- Configuration shipped in recipes, when the recipe is applied regardless of the site default language or if locale is installed or not!. Even if locale module is installed recipe shipped config is always installed in the language it is in, regardless of whether that language is configured on the site or not.
- Site default language
- Configuration created through extension installation if locale module was previously installed already on the site. When a module is installed, its config is created in the site default language at the time.
So you already have config in various languages. Then Drupal tries to keep the config language up to date but that only ever happens with extension installed config. But!
- Extension config language update only happens when extensions get installed. If you modify the site default language, you need to THEN install an extension for the config of all previous extensions too to get updated.
- The update only ever happens if the config was still English and was now switched from English to something else. If it was not English, than a site default language modification does not result in config language modification even later when extensions get installed.
- Once again this modification only applies to extension installed config, not manually created config or recipe installed config or config action created config.
See locale_modules_installed() and core/modules/locale/src/LocaleConfigManager.php for this logic.
Steps to reproduce
- Install Drupal standard in English
- Enable the language module and add German on
admin/config/regional/language. - Create a new content type. This will be English. Existing installed config will be English.
- Create a new menu. Note that you can pick English or German for this menu. Create it in German. Config export will show the config entity got created as German.
- Go back to create a new content type. Add a language prefix (
/defor German) to the URL and load that page. While it is not apparent in this UI, this will create the content type in German. Verify with config export. - Add another language (for example French) on
admin/config/regional/language - Change the default language to French that you just added.
- Install Media module. The installed config will be English even though your site default is now French.
Another variant of the steps to use interface translation from the start for different dramatic effect:
- Install Drupal standard in English
- Enable the language module and Interface translation modules. Add French on
admin/config/regional/language. - Create a content type. This will be English. Verify with config export.
- Change the default language to French that you just added.
- Create a content type. This will be French as the URL has
/frin it because modifying the site default to French brought you there. Verify with config export. - Note that all of your config other than the French menu is still English. Verify with config export.
- Now install Media module. A big config update will happen that updates extension installed config to be French. Your English content type remains English. Verify with config export.
- Now switch the site default language to German. Nothing happens to config. Verify with config export.
- Install search module. This will still NOT rewrite your existing config to be German but search module related config will be installed in German now. Verify with config export.
- Now you have English, French and German config, most config is French.
Also, if you then switch site default language back to English, the configuration language for existing config also never switches back, not even when you install more modules. (This is true at any point after the site default language was once a foreign language).
Also, if you delete either of the 3 languages, which can be done without issue, you are left with configuration in that language Drupal does not know about.
Proposed resolution
Introduce the concept of "Configuration default language" separate from "Site default language". When Drupal is installed set up a "Configuration default language" explicitly. Do not change this with the "Site default language" but do ensure that the language that is the "Site default language" cannot be deleted (in the installer when English is not kept, it should not be possible to have English as the "Configuration default language").
Use this configuration default language to create new configuration on the site regardless of circumstance. This will ensure that all config is created in the same language by default, regardless of the site default language or the current request language or the imported config's language. Discuss if we want to keep the one-off language features of menus, taxonomy vocabularies, views and date formats or if we want to remove those and always use the configuration default language. #3608533: Introduce "Configuration language" settings page to control langcode visibility is related to that.
Add a UI to change the "Configuration default language". When that is changed, it should warn the user that config in other languages where they are not intended to be different will get updated. (Don't limit updates to extension installed config to keep config consistent between human created and extension created config -- in the example above English, French and German config will also become German by the end). Further extension installs will consider the same "Configuration default language" but should not result in massive updates as the user interaction previously will already do the update.
Remaining tasks
User interface changes
New option added to the Configuration language page. Site default does not result in changing the configuration default language.
API changes
Data model changes
Release notes snippet
Issue fork drupal-3337864
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
tsotoodeh commentedThe same issue observed in 9.5.x, it is a core design issue, I opened a multilingual support issue:
Multilingual support of strings in second language website
I Tried using configuration update manager module to adjust langcode from default language to primary language, time consuming process! Although the content is translated but it would not shown correctly in second language. Same issue here!
Comment #3
jose reyero commentedComment #4
jose reyero commentedUpdated task description to account for the fact that when you switch default language back to English, nothing happens, existing config language is never updated.
I guess we need to make locale_config_batch_set_config_langcodes() behave the same for all languages and not to make an exception if default language is "en", or maybe keep track of the last language set for configuration, and whether the default langcode has been changed or not...
Comment #5
tsotoodeh commentedWell, as far as I can see the Drupal multilingual efforts has come a long way from the time that i18n or internationalization and localization modules was once were.
To be truly multilingual the configuration translation and interface translation should be taken a second thought.
As you said, the the language switch should be respected both in terms of configuration of the elements of the site and also the contents. An architectural plan should be devised for this task. Currently the configuration in consistency after switching the language from default language are many to account.
Comment #7
almador commentedI don't know if this is the right topic to share my issue, but it's also related to switching the original language.
What I did - while upgrading Drupal 8 to Drupal 9 by mistake I changed my default language from English to Spanish. When I realized this (after the upgrade) I switched my default language back to English from this page:
admin/config/regional/languageBut now, when I'm trying to edit any of my translations related things it still says "Español (original)".
Is there any way to switch every translation option back to English (original)?
Comment #8
gábor hojtsyMade the title more specific.
Comment #9
gábor hojtsyLooking at why this happens. When a module is installed after the default language is changed:
All in all I think the logic protects the existing language changes in active config if they were made prior to the default language change. So if you already have a Swedish site let's say, you switch to Finnish, the active config items that were previously Swedish will remain Swedish. Newly installed modules will get their config in Finnish in active config, so you end up with a mix of config items with Swedish and Finnish. But the integrity of your config is maintained.
If you built out a part of the website in English and then switch the default langcode, this indeed ends up doing more dramatic changes later because English is considered special. (When the default language is set back to English, I think the data protection logic does what it was supposed to do).
Now as to what happens when default language is changed, I'll post another comment, this is already quite long :D
Comment #10
gábor hojtsyDefault language change on the UI is implemented in LanguageListBuilder::submitForm(), and does this essentially:
Language module reacts on the config save of the default langcode in its ConfigSubscriber but that of course is not related to interface translation.
Finally locale has its own LocaleConfigSubscriber but that does not consider a default language code change as something to care about.
Comment #11
gábor hojtsyI'm a bit torn as to how to resolve this. For one, we want to make default language changing as easy as possible. The intent of the code is to consider config similar to content, where the existing language and overrides of configs is kept, except in the English special case that it assumes belongs to the default config that needs changing. There is no such logic for content entities either to swap their default language and translations when a site default language changes.
At the same time, users likely expect to edit configuration in the site's default language by default, which the current logic attempts to ensure, at least as long as that default is English and after the first transition from English to non-English. It does not maintain that user experience once you want to make the second language transition, whether back to English or to something else. It does leave your config intact but it does not maintain the assumed user experience. Also, if the first language transition happens later in the site's life, a massive config change happens then. That in itself is expected, but not when you install a new module :D So the problems are:
Comment #12
drupaldope commentedIt seems that someone has been changing some things in how languages work.
I am now unable to rename a certain language (D 10.2.4).
I wanted to name English en and German de.
The YML configuration is correct, but when the page is shown in the default original language German, it will just say "Deutsch" no matter what.
I guess the new code changes fail to retrieve and display the correct label.
Comment #13
drupaldope commentedActually I had it working correctly on a site where I did the following :
Installed the site in English
Added German
Added British English
Deleted English
works.
Comment #14
drupaldope commentedthere is actually more to this issue.
languages need a translatable label, which would resolve the present issue and a dozen more related issues I have found today when going down this rabbit hole.
BUT
languages also need editable labels that will be displayed in translations, verbose translations and abbreviated translations, URLs ...
So for example, a site could have installed British English and it would display the following way :
"en-gb" (non translatable) in any technical-related stuff such as hreflang, html, etc.
"British English" (translatable) in any configuration dialog in the admin interface, translation forms, etc.
"en" (translatable) as a label for language switcher links
and potentially, the site owner would want something else (translatable) to be displayed in the URL, such as /eng/ or /english/ or ... whatever
so the short ISO language code would be used by Drupal to identify the language and source translations, and would be untranslatable.
and then there should be 3 translatable labels on top.
Comment #15
drupaldope commentedI can now also confirm the workaround to correct this issue on running sites.
First, install an additional language.
Then change the language of all localized content to that new language you just installed.
That may be nodes, blocks, media, redirects and URLs, etc.
Then delete the language of which you can't change the name (be careful, this will delete all content you forgot to switch to the new language).
Purge the cache and then re-install the language you just deleted.
Edit the name of that language to what you wanted and then change the contents' language back to what it was.
So it seems like something screws up the language settings when installing the site or when declaring a language default.
Comment #16
drupaldope commentednever mind the workaround, one of the language labels reverted back to original after doing something else on the site.
Comment #17
claudiu.cristeaI don't know whether is related to this. I set the default language to other than English. Then I've exported the config (drush cex). Reinstalled the site from config but the English language is gone. Checked the config sync directory, I can see thelanguage.entity.en.ymlfile. Checked the{config}table, nolanguage.entity.enat all. It just vanished.EDIT: Ignore this comment. I just discovered that I need to set
keep_english: truein the installed profile. Maybe this deserves to be better documented, even by showing a warning message to the site builder when they are changing the default language?EDIT2: I have created #3545306: Installation from config removes English if the installed profile does not have keep_english for this issue
Comment #18
anybodyNice, just found this and I think it's very similar to this one: #3568743: Convert / unify all default configs to the site default language (which has a possible solution).
For the future I'd vote to always store the default config in English by design, so we can't have such cases any more and treat any other language as translations in their respective collection / folder!
That will also simplify importing (typically English) config from modules etc...
Comment #20
dqdAdded to the "Refine settings, flexibility and coherences between translatable areas" outline on git.drupalcode.org. Thoughts appreciated.
Comment #21
ressaConnecting related issue and adding "Update Install a language doc page" in Issue Summary as a task.
Comment #22
gábor hojtsy@anybody: in some European studies (eg a study of 100k websites of in the EU, 4-5k sites per country) it was found that 80% of the sites are not English single language. Why would they need to create content types, views, etc. in English? That would be bad :) Drupal already takes some effort to keep the default config in your language, we need to fix the missing use cases.
I wrote out some plans above 2 years ago in #9, #10 and #11. Since then I realized we probably don't need to deal with this in config import as that would assume you are already deploying an updated set of config. So we need to do this on the form. Since that already happens later when you install a module, we should at first bring the same behaviour forward to the default language change IMHO as a first step.
Comment #23
anybody@gábor hojtsy thanks. Yes I understand that. My recurring issue in the role of a site builder is, that again and again I have to think about in which language I'm acting and how I should name even the machine names.
In 60% of our cases the projects are in German, some of them are ONLY in German and some of them are translatable into other languages. But we love the configs to be consistently in English as base language..
From our perspective it would be more appropriate to be able to rely on English as base language and use translation for anything else.
You know a lot more about the internal concepts and I think you discussed this 100000x more than me and have good reasons. So this comment is not meant to tell what should be done, just to let you know about the background and our daily pain with the "mix" we're experiencing.
Still my solution would not save us from having clients that then create entity types with German names ;) So there's no perfect. Most importantly the bug needs to be fixed, as you wrote. For the other things we'll still have to find a better / best practice.
Thank you so much! :)
Comment #24
gábor hojtsyI'm working on implementing this now :)
Comment #25
gábor hojtsy@andybody: for your base English use case you can install the site in English and keep site default in English, why not do that?
Comment #27
gábor hojtsyWhile I pushed a complete lifecycle solution above in an MR, I decided that this will not be the best route :D Instead I think there is a lot of merit in trying to cater more for what @anybody is saying about consistent source language AND decouple the config default language from site default after that (so changing config default language is a conscious choice separate from site default). For the first part of this, I opened #3608533: Introduce "Configuration language" settings page to control langcode visibility. Once that lands, I think we can return here and introduce the Config default language and adjust the code to use that when dealing with config.
I'll work on #3608533: Introduce "Configuration language" settings page to control langcode visibility tomorrow, marking this postponed on that. I already posted the rationale and high level plan there though :)
Comment #28
anybody@gábor hojtsy re #25 we do that in many cases, but it doesn't feel perfect because then you have the English language also in many Content (related) areas. It just doesn't feel natural and correct to me. And you still have to be very careful to not accidentally use the wrong language somewhere.
#27 sounds like you came to a similar conclusion. Thank you so much for all your work put into this.
Comment #29
gábor hojtsy@anybody: yeah I did came to the conclusion that we need to decouple the "Configuration default language" from the "Site default language", which is another way to approach "enforce a config language". I also came to the conclusion that the few core changeable config languages are in the way sort of :D So I created #3608533: Introduce "Configuration language" settings page to control langcode visibility and proposed a solution there. That introduces explicit intent about language of those config, so after that as we want to I think introduce a dedicated "Configuration default language" here, we can rely on that intent / configuration to not change things that site owner explicitly wanted to be in other languages but change the rest of the config as needed. (Also to not change config language on site default language change ever). Let's reposition this issue for that, but we need to resolve #3608533: Introduce "Configuration language" settings page to control langcode visibility so we have data on the intent of the config that is currently potentially in other languages. That also helps enforce a consistent language if you don't configure those entities to be able to pick a language which is the new core default as proposed there.
Please review that one to push this cause forward :)
Comment #30
gábor hojtsyCreated a parent issue to group related problems and show how this leads to resolving config language issues once and for all hopefully :D
Comment #31
gábor hojtsyRewrote the issue summary. Will of course need more expansion but this is a good start IMHO.
Comment #32
gábor hojtsyFix table HTML.
Comment #33
gábor hojtsyFix one more HTML issue and reorder the events in the HTML to make it easier to follow.
Comment #34
gábor hojtsyMore elaborate items in the table to point out the problems better.
Comment #35
gábor hojtsyFix list markup.
Comment #36
gábor hojtsyComment #37
gábor hojtsyComment #38
gábor hojtsyMassive update to issue summary based on recent discoveries. I found 3 new problems since the above, so getting more convinced that we want to have one unified "Configuration default language".
Comment #39
gábor hojtsyClarified a few items.
Comment #42
gábor hojtsyComment #43
roderikThank you for this :-)
I was tracing a situation that I wasn't sure is 'my' bug or not, and I haven't seen it mentioned anywhere:
The samlauth module starts out with very minimal installed config, with no label values and no language code. But there are labels in the config object, and as soon as you set a label value... Configuration Inspector reports a missing language code. #3611776: samlauth.authentication config object must specify a language code
It felt like either I was missing how exactly I should solve this... or the only way to solve that reliably would be adding code into
Config::save(). (Which felt like too big a thing to propose for someone without intricate knowledge of the config system...)Luckily, I read your latest MR's code and it does just that! So... I believe I bumped into yet another issue that is solved by your MR!
Comment #44
gábor hojtsy@roderik: I have a targeted issue for that problem at #3600904: Shipped configuration entities that do not have translatable elements are not set to the site default langcode as that is also reproducible with core only :)
Comment #45
gábor hojtsyI've been experimenting how far this needs to be stretched in the past few days and ended up building https://www.drupal.org/project/config_language_lock which has about 900 lines of PHP code and almost 2x the amount of that in docs and 4x the amount that in tests to prove how core works vs how the module works. People following this issue would be welcome to test that (in dev environments for now, it is very early stages). That said the docs and tests and SUPER thorough, so I'm fairly confident it is fine. Read the very extensive docs at https://project.pages.drupalcode.org/config_language_lock/
Comment #46
roderikD'oh! I failed to read this issue's meta parent and its children.
Reviewed #3600904: Shipped configuration entities that do not have translatable elements are not set to the site default langcode. The issue I stumbled into is not currently solved by it though (because it's simple config), so curious for the next step.
Comment #47
alexpottI changed the MR to result in less changes by ensuring we're only adding a langcode to config with translatable parts. I've also enforced the 'en' default in code which makes the change less disruptive to kernel testing where the system module might not be installed.
Comment #48
catchIt would be useful for installer refactoring if we were able to move the default language configuration out of system module to core/
This is because if you try to install system module along with any other modules at the same time, it's impossible to set the system default language in between system module being installed and the other modules getting installed, and that information comes from the request.
Currently working around this in #3614153: Reduce container rebuilds in the installer where you can see having the config outside system would make it a lot easier.
Comment #49
alexpott@catch sure we can introduce a core.language and open a follow-up to move the site default langcode there too. Sometimes I wish we could move this to container parameters instead of config.
We also need to prevent the language that is the default config langcode from being deleted.