This is related to the core issue #1499532: Cannot programmatically specify node path alias language. The current code added in #1155132: Add Entity Translation support to Pathauto auto detects the language of the path based on the entity, preventing a programmatic setting of the language. I think Pathauto should respect $entity->path['language'] if it is present. Thoughts?

#2 pathauto-2030983-respect-entity-path-language-2.patch1016 bytesq0rban
PASSED: [[SimpleTest]]: [MySQL] 322 pass(es). View


Dave Reid’s picture

Using $entity->path['language'] present first, then falling back to entity_language() seems reasonable.

q0rban’s picture

Status: Active » Needs review
1016 bytes
PASSED: [[SimpleTest]]: [MySQL] 322 pass(es). View

Attached patch fixes the issue for me.

pablojais’s picture

I'm not entirely sure why this happens, but applying this patch to the stable version causes a side effect. I have a node with, say,

  [title] => basic title
  [nid] => 21
  [language] => es
  [title_field] => Array (
    [en] => Array ([0] => Array ([value] => english title, ...), ...)
    [es] => Array ([0] => Array ([value] => spanish title, ...), ...)

and autogenerated aliases (en/english-title and es/spanish-title). However, when I run this script:

  $node = node_load(21);
  $node->title_field[en][0] = "new english title";
  $node->path['pathauto'] = TRUE;
  $node->path['language'] = 'it';

I get

  [title] => new english title
  [nid] => 21
  [language] => es
  [title_field] => Array (
    [en] => Array ([0] => Array ([value] => new english title, ...), ...)
    [es] => Array ([0] => Array ([value] => new english title, ...), ...)
aliases: en/new-english-title and es/spanish-title

I noticed that this happened when the replacement pattern was [node:title] but not when it's [node:title_field]. Of course I should use the second one, but I don't think this should happen anyway. I managed to track down the issue up to the $alias = token_replace($pattern, $data, ...); in line 359 of the stable version. The titles change somewhere during that call. I know it's not a lot of info, but I can't test this in the dev version right now.


PedroMiguel’s picture

Issue summary: View changes

q0rban patch works well for me, thanks, all my translated paths are created.

kpyan8s’s picture

The path may apply by running:

curl -sL | patch -p1
kopeboy’s picture

Should I use this other patch together with this to have the pathauto patterns work with all languages (when using Entity Translation?

Or this is just a non-required add-on to that patch?

Dave Reid’s picture

Issue tags: +Needs tests
Dave Reid’s picture

Dave Reid’s picture

joelpittet’s picture

I've been using this and it seems to work for my needs.

Simon Georges’s picture

Status: Needs review » Reviewed & tested by the community

It seems several people have it working for their needs.

joseph.olstad’s picture

for us the patch above didn't help.
english / french generating /scripting node creates and translations, english ok path alias is there, french nothing.

We are programmatically /script creating nodes and adding entity translation translation using the entity entity_metadata_wrapper . What we found in our D7 setup is that after saving the source language node (calling the entity_metadata_wrapper save function) pathauto_state was changed or removed for that node, however a path auto was automatically generated for english. What our issue was is that we found that there was no french auto generated alias, and the pathauto_state was deleted for the entity_id (same id for french and english as its one node, field translation/entity translation).

So , right after the entity_metadata_wrapper save() for english, we insert the pathauto_state

  $video = entity_create('node', array('type' => 'video'));
  $video->uid = 1;
  $w_video = entity_metadata_wrapper('node', $video);
  $w_video->status->set(1);  // published
  $w_video->promote->set(0); // not promoted to front page
  $w_video->body->set(array('value' => $vid['desc_en'] . "\n\n" . $sample_en));
  $w_video->save();//saves english version with a automatically generated path alias as we expect

//at this point, for some reason, pathauto_state is missing

  db_insert('pathauto_state') // Table name no longer needs {}
      'entity_type' => 'node',
      'entity_id' => $video->nid,
      'pathauto' => 1,

//call the custom function shown at the bottom of this comment
_mymodule_createUrlAlias('node/' . $video->nid, $alias, 'fr');

Then we create the translation of the english.

  $handler = entity_translation_get_handler('node', $video);

  // Configuration about what to translate
  $translation = array(
    'translate' => 0,
    'status' => 1,
    'language' => 'fr',
    'source' => 'en',


  $w_video->body->set(array('value' => $vid['desc_fr'] . "\n\n" . $sample_fr));

function _mymodule_createUrlAlias($source, $alias, $language) {
  $alias = str_replace(' ', '-', $alias );//replace spaces with dashes
  $alias = strtolower($alias);
  $search = array('/é/', '/ç/', '/à/', '/ö/', '/ò/', '/è/', '/ù/', '/ú/', '/’/');
  $replace = array('e', 'c', 'a', 'o', 'o', 'e', 'u', 'u', '');
  $alias = preg_replace($search, $replace, $alias);
  //accents must be removed because w3c is tightly controlled by the english language police
  $alias = 'video/' . $alias;

  $sql = "SELECT * from {url_alias} as ua where ua.source like '" . $source . "' and ua.language like '" . $language . "'";

  $result = db_query($sql);
  $count = 0;
  foreach ($result as $row) {

  if ($count >= 1) {
    drupal_set_message('success: url-alias for ' . $language . ' ' . $alias . ' is already found, good job', 'status', TRUE);

  if ($count == 0) {
    $pid = db_insert('url_alias')
        'source' => $source,
        'alias' => $alias,
        'language' => $language,
    $result = db_query($sql);

    foreach ($result as $row) {
      drupal_set_message("success: added url_alias for source: $source to alias: $alias of pid: $pid", 'status', TRUE);

after all this, the path alias gets created for french and the pathauto_state is set for this entity.

Not sure why this is, however, after much tests of various patches , the easiest way was the brute force way.