• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1---
2layout: default
3title: Message Formatting Examples
4nav_order: 1
5parent: Formatting Messages
6grand_parent: Formatting
7---
8<!--
9© 2020 and later: Unicode, Inc. and others.
10License & terms of use: http://www.unicode.org/copyright.html
11-->
12
13# Message Formatting Examples
14{: .no_toc }
15
16## Contents
17{: .no_toc .text-delta }
18
191. TOC
20{:toc}
21
22---
23
24## `MessageFormat` Class
25
26ICU's `MessageFormat` class can be used to format messages in a locale-independent
27manner to localize the user interface (UI) strings.
28
29### C++
30
31```cpp
32
33/* The strings below can be isolated into a resource bundle
34* and retrieved dynamically
35*/
36#define LANGUAGE_NAMES "{0}<{1}languages {2}>\n"
37#define LANG_ATTRIB   "{0}<language id=\"{1}\" >{2}</language>\n"
38#define MONTH_NAMES "{0}<monthNames>\n"
39#define END_MONTH_NAMES "{0}</monthNames>\n"
40#define MONTH   "{0}<month id=\"{1}\">{2}</month>\n"
41#define MONTH_ABBR "{0}<monthAbbr>\n"
42#define END_MONTH_ABBR "{0}</monthAbbr>\n"
43
44UnicodeString CXMLGenerator::formatString(UnicodeString& str,UnicodeString&
45argument){
46Formattable args[] ={ argument};
47UnicodeString result;
48MessageFormat format(str,mError);
49FieldPosition fpos=0;
50format.format(args,1, result,fpos,mError);
51if(U_FAILURE(mError)) {
52  return UnicodeString("Illegal argument");
53}
54
55return result;
56}
57
58void CXMLGenerator::writeLanguage(UnicodeString& xmlString){
59
60UnicodeString *itemTags, *items;
61char* key="Languages";
62int32_t numItems;
63
64if(U_FAILURE(mError)) {
65  return;
66}
67
68mRBundle.getTaggedArray(key,itemTags, items, numItems, mError);
69if(mError!=U_USING_DEFAULT_ERROR && U_SUCCESS(mError) &&
70mError!=U_ERROR_INFO_START){
71
72  Formattable args[]={indentOffset,"",""};
73  xmlString= formatString(UnicodeString(LANGUAGE_NAMES),args,3);
74  indentOffset.append("\t");
75  for(int32_t i=0;i<numItems;i++){
76
77    args[0] = indentOffset;
78    args[1] =itemTags[i] ;
79    args[2] = items[i] ;
80    xmlString.append(formatString(UnicodeString(LANG_ATTRIB),args,3));
81  }
82
83  chopIndent();
84  args[0]=indentOffset;
85  args[1] =(UnicodeString(XML_END_SLASH));
86  args[2] = "";
87  xmlString.append(formatString(UnicodeString(LANGUAGE_NAMES),args,3));
88
89  return;
90}
91mError=U_ZERO_ERROR;
92xmlString.remove();
93}
94
95
96void CXMLGenerator::writeMonthNames(UnicodeString& xmlString){
97
98int32_t lNum;
99const UnicodeString* longMonths=
100mRBundle.getStringArray("MonthNames",lNum,mError);
101if(mError!=U_USING_DEFAULT_ERROR && mError!=U_ERROR_INFO_START && mError !=
102U_MISSING_RESOURCE_ERROR){
103  xmlString.append(formatString(UnicodeString(MONTH_NAMES),indentOffset));
104  indentOffset.append("\t");
105  for(int i=0;i<lNum;i++){
106   char c;
107   itoa(i+1,&c,10);
108   Formattable args[]={indentOffset,UnicodeString(&c),longMonths[i]};
109   xmlString.append(formatString(UnicodeString(MONTH),args,3));
110  }
111  chopIndent();
112  xmlString.append(formatString(UnicodeString(END_MONTH_NAMES),indentOffset));
113  mError=U_ZERO_ERROR;
114  return;
115}
116xmlString.remove();
117mError= U_ZERO_ERROR;
118}
119```
120
121### C
122
123```c
124
125void msgSample1(){
126
127    UChar *result, *tzID, *str;
128    UChar pattern[100];
129    int32_t resultLengthOut, resultlength;
130    UCalendar *cal;
131    UDate d1;
132    UErrorCode status = U_ZERO_ERROR;
133    str=(UChar*)malloc(sizeof(UChar) * (strlen("disturbance in force") +1));
134    u_uastrcpy(str, "disturbance in force");
135    tzID=(UChar*)malloc(sizeof(UChar) * 4);
136     u_uastrcpy(tzID, "PST");
137     cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
138     ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
139     d1=ucal_getMillis(cal, &status);
140     u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet
141{2,number,integer}");
142     resultlength=0;
143     resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern),
144NULL,
145resultlength, &status, d1, str, 7);
146     if(status==U_BUFFER_OVERFLOW_ERROR){
147         status=U_ZERO_ERROR;
148         resultlength=resultLengthOut+1;
149         result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
150         u_formatMessage( "en_US", pattern, u_strlen(pattern), result,
151resultlength, &status, d1, str, 7);
152     }
153     printf("%s\n",austrdup(result) ); //austrdup( a function used to convert
154UChar* to char*)
155     free(tzID);
156     free(str);
157     free(result);
158}
159
160char *austrdup(const UChar* unichars)
161
162{
163    int   length;
164    char *newString;
165
166    length    = u_strlen ( unichars );
167    newString = (char*)malloc ( sizeof( char ) * 4 * ( length + 1 ) );
168    if ( newString == NULL )
169        return NULL;
170
171    u_austrcpy ( newString, unichars );
172
173    return newString;
174}
175
176This is a more practical sample which retrieves data from a resource bundle
177and
178feeds the data
179to u_formatMessage to produce a formatted string
180
181void msgSample3(){
182
183char* key="Languages";
184int32_t numItems;
185    /* This constant string can also be in the resouce bundle and retrieved at
186the time
187     * of formatting
188     * eg:
189     * UResouceBundle* myResB = ures_open("myResources",currentLocale,&err);
190     * UChar* Lang_Attrib = ures_getString(myResb,"LANG_ATTRIB",&err);
191     */
192    UChar* LANG_ATTRIB   =(UChar*) "{0}<language id=\"{1}\"
193>{2}</language>\n";
194    UChar *result;
195    UResourceBundle* pResB,*pDeltaResB=NULL;
196    UErrorCode err=U_ZERO_ERROR;
197    UChar* indentOffset = (UChar*)"\t\t\t";
198    pResB = ures_open("","en",&err);
199if(U_FAILURE(err)) {
200  return;
201}
202
203    ures_getByKey(pResB, key, pDeltaResB, &err);
204
205    if(U_SUCCESS(err)) {
206        const UChar *value = 0;
207        const char *key = 0;
208        int32_t len = 0;
209        int16_t indexR = -1;
210        int32_t resultLength=0,resultLengthOut=0;
211        numItems = ures_getSize(pDeltaResB);
212        for(;numItems-->0;){
213            key= ures_getKey(pDeltaResB);
214            value = ures_get(pDeltaResB,key,&err);
215            resultLength=0;
216            resultLengthOut=u_formatMessage( "en_US", LANG_ATTRIB,
217u_strlen(LANG_ATTRIB),
218                                                NULL, resultLength, &err,
219indentOffset, value, key);
220            if(err==U_BUFFER_OVERFLOW_ERROR){
221                 err=U_ZERO_ERROR;
222                 resultLength=resultLengthOut+1;
223                 result=(UChar*)realloc(result, sizeof(UChar) * resultLength);
224                 u_formatMessage("en_US",LANG_ATTRIB,u_strlen(LANG_ATTRIB),
225                                result,resultLength,&err,indentOffset,
226                                value,key);
227
228                 printf("%s\n", austrdup(result) );
229            }
230
231        }
232
233  return;
234
235}
236err=U_ZERO_ERROR;
237}
238```
239
240### Java
241
242```java
243import com.ibm.icu.text.*;
244import java.util.Date;
245import java.text.FieldPosition;
246
247public class TestMessageFormat{
248    public void runTest() {
249        String format = "At {1,time,::jmm} on {1,date,::dMMMM}, there was {2} on planet {3,number,integer}.";
250        MessageFormat mf = new MessageFormat(format);
251        Object objectsToFormat[] = { new Date(System.currentTimeMillis()), new Date(System.currentTimeMillis()), "a Disturbance in the Force", new Integer(5)};
252        FieldPosition fp = new FieldPosition(1);
253        StringBuffer sb = new StringBuffer();
254        try{
255            sb = mf.format(objectsToFormat, sb, fp);
256            System.out.println(sb.toString());
257        }catch(IllegalArgumentException e){
258            System.out.println("Exception during formatting of type :" +e);
259        }
260    }
261
262    public static void main(String args[]){
263        try{
264            new TestMessageFormat().runTest();
265        }catch(Exception e){
266            System.out.println("Exception of type: "+e);
267        }
268    }
269}
270```
271
272## `ChoiceFormat` Class
273
274**Important:** The following documentation is outdated. *`ChoiceFormat` is
275probably not what you need. Please use `MessageFormat` with plural arguments for
276proper plural selection, and select arguments for simple selection among a fixed
277set of choices!*
278
279ICU's `ChoiceFormat` class provides more flexibility than the `printf()` and `scanf()`
280style functions for formatting UI strings. This interface can be useful if you
281would like a message to change according to the number of items you are
282displaying.
283
284Note: Some Asian languages do not have plural words or phrases.
285
286### C++
287
288```cpp
289void msgSample1(){
290
291    UChar *result, *tzID, *str;
292    UChar pattern[100];
293    int32_t resultLengthOut, resultlength;
294    UCalendar *cal;
295    UDate d1;
296    UErrorCode status = U_ZERO_ERROR;
297    str=(UChar*)malloc(sizeof(UChar) * (strlen("disturbance in force") +1));
298    u_uastrcpy(str, "disturbance in force");
299    tzID=(UChar*)malloc(sizeof(UChar) * 4);
300     u_uastrcpy(tzID, "PST");
301     cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
302     ucal_setDateTime(cal, 1999, UCAL_MARCH, 18, 0, 0, 0, &status);
303     d1=ucal_getMillis(cal, &status);
304     u_uastrcpy(pattern, "On {0, date, long}, there was a {1} on planet
305
306{2,number,integer}");
307     resultlength=0;
308     resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern),
309NULL,
310resultlength, &status, d1, str, 7);
311     if(status==U_BUFFER_OVERFLOW_ERROR){
312         status=U_ZERO_ERROR;
313         resultlength=resultLengthOut+1;
314         result=(UChar*)realloc(result, sizeof(UChar) * resultlength);
315         u_formatMessage( "en_US", pattern, u_strlen(pattern), result,
316resultlength, &status, d1, str, 7);
317     }
318     printf("%s\n",austrdup(result) ); //austrdup( a function used to convert
319UChar* to char*)
320     free(tzID);
321     free(str);
322double filelimits[] = {0,1,2};
323UErrorCode err;
324UnicodeString filepart[] = {"are no files","is one file","are {2} files"};
325ChoiceFormat fileform(filelimits, filepart,err);
326Format testFormats[] = {fileform, null, NumberFormat.getInstance()};
327MessageFormat pattform("There {0} on {1}",err);
328pattform.setFormats(testFormats);
329Formattable testArgs[] = {null, "ADisk", null};
330for (int i = 0; i < 4; ++i) {
331     testArgs[0] = i;
332     testArgs[2] = testArgs[0];
333     FieldPosition fpos=0;
334     format.format(args,1, result,fpos,mError);
335     UnicodeString result = pattform.format(testArgs);
336}
337```
338
339### C
340
341```c
342void msgSample2(){
343     UChar* str;
344     UErrorCode status = U_ZERO_ERROR;
345     UChar *result;
346     UChar pattern[100];
347     int32_t resultlength,resultLengthOut, i;
348     double testArgs[3]= { 100.0, 1.0, 0.0};
349     str=(UChar*)malloc(sizeof(UChar) * 10);
350     u_uastrcpy(str, "MyDisk");
351     u_uastrcpy(pattern, "The disk {1} contains {0,choice,0#no files|1#one
352file|1<{0,number,integer} files}");
353     for(i=0; i<3; i++){
354         resultlength=0;
355         resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern),
356NULL, resultlength, &status, testArgs[i], str);
357         if(status==U_BUFFER_OVERFLOW_ERROR){
358             status=U_ZERO_ERROR;
359             resultlength=resultLengthOut+1;
360             result=(UChar*)malloc(sizeof(UChar) * resultlength);
361             u_formatMessage( "en_US", pattern, u_strlen(pattern), result,
362resultlength, &status, testArgs[i], str);
363         }
364     }
365     printf("%s\n", austrdup(result) ); //austrdup( a function used to
366convert
367UChar* to char*)
368     free(result);
369
370}
371```
372
373### Java
374
375```java
376import java.text.ChoiceFormat;
377import com.ibm.icu.text.*;
378import java.text.Format;
379
380public class TestChoiceFormat{
381    public void run(){
382        double[] filelimits = {0,1,2};
383        String[] filepart = {"are no files","is one file","are {2} files"};
384        ChoiceFormat fileform = new ChoiceFormat(filelimits,filepart);
385        Format[] testFormats = {fileform,null,NumberFormat.getInstance()};
386        MessageFormat pattform = new MessageFormat("There {0} on {1}");
387        Object[] testArgs = {null,"ADisk",null};
388        for(int i=0;i<4;++i) {
389            testArgs[0] = new Integer(i);
390            testArgs[2] = testArgs[0];
391            System.out.println(pattform.format(testArgs));
392        }
393    }
394
395    public static void main(String args[]){
396        new TestChoiceFormat().run();
397    }
398}
399```
400