WordPress.org

Make WordPress Core

Opened 3 years ago

Closed 6 months ago

Last modified 3 weeks ago

#29783 closed feature request (fixed)

User Admin Language

Reported by: faevilangel Owned by: ocean90
Milestone: 4.7 Priority: normal
Severity: normal Version: 4.0
Component: I18N Keywords: needs-dev-note
Focuses: administration Cc:

Description

How possible is it to enable a language switcher in the user profile for the admin area?

My reason for this (and I am not alone) is I work with a lot of international clients and they use a whole raft of different languages, from chinese to Russian.

We can use plugins to change the frontend language but if a Chinese client asks me to look into an issue in their site admin, I need to change the default WP language in WP config to English, do what I need to do and then change it back.

Another example, lets say I run a blog (similar to Mashable) where there are loads of different contributors from around the world, it would be much easier for them to see the admin in their native language.

Is this something WP would be looking at adding in the future (I think it would be a great benefit to the internalisation of WP).

Attachments (13)

29783.patch (4.4 KB) - added by ocean90 2 years ago.
29783.2.patch (14.1 KB) - added by ocean90 23 months ago.
29783.3.patch (14.2 KB) - added by ipm-frommen 23 months ago.
Remove var_dump, improve minor things
29783.diff (14.5 KB) - added by swissspidy 8 months ago.
29783.2.diff (16.2 KB) - added by swissspidy 8 months ago.
29783.3.diff (16.6 KB) - added by swissspidy 8 months ago.
user-language-admin-toolbar.php (682 bytes) - added by swissspidy 8 months ago.
29783.4.diff (15.6 KB) - added by ocean90 7 months ago.
Reverts changes to wp-settings.php
29783.5.diff (16.5 KB) - added by ocean90 7 months ago.
Includes changes to wp-admin/options.php
29783.6.diff (17.8 KB) - added by swissspidy 7 months ago.
29783.7.diff (1.9 KB) - added by pento 6 months ago.
29783.8.diff (447 bytes) - added by johnjamesjacoby 6 months ago.
Update label for value to locale instead of site_language
29783.9.diff (380 bytes) - added by johnjamesjacoby 6 months ago.
Use $profileuser->locale instead of get_user_option( 'locale', $profileuser->ID ); when editing a user

Download all attachments as: .zip

Change History (90)

#1 @kraftner
3 years ago

  • Resolution set to invalid
  • Status changed from new to closed

Hi faevilangel! Sorry to inform you that this is not a support forum, but a bug tracker. Please post this as a question at https://wordpress.org/support/

#2 @SergeyBiryukov
3 years ago

  • Component changed from General to I18N
  • Milestone changed from Awaiting Review to Future Release
  • Resolution invalid deleted
  • Status changed from closed to reopened

I think this is actually a good idea, and it was just mentioned in the IRC meeting on WCEU 2014 contributor day.

Should be doable now that WPLANG is deprecated and the language can be chosen in the admin.

#3 @SergeyBiryukov
3 years ago

  • Focuses administration added; accessibility removed

#4 @faevilangel
3 years ago

Thanks Sergey, it would make my life (and probably others) easier when managing sites for their international clients.

@ocean90
2 years ago

#5 @ocean90
2 years ago

  • Keywords has-patch 2nd-opinion added

29783.patch adds site language per user, currently used for the front and the admin.

#6 @Chouby
2 years ago

As this feature is already included in several multilingual plugins, and although I never understood why, I just wanted to warn that it will raise a conflict with bbpress: see https://bbpress.trac.wordpress.org/ticket/2309

#7 follow-up: @faevilangel
2 years ago

I just updated the first of many sites to 4.0.1 and guess what, my idea is in the release, I am absoloutely thrilled as this will make my life easier (and hopefully millions of other users). Thank you so much to the WP team.

#8 in reply to: ↑ 7 @johnbillion
2 years ago

  • Version changed from trunk to 4.0

Replying to faevilangel:

I just updated the first of many sites to 4.0.1 and guess what, my idea is in the release

The current language setting is actually a site-wide setting, not a per-user setting. Sorry to disappoint!

We'll hopefully be looking at this in 4.2, starting with ocean90's patch above.

This ticket was mentioned in Slack in #core by ocean90. View the logs.


2 years ago

#10 @ocean90
2 years ago

  • Milestone changed from Future Release to 4.3
  • Owner set to ocean90
  • Status changed from reopened to assigned

Let's try this in 4.3.

#12 @ocean90
2 years ago

Some questions:

1) Should users locale be inside get_locale()?
Maybe, but not as in 29783.patch because it requires us to reset the locale back to the site locale for things like API stuff, wp_credits(), options-general.php, or update-core.php.

2) Do we need something like get_users_locale() to avoid add_filter( 'get_user_option_site_language', '__return_false' );?
Yes, maybe get_locale( $user = true|false ) can work too.

3) Currently the themes and plugins API sends the result of get_locale() too. Is this good?
That's fine for the plugin details, but it should download all language packs, at least the ones for user's locale and the site language. User's locale for plugin details and language packs for every? installed language.

4) Should the locale be limited to the admin only? What about the toolbar?
Filtering a locale for the front-end shouldn't affect language_attributes() or is_rtl().

This ticket was mentioned in Slack in #core-i18n by ocean90. View the logs.


2 years ago

This ticket was mentioned in Slack in #core by ocean90. View the logs.


2 years ago

#15 @johnbillion
2 years ago

How might this affect wp_mail()? Should we attempt to send mail to a given user in their selected language? If not (or if they don't have a chosen language), we should probably send it in the site's chosen language, rather than the current user's chosen language.

#16 @nacin
2 years ago

1) Should users locale be inside get_locale()?
2) Do we need something like get_users_locale()?

Let's first avoid considering the existing complexity of get_locale(), which includes querying a few options and caching it. The simplest API would be something like get_locale( $user = false ), where $user is false, true for current user, or WP_User (or user ID as int) for another user.

In practice, this is probably both too magical and too complex. So I'd probably recommend get_user_locale( $user = current ). That way you can also replace all instances of get_locale() with get_user_locale() when appropriate, and it'll be clear why you use one over the other.

I also don't think it'll be a compatibility concern — you don't use get_locale() often. It'd be worse if you called load_textdomain() directly in a theme or plugin and thus called get_locale() on your own. (This would support changing the default for get_locale() to return the user locale, but I don't think that'd work too well.)

Currently the themes and plugins API sends the result of get_locale() too. Is this good?

The .org translations API is already designed to accept an array of languages, as possibly dictated by the existing plugins_update_check_locales and themes_update_check_locales I added in 3.7. It was designed for someone to possibly query their entire network and query all of the languages that are set. (Unfortunately, lang_id in wp_blogs is an integer field and has never been used AFAIK.) At the same time, it also already handles updating all languages that are installed, which I think would handle this in pretty much every case? I'm not sure. Perhaps it needs a tweak?

At the very least, it sounds like we should start sending an array of the following: the network's language (get_site_option( 'WPLANG' )), the site's language (get_locale()), and the user's language (get_user_locale()).

4) Should the locale be limited to the admin only? What about the toolbar?
Filtering a locale for the front-end shouldn't affect language_attributes() or is_rtl().

This is correct, in theory. We use both of these functions in the dashboard, so we need to be mindful of that. I do think the toolbar *should* be translated per the user's preference. This *will* complicate things like RTL and language attributes and such.


This opens up a new giant question mark, which is one reason why we haven't really done this yet. This isn't really about the user's language. It's about the user's locale. This includes date/time formats (which right now are a bit of a mess, even after [31862], and have zero abstraction*), number formats, the user's timezone, and even calendar stuff like first day of the week. We should ideally approach this holistically, and I'd argue if not together / at the same time, then we should try to plot a potential course before taking the next steps.

(* It might be time for a rewrite of WP_Locale.)

@ocean90
23 months ago

#17 @ocean90
23 months ago

We - @toscho, @ipm-frommen, @bueltge, @obenland, @giede, @dreamfish, and me - had a discussion about this at the contributor day of WordCamp Cologne. The following is a short summary:

  • Introduce get_user_locale() which retrieves the locale from a meta key locale. Fall back to get_locale().
  • Check bbPress/BuddyPress for compatibility issues because the user will be loaded early. (Known issue, @toscho is looking into it, provide patches if necessary.)
  • switch_to_(language|locale)():
    • We should avoid loading multiple languages into memory, only one at the same time.
    • Check if file exists before switching a language
    • Core isn't an issue, support was added in [29630]
    • load_(theme|plugin)_textdomain should maintain a history/stack about the loaded textdomains and language files. For v1 we want to provide a do_action when doing a language switch. We want to write a best practice guide to gather feedback.
    • @obenland mentioned, that wp.com is doing language switches already and will look into it.
  • For v1 we want to focus on admin screens and API calls, like plugin details.
    • Because of the architecture of admin-ajax.php this will include AJAX calls too.
    • Mails should be send in global site language.
  • Toolbar, plugins and themes is something for v2.
  • Date/time formats, timezone settings, etc should all be user settings. #18146 for timezone setting.

29783.2.patch is a first pass for get_user_locale(). Instead of using 'default' for the fallback I'm now using an empty string which is currently the default value, if a user hasn't selected a locale. If a user selects 'en_US' it stores 'en_US' into $user->locale. This is different from $locale where an empty string is 'en_US'.

#18 @nacin
23 months ago

Sounds great! Pretty much exactly in line with what I have been thinking.

Mails should be send in global site language.

I'll add that this makes sense for v1 if it's the easiest thing to do, but our end goal should definitely be for users to receive emails in their native language.

#19 follow-up: @GregLone
23 months ago

Simple suggestion if I may: add a filter in get_user_locale()?
Reason: admin-ajax.php and admin-post.php can be used for front-end stuff, so a plugin could filter the returned value depending on a $_REQUEST['lang'] parameter for example.

#20 in reply to: ↑ 19 ; follow-up: @toscho
23 months ago

Replying to GregLone:

Simple suggestion if I may: add a filter in get_user_locale()?

Maybe we should wait until we have some actual use cases (v2). It isn’t even clear what we would need to pass as parameters: current user language and site language, network ID, an array of available language files, the user object … should that be an array, an object or a bunch of separate parameters? Let’s wait and discuss that later in a separate ticket.

I still haven’t found the time to test my fix for the BuddyPress/BBPress issue. Will do that next week.

@ipm-frommen
23 months ago

Remove var_dump, improve minor things

#21 in reply to: ↑ 20 @Chouby
23 months ago

Replying to toscho:

Replying to GregLone:

Simple suggestion if I may: add a filter in get_user_locale()?

Maybe we should wait until we have some actual use cases (v2).

I would rather not wait as it would introduce a regression and mix languages in multilingual websites.

Currently, plugins make it possible for a user to have its backend in one language and browsing the website in another language (including of course the ajax calls, for which a plugin needs to differentiate if the ajax call is on backend or frontend).

It isn’t even clear what we would need to pass as parameters: current user language and site language, network ID, an array of available language files, the user object … should that be an array, an object or a bunch of separate parameters?

Currently get_locale() passes only the locale. I don't believe that we need more for get_user_locale().

This ticket was mentioned in Slack in #core by ocean90. View the logs.


23 months ago

#23 @ocean90
22 months ago

  • Milestone changed from 4.3 to Future Release

Punting because the code for switching a language when sending mails is still missing.

#24 follow-up: @trialotto
22 months ago

I have registered, just to comment on this topic.

In essence, the topic "user languages", for multiple admins (users) with different languages, is addressed.

It surprises me how little attention is being paid to issues, related to a necessity to have an admin panel with a specific language, while having a different site language.

Naturally, a "quick fix" (in the form of a get_users_locale() function) or even a "work-around" (in the form of symlinking .mo files) can be identified and implemented.

However, in my humble opinion, that is restrictive and not the proper way of doing things.

For instance, most of plugins are using the get_locale() directive and it can be expected that, at least in most cases, the implementation of this directive will not and/or cannot change, given the fact that the "common plugin" will and/or has to use the language, set in wp-config.php.

A (very) simple and alternative solution can be found in implementing a process, similar to that of the site language, that can be freely chosen.

In summary, the site language can be set in the general settings.

It would be more convenient to add an WP constant with (for instance) the name WPADMINLANG.

This would require a couple of lines in the code, defining WP constants.

In addition, the get_locale() directive can be augmented with some (minor) lines of code, reading both the WPLANG and the WPADMINLANG and passing them on to the various php files using get_locale().

This would be a simple, fast and more flexible (!) solution, not requiring any heavy adjustments of code and/or change of code of all (!) plugins and/or creation of a new get_users_locale() directive.

Maybe I am missing the point and/or some relevant information, but why does one not opt for the above or a similar solution?

Kind regards....

Last edited 22 months ago by trialotto (previous) (diff)

#25 in reply to: ↑ 24 ; follow-up: @zodiac1978
22 months ago

Replying to trialotto:

[...]
It would be more convenient to add an WP constant with (for instance) the name WPADMINLANG.
[...]
In addition, the get_locale() directive can be augmented with some (minor) lines of code, reading both the WPLANG and the WPADMINLANG and passing them on to the various php files using get_locale().

This would be a simple, fast and more flexible (!) solution, not requiring any heavy adjustments of code and/or change of code of all (!) plugins and/or creation of a new get_users_locale() directive.

Maybe I am missing the point and/or some relevant information, but why does one not opt for the above or a similar solution?

The WPLANG constant is deprecated, please see:
https://make.wordpress.org/core/2014/09/05/language-chooser-in-4-0/

#26 in reply to: ↑ 25 @trialotto
22 months ago

Replying to zodiac1978:

Replying to trialotto:

[...]
It would be more convenient to add an WP constant with (for instance) the name WPADMINLANG.
[...]
In addition, the get_locale() directive can be augmented with some (minor) lines of code, reading both the WPLANG and the WPADMINLANG and passing them on to the various php files using get_locale().

This would be a simple, fast and more flexible (!) solution, not requiring any heavy adjustments of code and/or change of code of all (!) plugins and/or creation of a new get_users_locale() directive.

Maybe I am missing the point and/or some relevant information, but why does one not opt for the above or a similar solution?

The WPLANG constant is deprecated, please see:
https://make.wordpress.org/core/2014/09/05/language-chooser-in-4-0/

I know, that was not the most happiest of choices, even though it is a very rational (and good) decision.

Problem now arises that

a) WordPress installations get flushed with all kinds of translations, when switching languages,

b) the above is also valid for all plugins, using the get_locale() directive,

c) updates for a specific language require switching to the specific language (and even waiting if the particular language pack update is not immediately detected and/or forced by the admin),

d) and so on,

and hence resulting in an abundance of files (in this case .po, .mo and .pot files), for languages that are often not used (only one language is selected at any given point in time).

In short, it has been a good choice to deprecate the WPLANG constant, but the implications thereof have not been considered carefully.

Nevertheless, let´s return to the issue, since the above is somewhat off-topic.

Any introduction of a constant will reduce the load on the database and CAN increase flexibility.

However, the current approach of

a) identifying a website language (on the one hand), AND

b) associating users, including admin (and therefore the local of the admin panel), with languages (on the other hand)

can work properly and/or sufficiently, if one does not bother about the practical implications.

One of those implications is the unnecessary use of disk space, given unused localisation files.

Another implication is the necessity to update all plugins (and that can be a real threat).

In short, the ability to set a separate constant for admin language should still be a valid alternative, besides the introduction of the possibility to set languages for users (i.e. end-users).

An argument for using a separate method for setting admin language is that one does select one language at any given point in time, as opposed to users languages, that can differ amongst various users at any given point in time.

The before mentioned (separate) method for setting admin language should still be able to use the current get_locale() directive, at least that is desirable (not required though).

Kind regards....

#27 follow-up: @GregLone
22 months ago

@ocean90
Related: #32879

#28 in reply to: ↑ 27 @trialotto
22 months ago

Replying to GregLone:

@ocean90
Related: #32879

@GregLone (and @ocean90),

Thanks for the hint to some elegant code, that can resolve some or most issues.

I am still seeing a problem: loading locales and changing them immediately is not "good practice", as opposed to loading the correct locale immediately.

Sure, when switching is required, the code can suffice, but the current core code can also do a lot.

Furthermore, I see another (general) problem: plugin locales.

To illustrate, it often is the case that a (international) company uses and/or desires various site languages, one admin panel language (with possibilities to switch languages from time to time) AND various plugin languages.

For instance, english admin and site language, but french language for the local shipment provider.

At this moment, WordPress is only supporting this type of common business scenario´s with (in essence) hard coded hacks (of WP core code, in the form of additional functions and filters, or of plugin code).

If one is going to alter locale setting options, one can easily take into account that WordPress has to be flexible enough to allow for all possible scenario´s.

#29 @ocean90
16 months ago

#35403 was marked as a duplicate.

This ticket was mentioned in Slack in #core-i18n by ocean90. View the logs.


12 months ago

This ticket was mentioned in Slack in #core by paaljoachim. View the logs.


12 months ago

#33 @ocean90
8 months ago

  • Keywords needs-refresh added

@swissspidy
8 months ago

#34 @swissspidy
8 months ago

  • Keywords needs-refresh removed

@swissspidy
8 months ago

#35 @swissspidy
8 months ago

  • Keywords has-unit-tests added

#36 follow-up: @swissspidy
8 months ago

Looks like $locale = get_locale(); in options-general.php needs to be $locale = get_option('WPLANG');, otherwise the user locale will always be selected.

Edit: We should just not touch wp-settings.php like the current patches do.

Last edited 8 months ago by swissspidy (previous) (diff)

#37 in reply to: ↑ 36 @ocean90
8 months ago

Replying to swissspidy:

Looks like $locale = get_locale(); in options-general.php needs to be $locale = get_option('WPLANG');, otherwise the user locale will always be selected.

See #31318 why we can't do that.

To workaround polluting the global $locale we can leave the get_locale() call:

$locale = get_locale();

$user_locale = get_user_locale();
$locale_file = WP_LANG_DIR . "/$user_locale.php";
if ( ( 0 === validate_file( $user_locale ) ) && is_readable( $locale_file ) )
	require( $locale_file );
unset( $locale_file, $user_locale );

#38 @swissspidy
8 months ago

  • Milestone changed from Future Release to 4.7

This ticket was mentioned in Slack in #core by swissspidy. View the logs.


8 months ago

@swissspidy
8 months ago

#40 @swissspidy
8 months ago

  • Keywords 2nd-opinion removed

In 29783.3.diff:

  • Remove is_admin() check in get_user_locale()
  • Move is_admin() check to load_default_textdomain() so the admin is always in the user's locale by default
  • Loads {$locale}.php for both the site locale and the user locale. (Not 100% sure about this one).
  • Adjusts tests.

user-language-admin-toolbar.php is a proof-of-concept plugin that, when applying the patch from #26511, changes the toolbar language depending on the user's locale, but keeps the rest of the site in the site's locale. See https://twitter.com/swissspidy/status/773571032963751936 for a screenshot. For sending emails etc. this can be done similarly.

#41 follow-up: @swissspidy
7 months ago

  • Keywords needs-refresh added

There seem to be some problems with the current patch (without any plugins installed):

  • Should {$locale}.php be loaded for both locales?
  • Imagine the following scenario: site locale is en_US, user locale is not set yet.
    1. Change user locale to es_ES. Expected: backend is in es_ES. Actual: backend is in es_ES, frontend is in es_ES and us_US. Pretty weird, see https://cloudup.com/c7ZU9Ov2ECl for a screenshot.
    2. Go to Settings -> General. Expected: site locale is shown as en_US. Actual: es_ES is selected.
    3. Change site locale to nl_NL. Expected: backend is still es_ES. Actual: The success admin notice is in nl_NL, the rest is in es_ES. Frontend is still mixed nl_NL and es_ES.

#42 in reply to: ↑ 41 @ocean90
7 months ago

Replying to swissspidy:

  • Should {$locale}.php be loaded for both locales?

To answer this question we should take a look at existing {$locale}.php files:

Our long-term goal is to get rid of all the locale files, either by moving the code into core or a plugin. I think we shouldn't change the existing loading behaviour and load only a locale file for the site language.


  • Imagine the following scenario: site locale is en_US, user locale is not set yet.
    1. Change user locale to es_ES. Expected: backend is in es_ES. Actual: backend is in es_ES, frontend is in es_ES and us_US. Pretty weird, see https://cloudup.com/c7ZU9Ov2ECl for a screenshot.
    2. Go to Settings -> General. Expected: site locale is shown as en_US. Actual: es_ES is selected.
    3. Change site locale to nl_NL. Expected: backend is still es_ES. Actual: The success admin notice is in nl_NL, the rest is in es_ES. Frontend is still mixed nl_NL and es_ES.
  1. That's because in your latest patch wp-settings.php still contains $locale = get_user_locale(). $locale should always hold the site language so it needs to be $locale = get_locale(). Based on my answer for the locale.php I think we can leave wp-settings.php as it is.
  2. See 1.
  3. That's caused by these lines to fix #29281.

@ocean90
7 months ago

Reverts changes to wp-settings.php

@ocean90
7 months ago

Includes changes to wp-admin/options.php

#43 @ocean90
7 months ago

  • Keywords needs-refresh removed

@swissspidy 29783.5.diff should fix the three issues.

This ticket was mentioned in Slack in #core by swissspidy. View the logs.


7 months ago

@swissspidy
7 months ago

#45 @swissspidy
7 months ago

In 29783.6.diff:

  • Add some more tests, especially for multisite
  • Change $locale to $user_locale in wp-admin/user-edit.php because it would override the global $locale. That way, when no user locale is chosen, the site locale is properly selected as the default (instead of being false).

We're almost there. One misbehaviour I noticed is that post type labels aren't properly translated because they are set before the user locale is loaded. In fact, create_initial_post_types() is called before wp_get_current_user() is even defined. See #26511 for a discussion about translating post type labels.

#46 @swissspidy
7 months ago

  • Keywords commit added

Turns out the post type labels are not translated because the context of these strings changed and translations aren't updated yet. So it only really affects #26511 — where there can be multiple locales on 1 page — but not this ticket. Thus, I feel like this one is good to go.

#47 @swissspidy
7 months ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 38705:

I18N: Introduce a user-specific language setting.

By enabling the user to select their preferred locale when editing the profile, we allow for greater personalization of the WordPress admin and therefore a better user experience.

The back end will be displayed in the user's individual locale while the locale used on the front end equals the one set for the whole site. If the user didn't specify a locale, the site's locale will be used as a fallback. The new locale property of the WP_User class can be used to retrieve the user's locale setting.

Props ocean90, ipm-frommen, swissspidy.
Fixes #29783.

#48 @ocean90
7 months ago

  • Keywords needs-dev-note added

The commit message doesn't mention the new get_user_locale() function. That's something we have to inform developers about.

#49 @swissspidy
7 months ago

Ugh, totally missed to mention the function in the commit… Wanted to write a dev note anyway though.

#50 follow-up: @pento
7 months ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

load_default_textdomain () is called from wp-settings.php, it calls get_user_locale(), which includes a call to wp_get_current_user(). In the past, this hasn't been called before init, the Customizer's theme preview being the notable exception.

This behaviour causes bbPress to throw a notice, see #24169, #BB2309.

/cc @johnjamesjacoby for bbPress perspective.

#51 in reply to: ↑ 50 @netweb
7 months ago

Replying to pento:

load_default_textdomain () is called from wp-settings.php, it calls get_user_locale(), which includes a call to wp_get_current_user(). In the past, this hasn't been called before init, the Customizer's theme preview being the notable exception.

This behaviour causes bbPress to throw a notice, see #24169, #BB2309.

/cc @johnjamesjacoby for bbPress perspective.

See also #23016 and https://codex.bbpress.org/bbp_setup_current_user/was-called-incorrectly/

Last edited 7 months ago by netweb (previous) (diff)

#52 @ocean90
7 months ago

I mentioned this already 15 months ago in ticket:24169:17. I don't see the notice as a blocker for this feature. If #23016 is required to make bbPress/BuddyPress working correctly then we should focus on this ticket.

#53 @pento
7 months ago

Agreed, the bbPress notice isn't a blocker.

We should aim to resolve it before 4.7 is released, though. Avoidable notices aren't a good look, regardless of the reason. :-)

I'm fine with #23016 and #BB2452 being the focus for getting this fixed.

#54 @pento
7 months ago

  • Resolution set to fixed
  • Status changed from reopened to closed

This ticket was mentioned in Slack in #core by swissspidy. View the logs.


7 months ago

#56 @ocean90
6 months ago

In 38955:

I18N: Add $user_id argument to get_user_locale().

This allows to retrieve the locale of any user with the additional fallback to the site locale.

Fixes #38512.
See #29783, #26511.

#57 @ocean90
6 months ago

In 38961:

I18N: Introduce a locale-switching function.

With the introduction of user-specific languages in [38705] it's necessary to be able to switch translations on the fly. For example emails should be sent in the language of the recipient and not the one of the current user.

This introduces a new WP_Locale_Switcher class which is used for switching locales and translations. It holds the stack of locales whenever switch_to_locale( $locale ) is called. With restore_previous_locale() you can restore the previous locale. restore_current_locale() empties the stack and sets the locale back to the initial value.

switch_to_locale() is added to most of core's email functions, either with the value of get_locale() (site language) or get_user_locale() (user language with fallback to site language).

Props yoavf, tfrommen, swissspidy, pbearne, ocean90.
See #29783.
Fixes #26511.

This ticket was mentioned in Slack in #core-i18n by swissspidy. View the logs.


6 months ago

#59 @danielbachhuber
6 months ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

This causes a fatal when WordPress can't connect to the database:

PHP   7. require_wp_db() /tmp/wp-cli-test-run-581135addf76f9.69107318/wp-settings.php:102
PHP   8. wpdb->__construct() /tmp/wp-cli-test-run-581135addf76f9.69107318/wp-includes/load.php:403
PHP   9. wpdb->db_connect() /tmp/wp-cli-test-run-581135addf76f9.69107318/wp-includes/wp-db.php:658
PHP  10. wpdb->select() /tmp/wp-cli-test-run-581135addf76f9.69107318/wp-includes/wp-db.php:1615
PHP  11. wp_load_translations_early() /tmp/wp-cli-test-run-581135addf76f9.69107318/wp-includes/wp-db.php:1098
PHP  12. WP_Locale_Switcher->__construct() /tmp/wp-cli-test-run-581135addf76f9.69107318/wp-includes/load.php:920
PHP  13. get_locale() /tmp/wp-cli-test-run-581135addf76f9.69107318/wp-includes/class-wp-locale-switcher.php:51
PHP  14. get_option() /tmp/wp-cli-test-run-581135addf76f9.69107318/wp-includes/l10n.php:64

get_locale() / get_option() needs some form of fallback when $wpdb isn't initialized.

Discovered in https://travis-ci.org/wp-cli/wp-cli/jobs/170935443

@pento
6 months ago

#60 @pento
6 months ago

  • Keywords needs-testing added; commit removed

29783.patch adds fallbacks to get_locale() when $wpdb isn't ready yet.

@danielbachhuber - could you confirm that this works for you?

#61 @danielbachhuber
6 months ago

@pento Confirmed that I see "Error establishing a database connection" with 29783.7.diff applied and DB_HOST=localghost. Without 29783.7.diff applied I see:

PHP Fatal error:  Call to undefined function wp_cache_get() in /srv/www/wordpress-develop.dev/src/wp-includes/option.php on line 64

#62 @pento
6 months ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In 38976:

I18N: Fix a PHP fatal when get_locale() is called before $wpdb is ready.

If WPDB needs to bail early, it loads the translations, which need to load the locale. Without WPDB, we can't get any database options, so can only rely on what's been loaded so far.

Fixes #29783.

#63 @swissspidy
6 months ago

@pento Shouldn't the locale filter be applied in [38976]?

#64 @pento
6 months ago

  • Keywords has-patch has-unit-tests needs-testing removed
  • Resolution fixed deleted
  • Status changed from closed to reopened

Yes. Can you take care of that, please?

#65 @swissspidy
6 months ago

In 38978:

I18N: Apply the locale filter when returning early in get_locale().

See [38976].
See #29783.

#66 @swissspidy
6 months ago

  • Resolution set to fixed
  • Status changed from reopened to closed

This ticket was mentioned in Slack in #core-i18n by swissspidy. View the logs.


6 months ago

#68 @geminorum
6 months ago

why not a default option with fallback to the current blog locale? (and not to mention extra load of unnecessary user meta rows in the db in large sites.)

#69 @ocean90
6 months ago

In 39005:

I18N: Don't initialize WP_Locale_Switcher in wp_load_translations_early().

wp_load_translations_early() is used when WordPress isn't fully initialized. Therefore using the WP_Locale_Switcher with get_locale()/get_user_locale() can cause PHP fatal errors.
This reverts [38976] and [38977], and instead removes WP_Locale_Switcher from wp_load_translations_early().

See #29783.
Fixes #38535.

#70 @johnjamesjacoby
6 months ago

A few things I see that need fixing:

  • When editing a user profile, the label is for site_language but the select name is locale. I recommend keeping locale -- I think site_language is copy-pasta from the site setting.
  • The profile code uses get_user_option( 'locale', $profileuser->ID ) instead of the get_user_locale() function. Why can a user set a per-site language, but wp_insert_user() sets locale using update_user_meta()?
  • Also, _get_additional_user_keys() includes locale as a global piece of meta, not as a per-site option.

I'll include patches with recommended fixes.

@johnjamesjacoby
6 months ago

Update label for value to locale instead of site_language

#71 follow-up: @ocean90
6 months ago

@johnjamesjacoby Please create new tickets for new issues. Thank you.

@johnjamesjacoby
6 months ago

Use $profileuser->locale instead of get_user_option( 'locale', $profileuser->ID ); when editing a user

#72 in reply to: ↑ 71 @johnjamesjacoby
6 months ago

Replying to ocean90:

@johnjamesjacoby Please create new tickets for new issues. Thank you.

OK. This ticket was opened & closed 4 times previously, so the precedence was set to continue fixes here.

#73 @ocean90
6 months ago

In 39122:

I18N: Show "Settings saved." in the correct language after switching the site language.

This simplifies the logic by comparing get_user_locale() before and after an settings update.

Props swissspidy, ocean90.
See #29783, #29281.
Fixes #38482.

#74 @swissspidy
6 months ago

In 39169:

I18N: Add ability to change user's locale back to site's locale.

Previously there was no way to remove the user locale setting again, even though that might be desirable.

This adds a new 'Site Default' option to the user-specific language setting by introducing a new show_site_locale_default argument to wp_dropdown_languages().

Props ocean90.
See #29783.
Fixes #38632.

#75 @ocean90
5 months ago

In 39269:

Users: In edit_user() fall back to site's locale instead of en_US for invalid user locales.

See #38632, #29783.
Fixes #38798.

#76 @swissspidy
3 weeks ago

In 40368:

Customize: User get_user_locale() in customizer body class.

Otherwise CSS specific to the site's locale would be applied, even though the customizer is displayed in the user's locale.

See #29783.
Fixes #40271.

#77 @swissspidy
3 weeks ago

In 40369:

Customize: Use get_user_locale() in customizer body class.

Otherwise CSS specific to the site's locale would be applied, even though the customizer is displayed in the user's locale.

See #29783.
Fixes #40271.

Merges [40368] to the 4.7 branch.

Note: See TracTickets for help on using tickets.