version 1.2, 2003/07/30 12:34:07
|
version 1.6.38.1, 2007/01/30 18:59:01
|
|
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> |
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en"> |
<html> | <html> |
<head> | <head> |
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
<meta http-equiv="Content-Type" |
<meta name="GENERATOR" content="Mozilla/4.76 [en] (X11; U; Linux 2.4.2-2 i686) [Netscape]"> |
content="text/html; charset=iso-8859-1"> |
|
<meta name="GENERATOR" |
|
content="Mozilla/4.78 [en] (X11; U; Linux 2.4.7-10 i686) [Netscape]"> |
</head> | </head> |
<body text="#000000" bgcolor="#FFFFFF" link="#0000EF" vlink="#55188A" alink="#FF0000"> |
<body text="#000000" bgcolor="#ffffff" link="#0000ef" vlink="#55188a" |
|
alink="#ff0000"> |
<center><font size=+4>Globalization HOWTO</font> |
<center> |
<p>Release: Pegasus 2.3 |
<p><big><big><big>Globalization HOWTO</big></big></big></p> |
<p>Author: Chuck Carmack (carmack@us.ibm.com) |
<p>Release: Pegasus 2.3 </p> |
<p>July 28, 2003</center> |
<p>Author: Chuck Carmack (carmack@us.ibm.com) </p> |
|
<p>December 1, 2003</p> |
|
</center> |
<p><br> | <p><br> |
<h2> |
Change History:<br> |
1.0 Introduction</h2> |
</p> |
|
<table cellpadding="2" cellspacing="2" border="1" |
<p><br>As part of the Pegasus 2.3 release, functions were added for globalization |
style="text-align: left; width: 100%; margin-left: auto; margin-right: auto;"> |
support. Globalization involves two major aspects: internationalization |
<tbody> |
and localization. |
<tr> |
<br> |
<td style="vertical-align: top;">01/12/03<br> |
<p>Internationalization is the process of writing a program that is locale-neutral. |
</td> |
In other words, the program should be able to run in any locale without |
<td style="vertical-align: top;">carmack<br> |
change. There are several categories in a locale, including the language |
</td> |
of message strings, date format, time format, etc. For release 2.3, |
<td style="vertical-align: top;">Section 2.2.2. Changed how |
the Pegasus server is concerned with the language of the message strings |
the package name parameter should be used. It should no longer be |
it returns to its clients. |
used as part of the table name inside the bundle.<br> |
<br> |
</td> |
<p>To support internationalization, a program is designed to do the following: |
</tr> |
<br> |
<tr> |
<blockquote> |
<td style="vertical-align: top;">01/23/07<br> |
<li> |
</td> |
Support character sets that can represent customer data in any language. |
<td style="vertical-align: top;">Sushma Fernandes<br> |
Typically, the program supports some variation of Unicode for internal |
</td> |
data. There is usually some conversion between the supported character |
<td style="vertical-align: top;">Section 2.2.5. Added information on special considerations while creating a new message.<br> |
sets for external data, and the internal character set. Since Unicode |
</td> |
covers all characters, and usually has converters on the platform, it is |
</tr> |
a good choice for the 'normalized' internal character set. |
</tbody> |
The most 'interoperable' solution for external data is to support UTF-8 |
</table> |
(eg. network and file system data). The internal data is usually |
<p><br> |
UTF-16 (or UCS-2, but that is deprecated).</li> |
</p> |
|
<h2> 1.0 Introduction</h2> |
<br> |
<p><br> |
<li> |
As part of the Pegasus 2.3 release, functions were added for |
Extract locale-sensitive resources, such as message strings, from the code |
globalization support. Globalization involves two major |
to external resource files. Typically, the resources are loaded based |
aspects: internationalization and localization. <br> |
on the locale requested by the end-user, and returned to the end-user for |
</p> |
display.</li> |
<p>Internationalization is the process of writing a program that is |
|
locale-neutral. In other words, the program should be able to run |
|
in any locale without change. There are several categories in a |
|
locale, including the language of message strings, date format, time |
|
format, etc. For release 2.3, the Pegasus server is concerned with |
|
the language of the message strings it returns to its clients. <br> |
|
</p> |
|
<p>To support internationalization, a program is designed to do the |
|
following: <br> |
|
</p> |
|
<blockquote> <li> Support character sets that can represent customer |
|
data in any language. Typically, the program supports some |
|
variation of Unicode for internal data. There is usually some |
|
conversion between the supported character sets for external data, and |
|
the internal character set. Since Unicode covers all characters, |
|
and usually has converters on the platform, it is a good choice for the |
|
'normalized' internal character set. The most |
|
'interoperable' solution for external data is to support UTF-8 (eg. |
|
network and file system data). The internal data is usually UTF-16 |
|
(or UCS-2, but that is deprecated).</li> |
|
<br> |
|
<li> Extract locale-sensitive resources, such as message |
|
strings, from the code to external resource files. Typically, the |
|
resources are loaded based on the locale requested by the end-user, and |
|
returned to the end-user for display.</li> |
</blockquote> | </blockquote> |
|
<p><br> |
<p><br>Localization is the process of customizing a software product to |
Localization is the process of customizing a software product to |
support particular locales. For example, a product that is internationalized |
support particular locales. For example, a product that is |
might want to only localize for certain countries. This would mean |
internationalized might want to only localize for certain |
that the localized resources (eg. message files) would only be translated |
countries. This would mean that the localized resources (eg. |
and shipped for the countries that the product supports. Since the |
message files) would only be translated and shipped for the countries |
code for the product is locale-neutral, it will be easy to drop in new |
that the product supports. Since the code for the product is |
translations as more countries are supported. |
locale-neutral, it will be easy to drop in new translations as more |
<br> |
countries are supported. <br> |
|
</p> |
<p>The Pegasus 2.3 release added support for globalization. At a | <p>The Pegasus 2.3 release added support for globalization. At a |
high-level, the following additions were made to Pegasus 2.3: |
high-level, the following additions were made to Pegasus 2.3: <br> |
<br> |
</p> |
<ul> | <ul> |
<li> |
<li> Support UTF-8 for external data.</li> |
Support UTF-8 for external data.</li> |
<br> |
|
|
<br> |
|
<ul> | <ul> |
<li> |
<li> The CIM-XML documents contained in the HTTP messages</li> |
The CIM-XML documents contained in the HTTP messages</li> |
<li> The files in the repository</li> |
|
<li> Note: Pegasus 2.3 does NOT support UTF-8 in the MOF |
<li> |
files</li> |
Repository files and MOF files (<b>TODO</b> - remove MOF files if |
<br> |
we can't get this into 2.3)</li> |
|
</ul> | </ul> |
|
<li> Support UTF-16 for internal data.</li> |
<li> |
<br> |
Support UTF-16 for internal data.</li> |
<li> Extract the hardcoded messages from the Pegasus code into |
|
message files. An API was added to load messages from the message |
<br> |
files.</li> |
<li> |
<br> |
Extract the hardcoded messages from the Pegasus code into message files. |
<li> APIs were added for clients to associate a language with |
An API was added to load messages from the message files.</li> |
the CIM objects they are sending to Pegasus. Also, APIs were added |
|
for clients to determine the language of the error message or CIM |
<br> |
object that Pegasus returns.</li> |
<li> |
<br> |
APIs were added for clients to associate a language with the CIM objects |
<li> APIs were added for providers to determine the language of |
they are sending to Pegasus. Also, APIs were added for clients to |
CIM objects sent by the client. Also, APIs were added for |
determine the language of the error message or CIM object that Pegasus |
providers to associate a language with the CIM object, or error message, |
returns.</li> |
they return to the client.</li> |
|
|
<br> |
|
<li> |
|
APIs were added for providers to determine the language of CIM objects |
|
sent by the client. Also, APIs were added for providers to associate |
|
a language with the CIM object, or error message, they return to the client.</li> |
|
</ul> | </ul> |
|
<p><br> |
<p><br>Please refer to PEPs 56 and 58 for details about the globalization |
Please refer to PEPs 56 and 58 for details about the globalization |
design in Pegasus 2.3. |
design in Pegasus 2.3. <br> |
<br> |
</p> |
<p>This document provides a HOWTO guide to be used by developers to globalize |
<p>This document provides a HOWTO guide to be used by developers to |
code that is being added to Pegasus. The audience for this document |
globalize code that is being added to Pegasus. The audience for |
are: |
this document are: <br> |
<br> |
</p> |
<ul> | <ul> |
<li> |
<li> Provider developers - both CMPI and C++</li> |
Provider developers - both CMPI and C++</li> |
<li> Client developers</li> |
|
<li> Pegasus developers</li> |
<li> |
|
Client developers</li> |
|
|
|
<li> |
|
Pegasus developers</li> |
|
</ul> | </ul> |
|
<p><br> |
<p><br>The quickest way to approach this document is to read the General |
The quickest way to approach this document is to read the General |
section, and then the developer section that relates to what you are doing. |
section, and then the developer section that relates to what you are |
<br> |
doing. <br> |
<h2> |
</p> |
2.0 General</h2> |
<h2> 2.0 General</h2> |
| |
<h3> |
<h3> 2.1 Unicode Support</h3> |
2.1 Unicode Support</h3> |
<p><br> |
|
Pegasus 2.3 supports Unicode throughout the processing of |
<p><br>Pegasus 2.3 supports Unicode throughout the processing of requests. |
requests. External data to Pegasus is encoded in UTF-8. |
External data to Pegasus is encoded in UTF-8. Internal data is encoded |
Internal data is encoded in UTF-16. <br> |
in UTF-16. |
</p> |
<br> |
<p>UTF-8 support for external data includes the CIM-XML messages passed |
<p>External data includes the CIM-XML messages passed over the network, |
over the network, and the repository files. Note: UTF-8 |
the repository files, and the MOF files. For the CIM-XML messages, |
support was NOT added to the MOF Compiler for MOF files in release |
Pegasus follows section 4.8 of the <a href="http://www.dmtf.org/standards/documents/WBEM/DSP200.html">CIM-HTTP |
2.3. For the CIM-XML messages, Pegasus follows section 4.8 of |
|
the <a |
|
href="http://www.dmtf.org/standards/documents/WBEM/DSP200.html">CIM-HTTP |
specification</a> Specifically, Pegasus supports the | specification</a> Specifically, Pegasus supports the |
"utf-8" setting for the charset parameter of the Content-Type header and | "utf-8" setting for the charset parameter of the Content-Type header and |
the XML encoding attribute. If no charset is specified, the 7-bit | the XML encoding attribute. If no charset is specified, the 7-bit |
ASCII is assumed. The Pegasus MOF compiler supports UTF-8 encoding |
ASCII is assumed. <br> |
in the MOF files. (<b>TODO</b> - remove this statement if this is |
</p> |
not in 2.3) |
|
<br> |
|
<p>The internal support of UTF-16 is encapsulated in the Pegasus String | <p>The internal support of UTF-16 is encapsulated in the Pegasus String |
class. This class has been updated to contain UTF-16 characters. |
class. This class has been updated to contain UTF-16 |
Specifically, the Char16 objects inside the String contain UTF-16 characters. |
characters. Specifically, the Char16 objects inside the String |
Note: a UTF-16 surrogate pair is contained in two consecutive Char16 objects. |
contain UTF-16 characters. Note: a UTF-16 surrogate pair is |
To keep backwards compatibilty, the methods on the String class have not |
contained in two consecutive Char16 objects. To keep backwards |
changed. New methods have been added as needed. The following |
compatibilty, the methods on the String class have not changed. |
describes this in more detail: |
New methods have been added as needed. The following describes |
|
this in more detail: </p> |
<ul> | <ul> |
<li> |
<li> The Pegasus 2.2 methods that take a char *, or return char *, are |
The Pegasus 2.2 methods that take a char *, or return char *, are unchanged. |
unchanged. Code written to Pegasus 2.2 may have expected to store |
Code written to Pegasus 2.2 may have expected to store 8-bit ASCII (ISO-8859-1) |
8-bit ASCII (ISO-8859-1) characters into String. These methods |
characters into String. These methods will convert the input to UTF-16 |
will convert the input to UTF-16 from 8-bit ASCII. (This is simple |
from 8-bit ASCII. (This is simple because UTF-16 is a superset of |
because UTF-16 is a superset of 8-bit ASCII - simply need to prepend |
8-bit ASCII - simply need to prepend '\0' to each char). The Pegasus |
'\0' to each char). The Pegasus 2.2 methods that return char data |
2.2 methods that return char data will attempt to convert from the UTF-16 |
will attempt to convert from the UTF-16 internal representation to |
internal representation to 8-bit ASCII. Characters that cannot be |
8-bit ASCII. Characters that cannot be converted will be replaced |
converted will be replaced with a substitution character.</li> |
with a substitution character.</li> |
|
<br> |
<br> |
<li> All methods that take or return Char16 data are |
<li> |
unchanged. The String class now supports UTF-16 data in Char16, |
All methods that take or return Char16 data are unchanged. The String |
although surrogate pairs will require two consecutive Char16 |
class now supports UTF-16 data in Char16, although surrogate pairs will |
objects. The String class does NO checking for unmatched surrogate |
require two consecutive Char16 objects. The String class does NO |
pairs.</li> |
checking for unmatched surrogate pairs.</li> |
<br> |
|
<li> New methods have been added to take and return UTF-8 |
<br> |
data. The String class will convert between UTF-8 and the UTF-16 |
<li> |
internal representation as needed. These new methods will use char |
New methods have been added to take and return UTF-8 data. The String |
* parameters, but will be clearly labelled as UTF-8 methods.</li> |
class will convert between UTF-8 and the UTF-16 internal representation |
<br> |
as needed. These new methods will use char * parameters, but will |
|
be clearly labelled as UTF-8 methods.</li> |
|
|
|
<br> </ul> |
|
PROGRAMMING NOTE: Putting EBCDIC data into the String class is dangerous. |
|
The String class is designed for UTF-16, which is a superset of 8-bit ASCII. |
|
Any String object containing EBCDIC data will not work if it is used by |
|
Pegasus to read or write data from external sources, such as the network |
|
or repository files. In other words, any String containing EBCDIC |
|
data should not leave the code using it. |
|
<br> |
|
<br> |
|
<h3> |
|
2.2 Localization Support</h3> |
|
| |
<h4> |
</ul> |
2.2.1 Language Headers</h4> |
PROGRAMMING NOTE: Putting EBCDIC data into the String class is |
|
dangerous. The String class is designed for UTF-16, which is a |
<p><br>Pegasus 2.3 supports clients and providers that wish to localize. |
superset of 8-bit ASCII. Any String object containing EBCDIC data |
There are two areas to be localized: <a href="http://www.dmtf.org/standards/documents/WBEM/DSP201.html#SecERROR">ERROR</a> |
will not work if it is used by Pegasus to read or write data from |
elements in the CIM-XML; and <a href="http://www.dmtf.org/standards/documents/WBEM/DSP201.html#SecObjectDefinitionElements">Object |
external sources, such as the network or repository files. In |
Definition</a> elements in the CIM-XML. Clients can request |
other words, any String containing EBCDIC data should not leave the code |
the server to return error messages and CIM objects in a set of languages |
using it. <br> |
of their choosing. Clients can also tag a language to the CIM objects |
<br> |
they are sending to the server. Providers and the server can return |
|
error messages and CIM objects that are tagged with one of languages |
<h3> 2.2 Localization Support</h3> |
requested by the client. |
|
<br> |
<h4> 2.2.1 Language Headers</h4> |
<p>The localization design is based on section 4.8 of the <a href="http://www.dmtf.org/standards/documents/WBEM/DSP200.html">CIM-HTTP |
<p><br> |
specification</a> , which refers to <a href="http://www.ietf.org/rfc/rfc2616.txt?number=2616">RFC |
Pegasus 2.3 supports clients and providers that wish to localize. |
2616</a>. The method used to tag a language to the CIM-XML is through |
There are two areas to be localized: <a |
the Accept-Language and Content-Language HTTP headers. These headers |
href="http://www.dmtf.org/standards/documents/WBEM/DSP201.html#SecERROR">ERROR</a> |
|
elements in the CIM-XML; and <a |
|
href="http://www.dmtf.org/standards/documents/WBEM/DSP201.html#SecObjectDefinitionElements">Object |
|
Definition</a> elements in the CIM-XML. Clients can |
|
request the server to return error messages and CIM objects in a |
|
set of languages of their choosing. Clients can also tag a |
|
language to the CIM objects they are sending to the server. |
|
Providers and the server can return error messages and CIM objects that |
|
are tagged with one of languages requested by the client. <br> |
|
</p> |
|
<p>The localization design is based on section 4.8 of the <a |
|
href="http://www.dmtf.org/standards/documents/WBEM/DSP200.html">CIM-HTTP |
|
specification</a> , which refers to <a |
|
href="http://www.ietf.org/rfc/rfc2616.txt?number=2616">RFC 2616</a>. |
|
The method used to tag a language to the CIM-XML is through the |
|
Accept-Language and Content-Language HTTP headers. These headers |
are basically lists of language tags. An HTTP request can contain | are basically lists of language tags. An HTTP request can contain |
an Accept-Language header, which indicates the list of preferred languages |
an Accept-Language header, which indicates the list of preferred |
that the client wants in the response. This list can be prioritized |
languages that the client wants in the response. This list can be |
by using the quality numbers. An HTTP request or response can contain |
prioritized by using the quality numbers. An HTTP request or |
a Content-Language header, which indicates the language(s) of the content |
response can contain a Content-Language header, which indicates the |
in the message. In the Pegasus case, this would be the CIM-XML. |
language(s) of the content in the message. In the Pegasus case, |
Note that the Content-Language header is a list of language tags. |
this would be the CIM-XML. Note that the Content-Language header |
This allows the content of an HTTP message to contain more than one translation. |
is a list of language tags. This allows the content of an HTTP |
However, in the Pegasus case, there is only one CIM-XML document in the |
message to contain more than one translation. However, in the |
HTTP message, and thus one translation. |
Pegasus case, there is only one CIM-XML document in the HTTP message, |
<br> |
and thus one translation. <br> |
<p>CIM clients may use the Accept-Language HTTP header to specify the languages |
</p> |
they wish to be returned in the CIM response message. CIM clients |
<p>CIM clients may use the Accept-Language HTTP header to specify the |
may also use the Content-Language header to tag the language of any CIM |
languages they wish to be returned in the CIM response message. |
objects they are sending to the server in the CIM request message. |
CIM clients may also use the Content-Language header to tag the language |
The server, and providers, should attempt to return error messages and |
of any CIM objects they are sending to the server in the CIM request |
CIM objects in one of the accept languages requested by the client. |
message. The server, and providers, should attempt to return |
The server and providers should set the Content-Language header in the |
error messages and CIM objects in one of the accept languages requested |
CIM response message to indicate which of the requested languages they |
by the client. The server and providers should set the |
are returning. |
Content-Language header in the CIM response message to indicate which of |
<br> |
the requested languages they are returning. <br> |
|
</p> |
<p>NOTE: Localization support was not added for the MOF files and | <p>NOTE: Localization support was not added for the MOF files and |
repository in Pegasus 2.3. The #pragma locale, #pragma instancelocale, |
repository in Pegasus 2.3. The #pragma locale, #pragma |
and translatable qualifier flavor are not supported in the Pegasus 2.3 |
instancelocale, and translatable qualifier flavor are not supported in |
MOF compiler. From the client perspective, classes, qualifiers, and |
the Pegasus 2.3 MOF compiler. From the client perspective, |
instances stored in the repository are not tagged with a language. |
classes, qualifiers, and instances stored in the repository are not |
The Accept-Language and Content-Language headers will be ignored for repository |
tagged with a language. The Accept-Language and Content-Language |
operations. However, since the repository will support UTF-8, |
headers will be ignored for repository operations. However, since |
characters for any language may be stored there. |
the repository will support UTF-8, characters for any language may |
<br> |
be stored there. <br> |
|
</p> |
<p>NOTE: Since the Content-Language header applies to the entire | <p>NOTE: Since the Content-Language header applies to the entire |
HTTP message, it applies to the entire CIM-XML document. This includes |
HTTP message, it applies to the entire CIM-XML document. This |
all the objects in the document, including enumerated objects, and all |
includes all the objects in the document, including enumerated objects, |
the values in the objects. This is a limitation that will remain |
and all the values in the objects. This is a limitation that will |
until the CIM standard has been updated to support language tags tied to |
remain until the CIM standard has been updated to support language tags |
individual CIM values. From the client perspective, it is possible |
tied to individual CIM values. From the client perspective, it is |
for Pegasus to send a CIM response with NO Content-Language, even if the |
possible for Pegasus to send a CIM response with NO Content-Language, |
client had sent Accept-Language. This can happen if Pegasus |
even if the client had sent Accept-Language. This can happen |
does not know the language of the response. An example is a request |
if Pegasus does not know the language of the response. An example |
that was sent to a Pegasus 2.2 provider. Another example is an enumerated |
is a request that was sent to a Pegasus 2.2 provider. Another |
response where each provider returned a different language. Please |
example is an enumerated response where each provider returned a |
refer to PEP58 for details on these provider scenarios. |
different language. Please refer to PEP58 for details on these |
<br> |
provider scenarios. <br> |
<p>Pegasus 2.3 has added classes for the localization support. There |
</p> |
are new classes called AcceptLanguages and ContentLanguages that encapsulate |
<p>Pegasus 2.3 has added classes for the localization support. |
the Accept-Language and Content-Language headers, respectively. These |
There are new classes called AcceptLanguages and ContentLanguages that |
classes are basically containers of AcceptLanguageElement and ContentLanguageElement, |
encapsulate the Accept-Language and Content-Language headers, |
where a language element represents one language tag. The AcceptLanguages |
respectively. These classes are basically containers of |
class will keep the AcceptLanguageElement's prioritized based on quality, |
AcceptLanguageElement and ContentLanguageElement, where a language |
according to RFC 2616. |
element represents one language tag. The AcceptLanguages class |
<br> |
will keep the AcceptLanguageElement's prioritized based on quality, |
<p>AcceptLanguages and ContentLanguages are the objects used by code throughout |
according to RFC 2616. <br> |
the request/response processing, from the client to the server to the providers |
</p> |
and back. The server handles the creation of these objects from the |
<p>AcceptLanguages and ContentLanguages are the objects used by code |
HTTP headers. Code at each point in the process will have access |
throughout the request/response processing, from the client to the |
to these objects. |
server to the providers and back. The server handles the creation |
<br> |
of these objects from the HTTP headers. Code at each point in the |
<p>Please refer to the following files for details on the new Pegasus classes. |
process will have access to these objects. <br> |
<br> |
</p> |
|
<p>Please refer to the following files for details on the new Pegasus |
|
classes. <br> |
|
</p> |
<ul> | <ul> |
<li> |
<li> pegasus/src/Pegasus/Common/AcceptLanguages.h</li> |
pegasus/src/Pegasus/Common/AcceptLanguages.h</li> |
<li> pegasus/src/Pegasus/Common/AcceptLanguageElement.h</li> |
|
<li> pegasus/src/Pegasus/Common/ContentLanguages.h</li> |
<li> |
<li> pegasus/src/Pegasus/Common/ContentLanguageElement.h</li> |
pegasus/src/Pegasus/Common/AcceptLanguageElement.h</li> |
<li> pegasus/src/Pegasus/Common/LanguageElementContainer.h</li> |
|
<li> pegasus/src/Pegasus/Common/LanguageElement.h</li> |
<li> |
|
pegasus/src/Pegasus/Common/ContentLanguages.h</li> |
|
|
|
<li> |
|
pegasus/src/Pegasus/Common/ContentLanguageElement.h</li> |
|
|
|
<li> |
|
pegasus/src/Pegasus/Common/LanguageElementContainer.h</li> |
|
|
|
<li> |
|
pegasus/src/Pegasus/Common/LanguageElement.h</li> |
|
</ul> | </ul> |
|
<p><br> |
<p><br>See the sections below for details on how to write clients and providers |
See the sections below for details on how to write clients and |
to use these classes. |
providers to use these classes. <br> |
<br> |
<br> |
<br> |
</p> |
<h4> |
<h4> 2.2.2 Message Bundles</h4> |
2.2.2 Message Bundles</h4> |
<p><br> |
|
One of the goals of globalization for Pegasus 2.3 is the extraction of |
<p><br>One of the goals of globalization for Pegasus 2.3 is the extraction |
hardcoded messages into translated message files, loading |
of hardcoded messages into translated message files, loading translated |
translated messages from those files, and returning those messages to |
messages from those files, and returning those messages to the client. |
the client. The topics to be discussed here are: how to |
The topics to be discussed here are: how to create message files, |
create message files, how to compile message files, and how to load |
how to compile message files, and how to load messages into Pegasus. |
messages into Pegasus. <br> |
<br> |
</p> |
<p>At the time of writing, the message loading function in Pegasus 2.3 | <p>At the time of writing, the message loading function in Pegasus 2.3 |
used the International Components for Unicode (<a href="http://oss.software.ibm.com/icu">ICU)</a> |
used the International Components for Unicode (<a |
libraries. This is expected to be the future direction for Pegasus. |
href="http://oss.software.ibm.com/icu">ICU)</a> libraries. This |
<a href="http://oss.software.ibm.com/icu">ICU |
is expected to be the future direction for Pegasus. <a |
</a>uses |
href="http://oss.software.ibm.com/icu">ICU </a>uses a resource bundle |
a resource bundle format for their message files. In order |
format for their message files. In order to load the |
to load the messages, ICU requires that the resource bundles are compiled |
messages, ICU requires that the resource bundles are compiled into a |
into a binary form (.res file) using their genrb tool. |
binary form (.res file) using their genrb tool. <br> |
<br> |
</p> |
<p>Platform Maintainers Note: Please refer to PEP 58 for information |
<p>Platform Maintainers Note: Please refer to PEP 58 for |
about how to build Pegasus to use the ICU libraries. |
information about how to build Pegasus to use the ICU libraries. <br> |
<br> |
</p> |
<p>The documentation for ICU resource bundles is in the <a href="http://oss.software.ibm.com/icu/userguide/ResourceManagement.html">Resource |
<p>The documentation for ICU resource bundles is in the <a |
Management</a> section of the <a href="http://oss.software.ibm.com/icu/userguide/">ICU |
href="http://oss.software.ibm.com/icu/userguide/ResourceManagement.html">Resource |
User Guide</a> . This section will tell you how to |
Management</a> section of the <a |
<br>create and organize your resource bundles for different languages. |
href="http://oss.software.ibm.com/icu/userguide/">ICU User Guide</a> |
Note: your resource bundles should be organized in a tree structure |
. This section will tell you how to create and organize your |
similiar to the one shown in the Resource Management section, including |
resource bundles for different languages. Note: your |
the empty bundles in the tree. It is recommended that you ship a |
resource bundles should be organized in a tree structure similiar to |
root resource bundle to be used as the fallback in case the client requests |
the one shown in the Resource Management section, including the empty |
a language that you are not supporting. |
bundles in the tree. <br> |
<br> |
</p> |
|
<p><br> |
|
It is recommended that you ship a root resource bundle to be used as |
|
the fallback in case the client requests a language that you are not |
|
supporting. The Pegasus make files are set up to automatically |
|
create and compile a root resource bundle for you. For Pegasus |
|
2.3, the make will use your "en" bundle, upper case all the messages, |
|
and then put the uppercased messages into the root bundle. The |
|
uppercasing of the messages is necessary to create a "fallback" root |
|
bundle that contains invariant characters across all EBCDIC and |
|
ASCII codepages. <br> |
|
</p> |
|
<p>NOTE: When creating your resource bundles, the name of the |
|
table resource should <span style="font-style: italic;">not</span> |
|
contain the package name. For example, if you <br> |
|
have a bundle with a package name of "xyz", then the "en" bundle should |
|
start like this: </p> |
|
<p><br> |
|
en:table { <br> |
|
..... messages here <br> |
|
|
|
}</p> |
|
<p><i>not</i> like this:</p> |
|
<p>xyz_en:table { <br> |
|
..... messages here <br> |
|
|
|
} <br> |
|
<br> |
|
</p> |
|
<p>This is needed because the package name (-p) option is used by the |
|
Pegasus make files on the call to genrb. <br> |
|
</p> |
<p>NOTE: Pegasus 2.3 only supports simple string resources in the | <p>NOTE: Pegasus 2.3 only supports simple string resources in the |
ICU resource bundles. String resources may only be loaded by key. |
ICU resource bundles. String resources may only be loaded by |
Tables, arrays, and other complex resource types, are not supported. |
key. Tables, arrays, and other complex resource types, are not |
<br> |
supported. <br> |
|
</p> |
<p>In order to compile your resource bundles, support has been added to | <p>In order to compile your resource bundles, support has been added to |
the Pegasus make files to run genrb. A new make target, "messages", |
the Pegasus make files to run genrb. A new make target, |
has been added that will call genrb and put the compiled bundles (.res) |
"messages", has been added that will call genrb and put the compiled |
in a directory of your choosing. An example of ICU resource bundles |
bundles (.res) in a directory of your choosing. An example of ICU |
and the make files to compile them are located in: |
resource bundles and the make files to compile them are located in: <br> |
<br> |
</p> |
<ul> | <ul> |
<li> |
<li> pegasus/src/Providers/sample/LocalizedProvider/Makefile (just |
pegasus/src/Providers/sample/LocalizedProvider/Makefile (just causes the |
causes the make to recurse to the msg sub-directory)</li> |
make to recurse to the msg sub-directory)</li> |
<li> pegasus/src/Providers/sample/LocalizedProvider/msg/Makefile |
|
(compiles the bundles in the msg/ directory)</li> |
<li> |
<li> pegasus/src/Providers/sample/LocalizedProvider/msg/*.txt (the |
pegasus/src/Providers/sample/LocalizedProvider/msg/Makefile (compiles the |
resource bundles to compile, using the recommended ICU language tree |
bundles in the msg/ directory)</li> |
structure)</li> |
|
|
<li> |
|
pegasus/src/Providers/sample/LocalizedProvider/msg/*.txt (the resource |
|
bundles to compile, using the recommended ICU language tree structure)</li> |
|
</ul> | </ul> |
|
<p><br> |
<p><br>NOTE: At the time of writing, only the Linux make files have |
NOTE: At the time of writing, only the Linux make files have been |
been updated to compile ICU resource bundles. |
updated to compile ICU resource bundles. <br> |
<br> |
</p> |
<p>It is important to place the compiled resource bundles in a directory |
<p>It is important to place the compiled resource bundles in a |
where your code can find them . The make files above compile the |
directory where your code can find them . The make files above |
resource bundles into $PEGASUS_HOME/msg/provider/localizedProvider. |
compile the resource bundles into |
The code that loads these messages uses the MessageLoader class (next section) |
$PEGASUS_HOME/msg/provider/localizedProvider. The code that loads |
to load messages from this directory. |
these messages uses the MessageLoader class (next section) to load |
<br> |
messages from this directory. <br> |
<br> |
<br> |
<h4> |
</p> |
2.2.3 Message Loading</h4> |
<h4> 2.2.3 Message Loading</h4> |
|
<p><br> |
<p><br>Code that needs to load a message in Pegasus does not call ICU directly. |
Code that needs to load a message in Pegasus does not call ICU |
Two message loading classes were added for Pegasus 2.3: MessageLoader |
directly. Two message loading classes were added for Pegasus |
and MessageLoaderParms. These classes are abstractions designed to |
2.3: MessageLoader and MessageLoaderParms. These classes are |
hide of the actual loader used (but note that at the time of writing, only |
abstractions designed to hide of the actual loader used (but note that |
ICU is supported). The MessageLoader is used to load a message |
at the time of writing, only ICU is supported). The |
using a list of preferrred languages. The parameters to MessageLoader |
MessageLoader is used to load a message using a list of preferrred |
are encapsulated in a MessageLoaderParms object. |
languages. The parameters to MessageLoader are encapsulated in a |
<br> |
MessageLoaderParms object. <br> |
<p>The MessageLoader is the place where the Accept-Language header, Content-Language |
</p> |
header, and the ICU resource bundles, join up. The MessageLoader |
<p>The MessageLoader is the place where the Accept-Language header, |
class is designed to receive an AcceptLanguages object, and a set of parameters |
Content-Language header, and the ICU resource bundles, join up. |
indicating the bundle base-name and message ID to use. The AcceptLanguages |
The MessageLoader class is designed to receive an AcceptLanguages |
object contains the list of requested languages sent by the client. |
object, and a set of parameters indicating the bundle base-name and |
The MessageLoader searches for the message in the set of bundles named |
message ID to use. The AcceptLanguages object contains the list of |
with the base-name, using the AcceptLanguages for the list of specific |
requested languages sent by the client. The MessageLoader |
translated bundles to search. The MessageLoader returns the message |
searches for the message in the set of bundles named with the base-name, |
that it found, along with a ContentLanguages object indicating the language |
using the AcceptLanguages for the list of specific translated bundles |
of the message. The ContentLanguages object should be used to indicate |
to search. The MessageLoader returns the message that it found, |
the language of the response sent back to the client. |
along with a ContentLanguages object indicating the language of the |
<br> |
message. The ContentLanguages object should be used to indicate |
<p>The MessageLoaderParms object contains the parameters to load the message. |
the language of the response sent back to the client. <br> |
There are many parameters, but many can be allowed to default. Here |
</p> |
is a description of the parameters: |
<p>The MessageLoaderParms object contains the parameters to load the |
<br> |
message. There are many parameters, but many can be allowed to |
<br> |
default. Here is a description of the parameters: <br> |
<table BORDER COLS=3 WIDTH="100%" NOSAVE > |
<br> |
|
|
|
<table border="1" cols="3" width="100%" nosave=""> |
|
<tbody> |
<tr> | <tr> |
<td>String msg_id; </td> | <td>String msg_id; </td> |
|
<td>Input. <br> |
<td>Input. |
Required.</td> |
<br>Required.</td> |
<td>Message ID of the message to load from the resource |
|
bundle. This is the key that ICU will use to load the message.</td> |
<td>Message ID of the message to load from the resource bundle. |
|
This is the key that ICU will use to load the message.</td> |
|
</tr> | </tr> |
|
|
<tr> | <tr> |
<td>String default_msg;</td> | <td>String default_msg;</td> |
|
<td>Input. <br> |
<td>Input. |
Required</td> |
<br>Required</td> |
<td>Message to return if the no message can be loaded for msg_id |
|
from any resource bundle. Note: The args parameters below |
<td>Message to return if the no message can be loaded for msg_id from any |
are substituted into this string. <br> |
resource bundle. Note: The args parameters below are substituted |
Note: For the args into this string, use the Pegasus '$' |
into this string. |
form, as described in pegasus/src/Pegasus/Common/Formatter.h. |
<br>Note: For the args into this string, use the Pegasus '$' |
Don't use the ICU substitution format for the default message string.</td> |
form, as described in pegasus/src/Pegasus/Common/Formatter.h. Don't |
|
use the ICU substitution format for the default message string.</td> |
|
</tr> | </tr> |
|
|
<tr> | <tr> |
<td>String msg_src_path; </td> | <td>String msg_src_path; </td> |
|
<td>Input. <br> |
<td>Input. |
Optional <br> |
<br>Optional |
Default: $PEGASUS_HOME/msg/pegasus/pegasusServer</td> |
<br>Default: $PEGASUS_HOME/msg/pegasus/pegasusServer</td> |
<td>Path to the resource bundle file which contains the |
|
msg_id. <br> |
<td>Path to the root resource bundle file which contains the msg_id. |
Note: Only specify the path down to the bundle base-name. Do not |
<br>Note: Only specify the path down to the bundle base-name. Do |
append a language tag, such as "_root" or "_en". Do not append a |
not append a language tag, such as "_root" or "_en". Do not append |
file extension. <br> |
a file extension. |
Note: relative paths start at $PEGASUS_HOME/msg. <br> |
<br>Note: relative paths start at $PEGASUS_HOME/msg. |
Note: defaults to the bundle containing the Pegasus server messages.</td> |
<br>Note: defaults to the bundle containing the Pegasus server messages.</td> |
|
</tr> | </tr> |
|
|
<tr> | <tr> |
<td>AcceptLanguages acceptlanguages;</td> | <td>AcceptLanguages acceptlanguages;</td> |
|
<td>Input. <br> |
<td>Input. |
Optional <br> |
<br>Optional |
Default: AcceptLanguages::EMPTY</td> |
<br>Default: AcceptLanguages::EMPTY</td> |
<td>Contains the list of preferred languages, in priority |
|
order. This is combined with msg_src_path to determine which |
<td>Contains the list of preferred languages, in priority order. |
resource bundles to search for for the msg_id. If not empty, |
This is combined with msg_src_path to determine which resource bundles |
overrides useThreadLocale and useProcessLocale.</td> |
to search for for the msg_id. If not empty, overrides useThreadLocale |
|
and useProcessLocale.</td> |
|
</tr> | </tr> |
|
|
<tr> | <tr> |
<td>ContentLanguages contentlanguages;</td> | <td>ContentLanguages contentlanguages;</td> |
|
|
<td>Output</td> | <td>Output</td> |
|
<td>Contains the language that MessageLoader found for the |
<td>Contains the language that MessageLoader found for the msg_id. </td> |
msg_id. </td> |
</tr> | </tr> |
|
|
<tr> | <tr> |
<td>Boolean useProcessLocale;</td> | <td>Boolean useProcessLocale;</td> |
|
<td>Input <br> |
<td>Input |
Optional <br> |
<br>Optional |
Default = false</td> |
<br>Default = false</td> |
<td>If true, MessageLoader will use the default locale of the |
|
process. If true, overrides useThreadLocale.</td> |
<td>If true, MessageLoader will use the default locale of the process. |
|
If true, overrides useThreadLocale.</td> |
|
</tr> | </tr> |
|
|
<tr> | <tr> |
<td>Boolean useThreadLocale;</td> | <td>Boolean useThreadLocale;</td> |
|
<td>Input <br> |
<td>Input |
Optional <br> |
<br>Optional |
Default = <font color="#ff0000">true</font></td> |
<br>Default = <font color="#FF0000">true</font></td> |
<td>If true, MessageLoader will use the AcceptLanguages set by |
|
Pegasus into the caller's Thread. See the Note below for |
<td>If true, MessageLoader will use the AcceptLanguages set by Pegasus |
details. </td> |
into the caller's Thread. See the Note below for details. </td> |
|
</tr> | </tr> |
|
|
<tr> | <tr> |
<td>Boolean useICUfallback</td> | <td>Boolean useICUfallback</td> |
|
<td>Input <br> |
<td>Input |
Optional <br> |
<br>Optional |
Default = false</td> |
<br>Default = false</td> |
<td>If true, use ICU's fallback mechnism to search more general |
|
resource bundles if the msg_id cannot be found. Note: the |
<td>If true, use ICU's fallback mechnism to search more general resource |
recommended setting is false if you are using an AcceptLanguages from a |
bundles if the msg_id cannot be found. Note: the recommended setting |
CIM client. The Accept-Languages HTTP header from the client |
is false if you are using an AcceptLanguages from a CIM client. The |
contains the fallback specifications. Using ICU's fallback in this |
Accept-Languages HTTP header from the client contains the fallback specifications.</td> |
case may lead to returning a language that the client didn't ask for.</td> |
</tr> | </tr> |
|
|
<tr> | <tr> |
<td>Formatter::Arg arg0; |
<td>Formatter::Arg arg0; <br> |
<br> Formatter::Arg arg1; |
Formatter::Arg arg1; <br> |
<br> Formatter::Arg arg2; |
Formatter::Arg arg2; <br> |
<br> Formatter::Arg arg3; |
Formatter::Arg arg3; <br> |
<br> Formatter::Arg arg4; |
Formatter::Arg arg4; <br> |
<br> Formatter::Arg arg5; |
Formatter::Arg arg5; <br> |
<br> Formatter::Arg arg6; |
Formatter::Arg arg6; <br> |
<br> Formatter::Arg arg7; |
Formatter::Arg arg7; <br> |
<br> Formatter::Arg arg8; |
Formatter::Arg arg8; <br> |
<br> Formatter::Arg arg9;</td> |
Formatter::Arg arg9;</td> |
|
<td>Input <br> |
<td>Input |
Optional <br> |
<br>Optional |
Default: Formatter::Arg( ) // empty arg</td> |
<br>Default: Formatter::Arg( ) // empty arg</td> |
<td>These are the substitution variables, using the Pegasus |
|
Formatter::Arg class.</td> |
<td>These are the substitution variables, using the Pegasus Formatter::Arg |
|
class.</td> |
|
</tr> | </tr> |
|
</tbody> |
</table> | </table> |
|
</p> |
<p>Notes: |
<p>Notes: <br> |
<br> |
</p> |
<p>The "useThreadLocale" parameter defaults to true. This flag indicates |
<p>The "useThreadLocale" parameter defaults to true. This flag |
to use the AcceptLanguages object set by Pegasus into the Pegasus Thread |
indicates to use the AcceptLanguages object set by Pegasus into the |
in which the caller's code is running. This AcceptLanguages object |
Pegasus Thread in which the caller's code is running. This |
reflects the languages requested by the client. This is useful for |
AcceptLanguages object reflects the languages requested by the |
code that may not have access to the AcceptLanguages from the client. |
client. This is useful for code that may not have access to the |
Pegasus sets this AcceptLanguages object into the Thread of providers and |
AcceptLanguages from the client. Pegasus sets this AcceptLanguages |
internal Pegasus code. For this reason, it is recommended that provider |
object into the Thread of providers and internal Pegasus code. |
and internal Pegasus code use the "useThreadLocale" flag instead of explicity |
For this reason, it is recommended that provider and internal Pegasus |
passing in an AcceptLanguages object. See the Provider Developer |
code use the "useThreadLocale" flag instead of explicity passing in an |
and Pegasus Developer sections for details. |
AcceptLanguages object. See the Provider Developer and Pegasus |
<br> |
Developer sections for details. <br> |
|
</p> |
<p>The "useProcessLocale" flag can be used to tell MessageLoader to use | <p>The "useProcessLocale" flag can be used to tell MessageLoader to use |
the default locale of the process, as determined by ICU. This is | the default locale of the process, as determined by ICU. This is |
useful for situations where the caller is not localizing for a client request. |
useful for situations where the caller is not localizing for a client |
The caller may itself be a client (eg. cimconfig), or may need to log messages |
request. The caller may itself be a client (eg. cimconfig), or may |
to the system log in the locale of the Pegasus server process. See |
need to log messages to the system log in the locale of the Pegasus |
the CLI Messages and Logger Messages sections below. |
server process. See the CLI Messages and Logger Messages sections |
<br> |
below. <br> |
<p>"Master switch" |
</p> |
<br>The MessageLoader class has a public static Boolean variable called |
<p>"Master switch" <br> |
|
The MessageLoader class has a public static Boolean variable called |
_useProcessLocale that may be used to override all the AcceptLanguages | _useProcessLocale that may be used to override all the AcceptLanguages |
and useThreadLocale settings in the MessageLoaderParms objects passed in. |
and useThreadLocale settings in the MessageLoaderParms objects passed |
This is useful for CLI code (eg cimconfig) that needs to localize its messages |
in. This is useful for CLI code (eg cimconfig) that needs to |
based on the locale of its process, which refects the locale set by the |
localize its messages based on the locale of its process, which refects |
user running the CLI (eg. $LANG on Unix). The CLI code may call Pegasus |
the locale set by the user running the CLI (eg. $LANG on Unix). |
APIs that are coded to use the Thread's AcceptLanguages, which will not |
The CLI code may call Pegasus APIs that are coded to use the Thread's |
be set in this case. The _useProcessLocale static variable tells |
AcceptLanguages, which will not be set in this case. The |
the MessageLoader to ignore the AcceptLanguages, useThreadLocale, and useProcessLocale |
_useProcessLocale static variable tells the MessageLoader to ignore the |
settings in MessageLoaderParms that it gets. The MessageLoader will |
AcceptLanguages, useThreadLocale, and useProcessLocale settings in |
use the default process locale, as determined by ICU, in this case. |
MessageLoaderParms that it gets. The MessageLoader will use the |
<br> |
default process locale, as determined by ICU, in this case. <br> |
|
</p> |
<p><i>Important Note:</i> The MessageLoader defaults to <i>not </i>use | <p><i>Important Note:</i> The MessageLoader defaults to <i>not </i>use |
the "fallback" mechanism described in the ICU Resource Management section. |
the "fallback" mechanism described in the ICU Resource Management |
This is because the Accept-Language header itself describes the fallback |
section. This is because the Accept-Language header itself |
that the client wants. However, the MessageLoader does "fallback" |
describes the fallback that the client wants. However, the |
to the root resource bundle if none of the languages in AcceptLanguages |
MessageLoader does "fallback" to the root resource bundle if none of the |
can be found. If the root resource bundle cannot be found, then the |
languages in AcceptLanguages can be found. If the root resource |
default_msg is returned. The "useICUFallback" flag can be set to |
bundle cannot be found, then the default_msg is returned. The |
have MessageLoader use ICU fallback on all message load attempts. |
"useICUFallback" flag can be set to have MessageLoader use ICU fallback |
However, usage of this flag for client requests may lead to incorrect results. |
on all message load attempts. However, usage of this flag for |
For example, a client sets Accept-Language to french, german, and spanish, |
client requests may lead to incorrect results. For example, a |
in that order, but there is no french resource bundle. A call to |
client sets Accept-Language to french, german, and spanish, in that |
|
order, but there is no french resource bundle. A call to |
MessageLoader with useICUfallback == true would cause the root resource | MessageLoader with useICUfallback == true would cause the root resource |
bundle string to be returned on the attempt to load from the french bundle. |
bundle string to be returned on the attempt to load from the french |
But the client requested german to be the fallback after french. |
bundle. But the client requested german to be the fallback after |
<br> |
french. <br> |
<p>Please refer to the following files for details on the new Pegasus classes. |
</p> |
<br> |
<p>Please refer to the following files for details on the new Pegasus |
|
classes. <br> |
|
</p> |
<ul> | <ul> |
<li> |
<li> pegasus/src/Pegasus/Common/MessageLoader.h</li> |
pegasus/src/Pegasus/Common/MessageLoader.h</li> |
|
</ul> | </ul> |
|
<h4> 2.2.4 Message Loading Example</h4> |
<h4> |
<p><br> |
2.2.4 Message Loading Example</h4> |
The following example shows how a message may be loaded using the |
|
|
<p><br>The following example shows how a message may be loaded using the |
|
classes described above. Note: this a generic example. Each | classes described above. Note: this a generic example. Each |
of the developer sections below have 'real-life' examples that are better |
of the developer sections below have 'real-life' examples that are |
suited to each type of code. |
better suited to each type of code. </p> |
<p>// Build an AcceptLanguages with some language elements |
<p>// Build an AcceptLanguages with some language elements <br> |
<br>AcceptLanguages acceptLangs; |
AcceptLanguages acceptLangs; <br> |
<br>acceptLangs.add(AcceptLanguageElement("fr", 0.5)); |
acceptLangs.add(AcceptLanguageElement("fr", 0.5)); <br> |
<br>acceptLangs.add(AcceptLanguageElement("de", 0.8)); |
acceptLangs.add(AcceptLanguageElement("de", 0.8)); <br> |
<br>acceptLangs.add(AcceptLanguageElement("es", 0.4)); |
acceptLangs.add(AcceptLanguageElement("es", 0.4)); </p> |
<p>// Construct a MessageLoaderParms |
<p>// Construct a MessageLoaderParms <br> |
<br>MessageLoaderParms parms("msgID", "default message"); |
MessageLoaderParms parms("msgID", "default message"); <br> |
<br>parms. msg_src_path = "/my_msg_dir/my_bundle"; |
parms. msg_src_path = "/my_msg_dir/my_bundle"; <br> |
<br>parms.acceptlanguages = acceptLangs; |
parms.acceptlanguages = acceptLangs; </p> |
<p>// Note: If you have args, set them into MessageLoaderParms |
<p>// Note: If you have args, set them into MessageLoaderParms </p> |
<p>// Load the localized String |
<p>// Load the localized String <br> |
<br>String localizedMsg = MessageLoader::getMessage(parms); |
String localizedMsg = MessageLoader::getMessage(parms); <br> |
<br> |
<br> |
<br> |
</p> |
<h4> |
<h4> 2.2.5 Message Writing Guidelines</h4> |
2.2.4 Message Writing Guidelines</h4> |
<p><br> |
|
Here are some basic rules for writing messages: <br> |
<p><br>Here are some basic rules for writing messages: |
</p> |
<br> |
|
<ul> | <ul> |
<li> |
<li> If you want to claim that you are globalized, no hardcoded |
If you want to claim that you are globalized, no hardcoded messages!</li> |
messages!</li> |
|
<li> Avoid creating a message in the code by combining other |
|
messages. When you do this you are assuming that you know the |
|
grammar for every language.</li> |
|
<li> String substitutions into messages are generally untranslated, |
|
ie. not loaded from the resource bundle. Example: a file |
|
name.</li> |
|
<li> Avoid jargon, humour, and cultural idioms. Use full |
|
sentences. Have your messages reviewed by your globalization |
|
team. Your messages need to make sense to the translators, and |
|
ultimately the customer.</li> |
|
<li> <b>TODO </b>- find a good message writing guide to link to</li> |
|
</ul> |
| |
<li> |
<p><b>Are there any special considerations while creating a new message ? </b></p> |
Avoid combining messages in the code from other messages. When you |
|
do this you are assuming that you know the grammar for every language.</li> |
|
| |
<li> |
<ul> |
String substitutions into messages are generally untranslated, ie. not |
<li>If a message definition contains text within a single quote |
loaded from the resource bundle. Example: a file name.</li> |
it is not interpreted in any way. |
| |
<li> |
<p><i>Example:</i></p> |
Avoid jargon, humour, and cultural idioms. Use full sentences. |
<p> Server.CIMOperationRequestAuthorizer.NOT_IN_AUTHORIZED_GRP: |
Have your messages reviewed by your globalization team. Your messages |
string {"PGS05202: User '{0}' is not authorized to access CIM data."} |
need to make sense to the translators, and ultimately the customer.</li> |
</p> |
|
|
|
<p><i>Processed message:</i></p> |
|
<p> User {0} is not authorized to access CIM data. </p> |
|
</li> |
|
|
|
<li> For a single quote to appear in a processed message, it needs to be preceded by |
|
another single quote. |
|
|
|
<p><i>Example:</i></p> |
|
<p> Server.CIMOperationRequestAuthorizer.NOT_IN_AUTHORIZED_GRP: |
|
string {"PGS05202: User ''{0}'' is not authorized to access CIM data."} |
|
</p> |
|
|
|
<p><i>Processed message:</i></p> |
|
<p> User 'wbemuser' is not authorized to access CIM data. </p> |
|
</li> |
| |
<li> |
<li> For a double quote to appear in a processed message, it needs to be preceded by |
<b>TODO </b>- find a good message writing guide to link to</li> |
a back slash. |
</ul> |
|
| |
<h4> |
<p><i>Example:</i></p> |
</h4> |
<p> |
|
ControlProviders.ProviderRegistrationProvider.ProviderRegistrationProvider. |
|
UNSUPPORTED_USERCONTEXT_VALUE:string {"PGS03029: Unsupported UserContext |
|
value: \"{0}\"."} |
|
</p> |
|
|
|
<p><i>Processed message:</i></p> |
|
<p> Unsupported UserContext value: "10". </p> |
|
</li> |
|
</ul> |
| |
<h4> |
<p> </p> |
2.2.5 Localized Exceptions</h4> |
|
| |
<p><br>The base Exception class, and derived classes, have been updated |
<h4> 2.2.6 Localized Exceptions</h4> |
to support localization. Constructors have been added that take a |
<p><br> |
MessageLoaderParms object. These constructors will use the MessageLoaderParms |
The base Exception class, and derived classes, have been updated to |
object to call the MessageLoader to load the localized exception message. |
support localization. Constructors have been added that take a |
The localized message is saved in the Exception. The ContentLanguages |
MessageLoaderParms object. These constructors will use the |
object returned by MessageLoader is also saved in the Exception. |
MessageLoaderParms object to call the MessageLoader to load the |
This indicates the language of the message. The ContentLanguages |
localized exception message. The localized message is saved in the |
object is used later to set the Content-Language header in the HTTP message |
Exception. The ContentLanguages object returned by MessageLoader |
to the client. |
is also saved in the Exception. This indicates the language of |
<br> |
the message. The ContentLanguages object is used later to set the |
|
Content-Language header in the HTTP message to the client. <br> |
|
</p> |
<p>The old Exception constructors that take a String will remain. | <p>The old Exception constructors that take a String will remain. |
These should be used in cases where the code throwing the exception is | These should be used in cases where the code throwing the exception is |
not localized, or the String is not localized (for example, a file name). |
not localized, or the String is not localized (for example, a file |
Also, there are several exceptions in Pegasus where the String parameter |
name). Also, there are several exceptions in Pegasus where the |
is meant to be a non-localized substitution in a localized message owned |
String parameter is meant to be a non-localized substitution in a |
by the Exception (see InternalException.h, ClassNotResolved for an example). |
localized message owned by the Exception (see InternalException.h, |
The old constructors for these have been kept. |
ClassNotResolved for an example). The old constructors for these |
<br> |
have been kept. <br> |
<br> |
<br> |
<h2> |
</p> |
3.0 Provider Developers</h2> |
<h2> 3.0 Provider Developers</h2> |
| |
<h3> |
<h3> 3.1 Design Issues</h3> |
3.1 Design Issues</h3> |
<p><br> |
|
Providers that wish to globalize should consider the following in their |
<p><br>Providers that wish to globalize should consider the following in |
design: <br> |
their design: |
</p> |
<br> |
|
<ul> | <ul> |
<li> |
<li> Are there localized string properties that need to be |
Are there localized string properties that need to be supported? |
supported? If so, then the client will use Accept-Language to |
If so, then the client will use Accept-Language to request specific languages |
request specific languages for these properties. If the properties |
for these properties. If the properties are read-only, use MessageLoader |
are read-only, use MessageLoader to load the localized strings for the |
to load the localized strings for the properties.</li> |
properties.</li> |
|
<li> If you have a localized read/write string property, then the |
<li> |
client will use Content-Language to set the property with an associated |
If you have a localized read/write string property, then the client will |
language. The client will expect to be able to retrieve the |
use Content-Language to set the property with an associated language. |
property in that same language later (using Accept-Language).</li> |
The client will expect to be able to retrieve the property in that same |
<li> Note: only the string property types in CIM are candidates for |
language later (using Accept-Language).</li> |
localization. The other types, including datetime, are |
|
locale-neutral.</li> |
<li> |
<li> Are there error messages that need to returned to the client in |
Note: only the string property types in CIM are candidates for localization. |
different languages? The client will use Accept-Language to |
The other types, including datetime, are locale-neutral.</li> |
request specific languages for the error messages.</li> |
|
<li> What resource bundle translations, if any, will be shipped with |
<li> |
the provider?</li> |
Are there error messages that need to returned to the client in different |
<li> Do any codepage conversions need to be done between the UTF-16 |
languages? The client will use Accept-Language to request specific |
characters in the String objects and the codepage of data stored on the |
languages for the error messages.</li> |
system? This is a concern for EBCDIC platforms. All EBCDIC |
|
data needs to be converted to at least 7-bit ASCII before it is passed |
<li> |
into the String object.</li> |
What resource bundle translations, if any, will be shipped with the provider?</li> |
|
|
|
<li> |
|
Do any codepage conversions need to be done between the UTF-16 characters |
|
in the String objects and the codepage of data stored on the system? |
|
This is a concern for EBCDIC platforms. All EBCDIC data needs to |
|
be converted to at least 7-bit ASCII before it is passed into the String |
|
object.</li> |
|
</ul> | </ul> |
|
<p><br> |
<p><br>To help providers handle the situations described above, Pegasus |
To help providers handle the situations described above, Pegasus 2.3 |
2.3 will pass the Accept-Language received from the client to the provider. |
will pass the Accept-Language received from the client to the |
The provider should load strings from its resource bundle based on the |
provider. The provider should load strings from its resource |
client's Accept-Language. The client's Accept-Language is passed |
bundle based on the client's Accept-Language. The client's |
to the provider in two ways: |
Accept-Language is passed to the provider in two ways: <br> |
<br> |
</p> |
<ul> | <ul> |
<li> |
<li> Pegasus will set the Accept-Language from the client into the |
Pegasus will set the Accept-Language from the client into the thread in |
thread in which the provider is running. By using the |
which the provider is running. By using the useThreadLocale setting |
useThreadLocale setting in MessageLoaderParms, providers can easily load |
in MessageLoaderParms, providers can easily load strings using the client's |
strings using the client's requested Accept-Language. The |
requested Accept-Language. The provider does not need to know what |
provider does not need to know what the Accept-Language is. This |
the Accept-Language is. This is the recommended method to load messages |
is the recommended method to load messages based on the client's request.</li> |
based on the client's request.</li> |
<br> |
|
<li> The OperationContext will contain an AcceptLanguages object |
<br> |
that has the Accept-Language requested by the client. The provider |
<li> |
can use this AcceptLanguages object to load strings with MessageLoader.</li> |
The OperationContext will contain an AcceptLanguages object that has the |
|
Accept-Language requested by the client. The provider can use this |
|
AcceptLanguages object to load strings with MessageLoader.</li> |
|
</ul> | </ul> |
|
<p><br> |
<p><br>The OperationContext will also contain a ContentLanguages object |
The OperationContext will also contain a ContentLanguages object that |
that is set from the Content-Language in the client request. This |
is set from the Content-Language in the client request. This is |
is the language of the CIM objects being passed to the provider on that |
the language of the CIM objects being passed to the provider on that |
request. A localized provider should store the content language along |
request. A localized provider should store the content language |
with the data from the CIM objects. This will allow the client to |
along with the data from the CIM objects. This will allow the |
use Accept-Language later to retreive the data in that language. |
client to use Accept-Language later to retreive the data in that |
<br> |
language. <br> |
<p>The provider should indicate the language of CIM objects it is returning |
</p> |
by calling setLanguage( ) on the ResponseHandler. This will be used |
<p>The provider should indicate the language of CIM objects it is |
to set the Content-Language in the CIM response message sent back to the |
returning by calling setContext( ) on the ResponseHandler. This |
client. If setLanguage( ) is not called, then no Content-Language |
will be used to set the Content-Language in the CIM response message |
will be returned to the client. setLanguage( ) should only be called |
sent back to the client. If setContext( ) is not called, then no |
once per response. |
Content-Language will be returned to the client. The setContext( ) |
<br> |
function should only be called once per response. <br> |
<h3> |
</p> |
3.2 Sample Code</h3> |
<h3> 3.2 Sample Code</h3> |
|
<p><br> |
<p><br>The following sample code shows a localized getInstance( ) where |
The following sample code shows a localized getInstance( ) where the |
the instance returned is localized based on the Accept-Language of the |
instance returned is localized based on the Accept-Language of the |
client request. Note that this example also throws a localized exception. |
client request. Note that this example also throws a localized |
<br> |
exception. <br> |
<p>void LocalizedProvider::getInstance( |
</p> |
<br> const OperationContext & context, |
<p>void LocalizedProvider::getInstance( <br> |
<br> const CIMObjectPath & instanceReference, |
const OperationContext & context, <br> |
<br> const Boolean includeQualifiers, |
const CIMObjectPath & instanceReference, <br> |
<br> const Boolean includeClassOrigin, |
const Boolean includeQualifiers, <br> |
<br> const CIMPropertyList & propertyList, |
const Boolean includeClassOrigin, <br> |
<br> InstanceResponseHandler & handler) |
const CIMPropertyList & propertyList, <br> |
<br>{ |
InstanceResponseHandler & handler) <br> |
<br> // convert a potential fully qualified reference |
{ <br> |
into a local reference |
// convert a potential fully qualified |
<br> // (class name and keys only). |
reference into a local reference <br> |
<br> CIMObjectPath localReference = CIMObjectPath( |
// (class name and keys only). <br> |
<br> String(), |
CIMObjectPath localReference = CIMObjectPath( <br> |
<br> String(), |
String(), <br> |
<br> instanceReference.getClassName(), |
String(), <br> |
<br> instanceReference.getKeyBindings()); |
|
<p> // begin processing the request |
instanceReference.getClassName(), <br> |
<br> handler.processing(); |
|
<p> // Find the instance to be returned. |
instanceReference.getKeyBindings()); </p> |
<br> Uint32 i; |
<p> // begin processing the request <br> |
<br> Uint32 n = _instances.size(); |
handler.processing(); </p> |
<br> for (i = 0; i < n; i++) |
<p> // Find the instance to be returned. <br> |
<br> { |
Uint32 i; <br> |
<br> if(localReference |
Uint32 n = _instances.size(); <br> |
== _instanceNames[i]) |
for (i = 0; i < n; i++) <br> |
<br> { |
{ <br> |
<br> |
|
// We found the instance to return |
if(localReference == _instanceNames[i]) <br> |
|
{ <br> |
|
|
|
// We found the instance to return </p> |
<p> | <p> |
// Build the parameters for loading the localized string property. |
// Build the parameters for loading the localized string property. <br> |
<br> |
|
// We are going to let the message loader parameters default to use the |
// We are going to let the message loader parameters default to use the <br> |
<br> |
|
// AcceptLanguages that Pegasus set into our thread. |
// AcceptLanguages that Pegasus set into our thread. <br> |
<br> |
|
// (this equals the AcceptLanguages requested by the client) |
// (this equals the AcceptLanguages requested by the client) <br> |
<br> |
|
// Note: This parms object could be constructed once and |
// Note: This parms object could be constructed once and <br> |
<br> |
|
// reused. |
// reused. <br> |
<br> |
|
MessageLoaderParms parms("myMsgID", "myDefaultString"); |
MessageLoaderParms parms("myMsgID", "myDefaultString"); <br> |
<br> |
|
parms.msg_src_path = "/myprovider/msg/myResourceBundle"; |
parms.msg_src_path = "/myprovider/msg/myResourceBundle"; </p> |
<p> | <p> |
// Load the string for the localized property from the resource bundle |
// Load the string for the localized property from the resource bundle <br> |
<br> |
|
String localizedString = MessageLoader::getMessage(parms); |
String localizedString = MessageLoader::getMessage(parms); </p> |
<p> | <p> |
// Remove the old property from the instance to be returned |
// Remove the old property from the instance to be returned <br> |
<br> |
|
Uint32 index = instances[i].findProperty("myProperty"); |
Uint32 index = instances[i].findProperty("myProperty"); <br> |
<br> |
|
if (index != PEG_NOT_FOUND) |
if (index != PEG_NOT_FOUND) <br> |
<br> |
|
{ |
{ <br> |
<br> |
|
_instances[i].removeProperty(index); |
_instances[i].removeProperty(index); <br> |
<br> |
|
} |
} </p> |
<p> |
|
// Add the localized string property to the instance |
|
<br> |
|
instances[i].addProperty(CIMProperty("myProperty", localizedString)); |
|
<p> | <p> |
// The MessageLoader set the contentlanguages member |
// Add the localized string property to the instance <br> |
<br> |
|
// of parms to the language that it found for the message. |
instances[i].addProperty(CIMProperty("myProperty", localizedString)); </p> |
<br> |
|
ContentLanguages rtnLangs = parms.contentlanguages; |
|
<p> | <p> |
// We need to tag the instance we are returning with the |
// The MessageLoader set the contentlanguages member <br> |
<br> |
|
// the content language. |
// of parms to the language that it found for the message. <br> |
<br> |
|
handler.setLanguages(rtnLangs); |
ContentLanguages rtnLangs = parms.contentlanguages; </p> |
<p> | <p> |
// deliver requested instance |
// We need to tag the instance we are returning with the <br> |
<br> |
// the |
|
content language. <br> |
|
|
|
OperationContext context;<br> |
|
|
|
context.insert(ContentLanguageListContainer(rtnLangs));<br> |
|
|
|
handler.setContext(context);<br> |
|
</p> |
|
|
|
// deliver requested instance<br> |
|
|
handler.deliver(_instances[i]); | handler.deliver(_instances[i]); |
<p> | <p> |
break; |
break; <br> |
<br> |
|
} // end if |
} // end if <br> |
<br> } |
|
// end for |
} // |
|
end for </p> |
<p> // throw an exception if | <p> // throw an exception if |
the instance wasn't found |
the instance wasn't found <br> |
<br> if (i == n) |
if (i == n) <br> |
<br> { |
{ <br> |
<br> |
|
// Build the parameters for loading the localized error message. |
// Build the parameters for loading the localized error message. <br> |
<br> |
|
// We are going to let the message loader parameters default to use the |
// We are going to let the message loader parameters default to use the <br> |
<br> |
|
// AcceptLanguages that Pegasus set into our thread. |
// AcceptLanguages that Pegasus set into our thread. <br> |
<br> |
|
// (this equals the AcceptLanguages requested by the client) |
// (this equals the AcceptLanguages requested by the client) <br> |
<br> |
|
// Note: This parms object could be constructed once and |
// Note: This parms object could be constructed once and <br> |
<br> |
|
// reused. |
// reused. <br> |
<br> |
|
MessageLoaderParms errParms("myErrorMsgID", "myErrorDefaultString"); |
MessageLoaderParms errParms("myErrorMsgID", "myErrorDefaultString"); <br> |
<br> |
|
errParms.msg_src_path = "/myprovider/msg/myResourceBundle"; |
errParms.msg_src_path = "/myprovider/msg/myResourceBundle"; </p> |
<p> | <p> |
// Note: the exception calls MessageLoader::getMessage( ) |
// Note: the exception calls MessageLoader::getMessage( ) <br> |
<br> |
|
// Note: no need to call handler.setLanguages( ) in this case |
// Note: no need to call handler.setContext( ) in this case <br> |
<br> |
|
throw CIMObjectNotFoundException(errParms); |
throw CIMObjectNotFoundException(errParms); <br> |
<br> } |
} <br> |
<br> |
</p> |
<p> // complete processing the |
<p> // complete processing |
request |
the request <br> |
<br> handler.complete(); |
handler.complete(); <br> |
<br>} |
} <br> |
<br> |
</p> |
<p>NOTE: A sample provider has been written that fully demonstates the | <p>NOTE: A sample provider has been written that fully demonstates the |
design issues described above. This provider is located at: |
design issues described above. This provider is located at: <br> |
<br> |
</p> |
<ul> | <ul> |
<li> |
<li> pegasus/src/Providers/sample/LocalizedProvider/</li> |
pegasus/src/Providers/sample/LocalizedProvider/</li> |
|
</ul> | </ul> |
|
<p><br> |
<p><br>This sample provider also demonstrates how some of the special issues |
This sample provider also demonstrates how some of the special issues |
can be handled. The special issues are caused by having a read/only |
can be handled. The special issues are caused by having a |
localized property and a read/write localized property. What happens |
read/only localized property and a read/write localized property. |
if the client sets the read/write property with a Content-Language that |
What happens if the client sets the read/write property with a |
is not one of the supported languages for the read/only property? |
Content-Language that is not one of the supported languages for the |
This provider allows the client to set any language into the read/write |
read/only property? This provider allows the client to set any |
property, and get that property back in the same language. This becomes |
language into the read/write property, and get that property back in the |
an issue when the client does a getInstance( ) later, because the Content-Language |
same language. This becomes an issue when the client does a |
on the returned instance applies to all the properties. A related |
getInstance( ) later, because the Content-Language on the returned |
issue is what to return for Content-Language when the client does enumerateInstances, |
instance applies to all the properties. A related issue is what to |
but the instances have different languages. Recall that Content-Language |
return for Content-Language when the client does enumerateInstances, |
applies to the entire response (a limitation in the CIM specification). |
but the instances have different languages. Recall that |
<br> |
Content-Language applies to the entire response (a limitation in the CIM |
<p>NOTE: Indication Providers have other special considerations for |
specification). <br> |
language support. Please refer to PEP58. |
</p> |
<br> |
<p>NOTE: Indication Providers have other special considerations |
<p>NOTE: The CMPI interface has been updated for language support. |
for language support. Please refer to PEP58. <br> |
Please refer to the CMPI documentation for details. |
</p> |
<br> |
<p>NOTE: The CMPI interface has been updated for language |
<p>NOTE: SPECIAL ISSUES FOR OS/400 PROVIDERS: |
support. Please refer to the CMPI documentation for details. <br> |
|
</p> |
|
<p>NOTE: SPECIAL ISSUES FOR OS/400 PROVIDERS: </p> |
<ul> | <ul> |
<li> |
<li> Convert between UTF-16 in the String objects and EBCDIC system |
Convert between UTF-16 in the String objects and EBCDIC system data as |
data as needed. The converters in |
needed. The converters in Pegasus/Common/OS400ConvertChar.h may be |
Pegasus/Common/OS400ConvertChar.h may be used to convert between EBCDIC |
used to convert between EBCDIC CCSID 37 and ASCII CCSID 819 (a subset of |
CCSID 37 and ASCII CCSID 819 (a subset of UTF-16).</li> |
UTF-16).</li> |
<li> The Pegasus program, and all bound service programs, will |
|
run in a UTF-8 locale even though the job CCSID is 37. The |
<li> |
C-runtime library (printf, fopen, isalpha, strcmp, etc) will expect |
The Pegasus program, and all bound service programs, will run in |
UTF-8, or at least 7-bit ASCII, characters.</li> |
a UTF-8 locale even though the job CCSID is 37. The C-runtime library |
<li> Consideration should be given to the codepage for the compiled |
(printf, fopen, isalpha, strcmp, etc) will expect UTF-8, or at least 7-bit |
string literals. Use #pragma convert as needed. But, |
ASCII, characters.</li> |
remember that the C-runtime will expect UTF-8.</li> |
|
<li> For more details, refer to "Unicode support" in chapter 3 of the <u>ILE |
<li> |
|
Consideration should be given to the codepage for the compiled string literals. |
|
Use #pragma convert as needed. But, remember that the C-runtime will |
|
expect UTF-8.</li> |
|
|
|
<li> |
|
For more details, refer to "Unicode support" in chapter 3 of the <u>ILE |
|
C/C++ for iSeries Run-Time Functions, Version 5</u> publication for V5R3 | C/C++ for iSeries Run-Time Functions, Version 5</u> publication for V5R3 |
(SC41-5607-02). The Pegasus string literals will be compiled with | (SC41-5607-02). The Pegasus string literals will be compiled with |
the UTF-8 compile switch described in this section. OS/400 provider |
the UTF-8 compile switch described in this section. OS/400 |
developers should strongly consider using the same compile switch for their |
provider developers should strongly consider using the same compile |
string literals. This would allow the literals to match the UTF-8 |
switch for their string literals. This would allow the literals to |
encoding expected by the C-runtime.</li> |
match the UTF-8 encoding expected by the C-runtime.</li> |
</ul> | </ul> |
|
<h2> 4. 0 Client Developers</h2> |
<h2> |
<p><br> |
4. 0 Client Developers</h2> |
Methods have been added to CIMClient to set the Accept-Language and |
|
Content-Language on the request, and retrieve Content-Language on the |
<p><br>Methods have been added to CIMClient to set the Accept-Language |
response. The language tags in the Accept-Language header must |
and Content-Language on the request, and retrieve Content-Language on the |
meet the ISO-639 and ISO-3166 standards. <br> |
response. The language tags in the Accept-Language header must meet |
</p> |
the ISO-639 and ISO-3166 standards. |
<p>Please refer to <br> |
<br> |
</p> |
<p>Please refer to |
|
<br> |
|
<ul> | <ul> |
<li> |
<li> pegasus/src/Pegasus/Client/CIMClient.h</li> |
pegasus/src/Pegasus/Client/CIMClient.h</li> |
<br> |
|
|
<br> </ul> |
</ul> |
for the new methods on CIMClient. |
for the new methods on CIMClient. <br> |
<br> |
|
<p>Here is a code fragment that uses the new methods on CIMClient |
<p>Here is a code fragment that uses the new methods on CIMClient </p> |
<p> // |
<p> // <br> |
<br> // Get a localized instance in French |
// Get a localized instance in French <br> |
<br> // |
// </p> |
<p> // Language priority is martian, pig-latin, and french. |
<p> // Language priority is martian, pig-latin, and |
We should |
french. We should <br> |
<br> // get french back, even though its the lowest priority |
// get french back, even though its the lowest priority <br> |
<br> AcceptLanguages acceptLangs; |
AcceptLanguages acceptLangs; <br> |
<br> acceptLangs.add(AcceptLanguageElement("x-martian")); |
acceptLangs.add(AcceptLanguageElement("x-martian")); <br> |
<br> acceptLangs.add(AcceptLanguageElement("fr", 0.1)); |
acceptLangs.add(AcceptLanguageElement("fr", 0.1)); <br> |
<br> acceptLangs.add(AcceptLanguageElement("x-pig-latin", 0.4)); |
acceptLangs.add(AcceptLanguageElement("x-pig-latin", 0.4)); </p> |
<p> // Set the requested languages into the CIMClient |
<p> // Set the requested languages into the CIMClient <br> |
<br> client.setRequestAcceptLanguages(acceptLangs); |
client.setRequestAcceptLanguages(acceptLangs); </p> |
<p> // Get the instance |
<p> // Get the instance <br> |
<br> CIMInstance instance = client.getInstance( |
CIMInstance instance = client.getInstance( <br> |
<br> NAMESPACE, |
NAMESPACE, <br> |
<br> cimNInstances[0].buildPath(sampleClass), |
cimNInstances[0].buildPath(sampleClass), <br> |
<br> localOnly, |
localOnly, <br> |
<br> includeQualifiers, |
includeQualifiers, <br> |
<br> includeClassOrigin); |
includeClassOrigin); </p> |
<p> // Get the string property that should be french |
<p> // Get the string property that should be french <br> |
<br> String returnedString; |
String returnedString; <br> |
<br> instance.getProperty ( |
instance.getProperty ( <br> |
<br> instance.findProperty("myProp")). |
instance.findProperty("myProp")). <br> |
<br> |
|
getValue(). |
getValue(). <br> |
<br> |
|
get(returnedString); |
get(returnedString); </p> |
<p> // Check that we got back french |
<p> // Check that we got back french <br> |
<br> ContentLanguages CL_FR("fr"); |
ContentLanguages CL_FR("fr"); <br> |
<br> String expectedFRString = "oui"; |
String expectedFRString = "oui"; <br> |
<br> PEGASUS_ASSERT(CL_FR == client.getResponseContentLanguages()); |
PEGASUS_ASSERT(CL_FR == client.getResponseContentLanguages()); <br> |
<br> PEGASUS_ASSERT(expectedFRString == returnedString); |
PEGASUS_ASSERT(expectedFRString == returnedString); </p> |
<p> // |
<p> // <br> |
<br> // Create an instance in French |
// Create an instance in French <br> |
<br> // |
// </p> |
<p> String oui = "Oui"; |
<p> String oui = "Oui"; <br> |
<br> CIMInstance frInstance(CLASSNAME); |
CIMInstance frInstance(CLASSNAME); <br> |
<br> frInstance.addProperty(CIMProperty( |
frInstance.addProperty(CIMProperty( <br> |
<br> |
|
CIMName("myProp"), |
CIMName("myProp"), <br> |
<br> |
|
oui)); |
oui)); </p> |
<p> CIMObjectPath frInstanceName = frInstance.buildPath(sampleClass); |
<p> CIMObjectPath frInstanceName = |
<p> client.setRequestContentLanguages(CL_FR); |
frInstance.buildPath(sampleClass); </p> |
<p> client.createInstance(NAMESPACE, frInstance); |
<p> client.setRequestContentLanguages(CL_FR); </p> |
<br> |
<p> client.createInstance(NAMESPACE, frInstance); <br> |
<br> |
<br> |
<br> |
<br> |
<p>Also, refer to |
</p> |
|
<p>Also, refer to </p> |
<ul> | <ul> |
<li> |
<li> pegasus/src/Clients/g11ntest/</li> |
pegasus/src/Clients/g11ntest/</li> |
|
</ul> | </ul> |
for more examples of a client that uses Accept-Language and Content-Language. |
for more examples of a client that uses Accept-Language and |
<br> |
Content-Language. <br> |
|
|
<p>NOTE: Consideration should be given for converting the UTF-16 | <p>NOTE: Consideration should be given for converting the UTF-16 |
characters in the String objects passed over the CIMClient interface to | characters in the String objects passed over the CIMClient interface to |
a platform codepage. This is especially needed for EBCDIC platforms. |
a platform codepage. This is especially needed for EBCDIC |
See the Provider developer section for details of the EBCDIC considerations. |
platforms. See the Provider developer section for details of the |
<br> |
EBCDIC considerations. <br> |
<br> |
<br> |
<h3> |
</p> |
4.1 Default Process Locale</h3> |
<h3> 4.1 Default Process Locale</h3> |
|
<p><br> |
<p><br>A method has been added to CIMClient to set the Accept-Language |
A method has been added to CIMClient to set the Accept-Language for the |
for the requests based on the default locale of the process, as determined |
requests based on the default locale of the process, as determined by |
by ICU. If ICU is installed on the client system then CIMClient will |
ICU. If ICU is installed on the client system then CIMClient will |
set the Accept-Language from the default ICU process locale. If ICU |
set the Accept-Language from the default ICU process locale. If |
is not installed then the caller is required to set an AcceptLanguages |
ICU is not installed then the caller is required to set an |
into CIMClient that meets the ISO-639 and IS0-3166 standards. Note: |
AcceptLanguages into CIMClient that meets the ISO-639 and IS0-3166 |
this is useful for local clients, such as the Pegasus CLIs, where ICU would |
standards. Note: this is useful for local clients, such as |
be installed on both the client and server sides. |
the Pegasus CLIs, where ICU would be installed on both the client and |
<br> |
server sides. <br> |
<br> |
<br> |
<h2> |
</p> |
5. 0 Pegasus Developers</h2> |
<h2> 5. 0 Pegasus Developers</h2> |
|
<p><br> |
<p><br>The design for Pegasus releases beyond 2.3 is to avoid using hardcoded |
The design for Pegasus releases beyond 2.3 is to avoid using hardcoded |
messages. All new messages should be loaded from a Pegasus resource |
messages. All new messages should be loaded from a Pegasus |
bundle. This section describes the process to follow if you are creating |
resource bundle. This section describes the process to follow if |
a new message. The process depends on where you are in the code. |
you are creating a new message. The process depends on where you |
<br> |
are in the code. <br> |
<br> |
<br> |
<h3> |
</p> |
<b>5.1 Pegasus Resource Bundles</b></h3> |
<h3> <b>5.1 Pegasus Resource Bundles</b></h3> |
|
<p><br> |
<p><br>Place any new Pegasus messages into one of the following resource |
Place any new Pegasus messages into one of the following resource |
bundles: |
bundles: <br> |
<br> |
</p> |
<ul> | <ul> |
<li> |
<li> pegasus/src/Pegasus/msg/Server/pegasusServer_*.txt for |
pegasus/src/Pegasus/msg/Server/pegasusServer.txt for server messages</li> |
server and MOF compiler (cimmof, cimmofl) messages</li> |
|
<li> pegasus/src/Pegasus/msg/CLI/pegasusCLI_*.txt for all CLI messages |
<li> |
(except the MOF compiler)</li> |
pegasus/src/Clients/<cli_name>/msg/<cli_name>.txt for CLI messages</li> |
|
</ul> | </ul> |
|
<p><br> |
<p><br>The make messages target will compile these resource bundles. |
The make messages target will compile these resource bundles. </p> |
<p>Note: As described above, the resource bundle path in MessageLoaderParms |
<p>Note: As described above, the resource bundle path in |
defaults to the server resource bundle. For CLI messages, you will |
MessageLoaderParms defaults to the server resource bundle. For CLI |
need to specify the bundle for your CLI. |
messages, you will need to specify the bundle for your CLI. <br> |
<br> |
</p> |
<h3> |
<h3> 5.2 Server Messages</h3> |
5.2 Server Messages</h3> |
<p><br> |
|
For messages returned from one of the services in the Pegasus server |
<p><br>For messages returned from one of the services in the Pegasus server |
|
(eg. CIMOperationRequestDispatcher, or ProviderManagerService), the goal | (eg. CIMOperationRequestDispatcher, or ProviderManagerService), the goal |
is to make it easy for any code in the call chain to throw an exception | is to make it easy for any code in the call chain to throw an exception |
with a localized error string. The code throwing the exception will |
with a localized error string. The code throwing the exception |
not need to know the Accept-Language that the client requested. To |
will not need to know the Accept-Language that the client |
understand how this works, some design points need to described: |
requested. To understand how this works, some design points need |
<br> |
to described: <br> |
<p><b>Server Design Points:</b> |
</p> |
<br> |
<p><b>Server Design Points:</b> <br> |
<p>The CIMMessage object has been expanded to include an AcceptLanguages |
</p> |
object and a ContentLanguages object. For CIMRequestMessage, these |
<p>The CIMMessage object has been expanded to include an |
objects contain the Accept-Language and Content-Language headers that were |
AcceptLanguages object and a ContentLanguages object. For |
built from the client request. For CIMResponseMessage, the ContentLanguages |
CIMRequestMessage, these objects contain the Accept-Language and |
object is used to build the Content-Language header associated with the |
Content-Language headers that were built from the client request. |
CIM <i>objects </i>in the response message. The AcceptLanguages object |
For CIMResponseMessage, the ContentLanguages object is used to build the |
in the CIMResponseMessage is ignored. |
Content-Language header associated with the CIM <i>objects </i>in the |
<br> |
response message. The AcceptLanguages object in the |
<p>The localization of the cimException object in the CIMResponseMessage |
CIMResponseMessage is ignored. <br> |
is handled separately from the CIM objects. The message string in |
</p> |
the cimException object is assumed to have been localized by the time it |
<p>The localization of the cimException object in the |
is built into the XML. For this reason, the localization of the exception |
CIMResponseMessage is handled separately from the CIM objects. The |
is the responsibility of the code throwing the exception. (The goal |
message string in the cimException object is assumed to have been |
of the design is to make that easy - see below). The ContentLanguages |
localized by the time it is built into the XML. For this reason, |
object in the CIMResponseMessage has NO relation to this exception. |
the localization of the exception is the responsibility of the code |
The cimException object keeps its own localization information once it |
throwing the exception. (The goal of the design is to make that |
is created. |
easy - see below). The ContentLanguages object in the |
<br> |
CIMResponseMessage has NO relation to this exception. The |
|
cimException object keeps its own localization information once it is |
|
created. <br> |
|
</p> |
<p>To enable exceptions to be localized, the ability was added to set a | <p>To enable exceptions to be localized, the ability was added to set a |
global language for all the code running from a Pegasus Thread object. |
global language for all the code running from a Pegasus Thread |
The top level code for a Thread can set a global AcceptLanguages object |
object. The top level code for a Thread can set a global |
that can be accessed by all the low-level functions that it calls. |
AcceptLanguages object that can be accessed by all the low-level |
This will allow an exception thrown by the low-level function to be localized |
functions that it calls. This will allow an exception thrown by |
based on this global AcceptLanguages object. Note: This applies |
the low-level function to be localized based on this global |
only to Threads that are managed by a ThreadPool. |
AcceptLanguages object. Note: This applies only to Threads |
<br> |
that are managed by a ThreadPool. <br> |
<p>Each service in the request path of the Pegasus server sets the AcceptLanguages |
</p> |
into its Thread from the AcceptLanguages in the CIMRequestMessage object |
<p>Each service in the request path of the Pegasus server sets the |
that it dequeues. This sets the global langauge for all the functions |
AcceptLanguages into its Thread from the AcceptLanguages in the |
in the same thread that are called below handleEnqueue. <i>If you |
CIMRequestMessage object that it dequeues. This sets the global |
are writing a new service that processes requests, or discover a request |
langauge for all the functions in the same thread that are called below |
service that was missed, please do this. </i> The CIMOperationRequestDispatcher |
handleEnqueue. <i>If you are writing a new service that processes |
service is an example. |
requests, or discover a request service that was missed, please do |
<br> |
this. </i> The CIMOperationRequestDispatcher service is an example. <br> |
<p><b>How to Throw a Localized Exception from Server code:</b> |
</p> |
<br> |
<p><b>How to Throw a Localized Exception from Server code:</b> <br> |
<p>With all that background, here is how code running in a Pegasus service |
</p> |
can throw a localized exception: |
<p>With all that background, here is how code running in a Pegasus |
<br>This example assumes that the top-level code in the service had set |
service can throw a localized exception: <br> |
the global thread AcceptLanguages beforehand. As described above, |
This example assumes that the top-level code in the service had set the |
every service in Pegasus should do that. The code here may be buried |
global thread AcceptLanguages beforehand. As described above, |
several layers deep in the call chain, but does not need to know the AcceptLanguage |
every service in Pegasus should do that. The code here may be |
of the current client request. |
buried several layers deep in the call chain, but does not need to know |
<p>// First, construct a MessageLoaderParms |
the AcceptLanguage of the current client request. </p> |
<br>// |
<p>// First, construct a MessageLoaderParms <br> |
<br>// Notes: |
// <br> |
<br>// 1) The errorMessageID must be in the Pegasus server resource |
// Notes: <br> |
bundle. |
// 1) The errorMessageID must be in the Pegasus server resource |
<br>// 2) The default message is the old "hardcoded" message. |
bundle. <br> |
<br>// 3) The MessageLoaderParms will default to use the Pegasus |
// 2) The default message is the old "hardcoded" message. <br> |
server resource bundle |
// 3) The MessageLoaderParms will default to use the Pegasus |
<br>// 4) The MessageLoaderParms will default to use the AcceptLanguages |
server resource bundle <br> |
set into the current Thread. Don't change this! |
// 4) The MessageLoaderParms will default to use the |
<br>// 5) You might need to set the arguments for the message into |
AcceptLanguages set into the current Thread. Don't change this! <br> |
the MessageLoaderParms |
// 5) You might need to set the arguments for the message into |
<br>MessageLoaderParms parms("errorMessageID", "default message"); |
the MessageLoaderParms <br> |
<p>// Second, throw the Exception |
MessageLoaderParms parms("errorMessageID", "default message"); </p> |
<br>// Note: this applies to all the derived classes from Exception, including |
<p>// Second, throw the Exception <br> |
the CIMException's |
// Note: this applies to all the derived classes from Exception, |
<br>throw new Exception(parms); |
including the CIMException's <br> |
<br> |
throw new Exception(parms); <br> |
|
</p> |
<p>NOTE: If you are throwing an Exception with un-localized data, | <p>NOTE: If you are throwing an Exception with un-localized data, |
use the constructor that takes a String. An example of this would | use the constructor that takes a String. An example of this would |
be an Exception where you are passing in a file name. Most of the | be an Exception where you are passing in a file name. Most of the |
"non-CIM" exceptions defined in Exception.h and InternalException.h take | "non-CIM" exceptions defined in Exception.h and InternalException.h take |
un-localized data. |
un-localized data. <br> |
<br> |
</p> |
<p><b>The Exception Macros</b> |
<p><b>The Exception Macros</b> <br> |
<br> |
</p> |
<p>There are many spots in the server code that use the PEGASUS_CIM_EXCEPTION |
<p>There are many spots in the server code that use the |
macro to throw a TraceableCIMException. The use of this macro in |
PEGASUS_CIM_EXCEPTION macro to throw a TraceableCIMException. The |
the code like the following example presented a design problem: |
use of this macro in the code like the following example presented a |
<p>.... |
design problem: </p> |
<br>} catch (Exception & e) |
<p>.... <br> |
<br>{ |
} catch (Exception & e) <br> |
<br> throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, e.getMessage()); |
{ <br> |
<br>} |
throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, |
<br> |
e.getMessage()); <br> |
|
} <br> |
|
</p> |
<p>This type of code would have lost the ContentLanguages saved in "e", | <p>This type of code would have lost the ContentLanguages saved in "e", |
so that the Content-Language would not be set in HTTP response to the client. |
so that the Content-Language would not be set in HTTP response to the |
<br> |
client. <br> |
<p>For Pegasus 2.3, these types of macro calls can stay. The TraceableCIMException |
</p> |
constructed by the macro will "re-localize". That is, the "CIM" part |
<p>For Pegasus 2.3, these types of macro calls can stay. The |
of the message (the part based on the error code) will be localized at |
TraceableCIMException constructed by the macro will "re-localize". |
throw time, and the ContentLanguages re-established. A key is to |
That is, the "CIM" part of the message (the part based on the error |
avoid a "language mismatch" problem between the CIM part of the message |
code) will be localized at throw time, and the ContentLanguages |
and the extra part of the message. The design point here is that |
re-established. A key is to avoid a "language mismatch" problem |
all internal exceptions thrown by Pegasus code are localized using the |
between the CIM part of the message and the extra part of the |
global AcceptLanguages of the Thread...see above. |
message. The design point here is that all internal exceptions |
<br> |
thrown by Pegasus code are localized using the global AcceptLanguages |
<p>In the future, it will be safer and more maintainable to use of the |
of the Thread...see above. <br> |
new "localized" flavors of the macro. For example: |
</p> |
<br> |
<p>In the future, it will be safer and more maintainable to use of |
<p>When the message from a caught Exception needs to be become the |
the new "localized" flavors of the macro. For example: <br> |
extra message in a thrown CIMException: |
</p> |
<p>.... |
<p>When the message from a caught Exception needs to be become |
<br>} catch (Exception & e) |
the extra message in a thrown CIMException: </p> |
<br>{ |
<p>.... <br> |
<br> throw PEGASUS_CIM_EXCEPTION_LANG(e.getContentLanguages( |
} catch (Exception & e) <br> |
), |
{ <br> |
<br> |
throw |
CIM_ERR_FAILED, |
PEGASUS_CIM_EXCEPTION_LANG(e.getContentLanguages( ), <br> |
<br> |
|
e.getMessage( )); |
CIM_ERR_FAILED, <br> |
<br>} |
|
<br> |
e.getMessage( )); <br> |
<p>This guarantees that the ContentLanguages in "e" is copied to the newly |
} <br> |
created TraceableCIMException. |
</p> |
<br> |
<p>This guarantees that the ContentLanguages in "e" is copied to the |
<p>In the case where the extra message for the CIMException is determined |
newly created TraceableCIMException. <br> |
by the throwing code: |
</p> |
<br> |
<p>In the case where the extra message for the CIMException is |
<p>throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, |
determined by the throwing code: <br> |
<br> |
</p> |
MessageLoaderParms("Repository.CIMRepository.COMPACT_FAILED", "compact |
<p>throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, <br> |
failed")); |
|
<br> |
MessageLoaderParms("Repository.CIMRepository.COMPACT_FAILED", |
<p>(example from CIMRepository.cpp) |
"compact failed")); <br> |
<br>This uses a MessageLoaderParms object to localize the extra message |
</p> |
in the newly created TraceableCIMException. |
<p>(example from CIMRepository.cpp) <br> |
<br> |
This uses a MessageLoaderParms object to localize the extra message in |
<h3> |
the newly created TraceableCIMException. <br> |
5.2 Logger Messages</h3> |
</p> |
|
<h3> 5.2 Logger Messages</h3> |
<p><br>New methods have been added to Logger to take a message ID of a |
<p><br> |
message to be loaded from the Pegasus server resource bundle. The |
New methods have been added to Logger to take a message ID of a message |
caller is only required to pass in the message ID, the old "hardcoded" |
to be loaded from the Pegasus server resource bundle. The caller |
message, and the args. The Logger will use MessageLoader to load |
is only required to pass in the message ID, the old "hardcoded" message, |
the message in the locale of the Pegasus server <i>process</i>, using the |
and the args. The Logger will use MessageLoader to load the |
hardcoded message as the default string. Please refer to pegasus/src/Pegasus/Logger.h. |
message in the locale of the Pegasus server <i>process</i>, using the |
|
hardcoded message as the default string. Please refer to |
|
pegasus/src/Pegasus/Logger.h. </p> |
<p>Note: Messages sent to the "logs", whether the system logs or | <p>Note: Messages sent to the "logs", whether the system logs or |
the Pegasus log file, are converted to UTF-8 before being sent. |
the Pegasus log file, are converted to UTF-8 before being sent. <br> |
<br> |
</p> |
<h3> |
<h3> 5.3 CLI Messages</h3> |
5.3 CLI Messages</h3> |
<p><br> |
|
The goal for messages returned by the Pegasus CLIs is to localize in |
<p><br>The goal for messages returned by the Pegasus CLIs is to localize |
the locale of the user running the CLI. This should be automatic |
in the locale of the user running the CLI. This should be automatic |
-- the user should not be required to tell the CLI what the locale |
-- the user should not be required to tell the CLI what the locale is. |
is. For the CLIs that are CIM clients (cimconfing, |
For the CLIs that are CIM clients (cimconfing, cimprovider) there are two |
cimprovider) there are two sets of messages to localize -- |
sets of messages to localize -- messages generated in the CLI process |
messages generated in the CLI process itself, and messages returned from |
itself, and messages returned from the Pegasus server . For CLIs |
the Pegasus server . For CLIs that are directly linked into |
that are directly linked into Pegasus (cimmofl), all the messages are generated |
Pegasus (cimmofl), all the messages are generated in the CLI's process, |
in the CLI's process, but the CLI may call Pegasus APIs that are coded |
but the CLI may call Pegasus APIs that are coded to localize based on a |
to localize based on a client's requested languages. |
client's requested languages. <br> |
<br> |
</p> |
<p>Code in the client side of the client/server CLIs (eg. cimconfig, cimmof), |
<p>Code in the client side of the client/server CLIs (eg. cimconfig, |
or in directly linked CLIs (cimmofl), should use the _useProcessLocale |
cimmof), or in directly linked CLIs (cimmofl), should use the |
"master switch" described in the Message Loading section. This will |
_useProcessLocale "master switch" described in the Message Loading |
cause all messages, including exceptions thrown by Pegasus APIs, |
section. This will cause all messages, including exceptions thrown |
to be loaded in the locale based on the environment in which the program |
by Pegasus APIs, to be loaded in the locale based on the |
is running. This locale can be set by the user before running the |
environment in which the program is running. This locale can be |
program. |
set by the user before running the program. <br> |
<br> |
</p> |
<p>Code in the client side of the client/server CLIs need to send an Accept-Language |
<p>Code in the client side of the client/server CLIs need to send an |
to the Pegasus server that reflects the default locale of the CLI's process. |
Accept-Language to the Pegasus server that reflects the default locale |
See the Client Developer section for details. |
of the CLI's process. See the Client Developer section for |
<br> |
details. <br> |
<p>An example of these considerations can be seen in the source code for |
</p> |
cimconfig. |
<p>An example of these considerations can be seen in the source code |
<br> |
for cimconfig. <br> |
<p> |
</p> |
|
<p> </p> |
<hr> | <hr> |
<p><i>Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, |
<p><i>Copyright (c) 2003 BMC Software; Hewlett-Packard Development |
L.P.; IBM Corp.; The Open Group</i> |
Company, L.P.; IBM Corp.; The Open Group</i> </p> |
<p><i>Permission is hereby granted, free of charge, to any person obtaining |
<p><i>Permission is hereby granted, free of charge, to any person |
a copy of this software and associated documentation files (the "Software"), |
obtaining a copy of this software and associated documentation |
to deal in the Software without restriction, including without limitation |
files (the "Software"), to deal in the Software without restriction, |
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
including without limitation the rights to use, copy, modify, merge, |
and/or sell copies of the Software, and to permit persons to whom the Software |
publish, distribute, sublicense, and/or sell copies of the Software, and |
is furnished to do so, subject to the following conditions:</i> |
to permit persons to whom the Software is furnished to do so, subject |
<p><i>THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED |
to the following conditions:</i> </p> |
IN ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS |
<p><i>THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE |
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
INCLUDED IN ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE |
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT |
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
SOFTWARE.</i> |
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
<br> |
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</i> <br> |
<br> |
<br> |
|
</p> |
</body> | </body> |
</html> | </html> |