Hi,

I enabled 3 languages on my site. When I use the views module "i18n: Content negotiation" I do not get what I expect when using "Mixed current language" in the Administer / Site configuration / Languages / Languages
If I set it to Only current language for example, it does work and I only see current language. When I use the mixed "Mixed current language" option, I see the current language + default language also if a current language translation exists. I should only see the current language in that case.

I'm not sure this is a views problem or a problem of this module.

Comments

JGO’s picture

Not anyone who can help me with this ?

----------------------------
JGO | http://www.e2s.be
----------------------------

keon’s picture

I can not help - i don't get that far even (error while adding the filter),
but it would be great if it does work like you say,
then maybe we can avoid having to clone each view for the extra languages !

keon’s picture

making the view again helped me to get rid of the error i had earlier, now it works as you discribed,
but correctly, only 1 item is shown: handy, now just make the menu-item in the 3 languages pointing to the same path ...

succes!

JGO’s picture

I still have the problem:

This is the query it builds in my case (which looks clearly wrong):

When set to site default language (probably ok)

SELECT node.nid AS nid
FROM node node
LEFT JOIN term_node term_node ON node.vid = term_node.vid
LEFT JOIN term_data term_data ON term_node.tid = term_data.tid
WHERE (term_data.vid in ('8'))
AND (node.language ='en' OR node.language ='' OR node.language IS NULL)

When set to nl seems wrong:

SELECT node.nid AS nid
FROM node node
LEFT JOIN term_node term_node ON node.vid = term_node.vid
LEFT JOIN term_data term_data ON term_node.tid = term_data.tid
WHERE (term_data.vid in ('8'))
AND (node.language ='nl' OR node.language ='en' OR node.language ='' OR node.language IS NULL)

It should be only showing the en if there is no node found in the current language

EDIT:

A quick (but prolly dirty fix) is modifying the following inside i18n.module

function i18n_db_rewrite_where($alias, $type, $mode = NULL) {
  if (!$mode) {
    // Some exceptions for query rewrites.
    $mode = i18n_selection_mode();
  }

  // Get languages to simplify query building.
  $current = i18n_get_lang();
  $default = i18n_default_language();

  if ($mode == 'strict' && $type != 'node') {
    // Special case. Selection mode is 'strict' but this should be only for node queries.
    $mode = 'simple';
  }
  elseif ($mode == 'mixed' && $current == $default) {
    // If mode is mixed but current = default, is the same as 'simple'.
    $mode = 'simple';
  }

  switch ($mode) {
    case 'off':
      return '';

    case 'simple':
      return "$alias.language ='$current' OR $alias.language ='' OR $alias.language IS NULL" ;

    case 'mixed':
//==> Modification here: if it's node, do some extra stuff
	if($type == 'node')
	  return "$alias.language ='$current' or (($alias.language ='$default' OR $alias.language ='' OR $alias.language IS NULL) AND NOT exists(select * from $alias sub where $alias.tnid = sub.tnid and sub.language = '$current') )";
	else
	  return "$alias.language ='$current' OR $alias.language ='$default' OR $alias.language ='' OR $alias.language IS NULL" ;
//==> END MOD
    case 'strict':
      return "$alias.language ='$current'" ;

    case 'node':
    case 'translation':
      return "$alias.language ='". i18n_selection_mode('params') ."' OR $alias.language ='' OR $alias.language IS NULL" ;

    case 'default':
      return "$alias.language ='$default' OR $alias.language ='' OR $alias.language IS NULL" ;

    case 'custom':
      return str_replace('%alias', $alias, i18n_selection_mode('params'));
  }
}

The problem is actually that the vocabulary is a localizable one in the site's default language (en)
So it finds also nodes associated with it in other languages.

So a node can be translated and being related to the same vocabulary.

----------------------------
JGO | http://www.e2s.be
----------------------------

cels’s picture

This issue is a logic/config problem with all the i18n system.

The best would a option check for control the logic:
A) Do you display ALL the languages of the nodes?
b) Do you display the current language if the node have the translated version?

If not, the i18n_db_rewrite_where should be changed with the **correct** behavior (don't mix the node's translates).

Related:
multilingual views like i18n's "Mixed current language (if available) or default language (if not) and language neutral."
#337089: Mixed mode ultra slow on large db

hiwilson’s picture

I have the same problem as JGO and I implement his code. However, if there is a node with current language only, then all language neutral item will disappear. I rearrange JGO's code to solve this problem.

from:

return "$alias.language ='$current' or (($alias.language ='$default' OR $alias.language ='' OR $alias.language IS NULL) AND NOT exists(select * from $alias sub where $alias.tnid = sub.tnid and sub.language = '$current') )";

to:

return "$alias.language ='$current' OR (($alias.language ='$default') AND NOT exists(select * from $alias sub where $alias.tnid = sub.tnid and sub.language = '$current') ) OR $alias.language ='' OR $alias.language IS NULL";

gedvan’s picture

Both codes above do not support table prefixes. I rewrote JGO and hiwilson's code to:

    case 'mixed':
      if($type == 'node') {
        $subquery = db_prefix_tables("select * from {{$alias}} sub where $alias.tnid = sub.tnid and sub.language = '$current'");
        return "$alias.language ='$current' OR (($alias.language ='$default') AND NOT exists($subquery) ) OR $alias.language ='' OR $alias.language IS NULL";
      }
      else
        return "$alias.language ='$current' OR $alias.language ='$default' OR $alias.language ='' OR $alias.language IS NULL" ;

Works for me.

* Sorry my english...

JGO’s picture

There was another bug, changed the code to:

<?php
    case 'mixed':
    if($type == 'node') {
        $subquery = db_prefix_tables("select * from {{$alias}} sub WHERE $alias.tnid = sub.tnid AND sub.language = '$current' AND $alias.tnid <> 0");
        return "$alias.language ='$current' OR (($alias.language ='$default') AND NOT exists($subquery) ) OR $alias.language ='' OR $alias.language IS NULL";
    }
    else
        return "$alias.language ='$current' OR $alias.language ='$default' OR $alias.language ='' OR $alias.language IS NULL" ;
?>
 

I added AND $alias.tnid <> 0
As long as there exist no translation at all, the tnid = 0. So the subclause would always return true if a node is created in another language but not translated.
Normally the nodes should always be first created in the main language, but better catch the case where it's created first in another language too!

----------------------------
JGO | http://www.e2s.be
----------------------------

Johnny vd Laar’s picture

wouldn't it be possible/faster to use the mysql "find_in_set" function and order on that and then group by tnid?
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_fi...

then all you need to do is make a prioritized ordering of the languages

abaddon’s picture

same as above, but i was having a problem with forums displaying both default and current language on /forum
i dont understand the {{$alias}} notation, for me $alias was "t", it failed but the below worked, im using prefixed tables too

<     if($type == 'taxonomy') {
<         $subquery = db_prefix_tables("select * from {term_data} sub WHERE $alias.trid = sub.trid AND sub.language = '$current' AND $alias.trid <> 0");
<         return "$alias.language ='$current' OR (($alias.language ='$default') AND NOT exists($subquery) ) OR $alias.language ='' OR $alias.language IS NULL";
<     }
<     else

might help someone..

(edit: some typos :-)

JGO’s picture

Yep I hope someone will implement this properly soon.
This should have been working for long long time :|

----------------------------
JGO | http://www.e2s.be
----------------------------

Sylvain_G’s picture

subscribe

klonos’s picture

I do not see any 'i18n: Content negotiation' filter in my view. Some thing I am missing here?

views 6.x-3.x-dev (2010-Mar-26)
i18n 6.x-1.x-dev (2010-Apr-01)

Sylvain_G’s picture

It as moved to node:Content negociation

klonos’s picture

...actually it is in 'Node translation: Content negotiation' but thanx for the heads-up.

To get what I was looking for to work, I used the viewfield module to 'embed' my views in nodes and then used translation.

Jose Reyero’s picture

Project: Internationalization » Internationalization Views
Version: 6.x-1.2 » 6.x-2.x-dev
kasiawaka’s picture

I want to confirm that the solution presented in #8 works on Drupal 6.15 with Views 6.x-2.10 and i18n 6.x-1.5

To capture all the information in one place:

Goal

Use views to display the multi-lingual content as per website Language settings (admin/settings/language/i18n) that are set to

Content selection mode: Mixed current language (if available) or default language (if not) and language neutral

In my example, I have English and French content. English is a default language. Not all the content is translated to French so Views should display the content the user selected language but if any node is not available in that language, show the content in the default language (in this case English).

Problem

Internalization (i18n) module has Views filter "i18n: Content negotiation" that is suppose to "Removes the nodes that are not valid according to the content selection mode".
Unfortunately, this is not working correctly because when viewing the page in French, both French and English nodes were displayed although there were a translation of each other and only French nodes should be visible because they existed.

Solution

Thanks to the posters in this thread, the solution is: modify the file i18n.module (i18n module root directory) by modifying the function i18n_db_rewrite_where

Replace

   case 'mixed':
      return "$alias.language ='$current' OR $alias.language ='$default' OR $alias.language ='' OR $alias.language IS NULL" ;

with

    case 'mixed':
    if($type == 'node') {
        $subquery = db_prefix_tables("select * from {{$alias}} sub WHERE $alias.tnid = sub.tnid AND sub.language = '$current' AND $alias.tnid <> 0");
        return "$alias.language ='$current' OR (($alias.language ='$default') AND NOT exists($subquery) ) OR $alias.language ='' OR $alias.language IS NULL";
    }
    else
        return "$alias.language ='$current' OR $alias.language ='$default' OR $alias.language ='' OR $alias.language IS NULL" ;
JGO’s picture

Indeed, if now somebody implements it properly into the module that would be great!

kirie’s picture

I've also tested the summary given in #17 and works well so far. Should we move this issue over to the i18n queue - as that is module being patched?

Danny Englander’s picture

Subscribing

kasiawaka’s picture

Using the solution from #17 (thanks to all previous contributors), I've created a patch for i18n module: http://drupal.org/node/887116
Please test it and post comments that the i18n thread, where the patch was supplied.

YK85’s picture

I was wondering if there may have been further development? Thank you

miro_dietiker’s picture

Recheck
#887116: Views filter "i18n: Content negotiation" is not working properly for "Mixed current language (if available) or default lang ..."

And report current state. As Jose said, in D6 is a huge risk of regressions and we should try to address it in D7 as early as possible.