Learn how to switch the language of the current instance of artyom on the fly using a voice command.

Artyom.js makes everything easy when we talk about implementing a simple voice assistant in Google Chrome with JavaScript. It will automatically expose an API that is very easy to work with and wraps very well the Speech Recognition and Speech Synthesis APIs. Although the library is well documented, you may sometimes don't figure out by yourself easy things that maybe the developer didn't think about like switching the language on the fly with a voice command.

If you are thinking in do this, you will have to think logically about what should I do with the library to start with other language. As first, the original Speech Recognition API doesn't allow to switch the recognized language on the fly, which means you have to restart the instance. The same goes for Artyom.js, to switch from language, you will need to restart it. If you work with the plain API of Speech Recognition, this would be a headache if you want to do it from scratch, but thanks to Artyom, this is very easy to achieve.

According to the way you want to work, you may want to use a single or multiple instances of Artyom (1 for every language), feel free to work as you want.

A. Working with a single instance of Artyom

If you want to switch the language on the fly with a single instance of Artyom, you would need to follow these steps:

1. Create instance and configuration

In this case our instance will be available as Jarvis, then we'll store our configuration in a plain JS object with 2 different keys for every language, namely spanish and english:

// Initialize an instance of artyom
var Jarvis = new Artyom();

// Create an object to store the configuration for every language
var JarvisConfigurations = {
    spanish: {
        lang: "es-ES",
        continuous: true,
        listen: true,
        debug: true
    },
    english: {
        lang: "en-GB",
        continuous: true,
        listen: true,
        debug: true
    }
};

2. Add the command to switch language

As we have only 2 languages within a single instance, the commands will be stored as well in the same instance and they should react to "Switch to Spanish" and "Cambiar a inglés (Switch to English in Spanish)".  We will add 2 commands that follow the next logic:

  1. When the command is triggered, stop artyom using fatality()
  2. When the promise of fatality is fulfilled, initialize again with the initial configuration stored in the JarvisConfigurations variable according to the language.
  3. When the promise of initialize is fulfilled, say hello on the respective language.
Jarvis.addCommands([
    // English Command
    {
        indexes: ["Switch to Spanish"],
        action: function(){
            // Stop Jarvis
            Jarvis.fatality().then(function(){

                // When it stops, initialize with Spanish configuration :)
                Jarvis.initialize(JarvisConfigurations.spanish).then(function(){
                    Jarvis.say("Hola");
                });
            });
        }
    },
    // Spanish Command
    {
        indexes: ["Cambiar a inglés"],
        action: function(){
            // Stop Jarvis
            Jarvis.fatality().then(function(){

                // When it stops, initialize with english configuration :)
                Jarvis.initialize(JarvisConfigurations.english).then(function(){
                    Jarvis.say("Hello");
                });
            }); 
        }
    }
]);

3. Initialize for first time with a default language

As we are using commands to switch the language dinamically, there need to be an already running instance of Artyom or nobody will recognize anything. In this case we'll start it with the english configuration:

// Initialize for first time !
Jarvis.initialize(JarvisConfigurations.english).then(function(){
    console.log("Ready to work, try changing the language!");
});

Once Artyom starts, as we are in the english mode, you can change to spanish saying "Switch to Spanish" and Artyom will say "Hola" and viceversa.

B. Working with multiple instances of Artyom

When working with different languages, many developers like to abstract and separate the logic for every language creating multiple instances of Artyom. In this way, you won't have for example Spanish Commands inside the English instance (as they would never be triggered because the recognition service is in other language) of Artyom and viceversa.

Note

If you are planning to support more than 2 languages, this approach ain't useful anymore so skip to option C. This option is only for understanding purposes.

1. Create instances and configuration

If you want to use multiple instances of Artyom to be organized, they would need to be obviously named differently. In this case for our English instance the name in the code will be Jarvis and for the Spanish instance its name will be Maria:

// Initialize English Instance of Artyom
var Jarvis = new Artyom();

// Initialize Spanish Instance of Artyom
var Maria = new Artyom();

// Create an object to store the configuration for every instance
var ArtyomConfiguration = {
    spanish: {
        lang: "es-ES",
        continuous: true,
        listen: true,
        debug: true
    },
    english: {
        lang: "en-GB",
        continuous: true,
        listen: true,
        debug: true
    }
};

2. Add the commands to switch the language respectively

Now you would need to add the 2 commands that triggers the logic of restarting with a different configuration:

// Add Switch language command for Maria (Spanish Mode)
Maria.addCommands([
    {
        indexes: ["Cambiar a inglés"],
        action: function(){
            // Stop the Spanish (Maria) Instance
            Maria.fatality().then(function(){

                // Initialize Jarvis
                Jarvis.initialize(ArtyomConfiguration.Jarvis).then(function(){
                    Jarvis.say("Hello");
                });
            }); 
        }
    }
]);

// Add Switch language command for Jarvis (English Mode)
Jarvis.addCommands([
    {
        indexes: ["Switch to Spanish"],
        action: function(){

            // Stop the English (Jarvis) Instance
            Jarvis.fatality().then(function(){

                // Initialize Maria
                Maria.initialize(ArtyomConfiguration.Maria).then(function(){
                    Maria.say("Hola");
                });
            }); 
        }
    }
]);

3. Initialize for first time with a default language.

As expected, the commands are only triggered when the user talks, so artyom needs to be running. In this case, we'll start with the default English mode.

// Initialize for first time !
Jarvis.initialize(ArtyomConfiguration.Jarvis).then(function(){
    console.log("Ready to work, try changing the language!");
});

C. Working with 3 or more instances of Artyom

If you work with 3 or more languages with Artyom, you would need now to think an easy way to store all the instances and work peacefully with all of them to prevent the crashing from the API, besides it needs to work as a clock ! As author of the Artyom Library, the following way is the easiest, however it may change according to what you need.

1. Create instances and configuration

As first, we need to store as well the configuration and instances inside a JS object and we'll use 3 instances in our example (for more, you can follow the same logic):

var InstancesCollector = {
    Jarvis: new Artyom(),
    Maria: new Artyom(),
    Christine: new Artyom()
    // Add more if you need to
};

var InstancesConfiguration = {
    Jarvis: {
        lang: "en-GB",
        continuous: true,
        listen: true,
        debug: true
    },
    Maria: {
        lang: "es-ES",
        continuous: true,
        listen: true,
        debug: true
    },
    Christine: {
        lang: "de-DE",
        continuous: true,
        listen: true,
        debug: true
    }
    // Add more if you need to
};

2. Create reusable initializers

As you are working with multiple instances and you may not want to type a different initialization function for every language as your code may end up with a lot of the same, you can create another variable that stores the initialization model with simple functions:

/**
 * The initializers will be stored in this variable as normally you would want to execute this
 * more than once, however writing just once.
 */
var AutoInitializers = {
    Jarvis: function(){
        // Start English
        InstancesCollector.Jarvis.initialize(InstancesConfiguration.Jarvis).then(function(){
            InstancesCollector.Jarvis.say("Hello, i'm Jarvis");
        });
    },
    Maria: function(){
        // Start Spanish
        InstancesCollector.Maria.initialize(InstancesConfiguration.Maria).then(function(){
            InstancesCollector.Maria.say("Hola, soy Maria");
        });
    },
    Christine: function(){
        // Start German
        InstancesCollector.Christine.initialize(InstancesConfiguration.Christine).then(function(){
            InstancesCollector.Christine.say("Hallo, ich bin Christine");
        });
    }
};

In this way, everytime a different language starts, it will speak something in its own language (just testing purposes).

3. Add commands to switch languages respectively

Now in this part you need to be careful. As the change of language is triggered by the voice, you need to identify from which language are you switching and to where. Besides, you need to stop the current instance from where the request comes e.g if you are requesting a change of language speaking English (Jarvis Instance), you would need to stop Jarvis. In the action of every command we'll identify with the recognized command to which language should we change after the current instance stops:

// Add command switcher from english to: spanish or german
InstancesCollector.Jarvis.addCommands([
    {
        indexes: ["Switch to Spanish", "Switch to German"],
        action: function(i){
            switch(i){
                case 0:
                    // Stop English Instance
                    InstancesCollector.Jarvis.fatality().then(function(){
                        
                        // Start Maria
                        AutoInitializers.Maria();
                    });
                break;

                case 1:
                    // Stop English Instance
                    InstancesCollector.Jarvis.fatality().then(function(){
                        
                        // Start German
                        AutoInitializers.Christine();
                    });
                break;
            }
        }
    }
]);

// Add command switcher from spanish to: english or german
InstancesCollector.Maria.addCommands([
    {
        indexes: ["Cambiar a inglés", "Cambiar a alemán"],
        action: function(i){
            switch(i){
                case 0:
                    // Stop Spanish Instance
                    InstancesCollector.Maria.fatality().then(function(){

                        // Start English
                        AutoInitializers.Jarvis();
                    });
                break;

                case 1:
                    // Stop Spanish Instance
                    InstancesCollector.Maria.fatality().then(function(){

                        // Start German
                        AutoInitializers.Christine();
                    });
                break;
            }
        }
    }
]);

// Add command switcher from german to: english or spanish
InstancesCollector.Christine.addCommands([
    {
        indexes: ["zu Englisch wechseln", "zu Spanisch wechseln"],
        action: function(i){
            switch(i){
                case 0:
                    // Stop German Instance
                    InstancesCollector.Christine.fatality().then(function(){

                        // Start English
                        AutoInitializers.Jarvis();
                    });
                break;

                case 1:
                    // Stop German Instance
                    InstancesCollector.Christine.fatality().then(function(){
                        
                        // Start Spanish
                        AutoInitializers.Maria();
                    });
                break;
            }
        }
    }
]);

So you can now switch from any language to other as every case is being covered by our initialization code e.g From Spanish to German, From German to English etc.

4. Initialize for first time with a default language

As last step, start for first time Artyom with a default language so you can switch from language with your voice:

InstancesCollector.Jarvis.initialize(InstancesConfiguration.Jarvis).then(function(){
    InstancesCollector.Jarvis.say("Ready to work, try changing the language!");
});

As you noticed in the Step B for 2 different languages, the more languages you have, the more complex is the logic to handle.

Happy coding !


Senior Software Engineer at Software Medico. Interested in programming since he was 14 years old, Carlos is a self-taught programmer and founder and author of most of the articles at Our Code World.

Sponsors