Internationalize a Podcast Skill

A locale is a language used in a particular country or region. For example, Canada has both en-CA (English) and fr-CA (French) locales. Alexa podcast skills support the following locales: de-DE, en-AU, en-CA, en-GB, en-IN, en-US, es-ES, es-MX, es-US, fr-CA, fr-FR, hi-IN, it-IT, ja-JP, pt-BR.

To make your podcast skill available to international users, you must internationalize it. This section describes how to add international support to your podcast skill.

Summary of changes for internationalization

To support internationalization in your podcast skill, you must make the following changes:

  1. Implement availability checking in your GetPlayableContent handler.
  2. Internationalize your podcast catalog.
  3. Update your skill's AWS Lambda function to minimize latency for international users.
  4. Optimize your skill's content resolution.
  5. Contact your Alexa Podcast representative in case you need to make additional changes.

Implement availability checking

When a customer requests a podcast, Alexa searches the catalogs for all countries to determine if the requested podcast is a valid podcast name. If it's a valid name, Alexa invokes the skill associated with the podcast catalog.

Alexa doesn't perform any availability checking at the catalog level. Instead, podcast skills must perform availability checking before responding to GetPlayableContent requests.

For example, suppose Podcast Skill X is available in two countries – the United States and India – however, Podcast X episodes are available only in the US. When a user requests Podcast X, Alexa invokes Skill X. If the user is in India, Skill X makes the determination that Podcast X is only available in the US and returns an error response with GEOGRAPHICAL_RESTRICTION_ERROR in the error response payload.

How to implement availability checking

  1. To determine if requested podcast is available in a country or region, check the request context object in the GetPlayableContent request. This object contains the user's country code (in ISO-3166 alpha-2 format) and the language of the request.
  2. If the requested podcast is available in the user's country or region, GetPlayableContent should return it. If it isn't available, GetPlayableContent should return a GEOGRAPHICAL_RESTRICTION_ERROR error response. Following is a sample error response:
    {
       "header": {
          "messageId": "2cae4d53-6bc1-4f8f-aa98-7dd2727ca84b",
          "namespace": "Alexa.Media",
          "name": "ErrorResponse",
          "payloadVersion": "1.0"
       },
       "payload": {
          "type": "GEOGRAPHICAL_RESTRICTION_ERROR",
          "message": "The requested content could not be found."
       }
    }
    

    If a single episode of a multi-episode podcast is unavailable in a country, consider skipping that episode rather than returning an error. For example, if episode N isn't appropriate for a country, your skill should skip episode N. For a serialized podcast, your skill should advance to episode N+1. For an episodic podcast, your skill should play episode N-1.

Internationalize a podcast catalog

To internationalize your podcast catalog, change the locales field to match the following example, and make sure that the podcast names follow the podcast naming conventions.

{
    "type": "AMAZON.ProgramSeries",
    "version": 2.0,
    "locales": [
        {
            "country": "US",
            "language": "en"
        },
        {
            "country": "IN",
            "language": "en"
        },
        {
            "country": "GB",
            "language": "en"
        },
        {
            "country": "AU",
            "language": "en"
        },
        {
            "country": "CA",
            "language": "en"
        },
        {
            "country": "IN",
            "language": "hi"
        },
        {
            "country": "CA",
            "language": "fr"
        },
        {
            "country": "FR",
            "language": "fr"
        },
        {
            "country": "DE",
            "language": "de"
        },
        {
            "country": "IT",
            "language": "it"
        },
        {
            "country": "ES",
            "language": "es"
        },
        {
            "country": "MX",
            "language": "es"
        },
        {
            "country": "JP",
            "language": "ja"
        },
        {
            "country": "US",
            "language": "es"
        },
        {
            "country": "BR",
            "language": "pt"
        }
    ],
    "entities": [
        {
            "id": "program.series.001",
            "names": [
                {
                    "language": "en",
                    "value": "[PROGRAM_SERIES_NAME]"
                }
            ],
            "popularity": {
                "default": 100,
                "overrides": [
                    {
                        "locale": {
                            "country": "US",
                            "language": "en"
                        },
                        "value": 100
                    }
                ]
            },
            "lastUpdatedTime": "2018-08-01T00:00:00.000Z",
            "alternateNames": [
                {
                    "language": "en",
                    "values": [
                        "[ALTERNATE_PROGRAM_SERIES_NAME]"
                    ]
                }
            ],
            "locales": [
                {
                    "country": "US",
                    "language": "en"
                }
            ],
            "languageOfContent": [
                "en"
            ],
            "deleted": false
        },
        {
            "id": "program.series.002",
            "names": [
                {
                    "language": "en",
                    "value": "[PROGRAM_SERIES_NAME]"
                }
            ],
            "popularity": {
                "default": 100,
                "overrides": [
                    {
                        "locale": {
                            "country": "US",
                            "language": "en"
                        },
                        "value": 100
                    }
                ]
            },
            "lastUpdatedTime": "2018-08-01T00:00:00.000Z",
            "alternateNames": [
                {
                    "language": "en",
                    "values": [
                        "[ALTERNATE_PROGRAM_SERIES_NAME]"
                    ]
                }
            ],
            "locales": [
                {
                    "country": "US",
                    "language": "en"
                }
            ],
            "languageOfContent": [
                "en"
            ],
            "deleted": false
        },
        {
            "id": "program.series.999",
            "lastUpdatedTime": "2018-08-01T00:00:00.000Z",
            "deleted": true
        }
    ]
}

Podcast naming conventions

Your podcast's program names must obey the following conventions:

  • Program names can contain non-Roman characters, such as Devanagari and Japanese characters.
  • Program name can contain accents, umlauts, and other diacritics.
  • Program names can't contain any special characters except for periods (.) and single quotes (').
  • Program names can't contain HTML code.

Minimize Lambda function latency

If you make your skill available in multiple countries, you need to minimize its latency for international users. To do this, consider creating three identical Lambda functions, each deployed to a different region: NA, EU and FE.

To configure your skill's Lambda functions for specific regions

  1. Create three Lambda functions in the AWS Lambda console, deploying each to one of NA, EU and FE.
  2. Open the Alexa Skills Kit Developer Console.
  3. In the list of skills, click the name of your skill.
  4. Click Endpoint in the left pane.
  5. In the box next to each region endpoint, enter the Lambda ARN for that region. Then click the Save button.

Optimize content resolution

Your internationalized podcast skill can receive utterances in English, Spanish, French, Hindi, Japanese, German, Italian, and Portuguese. Skills receive the user's spoken language in the location field of the RequestContext object. Your skill should use this information to interpret user utterances and determine which content is relevant to the user, whether that content is in English or in the user's language.

Search by topic

Your podcast skill must also be able to search for a podcast that matches the topic that the user specifies when Alexa sends a GetPlayableContent request to your skill. For example, if a user says "Alexa, play program series name about/with topic name", the skill receives a GetPlayableContent request that contains information about the user and the requested content. In addition to the user's language, the GetPlayableContent request contains the topic name in the selectionCriteria object, as shown in the following request content example:

{
    "header": {
        "messageId": "2cae4d53-6bc1-4f8f-aa98-7dd2727ca84b",
        "namespace": "Alexa.Media.Search",
        "name": "GetPlayableContent",
        "payloadVersion": "1.0"
    },
    "payload": {
        "requestContext": {
            "user": {
                "id": "[ALEXA_USER_ID]",
                "accessToken": "[ACCESS_TOKEN]"
            },
            "location": {
                "originatingLocale": "en-US",
                "countryCode": "US"
            }
        },
        "filters": {
            "explicitLanguageAllowed": true
        },
        "selectionCriteria": {
            "attributes": [
                {
                    "type": "PROGRAM_SERIES",
                    "entityId": "program.series.001"
                },
                {
                    "type": "TOPIC_NAME",
                    "value": "[TOPIC_NAME]"
                }
            ]
        }
    }
}

Your skill can use this information to match the user's requested topic to your podcast topics. It should use country information to determine the relevance of a podcast for a particular topic. For example, "topic": "Sports" should return a relevant sports podcast for a country. If the topic is "football", the relevant sport may be American football for a user in the United States, while it would likely be soccer (football) for users in other countries.