Catégories
DĂ©veloppement WordPress

🌎Blog bilingue avec Polylang : afficher les articles originaux dans les listings s’ils n’ont pas de traduction dans la langue courante

❓Le problùme

La question fut initialement posée par Pascal Birchler, Core committer de WP et développeur chez Google.

Avec Polylang, comment requĂȘter les articles sur toutes les langues mais n’afficher qu’une seule version de l’article (celle de la langue du visiteur) si celui-ci dispose de multiples traductions

Ça tombe bien, j’ai eu le mĂȘme besoin sur mon site personnel 🙂

L’idĂ©e, c’est donc d’afficher TOUS les articles sur la page de liste des articles du blog.

  • Si l’article est disponible dans la langue courante (= celle avec laquelle le visiteur consulte le site), alors afficher cet article dans la langue courante et ne pas afficher les autres traductions de l’article.
  • Si l’article n’est pas disponible dans la langue courante, alors afficher une langue alternative.
  • Bonus : rendre cela le plus accessible possible 😌

đŸ’„La solution

Dans notre fichier functions.php, modifions la requĂȘte principale pour supprimer les paramĂštres de Polylang. Ainsi, tous les articles et leurs traductions seront affichĂ©s sur la page du blog.

/*
 * Query all posts versions on home page.
 */
function jba_modify_home_query( $query ) {
	if ( function_exists( 'pll__' ) && ! is_admin() && is_home() ) {
		$query->set('tax_query', '');
		$query->set('lang', '');
	}
}
add_action( 'pre_get_posts', 'jba_modify_home_query' );

Petit dĂ©tail des conditions utilisĂ©es avant d’altĂ©rer la requĂȘte :

  • la fonction pll__() doit exister (sinon, ça veut dire que Polylang n’est pas installĂ© donc notre blog n’est pas multilingue !)
  • nous nous situons en front-end (donc pas sur WP Admin)
  • nous sommes sur la page d’accueil du blog

Maintenant, c’est parti pour modifier un peu la boucle du fichier home.php.

Disons que nous avons la boucle (volontairement simplifiĂ©e) suivante :

<?php if ( have_posts() ) : ?>
	<?php while ( have_posts() ) : the_post(); ?>
		<article id="post-<?php the_ID(); ?>">
			<h2 class="entry-title">
				<a href="<?php the_permalink(); ?>">
					<?php the_title(); ?>
				</a>
			</h2>
			<div class="entry-content excerpt-home">
				<?php the_excerpt(); ?>
			</div>
		</article>
	<?php endwhile; ?>
<?php endif; ?>

Juste aprĂšs l’ouverture du while (ligne 2), ajoutons les instructions suivantes :

<?php
if ( pll_get_post( get_the_ID() ) && get_the_ID() !== pll_get_post( get_the_ID() ) ) {
	continue;
}
?>

Avec ce code, nous allons vĂ©rifier si l’article courant de la boucle est une traduction d’un article qui existe dans la langue courante du visiteur. Si oui, nous utilisons l’instruction continue pour ignorer les instructions suivantes dans la boucle while. Ainsi, l’article traduit ne sera pas affichĂ© du tout (car il existe dans la langue courante dans laquelle le site est actuellement consultĂ©).

Et c’est tout pour la partie fonctionnelle ! Nous avons maintenant un blog bilingue oĂč les articles sont affichĂ©s en premier lieu dans la langue du visiteur, et pour lesquelles nous proposons une langue alternative s’ils aucune traduction n’existe dans la langue du visiteur ! 🙌

Cependant, ce n’est pas trĂšs accessible, puisque nous avons tantĂŽt un article dans une langue, tantĂŽt dans une autre, sans donner d’information au visiteur (ou aux moteurs d’indexation) sur la langue concernĂ©e.

☝HĂ© ho, je veux que ce soit accessible !

TrĂšs bien, prĂ©parons donc dĂ©jĂ  quelques trucs qui seront utiles pour afficher des informations sur la langue des articles qui ne sont disponibles que d’en d’autres langues que celle du visiteur :

<?php
$lang_attribute = '';
$lang_title = '';
$lang_slug = pll_get_post_language( get_the_ID(), 'slug' );
$lang_name = pll_get_post_language( get_the_ID(), 'name' );
if ( pll_current_language() !== $lang_slug ) {
	$lang_attribute = 'lang="' . $lang_slug . '"';
	$lang_title = '<span aria-label="(' . $lang_name . ')">[' . strtoupper( $lang_slug ) . ']</span> ';
}
?>

Avec ce bout de code, je vais remplir deux variables (uniquement si l’article remontĂ© par la boucle n’est pas dans la langue courante) :

  • $lang_attribute : cette variable contiendra quelque chose comme lang="en" qui sera ainsi ajoutĂ© dans l’Ă©lĂ©ment <article>, ce qui donnera : <article lang="en">. C’est utile pour les moteurs, et obligatoire pour les technologies d’assistance telles que les lecteurs d’Ă©crans (pour que la vocalisation puisse basculer sur la langue de l’article).
  • $lang_title : cette variable contiendra un texte pour indiquer visuellement la langue de l’article dans le titre de cet article. Exemple : « [EN] My post title ». Je l’ai placĂ© dans un Ă©lĂ©ment <span> avec un attribut aria-label pour utiliser un label complet afin que les lecteurs d’Ă©crans puisse lire « Anglais » Ă  la place de « EN ».

Ensuite, il suffit d’utiliser tout ça dans le code HTML vu prĂ©cĂ©demment :

<article id="post-<?php the_ID(); ?>" <?php echo $lang_attribute; ?>>
	<h2 class="entry-title">
		<a href="<?php the_permalink(); ?>">
			<?php echo $lang_title; ?><?php the_title(); ?>
		</a>
	</h2>
	<div class="entry-content excerpt-home">
		<?php the_excerpt(); ?>
	</div>
</article>

Et voilĂ  les amis !

Pour voir un exemple de tout ça, vous pouvez tout simplement visiter ma page d’accueil 😃

🌼Demandez le bout de code complet, Ă  emporter !

Dans functions.php :

/*
 * Query all posts versions on home page.
 */
function jba_modify_home_query( $query ) {
	if ( function_exists( 'pll__' ) && ! is_admin() && is_home() ) {
		$query->set('tax_query', '');
		$query->set('lang', '');
	}
}
add_action( 'pre_get_posts', 'jba_modify_home_query' );

Dans home.php :

<?php if ( have_posts() ) : ?>
		
	<?php while ( have_posts() ) : the_post(); ?>
		
		<?php
		if ( pll_get_post( get_the_ID() ) && get_the_ID() !== pll_get_post( get_the_ID() ) ) {
			// Do not display other languages posts if a translation in the current language exists.
			continue;
		}
		$lang_attribute = '';
		$lang_title = '';
		$lang_slug = pll_get_post_language( get_the_ID(), 'slug' );
		$lang_name = pll_get_post_language( get_the_ID(), 'name' );
		if ( pll_current_language() !== $lang_slug ) {
			$lang_attribute = 'lang="' . $lang_slug . '"';
			$lang_title = '<span aria-label="(' . $lang_name . ')">[' . strtoupper( $lang_slug ) . ']</span> ';
		}
		?>
		<article id="post-<?php the_ID(); ?>" <?php echo $lang_attribute; ?>>
			<h2 class="entry-title">
				<a href="<?php the_permalink(); ?>">
					<?php echo $lang_title; ?><?php the_title(); ?>
				</a>
			</h2>
			<div class="entry-content excerpt-home">
				<?php the_excerpt(); ?>
			</div>
		</article>
	<?php endwhile; ?>

<?php endif; ?>

Maintenant, il vous suffit d’adapter ces bouts de code pour vos besoins. N’hĂ©sitez pas Ă  commenter ci-dessous si vous avez des questions ou si vous utilisez cette solution sur votre site !

Ou mĂȘme si vous utilisez une solution diffĂ©rente (et peut-ĂȘtre meilleure !) 💜💬

Mentions légales