Formulaires i18n et ajout de langues automatisé

Ce post à pour but de faciliter les embedI18n pour les formulaires ayant des champs en i18n.

Il s’agit normalement de ceci dans votre formulaire principal (donc objectForm.class.php, et non objectTranslationForm.class.php) :

$this->embedI18n(array('en', 'fr',...));
$this->widgetSchema->setLabel('en', 'Anglais');
$this->widgetSchema->setLabel('fr', 'Français');
...
...
...

Il y aura donc autant de lignes que de langues à ajouter.

Imaginons maintenant la situation suivante :

Je suis développeur web, et je réalise un site international pour un client Mr Gui, il me donne la liste des langues, je code tous mes formulaires, et le lendemain, Mr Gui m’appelle, et me dit qu’il est désolé, il a oublié 3 langues, seulement voilà, j’ai 27 formulaires dans mon appli… (et oui il s’agit d’un énorme site, Mr Gui est un très gros client…). Je reprend donc mes 27 formulaires, et je rajoute mes embedForm et mes setLabel.
Mais, le lendemain, Mr Gui me rappelle pour me dire que finalement, le finlandais c’est pas la peine de le mettre, je dois donc r’ouvrir mes 27 formulaires et supprimer dans chacun le finlandais dans le embedI18n et dans le setLabel.

En résumé, même si une situation pareil est exagérée, il serait quand même pratique de centraliser les cultures, et d’automatiser les embedI18n et setLabel.

Voilà donc la solution que je propose aujourd’hui, en 2 étapes :

Etape 1 : centraliser les cultures

On sait déjà que Symfony permet l’utilisation dans les apps des fichier de configuration app.yml pour tout ce qui est options du site, et paramètres globaux. Nous allons donc utiliser ce principe pour définir toutes les langues.
Sachant que ces langues ne sont pas forcément propres à une application en particulier (frontend, backend, etc.) il convient de placer le fichier des langues dans un dossier plus haut placé. Créons donc un dossier config dans le dossier apps, et plaçons y un fichier app.yml (il pourra éventuellement contenir d’autres infos que les langues, on ne l’appellera donc pas languages.yml ou cultures.yml, …)

/apps/config/app.yml :

all:
  cultures:
    enabled:
      fr: Français
      en: English
      es: Español

Facile pour l’instant non ?
La syntaxe globale est en fait la suivante :

environnement:
  cultures:
    enabled:
      clé: label

Etape 2 : automatisation dans les formulaires

Maintenant que les langues sont centralisées, reste plus qu’à automatiser les formulaires, la méthode est la suivante:

public function configure()
{
  $array = sfYaml::load(sfConfig::get('sf_apps_dir').'/../config/app.yml'); /* 1 */
  $languages = $array['all']['cultures']['enabled']; /* 2 */
  $keys = array_keys($languages); /* 3 */
  $this->embedI18n($keys); /* 4 */

  /* 5 */
  foreach($languages as $key=>$lang)
  {
    $this->widgetSchema->setLabel($key, $lang);
  }
  parent::configure();    
}

Explications :
1 : le sfConfig::get() n’est pas joignable depuis les formulaires, et puis de toutes façons, le fichier n’est pas placé dans une app, il faut donc le charger autrement.
Le framework Symfony dispose d’un Yaml Loader qui le permet.

2 : les fichiers *.yml sont chargé par le loader Symfony comme des tableaux, construits de la manière suivante :

tableau:
  clé1: valeur
  sous-tableau:
    sous-clé1: valeur
    sous-tableau2 : { sous-sous-clé1: valeur, sous-sous-clé2: valeur }

Tout ceci sera chargé comme suit par le loader :

array(
  'tableau' => array(
    'clé1' => valeur,
    'sous-tableau' => array(
      'sous-clé1' => valeur,
      'sous-sous-tableau' => array(
        'sous-sous-clé1' => valeur,
        'sous-sous-clé2' => valeur
      ),
    ),
  ),
);

La lige marquée /* 2 */ permet donc de stocker dans la variable $languages un tableau de la forme :

array(
  'fr' => 'Français',
  'en' => 'English',
  ...,
  ...
);

3 : cette ligne permet des ranger les clés du tableaux languages (donc ‘fr’, ‘en’, etc.) dans un tableaux où elles seront valeurs, et non clés.
4 : cette ligne embed donc toutes les langues présentes dans le yml
5 : le foreach permet donc de set tous les labels, en correspondance avec les langues.

Et voilà !

Laisser un commentaire

Besoin d’un coup de main ?

Prenez rendez vous au tél avec nous pour discuter de votre projet.
C'est gratuit :)

Prenez RDV gratuitement (30 min)
Photo de Samuel Breton, Directeur Conseil chez agence Choosit à Montpellier

Aucun commentaire

  1. Peut être pourrait on déplacer ce code dans lib afin de factoriser au maximum le code et cerisesur le gâteau rédiger un test unitaire le couvrant.

  2. La gestion de ce projet est sacrement mal faite dans ce projet. Tous ces changements pendant la production…

  3. @ Tenshu > c’est exact, ce code doit être factorisé. Même s’il ne bougera plus une fois écrit dans chaque formulaire, cela reste une répétition du même bout de code, et effectivement cela mérite un refactorisation.

Laisser un commentaire

Voir l’étude de cas
Lire l’article