Cambiar texto "Añadir cupones" en WooCommerce (clásico y con bloques)

Cambiar texto «Añadir cupones» en WooCommerce (clásico y con bloques)

Hace poco tuve que rehacer la tienda WooCommerce de un cliente, pasando de un sistema clásico basado en un tema comercial y Visual Composer para el contenido, a una solución moderna basada en bloques de WordPress. Para ello tuve que desarrollar un tema FSE desde cero que replicase fielmente el diseño original.

Con algunos contratiempos iniciales, dada la ambición del proyecto, la tienda quedó totalmente migrada. Visualmente todo era igual y, a nivel funcional, también. Sin embargo, tras ponerla online apareció un detalle aparentemente menor. Y es que me pidió cambiar el texto «Añadir cupones» en el carrito y el checkout.

Un ajuste sencillo que había hecho en múltiples ocasiones pero que esta vez, no respondió a la solución habitual que venía usando años atrás.

El problema es que, tras migrar a bloques, esa solución dejó de funcionar, aunque el código fuera correcto. Pero no porque WooCommerce fallara, sino porque el texto ya no se generaba en PHP. Y esto no es una tontería, porque cambia por completo dónde y cómo debe aplicarse la solución.

Teniendo en cuenta esto, se me ha ocurrido que sería buena idea hacer un artículo y así abordar esta cuestión para quien le pueda ser de utilidad.

¿Carrito clásico o carrito con bloques?

Antes de pasar a la acción, hay que pararse en ver qué sistema usa actualmente la tienda en la que queremos cambiar el texto. Este punto es clave, porque la solución depende completamente de cómo esté construido el carrito y el checkout.

Lo primero que debemos tener en cuenta es que hay dos vías de implementar este cambio en función del tipo de tienda que tengamos.

Hagamos un repaso rápido para que puedas identificar la arquitectura con la que está desarrollado tu ecommerce:

  • Sistema clásico
    Plantillas PHP, shortcodes ([woocommerce_cart], [woocommerce_checkout]), archivos como form-coupon.php.
  • Sistema con bloques (WooCommerce Blocks / FSE)
    Carrito y checkout editables desde el editor de bloques o el editor del sitio. Renderizado en JavaScript.

Si puedes editar el carrito desde el editor del sitio, estás usando bloques. Si no, con toda probabilidad estás usando el sistema clásico.

WooCommerce clásico (sin bloques)

Cuando alguien quiere cambiar un texto en WooCommerce, la reacción lógica es usar gettext. Durante años, esa ha sido la solución correcta y por eso es la que se ha venido utilizando en este caso.

El texto «Añadir cupones» procede originalmente del string en inglés «Add a coupon», y en un sistema clásico pasa por el sistema de traducciones de WordPress, así que interceptarlo es trivial.

Solución normal

El texto se genera en PHP, pasa por el dominio de traducciones de WooCommerce y gettext hace exactamente lo que debe. Con el siguiente snippet capturamos el texto y lo remplazamos por el que queramos.

add_filter( 'gettext_woocommerce', function( $translated, $text, $domain ) {

    // Cadenas originales en inglés utilizadas por WooCommerce (sistema clásico)
    $targets = array( 'Add a coupon', 'Add coupon' );

    if ( in_array( $text, $targets, true ) ) {
        // Texto personalizado que se mostrará en el carrito y checkout
        return '¿Tienes un cupón?';
    }

    return $translated;

}, 10, 3 );

Recuerda que este código no funciona en carrito y checkout con bloques. Para ello encontrarás una solución específica más abajo.

Compatible con WPML

Puede que tu tienda esté traducida a varios idiomas y uses WPML para ello. En ese caso puedes usar este otro snippet que te garantizará compatibilidad con el plugin. Puedes añadir tantos idiomas como necesites, solo debes personalizar la parte correspondiente.

add_filter( 'gettext_woocommerce', function( $translated, $text, $domain ) {

    // Cadenas originales en inglés utilizadas por WooCommerce (sistema clásico)
    $targets = array( 'Add a coupon', 'Add coupon' );

    if ( in_array( $text, $targets, true ) ) {

        // Obtenemos el idioma actual a través de WPML (devuelve 'es', 'en', etc.)
        $lang = apply_filters( 'wpml_current_language', null );

        // Personaliza el texto por idioma
        if ( $lang === 'es' ) {
            return '¿Tienes un cupón?';
        }

        if ( $lang === 'en' ) {
            return 'Have a discount code?';
        }

        // Idioma no contemplado: devolvemos el texto por defecto que prefieras
        return 'Have a discount code?';
    }

    return $translated;

}, 10, 3 );

WooCommerce con bloques

En el sistema moderno de bloques, el carrito y el checkout se renderizan en JavaScript (React). Eso implica que el texto no pasa por PHP y no atraviesa gettext.

En otras palabras, si el texto se genera en el navegador, hay que interceptarlo en el navegador y por tanto la lógica a emplear debe ser diferente al visto anteriormente.

Solución normal

La alternativa moderna a gettext es el sistema de filtros de i18n en JavaScript, concretamente i18n.gettext.

Con este script interceptaremos el texto original, comprobaremos tanto dominio como la cadena y, por último, devolveremos el texto personalizado según el idioma activo.

add_action( 'wp_enqueue_scripts', function () {

    // Solo cargamos esto en Carrito o Checkout
    if ( function_exists('is_cart') && ( is_cart() || is_checkout() ) ) {

        // Registramos un script “vacío” para poder inyectar código inline con dependencias correctas
        wp_register_script(
            'my-wcblocks-i18n-overrides',
            false,
            array( 'wp-i18n', 'wp-hooks' ), // Paquetes de i18n y filtros en JS
            null,
            true
        );

        // Inyectamos el filtro JS que sustituye el texto en los bloques de WooCommerce
        wp_add_inline_script(
            'my-wcblocks-i18n-overrides',
            <<<JS
(function(){
    var addFilter = wp.hooks.addFilter;

    // Intercepta traducciones en JavaScript antes de renderizarse
    addFilter('i18n.gettext','my/override-coupon', function( translated, text, domain ){

        // Dominios típicos de WooCommerce y sus bloques
        var domains = ['woocommerce','woocommerce-blocks','woo-gutenberg-products-block'];

        // Cadenas originales (en inglés) que suelen corresponder al bloque de cupones
        var targets = ['Add a coupon','Add coupon','Add coupons','Add a coupon code'];

        if ( domains.indexOf(domain) !== -1 && targets.indexOf(text) !== -1 ) {
            // Texto personalizado (sin lógica de idiomas)
            return '¿Tienes un cupón?';
        }

        return translated;
    });
})();
JS
        );

        // Cargamos el script
        wp_enqueue_script( 'my-wcblocks-i18n-overrides' );
    }

}, 20 );

Aclarar que esto no modifica archivos de traducción, funciona al vuelo sobre el navegador. Así que si te preocupa romper WooCommerce no hay ningún problema.

Compatible con WPML

En caso de que uses en tu tienda WooCommerce el plugin WPML para las traducciones y que quieras cambiar el texto «Añadir cupones» en cada uno de los idiomas que tengas, el script debemos modificar el script por el siguiente.

add_action( 'wp_enqueue_scripts', function () {

    // Solo cargamos esto en Carrito o Checkout
    if ( function_exists('is_cart') && ( is_cart() || is_checkout() ) ) {

        // Registramos un script “vacío” para poder inyectar código inline con dependencias correctas
        wp_register_script(
            'my-wcblocks-i18n-overrides',
            false,
            array( 'wp-i18n', 'wp-hooks' ), // Paquetes de i18n y filtros en JS
            null,
            true
        );

        // Obtenemos el idioma actual desde WPML (devuelve 'es', 'en', etc.)
        $lang = apply_filters( 'wpml_current_language', null );

        // Pasamos el idioma a JavaScript
        wp_add_inline_script(
            'my-wcblocks-i18n-overrides',
            'window.__MY_LANG__ = ' . wp_json_encode( $lang ?: 'en' ) . ';'
        );

        // Inyectamos el filtro JS que sustituye el texto en los bloques de WooCommerce
        wp_add_inline_script(
            'my-wcblocks-i18n-overrides',
            <<<JS
(function(){
    var addFilter = wp.hooks.addFilter;

    // Intercepta traducciones en JavaScript antes de renderizarse
    addFilter('i18n.gettext','my/override-coupon', function( translated, text, domain ){

        // Dominios típicos de WooCommerce y sus bloques
        var domains = ['woocommerce','woocommerce-blocks','woo-gutenberg-products-block'];

        // Cadenas originales (en inglés) que suelen corresponder al bloque de cupones
        var targets = ['Add a coupon','Add coupon','Add coupons','Add a coupon code'];

        if ( domains.indexOf(domain) !== -1 && targets.indexOf(text) !== -1 ) {

            // Idioma actual (WPML) o, si fallase, el atributo lang del HTML
            var lang = (window.__MY_LANG__ || (document.documentElement.lang||'en').slice(0,2)).toLowerCase();

            // Personaliza el texto por idioma
            if (lang === 'es') {
                return '¿Tienes un cupón?';
            }

            if (lang === 'en') {
                return 'Have a discount code?';
            }

            // Idioma no contemplado: usa el texto por defecto que prefieras
            return 'Have a discount code?';
        }

        return translated;
    });
})();
JS
        );

        // Cargamos el script
        wp_enqueue_script( 'my-wcblocks-i18n-overrides' );
    }

}, 20 );

Dos sistemas, dos soluciones

Debo comentar que la solución correcta dependerá del sistema que estés utilizando. Desde un punto de vista meramente técnico, no hay una mejor que otra, sino que cada una atiende a un momento y arquitectura diferentes.

Desde hace bastantes años, el método clásico ha sido el único posible a la hora de crear una tienda online y no es hasta la llegada de Gutenberg cuando las cosas empiezan a cambiar.

Si aún no lo tienes claro, quédate con la siguiente tabla que puede ayudarte a terminar de afianzar mejor todo lo que hemos visto. Sencillamente recuerda que el texto se genera en lugares diferentes.

SistemaDónde se genera el textoSolución
ClásicoPHPgettext
BloquesJavaScripti18n.gettext

Para finalizar, como desarrollador de tiendas WooCommerce, puedo decirte que en este momento WordPress está en una fase de transición en la que conviven ambos mundos, y durante bastante tiempo seguiremos encontrándonos con este tipo de situaciones.

Jesús Tovar - Desarrollador web freelance Sevilla

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *