subscription_payment_success, subscription_renewed, subscription_cancelled : chaque événement webhook envoyé par un prestataire de paiement par abonnement arrive sans connaître la langue dans laquelle le client a initialement choisi de s’abonner. C’est le problème rencontré par une start-up qui commercialise un logiciel en français et en anglais via Lemon Squeezy, avec des notifications de facturation générées par WordPress à la réception de chaque webhook.
Problème : le webhook ignore tout du contexte visiteur
Au moment de l’achat initial, la page de paiement s’affichait dans la langue du visiteur, déterminée par Polylang. Mais un webhook de renouvellement, déclenché des mois plus tard par les serveurs du prestataire de paiement, n’a plus aucun lien avec cette session de navigation d’origine : il arrive avec un identifiant d’abonnement et un montant, rien d’autre concernant la langue.
Sans traitement particulier, la notification de renouvellement partait systématiquement dans la langue par défaut du site, ce qui a généré plusieurs messages d’incompréhension de clients francophones recevant leurs factures de renouvellement en anglais.
Snippet commenté : capturer la langue dès l’achat initial
La correction commence avant même le premier webhook, au moment de la création de la session de paiement, en enregistrant la langue courante comme métadonnée personnalisée transmise au prestataire :
add_filter( 'ma_boutique_avant_creation_session_paiement', function ( $donnees_session ) {
$donnees_session['custom_data'] = array(
'langue_achat' => pll_current_language(),
);
return $donnees_session;
} );
Cette donnée personnalisée, renvoyée telle quelle par le prestataire dans chaque webhook ultérieur lié à cet abonnement, devient la source de vérité pour la langue à utiliser, indépendamment de la langue du serveur qui traite l’événement.

Snippet commenté : relire la langue à chaque webhook
add_action( 'ma_boutique_webhook_recu', function ( $evenement ) {
$langue_achat = $evenement['data']['custom_data']['langue_achat'] ?? 'fr';
switch_to_locale( $langue_achat );
wp_mail(
$evenement['data']['customer_email'],
__( 'Confirmation de votre renouvellement', 'ma-boutique' ),
generer_corps_facture( $evenement, $langue_achat )
);
restore_previous_locale();
}, 10, 1 );
Le point de vigilance ici est la valeur de repli (?? 'fr') : sans elle, un ancien abonnement souscrit avant la mise en place de ce mécanisme se retrouverait sans langue définie et ferait échouer switch_to_locale() silencieusement.
Persister la langue en méta utilisateur pour les événements ultérieurs
Au-delà du webhook de paiement, d’autres notifications (rappel d’échéance, alerte d’échec de prélèvement) doivent elles aussi respecter cette langue d’origine. Plutôt que de relire la donnée personnalisée du prestataire à chaque fois, la langue est également stockée en méta utilisateur WordPress dès la première capture, ce qui centralise sa lecture pour tout traitement futur :
update_user_meta( $utilisateur_id, 'langue_abonnement', $langue_achat );
Variantes selon les événements
- Échec de paiement : le message de relance doit rester dans la langue d’abonnement, jamais dans la langue de la carte bancaire ou de l’adresse IP du serveur qui traite l’échec.
- Changement de plan : si le client change de langue d’interface après l’achat initial, un mécanisme de mise à jour explicite de la méta utilisateur doit exister, sans quoi les webhooks continueront à utiliser l’ancienne langue enregistrée.
- Résiliation : l’e-mail de confirmation de résiliation suit la même règle : lecture de la méta utilisateur, jamais de la locale ambiante du serveur au moment du traitement du webhook.
Un webhook ne porte que ce qu’on lui a explicitement confié au moment de la création de la ressource : la langue n’échappe pas à cette règle et doit être transmise, jamais supposée.
En résumé
La langue d’un abonnement multilingue doit être traitée comme une donnée métier à part entière, capturée à l’achat, transmise dans les métadonnées personnalisées du prestataire de paiement, et relue explicitement à chaque événement webhook plutôt que déduite d’un contexte d’exécution qui n’a plus rien à voir avec le visiteur d’origine.