Data Format Description Language (DFDL) v1.0 Specification
OGF Proposed Recommendation GFD-P-R.174, January 31, 2011


12.3 Properties for Specifying Lengths

These properties are used to determine the representation length of an element and apply to elements of all types (simple and complex).

Property Name

Description

lengthKind

Enum

Controls how the representation length of the component is determined.

Valid values are: 'explicit', 'delimited', 'prefixed', 'implicit', 'pattern', 'endOfParent'

A full description of each enumeration is given in the later sections.

'explicit' means the length of the item is given by the dfdl:length property

'delimited' means the item is delimited by a terminator or separator

‘prefixed’ means the length of the item is given by an immediately preceding prefix field specified using prefixLengthType.

‘implicit means the length is to be determined in terms of the type of the element and its schema-specified properties if any.

‘pattern’ means the length of the item is given by a regular expression specified using the dfdl:lengthPattern property.

‘endOfParent’ means that the item is terminated by the termination of the containing construct.

Annotation: dfdl:element, dfdl:simpleType

lengthUnits

Enum

Valid values ‘bytes’, ‘characters’, '‘bits’.

Specifies the units to be used whenever a length is being used to extract or write data. Applicable when lengthKind is ‘explicit’, 'implicit' (for xs:string and xs:hexBinary) or ‘prefixed’.

'characters' may only be used for simple elements with representation 'text' and complex elements where all the simple child elements must be dfdl:representation 'text', dfdl:lengthUnits 'characters' and the same dfdl:encoding as the parent.

'bits' may only be used for xs:boolean, xs:unsignedByte, xs:unsignedShort, xs:unsignedInt, and xs:unsignedLong simple types with representation 'binary'.

Annotation: dfdl:element, dfdl:simpleType

12.3.1 dfdl:lengthKind 'explicit'

When lengthKind='explicit' the length of the item is given by the dfdl:length property, and is measured in units given by dfdl:lengthUnits. Used on parsing and unparsing.

Property Name

Description

length

Non-negative Integer or DFDL Expression.

Only used when lengthKind is ’explicit’.

Specifies the length of this element in units specified by dfdl:lengthUnits.

This property can be computed by way of an expression which returns a non-negative integer. The expression must not contain forward references to elements which have not yet been processed.

Annotation: dfdl:element, dfdl:simpleType

When dfdl:lengthKind 'explicit', the method of extracting data that is described in section: ‎12.3.7 Elements of Specified Length.

12.3.2 dfdl:lengthKind 'delimited'

On parsing, the length of an element with dfdl:lengthKind 'delimited' is determined by scanning the datastream for any of

dfdl:lengthKind 'delimited' may be specified for

The rules for resolving ambiguity between delimiters are:

  1. When two delimiters have a common prefix, the longest delimiter has precedence.

  2. When two delimiters have exactly the same value, the innermost (most deeply nested) delimiter has precedence.

  3. When the separator and terminator on a group have the same value, the separator has precedence.

On unparsing the length of an element in the data stream is the representation length of the value, padded to dfdl:textOutputMinLength or xs:minLength if dfdl:textPadKind is 'padChar'.

12.3.2.1 Simple Elements of Specified Length within Delimited Constructs

When a simple element has a specified length then delimiter scanning is suspended for the duration of the processing of the specified-length element.

This allows formats to be parsed which are not scanable in that they contain non-character data.

12.3.3 dfdl:lengthKind 'implicit'

When dfdl:lengthKind is ‘implicit', the length is determined in terms of the type of the element and its schema-specified properties.

For complex elements, 'implicit' means the length is determined by the combined lengths of the contained children, that is the ComplexContent region.

For simple elements the length is fixed and is given in the following table.
 

Representation

 

text

binary

String

maxlength

Not applicable

Float

Not allowed

32

Double

Not allowed

64

Decimal, Integer, nonNegativeInteger

Not allowed

packed/bcd : Not allowed

binary: Not allowed

Long, UnsignedLong

Not allowed

packed/bcd : Not allowed

binary: 64

Int, UnsignedInt

Not allowed

packed/bcd : Not allowed

binary: 32

Short, UnsignedShort

Not allowed

packed/bcd : Not allowed

binary: 16

Byte, UnsignedByte

Not allowed

packed/bcd : Not allowed

binary: 8

DateTime

Not allowed

packed/bcd: Not allowed

binarySeconds: 32, binaryMilliseconds:64

Date

Not allowed

packed/bcd : Not allowed

binarySeconds: 32, binaryMilliseconds:64

Time

Not allowed

packed/bcd : Not allowed

binarySeconds: 32, binaryMilliseconds:64

Boolean

Length of longest of textBooleanTrue and textBooleanFalse

32

HexBinary

Not applicable

maxlength

Table 15 Length in bits for simpleTypes when dfdl:lengthKind='implicit'

 

Note: Specifying the implicit length in bits does not imply that dfdl:lengthUnits 'bits' can be specified for all simple types.

When dfdl:lengthKind is 'implicit', the method of extracting data that is described in section: ‎12.3.7 Elements of Specified Length.

12.3.4 dfdl:lengthKind 'prefixed'

When dfdl:lengthKind is ‘prefixed’ the length of the element is given by the PrefixLength region specified using prefixLengthType. The property prefixIncludesPrefixLength also can be used to adjust the length appropriately.

When dfdl:lengthKind is 'prefixed' the method of extracting data that is described in section: ‎12.3.7 Elements of Specified Length.

Property Name

Description

prefixIncludesPrefixLength

Enum

Valid values are 'yes', 'no'

Whether the length given by a prefix includes the length of the prefix as well as the length of the content region.

Used only when lengthKind=’prefix’.

Annotation: dfdl:element, dfdl:simpleType

prefixLengthType

QName

Name of a simple type derived from xs:integer or any subtype of it.

This type, with its DFDL annotations specifies the representation of the length prefix, which is in the PrefixLength region.

It is a schema definition error if the xs:simpleType specifies dfdl:lengthKind 'delimited' or 'endOfParent' or a dfdl:outputValueCalc

Annotation: dfdl:element, dfdl:simpleType

The representation of the element is in two parts.

  1. The 'length prefix' is an integer which specifies the length of the element's content. The representation of the length prefix is described by a simple type which is identified using the dfdl:prefixLengthType property.

  2. The content of the element.

When parsing, the length of the element’s content is obtained by parsing the simple type specified by dfdl:prefixLengthType to obtain an integer value. Note that all required properties must be present on the specified simple type or defaulted because there is no element declaration to supply any missing required properties.

If the dfdl:prefixIncludesPrefixLength property is 'yes' then the length of the element's content is the value of the length prefix minus the length of the representation of the length prefix.

When unparsing, the length of the element’s content must be determined first. The length of a simple element in the data stream is the representation length of the value, padded to dfdl:textOutputMinLength or xs:minLength if dfdl:textPadKind is 'padChar'. The length of a complex element is the combined length of its children including their initiators, separators and terminators.

Then the value of the prefix length must be calculated using dfdl:prefixIncludesPrefixLength.

Then the prefix length can be written to the data stream using the properties on the dfdl:prefixLengthType, and finally the element's content can be written to the data stream.

. Consider this example:
<xs:element name="myString" type="xs:string"
      dfdl:lengthKind="prefixed"
      dfdl:prefixIncludesPrefixLength="false"
      dfdl:prefixLengthType="packed3"/>

<xs:simpleType name="packed3"
      dfdl:representation="binary"
      dfdl:binaryNumberRep ="packed"
      dfdl:lengthKind="explicit"
      dfdl:length="2" >
  <xs:restriction base="integer" />
</xs:simpleType>

In the above, the string has a prefix element of type 'packed3' containing 3 packed decimal digits.

The property dfdl:prefixIncludesPrefixLength is an enumeration which allows the length computation to be varied to include or exclude the length of the prefix element itself.

The prefix element's value contains the length measured in units given by dfdl:lengthUnits.

When unparsing data, the value of the prefix is computed automatically and inserted into the data before the element.

12.3.5 dfdl:lengthKind 'pattern'

The dfdl:lengthKind ‘pattern’ means the length of the element is given by a regular expression specified using the dfdl:lengthPattern property. The DFDL processor scans the data stream to determine a string value that is the longest match to a regular expression. The pattern is only used on parsing.

Property Name

Description

lengthPattern

DFDL Regular Expression.

Only used when lengthKind is ’pattern’.

Specifies a regular expression that, on parsing, is executed against the datastream to determine the length of the element.

The data stream beginning at the starting offset of the content region of the element is interpreted as a stream of characters in the encoding of the element, and the regular expression contained in the dfdl:lengthPattern property is executed against that stream of characters. When the element is complex this is the dfdl:encoding of the complex element itself. Child content contained within the element must be scannable (see below).

Escape schemes are not applied when executing the regular expression.

If the regular expression returns a matched length of zero ( i.e. no match ) then the element has a zero-length representation. If the element is not allowed to have a zero-length representation then the appropriate processing error is reported. Otherwise, normal processing of nils and default values occurs.

It is a processing error if conversion of data into a string based on the character set encoding causes an error due to illegal bit patterns that are not legal for the encoding.

Annotation: dfdl:element, dfdl:simpleType

On unparsing if the element is complex then the length of the element is the length of its children. If the element is simple then the length is given in Table 16 Unparse lengths (in bits) for dfdl:lengthKind 'pattern'.
 

Representation

 

text

binary

String

unpadded length

Not applicable

Float

unpadded length

32

Double

unpadded length

64

Decimal, Integer, nonNegativeInteger

unpadded length

Minimum number of bytes to represent significant digits and sign

Long, UnsignedLong

unpadded length

packed/bcd : as decimal

binary: 64

Int, UnsignedInt

unpadded length

packed/bcd : as decimal

binary: 32

Short, UnsignedShort

unpadded length

packed/bcd : as decimal

binary: 16

Byte, UnsignedByte

unpadded length

packed/bcd : as decimal

binary: 8

DateTime

unpadded length

packed/bcd : as decimal

binarySeconds: 32, binaryMilliseconds:64

Date

unpadded length

packed/bcd : as decimal

binarySeconds: 32, binaryMilliseconds:64

Time

unpadded length

packed/bcd : as decimal

binarySeconds: 32, binaryMilliseconds:64

Boolean

Length of textBooleanTrue or textBooleanFalse

32

HexBinary

Not applicable

Length of infoset value

Table 16 Unparse lengths (in bits) for dfdl:lengthKind 'pattern'

 

12.3.5.1 Pattern-Based Lengths - Scanability

Any element (complex, simple text, simple binary) may have a dfdl:lengthKind 'pattern' as long as the bytes in the content region of the element are legal in the stated encoding of that element. Where a complex element has children with binary representation in practice this means an 8-bit ASCII encoding. Binary data can be handled by way of treating it as text with encoding='iso-8859-1'. In this case the text is interpreted as in the iso-8859-1 character encoding, and the correspondence of byte values in the data to a string in the DFDL infoset is one to one. That is, byte with value N, produces an infoset character with character code N.

12.3.6 dfdl:lengthKind 'endOfParent'

The dfdl:lengthKind ‘endOfParent’ means that the element is terminated by the end of the data stream or the end of an enclosing complex element, sequence or choice. The enclosing component must have an identifiable end point, such as a known length, a delimiter, or end of data stream. The enclosing component does not have to be the immediate parent of the element, but there must be no other elements defined between the element specifying 'endOfParent' and the end of the enclosing component.

A dfdl:lengthKind of 'endOfParent' can only be used on simple elements in the following locations:

It is a schema definition error if the element has a terminator.

It is a schema definition error if the element has dfdl:trailingSkip not equal to 0.

It is a schema definition error if the element has maxOccurs > 1.

It is a schema definition error if any other element is defined between this element and the end of the enclosing component.

The dfdl:lengthKind 'endOfParent' is used when the length of an element is defined by an enclosing element . For example, the parent is a fixed length element then an element with dfdl:lengthKind 'endOfParent' will consume all the remaining data up to the length of the parent. A dfdl:lengthKind 'endOfParent' can also be used to allow the last element to consume the data up to the end of the data stream.

This is distinct from situation where the lengths of the elements of a sequence are known but are not sufficient to fill the fixed length parent. In that case the remaining data are ignored on parsing and filled with dfdl:fillByte on unparsing.

12.3.7 Elements of Specified Length

An element has a specified length when dfdl:lengthKind is 'explicit', 'implicit' or 'prefixed'. The units that the length represents are specified by the dfdl:lengthUnits property, expect when dfdl:lengthKind is 'implicit' and the simpleType is not xs:string or xs:hexBinary.

If dfdl:lengthUnits='bytes' then the value of the length property gives the exact length in bytes.

If dfdl:lengthUnits='characters' then the length in bytes will depend on the encoding of the characters. If the encoding property specifies a fixed-width encoding then the length in bytes is (character width*length). If the encoding property specifies a variable-width encoding then the length in bytes will depend on the actual characters in the element's value. The dfdl:lengthUnits 'characters' may only be used when dfdl:representation is 'text'.

If dfdl:lengthUnits='bits' then the value of the length property gives the exact length in bits. 'Bits' may only be used for a limited set of schema types. See section: ‎12.3.7.2 Length of Bit Fields

Using specified length, it is possible for an element to have representation length longer than needed to represent just the data. For example, a simple text element may be padded in the RightPadOrFill region if the data is not long enough.

12.3.7.1 Length of Simple Elements with dfdl:representation 'text'

Textual data is defined to mean either data of type string (independent of representation), or data where the representation property is 'text'.

12.3.7.1.1 Character Width

The width of a character is the length of its representation in bytes and depends on the dfdl:encoding property.

Character encodings are themselves either intrinsically fixed or variable width, but this is modified by additional properties.

fixed, 1 byte (e.g., ASCII)

fixed, 2 byte (e.g., UCS-2)

fixed, 4 byte (e.g., UTF-32)

variable (e.g., Shift_JIS, UTF-8, UTF-16)

1

2

4

Variable width.

Min = 1, Max = encoding dependent, 2

Table 17 Character Widths

 

We define the term fixed width encoding to mean an encoding and associated other representation properties where the value in the bottom row of the above table is a fixed integer.

The term variable width encoding is the opposite. In a variable width encoding, the characters have a minimum and a maximum length. The maximum depends on the encoding, but is typically either 3 (Shift-JIS), or 4 (UTF-8).

UTF-16, UTF16LE and UTF16BE are a variable width encodings, however when dfdl:utf16Width is 'fixed' they are treated as a 2 byte fixed width encoding.

12.3.7.1.2 Text Length in Characters when Specified in Bytes

If a simple element has dfdl:representation=’text’ but dfdl:lengthUnits=’bytes’ then the following rules apply:

12.3.7.1.3 Byte Order Mark

If a byte-order mark codepoint appears at the start of a UTF-8, UTF-16 or UTF-32 encoded string then the byte-order mark will be included as part of the string payload.1 That is, for the UTF-8, UTF-16 and UTF-32 character encodings, a byte-order-mark codepoint is treated as a character of the string in DFDL and contributes to the length.

A way of eliminating the byte-order mark so that it does not end up in the infoset is that the byte-order mark can be modeled as a separate element before the string. This BOM element can be either required or optional depending on whether one is expected or optional at the beginning of the string.

12.3.7.2 Length of Bit Fields

A bit field is an element of integer type where the lengthUnits=’bits’.

It is a schema definition error if the length of a bit field is too large for the corresponding integer type, and the length can be statically determined (from the schema only).

It is a runtime schema definition error if the length of a bit field can only be determined dynamically (for example because it is stored in the data), and the resulting length is too large for the integer type.

Definition: Bit position

The data stream is assumed to be a collection of consecutively numbered unsigned bytes. Each byte is a numeric value, and bit position within an individual byte is given by numeric behavior.  The bits within each byte are numbered, with the most significant bit having position 1, and the least significant bit having position 8. 

This gives every bit in the data stream a specific bit position. Furthermore, the bit position of the least significant bit of byte N is numerically adjacent to the bit position of the most significant bit of byte N+1. 

Definition: Bit string

For types xs:boolean, xs:unsignedByte, xs:unsignedShort, xs:unsignedInt, and xs:unsignedLong, it is possible to specify dfdl:lengthUnits='bits', dfdl:lengthKind='explicit', and then provide a dfdl:length expression. This expression must be a literal integer, the value of which is between (inclusively) 1 and 32, 8, 16, 32, and 64 respectively for these types. Such an element is called a bit string for brevity.

If the dfdl:length expression contains a value out of range then it is a schema definition error.

When parsing, if the data stream ends without enough bits to parse a bit string, that is, N bits are required based on the dfdl:length, but only M < N bits are available, then it is a processing error. 

(Note: This is not specific to bit strings. Any binary type whose length cannot be satisfied from the data will cause a processing error.

Bit strings, Alignment, and dfdl:fillByte

The dfdl:alignmentUnits='bits', and dfdl:alignment='1' can be used to position a bit string anywhere in the data stream without regard for any other grouping of bits into bytes. 

The numeric value of the unsigned integer represented by a bit string is unaffected by alignment. 

When unparsing a bit string, alignment may cause the bits of the bit string to occupy only some of the bits within a byte of the data stream. The bits of data in the alignment fill region are unspecified by the elements of the DFDL schema, and are not found in the DFDL infoset. Such unspecified bits are filled in using the value of the dfdl:fillByte property. Corresponding bits from the dfdl:fillByte value are used to fill in unspecified bits of the data stream. That is, if bit K (K will be 1 or greater, but less than or equal to 8) of a data stream byte is unspecified, its value will be taken from bit K of the dfdl:fillByte property value. 

Since the value of any bit string element is unaffected by alignment, the logical integer value for a bit-string is always computed as if the first bit were at position 1 of the bit stream. If the dfdl:length for the bit-string evaluates to M, then the bit-string conceptually occupies bits 1 to M of a data stream for purposes of computing its value.

Bits within Bit Strings of Length <= 8

Any time the length in bits is < 8, then when set, the bit at position Z supplies value 2^(M-Z), and the value of the bit string as an integer is the sum of these values for each of its bits. 

Bits within Bit Strings of Length > 8

Call M the length of the bit string element in bits. In general, when M > 8 the contribution of a bit in position i to the numeric value of a bit string is given by a formula specific to the dfdl:byteOrder.

For dfdl:byteOrder='bigEndian' the value of bit i is given by 2^(M - i).

For dfdl:byteOrder='littleEndian' the value of bit i is given by a more complex formula. The following pseudo code computes the value of a bit in a littleEndian bit string. It is just a very big expression, but is spread out over many local variables to illustrate the various sub-calculations clearly. DFDL implementations may use any way of converting bit strings to the corresponding integer values that is consistent with this:

In the pseudo code below:

littleEndianBitValue(bitPosition, bitStringLength) 
      assert bitPosition >= 1;
      assert bitStringLength >= 1;
      assert bitStringLength >= bitPosition;
      numBitsInFinalPartialByte = bitStringLength % 8;
      numBitsInWholeBytes = bitStringLength - 
      numBitsInFinalPartialByte;
      bitPosInByte = ((bitPosition - 1) % 8) + 1;
      widthOfActiveBitsInByte = (bitPosition <= numBitsInWholeBytes) 
      ? 8 : numBitsInFinalPartialByte;
      placeValueExponentOfBitInByte = widthOfActiveBitsInByte – 
      bitPosInByte;
      bitValueInByte = 2^placeValueExponentOfBitInByte;
      byteNumZeroBased = (bitPosition - 1)/8;
      scaleFactorForBytePosition = 2^(8 * byteNumZeroBased);
      bitValue = bitValueInByte * scaleFactorForBytePosition;
      return bitValue;
Little Endian bit position and value

Examples

Example: consider the first three bytes of the data stream. Imagine their numeric values as 0x5A 0x92 0x00.

Positions:
00000000 01111111 11122222
12345678 90123456 78901234
Bits:
01011010 10010010 00000000
Hex values
   5   A    9   2    0   0 
Beginning at bit position 1, (the very first bit) if we consider the first two bytes as a bigEndian short, the value will be 0x5A92. 
< xs:element name="num" type="unsignedShort"
     dfdl:alignment="1"
     dfdl:alignmentUnits="bytes" 
     dfdl:byteOrder="bigEndian"
     dfdl:representation="binary"/>
As a littleEndian short, the value will be 0x925A.
< xs:element name="num" type="unsignedShort"
     dfdl:alignment="1"
     dfdl:alignmentUnits="bytes" 
     dfdl:byteOrder="littleEndian"
     dfdl:representation="binary"/>
Now let us examine a bit string of length 13, beginning at position 2.
< xs:sequence>
  < xs:element name="ignored" type="unsignedByte"
        dfdl:alignment="1" 
        dfdl:alignmentUnits="bits" 
        dfdl:lengthUnits="bits" 
        dfdl:length="1" 
        dfdl:representation="binary"/>
  < xs:element name="x" type="unsignedShort" 
        dfdl:alignment="1" 
        dfdl:alignmentUnits="bits" 
        dfdl:byteOrder="bigEndian"
        dfdl:lengthUnits="bits" 
        dfdl:length="13" 
        dfdl:representation="binary"/>
   ...
< /xs:sequence>

Let's examine the same data stream and consider the bit positions that make up element 'x', which are the bits at positions 2 through 14 inclusive.

Positions:
00000000 01111111 11122222
12345678 90123456 78901234
Bits:
 1011010 100100 

Since alignment does not affect logical value, we will obtain the same logical value as if we realigned the bits. That is, the value is the same as if we began the bits of the element's representation with bit position 1.

Realigned Positions:
00000000 01111111 11122222
12345678 90123456 78901234
Bits:
10110101 00100

The DFDL schema fragment above gives element ‘x’ the dfdl:byteOrder='bigEndian' property. In this case the place value of each position is given by 2^(M – i)

PlaceValue positions 2^(M - i)

...11110 00000000
...21098 76543210
Bit values
...10110 10100100
Hex values
   1   6    A   4

The value of element 'x' is 0x16A4. Notice how it is the most-significant byte -- which is the first byte when big endian -- that becomes the partial byte (having fewer than 8 bits) in the case where the length of the bit string is not a multiple of 8 bits. 

For dfdl:byteOrder='littleEndian'. The place values of the individual bits are not as easily visualized. However there is still a basic formula (given in the pseudo code in Figure 4 Little Endian bit position and value.

Looking again at our realigned positions:

Realigned Positions:
00000000 01111111 11122222
12345678 90123456 78901234
Bits:
10110101 00100
The place values of each of these bits, for little endian byte order can be seen to be:
00000000 ...11100
76543210 ...21098
Bit values
10110101 ...00100
Hex values
   B   5    0   4 

We must reorder the bytes for little endian byte order. The value of element 'x' is 0x04B5. In little endian form, the first 8 bits make up the first byte, and that contains the least-significant byte of the logical numeric unsignedShort value. The additional bits of the partial byte are once again the most significant byte; however, for little endian form, this is the second byte. The second byte contains only 5 bits, those make up the least significant 5 bits of that byte, but that logical 5-bit value makes up the most-significant byte of the unsignedShort integer.

Booleans

The properties dfdl:binaryBooleanTrueRep and dfdl:binaryBooleanFalseRep are unsigned integers. Specifically, their numeric ranges are restricted as if of type xs:unsignedInt, with additional restriction in range when the dfdl:lengthUnits=’bits’ and dfdl:length are used to specify fewer than the maximum of 32 bits.

12.3.7.3 Length of Complex Element of Specified Length

A complex element of known length is defining a 'box' in which its child element exist. For example a fixed length record with a variable number of children that may not fill the full length of the record.

For example, an element of complex type may have explicit length of 100 bytes, but contain a sequence of child elements that use up less than 100 bytes of data. In this case the remaining unused data is called the FinalUnusedRegion. It is skipped when parsing, and is filled with the dfdl:fillByte on unparsing.

When the dfdl:lengthUnits is 'characters' on a complex element of specified length then the dfdl:lengthUnits of all its children must be characters also.

12.3.8 Length of Simple Types with Binary Representations

Elements with dfdl:representation 'binary' and dfdl:binaryNumberRep or dfdl:binaryCalendarRep 'packed' or 'bcd' may be delimited or known length. All other elements with dfdl:representation 'binary' must be of known length and it is a schema definition error if dfdl:lengthKind 'delimited' or 'endOfParent', where the parent dfdl:lengthKind is 'delimited'.
1 Byte-order marks are explicitly stated to be “not characters” in the Unicode standard.

Copyright (C) Open Grid Forum (2005-2010). All Rights Reserved.

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 the OGF or other organizations, except as needed for the purpose of developing Grid Recommendations in which case the procedures for copyrights defined in the OGF Document process must be followed, or as required to translate it into languages other than English.