Browse Source

Utilise la langue du navigateur à l'installation

L'installeur reconnait les langues du navigateur. Pour chacune d'elle, dans l'ordre indiqué, il tente de charger la traduction correspondante. Si aucune ne convient, le français est utilisé. Comme auparavant, s'il manque un élément au sein d'une traduction, c'est la traduction française qui est utilisée. À défaut, la clé elle-même (INSTALLATION_PARAGRAPH...) est affichée.

Le singleton Translation utilise par défaut le français. Il renseigne sur la langue sélectionnée parmi celles proposées à l'initialisation. Il fournit la liste des langues supportées. Il n'y a plus à se soucier de la langue par défaut, c'est pris en charge.
Christophe HENRY 7 years ago
parent
commit
f50bc3cdab
4 changed files with 79 additions and 29 deletions
  1. 12 0
      Functions.class.php
  2. 1 1
      common.php
  3. 57 17
      i18n.php
  4. 9 11
      install.php

+ 12 - 0
Functions.class.php

@@ -355,5 +355,17 @@ class Functions
         return true;
     }
 
+    /**
+    * @return les langues acceptées par le navigateur
+    */
+    public static function getBrowserLanguages() {
+        /* http://www.w3.org/International/questions/qa-lang-priorities.en.php
+         * ex: da, en-gb;q=0.8,en;q=0.7 --> array('da','en');
+        */
+        $languages = array();
+        $chunks = preg_split('/,\s*/', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
+        foreach($chunks as $chunk) $languages []= substr($chunk, 0, 2);
+        return array_unique($languages);
+    }
 }
 ?>

+ 1 - 1
common.php

@@ -57,7 +57,7 @@ raintpl::configure("base_url", null );
 raintpl::configure("tpl_dir", './templates/'.DEFAULT_THEME.'/' );
 raintpl::configure("cache_dir", "./cache/tmp/" );
 
-i18n_init();
+i18n_init(LANGUAGE);
 
 
 $view = '';

+ 57 - 17
i18n.php

@@ -6,30 +6,66 @@
  @description:  Fonctions de gestion de la traduction
  */
 
-define('DEFAULT_LANGUAGE', 'fr');
-
 class Translation {
 
-    const LOCALE_DIR='locale';
+    // Répertoire contenant les traductions
+    const LOCALE_DIR = 'locale';
+
+    /* Langue utilisée si aucune langue n'est demandée ou si les langues
+     * demandées ne sont pas disponibles. Idem pour les traductions.*/
+    const DEFAULT_LANGUAGE = 'fr';
 
     // tableau associatif des traductions
     var $trans = array();
+    var $language = ''; // langue courante
+    var $languages = array(); // langues disponibles
 
-    function __construct($location,$p_language=null) {
-        (defined('LANGUAGE')?$this->language = LANGUAGE:$this->language=$p_language);
-        $this->defaultLanguage = DEFAULT_LANGUAGE;
+    /** @param location L'endroit où se trouve le dossier 'locale'
+     *  @param languages Les langues demandées */
+    function __construct($location, $languages=array()) {
         $this->location = $location;
-        $this->load();
+        if (!is_array($languages)) $languages = array($languages);
+        $this->listLanguages();
+        $languages[]=self::DEFAULT_LANGUAGE;
+        foreach ($languages as $language)
+            if ($this->load($language)) {
+                $this->language = $language;
+                break;
+            }
     }
 
-    /* Charge la traduction pour la langue sélectionnée.*/
-    protected function load() {
-        $trans = $this->loadFile($this->language);
-        if ($this->language!=$this->defaultLanguage) {
-            $defaultTrans = $this->loadFile($this->defaultLanguage);
+    /* Peuple la liste des langues avec une traduction */
+    protected function listLanguages() {
+        $files = glob($this->location.'/'.self::LOCALE_DIR.'/*.json');
+        assert('is_array($files)');
+        //~ die(var_dump($files));
+        $this->languages = array();
+        foreach($files as $file){
+            preg_match('/([a-z]{2})\.json$/', $file, $matches);
+            assert('!empty($matches)');
+            //~ error_log(var_dump($file));
+            $this->languages [] = $matches[1];
+        }
+    }
+
+    /* Charge la traduction
+     * @param language la langue sélectionnée
+     * @return TRUE si le chargement s'est bien fait, FALSE sinon */
+    protected function load($language) {
+        if (!preg_match('/^[a-z]{2}$/', $language)) {
+            error_log("Invalid language: '$language'");
+            return false;
+        }
+        $trans = $this->loadFile($language);
+        if (empty($trans)) return false;
+        assert('in_array($language, $this->languages)');
+        if ($language!=self::DEFAULT_LANGUAGE) {
+            $defaultTrans = $this->loadFile(self::DEFAULT_LANGUAGE);
+            assert('!empty($defaultTrans)');
             $trans = array_merge($defaultTrans, $trans);
         }
         $this->trans = $trans;
+        return true;
     }
 
     /* Charge un fichier
@@ -39,7 +75,6 @@ class Translation {
         $fileName = $this->location.'/'.self::LOCALE_DIR.'/'.$language.'.json';
         $content = @file_get_contents($fileName);
         if (empty($content)) {
-            error_log("Translation for $language ($fileName) not found!");
             $translations = array();
         } else {
             $translations = json_decode($content, true);
@@ -62,25 +97,30 @@ class Translation {
         return $value;
     }
 
-    /* Ajoute une traduction à la suite de celle-ci. */
+    /* Ajoute une traduction à la suite de celle-ci.
+     * Note : il faudra appeler getJson() si nécessaire */
     function append(Translation $other) {
         $this->trans = array_merge($this->trans, $other->trans);
     }
 
+    /* @return la version Json des traductions */
     function getJson() {
         return json_encode($this->trans);
     }
 
 }
 
-function i18n_init($language=null){
+// Initialise le singleton, avec les langues possibles
+function i18n_init($languages){
     global $i18n,$i18n_js;
-    if(!isset($i18n)){
-        $i18n = new Translation(dirname(__FILE__),$language);
+    if (!isset($i18n)) {
+        $i18n = new Translation(dirname(__FILE__), $languages);
         $i18n_js = $i18n->getJson();
     }
+    return $i18n->language;
 }
 
+// Appel rapide de la traduction
 function _t($key,$args=array(),$debug=false){
     global $i18n;
     return $i18n->get($key, $args);

+ 9 - 11
install.php

@@ -11,8 +11,12 @@ require_once('i18n.php');
 global $i18n;
 $install_terminee=false;
 
-(isset($_GET['lang'])?$language=$_GET['lang']:$language=DEFAULT_LANGUAGE);
-i18n_init($language);
+if (isset($_GET['lang']))
+    $currentLanguage = i18n_init($_GET['lang']);
+else
+    $currentLanguage = i18n_init(Functions::getBrowserLanguages());
+
+$languageList = $i18n->languages;
 
 if (file_exists('constant.php')) {
     die(_t('ALREADY_INSTALLED'));
@@ -320,15 +324,9 @@ if (isset($_['installButton']) && empty($test[$lib_errors])) { // Pas d'erreur,
                 <span><?php echo _t('INSTALL_LANGUAGE') ?></span>
                 <select name="install_changeLngLeed" onchange="window.location.href='install.php?lang='+this[this.selectedIndex].value">
                 <?php
-                    $filesLeed = glob('./locale/*.json');
-                    foreach($filesLeed as $file){
-                        preg_match('#./locale/([a-z][a-z]).json#',$file,$matches);
-                        if ($file=='./locale/'.$language.'.json')
-                        {
-                            echo '<option selected=selected value="'.$matches[1].'">'.$matches[1].'</option>';
-                        } else {
-                            echo '<option value="'.$matches[1].'">'.$matches[1].'</option>';
-                        }
+                    foreach($languageList as $lang){
+                        $sel = $lang==$currentLanguage?'selected=selected':'';
+                        echo "<option $sel value='$lang'>$lang</option>";
                     }
                 ?>
                 </select>