Download & Extend

Provide a distinct administration user interface language option

Project:Drupal core
Version:8.x-dev
Component:language system
Category:feature request
Priority:normal
Assigned:penyaskito
Status:closed (fixed)
Issue tags:D8MI, language-base, negotiation, Usability

Issue Summary

My site's default language is Finnish but I need to use English for admin pages. There should be next to Default language option the second one where user could choose the admin language. I tried also to change language from my user account but it didn't make any change (bug?).

Change records for this issue

Comments

#1

Priority:critical» normal

Old Issue, but it's a good question - admin in different language? Available, or move to D8?

#2

Solution in contrib:

http://drupal.org/project/admin_language

Feature request for D8?

#3

Version:6.5» 8.x-dev

Should this live in contrib? If so please set to closed(fixed).

#4

You can certainly set your user preferred language to whatever language you want and browse the site in that language. That sounds like the easiest, no extra module required :)

#5

#6

In D7 it is possible to move the user language detection method on top and having it prevale over URL language. This allows an admin user to set her preferred interface language. I ain't sure we need something more advanced in D8.

#7

Looks like http://drupal.org/project/admin_language sets one global admin language for the whole site. Is that generally accurate? Thinking about this, it sounds like this would be per-user, so that a multilingual site can be managed by people in their own language. I assume the problems solved here include that the language changes when you hit a node that you want to translate for example, from where admin links would get to keep that modified language, that is not desired. I agree it is probably easy to implement per site instead of per user though, given that if we implement per user, it becomes a problem to display the admin language selector to some people on their profile but not to others. It is hard to tell generally if someone has "some kind of admin access" or not.

Maybe we should think of this as a second session language provider that only applies to admin pages (with a block specific for that to let admins set it?). Blocks don't work well with the Seven theme though... Well, just thinking out loud here :)

#8

My current personal recipe for the scenario described in #7 is:

  • enable content language negotiation (for instance by enabling Entity Translation)
  • configure interface language detection: user, URL
  • configure content language detection: URL
  • enable the content language switcher block globally

If I wish to have the possibiliy to switch even interface language:

  • configure interface language detection: Session, user, URL
  • configure content language detection: URL
  • enable the content language switcher block globally
  • enable the interface language switcher block only for the admin roles

My main doubt is: do we need some usability improvement to make clear that all of this is actually possibile?

Another possibility might introducing a Role language provider that would allow to configure a language for each available role. But all of this looks to me fairly complex to setup for the average user.

#9

Marked #744656: No translations for admin interface and #289114: Set different presentation language for Admin only as duplicates. There is clearly *lots* of interest in this.

#10

Fascinatingly also closed down #427782: All English has gone RTL? as duplicate. Huh.

#11

#12

@plach: I think your suggestions from #8 are not entirely good in that they have front-end consequences, when the requestors only want their admin language changed, not to have users fiddle with language changes persisting in their sessions.

#13

Subscribing.
It should also be possible to hide the admin language from "Language settings" on the user edit account form if the admin language is not one of the "public" languages. And if the site is a single language site where the admin language is different from the default language, it should be possible to hide "Language Settings".

#14

A new 7.x-1.x-dev version of Administration Language has just been released fixing some of what I mentioned in #13.

And it has this feature request: #1239204: Use preferred language on per-user basis instead of global setting

#15

Title:Language For Admin option» Provide a distinct administration user interface language option

Retitling to better explain the feature request. I've pinged @wulff (the admin_language module maintainer) if he would be interested in integrating some of the module functionality in core. Looking at the code, it seems to be doing numerous other things, like optionally forcing language neutral nodes and path aliases which definitely sound unrelated.

#16

BTW I think the spec for this feature at its most basic form is a language provider that only kicks in for hook_admin_paths() paths, and provides a concrete language. Then this can be enabled on the UI like any other provider. A bonus for it providing a per-user configuration option as well for admin language. Where it gets tricky is that it would change the content language as well with our current default fallback method in core, so we'd need to expose those settings somehow to let people disconnect content from interface, which is the primary goal of this feature anyway.

#17

As I was writing in #1036212: Use hook_language_types_info() instead of hook_init() in D7, I think the admin language provider is the way to go too: it could set the default admin language using the user setting and falling back to the default admin language.

Where it gets tricky is that it would change the content language as well with our current default fallback method in core, so we'd need to expose those settings somehow to let people disconnect content from interface, which is the primary goal of this feature anyway.

The provider should be defined to be assignable only to the UI language. To actually take advantage of this we should make content language negotiation enabled by default in D8: node translation, if present, could exploit it through the tnode/1 feature we were speaking about in the last months.

#18

Issue tags:+D8MI

tagging

#19

@plach: it does sound like a usability problem if we need to expose both interface and content language config separately in D8, that does not sound like good news. However, I see that trying to not inherit to content language if it was picked by the admin language one would be a bad case of special casing that we should not pursue. Hm.

#20

The issue for me is that I am below survival level for both Spanish and Chinese for a trilingual website (with English as the main language and selected content translated). It is also possible we would be adding additional languages for which I know nothing. I may need to post content simply by somebody providing me a Word doc with the translation, and I just copy and paste. I want all interface content to be in English, but the content page would be marked as Spanish or Chinese and show up in Spanish or Chinese.

An anonymous viewer of the Spanish or Chinese page would see everything on the page entirely in that language except, of course, for the other-languages entries in the language-switcher block.

However a logged-in staff content-administering viewer would want to see Drupal interface links such as "Log out," "Edit," "Add new content" and the administrator menu in the logged-in viewer's preferred administration language, not in the content language.

#21

This should be already possible in D7 core: just enable the User language detection method on top of the URL one.

#22

Issue tags:+language-base

Tagging for base language system.

#23

Issue tags:+negotiation

Tagging for language negotiation too.

#24

Actually, the other languages have just hit and it's likely to affect many U.S. local government transportation websites due to action by the Federal Transportation Administration. As part of U.S. Title VI of the Civil Rights act, the San Francisco Municipal Transportation Agency website is now going to have at least a few pages each in Arabic, French, Japanese, Korean, Italian, Russian, Thai, Vietnamese and possibly Tagalog. I have to be able to copy and paste content in those languages, as well as verify they can be viewed by an anonymous visitor, but manage that content using an English-language interface.

#25

Anybody want to work on this?

#26

Assigned to:Anonymous» c31ck

I'll work on this.

#27

Tagging with sprint.

#28

Status:active» needs review
Issue tags:+sprint

Initial patch that adds a language provider and allows a user to choose their admin language. Users can choose their admin language if they have the access administration pages permission and if the user admin language provider is enabled.

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-28.patch6.9 KBIdleFAILED: [[SimpleTest]]: [MySQL] 40,566 pass(es), 0 fail(s), and 20 exception(s).View details

#29

Status:needs review» needs work

The last submitted patch, admin-user-interface-language-option-322995-28.patch, failed testing.

#30

Status:needs work» needs review

Attempt at fixing test failures.

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-30.patch6.97 KBIdleFAILED: [[SimpleTest]]: [MySQL] 40,515 pass(es), 50 fail(s), and 28 exception(s).View details

#31

Status:needs review» needs work

The patch looks pretty good to me, I have a small observation:

+++ b/core/modules/user/lib/Drupal/user/AccountFormController.phpundefined
@@ -224,6 +226,18 @@ abstract class AccountFormController extends EntityFormController {
+    if (user_access('access administration pages')) {
+      language_negotiation_include();
+      $form['language']['preferred_admin_langcode'] = array(
+        '#type' => 'language_select',
+        '#title' => t('Admin language'),
+        '#languages' => LANGUAGE_CONFIGURABLE,
+        '#default_value' => $user_preferred_admin_language->langcode,
+        '#description' => t("This account's preferred language for administration pages."),
+        '#access' => language_negotiation_method_enabled(LANGUAGE_NEGOTIATION_USER_ADMIN),
+      );

The language_negotiation_include() function is implemented by the language module, which is not a required core module, so I think this will generate a fatal error on the sites that have the language module disabled.

After a talk with Gabor, I think a better idea would be to just remove the language_negotiation check from the #access, so then you do not need to include the file anymore. The user_access call should also be called with the user account parameter. Also, you can move the "user_access('access administration pages')" into the #access and then the code will be just more straightforward.

#32

Status:needs work» needs review

I've removed the language_negotiation check and moved the user_access into the #access. Also, $account is now passed to user_access.

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-32.patch6.84 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,568 pass(es).View details

#33

Status:needs review» needs work

Looks good to me now.

But, I think we now have another issue: the user_preferred_admin_language() function generates code duplication, because the almost exactly same code and comments can be found in user_preferred_language(). One solution would be to juse use the user_preferred_language() in both cases, and add a parameter, so you will end up in having something like:

function user_preferred_language($account, $type, $default = NULL) {
...
}

Then, inside the function, depending on the $type parameter, we will have to use (preferable in the most clever and flexible way) the right attribute. A good approach would be to use the $type parameter in a way that if you will add another type of language in the future, then the code in the user_preferred_language() should not change.

#34

Assigned to:c31ck» Schnitzel

#35

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

removed the user_preferred_admin_language() function and added a new parameter for user_preferred_language()

also needs tests!

AttachmentSizeStatusTest resultOperations
32-53.txt2.97 KBIgnored: Check issue status.NoneNone
admin-user-interface-language-option-322995-35.patch6.87 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,631 pass(es).View details

#36

You changed the parameters for user_preferred_language(). user_preferred_language() is used in a few places in core. I also prefere NULL as default value for $type.

  • core/includes/mail.inc
  • contact module

#37

checked the rest of the core, user_preferred_language() is all the time called with 1 parameter, so no issue there.

But the default parameter NULL is a good idea.

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-37.patch6.87 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,637 pass(es).View details

#38

discussed with @webflo and @gabor: that language_from_user_admin() and language_from_user() should check if the preferred language is a valid language. did this now.

also added 6 new tests for testing LANGUAGE_NEGOTIATION_USER_ADMIN and LANGUAGE_NEGOTIATION_USER

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-38.patch11.7 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,641 pass(es).View details
37-38.txt5.43 KBIgnored: Check issue status.NoneNone

#39

#40

Status:needs review» needs work
Issue tags:-Needs change notification+Needs tests

some missing dots

+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.phpundefined
@@ -196,6 +196,107 @@ class LanguageUILanguageNegotiationTest extends WebTestBase {
+    // Set preferred langcode for user to NULL

missing dot

+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.phpundefined
@@ -196,6 +196,107 @@ class LanguageUILanguageNegotiationTest extends WebTestBase {
+    // Set preferred langcode for user to unknown language

missing dot

+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.phpundefined
@@ -196,6 +196,107 @@ class LanguageUILanguageNegotiationTest extends WebTestBase {
+    // Set preferred admin langcode for user to NULL

missing dot

+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.phpundefined
@@ -196,6 +196,107 @@ class LanguageUILanguageNegotiationTest extends WebTestBase {
+    // Set preferred admin langcode for user to unknown language

missing dot at the end

#41

Can this get a screenshot?

#42

screenies

AttachmentSizeStatusTest resultOperations
Languages | drupal8.jpg435.62 KBIgnored: Check issue status.NoneNone
admin | drupal8.jpg353.98 KBIgnored: Check issue status.NoneNone

#43

Schnitzel explained it to me, looks like we just need to fix some of the labeling.

http://drupal.org/files/admin%20%7C%20drupal8.jpg
On the account page, we want to remove the description and clarify the label a bit. This because "Admin Language" isn't very clear, people don't know what the "Admin" is. Therefor we suggest changing it to:

"Administration pages language"

This also means that we need to change Language, to "Site Language".

http://drupal.org/files/Languages%20%7C%20drupal8.jpg
Almost all the labels here are overly descriptive, it could probably be something like:

Language from the URL(Path prefix or domain)
Language from the requestion/session paramter
Account language setting.
Language from the browser's language setting.
Account administration pages language setting.
Default site language (English)

We have to figure out whether we want setting or preference, I am not sure what the standard is.

#44

Status:needs work» needs review

fixxed codestyle and textadaptions

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-44.patch13.41 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,641 pass(es).View details
38-44.txt5.33 KBIgnored: Check issue status.NoneNone
admin | drupal8-1.jpg112.66 KBIgnored: Check issue status.NoneNone
Languages | drupal8-1.jpg427.81 KBIgnored: Check issue status.NoneNone

#45

Status:needs review» needs work

I find the description a bit odd:

+++ b/core/modules/language/language.moduleundefined
@@ -388,8 +388,8 @@ function language_language_negotiation_info() {
+    'description' => t("Account site language setting."),

alternatives:
- Site language setting of the user.
- Site language setting of the user's account.

+++ b/core/modules/language/language.moduleundefined
@@ -419,6 +419,15 @@ function language_language_negotiation_info() {
+    'description' => t("Account administration pages language setting."),

- "Language setting of the user for the administration pages"
- "Administration pages language of the user"

+++ b/core/modules/language/language.negotiation.incundefined
@@ -162,6 +167,27 @@ function language_from_user($languages) {
+  // User preference (only for logged users).

only for authenticated users

+++ b/core/modules/user/lib/Drupal/user/AccountFormController.phpundefined
@@ -218,12 +220,20 @@ abstract class AccountFormController extends EntityFormController {
+      '#title' => t('Site Language'),

Site language (without a capital L)

#46

Status:needs work» needs review

thanks @atticks for the review. Also discussed the change and we both agree that Account is a bit confusing, but overall we say:

- I send a mail to an user
- An user makes changes in is account

So account makes more sense.

so fixxed the capital and "authenticated users"

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-46.patch13.58 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,642 pass(es).View details

#47

Status:needs review» needs work

+++ b/core/modules/language/language.moduleundefined
@@ -367,7 +367,7 @@ function language_language_negotiation_info() {
-    'description' => t('Determine the language from the URL (Path prefix or domain).'),
+    'description' => t('Language from the URL (Path prefix or domain).'),

@@ -380,7 +380,7 @@ function language_language_negotiation_info() {
-    'description' => t('Determine the language from a request/session parameter.'),
+    'description' => t('Language from a request/session parameter.'),

@@ -388,8 +388,8 @@ function language_language_negotiation_info() {
-    'name' => t('User'),
-    'description' => t("Follow the user's language preference."),
+    'name' => t('Account'),
+    'description' => t("Account site language setting."),

@@ -398,7 +398,7 @@ function language_language_negotiation_info() {
-    'description' => t("Determine the language from the browser's language settings."),
+    'description' => t("Language from the browser's language settings."),

Lets rename this negotiation methods in follow-up issue.

+++ b/core/modules/language/language.negotiation.incundefined
@@ -150,10 +155,10 @@ function language_from_browser($languages) {
+  if ($user->uid && !empty($user->preferred_langcode) && array_key_exists($user->preferred_langcode, $languages)) {

@@ -162,6 +167,27 @@ function language_from_user($languages) {
+  if ($user->uid && !empty($user->preferred_admin_langcode) && array_key_exists($user->preferred_admin_langcode, $languages) && path_is_admin(current_path())) {

Why not just use isset($langauges[$user->preferred_language])?

+++ b/core/modules/user/user.moduleundefined
@@ -2962,14 +2962,24 @@ function theme_user_signature($variables) {
+  if (empty($type)) {

isset($type) is more accurate.

#48

Status:needs work» needs review

thanks for review, removed the textchanges and using isset()

AttachmentSizeStatusTest resultOperations
46-48.txt4.09 KBIgnored: Check issue status.NoneNone
admin-user-interface-language-option-322995-48.patch12.04 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,637 pass(es).View details

#49

#50

Status:needs review» needs work

I found one last issue.

+++ b/core/modules/user/user.installundefined
@@ -224,6 +224,13 @@ function user_schema() {
+        'not null' => TRUE,

@@ -475,5 +482,18 @@ function user_update_8003() {
+    'not null' => FALSE,

The db schema is not identical. The 'default' key is missing too.

#51

Status:needs work» needs review

thanks! fixed with using the same schema for update and install

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-51.patch15.61 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,640 pass(es).View details

#52

Status:needs review» reviewed & tested by the community

Looks good now.

#53

Status:reviewed & tested by the community» needs work

sorry missed it before

+++ b/core/modules/language/language.admin.incundefined
@@ -325,34 +325,34 @@ function language_admin_add_custom_form_validate($form, &$form_state) {
+  $language = (object) array(
+    'langcode' => $langcode,
+    'name' => $form_state['values']['name'],
+    'direction' => $form_state['values']['direction'],
+  );

better switch to using new Language()

+++ b/core/modules/language/language.admin.incundefined
@@ -325,34 +325,34 @@ function language_admin_add_custom_form_validate($form, &$form_state) {
+  $language = (object) array(
+    'langcode' => $langcode,
+  );

dito

#54

Status:needs work» needs review

Fixed the bugs mentioned by attiks.

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-54.patch15.82 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,635 pass(es).View details
admin-user-interface-language-option-322995-54.interdiff.txt1.68 KBIgnored: Check issue status.NoneNone

#55

looks good, RTBC when green

#56

Status:needs review» reviewed & tested by the community

#57

Status:reviewed & tested by the community» needs review

Rebased against 8.x HEAD is much smaller now. Its only one submit handler (language_admin_add_form_submit) for predefined and custom languages.

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-57.patch13.24 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,637 pass(es).View details

#58

And added the more descriptive strings for 46.

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-58.patch13.25 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,633 pass(es).View details
admin-user-interface-language-option-322995-58.interdiff.txt668 bytesIgnored: Check issue status.NoneNone

#59

Status:needs review» reviewed & tested by the community

the new patch is better now, so RTBC!

#60

Assigned to:Schnitzel» penyaskito

Rerolled.

AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-60.patch12.5 KBIdleFAILED: [[SimpleTest]]: [MySQL] Invalid PHP syntax in core/modules/language/language.admin.inc.View details

#61

Status:reviewed & tested by the community» needs work

The last submitted patch, admin-user-interface-language-option-322995-60.patch, failed testing.

#62

Duplicated use?

diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc
index 2fadec7..b388986 100644
--- a/core/modules/language/language.admin.inc
+++ b/core/modules/language/language.admin.inc
@@ -7,7 +7,6 @@

use Drupal\Core\Language\Language;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
-use Drupal\Core\Language\Language;

/**
  * User interface for the language overview screen.
AttachmentSizeStatusTest resultOperations
admin-user-interface-language-option-322995-62.patch12.07 KBIdlePASSED: [[SimpleTest]]: [MySQL] 40,717 pass(es).View details

#63

Status:needs work» needs review

#64

Status:needs review» needs work

The last submitted patch, admin-user-interface-language-option-322995-62.patch, failed testing.

#65

#66

Status:needs work» needs review

#62: admin-user-interface-language-option-322995-62.patch queued for re-testing.

#67

Status:needs review» reviewed & tested by the community

Thanks for the rerolls.

#68

Status:reviewed & tested by the community» fixed
Issue tags:-Needs tests

This looks good. Committed to 8.x. Thanks.

#69

Added a site builders' change notice for this at http://drupal.org/node/1776768 - CHANGELOG.txt patch forthcoming from rvilar.

#70

Issue tags:-sprint

Changelog action happening in #1777870: Catch up changelog.txt with recent languages changes, removing off sprint. Thanks all!

#71

Status:fixed» closed (fixed)

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