From 03b9cb600a85fed79b8afa72ccdad2725da5f3da Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Tue, 7 Mar 2017 19:27:17 +0100 Subject: [PATCH] Fix autoLocale error and cover it with unit tests --- application/Utils.php | 34 ++++++++----- tests/languages/de/UtilsDeTest.php | 76 ++++++++++++++++++++++++++++++ tests/languages/en/UtilsEnTest.php | 76 ++++++++++++++++++++++++++++++ tests/languages/fr/UtilsFrTest.php | 76 ++++++++++++++++++++++++++++++ 4 files changed, 249 insertions(+), 13 deletions(-) diff --git a/application/Utils.php b/application/Utils.php index a936b09..5c07745 100644 --- a/application/Utils.php +++ b/application/Utils.php @@ -216,22 +216,30 @@ function is_session_id_valid($sessionId) function autoLocale($headerLocale) { // Default if browser does not send HTTP_ACCEPT_LANGUAGE - $attempts = array('en_US', 'en_US.utf8', 'en_US.UTF-8'); - if (isset($headerLocale)) { - // (It's a bit crude, but it works very well. Preferred language is always presented first.) - if (preg_match('/([a-z]{2,3})[-_]?([a-z]{2})?/i', $headerLocale, $matches)) { - $first = [strtolower($matches[1]), strtoupper($matches[1])]; - $separators = ['_', '-']; - $encodings = ['utf8', 'UTF-8']; - if (!empty($matches[2])) { - $second = [strtoupper($matches[2]), strtolower($matches[2])]; - $attempts = cartesian_product_generator([$first, $separators, $second, ['.'], $encodings]); - } else { - $attempts = cartesian_product_generator([$first, $separators, $first, ['.'], $encodings]); + $locales = array('en_US', 'en_US.utf8', 'en_US.UTF-8'); + if (! empty($headerLocale)) { + if (preg_match_all('/([a-z]{2,3})[-_]?([a-z]{2})?,?/i', $headerLocale, $matches, PREG_SET_ORDER)) { + $attempts = []; + foreach ($matches as $match) { + $first = [strtolower($match[1]), strtoupper($match[1])]; + $separators = ['_', '-']; + $encodings = ['utf8', 'UTF-8']; + if (!empty($match[2])) { + $second = [strtoupper($match[2]), strtolower($match[2])]; + $items = [$first, $separators, $second, ['.'], $encodings]; + } else { + $items = [$first, $separators, $first, ['.'], $encodings]; + } + $attempts = array_merge($attempts, iterator_to_array(cartesian_product_generator($items))); + } + + if (! empty($attempts)) { + $locales = array_merge(array_map('implode', $attempts), $locales); } } } - setlocale(LC_ALL, implode('implode', iterator_to_array($attempts))); + + setlocale(LC_ALL, $locales); } /** diff --git a/tests/languages/de/UtilsDeTest.php b/tests/languages/de/UtilsDeTest.php index 8a74038..545fa57 100644 --- a/tests/languages/de/UtilsDeTest.php +++ b/tests/languages/de/UtilsDeTest.php @@ -22,4 +22,80 @@ class UtilsDeTest extends UtilsTest $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $this->assertEquals('So 01 Jan 2017 10:11:12 EAT', format_date($date, false)); } + + /** + * Test autoLocale with a simple value + */ + public function testAutoLocaleValid() + { + $current = setlocale(LC_ALL, 0); + $header = 'en-us'; + autoLocale($header); + $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with an alternative locale value + */ + public function testAutoLocaleValidAlternative() + { + $current = setlocale(LC_ALL, 0); + $header = 'en_us.UTF8'; + autoLocale($header); + $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with multiples value, the first one is valid + */ + public function testAutoLocaleMultipleFirstValid() + { + $current = setlocale(LC_ALL, 0); + $header = 'en-us,de-de'; + autoLocale($header); + $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with multiples value, the second one is valid + */ + public function testAutoLocaleMultipleSecondValid() + { + $current = setlocale(LC_ALL, 0); + $header = 'pt_BR,fr-fr'; + autoLocale($header); + $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale without value: defaults to en_US. + */ + public function testAutoLocaleBlank() + { + $current = setlocale(LC_ALL, 0); + autoLocale(''); + $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with an invalid value: defaults to en_US. + */ + public function testAutoLocaleInvalid() + { + $current = setlocale(LC_ALL, 0); + autoLocale('pt_BR'); + $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } } diff --git a/tests/languages/en/UtilsEnTest.php b/tests/languages/en/UtilsEnTest.php index 60bcb65..7c829ac 100644 --- a/tests/languages/en/UtilsEnTest.php +++ b/tests/languages/en/UtilsEnTest.php @@ -22,4 +22,80 @@ class UtilsEnTest extends UtilsTest $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $this->assertEquals('Sun 01 Jan 2017 10:11:12 AM EAT', format_date($date, false)); } + + /** + * Test autoLocale with a simple value + */ + public function testAutoLocaleValid() + { + $current = setlocale(LC_ALL, 0); + $header = 'de-de'; + autoLocale($header); + $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with an alternative locale value + */ + public function testAutoLocaleValidAlternative() + { + $current = setlocale(LC_ALL, 0); + $header = 'de_de.UTF8'; + autoLocale($header); + $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with multiples value, the first one is valid + */ + public function testAutoLocaleMultipleFirstValid() + { + $current = setlocale(LC_ALL, 0); + $header = 'de-de;en-us'; + autoLocale($header); + $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with multiples value, the second one is valid + */ + public function testAutoLocaleMultipleSecondValid() + { + $current = setlocale(LC_ALL, 0); + $header = 'pt_BR,fr-fr'; + autoLocale($header); + $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale without value: defaults to en_US. + */ + public function testAutoLocaleBlank() + { + $current = setlocale(LC_ALL, 0); + autoLocale(''); + $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with an invalid value: defaults to en_US. + */ + public function testAutoLocaleInvalid() + { + $current = setlocale(LC_ALL, 0); + autoLocale('pt_BR'); + $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } } diff --git a/tests/languages/fr/UtilsFrTest.php b/tests/languages/fr/UtilsFrTest.php index 890308d..45996ee 100644 --- a/tests/languages/fr/UtilsFrTest.php +++ b/tests/languages/fr/UtilsFrTest.php @@ -22,4 +22,80 @@ class UtilsFrTest extends UtilsTest $date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $this->assertEquals('dim. 01 janv. 2017 10:11:12 EAT', format_date($date, false)); } + + /** + * Test autoLocale with a simple value + */ + public function testAutoLocaleValid() + { + $current = setlocale(LC_ALL, 0); + $header = 'de-de'; + autoLocale($header); + $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with an alternative locale value + */ + public function testAutoLocaleValidAlternative() + { + $current = setlocale(LC_ALL, 0); + $header = 'de_de.UTF8'; + autoLocale($header); + $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with multiples value, the first one is valid + */ + public function testAutoLocaleMultipleFirstValid() + { + $current = setlocale(LC_ALL, 0); + $header = 'de-de;en-us'; + autoLocale($header); + $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with multiples value, the second one is valid + */ + public function testAutoLocaleMultipleSecondValid() + { + $current = setlocale(LC_ALL, 0); + $header = 'pt_BR,de-de'; + autoLocale($header); + $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale without value: defaults to en_US. + */ + public function testAutoLocaleBlank() + { + $current = setlocale(LC_ALL, 0); + autoLocale(''); + $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } + + /** + * Test autoLocale with an invalid value: defaults to en_US. + */ + public function testAutoLocaleInvalid() + { + $current = setlocale(LC_ALL, 0); + autoLocale('pt_BR'); + $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + + setlocale(LC_ALL, $current); + } }