Updated: Comment #N

Problem/Motivation

hook_init() is too late to switch language, a lot of language processing already happened. This causes a lot of undesirable side effects when the module is enabled.

Proposed resolution

Use hook_language_negotiation_info() to ensure the language switch is actually done in the appropriate bootstrap level
The idea of using hook_language_negotiation_info() didn't take in account that there are language negotiation providers which make quite some runtime environment changes (e.g. the url language negotiation provider changes $_GET['q']) and this would be difficult to clone within our own language negotiation provider.
However, there's the hook hook_language_init() that runs right after the language negotiation and on the same bootstrap level.
This should work as intended without interfering to much with the language negotiation itself.

Attention: The patch in #8 incorporates the idea of #2022269: Use the core function path_get_admin_paths() to "dynamically" detect administrative paths - in case of anger about that please bash das-peter for mixing up two features ;).

Remaining tasks

Reviews needed.

User interface changes

Additional configuration setting.

API changes

None.

Original report by @HnLn

We started using this module but then decided to drop it since some pages were still rendered in the default language (or parts of the interface, most notably the ajax parts of views and panels). Main reason for this is that hook_init is too late to switch language, a lot of language processing already happened.

We created out own module using hook_language_negotiation_info and creating our own language detector and placing that first. This gives much better results and also ensured that drush commands are also executed in english.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

stBorchert’s picture

Any chance you can provided this as a patch?

kmajzlik’s picture

Hi, no patch here at this time (i believe i will attach it later today or tomorrow), just a small workaround:

1) add function admin_language_language_negotiation_info()
2) change your hook_init() into language callback function defined in step 1. No changing of global $language is done here (we much more before it is set), just return $admin_language if needed.

Activating of language callback and setting to top is needed at: admin/config/regional/language/configure

I think this is ONLY one 100% working solution, hook_init is not correct for this use in Drupal 7.

https://drupal.org/node/874760#comment-7872837

kmajzlik’s picture

My first try for post patch ever :)
Bad one

kmajzlik’s picture

Category: feature » bug
Status: Active » Needs review
FileSize
3.75 KB

Second try.

HnLn’s picture

FYI, this is the language provider callback code I use in our custom admin_language module

function admin_language_language_provider_callback($languages) {

  $path = $_GET['q'];

  //we are early in the bootstrap process and language prefixes aren't removed yet

  drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES, FALSE);
  require_once DRUPAL_ROOT . '/includes/path.inc';

  $negotiation = variable_get('language_negotiation_language');

  if (in_array('locale-url', array_keys($negotiation))) {

    $languages = language_list('enabled');
    $languages = $languages[1];

    $split = language_url_split_prefix($path, $languages);
    if ($split[0]) {
      $path = $split[1];
    }

  }

  //getting our paths
  $paths = variable_get('dmin_language_paths', ADMIN_LANGUAGE_DEFAULT_PAGES);

  if ((drupal_match_path($path, $paths) && user_access('admin language')) || drupal_is_cli()) {
    return 'en';
  }

}

And these are the paths used (note it's not just admin/... but also a lot of ajax paths for ctools, panels and ajax)

define('ADMIN_LANGUAGE_DEFAULT_PAGES', "admin\nadmin/*\nadmin_menu\nadmin_menu/*\nsystem/ajax\nsystem/ajax/*\nfile/ajax\nfile/ajax/*\nctools/ajax\nctools/ajax/*\nctools/context/ajax\nctools/context/ajax/*\npanels/ajax\npanels/ajax/*\nviews/ajax\nviews/ajax/*\nfeatures\nfeatures/*\nbatch");
kmajzlik’s picture

ok, i think that with drupal_is_cli() added to my patch can be drush solved.. please can somebody test patch?

maybe i will change there

require_once DRUPAL_ROOT . '/includes/path.inc';

for use of standard drupal_match_path($path, $paths)

killua99’s picture

Subscriber (old way)

das-peter’s picture

Title: hook_language_negotiation_info gives better results » Use hook_language_init() for more reliable language switch.
Issue summary: View changes
Related issues: +#2022269: Use the core function path_get_admin_paths() to "dynamically" detect administrative paths
FileSize
9.49 KB

I gave this patch a shot but I wasn't to happy, there where issues when the url language negotiation provider was enabled.
Thus I've changed the approach to use hook_language_init() instead.
This hook is fired right after the language negotiation and on the same bootstrap level. I think this should work as intended without interfering to much with the language negotiation itself.
Further I've incorporated the idea of #2022269: Use the core function path_get_admin_paths() to "dynamically" detect administrative paths into the patch - I know mixing two features might be to much but I was just "in the flow" :).
If there's really the need for two patches I'll split that up, but please give it a shot first ;)

das-peter’s picture

I just found an issue with the current patch.
user_access() isn't available at that point in the bootstrap. For me it worked because I've enabled the devel module which explicitly loads the user module - see: http://drupalcode.org/project/devel.git/blob/0bf83029239dfac6f75152d83f4...
I've added the same code now into the language module - I don't see another way how we can maintain the feature of providing a dedicated permission to change the administrative language.

wulff’s picture

Status: Needs review » Fixed

I have applied your latest patch and create a beta release. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.