Currently in the localization systems we are missing the support for managing more than one language on a single page request. This is needed for:
- Modules that produce email need to localize that emails for each user's language, not for the page request language. These emails are usually triggered on cron.
- When an administrator creates/approves an user account and the user gets a notification it is currently in the administrator's language. It should be in the user's language.
- When a user registers and the administrator is notified, the email is currently in the language the user has used for registering, that the administrator may understand or not...
This patch has several parts.
- It adds the ability to translate into several languages in the same page request to locale module and a 'locale_switch_language' function that will temporarily change the current language, while it stores the original one to reset it later
- Adds a 'user_context' function to user module, which will be the one to switch language and maybe other settings for a specific user. This is meant to be a simple api function in user module. To switch language back and forth for an user account, the code would look like
user_context($account); // Will switch language to user account
// operations here
// ........
user_context() // Will reset the language to the original one in the request
Hope I've been able to explain right this language mess.. :-)
There are some tricky issues in this patch, like switching global variables, and this 'context' hook that needs to be documented also. But this is just a starting point. There's been some talk in the past about global variables, user variables, etc... This new hook operation at least would allow modules to switch global settings -in the $conf array- on a per user basis, which is something to start with.
Also, I've implemented the whole thing to show the complete picture, but I could post some smaller patch just for the locale module.
Comment | File | Size | Author |
---|---|---|---|
#10 | locale_multilingual_requests_02.patch | 5.95 KB | Jose Reyero |
#5 | locale_multilingual_requests_01.patch | 6.17 KB | Jose Reyero |
locale_multilingual_requests.patch | 7.83 KB | Jose Reyero | |
Comments
Comment #1
Gábor HojtsyHave you looked into somehow passing on the required language instead (which is only what we need to know there)? Having a global environment switching around sounds rather dangerous. If you have other parts of code, or overlapping reused strings, you get mixed language output. Like in your patch when user #1 gets a mail, he gets the $subject set previously, so it will be in some other language then what t() will produce there.
Comment #2
Jose Reyero CreditAttribution: Jose Reyero commentedGabor
Yes, but then you need the modules using it to mess with languages, like checking language for the user, then switching to default language if the user doesn't have one. This way we isolate everything into locale module and this looked to me like the simpler api to do it, just 'user_context()'....
Also, just a possibility, other modules may use language for some query rewriting.
Well, we just switch global language in core for now. We are just allowing that possibility for other modules to play.
Also, the url rewriting code will need to know about language to get the work done.
That we should avoid. That subject setting needs to be moved after the 'user_context()'.
However, the option of just adding a language argument to locale also makes sense. I just think this is a more powerful option but also, I agree with you, somehow more risky.
Comment #3
moshe weitzman CreditAttribution: moshe weitzman commentedsuscribe
Comment #4
Gábor HojtsyOK, I put some more though to this yesterday. As we are really only dealing with emails here, what about introducing a user_mail() function which would get a user object to send email to and some kind of parameters to indicate what to send in the email. I mean maybe we can separate this language swtching into one function for this purpose, where we might as well be able to pass on the required language. So the outer code will not need to deal with the language at all.
Comment #5
Jose Reyero CreditAttribution: Jose Reyero commentedOk Gabor, sure we can find some other solution.
In the meanwhile, here's a patch, only for locale module and 't()' function to support multilingual requests. It just adds a language parameter to 't' and 'locale' functions. Nothing here about user emails or global language switching.
I think this functionality alone makes sense, as in the worst case it will allow contributed modules to workout some solution for emailing users in different languages while still being able to use the localization system.
Btw, in the previous patch slipped some php file intended just for testing (/languageswitch.php). Here's the code for testing this new patch. Copy and paste it into a php file in the root folder and run it.
Comment #6
Gábor HojtsyWell, this gets much more reasonable. :) I have two remarks:
- What about having a $langcode parameter instead of passing on a full fledged $t_language? The $user only has a langcode anyway. That would simplify the code greatly, so you would not need to reference $t_language->language at every places.
- Use isset() when checking for whether the parameter was passed, not simply the value itself, so we are E_ALL compatible.
Comment #7
Gábor HojtsyHm, db_set_active() might be an interesting prior practice to look at too. Hm... Maybe we can get some independent reviewers (Moshe, Dries, Steven?) to help decide whether such global environment switches are good. I would not say I like db_set_active() either, but it is definitely in Drupal, so a language_set_active() might as well be possible after all. Hm... We should think about it. (I am not decided yet).
Comment #8
Gábor HojtsyBTW I would envision language_set_active() to be much simpler then the user_context stuff, just switching between one language to another (from among the list of defined languages).
Comment #9
Dries CreditAttribution: Dries commentedThe db_set_active() function has always been a pain. We've had other issues with global swithces (i.e. the global $user object getting switched). So, I'd prefer not to use a global switch, but to pass a language parameter to drupal_mail().
Comment #10
Jose Reyero CreditAttribution: Jose Reyero commentedReworked the patch to use $langcode parameter instead of $language object
Gabor, as long as we have a default value for the parameter (NULL), it should be ok about E_ALL notices
We can work on the user emails in a different patch.
Comment #11
Jose Reyero CreditAttribution: Jose Reyero commentedPlease, see also #82499 which is the related patch for user emails, relying on this one
Comment #12
Gábor HojtsyOK, updated the patch:
- Documentation still said $t_language, not $langcode.
- As far as I know, we use isset($value) for $value = NULL parameters, so used that
Applied the patch to my testing environment, and because I have some Czech translations around, I quickly tested how it works. Turned PHP module on, created a block with this content:
return t('Home') . t('Home', 0, 'cs') . t('Nosuchstuff', 0, 'cs');
And checked whether it works. Well, it does, "Home" is translated, and Nosuchstuff gets into the DB. I also checked the cache refresh function, and it does refresh the cache for all languages, so it does not need modification.This is a simple and straightforward change, so committed it right away.
Comment #13
(not verified) CreditAttribution: commented