Text Translation and Localization

Extensions have two main ways to support multiple languages: Tecton Localization and UI Text. Tecton Server and Client-side rendered extensions have built-in support for Tecton Localization through the use of language files and Tecton’s localization helpers. UI Text is a database-driven approach that can be used in any extension type, but primarily for non-Tecton extensions and when text translation and localization are needed server-side. Using Text Translation and Localization ensures that not only can your extension support multiple languages, but that text customization can be done without needing to modify code or redeploy the extension.

Tecton Localization

Tecton Server and Client-side rendered extensions have built-in localization support. When extensions are created using the q2 create extension command, a languages directory is created in the frontend/public/assets directory. This directory contains JSON files for common languages supported in the Q2 Online Banking platform.

  • en-US.json - English (US) [Default]

  • es-MX.json - Spanish (Mexico)

  • zh-CN.json - Chinese (Simplified, China)

  • zh-HK.json - Chinese (Traditional, Hong Kong)

  • zh-TW.json - Chinese (Traditional, Taiwan)

  • pt-BR.json - Portuguese (Brazil)

Each language file contains key-value pairs where the key is a unique identifier for the text and the value is the translated text in that language.

// en-US.json
{
    "_t.next": "Next",
    "_t.back": "Back",
    "_t.cancel": "Cancel",
    "_t.submit": "Submit",
}

// es-MX.json
{
    "_t.next": "Siguiente",
    "_t.back": "Regresar",
    "_t.cancel": "Cancelar",
    "_t.submit": "Enviar",
}

At a minimum, we recommend providing translations for your extensions into the provided default English (US) language file. You may provide your own translations for your extensions into all provided language files, or values can be dynamically added for your localization keys using the Q2 Config application’s string editing feature. This feature allows administrators to modify the text associated with localization keys without needing to change the code or redeploy the extension.

To use localized text in your front-end, Tecton provides a localization capability as well as a localization web component.

tecton.sources.loc('_t.next');
<q2-loc value="_t.next"></q2-loc>

On connection of your extension to the platform, a language file is automatically selected based on the user’s language preference in the platform. Any time a language is changed in session, the appropriate language file is loaded. The localization capability and web component automatically will load the appropriate strings from the language file in use.

UI Text

UI Text works by splitting verbiage into a text element and a text value. The text element describes the verbiage, and the text value is the actual text. There is a one-to-many relationship between the element and value, which allows for multiple languages to be supported.

DB Plan

You can populate your verbiage in the database by using the ui_text_elements install step. Below is an example db_plan.py file that shows how to utilize the install step. This db_plan.py file will be run at the time of form install. You can also run this file with the q2 run_db_plan command.

from q2_sdk.core.install_steps import db_plan


class DbPlan(db_plan.DbPlan):
    def __init__(self):
        """
        It is often necessary to configure the database with information
        for an extension to run appropriately. This is your home to do so.

        Each of these attributes corresponds to a table (or set of tables) in the
        database. Instead of forcing all Antilles users to learn the
        database structure of Q2, we've opted for this handy abstraction.
        """

        super().__init__()
        self.ui_text_prefix = 'MyExtension'  # Will be used for all self.ui_text_elements

        # self.send_account_list = True  # Populate self.account_list when HQ calls the extension
        # self.send_account_details = True  # Populate HADE data on accounts in self.account_list
        # self.wedge_payload_stored_proc = None  # Run a given Stored Procedure to manipulate the call shape from HQ
        # self.insight_features = []  # Run a list of Insight API Features as part of the install (Custom stored procedures)
        # self.api_stored_procs = [db_plan.ApiStoredProc()]
        # self.audit_actions = [db_plan.AuditAction()]
        # self.disclaimers = [db_plan.Disclaimer()]
        # self.gt_data_elements = [db_plan.GTDataElement()]
        # self.report_info = [db_plan.ReportInfo()]
        # self.required_forms = [db_plan.RequiredForm()]
        # self.third_party_data_elements = [db_plan.ThirdPartyDataElement()]
        # self.ui_config_property_data = [db_plan.UIConfigPropertyData()]
        # self.ui_text_elements = [db_plan.UiTextElement()]
        # self.user_account_attributes = [db_plan.UserAccountAttribute()]
        # self.user_property_data_elements = [db_plan.UserPropertyDataElement()]
        # self.user_property_data = [db_plan.UserPropertyData()]
        # self.vendors = [db_plan.Vendor()]
        # self.vault_info = [db_plan.VaultInfo()]
        self.ui_text_elements = self.get_ui_text_elements()

    def get_ui_text_elements(self):
        device_id = 1
        description = 'extension verbiage'
        english_verbiage = {
            'pageTitle': "My Extension",
        }
        spanish_verbiage = {
            'pageTitle': "Mi extensión",
        }

        verbiage_to_install = []
        for element, value in english_verbiage.items():
            verbiage_to_install.append(
                db_plan.UiTextElement(
                    short_name=element,
                    description=description,
                    text_value=value,
                    device_id=device_id,
                    language='USEnglish'
                )
            )

        for element, value in spanish_verbiage.items():
            verbiage_to_install.append(
                db_plan.UiTextElement(
                    short_name=element,
                    description=description,
                    text_value=value,
                    device_id=device_id,
                    language='Spanish'
                )
            )
        return verbiage_to_install
Things to note in this example:
  • The device_id is hard-coded to 1. This is a value that was deprecated in the Q2 product, so hard-coding is expected.

  • The dictionary keys in both english_verbiage and spanish_verbiage are the same. The keys are the same as the UI Text Elements, and should remain the same in both dictionaries.

  • The language for English is USEnglish. This is the default language of the Q2 product. These languages reference the values found in the Q2_UiLanguage table.

Fetching the UI Text

After you have installed the verbiage with the db_plan, you can use the self.get_ui_text function to get the verbiage. The code sample below shows how to call this function and get the verbiage.

verbiage_dictionary = await self.get_ui_text()

The function, which needs to be awaited, returns the same dictionary that was put in the database from the db_plan.py file. This function will also try to auto-detect the language to fetch from the incoming request (if the request originates from HQ), but will default to USEnglish if it is unable to determine the language. You can also specify the language to get if the extension is unable to detect the language.

verbiage_dictionary = await self.get_ui_text(language='Spanish')

After the UI Text has been received, you can use it in a Jinja template to put the verbiage into the front-end.

form_replacements = {
    'verbiage': verbiage_dictionary
}
template = self.get_template('index.html.jinja', form_replacements)
html = forms.Q2Form(
    "PersonToPersonTransfer",
    custom_template=template,
    # Hide the submit button as there is no form on this route.
    hide_submit_button=True
)
<div class="container">
    <div class="page-header">
        <h3>{{ verbiage.pageTitle }}</h3>
    </div>
</div>