From 3a6317c25a8592371f710757094b1681138706fc Mon Sep 17 00:00:00 2001
From: Nicolas Bouilleaud <nico@bou.io>
Date: Thu, 18 Apr 2019 10:16:00 +0200
Subject: [PATCH] Rework i18n using Symfony/translation

Reimplement the __() and __f() functions using Symfony.
---
 README.md        |  2 +-
 app/inc/i18n.php | 53 ++++++++++++++++++++++++++++-------
 composer.json    |  3 +-
 composer.lock    | 72 +++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 117 insertions(+), 13 deletions(-)

diff --git a/README.md b/README.md
index de315d6b..9716782f 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ Follow the instructions on <https://framagit.org/framasoft/framadate/framadate/w
 
 * PHP [PHP 5.6](http://php.net)
 * Templating [Smarty](http://www.smarty.net/),
-* I18N [o80-i18n](https://github.com/olivierperez/o80-i18n)
+* i18n [Symfony/Translation](https://github.com/symfony/Translation)
 * Database: PostgreSQL 9.6 or [MySQL 5.6+](https://dev.mysql.com/downloads/mysql/5.6.html)/[MariaDB 10.1+](https://www.debian.org/releases/stable/mips/release-notes/ch-whats-new.en.html#mariadb-replaces-mysql)
 
 ---
diff --git a/app/inc/i18n.php b/app/inc/i18n.php
index 002837b6..ebcc4ece 100644
--- a/app/inc/i18n.php
+++ b/app/inc/i18n.php
@@ -17,19 +17,52 @@
  * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
  */
 
-// Prepare I18N instance
-$i18n = \o80\i18n\I18N::instance();
-$i18n->setDefaultLang(DEFAULT_LANGUAGE);
-$i18n->setPath(__DIR__ . '/../../locale');
+// Change language when requested
+if (isset($_REQUEST['lang'])
+    && is_string($_REQUEST['lang'])
+    && in_array($_REQUEST['lang'], array_keys($ALLOWED_LANGUAGES), true)) {
+    $_SESSION['lang'] = $_REQUEST['lang'];
+}
+
+// Use the user-specified locale or the browser-specified locale
+$locale = $_SESSION['lang']
+    ?: locale_accept_from_http($_SERVER['HTTP_ACCEPT_LANGUAGE']);
 
-// Change langauge when user asked for it
-if (isset($_POST['lang']) && is_string($_POST['lang']) && in_array($_POST['lang'], array_keys($ALLOWED_LANGUAGES), true)) {
-    $_SESSION['lang'] = $_POST['lang'];
+/* i18n helper functions */
+use Symfony\Component\Translation\Loader\PoFileLoader;
+use Symfony\Component\Translation\Translator;
+
+class __i18n {
+    private static $translator;
+    private static $fallbacktranslator;
+    public static function translate($key) {
+        if (!isset(self::$translator)) {
+            global $locale, $ALLOWED_LANGUAGES;
+            $found_locale = locale_lookup(array_keys($ALLOWED_LANGUAGES), $locale);
+            self::$translator = new Translator($found_locale);
+            self::$translator->addLoader('pofile', new PoFileLoader());
+            self::$translator->addResource('pofile', ROOT_DIR . "po/{$found_locale}.po", $found_locale);
+            # Fallback:
+            # For Symfony/Translation, empty strings are valid, but in po files, untranslated strings are "".
+            # This means we cannot use the standard $translator->setFallbackLocales() mechanism :(
+            self::$fallbacktranslator = new Translator(DEFAULT_LANGUAGE);
+            self::$fallbacktranslator->addLoader('pofile', new PoFileLoader());
+            self::$fallbacktranslator->addResource('pofile', ROOT_DIR . "po/" . DEFAULT_LANGUAGE . ".po", DEFAULT_LANGUAGE);
+        }
+        return self::$translator->trans($key)
+            ?: self::$fallbacktranslator->trans($key);
+    }
 }
 
-/* <html lang="$locale"> */
-$i18n->get('', 'Something, just to load the dictionary');
-$locale = str_replace('_', '-', $i18n->getLoadedLang());
+function __($section, $key) {
+    return __i18n::translate($key);
+}
+
+function __f($section, $key, $args) {
+    $msg = __i18n::translate($key);
+    $args = array_slice(func_get_args(), 2);
+    return vsprintf($msg, $args);
+}
 
 /* Date Format */
 $date_format['txt_full'] = __('Date', '%A, %B %e, %Y'); //summary in create_date_poll.php and removal date in choix_(date|autre).php
diff --git a/composer.json b/composer.json
index ba935307..8405dc79 100644
--- a/composer.json
+++ b/composer.json
@@ -65,7 +65,8 @@
         "egulias/email-validator": "~2.1",
         "doctrine/dbal": "^2.5",
         "doctrine/migrations": "^1.5",
-        "sensiolabs/ansi-to-html": "^1.1"
+        "sensiolabs/ansi-to-html": "^1.1",
+        "symfony/translation": "^3.4"
     },
 
     "require-dev": {
diff --git a/composer.lock b/composer.lock
index f11945d6..fd91a7bf 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "3209f04f589a5ea384cad035ab70b68b",
+    "content-hash": "e66be74bb56015e4d3bb7b83fd8fc044",
     "packages": [
         {
             "name": "doctrine/annotations",
@@ -1420,6 +1420,76 @@
             ],
             "time": "2018-04-26T10:06:28+00:00"
         },
+        {
+            "name": "symfony/translation",
+            "version": "v3.4.26",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/translation.git",
+                "reference": "aae26f143da71adc8707eb489f1dc86aef7d376b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/translation/zipball/aae26f143da71adc8707eb489f1dc86aef7d376b",
+                "reference": "aae26f143da71adc8707eb489f1dc86aef7d376b",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5.9|>=7.0.8",
+                "symfony/polyfill-mbstring": "~1.0"
+            },
+            "conflict": {
+                "symfony/config": "<2.8",
+                "symfony/dependency-injection": "<3.4",
+                "symfony/yaml": "<3.4"
+            },
+            "require-dev": {
+                "psr/log": "~1.0",
+                "symfony/config": "~2.8|~3.0|~4.0",
+                "symfony/dependency-injection": "~3.4|~4.0",
+                "symfony/finder": "~2.8|~3.0|~4.0",
+                "symfony/http-kernel": "~3.4|~4.0",
+                "symfony/intl": "^2.8.18|^3.2.5|~4.0",
+                "symfony/var-dumper": "~3.4|~4.0",
+                "symfony/yaml": "~3.4|~4.0"
+            },
+            "suggest": {
+                "psr/log-implementation": "To use logging capability in translator",
+                "symfony/config": "",
+                "symfony/yaml": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Translation\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Translation Component",
+            "homepage": "https://symfony.com",
+            "time": "2019-04-10T16:00:48+00:00"
+        },
         {
             "name": "symfony/yaml",
             "version": "v3.4.12",
-- 
GitLab