Voilà, voilà... Fin de l'aventure...

 

Fermeture de kolossaldrupal.org dans...


Bonjour tout le monde,

Drupal évolue, les versions changent et Kolossaldrupal.org était essentiellement consacré à la version 6 de Drupal.

Autant dire que les infos présentées ici commencent à dater...

Faute de temps, je ne peux plus garder le site Kolossaldrupal à jour...

Je vous aurais bien proposé de reprendre le flambeau mais... c'est tellement simple de nos jours de se faire son propre site à soi...Pourquoi s'embêter alors ? :-)

Ce site restera donc en l'état, tel qu'il était en 2011...

Ah la la ! Cela ne nous rajeunit pas !

Manuel Vila - Avril 2016

Callbacks de titre d'éléments de menu et de description, localisation

Référence en anglais sur drupal.org : 19 Janvier 2009 - 13h10
http://drupal.org/node/140311


Lors de la réécriture du système de menus de Drupal 6.x, les titres ont subi des plusieurs changements notables. Bien que ces changements apportent une nouvelle souplesse au système de menu, la plupart des modules contribués n'ont pas besoin des nouvelles fonctionnalités. Pour cette raison, cet article est structuré avec les infos les plus utiles en début, et devient plus complexe au fil de la lecture.

De toutes les modifications apportées au système de menu de Drupal 6, il y en a une pour laquelle TOUS les développeurs de modules doivent faire attention :

Les titres et descriptions ne doivent plus être passés via t().

Depuis sa version 6.x, Drupal manipule de façon interne la traduction des titres de menus et de leurs descriptions dans la langue de l'utilisateur. Les descriptions, si elles existent, sont toujours traduites avec t(), on ne peut pas lui passer des données supplémentaires pour une substitution via des caractères jokers (Dans D5 et antérieurs, passer des caractères de substituions était déconseillé - avec cette modification, le système de menu applique cette règle directement). Par défaut, les titres sont traduits avec t(), mais le remplacement de chaîne à la t() est possible via l'utilisation de la nouvelle propriété title arguments. Vous pouvez aussi choisir de remplacer t() avec votre propre callback personnalisé.

Pour la plupart des modules, cela signifie que les t() entourant vos Titres et Descriptions doivent être ôtés. Cependant, l'ajout des nouvelles propriétés de titres de menu ('title callback' et (title arguments) signifie qu'il y a désormais quatre façons possibles de définir un titre pour un élément de menu. Notez que dans les exemples qui suivent, les codes produisent tous des titres pour le même formulaire : la version localisée de Example title - Case #, où # est le numéro du case.

Cas 1 : juste 'title'

Dans le cas n°1, aucune des nouvelles propriétés des titres de menu ne sont utilisées. Nous supprimons simplement les appels à t() qui auraient été présents dans une version pour D5 :

<?php
  $items
['example/case1'] = array(
    
'title' => 'Example title - Case 1',
    
'description' => 'Description of the Case 1 item, with no t()!',
    
'access callback' => 'example_access_callback',
    
'page callback' => 'example_page_callback',
  );
?>

A titre d'information, voici à quoi Case 1 aurait ressemblé dans Drupal 5 :

<?php
  $items
[] = array(
    
'title' => t('Example title - Case 1'),
    
'description' => t("Description of the Case 1 item - but with t(), b/c this is D5."),
    
'access' => example_access_callback(),
    
'callback' => 'example_page_callback',
  );
?>

Nous le répétons : la plupart des modules n'auront pas besoin de plus que le Case 1.

Cas 2 : 'title' + 'title arguments'

Dans le cas n° 2, nous laissons le système de menus utiliser t() comme fonction callback, mais nous passons également quelques arguments supplémentaires à t() pour la substitution:

<?php
  $items
['example/case2'] = array(
    
'title' => 'Example !sub1 - Case !op2',
    
'title arguments' => array('!sub1' => 'title''!op2' => '2'),
    
'access callback' => 'example_access_callback',
    
'page callback' => 'example_page_callback',
  );
?>

Quand le système de menus tombe sur un lien avec cette configuration - 'title arguments' et 'title' déclarés - il appelle t() ainsi :

<?php
  t
($menu_item['title'], $menu_item['title arguments']);
?>

L'équivalent D5 de Case 2 serait :

<?php
  $items
[] = array(
    
'title' => t('Example @sub1 - Case @op2', array('@sub1' => 'title''@op2' => '2')),
    
'access' => example_access_callback(),
    
'callback' => 'example_page_callback',
  );
?>

Cas 3 : 'title' + 'title callback'

Dans le cas n° 3, nous modifions le comportement par défaut du système de menus en appelant notre propre fonction callback au lieu de la fonction t() :

<?php
  $items
['example/case3'] = array(
    
'title' => t('Example title'),
    
'title callback' => 'example_title_callback',
    
'access callback' => 'example_access_callback',
    
'page callback' => 'example_page_callback',
  );
?>

 

<?php
function example_title_callback($title) {
  
$title $title ' - ' t('Case 3');
  return 
$title;
}
?>

Vous remarquerez que nous avons nous-mêmes exécuté l'affichage via t(), et que nous l'avons fait dans une partie où nous ne sommes plus supposés le faire ! (notamment dans 'title'). Quand notre callback de titre remplace t() comme « localisateur », nous devons soit l'appeler nous-mêmes dans notre callback de titre personnalisé, soit faire la localisation d'une autre façon.

Notez que découper ainsi des chaînes de caractères en plusieurs morceaux est totalement déconseillé - cela décontextualise les données, ce qui en rend la traduction malaisée. Nous ne l'avons fait ici que pour illustrer cet exemple.

Case 3 est le premier cas pour lequel il n'y a pas d'équivalent D5 simple. Il y avait plusieurs façons de faire, mais elles impliquaient de charger des données supplémentaires lors du hook_menu() et de les substituer dans la propriété titre, pas très propre et potentiellement source de ralentissements du hook_menu() pour TOUS les modules, et non seulement celui qui effectuait le chargement.

Cas 4 : 'title callback' + 'title arguments'

Ce Cas 4 est le plus complexe des quatre. En fait, il s'agit plus d'un hack bolt on portant sur les situations un peu pointues que les concepteurs du système de menu n'ont pas encore traité. Dans ce Cas 4, il y a deux choses à garder en mémoire :

  1. Lorsque vous définissez un title callback et un title arguments, le système de menu ignorera totalement ce qui sera mis dans la propriété title.
  2. Pour ce cas, le système de menu doit utiliser call_user_func_array(). Alors que t() s'attend à un deuxième argument de type tableau (et peut donc lire le contenu de title arguments directement), il n'y a aucune certitude que le callback déclaré dans title callback puisse manipuler un tableau comme deuxième argument.
<?php
  $items
['example/case4'] = array(
    
'title' => 'Hangar à vélos plein de Schtroumpfs'// TOTALEMENT ignoré. Good thing, too.
    
'title callback' => 'example_title_callback',
    
'title arguments' => array(t('Example title'), t('Case 4')),
    
'access callback' => 'example_access_callback',
    
'page callback' => 'example_page_callback',
  );
?>

 

<?php
function example_title_callback($arg1$arg2) {
  
$title $arg1 ' - ' $arg2;
  return 
$title;
}
?>

Il n'y aura ni hangar à vélo ni Schtroumpfs passés à la fonction example_title_callback - seulement les données paramétrées dans title arguments. De même, comme dans Case 3, notre fonction title callback devra s'occuper de la traduction puisque nous avons remplacé l'appel interne à t() du système de menu.

Quelques exemples du core D6

<?php
function block_menu() {
  
$items['admin/build/block'] = array(
    
// Title as literal string, callback not defined, so falls back to the default t() callback
    
'title' => 'Blocks',
    
// Description as literal string, always translated with t().
    
'description' => 'Configure what block content appears in your site\'s sidebars and other regions.',
    
'page callback' => 'drupal_get_form',
    
'page arguments' => array('block_admin_display'),
    
'access arguments' => array('administer blocks'),
  );
?>

 

<?php
  $default 
variable_get('theme_default''garland');
  foreach (
list_themes() as $key => $theme) {
    
$items['admin/build/block/list/'$key] = array(
      
// Title is string with placeholder, callback not defined, so falls back to the default t()
      
'title' => '!key settings',
      
// "title arguments" specify the arguments to pass on to the title callback
      
'title arguments' => array('!key' => $theme->info['name']),
      
'page arguments' => array('block_admin_display'$key),
      
'type' => $key == $default MENU_DEFAULT_LOCAL_TASK MENU_LOCAL_TASK,
      
'weight' => $key == $default ? -10 0,
    );
  }
  return 
$items;
}
?>

 

<?php
function search_menu() {
  
//...

  
foreach (module_implements('search') as $name) {
    
$items['search/'$name .'/%'] = array(
      
// Custom callback to get the title from
      
'title callback' => 'module_invoke',
      
// List of arguments to pass to "title callback"
      
'title arguments' => array($name'search''name'TRUE),
      
'page callback' => 'search_view',
      
'page arguments' => array($name),
      
'access callback' => '_search_menu',
      
'access arguments' => array($name),
      
'type' => $name == 'node' MENU_DEFAULT_LOCAL_TASK MENU_LOCAL_TASK,
      
'parent' => 'search',
    );
  }
  return 
$items
}
?>