Traduire l’admin generator symfony

computer Petit billet Symfony du mardi, principalement pour combler un manque que j’ai pu voir dans google voir même dans la doc Symfony sur l’admin generator.

En effet, on y lit que l’admin generator est i18n ready, en gros que le système de traduction est en place, qu’il ne reste plus que le fichier xliff (le format utilisé pour la traduction dans Symfony) à faire et à placer dans apps/backend/i18n mais aucune ligne qui semble indiquer que les plugins sfPropelPlugin et sfDoctrinePlugin intègre déjà les traductions de la plupart des langues. Or c’est le cas!

Du coup, pour traduire un admin generator en français (entendre par là, le rendre par défaut en français), cela prend 3 lignes. Les deux premières à ajouter dans le fichier config/settings.yml

.all:
  .settings:
    i18n:  on      # Enable interface translation. Set to off if your application should not be translated.
    default_culture:        fr       # Default user culture

Puis un lien symbolique à placer:

ln -s /votre/chemin/vers/symfony/lib/plugins/sfPropelPlugin/i18n/sf_admin.fr.xml votre/chemin/vers/votre/projet/apps/backend/i18n/sf_admin.xml

Et voilà, l’affaire est dans le sac, un Back office en français, ce qui fait toujours plaisir à des clients français ;)
image-54

Tags: , , ,

A propos de l'auteur

Développeur web spécialisé Symfony, il est avant tout passionné de web tout simplement. Il aime les défis et farfouiller dans le code de Symfony ou Doctrine. Fondateur du blog, il exerce chez Autrement.

Vous avez aimé ce billet? Faites le savoir!

  • Delicious
  • Twitter
  • Technorati Favorites
  • FriendFeed
  • Google Bookmarks
  • Share

39 Réponses

  1. Kévin Dunglas 9 juin 2009 à 23 h 58 min #

    Super !
    Tu n’autais pas un truc similaire en stock pour traduire les messages d’erreurs d’origine des formulaires ?

  2. Tim 10 juin 2009 à 10 h 18 min #

    Hello!

    Pour les msg des forms, depuis la 1.2, 2 nouvelles méthodes static ont fait leur apparition dans sfValidatorBase.

    Du coup personnellement je rajoute ceci dans mon BaseFormPropel (vu que tous les forms l’héritent):

      public function setup()
      {
        sfValidatorBase::setRequiredMessage('Champ obligatoire');
        sfValidatorBase::setInvalidMessage('Valeur non valide');
        parent::setup();
      }
    

    Alors évidemment, on peut mettre une valeur i18n directement.

  3. Antoine 10 juin 2009 à 15 h 43 min #

    Merci pour le billet.

    Je pense qu’il te manque un « fr » dans le chemin vers lequel tu lies le fichier XLIFF :
    [..]/i18n/fr/sf_admin.xml

  4. Tim 10 juin 2009 à 17 h 25 min #

    Salut Antoine,

    De mon côté ça marche bien comme ça. Mais c’est peut être parce que je parle de mettre le backoffice par défaut en français, sans possibilité de changer après coup la culture.

  5. Garfield-fr 10 juin 2009 à 21 h 35 min #

    Salut,

    Il n’est pas nécessaire de faire un lien sur le fichier xml. Il suffit de lancer la commande ./symfony plugin:publish-assets pour que l’alias du plugin se passe dans le dossier web. Ensuite il suffit d’activer le i18n.

    Par contre, la traduction n’est pas totale. Il manque des choses comme par exemple, impossible de traduire « is_empty » et « yes or no, yes, no ». C’est un oubli de l’admin.

    Voilà pour les explications.

    Et merci de faire ce genre de petit article.

  6. Tim 10 juin 2009 à 22 h 36 min #

    Hello,

    C’est ce que je pensais aussi avant, mais le plublish-assets ne fait que le lien sur le dossier web du plugin et le i18n n’est pas dedans.

    En tout cas, le simple fait d’activer le i18n et de changer la culture ne me traduit pas mon admin generator, mais je suis preneur si j’ai loupé un épisode!

    Et merci à vous d’apporter votre pierre au sujet ;)

  7. Stephane 16 juin 2009 à 15 h 21 min #

    Salut,

    Super ce billet …. Dommage que je ne le rencontre que si tardivement … Enfin quoique …. Ca m’a quand même servi pour un autre projet.

    Par contre question :
    Comment traduire le message du bout de code Javascript associé à la suppression d’un objet ? le « Are you sure ? » ?

    Par avance merci

  8. Stephane 16 juin 2009 à 15 h 32 min #

    Je n’ai rien dit ….

    Désolé, erreur de ma part, j’avais simplement oublié de faire un CC

    En tout cas excellent site, je ne le connaissais pas mais très sympas ;)

  9. Tim 16 juin 2009 à 17 h 07 min #

    Merci : )

    Et surtout n’hésite pas, je suis tjrs ouvert pour discuter de Symfony et je cherche activement des sujets :p

  10. Jf 18 juin 2009 à 17 h 05 min #

    Pour les messages d’erreurs ou d’actions javascript, il suffit de créer un fichier dans /tonprojet/apps/nomapplicaton/i18n/messages.fr.xml

    et dans ce fichier mettre :

    reset
    Remise à zéro

    filter

    Enfin dans le 1.0 maitenenant dans le 1.2 ??

  11. Jf 18 juin 2009 à 17 h 06 min #

    Zut mon code xml n’est pas passé dans le commentaire :-(

  12. Tim 18 juin 2009 à 18 h 32 min #

    Il faut mettre la balise <pre> avant pour mettre des tags xml/html ^^

  13. Jf 19 juin 2009 à 9 h 03 min #
    
    
      
        
          
            reset
            Remise à zéro
          
          
            filter
            Rechercher
          
    
    
  14. Jf 19 juin 2009 à 9 h 04 min #
    
    
      
        
          
            reset
            Remise à zéro
          
          
            filter
            Rechercher
          
  15. Jf 19 juin 2009 à 9 h 04 min #

    Bon ben déso Tim mais ça marche pas

  16. Sebastien 4 août 2009 à 12 h 33 min #

    Salut,

    Dit, j’ai essayé ta méthode :

      public function setup()
      {
        sfValidatorBase::setRequiredMessage('Champ obligatoire');
        sfValidatorBase::setInvalidMessage('Valeur non valide');
        parent::setup();
      }
    

    pour traduire les messages d’erreurs « Required » et « Invalid », mais ça ne fonctionne pas, j’ai pourtant c/c ton code.

    J’ai passé un « php symfony cc » et j’ai verifié que rien dans mon Base*Form et *Form ne surcharge le message, mais pas de résultat.

    Merci d’avance ! :)

  17. Tim 4 août 2009 à 13 h 03 min #

    Effectivement, ca ne fonctionne pas (plus?).

    J’ai pas regardé en détail, mais apparemment le parent::setup des BaseForm généré est maintenant à la fin, or ces 2 méthodes doivent être appelées en tout premier.

    En attendant une meilleur solution tu peux mettre le code dans une méthode dans BaseFormPropel:

    function initMsg()
    {
      sfValidatorBase::setRequiredMessage('Champ obligatoire');
      sfValidatorBase::setInvalidMessage('Valeur non valide');
    }
    

    et dans tes formulaires cibles:

    public function setup()
      {
        $this->initMsg();
        parent::setup();
      }
    

    C’est pas l’idéal, mais pas de meilleur solution pour l’instant.

  18. Sebastien 4 août 2009 à 14 h 35 min #

    J’avoue que je comprends pas bien le fonctionnement, j’ai fais quelques recherche est voici le résultat, lorsque j’ai ça :

    	public function setup()
    	{
    		sfValidatorBase::setRequiredMessage('Ce champ est obligatoire.');
    		sfValidatorBase::setInvalidMessage('Ce champ est invalide.');
    		parent::setup();
    	}
    

    et le « configure() » de mon *Form, vide, les setRequiredMessage ne sont pas appelés et j’ai donc « Required » au lieu de mon nouveau texte.

    mais si je fais juste ça dans le « configure() » de mon *Form :

    	public function configure()
    	{
    $this->validatorSchema['label'] = new sfValidatorString(array('max_length' => 32), array('max_length' => 'Le nom ne doit pas dépasser %max_length% caractères.'));
    	}
    

    cette fois les setRequiredMessage sont pris en compte et j’ai les bons messages d’erreurs…

    J’ai testé et si je modifie le validateur d’un autre widget, j’ai toujours le mauvais message d’erreur, il faut donc pour que le setRequiredMessage() soit pris en compte, que je modifie son validateur..

    Je sais pas si ça peut te donner une piste, enfin ça confirme ce que tu as dit concernant le fait que le « parent::setup() » du Base*Form doit être appelé avant..

  19. Sebastien 4 août 2009 à 14 h 36 min #

    Désolé, j’ai dépassé avec mon « %3Cpre> »… :(

  20. Tim 4 août 2009 à 15 h 08 min #

    En fait, le fonctionnement est pas idéal. Mais tu as mis le doigt sur la logique.

    Tous les validators héritent de sfValidatorBase, donc du moment que tu redéfinis un validator, il peux prendre en compte tes derniers setRequiredMessage, vu qu’il crée une nouvelle instance.

    De ce que j’ai lu, ce fonctionnement va changer avec la 1.3, ca mérite que je me penche dessus prochainement :)

  21. Guillaume 18 août 2009 à 15 h 26 min #

    Salut Tim,

    Il faut savoir que pour Doctrine, le lien symbolique est légèrement différent car sfDoctrineplugin n’est pas installé dans l’application mais dans Symfony.

    Donc le chemin du XML dans mon cas (serveur UBUNTU), devient : /usr/share/php/symfony/plugins/sfDoctrinePlugin/i18n/sf_admin.fr.xml

    Cordialement.

  22. Tim 18 août 2009 à 18 h 17 min #

    c’est pareil pour Propel, pour ça que je précise bien « /votre/chemin/vers/symfony » :D

  23. shakir33 11 septembre 2009 à 17 h 24 min #

    je suis dsl mais ça marche pas ce billet

  24. Tim 16 septembre 2009 à 13 h 53 min #

    Et pourtant! Mais peut-être pourrait-tu être plus explicite sur le souci pour savoir ce qui ne marche pas :)

  25. kwark 19 septembre 2009 à 13 h 13 min #

    Bien le bonjour,

    bon je viens avec un problème incompréhensible ou peut être juste moi qui passe à coté d’un détail.

    J’ai fait tout ce qu’il faut comme expliqué dans le tuto.

    J’utilise symfo 1.2.8 avec propel.

    J’ai le fichier dans mon rep d’application :

    H:\symfony\chahut\apps\backend\i18n\sf_admin.xml

    J’ai config mon settings.yml :

    all:
    .settings:
    i18n: on
    default_culture: fr
    standard_helpers: [Partial, Cache, Form, I18N]

    J’ai clean cache 1K fois. Pas d’erreur.

    J’ai supprimé mon cache de mon navigateur, mes cookies je les ai mangés (supprimés).

    Et malgré tout cela rien pas de backend en français.

    Je capte pas ce que j’ai raté. Si quelqu’un aurait une réponse je suis preneur.

    Merci d’avance

    kwark

  26. Tim 20 septembre 2009 à 3 h 31 min #

    Hello,

    Tu peux déja vérifier dans ta debug bar que la culture est bien à fr. Ca permettra de voir si c’est un souci de culture ou de chargement du xml : )

  27. kwark 20 septembre 2009 à 13 h 29 min #

    Salut,

    Merci pour cette réponse, c’est vrai que j’avais zap de regarder dans la debug bar. Y a un truc bizarre dans la partie User. Voici ce que j’ai :

    User
    options:
    culture: null
    default_culture: fr

    attributeHolder:
    sfGuardSecurityUser: { user_id: 1 }
    symfony/user/sfUser/attributes: { }
    culture: fr

    settings:
    sf_default_culture: fr
    sf_i18n: true
    sf_i18n_cache_dir: ‘H:\symfony\chahut\cache\backend\dev\i18n’

    session:
    symfony/user/sfUser/culture: fr

    Le « culture:null » me trouble car tout le reste est bien en « fr ».
    Peux tu me dire de ton coté si tu as ça aussi ?

    Merci

  28. Tim 20 septembre 2009 à 13 h 41 min #

    Le champ culture devrait être à fr effectivement. C’est donc là le souci.

    Tu dois avoir quelque part dans ton application un setCulture problématique je pense.

    Tu as quelques lignes dans ton application où tu forces la culture?

  29. kwark 20 septembre 2009 à 21 h 26 min #

    Je viens de faire une recherche sur toute mon application pour vérifier si un setCulture était planqué car j’en ai pas mis vu que mon application est fraichement sortie des lignes de commandes de création.

    J’ai test au passage de le forcer avec un setCulture cela ne change rien.

    Ce qui me dérange dans le debug c’est d’avoir 2 lignes « culture », l’un en « null » et l’autre en « fr »

    Je continu de chercher car j’aimerai bien avoir trouver la réponse qui commence à me faire */é’*/

  30. Tim 21 septembre 2009 à 3 h 46 min #

    Je viens de refaire un test. J’ai également le culture à null.

    Donc c’est censé fonctionner. Si c’est pas un problème de culture, ca ne peut être qu’un problème de fichier de traduction.

    Tu as jeter un oeil à ton fichier? Il semble correspondre? J’avoue que j’ai pas énormément d’idée pour le coup

  31. virginie 23 octobre 2009 à 12 h 11 min #

    @kwark : j’avais a priori le même problème que toi. Je l’ai résolu de la façon suivante (même si débutante en Symfony, ce n’est peut être pas la meilleure façon de faire).

    - Déjà, le fichier recherché pour la traduction n’était pas sf_admin.xml mais message.xml (un oubli de config de ma part quelque part ?) Ça, je l’ai découvert en faisant un print_r($catalogue) dans la fonction __() de la classe I18Nhelper.
    Bref : renommage de sf_admin.xml en message.xml

    - Ensuite, en faisant un print_r($this->messages[$catalogue]) dans la fonction formatString() de la classe sfMessageFormat, j’ai vu que les traductions étaient bien récupérées mais que les clés du tableau n’avaient pas la bonne casse (‘Save and add’ au lieu de ‘save and add’ par exemple).
    Du coup je pense que le problème vient du fichier de traduction qui n’est peut être pas le bon… D’autant plus que certains messages manquent dans ce fichier.
    Pour ne pas reprendre tout le fichier de traduction (flemme, pas bien…), j’ai légèrement modifié la fonction formatString() en remplaçant :

          if (isset($variant[$string]))
          {
                  	$target = $variant[$string];
    

    par :

     if ((isset($variant[$string])) or (isset($variant[ucfirst($string)])))
          {
          	if(isset($variant[$string]))
            	$target = $variant[$string];
            else
    		$target = $variant[ucfirst($string)];
    

    Et j’ai ajouté dans le fichier de traduction certaines trad manquantes (il y en a sûrement d’autres)

          
            remove file
            Supprimer le fichier
          
           
            [show file]
            [Voir le fichier]
          
          
            Your modifications have been saved
            Enregistrer
          
          
            The form is not valid because it contains some errors.
            L'enregistrement n'a pas pu être effectué.
          
    

    Bon, je pense que c’est pas la meilleure solution de modifier la source de Symfony, et un fichier de traduction plus approprié serait sans doute une meilleure solution, mais bon, ça marche :-)

    J’espère que ça dépannera certain, personnellement ça faisait un bon moment que je m’arrachais les cheveux !

  32. Max 10 novembre 2009 à 11 h 00 min #

    Bonjour,

    Pour la traduction des libellés « Required. » et « Invalid. », j’ai trouvé le post suivant sur le groupe google.

    Il explique qu’il faut créer un fichier apps/mon_admin/i18n/messages.fr.xml avec le contenu ci-dessous :

    
    
        
        
          
            Required.
            Ce champ est obligatoire.
          
          
            Invalid.
            Ce champ est incorrect.
          
        
     
    

    Un petit cc et le tour est joué. Chez moi ça fonctionne avec sf 1.2.9.

  33. Stéphane 10 janvier 2010 à 21 h 02 min #

    Bonjour,

    Je vous propose un lien vers un billet de mon blog :http://www.zen-in-progress.com/symfony-traduction-totale-de-ladmin-generator/

    Dans ce dernier, j’explique une méthode pour traduire l’admin generator en français, notamment les « yes », « no », « yes or not », « Are you sure? » et « is empty ».

  34. [...] l'utilisateur. Par défaut, les modules d'admin de Symfony gèrent l'i18n. Ainsi, il est simple de traduire ces modules. Dans cet article je vais vous expliquer [...]

  35. loulourarph 15 avril 2010 à 15 h 55 min #

    Hello,

    Pour la version 1.4, pour définir les messages par défaut :

    abstract class BaseFormDoctrine extends sfFormDoctrine
    {
    public function setup()
    {
    sfValidatorBase::setDefaultMessage(‘required’, ‘champ obligatoire’);
    sfValidatorBase::setDefaultMessage(‘invalid’, ‘champ obligatoire’);
    parent::setup();
    }
    }

  36. loulourarph 15 avril 2010 à 15 h 57 min #

    J’ai été un peu vite…

    Il fallait lire:

    abstract class BaseFormDoctrine extends sfFormDoctrine
    {
    public function setup()
    {
    sfValidatorBase::setDefaultMessage(‘required’, ‘Champ obligatoire’);
    sfValidatorBase::setDefaultMessage(‘invalid’, ‘Valeur non valide’);
    parent::setup();
    }
    }

  37. loulourarph 15 avril 2010 à 16 h 37 min #

    Tout compte fait, ca ne marche pas terrible,
    ça ne fonctionne que si on définit le champ obligatoire dans le setup du formulaire…

  38. Tim 19 avril 2010 à 17 h 43 min #

    Merci loulouarph,

    je me suis pas encore penché sur ce changement de la 1.4!

  39. Toma 18 avril 2011 à 11 h 53 min #

    Le ticket est vieux mais vu qu’il n’y a pas de réponse, je vous la donne:
    C’est dans le projectConfiguration qu’il faut faire la config (ou seulement dans le backendConfiguration) :

    class backendConfiguration extends sfApplicationConfiguration
    {
    public function configure()
    {
    sfValidatorBase::setDefaultMessage(‘required’, ‘Ce champ est obligatoire.’);
    sfValidatorBase::setDefaultMessage(‘invalid’, ‘La valeur est invalide.’);
    }
    }


Laisser un message