Chapter 6—Localization

If you are developing web or mobile applications for an international market, using the JavaScript Client, you may want to translate the text and labels in your apps into another language, or support multiple languages. You can use the String Table Editor in Omnis to create an external file to store alternative strings for the labels and text in your app to support multiple languages in your JavaScript remote forms. The external file is stored in Tab Separated Value (TSV) format.

Using TSV files is now the preferred method for localization and the String Table Editor uses this format by default. The old way of storing string tables internally (in.stb files) and handling them via $stringtabledata and $stringtabledesignform still works (for Omnis Studio 6.0 or above), but is only present for backwards compatibility and should not be used for new applications. This technique is described in the Localization chapter in the Omnis Programming manual.

Localization for the JavaScript Client

String Table Format

The String Table external component uses a Tab Separated Value (TSV) file for storing string tables. TSV files should be stored in the same folder as the library file, and have the following format and features:

If you open the Catalog (press F9) while editing a remote form or remote task that has a string table associated with it (via $stringtable), then the Catalog automatically loads the string table specified in $stringtable, if it is not already loaded, or reloads it if it has changed on disk.

Localizing Remote Forms

Remote tasks have a property, $stringtable which is the name of the string table for the current library and shared by all JavaScript Client remote form instances in the remote task. When a client connects and the remote task is using the $stringtable property, Omnis loads the appropriate string table.

When you test a remote form that has an associated string table, Omnis generates a JavaScript file automatically if the file does not exist or if the string table file (.tsv) is more up to date than the script file. In addition, Omnis inserts a script tag for the string table into the HTML file generated automatically by the Test Form option. If you change the string table file name in $stringtable, you need to test the form again in order to regenerate the HTML file containing the correct name. Note that only the Omnis development version rebuilds the JavaScript string table file: this is not produced automatically in the Omnis Server.

The path of the string table JavaScript file is of the form:

html/strings/libname/file.js

where ‘strings’ is a folder in the html folder, ‘libname’ is a folder for the library, and file.js is the JavaScript file for the remote task strings, named using the name of the task string table file.

For deployment, you need to place the file.js in the equivalent folder in the web server tree where the other Omnis HTML pages, scripts, etc are located. Alternatively, you can use an option in the String Table Editor to export the string table JavaScript file, rather than using the exported file from your development tree. This option can be used to output the entire table as a JavaScript file, or you can output one or more files for selected locales, where each file contains a single selected locale column and is named file.locale.js.

String tables are converted to separate JavaScript files and transferred to the client as needed and depending on its locale. The script file is cached in the client browser and only reloaded when the string table has changed.

Optimizing string tables

Single-locale JavaScript string tables can be used to further improve loading performance for string tables. There is a new file, jsStringTableSwitch.htm in the html folder in the main Omnis development tree. This file can be used as the initial remote form for an application, and has markers where it can be customized - this allows you to specify the string table file to use for each locale, and a default for unknown locales. In addition, jsStringTableTempl.htm needs to be customized to set up the initial remote form etc, and the string table path. When a page based on jsStringTableSwitch.htm loads, the page:

This results in an HTML page for the remote form that only loads the strings for the current locale, and which still has the original URL you have chosen for your application.

Standalone Client

If you run your application in the Standalone client you have to set the library preference $serverlessclientstringtable to specify which string table to use for the remote form instances in the SCAF for the library. This takes the name of a string table (tab-separated value .tsv file in library folder).

String table functions

The client accesses the current string table for the stgettext() function, and properties assigned with the $st prefix. In addition, server methods can also use stgettext() to look up strings for the client locale (either the locale received from the client, or the locale set using $stringtablelocale). If the locale is not present in the string table, stgettext() will return values from column 2 of the string table.

Setting the Client Locale

You can use the ‘setlocale’ client command to override the locale on the client device in the JavaScript Client.

The application needs to be restarted on the client for the change in locale to have an effect. Note that the client commands set this as a localStorage preference, so all Omnis JS client applications (forms) on the same client device will use this setting.

Localizing Built-in Strings

There are a number of strings that can appear in error messages and other dialogs in the JavaScript Client. These are built into the JS client and are in English by default, but from Studio 10.2 onwards, support for German, French, Italian and Spanish translations is provided, while support for other languages can be added as required.

Localized String files

The ‘locale’ folder under html/scripts/ contains a number of ,js files containing the strings for English and other languages. The files are named in the format strings_[language code].js using either a 2 or 4 letter language code; for example, strings_en.js for standard English, or strings_en_us.js for American English. Inside each file is an object, which is a member of jOmnisStrings, containing key-value pairs to translate to the given language. The member name should match the language code given in the file name, therefore, for french, the strings_fr.js file contains an object jOmnisStrings.fr. The strings_base.js file contains the base strings, and should always be present.

There is a template file called strings_template.js, which provides more information about creating your own translations, with comments for each key-value to help you understand what each string is used for.

Setting the supported languages

The global variable supportedLanguages is defined in the htm file for a remote form (i.e. the application). This contains an array of language codes for the supported languages. On loading a remote form, the locale of the client is detected, and then checked against the supported languages in the array. It will look for both the 4 and 2 letter language codes, and if found, will request strings_base.js and the relevant localized versions. This means the JS client will only download the strings it needs.

Built-in Strings

The following strings are present in the jOmnisStrings strings object in the JavaScript Client, where \x01 is a place-holder which is replaced by parameters added to the string when it is called by the client; you should retain \x01 in your translated text. You can use the contents of strings_template.js for a definitive list of strings.

(Note that some of the error messages are very unlikely to appear in the final deployed version of your app, since they relate to design mode only, so it is not entirely necessary to translate all of the error strings.)

String object String text (English default)
comms_error An error has occurred when communicating with the server. Press OK to retry the request
comms_timeout The server has not responded. Press OK to continue waiting
ctl_dgrd_id You cannot use \x01 as a list column name for a list bound to a data grid
ctl_dgrd_other (1 other)
ctl_dgrd_others (\x01 others)
ctl_file_batchsizeerror Total batch of files is larger than maximum allowed upload size (\x01)
ctl_file_batchsizetext \x01 of \x01
ctl_file_downloaderror Download error
ctl_file_filesizeerror File size is larger than maximum allowed upload size (\x01)// \x01 //
ctl_file_filesizetext \x01 of \x01
ctl_file_filesuploaded \x01/\x01 files
ctl_file_stopbutton Cancel upload
ctl_file_uploadbutton Upload
ctl_file_uploaderror Upload error
ctl_file_uploadmultipletitle Upload files
ctl_file_uploadstopped Upload stopped
ctl_file_uploadtitle Upload file
ctl_subf_params Control \x01: $parameters cannot be assigned at runtime
ctl_tree_badgnl Control \x01: Internal error calling get node line for dynamic tree
ctl_tree_badident Control \x01: You cannot use \x01 as a tree node ident - tree node idents must be a non-zero positive integer
ctl_tree_dupident Control \x01: The tree already has a node with ident \x01 - tree node idents must be unique
ctl_tree_invmode Control \x01: Invalid data mode for tree
disconnected You have been disconnected. Refresh or restart application to reconnect
error Error
local_storage_unavailable_error Unable to access localStorage (perhaps cookies are disabled?).//The application will not run.
omn_cli_badobj object $objs.\x01 does not exist
omn_cli_callprivate callprivate cannot call "\x01"://Exception: \x01
omn_cli_cgcanassign cannot use $canassign for row section object "\x01" in complex grid because it has exceptions
omn_form_addbadpage Parent page number \x01 not valid for paged pane "\x01 
omn_form_addbadparent Parent object "\x01" for add control is not a paged pane
omn_form_addcg Cannot add control to parent object \x01 contained in complex grid
omn_form_addparent Cannot find parent object \x01 for add control
omn_form_addsrc Cannot find source object \x01 for add control
omn_form_ctrlinst Failed to install the control \x01. Possible missing class script
omn_form_nofile There is no file with the specified ident (\x01)
omn_form_noinstvar Instance variable does not exist (\x01)
omn_form_readfileerror Error \x01 occurred when reading the file with ident \x01
omn_inst_assignpdf Assign PDF: HTML control "\x01" not found
omn_inst_badformlist \x01: Invalid formlist
omn_inst_badparent \x01: Invalid parent for subform set
omn_inst_badpn \x01: Paged pane does not have page \x01
omn_inst_badpp \x01: Cannot find the paged pane with name "\x01 
omn_inst_badservmethcall Cannot make server method call when waiting for a response from the server
omn_inst_badsfsname \x01: Invalid or empty name for subform set
omn_inst_cliexcep Exception occurred when executing client method://
omn_inst_dupsfsname \x01: A subform set with this name already exists
omn_inst_dupuid Subform set already contains unique id \x01
omn_inst_excep Exception occurred when processing server response://
omn_inst_excepfile File "\x01" Line \x01//
omn_inst_formloaderr Failed to load form data for \x01. Server returned \x01
omn_inst_formnum Invalid form number. Parameter error \x01
omn_inst_objnum Invalid object number. Parameter error \x01
omn_inst_respbad Unknown response received from server
omn_inst_senderr Failed to send message to server
omn_inst_sfsnotthere \x01: A subform set with name "\x01" does not exist
omn_inst_xmlhttp Failed to initialize XMLHttpRequest
omn_list_badaddcols The argument count for $addcols must be a multiple of 4
omn_list_badrow Invalid list row
omnis_badhtmlesc Invalid HTML escape
omnis_badstyleesc Invalid style escape sequence
omnis_convbad Error setting \x01: variable type \x01 not supported by JavaScript client
omnis_convbool Error setting \x01: data cannot be converted to Boolean
omnis_convchar Error setting \x01: data cannot be converted to Character
omnis_convdate Error setting \x01: data cannot be converted to Date
omnis_convint Error setting \x01: data cannot be converted to Integer
omnis_convlist Error setting \x01: data cannot be converted to List
omnis_convnum Error setting \x01: data cannot be converted to Number
omnis_convrow Error setting \x01: data cannot be converted to Row
omnis_escnotsupp Text escape not supported by JavaScript client
switch_off OFF
switch_on ON