This article covers the two admin-side language controls that the wpresidence-translate plugin wires into wp-admin: the admin-bar Content Language dropdown and the block editor header language badge. Both are thin layers on top of the language manager; the interesting parts are where they store state, how they gate access, and where they hook in. The sibling user article explains the UX. Product context lives on the multi-language real estate website page.
Source Files
| File | Role |
|---|---|
includes/admin/admin-bar-language-switcher.php |
Admin bar dropdown — node registration, switch handler, nonce-protected URL. |
includes/admin/editor-header-language.php |
Block editor language badge — localizes the payload into the admin JS bundle. |
includes/admin/post-editor.php |
Post editor auto-translate button; reads the same language resolution helpers. |
Admin Bar Switcher — Bootstrap
wpr_translate_bootstrap_admin_bar_language_switcher() is called from the plugin bootstrap. It registers two hooks:
add_action( 'admin_init', 'wpr_translate_handle_admin_language_switch' );
add_action( 'admin_bar_menu', 'wpr_translate_register_admin_bar_language_switcher', 90 );
Admin Bar Node Registration
wpr_translate_register_admin_bar_language_switcher( $wp_admin_bar ) runs at priority 90 on admin_bar_menu. It bails early unless:
is_admin()is true.$wp_admin_bar instanceof WP_Admin_Bar.current_user_can( 'edit_posts' ).is_admin_bar_showing().count( wpr_translation_get_active_languages() ) >= 2.
The parent node is registered with ID wpr-translate-admin-language and title Content language: {Current}. Each child node is wpr-translate-admin-language-{code}, with the current entry receiving class wpr-translate-admin-language-current.
State — User Meta
The selection is stored per user under the meta key:
| Meta key | Type | Written by |
|---|---|---|
wpr_translate_admin_language |
string (ISO code) | wpr_translate_handle_admin_language_switch() via update_user_meta(). |
Reads go through wpr_translate_get_admin_selected_language_code(), which sanitizes via sanitize_key() and validates against wp_list_pluck( wpr_translation_get_active_languages(), 'code' ). Invalid values return an empty string, letting callers fall back to the default language.
Switch Handler Flow
wpr_translate_handle_admin_language_switch() runs on admin_init. Only triggers when $_GET['wpr_translate_admin_language'] is present. Steps:
- Check
current_user_can( 'edit_posts' ). - Verify
$_GET['_wpnonce']against the actionwpr_translate_switch_admin_language. sanitize_key()the requested code and validate against active languages.- If valid:
update_user_meta( $user_id, 'wpr_translate_admin_language', $code ). - If invalid or empty:
delete_user_meta( $user_id, 'wpr_translate_admin_language' ). - Build the redirect URL by stripping
wpr_translate_admin_languageand_wpnoncefromREQUEST_URI, thenwp_safe_redirect()andexit.
URLs are built by wpr_translate_get_admin_language_switch_url( $code ), which composes add_query_arg() onto the current REQUEST_URI and wraps with wp_nonce_url().
Fallback Language
When the user has no stored meta, the current label resolves through wpr_translation_get_default_language_code( $languages ). This keeps the dropdown title informative on first visit.
Editor Header Badge — Bootstrap
wpr_translate_enqueue_post_editor_language_badge_assets( $hook ) is registered at priority 20:
add_action( 'admin_enqueue_scripts',
'wpr_translate_enqueue_post_editor_language_badge_assets', 20 );
It only acts when $hook is post.php or post-new.php. Priority 20 ensures the admin script bundle wpr-translate-admin is already registered and can receive the wp_localize_script() payload.
Language Resolution Order
wpr_translate_return_current_language_admin()— mirrors the admin bar user meta when available.wpr_translation_get_default_language_code( wpestate_translation_get_active_languages() ).get_option( 'wpestate_default_language', '' )— legacy compatibility for sites upgraded from older WPResidence translation helpers.- Hardcoded
'en'.
JS Payload Shape
The badge data is exposed to the admin bundle under wprTranslatePostLanguage:
window.wprTranslatePostLanguage = {
label: 'Français ( France )',
code: 'fr',
flagUrl: 'https://example.com/wp-content/plugins/wpresidence-translate/assets/img/flags/4x3/fr.svg',
flagAlt: 'Français ( France ) flag',
};
Flag URLs resolve via WPR_TRANSLATE_URL . 'assets/img/flags/4x3/{flag}.svg', falling back to the language code when no flag is set on the language record. The alt text template is __( '%s flag', 'wpr-translate' ).
Post Editor Auto-Translate Button
The related file includes/admin/post-editor.php hooks post_submitbox_misc_actions via wpr_translate_render_post_auto_translation_button(). It reuses the same language resolution chain — wpr_translate_get_post_language(), then wpr_translation_resolve_post_language_code(), then the default — so the publish-panel button, the editor header badge, and the admin bar switcher stay coherent.
When the target post’s language equals the default language, the button is replaced with the Original post – no translation action. notice. When no source post can be resolved via wpr_translate_resolve_metabox_source_post_id(), the button is rendered disabled.
Capability Map
| Surface | Capability |
|---|---|
| Admin bar node render | edit_posts |
| Admin bar switch handler | edit_posts + nonce wpr_translate_switch_admin_language |
| Editor badge payload | Any user who can load post.php/post-new.php |
| Auto-translate button | current_user_can( 'edit_post', $post->ID ) |
| Languages admin page | manage_options |
Extension Notes
- Do not write to
wpr_translate_admin_languagedirectly from custom code — always go throughupdate_user_meta()after validating againstwpr_translation_get_active_languages(). - If you are adding your own language-aware list filter, read the user’s selection via
wpr_translate_get_admin_selected_language_code()and fall back towpr_translation_get_default_language_code(). - The editor badge reads on every post editor page load — consumers should prefer
wpr_translate_get_post_language( $post_id )to follow the same source of truth. - The switcher intentionally does not alter the admin UI locale. Changing WordPress admin language remains a user-profile concern; this switcher only filters content.
Related Articles
- Managing Languages — Developer Reference — the language manager API both surfaces read from.
- Translating Posts & Pages — the editor-side user workflow.
- Post List Table Enhancements — how the admin language filter interacts with list screens.
For background, see the multi-language real estate website page.