1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2007-2014, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ******************************************************************************* 8 * 9 10 * File PLURFMT.H 11 ******************************************************************************** 12 */ 13 14 #ifndef PLURFMT 15 #define PLURFMT 16 17 #include "unicode/utypes.h" 18 19 /** 20 * \file 21 * \brief C++ API: PluralFormat object 22 */ 23 24 #if !UCONFIG_NO_FORMATTING 25 26 #include "unicode/messagepattern.h" 27 #include "unicode/numfmt.h" 28 #include "unicode/plurrule.h" 29 30 U_NAMESPACE_BEGIN 31 32 class Hashtable; 33 class NFRule; 34 35 /** 36 * <p> 37 * <code>PluralFormat</code> supports the creation of internationalized 38 * messages with plural inflection. It is based on <i>plural 39 * selection</i>, i.e. the caller specifies messages for each 40 * plural case that can appear in the user's language and the 41 * <code>PluralFormat</code> selects the appropriate message based on 42 * the number. 43 * </p> 44 * <h4>The Problem of Plural Forms in Internationalized Messages</h4> 45 * <p> 46 * Different languages have different ways to inflect 47 * plurals. Creating internationalized messages that include plural 48 * forms is only feasible when the framework is able to handle plural 49 * forms of <i>all</i> languages correctly. <code>ChoiceFormat</code> 50 * doesn't handle this well, because it attaches a number interval to 51 * each message and selects the message whose interval contains a 52 * given number. This can only handle a finite number of 53 * intervals. But in some languages, like Polish, one plural case 54 * applies to infinitely many intervals (e.g., the plural case applies to 55 * numbers ending with 2, 3, or 4 except those ending with 12, 13, or 56 * 14). Thus <code>ChoiceFormat</code> is not adequate. 57 * </p><p> 58 * <code>PluralFormat</code> deals with this by breaking the problem 59 * into two parts: 60 * <ul> 61 * <li>It uses <code>PluralRules</code> that can define more complex 62 * conditions for a plural case than just a single interval. These plural 63 * rules define both what plural cases exist in a language, and to 64 * which numbers these cases apply. 65 * <li>It provides predefined plural rules for many languages. Thus, the programmer 66 * need not worry about the plural cases of a language and 67 * does not have to define the plural cases; they can simply 68 * use the predefined keywords. The whole plural formatting of messages can 69 * be done using localized patterns from resource bundles. For predefined plural 70 * rules, see the CLDR <i>Language Plural Rules</i> page at 71 * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html 72 * </ul> 73 * </p> 74 * <h4>Usage of <code>PluralFormat</code></h4> 75 * <p>Note: Typically, plural formatting is done via <code>MessageFormat</code> 76 * with a <code>plural</code> argument type, 77 * rather than using a stand-alone <code>PluralFormat</code>. 78 * </p><p> 79 * This discussion assumes that you use <code>PluralFormat</code> with 80 * a predefined set of plural rules. You can create one using one of 81 * the constructors that takes a <code>locale</code> object. To 82 * specify the message pattern, you can either pass it to the 83 * constructor or set it explicitly using the 84 * <code>applyPattern()</code> method. The <code>format()</code> 85 * method takes a number object and selects the message of the 86 * matching plural case. This message will be returned. 87 * </p> 88 * <h5>Patterns and Their Interpretation</h5> 89 * <p> 90 * The pattern text defines the message output for each plural case of the 91 * specified locale. Syntax: 92 * <pre> 93 * pluralStyle = [offsetValue] (selector '{' message '}')+ 94 * offsetValue = "offset:" number 95 * selector = explicitValue | keyword 96 * explicitValue = '=' number // adjacent, no white space in between 97 * keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+ 98 * message: see {@link MessageFormat} 99 * </pre> 100 * Pattern_White_Space between syntax elements is ignored, except 101 * between the {curly braces} and their sub-message, 102 * and between the '=' and the number of an explicitValue. 103 * 104 * </p><p> 105 * There are 6 predefined casekeyword in CLDR/ICU - 'zero', 'one', 'two', 'few', 'many' and 106 * 'other'. You always have to define a message text for the default plural case 107 * <code>other</code> which is contained in every rule set. 108 * If you do not specify a message text for a particular plural case, the 109 * message text of the plural case <code>other</code> gets assigned to this 110 * plural case. 111 * </p><p> 112 * When formatting, the input number is first matched against the explicitValue clauses. 113 * If there is no exact-number match, then a keyword is selected by calling 114 * the <code>PluralRules</code> with the input number <em>minus the offset</em>. 115 * (The offset defaults to 0 if it is omitted from the pattern string.) 116 * If there is no clause with that keyword, then the "other" clauses is returned. 117 * </p><p> 118 * An unquoted pound sign (<code>#</code>) in the selected sub-message 119 * itself (i.e., outside of arguments nested in the sub-message) 120 * is replaced by the input number minus the offset. 121 * The number-minus-offset value is formatted using a 122 * <code>NumberFormat</code> for the <code>PluralFormat</code>'s locale. If you 123 * need special number formatting, you have to use a <code>MessageFormat</code> 124 * and explicitly specify a <code>NumberFormat</code> argument. 125 * <strong>Note:</strong> That argument is formatting without subtracting the offset! 126 * If you need a custom format and have a non-zero offset, then you need to pass the 127 * number-minus-offset value as a separate parameter. 128 * </p> 129 * For a usage example, see the {@link MessageFormat} class documentation. 130 * 131 * <h4>Defining Custom Plural Rules</h4> 132 * <p>If you need to use <code>PluralFormat</code> with custom rules, you can 133 * create a <code>PluralRules</code> object and pass it to 134 * <code>PluralFormat</code>'s constructor. If you also specify a locale in this 135 * constructor, this locale will be used to format the number in the message 136 * texts. 137 * </p><p> 138 * For more information about <code>PluralRules</code>, see 139 * {@link PluralRules}. 140 * </p> 141 * 142 * ported from Java 143 * @stable ICU 4.0 144 */ 145 146 class U_I18N_API PluralFormat : public Format { 147 public: 148 149 /** 150 * Creates a new cardinal-number <code>PluralFormat</code> for the default locale. 151 * This locale will be used to get the set of plural rules and for standard 152 * number formatting. 153 * @param status output param set to success/failure code on exit, which 154 * must not indicate a failure before the function call. 155 * @stable ICU 4.0 156 */ 157 PluralFormat(UErrorCode& status); 158 159 /** 160 * Creates a new cardinal-number <code>PluralFormat</code> for a given locale. 161 * @param locale the <code>PluralFormat</code> will be configured with 162 * rules for this locale. This locale will also be used for 163 * standard number formatting. 164 * @param status output param set to success/failure code on exit, which 165 * must not indicate a failure before the function call. 166 * @stable ICU 4.0 167 */ 168 PluralFormat(const Locale& locale, UErrorCode& status); 169 170 /** 171 * Creates a new <code>PluralFormat</code> for a given set of rules. 172 * The standard number formatting will be done using the default locale. 173 * @param rules defines the behavior of the <code>PluralFormat</code> 174 * object. 175 * @param status output param set to success/failure code on exit, which 176 * must not indicate a failure before the function call. 177 * @stable ICU 4.0 178 */ 179 PluralFormat(const PluralRules& rules, UErrorCode& status); 180 181 /** 182 * Creates a new <code>PluralFormat</code> for a given set of rules. 183 * The standard number formatting will be done using the given locale. 184 * @param locale the default number formatting will be done using this 185 * locale. 186 * @param rules defines the behavior of the <code>PluralFormat</code> 187 * object. 188 * @param status output param set to success/failure code on exit, which 189 * must not indicate a failure before the function call. 190 * @stable ICU 4.0 191 * <p> 192 * <h4>Sample code</h4> 193 * \snippet samples/plurfmtsample/plurfmtsample.cpp PluralFormatExample1 194 * \snippet samples/plurfmtsample/plurfmtsample.cpp PluralFormatExample 195 * <p> 196 */ 197 PluralFormat(const Locale& locale, const PluralRules& rules, UErrorCode& status); 198 199 /** 200 * Creates a new <code>PluralFormat</code> for the plural type. 201 * The standard number formatting will be done using the given locale. 202 * @param locale the default number formatting will be done using this 203 * locale. 204 * @param type The plural type (e.g., cardinal or ordinal). 205 * @param status output param set to success/failure code on exit, which 206 * must not indicate a failure before the function call. 207 * @stable ICU 50 208 */ 209 PluralFormat(const Locale& locale, UPluralType type, UErrorCode& status); 210 211 /** 212 * Creates a new cardinal-number <code>PluralFormat</code> for a given pattern string. 213 * The default locale will be used to get the set of plural rules and for 214 * standard number formatting. 215 * @param pattern the pattern for this <code>PluralFormat</code>. 216 * errors are returned to status if the pattern is invalid. 217 * @param status output param set to success/failure code on exit, which 218 * must not indicate a failure before the function call. 219 * @stable ICU 4.0 220 */ 221 PluralFormat(const UnicodeString& pattern, UErrorCode& status); 222 223 /** 224 * Creates a new cardinal-number <code>PluralFormat</code> for a given pattern string and 225 * locale. 226 * The locale will be used to get the set of plural rules and for 227 * standard number formatting. 228 * @param locale the <code>PluralFormat</code> will be configured with 229 * rules for this locale. This locale will also be used for 230 * standard number formatting. 231 * @param pattern the pattern for this <code>PluralFormat</code>. 232 * errors are returned to status if the pattern is invalid. 233 * @param status output param set to success/failure code on exit, which 234 * must not indicate a failure before the function call. 235 * @stable ICU 4.0 236 */ 237 PluralFormat(const Locale& locale, const UnicodeString& pattern, UErrorCode& status); 238 239 /** 240 * Creates a new <code>PluralFormat</code> for a given set of rules, a 241 * pattern and a locale. 242 * @param rules defines the behavior of the <code>PluralFormat</code> 243 * object. 244 * @param pattern the pattern for this <code>PluralFormat</code>. 245 * errors are returned to status if the pattern is invalid. 246 * @param status output param set to success/failure code on exit, which 247 * must not indicate a failure before the function call. 248 * @stable ICU 4.0 249 */ 250 PluralFormat(const PluralRules& rules, 251 const UnicodeString& pattern, 252 UErrorCode& status); 253 254 /** 255 * Creates a new <code>PluralFormat</code> for a given set of rules, a 256 * pattern and a locale. 257 * @param locale the <code>PluralFormat</code> will be configured with 258 * rules for this locale. This locale will also be used for 259 * standard number formatting. 260 * @param rules defines the behavior of the <code>PluralFormat</code> 261 * object. 262 * @param pattern the pattern for this <code>PluralFormat</code>. 263 * errors are returned to status if the pattern is invalid. 264 * @param status output param set to success/failure code on exit, which 265 * must not indicate a failure before the function call. 266 * @stable ICU 4.0 267 */ 268 PluralFormat(const Locale& locale, 269 const PluralRules& rules, 270 const UnicodeString& pattern, 271 UErrorCode& status); 272 273 /** 274 * Creates a new <code>PluralFormat</code> for a plural type, a 275 * pattern and a locale. 276 * @param locale the <code>PluralFormat</code> will be configured with 277 * rules for this locale. This locale will also be used for 278 * standard number formatting. 279 * @param type The plural type (e.g., cardinal or ordinal). 280 * @param pattern the pattern for this <code>PluralFormat</code>. 281 * errors are returned to status if the pattern is invalid. 282 * @param status output param set to success/failure code on exit, which 283 * must not indicate a failure before the function call. 284 * @stable ICU 50 285 */ 286 PluralFormat(const Locale& locale, 287 UPluralType type, 288 const UnicodeString& pattern, 289 UErrorCode& status); 290 291 /** 292 * copy constructor. 293 * @stable ICU 4.0 294 */ 295 PluralFormat(const PluralFormat& other); 296 297 /** 298 * Destructor. 299 * @stable ICU 4.0 300 */ 301 virtual ~PluralFormat(); 302 303 /** 304 * Sets the pattern used by this plural format. 305 * The method parses the pattern and creates a map of format strings 306 * for the plural rules. 307 * Patterns and their interpretation are specified in the class description. 308 * 309 * @param pattern the pattern for this plural format 310 * errors are returned to status if the pattern is invalid. 311 * @param status output param set to success/failure code on exit, which 312 * must not indicate a failure before the function call. 313 * @stable ICU 4.0 314 */ 315 void applyPattern(const UnicodeString& pattern, UErrorCode& status); 316 317 318 using Format::format; 319 320 /** 321 * Formats a plural message for a given number. 322 * 323 * @param number a number for which the plural message should be formatted 324 * for. If no pattern has been applied to this 325 * <code>PluralFormat</code> object yet, the formatted number 326 * will be returned. 327 * @param status output param set to success/failure code on exit, which 328 * must not indicate a failure before the function call. 329 * @return the string containing the formatted plural message. 330 * @stable ICU 4.0 331 */ 332 UnicodeString format(int32_t number, UErrorCode& status) const; 333 334 /** 335 * Formats a plural message for a given number. 336 * 337 * @param number a number for which the plural message should be formatted 338 * for. If no pattern has been applied to this 339 * PluralFormat object yet, the formatted number 340 * will be returned. 341 * @param status output param set to success or failure code on exit, which 342 * must not indicate a failure before the function call. 343 * @return the string containing the formatted plural message. 344 * @stable ICU 4.0 345 */ 346 UnicodeString format(double number, UErrorCode& status) const; 347 348 /** 349 * Formats a plural message for a given number. 350 * 351 * @param number a number for which the plural message should be formatted 352 * for. If no pattern has been applied to this 353 * <code>PluralFormat</code> object yet, the formatted number 354 * will be returned. 355 * @param appendTo output parameter to receive result. 356 * result is appended to existing contents. 357 * @param pos On input: an alignment field, if desired. 358 * On output: the offsets of the alignment field. 359 * @param status output param set to success/failure code on exit, which 360 * must not indicate a failure before the function call. 361 * @return the string containing the formatted plural message. 362 * @stable ICU 4.0 363 */ 364 UnicodeString& format(int32_t number, 365 UnicodeString& appendTo, 366 FieldPosition& pos, 367 UErrorCode& status) const; 368 369 /** 370 * Formats a plural message for a given number. 371 * 372 * @param number a number for which the plural message should be formatted 373 * for. If no pattern has been applied to this 374 * PluralFormat object yet, the formatted number 375 * will be returned. 376 * @param appendTo output parameter to receive result. 377 * result is appended to existing contents. 378 * @param pos On input: an alignment field, if desired. 379 * On output: the offsets of the alignment field. 380 * @param status output param set to success/failure code on exit, which 381 * must not indicate a failure before the function call. 382 * @return the string containing the formatted plural message. 383 * @stable ICU 4.0 384 */ 385 UnicodeString& format(double number, 386 UnicodeString& appendTo, 387 FieldPosition& pos, 388 UErrorCode& status) const; 389 390 #ifndef U_HIDE_DEPRECATED_API 391 /** 392 * Sets the locale used by this <code>PluraFormat</code> object. 393 * Note: Calling this method resets this <code>PluraFormat</code> object, 394 * i.e., a pattern that was applied previously will be removed, 395 * and the NumberFormat is set to the default number format for 396 * the locale. The resulting format behaves the same as one 397 * constructed from {@link #PluralFormat(const Locale& locale, UPluralType type, UErrorCode& status)} 398 * with UPLURAL_TYPE_CARDINAL. 399 * @param locale the <code>locale</code> to use to configure the formatter. 400 * @param status output param set to success/failure code on exit, which 401 * must not indicate a failure before the function call. 402 * @deprecated ICU 50 This method clears the pattern and might create 403 * a different kind of PluralRules instance; 404 * use one of the constructors to create a new instance instead. 405 */ 406 void setLocale(const Locale& locale, UErrorCode& status); 407 #endif /* U_HIDE_DEPRECATED_API */ 408 409 /** 410 * Sets the number format used by this formatter. You only need to 411 * call this if you want a different number format than the default 412 * formatter for the locale. 413 * @param format the number format to use. 414 * @param status output param set to success/failure code on exit, which 415 * must not indicate a failure before the function call. 416 * @stable ICU 4.0 417 */ 418 void setNumberFormat(const NumberFormat* format, UErrorCode& status); 419 420 /** 421 * Assignment operator 422 * 423 * @param other the PluralFormat object to copy from. 424 * @stable ICU 4.0 425 */ 426 PluralFormat& operator=(const PluralFormat& other); 427 428 /** 429 * Return true if another object is semantically equal to this one. 430 * 431 * @param other the PluralFormat object to be compared with. 432 * @return true if other is semantically equal to this. 433 * @stable ICU 4.0 434 */ 435 virtual UBool operator==(const Format& other) const; 436 437 /** 438 * Return true if another object is semantically unequal to this one. 439 * 440 * @param other the PluralFormat object to be compared with. 441 * @return true if other is semantically unequal to this. 442 * @stable ICU 4.0 443 */ 444 virtual UBool operator!=(const Format& other) const; 445 446 /** 447 * Clones this Format object polymorphically. The caller owns the 448 * result and should delete it when done. 449 * @stable ICU 4.0 450 */ 451 virtual Format* clone(void) const; 452 453 /** 454 * Formats a plural message for a number taken from a Formattable object. 455 * 456 * @param obj The object containing a number for which the 457 * plural message should be formatted. 458 * The object must be of a numeric type. 459 * @param appendTo output parameter to receive result. 460 * Result is appended to existing contents. 461 * @param pos On input: an alignment field, if desired. 462 * On output: the offsets of the alignment field. 463 * @param status output param filled with success/failure status. 464 * @return Reference to 'appendTo' parameter. 465 * @stable ICU 4.0 466 */ 467 UnicodeString& format(const Formattable& obj, 468 UnicodeString& appendTo, 469 FieldPosition& pos, 470 UErrorCode& status) const; 471 472 /** 473 * Returns the pattern from applyPattern() or constructor(). 474 * 475 * @param appendTo output parameter to receive result. 476 * Result is appended to existing contents. 477 * @return the UnicodeString with inserted pattern. 478 * @stable ICU 4.0 479 */ 480 UnicodeString& toPattern(UnicodeString& appendTo); 481 482 /** 483 * This method is not yet supported by <code>PluralFormat</code>. 484 * <P> 485 * Before calling, set parse_pos.index to the offset you want to start 486 * parsing at in the source. After calling, parse_pos.index is the end of 487 * the text you parsed. If error occurs, index is unchanged. 488 * <P> 489 * When parsing, leading whitespace is discarded (with a successful parse), 490 * while trailing whitespace is left as is. 491 * <P> 492 * See Format::parseObject() for more. 493 * 494 * @param source The string to be parsed into an object. 495 * @param result Formattable to be set to the parse result. 496 * If parse fails, return contents are undefined. 497 * @param parse_pos The position to start parsing at. Upon return 498 * this param is set to the position after the 499 * last character successfully parsed. If the 500 * source is not parsed successfully, this param 501 * will remain unchanged. 502 * @stable ICU 4.0 503 */ 504 virtual void parseObject(const UnicodeString& source, 505 Formattable& result, 506 ParsePosition& parse_pos) const; 507 508 /** 509 * ICU "poor man's RTTI", returns a UClassID for this class. 510 * 511 * @stable ICU 4.0 512 * 513 */ 514 static UClassID U_EXPORT2 getStaticClassID(void); 515 516 /** 517 * ICU "poor man's RTTI", returns a UClassID for the actual class. 518 * 519 * @stable ICU 4.0 520 */ 521 virtual UClassID getDynamicClassID() const; 522 523 private: 524 /** 525 * @internal 526 */ 527 class U_I18N_API PluralSelector : public UMemory { 528 public: 529 virtual ~PluralSelector(); 530 /** 531 * Given a number, returns the appropriate PluralFormat keyword. 532 * 533 * @param context worker object for the selector. 534 * @param number The number to be plural-formatted. 535 * @param ec Error code. 536 * @return The selected PluralFormat keyword. 537 * @internal 538 */ 539 virtual UnicodeString select(void *context, double number, UErrorCode& ec) const = 0; 540 }; 541 542 /** 543 * @internal 544 */ 545 class U_I18N_API PluralSelectorAdapter : public PluralSelector { 546 public: PluralSelectorAdapter()547 PluralSelectorAdapter() : pluralRules(NULL) { 548 } 549 550 virtual ~PluralSelectorAdapter(); 551 552 virtual UnicodeString select(void *context, double number, UErrorCode& /*ec*/) const; /**< @internal */ 553 554 void reset(); 555 556 PluralRules* pluralRules; 557 }; 558 559 Locale locale; 560 MessagePattern msgPattern; 561 NumberFormat* numberFormat; 562 double offset; 563 PluralSelectorAdapter pluralRulesWrapper; 564 565 PluralFormat(); // default constructor not implemented 566 void init(const PluralRules* rules, UPluralType type, UErrorCode& status); 567 /** 568 * Copies dynamically allocated values (pointer fields). 569 * Others are copied using their copy constructors and assignment operators. 570 */ 571 void copyObjects(const PluralFormat& other); 572 573 UnicodeString& format(const Formattable& numberObject, double number, 574 UnicodeString& appendTo, 575 FieldPosition& pos, 576 UErrorCode& status) const; /**< @internal */ 577 578 /** 579 * Finds the PluralFormat sub-message for the given number, or the "other" sub-message. 580 * @param pattern A MessagePattern. 581 * @param partIndex the index of the first PluralFormat argument style part. 582 * @param selector the PluralSelector for mapping the number (minus offset) to a keyword. 583 * @param context worker object for the selector. 584 * @param number a number to be matched to one of the PluralFormat argument's explicit values, 585 * or mapped via the PluralSelector. 586 * @param ec ICU error code. 587 * @return the sub-message start part index. 588 */ 589 static int32_t findSubMessage( 590 const MessagePattern& pattern, int32_t partIndex, 591 const PluralSelector& selector, void *context, double number, UErrorCode& ec); /**< @internal */ 592 593 void parseType(const UnicodeString& source, const NFRule *rbnfLenientScanner, 594 Formattable& result, FieldPosition& pos) const; 595 596 friend class MessageFormat; 597 friend class NFRule; 598 }; 599 600 U_NAMESPACE_END 601 602 #endif /* #if !UCONFIG_NO_FORMATTING */ 603 604 #endif // _PLURFMT 605 //eof 606