-
Notifications
You must be signed in to change notification settings - Fork 10
Messages and National Language Support for toolkits
IBM Streams supports globalized messages with unique message IDs. Each toolkit can implement it's own set of messages. The messages are collected in resource files in the toolkit file structure. There are 2 kinds of resources:
- XLF resources - You can use this message interface in SPL, Perl, and C/C++ code
- .properties resources - You can use this message interface in java code
You can load and format string resources for different locales by using the tools that are provided with IBM Streams.
The messages are present at different outputs of IBM Streams, for example in Streams Console or Streams Studio. But not each message is the part of the resource specification for globalizing. The application trace is an example of the messages that does not need the resource specification.
The messages are addressed to application users and administrators. The application LOGs for operation teams, the help pages, or the compiler outputs in Streams Studio are examples of messages that must be defined in resource files.
The message ID is the unique identifier that is a global resource in the IBM Streams application. The format of the message IDs is described in IBM Knowledge Center: https://www.ibm.com/support/knowledgecenter/SSCRJU_4.2.0/com.ibm.streams.msg.doc/doc/rnamingmessageids.html
Each message specification has a text identifier with a toolkit-specific prefix, for example NETWORK_. The identifier is the value of the extraData attribute in the XLF file and it is the key of the property in the java resource property file.
A XLF example (NETWORK_):
<trans-unit id="StreamsNetworkToolkitMessages_CDIST0253E"
extraData="NETWORK_MISSING_PARAMETER_PCAP_FILENAME_OR_INPUT_PORT"
resname="CDIST0253E">
<source>Sorry, either ''pcapFilename'' parameter or an input port must be specified.</source>
</trans-unit>
A Java example (HBASE_):
HBASE_DEL_CONSISTENT_REGION=CDIST2901E When in a consistent region ''{0}'' must be true for ''{1}''
Each resource file needs an entry in the info.xml file. One of the resource files must have the default attribute. The XLF file must be located in the following subfolder of the toolkit directory:
<toolkit-directory>/impl/nl/<language>/
The different languages are separated by directories, for example:
<toolkit-directory>/impl/nl/en_US/Resources.xlf
<toolkit-directory>/impl/nl/es_ES/Resources.xlf
The spl-make-toolkit tool uses references from the info.xml to generate a header file (.h), a Perl module (.pm) and a binary data file (.dat) from the resource files.
The binary data file is located in directory:
<toolkit-directory>/impl/nl/
The Perl module and the header file are located in directory:
<toolkit-directory>/impl/nl/include
The details are described in IBM Knowledge Center: https://www.ibm.com/support/knowledgecenter/en/SSCRJU_4.2.0/com.ibm.streams.dev.doc/doc/creatingatoolkitforglobalization.html
An example of the message implementation is the Localization sample that is installed in the $STREAMS_INSTALL/samples/spl/features/Localization directory
Java resources use the java specific globalization process. This description is one of the possible java solutions.
Many toolkits implement the .properties files in the class path of java code to specify the NL resource properties, for example:
<toolkit-directory>/impl/java/src/com/ibm/streamsx/<toolkit-name>/Messages.properties
The different languages are separated by file name decoration, for example:
<toolkit-directory>/impl/java/src/com/ibm/streamsx/<toolkit-name>/Messages_en_US.properties
<toolkit-directory>/impl/java/src/com/ibm/streamsx/<toolkit-name>/Messages_es_ES.properties
The properties file must specify the message format handling that is processed by the MessageFormat class. The most used settings for NLS are:
# NLS_MESSAGEFORMAT_VAR
# NLS_ENCODING=UNICODE
The input parameter value that must be a part of the message, is indexed from 0 and formatted in curly braces, for example {0}. The single quote must be redoubled from a single quote ' to two single quotes ''.
The example of the Messages_en_US.properties file:
# NLS_MESSAGEFORMAT_VAR
# NLS_ENCODING=UNICODE
#
# com.ibm.streamsx.my_toolkit.i18n MSG001 - MSG199
#
THE_ERROR_MESSAGE_EXAMPLE=MSG001E The following file cannot be found: ''{0}''
THE_INFO_MESSAGE_EXAMPLE=MSG002I The application finished successful.
The XLF resources support SPL, Perl, and C/C++ interfaces. The .properties resources support the Java interface. If you need the same message in SPL and in Java, you must specify the message twice by using the same message text.
The APIs:
-
SPL provides functions:
rstring loadAndFormatResource(ToolkitName, BundleName, rstring resname, T tuple) rstring loadAndFormatResource(ToolkitName, BundleName, rstring resname, T tuple, rstring locale) rstring loadAndFormatResource(ToolkitName, BundleName, rstring resname) rstring loadAndFormatResource(ToolkitName, BundleName, rstring resname, rstring locale)
This is an example of a potential function call in the streamsx.network toolkit:
mutable rstring text = loadAndFormatResource("com.ibm.streamsx.network", "NetworkResources", "CDIST0257E", { operatorName="AnOperator" });
-
C/C++ generates a set of defines in the header:
#define MESSAGE_IDENTIFIER_FROM_EXTRA_DATA_X \ (::SPL::FormattableMessage0(<toolkit-name>, <resource-name>, <path-to-xlf>, <message-id>,<default-text>, true) #define MESSAGE_IDENTIFIER_FROM_EXTRA_DATA_Y(p0) \ (::SPL::FormattableMessage1<typeof(p0)>(<toolkit-name>, <resource-name>, <path-to-xlf>, <message-id>,<default-text>, true, p0)) #define MESSAGE_IDENTIFIER_FROM_EXTRA_DATA_Z(p0, p1) \ (::SPL::FormattableMessage2<typeof(p0),typeof(p1)>(<toolkit-name>, <resource-name>, <path-to-xlf>, <message-id>,<default-text>, true, p0, p1))
This is an example for NetworkResources bundle and NETWORK_LESS_FIELDS_IN_RECORD message in the streamsx.network toolkit:
#include "NetworkResources.h" ... SPLAPPLOG(L_ERROR, NETWORK_LESS_FIELDS_IN_RECORD(lineTokens.size(), MIN_BLOCKSFILE_FIELD_COUNT, line), IP_SPATIAL);
-
Perl generates a set of subfunctions
sub <PREFIX>_THE_MESSAGE_IDENTIFIER_FROM_EXTRA_DATA_X() { my $defaultText = <<'::STOP::'; Default text message X. ::STOP:: return SPL::Helper::SPLFormattedMessageWithResname($toolkitRoot, <toolkit-name>,<resource-name>, <path-to-xlf>, <message-id>, \$defaultText, @_); } sub <PREFIX>_THE_MESSAGE_IDENTIFIER_FROM_EXTRA_DATA_X($) { my $defaultText = <<'::STOP::'; Default text message X with parameter {0}. ::STOP:: return SPL::Helper::SPLFormattedMessageWithResname($toolkitRoot, <toolkit-name>,<resource-name>, <path-to-xlf>, <message-id>, \$defaultText, @_); }
This is an example for the NetworkResources bundle and NETWORK_NO_OUTPUT_PORTS message in the streamsx.network toolkit:
require NetworkResources; ... SPL::CodeGen::exit(NetworkResources::NETWORK_NO_OUTPUT_PORTS()) unless scalar(@outputPortList);
A detailed description is in IBM Knowledge Center: https://www.ibm.com/support/knowledgecenter/en/SSCRJU_4.2.0/com.ibm.streams.dev.doc/doc/globalizationsample.html
The major steps are:
-
specify the bundle by calling the getBundle():
// <classpath=com.ibm.streamsx.messaging.i18n>.<bundle=CommonMessages> private static final String BUNDLE_NAME = "com.ibm.streamsx.messaging.i18n.CommonMessages"; private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME);
-
get the message by calling the getString():
// key: message property key String msg = RESOURCE_BUNDLE.getString(key);
An example of the Messages class that uses the ResourceBundle class to fetch the message text is implemented in the streamsx.messaging toolkit: https://github.com/IBMStreams/streamsx.messaging/blob/master/com.ibm.streamsx.messaging/impl/java/src/com/ibm/streamsx/messaging/i18n/Messages.java
The example shows how to format the message and how to handle message parameters.
For a detailed description, go to the Java tutorial: http://docs.oracle.com/javase/tutorial/i18n/
If you need more messages for an existing project that uses resource bundles, open an issue with request for the message ID range. The project committer provides the information about the range that the project specifies.
The CDISTxxxx message ID range is reserved for toolkits that are part of the IBM Streams product. The committer, who supports the product deliveries, is responsible for the translation of the CDISTxxxx messages.
If you have a new toolkit project and you are going to use the resource bundles for globalization, specify your own unique message ID range. Before the project can become part of the IBM Streams product, the message IDs must be changed to match the product requirements.