PHPFrance

Discuter de tout ce qui touche au PHP, en français.

Vers le contenu

» Masquer les résultats de la recherche

Recherche dynamique PHPfrance

  1. Effectuez une recherche, les résultats s'afficheront dynamiquement ici.

Traduction et localisation, comment s'y prendre ?  Sujet résolu

Discussions générales sur les méthodes de développement d'une application web, et l'aspect sécurité.

Traduction et localisation, comment s'y prendre ?

Messagede Hywan le 04 Juil 2007, 16:48

Bonjour,

je m'attaque à un système de traduction et de localisation (en PHP 5).
Alors, je me pose pas mal de questions sur la méthodologie à adapter.

On a en fait 2 problèmes de méthodologie : (1) la localisation : i10n ; (2) la traduction : l18n.

1. La localisation :

Déjà, est-ce que c'est bien ce que je pense : l10n (au sens strict du terme) ? Je ne pense pas me tromper sur le vocabulaire pour l'instant.
Ensuite, qu'est-ce qu'on doit gérer ? J'aimerais ne rien oublier, car j'en ai mal à la tête juste d'y penser, et me plonger dans le code ne me motive pas plus que ça, alors autant ne rien oublier ;-)
Quand je dis : « Qu'est-ce qu'on doit gérer ? », j'entends, qu'est-ce PHP gère et ne gère pas. Donc qu'est-ce qu'on peut utiliser, et qu'est-ce qu'on doit construire ?

Il y a le célèbre setLocal(), mais quoi d'autres ? J'ai vu qu'on pouvait comparer des chaînes localisées, ça veut dire quoi ?

On va également rencontrer le problème de format de dates. Comment est-ce qu'on peut gérer tout ça ?


2. La traduction :

Je pense que la traduction c'est l'i18n (internationalisation), sauf erreur de ma part.

Là encore, beaucoup de problèmes. J'ai beau retourner le problème dans tous les sens, on ne peut que passer par des fichiers de traductions (chaîne de référence => chaîne traduite). J'ai vu qu'il y a différents formats : Gettext (.mo, binaire), TMX (.tmx, basé sur XML), CSV (.csv, texte) etc.

Qu'est-ce que PHP supporte le mieux ? Qu'est-ce qui le plus rapide ? Je pense que le mieux est de supporter tous les formats, mais je préfère d'abord me concentrer sur un seul.

Gettext me paraît le plus adapter, car le plus utiliser. En revanche, XML est plus adapté pour les humains (nous sommes tous des extra-terrestres sur ce forum ;-) ne l'oublions pas !). Comment exploiter le binaire de Gettext ?

Ne doit-on pas faire un lien en la traduction et l'encodage aussi ? Pour le CMS que je compte préparer, je pensais forcer l'UTF-8. Peut être un petit peu contraignant, mais tellement plus simple ... Si vous avez des suggestions à ce sujet, je suis preneur !



J'ai tellement de questions, que je n'ose pas tout poser. J'ai donc 2 problèmes bien distincts. Je ne sais pas trop comment procéder, vous vous en êtes rendu compte :roll:.
J'espère que ce thread sera être utile à plusieurs personnes.
J'aimerais développer quelques choses de professionnels, donc on oublie le simple tableaux de traductions (même si c'est à envisager), je préfère rester sur des standards.
Peut être qu'il serait bon de faire 2 sujets pour chaque problème. Je ne sais pas.

Bref, vous avez mon avenir entre vos mains ! (bon, j'ai essayé ^^)
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa Framework : http://hoa-project.net (sur identi.ca/hoaproject et twitter.com/hoaproject).
Avatar de l’utilisateur
Hywan
ViPHP
ViPHP
 
Messages: 4446
Inscription: 03 Mai 2005, 21:01
Localisation: Haut-doubs

Publicité

Messagede Invité le 04 Juil 2007, 17:02

Je ne m'exprimerai que sur deux points, premièrement le charset. Je soutiens ta décision de forcer l'UTF-8, c'est en effet bien plus pratique que de s'embêter à gérer tous les charsets possibles. Cependant il faudra que dans la documentation de ton CMS tu fasses une section claire et simple expliquant comment éditer un fichier UTF-8 sans y rajouter le fameux BOM. Quant aux fichiers de langues, un fichier XML à parser à chaque fois me semble un mauvaise solution, mais pourquoi ne pas garder l'idée du XML qui est - en effet - facilement compréhensible par les humains ? Dans ce cas la il suffirait de créer un système de cache. Une fois parsé les phrases seraient par exemple incluses dans un fichier PHP en tant que variables.

HF & GL, Nowan :P
Invité
 

Messagede Sékiltoyai le 04 Juil 2007, 17:04

Pour GetText, tu peux l'exploiter en fournissant les outils nécessaires aux utilisateurs pour l'édition des fichiers en format binaire, soit en intégrant les outils de modification dans ton script, soit en crant des scripts ou même des binaires indépendants.
Sékiltoyai
ViPHP
ViPHP
 
Messages: 5228
Inscription: 22 Avr 2007, 14:53
Localisation: Le Havre | Rennes

Messagede naholyr le 04 Juil 2007, 17:38

Tout d'abord, oui pour l'UTF-8. Il faut ignorer tout autre charset sinon c'est l'enfer. Dès qu'on mélange deux charset c'est atroce à gérer, et dès qu'on sort de l'Unicode on est vite limité. Attention à l'utilisation des fonctions php (par exemple strrev n'existe pas en version mb_string).

Le XML plus lisible pour les humains ? C'est une légende urbaine ça... Je n'ai jamais vu quelqu'un qui soit heureux de lire du XML par rapport à un fichier ini par exemple. Le XML est verbeux et illisible, tu seras de toute façon obligé de te taper une interface d'administration car le fichier sera inutilisable tel quel par un profane.

Personnellement je m'étais fait un système inspiré de gettext mais en plus «transparent» car il ne passe pas par des fichiers binaires à compiler soi-même (ce qui peut être assez pénible) :

- Une constante qui définit la «langue de référence».
- Une variable de session “lang” pour stocker le choix de l'utilisateur.
- Un fichier ##.lng dans un dossier défini qui contient les traductions.
- Une fonction __() (pour ne pas entrer en conflit avec ()).

Au lieu d'affecter des idefiants ts aux chaines (ce que je trouve absolument débile et illisible dans l'appli finale) je fais comme dans gettext : on prend le message dans la langue de référence, et et si l'utilisateur a choisi une autre langue alors on cherche la traduction.

Syntaxe: [ Télécharger ] [ Masquer ]
Code php
<?php echo __('Hello World') ?>


Le fichier de traduction est d'un format simplissime :
- Le message dans la langue de référence
- Le message traduit en-dessous
Les lignes vides sont ignorées, et on prévoit bien sûr d'ignorer les lignes qui commencent par # (commentaires).
Ce format a l'immense avantage d'être extrêmement lisible, par contre si on zappe une ligne ça décale tout et ça n'a plus aucun sens :( (on n'a rien sans rien)

Exemple de fichier “fr.lng”
Hello World
Salut le Monde

Hey, who are you ?
Hé, t'es qui ?

# etc...


Et l'exemple précédent, si $_SESSION['lang'] == 'fr', donnera «Salut le Monde».

Pour des raisons évidentes de performances ce fichier n'est parsé qu'une fois et et transformé en tableau associatif (phase de compilation transparente) qu'on stocke dans un fichier “compiled” sous le dossier contenant les fichier de traduction.

Je me suis même permis la fantaisie de logger toute lacune de traduction (vu que tout passer par la fonction __()) afin d'aider à la complétion de ces fichiers.
Comment ils sont vraiment lisibles par n'importe qui, on on peut les laisser à l'édition directe par le client final, ils s'en sort ;)

J'avais trouvé pas mal d'avantages à ce système, mais il n'est pas «fool-proof» du tout, et si on veut s'assurer de la robustesse, on est bien obligé de passer par une interface d'admin :(

La fonction __ est très simple à écrire :
Syntaxe: [ Télécharger ] [ Masquer ]
Code php
function __($message, $lang = null) {

  static $translations = array(); // traductions mises en cache dans la fonction (chargé une seule fois en mémoire)

  if (!$lang) { // paramètre par défaut : on prend la langue de l'utilisateur

    $lang = @$_SESSION['lang'];

  }

  if (!isset($translations[$lang])) { // Il faut charger les traductions

    if (!is_file(DIR_LANGS.$lang.'.lng')) { // Le fichier de traduction n'existe pas

      return $message;

    }

    $not_compiled = !is_file(DIR_LANGS_COMPILED.$lang.'.php');

    $compiled_expired = @filemtime(DIR_LANGS_COMPILED.$lang.'.php') < filemtime(DIR_LANGS.$lang.'.lng');

    if ($not_compiled || $compiled_expired) { // le fichier compilé n'existe pas ou le fichier de traduction a été modifié depuis

      compile_lang($lang);

    }

    $translations[$lang] = include DIR_LANGS_COMPILED.$lang.'.php';

  }

  if (!isset($translations[$lang][$message])) { // Le fichier de traduction existe, mais ce message n'est pas traduit

    return $message;

  } else { // on retourne la traduction

    return $translations[$lang][$message];

  }

}


Et la phase de compilation est un simple parsing pour générer un tableau stocké dans un fichier avec var_export :
Syntaxe: [ Télécharger ] [ Masquer ]
Code php
function compile_lang($lang) {

  $lines = @file(DIR_LANGS.$lang.'.lng');

  if (is_array($lines)) {

    $original_message = null;

    $translations = array();

    foreach ($lines as $line) {

      $line = trim($line);

      if ($line == '' || $line{0} == '#') { // commentaire ou ligne vide

        continue;

      }

      if ($original_message === null) { // il s'agit d'un message à traduire

        $original_message = $line;

      } else { // il s'agit de la traduction du message à traduire précédemment rencontré

        $translations[$original_message] = $line;

      }

    }

    // on a généré le tableau, on stocke le résultat ("compilation")

    $code = '<'.'?php return ' . var_export($translations, true) . '; ?'.'>';

    file_put_contents(DIR_LANGS_COMPILED.$lang.'.php', $code);

  }

}


Je n'ai pas eu de souci particulier de performances, mais ce système n'a jamais été utilisé que sur des intranets (donc assez peu de visites par rapport à un gros site communautaire).
Les projets sur lesquels je bosse actuellement tournent avec Copix, Symfony, et un autre framework de notre boite qui tous trois intègrent leur système de traduction donc je ne vais pas le ressortir avant un petit moment a priori :lol:
Avatar de l’utilisateur
naholyr
Administrateur PHPfrance
Administrateur PHPfrance
 
Messages: 2811
Inscription: 07 Fév 2005, 16:31
Localisation: Villefranche Sur Saone

Messagede Klomac le 04 Juil 2007, 18:48

Je ne me suis jamais vraiment penché sur la question donc je ne saurais pas trop te répondre :-/ Cela dit la solution proposée par naholyr me semble intéressante :)
Klomac - Blog Lambda
Klomac
J'ai codé une fonction !
 
Messages: 170
Inscription: 17 Mai 2007, 22:00
Localisation: Angers

Messagede Hywan le 04 Juil 2007, 19:01

Hehe ok merci pour cette grosse contribution, c'est exactement ce que j'attendais.

Alors le système est bon pour la traduction, dans le sens où : oui je suis d'accord de mettre une phrase à la place d'un id, ou tag de références pour chaque traduction. Mais ça pose un problème, on est obligé de taper la phrase avec la même case (minuscule/majuscule), sinon on ne trouvera pas l'entrée dans notre tableau.

Bon, on peut toujours utiliser array_map et faire une comparaison binaire, mais ça risque de prendre un peu de temps :s, ou alors on met tout en minuscule. Comme ça, c'est plus rapide. Je doute que ce soit une bonne idée pour l'utilisateur de bases.

On pourrait partir sur un fichier .ini. Comme il serait interpréter par PHP, ce sera nettement plus rapide. Ensuite, on enregistre le tableau en cache, et plus de soucis.

Je ferais des adaptateurs pour Gettex, TMX etc., après. Je commence sur cette idée.

Maintenant, reste à résoudre le problème de la localisation.

PS : je suis content de voir que mon idée de forcer l'UTF-8 n'est pas aussi farfelue que ça :)
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa Framework : http://hoa-project.net (sur identi.ca/hoaproject et twitter.com/hoaproject).
Avatar de l’utilisateur
Hywan
ViPHP
ViPHP
 
Messages: 4446
Inscription: 03 Mai 2005, 21:01
Localisation: Haut-doubs

Messagede orgerix le 04 Juil 2007, 19:11

Le systeme de langue de Phpbb est un simple tableau associatif. Pour chaque clef on associe une traduction et chaque langue a on fichier propre. Ensuite, lors de la cration de la page, le parser inclut le fichier corespondant à la langue. Ensuire, on y accède comme tout les tableaux.
orgerix
Eléphant
 
Messages: 689
Inscription: 22 Jan 2007, 16:46

Messagede Hywan le 04 Juil 2007, 19:20

Oui mais PHPbb n'est pas une si grosse application que ça.

http://unicode.org/cldr/data/common/sup ... alData.xml ça peut être utile pour les petits curieux :) (je sens que j'ai pas fini de le lire celui là hehe).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa Framework : http://hoa-project.net (sur identi.ca/hoaproject et twitter.com/hoaproject).
Avatar de l’utilisateur
Hywan
ViPHP
ViPHP
 
Messages: 4446
Inscription: 03 Mai 2005, 21:01
Localisation: Haut-doubs

Messagede orgerix le 04 Juil 2007, 19:51

ok, je retourner faire mes bidouilles sur mon ordi. Moi qui pensait que phpbb était une assez grosse application, vous me dites que c'est pas le cas, je me sens tout de suite... heu... coment dire... campagnard. :D
orgerix
Eléphant
 
Messages: 689
Inscription: 22 Jan 2007, 16:46

Messagede Hywan le 04 Juil 2007, 20:54

Haha :D pardon, faut pas le prendre mal ^^

Je vois plus PHPbb comme un gros module (un forum) que comme un réel programme Web. C'est une application certes, mais on en a d'autre, autrement plus compliquées et plus intéressantes à étudier. Je ne dis pas que PHPbb est de la merde, loin de là, mais c'est mon point de vue :P Coder PHPbb, ça se fait. C'est long (et peut être chiant), mais ça se fait :)

Si tu voyais où j'habite, tu te sentirais moins campagnard ;-)
Dernière édition par Hywan le 07 Juil 2007, 18:48, édité 1 fois.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa Framework : http://hoa-project.net (sur identi.ca/hoaproject et twitter.com/hoaproject).
Avatar de l’utilisateur
Hywan
ViPHP
ViPHP
 
Messages: 4446
Inscription: 03 Mai 2005, 21:01
Localisation: Haut-doubs

Messagede orgerix le 04 Juil 2007, 20:58

Je le prend pas mal du tout.

C'est juste qu'on est pas dans la même cathégorie :P
orgerix
Eléphant
 
Messages: 689
Inscription: 22 Jan 2007, 16:46

Messagede Sékiltoyai le 04 Juil 2007, 21:27

HyWaN a écrit:Je ne dis pas que PHPbb est de la merde

Moi je le dis :P :mrgreen:
Sékiltoyai
ViPHP
ViPHP
 
Messages: 5228
Inscription: 22 Avr 2007, 14:53
Localisation: Le Havre | Rennes

Messagede zeus le 04 Juil 2007, 21:30

il ne faut pas être aussi catégorique ... ;)

C'est une usine à gaz qui à ses défauts, mais qui rend d'énormes services tout de même.

M'enfin bref, tu as le droit d'avoir tes opinions, c'est normal ;)
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - site de ma société
Avatar de l’utilisateur
zeus
Modérateur PHPfrance
Modérateur PHPfrance
 
Messages: 12100
Inscription: 22 Avr 2005, 11:11
Localisation: Lyon

Messagede Shrell le 05 Juil 2007, 00:19

Juste une petite précision : tu fais une erreur au niveau l10n et i18n
l'internationalisation (pfiou...) c'est le fait de "préparer son programme afin qu'il soit traduisible"
Donc, dans la pratique, remplacer "<span>Mon texte en français</span>" par "<span><?=_("Mon texte dans n'importe quelle langue") ?></span>"
Puis, une fois que ceci est fait, passer le tout dans la moulinette de xgettext ou equivalent pour récupérer ton fichier .po

Seconde partie : la localisation. Là, beaucoup moins de problèmes, tu prends ton joli fichier .po que tu envoies à tes gentils traducteurs et qui le traduisent (ils peuvent bien faire ça, tu as fait le plus dur ;))

Sinon, moi j'utilise gettext, je pars du principe que même si il peut paraitre lourd, il a été développé par des gens biens plus au fait de ce genre de choses que moi, et je n'ai aucune intention de réinventer la roue.
En plus il gère un nombre impressionnant de choses auxquelles je n'aurais même jamais pensé tout seul dans mon coin

Enfin, si tu te décides à partir dans cette direction, voici un lien qui m'a été utile
http://www.mandragor.org/tutoriels/gettext/0

Voilou ;)
Petit scarabée deviendra grand
Shrell
Eléphanteau
 
Messages: 350
Inscription: 03 Juil 2005, 23:04
Localisation: Espagne

Messagede naholyr le 05 Juil 2007, 07:41

HyWaN a écrit:Mais ça pose un problème, on est obligé de taper la phrase avec la même case (minuscule/majuscule), sinon on ne trouvera pas l'entrée dans notre tableau.
Être sensible à la casse me paraît vital en effet :? On ne peut pas être sûr que la ponctuation ou la gestion de la casse sera la même d'une langue à l'autre, donc il faut rester sensible à la casse. C'est d'ailleurs le cas de gettext et de TMX.
Non la grosse faiblesse de mon système, ou plutôt la grosse force de gettext (je ne connais pas le détail de TMX) c'est la gestion des pluriels. Par exemple en français on dira "0 objets" (on met au pluriel) alors qu'en anglais ce sera "0 object" (on laisse au singulier). Dans un système où on ne peut gérer les pluriels on devra se contenter d'une traduction générique "%u object(s)" => "%u objet(s)", alors que gettext permettra de gérer ça finement (je n'ai plus le détail de la méthode en tête, mais ça se fait dans des directives de config au début du fichier .po).

Si tu tiens à être insensible à la casse, il faut simplement mettre les clés du tableau en basse casse et comparer avec le message en basse casse :
Syntaxe: [ Télécharger ] [ Masquer ]
Code php
function __($message, $lang = null) {

  $message = mb_strtolower($message, mb_detect_encoding($message));

  ...

}
Syntaxe: [ Télécharger ] [ Masquer ]
Code php
function compile_lang($lang) {

  ...

        $translations[mb_strtolower($original_message, mb_detect_encoding($original_message))] = $line;

  ...

}


Ainsi s'il y a l'entrée "Object" => "Objet", alors "objeCt" sera aussi traduit par "Objet", mais est-ce bien élégant ? Quant à reporter la casse du message à traduire sur le message traduit, comment le faire alors qu'il n'y aura pas le même nombre de lettres, et pas les mêmes mots dans le même ordre (ni au même nombre non plus) dans le message traduit ?
Avatar de l’utilisateur
naholyr
Administrateur PHPfrance
Administrateur PHPfrance
 
Messages: 2811
Inscription: 07 Fév 2005, 16:31
Localisation: Villefranche Sur Saone

Suivante

Retourner vers Méthodologie, modélisation, sécurité

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 4 invités

  • Publicité