21 Languages and Skills

You can design both single-language and multi-language skills. For understanding user input, you can either use Oracle Digital Assistant's native support for various languages or a translation service. For output, you typically define the strings for each target language in resource bundles.

Language Use Cases for Skills

The approach you take to handling your language requirements for skills depends on a number of factors. Here are some typical use cases and ways you can approach them.

You Want the Skill to Work Equally Well in Multiple Languages

For skills that you target to the languages that Oracle Digital Assistant supports natively, you can add training data for all of the target languages. This includes example utterances for intents and custom entity values.

Prerequisites:

  • The languages you are targeting all are on the list of Natively-Supported Languages.
  • The Platform Version of the skill is 20.12 or higher.

General steps:

  • When creating the version (or clone) of the skill, designate one of the natively-supported languages as the primary language. This language will serve as the default language in the skill. Once you have set it, you can not change it.
  • On the skill's Settings, Intents, or Entities page, add any additional natively-supported languages that you want to target.
  • Build the training corpus in the primary language.
  • For each additional language, augment the training corpus as necessary.
  • For any value list entities that you create in the primary language, add values in the additional language that correspond to each of the values in the primary language.
  • Create resource bundles for each of the skill's output strings, provide entries for each language, and reference the resource bundle keys from the appropriate places in the dialog flow and the skill's settings.

Other notes and considerations:

  • In terms of user experience, this approach gives you the best opportunity to satisfy user expectations in multiple languages.
  • To realize the potential of this approach, be sure to allocate adequate resources for multi-language intent training and formulating effective output messages in all of the target languages.

You Want to Avoid Using a 3rd-Party Translation Service

If you want to create a skill with one or more non-English languages but don't want to use a 3rd-party translation service, you can use Digital Assistant's native language support. See the above section on optimizing skills for multiple languages.

You Want to Create a Single-Language Skill in a Language Not Supported Natively

Prerequisite:

  • You have configured a translation service (either Microsoft Translator or the Google Translation API).

General steps:

  • Create intent utterances and entity values in the language that you are supporting.
  • Add code to the dialog flow to detect the language of the user input and to translate it behind the scenes. (For non-English skills that rely on a translation service, the underlying training model of the skill is in English.)
  • Create resource bundles for the skill responses.

Other notes and considerations:

  • If the target language of your skill is among the natively-supported languages, consider using the native language approach. Then, if you later need to add other languages that are natively supported, you will be able to optimize intent resolution for each language (in addition to having more control over the output messages).
  • If you later want to add other languages to the skill and one or more of the desired languages isn't supported natively, you would need to create a new skill from scratch and set English as the primary language in the new skill.
  • Entity values for built-in entity types (such as NUMBER, EMAIL, and DATE) are extracted after the user input has been translated to English behind the scenes.

You Want to Create a Multi-Language Skill that Contains One or More Languages That Are Not Supported Natively

Prerequisites:

  • You have configured a translation service (either Microsoft Translator or the Google Translation API).
  • The primary language of the skill is English.
  • All languages that you add are handled through the translation service.

General steps:

  • When creating the skill, designate English as the primary language (and in translation mode).
  • Create intent utterances and entity values in English.
  • Add code to the dialog flow to detect the language of the user input and to translate it behind the scenes.
  • To handle skill responses, either:
    • Set up the dialog flow to translate skill responses from English to the user's language.
    • Create resource bundles with entries for each target language and configure the skill to use them in its responses.

Other notes and considerations:

  • Entity values for built-in entity types (such as NUMBER, EMAIL, and DATE) are extracted after the user input has been translated to English behind the scenes.

You Want a Multi-Language Skill Without Needing to Create Resource Bundles for Each Language

If you'd like to create a multi-language skill but do not want to create resource bundle entries for the various languages, you can use the translation service to handle the skill's responses. (This approach does not work with Digital Assistant's native language support.)

Prerequisites:

  • You have configured a translation service (either Microsoft Translator or the Google Translation API).
  • The primary language of the skill is English.
  • All languages that you add are handled through the translation service.

General steps:

  • When creating the skill, designate English as the primary language (and in translation mode).
  • Add code to the dialog flow to detect the language of the user input and to translate it behind the scenes.
  • Set up the dialog flow to translate skill responses to the user's language.

Other notes and considerations:

  • If the target languages of your skill are all among the natively-supported languages, consider using the native language approach, since this will enable you to optimize intent resolution for each language (in addition to having more control over the output messages).
  • Even if you need to target languages that are not natively supported, you may find that the benefits of having greater control of the output messages justify the costs.

Language Mode

When you create a new skill (or version or clone of a skill), you use the Primary Language field in the Create dialog to determine both:

  • A primary language.
  • A language mode (either Natively Supported or Translation Service).

The language mode determines:

  • How the user language is detected and processed.
  • Which languages you can add to your skill.
    • If your skill uses the Natively Supported language mode, you can use any of the languages that are supported natively in Oracle Digital Assistant.
    • If it uses the Translation Service mode, you can use any of the languages supported by the translation service.

Caution:

Once you have clicked Create in the wizard, the language mode is permanently set for that version of the skill. You can't mix and match language mode in skills or digital assistants.

Native Language Support for Skills

Starting with Platform Version 20.12, there is native support in Oracle Digital Assistant for multiple languages. When you develop a skill with this native language support, you don't need to use a 3rd-party translation service to handle user input and skill responses in those languages.

If you are developing such skills for inclusion in a digital assistant, that digital assistant must also use the native language support. See Native Language Support in Digital Assistants.

How Native Language Support Works

  • Training data can be supplied in each of the (natively-supported) languages that you are designing the skill for.

    When you use native language support, the skill is trained according to a unified model that incorporates all of the natively-supported languages. You can provide training utterances in one or more of your skill's target languages.The training utterances that you provide in one language help build the model for all of the natively-supported languages that you are using in your skill. For skills that you target to multiple languges, typically you will start by building your training corpus in the skill's primary language. Then you can (and should) add training utterances in the other languages, though you probably won't need nearly as many in those other languages.

    This differs from skills that use a translation service. In those skills, the underlying training model is always in English, even if the training corpus is provided in another language.

  • Entity values for built-in entity types (such as NUMBER, EMAIL, and DATE) are extracted in the language of the conversation. (This differs from the case with skills in translation service mode, where the values are extracted after the input has been translated by the translation service.
  • Entity values for custom entities are matched to the values provided for the language of the current conversation.

Natively-Supported Languages

Here are the languages (and the corresponding languages codes) that are currently supported natively in Oracle Digital Assistant.

  • Arabic (ar)
  • Dutch (nl)
  • English (en)
  • French (fr)
  • German (de)
  • Italian (it)
  • Portuguese (pt)
  • Spanish (es)

This means that you can create skills and digital assistants for these languages without using a translation service, such as Google Translate.

Here's an overview of the level of support for each language.

Language Language Understanding Voice Insights Data Manufacturing Conversation Designer
Arabic (ar) Yes No Yes Yes No
Dutch (nl) Yes No Yes Yes No
English (en) Yes Yes Yes Yes Yes
French (fr) Yes Yes Yes Yes No
German (de) Yes No Yes Yes No
Italian (it) Yes No Yes Yes No
Portuguese (pt) Yes Yes Yes Yes No
Spanish (es) Yes Yes Yes Yes No

For a more detailed comparison of the support for each language, see Feature Support by Language.

Create a Skill with Natively-Supported Languages

Here are the general steps for creating a skill that uses Oracle Digital Assistant's native support for multiple languages.

  1. When creating the skill, select Platform Version 20.12 or higher and select the primary language that you want to support from the Primary Language dropdown.

    The language you select must be within the Natively-Supported section of the dropdown.

  2. For each intent that you create, add utterances for your skill in the primary language:
    1. Click icon to open the side menu to open the side menu, select Development > Skills, and open your skill.
    2. In the left navigation for the skill, click This is an image of the Intent icon.
    3. Select an intent.
    4. In the Examples text field, type the utterance and press Enter.
    5. Repeat the previous two sub-steps for each intent.
  3. For any custom entities in your skill, make sure the values are in the skill's primary language.

    You can add and edit custom entities by clicking An image of the Entities icon in the left navigation of the skill.

  4. For any components in your dialog flow that have properties that display prompts or labels, make sure that you explicitly define those properties. If you don't define these properties, customers may encounter default text from those properties, which are in English.
  5. In the skill's settings, update all of the configuration messages and prompts to use the primary language:

    To access these messages and prompts:

    • In the left navigation for the skill, click The Settings icon in the left navbar.

    The messages and prompts are located on the Configuration and Digital Assistant tabs.

    Note:

    If you're planning to support multiple languages in the skill, you will need to define resource bundle keys for these values and then refer to those keys in the fields for these properties. And, even if you don't plan to support multiple languages, you may want to do this anyway, since the resource bundle provides a single place where you can edit the values of all of your strings. See Resource Bundles for Skills.

Add Natively-Supported Languages to a Skill

For skills (or versions of skills) where you have chosen a natively-supported primary language, you can add additional natively-supported languages.

  1. Make sure your skill is running on Platform Version 20.12 or higher.

    If it isn't, you need to create a clone or a new version of the skill and set it to use Platform Version 20.12 or higher.

  2. In the skill's left navbar, click the Settings(an image of the left navbar's Settings icon) icon and select the General tab.
  3. Scroll down to the languages section, click Add Language and select the language from the dropdown.
  4. For each of the intents in the skill, add a conversation name and additional utterances in the added language:
    1. Click Intents (This is an image of the Intent icon.) in the left navbar.
    2. Select the intent to edit.
    3. Select the tab for the language that you just added.
    4. Click This is an image of the Edit icon to enter a descriptive name or phrase for the intent in the Conversation Name field.
  5. For any entities that are based on key-value pairs (value list entities and dynamic entities), enter values for that language.
  6. Enable the skill to display entity values in the language of the conversation:
    1. In components that you use to resolve entities (System.ResolveEntities and System.CommonResponse), add the useFullEntityMatches property and set it to true.

      By making this change, custom entity values are stored as JSON objects instead of as simple strings.

    2. In all of your FreeMarker expressions that reference custom entity values (whether in the dialog flow or in various skill properties), insert the attribute corresponding to the value you want to read. You can use any of the following attributes:
      • value - returns the value of the entity in the conversation of the language.
      • primaryLanguageValue - returns the value of the entity in the primary language of the skill. You would use this option for expressions that are used for business logic (e.g. to determine whether or not to display a prompt, based on the entity value).
      • originalString - returns the value that the user entered to match the entity. This value could be a synonym of the entity value.

      For example, if you have the expression ${PizzaSize} for referencing the value of the PizzaSize entity, you would change it to ${PizzaSize.value} to display the value in the language of the conversation.

  7. If you haven't already done so, create resource bundle keys for all of the output that users will see, enter values for the primary language, and insert references to those keys in the appropriate places. This includes:
    • Output text in the dialog flow.
    • Prompts for entities that are included in the entity definition.
    • Messages and prompts defined in the skill's settings. To access them:
      • In the left navigation for the skill, click The Settings icon in the left navbar.

      The messages and prompts are located on the Configuration and Digital Assistant tabs.

    See Resource Bundles for Skills.
  8. For any components in your dialog flow that have properties that display prompts or labels, make sure that you explicitly define those properties (so that they don't default to English values) and create resource bundle entries for them.
  9. Add values in the additional language for all of the resource bundle keys.
  10. Augment the training corpus as necessary in the additional language.

    Since skills with natively-supported languages are based on a unified training model in which all of the training helps with intent resolution in all of the skill's target languages, the training model should already work for your additional language, even without adding utterances in that language. But its accuracy will be probably be lower than it is for the primary language. To improve the accuracy, do the following:

    • Build batch tests in the additional language and run them to determine how well the model performs without any utterances in the additional language. See Batch Test Intents.
    • Iteratively add training utterances in that language and test until you get a satisfactory level of intent resolution.
      1. Click Intents (This is an image of the Intent icon.) in the left navbar.
      2. Select the intent to edit.
      3. Select the tab for the language that you just added.
      4. In the Examples section, enter example utterances in the additional language.

      You probably won't need to add as many utterances in those additional target languages as you did in the primary language.

Switch from a Translation Service to Native Language Support

If you want to take advantage of Oracle Digital Assistant native language support in a skill that has been configured to use a translation service, you can create a new version or clone of that skill and enable that support.

To convert a skill to use native language support, all of the following conditions need to be met:

  • The version of the skill that you are converting must only use languages that are supported natively in the version of the platform that you are converting to. For that list, see Natively-Supported Languages.
  • Upon creation of the skill (or new version or clone), specifying the Platform Version as 20.12 (or later).

If all of those conditions aren't met, you'll need to continue using a translation service for all of the non-English languages in the skill.

To convert a skill to use Digital Assistant's native language support:

  1. Create the new version or clone, and specify the primary language for the skill.
    1. Click icon to open the side menu to open the side menu and select Development > Skills.

    2. In the tile for the skill that you want to version or clone, click icon to open the Options menu and select Version or Clone.

    3. In the Platform Version field, select version 20.12 or later.

      If it wasn't present before, a Primary Language field will appear.

    4. In the Primary Language dropdown, select the language from the Natively Supported section of the dropdown that best corresponds to the predominant language of the previous version of the skill.

      Note:

      The platform version and primary language can't be changed after you click Create.
    5. Click Create.
  2. Add any additional languages that you want to support.
  3. In your dialog flow, remove any translation components (System.DetectLanguage, System.TranslateInput, and System.TranslateOutput), the autotranslate context variable, and the component-level translate property.

Training Corpus for an Additional Language

When you add a language, here's how the various parts of the skill are handled:

  • Intents—The intent names, whatever their language, remain the same for each language. For each intent, you can add example utterances in each language. Since the model for natively-supported skills is unified, any utterances that you add for a given language can also help the model for other languages. Nevertheless, you can strengthen your model by adding utterances for each language.

    In particular, you should concentrate on adding phrases that express an intent in a languages that are not direct translations of the phrase in the primary language.

  • Entities—For entities that are based on key-value pairs (value list entities and dynamic entities), you define the values in the primary language and then, for each additional language, add values that correspond to the primary language's values.

    For prompts and messages that are defined in the entities (including prompts that are defined in composite bag entities), you reference resource bundle keys, where you provide the appropriate text in each target language.

    For other properties, such as Enumeration Range Size, the values apply for all languages.

    Note:

    The Fuzzy Match property is disabled for skills where it is not supported for all of the languages.

Language Detection in Skills with Natively-Supported Languages

In skills that use multiple natively-supported languages, the digital assistant (or standalone skill) can automatically detect the user's language at the beginning of the session. Here's how it works:

  • The language is automatically detected for digital assistants and skills that are configured with multiple natively-supported languages.
    • If there is only one (natively-supported) language in the skill or digital assistant, language detection is turned off.
    • If the digital assistant or skill uses a translation service, the translation service handles the language detection, not the skill or digital assistant.
  • The language is not automatically detected if the skill or digital assistant is accessed through a channel where the profile.languageTag or profile.locale variable has been set.
  • The language is detected in the first utterance of the conversation and not updated in the session, even if the user switches languages.
  • By default, the channel session last 7 days before it expires.

Translation Services in Skills

For skills that target languages other than English and which don't use Digital Assistant's native language support, you need to configure a translation service. You can use either Microsoft Translator or the Google Translation API.

For such skills, when a user enters a non-English request or response, the skill uses the translation service to convert this input to English. Once it’s translated, the Natural Language Processing (NLP) engine can resolve it to an intent and match the entities. The skill can then respond to the user by using the translation service to translate the labels and prompts or by referencing language-specific strings in resource bundles.

For skills that have a training corpus in a non-English language, the translation service is also used at design time. When you train such a non-English skill, it creates English versions of the example utterances and custom entity values to be used in the training model (though these translations are not shown in the skill designer).

Note:

If you intend to add a skill that is based on a translation service to a digital assistant, that digital assistant must also use a translation service.

Change in Translation Service Skills Starting with Platform Version 20.12

Starting with Platform Version 20.12 of Oracle Digital Assistant, support for working with translation services has changed:

  • When you create a new skill, skill version, clone, or skill extension using platform version 20.12 or later, you need to designate a primary language. (On platform versions 20.09 and prior, the predominate language is detected, based on your training data for the skill.)
  • The autotranslate context variable and the translate property now can be given different values for input and output. See autotranslate context variable and translate property.

Note:

If you are working with a version of a skill that is based on Platform Version 20.09 or earlier, the automatically-detected predominant language is still used.

Translation Services Supported

Google Translation API

To use the Google Translation API, you need to generate the API Key. You create this key from the GCP Console (APIs & services > Credentials). To find out more, see the Google Cloud Platform Documentation.

Microsoft Translator

If you want to use Microsoft Translator as your translation service in Oracle Digital Assistant, you need to subscribe to Translator or the Cognitive Services multi-service and get a secret key. See https://docs.microsoft.com/en-gb/azure/cognitive-services/translator/reference/v3-0-reference.

These are the main things you need to know:

  • You need to use the Global region and its corresponding URL (https://api.cognitive.microsofttranslator.com/).
  • You need to obtain a secret key for authentication. You can get it from the Keys and Endpoints section of the Azure Portal.

Register a Translation Service in Oracle Digital Assistant

  1. Click icon to open the side menu to open the side menu and select Settings > Translation Service.

  2. Click + Service.

  3. In the Translation Services dialog, enter the URL and authorization key (for the Microsoft Translator service) or authorization token (for the Google Translation API) .

    1. URL
    2. Authorization key (for the Microsoft Translator service) or authorization token (for the Google Translation API) .

Add a Translation Service to Your Skill

  1. If you haven't done so already, register a translation service in Oracle Digital Assistant.
  2. Click icon to open the side menu to open the side menu, select Development > Skills, and select your skill.
  3. In the skill's left navbar, click the Settings(an image of the left navbar's Settings icon) icon and select the General tab.
  4. Navigate to the Translation Service dropdown and select your translation service.

Predominant Language

For skills that you set up to use Platform Version 20.09 or earlier and which have been configured with a translation service, Oracle Digital Assistant automatically assigns a predominant language for that skill, based on the language of the skill's example utterances.

You can find what predominant language has been assigned for a skill by clicking the Settings(an image of the left navbar's Settings icon) icon in the skill's left navbar, selecting the General tab, and checking the value of the Predominant Language property.

For such skills, make sure that all of your intent example utterances, entities, and dialog response text are in the predominant language.

If you are designing the skill to support multiple languages, the predominant language must be English.

For digital assistants that are based on Platform Version 20.09 or earlier, the predominant language is determined by the predominant language of the first skill that you add to the digital assistant. Any other skills that you add to the digital assistant must have the same predominant language.

If the first skill that you add has no predominant language (because no translation service has been specified in the skill), the digital assistant's predominant language is set to English. In this case, you can either add skills that have English as the predominant language (or which have no predominant language set).

Note:

For skills and digital assistants that are based on Platform Version 20.12 or higher, a predominant language is not set. Instead, you specify the primary language when you create the skill or digital assistant.

Approaches Based on Translation Services

When you use a translation service to support skills that converse in non-English languages, you can use one of these development approaches:

  • Create non-English single-language skills where you:
    • Prepare the training corpus in the target language of the skill.

    When you develop non-English single-language digital assistants, you populate them with such single-language skills (where all of the skills in a given digital assistant have the same predominant language).

  • Create multi-language skills where you:
    • Prepare the training corpus in English.
    • Enhance the skill's dialog flow to manage the translation of the user input and the skill's responses.
    • Optionally (but preferably), create resource bundles for one or more languages for the skill's labels, prompts, and messages. This is desirable because it allows you to control the wording of the skill's responses.

In both cases, Digital Assistant uses the translation service to translate user input to the base language. For responses, it uses resource bundles (if provided in the skill) or the translation service to translate the skill's response back to the user's language.

Non-English Single-Language Skill Using a Translation Service

To develop a skill for a single non-English language that relies on a translation service, you:

  1. If you haven't already done so, add a translation service to your skill.

  2. Create the utterances for your skill in the target language of the skill (instead of in English):
    1. Click icon to open the side menu to open the side menu, select Development > Skills, and open your skill.
    2. In the left navigation for the skill, click This is an image of the Intent icon.
    3. Select an intent.
    4. In the Examples text field, type the utterance and press Enter.
    5. Repeat the previous two sub-steps for each intent.
  3. For any custom entities in your skill, make sure the values are in the skill's predominant language.

    You can add and edit custom entities by clicking An image of the Entities icon in the left navigation of the skill.

    If you don't provide custom entity values in the predominant language, the skill won't be able to properly process user input that contains any values that need to be matched by a custom entity.

  4. In the skill, update all of the configuration messages and prompts to use the predominant language:

    To access these messages and prompts:

    • In the left navigation for the skill, click The Settings icon in the left navbar.

    The messages and prompts are located on the Configuration and Digital Assistant tabs.

There are a couple of other things to keep in mind:
  • You can’t translate the names of the built-in entities.

  • When you set up your skill this way, the language processing framework detects non-English input and then translates it into English (the language of the training model) behind the scenes. After evaluating the input, it determines the appropriate response and translates it back to the target language.

    This can impact translation costs because it requires more calls to the translation service than a skill where the training corpus is already in the English.

Multi-Language Skills with Auto-Translation

For skills that use a translation service, you can enable a to automatically detect the user’s language and communicate in that language.

To set this up, you need to update the dialog flow to:

  • Detect the user's language.
  • Translate the user input so that it can be resolved by the System.Intent component.

You can handle translation of user input using either of the following strategies:

  • Opt-in: You individually set the translate property to true for each component that you want to have translated.
  • Opt-out: You set the autoTranslate context variable to true so that input for each component is translated by default. If there is a component for which you don't want translation, you set its translate property to false.

Note:

For both the translate property and the autoTranslate context variable, you can also distinguish between input and output. For example, you may wish to have the input translated by the translation service but leave the output untranslated by the translation service (so that you can provide the translations yourself through resource bundles).
autotranslate context variable and translate property

You can use either or both the autotranslate context variable and the component-level translate property to determine what gets translated by the translation service.

  • The autotranslate context variable applies globally to the whole skill. If you don't specify autotranslate, it's value is false.
  • The translate property can be set individually for each component. When the translate property is set for a component, it overrides the autotranslate value for that component.

For both autotranslate and translate, you can set the value as a single Boolean or you can specify separate Boolean values for input and output.

autotranslate Context Variable

Here's an example of using autotranslate, to turn on automatic translation for both input and output:

  setAutoTranslate:
    component: "System.SetVariable"
    properties:
      variable: "autoTranslate"
      value: true

And here's how you could use autotranslate to translate input by default, but not output:

  setAutoTranslate:
    component: "System.SetVariable"
    properties:
      variable: "autoTranslate"
      value:
        input: true
        output: false

Note:

You don't have to specify autotranslation values that are false. For example, in the previous snippet, you don't need to include the line:

        output: false
translate Property

Here's an example of setting the translate property to send both the component's input and output to the translation service that has been specified for the skill:

  askName:
    component: "System.Text"
    properties:   
      prompt: "${rb.askNamePrompt}"
      variable: "name"
      translate: true

And here's an example of sending on the component's input to the translation service:

  askName:
    component: "System.Text"
    properties:   
      prompt: "${rb.askNamePrompt}"
      variable: "name"
      translate:       
        input: true
        output: false
Opt-In Translation

Here are the steps if you want to individually specify which components to translate :

  1. If you haven't already done so, add a translation service to your skill.
  2. Make sure that the autoTranslate context variable is not set (or set to false).
  3. Above the state for the System.Intent component, add the System.DetectLanguage component:
      detect:
        component: "System.DetectLanguage"
        properties:
          useExistingProfileLanguageTag: true
        transitions: {}

    Note:

    The useExistingProfileLanguageTag property is used when a skill is part of a digital assistant that has a translation service. This enables the skill to use the language that is detected by the digital assistant immediately. Otherwise, the skill might provide a message or prompt in English before the language is (re-)detected. If the skill is not in a translation-enabled digital assistant, the property is ignored.
  4. In the System.Intent component, set the translate property to true.
      intent:
        component: "System.Intent"
        properties:
          variable: "iResult"
          translate: true
  5. For other input components, also set the translate property property to true, or set the input attribute of the translate property to true, e.g.:
      askName:
        component: "System.Text"
        properties:   
          prompt: "${rb.askNamePrompt}"
          variable: "name"
          translate:       
            input: true
            output: false
Example: Multi-Language Skill with Auto-Translation (Opt-In)
metadata:
  platformVersion: "1.0"
main: true
name: "AutoTranslatePizzaJoe"
parameters:
  age: 18
context:
  variables:
    size: "PizzaSize"
    type: "PizzaType"
    crust: "PizzaCrust"
    iResult: "nlpresult" 
states:
  detect:
    component: "System.DetectLanguage"
    properties:
      useExistingProfileLanguageTag: true
    transitions: {}
  intent:
    component: "System.Intent"
    properties:
      variable: "iResult" 
      translate: true
  ShowMenu:
    component: "System.CommonResponse"
    properties:
      processUserMessage: true
      translate:       
        input: true
        output: false
      metadata:
        responseItems:
          - type: "text"
            text: "Hello ${profile.firstName}, this is our menu today:"
            ...
  ...  
Opt-Out Translation

Here are the steps if you want to use auto-translation by default (and individually specify components to not translate) :

  1. If you haven't already done so, add a translation service to your skill.
  2. Add autoTranslate: "map" as a variable to the context node.
    context:
      variables:
        ...
        autoTranslate: "map"
  3. Within the states node, above your System.Intent component, add a System.SetVariable component. Then set the variable property to use the autoTranslate context variable and set the input (and, optionally, output) attribute of the value property to true.
      setAutoTranslate:
        component: "System.SetVariable"
        properties:
          variable: "autoTranslate"
          value:
            input: true
            output: true
        transitions:
        ...

    Note:

    If you are using resource bundles, you'd set the output value to false.
  4. For the next state, add the System.DetectLanguage component:
      detect:
        component: "System.DetectLanguage"
        properties:
          useExistingProfileLanguageTag: true
        transitions: {}

    Note:

    The useExistingProfileLanguageTag property is used when a skill is part of a digital assistant that has a translation service. This enables the skill to use the language that is detected by the digital assistant immediately. Otherwise, the skill might provide a message or prompt in English before the language is (re-)detected. If the skill is not in a translation-enabled digital assistant, the property is ignored.
  5. For any components that you don't want auto-translated, see the translate property to false, e.g.:
      done:
        component: "System.Output"
        properties:
          text: "${rb('OnTheWay','${size.value}','${type.value}')}"
          translate:       
            input: true
            output: false
        transitions:
          return: "done"
Example: Multi-Language Skill with Auto-Translation for Input (Opt-Out)

In this example, auto-translation is set up for input, but it is off for output (so that output text can be specified in resource bundles).

metadata:
  platformVersion: "1.0"
main: true
name: "AutoTranslatePizzaJoe"
parameters:
  age: 18
context:
  variables:
    size: "PizzaSize"
    type: "PizzaType"
    crust: "PizzaCrust"
    iResult: "nlpresult"
    autoTranslate: "map" 
states:
  setAutoTranslate:
    component: "System.SetVariable"
    properties:
      variable: "autoTranslate"
      value:
        input: true
        output: false
    transitions: {}
  detect:
    component: "System.DetectLanguage"
    properties:
      useExistingProfileLanguageTag: true
    transitions: 
    ...
 
Manipulate Input Before Translation

If you want to be able to manipulate input text before sending it to the translation service, you can use the System.TranslateInput component. For example, you might want to process user input to remove some personal data before sending it to the translation service.

In the following snippet, the sourceString variable holds the text to be translated. (This input, for example, may have been gathered by a System.Text component and processed by another component.) After the System.TranslateInput completes its processing, the English translation is stored in the translatedString variable.
context:
  variables:
    autoTranslate: "boolean" 
    translatedString: "string"
    sourceString: "string"    
   ...
states:
   ...
  translateInputString:
    component: "System.TranslateInput"
    properties:
      source: "sourceString"
      variable: "translatedString"
    transitions: {}

Resource Bundles for Skills

If your skill is designed to handle multiple languages and you want to control the wording for your skill’s responses, use resource bundles. You can provide resources bundles for as many languages and dialects as you need.

Even if your skill is targeted toward only one language, using resource bundles has benefits, such as enabling you to put all of your use-facing text in one place.

There are number of options for parameterizing resource bundle entries, which enables you to embed variables in the strings. In addition, you can use ICU formatting for bundle entries to help construct the wording of a response depending on how its parameters are resolved. This enables you to do things like adjust wording according to whether something is singular or plural.

Create a Resource Bundle Key

For each skill, you can define resource bundle keys that identify the output text that needs to be translated and then provide values for those keys in one or more languages. Keys are automatically defined for the conversation name of any intents you have created as well as for the answers for any answer intents. However, you need to create keys yourself for other output text that you want to translate, such as text from your dialog flow.

To create resource bundle entries:
  1. In the skill's left navbar, click Resource Bundle icon..

  2. Click the User-Defined tab.
  3. Click Add Bundle.

    The Create Entry dialog appears, which enables you to create your first entry in the skill's primary language.

  4. Enter the a key (which you use to reference the bundle entry) and its corresponding text. For example, for the user prompt How old are you?, you might enter HowOld in the Key field and then How old are you? in the Text field.

  5. For Annotation, enter any information that will be useful for those that may need to reference the entry later, such as translators.
  6. Click Create Entry.

Note:

Resource bundles are not the mechanism for translating value list entities. Instead, you provide the translation within the custom entity definition. For skills using natively-supported languages, you provide values for that native language. For skills based on a translation service, you provide the translated values as synonyms for the values in the default language.

Add a Language to a Resource Bundle Key

When you create a bundle key, its initial Text value is for the skill's default (i.e. primary or predominant language).

To add text for a bundle key in another language:

  1. Select the key and then click Add Language.
  2. Complete the Create Entry dialog:
    • Language—Add an IETF BCP 47 language tag like fr for French or de for German.

    • Text—The output string. For example, for a French translation (fr) of the HowOld key, you’d add a string like quel âge avez-vous ?

      Note:

      You can also use more specific locales (such as en-US), but they are not useful in most cases. For example, if you are using a translation service (via the System.DetectLanguage component) to detect the language, only a two-letter code will be returned.

      If the skill can’t match the input language with a language tag defined in the bundle, it defaults to a less-specific tag (if one is available). If none of the entries match the browser’s language, the skill uses the default entry, English. See Resource Bundle Entry Resolution for details.

Translate Conversation Name

At some points within a conversation, such as when the skill is trying to determine what flow the user wants to follow, the skill may present a dialog that refers to one more intents. In these cases, the skill refers to the intents by their conversation names, for which keys and default entries are generated in the resource bundle.

To provide a translation for a conversation name:

  1. Click Resource Bundle in the left navbar (This is an image of the left navbar Resource Bundle icon.).

  2. Click the Intents tab on the Resource Bundles page.



  3. Select the intent

  4. Click Add Language.

  5. Complete the Create Entry dialog:
    • Language—Add an IETF BCP 47 language tag like fr for French, de for German, or en-US for U.S. English.

    • Text—The output string. For example, for a French translation (fr) of the HowOld key, you’d add a string like quel âge avez-vous ?

Note:

If the intent for which you want to change the conversation name doesn't appear in the list, click This is an image of the Intent icon. to go back to the Intents page, select the intent, and edit its Conversation Name field. When you return the Resource Bundles page, it should then appear under the Intents tab.

Translate Answers for Answer Intents

When you create an answer intent, a resource bundle key is automatically created for the answer.

To provide a translation for an answer in an answer intent:

  1. Click Resource Bundle in the left navbar (This is an image of the left navbar Resource Bundle icon.).

  2. Click the Q&A tab on the Resource Bundles page.

  3. Select the key for the answer that you want to translate.

  4. Click Add Language.

  5. Complete the Create Entry dialog:
    • Language—Add an IETF BCP 47 language tag like fr for French, de for German, or en-US for U.S. English.

    • Text—The output string.

Reference Resource Bundles in the Dialog Flow

To set the output for a built-in component, you reference the resource bundle context variable and message key.

In the following OBotML snippet for a pizza skill, the resource bundle is declared as the variable, rb, in the context section. Further down, value expressions define the text property for the System.Output components reference the rb variable and the keys, WhatType and OnTheWay. The first outputs a simple string and the other uses dynamic values.
context:
  variables:
    rb: "resourcebundle"
...

pizzaType:
  component: "System.Output"
  properties:
    text: "${rb('WhatType')}" # rb refers to the variable, WhatType is the key to the message in the resource bundle.
  transitions: {}
...

done:
  component: "System.Output"
  properties:
    text: "${rb('OnTheWay','${size.value}','${type.value}')}" # size.value and type.value are the arguments for the 'OnTheWay' message key.
  transitions:
    return: "done"

You can also create bundle entries with more complex message formats to handle plurals and other cases. See the following topics to learn about the range of message formats and how to reference them in your dialog flow.

Tip:

To test your resource bundles using the tester, set your browser to another language.

Message Formats

There are several formats that you can use for your resource bundle messages to handle everything from returning static messages to assembling messages depending on multiple variables.

Simple Messages

For simple static messages:

  • As the value for the bundle key, provide plain text. For example: This is the value of my bundle key
  • From the dialog flow or the configuration property, reference the bundle key in the form: {rb.bundleKey} or {rb('bundleKey')}
Example: Simple Message

Here's an example without any parameters.

  • Resource Bundle Key: pizzaOnTheWay
  • Resource Bundle Message: Your pizza is on the way.
  • Expression for Referencing the Resource Bundle Key: ${rb('pizzaOnTheWay')} (or ${rb.pizzaOnTheWay})
Messages with Parameters

For messages with variables:

  • As the value for the bundle key, provide text and include parameters in one of the following formats:
    • Named parameters in the form {parameterName}
    • Sequentially-numbered parameters starting with {0}
  • From the dialog flow or the configuration property, reference the bundle key in the form:
    {rb('bundleKey','variable1','variable2',...)}
Example: Message with Named Parameters

Here's an example with two named parameters:

  • Resource Bundle Key: pizzaOnTheWayWithNamedParams
  • Resource Bundle Message (in English):
    Your {pizzaSizeParam} {pizzaTypeParam} pizza is on the way.
    (where {pizzaSizeParam} and {pizzaTypeParam} are parameters for values to be resolved and inserted during the conversation)
  • Expression for Referencing Resource Bundle Key:
    ${rb('pizzaOnTheWayWithNamedParams','pizzaSizeParam,pizzaTypeParam',pizzaSize.value,
          pizzaType.value)}
    (where pizzaSize and pizzaType are variables defined in the dialog flow)
Example: Message with Numbered Parameters

Here's an example using numbered parameters:

  • Resource Bundle Key: pizzaOnTheWayWithNumberedParams
  • Resource Bundle Message:
    Your {0} {1} pizza is on the way.
    (where {0} and {1} are parameters for values to be resolved and inserted during the conversation)
  • Expression for Referencing the Resource Bundle Key:
    ${rb('pizzaOnTheWayWithNumberedParams','pizzaSize.value', 'pizzaType.value')}
    (where pizzaSize and pizzaType are variables defined in the dialog flow)
Complex Messages

You can also create complex messages, where the value of one or more variables may affect the surrounding output text. For example, if the response includes a variable for the number of pizzas ordered, you can use a complex message to determine whether to use the singular ("pizza") or plural ("pizzas").

Tip:

When you compose complex bundle entries, you can use this tester to make sure that the entries resolve as you intend:https://format-message.github.io/icu-message-format-for-translators/editor.html.
Messages that Handle Both Singular and Plural

For messages that include a variable that expresses a quantity of something, you may need to vary the wording of the assembled message depending on how the variable resolves. And for some languages, you may need to account for more than a simple singular/plural distinction. To handle messages with variables for quantity, you can use a plural argument in the key's value to specify the different ways the message may need to be constructed.

In a plural argument, part of the message is determined by a numeric value along with grammar rules for the specified language. You define the message text for different cases, depending on how the plural argument resolves. There are several predefined cases, such as one, two, few, many, and other. You can also specify a case for a specific number by pre-pending = to that number (e.g., =3). Not all of the predefined cases are relevant for every language. For example, for English you might just use =0, =1, and other.

You must always include a case and a message for other. To include the resolved number in the message text for a case, use # to output the number.

When you use plural arguments, the format typically looks something like this:

{plural_arg_name, plural,
=0 {Text used when the plural argument resolves to 0}
=1 {Text used when the plural argument resolves to 1}
other {Text used when the plural argument resolves to a value that doesn't match the other cases (in this case 0 or 1)}
}

In the above example 0, 1, and other are the possible quantities. More details on how plural argument types work can be found in the Unicode Locale Data Markup specification.

For details on the plural support for various languages, see the unicode.org plural language rules.

Other Complex Messages

If the content of the message needs to based on other conditions, you can use a select argument with keywords that you define to assemble the message.

{select_arg_name, select,
keyword1 {Text used when the select argument resolves to keyword1}
keyword2 {Text used when the select argument resolves to keyword2}
other {Text used when the plural argument resolves to a value that doesn't match the other keywords}
}

You can also nest plural and select arguments:

{select_arg_name, select,
keyword1 {
{plural_arg_name, plural,
=0{Text used when the select argument resolves to keyword1 and the plural argument resolves to 0.}
=1 {Text used when the select argument resolves to keyword1 and the plural argument resolves to 1}
other {Text used when the select argument resolves to keyword1 and the plural argument resolves to a value that doesn't match the other cases (in this case 0 or 1)}}}
keyword2 {
{plural_arg_name, plural,
=0 {Text used when the select argument resolves to keyword2 and the plural argument resolves to 0.}
=1 {Text used when the select argument resolves to keyword2 and the plural argument resolves to 1}
other {Text used when the select argument resolves to keyword2 and the plural argument resolves to a value that doesn't match the other cases (in this case 0 or 1)}}}
other {
{plural_arg_name, plural,
=0 {Text used when the select argument resolves to other and the plural argument resolves to 0.}
=1 {Text used when the select argument resolves to other and the plural argument resolves to 1}
other {Text used when the select argument resolves to other and the plural argument resolves to a value that doesn't match the other cases (in this case 0 or 1)}}}
}

Note:

For the keyword names, you should only use ASCII alphabet characters (A-Z,a-z).

You can find more details on complex messages in the ICU User Guide.

Referencing Complex Messages

You can reference complex messages in one of the following two ways:

  • Using a map variable where values for each of the parameters are assembled:
    ${rb('bundleKey', formatMap.value)}
  • Including a list argument with the parameter names followed by arguments for each value:
    ${rb('bundleKey', 'param1, param2, param3', paramValue1, paramValue2, paramValue3)}

    Note:

    Where the parameter values are strings, they should be enclosed in single quotes (').

For further details, see the Complex Argument Types topic in the ICU documentation.

Maps for Complex Resource Bundle Values

If you decide to use map variable to assemble the parameters for a complex messages, here's what you do:

  1. Declare a map context variable.
    context:
      variables:
        formatMap: "map"
  2. Use a System.SetVariable component to populate the value of the map from other variables.
    
      populateMap:
        component: "System.SetVariable"
        properties:
          variable: "formatMap"
          value:
            pizzaSize: "${pizzaSize.value}"
            pizzaType: "${pizzaType.value}"
            count: "${pizzaNum.value}"
  3. In the expression where you reference the bundle key, include the map as an argument. For example:
    
      plural:
        component: "System.Output"
        properties:
          # use map variable to resolve
          text: "${rb('pizzaOnTheWaySingularOrPlural', formatMap.value)}"
Example: Message that Handles Both Singular and Plural Variants

Here's an example of a resource bundle entry for a message that could have either singular or plural content:

  • Resource Bundle Key: pizzaOnTheWaySingularOrPlural
  • Resource Bundle Message (in English):
    {count, plural,
    =0 {No pizzas will be delivered.}
    =1 {Your {pizzaSizeParam} {pizzaTypeParam} pizza is on the way.}
    other {# pizzas are on the way.}
    }
  • Expression for Reference to Resource Bundle Key:
    ${rb('pizzaOnTheWaySingularOrPlural','count, pizzaSizeParam, pizzaTypeParam', 'pizzaNum.value, pizzaSize.value, pizzaType.value')}
    As you can see, the expression contains two arguments:
    • A list of parameter names (count, pizzaSizeParam, pizzaTypeParam)
    • A list of values for those parameters (pizzaNum.value, pizzaSize.value, pizzaType.value)
Example: Message with Nested Parameters
{ gender, select,
female
{{count, plural,
=0 {She has not ordered anything.}
=1 {She has ordered only one.}
other {She has ordered #.}}}
male
{{count, plural,
=0 {He has not ordered anything.}
=1 {He has ordered only one.}
other {He has ordered #.}}}
other
{{count, plural,
=0 {They have not ordered anything.}
=1 {They have ordered only one.}
other {They have ordered #.}}}}
Here are the variations of how that message may be resolved:
  • She has not ordered anything.
  • She has ordered only one.
  • She has ordered 2.
  • He has not ordered anything.
  • He has ordered only one.
  • He has ordered 2.
  • They have not ordered anything.
  • They have ordered only one.
  • They have ordered 2.

Note:

2 is given in the above example as the number resolved by the count argument, but it could be any number other than 0 or 1.

Resource Bundles and Auto-Translation of Skills

Here are the general steps for setting up a skill to use a translation service only for user input while using resource bundles for the skill's responses:

  1. If you haven't already done so, add a translation service to your skill.
  2. Use the System.DetectLanguage component to determine the language of the user's input.
  3. Apply resource bundles to handle the skill's responses to the user.
  4. For any components that reference resource bundles, make sure that the output is not translated automatically. You can handle this globally in the skill by setting the autoTranslate context variable to translate input and not translate output. For example:
      setAutoTranslate:
        component: "System.SetVariable"   
        properties:
          variable: "autoTranslate"     
          value:
           input: true
           output: false

    Note:

    You can also handle this at the component level by using each component's translate property and not setting the autoTranslate variable. For example, to set up automatic translation for a System.Text component's input and disable automatic translation for its output, you might do something like this:
      askName:
        component: "System.Text"
        properties:   
          prompt: "${rb.askNamePrompt}"
          variable: "name"
          translate:       
            input: true
            output: false

If your skill uses resource bundles for some components but relies on auto-translation for other components, you can:

  • Set the autoTranslate context variable to true.
  • Like in the above code sample, set the translate:input property to false for each component that uses a resource bundle.
Conditional Auto-Translation

If you have defined resource bundles for some languages but also want to be able to provide responses for languages for which you don't have resource bundle entries, you can use FreeMarker expressions to determine how autotranslate and translate resolve. For example, if only English and Dutch resource bundles are defined, you could conditionally enable output translation for the other languages like this:

  detectLanguage:
    component: "System.DetectLanguage"
    properties: {}    
 
  setAutoTranslate:
    component: "System.SetVariable"   
    properties:
      variable: "autoTranslate"
      value:  
        input: true
        output: "${profile.languageTag!='en'&& profile.languageTag!='nl'}"

Resource Bundle Entry Resolution

The resource bundle that gets applied depends on the value stored for the two location-specific user context variables, profile.languageTag and profile.locale. If both variables are set, profile.languageTag takes precedence.

profile.languageTag is set to the language of the user's input by the System.DetectLanguage component, if you have that component in your dialog flow. The value of profile.languageTag takes the form of a two-character language code (e.g. en for English).

profile.locale is set by the messenging client. The value of profile.locale can take the form of language-country-variant (e.g. en-AU-sydney), language-country (e.g. en-AU), or language (e.g. en).

When resolving which language to use, Oracle Digital Assistant first searches for an exact match. If it doesn't find one, it incrementally broadens its search until it succeeds. If it still can't find a match, it returns the default language, which is English (en).

For example, if the value of ${profile.locale} is en-AU-sydney (and profile.languageTag isn't set), Oracle Digital Assistant does the following to find the best language match:
  1. Searches the bundle by the language-country-variant criteria (en-AU-sydney).

  2. If it can’t find that, it searches the bundle by language and country (en-AU).

  3. Failing that, it broadens its search for language (en).

Export and Import Resource Bundles

You can export and import resource bundles in the form of a CSV file, which enables you to work with the bundles offline.

The CSV file needs to have the following columns:

  • languageTag
  • key
  • message
  • annotation

To export a CSV file with the existing resource bundle:

  • On the Resource Bundle page for your skill or digital assistant, click Export Resource Bundle icon to export a CSV file with the existing resource bundle.

    Even if you haven't yet added any keys to the resource bundle, a file with the required format of the CSV will be exported.

To import a resource bundle file:

  • On the Resource Bundle page for your skill or digital assistant, click Import Resource Bundle icon .

How Do I Translate Custom Component Responses?

There are three methods for returning translated content from your custom components:
  1. Store a data object sent from a custom component in a context variable. You can then reference this variable in the built-in user interface components like System.Output, System.Text, or System.CommonResponse.
  2. Save string messages in a context variable, and then pass the name of the context variable as an input parameter to system components like System.Output, System.List, System.CommonResponse, or System.TranslateOutput.
  3. Translate the custom component output in the component itself and then directly write the response to the messenger client (thus avoiding the system components altogether).

Option 1: Storing Data in a Context Variable

Custom components that query backend services might return data in a complex format like an object or an array of objects. If this data requires translation:
  1. Save the data in a context variable in your dialog flow.

    To write data from a data object to a context variable, add the following code to your custom component:
    conversation.variable('dialogVar', dataObject);
    conversation.transition();
    done();
    
    For this particular line of code to work, you need to add a corresponding context variable to your dialog flow definition named dialogVar that’s a string type :
    dialogVar: "string"

    Tip:

    As a best practice, pass the name of the context variable that the custom component should write to as a input parameter to the custom component. This way, you ensure that the context parameter really exists when accessing it.
  2. Include the translate: true property in an output component definition, or use the System.TranslateOutput component to translate it to the user’s language.

    The system components can’t translate a data object as a whole, so if you need to translate data objects stored in a context variable, then you need to reference the context variable along with the name of the data object attribute that’s displayed to user and gets translated by an output component. In the following example, the context variable is dialogVar. The data object that’s passed from the custom component to this context variable is {product: "an apple", type: "fruit", origin: "Spain" }. To display and translate this object, you’d reference it a System.Output component and enable its translation:
    printProduct:
      component: "System.Output"
      properties:
        text: "The product in your cart is a ${dialogVar.value.type}. It is
               ${dialogVar.value.product} from ${dialogVar.value.origin}"
        translate: true
    
    If a translation service is enabled for the skill, then this message gets translated to the user’s language. The custom component also passes the translated content of the data object.

Option 2: Saving Messages in a Context Variable

In this approach, you can pass the name of the context variable that holds the component response as an input parameter to the custom component. This ensures that custom components are not dependent on a specific OBotML implementation code and remain reusable.

The following OBotML sample references a custom component in the initializeReceipt state and passes the name of the context variable (receipt) that holds the component response and purchaseId as input parameters.
initializeReceipt:
  component: "sample.receipt.dataresponse"
  properties:
    dataVariable: "receipt"
    purchaseid: "${purchaseId.value}

printReceipt:
  component: "System.Output"
  properties:
    text:"${receipt.value}"
    translate: true
 ...
The custom code for accessing these input parameters is as follows:
...
invoke: (conversation, done) => {
  var responseVariable = conversation.properties().dataVariable;
  var purchaseId = conversation.properties().purchaseId;
  ...
  var message = queryRemoteServiceForReceipt(purchaseId);
  ...
  conversation.variable(responseVariable, message);
  conversation.transition(); 
  done();
}
To display messages in the detected user language, you can either use the System.TranslateOutput component or set the translate property on an output component like System.CommonResponse or System.Output, as shown in the printReceipt state:If a custom component returns a message that’s not in English and therefore requires processing by the Natural Language Processing (NLP) engine, then you’d position the System.TranslateInput component before the System.Intent in the dialog flow. This allows the System.Intent component to process the English version of the message.
translateMessage:
  component: "System.TranslateInput"
  properties:
    source: "variable_populated_by_custom_component"
    variable: "translationStringVar"
getIntent:
  component: "System.Intent"
  properties:
    variable: "iResult"
    sourceVariable: "translationStringVar"
...

Option 3: Sending Responses Directly to the User

In some cases, custom components can be self-contained: they don’t send a message directly to a message channel or save data to a context variable. These custom components return responses directly to the user because they use the conversation.reply helper method.

Note:

Responses that are directly sent to a user can’t be translated by a translation service. In this case, you'd need to code the translations into the custom component
There are two ways to translate the skill responses that are sent directly from a custom component:
  • Let the component’s output be translated by the translation service (which can be enabled by setting the skill's autotranslate context variable to true or by defining the translate property on the component and setting it to true). Use this approach when the message does not originate from the custom component, but is queried from a remote backend.
  • Use message bundles to provide translated responses for the languages you that want the skill to support. Message bundles can use placeholders in the translated strings in which the custom component inserts the data value at runtime. Message bundles in custom components are a viable option if the custom component queries data from a remote service.
    To detect the preferred language in the custom component, you can either pass the locale as an input parameter to the component or access the profile.locale and profile.languageTag variables as shown in the following example:
    //detect user locale. If not set, define a default
    var locale = conversation.variable('profile.locale')?
                 conversation.variable('profile.locale') : 'en';
    //when profile languageTag is set, use it. If not, use profile.locale
    var languageTag = conversation.variable('profile.langageTag')?
                      conversation.variable('profile.langageTag') : locale;