Support Multiple Locales With the Alexa Conversations Description Language (Beta)

You can use the Alexa Conversations Description Language (ACDL) to create skills for multiple locales. A locale is the combination of a language and a location. For example, en-IN is a locale that represents the English language spoken in India.

Your skill can support a single locale, or any combination of the following locales that ACDL supports:

  • English (AU) (en-AU)
  • English (CA) (en-CA)
  • English (IN) (en-IN)
  • English (UK) (en-GB)
  • English (US) (en-US)
  • German (DE) (de-DE)

Localization is optional. Expressions that you don't explicitly annotate by the methods described on this page are considered to be global (that is, apply to all locales). Therefore, if you already developed a non-localized skill with ACDL, you can continue to compile and deploy the skill without modification.

Prerequisites

Before you localize your skill, you must meet the following prerequisites:

Steps to localize your skill

Take the following steps to add locales to an existing skill.

  1. Add all supported locales to the skill manifest.
  2. Add an interaction model file for each locale.
  3. Use the @locale() annotation.
  4. Specify locales in the skill entry point.

Step 1: Add all supported locales to the skill manifest

As with any Alexa skill, your skill manifest must include publishing information for each supported locale. This publishing information contains the skill name, description, example phrases, and so on.

To specify this information, you include an object for each supported locale in the publishingInformation.locales object of the skill manifest. For details, see locales in the skill manifest documentation.

The following is an example of the skill manifest of a skill that supports en-US and en-GB.

Step 2: Add an interaction model file for each locale

Your skill must also have an interaction model file for each locale that your skill supports.

Interaction model files are named after the locale (en-US.json, en-in.json, and so on) and are located in the <skill directory>/skill-package/conversations/interactionModels/custom directory.

You specify the invocation name for your skill in the interaction model files. For details about how to choose an invocation name, see Choose the Invocation Name for a Custom Skill. You can use the same invocation name for different locales.

The following examples show interaction model files for en-US and en-GB.

Step 3: Use the @locale() annotation

To localize your Alexa Conversations skill assets, you apply the @locale() annotation to your utterance sets, responses, dialogs, and samples. For utterance sets and responses, you then group the localized assets together by using the variations() action. As mentioned previously, if you don't apply the locale@ annotation to an expression, the expression applies to all locales.

The @locale() annotation takes a locale as a parameter, which you specify by using a property of the Locale enum. The Locale enum can be one of the following values.

enum Locale {
  en_AU   // English (AU)
  en_CA   // English (CA)
  en_IN   // English (IN) 
  en_GB   // English (UK)
  es_US   // English (US)
  de_DE   // German (DE) 
}

For example, you specify the en-US locale by using Locale.en_US.

The following sections show how to apply the @locale() annotation to utterance sets, responses, dialogs, and samples.

Localize utterance sets

To localize a set of utterances, you put the @locale() annotation before the utterance event declaration for each locale. The utterance event declaration action is utterances<T>().

You then use the variations() action to group all the corresponding utterance sets together into one locale-agnostic utterance set that you use as the argument to the expect() action when you declare an event.

Localize responses

To localize a set of responses, you put the @locale() annotation before the apl<T>() and apla<T>() actions to indicate the path of the APL/APLA response files for a particular locale.

You then use the variations() action to group all the corresponding responses together into one locale-agnostic response that you use wherever you specify a response: skill-level responses are in the skill() declaration (see the next step), and other responses are arguments to the response() action within dialogs.

Localize dialogs and samples

Dialogs contain the conversational flow. To specify that a dialog applies to one or more locales, precede the dialog with the @locale() annotation.

Similarly, you can apply the locale@ annotation to individual samples within the dialog.

For many skills, you can use the same dialog and samples for all locales, because the conversational flow of the skill is the same. In that case, you can omit the @locale() annotation for the dialogs and samples if you choose.

Step 4: Specify locales in the skill entry point

You specify the locales to which the skill is to be deployed by using the locales parameter of the skill() action. The skill() action is the skill entry point.

Complete example

The following example shows the ACDL for a localized skill.

namespace com.weatherbot

import com.amazon.alexa.ask.conversations.*
import com.amazon.ask.types.builtins.AMAZON.*
import slotTypes.*

type CityAndDate {
    optional CityName cityName
    optional DATE date
}

type WeatherResult {
    CityName cityName
    NUMBER highTemp
    NUMBER lowTemp
}

type ResponsePayload {
    WeatherResult weatherResult
}

@locale(Locale.en_GB)
getWeatherEventGB = utterances<CityAndDate>(
    [
        "What's the weather {date} in {cityName} in Great Britain",
        "what is the weather {date} in Great Britain",
        "How is the weather in {cityName} in Great Britain",
        "How is weather in {cityName} {date} in Great Britain",
        "how is weather in Great Britain",
        "can you please give me weather report for {date} in Great Britain"
    ]
)

@locale(Locale.en_US, Locale.en_CA)
getWeatherEventNA = utterances<CityAndDate>(
    [
        "What's the weather {date} in {cityName} in North America",
        "what is the weather {date} in North America",
        "How is the weather in {cityName} in North America",
        "How is weather in {cityName} {date} in North America",
        "how is weather in North America",
        "can you please give me weather report for {date} in North America"
    ]
)

getWeatherEvent = variations(getWeatherEventGB, getWeatherEventNA)

// Because the current folder path is skill-package/conversations/
@locale(Locale.en_US, Locale.en_CA)
request_city_NA = apla<CityName>("../../lib/prompts/en/request_city_apla_NA")
@locale(Locale.en_GB)
request_city_GB = apla<CityName>("../../lib/prompts/en/request_city_apla_GB")
request_city = variations(request_city_NA, request_city_GB)

// Nested variations() action
@locale(Locale.en_US)
request_date_en_US = apla<DATE>("../../lib/prompts/en/request_date_apla/document.json")
@locale(Locale.en_CA)
request_date_en_CA = apla<DATE>("../../lib/prompts/en/request_date_apla/document.json")
request_date_NA = variations(request_date_en_US, request_date_en_CA)
@locale(Locale.en_GB)
request_date_GB = apla<DATE>("../../lib/prompts/en/request_date_apla/document.json")
request_date = variations(request_date_NA, request_date_GB)

@locale(Locale.en_US, Locale.en_CA)
request_city_date_NA = apla<CityAndDate>("../../lib/prompts/en/request_city_date_apla_NA/document.json")
@locale(Locale.en_GB)
request_city_date_GB = apla<CityAndDate>("../../lib/prompts/en/request_city_date_apla_GB/document.json")
request_city_date = variations(request_city_date_NA, request_city_date_GB)

@locale(Locale.en_US, Locale.en_CA)
weather_prompt_NA = apla<ResponsePayload>("../../lib/prompts/en/weather_apla_NA/document.json")
@locale(Locale.en_GB)
weather_prompt_GB = apla<ResponsePayload>("../../lib/prompts/en/weather_apla_GB/document.json")
weather_prompt = variations(weather_prompt_NA, weather_prompt_GB)


// ================= Skill-level responses ==================
@locale(Locale.en_GB)
myWelcomeGB = apla("../../lib/prompts/en/Welcome_GB")
@locale(Locale.en_US, Locale.en_CA)
myWelcomeNA = apla("../../lib/prompts/en/Welcome_NA")
myWelcome = variations(myWelcomeGB, myWelcomeNA)

@locale(Locale.en_US, Locale.en_GB, Locale.en_CA)
out_of_domain = apla("../../lib/prompts/en/OutOfDomain")

@locale(Locale.en_US, Locale.en_GB, Locale.en_CA)
bye = apla("../../lib/prompts/en/Bye")

@locale(Locale.en_US, Locale.en_GB, Locale.en_CA)
reqmore = apla("../../lib/prompts/en/RequestMore")

@locale(Locale.en_US, Locale.en_GB, Locale.en_CA)
provide_help = apla("../../lib/prompts/en/ProvideHelp")

@locale(Locale.en_US, Locale.en_GB, Locale.en_CA)
thank_you = apla("../../lib/prompts/en/ThankYou")

@locale(Locale.en_US, Locale.en_GB, Locale.en_CA)
you_are_welcome = apla("../../lib/prompts/en/YouAreWelcome")

@locale(Locale.en_US, Locale.en_GB, Locale.en_CA)
notify_failure = apla("../../lib/prompts/en/NotifyFailure")

skillLevelResponses = SkillLevelResponses
    {
        welcome = myWelcome,
        out_of_domain = out_of_domain,
        bye = bye,
        reqmore = reqmore,
        provide_help = provide_help,
        thank_you = thank_you,
        you_are_welcome = you_are_welcome,
        notify_failure = notify_failure
    }

// The skill will be deployed to en-US and en-GB
mySkill = skill(
    locales = [Locale.en_US, Locale.en_GB],
    skillLevelResponses = skillLevelResponses
)

action WeatherResult getWeather(CityName cityName, DATE date)

@locale(Locale.en_US, Locale.en_GB)
dialog void Weather {
    sample {
        weatherRequest = expect(Invoke, getWeatherEvent)

        ensure(
            RequestArguments {arguments = [getWeather.arguments.cityName], response = request_city},
            RequestArguments {arguments = [getWeather.arguments.date], response = request_date},
            RequestArguments {arguments = [getWeather.arguments.cityName, getWeather.arguments.date], response = request_city_date}
        )

        weatherResult = getWeather(weatherRequest.cityName, weatherRequest.date)

        response(weather_prompt, Notify {actionName = getWeather}, payload = ResponsePayload {weatherResult = weatherResult})
    }
}