Commit fcd0f72cdd0 for php.net

commit fcd0f72cdd06728d1276419d77ca079c0789af48
Author: David Carlier <devnexen@gmail.com>
Date:   Fri Apr 18 19:10:23 2025 +0100

    GH-18345: adding Locale::isRightToLeft.

    Checks is the locale is written left to right.
    It makes sure all the needed likely subtags are included (maximization)
    then determines the direction by known matches.

    close GH-18351

diff --git a/NEWS b/NEWS
index 80bda686a1b..47bf820d6b6 100644
--- a/NEWS
+++ b/NEWS
@@ -85,6 +85,8 @@ PHP                                                                        NEWS
     with uninitialised classes or clone failure. (David Carlier)
   . Added DECIMAL_COMPACT_SHORT/DECIMAL_COMPACT_LONG for NumberFormatter class.
     (BogdanUngureanu)
+  . Added Locale::isRightToLeft to check if a locale is written right to left.
+    (David Carlier)

 - MySQLi:
   . Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice).
diff --git a/UPGRADING b/UPGRADING
index 2ce2ba3c120..6b6c555adcf 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -309,6 +309,10 @@ PHP 8.5 UPGRADE NOTES
   . Added enchant_dict_remove() to put a word on the exclusion list and
     remove it from the session dictionary.

+- Intl:
+  . Added locale_is_right_to_left/Locale::isRightToLeft, returns true if
+    the locale is written right to left (after its enrichment with likely subtags).
+
 - Pdo\Sqlite:
   . Added support for Pdo\Sqlite::setAuthorizer(), which is the equivalent of
     SQLite3::setAuthorizer(). The only interface difference is that the
diff --git a/ext/intl/locale/locale.stub.php b/ext/intl/locale/locale.stub.php
index 1ec2af308ed..fcda8f68409 100644
--- a/ext/intl/locale/locale.stub.php
+++ b/ext/intl/locale/locale.stub.php
@@ -133,4 +133,9 @@ public static function canonicalize(string $locale): ?string {}
      * @alias locale_accept_from_http
      */
     public static function acceptFromHttp(string $header): string|false {}
+
+    /**
+     * @alias locale_is_right_to_left
+     */
+    public static function isRightToLeft(string $locale): bool {}
 }
diff --git a/ext/intl/locale/locale_arginfo.h b/ext/intl/locale/locale_arginfo.h
index 7bba882d204..40426a1aa9e 100644
Binary files a/ext/intl/locale/locale_arginfo.h and b/ext/intl/locale/locale_arginfo.h differ
diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c
index b2891de9d4a..bba52a90994 100644
--- a/ext/intl/locale/locale_methods.c
+++ b/ext/intl/locale/locale_methods.c
@@ -1619,3 +1619,19 @@ PHP_FUNCTION(locale_accept_from_http)
 	RETURN_STRINGL(resultLocale, len);
 }
 /* }}} */
+
+PHP_FUNCTION(locale_is_right_to_left)
+{
+	char *locale;
+	size_t locale_len;
+
+	ZEND_PARSE_PARAMETERS_START(1, 1)
+		Z_PARAM_STRING(locale, locale_len)
+	ZEND_PARSE_PARAMETERS_END();
+
+	if (!locale_len) {
+		locale = (char *)intl_locale_get_default();
+	}
+
+	RETURN_BOOL(uloc_isRightToLeft(locale));
+}
diff --git a/ext/intl/php_intl.stub.php b/ext/intl/php_intl.stub.php
index f3a80dd5119..4469845483e 100644
--- a/ext/intl/php_intl.stub.php
+++ b/ext/intl/php_intl.stub.php
@@ -501,6 +501,8 @@ function locale_lookup(array $languageTag, string $locale, bool $canonicalize =

 function locale_accept_from_http(string $header): string|false {}

+function locale_is_right_to_left(string $locale): bool {}
+
 /* msgformat */

 function msgfmt_create(string $locale, string $pattern): ?MessageFormatter {}
diff --git a/ext/intl/php_intl_arginfo.h b/ext/intl/php_intl_arginfo.h
index 11c585d8df6..bf016abf99d 100644
Binary files a/ext/intl/php_intl_arginfo.h and b/ext/intl/php_intl_arginfo.h differ
diff --git a/ext/intl/tests/locale_is_right_to_left.phpt b/ext/intl/tests/locale_is_right_to_left.phpt
new file mode 100644
index 00000000000..c586582d422
--- /dev/null
+++ b/ext/intl/tests/locale_is_right_to_left.phpt
@@ -0,0 +1,16 @@
+--TEST--
+locale_is_right_to_left
+--EXTENSIONS--
+intl
+--FILE--
+<?php
+var_dump(Locale::isRightToLeft("en-US"));
+var_dump(Locale::isRightToLeft("\INVALID\\"));
+var_dump(Locale::isRightToLeft(""));
+var_dump(Locale::isRightToLeft("ar"));
+?>
+--EXPECT--
+bool(false)
+bool(false)
+bool(false)
+bool(true)