Rendre un plugin traduisible

L’une des conditions préalables à l’adoption par le plus grand nombre d’un plugin CakePHP, c’est la possibilité de pouvoir le traduire dans n’importe quelle langue. Voyons comment préparer un plugin à son internationalisation.

1. La méthode __d()

Nous avons vu dans des précédents articles l’utilisation des fonctions gettext __() et __n(). Il existe une troisième fonction, __d() qui permet, en plus de la chaine traduisible, de définir un « domaine », une sorte de contexte de la traduction. Cette fonction prend 3 paramètres :
  • $domain : le domaine
  • $msg : la chaine de caractères traduisible
  • $return : un booléen, false (par défaut) affiche directement la chaine ou sa traduction, true la renvoie seulement.

Dans le cadre d’un plugin, le plus simple est d’utiliser le nom du plugin comme domaine. Par exemple, dans la vue d’ajout d’un nouveau tag dans notre plugin de tagging multi-modèles :

<?php __d('tagging', 'Add Tag');?>

Nous avons pris le parti de développer le plugin en anglais, pour ensuite fournir la traduction en français. Bien évidemment, l’inverse est tout à fait possible !

Autre exemple avec les messages d’erreur des règles de validation, sachant qu’il est impossible d’utiliser une fonction directement dans le tableau $validate du modèle :

class Tag extends TaggingAppModel
{
	var $validate = array(
		'name' => array(
			'notEmpty' => array(
				'rule' => 'notEmpty',
				'required' => true,
				'allowEmpty' => false,
				'message' => 'notEmpty'
			),
			'isUnique' => array(
				'rule' => 'isUnique',
				'on' => 'create',
				'message' => 'isUnique'
			)
		),
		...
	);
}

Dans la vue d’ajout :

echo $form->input('name', array(
	'label' => __d('tagging', 'Name:', true),
	'error' => array(
		'notEmpty' => __d('tagging', 'Tag name cannot be left blank', true),
		'isUnique' => __d('tagging', 'This Tag already exists.', true),
	)
));

2. Extraction des chaines

La méthode est la même que pour extraire les chaines de l’application ou les chaines du coeur de CakePHP. Nous lançons la console en ligne de commande :

  1. cake i18n
  2. [E]xtract POT file from sources
  3. What is the full path you would like to extract? > {...}/plugins/tagging
  4. What is the full path you would like to output? > {...}/plugins/tagging/locale
  5. Would you like to merge all translations into one file? (y/n) > y
  6. What should we name this file? > tagging

Nous voyons ensuite CakePHP parcourir les fichiers du plugin à la recherche des appels aux fonctions gettext. Nous pouvons maintenant ouvrir PoEdit et créer un nouveau fichier à partir du catalogue /plugins/tagging/locale/tagging.pot, traduire notre plugin dans n’importe quelle langue et sauvegarder le fichier sous /plugins/tagging/locale/{code de la langue}/LC_MESSAGES/tagging.po.

Le changement de la langue du plugin se fera comme pour changer la langue de l’application, en définissant la variable de configuration ‘Config.language’ quelque part dans le bootstrap ou dans l’AppController :

Configure::write('Config.language', 'fre');
Pierre-Emmanuel Fringant

Articles connexes

Commentaires

Question subsidiaire : Comment t’y prends tu ensuite pour extraire les traduction propres à ton application en en excluant les traductions du plugin ? Par défaut cake i18n va scanner l’ensemble des fichiers, dont les plugins, non ?

(ie. avoir un fichier default.po/mo pour l’application en elle-même et un fichier .po/mo par plugin)

C’est vrai que l’extraction des chaines gettext de l’application va extraire également les chaines des plugins, mais en soit ce n’est pas très gênant, il suffit de ne pas traduire les chaines de plugins dans le fichier default.

La version 1.3.0-beta corrige ce problème, les chaines d’un domaine ne seront plus mergées dans le fichier default.pot de l’application.

Effectivement, je viens de tester cela avec la 1.3 RC3 et chaque domaine possède désormais sont fichier .pot.

Malheureusement, ils sont tous enregistrés dans app/locale.

J’aurais aimé pouvoir, au sein d’un plugin, utiliser __d(‘pluginname’, ‘My string’) et lorsque je lance cake i18n extract qu’il me créé un fichier pluginname.pot dans app/plugins/plugin_name/locale, plutot que dans app/locale. Cela aurait été bien plus simple pour mettre à jour les plugins et les distribuer avec l traduction.

J’ai pour le moment modifié manuellement ExtractTask pour lui faire faire ce que je désire, mais j’aurais bien aimé avoir ça directement dans le core. Ou alors il y a quelque chose que je n’ai pas compris.

Participez

Pour insérer une portion de code, utilisez <pre lang="php">...</pre>