In a module I developed, I need to change $user->language for those users who don't have the "change own user language" permission, a permission the module itself defines. The module is actually doing two things:

  • Hiding the language selector in the user edit form for those users who don't have the permission to set a language by setting its #access property to FALSE
  • Loading the default language for those users

The first part works. For the second part, I was first using hook_user_load() but due to the following warning shown in the documentation page, I changed the code to use hook_init().

Due to the static cache in user_load_multiple() you should not use this hook to modify the user properties returned by the {users} table itself since this may result in unreliable results when loading from cache.

The problem is that with hook_init() I am not doing anything when a module loads a user object, sets that as current user, does something, and then changes back the global $user.
I know I could load the language in a custom property, but I should still need to change the $user->language property before Drupal or any module uses it.

How can I change a user object property that is loaded from the users table?

  • I don't know if it could be useful, but perhaps you should look at EntityAPI module.
    – arrubiu
    Commented Sep 11, 2013 at 9:11
  • hook_entity_load() doesn't have the same warning, maybe that's the way to go?
    – Clive
    Commented Sep 11, 2013 at 12:30
  • It seems the same problem would be present for that hook, since Drupal first load the user objects from the cache, then loads the the user objects left from the database, and invokes hook_entity_load() and hook_user_load() for those objects loaded from the cache. The problem is that: Objects retrieved from the cache are not passed to those hooks.
    – apaderno
    Commented Sep 11, 2013 at 19:50
  • I have forgotten to write an answer, but I found how to achieve what I wanted. I posted it today.
    – apaderno
    Commented Dec 20, 2021 at 17:22

1 Answer 1


To always be able to set the default language for the loaded accounts, I implemented hook_entity_info_alter() using the following code.

function mymodule_entity_info_alter(&$entity_info) {
  // Disable the static cache for users.
  if (!empty($entity_info['user']))
    $entity_info['user']['static cache'] = FALSE;

The alternative would be to implement hook_entity_info_alter() to change the language callback, which is used from entity_language(), a function introduced from Drupal 7.15 which uses the following code.

// Invoke the callback to get the language. If there is no callback, try to
// get it from a property of the entity, otherwise NULL.
if (isset($info['language callback']) && function_exists($info['language callback'])) {
  $langcode = $info['language callback']($entity_type, $entity);
elseif (!empty($info['entity keys']['language']) && isset($entity->{$info['entity keys']['language']})) {
  $langcode = $entity->{$info['entity keys']['language']};

For example, the following functions would achieve what I wanted. In this case, the code is specific for changing the language associated to the user account; to change from hook_user_load() any value Drupal loads from the users table, the first approach works for any value loaded from that database table.

function mymodule_entity_info_alter(&$entity_info) {
  // Add the language callback for users.
  if (!empty($entity_info['user']))
    $entity_info['user']['language callback'] = 'mymodule_user_language';

function mymodule_user_language($entity_type, $entity) {
  if ($entity_type == 'user' && !user_access('change own user language', $entity)) {
    $entity->language = language_default('language');

In both the cases, there could be a conflict between two modules implementing the same hook. In the first case, the conflict would create less disruption.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.