NIH or multi-lingual interactive help

(Interactive help system allowing an harmonious coexistence between English applications and localized applications)
Current release is 0.3
Author: Benoît GILON
Logo de HTMLEdit v3

Overview

Target audience for this document

Background

Localization of RISC OS applications is likely to be the most straightforward and flexible on our planet.

People who would like to develop and market applications in non English speaking countries have to use standard development tools, with one file per resource type and supported language (or a directory per supported language).
Applications written in BASIC can benefit from the code fragment named ResFind (written by Olaf Krumnow and Herbert zur Hedden from the German Archimedes Group).
Applications written in C can benefit from the SetRes program (I wrote) for all Toolbox based Wimp applications (or else refer to the Local article for applications still using RISCOSlib).
Interactive help allows client applications, as they submit text messages to display in !Help application's window, to specify tokens which will be then translated by the !Help application into readable sentences (after having read an internal dictionary).
This shortens the data (and then help to put more text in a single Wimp message).
Every token is prefixed in the transmitted data by the backslash character (\) which acts as an escape character. Following this prefix is a single character (code is greater than space) specifying the pattern for the !Help application to use when reading from the dictionary. You can find samples of such messages by viewing message files in the Resources:$.Resources hierarchy. Navigate to the subdirectories associated with classic Acorn desktop applications (such as !Alarm).
Unfortunately, only translating the Messages file within the Help resource directory can only solve the problem provided that every installed application or system component on the user computer speak the same language. At most times, this should be English because:

If all you do is to translate the Message file in your Help resource directory, then such terrible message as "Cliquez SELECT pour merge the paths." would pop up in your Interactive Help window (I assume here that the user speaks French, "Cliquez SELECT pour" means "Click SELECT to"). The underline red italics part comes from the !Help application internal dictionary and the trailing part comes from the English speaking application (the text included in the Wimp message being "\Smerge the paths").
The well known user friendliness of the RISC OS desktop should also apply in these domains (text clarity). So (and up to now), interactive-help definitions from within resource files supporting other than English language of a localized application must held no token. This implies:

Provided tools abilities

The following paragraph details a method to implement inside the two most well known IH applications (namely Acorn !Help and Miles Sabin's !BubbleHlp) an alternate dictionary for user's language token translation along with the unmodified English version.
To guide the IH application to differentiate the messages, the new tokens will be prefixed by two backslashes instead of only one. The incoming text data "\\Srassembler les chemins." will then be translated to the string "Cliquez SELECT pour rassembler les chemins." to be displayed in the IH application's main window. This implies:

!Help application patch (!RunImage file)

Token expansion

The BASIC procedure in charge of translating data originated from the client applications is named "e": below is a code extract from it:
DEFPROCe:LOCALx%,T%,M%,A%,p%,m%,N%,I%,y%,oa%: \
SYS39,a%+20,n%,512+(1<<31)TOp%,,A%:A%+=n%:?A%=13:p%?-1=13:t$=$(a%+20):IFt$=c$ENDPROC
c$=t$:y%=J%:FORx%=n%TOA%:?y%=?x%:IF?x%<>ASC("\")THEN
y%+=1
ELSE:x%+=1:IF?x%=ASC("\")THEN
y%+=1
ELSE:$(y%)=FNa("T"+CHR$(?x%)):IF?y%=ASC("T")AND?(y%+1)=?x%ANDLEN($(y%))=2THEN?y%=ASC("\")
y%+=LEN($(y%))
ENDIF
ENDIF
And now, the patched version which uses an additional local string variable z$ (holding the first letter from the token to be used as a key when reading the token definition from the dictionary):
DEF PROCe:LOCAL x%,T%,M%,A%,p%,m%,N%,I%,y%,oa%,z$: \
SYS39,a%+20,n%,512+(1<<31)TOp%,,A%:A%+=n%:?A%=13:p%?-1=13:t$=$(a%+20):IF t$=c$ENDPROC
c$=t$:y%=J%:FOR x%=n%TOA%:?y%=?x%:IF?x%<>ASC("\")THEN
y%+=1
ELSE:x%+=1:IF?x%=ASC("\")THENx%+=1:z$="U"ELSEz$="T"
$(y%)=FNa(z$+CHR$(?x%)):IF?y%=ASC(z$)AND?(y%+1)=?x%ANDLEN($(y%))=2THEN?y%=ASC("\")
y%+=LEN($(y%))
ENDIF

Dealing with different token dictionaries (for non UK Messages hosts)

The procedure in charge of opening the dictionary message file is procedure "t". Here is the new procedure which handles an OS specific version at first.
DEF PROCt:LOCAL F%,M$:M$="Help:<Boot$OSVersion>"
DIM e%256:SYS30,6,,,17+LEN(M$)TO,,t%:$(t%+16)=M$:SYS398592,,t%+16TO;F%
IF F%AND1THEN$(t%+16)="Help:Messages"
SYS267521,t%,t%+16,0:ENDPROC

BubbleHelp application patch

Two topics are covered here: The first update involves changes to Config.s.ConfigMain; Help.s.ConfigMain and Kernel.s.AString source code files. The second update involves changes to Help.s.HelpExpand source code files.

Help$Path environment variable setting

This is usually done within the !Run file of the !Help application. As !Help is a BASIC application, the use of ResFind comes to mind. Below is the original !Run file content (stored in the Resources:$.Apps.!Help directory):
| > !Run
| Check for the required amount of memory first
WimpSlot -min 32K -max 32K
| Having succeeded there, do not start up if
| Help is already running.
If "<Help$Dir>"<>"" Then Error Help is already running
| Then start the application
Set Help$Dir <Obey$Dir>
Set Help$Path <Obey$Dir>.,Resources:$.Resources.Help.
Run Help:!RunLink
And now the new !Run file (a modified version can be found in the archive, to be used if the application should be started from within the Apps icon on the iconbar, the RISC OS command AddApp was used to place this icon during the boot sequence).
| > !Run
| Check for the required amount of memory first
WimpSlot -min 32K -max 32K
| Having succeeded there, do not start up if Help is already running.
If "<Help$Dir>"<>"" Then Error Help is already running
| Then start the application
Run <Obey$Dir>.Resources.ResFind
Unset HelpRes$Path
Unset Help$Dir
If "<HelpRes$Dir>"="<Obey$Dir>" Then /Resources:$.Apps.!Help
Set Help$Path <HelpRes$Dir>.,Resources:$.Resources.Help.
Unset HelpRes$Dir
Set Help$Dir Resources:$.Apps.!Help
Run <Obey$Dir>.!RunImage

Client applications changes

Toolbox based applications

The current paragraph will describe a method for updating Acorn toolbox based applications so that they can easily benefit from the new help system. I presume that they already used the SetRes program I often use in applications I've written. As a reminder, SetRes sets an environment variable (<AppNameR$Dir>) according to the current setting of another environment variable ("<AppName>") and to the country currently set (which value can be read/written with the Country RISC OS command).
For every supported language (other than English), we'll have two versions for the file res (presuming that all text data going to the IH window are defined within this file).
  1. the file <AppNameR$Dir>.res for messages which make no use of tokens;
  2. the file <AppNameR$Dir>.nhelp.res for messages making use of tokens.
An issue with the toolbox_initialize API is that it requires that the pathname given for it to search the res and Messages files must not be a pseudo FS specifier (like AppNameR: which use the setting of the AppNameR$Path environment variable). To work around this glitch, we have to duplicate the Messages file in both directories. The choice of one file from the list above is based on the criteria below:

The first detection to perform is to determine the "default" interactive help application (either Acorn !Help or !BubbleHlp) according to the value of the Help$Start system variable.

The program which performs all those checking is a small piece of BASIC code (which is inspired from code inside ResFind) and is included in the archive. This program takes the current value of the <AppName>R$Dir variable, and output a modified value for it according to the predicate evaluation described above.

BASIC and RiscOSLib based applications

BASIC applications update mechanism is based upon the use of two small BASIC modules. From the point the change occurs, trying to access the file under the pathname AppNameRes:Messages will access the file <AppNameRes$Dir>.nhelp.Messages instead of <AppNameRes$Dir>.Messages.

Sample applications which have been updated this way to make them compliant with NIH are the latest release of !Player from ESP and my own localisation initiative of !StrongED (4.62) you can find on this Web site too.

An helper application: !NIHTool

This tool can help you doing these tasks: Typically the process can be described shortly: It takes input from three sources; two are files (the last one being some command line option setting) Those two mandatory parameters and others can be entered with the help of the dialog box below:
NIHTool setup window

The more esoteric options can be activated via the use of the popup menu below:

NIHTool setup menu

Conclusion

After having performed the above changes, you will have: I hope that this article will help the reader who is involved in localizing is desktop. Do not hesitate to contact me if in need of further explanations.
Remarks are welcome... click here to drop me a note.