Blog image logo

How to Support Multiple Languages in Copilot Plugins

M365 Jun 30, 2024

This time, it's not about writing fancy copilot plugins. Moreover, you will gain some insight into usability.

So, I faced the problem of writing only German plugins, but yeah... we have more than German-speaking people. What a surprise πŸ˜„.

So, let's take this post as additional information to my post.

The Importance of Multilingual Support

In many cases, Copilot recognizes languages and will translate them into the target language (mostly English). But if you have unique wordings within your organization that Copilot does not know (see description here), then it will be challenging to hit the proper function for them. Let's take the example from this post. I told you how to get information about absences/holidays or time off from the external data. That's three wordings, so in German, "Abwesenheiten" / "Urlaube" are the most commonly used words. So, not three, only two.

But how do we tell the plugin to support multiple languages?

The manifest file

So it's not a secret; the manifest will tell Copilot what your plugin will do and when to use this plugin. So, my plugin contains the following description.

  "name": {
        "short": "Holiday/Vacation/Absences",
        "full": "Ask me anything about absences, holdays or vacations for all your Employees"
    "description": {
        "short": "Getting all informations about vacations / holidays oder absences.",
        "full": "Getting all informations about vacations / holidays oder absences. Can be used to ask for time off by date range or specific date and or for specific users / employees or Colleagues"

Each section (name and description) contains a short and full version. So, each is a part that copilot to "understand" the functionality of your plugin.

Now, when a German user comes up, Copilot uses the English description and tries to provide the data for the user's request.

But how to translate these manifest?

Adding language resources

Each language will be created as a new file, named with your language code and culture specification. For example, the German language with the common culture is called "de-de.json." Place it in the folder where your manifest.json is located.

Display the location of the files

In this file, you must not create the manifest from scratch. So my manifest looks like this:

    "$schema": "",
    "name.short": "Urlaube / Abwesenheiten",
    "name.full": "Plugin zur Ermittlung der Urlaube und Abwesenheitsn",
    "description.short": "Ermittlet alle Informationen zu Abwesenheiten order UrlaubeGetting.",
    "description.full": "Ermittlet alle Informationen zu Abwesenheiten order UrlaubeGetting. Kann verwendet werden um nach Abwesenheiten / Urlaubs oder Auszeiten fΓΌr ein Datum oder Bereich zu Fragen. Hier kΓΆnnen auch optional gezielt nach Urlauben fΓΌr bestiemmte Mitarbeiter / Benutzer gefragt werden.",
    "composeExtensions[0].commands[0].description": "Kann verwendet werden um nach Abwesenheiten / Urlaube fΓΌr einen Zeitraum und oder Benutzer zu fragen.",
    "composeExtensions[0].commands[0].title": "Suche Urlaube",

    "composeExtensions[0].commands[0].parameters[0].title": "Mitarbeiter",
    "composeExtensions[0].commands[0].parameters[0].description": "Beinhaltet die EntraId des angeforderten Benutzers. Es ist optional das Format 'Lastname, firstname'",
    "composeExtensions[0].commands[0].parameters[1].title": "Start",
    "composeExtensions[0].commands[0].parameters[1].description": "Beinhaltet das angeforderte Startdatum. Output ist ein date",
    "composeExtensions[0].commands[0].parameters[2].title": "Ende",
    "composeExtensions[0].commands[0].parameters[2].description": "Beinhaltet das angeforderte Enddatum. Output ist ein date",
    "composeExtensions[0].commands[0].parameters[3].title": "Bereich",
    "composeExtensions[0].commands[0].parameters[3].description": "Beinhaltet den Bereich der Abfrage. MΓΆgliches mapping ist 'user','mine', 'team', 'all' und 'none'",

Let me explain this a little bit; it's not as complex as you think. It's built upon JSON-Paths. So, the key is the path where the value will apply. So then you want to override the name of the plugin the path will be "name.short," and the value in this is "Urlaube / Abwesenheiten" Finally it looks like this

"name.short": "Urlaube / Abwesenheiten"

In my example, you can also do this for parameters in queries. Just uses the path and addresses it like an array (start with zero).

So now you can go through your manifest and "replace" the English text with your own language. But that's not all

Map the languages

You just created the translations, but you mus tell the app then to use the german translation for the german language. You can configure this in your manifest also. But pay attention, if you do this, you must define the default language of the manifest data. In addition you can tell the supported languaes then.

  "localizationInfo": {
        "defaultLanguageTag": "en-us",
        "additionalLanguages": [
                "file": "de-de.json",
                "languageTag": "de"

So, the defaultLanguageTag will define the default language (in my case, English). Next, there is a "list" of supported languages. In this, we will define our file and the map to the language. You can use a two-letter code like "de" or define the variant ("de-de"), too.

How can I check this?

It's not very easy; just start the debugger and let it attach to teams. This will then show the "installation" dialog. Then, you will see the new "supported languages" section appearing. Now you are able to refine your copilot plugin to use it for precise meanings and... of course ... translation ;)


In this blog post, you learned a little bit about how and why to use the translations for your Copilot plugins. In many cases, you will use only the English version, and it is enough, but to be professional, you should integrate other languages, too.