Support for platform resource formats
The subclasses of NlsPlatformResourceConverter are provided to enable pool dictionaries containing localized messages to be stored in and retrieved from platform resource file formats.
RCConverter
Dynamic link libraries (.DLL files) created using the Microsoft Windows resource compiler are supported. The class RCConverter can produce a resource compiler input file from a pool dictionary, and can re-create the pool dictionary from the input file and the dynamic link library it produces.
Structure of the resource compiler input file
The first portion of the resource compiler input file generated by the RCConverter is a comment that identifies the file along with the date and time when it was created.
Immediately following the first comment is a series of define statements that describe the pool dictionary from which the file was created. Localized messages stored as VA Smalltalk pool variables are identified by string keys in a pool dictionary; however, when these messages are stored in dynamic link libraries they must be identified by ordinal constants. The conversion of string identifiers to ordinal values is accomplished by associating each string identifier with an ordinal value using a define statement in the resource compiler input file. For example:
define <aPoolDictionaryKey> <anInteger>
Localized messages and their associated comments follow the series of define statements. Localized messages are represented as entries in a STRINGTABLE statement associated with an ordinal value declared in the series of define statements.
Note:
The resource file representation of a string can be quite different from its Smalltalk appearance. Many non-printing and special characters must be converted into the '\DDD' format for use with the resource compiler. When retrieved from a dynamic link library using an RCConverter or a PlatformFunction the string is equivalent to the original Smalltalk string.
Creating resource compiler input files
RCConverter provides the
convertMessages:toResourceFile: and
convertMessages:comments:toResourceFile: methods to convert a dictionary containing localized messages into a resource compiler input file. The dictionary containing localized messages must be keyed by string identifiers, and can contain only messages conforming to the conditions described in
RCConverter limitations. An attempt to convert a dictionary containing messages that are not valid generates an error.
In addition to a file name and a dictionary containing localized messages, the convertMessages:comments:toResourceFile: method accepts a dictionary containing comments to be written into the resource compiler input file. The dictionary containing comments should have the same keys as the dictionary that contains localized messages. The comment dictionary must conform to the same limitations that apply to message dictionaries, but need not contain a comment for every message in the dictionary being converted.
The following code example creates a resource compiler input file:
"Create a resource compiler input file."
| dict comments |
dict :=
Dictionary new
at: 'X' put: 'localized message X';
at: 'Y' put: 'localized message Y';
at: 'Z' put: 'localized message Z';
yourself.
comments :=
Dictionary new
at: 'X' put: 'comment X';
at: 'Y' put: 'comment Y';
yourself.
"Store the new pool dictionary in Smalltalk."
Smalltalk at: #DemoPool put: dict.
RCConverter new
convertMessages: (Smalltalk at: #DemoPool)
comments: comments
toResourceFile: 'demo.rc'
The preceding example illustrates how dictionaries containing localized messages and comments are converted into a resource compiler input file. The example produces the resource compiler input file called demo.rc, whose contents are presented in the following example:
/* Resource File for: #DemoPool.
This file is generated automatically for use as the input file for the
Microsoft Resource Compiler. When this file was constructed Smalltalk
message identifiers were converted into numeric identifiers stored as
a group of #define statements within this file.
This file is: demo.rc
Creation date: 14.03.94 at: 14,37,12
This file was created with the following Smalltalk locale settings:
Language: german
Territory: switzerland
Code page/Language driver: deu
*/
#define X 0
#define Z 1
#define Y 2
STRINGTABLE
BEGIN
0, "localized message X" /* comment X */
1, "localized message Z"
2, "localized message Y" /* comment Y */
END
Reading from platform resource files
RCConverter provides the indexFrom: and messagesFromDLL:index: methods to rebuild a dictionary containing localized messages from messages stored in a dynamic link library (DLL).
Dynamic link libraries use integers to identify localized messages and VA Smalltalk pool dictionaries use string identifiers. You must provide the mapping between string identifiers to be used in the reconstructed dictionary and the integer identifier used by the dynamic link library. The indexFrom: method can be used to reconstruct an index from a resource compiler input file based upon a series of define statements that bind string identifiers to integer values. The following example demonstrates the process of rebuilding an index from an existing resource compiler input file:
"Retrieve an index by parsing a resource compiler input file."
^RCConverter new indexFrom: 'demo.rc'
The messagesFromDLL:index: protocol answers a reconstructed dictionary of localized messages based upon the contents of a dynamic link library and an index provided by the developer. messagesFromDLL:index: accepts any dictionary that provides mappings between strings and integers as its index parameter, although the indexFrom: method is the recommended mechanism for generating the index. The messagesFromDLL:index: method does not require a resource compiler input file to function. The following example illustrates the reconstruction of a dictionary containing localized messages from a dynamic link library:
"Answer a dictionary reconstructed from a DLL."
| converter index |
converter := RCConverter new.
index := converter indexFrom: 'demo.rc'.
^converter messagesFromDLL: 'demo.dll' index: index.
RCConverter limitations
Messages must be instances of String or DBString containing Characters whose values are strictly greater than zero (1 to 65535).
Note:
The resource file representation of a single Character can range from 1 to 4 bytes. Characters expanded in this manner are the special or nonprinting characters whose values are 1 through 31, 34, and 127. For example, (Character value: 7) has a resource file representation of: '\007.'
RCConverter error codes
All errors codes and their corresponding messages are detailed below. Each error code is associated with a descriptive error string and an error object, which is typically related to or the cause of the current error. This error object can be obtained by sending the message currentErrorObject to an instance of RCConverter. Similarly, the descriptive error string can be obtained by sending the message currentErrorString to an instance of RCConverter. The interpretation of the error object for each error follows.
Error code
Message
2
Error string: 'Message names cannot contain double byte characters.'
Error object: The invalid message name.
3
Error string: 'Message cannot contain characters of value < 2.'
Error object: The invalid message text.
4
Error string: 'Some of the messages contain non-string objects.'
Error object: The invalid message name.
5
Error string: 'Some of the messages contain empty strings. Messages cannot be empty strings.'
Error object: The invalid message text.
6
Error string: 'Invalid message name the phrase _part_ is a reserved token.'
Error object: The invalid message name.
7
Error string: 'File Error: Could not open specified file.'
Error object: File name (String) of the file that could not be opened.
8
Error string: 'Could not open DLL'
Error object: File name (String) of the DLL that could not be opened.
9
Error string: 'Could read messages from DLL.'
Error object: The integer identifier of the unreadable message.
10
Error string: 'Could not close resource DLL.'
Error object: The module handle that could not be closed.
11
Error string: 'Could not read index from resource file DLL.'
Error object: File name (String) of the invalid resource file.