====== PHP RFC: Add Locale::getDisplayKeyword() and Locale::getDisplayKeywordValue() ====== * Version: 1.0 * Date: 2026-05-22 * Author: Weilin Du, lamentxu@163.com * Status: Under Discussion * Implementation: TBD * Discussion thread: ===== Introduction ===== This RFC proposes adding ''%%Locale::getDisplayKeyword()%%'' and ''%%Locale::getDisplayKeywordValue()%%'' to ''%%ext/intl%%'', also with their procedural aliases. These APIs expose ICU’s ''%%uloc_getDisplayKeyword()%%'' and ''%%uloc_getDisplayKeywordValue()%%'' to PHP userland. PHP already exposes a family of locale display helpers such as ''%%Locale::getDisplayLanguage()%%'', ''%%Locale::getDisplayRegion()%%'', ''%%Locale::getDisplayVariant()%%'', and ''%%Locale::getDisplayName()%%''. PHP also exposes ''%%Locale::getKeywords()%%'', which allows code to extract locale keyword pairs. What is currently missing is a way to localize the keyword names themselves and the display labels for their values. This proposal fills that gap in a way that is consistent with the existing ''%%Locale%%'' API surface. ===== Proposal ===== Add two new procedural functions and two new ''%%Locale%%'' static methods: function locale_get_display_keyword( string $keyword, ?string $displayLocale = null ): string|false {} function locale_get_display_keyword_value( string $locale, string $keyword, ?string $displayLocale = null ): string|false {} class Locale { public static function getDisplayKeyword( string $keyword, ?string $displayLocale = null ): string|false {} public static function getDisplayKeywordValue( string $locale, string $keyword, ?string $displayLocale = null ): string|false {} } The proposed methods intentionally follow the existing ''%%Locale::getDisplay*()%%'' naming pattern. The new APIs should follow the behavior of the existing display-oriented ''%%Locale%%'' methods: * If ''%%$displayLocale%%'' is ''%%null%%'', the current default locale is used. * On ICU failure, the function returns ''%%false%%'' and reports the error through the existing intl error mechanism. * Embedded NUL bytes in string parameters should continue to throw ''%%ValueError%%'', consistent with current locale input handling. * Invalid locale strings should continue to follow existing ICU-backed ''%%ext/intl%%'' behavior. ==== Motivation ==== This proposal brings practical value because it completes an already existing workflow in ''%%ext/intl%%'': * Parse or receive a locale identifier. * Extract keyword/value pairs via ''%%Locale::getKeywords()%%''. * Render those keywords and values for humans in a chosen display locale. Without these APIs, userland code must maintain its own mapping layer for keyword labels and keyword values, even though ICU already contains the data and PHP already exposes adjacent display APIs. Another important motivation is: as mentioned, php already has a family of Locale::getDisplay* functions, each matching with a corresponding ICU internal API. Now, every ICU internal API in the getDisplay* family has a php interface without ''%%uloc_getDisplayKeyword()%%'' and ''%%uloc_getDisplayKeywordValue()%%''. This change fills the little gap between ICU and php's userland interface. In the past, similar changes have been done without a RFC. The locale::isRightToLeft function is added without a RFC procedure since it is a direct exposure to a ICU API that php didn't cover. See: https://github.com/php/php-src/issues/18345. This is also true in Locale::addLikelySubtags/Locale::minimizeSubtags. However, with further discussion with the current maintainer of the extension it is decided to go through a RFC process of this change. ==== API Details ==== === locale_get_display_keyword() / Locale::getDisplayKeyword() === Returns a localized display label for a locale keyword, such as ''%%collation%%'' or ''%%calendar%%''. The first parameter indicates the keyword to be displayed. The second parameter determines the display locale, if it is null, the display locale should be the current default locale. Example intent: Locale::getDisplayKeyword('collation', 'en'); // should return the English display label for the ''%%collation%%'' keyword. Locale::getDisplayKeyword('currency', 'fr'); // should return the French display label for the ''%%calendar%%'' keyword. Procedural alias of ''%%Locale::getDisplayKeyword()%%'' is ''%%locale_get_display_keyword()%%''. === locale_get_display_keyword_value() / Locale::getDisplayKeywordValue() === Returns a localized display label for the value of a given locale keyword. The first parameter is the locale string that carries the keyword value. The second parameter identifies which keyword should be resolved from that locale. Similar to the above function, the third parameter determines the display locale, if it is null, the display locale should be the current default locale. Example intent: Locale::getDisplayKeywordValue( 'de_DE@collation=phonebook', 'collation', 'en' ); // should return the English display label for the ''%%phonebook%%'' collation value, which is "Phonebook Sort Order" Procedural alias of ''%%Locale::getDisplayKeywordValue()%%'' is ''%%locale_get_display_keyword_value()%%''. ===== Backward Incompatible Changes ===== There are no intentional backward incompatible changes to existing behavior. (Unless a PHP application declares its own function with an identical name.) ===== Proposed PHP Version(s) ===== PHP 8.6 ===== RFC Impact ===== ==== To the Ecosystem ==== This is a straightforward API addition. IDEs, LSPs, static analyzers, and documentation generators would need updated stubs so the new functions and methods are recognized. Userland internationalization libraries and admin UIs may simplify their own locale metadata mapping code if they choose to adopt these APIs. ==== To Existing Extensions ==== No existing extension behavior should change. ==== To SAPIs ==== No SAPI-specific impact is expected. ===== Voting Choices ===== Starting at 5th June if no further discussion emerged ===== Patches and Tests ===== TBD ===== Implementation ===== TBD ===== References ===== * ICU ''%%uloc_getDisplayKeyword()%%'' and ''%%uloc_getDisplayKeywordValue()%%'': https:%%//%%unicode-org.github.io/icu-docs/apidoc/released/icu4c/uloc_8h.html ===== Rejected Features ===== None ===== Changelog ===== * 2026-05-22: Initial wiki-format draft created..