plurfmt.h 25 KB

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