i18n

You can generate flexible number or date format patterns, format and parse dates and numbers for any locale, manage time zones, create alphabetic indexes, and manage right-to-left scripts, such as Arabic. The i18n API is implemented by using the ICU library.

The main features of the i18n API include:

Note

The Alphabetic Index, FieldPosition, Format, Formattable, Measure, MeasureFormat, MeasureUnit, ParsePosition, Ubidi, Ushape, and Utmscale APIs are supported since Tizen 3.0. The PluralRules, Uversion, and UCharIter APIs are supported since Tizen 4.0. The Immutable Index, PluralFormat, DateInterval, and DateIntervalFormat are supported from Tizen 5.0.

Location Boundaries with Ubrk

The Ubrk API (in mobile and wearable applications) is used to find the location of boundaries in text. The i18n_ubreak_iterator_h handle maintains a current position and scans over the text returning the index of characters where the boundaries occur.

The following boundary analyzing methods are available:

  • Line boundary analysis determines where a text string can be broken when line-wrapping. The mechanism correctly handles punctuation and hyphenated words.
  • Sentence boundary analysis allows selection with correct interpretation of periods within numbers and abbreviations, and trailing punctuation marks, such as quotation marks and parentheses.
  • Word boundary analysis is used by search and replace functions, as well as within text editing applications that allow the user to select words with a double-click. Word selection provides correct interpretation of punctuation marks within and following words. Characters that are not part of a word, such as symbols or punctuation marks, have word-breaks on both sides.
  • Character boundary analysis identifies the boundaries of Extended Grapheme Clusters, which are groupings of codepoints that must be treated as character-like units for many text operations. For more information on grapheme clusters and guidelines on their use, see Unicode Standard Annex #29, Unicode Text Segmentation.
  • Title boundary analysis locates all positions, typically starts of words, that must be set to Title Case when title casing the text.
  • The text boundary positions are found according to the rules described in Unicode Standard Annex #29, Unicode Text Segmentation, and Unicode Standard Annex #14, Unicode Line Breaking Algorithm.

Calendar Dates with Ucalendar

The Ucalendar API (in mobile and wearable applications) is used for converting between a Udate object and a set of integer fields, such as I18N_UCALENDAR_YEAR, I18N_UCALENDAR_MONTH, I18N_UCALENDAR_DAY, and I18N_UCALENDAR_HOUR. A Udate object represents a specific instant in time with one millisecond precision.

The types of Ucalendar interpret a Udate according to the rules of a specific calendar system, such as the Gregorian or traditional system.

A Ucalendar object can produce all the time field values needed to implement the date-time formatting for a particular language and calendar style (for example, Japanese-Gregorian, Japanese-Traditional).

Table: Available calendar field combinations

Date information to be determined Field combination
Day I18N_UCALENDAR_MONTH + I18N_UCALENDAR_DAY_OF_MONTH
Day I18N_UCALENDAR_MONTH + I18N_UCALENDAR_WEEK_OF_MONTH + I18N_UCALENDAR_DAY_OF_WEEK
Day I18N_UCALENDAR_MONTH + I18N_UCALENDAR_DAY_OF_WEEK_IN_MONTH + I18N_UCALENDAR_DAY_OF_WEEK
Day I18N_UCALENDAR_DAY_OF_YEAR
Day I18N_UCALENDAR_DAY_OF_WEEK + I18N_UCALENDAR_WEEK_OF_YEAR
Time of day I18N_UCALENDAR_HOUR_OF_DAY
Time of day I18N_UCALENDAR_AM_PM + I18N_UCALENDAR_HOUR

Note

For some non-Gregorian calendars, different fields are necessary for complete disambiguation. For example, a full specification of the historical Arabic astronomical calendar requires the year, month, day-of-month and day-of-week in some cases.

When computing a Udate from the time fields, 2 special circumstances can arise. The information can be insufficient to compute the Udate (you have only the year and the month, but not the day of the month), or the information can be inconsistent (such as “Tuesday, July 15, 1996” even though July 15, 1996 is actually a Monday).

  • Insufficient information:

    The calendar uses the default information to specify the missing fields. This can vary by calendar. For example, the Gregorian calendar, the default for a field is the same as that of the start of the epoch, such as I18N_UCALENDAR_YEAR = 1970, I18N_UCALENDAR_MONTH = JANUARY, I18N_UCALENDAR_DATE = 1.

  • Inconsistent information:

    If there is field’s conflict, the calendar prefers the most recently set fields. For example, when determining the day, the calendar looks for one of the following field combinations listed in the following table. The most recent combination, as determined by the most recently set single field, is used.

Unicode Character Management with Uchar

The Uchar API (in mobile and wearable applications) provides low-level access to the Unicode Character Database.

Unicode assigns each code point (not only the assigned character) values for several properties. Most of them are simple boolean flags, or constants from a small enumerated list. For some properties, values are strings or other relatively more complex types.

For more information, see About the Unicode Character Database and ICU User Guide chapter on Properties.

The following table describes the details of script codes that you can get using the i18n_uchar_get_int_property_value() function.

Table: Script codes

Value Code English name Value Code English name
0 Zyyy Code for undetermined script 80 Latf Latin (Fraktur variant)
1 Zinh Code for inherited script 81 Latg Latin (Gaelic variant)
2 Arab Arabic 82 Lepc Lepcha (Rong)
3 Armn Armenian 83 Lina LinearA
4 Beng Bengali 84 Mand Mandaic, Mandaean
5 Bopo Bopomofo 85 Maya Mayan hieroglyphs
6 Cher Cherokee 86 Mero Meroitic hieroglyphs
7 Copt Coptic 87 Nkoo N’Ko
8 Cyrl Cyrillic 88 Orkh Old Turkic, Orkhon Runic
9 Dsrt Deseret (Mormon) 89 Perm Old Permic
10 Deva Devanagari (Nagari) 90 Phag Phags-pa
11 Ethi Ethiopic (Geʻez) 91 Phnx Phoenician
12 Geor Georgian (Mkhedruli) 92 Plrd Miao (Pollard)
13 Goth Gothic 93 Roro Rongorongo
14 Grek Greek 94 Sara Sarati
15 Gujr Gujarati 95 Syre Syriac (Estrangelo variant)
16 Guru Gurmukhi 96 Syrj Syriac (Western variant)
17 Hani Han (Hanzi, Kanji, Hanja) 97 Syrn Syriac (Eastern variant)
18 Hang Hangul (Hangŭl, Hangeul) 98 Teng Tengwar
19 Hebr Hebrew 99 Vaii Vai
20 Hira Hiragana 100 Visp Visible Speech
21 Knda Kannada 101 Xsux Cuneiform, Sumero-Akkadian
22 Kana Katakana 102 Zxxx Code for unwritten documents
23 Khmr Khmer 103 Zzzz Code for uncoded script
24 Laoo Lao 104 Cari Carian
25 Latn Latin 105 Jpan Japanese (alias for Han+Hiragana+Katakana)
26 Mlym Malayalam 106 Lana TaiTham (Lanna)
27 Mong Mongolian 107 Lyci Lycian
28 Mymr Myanmar (Burmese) 108 Lydi Lydian
29 Ogam Ogham 109 Olck Ol Chiki (Ol Cemet’, Ol Santali)
30 Ital Old Italic (Etruscan, Oscan) 110 Rjng Rejang (Redjang, Kaganga)
31 Orya Oriya 111 Saur Saurashtra
32 Runr Runic 112 Sgnw SignWriting
33 Sinh Sinhala 113 Sund Sundanese
34 Syrc Syriac 114 Moon Moon (Mooncode, Moonscript, Moontype)
35 Taml Tamil 115 Mtei Meitei Mayek (Meithei, Meetei)
36 Telu Telugu 116 Armi Imperial Aramaic
37 Thaa Thaana 117 Avst Avestan
38 Thai Thai 118 Cakm Chakma
39 Tibt Tibetan 119 Kore Korean (alias for Hangul+Han)
40 Cans Unified Canadian Aboriginal Syllabics 120 Kthi Kaithi
41 Yiii Yi 121 Mani Manichaean
42 Tglg Tagalog (Baybayin, Alibata) 122 Phli Inscriptional Pahlavi
43 Hano Hanunoo (Hanunoo) 123 Phlp Psalter Pahlavi
44 Buhd Buhid 124 Phlv Book Pahlavi
45 Tagb Tagbanwa 125 Prti Inscriptional Parthian
46 Brai Braille 126 Samr Samaritan
47 Cprt Cypriot 127 Tavt TaiViet
48 Limb Limbu 128 Zmth Mathematical notation
49 Linb LinearB 129 Zsym Symbols
50 Osma Osmanya 130 Bamu Bamum
51 Shaw Shavian (Shaw) 131 Lisu Lisu (Fraser)
52 Tale TaiLe 132 Nkgb Nakhi Geba ('Na-'Khi ²Ggŏ-¹baw, Naxi Geba)
53 Ugar Ugaritic 133 Sarb Old South Arabian
54 Hrkt Japanese syllabaries (alias for Hiragana+Katakana) 134 Bass BassaVah
55 Bugi Buginese 135 Dupl Duployan shorthand, Duployan stenography
56 Glag Glagolitic 136 Elba Elbasan
57 Khar Kharoshthi 137 Gran Grantha
58 Sylo Syloti Nagri 138 Kpel Kpelle
59 Talu New Tai Lue 139 Loma Loma
60 Tfng Tifinagh (Berber) 140 Mend Mende Kikakui
61 Xpeo Old Persian 141 Merc Meroitic Cursive
62 Bali Balinese 142 Narb Old North Arabian (Ancient North Arabian)
63 Batk Batak 143 Nbat Nabataean
64 Blis Blissymbols 144 Palm Palmyrene
65 Brah Brahmi 145 Sind Khudawadi, Sindhi
66 Cham Cham 146 Wara Warang Citi (Varang Kshiti)
67 Cirt Cirth 147 Afak Afaka
68 Cyrs Cyrillic (Old Church Slavonic variant) 148 Jurc Jurchen
69 Egyd Egyptian demotic 149 Mroo Mro, Mru
70 Egyh Egyptian hieratic 150 Nshu Nushu
71 Egyp Egyptian hieroglyphs 151 Shrd Sharada, Śāradā
72 Geok Khutsuri (Asomtavruli and Nuskhuri) 152 Sora Sora Sompeng
73 Hans Han (Simplified variant) 153 Takr Takri, Ṭākrī, Ṭāṅkrī
74 Hant Han (Traditional variant) 154 Tang Tangut
75 Hmng Pahawh Hmong 155 Wole Woleai
76 Hung Old Hungarian (Hungarian Runic) 156 Hluw Anatolian hieroglyphs (Luwian hieroglyphs, Hittite hieroglyphs)
77 Inds Indus (Harappan) 157 Khoj Khojki
78 Java Javanese 158 Tirh Tirhuta
79 Kali KayahLi -1 Invalid code

Since Tizen 4.0, you can also check for specific Unicode character properties, retrieve alternate representations of the same character, such as uppercase and lowercase, and get the name for a specific character.

To verify whether a character is in a specific character class, use the i18n_uchar_is_xxx() function corresponding to the binary property in the following table:

Table: Binary properties

Binary property Description
alnum Alphanumeric characters (letters and digits)
alpha Alphabetic characters
blank Horizontal space characters. This category includes tab characters and space separators, but excludes zero-width spaces.
control Control characters, such as backspace, tab, and escape
digit Decimal digits
graph Graphic characters. This category includes all printable characters, excluding spaces.
java_space_char Separator characters or non-breaking space. The same characters are detected by the isSpaceChar() function in Java.
lower Lowercase characters
printable Non-control characters
punct Punctuation characters
space Space characters. The category includes separators, whitespace ISO controls, and non-breaking spaces.
title Titlecase characters
upper Uppercase characters
whitespace Separator characters or whitespace ISO control characters, excluding non-breaking space. The same characters are detected by the isWhitespace() function in Java.
white_space Characters with the Unicode White_Space property. The category includes most separators and whitespace ISO controls, including non-breaking spaces, but excludes IS1 to IS4 control characters and zero-width spaces.
xdigit Hexadecimal digits

You can retrieve alternate representations of Unicode characters, such as the upper- or lowercase form, using the i18n_uchar_to_xxx() functions, or perform case folding using the i18n_uchar_fold_case() function.

For more information on case mapping, see the ICU User Guide chapter on Case Mappings.

String Comparison with Ucollator

The Ucollator API (in mobile and wearable applications) performs locale-sensitive string comparison. It builds searching and sorting routines for natural language text and provides correct sorting orders for most supported locales. If specific data for a locale is not available, the order eventually falls back to the CLDR root sort order. The sorting order can be customized by providing your own set of rules. For more information, see the ICU Collation Customization section of the User Guide.

Date Formats with Udate

The Udate API (in mobile and wearable applications) consists of functions that convert dates and times from their internal representations to textual form and back again in a language-independent manner. Converting from the internal representation (milliseconds since midnight, January 1, 1970) to text is known as formatting, and converting from text to milliseconds is known as parsing. Tizen currently defines only one concrete handle (i18n_udate_format_h), which can handle practically all normal date formatting and parsing actions.

The Udate format helps you to format and parse dates for any locale. Your code can be completely independent of the locale conventions for months, days of the week, or even the lunar or solar calendar format.

You can pass in different options for the arguments for date and time style to control the length of the result; you can select from SHORT, MEDIUM, LONG, and FULL. The exact result depends on the locale.

  • I18N_UDATE_SHORT is completely numeric, such as 12/13/52 or 3:30pm
  • I18N_UDATE_MEDIUM is longer, such as Jan 12, 1952
  • I18N_UDATE_LONG is longer, such as January 12, 1952 or 3:30:32pm
  • I18N_UDATE_FULL is completely specified, such as Tuesday, April 12, 1952 AD or 3:30:42pm PST.

Date and Time Patterns

The date and time formats are specified by the date and time pattern strings. Within the date and time pattern strings, all unquoted ASCII letters (A-Z and a-z) are reserved as pattern letters representing calendar fields. The i18n_udate_format_h handle supports the date and time formatting algorithm and pattern letters defined by the Unicode Technical Standard #35, Unicode Locale Data Markup Language (LDML). It is further documented in the ICU User Guide.

Date Format Patterns with Udatepg

The Udatepg API (in mobile and wearable applications) enables flexible generation of date format patterns, such as “yy-MM-dd”. The user can build up the generator by adding successive patterns. After this, a query can be made using a pattern that includes only the desired fields and lengths. The generator returns the a pattern that is most similar to it.

The main method is the i18n_udatepg_get_best_pattern() function, since normally the Udatepg API is prebuilt with data from a particular locale. However, generators can be built directly from other data as well.

Enumeration Management with Uenumeration

The Uenumeration API (in mobile and wearable applications) enables you to create an enumeration object out of a given set of strings. The object can be created out of an array of const char* strings or an array of i18n_uchar* strings.

The enumeration object enables navigation through the enumeration values, with the use of the i18n_uenumeration_next() or i18n_uenumeration_unext() function (depending on the type used for creating the enumeration object), and with the i18n_uenumeration_reset() function.

You can get the number of values stored in the enumeration object with the i18n_uenumeration_count() function.

Locale-Sensitive Operations with Ulocale

The Ulocale API (in mobile and wearable applications) represents a specific geographical, political, or cultural region. Locale-sensitive operations use the Ulocale functions to tailor information for the user. For example, displaying a number is a locale-sensitive operation. The number must be formatted according to the customs and conventions of the user’s native country, region, or culture.

You create a locale with one of the following options. Each component is separated by an underscore in the locale string.

  • newLanguage

    A valid ISO language code (lower-case 2-letter code as defined by the ISO-639 standard).

  • newLanguage + newCountry

    A valid ISO language code and an additional ISO country code.

  • newLanguage + newCountry + newVariant

    A valid ISO language code, ISO country code, and additional information on the variant. The variant codes are vendor and browser-specific. For example, use WIN for Windows, MAC for Macintosh, and POSIX for POSIX. Where there are two variants, separate them with an underscore, and put the most important one first. For example, a Traditional Spanish collation might be referenced, with ES, ES, Traditional_WIN.

Because a locale is simply an identifier for a region, no validity check is performed when you specify a locale. If you want to see whether particular resources are available for the locale you asked for, you must query those resources.

Once you have specified a locale you can query it for information about itself. Use i18n_ulocale_get_language() to get the ISO Language Code. You can use i18n_ulocale_get_display_name() to get the name of the language suitable for display to the user.

Unicode Normalization with Unormalization

The Unicode normalization API (in mobile and wearable applications) is for the standard Unicode normalization. All instances of i18n_unormalizer_s are unmodifiable and immutable. Instances returned by i18n_unormalization_get_instance() are singletons that must not be deleted by the caller.

Number Formats with Unumber

The Unumber API (in mobile and wearable applications) helps you to format and parse numbers for any locale. Your code can be completely independent of the locale conventions for decimal points, thousands-separators, or even the particular decimal digits used, or whether the number format is even decimal. There are different number format styles like decimal, currency, percent and spellout.

Text Search with Usearch

The Usearch API (in mobile and wearable applications) provides language-sensitive text searching based on the comparison rules defined in a Ucollator data struct. This ensures that language eccentricity can be handled. For example, for the German collator, characters ß and SS are matched if case is chosen to be ignored. That is why it can be important to pass a locale when creating the usearch with the i18n_usearch_create_new() function.

Character and String Management with Uset

Uset is a mutable set of Unicode characters and multicharacter strings that you can manage. The sets represent character classes used in regular expressions. A character specifies a subset of the Unicode code points. The legal code points are U+0000 to U+10FFFF, inclusive.

The set supports two functions:

  • The operand function allows the caller to modify the value of the set. The operand function works similarly to the boolean logic: a boolean OR is implemented by add, a boolean AND is implemented by retain, a boolean XOR is implemented by a complement taking an argument, and a boolean NOT is implemented by a complement with no argument. In terms of traditional set theory function names, add is a union, retain is an intersection, remove is an asymmetric difference, and complement with no argument is a set complement with respect to the superset range MIN_VALUE-MAX_VALUE.
  • The i18n_uset_apply_pattern() or i18n_uset_to_pattern() function. Unlike the functions that add characters or categories, and control the logic of the set, the i18n_uset_apply_pattern() function sets all attributes of a set at once, based on a string pattern.

Pattern Syntax

Patterns are accepted by the i18n_uset_create_pattern(), i18n_uset_create_pattern_options(), and i18n_uset_apply_pattern() functions and returned by the i18n_uset_to_pattern() function. The patterns follow a syntax similar to that employed by version 8 regular expression character classes.

Table: Examples of simple pattern syntax

Pattern Description
[] No characters
[a] Character ‘a’
[ae] Characters ‘a’ and ‘e’
[a-e] Characters ‘a’ through ‘e’ inclusive, in Unicode code point order
[\u4E01] Character U+4E01
[a{ab}{ac}] Character ‘a’ and the multicharacter strings ‘ab’ and ‘ac’
[\p{Lu}] All characters in the general category ‘uppercase letter’

Any character can be preceded by a backslash in order to remove any special meaning. Whitespace characters are ignored, unless they are escaped.

Property patterns specify a set of characters having a certain property as defined by the Unicode standard. Both the POSIX-like [:Lu:] and the Perl-like syntax \\p{Lu} are recognized.

Patterns specify individual characters, ranges of characters, and Unicode property sets. When the elements are concatenated, they specify their union. To complement a set, place a ‘^’ immediately after the opening ‘[’. Property patterns are inverted by modifying their delimiters, [:^foo] and \\P{foo}. In any other location, ‘^’ has no special meaning.

Ranges are indicated by placing a ‘-’ between two characters, as in “a-z”. This specifies the range of all characters from the left to the right, in Unicode order. If the left character is greater than or equal to the right character, it is a syntax error. If a ‘-’ occurs as the first character after the opening ‘[’ or ‘[^’, or if it occurs as the last character before the closing ‘]’, it is taken as a literal. This means that [a\-b], [-ab], and [ab-] all indicate the same set of 3 characters, ‘a’, ‘b’, and ‘-’.

Sets can be intersected using the ‘&’ operator or the asymmetric set difference can be taken using the ‘-’ operator. For example, [[:L:]&[\\u0000-\\u0FFF]] indicates the set of all Unicode letters with values less than 4096. Operators (’&’ and ‘|’) have equal precedence and bind left-to-right. This means that [[:L:]-[a-z]-[\\u0100-\\u01FF]] is equivalent to [[[:L:]-[a-z]]-[\\u0100-\\u01FF]]. This only really matters for difference; intersection is commutative.

Table: Examples of set syntax

Set Description
[a] Set containing ‘a’
[a-z] Set containing ‘a’ through ‘z’ and all letters in between, in Unicode order
[^a-z] Set containing all characters but ‘a’ through ‘z’, that is, U+0000 through ‘a’-1 and ‘z’+1 through U+10FFFF
[[pat1][pat2]] Union of sets specified by pat1 and pat2
[[[pat1]&[pat2]] Intersection of sets specified by pat1 and pat2
[[pat1]-[pat2]] Asymmetric difference of sets specified by pat1 and pat2
[:Lu:] or \p{Lu} Set of characters having the specified Unicode property, in this case Unicode uppercase letters
[:^Lu:] or \P{Lu} Set of characters not having the given Unicode property

Note

You cannot add an empty string ("") to a set.

Formal Syntax

The following table provide examples of formal syntax patterns:

Table: Formal syntax patterns

Pattern Description
pattern := (’[’ ‘^’? item* ‘]’) | property
item := char | (char ‘-’ char) | pattern-expr
pattern-expr := pattern | pattern-expr pattern | pattern-expr or pattern
op := ‘&’ | ‘-’
special := ‘[’ | ‘]’ | ‘-’
char := Any character that is not special | (’\’ any character) | (’\u’ hex hex hex hex)
property := Unicode property set pattern
a := b a can be replaced by b
a? 0 or 1 instance of a
a* 1 or more instances of a
a | b Either a or b
'a' Literal string between the quotes

Unicode Strings with Ustring

The Ustring API (in mobile and wearable applications) allows you to handle general Unicode strings. Some functions are similar in name, signature, and behavior to the ANSI C <string.h> functions, and other functions provide more Unicode-specific functionality.

The i18n uses 16-bit Unicode (UTF-16) in the form of arrays of i18n_uchar code units. UTF-16 encodes each Unicode code point with either 1 or 2 i18n_uchar code units. This is the default form of Unicode, and a forward-compatible extension of the original, fixed-width form that was known as UCS-2. UTF-16 superseded UCS-2 with Unicode 2.0 in 1996.

The i18n also handles 16-bit Unicode text with unpaired surrogates. Such text is not well-formed UTF-16. Code-point-related functions treat unpaired surrogates as surrogate code points, such as separate units.

Although UTF-16 is a variable-width encoding form, such as some legacy multi-byte encodings, it is much more efficient even for random access because the code unit values for single-unit characters versus lead units versus trail units are completely disjoint. This means that it is easy to determine character (code point) boundaries from random offsets in the string.

Unicode (UTF-16) string processing is optimized for the single-unit case. Although it is important to support supplementary characters, which use pairs of lead/trail code units called “surrogates”, their occurrence is rare. Almost all characters in modern use require only a single i18n_uchar code unit (such as their code point values are <=0xffff).

Character Set Mapping Tables

The i18n API provides a character set conversion with mapping tables for a number of important codepages. The default tables are a subset of IBM’s CDRA conversion table repository. ICU’s Converter Explorer shows aliases and codepage charts for the default tables that are built into a standard ICU distribution.

Conversions for most codepages are implemented differently on different platforms. We are providing mapping tables here from many different sources, so that the i18n users and others can use these tables to get the same conversion behavior as on the original platforms.

The mapping tables and some of the source code of the tools that collected these tables are checked into a CVS repository.

For more information on character sets, codepages, and encodings, see Coded Character Sets on the IBM site.

Alphabetic Index Creation

The Alphabetic Index API (in mobile and wearable applications) allows you to generate a list of alphabetical labels that can be used as an “index”, such as in a UI. In other words, it is a list of clickable characters (or character sequences) that allow the user to see a segment (bucket) of a larger target list. Each label corresponds to a bucket in the target list, where all items in the bucket are greater than or equal to the selected character, based on the locale’s collation order. Strings added to the index are sorted and placed in order in the appropriate bucket.

You can use the index directly, or with a client that does not support localized collation. The following example shows an alphabetical index.


… A B C D E F G H I J K L M N O P Q R S T U V W X Y Z …

A

  • Addison
  • Albertson
  • Azensky

B

  • Baker

The Alphabetic Index API also supports creating buckets for strings that are sorted before the first label (underflow), after the last label (overflow), and between scripts (inflow). For example, if an index is constructed with labels for Russian and for English characters, Greek characters can be placed in an inflow bucket between the other two scripts.

Using Immutable Index

The immutable index API (in mobile and wearable applications) provides an immutable, thread-safe version of an alphabetic index. Immutable indices also allow random access to buckets. An immutable index is constructed using a regular alphabetic index. The immutable index contains similar data as the alphabetic index on which it is based, except for the data records. For more information on the creation and the basic usage of an immutable index, see example.

Field Identification in Formatted Output

The FieldPosition API (in mobile and wearable applications) allows you to manage the field positions in formatted output.

Fields are identified by constants defined in the xxx_format_field_e enumerations.

The field position within formatted output is tracked with two indices, which includes the indices of the first and the last characters of the field. Some formatting functions require a field position object as a parameter. These formatting functions can be used to perform partial formatting or retrieve information about formatted output, such as field positions.

String Format Management

The Format API (in mobile and wearable applications) allows you to manage formatting for displayed strings.

The Format API specifies the protocol for classes which convert between objects or values, such as numeric values and dates, and their string representations. These representations can be localized or contain localized characters or strings.

There is no function for creating an i18n_format_h object, as this module uses a mechanism similar to inheritance in object-oriented languages. All functions with the i18n_format_h handle as a parameter can instead take the handle to a more specific format object from the derived classes.

The Formattable API (in mobile and wearable applications) allows you to interconvert between Udate, char string, and primitive numeric types, such as double and long.

Internally, an i18n_formattable_h handle holds an object that is a union of primitive types. As such, it can only store 1 flavor of data at a time. To determine what flavor of data it contains, use the i18n_formattable_get_type() function.

The Formattable API is a helping object for the Format API and its derived format objects. The formattable object holds the value to be formatted or the formatting result.

Measurement Values with Units

The Measure API (in mobile and wearable applications) allows you to create measure objects containing a numerical value and a measurement unit. You can, for example, store a length value in feet or meters.

The MeasureUnit API (in mobile and wearable applications) allows you to create measure unit objects and combine them with numerical values to create measure objects. The measure objects can also be formatted using the MeasureFormat API (in mobile and wearable applications).

The following table lists the supported measures and units:

Table: Measures and units

Measure Unit Symbol
Acceleration g-force g-force
Acceleration meter per second squared m/s2
Angle arc minute arcmin
Angle arc second arcsec
Angle degree °
Angle radian rad
Area acre ac
Area hectare ha
Area square centimeter cm2
Area square meter m2
Area square kilometer km2
Area square foot ft2
Area square inch in2
Area square mile mi2
Area square yard yd2
Consumption liter per kilometer l/km
Consumption mile per gallon mpg
Digital bit bit
Digital byte B
Digital kilobit kbit
Digital kilobyte kB
Digital megabit Mbit
Digital megabyte MB
Digital gigabit Gbit
Digital gigabyte GB
Digital terabit Tbit
Digital terabyte TB
Duration nanosecond ns
Duration microsecond µs
Duration millisecond ms
Duration second s
Duration minute min
Duration hour h
Duration day d
Duration week week
Duration month month
Duration year year
Electric ampere A
Electric milliampere mA
Electric ohm
Electric volt V
Energy calorie cal
Energy kilocalorie kcal
Energy food calorie Cal
Energy joule J
Energy kilojoule kJ
Energy kilowatt-hour kWh
Frequency hertz Hz
Frequency kilohertz kHz
Frequency megahertz MHz
Length picometer pm
Length nanometer nm
Length micrometer µm
Length millimeter mm
Length centimeter cm
Length decimeter dm
Length meter m
Length kilometer km
Length inch in
Length foot ft
Length fathom fathom
Length yard yd
Length furlong fur
Length mile mi
Length nautical mile nmi
Length astronomical unit au
Length light year ly
Length parsec pc
Illuminance lux lx
Mass carat ct
Mass microgram µg
Mass milligram mg
Mass gram g
Mass kilogram kg
Mass metric ton t
Mass ounce oz
Mass troy ounce oz t
Mass pound lb
Mass stone st
Mass ton ton
Power horsepower hp
Power milliwatt mW
Power watt W
Power kilowatt kW
Power megawatt MW
Power gigawatt GW
Pressure hectopascal hPa
Pressure inch of mercury inHg
Pressure millibar mbar
Pressure millimeter of mercury mmHg
Pressure pound per square inch psi
Proportion karat K or kt
Speed meter per second m/s
Speed kilometer per hour km/h
Speed mile per hour mph
Temperature degree Celsius °C
Temperature degree Fahrenheit °F
Temperature kelvin K
Volume acre-foot ac-ft
Volume bushel bsh or bu
Volume milliliter ml
Volume centiliter cl
Volume deciliter dl
Volume liter l
Volume hectoliter hl
Volume megaliter Ml
Volume cubic centimeter cm3
Volume cubic foot ft3
Volume cubic inch in3
Volume cubic kilometer km3
Volume cubic meter m3
Volume cubic mile mi3
Volume cubic yard yd3
Volume cup cup
Volume fluid ounce fl oz
Volume gallon gal
Volume pint pt
Volume quart qt
Volume teaspoon tsp
Volume tablespoon tbsp

Parse Position Tracking

The ParsePosition API (in mobile and wearable applications) is used by the Format API (in mobile and wearable applications) and the MeasureFormat API (in mobile and wearable applications) API to track the current position while parsing.

The xxx_parse_object() functions require a parse position pointer as an argument. By design, you can use the same parse position pointer as you parse through a string with various formats, since the index parameter records the current position.

Bidirectional Text Management with Ubidi

The Ubidi API (in mobile and wearable applications) allows you to use the Unicode Bidirectional Algorithm to correctly display text containing characters that flow from right to left, such as Arabic and Hebrew scripts.

The algorithm is defined in the Unicode Standard Annex #9, Unicode Bidirectional Algorithm. Libraries that perform a bidirectional algorithm and reorder strings accordingly are sometimes called “Storage Layout Engines”.

Arabic Character Shaping with Ushape

The Ushape API (in mobile and wearable applications) allows you to manage Arabic character shapes.

To shape Arabic text, use the i18n_ushape_shape_arabic() function with the appropriate shaping options. There are various digit and letter shaping options, which you can combine using the “|” pipe operation.

The following table lists some common sets of shaping options for digits.

Table: Digit shaping option combinations

Digit options Result
I18N_USHAPE_DIGIT_EN2AN | I18N_USHAPE_DIGIT_TYPE_AN Replace all European digits with Arabic-Indic digits
I18N_USHAPE_DIGIT_EN2AN | I18N_USHAPE_DIGIT_TYPE_AN_EXTENDED Replace all European digits with Extended Arabic-Indic digits
I18N_USHAPE_DIGIT_AN2EN | I18N_USHAPE_DIGIT_TYPE_AN Replace all Arabic-Indic digits with European digits
I18N_USHAPE_DIGIT_AN2EN | I18N_USHAPE_DIGIT_TYPE_AN_EXTENDED Replace all Extended Arabic-Indic digits with European digits
I18N_USHAPE_DIGIT_ALEN2AN_INIT_AL | I18N_USHAPE_DIGIT_TYPE_AN Replace all European digits with Arabic-Indic digits, if the most recent strongly-directional character is an Arabic letter, and the first preceding strongly-directional character is assumed to be an Arabic letter.
I18N_USHAPE_DIGIT_ALEN2AN_INIT_AL | I18N_USHAPE_DIGIT_TYPE_AN_EXTENDED Replace all European digits with Extended Arabic-Indic digits, if the most recent strongly-directional character is an Arabic letter, and the first preceding strongly-directional character is assumed to be an Arabic letter.
I18N_USHAPE_DIGIT_ALEN2AN_INIT_LR | I18N_USHAPE_DIGIT_TYPE_AN Replace all European digits with Arabic-Indic digits, if the most recent strongly-directional character is an Arabic letter, and the first preceding strongly-directional character is assumed to not be an Arabic letter.
I18N_USHAPE_DIGIT_ALEN2AN_INIT_LR | I18N_USHAPE_DIGIT_TYPE_AN_EXTENDED Replace all European digits with Extended Arabic-Indic digits, if the most recent strongly-directional character is an Arabic letter, and the first preceding strongly-directional character is assumed to not be an Arabic letter.

The following table lists some shaping options for letters.

Table: Letter shaping options

Letter options Result
I18N_USHAPE_LETTERS_NOOP Do not perform letter shaping
I18N_USHAPE_LETTERS_SHAPE Replace abstract letter characters with shaped ones
I18N_USHAPE_LETTERS_UNSHAPE Replace shaped letter characters with abstract ones
I18N_USHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED Same as I18N_USHAPE_LETTERS_SHAPE, but also replace tashkeel medial forms with isolated forms
I18N_USHAPE_TEXT_DIRECTION_VISUAL_LTR The source is in visual LTR order; the leftmost displayed character stored first
I18N_USHAPE_TEXT_DIRECTION_VISUAL_RTL The source is in visual RTL order; the rightmost displayed character stored first
I18N_USHAPE_TEXT_DIRECTION_LOGICAL The source is in the logical (keyboard) order
I18N_USHAPE_TASHKEEL_BEGIN Replace tashkeel characters with spaces placed at the beginning of the buffer
I18N_USHAPE_TASHKEEL_END Replace tashkeel characters with spaces placed at the end of the buffer
I18N_USHAPE_TASHKEEL_RESIZE Remove tashkeel characters and reduce the length of the buffer
I18N_USHAPE_TASHKEEL_REPLACE_BY_TATWEEL Replace tashkeel characters with tatweel if they are connected to adjacent characters (shaped on tatweel) or replace by space if they are not connected
I18N_USHAPE_PRESERVE_PRESENTATION Do not replace Arabic Presentation Forms-A and Arabic Presentation Forms-B characters with U+06xx characters before shaping
I18N_USHAPE_PRESERVE_PRESENTATION_NOOP Replace Arabic Presentation Forms-A and Arabic Presentation Forms-B before shaping
I18N_USHAPE_AGGREGATE_TASHKEEL_NOOP Do not aggregate tashkeel characters
I18N_USHAPE_AGGREGATE_TASHKEEL Replace any combination of U+0651 with one of U+064C, U+064D, U+064E, U+064F, or U+0650 with U+FC5E, U+FC5F, U+FC60, U+FC61, or U+FC62, respectively
I18N_USHAPE_YEHHAMZA_TWOCELL_NEAR Expand the “yeh hamza” character into 2 characters when near a space
I18N_USHAPE_SEEN_TWOCELL_NEAR Expand the “seen” character into 2 characters when near a space

Note

Not all option combinations make sense. For example, the combination I18N_USHAPE_TASHKEEL_END | I18N_USHAPE_TASHKEEL_RESIZE results in unexpected behavior.

Time Scale Conversion with Utmscale

The Utmscale API (in mobile and wearable applications) allows you to convert between time scales.

There are various conventions for binary datetime, depending on the platform and protocol. Some of these have severe drawbacks. For example, 32-bit Unix time (seconds since Jan 1, 1970) cannot support datetimes beyond the beginning of the year 2038. Arithmetic manipulations can also cause serious problems. For example, when calculating the average of 2 datetimes, if you calculate them with average_time = (time1 + time2)/2, there can be overflow even with dates around the present. Additionally, there is the issue of converting between different systems.

The i18n_utmscale_scale_e enumeration (in mobile and wearable applications) defines the supported time scales. Their details are listed in the following table.

Table: Time scales

Enumeration value Usage Datatype Unit Epoch
I18N_UTMSCALE_JAVA_TIME Java Development Kit int64_t milliseconds January 1, 1970
I18N_UTMSCALE_UNIX_TIME Unix systems int32_t or int64_t seconds January 1, 1970
I18N_UTMSCALE_ICU4C_TIME ICU4C double milliseconds January 1, 1970
I18N_UTMSCALE_WINDOWS_FILE_TIME Windows file times int64_t ticks (1 tick = 100 nanoseconds) January 1, 1601
I18N_UTMSCALE_DOTNET_DATE_TIME .NET framework System.DataTime structure int64_t ticks (1 tick = 100 nanosecods) January 1, 0001
I18N_UTMSCALE_MAC_OLD_TIME Older Macintosh systems int32_t or int64_t seconds January 1, 1904
I18N_UTMSCALE_MAC_TIME Newer Macintosh systems double seconds January 1, 2001
I18N_UTMSCALE_EXCEL_TIME Excel ? days December 31, 1899
I18N_UTMSCALE_DB2_TIME DB2 ? days December 31, 1899
I18N_UTMSCALE_UNIX_MICROSECONDS_TIME Unix systems long microseconds January 1, 1970

All the epochs start at 00:00 AM (the earliest possible time on the day in question), and are assumed to be UTC.

The ranges for different datatypes are given in the following table, with all values in years. The range of years includes the entire range expressible with positive and negative values of the datatype. The range of years for double is the range that does not lose precision to the corresponding unit.

Table: Datatype ranges

Unit int64_t double int32_t
1 second 5.84542×1011 285,420,920.94 136.10
1 millisecond 584,542,046.09 285,420.92 0.14
1 microsecond 584,542.05 285.42 0.00
100 nanoseconds (tick) 58,454.20 28.54 0.00
1 nanosecond 584.5420461 0.2854 0.00

ICU implements the .NET framework System.DateTime as the universal time scale ‘pivot’, and uses the full range allowed by the datatype, allowing for datetimes back to 29,000 BC and up to 29,000 AD. This time scale is very fine-grained, does not lose precision, and covers a range that meets most requirements. Using the Utmscale functions, datetimes can be converted to the pivot time scale, safely manipulated, and converted back to any other time scale.

Pluralization Rule Creation

Languages define plural categories in various ways. The PluralRules API (in mobile and wearable applications) allows you to create rules for determining the appropriate plural word form when formatting messages using numeric placeholders.

Rules are constructed from a text description consisting of a list of keywords and conditions. The i18n_plural_rules_select_int32() and i18n_plural_rules_select_double() functions examine each condition in order and return the keyword for the first condition that matches the given number. If no condition matches, the default rule (‘other’) is returned.

Rules are expressed using the following syntax:

rules           = rule (';' rule)*
rule            = keyword ':' condition
keyword         = <identifier>

There are 6 predefined keywords in ICU - ‘zero’, ‘one’, ‘two’, ‘few’, ‘many’ and ‘other’. Keywords can be user-defined or retrieved from ICU locale data, and must be a sequence of characters that do not have the Unicode Pattern_Syntax or Pattern_White_Space properties.

Conditions are expressed using the following syntax:

condition       = and_condition ('or' and_condition)*
and_condition   = relation ('and' relation)*
relation        = is_relation | in_relation | within_relation | 'n' <EOL>
is_relation     = expr 'is' ('not')? value
in_relation     = expr ('not')? 'in' range_list
within_relation = expr ('not')? 'within' range
expr            = ('n' | 'i' | 'f' | 'v' | 'j') ('mod' value)?
range_list      = (range | value) (',' range_list)*
value           = digit+  ('.' digit+)?
digit           = 0|1|2|3|4|5|6|7|8|9
range           = value'..'value

Note

While ‘in’ only includes integers in the specified range, ‘within’ includes all values in the range. Using ‘within’ with a range_list consisting entirely of values is the same as using ‘in’.

The following examples show how rules can be constructed:

  • “one: n is 1; few: n in 2…4”

    This example defines 2 rules: for ‘one’ and ‘few’. The condition for ‘one’ is “n is 1”, which means that the number must be 1 for this condition to pass. The condition for ‘few’ is “n in 2…4”, which means that the number must be between 2 and 4 inclusive for this condition to pass. All other numbers are assigned the keyword “other” by the default rule.

  • “zero: n is 0; one: n is 1; zero: n mod 100 in 1…19”

    This example shows how the same keyword can be defined multiple times. Each rule is examined in order, and the first keyword whose condition passes is returned. In the last rule, a modulus is applied to n.

  • “one: n is 1; few: n mod 10 in 2…4 and n mod 100 not in 12…14”

    This example shows conjunction and negation. The condition for ‘few’ has 2 parts, both of which must be met:

    1. “n mod 10 in 2…4”

      This applies a modulus to n, as in the previous example. It matches all numbers ending in 2, 3, and 4.

    2. “n mod 100 not in 12…14”

      This applies a different modulus and also negation. It matches all numbers not ending in 12, 13, or 14.

Pluralization conditions can also be defined based on specific parts of the numeric value.

Table: Numeric value parts

Symbol Value
n Absolute value of the number (integer and decimals)
i Integer digits of n
f Fractional digits of n
v Number of fractional digits in n
j Absolute value of an integer number that has no fractional digits. For example, “j is 3” fails for 3.1 or 3.0.

Table: Numeric value part examples

Number (n) Integer digits (i) Fractional digits (f) Number of fractional digits (v)
1.0 1 0 1
1.00 1 0 2
1.3 1 3 1
1.03 1 3 2
1.23 1 23 2

For more information on how to create rules, see Unicode Technical Standard #35, Unicode Locale Data Markup Language Part 3, Numbers: Language Plural Rules.

String Iteration with UCharIter

The UCharIter API (in mobile and wearable applications) allows you to iterate through strings.

The current() and next() functions only check the current index against the limit, and the previous() function only checks the current index against the start, to see if the iterator has already reached the beginning of the iteration range. The assumption - in all iterators - is that the index is moved though the API, which means that it cannot go out of bounds, or that the index is modified though the application code by a developer who knows enough about the iterator implementation to set valid index values.

The UCharIter functions return code unit values in the range of 0 - 0xffff. Before any functions operating on strings are called, the string must be set with the i18n_uchar_iter_set_string(), i18n_uchar_iter_set_UTF16BE(), or i18n_uchar_iter_set_UTF8() function.

Format Plural Messages with PluralFormat

The PluralFormat API (in mobile and wearable applications) allows you to format defined plural words. Alongside with PluralRules module, you can define rules to which format would apply.

PluralFormat supports creation of locale-dependent messages with plural inflection. To enable plural formatting, you have to specify each message for every plural case that will be used, based on the desired language. Then, the PluralFormat module will select appropriate text based on the provided number.

Issues of Plural Forms in Internationalized Messages

Many languages have different approach to create plural nouns. The locale-dependent message is workable when the framework enables to manage plural forms of all language correctly. For example, in Polish, there is different plural case for nouns counted as few (numbers as 2, 3 or 4) and in case with many objects (more than 5).

PluralFormat deals with this by dividing the problem into two parts:

  • It uses Plural Rules that can define more complex conditions for a plural case than just a single interval. These plural rules define both what plural cases exist in a language, and to which numbers these cases apply.

  • It provides predefined plural rules for many languages. Thus, the programmer need not worry about the plural cases of a language and does not have to define the plural cases; they can simply use the predefined keywords. The whole plural formatting of messages can be done using localized patterns from resource bundles. For predefined plural rules, see Language Plural Rules.

Usage of PluralFormat

The following lists the usage of PluralFormat:

  • You will need to use Plural module to properly use PluralFormat module.
  • To get default set of rules, you can use constructor, which takes local object as parameter.
  • A message pattern is specified by passing argument to constructor, or set it explicitly by using i18n_plural_format_apply_pattern().
  • To obtain formatted message, you need to use one of i18n_plural_format_format_*, which also takes a number object and returns corresponding message based on the defined rules.

Pattern Interpretation

The following pattern text defines the message output for each plural case of the specified locale:

Syntax:

pluralStyle = [offsetValue] (selector '{' message '}')+
offsetValue = "offset:" number
selector = explicitValue | keyword
explicitValue = '=' number  // adjacent, no white space in between
keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+
message: message = messageText (argument messageText)*
argument = noneArg | simpleArg | complexArg
complexArg = pluralArg | selectordinalArg
noneArg = '{' argNameOrNumber '}'
simpleArg = '{' argNameOrNumber ',' argType [',' argStyle] '}'
pluralArg = '{' argNameOrNumber ',' "plural" ',' pluralStyle '}'
selectordinalArg = '{' argNameOrNumber ',' "selectordinal" ',' pluralStyle '}'
argNameOrNumber = argName | argNumber
argName = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+
argNumber = '0' | ('1'..'9' ('0'..'9')*)
argType = "number" | "date" | "time" | "spellout" | "ordinal" | "duration"
argStyle = "short" | "medium" | "long" | "full" | "integer" | "currency" | "percent" | argStyleText

Examples:

one{dog} other{dogs}                 // English plural format for dog
one{pies} few{psy} other{psów}       //Polish translation of dog in plural format

Pattern_White_Space between syntax elements is ignored, except between the {curly braces} and their sub-message, and between the ‘=’ and the number of an explicitValue.

In International Components for Unicode (ICU) there are six predefined keywords: zero, one, two, few, many and other. It is obligatory to define message text for the other keyword, which is included in every rule set. In case if you do not define the specified message for a particular number object, the other keyword message will be returned to this plural case.

When formatting, the input number is first matched against the explicitValue clauses. If there is no exact-number match, then a keyword is selected by calling the Plural Rules with the input number minus the offset. (The offset defaults to 0 if it is omitted from the pattern string.) If there is no clause with that keyword, then the other clauses is returned.

An unquoted pound signal (#) is a selected sub message (that is, outside of argument nested in the sub message) is replaced by the input number-minus-offset value. The number-minus-offset value is formatted using a Number format for the PluralFormat locale.

Note

That argument is formatting without subtracting the offset. If you need a custom format and have a non-zero-offset, then you need to pass the number-minus-offset value as a separate parameter.

Define Custom Plural Rules

To add custom plural rules to the PluralFormat, create a PluralRules object and add it in PluralFormat constructor. If you also pass a locale object to constructor, this locale will affect formatted number in the returned message texts.

Usages of Date Intervals

Create Date Interval Object

The DateInterval API (in mobile and wearable applications) allows you to create date intervals.

DateInterval module represents time period between pair of i18n_udate values. For example, this type contains number of milliseconds from 1 January 1970 00:00 UTC to desired date.

Format Date Intervals

The DateIntervalFormat API (in mobile and wearable applications) allows you to format created date intervals.

Purpose of this module is to enable formatting date intervals in a language-independent manner. DateIntervalFormat module formats a date interval into text as compactly as possible. For example, the date interval format from “Jan 11, 2008” to “Jan 18, 2008” is “Jan 11-18, 2008” for English.

There is no structural information in date time patterns. For any punctuation or string literals in a date time pattern, you do not know whether it is just a separator, a prefix, or a suffix. Without such information, it is difficult to generate a sub-pattern (or super-pattern) using algorithm. Therefore, formatting a date interval is pattern-driven.

A skeleton:

  • Only keeps the field pattern letter and ignores all other parts in a pattern, such as space, punctuations, and string literals.
  • Hides the order of fields.
  • Can hide a field’s pattern letter length.

For the non-digit calendar fields, the pattern letter length is important. The pattern length are MMM, MMMM, and MMMMM; EEE and EEEE. The field’s pattern letter length is effectively considered. For example, the EEE pattern matches the short names of the weekdays (For instance, Mon, Tue, and so on.). If the pattern should match the entire weekday name, use the EEEE pattern.

For interval formatting, ICU supports the calendar fields such as year, month, date, day-of-week, am or pm, hour, hour-of-day, minute, and second (currently, ICU does not have specific interval format date for skeletons with seconds). These calendar fields are defined in the following order: year > month > date > hour (in day) > minute > second.

For example, the largest different calendar fields between “Jan 10, 2007” and “Feb 20, 2008” is the year.

For other calendar fields, the compact interval formatting is not supported. The function returns formatted date intervals depending on the interval value. The date interval format is {date0} - {date1}. For example, 20 - 25 September or 20 April - 15 May.

For the pre-defined skeletons in locales resource files, there are pre-defined interval patterns. For example, for a skeleton I18N_UDATE_YEAR_ABBR_MONTH_DAY, which is yMMMd in en_US.

  • If the largest different calendar field between date1 and date2 is year, then the date interval pattern is MMM d, yyyy - MMM d, yyyy, that is Jan 10, 2007 - Jan 10, 2008.
  • If the largest different calendar field between date1 and date2 is month, then the date interval pattern is MMM d - MMM d, yyyy, that is Jan 10 - Feb 10, 2007.
  • If the largest different calendar field between date1 and date2 is day, then the date interval pattern is MMM d-d, yyyy, that is Jan 10-20, 2007.

For date skeleton, the interval patterns for a year, a month, or a date is different and are defined in the resource files. For time skeleton, the interval patterns for am or pm, hour, or minute is different and are defined in the resource files.

Prerequisites

To use the functions and data types of the i18n API (in mobile and wearable applications) and its submodules, include the <utils_i18n.h> header file in your application:

#include <utils_i18n.h>

Manage Characters and Strings

Character and string management tasks include:

Note

All source and destination buffers must be different.

Compare Ustrings

To compare two Ustrings for bitwise equality, use the i18n_ustring_compare() function.

The obtained result is equal to 0 if the compared Ustrings are equal. The result is a negative value if the first Ustring is smaller bitwise than the second one, and a positive value if the first Ustring is greater than the second one.

#define BUF_SIZE 64

i18n_uchar s1[BUF_SIZE];
i18n_ustring_copy_ua(s1, "Tizen");
i18n_uchar s2[BUF_SIZE];
i18n_ustring_copy_ua(s2, "Bada");
int32_t result = i18n_ustring_compare(s1, s2);

For a more complex, locale-sensitive comparison, use the Ucollator API (in mobile and wearable applications):

  1. Create a Ucollator using the i18n_ucollator_create() function.

    Specify the locale as the first parameter and a handle to the created Ucollator as the second parameter.

    i18n_ucollator_h coll;
    i18n_ucollator_create(I18N_ULOCALE_US, &coll);
    
  2. Set the Ucollator strength using the i18n_ucollator_set_strength() function.

    The strength influences how the strings are compared. The following strength levels are available:

    • I18N_UCOLLATOR_DEFAULT_STRENGTH: Default
    • I18N_UCOLLATOR_PRIMARY: Compares the primary differences only, such as different base letters (“a” vs. “b”).
    • I18N_UCOLLATOR_SECONDARY: Compares primary and secondary differences, such as different accented forms of the same base letter (“a” vs. “ä”).
    • I18N_UCOLLATOR_TERTIARY: Compares primary, secondary, and tertiary differences, such as case differences (“a” vs. “A”).
    i18n_ucollator_set_strength(coll, I18N_UCOLLATOR_DEFAULT_STRENGTH);
    

    Since Tizen 4.0, you can also retrieve the current Ucollator strength using the i18n_ucollator_get_strength() function:

    i18n_ucollator_strength_e strength;
    i18n_ucollator_get_strength(coll, &strength);
    
  3. Compare two Ustrings.

    To compare two Ustrings, you have two options:

    • i18n_ucollator_equal(): Shows whether the compared Ustrings are equal.
    • i18n_ucollator_str_collator(): Shows whether the first Ustring is equal to, smaller, or greater than the second Ustring (I18N_UCOLLATOR_EQUAL, I18N_UCOLLATOR_LESS, or I18N_UCOLLATOR_GREATER).
    i18n_ubool equal;
    i18n_ucollator_equal(coll, s1, -1, s2, -1, &equal);
    
    i18n_ucollator_result_e result;
    i18n_ucollator_str_collator(coll, s1, -1, s2, -1, &result);
    

    Since Tizen 4.0, you can use the i18n_ucollator_greater_or_equal() function to check whether the first string is greater or equal to the second string:

    i18n_ubool result;
    i18n_ucollator_greater_or_equal(coll, s1, -1, s2, -1, &result);
    
  4. When no longer needed, destroy the Ucollator using the i18n_ucollator_destroy() function:

    i18n_ucollator_destroy(coll);
    

Since Tizen 4.0, you can also:

  • Check which locales the Ucollator API works with:

    • Retrieve an enumeration with all supported locales with the i18n_ucollator_create_available_locales() function:

      i18n_uenumeration_h locales;
      i18n_ucollator_create_available_locales(&locales);
      
    • Retrieve the count of all supported locales with the i18n_ucollator_count_available() function:

      int32_t n_available;
      i18n_ucollator_count_available(&n_available);
      
    • Retrieve a locale with a specified index by using the i18n_ucollator_get_available() function:

      const char *locale = NULL;
      int32_t locale_index = 0;
      i18n_ucollator_get_available(locale_index, &locale);
      
  • Clone a given collator in a thread-safe way:

    i18n_ucollator_h collator;
    i18n_collator_create(I18N_ULOCALE_US, &collator);
    i18n_ucollator_h clone;
    
    i18n_ucollator_safe_clone(collator, &clone);
    
  • Retrieve version information:

    • Ucollator version:

      i18n_uversion_info info;
      i18n_ucollator_get_version(coll, info);
      
    • UCA version information for Ucollator:

      i18n_uversion_info info;
      i18n_ucollator_get_uca_version(coll, info);
      
  • Manage keywords:

    • Retrieve an enumeration containing all possible keywords that are relevant to a collation:

      i18n_uenumeration_h keywords;
      i18n_ucollator_get_keywords(&keywords);
      
    • Retrieve all currently-used values of a keyword:

      i18n_uenumeration_h keyword_values;
      i18n_ucollator_get_keyword_values("collation", &keyword_values);
      
    • Retrieve an array of string values in a preferred order that can make a difference, based on the keyword and locale:

      i18n_uenumeration_h keywords;
      i18n_ucollator_get_keyword_values_for_locale("collation", "en_US", false, &keywords);
      
  • Manage sort keys:

    • Retrieve a sort key with the i18n_ucollator_get_sort_key() function:

      i18n_uchar src[64];
      i18n_ustring_copy_ua(src, str1);
      uint8_t sort_key[64];
      int32_t result_length;
      i18n_ucollator_get_sort_key(g_coll, src, -1, 64, sort_key, &result_length);
      
    • Retrieve the next count bytes of a sort key with the i18n_ucollator_next_sort_key_part() function:

      uint32_t state[2];
      uint8_t dest[64];
      int32_t result_length;
      i18n_uchar_iter_h iter = NULL;
      
      i18n_uchar_iter_create(&iter);
      i18n_uchar_iter_set_utf8(iter, str1, strlen(str1));
      i18n_ucollator_next_sort_key_part(g_coll, iter, state, dest, 1, &result_length);
      
    • Retrieve a bound for a given sort key and a number of levels by using the i18n_ucollator_get_bound() function:

      i18n_uchar src[64];
      i18n_ustring_copy_ua(src, str1);
      uint8_t sort_key[64];
      int32_t result_length;
      uint8_t bound[128];
      int32_t bound_length;
      
      i18n_ucollator_get_sort_key(g_coll, src, -1, 64, sort_key, &result_length);
      i18n_ucollator_get_bound(sort_key, result_length, I18N_UCOLLATOR_BOUND_UPPER, 1, bound, 128, &bound_length);
      
    • Merge two sort keys with the i18n_ucollator_merge_sort_keys() function:

      i18n_uchar src1[64];
      i18n_uchar src2[64];
      i18n_ustring_copy_ua(src1, "First string");
      i18n_ustring_copy_ua(src2, "Second string");
      uint8_t sort_key1[64];
      uint8_t sort_key2[64];
      
      int32_t result_length1;
      int32_t result_length2;
      uint8_t merged[128];
      int32_t merged_length;
      
      i18n_ucollator_get_sort_key(g_coll, src1, -1, 64, sort_key1, &result_length1);
      i18n_ucollator_get_sort_key(g_coll, src2, -1, 64, sort_key2, &result_length2);
      i18n_ucollator_merge_sort_keys(sort_key1, result_length1, sort_key2, result_length2, 128, merged, &merged_length);
      

Convert Strings to Ustrings

To convert strings to Ustrings:

  • To convert a byte string to a Unicode string (Ustring), use the i18n_ustring_copy_ua() function:

    const char *src = "Tizen";
    i18n_uchar dest[BUF_SIZE];
    i18n_ustring_copy_ua(dest, src);
    
  • To convert a byte string to a Ustring while defining a maximum number of characters to be copied, use the i18n_ustring_copy_ua_n() function and set the character limit as the third parameter:

    const char *src = "Tizen";
    i18n_uchar dest[BUF_SIZE];
    i18n_ustring_copy_ua_n(dest, src, BUF_SIZE);
    
  • To convert a UTF-8 string to a UTF-16 string, use the i18n_ustring_from_UTF8() function.

    The function returns the length of the converted string and an error code variable as out parameters.

    const char *src = "Tizen";
    i18n_uchar dest[BUF_SIZE];
    int dest_len;
    i18n_uerror_code_e error_code = I18N_ERROR_NONE;
    i18n_ustring_from_UTF8(dest, BUF_SIZE, &dest_len, src, -1, &error_code);
    

Convert Ustrings to Strings

To convert Ustrings to strings:

  • To convert a Ustring to a byte string, use the i18n_ustring_copy_au() function:

    i18n_uchar src[BUF_SIZE];
    i18n_ustring_copy_ua(src, "Tizen");
    char dest[BUF_SIZE];
    i18n_ustring_copy_au(dest, src);
    
  • To convert a Ustring to a byte string while defining a maximum number of characters to be copied, use the i18n_ustring_copy_au_n() function and set the character limit as the third parameter:

    i18n_uchar src[BUF_SIZE];
    i18n_ustring_copy_ua(src, "Tizen");
    char dest[BUF_SIZE];
    i18n_ustring_copy_au_n(dest, src, BUF_SIZE);
    
  • To convert a UTF-16 string to a UTF-8 string, use the i18n_ustring_to_UTF8() function.

    The function returns the length of the converted string and an error code variable as out parameters.

    To get the length of a Ustring, use the i18n_ustring_get_length() function.

    i18n_uchar src[BUF_SIZE];
    i18n_ustring_copy_ua(src, "Tizen");
    char dest[BUF_SIZE];
    int dest_len;
    i18n_uerror_code_e error_code = I18N_ERROR_NONE;
    i18n_ustring_to_UTF8(dest, BUF_SIZE, &dest_len, src, i18n_ustring_get_length(src), &error_code);
    

Get the Unicode Block of a Character

To get information about the location of a specified character, use the i18n_uchar_get_ublock_code() function.

The function returns, as an out parameter, the Unicode allocation block that contains the specified character. The Unicode blocks are defined in the i18n_uchar_ublock_code_e enumeration (in mobile and wearable applications).

i18n_uchar character = 0xC131;
i18n_uchar_ublock_code_e ublock;
i18n_uchar_get_ublock_code(character, &ublock);

Get the Property Value of a Character

To get the property value of a specified character, use the i18n_uchar_get_int_property_value() function.

The character properties are defined in the i18n_uchar_uproperty_e enumeration (in mobile and wearable applications).

The following example shows how to read the East Asian width property:

i18n_uchar character = 0xC131;
int32_t property_value;
i18n_uchar_get_int_property_value(character, I18N_UCHAR_EAST_ASIAN_WIDTH, &property_value);

Get the Name of a Character

You can retrieve the name of a Unicode character or retrieve the character from its name:

  • To retrieve the name of a Unicode character, use the i18n_uchar_char_name() function:

    i18n_uchar32 c = 0x03B1; /* Hexadecimal code for "α" character */
    i18n_uchar_u_char_name_choice_e name_choice = I18N_UCHAR_U_UNICODE_CHAR_NAME;
    char buffer[BUF_SIZE];
    int32_t *name_length;
    
    i18n_uchar_char_name(c, name_choice, buffer, BUF_SIZE, &name_length); /* Buffer contains "GREEK SMALL LETTER ALPHA" */
    
  • To retrieve the character from its name, use the i18n_uchar_char_from_name() function:

    i18n_uchar_u_char_name_choice_e name_choice = I18N_UCHAR_U_UNICODE_CHAR_NAME;
    const char *name = "GREEK SMALL LETTER ALPHA";
    i18n_uchar32 char_from_name;
    
    i18n_uchar_char_from_name(name_choice, name, &char_from_name);
    

Get the Decimal Digit Value of a Character

To retrieve the decimal digit value of a character, use the i18n_uchar_digit_value() function:

i18n_uchar32 c = 0x39; /* Hexadecimal code for digit "9" */
int32_t char_digit_value = 0;

i18n_uchar_char_digit_value(c, &char_digit_value); /* char_digit_value has value "9" */

Check for a Character Binary Property

You can verify whether a Unicode character has a specific binary property in two ways:

  • Use the corresponding i18n_uchar_is_xxx() function.

    The following example checks whether the character has the lowercase property:

    i18n_uchar32 c = 0x6D;
    i18n_ubool is_lowercase = false;
    i18n_uchar_is_lowercase(c, &is_lowercase);
    
  • Use the i18n_uchar_has_binary_property() function with the name of the binary property.

    The binary properties are defined in the i18n_uchar_uproperty_e enumeration (in mobile and wearable applications).

    i18n_uchar32 c = 0x6D;
    i18n_uchar_uproperty_e which = I18N_UCHAR_LOWERCASE;
    i18n_ubool has_binary_property = false;
    i18n_uchar_has_binary_property(c, which, &has_binary_property);
    

Get an Alternate Representation of a Character

To get an alternate representation of a character, use the i18n_uchar_to_xxx() functions.

The following example shows how to obtain the uppercase representation of the letter “m”:

i18n_uchar32 c = 0x6D;
i18n_uchar32 to_upper;
i18n_uchar_to_upper(c, &to_upper);

Get the Character Age and Unicode Version

The character age is the Unicode version in which the character was first designated (as a non-character or for private use) or assigned:

  • To retrieve the character age:

    i18n_uchar32 c = 0x1207;
    i18n_uversion_info char_age;
    i18n_uchar_char_age(c, &char_age);
    
  • To retrieve the Unicode version information:

    i18n_uversion_info version_array;
    i18n_uchar_get_unicode_version(version_array);
    

Normalize Ustrings

To normalize a Ustring:

  1. Get a Unormalizer instance using the i18n_unormalization_get_instance() function of the Unormalization API (in mobile and wearable applications).

    To use the built-in normalizer, set the first parameter to NULL.

    i18n_unormalizer_h normalizer;
    i18n_unormalization_get_instance(NULL, "nfc", I18N_UNORMALIZATION_DECOMPOSE, &normalizer);
    
  2. Normalize a Ustring or Uchar with the obtained normalizer using the i18n_unormalization_normalize() function:

    i18n_uchar src = 0xACE0;
    i18n_uchar dest[4];
    int dest_str_len;
    i18n_unormalization_normalize(normalizer, &src, 1, dest, 4, &dest_str_len);
    

Search Text in a Ustring

To search for a substring in a Ustring:

  1. Create a search iterator using the i18n_usearch_create_new() function of the Usearch API (in mobile and wearable applications):

    i18n_uchar text[BUF_SIZE];
    i18n_ustring_copy_ua(text, "TIZEN");
    i18n_uchar pattern[BUF_SIZE];
    i18n_ustring_copy_ua(pattern, "ZEN");
    i18n_usearch_h usearch;
    i18n_usearch_create_new(pattern, -1, text, -1, I18N_ULOCALE_US, NULL, &usearch);
    
  2. Get the index of the first match (the first occurrence of the found pattern) using the i18n_usearch_first() function:

    int index;
    i18n_usearch_first(usearch, &index);
    
  3. When no longer needed, destroy the search iterator using the i18n_usearch_destroy() function:

    i18n_usearch_destroy(usearch);
    

Change the Case in a Ustring

To change the case in a Ustring:

  1. To change all characters’ case in a Ustring, use the i18n_ustring_to_upper() or i18n_ustring_to_lower() function:

    i18n_uchar src[BUF_SIZE];
    i18n_ustring_copy_ua(src, "Tizen");
    i18n_uchar dest[BUF_SIZE];
    i18n_ustring_to_upper(dest, BUF_SIZE, src, -1, I18N_ULOCALE_US, &error_code);
    i18n_ustring_to_lower(dest, BUF_SIZE, src, -1, I18N_ULOCALE_US, &error_code);
    
  2. To change the string case to title case, use the i18n_ustring_to_title_new() function:

    i18n_uchar src[BUF_SIZE];
    i18n_ustring_copy_ua(src, "Tizen");
    i18n_uchar dest[BUF_SIZE];
    i18n_ustring_to_title_new(dest, BUF_SIZE, src, BUF_SIZE, NULL, NULL);
    

Concatenate Ustrings

To concatenate two Ustrings, use the 18n_ustring_cat() or 18n_ustring_cat_n() function.

The functions differ in that the latter takes a third parameter to define a maximum number of characters to append to the destination string.

i18n_uchar src[BUF_SIZE];
i18n_uchar dest[BUF_SIZE];

i18n_ustring_copy_ua(dest, "Destination string");
i18n_ustring_copy_ua(src, "Appended string");

i18n_ustring_cat_n(dest, src, BUF_SIZE);
/* Or */
i18n_ustring_cat(dest, src);

Find a Substring

To find a substring in a Ustring, use the i18n_ustring_string() function.

The result is a pointer to the first occurrence of the substring, or NULL if the substring is not found. You can use pointer arithmetic to find the index of the character at which the first occurrence begins.

i18n_uchar s[BUF_SIZE];
i18n_uchar substring[BUF_SIZE];

i18n_uchar *result = i18n_ustring_string(s, substr);

if (result == NULL)
    dlog_print(DLOG_DEBUG, LOG_TAG, "Substring not found");
else
    dlog_print(DLOG_DEBUG, LOG_TAG, "Substring index: %d", result - s);

Manage Dates and Calendar

To create and use a calendar:

  1. To manage dates and calendar, the Ucalendar (in mobile and wearable applications), Udate (in mobile and wearable applications), and Udatepg (in mobile and wearable applications) APIs are used.

    • The Ucalendar API is used for converting between an i18n_udate object and a set of integer fields, such as I18N_UCALENDAR_YEAR, I18N_UCALENDAR_MONTH, I18N_UCALENDAR_DAY, and I18N_UCALENDAR_HOUR.
    • The Udate API is used to convert dates and times from their internal representations to a textual form and back again in a language-independent manner.
    • The Udatepg API is used to generate date format patterns, such as “yy-MM-dd”.
  2. To create a Ucalendar, use the i18n_ucalendar_create() function:

    i18n_uchar timezone[BUF_SIZE];
    const char *timezone_name = "America/New_York";
    int timezone_name_len = strlen(timezone_name);
    i18n_ustring_copy_ua_n(timezone, timezone_name, timezone_name_len + 1);
    i18n_ucalendar_h ucalendar;
    i18n_ucalendar_create(timezone, -1, I18N_ULOCALE_US, I18N_UCALENDAR_DEFAULT, &ucalendar);
    
  3. To set a date in the Ucalendar, use the i18n_ucalendar_set_date_time() function.

    In the following example, the date is set as 1 July 2014, 9:00:00.

    To define the month, you can use numbers (month reduced by 1, such as 0 for January and 1 for February), or to avoid mistakes, the values of the i18n_ucalendar_months_e enumeration (in mobile and wearable applications).

    i18n_ucalendar_set_date_time(ucalendar, 2014, I18N_UCALENDAR_JULY, 1, 9, 0, 0);
    

    To set a date using milliseconds from the epoch, use the i18n_ucalendar_set_milliseconds() function:

    i18n_udate udate;
    /* udate must be set */
    i18n_ucalendar_set_milliseconds(ucalendar, udate);
    

    To add a specified period to the Ucalendar, use the i18n_ucalendar_add() function.

    Specify the date field to modify (such as year, week, or day) using the i18n_ucalendar_date_fields_e enumeration (in mobile and wearable applications) as the second parameter, and the amount to modify as the third parameter (use a negative value to subtract from the existing value).

    i18n_ucalendar_add(ucalendar, I18N_UCALENDAR_HOUR, 3);
    
  4. To get a date from the Ucalendar, you can use various functions:

    • To get a specific date field from a Ucalendar instance, use the i18n_ucalendar_get() function and define the wanted date field with the i18n_ucalendar_date_fields_e enumeration:

      int uday;
      i18n_ucalendar_get(ucalendar, I18N_UCALENDAR_DAY_OF_YEAR, &uday);
      
    • To get a date from a Ucalendar in milliseconds from the epoch, use the i18n_ucalendar_get_milliseconds() function:

      i18n_udate date;
      i18n_ucalendar_get_milliseconds(ucalendar, &date);
      
    • To get the actual current date from the system, use the i18n_ucalendar_get_now() function. The obtained date is represented as milliseconds from the epoch.

      i18n_udate now;
      i18n_ucalendar_get_now(&now);
      
    • To verify whether the Ucalendar date is in daylight saving time, use the i18n_ucalendar_is_in_daylight_time() function:

      bool dst;
      i18n_ucalendar_is_in_daylight_time(ucalendar, &dst);
      
  5. To format a date, you can use a pattern generator or define a date format:

    • Using a pattern generator:

      1. To create a Udatepg pattern generator instance, use the i18n_udatepg_create() function and define the desired locale as the first parameter:

        i18n_udatepg_h udatepg;
        i18n_udatepg_create(I18N_ULOCALE_UK, &udatepg);
        
      2. To generate a date best pattern with the pattern generator, use the i18n_udatepg_get_best_pattern() function.

        As the second parameter, you need a draft format, which defines the fields to be displayed (for example, E for the day of the week, M for month, y for year, d for the day of the month, and D for day of the year).

        int pattern_len;
        i18n_uchar format[BUF_SIZE];
        i18n_ustring_copy_ua_n(format, "EEEdMMMyyyyHHmmssz", BUF_SIZE);
        i18n_uchar best_pattern[BUF_SIZE];
        i18n_udatepg_get_best_pattern(udatepg, format, BUF_SIZE, best_pattern, BUF_SIZE, &pattern_len);
        
    • Using a date format:

      1. To create a date format, use the i18n_udate_create() function.

        As the first and second parameter, specify the formatting style for time and date using the values of the i18n_udate_format_style_e enumeration (in mobile and wearable applications).

        i18n_udate_format_h date_format;
        const char *timezone_name = "Asia/Seoul";
        int timezone_name_len = strlen(timezone_name);
        i18n_ustring_copy_ua_n(timezone, timezone_name, timezone_name_len + 1);
        i18n_udate_create(I18N_UDATE_FULL, I18N_UDATE_FULL, I18N_ULOCALE_UK, timezone, -1, best_pattern, -1, &date_format);
        
      2. To obtain a Ustring with a specified date and the created date format, use the i18n_udate_format_date() function:

        i18n_uchar date_result[BUF_SIZE];
        int date_len;
        i18n_udate_format_date(date_format, now, date_result, BUF_SIZE, NULL, &date_len);
        
  6. When no longer needed, destroy the Ucalendar, Udatepg, and Udate instances using the i18n_ucalendar_destroy(), i18n_udatepg_destroy(), and i18n_udate_destroy() functions:

    i18n_ucalendar_destroy(ucalendar);
    i18n_udatepg_destroy(udatepg);
    i18n_udate_destroy(date_format);
    

Manage Locales

To manage the features of a specific geographical, political, or cultural region:

  • To get the language code associated with a locale, use the i18n_ulocale_get_language() function:

    char language[BUF_SIZE];
    int lang_len;
    i18n_ulocale_get_language(I18N_ULOCALE_GERMANY, language, BUF_SIZE, &lang_len);
    
  • To get the language ISO-3 code for the specified locale, use the i18n_ulocale_get_iso3_language() function:

    const char *language_iso = i18n_ulocale_get_iso3_language(I18N_ULOCALE_GERMANY);
    
  • To get the full name of the language for the specified locale, use the i18n_ulocale_get_display_language() function.

    In the following example, the name of the “fr_CA” locale is obtained in German:

    char *locale = I18N_ULOCALE_CANADA_FRENCH;
    i18n_uchar language_name[BUF_SIZE];
    int lang_len;
    i18n_ulocale_get_display_language(locale, I18N_ULOCALE_GERMANY, language_name, BUF_SIZE, &lang_len);
    
  • To get the line orientation for the specified locale, use the i18n_ulocale_get_line_orientation() function:

    const char *locale = I18N_ULOCALE_ENGLISH;
    i18n_ulocale_layout_type_e type;
    i18n_ulocale_get_line_orientation(locale, &type);
    
  • To get the character orientation for the specified locale, use the i18n_ulocale_get_character_orientation() function:

    const char *locale = I18N_ULOCALE_ENGLISH;
    i18n_ulocale_layout_type_e type;
    i18n_ulocale_get_character_orientation(locale, &type);
    
  • To get the variant code for the specified locale, use the i18n_ulocale_get_variant() function.

    The function returns the actual size of the variant code.

    const char *locale = I18N_ULOCALE_ENGLISH;
    char *variant = malloc(sizeof(char) * BUF_SIZE);
    int32_t variant_len = i18n_ulocale_get_variant(locale, variant, BUF_SIZE);
    
  • To get a full name for the specified locale, use the i18n_ulocale_get_display_name() function.

    In the following example, the name of the “fr_CA” locale is obtained in German:

    i18n_uchar name[BUF_SIZE];
    int name_len;
    i18n_ulocale_get_display_name(I18N_ULOCALE_CANADA_FRENCH, I18N_ULOCALE_GERMANY, name, BUF_SIZE, &name_len);
    
  • To get or set the default locale, use the i18n_ulocale_get_default() or i18n_ulocale_set_default() function:

    /* Get */
    char *locale;
    i18n_ulocale_get_default(&locale);
    
    /* Set */
    i18n_ulocale_set_default(I18N_ULOCALE_KOREA);
    

Manage Numbers

To format and parse numbers for a locale:

  1. To create a number format, use the i18n_unumber_create() function.

    Define the style as the first parameter using the i18n_unumber_format_style_e enumeration (in mobile and wearable applications).

    The fourth parameter sets the locale (NULL for default). Some string shortcuts for specific locales are defined in the utils_i18n_types.h header file. For example, I18N_ULOCALE_US is equal to “en_US”.

    i18n_unumber_format_h num_format;
    i18n_unumber_format_style_e format_style = I18N_UNUMBER_CURRENCY;
    const char* locale = I18N_ULOCALE_US;
    i18n_unumber_create(format_style, NULL, -1, locale, NULL, &num_format);
    
  2. To use the created number format to format a given number based on the rules of a specified locale, you can use various i18n_unumber_format_XXX() functions.

    The following example formats a double-type number:

    #define BUF_SIZE 64
    i18n_uchar myString[BUF_SIZE];
    double myNumber = 4.5;
    i18n_unumber_format_double(num_format, myNumber, myString, BUF_SIZE, NULL);
    

    The result set in the myString variable is equal to:

    $4.50
    
  3. To get a symbol associated with the created number format, use the i18n_unumber_get_symbol() function.

    The second parameter uses the values of the i18n_unumber_format_symbol_e enumeration (in mobile and wearable applications) to define the symbol to be retrieved.

    The function returns the symbol used in the given locale. In the following example, it returns the currency $ sign:

    i18n_uchar buffer[BUF_SIZE];
    int buf_len;
    i18n_unumber_format_symbol_e symbol = I18N_UNUMBER_CURRENCY_SYMBOL;
    i18n_unumber_get_symbol(num_format, symbol, buffer, BUF_SIZE, &buf_len);
    
  4. When no longer needed, destroy the number format with the i18n_unumber_destroy() function:

    i18n_unumber_destroy(num_format);
    

Manage Iteration Using Ubrk

To manipulate or iterate through strings, you can use the Ubrk library. It helps you to treat strings as a set of characters, words, or sentences:

  1. To create an iterator to iterate through a string, use the i18n_ubrk_create() function.

    The first parameter defines the type of the iterator:

    • I18N_UBRK_WORD for word iteration
    • I18N_UBRK_CHARACTER for character iteration
    • I18N_UBRK_LINE for line iteration
    • I18N_UBRK_SENTENCE for sentence iteration
    i18n_ubreak_iterator_h boundary;
    const char *str = "Twinkle, twinkle little star";
    int str_len = strlen(str);
    i18n_uchar* stringToExamine = malloc(sizeof(i18n_uchar)*(str_len + 1));
    i18n_ustring_copy_ua(stringToExamine, str);
    i18n_ubrk_create(I18N_UBRK_WORD, I18N_ULOCALE_US, stringToExamine, -1, &boundary);
    
  2. To change the position of the iterator, you can use several functions, such as i18n_ubrk_first(), i18n_ubrk_last(), i18n_ubrk_next(), and i18n_ubrk_previous().

    The following example retrieves the boundaries of the first word in the stringToExamine string. The start and end variables represent the boundaries of the first word, in this example 0 and 7.

    int32_t start = i18n_ubrk_first(boundary);
    int32_t end = i18n_ubrk_next(boundary);
    
  3. To retrieve a string delimited with the start and end boundary variables, use the i18n_ustring_copy_n() function.

    The second parameter defines the source string, and the third parameter defines the maximum number of characters to copy.

    i18n_ustring_copy_n(result, &str[start], end-start);
    
  4. When no longer needed, destroy the ubreak iterator with the i18n_ubrk_destroy() function. Remember to free all allocated memory with the free() function.

    i18n_ubrk_destroy(boundary);
    

Manage Enumerations

To create collections of strings and iterate through them, create an enumeration. You can also obtain enumerations from specific functions.

Create an Enumeration

To create an enumeration based on existing strings:

  1. Define an array of strings (pointers to char):

    const char* strings[] = {"First", "Second", "Third", "Fourth"};
    
    /* Length of the pointers array (the number of strings) */
    int32_t size = sizeof(strings) / sizeof(strings[0]);
    
  2. Create an enumeration of the char strings:

    i18n_uenumeration_h strings_enum;
    
    i18n_uenumeration_char_strings_enumeration_create(strings, size, &strings_enum);
    

    For i18n_uchar strings, use the i18n_uenumeration_uchar_strings_enumeration_create() function.

  3. Get the number of elements:

    int32_t count = i18n_uenumeration_count(strings_enum);
    

    If the enumeration was created successfully, the value is equal to the size variable used above.

  4. Iterate through the char elements using the i18n_uenumeration_next() function, until it returns NULL.

    The string is null-terminated, and the len variable is the length of the string.

    Do not free the returned string. The returned pointer is valid until a function is called for the enumeration.

    const char *element = NULL;
    int len;
    
    element = i18n_uenumeration_next(strings_enum, &len);
    while (element != NULL) {
        /* Use the returned string */
    
        element = i18n_uenumeration_next(strings_enum, &len);
    }
    

    For i18n_uchar strings, use the i18n_uenumeration_unext() function.

  5. When no longer needed, destroy the enumeration with the 18n_uenumeration_destroy() function:

    18n_uenumeration_destroy(strings_enum);
    

Obtain an Enumeration

Certain functions in the i18n module provide enumerations of values related to them. After the enumeration is obtained, you can iterate through its values.

  • To get an enumeration of available time zones and iterate through them, use the i18n_ucalendar_timezones_create() function:

    i18n_uenumeration_h timezones;
    i18n_ucalendar_timezones_create(&timezones);
    
    int32_t count = i18n_uenumeration_count(timezones);
    
    const char *tz = NULL;
    int len;
    
    tz = i18n_uenumeration_next(timezones, &len);
    while (tz != NULL) {
        /* Use the time zone string */
    
        tz = i18n_uenumeration_next(timezones, &len);
    }
    
    i18n_uenumeration_destroy(timezones);
    
  • After creating a date pattern generator for a given locale, you can obtain an enumeration of all the pattern skeletons in a canonical form.

    To get the enumeration and iterate through the skeletons, use the i18n_udatepg_skeletons_create() function:

    i18n_udatepg_h udatepg;
    i18n_udatepg_create(I18N_ULOCALE_UK, &udatepg);
    
    i18n_uenumeration_h skeletons;
    i18n_udatepg_skeletons_create(udatepg, &skeletons);
    
    i18n_udatepg_destroy(udatepg);
    
    int32_t count = i18n_uenumeration_count(skeletons);
    
    const char *sk = NULL;
    int len;
    
    sk = i18n_uenumeration_next(skeletons, &len);
    while (sk != NULL) {
        /* Use the skeleton string */
    
        sk = i18n_uenumeration_next(skeletons, &len);
    }
    
    i18n_uenumeration_destroy(skeletons);
    
  • To get an enumeration of keywords for a given locale string and iterate through the keywords, use the i18n_ulocale_keywords_create() function:

    const char *loc_string = "en_US@collation=PHONEBOOK;calendar=GREGORIAN;currency=USD";
    
    i18n_uenumeration_h keywords;
    i18n_ulocale_keywords_create(loc_string, &keywords);
    
    int32_t count = i18n_uenumeration_count(keywords);
    
    const char *keyword = NULL;
    int len;
    
    keyword = i18n_uenumeration_next(keywords, &len);
    while (keyword != NULL) {
        /* Use the keyword string */
    
        keyword = i18n_uenumeration_next(keywords, &len);
    }
    
    i18n_uenumeration_destroy(keywords);
    

Manage Time Zones

To manage time zone details, such as the time zone offset and daylight savings:

  1. To retrieve time zone information:

    • To get the default time zone based on the time zone where the program is running, use the i18n_timezone_create_default() function:

      i18n_timezone_h tmz;
      i18n_timezone_create_default(&tmz);
      
    • To get the display name of the time zone, use the i18n_timezone_get_display_name() function:

      char *display_name;
      i18n_timezone_get_display_name(tmz, &display_name);
      
    • To get the time zone ID, use the i18n_timezone_get_id() function:

      char *timezone_id;
      i18n_timezone_get_id(tmz, &timezone_id);
      
    • To check whether a given time zone uses daylight savings time (DST), use the i18n_timezone_use_daylight_time() function:

      bool dst_savings;
      i18n_timezone_use_daylight_time(tmz, &dst_savings);
      
    • To get the daylight savings (the amount of time to be added to the local standard time to get the local wall clock time), use the i18n_timezone_get_dst_savings() function.

      The result is returned in milliseconds (3600000 ms = 1 hour). In the following example, milliseconds are changed to minutes (1 min = 60000 ms).

      #define MS_TO_MIN 60000
      int32_t dst_savings;
      i18n_timezone_get_dst_savings(tmz, &dst_savings/MS_TO_MIN);
      
    • To get the raw GMT offset, use the i18n_timezone_get_raw_offset() function.

      The result is the number of milliseconds to add to GMT to get the local time, before taking DST into account, and it is returned in milliseconds. In the following example, milliseconds are changed to minutes (1 min = 60000 ms).

      #define MS_TO_MIN 60000
      int32_t offset_milliseconds;
      i18n_timezone_get_raw_offset(tmz, &offset_milliseconds/MS_TO_MIN);
      
    • To get the region code associated with the time zone ID, use the i18n_timezone_get_region() function:

      char region[BUF_SIZE];
      int32_t region_len = -1;
      i18n_timezone_get_region(timezone_id, region, &region_len, BUF_SIZE);
      
  2. When no longer needed, destroy the time zone instance with the i18n_timezone_destroy() function:

    i18n_timezone_destroy(tmz);
    

Manage Sets

You can create sets, which contain characters and strings. You can iterate through the set elements and carry out various operations on the set.

To manage sets:

  1. To create a set, use various i18n_uset_create_XXX() functions.

    The following example creates an empty set:

    i18n_uset_h set;
    i18n_uset_create_empty(&set);
    
  2. To manage character sets:

    A character set contains characters as its elements.

    • Add characters from a string to the set using the i18n_uset_add_all_code_points() function:

      const char *text = "Example string";
      i18n_uchar u_input_text[BUF_SIZE];
      i18n_ustring_copy_ua(u_input_text, text);
      
      i18n_uset_add_all_code_points(set, u_input_text, -1);
      
    • Get the list of characters in the set using the i18n_uset_char_at() function:

      int chars_count = i18n_uset_size(set);
      int i;
      
      /* Get all characters in the set */
      for (i = 0; i < chars_count; i++)
          i18n_uchar32 uchar = i18n_uset_char_at(set, i);
      
    • Verify whether the set contains a specific character using the i18n_uset_contains() function:

      i18n_ubool contains_character = i18n_uset_contains(set, 'a');
      
    • Verify whether the set contains characters from a specific range using the i18n_uset_contains_range() function.

      The following example uses the range “a-c”.

      i18n_ubool contains_character = i18n_uset_contains_range(set, 'a', 'c');
      
    • Verify whether the set contains characters from another set using the i18n_uset_contains_all() function:

      i18n_uset_h compare_set = NULL;
      i18n_uset_create_empty(&compare_set);
      /* Fill the second set */
      
      i18n_ubool contains_character = i18n_uset_contains_all(set, compare_set);
      
  3. To manage string sets:

    A string set contains strings as its elements.

    • Add a string to the set using the i18n_uset_add_string() function.

      The entire string is a single element.

      const char *text = "Example string";
      i18n_uchar u_input_text[BUF_SIZE];
      i18n_ustring_copy_ua(u_input_text, text);
      
      i18n_uset_add_string(set, u_input_text, -1);
      
    • List all strings in the set using the i18n_uset_get_item() function.

      The function returns the length of a string item, or 0, if the item is a range.

      int strings_count = i18n_uset_get_item_count(set);
      int32_t len = 0;
      int32_t i;
      for (i = 0; i < strings_count; ++i) {
          i18n_uchar32 start, end;
          i18n_uchar string[100];
          len = i18n_uset_get_item(set, i, &start, &end, string, 100);
          if (len != 0)
              /* String was found, use the 'string' variable */
      }
      
    • Verify whether the set contains a string using the i18n_uset_contains_string() function:

      const char *input_string = "Input string";
      int input_string_len = strlen(input_string);
      i18n_uchar *input_ustring = malloc(sizeof(i18n_uchar) * (input_string_len + 1));
      i18n_ustring_copy_ua(input_ustring, input_string);
      
      i18n_ubool contains = i18n_uset_contains_string(set, input_ustring, -1);
      

Manage Alphabetic Indexes

Since Tizen 3.0, you can generate an alphabetical list of clickable labels by using the Alphabetic Index API (in mobile and wearable applications).

To generate and manage an alphabetic index:

  1. To create an alphabetic index object for a specific locale:

    i18n_alpha_idx_create("en", "US", &alpha_idx);
    

    Note

    This function is deprecated from Tizen 5.0. Instead, use i18n_alpha_idx_create_from_locale_id(), which takes the locale ID parameter. To set the language as “en” and country as “US”, use the locale ID “en_US”.

  2. To manage index labels:

    • To add labels from a specific locale:

      i18n_alpha_idx_add_labels(alpha_idx, "ko", "KR");
      

      Note

      This function is deprecated from Tizen 5.0. Instead, use i18n_alpha_idx_add_labels_with_locale_id(), which takes the locale ID parameter. To set the language as “ko” and country as “KR”, use the locale ID “ko_KR”.

    • To add custom labels to the index:

      int record_data = 7;
      i18n_alpha_idx_add_record(alpha_idx, "AAA", &record_data); /* Adds label "AAA" at position 7 in index */
      
    • To manage the default label used for abbreviated buckets between other index characters:

      • To get the default label:

        char *label = NULL;
        i18n_alpha_idx_get_inflow_label(alpha_idx, &label);
        
      • To set the default label:

        const char *label = "Desired label";
        i18n_alpha_idx_set_inflow_label(alpha_idx, label);
        
    • To manage the overflow label used for items sorted after the last normal label:

      • To get the overflow label:

        char *label;
        i18n_alpha_idx_get_overflow_label(alpha_idx, &label);
        
      • To set the overflow label:

        char *label = "Overflow label";
        i18n_alpha_idx_set_overflow_label(alpha_idx, label);
        
    • To manage the underflow label used for items sorted before the first normal label:

      • To get the underflow label:

        char *label;
        i18n_alpha_idx_get_underlow_label(alpha_idx, &label);
        
      • To set the underflow label:

        char *label = "Underflow label";
        i18n_alpha_idx_set_underflow_label(alpha_idx, label);
        
    • To manage the number of labels permitted in the index:

      • To get the number of labels permitted in the index:

        int32_t count = 0;
        i18n_alpha_idx_get_max_label_count(alpha_idx, &count);
        
      • To set the number of labels permitted in the index:

        int32_t count = 50;
        i18n_alpha_idx_set_max_label_count(alpha_idx, count);
        
    • To get the label of the current bucket:

      char *record_name;
      i18n_alpha_idx_get_bucket_label(alpha_idx, &record_name);
      
    • To get the label type of the current bucket:

      i18n_alpha_idx_label_type_e type;
      i18n_alpha_idx_get_bucket_label_type(alpha_idx, &type);
      
  3. To move around the index:

    • To set the next bucket as the current bucket:

      bool available;
      i18n_alpha_idx_get_next_bucket(alpha_idx, &available);
      
    • To set the next record as the current record in the current bucket:

      bool available;
      i18n_alpha_idx_get_next_record(alpha_idx, &available);
      
    • To reset the iterators:

      • To reset the bucket iterator:

        i18n_alpha_idx_reset_bucket_iter(alpha_idx);
        

        The iterator is set before the first bucket. To move the iterator to the first bucket, use the i18n_alpha_idx_next_bucket() function.

      • To reset the record iterator:

        i18n_alpha_idx_reset_record_iter(alpha_idx);
        

        The iterator is set before the first record in the current bucket. To move the iterator to the first record, use the i18n_alpha_idx_next_record() function.

  4. To retrieve information:

    • To get the number of various objects in the index:

      • To get the number of buckets in the index:

        int32_t count = 0;
        i18n_alpha_idx_get_bucket_count(alpha_idx, &count);
        
      • To get the total number of records in all buckets:

        int32_t count = 0;
        i18n_alpha_idx_get_record_count(alpha_idx, &count);
        
      • To get the number of records in the current bucket:

        int32_t count = 0;
        i18n_alpha_idx_get_bucket_record_count(alpha_idx, &count);
        
    • To get the bucket index:

      • For a bucket with a specific name:

        int32_t index = -1;
        const char *name = "Desired bucket";
        i18n_alpha_idx_get_bucket_index(alpha_idx, name, &index);
        
      • For the current bucket:

        int32_t index = -1;
        i18n_alpha_idx_get_current_bucket_index(alpha_idx, &index);
        
    • To get the current record name:

      char *name;
      i18n_alpha_idx_get_record_name(alpha_idx, &name);
      
    • To get the pointer to the current record:

      void *data = NULL;
      data = i18n_alpha_idx_get_record_data(alpha_idx);
      
  5. To clear all records from the index:

    i18n_alpha_idx_clear_records(alpha_idx);
    
  6. When no longer needed, destroy the index:

    i18n_alpha_idx_destroy(alpha_idx);
    

From Tizen 5.0, you can use immutable index API (in mobile and wearable applications) to create an immutable index, a thread-safe version of an alphabetic index without data records.

  1. To create an immutable index:

    • Create an alphabetic index:

      i18n_alpha_idx_h alpha_idx;
      i18n_alpha_idx_create("en", "US", &alpha_idx);
      
    • Fill the index with data. See the alphabetic index example.

    • Create an immutable index:

      i18n_immutable_idx_h im_index;
      i18n_immutable_idx_create(alpha_idx, &im_index);
      
  2. To use the immutable index:

    • Get the number of buckets:

      int bucket_count = 0;
      i18n_immutable_idx_get_bucket_count(im_index, &bucket_count);
      
    • Get the bucket index using the bucket name:

      char *bucket_name = ...
      int32_t bucket_index;
      
      i18n_immutable_idx_get_bucket_index(im_index, bucket_name, &bucket_index);
      
    • Get the label of a given bucket using the bucket index:

      char *label = NULL;
      int32_t bucket_index = ...
      
      i18n_immutable_idx_get_bucket_label(im_index, bucket_index, &label);
      
      /* Use the label ... */
      
      free(label);
      
    • Get the label type of a given bucket:

      int32_t bucket_index = ...
      i18n_alpha_idx_label_type_e label_type;
      
      i18n_immutable_idx_get_bucket_label_type(im_index, bucket_index, &label_type);
      
  3. Destroy the index when it is no longer needed:

    i18n_immutable_idx_destroy(im_index);
    

Manage the Field Position

Since Tizen 3.0, you can use the FieldPosition API (in mobile and wearable applications) to manage the field position for formatted output.

To manage the field position:

  1. Create a field position pointer:

    • Without a specific field:

      i18n_field_position_h field_pos;
      i18n_field_position_create(&field_pos);
      
    • With a specific field:

      i18n_field_position_h field_pos;
      int32_t field = 10;
      i18n_field_position_create_for_field(field, &field_pos);
      
  2. To retrieve field position information:

    • To retrieve the field identifier:

      int32_t field;
      i18n_field_position_get_field(field_pos, &field);
      
    • To retrieve the index of the first character in the requested field:

      int32_t begin_index;
      i18n_field_position_get_begin_index(field_position, &begin_index);
      
    • To retrieve the index of the character after the last character in the requested field:

      int32_t end_index;
      i18n_field_position_get_end_index(field_position, &end_index);
      
  3. To set field position information:

    • To set the field identifier:

      int32_t field;
      i18n_field_position_set_field(field_pos, field);
      
    • To set the start index:

      int32_t begin_index;
      i18n_field_position_set_begin_index(field_position, begin_index);
      
    • To set the end index:

      int32_t end_index;
      i18n_field_position_set_end_index(field_position, end_index);
      
  4. To clone the field position pointer:

    i18n_field_position_h clone;
    i18n_field_position_clone(field_pos, &clone);
    
  5. When no longer needed, destroy the field position pointer:

    i18n_field_position_destroy(field_pos);
    

Manage String Formatting

Since Tizen 3.0, you can use the Format API (in mobile and wearable applications) to manage format objects, which derive from this module, and their string representations:

  1. To clone a format object:

    i18n_format_h original; /* original can be pointer to any object whose class derives from the Format module */
    i18n_format_h clone;
    i18n_format_clone(original, &clone);
    
  2. To retrieve the locale from a format object:

    i18n_ulocale_data_locale_type_e type = I18N_ULOCALE_DATA_LOCALE_TYPE_ACTUAL_LOCALE;
    char *language = NULL;
    char *country = NULL;
    i18n_format_get_locale(format, type, &language, &country);
    /* For example, language is "en" and country is "US" */
    

    Note

    This function is deprecated from Tizen 5.0. Instead, use i18n_format_get_locale_id(), which will return the locale ID parameter. For example for language “en” and country “US”, this function will return “en_US” string.

  3. To retrieve the string representation of a format object:

    • Without a field position:

      double double_to_set = 13.0;
      i18n_formattable_h formattable = NULL;
      i18n_formattable_create_with_double(double_to_set, &formattable);
      
      char *append_to = "Price: ";
      i18n_format_format(format, formattable, &append_to);
      /* append_to buffer now contains "Price: $13.00" string */
      
    • With a field position:

      double double_to_set = 13.0;
      i18n_formattable_h formattable = NULL;
      i18n_formattable_create_with_double(double_to_set, &formattable);
      char *append_to = "Price: ";
      
      i18n_field_position_h field_position = NULL;
      i18n_field_position_create(&field_position);
      i18n_format_format_with_field_position(format, formattable, &append_to, field_position);
      /* Same result as example above */
      
  4. To parse a string to a format object:

    • Without a parse position:

      const char *source = "$1,234.56";
      i18n_formattable_h result = NULL;
      i18n_format_parse_object(format, source, &result);
      
      double value = 0;
      i18n_formattable_get_double(result, &value);
      /* value variable now contains 1234.56 as double */
      
    • With a parse position:

      char *source = "$1,234.56 $456.78";
      i18n_formattable_h result = NULL;
      i18n_parse_position_h parse_position = NULL;
      int32_t index = 10; /* Index set after 10th character in source string */
      i18n_parse_position_create_with_index(index, &parse_position);
      
      /* Parses from 10th character to next space character */
      i18n_format_parse_object_with_parse_position(format, source, parse_position, &result);
      i18n_parse_position_destroy(parse_position);
      
      double value = 0;
      i18n_formattable_get_double(result, &value);
      /* Value retrieved is 456.78. If index was 0, result is 1234.56 */
      
  5. When no longer needed, destroy the format object pointer:

    i18n_format_destroy(format);
    

Convert Between Types

You can use the Formattable API (in mobile and wearable applications) to convert between data types.

To manage formattable objects:

  1. To create a formattable handler:

    • Without a specified data type:

      i18n_formattable_h formattable;
      i18n_formattable_create_default(&formattable);
      
    • With a specified data type, for example, double:

      double value = 20;
      i18n_formattable_create_double(value, &formattable);
      

      You can also create handles for udate, long, int64, char pointer, and formattable array.

  2. To clone a formattable object:

    i18n_formattable_h clone;
    i18n_formattable_clone(formattable, &clone);
    
  3. To retrieve formattable object information:

    • To check whether the value in the formattable object is numeric:

      bool is_numeric;
      i18n_formattable_is_numeric(formattable, &is_numeric);
      
    • To get the data type of the value in a formattable object:

      i18n_formattable_type_e type;
      i18n_formattable_get_type(formattable, &type);
      
    • To retrieve the value of the formattable object, use the i18n_formattable_get_xxx() function corresponding to the value’s data type:

      double value;
      i18n_formattable_get_double(formattable, &value);
      
    • To compare whether 2 formattable objects are equal:

      bool equal;
      i18n_formattable_equal(formattable, clone, &equal);
      

      You can also compare whether 2 objects are not equal, using the i18n_formattable_not_equal() function.

  4. To set a formattable object in a formattable array:

    i18n_formattable_h array[3] = {NULL};
    i18n_formattable_h element;
    
    i18n_formattable_create_with_formattable_array(array, 3, &formattable);
    i18n_formattable_create_double(30, &element);
    
    i18n_formattable_element_at(formattable, 0, &element);
    
  5. To set the type of a formattable object, for example, to int64_t:

    int64_t value = 15;
    i18n_formattable_set_int64(formattable, value);
    

    You can also set the type to double, array, udate, long, or string, using the corresponding i18n_formattable_set_xxx() function.

  6. When no longer needed, destroy the formattable object pointer:

    i18n_formattable_destroy(formattable);
    

Manage Measure Objects

Since Tizen 3.0, you can use the Measure API (in mobile and wearable applications) to create measure objects, containing a numerical value and a measurement unit.

Note

A measure object is immutable, so if you want to change its value, you must create a new object with the new value.

To manage measure objects:

  1. To create a measure object:

    i18n_measure_h measure;
    i18n_formattable_h formattable;
    i18n_measure_unit_h unit;
    double value = 7;
    
    i18n_formattable_create_with_double(value, &formattable);
    i18n_measure_unit_create_gigabit(&unit);
    
    i18n_measure_create(formattable, unit, &measure);
    /* Created object contains "7 Gigabits" */
    
  2. To clone a measure object:

    i18n_measure_h clone;
    i18n_measure_clone(measure, &clone);
    
  3. To get the numeric value:

    i18n_formattable_h formattable;
    i18n_measure_get_number(measure, &formattable);
    /* formattable contains 7 as double */
    
  4. To get the measurement unit:

    i18n_measure_unit_h unit;
    i18n_measure_get_unit(measure, &unit);
    /* unit contains Gigabits value */
    
  5. When no longer needed, destroy the measure object:

    i18n_measure_destroy(measure);
    

Manage Measurement Units

You can use the MeasureUnit API (in mobile and wearable applications) to create measure unit objects, which can be passed to the Measure or MeasureFormat (in mobile and wearable applications) APIs.

  1. To create a liter unit object:

    i18n_measure_unit_h unit;
    i18n_measure_unit_create_liter(&unit);
    

    You can create measure unit objects for various units, using the corresponding i18n_measure_unit_create_xxx() functions.

  2. To clone a measure unit object:

    i18n_measure_unit_h clone;
    i18n_measure_unit_clone(unit, &clone);
    
  3. To retrieve information about a measure unit object:

    • To retrieve the unit type:

      char *type;
      i18n_measure_unit_get_type(unit, &type);
      
    • To retrieve the unit subtype:

      char *subtype;
      i18n_measure_unit_get_subtype(unit, &subtype);
      
  4. To retrieve all available units:

    int32_t max = 20;
    i18n_measure_unit_h array[20];
    int32_t available;
    
    i18n_measure_unit_get_available(max, &array, &available);
    
  5. To retrieve the available units for a specific measure:

    int32_t max = 20;
    const char *type = "volume"; /* Specify the measure */
    i18n_measure_unit_h array[20];
    int32_t available;
    
    i18n_measure_unit_get_available_with_type(max, type, &array, &available);
    
  6. To invoke a callback for each available measure unit:

    1. Define the callback function:

      void
      measure_unit_available_types_cb(const char *type_id, void *user_data)
      {
          char *text = (char *)user_data;
          fprintf(stderr, "type_id : %s\n", text);
      
          return false;
      }
      
    2. Invoke the foreach function, using the callback and the data to pass to it as parameters.

      The data passed in the second parameter is used as the user_data parameter in the callback.

      char *data = "data";
      i18n_measure_unit_foreach_available_type(measure_unit_available_types_cb, data);
      
  7. When no longer needed, destroy the measure unit object:

    i18n_measure_unit_destroy(unit);
    

Format Measure Objects

You can format measure objects using the MeasureFormat API (in mobile and wearable applications).

To format measure objects:

  1. To create a format object:

    const char *language = "en";
    const char *country = "US";
    i18n_measure_format_h format;
    i18n_measure_format_create(language, country, I18N_UMEASFMT_WIDTH_WIDE, &measure_format);
    

    Note

    This function is deprecated from Tizen 5.0. Instead, use i18n_measure_format_create_from_locale_id(), which takes the locale ID parameter. To set the language as “en” and country as “US”, use the locale ID “en_US”.

  2. To clone a format object:

    i18n_format_h clone;
    i18n_measure_format_clone(measure_format, &clone);
    
  3. To format an object to produce a string:

    i18n_formattable_h formattable;
    double double_to_set = 13.0;
    i18n_formattable_create_with_double(double_to_set, &formattable);
    
    const char *input = "Price: ";
    int length = strlen(input);
    char *append_to = (char *) malloc (sizeof(input[0]) * (length + 1));
    strncpy(append_to, input, length + 1);
    
    i18n_field_position_h field_position;
    i18n_field_position_create_for_field(0, &field_position);
    i18n_field_position_set_field(field_position, 1);
    
    i18n_measure_format_format(measure_format, formattable, &append_to, field_position);
    
  4. To parse a string to produce an object:

    i18n_formattable_h formattable;
    i18n_parse_position_h parse_position;
    i18n_parse_position_create(&parse_position);
    
    i18n_unumber_format_h num_format;
    i18n_uparse_error_s parse_err;
    i18n_unumber_create(I18N_UNUMBER_NUMBERING_SYSTEM, NULL, -1,
                        I18N_ULOCALE_US, &parse_err, &num_format);
    
    const char *source = "X";
    i18n_measure_format_parse_object(num_format, source, parse_position, &formattable);
    
  5. To retrieve the currency formatter:

    • For a specific locale:

      const char *language = I18N_ULOCALE_KOREAN;
      const char *country = "KR";
      
      i18n_measure_format_create_currency_format_from_locale(language, country, &measure_format);
      

      Note

      This function is deprecated from Tizen 5.0. Instead, use i18n_measure_format_create_currency_format_from_locale_id(), which takes the locale ID parameter. To set the language as “ko” and country as “KR”, use the locale ID “ko_KR”.

    • For the default locale:

      i18n_measure_format_create_currency_format(&measure_format);
      
  6. Since Tizen 4.0, you can:

    • Format an object to produce a string:

      i18n_formattable_h formattable;
      i18n_field_position_h field_position;
      const char *sample_string = "Price: ";
      
      i18n_uchar append_to[BUFSIZE] = {0};
      i18n_ustring_copy_ua_n(append_to, sample_string, BUFSIZE);
      
      const char *language = I18N_ULOCALE_ENGLISH;
      const char *country = "US";
      i18n_measure_format_create_currency_format_from_locale(language, country, &measure_format);
      
      double double_to_set = 13.0;
      i18n_formattable_create_with_double(double_to_set, &formattable);
      
      i18n_field_position_create_for_field(I18N_FIELD_POSITION_DONT_CARE, &field_position);
      
      int output_length = -1;
      i18n_measure_format_format_buff(measure_format, formattable, field_position,
                                      BUFSIZE, append_to, &output_length);
      /* append_to buffer contains "Price: $13.00" string */
      
    • Format a measure object to produce a string:

      i18n_measure_unit_h measure_unit = NULL;
      i18n_measure_unit_create_kilometer(&measure_unit);
      
      double number = 6000;
      i18n_formattable_h formattable = NULL;
      i18n_formattable_create_with_double(number, &formattable);
      
      i18n_measure_h measure;
      i18n_measure_create(formattable, measure_unit, &measure);
      
      int n_measures = 1;
      i18n_field_position_h field_position;
      i18n_uchar append_to[BUFSIZE] = {0};
      
      i18n_field_position_create_for_field(I18N_FIELD_POSITION_DONT_CARE, &field_position);
      
      int output_length = -1;
      i18n_measure_format_format_measures(measure_format, measure, n_measures,
                                          field_position, BUFSIZE, append_to, &output_length);
      /* append_to buffer contains "6,000 kilometers" */
      
    • Format a measure per unit:

      i18n_measure_unit_h measure_unit;
      i18n_measure_unit_h measure_unit_2;
      i18n_measure_unit_create_second(&measure_unit);
      i18n_measure_unit_create_kilometer(&measure_unit_2);
      
      double number = 10;
      i18n_formattable_h formattable = NULL;
      i18n_formattable_create_with_double(number, &formattable);
      
      i18n_measure_h measure = NULL;
      i18n_measure_create(formattable, measure_unit_2, &measure);
      
      i18n_uchar append_to[BUFSIZE] = {0};
      i18n_field_position_h field_position;
      i18n_field_position_create_for_field(I18N_FIELD_POSITION_DONT_CARE, &field_position);
      
      int output_length = -1;
      ret = i18n_measure_format_format_measure_per_unit(measure_format, measure, measure_unit,
                                                        field_position, BUFSIZE, append_to, &output_length);
      /* append_to buffer contains "10 kilometers per second" string */
      
  7. When it is no longer needed, destroy the measure format object:

    i18n_measure_format_destroy(measure_format);
    

Manage the Parse Position

Since Tizen 3.0, you can use the ParsePosition API (in mobile and wearable applications) to track the current position while parsing.

To manage the parse position:

  1. To create a parse position object:

    • Without specifying a position index:

      i18n_parse_position_h parse_position;
      i18n_parse_position_create(&parse_position);
      
    • At a specific position index:

      i18n_parse_position_h parse_position;
      i18n_parse_position_create_with_index(new_text_offset, &parse_position);
      
  2. To clone a parse position pointer:

    i18n_parse_position_h parse_position_clone;
    i18n_parse_position_clone(parse_position, &parse_position_clone);
    
  3. To manage the parse position index:

    • To set the index:

      int32_t parse_position_index = 4;
      i18n_parse_position_set_index(parse_position, parse_position_index);
      
    • To retrieve the index:

      int32_t parse_position_index;
      i18n_parse_position_get_index(parse_position, &parse_position_index);
      
  4. To calculate the parsed length:

    i18n_format_h num_format;
    i18n_uparse_error_s parse_err;
    i18n_unumber_create(I18N_UNUMBER_PERCENT, NULL, -1, I18N_ULOCALE_US, &parse_err, &num_format);
    
    i18n_parse_position_h parse position;
    i18n_parse_position_create_with_index(3, &parse_position);
    
    i18n_formattable_h result;
    char* text_to_parse = "1234567%";
    int32_t begin;
    int32_t end;
    i18n_parse_position_get_index(parse_position, &begin);
    i18n_format_parse_object_with_parse_position(num_format, text_to_parse, parse_position, &result);
    i18n_parse_position_get_index(parse_position, &end);
    
    int length = end - begin;
    
  5. When it is no longer needed, destroy the parse position object:

    i18n_parse_position_destroy(parse_position);
    

Manage Bidirectional Text

Since Tizen 3.0, you can use the Ubidi API (in mobile and wearable applications) to implement the Unicode Bidirectional Algorithm.

To manage bidirectional text:

  1. To create an Ubidi object:

    • To create a default Ubidi object:

      i18n_ubidi_h ubidi;
      i18n_ubidi_create(&ubidi);
      
    • To create a Ubidi object with preallocated memory for internal structures:

      i18n_ubidi_h ubidi;
      int max_length = 100;
      int max_run_count = 100;
      i18n_ubidi_create(max_length, max_run_count, &ubidi);
      
  2. To retrieve the paragraph details:

    int32_t para_start;
    int32_t para_limit;
    i18n_ubidi_level para_level;
    i18n_ubidi_get_paragraph_by_index(ubidi, 2, &para_index, &para_limit, &para_level);
    
  3. To retrieve Ubidi object information:

    • To get the length:

      int32_t length;
      i18n_ubidi_get_length(ubidi, &length);
      
    • To retrieve the number of runs:

      int32_t count;
      i18n_ubidi_count_runs(ubidi, &count);
      
    • To retrieve the text direction:

      i18n_ubidi_direction_e direction;
      i18n_ubidi_get_direction(ubidi, &direction);
      
  4. To reorder the Ubidi string:

    uint16_t options = I18N_UBIDI_OUTPUT_REVERSE;
    int32_t dest_size = 20;
    i18n_uchar dest[dest_size];
    int32_t output_length;
    i18n_ubidi_write_reordered(ubidi, options, dest_size, dest, &output_length);
    
  5. To retrieve the index map:

    • To get the logical-to-visual map:

      int32_t index_map[20];
      i18n_ubidi_get_logical_map(ubidi, index_map);
      
    • To get the visual-to-logical map:

      int32_t index_map[20];
      i18n_ubidi_get_visual_map(ubidi, index_map);
      
  6. When no longer needed, destroy the Ubidi object:

    i18n_ubidi_destroy(ubidi);
    

Shape Arabic Characters

Since Tizen 3.0, you can use the Ushape API (in mobile and wearable applications) to manage Arabic character shapes.

  • To replace all European digits with Extended Arabic-Indic digits:

    const i18n_uchar *source = "...arabic source...";
    uint32_t options = I18N_USHAPE_DIGITS_EN2AN | I18N_USHAPE_DIGIT_TYPE_AN_EXTENDED;
    const int32_t dest_size = 20;
    i18n_uchar dest[dest_size];
    int32_t dest_len;
    i18n_ushape_shape_arabic(source, -1, options, dest_size, dest, &dest_len);
    char buf[50];
    i18n_ustring_copy_au(buf, dest);
    
  • To replace all abstract letters with shaped letters, shape all tashkeel letters into the isolated forms, preserve Arabic Presentation Forms-A and Arabic Presentation Forms-B characters, and replace any combination of U+0651 with one of U+064C, U+064D, U+064E, U+064F, or U+0650 with U+FC5E, U+FC5F, U+FC60, U+FC61, or U+FC62, respectively:

    const i18n_uchar *source = "...arabic source...";
    uint32_t options = I18N_USHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED | I18N_USHAPE_TEXT_DIRECTION_VISUAL_LTR
                       | I18N_USHAPE_PRESERVE_PRESENTATION | I18N_USHAPE_AGGREGATE_TASHKEEL;
    const int32_t dest_size = 20;
    i18n_uchar dest[dest_size];
    int32_t dest_len;
    i18n_ushape_shape_arabic(source, -1, options, dest_size, dest, &dest_len);
    char buf[50];
    i18n_ustring_copy_au(buf, dest);
    

Convert Time Scales

Since Tizen 3.0, you can use the Utmscale API (in mobile and wearable applications) to convert binary datetimes between various platform-dependent time scales.

To convert a datetime value:

  1. To retrieve conversion constants for a specific time scale, use the i18n_utmscale_get_time_scale_value() function with the values of the i18n_utmscale_value_e enumeration (in mobile and wearable applications):

    int64_t value = NULL;
    i18n_utmscale_get_time_scale_value(I18N_UTMSCALE_JAVA_TIME, I18N_UTMSCALE_VALUE_UNITS, &value);
    /* Returns 10000, the number of universal time units (ticks) in each Java time unit (milliseconds) */
    
  2. To convert the retrieved int64_t Java time to universal time scale:

    int64_t universal_time = NULL;
    i18n_utmscale_from_int64(value, I18N_UTMSCALE_ICU4C_TIME, &universal_time);
    
  3. To convert the universal time value back to Java time:

    i18n_utmscale_to_int64(universal_time, I18N_UTMSCALE_JAVA_TIME, &value);
    

Manage Pluralization Rules

Since Tizen 4.0, you can use the PluralRules API (in mobile and wearable applications) to create rules for number-dependent word representations.

To manage plural rules:

  1. Create a plural rules object:

    • Without a rules description:

      i18n_plural_rules_h rules;
      i18n_plural_rules_create(&rules);
      
    • With a rules description as a string:

      i18n_plural_rules_h rules;
      const char *description = "one: n is 1; few: n in 2..4";
      i18n_plural_rules_create_rules_from_descr(description, &rules);
      
  2. To clone a plural rules object:

    i18n_plural_rules_h clone;
    i18n_plural_rules_clone(rules, &clone);
    
  3. To retrieve predefined rules for a specific locale:

    i18n_plural_rules_for_locale("en", "US", I18N_UPLURAL_TYPE_CARDINAL, &rules);
    

    Note

    This function is deprecated from Tizen 5.0. Instead, use i18n_plural_rules_for_locale_id(), which takes the locale ID parameter. To set the language as “en” and country as “US”, use the locale ID “en_US”.

  4. To retrieve the keyword for the first rule that applies to the given number:

    int32_t number = 1;
    i18n_uchar buffer[BUFSIZE] = { 0 };
    
    int output_length = -1;
    i18n_plural_rules_select_int32(rules, number, BUFSIZE, buffer, &length);
    

    You can also retrieve the keyword for a double-type number, using the i18n_plural_rules_select_double() function.

  5. To retrieve keyword information:

    • To retrieve all keywords from the plural rules object:

      i18n_uenumeration_h result = NULL;
      i18n_plural_rules_get_keywords(rules, &result);
      
    • To retrieve sample values for a specific keyword:

      double array[BUFSIZE] = {0};
      const char *keyword = "few";
      int32_t count = 0;
      i18n_plural_rules_get_samples(rules, keyword, array, BUFSIZE, &count);
      
    • To check whether a given keyword is defined in the rules:

      i18n_ubool is_keyword = false;
      const char *keyword = "few";
      i18n_plural_rules_is_keyword(rules, keyword, &is_keyword);
      
    • To retrieve the default keyword:

      i18n_uchar buffer[BUFSIZE] = {0};
      int32_t length = 0;
      i18n_plural_rules_get_keyword_other(rules, BUFSIZE, buffer, &length);
      
  6. When no longer needed, destroy the plural rules object:

    i18n_plural_rules_destroy(rules);
    

Retrieve the ICU Version

Since Tizen 4.0, you can retrieve the current ICU library version by using the Uversion API (in mobile and wearable applications).

To retrieve the current version:

  1. To get the current ICU version, use the i18n_uversion_get_version() function, which returns the version number in a uversion array, in hexadecimal format:

    i18n_uversion_info array;
    i18n_uversion_get_version(array);
    
  2. To convert the version number between hexadecimal and dotted decimal format:

    • To convert the version number from hexadecimal format into a string in dotted decimal format, use the i18n_uversion_to_string() function:
      char *decimal_version;
      i18n_uversion_to_string(array, decimal_version);
      
    • To convert the version number from a string in dotted decimal format to hexadecimal format, use the i18n_uversion_from_string() function:
      char *decimal_version = "57.1";
      i18n_uversion_from_string(decimal_version, version);
      
      If your source string is of the i18n_uchar type, use the i18n_uversion_from_ustring() function instead.

Iterate through Strings

Since Tizen 4.0, you can use UcharIter API (in mobile and wearable applications) to safely iterate through strings:

  1. Create a UCharIter pointer:

    i18n_uchar_iter_h uchar_iter;
    i18n_uchar_iter_create(&uchar_iter);
    
  2. Set up iteration over a string of a specific type:

    • i18n_uchar string:

      i18n_uchar *uchar_string = "UChar test string";
      int32_t ulen = i18n_ustring_get_length(uchar_string);
      i18n_uchar_iter_set_string(uchar_iter, uchar_string, ulen);
      
    • UTF-16BE string:

      i18n_uchar *utf16be_string = "UTF-16BE test string";
      int32_t ulen = i18n_ustring_get_length(utf16be_string);
      i18n_uchar_iter_set_utf16be(uchar_iter, utf16be_string, ulen);
      
    • UTF-8 string:

      i18n_uchar *utf8_string = "UTF-8 test string";
      int32_t ulen = i18n_ustring_get_length(utf8_string);
      i18n_uchar_iter_set_utf16be(uchar_iter, utf8_string, ulen);
      
  3. Retrieve the iterator index:

    • To retrieve the start position:

      int32_t index;
      i18n_uchar_iter_get_index(uchar_iter, I18N_UCHAR_ITER_START, &index);
      
    • To retrieve the current position:

      int32_t index;
      i18n_uchar_iter_get_index(uchar_iter, I18N_UCHAR_ITER_CURRENT, &index);
      
    • To retrieve the string length:

      int32_t index;
      i18n_uchar_iter_get_index(uchar_iter, I18N_UCHAR_ITER_LENGTH, &index);
      
  4. Move the iterator to a desired position:

    • To move to the beginning:

      int32_t delta = 0;
      i18n_uchar_iter_move(uchar_iter, delta, I18N_UCHAR_ITER_START, &index);
      
    • To move to the current position:

      int32_t delta = 0;
      i18n_uchar_iter_move(uchar_iter, delta, I18N_UCHAR_ITER_CURRENT, &index);
      
    • To move to the end of a string:

      int32_t delta = 0;
      i18n_uchar_iter_move(uchar_iter, delta, I18N_UCHAR_ITER_LIMIT, &index);
      
    • To move 3 characters forward from the current position:

      int32_t delta = 3;
      i18n_uchar_iter_move(uchar_iter, delta, I18N_UCHAR_ITER_CURRENT, &index);
      
    • To move 3 characters backward from the end:

      int32_t delta = -3;
      i18n_uchar_iter_move(uchar_iter, delta, I18N_UCHAR_ITER_LIMIT, &index);
      
  5. Check whether it is possible to move:

    • Forward:

      bool has_next;
      i18n_uchar_iter_has_next(uchar_iter, &has_next);
      
    • Backward:

      bool has_previous;
      i18n_uchar_iter_has_previous(uchar_iter, &has_previous);
      
  6. Retrieve code units:

    • To retrieve the code unit from the current position:

      i18n_uchar32 current;
      i18n_uchar_iter_current(uchar_iter, &current);
      
    • To retrieve the previous character from the current position:

      i18n_uchar32 previous;
      i18n_uchar_iter_previous(uchar_iter, &previous);
      
    • To retrieve the next character from the current position:

      i18n_uchar32 next;
      i18n_uchar_iter_next(uchar_iter, &next);
      
  7. Manage states:

    States are iterator positions saved in the int32_t variable. When you need to be able to retrieve a previous position, it is more efficient to store and retrieve states than to use the i18n_uchar_iter_get_index() and i18n_uchar_iter_move() functions.

    • To set a state:

      int32_t state = 4;
      i18n_uchar_iter_set_state(uchar_iter, state);
      
    • To retrieve a state:

      int32_t state;
      i18n_uchar_iter_get_state(uchar_iter, &state);
      
  8. When the iteration is no longer needed, destroy it:

    i18n_uchar_iter_destroy(uchar_iter);
    

Manage Pluralization formatting

From Tizen 5.0, you can use the PluralFormat API (in mobile and wearable applications) to format words for its number-dependent representations.

To manage plural formatting:

  1. Create a PluralFormat object:

    • Without any additional parameters:

      i18n_plural_format_h plural_format;
      i18n_plural_format_create(&plural_format);
      
    • With locale, PluralRules and pattern:

      i18n_plural_rules_h rules;
      ... //create PluralRules object with specified properties
      
      i18n_plural_format_h plural_format;
      const char *pattern = "one{dog} other{dogs}";
      i18n_plural_format_create_from_locale_rules_pattern("en_US", rules, pattern, &plural_format);
      
  2. To clone a PluralFormat object:

    i18n_plural_format_h clone;
    i18n_plural_format_clone(plural_format, &clone);
    
  3. To set new pattern used by formatter:

    const char *new_pattern = "one{cat} other{cats}";
    i18n_plural_format_apply_pattern(plural_rules, new_pattern);
    
  4. To format a plural message:

    • For a given int32 number:

      i18n_uchar output[BUFSIZE] = { 0 };
      i18n_field_position_h field_position;
      i18n_field_position_create_for_field(I18N_FIELD_POSITION_DONT_CARE, &field_position);
      int32_t number = 4;
      int output_length = -1;
      
      i18n_plural_format_format_int32(format, number, field_position,
                                      BUFSIZE, output, &output_length);
      
    • For a given double number:

      i18n_uchar output[BUFSIZE] = { 0 };
      i18n_field_position_h field_position;
      i18n_field_position_create_for_field(I18N_FIELD_POSITION_DONT_CARE, &field_position);
      double number = 4;
      int output_length = -1;
      
      i18n_plural_format_format_double(format, number, field_position,
                                        BUFSIZE, output, &output_length);
      
    • For a given formattable object:

      i18n_uchar output[BUFSIZE] = { 0 };
      i18n_field_position_h field_position;
      int output_length = -1;
      i18n_formattable_h formattable;
      
      i18n_field_position_create_for_field(I18N_FIELD_POSITION_DONT_CARE, &field_position);
      i18n_formattable_create_with_double(4, &formattable);
      
      i18n_plural_format_format_formattable(plural_format, formattable, field_position,
                                            BUFSIZE, output, &output_length);
      
  5. To set the number format which will be used during formatting:

    i18n_unumber_format_h number_format;
    i18n_uparse_error_s parse_err;
    i18n_unumber_create(I18N_UNUMBER_NUMBERING_SYSTEM, NULL, -1,
                          locale, &parse_err, &number_format);
    
    i18n_plural_format_set_number_format(plural_format, number_format);
    
  6. To get a pattern string which is used in formatting:

    i18n_uchar output[BUFSIZE] = { 0 };
    i18n_field_position_h field_position;
    i18n_field_position_create_for_field(I18N_FIELD_POSITION_DONT_CARE, &field_position);
    
    int32_t output_length = -1;
    i18n_plural_format_to_pattern(plural_format, field_position,
                                    BUFSIZE, output, &output_length);
    

Manage Date Intervals

From Tizen 5.0, you can use the DateInterval API (in mobile and wearable applications) and the DateIntervalFormat API (in mobile and wearable applications) to manage and format date intervals.

To manage date interval objects:

  1. Create corresponding object:

    • DateInterval:

      i18n_udate from_date, to_date;
      i18n_date_interval_h interval;
      ...
      i18n_date_interval_create(from_date, to_date, &interval);
      
    • DateIntervalFormat:

      const char *skeleton, *locale;
      i18n_date_interval_fmt_h date_int_fmt_h;
      ...
      i18n_date_interval_fmt_create_from_locale(skeleton, locale, &date_int_fmt);
      
  2. Clone corresponding object:

    • DateInterval:

      i18n_date_interval_h clone;
      i18n_date_interval_clone(interval, &clone);
      
    • DateIntervalFormat:

      i18n_date_interval_fmt_h clone;
      i18n_date_interval_fmt_clone(date_int_fmt, &clone);
      
  3. Format date interval:

    • Using DateInterval object:

      char *append_to;
      i18n_field_position_h field_pos;
      ...
      i18n_date_interval_fmt_format_with_date_interval(date_int_fmt, interval, &append_to, field_pos);
      
    • Using calendar:

      char *append_to;
      i18n_ucalendar_t from, to;
      i18n_field_position_h field_pos;
      ...   // need to initialize calendars and field position object
      i18n_date_interval_fmt_format_with_calendar(date_int_fmt, from, to, &append_to, field_pos);
      
  4. When no longer needed destroy corresponding objects:

    • DateInterval:

      i18n_date_interval_destroy(interval);
      
    • DateIntervalFormat:

      i18n_date_interval_fmt_destroy(date_int_fmt);
      
  • Dependencies
    • Tizen 2.4 and Higher for Mobile
    • Tizen 2.3.1 and Higher for Wearable