Cómo imprimir texto con soporte de traducción incluyendo URL HTML

18 mar 2017, 06:28:20
Vistas: 13.5K
Votos: 9

Soy relativamente nuevo en WordPress cuando se trata de personalizaciones más avanzadas.

Actualmente tengo esta función:

esc_html_e( 'Estimado huésped, con su información no encontramos habitaciones disponibles en este momento. Por favor contáctenos por email info@whitesandsamuiresort.com.', 'awebooking' );

Y el texto se muestra correctamente hasta ahora.

Pero ¿qué función necesito usar cuando quiero agregar un enlace a href (enlace HTML)?

Quiero tener este texto:

Estimado huésped, con su información no encontramos habitaciones disponibles en este momento.

Por favor contáctenos en nuestra <a href="http://www.whitesandsamuiresort.com/contact-us/">página de contacto</a> o por email info@whitesandsamuiresort.com.

Tengo problemas para compatibilizar la traducción (internacionalización/localización) y el escape de enlaces HTML al mismo tiempo.

0
Todas las respuestas a la pregunta 3
3

Dado que esc_html_e escapará el enlace HTML (mostrando así el ancla HTML como texto plano), necesitarás segmentar el texto y escapar la parte no-HTML con esc_html_e o esc_html__, e imprimir la parte del ENLACE HTML sin escapado HTML.

Método-1 (solo para tu comprensión):

Puedes hacerlo por partes, así:

esc_html_e( 'Estimado Invitado, con su información no pudimos encontrar ninguna habitación disponible en este momento.', 'text-domain' );
echo "<br><br>";

printf(
    esc_html__( '%1$s %2$s', 'text-domain' ),
    esc_html__( 'Por favor contáctenos en nuestra', 'text-domain' ),
    sprintf(
        '<a href="%s">%s</a>',
        esc_url( 'http://www.example.com/contactanos/' ),
        esc_html__( 'Página de Contacto', 'text-domain' )
    )
);

printf(
    ' o <a href="%s">%s</a>',
    esc_url( 'mailto:info@example.com', array( 'mailto' ) ),
    esc_html__( 'Correo Electrónico', 'text-domain' )
);

Método-2 (solo para tu comprensión):

Obviamente, diferentes idiomas tendrán diferentes órdenes de textos, así que para dar más flexibilidad a los traductores (con el escapado y orden del texto), puedes hacerlo de la siguiente manera:

printf(
    esc_html__( '%1$s%2$s%3$s%4$s%5$s', 'text-domain' ),
    esc_html__( 'Estimado Invitado, con su información no pudimos encontrar ninguna habitación disponible en este momento.', 'text-domain' ),
    nl2br( esc_html__( "\n\n", 'text-domain' ) ),
    sprintf(
        esc_html__( '%1$s %2$s', 'text-domain' ),
        esc_html__( 'Por favor contáctenos en nuestra', 'text-domain' ),
        sprintf(
            '<a href="%s">%s</a>',
            esc_url( 'http://www.example.com/contactanos/' ),
            esc_html__( 'Página de Contacto', 'text-domain' )
        )
    ),
    esc_html__( ' o ', 'text-domain' ),
    sprintf(
        '<a href="%s">%s</a>',
        esc_url( 'mailto:info@example.com', array( 'mailto' ) ),
        esc_html__( 'Correo Electrónico', 'text-domain' )
    )
);

Esta forma de hacerlo:

  1. Escapa todos los textos traducidos necesarios.

  2. Permite el HTML para enlaces, correos (con sintaxis mailto:) etc.

  3. Permite a los traductores tener todo tipo de órdenes diferentes de textos para distintos idiomas. La notación de intercambio de argumentos (%1$s, %2$s etc.) se usa para que los traductores puedan reordenar el texto traducido cuando sea necesario.


Método-3 (Actualizado y Recomendado):

Como @shea señaló correctamente, el Método-2 funciona bien, pero puede ser difícil para los traductores agregar soporte para diferentes idiomas. Así que necesitamos una solución que:

  1. Mantenga las oraciones intactas (no las fragmente).

  2. Haga el escapado correcto.

  3. Proporcione formas de tener diferentes órdenes para enlaces de contacto y correo electrónico (o algo similar) dentro de la oración traducida.

Para evitar la complicación del método-2, la solución a continuación mantiene las oraciones traducibles intactas y realiza el escapado de URL y el intercambio de argumentos al mismo tiempo (más notas dentro de los comentarios del CÓDIGO):

// URL de contacto de ejemplo (puede provenir de un lugar inseguro como entrada de usuario)
$contact_url = 'http://www.example.com/contactanos/';
// escapando $contact_url
$contact_url = esc_url( $contact_url );

// correo de contacto de ejemplo (puede provenir de un lugar inseguro como entrada de usuario)
$contact_email = 'info@example.com';
// escapando, sanitizando y ocultando $contact_email.
// Sí, aún puedes necesitar sanitizar y escapar el correo electrónico al usar la función antispambot()
$contact_email = esc_url( sprintf( 'mailto:%s', antispambot( sanitize_email( $contact_email ) ) ), array( 'mailto' ) );

esc_html_e( 'Estimado Invitado, con su información no pudimos encontrar ninguna habitación disponible en este momento.', 'text-domain' );
echo "<br><br>";

printf(
    esc_html__( 'Por favor contáctenos en nuestra %1$s o por %2$s.', 'text-domain' ),
    sprintf(
        '<a href="%s">%s</a>',
        $contact_url,
        esc_html__( 'Página de Contacto', 'text-domain' )
        ),
    sprintf(
        '<a href="%s">%s</a>',
        $contact_email,
        esc_html__( 'Correo Electrónico', 'text-domain' )
        )
    );

Esta forma de hacerlo dará a los traductores dos oraciones completas y dos palabras separadas para traducir. Así, un traductor solo tendrá que preocuparse por las siguientes líneas simples (mientras que el CÓDIGO se encarga del resto):

esc_html_e( 'Estimado Invitado, con su información no pudimos encontrar ninguna habitación disponible en este momento.', 'text-domain' );
// ...
esc_html__( 'Por favor contáctenos en nuestra %1$s o por %2$s', 'text-domain' )
// ...
esc_html__( 'Página de Contacto', 'text-domain' )
// ...
esc_html__( 'Correo Electrónico', 'text-domain' )

Eso es todo, estructura simple que hace el escapado correcto y también permite el intercambio de argumentos.


Lee más sobre internacionalización para temas y internacionalización para plugins.

18 mar 2017 12:53:29
Comentarios

No estoy muy seguro de qué tan bien funcionaría el segundo ejemplo para todos los idiomas, como aquellos que usan una estructura de oración diferente al inglés. ¿No sería mejor no dividir oraciones o separar palabras?

shea shea
23 mar 2017 09:07:24

@shea No estoy seguro de lo que preguntas, pero, por ejemplo, incluso esta línea esc_html__( '%1$s%2$s%3$s%4$s%5$s', 'text-domain' ) puede cambiarse a %3$s%2$s%1$s%4$s%5$s con una traducción. Esta flexibilidad de orden debería cubrir diferentes estructuras de lenguaje.

Fayaz Fayaz
23 mar 2017 09:17:01

No todos los idiomas tienen una sola palabra para "o", o formularían cosas como "Por favor contáctenos en nuestro <link>". Lo que digo es que un método mejor sería proporcionar oraciones o frases completas para traducir, y luego dejar que los traductores hagan lo necesario para traducir esto. El método de intercambio de argumentos parece excesivamente complicado e ineficaz

shea shea
23 mar 2017 14:31:47
3

Creo que la respuesta de @Fayaz es muy buena; definitivamente están en el camino correcto al sugerir usar sprintf() junto con las traducciones para incluir elementos como HTML y enlaces.

Sin embargo, no creo que sea una buena idea dividir las oraciones en partes para la traducción, ya que muchos idiomas tienen estructuras de oraciones completamente diferentes al inglés. Al separar palabras individuales, se pierde gran parte del contexto en el que se traduce una palabra específica, lo que puede llevar a ambigüedades y errores de traducción.

En su lugar, recomiendo traducir frases y oraciones completas, y luego usar sprintf o diferentes funciones de escape cuando sea apropiado.

Para tu texto, la primera parte puede simplemente traducirse por sí misma con esc_html_e:

esc_html_e( 'Estimado Invitado, con su información no encontramos ninguna habitación disponible en este momento. ', 'text-domain' );

La segunda parte es un poco más compleja. Asumo que estás obteniendo la URL de la página y el correo electrónico de la base de datos de alguna manera, probablemente usando get_the_permalink() o get_option() u otra función. Así que voy a asumir que están almacenados en las variables $contact_page_url y $contact_email.

El primer paso es traducir el texto sin los enlaces. Nota que debemos usar __() sin escape en este punto - eso vendrá después.

__( 'Por favor contáctenos en nuestra <a href="%1$s">página de contacto</a> o por correo electrónico %2$s.', 'text-domain' );

De esta manera el traductor tiene libertad para estructurar la oración como sea necesario y colocar la URL del enlace y el correo donde corresponda.

El siguiente paso es usar sprintf() para insertar la URL del enlace y el correo. Nota que usamos esc_url() aquí para escapar la URL, y también antispambot() para codificar la dirección de correo y brindar protección mínima contra scrapers:

$text = sprintf(
    __( 'Por favor contáctenos en nuestra <a href="%1$s">página de contacto</a> o por correo electrónico %2$s.', 'text-domain' ),
    esc_url( $contact_page_url ),
    sprintf( '<a href="mailto:%1$s">%1$s</a>', antispambot( $contact_email ) )
);

Finalmente, en lugar de usar esc_html(), necesitamos usar wp_kses() para permitir solo elementos de enlace en el HTML traducido:

echo wp_kses( $text, array( 'a' => array( 'href'  => array() ) );

¡Y eso es todo! El código final es:

esc_html_e( 'Estimado Invitado, con su información no encontramos ninguna habitación disponible en este momento. ', 'text-domain' );

$text = sprintf(
    __( 'Por favor contáctenos en nuestra <a href="%1$s">página de contacto</a> o por correo electrónico %2$s.', 'text-domain' ),
    esc_url( $contact_page_url ),
    sprintf( '<a href="mailto:%1$s">%1$s</a>', antispambot( $contact_email ) )
);

echo wp_kses( $text, array( 'a' => array( 'href'  => array() ) );
26 mar 2017 07:14:42
Comentarios

Me gusta tu idea de wp_kses. Sin embargo, hay dos puntos (1) un traductor puede agregar enlaces adicionales dentro de la traducción y tu CÓDIGO no lo evitará. (2) un traductor tendrá que proporcionar HTML, es decir, <a href="%1$s">..</a> dentro de la traducción. Puede que no quieras eso, ya que podrían cometer errores al manejar incluso la etiqueta HTML más simple como <a>.

Fayaz Fayaz
1 abr 2017 16:57:17

Tienes razón @Fayaz, esos son puntos válidos. Si crees que son los más importantes, entonces quizás prefieras usar una solución diferente :)

shea shea
2 abr 2017 06:01:21

+1 por algunos buenos puntos. Ya que tu solución tiene esos problemas, he actualizado mi solución (Método-3) con una estructura más simple esta vez.

Fayaz Fayaz
2 abr 2017 09:10:20
1
-2

Si estás utilizando esc_html_e, esta función simplemente indica que escapa las etiquetas HTML. Por lo tanto, no podrás utilizar etiquetas HTML dentro de esta función esc_html_e.

18 mar 2017 07:28:45
Comentarios

el OP pregunta explícitamente qué función debería usar, sabe que esta es la incorrecta ;)

Mark Kaplun Mark Kaplun
18 mar 2017 09:50:33