Champs personnalisés, options, ACF et WPML : le tuto complet
J’utilise intensément ACF, à la fois pour des métas “classiques” (attachés à des posts, des termes de taxonomie ou des utilisateurs) et des pages d’options, très complètes, qui sont au coeur de l’optimisation SEO de mes sites. J’ai commencé à construire mon plugin maison il y a quelques années, pour des sites monolingues, et là il m’a fallu le rendre compatible WPML. (Tout ce qui est expliqué dans cet article devrait aussi fonctionner avec Polylang, avec le bon plugin et les fonctions Polylang)
Ça a marché relativement bien, avec néanmoins des petits bugs qui vous donnent envie de commander la chèvre.
Ce qu’il y a à traduire
ACF ce sont des groupes de champs, qui s’affichent dans l’admin comme des métaboxs, donc avec des libellés, des messages, éventuellement des titres d’onglets, etc. et des valeurs qui vont être saisies, toujours dans l’admin ou en front-end via acf_form()
et (théoriquement) affichées en front-end.
Dans un site multilingue, il faut obligatoirement traduire ce qui sera affiché en front-end, et on peut se donner la peine de traduire les affichages de l’administration, si on a des utilisateurs qui utilisent des langues autre que la langue par défaut du site. Ce qui peut être le cas si vous devez donner accès au support WPML, par exemple :)
En fonction du type de champ, la valeur qui s’affichera en front end sera directement stockée dans le champ (texte, wysiwig, etc) ou associée à la valeur stockée dans le champ (select, checkbox, etc).
Les options de WPML pour ACF
Pour les valeurs affichées en front-end, il faut utiliser l’extension ACF Multilingual. L’autre solution serait de passer par la traduction de chaînes, mais cet outil est le point noir pour la performance d’un site WPML, et il vaut mieux s’en passer autant que possible. Surtout pour des metas qui vont être nombreux !
Pour les valeurs affichées dans l’administration, WPML recommande de désactiver la traduction des groupes de champs, et c’est une “recommandation obligatoire” pour les groupes de champs qui incluent des répéteurs. On a donc le choix de passer par la traduction de chaines (bad) ou par un fichier .po,
L’outil ACF Multilingual
Pratiquement, ACF Multilingual rajoute une propriété au champ ‘Translation preferences’, que l’on peut remplir dans l’interface de création graphique ou directement dans le code php ou le json.
En php, cela donne 'wpml_cf_preferences' => 1
et en json "wpml_cf_preferences": 1
.
avec comme valeurs possibles :
- ignore, 0 : WPML ne traite pas la valeur. Elle est donc gérable indépendamment dans chaque langue
- copy, 1 : la valeur dans la langue originale sera toujours copiée (y compris quand elle est modifiée)
- copy-once, 3 : la valeur copiée peut être modifiée ensuite dans chaque langue (oui, manifestement ça a été rajouté après)
- translate, 2 : la valeur devra être traduite, apparaitra dans l’interface de traduction de WPML pour les contenus et devra être traduite pour que le contenu soit considéré comme “traduit” (et donc publiable)
Le fichier de configuration wpml-config.xml
Le fichier, à placer à la racine de votre plugin ou de votre thème permet de définir les préférences pour tous les éléments traduisibles pas WPML. (Et Polylang l’utilise aussi).
Pour les custom fields (que ce soient ceux d’ACF ou les autres), il se présente sous cette forme :
[pastacode lang=”javascript” manual=”%3Ccustom-fields%3E%0A%09%3Ccustom-field%20action%3D%22translate%22%20style%3D%22visual%22%3Ewprm_notes%3C%2Fcustom-field%3E%0A%09%3Ccustom-field%20action%3D%22copy%22%3Ewprm_author_display%3C%2Fcustom-field%3E%0A%09%3Ccustom-field%20action%3D%22translate%22%3Ewprm_author_name%3C%2Fcustom-field%3E%0A%3C%2Fcustom-fields%3E” message=”” highlight=”” provider=”manual”/](il s’agit d’un fichier wpml-config.php fait spécialement pour rendre Wpml et wp recipe maker). Le style permet de définir comment le champ va apparaitre dans l’interface de traduction de WPML : simple champ de type texte, ou éditeur avec TinyMce.
Les paramètres de traduction dans les réglages WPML
Sauf si vous n’avez que très peu de champs, cette méthode est particulièrement fastidieuse.
On y accède via le menu “paramètres” de WPML
Accéder au paramétrages de traduction des champs personnaliséset cela donne une liste de tous les custom fields existant dans la base de données (même des vieux trucs liés à des plugins désactivés).
Cette méthode est particulièrement ennuyeuse, et surtout elle ne permet pas de paramétrer correctement les champs de type répéteur.
Pour ces derniers, effectivement, ACF stocke la méta value en insérant un numéro d’ordre dans la meta key, comme ceci :
Il suffit de créer une troisième valeur pour voir un nouveau champ apparaître, qui ne sera pas configuré !
Donc pour ce type de champs ACF, il faut passer par l’utilisation d’ACF Multilingual, ou par le fichier wpml-config en utilisant des wildcards.
Quand un paramètre est défini via le fichier wpml-config, il apparait dans cette liste en grisé, avec un cadenas.
Les champs paramétrés via ACF multilingual et la propriété 'wpml_cf_preferences'
apparaissent normalement. En effet, on peut modifier dans les paramètres du site les réglages paramétrés dans le groupe de champs, qu’il soit créé dans l’admin ou via un fichier .php ou json, mais on ne peut pas modifier les réglages du fichier wpml-config.
Le cas particulier des options ACF multilingues
Les possibilités de paramétrage sont exactement les même : ignorer, copier, copier une fois, traduire.
Par contre, le comportement est différent. Pour un champ dont le nom de base est ‘mon_petit_champ’, ACF insère dans la table wp_options deux options :
- options_mon_petit_champ, avec la valeur de l’option
- _options_mon_petit_champ, qui a comme valeur l’identifiant du champ, par exemple field_8ec90e3af683b
Pour vous expliquer, j’ai fait deux groupes différents, un avec quatre champs avec chaque paramétrage possible (ignore, copy, copy_once et translate) et un groupe avec un champ unique en ignore. Et je vais les afficher sur une page, en français et en anglais.
Options avec acf get field
- option_ignore :
echo get_field('option_ignore', 'options');
- option_copy :
echo get_field('option_copy', 'options');
- option_copy_once :
echo get_field('option_copy_once', 'options');
- option_traduction :
echo get_field('option_traduction', 'options');
- option_ignore_seul :
echo get_field('option_ignore_seul', 'options');
Options avec la fonction wordpress
- option_ignore :
- option_copy :
- option_copy_once :
- option_traduction :
- option_ignore_seul :
Première étape : j’enregistre des valeurs pour les options, sans me soucier de la langue. Que le petit drapeau WPML soit sur “toutes les langues” ou sur “français”, la langue par défaut du site, le résultat dans la base de données est le même :
J’affiche ensuite ma page de test, en français : toutes les options sont là
En anglais, il n’y a pas de valeur avec get_field, par contre get_option affiche bien les valeurs
Les valeurs d’option en copy et copy_once n’ont pas été générées.
Il faut que j’affiche les options en anglais et que je les enregistre pour générer la copie.
L’écran a bien généré les valeurs pour copy et copy_once et m’empêche de modifier le champ en copy, mais il faut que je clique sur “mettre à jour” pour que ces valeurs soient enregistrées dans la base de données.
Après l’avoir fait en mettant des valeurs dans tous les champs, voici ce qui s’affiche sur ma page de test en anglais :
Pour résumer :
Le paramétrage ACF Multilingual pour les options ne gère que la façon dont elles apparaissent dans l’écran de traduction. Par contre, pour l’utilisation d’une option dans une langue traduction, la fonction get_field va systématiquement chercher la traduction de l’option.
Par conséquent, même pour des options qui n’ont pas de raison d’être traduites, vous devez systématiquement les enregistrer dans toutes les langues pour pouvoir les utiliser.
Je vous recommande, pour les options qui n’ont pas besoin d’être traduites, d’utiliser la fonction wordpress get_option et de réserver get_field aux options dont la valeur change en fonction de la langue.
Traduire les groupes de champs dans l’admin
Si vous voulez afficher les groupes de champs dans une langue différente il faut d’abord activer l’internationalisation pour ACF et définir le text domain, en rajoutant dans votre plugin ces lignes :
[pastacode lang=”php” manual=”function%20my_acf_settings_localization(%24localization)%7B%0A%20%20return%20true%20%3B%0A%7D%0Aadd_filter(‘acf%2Fsettings%2Fl10n’%2C%20’my_acf_settings_localization’%20)%3B%0A%0Afunction%20my_acf_textdomain(%24domain)%7B%0A%20%20return%20’my_textdomain’%3B%0A%7D%0Aadd_filter(‘acf%2Fsettings%2Fl10n_textdomain’%2C%20’my_acf_textdomain’%20%2C%201%20)%3B” message=”” highlight=”” provider=”manual”/]Ensuite, il suffira d’encadrer toutes les chaines dans la fonction __('string', 'my_textdomain')
dans les fichiers php qui génèrent vos champs.
(Et là, honnêtement, on oublie le format json).
Un petit coup dePoEdit par là dessus, et votre admin peut s’afficher dans la langue de l’utilisateur.
Trucs pour que ça marche bien
Utiliser le plugin dès la création du champs ou des groupes de champs
Sinon, il faudra repasser à travers tout le php pour rajouter la ligne wpml_cf_preferences
ou, pire, à travers tous les groupes de champ dans l’admin !
Champs ACF de type liste, bouton-radio, etc
Dans les liste de choix pour ces types de champs, toujours mettre une valeur numérique ou une id, toujours toujours toujours et traduire via le fichier .po l’affichage de cette valeur, et ne stocker que l’id. Tous les autres éléments doivent être traduits via Po Edit, pas stockés en base de données.
Pas de traduction de chaines
Pas une fois dans cet article je n’ai utilisé la traduction de chaines. Faites en autant et vous n’aurez pas de problèmes de performances.
Avec tout cela vous avez tout en main pour gérer sans aucun problème un site multilingue avec ACF et WPML.