rfc:getdisplaykeyword_and_getdisplaykeywordvalue

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..
rfc/getdisplaykeyword_and_getdisplaykeywordvalue.txt · Last modified: by lamentxu