Herramienta
Gravity Forms + WPML: el plugin que traduce los mensajes de validación que se quedan en inglés
Si usted gestiona un WordPress multiidioma con Gravity Forms y WPML, es probable que se haya encontrado con esta escena: el formulario está traducido, las etiquetas están traducidas, los placeholders están traducidos. Y entonces el usuario pulsa enviar sin rellenar un campo obligatorio y aparece un impecable «This field is required.» en mitad de una página en español, en francés o en checo.
Nosotros nos lo encontramos en un proyecto de cliente con formularios en varios mercados. Descartamos la configuración, el caché, el orden de carga y la lista habitual de sospechosos. Resultó que el problema no era del sitio.
Era estructural.
Por ello desarrollamos un mu-plugin que lo resuelve por tres vías distintas y lo hemos liberado como código abierto bajo licencia GPL-2.0, gratuito y sin registro.
¿Qué problema resuelve exactamente este plugin?
Resuelve que los mensajes de validación por defecto de Gravity Forms sigan apareciendo en inglés en todos los idiomas secundarios de un sitio con WPML, aunque el sitio esté bien configurado y aunque Gravity Forms Multilingual (GFML) esté activo.
Los mensajes afectados son siempre los mismos:
- This field is required.
- There was a problem with your submission.
- Please review the fields below.
- Please enter a valid email address.
- Invalid selection. Please select from the available choices.
- Please enter a valid value.
Está claro que no es un fallo que tumbe una web. Pero en un formulario de captación, un mensaje de error en un idioma que el usuario no espera es fricción pura: rompe la confianza justo en el segundo en que le está pidiendo sus datos.
¿Por qué WPML no traduce los mensajes por defecto de Gravity Forms?
Porque Gravity Forms tiene dos tipos de mensaje de validación y solo uno de los dos pasa por WPML. Me explico 🙂
Los mensajes personalizados sí se traducen
Son los que el administrador escribe a mano en cada campo, en el ajuste Custom Validation Message. GFML los registra como cadenas traducibles en WPML String Translation y funcionan sin ningún problema.
Los mensajes por defecto, no
Son los que genera el propio Gravity Forms cuando no hay mensaje personalizado, mediante __(‘This field is required.’, ‘gravityforms’). Estos no pasan ni por WPML ni por GFML: dependen del sistema estándar de traducción de WordPress, es decir, de los archivos .mo.
Y ahí se juntan tres problemas a la vez:
- WPML cambia el idioma dinámicamente en tiempo de ejecución, pero el textdomain de Gravity Forms puede haberse cargado ya en el idioma equivocado.
- No existen archivos .mo oficiales de Gravity Forms para varios locales habituales: checo, griego, rumano o las variantes latinoamericanas del español, por citar cuatro.
- GFML solo engancha el filtro gform_field_validation, que traduce los errorMessage Los mensajes basados en gettext se le escapan.
Básicamente, cada pieza hace bien su trabajo y el resultado sigue siendo un mensaje en inglés. Es un congreso con traducción simultánea impecable en todas las salas, salvo en la de al lado del guardarropa, que resulta ser justo donde el ponente suelta la frase importante.
¿Cómo funciona el sistema de tres capas?
El plugin no apuesta todo a una sola solución. Encadena tres, ordenadas de más a menos prioritaria: si la primera no consigue resolver el mensaje, lo intenta la segunda, y si tampoco, entra la tercera.
Capa 1 — Recarga automática del textdomain
Cuando WPML cambia de idioma (hook wpml_language_has_switched), el plugin descarga el textdomain activo de Gravity Forms con unload_textdomain(), resuelve el locale correcto mediante el filtro wpml_locale y carga el .mo que corresponde desde wp-content/languages/plugins/.
Si el .mo exacto no existe —pongamos es_CL—, prueba con el locale base del idioma —es_ES—.
Lo relevante de esta capa es que no hay diccionario manual. El locale se resuelve desde la propia configuración de WPML, así que funciona con cualquier idioma que usted tenga dado de alta hoy y con cualquiera que dé de alta mañana.
Capa 2 — WPML String Translation como red de apoyo
Si tras la recarga no existe .mo para ese locale, el plugin engancha el filtro gettext e intenta traducir la cadena vía apply_filters(‘wpml_translate_single_string’, …).
¿Qué significa esto en la práctica? Que usted puede traducir los mensajes a mano en WPML → String Translation → contexto gravityforms y el plugin los recogerá. Sin tocar una línea de código.
Capa 3 — Traducciones de emergencia
Como última red, el plugin incorpora traducciones directas de los cuatro mensajes más críticos para 35 idiomas. Solo se activan si las dos capas anteriores han fallado.
Le recomiendo verlo como el airbag del coche: está ahí para que nunca haga falta, no para conducir apoyado en él.
¿Qué mensajes e idiomas cubre la capa de emergencia?
La capa 3 cubre de forma literal estos cuatro mensajes, que son los que aparecen en el 90 % de las validaciones reales:
| Mensaje original | ¿Cubierto en capa 3? |
|---|---|
| This field is required. | Sí |
| There was a problem with your submission. | Sí |
| Please review the fields below. | Sí |
| Please enter a valid email address. | Sí |
| Resto de mensajes por defecto | Vía capas 1 y 2 |
Y los cubre en 35 idiomas: alemán, árabe, búlgaro, catalán, checo, chino, coreano, croata, danés, eslovaco, esloveno, español, euskera, finés, francés, gallego, griego, hebreo, hindi, húngaro, indonesio, italiano, japonés, malayo, neerlandés, noruego, polaco, portugués, rumano, ruso, sueco, tailandés, turco, ucraniano y vietnamita.
¿Cómo se instala el plugin?
- Descargue el archivo amdt-gf-wpml-validation-fix.php desde el repositorio de GitHub.
- Súbalo a la carpeta /wp-content/mu-plugins/ de su instalación. Si esa carpeta no existe, créela.
- Revise los permisos: 644 para el archivo y 755 para la carpeta.
- No active nada. Los mu-plugins se cargan solos.
- Compruébelo en Plugins → Imprescindibles del escritorio de WordPress.
Tiempo total: menos de dos minutos, y sin FTP si tiene acceso al gestor de archivos del hosting.
¿Por qué un mu-plugin y no un plugin normal?
Cuatro razones, y ninguna es capricho:
- No se puede desactivar por accidente desde el escritorio.
- Se carga antes que los plugins normales, que es exactamente donde tiene que estar para interceptar la carga del textdomain.
- Es más resistente frente a cuentas de administrador comprometidas.
- Sobrevive a las actualizaciones de WordPress y del resto de plugins.
He visto sitios multiidioma perder la traducción de sus formularios después de una actualización rutinaria porque alguien había metido el arreglo en el functions.php del tema y el tema se actualizó. Por ello, mu-plugin.
¿Seguirá funcionando si añado un idioma nuevo?
| Escenario | ¿Automático? |
|---|---|
| Idioma nuevo y Gravity Forms tiene .mo para él | Sí — capa 1 |
| Idioma nuevo sin .mo, traducido en WPML String Translation | Sí — capa 2 |
| Idioma nuevo sin .mo, ya incluido en el fallback | Sí — capa 3 |
| Idioma nuevo sin .mo, sin traducir en WPML ST y fuera del fallback | No — se queda en inglés |
Solo el cuarto escenario exige intervención, y ni siquiera obliga a tocar código: basta con traducir la cadena en WPML String Translation.
¿Qué hago si un mensaje sigue apareciendo en inglés?
El plugin no aparece en «Imprescindibles»
Verifique que el archivo está exactamente en /wp-content/mu-plugins/amdt-gf-wpml-validation-fix.php y no dentro de una subcarpeta: WordPress solo lee los .php que cuelgan directamente de mu-plugins/, no escanea subdirectorios. Revise también los permisos.
Un mensaje concreto sigue en inglés
Compruebe si esa cadena está en el array $emergency_fallback del código. Si no está, tiene tres caminos:
- Traducirla en WPML → String Translation, filtrando por el dominio gravityforms. Sin tocar código.
- Añadirla al array de fallback del plugin con sus traducciones.
- Definir un errorMessage personalizado en el editor del campo: ese sí lo traduce GFML con normalidad.
Conflictos con otro código
El plugin registra sus filtros con prioridad 20 y 25 precisamente para ejecutarse después de GFML, que trabaja en prioridad 10. Si usted tiene código propio en prioridad 30 o superior, sobrescribirá la salida del plugin.
Ficha técnica
| Campo | Valor |
|---|---|
| Nombre | GF WPML Validation Messages Fix |
| Identificador | amdt-gf-wpml-validation-fix |
| Versión | 2.0.0 |
| Tipo | mu-plugin (must-use plugin) |
| Licencia | GPL-2.0 o posterior |
| Autor | AMDT — Aún Más Difícil Todavía |
| Requisitos | WordPress · Gravity Forms · WPML (recomendado Gravity Forms Multilingual) |
| Archivos | 1 · amdt-gf-wpml-validation-fix.php |
| Idiomas en fallback | 35 |
| Precio | Gratuito |
| Repositorio | github.com/Consultora-AMDT/amdt-gf-wpml-validation-fix |
Preguntas frecuentes
¿El plugin es gratuito?
Sí. Se publica bajo licencia GPL-2.0 y se descarga directamente desde GitHub, sin registro ni correo electrónico.
¿Necesito Gravity Forms Multilingual (GFML)?
No es imprescindible para que el plugin funcione, pero le recomiendo mantenerlo. GFML traduce los formularios y los mensajes personalizados; este plugin cubre el hueco de los mensajes por defecto. Se complementan, no compiten.
¿Funciona con Polylang o TranslatePress?
No. El plugin se apoya en hooks específicos de WPML, así que fuera de WPML no tiene nada a lo que engancharse.
¿Afecta al rendimiento del sitio?
El plugin cachea internamente el idioma y el locale para no repetir llamadas a WPML dentro de la misma petición. El filtro gettext es el punto más sensible y por eso solo actúa cuando el idioma activo no es el inglés.
¿Puedo instalarlo como plugin normal en vez de mu-plugin?
El código se ejecutaría, sí, pero pierde la garantía de cargarse antes que el resto de plugins, que es media solución. Le recomiendo la ruta mu-plugin.
¿Recibe mantenimiento?
Está publicado en GitHub y las incidencias se reportan en la sección Issues del repositorio.
¿Puedo usarlo en proyectos de cliente?
Sí. La licencia GPL-2.0 permite el uso comercial y la modificación.
Resumiendo
Si tiene un WordPress multiidioma con Gravity Forms y WPML y los mensajes de validación se le quedan en inglés, no es su configuración. Es una costura del sistema por la que se cuelan los mensajes por defecto, y este mu-plugin la cose por tres sitios distintos para que aguante el día que añada el sexto idioma.
Lo hemos liberado porque encontrar la causa real nos costó unas cuantas horas de depuración, y no tiene demasiado sentido que otro equipo repita exactamente el mismo camino.
Recuerde, al final la traducción de una web no se juzga por la portada, sino por el mensaje de error que ve el usuario justo antes de decidir si le da sus datos o cierra la pestaña 😉