Un fabricant de mobilier sur mesure vend ses produits en France, en Belgique et en Suisse germanophone via une boutique WooCommerce. Son configurateur de produit, propulsé par une extension tierce spécialisée (non listée ici par respect de la confidentialité du contrat), permet de choisir dimensions, essence de bois, finition et quincaillerie. Le problème signalé : sur la version allemande de la boutique, la majorité des options du configurateur restaient affichées en français, rendant l’expérience incohérente pour les clients suisses germanophones.
Contrairement à un cas d’attributs et de variations WooCommerce classiques, ce configurateur ne stockait pas ses options dans les tables natives de WooCommerce (wc_product_attributes, taxonomies pa_*), mais dans un champ meta unique contenant un objet JSON structuré, propre à l’extension. WPML, qui s’appuie sur les taxonomies et les champs meta déclarés pour détecter le contenu traduisible, ne voyait tout simplement pas ces options.
Comprendre le stockage de l’extension
Un export du champ meta _configurateur_options d’un produit a révélé la structure suivante :
{
"dimensions": ["120x60", "140x70", "160x80"],
"essence": ["chene", "noyer", "hetre"],
"finition": ["brut", "vernis-mat", "vernis-satine"],
"quincaillerie": ["laiton", "acier-brosse"]
}
Les valeurs elles-mêmes (« chene », « noyer ») servaient à la fois de clé technique et de libellé affiché côté front via une fonction de rendu de l’extension, sans passage par un système de libellés séparé. Traduire ce champ tel quel via la traduction de champs personnalisés de WPML aurait cassé la logique métier du configurateur, qui utilise ces valeurs comme identifiants dans ses calculs de prix.
La méthode retenue

Plutôt que de toucher au stockage de l’extension, nous avons construit une couche de traduction d’affichage, indépendante des données métier. Un tableau de correspondance a été enregistré comme chaînes traduisibles via l’API String Translation de WPML, avec la clé technique comme identifiant stable :
add_action( 'init', function () {
$libelles = array(
'chene' => 'Chêne massif',
'noyer' => 'Noyer',
'hetre' => 'Hêtre',
'brut' => 'Brut',
'vernis-mat' => 'Vernis mat',
'vernis-satine' => 'Vernis satiné',
'laiton' => 'Laiton',
'acier-brosse' => 'Acier brossé',
);
foreach ( $libelles as $cle => $libelle_fr ) {
do_action(
'wpml_register_single_string',
'Configurateur mobilier',
'option_' . $cle,
$libelle_fr
);
}
} );
Ensuite, un filtre a été accroché à la fonction de rendu exposée par l’extension pour intercepter l’affichage de chaque option et la remplacer par sa version traduite :
add_filter( 'configurateur_render_option_label', function ( $libelle, $cle ) {
return apply_filters(
'wpml_translate_single_string',
$libelle,
'Configurateur mobilier',
'option_' . $cle
);
}, 10, 2 );
Ce filtre configurateur_render_option_label était heureusement déjà exposé par l’extension pour permettre de personnaliser l’affichage — un point à vérifier systématiquement avant de se lancer dans ce type d’adaptation, car toutes les extensions de configurateur n’offrent pas ce niveau de découplage entre logique métier et affichage.
Automatiser l’enregistrement des nouvelles options
Le client ajoute régulièrement de nouvelles finitions ou essences de bois. Pour éviter qu’une nouvelle option reste non traduite jusqu’à la prochaine intervention technique, un second hook a été branché sur la sauvegarde du produit, pour détecter et enregistrer automatiquement toute nouvelle clé apparue dans le champ JSON :
add_action( 'woocommerce_process_product_meta', function ( $product_id ) {
$options = json_decode( get_post_meta( $product_id, '_configurateur_options', true ), true );
if ( ! is_array( $options ) ) {
return;
}
foreach ( $options as $categorie => $valeurs ) {
foreach ( $valeurs as $valeur ) {
do_action(
'wpml_register_single_string',
'Configurateur mobilier',
'option_' . $valeur,
ucfirst( str_replace( '-', ' ', $valeur ) )
);
}
}
} );
Ce qui reste manuel
- La traduction elle-même des nouvelles chaînes, qui reste soumise à validation d’un traducteur professionnel avant publication ;
- La vérification que le libellé généré automatiquement (à partir du slug) reste lisible avant que la traduction ne soit faite, pour éviter un affichage brut du type « vernis satine » sans accent en attendant ;
- Le contrôle des combinaisons de prix par langue, l’extension calculant les tarifs indépendamment de la langue affichée — un point vérifié en amont pour s’assurer qu’aucune traduction n’affectait la logique de tarification.
Notre verdict
Ce cas illustre une règle plus générale valable pour toute extension tierce non pensée pour le multilingue : il est presque toujours possible de construire une couche de traduction d’affichage par-dessus une extension, à condition qu’elle expose un filtre de rendu et que sa logique métier reste indépendante du texte affiché. Quand ce n’est pas le cas, la seule option restante est de contacter l’éditeur de l’extension ou d’envisager une alternative plus ouverte, ce qui n’était heureusement pas nécessaire ici.