Fix AsYouTypeFormatter dropping parens from rule-based formats (BR, RU, CO)#3993
Open
PetroczyP wants to merge 1 commit intogoogle:masterfrom
Open
Fix AsYouTypeFormatter dropping parens from rule-based formats (BR, RU, CO)#3993PetroczyP wants to merge 1 commit intogoogle:masterfrom
PetroczyP wants to merge 1 commit intogoogle:masterfrom
Conversation
AsYouTypeFormatter rendered the bare format() string and ignored nationalPrefixFormattingRule, so any punctuation supplied by the rule (e.g. parens around the area code) was lost as the user typed. Affected regions include BR mobile, RU mobile, and CO; static format() already handled them correctly via the same metadata, since the rule is only applied on the AYTF template-build path. Adds a private applyNationalPrefixFormattingRule helper in AsYouTypeFormatter (Java/C++/JS) that splices the rule's punctuation into the format template at both call sites (createFormattingTemplate and attemptToFormatAccruedDigits). Three branches: empty rule or international-mode renders the bare format; rule beginning with the national prefix has the prefix and adjacent separator stripped, then the remainder spliced; rule that wraps the prefix in literal punctuation falls back to the bare format to avoid doubling the trunk prefix that AYTF renders separately via prefixBeforeNationalNumber. Also defensively falls back to EMPTY_METADATA when GetMetadataForNonGeographicalRegion returns null (unrecognised calling code), since the new helper now reads the current metadata's national prefix. Tests cover BR, RU, CO, the international-format path, and the existing US/AR/DE/AO/IT/GB regression guards in all three languages. Test-only metadata regenerated for BR/RU/CO; production PhoneNumberMetadata.xml is untouched. Fixes Issue Tracker #437456062.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes Issue Tracker #437456062
where
AsYouTypeFormatterdrops the parenthesis literals from countries whosenational format derives them from
nationalPrefixFormattingRulerather thanfrom the inline
<format>template — most visibly for BR mobile, RU mobile,and CO. Static
format()already produces the parens correctly using thesame metadata; the bug is isolated to AYTF's template-build path, which only
ever read
getFormat()and ignoredgetNationalPrefixFormattingRule()'swrap.
Fix
A small private helper —
applyNationalPrefixFormattingRule(Java) /ApplyNationalPrefixFormattingRule(C++, PascalCase per Google C++ style) /applyNationalPrefixFormattingRule_(JS, with the Closure private-nameunderscore) — is invoked at two sites in each language,
createFormattingTemplateandattemptToFormatAccruedDigits, to splice therule's punctuation into the format string before the existing template
substitution runs. Three branches:
(preserves current behavior for US, AR, DE, etc. and for the
format(num, INTERNATIONAL)rendering path)."$NP $FG"after metadatasubstitution →
"0 $1"for GB,"8 $1"for RU): strip the leading prefixplus any adjacent separator, then splice the remainder. The trunk prefix
continues to render separately via
prefixBeforeNationalNumber, so thisavoids doubling it.
"($NP$FG)"which wraps the prefix inside literal punctuation): returnthe bare format. Splicing such a rule would duplicate the trunk prefix
that AYTF renders separately.
A complementary defensive fallback at the country-code-extraction function
(
attemptToExtractCountryCallingCodein Java,AttemptToExtractCountryCodein C++,
attemptToExtractCountryCallingCode_in JS) preserves the"currentMetadata is never null" invariant the helper relies on: when the
country code maps to a non-geographical region (e.g.
+800toll-free) andgetMetadataForNonGeographicalRegionreturns null because the metadataisn't loaded, fall back to the existing
EMPTY_METADATAsentinel. Samepattern as the constructor and the regular-region path.
Test plan
(11) 3234-5678rendered char-by-char against region BR.Single test method per language asserts every digit boundary, covering
both the final-step assertion and the intermediate steps where parens
first materialise. (BR test metadata only carries a fixed-line
numberFormat; the($FG)rule shape is identical to production BRmobile, so a fix verified on BR fixed-line covers the reported BR
mobile case.)
8 (912) 345-67-89rendered char-by-char against region RU,including the closing
)that materialises only after a latersubscriber digit advances
lastMatchPositionpast it (transition8 (912→8 (912) 3at digit 5).(601) 1234567rendered char-by-char against region CO,same
($FG)rule shape on a different pattern length to prove the fixis structural rather than BR-specific.
+55 11 3234-5678rendered againstregion ZZ to confirm the
isInternationalModeshort-circuit returnsthe bare format (matching
format(num, INTERNATIONAL)).$NP$FG), GB (rule($NP$FG))AYTF tests all continue to pass — the no-change paths are byte-identical.
mvn -pl libphonenumber -am test -B→ 287 tests pass,0 failures.
./libphonenumber_test→ 331 tests pass across 16suites, 0 failures.
python -m scripts.run_js_tests→ all 3 test pages(phonenumberutil, asyoutypeformatter, shortnumberinfo) green via
Closure jsunit + Playwright.
CONTRIBUTING.md compliance
petroczyp@gmail.com,2026-05-02).
resources/PhoneNumberMetadata.xmland all auto-generated metadata derivatives are unchanged. The only
metadata-XML edit is to
PhoneNumberMetadataForTesting.xml(testfixtures) plus its regenerated derivatives (
test_metadata.cc,PhoneNumberMetadataProtoForTesting_{BR,CO,RU},metadatafortesting.js).cross-language porting expectation. Every change in
AsYouTypeFormatter.javahas a parallel inasyoutypeformatter.ccand
asyoutypeformatter.js.API surface changed;
applyNationalPrefixFormattingRule[_]isprivate in all three.
docstring sweeps.
Files
java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.javajava/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.javadata/PhoneNumberMetadataProtoForTesting_BR,_CO,_RUcpp/src/phonenumbers/asyoutypeformatter.h,.cccpp/test/phonenumbers/asyoutypeformatter_test.cccpp/src/phonenumbers/test_metadata.ccjavascript/i18n/phonenumbers/asyoutypeformatter.jsjavascript/i18n/phonenumbers/asyoutypeformatter_test.jsjavascript/i18n/phonenumbers/metadatafortesting.jsTest fixtures and
test_metadata.ccare regenerated outputs ofBuildMetadataProtoFromXml/BuildMetadataCppFromXml/BuildMetadataJsonFromXmlagainstresources/PhoneNumberMetadataForTesting.xml.