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 a 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.

Types of Resource Bundle Keys

A skill's user-facing strings come from several parts of the skill. In some cases, a resource bundle key is automatically created for you. In other cases, no key is generated, but you can define one yourself.

Here are the places from where user-facing strings originate and how you can manage them in the resource bundle.

  • The Conversation Name field for intents.

    When you set conversation names, resource bundle keys are created automatically and populated with the value that you have set for the default language. You can access the bundle keys for conversation names by clicking Resource Bundle icon and selecting the Intents tab.

  • The Answer field for intents (answer intents).

    When you set answers in intents, resource bundle keys are created automatically and populated with the answer text in the default language. You can access the bundle keys for answers by clicking Resource Bundle icon and selecting the Q&A tab.

  • The skill's configuration settings (which you access by clicking the Settings icon and selecting the Configuration tab).

    For these settings, resource bundle keys are generated with default values and the setting values are expressed as references to the resource bundle keys. You can edit the values of these keys by clicking Resource Bundle icon and selecting the Configuration tab.

  • Default prompts, labels, and messages that are built into standard dialog flow components.

    If you want to change the default value of any of these properties, you can do so within the resource bundle by clicking Resource Bundle icon and selecting the Configuration tab.

    You don't need to add the property to the component in the dialog flow definition to reference the updated value in the resource bundle.

    If you want to change the value of one of those properties for a component in a particular state without changing the default, you add the property to the component in that state.

  • Dialog flow strings. For text that you incorporate into your components, you can define your own resource bundle keys and then reference those keys from the dialog flow definition.

    You can create and edit these keys by clicking Resource Bundle icon and selecting the User-Defined tab.

  • Prompts and messages from entity definitions. For these strings, you can define your own resource bundle keys and then reference those keys from the fields for these properties in the entity definition.

    You can create and edit keys for these strings by clicking Resource Bundle icon and selecting the User-Defined tab.

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.

Create Resource Bundle Keys

Resource bundle keys are used to identify output text that needs to be translated and provide values in one or more languages. Keys are automatically defined for the intent conversation names, the responses for answer intents, and some common properties. 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.

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—Enter or select 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 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 message key through the variable rb (which is reserved for resource bundles).

Here is a simple expression that references a bundle key called WhatType to return a simple string:

${rb('WhatType')}

Here is an expression that uses dynamic values. It references a bundle key called OnTheWay where size.value and type.value are the arguments for the OnTheWay key.


${rb('OnTheWay','${size.value}','${type.value}')}

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 at https://unicode-org.github.io/icu/userguide/format_parse/messages/#complex-argument-types.

Referencing Complex Messages

You can reference complex resource bundle 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. Define a variable of type map and give it a value in valid JSON format. For example, the value for a pizza bundle entry might look something like:
    {
        "pizzaSize": "${pizzaSize.value}",
        "pizzaType:": "${pizzaType.value}",
        "count": "${pizzaNum.value}"
    }

    Note:

    In YAML-based dialog flows, you first declare the variable within the context node and then use a System.SetVariable component to set it's value with syntax like the following:
    
      populateMap:
        component: "System.SetVariable"
        properties:
          variable: "formatMap"
          value:
            pizzaSize: "${pizzaSize.value}"
            pizzaType: "${pizzaType.value}"
            count: "${pizzaNum.value}"
  2. In the expression where you reference the bundle key, include the map as an argument. For example:
    ${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 Detect Language 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.
    • For skills developed in Visual dialog mode, set the Translate Bot Response Message property on the skill's Settings page to False.
    • For skills developed in YAML dialog mode, 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:

For skills developed in YAML mode, 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 the Translate User Input Message and Translate Bot Response Message settings (for Visual Flow Designer skills) and autotranslate and translate properties (for YAML-based skills) resolve.

For example, if only English and Dutch resource bundles are defined, you could conditionally enable output translation for the other languages. Here's what that expression might look like:

${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 profile variables, profile.languageTag and profile.locale. If both variables are set, profile.languageTag takes precedence.

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).

    Note:

    profile.locale supports values in ISO language-country or ISO language_country formats.

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 .