Build a Multilingual IVR With Twilio and PHP

Imagine your company’s sales are growing rapidly and your sole customer support employee can no longer handle the increased call volume. In this instance, the only thing worse than an unsatisfied customer is an unsatisfied customer who finds your customer support number constantly busy.

So, you decide to do something about it and create an IVR (Interactive Voice Response). Nice, but your customers are from all around the world so not all of them can speak your language, and those that can may not, necessarily, be fluent. The solution? Create a multilingual IVR!

Prerequisites

What is an IVR?

An IVR is a technology that allows humans to interact with a computer-operated phone system through the use of voice and DTMF (Dual-tone multi-frequency signaling) tones input via a keypad.

In other words, when a customer calls, a computer system will respond and redirect the customer to the right department — or even record their complaint.

Twilio Programmable Voice

After collecting all the requirements for your new project, you decide to use the Twilio Programmable Voice service, because it’s straightforward to integrate with your current customer support system. What’s more, by using the service, you can also make and receive phone calls, make conference calls, and forward calls to other numbers.

What are we going to build?

You can see an overview of how it will work in the user flow diagram below.

User flow diagram for version 1

When someone calls your Twilio phone number, they will be asked to choose a department. They can press “1” for Sales or “2” for Latest Offers. Based on the choice that they make, they will hear a follow up response applicable to that choice. After that, the call will end.

Before we begin

Check if one of your existing Twilio phone numbers supports voice functionality. If none do, you will need to purchase a number that does. Otherwise, you won’t be able to receive phone calls.

View Twilio Phone Numbers

You can also buy a new phone number if you don’t have one already. To do that, search for one that has Voice capabilities; you can see an example of that in the screenshot below.

Buy Twilio phone number with voice capability

The search results will indicate that a phone number has voice capability by listing a phone icon in the Voice Capabilities column, as you can see in the screenshot below.

Search for a Twilio pone number with voice capability.

Pick a phone number from the search results, then click “Buy” to add it to your Twilio account.

How Twilio Voice works?

At its most basic, there isn’t a lot to Twilio Programmable Voice. Here’s a high-level overview of how it works. When a customer calls your Twilio number, Twilio will send an HTTP request to a webhook within your application. After your server receives the request, the webhook will answer with a TwiML response, instructing Twilio how it should handle the call.

How Twilio Voice works

What is TwiML?

TwiML, or Twilio Markup Language, is an XML formatted instruction that tells Twilio, among other things, what to do when receiving an incoming call. For example, the instructions in the example below tell Twilio to read a message to the caller using Textto-Speech.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say>Thanks for calling our customers support.</Say>
</Response>

TwiML example

There are many TwiML verbs you can use to control the flow of your IVR. They are:

<Dial>

Add another party to the call

<Enqueue>

Add the caller to a queue of callers

<Gather>

Collect digits the caller types on their keypad

<Hangup>

Hang up the call

<Leave>

Remove a caller from a queue of callers

<Pause>

Wait before executing more instructions

<Play>

Play an audio file for the caller

<Say>

Read text to the caller

<Record>

Record the caller’s voice

<Redirect>

Redirect call flow to a different TwiML document

<Refer>

Twilio initiates SIP REFER towards IP communication infrastructure

<Reject>

Decline an incoming call without being billed

Create the project file and directory structure

Now, let’s begin. From the command line, create a new project directory, named multi-language-ivr, and the required subdirectories. This directory structure will store the code for the project. Then, change into the new project directory. You can do both using the commands below.

mkdir -p multi-language-ivr/src/TwiML multi-language-ivr/src/call
cd multi-language-ivr/

Note: if you are using Microsoft Windows, you don’t need to use the -p flag.

Install the required packages

Next, install the required package which we’ll make use of in this article, Twilio’s PHP SDK. To install it, run the command below.

composer require twilio/sdk

Create the TwiML file

Now, create a new TwiML (XML) file in the src/TwiML/ directory named IVR.xml. In it, add the TwiML below. The code in this file will contain the initial webhook endpoint.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say>Thanks for calling.</Say>
    <Say>For support, press 1.</Say>
    <Say>For latest offers, press 2.</Say>
</Response>

Since the IVR system is being developed in a local development environment, you need to use ngrok to make it publicly available, so that Twilio can access it.

To do that, first start PHP’s built-in webserver listening on port 8080, so that ngrok has an application to expose to the wider world, and then start ngrok, by using the two commands below.

php -S 0:8080 -t . &
ngrok http 8080

When successful, you will see output similar to the example below.

Session Status                    online
Session Expires                   1 hour, 59 minutes
Version                           2.3.40
Region                            United States (us)
Web Interface                     http://127.0.0.1:4040
Forwarding                        http://0c6a2de7b72b.ngrok.io -> http://localhost:8080
Forwarding                        https://0c6a2de7b72b.ngrok.io -> http://localhost:8080
                                                                                                                                  
Connections                       ttl         opn         rt1         rt5         p50         p90
                                  0           0           0.00        0.00        0.00        0.00

Next, we need to activate the endpoint. To do that, copy the “Forwarding” URI from the console output. Then, in the Twilio Console, under “Phone Numbers > Active Numbers“, click the phone number that you want to use.

This opens its properties form. Under “Properties > Voice & Fax > A Call Comes In“, add the Forwarding URI that you copied into the text field next to the dropdown, followed by /src/TwiML/IVR.xml. When that’s done, click “Save” at the bottom of the page.

You can see an example in the screenshot below.

Twilio Voice and Fax configuration

Note: You can also choose whether Twilio should make a POST or GET request when accessing the webhook from the drop-down menu on the right.

After updating the phone number’s configuration, if you call your Twilio number you will hear the message asking you to press “1” or “2”. However, after that the call abruptly ends.

To fix this, you need to tell Twilio to first listen to the customer’s input and then tell them what to do next. To do that, update src/TwiML/IVR.xml with the XML below.

Note: Make sure to replace the ngrok URI with the Forwarding URI from your ngrok console output.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
   <Gather input="dtmf" 
        numDigits="1" 
        action="https://6656edd8baa7.ngrok.io/src/call/IvrRouting.php">
       <Say>Thanks for calling, For support, press 1</Say>
       <Say>Thanks for calling, For latest offers, press 2</Say>
   </Gather>
</Response>

Here’s what the new tags do:

  • <Gather> tells Twilio to listen for user input
  • input="dtmf" tells Twilio to listen for keyboard inputs instead of speech
  • action tells Twilio to go to this URL after the user presses a key

With these changes in place, when a customer calls your Twilio number and presses a key, Twilio will send a POST request to a new endpoint in the application, src/call/IvrRouting.php, with the field Digits={key}.

Create a new file named ivrRouting.php in the src/call directory and copy the code below into it.

<?php

declare(strict_types=1);

require_once __DIR__ . '/../../vendor/autoload.php';

use Twilio\TwiML\VoiceResponse;

$response = new VoiceResponse();

if (array_key_exists('Digits', $_POST)) {
   switch ($_POST['Digits']) {
       case 1:
           $response->say('Thanks for calling our customer support department');
           break;
       case 2:
           $response->say('Thanks for listening to our latest offers');
           break;
       default:
           $response->say('Sorry, This choice is not available');
   }
}

header('Content-Type: text/xml');
echo $response;

With the code in place, call your Twilio number again. Your routing should work as expected. If you get any errors, check the Twilio Debugger. Assuming that everything worked, you now have a working IVR.

If you have a look at the ngrok output, you should see two HTTP requests in the output, similar to the example below.

POST /src/call/IvrRouting.php  200 OK[Wed May  5 15:02:08 2021] 127.0.0.1:64067 Closing
POST /src/TwiML/IVR.xml           200 OK[Wed May  5 15:02:08 2021] 127.0.0.1:64067 [200]: POST /src/call/IvrRouting.php

Note: requests are listed from newest at the top to oldest at the bottom.

Using different Voice Engines

Now, let’s make the IVR multilingual by using Twilio’s voice engines. Specifically, let’s refactor the application so that callers can choose to hear options in Arabic as well as the original English. Since only Amazon Polly supports Arabic, we will use the default voice for English and Amazon Polly for Arabic.

You can see a user flow diagram of the new process below.

User flow diagram for version 2

The first thing that we need to do is to let the user choose their preferred language. To do that, replace the code in src/TwiML/IVR.xml with the code below

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Gather input="speech dtmf"
            timeout="3"
            numDigits="1"
            action="https://6656edd8baa7.ngrok.io/src/Call/IvrRouting.php">
            <Say>Thanks for calling, to continue in English press 1</Say>
            <Say voice="Polly.Zeina">شُكْرًا لِإِتْصَالُكَ. لِلْمُتَابَعَةِ بِاللُّغَةِ العَرَبيَّةِ , إِضْغِطُ الرَّقْمِ اثْنانِ.</Say>
    </Gather>
</Response>

Note: Make sure to replace the ngrok URI with the Forwarding URI from your ngrok console output.

Because of this change, when a user calls, they will be asked in English to press 1 if they want to continue in English, and asked in Arabic to press 2 if they want to continue in Arabic.

To provide the ability to have stage two in English and Arabic you need to create two new files: src/TwiML/IVR-English.xml and src/TwiML/IVR-Arabic.xml. After creating them, paste the code below into src/TwiML/IVR-English.xml.

<Response>
    <Gather input="speech dtmf" 
             timeout="3" 
             numDigits="1"
             action="https://6656edd8baa7.ngrok.io/src/Call/IvrRouting.php?lang=en">
        <Say>For sales, press one</Say>
        <Say>For latest offers, press two</Say>
    </Gather>
    <Say>We didn't receive any input. Goodbye!</Say>
</Response>

Then, paste the code below into src/TwiML/IVR-Arabic.xml.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
        <Gather input="speech dtmf" timeout="3" numDigits="1"
                action="https://6656edd8baa7.ngrok.io/src/Call/IvrRouting.php?lang=ar">
            <Say voice="Polly.Zeina">لِلْمَبِيعَاتِ اضْغَطْ الرَّقْمَ واحِد.
                <break strength="x-weak" time="1000ms"/>
            </Say>
            <Say voice="Polly.Zeina">لِلْعُرُوضِ اضْغَطْ الرَّقْمَ اثْنانِ.
                <break strength="x-weak" time="1000ms"/>
            </Say>
        </Gather>
</Response>

Note: Make sure to replace the ngrok URI in the two XML files above with the Forwarding URI from your ngrok console output.

With the code in place, regardless of the language that the user has chosen, in the second stage, they’ll be given two choices: choose “1” for the sales department, or choose “2” for latest offers.

A few things are worth mentioning. Firstly, the lang query parameter in Gather‘s action attribute. This lets the code know which language was in effect. en indicates English and ar represents Arabic. Next is the Say element’s voice attribute, in src/TwiML/IVR-Arabic.xml. This determines the voice engine to use.

With those files in place, we have to update src/call/IvrRouting.php to accommodate the language choices. To do that, replace the code in src/call/IvrRouting.php with the code below.

<?php

declare(strict_types=1);

require_once __DIR__ . '/../../vendor/autoload.php';

use Twilio\TwiML\VoiceResponse;

$response = new VoiceResponse();

if (array_key_exists('Digits', $_POST)) {
   if (empty($_GET['lang'])) {
       switch ($_POST['Digits']) {
           case 1: 
               $response->redirect(
                   'https://6656edd8baa7.ngrok.io/src/TwiML/IVR-english.xml'
               );
               break;
           case 2: 
               $response->redirect(
                   'https://6656edd8baa7.ngrok.io/src/TwiML/IVR-arabic.xml'
               );
               break;
           default:
               $response->say('Sorry, this choice is not available.');
       }
   } elseif ($_GET['lang'] === 'en') {
       switch ($_POST['Digits']) {
           case 1:
               $response->say('Thanks. One of our agents will contact you very soon.');
               break;
           case 2:
               $response->say('Thanks for listening to our latest offers.');
               break;
       }
   } elseif ($_GET['lang'] === 'ar') {
       switch ($_POST['Digits']) {
           case 1:
               $response->say('أَحَدُ مَنْدوبينا سَيَتَوَاصَلُ مَعَكَ حَالًا.', ['voice' => 'Polly.Zeina']);
               break;
           case 2:
               $response->say('شُكْرًا لِإِسْتِمَاعِكْ لاحَّدِثِ عُروضِنا', ['voice' => 'Polly.Zeina']);
               break;
       }
   }
}

// Render the response as XML in reply to the webhook request
header('Content-Type: text/xml');
echo $response;

Note: Make sure to replace the ngrok URI with the Forwarding URI from your ngrok console output.

src/call/IvrRouting.php first checks if the user has pressed a number on their keypad by checking if PHP’s $_POST superglobal contains a Digits element. If so, it then checks if the lang query parameter has been supplied.

If the lang query parameter has not been supplied, it:

  • Plays the responses in src/TwiML/IVR-english.xml if the value of $_POST['Digits'] is equal to 1
  • Plays the responses in src/TwiML/IVR-english.xml if the value of $_POST['Digits'] is equal to 2
  • Gives a default message if $_POST['Digits'] is equal to anything else.

If the lang query parameter has been supplied it plays a final response in English if the value of $_GET['lang'] is equal to en, otherwise it plays a final response in Arabic. The message that is played is determined by $_POST['Digits']‘s value.

With all the changes made, call your Twilio number one final time to make sure everything works as intended.

Note: After you’ve stepped through the process, make sure that you quit ngrok.

That’s how to build a multilingual IVR with PHP and Twilio Programmable Voice

Congratulations, your IVR is working and ready for further customizations. For example, you can create a ticket in your ticketing system, or record the customer’s complaint and save it in your cloud storage for later processing.

Do you have further questions? Leave a comment and let’s work through them together. You can find the source code on GitHub

Mohamad is a software engineer who started his technical writing journey on his former employer’s blog. Since then, he has written on his personal blog as a way of sharing his thoughts and learnings about software architecture, clean code, and best practices. In his spare time, he listens to audiobooks and spends time with his family. 

Imagine your company's sales are growing rapidly and your sole customer support employee can no longer handle the increased call volume. In this instance, the only thing worse than an unsatisfied customer is an unsatisfied customer who finds your customer support number constantly busy.

So, you decide to do something about it and create an IVR (Interactive Voice Response). Nice, but your customers are from all around the world so not all of them can speak your language, and those that can may not, necessarily, be fluent. The solution? Create a multilingual IVR!

Prerequisites

What is an IVR?

An IVR is a technology that allows humans to interact with a computer-operated phone system through the use of voice and DTMF (Dual-tone multi-frequency signaling) tones input via a keypad.

In other words, when a customer calls, a computer system will respond and redirect the customer to the right department — or even record their complaint.

Twilio Programmable Voice

After collecting all the requirements for your new project, you decide to use the Twilio Programmable Voice service, because it’s straightforward to integrate with your current customer support system. What's more, by using the service, you can also make and receive phone calls, make conference calls, and forward calls to other numbers.

What are we going to build?

You can see an overview of how it will work in the user flow diagram below.

User flow diagram for version 1

When someone calls your Twilio phone number, they will be asked to choose a department. They can press "1" for Sales or "2" for Latest Offers. Based on the choice that they make, they will hear a follow up response applicable to that choice. After that, the call will end.

Before we begin

Check if one of your existing Twilio phone numbers supports voice functionality. If none do, you will need to purchase a number that does. Otherwise, you won't be able to receive phone calls.

View Twilio Phone Numbers

You can also buy a new phone number if you don’t have one already. To do that, search for one that has Voice capabilities; you can see an example of that in the screenshot below.

Buy Twilio phone number with voice capability

The search results will indicate that a phone number has voice capability by listing a phone icon in the Voice Capabilities column, as you can see in the screenshot below.

Search for a Twilio pone number with voice capability.

Pick a phone number from the search results, then click "Buy" to add it to your Twilio account.

How Twilio Voice works?

At its most basic, there isn't a lot to Twilio Programmable Voice. Here's a high-level overview of how it works. When a customer calls your Twilio number, Twilio will send an HTTP request to a webhook within your application. After your server receives the request, the webhook will answer with a TwiML response, instructing Twilio how it should handle the call.

How Twilio Voice works

What is TwiML?

TwiML, or Twilio Markup Language, is an XML formatted instruction that tells Twilio, among other things, what to do when receiving an incoming call. For example, the instructions in the example below tell Twilio to read a message to the caller using Textto-Speech.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say>Thanks for calling our customers support.</Say>
</Response>

TwiML example

There are many TwiML verbs you can use to control the flow of your IVR. They are:

<Dial>

Add another party to the call

<Enqueue>

Add the caller to a queue of callers

<Gather>

Collect digits the caller types on their keypad

<Hangup>

Hang up the call

<Leave>

Remove a caller from a queue of callers

<Pause>

Wait before executing more instructions

<Play>

Play an audio file for the caller

<Say>

Read text to the caller

<Record>

Record the caller's voice

<Redirect>

Redirect call flow to a different TwiML document

<Refer>

Twilio initiates SIP REFER towards IP communication infrastructure

<Reject>

Decline an incoming call without being billed

Create the project file and directory structure

Now, let's begin. From the command line, create a new project directory, named multi-language-ivr, and the required subdirectories. This directory structure will store the code for the project. Then, change into the new project directory. You can do both using the commands below.

mkdir -p multi-language-ivr/src/TwiML multi-language-ivr/src/call
cd multi-language-ivr/

Note: if you are using Microsoft Windows, you don't need to use the -p flag.

Install the required packages

Next, install the required package which we'll make use of in this article, Twilio's PHP SDK. To install it, run the command below.

composer require twilio/sdk

Create the TwiML file

Now, create a new TwiML (XML) file in the src/TwiML/ directory named IVR.xml. In it, add the TwiML below. The code in this file will contain the initial webhook endpoint.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say>Thanks for calling.</Say>
    <Say>For support, press 1.</Say>
    <Say>For latest offers, press 2.</Say>
</Response>

Since the IVR system is being developed in a local development environment, you need to use ngrok to make it publicly available, so that Twilio can access it.

To do that, first start PHP's built-in webserver listening on port 8080, so that ngrok has an application to expose to the wider world, and then start ngrok, by using the two commands below.

php -S 0:8080 -t . &
ngrok http 8080

When successful, you will see output similar to the example below.

Session Status                    online
Session Expires                   1 hour, 59 minutes
Version                           2.3.40
Region                            United States (us)
Web Interface                     http://127.0.0.1:4040
Forwarding                        http://0c6a2de7b72b.ngrok.io -> http://localhost:8080
Forwarding                        https://0c6a2de7b72b.ngrok.io -> http://localhost:8080
                                                                                                                                  
Connections                       ttl         opn         rt1         rt5         p50         p90
                                  0           0           0.00        0.00        0.00        0.00

Next, we need to activate the endpoint. To do that, copy the "Forwarding" URI from the console output. Then, in the Twilio Console, under "Phone Numbers > Active Numbers", click the phone number that you want to use.

This opens its properties form. Under "Properties > Voice & Fax > A Call Comes In", add the Forwarding URI that you copied into the text field next to the dropdown, followed by /src/TwiML/IVR.xml. When that's done, click "Save" at the bottom of the page.

You can see an example in the screenshot below.

Twilio Voice and Fax configuration

Note: You can also choose whether Twilio should make a POST or GET request when accessing the webhook from the drop-down menu on the right.

After updating the phone number's configuration, if you call your Twilio number you will hear the message asking you to press "1" or "2". However, after that the call abruptly ends.

To fix this, you need to tell Twilio to first listen to the customer’s input and then tell them what to do next. To do that, update src/TwiML/IVR.xml with the XML below.

Note: Make sure to replace the ngrok URI with the Forwarding URI from your ngrok console output.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
   <Gather input="dtmf" 
        numDigits="1" 
        action="https://6656edd8baa7.ngrok.io/src/call/IvrRouting.php">
       <Say>Thanks for calling, For support, press 1</Say>
       <Say>Thanks for calling, For latest offers, press 2</Say>
   </Gather>
</Response>

Here's what the new tags do:

  • <Gather> tells Twilio to listen for user input
  • input="dtmf" tells Twilio to listen for keyboard inputs instead of speech
  • action tells Twilio to go to this URL after the user presses a key

With these changes in place, when a customer calls your Twilio number and presses a key, Twilio will send a POST request to a new endpoint in the application, src/call/IvrRouting.php, with the field Digits={key}.

Create a new file named ivrRouting.php in the src/call directory and copy the code below into it.

<?php

declare(strict_types=1);

require_once __DIR__ . '/../../vendor/autoload.php';

use Twilio\TwiML\VoiceResponse;

$response = new VoiceResponse();

if (array_key_exists('Digits', $_POST)) {
   switch ($_POST['Digits']) {
       case 1:
           $response->say('Thanks for calling our customer support department');
           break;
       case 2:
           $response->say('Thanks for listening to our latest offers');
           break;
       default:
           $response->say('Sorry, This choice is not available');
   }
}

header('Content-Type: text/xml');
echo $response;

With the code in place, call your Twilio number again. Your routing should work as expected. If you get any errors, check the Twilio Debugger. Assuming that everything worked, you now have a working IVR.

If you have a look at the ngrok output, you should see two HTTP requests in the output, similar to the example below.

POST /src/call/IvrRouting.php  200 OK[Wed May  5 15:02:08 2021] 127.0.0.1:64067 Closing
POST /src/TwiML/IVR.xml           200 OK[Wed May  5 15:02:08 2021] 127.0.0.1:64067 [200]: POST /src/call/IvrRouting.php

Note: requests are listed from newest at the top to oldest at the bottom.

Using different Voice Engines

Now, let’s make the IVR multilingual by using Twilio's voice engines. Specifically, let’s refactor the application so that callers can choose to hear options in Arabic as well as the original English. Since only Amazon Polly supports Arabic, we will use the default voice for English and Amazon Polly for Arabic.

You can see a user flow diagram of the new process below.

User flow diagram for version 2

The first thing that we need to do is to let the user choose their preferred language. To do that, replace the code in src/TwiML/IVR.xml with the code below

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Gather input="speech dtmf"
            timeout="3"
            numDigits="1"
            action="https://6656edd8baa7.ngrok.io/src/Call/IvrRouting.php">
            <Say>Thanks for calling, to continue in English press 1</Say>
            <Say voice="Polly.Zeina">شُكْرًا لِإِتْصَالُكَ. لِلْمُتَابَعَةِ بِاللُّغَةِ العَرَبيَّةِ , إِضْغِطُ الرَّقْمِ اثْنانِ.</Say>
    </Gather>
</Response>

Note: Make sure to replace the ngrok URI with the Forwarding URI from your ngrok console output.

Because of this change, when a user calls, they will be asked in English to press 1 if they want to continue in English, and asked in Arabic to press 2 if they want to continue in Arabic.

To provide the ability to have stage two in English and Arabic you need to create two new files: src/TwiML/IVR-English.xml and src/TwiML/IVR-Arabic.xml. After creating them, paste the code below into src/TwiML/IVR-English.xml.

<Response>
    <Gather input="speech dtmf" 
             timeout="3" 
             numDigits="1"
             action="https://6656edd8baa7.ngrok.io/src/Call/IvrRouting.php?lang=en">
        <Say>For sales, press one</Say>
        <Say>For latest offers, press two</Say>
    </Gather>
    <Say>We didn't receive any input. Goodbye!</Say>
</Response>

Then, paste the code below into src/TwiML/IVR-Arabic.xml.

<?xml version="1.0" encoding="UTF-8"?>
<Response>
        <Gather input="speech dtmf" timeout="3" numDigits="1"
                action="https://6656edd8baa7.ngrok.io/src/Call/IvrRouting.php?lang=ar">
            <Say voice="Polly.Zeina">لِلْمَبِيعَاتِ اضْغَطْ الرَّقْمَ واحِد.
                <break strength="x-weak" time="1000ms"/>
            </Say>
            <Say voice="Polly.Zeina">لِلْعُرُوضِ اضْغَطْ الرَّقْمَ اثْنانِ.
                <break strength="x-weak" time="1000ms"/>
            </Say>
        </Gather>
</Response>

Note: Make sure to replace the ngrok URI in the two XML files above with the Forwarding URI from your ngrok console output.

With the code in place, regardless of the language that the user has chosen, in the second stage, they'll be given two choices: choose "1" for the sales department, or choose "2" for latest offers.

A few things are worth mentioning. Firstly, the lang query parameter in Gather's action attribute. This lets the code know which language was in effect. en indicates English and ar represents Arabic. Next is the Say element's voice attribute, in src/TwiML/IVR-Arabic.xml. This determines the voice engine to use.

With those files in place, we have to update src/call/IvrRouting.php to accommodate the language choices. To do that, replace the code in src/call/IvrRouting.php with the code below.

<?php

declare(strict_types=1);

require_once __DIR__ . '/../../vendor/autoload.php';

use Twilio\TwiML\VoiceResponse;

$response = new VoiceResponse();

if (array_key_exists('Digits', $_POST)) {
   if (empty($_GET['lang'])) {
       switch ($_POST['Digits']) {
           case 1: 
               $response->redirect(
                   'https://6656edd8baa7.ngrok.io/src/TwiML/IVR-english.xml'
               );
               break;
           case 2: 
               $response->redirect(
                   'https://6656edd8baa7.ngrok.io/src/TwiML/IVR-arabic.xml'
               );
               break;
           default:
               $response->say('Sorry, this choice is not available.');
       }
   } elseif ($_GET['lang'] === 'en') {
       switch ($_POST['Digits']) {
           case 1:
               $response->say('Thanks. One of our agents will contact you very soon.');
               break;
           case 2:
               $response->say('Thanks for listening to our latest offers.');
               break;
       }
   } elseif ($_GET['lang'] === 'ar') {
       switch ($_POST['Digits']) {
           case 1:
               $response->say('أَحَدُ مَنْدوبينا سَيَتَوَاصَلُ مَعَكَ حَالًا.', ['voice' => 'Polly.Zeina']);
               break;
           case 2:
               $response->say('شُكْرًا لِإِسْتِمَاعِكْ لاحَّدِثِ عُروضِنا', ['voice' => 'Polly.Zeina']);
               break;
       }
   }
}

// Render the response as XML in reply to the webhook request
header('Content-Type: text/xml');
echo $response;

Note: Make sure to replace the ngrok URI with the Forwarding URI from your ngrok console output.

src/call/IvrRouting.php first checks if the user has pressed a number on their keypad by checking if PHP's $_POST superglobal contains a Digits element. If so, it then checks if the lang query parameter has been supplied.

If the lang query parameter has not been supplied, it:

  • Plays the responses in src/TwiML/IVR-english.xml if the value of $_POST['Digits'] is equal to 1
  • Plays the responses in src/TwiML/IVR-english.xml if the value of $_POST['Digits'] is equal to 2
  • Gives a default message if $_POST['Digits'] is equal to anything else.

If the lang query parameter has been supplied it plays a final response in English if the value of $_GET['lang'] is equal to en, otherwise it plays a final response in Arabic. The message that is played is determined by $_POST['Digits']'s value.

With all the changes made, call your Twilio number one final time to make sure everything works as intended.

Note: After you've stepped through the process, make sure that you quit ngrok.

That's how to build a multilingual IVR with PHP and Twilio Programmable Voice

Congratulations, your IVR is working and ready for further customizations. For example, you can create a ticket in your ticketing system, or record the customer’s complaint and save it in your cloud storage for later processing.

Do you have further questions? Leave a comment and let’s work through them together. You can find the source code on GitHub

Mohamad is a software engineer who started his technical writing journey on his former employer's blog. Since then, he has written on his personal blog as a way of sharing his thoughts and learnings about software architecture, clean code, and best practices. In his spare time, he listens to audiobooks and spends time with his family. 


Print Share Comment Cite Upload Translate
APA
Mohamed Aladdin | Sciencx (2024-03-29T04:47:12+00:00) » Build a Multilingual IVR With Twilio and PHP. Retrieved from https://www.scien.cx/2021/06/15/build-a-multilingual-ivr-with-twilio-and-php/.
MLA
" » Build a Multilingual IVR With Twilio and PHP." Mohamed Aladdin | Sciencx - Tuesday June 15, 2021, https://www.scien.cx/2021/06/15/build-a-multilingual-ivr-with-twilio-and-php/
HARVARD
Mohamed Aladdin | Sciencx Tuesday June 15, 2021 » Build a Multilingual IVR With Twilio and PHP., viewed 2024-03-29T04:47:12+00:00,<https://www.scien.cx/2021/06/15/build-a-multilingual-ivr-with-twilio-and-php/>
VANCOUVER
Mohamed Aladdin | Sciencx - » Build a Multilingual IVR With Twilio and PHP. [Internet]. [Accessed 2024-03-29T04:47:12+00:00]. Available from: https://www.scien.cx/2021/06/15/build-a-multilingual-ivr-with-twilio-and-php/
CHICAGO
" » Build a Multilingual IVR With Twilio and PHP." Mohamed Aladdin | Sciencx - Accessed 2024-03-29T04:47:12+00:00. https://www.scien.cx/2021/06/15/build-a-multilingual-ivr-with-twilio-and-php/
IEEE
" » Build a Multilingual IVR With Twilio and PHP." Mohamed Aladdin | Sciencx [Online]. Available: https://www.scien.cx/2021/06/15/build-a-multilingual-ivr-with-twilio-and-php/. [Accessed: 2024-03-29T04:47:12+00:00]
rf:citation
» Build a Multilingual IVR With Twilio and PHP | Mohamed Aladdin | Sciencx | https://www.scien.cx/2021/06/15/build-a-multilingual-ivr-with-twilio-and-php/ | 2024-03-29T04:47:12+00:00
https://github.com/addpipe/simple-recorderjs-demo