Mastering Chat locale

Goal

In this tutorial, we will use the Locale in order to change the locale of a Chat.

The application will be able to switch the discussion locale between English and Japanese.

Prerequisites

Before stepping in this tutorial, you should:

Let’s start a new project

  • Start a new project, let’s call it ChatLocalePepper.
  • Robotify it and make sure it implements the QiSDK & the Robot Life Cycle.

For further details, see: Creating a robot application.

Creating the topic files

First, we need to create 2 topic files: one in English, and the other in Japanese.

English

Create a new topic file named hello.top for the English (en) language.

Add the following content to this file:

topic: ~hello()

proposal: %start Say hello to start the discussion.

u:(hello) hello

Move it to the assets folder and rename it to hello-en.top.

Japanese

Create a new topic file named hello.top for the Japanese (ja) language.

Add the following content to this file:

topic: ~hello()

proposal: %start 会話を始めるためには、スタート、と言ってください!

u:(こんにちは) こんにちは

Move it to the assets folder and rename it to hello-ja.top.

Creating the Chat actions

In the same way, we need to create 2 Chat actions: one in English, and the other in Japanese.

Add the following buildChat method to your MainActivity:

private Chat buildChat(QiContext qiContext, String topicAssetName, Locale locale) {
    // Create a topic from the asset file.
    Topic topic = TopicBuilder.with(qiContext)
            .withAsset(topicAssetName)
            .build();

    Bookmark startBookmark = topic.getBookmarks().get("start");

    // Create a new QiChatbot with the specified Locale.
    QiChatbot qiChatbot = QiChatbotBuilder.with(qiContext)
            .withTopic(topic)
            .withLocale(locale)
            .build();

    // Create a new Chat action with the specified Locale.
    Chat chat = ChatBuilder.with(qiContext)
            .withChatbot(qiChatbot)
            .withLocale(locale)
            .build();

    chat.addOnStartedListener(() -> {
        Log.i(TAG, "Discussion is now in " + locale.getLanguage() + ".");
        qiChatbot.async().goToBookmark(startBookmark, AutonomousReactionImportance.HIGH, AutonomousReactionValidity.IMMEDIATE);
    });

    return chat;
}

In this implementation, we:

  • Use a TopicBuilder and the withAsset method to create a Topic with the specified asset file.
  • Retrieve the “start” Bookmark.
  • Use a QiChatbotBuilder and the withLocale method to create a QiChatbot with the specified Locale.
  • Use a ChatBuilder and the withLocale method to create a Chat with the specified Locale.
  • Add a started listener to the Chat to go to the “start” Bookmark when the Chat starts.
  • Return the configured Chat.

We will now create the Chat actions. Store 2 Chat actions in your MainActivity:

// Store the Chat actions.
private Chat chatEN;
private Chat chatJA;

Add the following buildEnglishChat and buildJapaneseChat methods to your MainActivity:

private void buildEnglishChat(QiContext qiContext) {
    Locale locale = new Locale(Language.ENGLISH, Region.UNITED_STATES);
    chatEN = buildChat(qiContext, "hello-en.top", locale);
}

private void buildJapaneseChat(QiContext qiContext) {
    Locale locale = new Locale(Language.JAPANESE, Region.JAPAN);
    chatJA = buildChat(qiContext, "hello-ja.top", locale);
}

Here we provide the asset file name and the corresponding Locale to the buildChat method.

In the onRobotFocusGained method, call these 2 methods:

@Override
public void onRobotFocusGained(QiContext qiContext) {
    // Prepare the Chat actions.
    buildEnglishChat(qiContext);
    buildJapaneseChat(qiContext);
}

In the onRobotFocusLost method, remove the listeners from the Chat actions:

@Override
public void onRobotFocusLost() {
    // Remove the listeners from the Chat actions.
    if (chatEN != null) {
        chatEN.removeAllOnStartedListeners();
    }
    if (chatJA != null) {
        chatJA.removeAllOnStartedListeners();
    }
}

Running the Chat actions

Now that we have built the Chat actions, we will create the methods to run them.

Store a Future<Void> in your MainActivity:

// Store the action execution future.
private Future<Void> currentChatFuture;

Add the following runChat method to your MainActivity:

private void runChat(Chat chat) {
    if (chat == null) return;
    currentChatFuture = chat.async().run();
}

Before running the Chat action, we need to cancel the current discussion, if any.

Add the following switchToChat method to your MainActivity:

private void switchToChat(Chat chat) {
    if (currentChatFuture != null) {
        // Cancel the current discussion.
        currentChatFuture.requestCancellation();
        // Run the Chat when the discussion stops.
        currentChatFuture.thenConsume(ignored -> runChat(chat));
    } else {
        // If no current discussion, just run the Chat.
        runChat(chat);
    }
}

To run the Chat actions, we will use 2 RadioButton in the UI.

Modify your activity_main.xml file with the following code:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <RadioGroup
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <RadioButton
            android:id="@+id/enButton"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="EN" />

        <RadioButton
            android:id="@+id/jaButton"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="JA" />
    </RadioGroup>

</android.support.constraint.ConstraintLayout>

Store 2 RadioButton in your MainActivity:

private RadioButton enButton;
private RadioButton jaButton;

And add this code in the onCreate method:

enButton = findViewById(R.id.enButton);
jaButton = findViewById(R.id.jaButton);

// Change the locale to English when checked.
enButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
    if (isChecked) {
        switchToChat(chatEN);
    }
});

// Change the locale to Japanese when checked.
jaButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
    if (isChecked) {
        switchToChat(chatJA);
    }
});

Here we find the buttons and we run the corresponding Chat action when the button is checked.

Handling buttons state

We will now change the buttons state depending on the application state.

Add the following enableButtons and disableButtons methods to your MainActivity:

private void disableButtons() {
    runOnUiThread(() -> {
        enButton.setEnabled(false);
        jaButton.setEnabled(false);
    });
}

private void enableButtons() {
    runOnUiThread(() -> {
        enButton.setEnabled(true);
        jaButton.setEnabled(true);
    });
}

When the Activity becomes visible, we want the buttons to be disabled and unchecked. Add this code in the onResume method:

@Override
protected void onResume() {
    super.onResume();

    // Disable and uncheck buttons.
    disableButtons();
    enButton.setChecked(false);
    jaButton.setChecked(false);
}

When the Chat actions are built, we want to enable the buttons. Call enableButtons in onRobotFocusGained:

@Override
public void onRobotFocusGained(QiContext qiContext) {
    // Prepare the Chat actions.
    buildEnglishChat(qiContext);
    buildJapaneseChat(qiContext);

    enableButtons();
}

When the user clicks on a button, we want to disable both buttons. Call disableButtons in the buttons listener:

// Change the locale to English when checked.
enButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
    if (isChecked) {
        disableButtons();
        switchToChat(chatEN);
    }
});

// Change the locale to Japanese when checked.
jaButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
    if (isChecked) {
        disableButtons();
        switchToChat(chatJA);
    }
});

When a Chat action starts, we want to enable the buttons. Call enableButtons in buildChat, in the Chat started listener:

// Enable buttons when the Chat starts.
chat.addOnStartedListener(() -> {
    enableButtons();
    Log.i(TAG, "Discussion is now in " + locale.getLanguage() + ".");
    qiChatbot.async().goToBookmark(startBookmark, AutonomousReactionImportance.HIGH, AutonomousReactionValidity.IMMEDIATE);
});

Let’s try it

github_icon The sources for this tutorial are available on GitHub.

Step Action

Install and run the application.

For further details, see: Running an application.

Choose “Mastering Chat locale”.

Wait for the buttons to be enabled.

Choose “EN”.

Pepper starts the discussion in English.

Choose “JA”.

Pepper starts the discussion in Japanese.

https://developers.softbankrobotics.com/sites/default/files/repository/58_rst_pepper/public/source/_build/html/_images/chat_locale.png

You are now able to change the locale of a discussion!