Exploiter les langues avec les pseudo-classes CSS

Vous connaissez certainement la technique CSS permettant d’afficher la langue d’un lien après le texte du lien. Elle repose sur l’utilisation d’un sélecteur d’attribut, en l’occurrence l’attribut hreflang qui sert à spécifier la langue du document cible.

Méthode de base

La méthode la plus simple consiste tout simplement à récupérer la valeur de l’attribut hreflang et à l’ajouter à la suite du texte du lien, avec un peu de formatage entre parenthèses ou entre crochets.

Exemple CSS :

a[hreflang]:after {
	color:#666;
	font-style:italic;
	content: "\A0("attr(hreflang)")";
}

On peut aller plus loin en ajoutant des règles spécifiques pour certaines langues et afficher un texte plus humain. On utilisera alors la pseudo-classe :after pour spécifier le nom de la langue au lieu de la valeur de l’attribut hreflang.

Exemple CSS :

a[hreflang='en']:after {
	content:"\A0(en anglais)";
}
a[hreflang='fr']:after {
	content:"\A0(en français)";
}
a[hreflang='pt-br']:after {
	content:"\A0(en portugais brésilien)";
}

Il vaut mieux conserver la première règle pour récupérer les valeurs d’attribut hreflang des langues qui ne sont pas prévues dans les autres règles.

Il y a toutefois un problème avec cette technique : les langues sont exprimées dans une langue particulière, ce qui peut poser problème pour un site multilingue. Si par exemple votre page est écrite en anglais, afficher  (en français) à la suite d’un lien ne sera probablement pas très utile pour votre lectorat, en tout cas ni logique ni naturel. Il serait préférable d’afficher  (in French).

Méthode avancée

Mais il existe une solution pour conserver la même feuille de styles pour plusieurs langues en utilisant les attributs lang ou xml:lang (voir plus bas le problème d’Opera).

Cette solution fait appel à la pseudo-classe :lang() de la spécification CSS (traduction française). Elle permet de cibler sélectivement tous les éléments en fonction de leur langue ou de la langue dont ils ont hérité.

Par exemple si vous avez déclaré le français comme langue du document (quelle que soit la langue du document vous devriez la déclarer dans la balise html avec l’attribut lang pour les pages HTML et xml:lang pour les pages XHTML [1].), vous pourrez définir les guillemets appropriés au français.

Exemple CSS :

:lang(fr) {
	quotes:"\AB\A0" "\A0\BB" "\201C\A0" "\A0\201D";
}

Vous pouvez donc également spécifier un contenu différent en fonction de la langue.

Exemple CSS :

/* Règles pour le français */
:lang(fr) > a[hreflang='en']:after {
	content:"\A0(en anglais)";
}
:lang(fr) > a[hreflang='fr']:after {
	content:"";
}
:lang(fr) > a[hreflang='pt-br']:after {
	content:"\A0(en portugais brésilien)";
}

/* Règles pour l'anglais */
:lang(en) > a[hreflang='en']:after {
	content:"";
}
:lang(en) > a[hreflang='fr']:after {
	content:"\A0(in French)";
}
:lang(en) > a[hreflang='pt-br']:after {
	content:"\A0(in Brazilian Portuguese)";
}

NB : N'oubliez pas le >, qui permet de cibler les enfants ; un simple espace devrait cibler tous les descendants mais ne fonctionnera pas.

L’avantage de cette méthode est qu'on peut éviter d’afficher la langue de la cible lorsqu’elle est identique à la langue du document (ou de l’élément, ou de son parent, etc.), même si elle est spécifiée dans l'attribut hreflang : inutile d’avertir un francophone qu’il va visiter une page en français. Il suffit pour cela de spécifier un contenu vide pour la valeur hreflang correspondant à la langue de la pseudo-classe :lang().

Voir l’exemple complet (lien direct vers la feuille de style).

Problèmes connus

Rien de tout cela ne fonctionne sous Internet Explorer.

Il existe aussi un problème avec Opera lorsque la page est servie en tant que XHTML, c’est-à-dire avec le type MIME approprié : application/xhtml+xml.

En XHTML 1.1 (qui proscrit l’utilisation de l’attribut lang et n’autorise que xml:lang), le résultat est sans appel : toutes les règles spécifiées avec la pseudo-classe :lang() sont ignorées dans Opera, alors que Firefox s’en tire aussi bien qu’en HTML (c’est-à-dire parfaitement).

En XHTML 1.0, avec à la fois lang et xml:lang, le résultat est encore pire, il y a apparemment un mélange de règles dévastateur pour Opera (alors qu’encore une fois, Firefox s’en sort impeccablement).

Le même exemple en XHTML 1.1

Note : la feuille de styles est la même pour les deux documents.

Je ne sais pas si le comportement d’Opera est lié à une interprétation plus stricte de la pseudo-classe :lang() (serait-il légitime de n’appliquer :lang() qu’à l’attribut lang, à l’exclusion de xml:lang ?). Peut-être faut-il chercher du côté des espaces de nommage CSS…

[Mise à jour] : Ted Drake donne un autre exemple d’utilisation de ces techniques, et ajoute l’information sur le pays, présente dans les codes pays composés (comme fr-ca, fr-be ou fr-fr qui se réfèrent tous à la même langue de base mais à trois pays différents) avec des drapeaux.

[Mise à jour] : Il semble qu’Opera 9[2] supportera finalement le sélecteur :lang() pour les pages XHTML (avec l’attribut xml:lang). Le changelog pour Opera 9.0 Technology Preview 1 pour Windows annonce à la rubrique selectors :

:lang() selector no longer applies to xml:lang attributes.

En français :

Le sélecteur :lang() n’est plus appliqué aux attributs xml:lang.

Là encore Anne van Kesteren nous éclaire sur ce point dans les commentaires de son article sur Opera 9

What I think that the release notes meant to say was that as we do no longer support namespaces in HTML (as in text/html) xml:lang is no longer recognized in text/html as a "lang" kind of attribute and therefore is not used for :lang() based matching. Unless it really is in a namespace which can only be done through the DOM for text/html documents.

En français :

La façon dont je comprends cette note est que puisque nous ne supportons plus les espaces de nommage en HTML (comme pour text/html), xml:lang n’est plus reconnu en HTML comme une sorte d’attribut « lang Â» est n’est donc pas utilisé pour la correspondance avec :lang(). Sauf si c’est effectivement dans un espace de nommage, ce qui ne peut être réalisé qu’à travers le DOM pour les documents text/html.

Confirmation dans Opera 9 avec ce document.

Mais cela n'empêche pas, bien au contraire, Opera 9 de supporter xml:lang pour les documents XHTML servis avec un type MIME XML (de préférence application/xhtml+xml) qui sont, eux, dans le bon espace de nommage pour cet attribut.

La preuve : L’exemple XHTML fonctionne sous Opera 9 !

Les documents XHTML servis avec le type MIME text/html qui suivent les règles de compatibilité de l’Annexe C de la spécification XHTML 1.0 (traduction française), auront nécessairement à la fois les attributs lang et xml:lang et fonctionneront donc toujours comme sous Opera 8. Confirmation dans Opera 9 avec ce document.

Notes :

  1. Ou les deux pour les pages écrites en XHTML mais envoyées en tant que HTML suivant les recommandations de l’Annexe C de XHTML 1.0 (traduction française). [retour 1]
  2. Dans ce document Opera 9 fait référence uniquement à la version Opera 9.0 Technology Preview 1 pour Windows, qui est une version beta destinée aux développeurs, et non la version finale de Opera 9. [retour 2]

← article précédentarticle suivant →

4 commentaires

1. karl a écrit :

Tu as essayé avec

@namespace xml url(http://www.w3.org/XML/1998/namespace);

xml|:lang(fr) > a[hreflang='en']:after {

content:"\A0(en anglais)";

}

dimanche 2 octobre 2005 à 3h04

2. Sébastien a écrit :

Karl, J'ai fait quelques essais mais je n'arrive à aucun résultat avec Opera ou Firefox.

exemple : http://sebastienguillon.com/test/css/lang-pseudo-class-css-namespace.xhtml

dimanche 2 octobre 2005 à 21h40

3. Stéphane Vincent a écrit :

Salut

Je cherche une méthode pour faire un site bilingue

les deux sur la même page en cachant le texte anglais ou français et pouvoir faire en sorte que le texte soit comme ceci:

texte français

english text

texte français

english text

en dhtml, est-ce c'est possible?

Merci!

ps.: Je suis programmeur mais je suis nouveau en programmation web, je connais un peu (css, javascript, html et php)

jeudi 27 octobre 2005 à 4h48

4. Sébastien a écrit :

Je ne comprends pas très bien pourquoi tu veux faire ça.

La solution pour un site bilingue est généralement de faire la négociation côté serveur et d'envoyer la page dans la langue demandée par le visiteur (si elle est disponible).

Je ne pense pas qu'une solution basée sur les pseudo-classes CSS soit à recommander, mais peut-être avec un simple cookie et du JavaScript...

jeudi 27 octobre 2005 à 6h04

Les commentaires pour cet article sont fermés.