formatOutOfCountryKeepingAlphaChars method
Formats a phone number for out-of-country dialing purposes.
Note that in this version, if the number was entered originally using alpha
characters and this version of the number is stored in rawInput
, this
representation of the number will be used rather than the digit
representation. Grouping information, as specified by characters such as '-'
and ' ', will be retained.
Caveats:
- This will not produce good results if the country calling code is both present in the raw input _and_ is the start of the national number. This is not a problem in the regions which typically use alpha numbers.
- This will also not produce good results if the raw input has any grouping information within the first three digits of the national number, and if the function needs to strip preceding digits/words in the raw input before these digits. Normally people group the first three digits together so this is not a huge problem - and will be fixed if it proves to be so.
number
the phone number that needs to be formatted.
regionCallingFrom
the region where the call is being placed.
Implementation
String formatOutOfCountryKeepingAlphaChars(
PhoneNumber number, String regionCallingFrom) {
String rawInput = number.rawInput;
// If there is no raw input, then we can't keep alpha characters because there
// aren't any. In this case, we return formatOutOfCountryCallingNumber.
if (rawInput.isEmpty) {
return formatOutOfCountryCallingNumber(number, regionCallingFrom);
}
int countryCode = number.countryCode;
if (!_hasValidCountryCallingCode(countryCode)) {
return rawInput;
}
// Strip any prefix such as country calling code, IDD, that was present. We do
// this by comparing the number in raw_input with the parsed number. To do
// this, first we normalize punctuation. We retain number grouping symbols
// such as ' ' only.
rawInput = _normalizeHelper(rawInput, _allPlusNumberGroupingSymbols, true);
// Now we trim everything before the first three digits in the parsed number.
// We choose three because all valid alpha numbers have 3 digits at the start
// - if it does not, then we don't trim anything at all. Similarly, if the
// national number was less than three digits, we don't trim anything at all.
String nationalNumber = getNationalSignificantNumber(number);
if (nationalNumber.length > 3) {
int firstNationalNumberDigit =
rawInput.indexOf(nationalNumber.substring(0, 3));
if (firstNationalNumberDigit != -1) {
rawInput = rawInput.substring(firstNationalNumberDigit);
}
}
PhoneMetadata? metadataForRegionCallingFrom =
getMetadataForRegion(regionCode: regionCallingFrom);
if (countryCode == _nanpaCountryCode) {
if (isNANPACountry(regionCallingFrom)) {
return '$countryCode $rawInput';
}
} else if (metadataForRegionCallingFrom != null &&
countryCode == _getCountryCodeForValidRegion(regionCallingFrom)) {
NumberFormat? formattingPattern = chooseFormattingPatternForNumber(
metadataForRegionCallingFrom.numberFormat,
nationalNumber,
);
if (formattingPattern == null) {
// If no pattern above is matched, we format the original input.
return rawInput;
}
NumberFormat newFormat = formattingPattern.deepCopy();
// The first group is the first group of digits that the user wrote
// together.
newFormat.pattern = '(\\d+)(.*)';
// Here we just concatenate them back together after the national prefix
// has been fixed.
newFormat.format = '\$1\$2';
// Now we format using this pattern instead of the default pattern, but
// with the national prefix prefixed if necessary.
// This will not work in the cases where the pattern (and not the leading
// digits) decide whether a national prefix needs to be used, since we have
// overridden the pattern to match anything, but that is not the case in the
// metadata to date.
return formatNsnUsingPattern(
rawInput, newFormat, PhoneNumberFormat.national);
}
String internationalPrefixForFormatting = '';
// If an unsupported region-calling-from is entered, or a country with
// multiple international prefixes, the international format of the number is
// returned, unless there is a preferred international prefix.
if (metadataForRegionCallingFrom != null) {
String internationalPrefix =
metadataForRegionCallingFrom.internationalPrefix;
internationalPrefixForFormatting =
matchesEntirely(_singleInternationalPrefix, internationalPrefix)
? internationalPrefix
: metadataForRegionCallingFrom.preferredInternationalPrefix;
}
String regionCode = getRegionCodeForCountryCode(countryCode);
// Metadata cannot be null because the country calling code is valid.
PhoneMetadata metadataForRegion =
_getMetadataForRegionOrCallingCode(countryCode, regionCode)!;
String formattedExtension = _maybeGetFormattedExtension(
number,
metadataForRegion,
PhoneNumberFormat.international,
);
if (internationalPrefixForFormatting.isNotEmpty) {
return '$internationalPrefixForFormatting $countryCode $rawInput$formattedExtension';
} else {
// Invalid region entered as country-calling-from (so no metadata was found
// for it) or the region chosen has multiple international dialling
// prefixes.
return _prefixNumberWithCountryCallingCode(
countryCode,
PhoneNumberFormat.international,
rawInput,
formattedExtension,
);
}
}