This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
This document describes how Java Resource Bundles
(ListResourceBundle
and
PropertyResourceBundle
) should be coded when
extracted to an XLIFF document.
This document is a Preliminary Working Draft of the committee. It is an OASIS draft document for review by OASIS members and other interested parties. Comments may be sent to xliff-comment@lists.oasis-open.org.
This document may be updated, replaced, or rendered obsolete by other documents at any time. It may also be discarded without further follow up. It is inappropriate to use this document as reference material other than "work in progress".
1. Introduction
1.1. Purpose
1.2. Transitional and Strict
2. General Considerations
2.1. Java Resource Types
2.2. ListResourceBundle
2.3. PropertyResourceBundle
2.4. Extraction Techniques
2.5. Order Of Extraction
2.6. Key Identifier
2.7. Preserving Message Replaceables in Value
2.8. Comments
2.9. Sample Properties File represented as XLIFF
2.10 Sample List Resources Java Class represented as XLIFF
As different tools may provide different filters to extract the content of Java Resource Bundles, it is important for interoperability that they represent the extracted data in identical manner in the XLIFF document.
The intent of this document is to provide a set of guidelines to represent data contained in Java Resource Bundles as XLIFF content. It offers a collection of recommended mapping of Java Resource Bundles that developers of XLIFF filters can implement, and users of XLIFF utilities can rely on to insure a better interoperability between tools.
XLIFF is specified in two "flavors". Indicate which of these variants you are using by selecting the appropriate schema. The schema may be specified in the XLIFF document itself or in an OASIS catalog. The namespace is the same for both variants. Thus, if you want to validate the document, the tool used knows which variant you are using. Each variant has its own schema that defines which elements and attributes are allowed in certain circumstances.
As newer versions of XLIFF are approved, sometimes changes are made that render some elements, attributes or constructs in older versions obsolete. Obsolete items are deprecated and should not be used even though they are allowed. The XLIFF specification details which items are deprecated and what new constructs to use.
Transitional - Applications that produce older versions of XLIFF may still use deprecated items. Use this variant to validate XLIFF documents that you read. Deprecated elements and attributes are allowed.
xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd'
Strict - All deprecated elements and attributes are not allowed. Obsolete items from previous versions of XLIFF are deprecated and should not be used when writing new XLIFF documents. Use this to validate XLIFF documents that you create.
xsi:schemaLocation='urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-strict.xsd'
This section discusses the general considerations to take in account when extracting Java Resource Bundle data.
Java's architecture supports the localization of application
resources via the java.util.ResourceBundle
abstract class. This class has two subclasses:
PropertyResourceBundle
and
ListResourceBundle
. A ResourceBundle
contains key/value pairs, where each key uniquely identifies
locale-specific objects in the bundle. Non-string resources,
binary objects, must be stored in
ListResourceBundle
, since the
PropertyResourceBundle
can only contain
String
objects. String values can contain
MessageFormat
replaceables, which are delimited
within {}
.
A ListResourceBundle
is a list of resources
stored in a .class file. Compiled resources are stored in
binary format, which means ListResourceBundle
can
contain localized resources of any data type.
Additional locales are created by copying the base .java file to a locale specific .java file identified by adding a locale suffix to its filename. After translation has been completed, the localized .java file is compiled into a .class file.
Listing 1 shows a sample
ListResourceBundle
class named
"DiskResources.java" and a version for "es" locale.
import java.awt.Rectangle; import java.util.ListResourceBundle; public class DiskResources extends ListResourceBundle { public Object[][] getContents() { return contents; } static final Object[][] contents = { {"key1", "Cabinet {0} contains {1} folders."}, {"key2", "Folder {0} contains {1,choice,0#no files|1#one file|1<{1,number,integer} files}."}, {"key3", "Folder \'{0}\' is empty."}, {"key4", "File \"My Stuff\" deleted."}, {"key5", "Added {0,number} files."}, {"key6", new Rectangle(10,25,100,150)}, {"key7", "No files were removed while processing " + "current folder."} }; } -------------------------------------------- import java.awt.Rectangle; import java.util.ListResourceBundle; public class DiskResources_es extends ListResourceBundle { public Object[][] getContents() { return contents; } static final Object[][] contents = { {"key1", "El gabinete {0} contiene {1} carpetas."}, {"key2", "La carpeta {0} contiene {1,choice,0#cero archivos|1#un archivo|1<{1,number,integer} archivos}".}, {"key3", "La carpeta \'{0}\' está vacía."}, {"key4", "Archivo \"Mis cosas\" eliminado."}, {"key5", "{0,number} archivos añadidos."}, {"key6", new Rectangle(10,25,100,150)}, {"key7", "Ningún archivo fue eliminado al procesar " + "la carpeta actual."} }; }
Listing 1 - Sample List Resource file
PropertyResourceBundle
is a concrete
implementation of ResourceBundle
class that stores
translatable String
resources in plain text files
via name-value pairs using "name=value" syntax.
The resources of a PropertyResourceBundle
are
stored in files with the extension ".properties". Properties
files strings are fetched at run-time, they are not compiled.
The keys are case-sensitive and should be unique within the
.properties file.
Listing 2 below is a sample
PropertyResourceBundle
.properties file with four
localizable strings.
# Copyright information key1=Copyright \u00A9 2006 FARO Inc. key2=Box 12 is {0,number} inches high. key3=Box ''{0}'' is blue. key4=Boxes are built in three sizes: small, \ medium and large.
Listing 2 - Sample .properties file
Resource Bundles are Java code and not XML. Therefore, XSL transformation standards cannot directly be utilized to convert the resource bundles into XLIFF. XSLT could be used to transform the translated XLIFF back to the native Java, or to manipulate an intermediate XML or initial XLIFF file in preparation for manual or automated Computer Aided Translation (CAT), but software best practices favour using the same technology for both extraction and recomposition.
The class java.util.Properties
provides methods
for converting .properties files to XML format. Listing 3 shows the XML version of the
.properties file from Listing 2.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>Listing 2</comment> <entry key="key4">Boxes are built in three sizes: small, medium and large.</entry> <entry key="key3">Box ''{0}'' is blue.</entry> <entry key="key2">Box 12 is {0,number} inches high.</entry> <entry key="key1">Copyright © 2006 FARO Inc. </entry> </properties>
Listing 3 - Java resources in XML format
XML files generated using class Properties
can
be converted to XLIFF using XSL transformations or specialized
XML filters. Processing of Java resources stored in XML format
is beyond the scope of this document.
It is necessary to extract the Java Resource Bundles- List and Property - to XLIFF by developing a custom filter application. Such tools can be written using a variety of programming and scripting languages such as Perl, Python, C, C++, C#, Java, etc..
This document makes no assumption on the type of language
used to process the Java ResourceBundle
input
documents. It also makes no assumptions whether or not the tool
creates a Skeleton file along with the XLIFF document
generated, or if it creates one, how data are represented in
the Skeleton.
The following guidelines should be adhered to:
<file>
element in an XLIFF documentdatatype
attribute of a
<file>
element is set to
javapropertyresourcebundle
or
javalistresourcebundle
, depending on the type of
resource<body>
element contains a separate
<trans-unit>
element for each key-value
pairtranslate
attribute of
<trans-unit>
element is set to
no
when the value string is a null string<source>
elementCharacters that require a special representation in a
ResourceBundle
should be parsed by the XLIFF
filter and represented appropriately in the XLIFF file. The
following cases should be contemplated when designing a
filter:
\
' character in ListResourceBundle
classes. Filters should use unescaped versions of these
characters in the XLIFF file.\uXXXX
Java notation for
Unicode. Filters should replace encoded characters with their
appropriate Unicode versions in the XLIFF file.+
'
operator in ListResourceBundle
classes (see the
last entry in Listing 1). Filters
should automatically merge concatenated strings.\
' character at the end of a line in a
.properties file indicates that the text to translate
continues in the following line (see the last entry in
Listing 2). Filters should
automatically merge split lines.The flow of the extracted data in the XLIFF document should
be in the same order as the flow of data in the original
ResourceBundle
. The extraction order should
reflect the order of the data in the source document, and the
author is responsible to group logical parts of the text
together as much as possible.
The identifier used for matching, leveraging, and other
ID-related functions is stored in the resname
attribute. The key of the resource becomes the
resname
attribute value of the
<trans-unit>
element.
The required id
attribute of the XLIFF
<trans-unit>
element is an identifier
allowing extraction tools to merge back the data. The value of
the id
attribute is serially assigned, according
the retrieval order, to maintain consistency and
uniqueness.
Variable data is represented in Java strings using special
descriptors surrounded by {
and }
.
Those descriptors, called "replaceables", are processed by the
MessageFormat
class at run-time to display
variable data in the appropriate format for the selected
locale. MessageFormat
replaceables should be
enclosed in <ph>
elements by the filter that
generates the XLIFF representation. If Skeleton files are used,
a replaceable can optionally be represented with an
<x/>
tag instead of a
<ph>
element.
Replaceables of type choice
include a parameter
with two or more translatable strings. The string to display is
selected at run-time according to a given condition.
Replaceables of type choice
should be encapsulated
in <ph>
elements, enclosing translatable
strings in <sub>
elements. Filter designers
can parse the parameter with strings and hide the logic from
the translator by using more than one <sub>
element or expose the whole parameter, giving the translator
the possibility to change the selection criteria according to
the grammar of the target language. Listing 4 shows a replaceable of type
choice
and its two possible representations.
key2=Folder {0} contains {1,choice,0#no files|1#one file|1<{2,number,integer}files}. -------------------------------------------- <source>Folder <ph id="1">{0}</ph> contains <ph id="2">{1,choice,0#<sub>no files</sub>|1#<sub>one file</sub>|1<{2,number,integer}<sub>files</sub>}</ph>. </source> <source>Folder <ph id="1">{0}</ph> contains <ph id="2">{1,choice,<sub>0#no files|1#one file|1<{2,number,integer}files</sub>}</ph>. </source>
Listing 4 - XLIFF representation of choice-type replaceables
Best localization practices recommend using class
java.text.MessageFormat
to produce concatenated
messages in language-neutral way. However, it is possible to
concatenate translatable strings and variables using a
'+
' operator.
Filters should encapsulate variables and operators using either
<ph>
or <x/>
tags as
shown in Listing 5.
String title = getBookTitle(); int bookNumber = 23801; public Object[][] getContents() { return contents; } static final Object[][] contents = { {"key1", "Title: " + title + " - Number: " + bookNumber}, }; -------------------------------------------- <source>Title: <ph id="1"> + title + </ph> - Number: <ph id="2"> + bookNumber</ph></source>
Listing 5 - Strings and variables concatenated.
Although most of the XLIFF inline tags are represented in
the TMX Standard, the <x/>
tag is not. TMX is a standard to
exchange Translation Memory (TM) data created by Computer Aided
Translation (CAT) and localization tools. If you plan to store
or deliver XLIFF text content using TMX, you may wish to use
<ph>
elements for encapsulating
replaceables. Otherwise, you will need to represent
<x/>
tags in some alternate way
in TMX.
Lines that start with a #
character are
comments in .properties files. These lines do not contain
translatable text. Filter designers may optionally concatenate
consecutive comment lines and include them as context
information in one <note>
element in the
first <trans-unit>
generated after
extracting the comments.
Comments in classes derived from
ListResourceBundle
are subject to Java coding
rules. If an XLIFF filter tool finds comments inside a run of
localizable text in a class that extends
ListResourceBundle
, the comment should be
preserved by being treated as inline code and enclosed in a
<ph>
element. If Skeleton files are used,
the comment can optionally be represented with an
<x/>
tag instead of a
<ph>
element.
In ListResourceBundle
resources, if an XLIFF
filter finds comments following a key value pair, those comments
can be associated with the corresponding
<trans-unit>
element using a
<note>
element.
Listing 6 below contains the XLIFF representation of the .properties file shown in Listing 2.
<?xml version="1.0" encoding="UTF-8"?> <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-strict.xsd"> <file original="sample.properties" source-language="en" datatype="javapropertyresourcebundle"> <body> <trans-unit id="0" resname="key1"> <source xml:lang="en">Copyright © 2006 FARO Inc. </source> <note>Copyright information</note> </trans-unit> <trans-unit id="1" resname="key2"> <source xml:lang="en">Box 12 is <ph id="1">{0,number}</ph> inches high.</source> </trans-unit> <trans-unit id="2" resname="key3"> <source xml:lang="en">Box ''<ph id="1">{0}</ph>'' is blue.</source> </trans-unit> <trans-unit id="3" resname="key4"> <source xml:lang="en">Boxes are built in three sizes: small, medium and large.</source> </trans-unit> </body> </file> </xliff>
Listing 6 - XLIFF representation of a .properties file
Listing 7 shows the XLIFF document with localizable data extracted from the class "DiskResources.java" included in Listing 1.
<?xml version="1.0" encoding="UTF-8"?> <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-strict.xsd"> <file original="DiskResources.java" source-language="en" datatype="javalistresourcebundle"> <body> <trans-unit id="0" resname="key1"> <source>Cabinet <ph id="1">{0}</ph> contains <ph id="2">{1}</ph> folders.</source> </trans-unit> <trans-unit id="1" resname="key2"> <source>Folder <ph id="1">{0}</ph> contains <ph id="2">{1,choice,<sub>0#no files|1#one file|1<{0,number,integer} files}</sub> </ph>.</source> </trans-unit> <trans-unit id="2" resname="key3"> <source>Folder '<ph id="1">{0}</ph>' is empty.</source> </trans-unit> <trans-unit id="3" resname="key4"> <source>File "My Stuff" deleted.</source> </trans-unit> <trans-unit id="4" resname="key5"> <source>Added <ph id="1">{0,number}</ph> files.</source> </trans-unit> <trans-unit id="5" resname="key7"> <source>No files were removed while processing current folder.</source> </trans-unit> </body> </file> </xliff>
Listing 7 - XLIFF representation of a List Resource Bundle
The following people have contributed to this document: