Hello,
I've seen the great work done by Leksat as part of this ticket: https://www.drupal.org/node/2322883
There is something that does not work as I was expecting with menu items though:
Here is my setup: I have 3 languages (en, fr, nl), the source language for i18n_string is EN, and here is how I configured fallbacks:
- EN: FR, NL
- FR: EN, NL
- NL: FR, EN
This seems to work great for entities.
But here is what does not work as I would expect:
I created a menu with the i18n option "Translate and Localize. Menu items with language will allow translations. Menu items without language will be localized".
I added a "Language neutral" menu entry to it so it is localized only (so it is available in EN only at this moment)
I then added a NL translation to it.
Here is what I get in the "translate" tab for this menu item:
LANGUAGE TITLE STATUS OPERATIONS
Dutch My item in NL translated translate
English (source) My item in EN original edit
French My item in NL fallback from Dutch translate
I was expecting the French version to fallback from English, not from Dutch.
I looked at the code in language_fallback.i18n.inc and my understanding is that language_fallback_i18n_string_textgroup_default->load_translation(...) looks for translation candidates in the locales_target database table only.
In my opinion this is wrong as it overlooks the source translation (English in our case) which causes my example above to fail.
When I patch this code so it looks in the locales_source table too, it works as expected and falls back to English, not to Dutch.
This said, I'm questioning my overall understanding of all the mechanics behind language_fallback and i18n_string, hence my question:
Am I missing something?
Here is how I recoded load_translation to test my theory, just for info:
public static function load_translation($i18nstring, $langcode) {
$chain = language_fallback_get_chain($langcode);
if (empty($chain)) {
return parent::load_translation($i18nstring, $langcode);
}
$langcodes = array_values(array_merge(array($langcode), $chain));
// Retrieve LID.
$lid = NULL;
if (empty($i18nstring->lid)) {
$query = db_select('i18n_string', 's');
$query->addField('s', 'lid');
$query->condition('s.textgroup', $i18nstring->textgroup);
$query->condition('s.context', $i18nstring->context);
$lid = $query->execute()->fetchField();
}
else {
$lid = $i18nstring->lid;
}
$translations = array();
$source_lang_code = variable_get('i18n_string_source_language', 'en');
// Get the source string.
$query = db_select('locales_source', 'l');
$query->fields('l', array('source'));
$query->condition('l.lid', $lid);
$source_lang_translation = $query->execute()->fetchAssoc();
if (!empty($source_lang_translation)) {
$translations[$source_lang_code] = (object) array(
'language' => $source_lang_code,
'translation' => $source_lang_translation['source'],
'i18n_status' => I18N_STRING_STATUS_CURRENT,
);
}
// Get all target translations.
$query = db_select('locales_target', 'l');
$query->fields('l', array('language', 'translation', 'i18n_status'));
$query->condition('l.lid', $lid);
// The i18n module can save empty strings as translations. In this case, it
// behaves as there is no translation and uses the original strings.
// Handle this case by simple excluding of empty translations.
$query->condition('l.translation', '', '<>');
$target_translations = $query->execute()->fetchAllAssoc('language', PDO::FETCH_ASSOC);
foreach ($target_translations as $target_lang_code => $target_translation) {
$translations[$target_lang_code] = (object) array(
'language' => $target_lang_code,
'translation' => $target_translation['translation'],
'i18n_status' => $target_translation['i18n_status'],
);
}
// Seek best candidate and return it.
foreach ($langcodes as $langcode) {
if (isset($translations[$langcode])) {
return $translations[$langcode];
}
}
// No match found, fail.
return NULL;
}
Disclaimer: If the issue is confirmed, this piece of code is not enough to fully fix the issue (it does not address the language_fallback_i18n_string_textgroup_default->multiple_translation_load(...) case, amongst other things...)
Comments