Work with Translations

You can use the Property Inspector to bind text strings to values that are stored as keys and values in JSON files. You can open and edit the translation JSON files in the code editor, and download and upload the files as application resources.

About Translation Resources

The keys and values for translating your application are stored as JSON files in translation bundles in your application.

The names and locations of your translation bundles are up to you, but you must understand the rules governing the file names and the structure of your bundle to ensure that the bundles are recognized when you run your application.

By default, web and mobile apps will contain a default app-level bundle with the name app located in the resources/strings folder of the app. The relative path to the default translations bundle is stored in app-flow.json. The path identifies the top-level JSON file in the bundle that identifies the translation locales included in the bundle. If you open the application artifact in the code editor you can see the entry for the path to the translation bundle.

    "translations": {
        "app": {
            "path": "./resources/strings/app/nls/app-strings"
        }
    },

The suggested location for a bundle is resource/strings/<bundle-name>/nls/<bundle-name>-strings.json, where <bundle-name> is the name for the bundle you create. Bundles can be located where you choose, however the paths to the bundles must be specified in app-flow.json. For example, if you created a resource folder containing a bundle for the flow MyFlow, the path in app-flow.json might be similar to ./MyWebApp/flows/MyFlow/resources/strings/MyFlow/nls/MyFlow. You would use the period ( . ) at the beginning of the path to make it relative to the file.

When using translations in code, you can replace code that produces or uses an untranslated string with code that uses the translations object to retrieve the translated string from the bundle. For more on the translations object, see Translations.

Understand the Structure of Translation Bundles

You will want to understand the structure of translation bundles if you want to create additional translation bundles in your application.

The following guidelines describe the structure for the application’s default translation bundle:

  • The bundle contains a root folder named nls.

  • The nls folder should contain a JSON file identifying the translation locales contained in the bundle.

  • All bundle files should be JSON files with –strings.json appended to the bundle name. (For example, the JSON files for the MyNewPage bundle will be named MyNewPage-strings.json.)

The path to the root JSON file in each bundle in your application must be specified in app-flow.json.

Description of translations-resources.png follows
Description of the illustration translations-resources.png

Your bundle contains a JSON file at the root level of the nls folder that identifies the supported languages, and one or more folders within the nls folder containing JSON files storing the keys and values of translation strings. By default, the nls folder contains a folder named root that contains the root translation file app-strings.json.

When no additional locales are specified, the root level app-strings.json file only contains "root": true. If one additional locale is supported, for example, a French locale and translations, the root level JSON file would contain the following locale identifiers:

{
  "root": true,
  "fr": true
}

For each locale, the nls folder should contain a corresponding folder containing a JSON translation file with the translation strings for that locale. The default name for the JSON file in the root folder is <bundle-name>-strings.json. If a French locale is added, the nls folder would also contain a folder named fr containing a JSON file <bundle-name>-strings.json. Each translation file contains key/value objects and object metadata. For each object you can include descriptive metadata, including unique id identifiers for the element details and details about the object’s context that can be useful for translators.

Understand Translation Keys for Display Texts

To translate your application into other languages, you need to create translation bundles that store keys and values for the texts in your application’s UI.

When you save a string using the Translatable String popup in the Property Inspector, the value for the string is externalized to the translation bundle, and the value of the string is bound to the key in the translation file in that bundle. If you open the page in the Code view you can see the name of the translation bundle and the key bound to the string value. For example, an input label in the Code view code might be similar to <oj-input-text label-hint="Name" id="oj-input-text--452490439-1" value="{{ $page.variables.authors.name }}"></oj-input-text>.

When you externalize the string, the value of the string is replaced with a string similar to the following that binds it to a key in the translation file:

[[ $application.translations.app.input_text_label_hint_daea ]]

The expression identifies the scope and name of the translation bundle, and the translation key, using the following syntax: <scope>.translations.<bundle-name>.<key>.

You can also include parameters in the expression by using the syntax <scope>.translations.format('<bundle>', '<key>', {params}). For example, if you use the expression [[ $application.translations.format('app', 'bind_text_value_372d', { region: $page.variables.Country.region }) ]] in the UI component, the key-value pair defined in the bundle might be "bind_text_value_372d": "(This country is in {region})". In this case, the string “This country is in “ would be translated, and region would be the value of the page variable.

When you open the translation file in the editor, the file contains a key and value pair similar to the following:

"input_text_label_hint_daea": "Name",
    "@input_text_label_hint_daea": {
        "description": ""
    }

By default, each key-value pair in the translation file contains a description field as part of the metadata for the pair that can be used to provide a description of the value, for example, to provide additional context for the string that can be useful when translating the string. You can modify the file in the editor to add description metadata and other metadata for each key-value pair.

Tip:

You can use the Code view to locate strings in a page that have not been externalized for translation and add the string to the translation bundle. You can use the Audits window to locate all the strings in the application that have not been externalized.
Description of page-designer-code-translate.png follows
Description of the illustration page-designer-code-translate.png

Generate Translation Keys for Display Texts

For static strings in the UI of your application, you can use the Property Inspector to add keys and values for the strings to a bundle for translation.

You can use the Property Inspector to generate and add keys for UI components to a translation bundle. When you use the Property Inspector to define the translatable string, a key is generated automatically, but you can specify your own key in the dialog box. You can also edit the keys, values and metadata in translation files directly using a text editor.

To generate a key for a string using the Property Inspector:

  1. Select the component on the canvas that you want to be translatable.
    You can select components that use a static string in their text fields, for example, a Button component. You cannot create translations for elements where the display label or text is the result of an expression or variable.
  2. Click the globe icon for the text field to open the Translatable String popup.
  3. Confirm or edit the string to be translated. Click Save.

    The Translatable String popup contains a Text field for the string to be translated. The popup also contains a Description field that you can use to provide a description of the context for the string. The description text is included as metadata in the translation bundle.

Download Bundles for Translation

You can download translation files to your local system from the Translations tab in the Settings editor when you want to translate the application’s strings with your preferred translation tool or service.

When you download the translation bundles of your visual application, the archive that you download contains the translation files for all of the applications in your visual application. The archive contains a folder for each translation bundle in your application, and each folder contains a file in the .arb format with the strings to be translated. The file also contains metadata defining the bundle name and path that is used when uploading the file after the strings have been translated. The metadata in the file might be similar to the following:

  "@@x-bundleName" : "app",
  "@@x-bundlePath" : "webApps/mycontacts/resources/strings/app/nls/app-strings",

When downloading the bundle, you can choose to download an archive containing all strings that are stored in the translation bundle or an archive containing only those strings in the translation bundle that were added or updated since the last time you downloaded the translation bundle. The first time that you download the translation bundle you can only choose to download an archive containing all strings.

To download a translation resource bundle:

  1. Open your web or mobile application and choose Settings in the application’s Options menu in the toolbar.

    Description of toolbar-settings-menu.png follows
    Description of the illustration toolbar-settings-menu.png

    Alternatively, on the Visual Builder home page, locate the application and choose Settings in the application’s Options menu.

  2. Open the Translations tab in the Settings editor.
  3. Click the link for the archive that you want to download to your local system.

Use Translation Strings in JavaScript Files

You can use translation strings in JavaScript files and retrieve the translated text from the bundle when the function is called.

When you use a text string in a JavaScript function, the text string can be externalized to a translation bundle. You can replace the code that produces or uses the untranslated string with code that uses the translations object to retrieve the translated string from the bundle. When you edit the JavaScript function you will need to either hard code the translation key in the code or pass the key into the function as a parameter. To use the translations object in the function, you need to pass the object into the function as a function parameter.

For example, you might have a UI component in your page that displays a text string that comes from a JavaScript function that is called by a callModuleFunction action in an action chain. In the action chain, you can pass the translations object (for example, $application.translations) to the function and then assign the result to a variable bound to the UI component that displays the string.

To display a translated string used in a JavaScript function:

  1. Create a key for the string that you want translated and add the key and string to the translation bundle.

    You can use the Make String Translatable button in the Property Inspector to create the key in the bundle and generate the expression for the key. Alternatively, you can edit the translation file in the editor to create the key in the bundle and enter the expression for the translation string in the UI component’s Text field in the Property Inspector.

  2. Copy the expression containing the bundle name and key. The expression is displayed in the Text field of the component after the string is externalized.

    The expression might look similar to [[ $application.translations.app.h1__text_041a ]]. In this example, app specifies the bundle name, and h1__text_041a is the key. The bundle and key are used to evaluate the translated string. $application.translations specifies that the application-scoped translations object is used. The translations object might also be $flow or $page scoped, depending on where the bundle is located.

  3. Modify the JavaScript function so that the translations object $application.translations can be passed to the function from the action chain.

    In the following example, the action for calling the function will use translations to pass the object to the function.

      PageModule.prototype.getMessageFromBundle = function(translations) {
        ...
      };
  4. Edit the function to replace the untranslated text that should be displayed in the component with code that retrieves the translated text using the translations object. When the object is available in the function, the bundle name and key are used to retrieve the translated string from the bundle. 

    For example, the function can return a simple translated string:

      PageModule.prototype.getMessageFromBundle = function(translations) {
        ...
        return translations.app.h1__text_041a;
      };

    You can also include parameters to generate a formatted message: translations.format('app', 'h1__text_041a', param1, param2)

  5. Create an action chain that calls the function (callModuleFunctionAction) and assigns the result (assignVariablesAction) to a variable (in this example, Value).

    In this example you can see that the translations object is a parameter of the callModuleFunction action that is passed to the function, and that assignVariables assigns the result of callModuleFunction to the page variable Value.

          "root": "callModuleFunction1",
          "actions": {
            "callModuleFunction1": {
              "module": "vb/action/builtin/callModuleFunctionAction",
              "parameters": {
                "module": "{{$page.functions}}",
                "functionName": "getMessageFromBundle",
                "params": [
                  "{{ $application.translations }}"
                ]
              },
              "outcomes": {
                "success": "assignVariables1"
              }
            },
            "assignVariables1": {
              "module": "vb/action/builtin/assignVariablesAction",
              "parameters": {
                "$page.variables.Value": {
                  "source": "{{ $chain.results.callModuleFunction1 }}"
                }
              }
            }
          }
  6. Edit the Text field of the UI component to replace the generated expression with the page variable storing the result of the method. (Value).


    Description of page-designer-translations-labelexample.png follows
    Description of the illustration page-designer-translations-labelexample.png

    Tip:

    Use the Text field’s Select Variable menu to select the correct page variable

Upload Translated Files

You can upload the resource files containing translated strings in the Translations tab in the Settings editor.

To upload translated file you need to create a ZIP archive containing the ARB files with the translated strings. Before you create the archive, however, you need to modify the file names of the ARB files to append the locale abbreviation to identify the correct locale. For example, to upload an ARB file that contains translations for the French locale, you will modify the file name to <bundle—name>-strings-fr.arb.

To upload an archive with translation files:

  1. Open your web or mobile application and choose Settings in the application’s Options menu in the toolbar.

    Description of toolbar-settings-menu.png follows
    Description of the illustration toolbar-settings-menu.png

    Alternatively, on the Visual Builder home page, locate the application and choose Settings in the application’s Options menu.

  2. Open the Translations tab in the visual application's Settings editor.
  3. Locate the archive containing the translated files on your local system and drag it into the upload area in the Translations tab. Click Close.
If you added a file with translations for a new locale, a folder for the new locale is created in the bundle. The new locale is also automatically added to the file defining the locales in the bundle.

Create Translation Bundles

You can use the Translation tab in the Settings editor to create additional translation bundles for application artifacts, flows and pages.

By default, each web or mobile app contains a translation bundle app in the app’s top-level resources folder. You can create additional translation bundles for the app in the app artifact’s Settings editor. You can also create bundles for individual flows and pages in the Settings editor for the flow or page when you want the translations to be flow-scoped or page-scoped.

When you create a new bundle in the Translations tab of the Settings editor, the metadata for the new bundle is automatically added to the JSON file of the app, flow or page. For example, if you create a translation bundle for a page in the page’s Settings editor, a resources folder containing the new bundle is created at the page level and the page’s JSON file is updated with the metadata for the bundle.


Description of translations-bundle-page.png follows
Description of the illustration translations-bundle-page.png

When you externalize a text for translation, the string and key are added to the nearest available bundle by default. For example, if you create a translation bundle for a page, the strings and keys are added to the page’s bundle when you externalize strings in the page. Strings in other pages are not added to that bundle when they are externalized.

To create a translation bundle:

  1. Open the Translations tab in the Settings editor of an application, flow or page artifact.

    The Translation Bundles tab displays a list of the bundles scoped for the selected artifact and the path to the bundle.


    Description of settings-editor-translations.png follows
    Description of the illustration settings-editor-translations.png
  2. Click +Bundle to open the New Translation Bundle dialog box.
  3. Supply the bundle name in the dialog box. Click Create.
When you click Create, the new translation bundle containing the translation files and folders is created in the strings folder in the resources folder of the artifact. The strings and resources folders are created if they do not exist for the artifact. The path to the new bundle is displayed in the Translations tab. The path is relative to the artifact’s JSON file.