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)
  • Japanese (JP) (ja-JP)
  • Spanish (US) (es-US)
  • Spanish (ES) (es-ES)

Localization is optional. ACDL considers expressions that you don't explicitly annotate by the methods described on this page as global (that is, they 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

Complete 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 the publishing information

  • 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 example skill manifest 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.

To add interaction model files

  1. Navigate to the <skill directory>/skill-package/conversations/interactionModels/custom directory.
  2. Create an interaction model file for each locale, using the locale name as the file name (for example, en-US.json, en-in.json, and so on).
  3. Specify the invocation name for your skill in each of 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 procedures show you how to apply the @locale() annotation to a set of utterances, a set of responses, dialogs, and samples.

To localize a set of utterances

  1. Put the @locale() annotation before the utterance event declaration for each locale.
    The utterance event declaration action is utterances<T>().
  2. 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.

To localize a set of responses

  1. 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.
  2. 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 Step 4), and other responses are arguments to the response() action within dialogs.

Dialogs contain the conversational flow.

To localize dialogs and samples

  1. To specify that a dialog applies to one or more locales, precede the dialog with the @locale() annotation.
  2. Similarly, apply the locale@ annotation to individual samples within the dialog.

Step 4: Specify locales in the skill entry point

You must specify the locales where you plan to deploy the skill.

To specify locales in the skill entry point

  • Use 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})
    }
}