Browser Language Module

Starting with HotDocs 10.1, the HotDocs Server JavaScript API includes a specification for creating "Browser Language Modules" (BLM). These modules allow interviews to be localized, which means that user interface text can be presented in languages other than US English. By following this specification, a language module can be defined which will allow HotDocs Server to present an interview in any language.

Although a language module may be created for any language, if the language is right-to-left (such as Arabic or Hebrew), HotDocs does not currently adjust the prompt positioning and justification as would be expected for these languages.

A BLM is implemented as a JavaScript object in the web browser’s scripting environment. This object specifies the language that it supports (for example, “en-US”), and can also contain appropriately-translated text strings necessary for the interview user interface, as well as code necessary for locale-appropriate interpreting and formatting of numeric and date values. Language module names (“en-US”) follow the same naming scheme as the .NET framework: the first (and required) part of the language module name is a 2-letter language code based on ISO 639-1, followed by an optional (and usually 2-letter) region code based on ISO 3166.

The BLM specification allows for a limited hierarchy of language modules to exist; each language module implicitly has a “parent” or “base” language module from which it inherits certain capabilities. For example, the “en-US” language module is implicitly based on the “en” language module, it would automatically inherit all the behaviors defined by its parent. The way language modules are invoked from within HotDocs allows any missing functionality in a BLM to be gracefully filled in by that module’s parent module(s). All browser language modules ultimately inherit from a base language module (known as “invariant”), which defines the default behavior of all language modules. So creating a HotDocs BLM is often as simple as providing translations for the various messages and strings which may be required for the user interface of a HotDocs interview.

Loading the Language Module

Since HotDocs BLMs are simply JavaScript objects, loading them simply means ensuring that an object with the expected properties and methods is loaded into the scripting environment where HotDocs is expecting to find it. This can be done either by loading a language module using a <script> tag in the page containing the HotDocs Server interview, or by declaring that language module in-line in the page. Either way, HotDocs Server interviews expect any language modules to be defined as part of the HOTDOC$.Locales associative array. You can declare a new language module as part of this array using a script such as this:

(function($) {  // Register the new language module with the HotDocs locale infrastructure.  var Locales = $.Locales = (typeof $.Locales === "undefined") ? {} : $.Locales;  // Add a new language module definition to the array.  Locales["de-DE"] = {     name: "German (Germany)"    // See below for additional properties and functions to define.  };  // Either use the existing array or create a new one if it is not yet defined in the global scope.  window.HOTDOC$ = $;}(typeof HOTDOC$ === "undefined" ? {} : HOTDOC$));

This code does not require that any HotDocs Server-related code has been loaded before it is executed, so it can be run at any stage of initialization or page loading. The only requirement is that it be loaded and executed before the HotDocs Server interview itself starts up.

Declaring the Interview Locale

It is recommended (but not required) that you explicitly declare a locale for a HotDocs Server interview. The locale informs the HotDocs Server interview that numeric and date input should (if possible) adhere to the norms for the declared locale, and dictates which set of translated user interface strings to use. You can declare the locale by setting a global variable in the JavaScript environment called HDInterviewLocale.

Once a locale has been determined, HotDocs Server will attempt to find a loaded BLM representing that locale. If one cannot be found, HotDocs Server will still attempt to do its best with interpreting or formatting numbers and dates according to the requested locale. Also, if text strings for the requested locale are not available, HotDocs Server attempts to find them in each successive parent locale, or it uses US English text if nothing else is found.

If you do not declare an interview locale, HotDocs Server will do its best to detect the end-user’s system locale automatically at runtime; otherwise, it will default to the US English ("en-US") locale.

Interview Locale vs. Assembled Document LANGUAGE

HotDocs continues to support the LANGUAGE keyword in templates to determine how dates and numbers should be formatted in assembled (output) documents. The new interview locale for HotDocs Server browser interviews is completely independent from the functionality associated with the LANGUAGE keyword—a BLM has no effect on the assembled document, and a LANGUAGE keyword has no effect on the interview. If you want to produce interviews and documents in languages other than English, you must use both features together.

Although the interview locale and a matching BLM can be used to specify the language used for the standard user interface elements, the prompts, dialog titles, and other template-specific text in the interview must still be specified separately by the template author. HotDocs does not have a way to specify multiple prompts (in different languages) for a single variable, but some users have achieved this functionality using a combination of variable fields in prompts and different overlay answer files that provide translated text for each language.

Definition of a Browser Language Module

Following is the JSON notation for an example browser language module:

This is an incomplete implementation of a "de-DE" BLM. It provides translations for month and day names, as well as "yes" and "no" used in True/False variables. All other text would be rendered using US English by default. Likewise, all date and number formatting would be done using the default English implementations since this BLM does not contain any definitions for locale-specific formatting methods.

{
    name: "German (Germany)",
    dateOrder: "DMY",
    months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
    monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"],
    days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
    daysShort: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
    calWeekBegin: 1,
    calWeekend: [0, 6],
    zeroFormats: ["Null"],
    numSeps: [",", "."],
    strings: { ui_yes: "Ja", ui_no: "Nein" },
    SpellNum: function(value, strZero, bOrdinal){}
}

Language Module Properties

The following table lists the properties you can specify in your language module:

Name Description Example
name A name for the language module. (It is not currently used in the user interface.) German (Germany)
dateOrder Determines the default date order: DMY (Day Month Year), MDY (Month Day Year), or YMD (Year Month Day) DMY
months An array of full month names ["Januar", "Februar",  "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]
monthsShort An array of abbreviated month names ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
days An array of full day names, beginning with Sunday ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"]
daysShort An array of abbreviated day names (used in the header row in the calendar) ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"]
calWeekBegin A number to indicate the first calendar day of the week, where Sunday is 0 1
calWeekend An array containing the numeric values for the days that constitute a calendar weekend, where Sunday is 0 [0, 6]
zeroFormats An array of words used to spell out the number 0 (zero) ["Null"]
numSeps An array containing number separators: the decimal separator followed by the thousands separator [",", "."]
strings An associative array of translated user interface text. For a complete list of strings that may be localized, see Language Module Strings. { ui_yes: "Ja", ui_no: "Nein" }

Language Module Methods

The following table lists the methods you can implement in your language module to handle date and number formatting:

If all the regular properties of the language module have been set appropriately, and assuming the interview is being run in either Silverlight or in Internet Explorer JavaScript, the default (US English) implementation of the methods should mostly suffice for most languages. The only methods that should commonly need to be implemented for full functionality in this case are: SpellNum: If omitted, numbers will not be spelled out, but will be displayed numerically instead, GetOrdinalSuffix: If omitted, ordinals will not be produced, InterpretSpelledNum: If omitted, traditional HotDocs-style number & date format examples may not work fully.

Name Description Function Signature
SpellNum This function takes an integer (value) and spells out the number in text (e.g., "three"), using strZero in place of zero and honoring bOrdinal. function(value, strZero, bOrdinal) {}
GetOrdinalSuffix This function returns the appropriate ordinal suffix for an integer value. function(value) {}
IsOrdinalSuffix This function determines whether str begins with an appropriate ordinal suffix for value. If so, it returns how many characters of str constitute that suffix. function(value, str) {}
ParseNumLoc This function parses a string (str) to create a double value, which is returned. (If str cannot be interpreted as a number, it should return return NaN instead.) function(str) {}
ParseDateLoc This function parses a string (str) to create a JavaScript Date object, which is returned. (If str) cannot be interpreted as a date, it should return null instead.) function(str) {}
FormatNumLocDef This function is used when a number needs to be formatted and no format example was recognized. It takes a double (value) and formats it according to locale conventions into a string, padding decimals out to the specified number of decimal places (nDecPlaces). function(value, nDecPlaces) {}
FormatNumLoc This function takes a double (value) and formats it according to the specified parameters: number of decimal places (nDecPlaces), whether or not to include the thousands separator (bThousandsSep), whether or not to zero-pad (bZeroPad), and whether or not to use native digits (bNativeDigits). function(value, nDecPlaces, bThousandsSep, bZeroPad, bNativeDigits) {}
FormatDateLoc This function is used when a date needs to be formatted and no format example was recognized. It takes number values for day (d), month (m), and year (y), and formats a date according to locale conventions—either full-length or abbreviated depending on the value of bLong. function(d, m, y, bLong) {}
FormatTextVal This function parses the given HotDocs format example (formatExample) and formats the text value accordingly. function(value, formatExample) {}
FormatNumVal This function parses the given HotDocs format example (formatExample) and formats the number value accordingly, out to the specified number of decimal places (decimalPlaces). function(value, formatExample, decimalPlaces) {}
FormatDateVal This function parses the given HotDocs format example (formatExample) and formats the date value accordingly. function(value, formatExample) {}
FormatTFVal This function parses the given HotDocs format example (formatExample) and formats the boolean value accordingly. function(value, formatExample) {}
FormatList This function parses the given HotDocs format example (formatExample) and formats the list of values in valueArray accordingly. function(valueArray, formatExample) {}