FOX - WooCommerce Currency Switcher Professional

Changer la devise selon la langue dans WooCommerce : Polylang, TranslatePress

Pour changer la devise selon la langue dans WooCommerce, FOX a besoin de quelques lignes de code : aucun réglage ne relie une devise à une langue, car la langue appartient à Polylang, TranslatePress, Weglot ou GTranslate, et non au sélecteur de devises. Le code est court, et les snippets qui circulent fonctionnent, mais ils réservent trois surprises : les visiteurs ne peuvent plus choisir une autre devise, les pages en cache reviennent à l'ancienne devise, et les traducteurs intégrés au navigateur n'atteignent jamais le code. Vous trouverez ci-dessous deux schémas, l'un qui lie définitivement la devise à la langue et l'autre qui ne la change que lorsque la langue change, ainsi que la marche à suivre pour chaque plugin de traduction.

Lire la langue courante en PHP

Chaque schéma commence par la langue de la page courante. Chaque plugin de traduction l'expose différemment :

PluginLangue courante en PHPExemple de valeur
Polylangpll_current_language()de
TranslatePressglobal $TRP_LANGUAGE;de_DE
Weglotweglot_get_current_language()de
WPMLapply_filters( 'wpml_current_language', null )de
Polylang, TranslatePress (alternative)get_locale()de_DE

La valeur doit correspondre exactement à votre code, majuscules et séparateur compris : en_US, et non en-US ou en-us. Lorsqu'une langue « ne fait rien », affichez la valeur une fois (par exemple dans un commentaire HTML du pied de page) et copiez-la à partir de là. Pour tout autre plugin, cherchez dans sa documentation la fonction qui renvoie la langue courante ; s'il n'en a pas, utilisez le schéma JavaScript ci-dessous, qui n'a besoin que de l'attribut lang de la page. Les utilisateurs de WPML peuvent aussi suivre changer de devise avec la langue dans WPML. WooCommerce Multilingual possède son propre mode multidevise : laissez-le désactivé lorsque FOX gère les devises.

Schéma 1 : la devise suit toujours la langue

Utilisez-le lorsque chaque langue correspond à un marché : les pages allemandes toujours en euros, les pages anglaises des États-Unis toujours en dollars. Le code définit la devise à chaque affichage de page ; il l'emporte donc sur le sélecteur, la devise de bienvenue et les règles GeoIP.

/*
 * FOX: the currency always follows the language.
 * Child theme functions.php or a code snippets plugin.
 */
add_action( 'template_redirect', function () {
    if ( ! class_exists( 'WOOCS' ) ) {
        return;
    }
    global $WOOCS;

    // Language => currency. Use the values your plugin returns (see the table).
    $map = array(
        'en' => 'USD',
        'de' => 'EUR',
        'fr' => 'EUR',
        'bg' => 'BGN',
    );

    // Polylang. For another plugin, replace this line with its function.
    $lang = function_exists( 'pll_current_language' ) ? pll_current_language() : '';

    if ( isset( $map[ $lang ] ) ) {
        $WOOCS->set_currency( $map[ $lang ] );
        // Tells FOX's script that this page was built in this currency (needed with page cache).
        $_GET['currency'] = $map[ $lang ];
    }
} );

Pourquoi il est écrit ainsi :

  • template_redirect, et non wp_head. Il s'exécute avant que le thème n'affiche quoi que ce soit : les en-têtes, les menus et les mini-paniers reçoivent donc déjà la devise de la langue, et il ne s'exécute pas pour les requêtes AJAX, où la langue est souvent inconnue. Les anciens snippets sur wp_head fonctionnent dans la plupart des thèmes, mais tout ce qui lit la devise plus tôt, comme un panier d'en-tête construit avant wp_head, reçoit encore l'ancienne.
  • La ligne $_GET['currency']. Sur une boutique en cache, FOX redessine les prix après le chargement dans la devise enregistrée pour le visiteur ; c'est ce redessin qui fait qu'une page affiche la bonne devise « pendant une seconde » avant de revenir en arrière. Une page construite avec une devise dans la requête saute le redessin. Cela empêche aussi une règle GeoIP de remplacer la devise de la langue sur la première page d'un visiteur. Le prix à payer : sur chaque page, FOX actualise le mini-panier une fois, comme après un changement de devise.
  • Cache de page et panier. Une page en cache n'exécute pas PHP : la devise enregistrée pour le visiteur n'est donc pas mise à jour par ce code. Réglez Stockage de la devise (Currency storage) sur Transient et activez J'utilise un plugin de cache sur mon site (I am using cache plugin on my site) : dans cette combinaison, le script de FOX copie la devise de la page dans le stockage du visiteur, de sorte que le panier et la page de paiement suivent eux aussi la langue. Contexte dans le sélecteur de devises revient à la devise par défaut.

Puisque le sélecteur ne peut plus rien changer, masquez-le, ou n'affichez que la devise de la langue courante. Les visiteurs qui veulent une autre devise changent de langue.

Schéma 2 : changer avec la langue, en gardant le sélecteur

La plupart des boutiques veulent quelque chose de plus souple : un visiteur qui ouvre les pages allemandes obtient des euros, peut toujours passer aux dollars et garde les dollars en naviguant en allemand. Il faut pour cela mémoriser pour quelle langue la devise a été définie en dernier, et n'agir que lorsque la langue change. Le faire dans le navigateur présente deux avantages : cela fonctionne sur les pages en cache, et avec tout plugin de traduction qui donne à chaque langue ses propres pages, car il ne lit que l'attribut lang de la page.

/*
 * FOX: switch the currency once when the page language changes;
 * the visitor can pick another currency afterwards.
 * Front end, in the footer: a code snippets plugin or the theme's
 * custom JavaScript field.
 */
window.addEventListener('load', function () {
    var map = { en: 'USD', de: 'EUR', fr: 'EUR', bg: 'BGN' }; // language: currency
    var lang = (document.documentElement.lang || '').slice(0, 2).toLowerCase();
    var params = new URLSearchParams(window.location.search);
    var last = null;

    if (!map[lang]) {
        return;
    }
    try {
        last = localStorage.getItem('my_currency_lang');
        localStorage.setItem('my_currency_lang', lang);
    } catch (e) {
        return; // storage blocked: leave the currency alone
    }
    // The visitor just picked a currency, or the language has not changed.
    if (params.has('currency') || last === lang) {
        return;
    }
    params.set('currency', map[lang]);
    window.location.replace(window.location.pathname + '?' + params.toString() + window.location.hash);
});

Lorsque la langue change, le script recharge la page une fois avec ?currency=EUR, le même paramètre que le sélecteur propre de FOX : FOX enregistre donc la devise pour le visiteur. Ensuite, le choix du visiteur prévaut jusqu'à ce qu'il change de nouveau de langue. Remarques :

  • Les deux premières lettres de lang sont utilisées : de-DE et de-AT comptent donc toutes deux comme de. Si deux variantes d'une même langue nécessitent des devises différentes, utilisez la valeur complète dans la table.
  • Lors de la toute première visite, rien n'est encore mémorisé : le script passe donc à la devise de la langue, après que la devise de bienvenue et les règles GeoIP en ont choisi une. Pour laisser GeoIP décider de la première devise, ajoutez if (last === null) { return; } juste après le bloc try.
  • Ne le combinez pas avec le schéma 1. Le code PHP écraserait le choix du visiteur à la page suivante.

GeoIP, devise de bienvenue et listes de devises par langue

  • Quelle règle l'emporte. Avec le schéma 1, la langue l'emporte sur chaque page, et les règles GeoIP et la Devise de bienvenue (Welcome currency) n'ont plus d'importance. Avec le schéma 2, GeoIP ne décide de la première devise que si vous ajoutez la ligne de première visite ci-dessus ; ensuite, la langue décide chaque fois qu'elle change. Dans les deux cas, Paiement selon les règles GeoIP (Checkout by GeoIP rules), s'il est activé, fait toujours payer les clients dans la devise de leur pays à la page de paiement ; voir devise de paiement selon le pays du client.
  • Masquer une devise pour une langue. Le filtre woocs_currency_manipulation_before_show modifie la liste affichée par chaque sélecteur FOX. Il masque la devise dans le sélecteur uniquement ; il ne change pas la devise d'un visiteur qui l'a déjà, ce dont se charge le schéma 1 ou 2.
/*
 * FOX: do not offer PLN on the English pages.
 * Child theme functions.php or a code snippets plugin.
 */
add_filter( 'woocs_currency_manipulation_before_show', function ( $currencies ) {
    if ( function_exists( 'pll_current_language' ) && pll_current_language() === 'en' ) {
        unset( $currencies['PLN'] );
    }
    return $currencies;
} );

Si la raison d'avoir une devise par langue est le prix lui-même, avec des montants arrondis par marché plutôt que convertis, combinez la règle de langue avec les prix fixes par devise.

GTranslate et autres traducteurs intégrés au navigateur

Le widget gratuit GTranslate, et les autres services qui traduisent la page dans le navigateur, changent la langue sans charger de nouvelle page. Aucune requête n'atteint WordPress : aucun code PHP ne peut donc réagir, et l'attribut lang de la page peut lui aussi rester inchangé. Avec un tel traducteur, aucun des deux schémas ci-dessus ne peut voir le changement de langue. Les options :

  • Si votre formule donne à chaque langue sa propre adresse (un sous-répertoire ou un sous-domaine), chaque langue est un chargement de page distinct. Vérifiez le code source d'une page traduite : si <html lang="…"> indique la langue, le schéma 2 fonctionne tel quel.
  • Les proxys de traduction peuvent indiquer la langue à WordPress dans un en-tête de requête ; les formules payantes de GTranslate utilisent X-GT-LANG, lu en PHP sous la forme $_SERVER['HTTP_X_GT_LANG']. Affichez-le une fois avant de vous y fier : s'il est vide, votre configuration ne l'envoie pas, et seul le support du fournisseur peut dire pourquoi.
  • Sinon, rendez la devise indépendante de la langue : laissez les règles GeoIP choisir la première devise et le sélecteur faire le reste. Voir changer automatiquement la devise selon le pays.

Si la devise ne suit pas la langue

  • Affichez la valeur de la langue et comparez-la aux clés de votre table, caractère par caractère.
  • Le sélecteur « ne fait rien » : le schéma 1 est actif. C'est ainsi qu'il fonctionne ; utilisez le schéma 2 si les visiteurs doivent pouvoir choisir.
  • La devise est correcte un instant, puis revient en arrière : la page provient d'un cache et la ligne $_GET['currency'] est absente, ou un autre snippet ou plugin définit lui aussi la devise. Recherchez set_currency dans le thème et dans les plugins de snippets.
  • La page est correcte mais le panier affiche l'ancienne devise : avec un cache de page, utilisez le stockage Transient avec l'option de cache, comme décrit dans le schéma 1.
  • Un mini-panier personnalisé affiche le nouveau symbole avec les anciens montants : il conserve ses propres données de panier en cache. Testez avec le mini-panier WooCommerce standard pour le confirmer.
  • Purgez tous les caches (plugin, serveur, CDN) après avoir ajouté ou modifié le code, et testez dans une fenêtre de navigation privée.

Si la devise ne suit toujours pas la langue, ouvrez un sujet sur le forum de support de FOX en indiquant le plugin de traduction que vous utilisez, votre snippet et un lien vers deux versions linguistiques d'une même page.