Why do witches burn?

Because they’re made of wood, like bridges, and so float on water, like churches, very small rocks, gravy, and a duck.

J’ai peut-être mal cherché, mais je n’ai pas trouvé de webservice de traduction.
Or j’avais deux besoins, que j’ai tous deux comblé : pouvoir faire traduire ce que j’écris facilement, et pouvoir lire des flux RSS dans d’autres langues.

Les moins fans d’entre vous de ma personne (qu’est ce que vous faites là ?) ignorent peut-être que grâce à mon dojinshi (BD avec les personnages et l’univers d’une BD déjà existante. Oui c’est illégal, mais toléré), je gère maintenant un site avec 7 langues différentes, sachant que j’en parle la moitié d’une.

Je vous raconterai plus tard la beauté de mon code du site de traduction, il n’a d’ailleurs pas grand-chose de compliqué. Site avec login, table avec un champs par langue, et hop (on appelle les textes par leur ID. Cela rends le code php appelant plutôt lisible et on se pose pas de questions d’index).

Bref, de nombreux fans (oui, j’ai des visiteurs môssieur) postent des commentaires dans leur langue, et moi je ne peux pas les suivre. Or, j’aime savoir.
D’ailleurs faudra que je vous partage mon code de commentaires, il est très cool. Un jour.

Lire le flux des commentaires

Yahoo Pipes!, un utilitaire extrêmement puissant dont personne ne parle parce que c’est pas Google qui le fait, a répondu à mes interrogations.

On donne notre flux de commentaires, on le pointe sur un cadre « traduction » en donnant la langue d’entrée et de sortie, on pointe ce cadre sur un nouveau flux, et Yahoo génère une flux XML modifié, auquel on peut s’inscrire avec notre agrégateur préféré.

Comment l’utiliser ? Un tuto vidéo simple qui marche :
How to Translate a Feed Using Pipes

Notez beaucoup de tutos parlent de « BabelFish ». IL EST DEPRECATED. Il ne SERT A RIEN.
Il faut utiliser le plus complexe et plus puissant Loop + String»Translator (comme dans la vidéo)

Maintenant, je suis abonné à 7 flux RSS différents.

Bon évidement c’est loin d’être parfait. Déjà la traduction automatique continue à être un art fortement mal maîtrisé. Mais en plus, des commentaires de blog… et bien c’est pas très bien écrit à la base…
Autre problème, si le texte contient du html, alors le résultat est immonde. J’ai ajouté un filtre RegExp pour virer le HTML mais je ne sais pas si ça a été très utile.
Dernière problème, a cause du html qui vole, le pseudo du type est collé au message (avec mon filtre, il y a un espace c’est déjà ça. Je pourrais ajouter un filtre pour mettre des jolies étoiles.)

Voilà les flux auxquels je suis abonné sur Google Reader :

Ce sont les flux que j’ai créé avec Yahoo Pipes (sauf pour FR et EN qui sont les originaux, mais enfin par définition c’est aussi moi qui les ai créé ;) ), vous pouvez créer les vôtres traduits dans ce que vous voulez, mais aussi vous abonner aux miens, puisqu’il sont déjà là ! (si vous êtes motivé, les espagnols postent autant que les français)

Traduction de mon propre commentaire

Maintenant que je lis les gens, j’ai des fois envie de leur répondre. Mais écrire un texte, aller sur un site de traduction, le passer, le copier et montrer les 2 versions (histoire que ceux qui peuvent lire la langue originelle échappent à la mauvaise traduction), c’est fastidieux.

Ne trouvant de webservice, j’ai transformé Google en ce dernier.
Histoire de ne pas ralentir et défoncer Google à chaque fois que quelqu’un ouvre la page des commentaires, je mets le résultat de traduction en cache.

Voici mon premier message auto-traduit :
http://www.dragonball-multiverse.com/es/page-54.html?comsall=1#c9444
Il y a bien sûr du code intégré dans mon système de commentaires pour déclencher l’ajout de trad sans travail de ma part, mais je le passe ici, pour vous montrer le système derrière.

Pour simplement créer un lien qui traduira le texte :
C’est ma première version, elle est plus simple à utiliser, mais vous n’affichez pas directement la traduction.

function link_translator($txt, $from='en', $to=null, $a_params='') {
    if ($to===null) $to = $GLOBALS['lang'];
    $txt = preg_replace('/<[^>]*>/', '', $txt);
 
    $url = 'http://translate.google.com/translate_t?sl='.$from.'&amp;tl='.$to.'&amp;text='.urlencode($txt);
    $str = function_exists('__')? __(63) : 'Translate from %s into %s';
    return "<a href=\"$url\" $a_params>".sprintf($str, strtoupper($from), strtoupper($to))."</a>";
}

Notez que mon site contient souvent un $GLOBALS[lang]. Evidement, dans la page de commentaires espagnols, la variable est à « es », le défaut est souvent mon ami. Enfin, j’écris plutôt en anglais, pensant stupidement que en2es est plus travaillé que fr2es (les langues étant plus proches, c’est pas évident), et puis il y a sûrement plus d’espagnols qui comprennent l’anglais que le français, pour profiter de ma VO.
Notez également qu’on vire le HTML qui fait du mal à google.
Profitez aussi que vous voyez là un extrait de ma fonction de traduction (deux underscores), mais si vous ne l’avez pas (ce dont je ne doute pas, vous n’avez sûrement pas non plus la table et son 63e élément qui va avec ^^), ça marche quand même.
Enfin, on envoie tout par GET par simplicité, ce qui exclu les textes trop longs.

Il n’y a pas vraiment de gestion d’erreurs, utilisez-la bien. $from et $to doivent être juste des mots de deux lettres, en minuscule (sauf pour le chinois qui fait chier)

Pour garder la traduction et l’afficher :
Passons au niveau deux. On va parser la réponse google et l’afficher, et la sauver en BDD.

Le plus simple, l’affichage du résultat, qui dépends d’une autre page, celle du webservice. Le webservice est à copier chez vous, n’allez pas me flooder ma BDD avec vos conneries :

function translator($txt, $from='en', $to=null, $div_params='') {
    if ($to===null) $to = $GLOBALS['lang'];
    $txt = preg_replace('/<[^>]*>/', '', $txt);
 
    $F = file_get_contents("http://tondomaine/webservice_translate.php?from=$from&to=$to&txt=".urlencode($txt));
    $str = function_exists('__')? __(63) : 'Translate from %s into %s';
    $str = sprintf($str, strtoupper($from), strtoupper($to));
    return "<div $div_params><h5>$str</h5>\n$F</div>\n";
}

Vite fait, le CSS que j’ai utilisé :
(en dernier argument de la fonction, j’ai bien sûr mis " class='auto_translation' ")

.auto_translation { border: 1px solid; background: #FFA; margin: 0.5em 1em 0 1em }
.auto_translation h5 { font: bold 0.8em sans-serif; margin: 0 0 0.2em 0 }

Voici maintenant le contenu de webservice_translate.php :

<?php
/** Cette page prends un texte et 2 langues.
  Elle utilise google pour traduire le texte d'une langue a l'autre.
  Sauve le resultat en cache.
  L'affiche.
  */
 
if (!$_REQUEST['txt']) die("Give some text to translate...");
 
if (!preg_match('/^[a-z][a-z]$/', $_REQUEST['from'])) die("Give a language to start from.");
if (!preg_match('/^[a-z][a-z]$/', $_REQUEST['to']  )) die("Give a language to get to.");
 
require('connect.php');
mysql_query("SET NAMES 'utf8'");
 
if (get_magic_quotes_gpc()) $_REQUEST['txt'] = stripslashes($_REQUEST['txt']);
 
//// cherche si deja la
$clef = $_REQUEST['from'].':'.$_REQUEST['to'].' '.md5($_REQUEST['txt']);
 
$R = mysql_query("SELECT `translation` FROM `autotranslations` WHERE `clef`='$clef'");
$R = mysql_fetch_row($R);
if ($R) {
    echo $R[0];
    exit();
}
 
/// demande google
 
$url = 'http://translate.google.com/translate_t?sl='.$_REQUEST['from'].'&tl='.$_REQUEST['to'].'&text='.urlencode($_REQUEST['txt']);
 
$F = file_get_contents($url);
 
$B = preg_match('|<td class=almost_half_cell><div id=result_box dir=[^>]+>(.*)</div></td></tr><tr><td class=submitcell>|s', $F, $M);
 
if (!$B) die("Could not translate. Tell Salagir about it.");
 
$M = $M[1];
$M = preg_replace('/[\r\n]/', "\n", $M);
$M = htmlentities($M);
$M = str_replace('&amp;', '&', $M);
$M = str_replace('&lt;', '<', $M);
$M = str_replace('&gt;', '>', $M);
 
if (!$M) die("Could not find any translation.");
 
echo $M;
 
// sauve
 
mysql_query("INSERT INTO `autotranslations` SET
        `clef`='$clef', `translation`='".mysql_real_escape_string($M)."'");
echo mysql_error();
 
?>

Alors en ce qui concerne les encodages, j’ai fais… n’importe quoi. Mon site est en utf8, et j’ai changé des trucs au hasard jusqu’à ce que ça s’affichait bien. Désolé.
Le htmlentities() essait d’éviter les problèmes d’encodages, mais il détruit le HTML, que donc comme vous voyez je remets.
En php5, on peut échapper à cela car htmlentities(), htmlspecialchars() sont nos amis, ont plus de paramètres, et chacun une fonction inversante. Mais bon, là je suis en 4.

Enfin, la table utilisée :

CREATE TABLE `autotranslations` (
  `id_at` INT(11) NOT NULL AUTO_INCREMENT,
  `clef` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `translation` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY  (`id_at`),
  KEY `clef` (`clef`)
);

Bonus : le 63e élément de ma table de traduction, remplis par les traducteurs de DBM, que je remercie grandement au passage !

  • EN: Automatic translation from %s into %s
  • FR: Traduction automatique de %s en %s
  • IT: Traduzione automatica da %s in %s
  • ES: Traducción automática de %s a %s
  • NL: Automatische translatie van %s naar %s

(au moment où j’ai écris l’article, tous les traducteurs ne sont pas passés)

3 Responses to “Webservice de traduction automatique”

  1. […] Version Française « Webservice de traduction automatique […]

    Why do witches burn? » Blog Archive » Fonctions temporelles 2 : le retour

  2. J’utilisais ce super webservice depuis un petit moment mais malheuresement, il ne fonctionne plus.

    En effet, google a modifié son système de traduction et cela ne fonctionne plus car le mise en page google est conservé dan la variable.

    J’ai donc à chaque fois le message d’erreur sur $f et $b …

    Si jamais tu utilise encore cette méthode ou un autre et a une solution, je serais preneur !

    bertel

  3. Après une longue attente, je répond enfin, parce que maintenant j’en suis sûr : je n’utilise absolument pas mon propre service, pas du tout.
    Je ne lis plus les coms DBM des autres langues, le texte reste mauvais (google a du mal avec le SMS espagnol, étonnant), et y’en a bien trop à lire.

    Ma table `autotranslations` contient deux éléments ^^.

    En bref, je ne vais pas patcher ce truc, qui demandera sûrement un autre patch bientôt d’ailleurs parce qu’ils changent surement tout le temps, puisque ça ne me sert à rien.
    Si quelqu’un l’a fait, il peut poster ici…

    Salagir

Leave a Reply