Parse the phone number withsscanf() or preg_match(), then translate with PHP's native numeric text formatter, and conditionally handle leading zeros. Demo
$usPhone = '123-456-7809';
$digits = sscanf($usPhone, '%1s%1s%1s-%1s%1s%1s-%2s%2s');
$f = new NumberFormatter('en', NumberFormatter::SPELLOUT);
echo implode(
' ',
array_map(
fn($d) => ($d !== (string)(int)$d ? 'oh ' : '')
. (!(int)$d ? 'oh' : $f->format((int)$d)),
$digits
)
);
Output
one two three four five six seventy-eight oh nine
103-050-0000 becomes:
one oh three oh five oh oh oh oh oh
103-050-4050 becomes:
one oh three oh five oh forty fifty
Here is another approach using preg_replace_callback() to which substrings get translated and how. Demo
$regex = <<<'REGEX'
~
(?:
([1-9]\d)(?=(?:\d{2})?$) # 1: double-digit in last segment
|(0) # 2: zero
|([1-9]) # 3: single digit
)
-? # consume optional delimiter
~x
REGEX;
$f = new NumberFormatter('en', NumberFormatter::SPELLOUT);
echo ltrim(
preg_replace_callback(
$regex,
fn($m) => sprintf(
' %s',
array_key_last($m) === 2
? 'oh'
: $f->format(intval($m[0]))
),
$usPhone
)
);
As a deviation of the original requirements to help developers with phone numbers to Australian speech, here is a version which does not respect two-digit values in the last segment, but respects, hundreds, thousands, etc. as well as multiple consecutive numbers. Demo
$regex = <<<'REGEX'
~
(?:
\b([1-9]0{2,})\b # 1: hundreds, thousands, etc
|(\d)\2+ # 2: multiples
|(0) # 3: zero
|([1-9]) # 4: single digit
)
-? # consume optional delimiter
~x
REGEX;
$f = new NumberFormatter('en', NumberFormatter::SPELLOUT);
$mapping = [
2 => 'double',
3 => 'triple',
4 => 'quadruple',
5 => 'quintuple',
6 => 'sextuple',
7 => 'septuple',
8 => 'octuple',
9 => 'nonuple',
10 => 'decuple',
];
echo ltrim(
preg_replace_callback(
$regex,
fn($m) => ' ' . match (array_key_last($m)) {
1, 4 => $f->format((int)
mapping[strlen(rtrim($m[0], '-'))] . " " . (
f->format((int)$m[2]) : 'oh'),
default => 'oh',
},
$usPhone
)
);
$usPhone = '800-000-7755' becomes eight hundred triple oh double seven double five
php - How do I convert a hyphenated phone number to words (with 0 as "oh")? - Stack Overflow
Phone numbers as words master list
How do I convert phone number to words in Google Sheets?
Just made a simple web app that converts phone numbers into unique phrases - Phonology.io - Thoughts?
Parse the phone number withsscanf() or preg_match(), then translate with PHP's native numeric text formatter, and conditionally handle leading zeros. Demo
$usPhone = '123-456-7809';
$digits = sscanf($usPhone, '%1s%1s%1s-%1s%1s%1s-%2s%2s');
$f = new NumberFormatter('en', NumberFormatter::SPELLOUT);
echo implode(
' ',
array_map(
fn($d) => ($d !== (string)(int)$d ? 'oh ' : '')
. (!(int)$d ? 'oh' : $f->format((int)$d)),
$digits
)
);
Output
one two three four five six seventy-eight oh nine
103-050-0000 becomes:
one oh three oh five oh oh oh oh oh
103-050-4050 becomes:
one oh three oh five oh forty fifty
Here is another approach using preg_replace_callback() to which substrings get translated and how. Demo
$regex = <<<'REGEX'
~
(?:
([1-9]\d)(?=(?:\d{2})?$) # 1: double-digit in last segment
|(0) # 2: zero
|([1-9]) # 3: single digit
)
-? # consume optional delimiter
~x
REGEX;
$f = new NumberFormatter('en', NumberFormatter::SPELLOUT);
echo ltrim(
preg_replace_callback(
$regex,
fn($m) => sprintf(
' %s',
array_key_last($m) === 2
? 'oh'
: $f->format(intval($m[0]))
),
$usPhone
)
);
As a deviation of the original requirements to help developers with phone numbers to Australian speech, here is a version which does not respect two-digit values in the last segment, but respects, hundreds, thousands, etc. as well as multiple consecutive numbers. Demo
$regex = <<<'REGEX'
~
(?:
\b([1-9]0{2,})\b # 1: hundreds, thousands, etc
|(\d)\2+ # 2: multiples
|(0) # 3: zero
|([1-9]) # 4: single digit
)
-? # consume optional delimiter
~x
REGEX;
$f = new NumberFormatter('en', NumberFormatter::SPELLOUT);
$mapping = [
2 => 'double',
3 => 'triple',
4 => 'quadruple',
5 => 'quintuple',
6 => 'sextuple',
7 => 'septuple',
8 => 'octuple',
9 => 'nonuple',
10 => 'decuple',
];
echo ltrim(
preg_replace_callback(
$regex,
fn($m) => ' ' . match (array_key_last($m)) {
1, 4 => $f->format((int)
mapping[strlen(rtrim($m[0], '-'))] . " " . (
f->format((int)$m[2]) : 'oh'),
default => 'oh',
},
$usPhone
)
);
$usPhone = '800-000-7755' becomes eight hundred triple oh double seven double five
After the question requirements were edits, I recommend isolating the strictly-formatted phone number and replacing each digit with its equivalent word. Demo
$text = 'Call 123-456-7800 between 16:00 and 4:00 for confidential support';
$f = new NumberFormatter('en', NumberFormatter::SPELLOUT);
echo preg_replace_callback(
'/\b(\d)(\d)(\d)-(\d)(\d)(\d)-(\d)(\d)(\d)(\d)\b/',
fn($m) => implode(' ', array_map([$f, 'format'], array_slice($m, 1))),
$text
);
// Call one two three four five six seven eight zero zero between 16:00 and 4:00 for confidential support
Can we assemble a master list of ND phone numbers and what they spell out?
For example:
Bess: -4468 = hint
Ned: -4357 = help
George: -2583 = clue
But what about others?
I’m currently playing White Wolf, so here are my contributions:
Tino Balducci: -5375 = jerk
Chantal (ICE): -2274 = cash