# Traduire un configurateur de produit sur mesure dans WooCommerce

> Un configurateur de mobilier sur mesure affichait des options non traduites selon la langue. Voici la méthode retenue pour ce cas précis, au-delà des attributs classiques.

- Auteur : Clément Hadrot
- Publié le : 2025-07-30
- Mis à jour le : 2025-07-30
- Catégorie : Multilingue
- URL : https://wpmoderne.dev.wordpress-developpement.fr/multilingue/traduire-configurateur-produit-woocommerce/

## L’essentiel

- Les options du configurateur étaient stockées en JSON hors des tables de traduction
- La solution combine un filtre de rendu et un hook d'enregistrement des chaînes
- Chaque option ajoutée par le client déclenche automatiquement son enregistrement pour traduction

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

> L'essentiel à retenir : Les options du configurateur étaient stockées en JSON hors des tables de traduction ; La solution combine un filtre de rendu et un hook d'enregistrement des chaînes ; Chaque option ajoutée par le client déclenche automatiquement son enregistrement pour traduction

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.
