This document describes how to use the cnls utility (cnls.exe), detailing how to set up customized language translation, test it, and apply it to your application.
NLS TRANSLATION
To set up a customized NLS translation, follow these steps:
  1. Start up the NLS utility by double clicking the cnls.exe, located in the CacheSys\Bin directory.
  2. Choose the server connection window, use the default LOCALTCP or select another server from the pull-down list. (Defined in the "Preferred Server" section).
  3. Under the Locale tab. Create the Locale with "New" in the lower right. Insert a description.
    The OK button in the lower right corner should then no longer be greyed out. Hit OK. Choose "Options" located at the top left of the screen and "Install the Locale". You can use the NLS "Import" or "Export" option, located in the far right corner, to import or export a locale from another Cache system. You can also import and export tables with this utility.
    Note: If selecting another standard locale as your current locale, you must use the NLS utility "Import Locale Option" to copy the locale definition from the Cache installation CD into the Cachesys\Bin directory. Standard locales are located in the \nt\install\eightbit or \nt\install\unicode directories. Locale definitions are the goq files. Locales are identified by a four-character locale name. Always import the_src.goq (source code) version of the locale. For example “English, United States Latin1” is “enu8_src.goq”. The install locale option also prompts you for these files from disk and you simply point it to the Cachesys\Bin directory or NLS Subdirectory.
  4. Go to the Translation Tab and set up the Translation Table choosing "New" in the lower right corner “Copy From,” is left blank. i.e. For printing use an "Output Only" table where "Translate From" would be "Latin 1" and "Translate To" is the new translation table which should always start with "y". If the translation is for terminal input, it would be an "Input Only" table and "Translate From", would be the new translation table and "Translate To" would be "Latin 1". "Mapping Type" is primarily "Single to Single" unless you have multiple characters you want to translate into one, or multiple to multiple which would then be a "Multiple to Single" or "Multiple to Multiple" table. The characters are translated in the table on on the far right. By default they are displayed in decimal, which are the ascii values. The table can also be displayed in hex or character mode. This is adjusted in the top left corner under the "Help" option. To set up your translation, you simply change the values in either row or add new values at the bottom next to the *.
  5. Once the translation table is set up go back to the "Locale Tab" to update it with the new translation table. In the "Translation Name Grid (the middle grid), go to the * to add your translation. Here you can call it anything you want. i.e. "sueprint" Then move over to the "Output" tab, or "Input" tab, whichever you are using, the drop down list should contain your new translation table, which you then choose. Depending on what you are translating "input" vs "output", you should always have a default table as a placeholder in either the "input" or "output" column. The Translation Name name is critical, as this is the name used by Cache to specify I/O translation. Each translation name is associated with an Output and an Input character set.
  6. Go to the "Translation Type" grid (the bottom grid), and change the "Programmer Window" to your new "Translation Name" i.e. "sueprint" (the name you assigned in the second grid) so that you can test the translation. The "Translation Name" is the name used by Cache to specify I/O translation. Each translation name is associated with an Output an Input character set.
  7. Install or Validate the locale again with the new translation. Validate compiles the sources for the tables and loads the objects into shared memory. Install validates the locale and makes it the current one.
  8. Open up a new terminal window:
    w $zm
    should list the translation name that you updated your locale with.
    >w $zm
    >RY\Latin1\K\SUEPRINT
    Note: i.e. Translation Name is "sueprint"
Additional Notes
To set translation for a printer, you set the translation when the device is opened.
u x s zzz=$$SetIO^%NLS("sueprint") 
Use the following syntax to test it:
>s x="|PRN|"

>o x
 
>u x s zzz=$$SetIO^%NLS("sueprint") w $C(146),!,$C(147),!
 
>c x
The $ZCVT function allows you to test your translation with the following syntax where "ySue" is the output translation table.
>f I=0:1:255 s x=$ZCVT($C(i),"o","ySue") if x'=$c(i) w I," ",$a(x),!
>177 49
 178 50
 180 52
 183 55
 184 56
 231 103
These are the translated characters.
The following command will list out the %NLS settings:
USER>d Dump^%NLSMISC
 
I/O Table Name  Offset:Type   Source Global
--------------  -------------  -------------
UnicodeLittleIn  4A0030:Struct8
      Out  4A0038:Struct8
UnicodeBig In   4A0020:Struct8
      Out  4A0028:Struct8
SAME    In   4A0000:Struct8
      Out  4A0008:Struct8
UTF8    In   4A0AAC:Struct8 %nls("Src","XLT","UTF8","Latin1")
      Out  4A0AB8:Struct8 %nls("Src","XLT","Latin1","UTF8")
BIN    In   4A0000:Struct8
      Out  4A0008:Struct8
RAW    In   4A0000:Struct8
      Out  4A0008:Struct8
Ricky   Out  4A0098:Struct8 %nls("Src","XLT","Latin1","yAquis")
 
$X/$Y Table Name Offset:Type   Source Global
---------------- -------------  -------------
Latin1      4A0074:Struct8
 
Collation Table  Offset:Type   Source Global
---------------  -------------  -------------
 0    Enc  Old ANSI
      Dec
 1    Enc  New ANSI
      Dec
 2    Enc
      Dec
 3    Enc
      Dec
 4    Enc
      Dec
 5    Enc  Unicode
      Dec
128    Enc  Old string
      Dec
129    Enc  New string
      Dec
133    Enc  Unicode string
      Dec
 
Default      Offset:Type   Source Global
-------      -------------  -------------
Pattern      4A0040:Struct8
Ident       4A004C:Struct8
UpperCase   4A0080:Struct8
LowerCase   4A008C:Struct8
TitleCase    4A0080:Struct8
 
I/O Default    Offset:Type   Name
-----------    -------------  ----
Process      490233:ByteStr Ricky
Direct Term  490233:ByteStr Ricky
Telnet/LAT   490002:ByteStr RAW
File         490002:ByteStr RAW
Magtape     490002:ByteStr RAW
Network     490002:ByteStr RAW
DSM-DDP      490002:ByteStr RAW
DTM-DCP      490002:ByteStr RAW
SysCalls     490002:ByteStr RAW
 
$X/$Y Default   Offset:Type   Name
-------------   -------------  ----
Process      49002D:ByteStr Latin1
 
I/O Slots     All Empty
 
$X/$Y Slots  All Empty
 
Process      Offset:Type   Source Global
-------      -------------  -------------
Pattern      4A0040:Struct8
Ident        4A004C:Struct8
UpperCase   4A0080:Struct8
LowerCase   4A008C:Struct8
TitleCase     4A0080:Struct8
 
Process I/O    Offset:Type   Name
-----------    -------------  ----
Process      490233:ByteStr Ricky
Direct Term  490233:ByteStr Ricky
Telnet/LAT   490002:ByteStr RAW
File         490002:ByteStr RAW
Magtape     490002:ByteStr RAW
Network     490002:ByteStr RAW
DSM-DDP   490002:ByteStr RAW
DTM-DCP   490002:ByteStr RAW
SysCalls     490002:ByteStr RAW
 
Process $X/$Y   Offset:Type   Name
-------------   -------------  ----
Process      49002D:ByteStr Latin1
To check the locale setting do the following:
>d ^%G
>Global ^%SYS("LOCALE","CURRENT") -- NOTE: translation in effect
>^%SYS("LOCALE","CURRENT")=yaq8
Here's a list of the known entry points in ^%NLS:
$$SetIO^%NLS(tblname) --> Select I/O Translation 
$$Set^%NLS("I",tblname) --> table for current device
$$SetPIO^%NLS(tblname) --> Select I/O Translation 
$$Set^%NLS("J",tblname) --> table for calling process
$$SetXY^%NLS(tblname) --> Select $X/$Y Action 
$$Set^%NLS("X",tblname) --> table for current device
$$SetPM^%NLS(tblname) --> Select Pattern Match 
$$Set^%NLS("P",tblname) --> table for calling process
$$SetIdent^%NLS(tblname) --> Select Identifier 
$$Set^%NLS("E",tblname) --> table for calling process
$$SetUpper^%NLS(tblname) --> Select Upper Case Conversion 
$$Set^%NLS("U",tblname) --> table for calling process
$$SetLower^%NLS(tblname) --> Select Lower Case Conversion 
$$Set^%NLS("L",tblname) --> table for calling process
$$SetTitle^%NLS(tblname) --> Select Title Case Conversion 
$$Set^%NLS("T",tblname) --> table for calling process
$$SetCOL^%NLS(tblname) --> Select Collation 
$$Set^%NLS("C",tblname) --> table for calling process
$$GetIO^%NLS --> Return I/O Translation 
$$Get^%NLS("I") --> table name for current device
$$GetPIO^%NLS --> Return I/O Translation 
$$Get^%NLS("J") --> table name for calling process
$$GetXY^%NLS --> Return $X/$Y Action 
$$Get^%NLS("X") --> table name for current device
$$GetPM^%NLS --> Return Pattern Match 
$$Get^%NLS("P") --> table name for calling process
$$GetIdent^%NLS --> Return Identifier 
$$Get^%NLS("E") --> table name for calling process
$$GetUpper^%NLS --> Return Upper Case Conversion 
$$Get^%NLS("U") --> table name for calling process
$$GetLower^%NLS --> Return Lower Case Conversion 
$$Get^%NLS("L") --> table name for calling process
$$GetTitle^%NLS --> Return Title Case Conversion 
$$Get^%NLS("T") --> table name for calling process
$$GetCOL^%NLS --> Return Collation 
$$Get^%NLS("C") --> table name for calling process
$$DefIO^%NLS[(type)] --> Return system default 
$$Def^%NLS("I"[,type]) --> I/O Translation table name
type 0 = process 
1 = M terminal (default type) 
2 = other terminal 
3 = sequential file 
4 = mag tape 
5 = network device
$$DefXY^%NLS --> Return system default 
$$Def^%NLS("X") --> $X/$Y Action table name
$$DefPM^%NLS --> Return system default 
$$Def^%NLS("P") --> Pattern Match table name
$$DefIdent^%NLS --> Return system default 
$$Def^%NLS("E") --> Identifier table name
$$DefUpper^%NLS --> Return system default 
$$Def^%NLS("U") --> Upper Case Conversion tbl name
$$DefLower^%NLS --> Return system default 
$$Def^%NLS("L") --> Lower Case Conversion tbl name
$$DefTitle^%NLS --> Return system default 
$$Def^%NLS("T") --> Title Case Conversion tbl name
$$DefCOL^%NLS --> Return system default 
$$Def^%NLS("C") --> Collation table name
$$SetPDefIO^%NLS(tblname[,type]) --> Select process default 
$$SetPDef^%NLS("I",tblname[,type]) --> I/O Xlate table name 
(see $$Def^%NLS for types)
$$SetPDefXY^%NLS(tblname) --> Select process default 
$$SetPDef^%NLS("X",tblname) --> $X/$Y Action table name
$$GetPDefIO^%NLS[(type)] --> Return process default 
$$GetPDef^%NLS("I"[,type]) --> I/O Translation table name 
(see $$Def^%NLS for types)
$$GetPDefXY^%NLS --> Return process default 
$$GetPDef^%NLS("X") --> $X/$Y Action table name
$$OnIO^%NLS --> Turn I/O xlate ON for current 
device and return previous state
$$OffIO^%NLS --> Turn I/O xlate OFF for current 
device and return previous state
$$StatIO^%NLS --> Return I/O xlate state for current 
device
$$OnPIO^%NLS --> Turn I/O xlate ON for calling 
process and return previous state
$$OffPIO^%NLS --> Turn I/O xlate OFF for calling 
process and return previous state
$$StatPIO^%NLS --> Return I/O xlate state for calling 
process
$$SetPitch^%NLS(value) --> Set pitch value for current device
$$GetPitch^%NLS --> Get pitch value for current device
The following operations are for modal translations only:
$$SetInpMode(nbr) --> Set input mode string index 
for current device
$$SetOutMode(nbr) --> Set output mode string index 
for current device
$$GetInpMode() --> Get input mode string index 
for current device
$$GetOutMode() --> Get output mode string index 
for current device
$$SetPInpMode(nbr) --> Set input mode string index 
for calling process
$$SetPOutMode(nbr) --> Set output mode string index 
for calling process
$$GetPInpMode() --> Get input mode string index 
for calling process
$$GetPOutMode() --> Get output mode string index 
for calling process
$$SetInpModeStr(nbr,value) --> Set input mode string value 
for current device; i.e. 
mode(nbr) = value
$$SetOutModeStr(nbr,value) --> Set output mode string value 
for current device
$$GetInpModeStr(nbr) --> Get input mode string value 
for current device
$$GetOutModeStr(nbr) --> Get output mode string value 
for current device
$$SetPInpModeStr(nbr,value) --> Set input mode string value 
for calling process
$$SetPOutModeStr(nbr,value) --> Set output mode string value 
for calling process
$$GetPInpModeStr(nbr) --> Get input mode string value 
for calling process
$$GetPOutModeStr(nbr) --> Get output mode string value 
for calling process
These functions set or get replacement attributes for I/O translations. ReplType is replacement type for characters/strings which do not have a valid translation:
0 = generate error 
1 = substitute (value or string) 
2 = ignore (use original character)
ReplVal is the value/string to be used if ReplType=1 (substitute)
ReplStat is the replacement status: 
0 = normal (no substitutions) 
1 = substitution has occurred
SetInpReplType(typ) --> Set input replacement type 
for current device
SetOutReplType(typ) --> Set output replacement type 
for current device
GetInpReplType --> Get input replacement type 
for current device
GetOutReplType --> Get output replacement type 
for current device
SetInpReplVal(val) --> Set input replacement value 
for current device
SetOutReplVal(val) --> Set output replacement value 
for current device
GetInpReplVal --> Get input replacement value 
for current device
GetOutReplVal --> Get output replacement value 
for current device
SetInpReplStat(typ) --> Set input replacement status 
for current device
SetOutReplStat(typ) --> Set output replacement status 
for current device
GetInpReplStat --> Get input replacement status 
for current device
GetOutReplStat --> Get output replacement status 
for current device
SetPInpReplType(typ) --> Set input replacement type 
for process
SetPOutReplType(typ) --> Set output replacement type 
for process
GetPInpReplType --> Get input replacement type 
for process
GetPOutReplType --> Get output replacement type 
for process
SetPInpReplVal(val) --> Set input replacement value 
for process
SetPOutReplVal(val) --> Set output replacement value 
for process
GetPInpReplVal --> Get input replacement value 
for process
GetPOutReplVal --> Get output replacement value 
for process
SetPInpReplStat(typ) --> Set input replacement status 
for process
SetPOutReplStat(typ) --> Set output replacement status 
for process
GetPInpReplStat --> Get input replacement status 
for process
GetPOutReplStat --> Get output replacement status
The “Set” functions typically return the prior setting, when this value is meaningful.