Building Multilingual Teams Bots: Adding Adaptive Cards with Dynamic Language Support
When building bots for Microsoft Teams, using Adaptive Cards provides a visually engaging way to present content.
For example, instead of a simple bot message:
You can impress your user with a more entertaining adaptive card:
Even better… what if you could detect the user’s locale and dynamically change the greeting language based on this?
In this article, I’ll walk you through how to create dynamic adaptive cards in a Teams bot using TypeScript.
What are Adaptive Cards?
An adaptive card is basically a configurable card that you can add to your Microsoft Teams application. As highlighted above, these cards are designed to make messages look better and more interactive. Instead of being limited to sending plain text chat messages, you can add features such as images, buttons, and formatted text.
Pre-requisites
- A working Microsoft Teams bot — read my last article to see how you can easily set yours up.
Table of Contents
1. Setting up Localisation in Teams Bot
To handle text translations, we will use i18next.
So, let’s jump right in! Open up your bot code in VS code.
Install i18next
If you don’t have i18next installed already, you can do so by running the following command in your terminal:
npm install i18next
Create your translations files for different languages. Here is a sample structure for English and Spanish translations:
Each translation.json
file contains key-value pairs for translated text.
For example, in src/locales/en/translation.json
:
{
"chat": {
"greeting_text": "Welcome to the bot!",
"greeting_text_help": "How can I assist you today?",
}
}
In src/locales/es/translation.json
:
{
"chat": {
"greeting_text": "¡Bienvenido al bot!",
"greeting_text_help": "¿Cómo puedo ayudarte hoy?",
}
}
Create a file in the src
folder called i18n.ts
and add the following code:
// src/i18n.ts
import i18n from "i18next";
import en from "./locales/en/translation.json";
import es from "./locales/es/translation.json";
i18n.init({
resources: {
en,
es,
},
lng: "en",
fallbackLng: "en",
interpolation: {
escapeValue: false,
},
});
export default i18n;
This code initialises the i18n library with the English (en
) and Spanish (es
) translation files that we just created. It sets English as the default language (lng
) and fallback language if no other locale is detected.
2. Creating an Adaptive Card with Translations
Now, let’s get to the fun stuff and create the adaptive card. Add the following function to your main bot file (mine is app.ts
) and we’ll dive into what it means.
// src/app.ts
// ...previous bot code
function createGreetingCard(locale: string) {
return {
$schema: "https://adaptivecards.io/schemas/adaptive-card.json",
type: "AdaptiveCard",
version: "1.0",
body: [
{
type: "Image",
url: "https://github.com/wymersam/dicogptimage/blob/main/dicoGPT.png?raw=true",
height: "150px",
},
{
type: "TextBlock",
text: i18n.t("chat.greeting_text", { lng: locale }),
wrap: true,
color: "accent",
},
{
type: "TextBlock",
text: i18n.t("chat.greeting_text_help", { lng: locale }),
color: "warning",
},
],
};
}
// ...end of file
Code Explanation:
This is the code that creates an adaptive card with dynamic translation possibilities.
- Structure: Adaptive cards are created via a JSON object, which makes them really easy to configure. In our super simple example, we include an image (note that this has to be a URL) and two blocks of text which come from the translation files we created in the previous step. We’ll add some more styling in the next steps.
- i18n.t: This method retrieves the translated text based on the locale (e.g. en-US) passed. As you can see, we pass the locale as an argument to this function to determine which language will be shown. But where do we get this locale value from?
3. Displaying the Adaptive Card in Teams
Once you have the function to create the adaptive card, you then need to create another function to display the card with the correct translation in the Teams chat:
// src/app.ts
async function showGreetingCard(context: TurnContext, locale: string) {
// Show the adaptive card in the chat
await context.sendActivity({
attachments: [CardFactory.adaptiveCard(createGreetingCard(locale))],
});
}
Code Explanation:
- context.locale: This is where we find out the locale of the user.
- defaultLanguage: In case no locale is detected, a fallback locale is used (e.g. en-US for English).
- CardFactory.adaptiveCard(): This method allows us to use the JSON object we created in the
createGreetingCard
function to style our adaptive card.
4. Complete Code Example
Here’s the complete code block for reference, including the event handler (onInstallationUpdate()
) for when the bot is installed:
// src/app.ts
import { CardFactory, TurnContext } from 'botbuilder';
import i18n from 'i18next';
// ...other code and imports
// Set a default locale as a fallback value
const defaultLanguage = "en-US";
// Show the adaptive card when the bot is installed/updated
// This event handler comes from the bot-builder package
this.onInstallationUpdate(async (context: TurnContext, next) => {
const { locale } = context.activity;
await showGreetingCard(context, locale ? locale : defaultLanguage);
await next();
});
// ...main bot code
function createGreetingCard(locale: string) {
return {
$schema: "https://adaptivecards.io/schemas/adaptive-card.json",
type: "AdaptiveCard",
version: "1.0",
body: [
{
type: "Image",
url: "https://github.com/wymersam/dicogptimage/blob/main/dicoGPT.png?raw=true",
height: "150px",
},
{
type: "TextBlock",
text: "Welcome to the bot!",
wrap: true,
color: "accent",
},
{
type: "TextBlock",
text: "How can I assist you today?",
wrap: true,
color: "warning",
},
],
};
}
async function showGreetingCard(context: TurnContext, locale: string) {
await context.sendActivity({
attachments: [CardFactory.adaptiveCard(createGreetingCard(locale))],
});
}
// end of code
5. Testing in Microsoft Teams
Once you’ve added this functionality to your bot, redeploy it to Azure and test it in your Microsoft Teams environment (if needed, you can refer to my previous article on how to do this).
- Install the Bot in a Team: After installing the bot on Teams, it should send the greeting card in the language based on your Teams locale settings.
Note: The text will only be translated if you have the appropriatetranslation.json
file for the user’s locale/language. For example, if your locale is de-DE but you don’t have a translation file for German, then the language will fallback to English. - Change Teams Locale: Go to Teams settings and change the language (e.g. from English to Spanish). Reinstall or update the bot, and you should see the greeting card now appears in Spanish!
6. Additional Configuration
You can configure your adaptive cards even more with features such as columns, buttons, colours, spacing, and more.
In this example, I updated the adaptive card JSON object to have columns, gave the columns a colour, and also added a button which would take the user to the URL provided:
// src/app.ts
function createGreetingCard() {
return {
$schema: "https://adaptivecards.io/schemas/adaptive-card.json",
type: "AdaptiveCard",
version: "1.0",
body: [
{
type: "ColumnSet",
style: "accent",
bleed: true,
columns: [
{
type: "Column",
items: [
{
type: "Image",
url: "https://github.com/wymersam/dicogptimage/blob/main/dicoGPT.png?raw=true",
height: "150px",
},
],
width: "auto",
},
{
type: "Column",
style: "warning",
bleed: true,
items: [
{
type: "TextBlock",
text: "Welcome to the bot!",
wrap: true,
},
{
type: "TextBlock",
text: "How can I assist you today?",
},
{
type: "ActionSet",
actions: [
{
type: "Action.Submit",
title: "Click Me",
url: "www.example.com",
},
],
},
],
width: "stretch",
},
],
},
],
};
}
Conclusion
In this guide, we covered how to create an adaptive card in Microsoft Teams that updates the text language dynamically based on the user’s locale. By using i18next and the Microsoft Bot Framework, you can create dynamic, user-friendly bots that support multiple languages.
Thanks for reading! Why not jump right in and start designing an adaptive card that fits your bot’s requirement?