Après avoir testé plusieurs plugins multilingues pour wordpress (xLanguage, qTranslate et gengo), je me suis arrêté sur zdmultilang.
Ce dernier correspondait à ce que je recherchais : la possibilité de gérer les traductions pratiquement comme de nouvelles pages/articles mais avec une relation particulière avec la source. Par ailleurs, afin de respecter au mieux l’esprit plugin, je cherchais aussi quelque chose qui laisse la plate-forme directement opérationnelle en cas de désactivation.
Les seuls points qui manquaient par rapport à mon usage tournaient autour de la gestion des widgets. Je me suis donc attelé à ajouter cette fonctionnalité que je décris ici.
La normalisation des widgets
WordPress utilise toujours le même schéma pour le stockage des données de widgets : il s’agit d’un tableau associatif nom du paramètre/valeur qui est enregistré dans la table wp_option de la base à travers les fonctions get_option
et update_option
. Aussi dans un premier temps, j’ai remis au format le widget zd_multilang pour se conformer à ce standard.
Vers des options par langue
Zdmultilang gère déjà des options par langue : blogname
et blogdescription
dans la table wp_zd_ml_langs
. Néanmoins, si nous souhaitons gérer les paramètres de widget par langue nous allons devoir changer d’architecture. Mon choix a été de créer une table wp_zd_ml_options
dont la structure se base sur la table wp_options
où j’ai ajouté un champ LanguageID
. Cette table contiendra toutes les options dont je souhaite conserver une version spécifique par langue. J’en ai profité pour y mettre blogname
et blogdescription
, cet emplacement me semblant désormais plus légitime.
Comment construire dynamiquement les hooks pour nos widgets ?
Comme indiqué plus haut, les paramètres des widgets sont stockés dans la table wp_options
. Afin de rester au plus proche de l’architecture WordPress, il m’a semblé judicieux d’associer des fonctions aux hooks pre_option_...
et pre_update_option_...
où ...
correspond au nom du widget. L’utilisation des hooks « pre » permet de sortir des fonctions initiales get_option
ou update_option
presque immédiatement. Cela nécessite par contre de réécrire des fonctions analogues dans le plugin. Par souci d’homogénéité, presque toutes les fonctions d’accès aux options ont été réécrites : get_option, update_option, add_option, load_alloptions
. Elles l’ont été en s’inspirant des fonctions WordPress initiales afin de tirer parti des outils de cache alloption
et notoption
évitant autant de requêtes vers la base de données. Ceci est d’autant plus utile dans notre cas que tous les widgets n’ont pas de paramètres, or comme nous ne pouvons le savoir à l’avance nous sommes obligés de créer des hooks pour tous les widgets enregistrés (voir plus quand leur dénomination ne suit pas la nomenclature WordPress). Si un widget n’a pas de paramètre, on ressortira alors très vite des fonctions que nous avons réécrites sans solliciter plus la base de données que les fonctions initiales.
Ensuite, il reste à associer ces fonctions aux hooks. Pour cela nous parcourons le tableau de hachage $wp_registered_widgets
et pour chaque widget enregistré nous construisons dynamiquement une fonction triviale qui pointera vers les fonctions réécrites dont il est question plus haut.
foreach($wp_registered_widgets as $widget_name => $widget) {
$funcname = 'zd_multilang_get_option_'.$widget['classname'];
$function = "function $funcname".'() {
$option=str_replace("zd_multilang_get_option_","",__FUNCTION__);
return zd_multilang_get_option($option);
}');
eval($function);
add_filter('pre_option_'.$widget['classname'], $funcname);
} |
foreach($wp_registered_widgets as $widget_name => $widget) {
$funcname = 'zd_multilang_get_option_'.$widget['classname'];
$function = "function $funcname".'() {
$option=str_replace("zd_multilang_get_option_","",__FUNCTION__);
return zd_multilang_get_option($option);
}');
eval($function);
add_filter('pre_option_'.$widget['classname'], $funcname);
}
Notons qu’une fois tous ces hooks installés, on peut relancer la commande wp_widgets_init()
qui réinitialise tous les widgets. Cependant, cette fois-ci, compte tenu des filtres installés, on ira chercher les paramètres dans notre table wp_zd_ml_options
. Ça tombe bien : c’était notre objectif.
Comment conserver nos « sidebars » par langue ?
Les colonnes latérales s’enregistrent dans les thèmes.A priori, nous ne savons pas combien il y en a. L’idée est de conserver dans une option supplémentaire un équivalant de l’option sidebars_widgets
qui contient les informations sur le contenu des colonnes latérales. Notre option contiendra les informations de nb de sidebars dans le thème x nb de langues gérées par zd_multilangue
. Ensuite, il s’agira de reconstruire à la volée le résultat que WordPress s’attend à trouver en fonction du contexte (lecture simple ou paramètrage des widgets).
Comment permettre l’enregistrement des informations de widget pour les utilisateurs ?
À l’origine je souhaitais faire un écran de configuration des widgets par langue un peu comme zdmultilang gère les catégories, les étiquettes… Cependant, la gestion des widgets par WordPress (wp-adminwidgets.php) est loin d’être évidente (possibilité de javascript ou non, récupération des données de modification dans la même page que la présentation…). Aussi, j’ai fini par me résigner à ajouter un sélecteur de langue à la page traditionnelle d’administration des widgets. Là encore, les hooks mis à disposition par WordPress ne sont pas des plus pratiques, mais on finit toutefois par y arriver.
Comment tester ces modifications du plugin ?
Vous pouvez accéder à mon code en suivant ce lien : zd_multilang avec support des widgets en multilingue, mais attention il est fourni avec le statut : it works for me. Par ailleurs, vous risquez de perdre vos données blogname
et blogdescription
par langue si vous décidez de revenir à une version antérieure.
N’hésitez pas toutefois à laisser vos commentaires.