Niveau Niveau expert

Traductions multilingues avec Timber

Tutorieldéveloppement

Publié par le (15974 lectures)

wordpress i18n timber international

On l'a vu dans l'article "Pourquoi écrire du Twig dans WordPress ?", Timber est une excellente dépendance pour WordPress faite pour les développeurs.

J'aimerais faire le lien avec l'article "Préparer un thème WordPress pour l'internationalisation", car la syntaxe n'est pas forcément évidente si vous êtes habitués à l'écriture standard de WordPress.

Les bases

Dans l'ensemble, rien de bien plus compliqué qu’avec PHP hormis la syntaxe. On utilise toujours la même fonction WordPress qui est aussi disponible dans Timber.

Voilà un exemple simple avec PHP :

<?php echo __( "Voir toutes les actualités", "textdomain" ); ?>

Et voilà son équivalent avec Timber :

{{ __( "Voir toutes les actualités", "textdomain" ) }}

Jusqu’ici tout va bien, si vous avez l’habitude d’écrire en Twig c’est la même chose.

Abordons maintenant un cas plus spécifique.

Gérer les singuliers et les pluriels

Dans cette partie, on utilisera l'exemple de la barre de recherche, qui est un composant que l'on retrouve fréquemment sur beaucoup de sites et qui est naturellement accompagnée d'une page de résultats, sur laquelle on retrouve une phrase récapitulant le nombre de résultats trouvés et la requête faite par l'utilisateur.

Le formulaire de recherche d'alsacreations.com

Cette dernière est souvent sous la forme : "X résultat(s) trouvé(s) pour le mot Y."

Ce qui induit qu'en fonction du nombre de résultats trouvés, cette phrase peut être au pluriel. Comme toujours, il y a plusieurs méthodes pour réaliser cela et je divulgâche, mais certaines de ces méthodes sont meilleures que d'autres sur plusieurs points.

Première méthode

En tant que développeur, on peut être tenté de gérer l'affichage avec une condition.

Par exemple :

  • Si le résultat de ma recherche est supérieur à 1, j'affiche le pluriel, sinon j'affiche le singulier.
  • J’utilise la fonction sprintf avec les spécificateurs adéquats respectivement pour le nombre de résultats et le terme de recherche.

En PHP, cela donnerait :

<?php if( $search_result > 1 ) : ?>

  <?php
    sprintf(
      __( "%d résultats trouvés pour le mot \"%s\".", "textdomain" ),
        $search_result,
        get_search_query()
    );
  ?>

<?php else : ?>

  <?php
    sprintf(
      __( "%d résultat trouvé pour le mot \"%s\".", "textdomain" ),
        $search_result,
        get_search_query()
      );
  ?>

<?php endif; ?>

Et avec Timber :

{% if search_result|length > 1 %}

  {{
    __( "%d résultats trouvés pour le mot \"%s\".", "textdomain")|format(
      search_result|length,
      fn('get_search_query')
    )
  }}

{% else %}
  {{
    __( "%d résultat trouvé pour le mot \"%s\".", "textdomain" )|format(
      search_result|length,
      fn('get_search_query')
    )
  }}

{% endif %}

C’est la même chose, excepté que l’on remplace un appel de fonction par un filtre.

On y retrouve :

  • Le filtre length sur la variable search_result renvoie le nombre d'éléments.
  • La fonction __() pour les traductions avec le bon textdomain
  • Le filtre format qui est l’équivalent de la fonction sprintf en PHP
  • fn() ou function() qui permet d’utiliser une fonction WordPress ou PHP

Avec cette méthode, si search_result est supérieur à 1, on obtiendra :

2 résultats trouvés pour le mot Burger.

Sinon :

1 résultat trouvé pour le mot Burger.

Parfait, le résultat est comme attendu. Ça fonctionne !

Dans notre outil de traduction (Poedit), on retrouve bien les chaînes de caractères à traduire. Cependant, il y a une chaîne pour gérer le singulier et une pour gérer le pluriel.

Les chaines de traduction dans Poedit

Pourquoi ça ne va pas ?!

  • On se retrouve avec deux traductions à produire, alors que c’est potentiellement la même phrase.
  • S'il y a des cas similaires à traiter sur le site, on aura un fichier de traduction long comme le bras, qui contient pleins de doublons de phrases.
  • Si le fichier doit être fourni à une tierce personne pour la traduction, cela manquera de contexte pour traduire correctement.

Il existe des fonctions faites pour ce genre de cas !

La bonne méthode

Pour avoir des traductions singulier/pluriel propres et optimisées, on utilise la fonction WordPress _n(), qui est un tout-en-un.

Il suffit de lui passer la valeur qui sert de référence et elle s'occupera de choisir d'afficher le singulier ou le pluriel.

Toujours dans l'exemple de page de résultats de recherche, voici comment l'utiliser avec PHP :

<?php
  sprintf(
    _n(
      "%d résultat trouvé pour le mot \"%s\".",
      "%d résultats trouvés pour le mot \"%s\".",
      $search_result,
      "textdomain"
    ),
    $search_result,
    get_search_query()
  );
?>

Et son équivalence avec Timber :

{{
  __(
    _n(
      "%d résultat trouvé pour le mot \"%s\".",
      "%d résultats trouvés pour le mot \"%s\".",
      search_result|length,
      "textdomain"
    )|format(
      search_result|length,
      fn('get_search_query')
    )
  )
}}

Mais c’est plus imbriqué, plus dur à lire/écrire et la finalité est la même ! Alors ça change quoi ? 🤔

Le résultat dans l'outil de traduction est complètement différent !

Un exemple de gestion correcte des pluriels dans Poedit

Pourquoi c’est mieux ? Pourquoi privilégier cette méthode ?

  • Le singulier et le pluriel se retrouvent dans le même champ pour la traduction
  • On apporte plus de contexte et de compréhension
  • On obtient un fichier de traduction optimisé et propre

Et voilà ! Vous avez une bonne pratique supplémentaire à intégrer dès le début du développement de votre thème WordPress avec Timber !

À bientôt pour un prochain article. 🙂

Commentaires

Je rejoins Nicolas sur le point d'attention.

Il suffit de prendre l'anglais "0 comments" pour se rendre compte qu'en anglais le 0 est (parfois) pluriel. Cela ne fait qu'ajouter un argument pour ne pas utiliser la première méthode "if/else" ??

J'ai une question pour Arteast : qu'en est-il des fonctions de traduction et nettoyage de chaîne combinées comme esc_html__() par exemple ?

Merci ?

Bonjour Nicolas et merci pour ton complément d’information !

Je n’ai pas encore rencontré ce genre de cas de figure. Mais il est bon de l’avoir à l’esprit et je ne manquerai pas d'aborder le sujet des pluriels un peu exotiques si c'est une demande que l'on rencontre !

Bonjour Geoffrey !

En effet, l’exemple “if/else” n’est pas la méthode à retenir ici.

Pour ce qui est des fonctions “tout-en-un”, on préfère essayer de se reposer au maximum sur la fonction __() quitte à l'encapsuler dans des appels de fonctions dédiés à l'échappement, dans le but de simplifier la génération des fichiers de traductions.

Ceci dit, c’est disponible aussi avec Timber en tant que filtre.

source : https://timber.github.io/docs/guides/escapers

Commenter

Vous devez être inscrit et identifié pour utiliser cette fonction.

Connectez-vous (déjà inscrit)

Oubli de mot de passe ? Pas de panique, on va le retrouver

Pas encore inscrit ? C'est très simple et gratuit.