[doc-en] master: intl: improve grapheme and Collator documentation (#5858)
| From: | Louis-Arnaud via GitHub | Date: | Fri, 23 Oct 2026 10:11:50 +0000 |
| Subject: | [doc-en] master: intl: improve grapheme and Collator documentation (#5858) | ||
| Groups: | php.doc.cvs | ||
| Request: | Send a blank email to doc-cvs+get-23882@lists.php.net to get a copy of this message | ||
Author: Louis-Arnaud (lacatoire)
Committer: GitHub (web-flow)
Pusher: lacatoire
Date: 2026-10-23T12:11:46+02:00
Commit: https://github.com/php/doc-en/commit/0b916fb90f8862046a56a5e05057ef6cd78384c1
Raw diff: https://github.com/php/doc-en/commit/0b916fb90f8862046a56a5e05057ef6cd78384c1.diff
intl: improve grapheme and Collator documentation (#5858)
- grapheme_strlen: add example showing null return on invalid UTF-8 input
with intl_get_error_code() / intl_error_name() error handling
- grapheme_strpos: expand locale parameter description to cover Unicode
locale extension key ks; add example distinguishing text vs. emoji
variation selectors with ks-identic
- grapheme_extract: add caution note that GRAPHEME_EXTR_COUNT limits
grapheme clusters, not bytes; use GRAPHEME_EXTR_MAXBYTES for byte budgets
- collator_set_strength: add example showing the ks locale extension key
as an alternative to setStrength(), with the full ks-* to Collator
constant mapping table
Fixes #5556, #5559, #5560, #5565
Changed paths:
M reference/intl/collator/set-strength.xml
M reference/intl/grapheme/grapheme-extract.xml
M reference/intl/grapheme/grapheme-strlen.xml
M reference/intl/grapheme/grapheme-strpos.xml
Diff:
diff --git a/reference/intl/collator/set-strength.xml b/reference/intl/collator/set-strength.xml
index df126fd13fdc..5dd1820f60aa 100644
--- a/reference/intl/collator/set-strength.xml
+++ b/reference/intl/collator/set-strength.xml
@@ -193,7 +193,7 @@ $arr = array( 'aรฒ', 'Ao', 'ao' );
$coll = collator_create( 'en_US' );
// Sort array using default strength.
-collator_sort( $coll, $arr );
+collator_sort( $coll, $arr );
var_export( $arr );
// Sort array using primary strength.
@@ -216,6 +216,67 @@ array (
1 => 'Ao',
2 => 'ao',
)
+]]>
+ </screen>
+ </example>
+ <example>
+ <title>Setting strength via the Unicode locale extension key
<literal>ks</literal></title>
+ <simpara>
+ Collation strength can also be set at <classname>Collator</classname> construction
time
+ using the Unicode locale extension key <literal>ks</literal> in the locale
identifier.
+ The mapping between <literal>ks</literal> values and
<classname>Collator</classname>
+ constants is:
+ </simpara>
+ <informaltable>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Locale key value</entry>
+ <entry>Collator constant</entry>
+ </row>
+ </thead>
+ <tbody>
+
<row><entry><literal>ks-level1</literal></entry><entry><constant>Collator::PRIMARY</constant></entry></row>
+
<row><entry><literal>ks-level2</literal></entry><entry><constant>Collator::SECONDARY</constant></entry></row>
+
<row><entry><literal>ks-level3</literal></entry><entry><constant>Collator::TERTIARY</constant></entry></row>
+
<row><entry><literal>ks-level4</literal></entry><entry><constant>Collator::QUATERNARY</constant></entry></row>
+
<row><entry><literal>ks-identic</literal></entry><entry><constant>Collator::IDENTICAL</constant></entry></row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <simpara>
+ <constant>Collator::DEFAULT_STRENGTH</constant> has no
<literal>ks-*</literal> equivalent
+ and must be set programmatically via <function>collator_set_strength</function>.
+ </simpara>
+ <programlisting role="php">
+<![CDATA[
+<?php
+
+$textStyle = "\u{263A}\u{FE0E}"; // U+263A + U+FE0E (text presentation selector)
+$emojiStyle = "\u{263A}\u{FE0F}"; // U+263A + U+FE0F (emoji presentation selector)
+
+// Default collator (TERTIARY strength): variation selectors are ignored.
+$collDefault = new Collator('en_US');
+var_dump($collDefault->compare($textStyle, $emojiStyle) === 0); // bool(true)
+
+// Identical strength via setStrength().
+$coll1 = new Collator('en_US');
+$coll1->setStrength(Collator::IDENTICAL);
+var_dump($coll1->compare($textStyle, $emojiStyle) === 0); // bool(false)
+
+// Equivalent: identical strength via the ks locale extension key.
+$coll2 = new Collator('en_US-u-ks-identic');
+var_dump($coll2->compare($textStyle, $emojiStyle) === 0); // bool(false)
+
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+bool(true)
+bool(false)
+bool(false)
]]>
</screen>
</example>
@@ -228,6 +289,7 @@ array (
<simplelist>
<member><link linkend="intl.collator-constants">Collator
constants</link></member>
<member><function>collator_get_strength</function></member>
+ <member><function>collator_create</function></member>
</simplelist>
</para>
</refsect1>
diff --git a/reference/intl/grapheme/grapheme-extract.xml
b/reference/intl/grapheme/grapheme-extract.xml
index c892ecc0dac9..0944a16853d4 100644
--- a/reference/intl/grapheme/grapheme-extract.xml
+++ b/reference/intl/grapheme/grapheme-extract.xml
@@ -49,14 +49,26 @@
</para>
<para>
<simplelist>
- <member>GRAPHEME_EXTR_COUNT (default) -<parameter>size</parameter> is
the number of default
+ <member><constant>GRAPHEME_EXTR_COUNT</constant> (default) -
<parameter>size</parameter> is the number of default
grapheme clusters to extract.</member>
- <member>GRAPHEME_EXTR_MAXBYTES -<parameter>size</parameter> is the
maximum number of bytes
+ <member><constant>GRAPHEME_EXTR_MAXBYTES</constant> -
<parameter>size</parameter> is the maximum number of bytes
returned.</member>
- <member>GRAPHEME_EXTR_MAXCHARS - <parameter>size</parameter> is the
maximum number of UTF-8
+ <member><constant>GRAPHEME_EXTR_MAXCHARS</constant> -
<parameter>size</parameter> is the maximum number of UTF-8
characters returned.</member>
</simplelist>
</para>
+ <caution>
+ <simpara>
+ <constant>GRAPHEME_EXTR_COUNT</constant> limits the number of grapheme clusters
(visual
+ units), not the number of bytes. A single grapheme cluster can span many bytes โ for
+ example, a family emoji with ZWJ sequences
(<literal>๐จโ๐ฉโ๐งโ๐ฆ</literal>) is
+ one grapheme cluster but 25 bytes. When the extracted string must fit within a byte budget,
+ use <constant>GRAPHEME_EXTR_MAXBYTES</constant> instead.
+ <constant>GRAPHEME_EXTR_MAXBYTES</constant> always returns complete grapheme
clusters
+ within the byte budget, but returns an empty string if the budget is smaller than the
+ first grapheme cluster.
+ </simpara>
+ </caution>
</listitem>
</varlistentry>
<varlistentry>
@@ -147,11 +159,13 @@ o%CC%88
<para>
<simplelist>
<member><function>grapheme_substr</function></member>
- <member>
- <link xlink:href="&uri.unicode.graphemes;">
- Unicode Text Segmentation: Grapheme Cluster Boundaries
- </link>
- </member>
+ <member><function>grapheme_strlen</function></member>
+ <member><function>grapheme_strpos</function></member>
+ <member>
+ <link xlink:href="&uri.unicode.graphemes;">
+ Unicode Text Segmentation: Grapheme Cluster Boundaries
+ </link>
+ </member>
</simplelist>
</para>
</refsect1>
diff --git a/reference/intl/grapheme/grapheme-strlen.xml
b/reference/intl/grapheme/grapheme-strlen.xml
index c565ebec1799..0aee41a3a7ef 100644
--- a/reference/intl/grapheme/grapheme-strlen.xml
+++ b/reference/intl/grapheme/grapheme-strlen.xml
@@ -64,6 +64,38 @@ print grapheme_strlen( 'abc' . $char_a_ring_nfd . $char_o_diaeresis_nfd
. $char_
6
]]>
</screen>
+ <example>
+ <title>Handling invalid UTF-8 input</title>
+ <simpara>
+ <function>grapheme_strlen</function> returns &null; or &false; on failure,
including
+ when the input is not valid UTF-8.
+ Use <function>intl_get_error_code</function> and
<function>intl_error_name</function>
+ to retrieve the ICU error details.
+ </simpara>
+ <programlisting role="php">
+<![CDATA[
+<?php
+
+$string = "\xFF"; // invalid UTF-8 byte sequence
+$length = grapheme_strlen($string);
+
+if (!is_int($length)) {
+ $code = intl_get_error_code();
+ printf("grapheme_strlen() failed: %s (%d)\n", intl_error_name($code), $code);
+} else {
+ echo $length, PHP_EOL;
+}
+
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+grapheme_strlen() failed: U_INVALID_CHAR_FOUND (10)
+]]>
+ </screen>
+ </example>
</refsect1>
<refsect1 role="seealso">
@@ -78,6 +110,8 @@ print grapheme_strlen( 'abc' . $char_a_ring_nfd . $char_o_diaeresis_nfd
. $char_
<member><function>iconv_strlen</function></member>
<member><function>mb_strlen</function></member>
<member><function>strlen</function></member>
+ <member><function>intl_get_error_code</function></member>
+ <member><function>intl_error_name</function></member>
</simplelist>
</para>
</refsect1>
diff --git a/reference/intl/grapheme/grapheme-strpos.xml
b/reference/intl/grapheme/grapheme-strpos.xml
index 4cfe2942f569..58962fd72805 100644
--- a/reference/intl/grapheme/grapheme-strpos.xml
+++ b/reference/intl/grapheme/grapheme-strpos.xml
@@ -55,7 +55,21 @@
<varlistentry>
<term><parameter>locale</parameter></term>
<listitem>
- &intl.param.grapheme.locale;
+ <simpara>
+ Locale to use. The locale affects how grapheme clusters are defined and
+ how strings are compared. An empty string or &null; uses the default
+ locale.
+ </simpara>
+ <simpara>
+ The locale identifier may include Unicode locale extension keys to
+ control collation behavior. In particular, the <literal>ks</literal>
+ key controls collation strength: for example,
+ <literal>en_US-u-ks-identic</literal> enables identical-level
+ comparison, which distinguishes Unicode variation selectors (such as
+ emoji vs. text presentation) that are otherwise treated as equivalent.
+ See <methodname>Collator::setStrength</methodname> for the full
+ mapping of <literal>ks</literal> values to collation strength levels.
+ </simpara>
</listitem>
</varlistentry>
</variablelist>
@@ -115,6 +129,42 @@ print grapheme_strpos( $char_a_ring_nfd . $char_a_ring_nfd .
$char_o_diaeresis_n
2
]]>
</screen>
+ <example>
+ <title>Using the <literal>ks-identic</literal> locale key to distinguish
variation selectors</title>
+ <simpara>
+ By default, Unicode variation selectors (U+FE0E text, U+FE0F emoji) are ignored
+ during comparison. Using the <literal>ks-identic</literal> locale extension key
+ enables identical-level collation, which treats them as distinct characters.
+ </simpara>
+ <note>
+ <simpara>
+ The <parameter>locale</parameter> parameter is available since PHP 8.5.0.
+ </simpara>
+ </note>
+ <programlisting role="php">
+<![CDATA[
+<?php
+
+$textStyle = "\u{263A}\u{FE0E}"; // U+263A + U+FE0E (text presentation selector)
+$emojiStyle = "\u{263A}\u{FE0F}"; // U+263A + U+FE0F (emoji presentation selector)
+
+// Default locale: variation selectors are ignored, so the needle is found at position 0.
+var_dump(grapheme_strpos($textStyle, $emojiStyle));
+
+// With ks-identic: variation selectors are significant, so no match is found.
+var_dump(grapheme_strpos($textStyle, $emojiStyle, 0, 'en_US-u-ks-identic'));
+
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+int(0)
+bool(false)
+]]>
+ </screen>
+ </example>
</refsect1>
<refsect1 role="seealso">
@@ -126,6 +176,7 @@ print grapheme_strpos( $char_a_ring_nfd . $char_a_ring_nfd . $char_o_diaeresis_n
<member><function>grapheme_strripos</function></member>
<member><function>grapheme_strrpos</function></member>
<member><function>grapheme_strstr</function></member>
+ <member><methodname>Collator::setStrength</methodname></member>
<member>
<link xlink:href="&uri.unicode.graphemes;">
Unicode Text Segmentation: Grapheme Cluster Boundaries