Flexible Administration Language
This module allows administrators to configure a separate language for administrative pages, independent of the website's interface or content language. It provides a dedicated language type for administration, enabling custom negotiation stacks with options for user-preferred or global default languages, and the ability to specify paths where this administration language should apply.
Purpose
flexible_admin_language adds a dedicated language_admin language type that
appears on admin/config/regional/language/detection alongside the built-in
Interface and Content language types. When enabled and customized, the
administration language is resolved by its own negotiation stack and then
bridged into the interface language on admin routes and configured paths.
Why This Exists
Drupal core hard-codes administration language detection into the interface
language stack via the language-user-admin plugin. That plugin only activates
for users with administration permissions and only on Drupal-flagged admin
routes. There is no way to configure a global fallback language for
administration, extend coverage to non-admin routes such as login pages,
or extend admin language detection with other types of plugins.
Many contributed projects were written to work around this but all solve
slightly different problems and neither provides an extensible framework for
others to build on. Rather than solving one or two specific cases only,
this module replaces the core approach with a first-class language type that
site builders can configure the same way they configure Content language:
with a "Customize" checkbox, a dedicated method table, and separate
configuration forms.
How It Works
The language_admin type
When the "Customize administration language detection" checkbox is checked on
admin/config/regional/language/detection, the language_admin type runs its
own negotiation stack. Two plugins are available:
- User preferred administration language — returns the language set on the
user's account under "Administration pages language". This field only appears
on account forms when this plugin is enabled. This reproduces the core
'Account administration language' option but without an admin path
restriction. - Global administration language — returns a site-wide default language
configured atadmin/config/regional/language/admin-language. Can be set to
the site default language, a specific language, or left disabled so this
method has no effect.
When the checkbox is unchecked, language_admin is not separately negotiated.
The bridge plugin
A plugin called Administration language sits in the Interface language
detection table. It activates on admin routes and configured paths, calls
getCurrentLanguage('language_admin') to run the administration language
stack, and returns that result as the interface language. On all other pages it
returns FALSE so the rest of the interface language stack runs normally.
The "Customize administration language" checkbox and the bridge plugin's
"Enabled" checkbox are kept in sync: enabling one automatically enables the
other, and disabling one disables the other.
Path configuration
The bridge plugin has a settings page at
admin/config/regional/language/admin-language-bridge with two sections:
- Anonymous and unprivileged users — path patterns where the
administration language applies for all users regardless of permissions.
Such pages could be login pages for examples where that is expected to
show up in the admin language. - Users with administration permissions — additional path patterns where
the administration language applies for users with the
access administration pagesorview the administration themepermissions.
These are additive on top of all Drupal-flagged admin routes (which also
limit to those two permissions already).
Comparison with related approaches
Drupal core: language-user-admin plugin
Core adds a single negotiation plugin to the Interface language stack. It
activates only for users with access administration pages or
view the administration theme and only on Drupal-flagged admin routes. It
reads the per-user preferred_admin_langcode field but provides no global
fallback, no path pattern configuration, and no way to extend coverage to
non-admin routes such as login pages. The detection settings appear in the
Interface language table with no separate section or "Customize" checkbox of
their own.
This module disables that plugin and replaces it entirely.
admin_user_language
This contributed module is complementary infrastructure rather than a
negotiation method. It does not add a plugin to any language stack; instead it
uses hook_entity_presave to automatically set preferred_admin_langcode on
user accounts based on a global site configuration. The settings form lets site
administrators choose a specific language or mirror whatever the user has set as
their preferred frontend language. A prevent_user_override option hides the
preferred_admin_langcode field on account edit forms and forces the globally
configured language on all users, removing per-user control entirely.
Because it only manages the preferred_admin_langcode field, it still depends
on core's language-user-admin plugin (or a replacement like this module) to
actually apply that preference during language negotiation, which could be
fragile if the user was not yet updated.
On its own the module does nothing for the language of the current request.
admin_language_negotiation
This contributed module is effectively a near-clone of core's
language-user-admin plugin with a single difference: the permission gate.
Where core checks access administration pages or
view the administration theme, this module checks a custom permission
admin_language_negotiation detection. This lets site builders grant
administration language negotiation to roles that do not have full
administration access without granting them any administration capability.
Beyond the permission change the behavior is identical to core: it works only
within the Interface language type, it reads getPreferredAdminLangcode(), it
activates only on Drupal-flagged admin routes via AdminContext::isAdminRoute(),
and it provides no global fallback, no path pattern configuration, and no way to
extend coverage to non-admin routes. Unless finer permission control over the
negotiation trigger is the only requirement, there is minimal value over core's
built-in method.
administration_language_negotiation
This contributed module adds a single Interface language negotiation plugin
protected by a custom permission: use administration language negotiation.
Only users with this permission are affected; for everyone else the plugin
returns FALSE and the rest of the Interface stack runs normally.
The plugin reads the per-user administration language preference and has a
use_default_lang option: when enabled the plugin falls back to the site
default language when no per-user preference is set; when disabled it passes
through to the next method in the Interface stack instead. A condition plugin
system lets site builders attach conditions (role, path, request path) that
must all pass before the plugin fires. A built-in path condition allows to
exclude certain paths even when they are admin paths.
Like core, it works entirely within the Interface language type — there is
no separate language_admin type — so the detection settings are mixed into
the Interface language table and cannot be managed independently.
The key differentiator is the condition plugin system, which is not available
in any of the other solutions. The module also requires locale as a
dependency.
Comparison table
Our module takes a different architectural approach: a dedicated language type
with its own method table, two positive list path patterns (all-users and
privileged), a global default language option, no custom permission
requirement, and no additional dependencies.
admin_user_language
admin_language_negotiation
administration_language_negotiation
flexible_admin_language
Separate language_admin type
No
No
No
No
Yes
Per-user preference
Always
Optional
Always
Always
Optional
Global fallback language
No
Yes (auto-set, stored on users)
No
Site default only
Site default or specific language
Coverage for non-admin-route paths for admins
No
No
No
No
Could support with custom plugin (two allowlists)
Coverage for anonymous / unprivileged users
No
No
No
Could support with custom plugin
Yes (path based)
Exclude paths from admin language
No
No
No
Yes, built-in plugin
No
Custom permission required
No
No
admin_language_negotiation detection
use administration language negotiation
No
Optionally don't allow per user control
No
Yes
No
No
Yes
locale dependency
No
No
No
Yes
No
Extensible via contrib plugins
No
No
No
Yes (condition plugins only)
Yes (negotiation methods only)
Dependencies
The module only depends on Language and User modules from core, no other dependencies or requirements.