diff --git a/application/Utils.php b/application/Utils.php index 48d474155..4d284ccbc 100644 --- a/application/Utils.php +++ b/application/Utils.php @@ -322,7 +322,7 @@ function format_date($date, $time = true, $intl = true) return $date->format($format); } $formatter = new IntlDateFormatter( - setlocale(LC_TIME, 0), + get_locale(LC_TIME), IntlDateFormatter::LONG, $time ? IntlDateFormatter::LONG : IntlDateFormatter::NONE ); @@ -503,3 +503,23 @@ function exception2text(Throwable $e): string { return $e->getMessage() . PHP_EOL . $e->getFile() . $e->getLine() . PHP_EOL . $e->getTraceAsString(); } + +/** + * Get the current locale, overrides 'C' locale which is no longer compatible with PHP-intl + * + * @param int $category Category of the locale (LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_ALL) + * + * @return string|false The locale, or false if not found. + * + * @see https://github.com/php/php-src/issues/12561 + */ +function get_locale(int $category = LC_CTYPE) +{ + $locale = setlocale($category, 0); + + if ($locale === 'C' || startsWith($locale, 'C.')) { + $locale = 'en_US.utf8'; // failback + } + + return $locale; +} diff --git a/application/front/controller/visitor/FeedController.php b/application/front/controller/visitor/FeedController.php index 622fe767e..88a455662 100644 --- a/application/front/controller/visitor/FeedController.php +++ b/application/front/controller/visitor/FeedController.php @@ -38,7 +38,7 @@ protected function processRequest(string $feedType, Request $request, Response $ } // Generate data. - $this->container->get('feedBuilder')->setLocale(strtolower(setlocale(LC_COLLATE, 0))); + $this->container->get('feedBuilder')->setLocale(strtolower(get_locale(LC_COLLATE))); $this->container->get('feedBuilder')->setHideDates($this->container->get('conf') ->get('privacy.hide_timestamps', false)); $this->container->get('feedBuilder')->setUsePermalinks( diff --git a/application/http/HttpUtils.php b/application/http/HttpUtils.php index 4bde1d5b8..a63b1fb45 100644 --- a/application/http/HttpUtils.php +++ b/application/http/HttpUtils.php @@ -55,7 +55,7 @@ function get_http_response( 'Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:45.0)' . ' Gecko/20100101 Firefox/45.0'; $acceptLanguage = - substr(setlocale(LC_COLLATE, 0), 0, 2) . ',en-US;q=0.7,en;q=0.3'; + substr(get_locale(LC_COLLATE), 0, 2) . ',en-US;q=0.7,en;q=0.3'; $maxRedirs = 3; if (!function_exists('curl_init')) { diff --git a/index.php b/index.php index def5b0889..560eb14d0 100644 --- a/index.php +++ b/index.php @@ -83,7 +83,7 @@ autoLocale($_SERVER['HTTP_ACCEPT_LANGUAGE']); } -new Languages(setlocale(LC_MESSAGES, 0), $conf); +new Languages(get_locale(LC_MESSAGES), $conf); $conf->setEmpty('general.timezone', date_default_timezone_get()); $conf->setEmpty('general.title', t('Shared bookmarks on ') . escape(index_url($_SERVER))); diff --git a/tests/languages/de/UtilsDeTest.php b/tests/languages/de/UtilsDeTest.php index d7a16eaca..014320d18 100644 --- a/tests/languages/de/UtilsDeTest.php +++ b/tests/languages/de/UtilsDeTest.php @@ -20,7 +20,7 @@ public function testIntlDateFormatter() */ public function testDateFormat() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('de-de'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/2\. Januar 2017 (um )?20:11:12 GMT\+0?3(:00)?/', format_date($date, true, true)); @@ -32,7 +32,7 @@ public function testDateFormat() */ public function testDateFormatNoTime() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('de-de'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/2\. Januar 2017/', format_date($date, false, true)); @@ -62,10 +62,10 @@ public function testDateFormatDefaultNoTime() */ public function testAutoLocaleValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'en-us'; autoLocale($header); - $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -75,10 +75,10 @@ public function testAutoLocaleValid() */ public function testAutoLocaleValidAlternative() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'en_US.UTF-8'; autoLocale($header); - $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -88,10 +88,10 @@ public function testAutoLocaleValidAlternative() */ public function testAutoLocaleMultipleFirstValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'en-us,de-de'; autoLocale($header); - $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -101,10 +101,10 @@ public function testAutoLocaleMultipleFirstValid() */ public function testAutoLocaleMultipleSecondAvailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'mgg_IN,fr-fr'; autoLocale($header); - $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('fr_FR.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -114,9 +114,9 @@ public function testAutoLocaleMultipleSecondAvailable() */ public function testAutoLocaleBlank() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale(''); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -126,9 +126,9 @@ public function testAutoLocaleBlank() */ public function testAutoLocaleUnavailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('mgg_IN'); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } diff --git a/tests/languages/en/UtilsEnTest.php b/tests/languages/en/UtilsEnTest.php index a59f989b5..af2226a2d 100644 --- a/tests/languages/en/UtilsEnTest.php +++ b/tests/languages/en/UtilsEnTest.php @@ -20,7 +20,7 @@ public function testIntlDateFormatter() */ public function testDateFormat() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('en_US.UTF-8'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); // Replace No-Break-Space with simple space @@ -34,7 +34,7 @@ public function testDateFormat() */ public function testDateFormatNoTime() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('en_US.UTF-8'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/January 2, 2017/', format_date($date, false, true)); @@ -64,10 +64,10 @@ public function testDateFormatDefaultNoTime() */ public function testAutoLocaleValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de-de'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -77,10 +77,10 @@ public function testAutoLocaleValid() */ public function testAutoLocaleValidAlternative() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de_de.UTF8'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -90,10 +90,10 @@ public function testAutoLocaleValidAlternative() */ public function testAutoLocaleMultipleFirstValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de-de;en-us'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -103,10 +103,10 @@ public function testAutoLocaleMultipleFirstValid() */ public function testAutoLocaleMultipleSecondAvailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'mgg_IN,fr-fr'; autoLocale($header); - $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('fr_FR.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -116,9 +116,9 @@ public function testAutoLocaleMultipleSecondAvailable() */ public function testAutoLocaleBlank() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale(''); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -128,9 +128,9 @@ public function testAutoLocaleBlank() */ public function testAutoLocaleUnavailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('mgg_IN'); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } diff --git a/tests/languages/fr/UtilsFrTest.php b/tests/languages/fr/UtilsFrTest.php index 799fa5c96..a6ae0e4b1 100644 --- a/tests/languages/fr/UtilsFrTest.php +++ b/tests/languages/fr/UtilsFrTest.php @@ -20,7 +20,7 @@ public function testIntlDateFormatter() */ public function testDateFormat() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('fr-fr'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/2 janvier 2017 (à )?20:11:12 UTC\+0?3(:00)?/', format_date($date)); @@ -32,7 +32,7 @@ public function testDateFormat() */ public function testDateFormatNoTime() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('fr-fr'); $date = DateTime::createFromFormat('Ymd_His', '20170102_201112'); $this->assertRegExp('/2 janvier 2017/', format_date($date, false, true)); @@ -62,10 +62,10 @@ public function testDateFormatDefaultNoTime() */ public function testAutoLocaleValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de-de'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -75,10 +75,10 @@ public function testAutoLocaleValid() */ public function testAutoLocaleValidAlternative() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de_de.UTF8'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -88,10 +88,10 @@ public function testAutoLocaleValidAlternative() */ public function testAutoLocaleMultipleFirstValid() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'de-de;en-us'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -101,10 +101,10 @@ public function testAutoLocaleMultipleFirstValid() */ public function testAutoLocaleMultipleSecondAvailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); $header = 'mgg_IN,de-de'; autoLocale($header); - $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); + $this->assertEquals('de_DE.utf8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -114,9 +114,9 @@ public function testAutoLocaleMultipleSecondAvailable() */ public function testAutoLocaleBlank() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale(''); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); } @@ -126,9 +126,9 @@ public function testAutoLocaleBlank() */ public function testAutoLocaleUnavailable() { - $current = setlocale(LC_ALL, 0); + $current = get_locale(LC_ALL); autoLocale('mgg_IN'); - $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0)); + $this->assertEquals('en_US.UTF-8', get_locale(LC_ALL)); setlocale(LC_ALL, $current); }