Cambiar la moneda según el idioma en WooCommerce: Polylang, TranslatePress
Para cambiar la moneda según el idioma en WooCommerce, FOX necesita unas pocas líneas de código: no hay ningún ajuste que vincule una moneda a un idioma, porque el idioma pertenece a Polylang, TranslatePress, Weglot o GTranslate, no al selector de moneda. El código es corto y los fragmentos que circulan funcionan, pero traen tres sorpresas: los visitantes ya no pueden elegir otra moneda, las páginas en caché vuelven a la moneda anterior y los traductores del navegador nunca llegan al código. A continuación verás dos patrones, uno que vincula la moneda al idioma de forma permanente y otro que solo la cambia cuando cambia el idioma, y qué hacer con cada plugin de traducción.
Lee el idioma actual en PHP
Todo patrón empieza por el idioma de la página actual. Cada plugin de traducción lo expone de forma distinta:
| Plugin | Idioma actual en PHP | Valor de ejemplo |
|---|---|---|
| Polylang | pll_current_language() | de |
| TranslatePress | global $TRP_LANGUAGE; | de_DE |
| Weglot | weglot_get_current_language() | de |
| WPML | apply_filters( 'wpml_current_language', null ) | de |
| Polylang, TranslatePress (alternativa) | get_locale() | de_DE |
El valor debe coincidir exactamente con tu código, incluidas las mayúsculas y el separador: en_US, no en-US ni en-us. Cuando un idioma "no hace nada", imprime el valor una vez (por ejemplo en un comentario HTML del pie de página) y cópialo desde ahí. Para cualquier otro plugin, busca en su documentación la función que devuelve el idioma actual; si no la tiene, usa el patrón de JavaScript de más abajo, que solo necesita el atributo lang de la página. Los usuarios de WPML también pueden seguir cambiar la moneda con el idioma en WPML. WooCommerce Multilingual tiene su propio modo multimoneda: déjalo desactivado cuando FOX gestione las monedas.
Patrón 1: la moneda siempre sigue al idioma
Úsalo cuando cada idioma represente un mercado: las páginas en alemán siempre en euros, las páginas en inglés de EE. UU. siempre en dólares. El código fija la moneda en cada visita a una página, por lo que anula el selector, la moneda de bienvenida y las reglas de 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 ];
}
} );
Por qué está escrito así:
template_redirect, nowp_head. Se ejecuta antes de que el tema imprima nada, así que las cabeceras, los menús y los minicarritos ya reciben la moneda del idioma, y no se ejecuta en las peticiones AJAX, donde el idioma suele ser desconocido. Los fragmentos antiguos conwp_headfuncionan en la mayoría de los temas, pero todo lo que lea la moneda antes, como un carrito de cabecera construido antes dewp_head, sigue recibiendo la anterior.- La línea
$_GET['currency']. En una tienda con caché, FOX vuelve a dibujar los precios después de la carga en la moneda guardada para el visitante; ese redibujado es lo que hace que una página muestre la moneda correcta "durante un segundo" y luego vuelva a la anterior. Una página construida con una moneda en la petición se salta el redibujado. También evita que una regla de GeoIP reemplace la moneda del idioma en la primera página de un visitante. El coste: en cada página FOX actualiza el minicarrito una vez, como hace tras un cambio de moneda. - Caché de página y carrito. Una página en caché no ejecuta PHP, así que este código no actualiza la moneda guardada para el visitante. Establece Almacenamiento de moneda (Currency storage) en Transitorio (Transient) y activa Estoy usando un complemento de caché en mi sitio (I am using cache plugin on my site): con esa combinación, el script de FOX copia la moneda de la página en el almacenamiento del visitante, de modo que el carrito y finalizar compra también siguen al idioma. Más información en el selector de moneda vuelve a la moneda por defecto.
Como el selector ya no puede cambiar nada, ocúltalo o muestra solo la moneda del idioma actual. Los visitantes que quieran otra moneda cambian de idioma.
Patrón 2: cambiar con el idioma, conservando el selector
La mayoría de las tiendas quieren algo más suave: un visitante que abre las páginas en alemán recibe euros, todavía puede cambiar a dólares y conserva los dólares mientras navega en alemán. Para eso hay que recordar para qué idioma se fijó la moneda por última vez y actuar solo cuando el idioma cambia. Hacerlo en el navegador tiene dos ventajas: funciona en las páginas en caché y funciona con cualquier plugin de traducción que dé a cada idioma sus propias páginas, porque lee solo el atributo lang de la página.
/*
* 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);
});
Cuando cambia el idioma, el script recarga la página una vez con ?currency=EUR, el mismo parámetro que usa el propio selector de FOX, de modo que FOX guarda la moneda para el visitante. Después, la elección del propio visitante se mantiene hasta que cambie de idioma otra vez. Notas:
- Se usan las dos primeras letras de
lang, así quede-DEyde-ATcuentan ambos comode. Si dos variantes de un mismo idioma necesitan monedas distintas, usa el valor completo en el mapa. - En la primerísima visita todavía no se recuerda nada, así que el script cambia a la moneda del idioma, después de que la moneda de bienvenida y las reglas de GeoIP hayan elegido una. Para que sea GeoIP quien decida la primera moneda, añade
if (last === null) { return; }justo después del bloquetry. - No lo combines con el Patrón 1. El código PHP anularía la elección del visitante en la página siguiente.
GeoIP, la moneda de bienvenida y las listas de monedas por idioma
- Qué regla gana. Con el Patrón 1, el idioma gana en cada página, y las reglas de GeoIP y la Moneda de bienvenida (Welcome currency) dejan de importar. Con el Patrón 2, GeoIP decide la primera moneda solo si añades la línea de primera visita de arriba; después, decide el idioma cada vez que cambia. En ambos casos, Pago por reglas de GeoIP (Checkout by GeoIP rules), si está activado, sigue haciendo que los clientes paguen en la moneda de su país al finalizar la compra; consulta moneda de pago según el país del cliente.
- Oculta una moneda para un idioma. El filtro woocs_currency_manipulation_before_show cambia la lista que muestra cada selector de FOX. Oculta la moneda solo en el selector; no cambia la moneda de un visitante que ya la tiene, de lo cual se encarga el Patrón 1 o el 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 el motivo de una moneda por idioma es el precio en sí, es decir, importes redondeados por mercado y no convertidos, combina la regla de idioma con precios fijos por moneda.
GTranslate y otros traductores del navegador
El widget gratuito de GTranslate, y otros servicios que traducen la página en el navegador, cambian el idioma sin cargar una página nueva. Ninguna petición llega a WordPress, así que ningún código PHP puede reaccionar, y el atributo lang de la página puede que tampoco cambie. Con un traductor así, ninguno de los dos patrones anteriores puede ver el cambio de idioma. Opciones:
- Si tu plan da a cada idioma su propia dirección (un subdirectorio o un subdominio), cada idioma es una carga de página independiente. Revisa el código fuente de una página traducida: si
<html lang="…">muestra el idioma, el Patrón 2 funciona tal cual. - Los proxies de traducción pueden informar a WordPress del idioma mediante una cabecera de la petición; los planes de pago de GTranslate usan
X-GT-LANG, que en PHP se lee como$_SERVER['HTTP_X_GT_LANG']. Imprímela una vez antes de fiarte de ella: si está vacía, tu configuración no la envía, y solo el soporte del proveedor puede decir por qué. - Si no, mantén la moneda independiente del idioma: deja que las reglas de GeoIP elijan la primera moneda y que el selector haga el resto. Consulta cambiar la moneda automáticamente según el país.
Si la moneda no sigue al idioma
- Imprime el valor del idioma y compáralo con las claves de tu mapa, carácter por carácter.
- El selector "no hace nada": el Patrón 1 está activo. Así es como funciona; usa el Patrón 2 si los visitantes deben poder elegir.
- La moneda es correcta un momento y luego vuelve a cambiar: la página vino de una caché y falta la línea
$_GET['currency'], o otro fragmento o plugin también fija la moneda. Buscaset_currencyen el tema y en los plugins de fragmentos. - La página es correcta pero el carrito muestra la moneda anterior: con una caché de página, usa el almacenamiento Transitorio (Transient) con la opción de caché, como se describe en el Patrón 1.
- Un minicarrito personalizado muestra el símbolo nuevo con los importes antiguos: guarda sus propios datos de carrito en caché. Prueba con el minicarrito estándar de WooCommerce para confirmarlo.
- Vacía todas las cachés (plugin, servidor, CDN) después de añadir o cambiar el código, y prueba en una ventana privada.
Si la moneda sigue sin seguir al idioma, abre un tema en el foro de soporte de FOX con el plugin de traducción que usas, tu fragmento y un enlace a dos versiones de idioma de una misma página.