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 :

1
2
3
4
5
6
all:
  cultures:
    enabled:
      fr: Français
      en: English
      es: Español

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

1
2
3
4
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 :

1
2
3
4
5
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 :

1
2
3
4
5
6
7
8
9
10
11
12
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 :

1
2
3
4
5
6
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à !

Partagez cet article