Home | History | Annotate | Download | only in unicode
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2011, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  * Copyright (C) 2010 , Yahoo! Inc.
      6  ********************************************************************
      7  *
      8  * File SELFMT.H
      9  *
     10  * Modification History:
     11  *
     12  *   Date        Name        Description
     13  *   11/11/09    kirtig      Finished first cut of implementation.
     14  ********************************************************************/
     15 
     16 #ifndef SELFMT
     17 #define SELFMT
     18 
     19 #include "unicode/messagepattern.h"
     20 #include "unicode/numfmt.h"
     21 #include "unicode/utypes.h"
     22 
     23 /**
     24  * \file
     25  * \brief C++ API: SelectFormat object
     26  */
     27 
     28 #if !UCONFIG_NO_FORMATTING
     29 
     30 U_NAMESPACE_BEGIN
     31 
     32 class MessageFormat;
     33 
     34 /**
     35   * <p><code>SelectFormat</code> supports the creation of  internationalized
     36   * messages by selecting phrases based on keywords. The pattern  specifies
     37   * how to map keywords to phrases and provides a default phrase. The
     38   * object provided to the format method is a string that's matched
     39   * against the keywords. If there is a match, the corresponding phrase
     40   * is selected; otherwise, the default phrase is used.</p>
     41   *
     42   * <h4>Using <code>SelectFormat</code> for Gender Agreement</h4>
     43   *
     44   * <p>Note: Typically, select formatting is done via <code>MessageFormat</code>
     45   * with a <code>select</code> argument type,
     46   * rather than using a stand-alone <code>SelectFormat</code>.</p>
     47   *
     48   * <p>The main use case for the select format is gender based  inflection.
     49   * When names or nouns are inserted into sentences, their gender can  affect pronouns,
     50   * verb forms, articles, and adjectives. Special care needs to be
     51   * taken for the case where the gender cannot be determined.
     52   * The impact varies between languages:</p>
     53   * \htmlonly
     54   * <ul>
     55   * <li>English has three genders, and unknown gender is handled as a  special
     56   * case. Names use the gender of the named person (if known), nouns  referring
     57   * to people use natural gender, and inanimate objects are usually  neutral.
     58   * The gender only affects pronouns: "he", "she", "it", "they".
     59   *
     60   * <li>German differs from English in that the gender of nouns is  rather
     61   * arbitrary, even for nouns referring to people ("M&#x00E4;dchen", girl, is  neutral).
     62   * The gender affects pronouns ("er", "sie", "es"), articles ("der",  "die",
     63   * "das"), and adjective forms ("guter Mann", "gute Frau", "gutes  M&#x00E4;dchen").
     64   *
     65   * <li>French has only two genders; as in German the gender of nouns
     66   * is rather arbitrary - for sun and moon, the genders
     67   * are the opposite of those in German. The gender affects
     68   * pronouns ("il", "elle"), articles ("le", "la"),
     69   * adjective forms ("bon", "bonne"), and sometimes
     70   * verb forms ("all&#x00E9;", "all&#x00E9;e").
     71   *
     72   * <li>Polish distinguishes five genders (or noun classes),
     73   * human masculine, animate non-human masculine, inanimate masculine,
     74   * feminine, and neuter.
     75   * </ul>
     76   * \endhtmlonly
     77   * <p>Some other languages have noun classes that are not related to  gender,
     78   * but similar in grammatical use.
     79   * Some African languages have around 20 noun classes.</p>
     80   *
     81   * <p><b>Note:</b>For the gender of a <i>person</i> in a given sentence,
     82   * we usually need to distinguish only between female, male and other/unknown.</p>
     83   *
     84   * <p>To enable localizers to create sentence patterns that take their
     85   * language's gender dependencies into consideration, software has to  provide
     86   * information about the gender associated with a noun or name to
     87   * <code>MessageFormat</code>.
     88   * Two main cases can be distinguished:</p>
     89   *
     90   * <ul>
     91   * <li>For people, natural gender information should be maintained  for each person.
     92   * Keywords like "male", "female", "mixed" (for groups of people)
     93   * and "unknown" could be used.
     94   *
     95   * <li>For nouns, grammatical gender information should be maintained  for
     96   * each noun and per language, e.g., in resource bundles.
     97   * The keywords "masculine", "feminine", and "neuter" are commonly  used,
     98   * but some languages may require other keywords.
     99   * </ul>
    100   *
    101   * <p>The resulting keyword is provided to <code>MessageFormat</code>  as a
    102   * parameter separate from the name or noun it's associated with. For  example,
    103   * to generate a message such as "Jean went to Paris", three separate  arguments
    104   * would be provided: The name of the person as argument 0, the  gender of
    105   * the person as argument 1, and the name of the city as argument 2.
    106   * The sentence pattern for English, where the gender of the person has
    107   * no impact on this simple sentence, would not refer to argument 1  at all:</p>
    108   *
    109   * <pre>{0} went to {2}.</pre>
    110   *
    111   * <p><b>Note:</b> The entire sentence should be included (and partially repeated)
    112   * inside each phrase. Otherwise translators would have to be trained on how to
    113   * move bits of the sentence in and out of the select argument of a message.
    114   * (The examples below do not follow this recommendation!)</p>
    115   *
    116   * <p>The sentence pattern for French, where the gender of the person affects
    117   * the form of the participle, uses a select format based on argument 1:</p>
    118   *
    119   * \htmlonly<pre>{0} est {1, select, female {all&#x00E9;e} other {all&#x00E9;}} &#x00E0; {2}.</pre>\endhtmlonly
    120   *
    121   * <p>Patterns can be nested, so that it's possible to handle  interactions of
    122   * number and gender where necessary. For example, if the above  sentence should
    123   * allow for the names of several people to be inserted, the  following sentence
    124   * pattern can be used (with argument 0 the list of people's names,
    125   * argument 1 the number of people, argument 2 their combined gender, and
    126   * argument 3 the city name):</p>
    127   *
    128   * \htmlonly
    129   * <pre>{0} {1, plural,
    130   *                 one {est {2, select, female {all&#x00E9;e} other  {all&#x00E9;}}}
    131   *                 other {sont {2, select, female {all&#x00E9;es} other {all&#x00E9;s}}}
    132   *          }&#x00E0; {3}.</pre>
    133   * \endhtmlonly
    134   *
    135   * <h4>Patterns and Their Interpretation</h4>
    136   *
    137   * <p>The <code>SelectFormat</code> pattern string defines the phrase output
    138   * for each user-defined keyword.
    139   * The pattern is a sequence of (keyword, message) pairs.
    140   * A keyword is a "pattern identifier": [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+</p>
    141   *
    142   * <p>Each message is a MessageFormat pattern string enclosed in {curly braces}.</p>
    143   *
    144   * <p>You always have to define a phrase for the default keyword
    145   * <code>other</code>; this phrase is returned when the keyword
    146   * provided to
    147   * the <code>format</code> method matches no other keyword.
    148   * If a pattern does not provide a phrase for <code>other</code>, the  method
    149   * it's provided to returns the error  <code>U_DEFAULT_KEYWORD_MISSING</code>.
    150   * <br>
    151   * Pattern_White_Space between keywords and messages is ignored.
    152   * Pattern_White_Space within a message is preserved and output.</p>
    153   *
    154   * <p><pre>Example:
    155   * \htmlonly
    156   *
    157   * UErrorCode status = U_ZERO_ERROR;
    158   * MessageFormat *msgFmt = new MessageFormat(UnicodeString("{0} est  {1, select, female {all&#x00E9;e} other {all&#x00E9;}} &#x00E0; Paris."), Locale("fr"),  status);
    159   * if (U_FAILURE(status)) {
    160   *       return;
    161   * }
    162   * FieldPosition ignore(FieldPosition::DONT_CARE);
    163   * UnicodeString result;
    164   *
    165   * char* str1= "Kirti,female";
    166   * Formattable args1[] = {"Kirti","female"};
    167   * msgFmt->format(args1, 2, result, ignore, status);
    168   * cout << "Input is " << str1 << " and result is: " << result << endl;
    169   * delete msgFmt;
    170   *
    171   * \endhtmlonly
    172   * </pre>
    173   * </p>
    174   *
    175   * Produces the output:<br>
    176   * \htmlonly
    177   * <code>Kirti est all&#x00E9;e &#x00E0; Paris.</code>
    178   * \endhtmlonly
    179   *
    180   * @stable ICU 4.4
    181   */
    182 
    183 class U_I18N_API SelectFormat : public Format {
    184 public:
    185 
    186     /**
    187      * Creates a new <code>SelectFormat</code> for a given pattern string.
    188      * @param  pattern the pattern for this <code>SelectFormat</code>.
    189      *                 errors are returned to status if the pattern is invalid.
    190      * @param status   output param set to success/failure code on exit, which
    191      *                 must not indicate a failure before the function call.
    192      * @stable ICU 4.4
    193      */
    194     SelectFormat(const UnicodeString& pattern, UErrorCode& status);
    195 
    196     /**
    197      * copy constructor.
    198      * @stable ICU 4.4
    199      */
    200     SelectFormat(const SelectFormat& other);
    201 
    202     /**
    203      * Destructor.
    204      * @stable ICU 4.4
    205      */
    206     virtual ~SelectFormat();
    207 
    208     /**
    209      * Sets the pattern used by this select format.
    210      * for the keyword rules.
    211      * Patterns and their interpretation are specified in the class description.
    212      *
    213      * @param pattern the pattern for this select format
    214      *                errors are returned to status if the pattern is invalid.
    215      * @param status  output param set to success/failure code on exit, which
    216      *                must not indicate a failure before the function call.
    217      * @stable ICU 4.4
    218      */
    219     void applyPattern(const UnicodeString& pattern, UErrorCode& status);
    220 
    221 
    222     using Format::format;
    223 
    224     /**
    225      * Selects the phrase for  the given keyword
    226      *
    227      * @param keyword  The keyword that is used to select an alternative.
    228      * @param appendTo output parameter to receive result.
    229      *                 result is appended to existing contents.
    230      * @param pos      On input: an alignment field, if desired.
    231      *                 On output: the offsets of the alignment field.
    232      * @param status  output param set to success/failure code on exit, which
    233      *                 must not indicate a failure before the function call.
    234      * @return         Reference to 'appendTo' parameter.
    235      * @stable ICU 4.4
    236      */
    237     UnicodeString& format(const UnicodeString& keyword,
    238                             UnicodeString& appendTo,
    239                             FieldPosition& pos,
    240                             UErrorCode& status) const;
    241 
    242     /**
    243      * Assignment operator
    244      *
    245      * @param other    the SelectFormat object to copy from.
    246      * @stable ICU 4.4
    247      */
    248     SelectFormat& operator=(const SelectFormat& other);
    249 
    250     /**
    251      * Return true if another object is semantically equal to this one.
    252      *
    253      * @param other    the SelectFormat object to be compared with.
    254      * @return         true if other is semantically equal to this.
    255      * @stable ICU 4.4
    256      */
    257     virtual UBool operator==(const Format& other) const;
    258 
    259     /**
    260      * Return true if another object is semantically unequal to this one.
    261      *
    262      * @param other    the SelectFormat object to be compared with.
    263      * @return         true if other is semantically unequal to this.
    264      * @stable ICU 4.4
    265      */
    266     virtual UBool operator!=(const Format& other) const;
    267 
    268     /**
    269      * Clones this Format object polymorphically.  The caller owns the
    270      * result and should delete it when done.
    271      * @stable ICU 4.4
    272      */
    273     virtual Format* clone(void) const;
    274 
    275     /**
    276      * Format an object to produce a string.
    277      * This method handles keyword strings.
    278      * If the Formattable object is not a <code>UnicodeString</code>,
    279      * then it returns a failing UErrorCode.
    280      *
    281      * @param obj       A keyword string that is used to select an alternative.
    282      * @param appendTo  output parameter to receive result.
    283      *                  Result is appended to existing contents.
    284      * @param pos       On input: an alignment field, if desired.
    285      *                  On output: the offsets of the alignment field.
    286      * @param status    output param filled with success/failure status.
    287      * @return          Reference to 'appendTo' parameter.
    288      * @stable ICU 4.4
    289      */
    290     UnicodeString& format(const Formattable& obj,
    291                          UnicodeString& appendTo,
    292                          FieldPosition& pos,
    293                          UErrorCode& status) const;
    294 
    295     /**
    296      * Returns the pattern from applyPattern() or constructor.
    297      *
    298      * @param  appendTo  output parameter to receive result.
    299      *                  Result is appended to existing contents.
    300      * @return the UnicodeString with inserted pattern.
    301      * @stable ICU 4.4
    302      */
    303     UnicodeString& toPattern(UnicodeString& appendTo);
    304 
    305     /**
    306      * This method is not yet supported by <code>SelectFormat</code>.
    307      * <P>
    308      * Before calling, set parse_pos.index to the offset you want to start
    309      * parsing at in the source. After calling, parse_pos.index is the end of
    310      * the text you parsed. If error occurs, index is unchanged.
    311      * <P>
    312      * When parsing, leading whitespace is discarded (with a successful parse),
    313      * while trailing whitespace is left as is.
    314      * <P>
    315      * See Format::parseObject() for more.
    316      *
    317      * @param source     The string to be parsed into an object.
    318      * @param result     Formattable to be set to the parse result.
    319      *     If parse fails, return contents are undefined.
    320      * @param parse_pos The position to start parsing at. Upon return
    321      *     this param is set to the position after the
    322      *     last character successfully parsed. If the
    323      *     source is not parsed successfully, this param
    324      *     will remain unchanged.
    325      * @stable ICU 4.4
    326      */
    327     virtual void parseObject(const UnicodeString& source,
    328                             Formattable& result,
    329                             ParsePosition& parse_pos) const;
    330 
    331     /**
    332      * ICU "poor man's RTTI", returns a UClassID for this class.
    333      * @stable ICU 4.4
    334      */
    335     static UClassID U_EXPORT2 getStaticClassID(void);
    336 
    337     /**
    338      * ICU "poor man's RTTI", returns a UClassID for the actual class.
    339      * @stable ICU 4.4
    340      */
    341     virtual UClassID getDynamicClassID() const;
    342 
    343 private:
    344     friend class MessageFormat;
    345 
    346     SelectFormat();   // default constructor not implemented.
    347 
    348     /**
    349      * Finds the SelectFormat sub-message for the given keyword, or the "other" sub-message.
    350      * @param pattern A MessagePattern.
    351      * @param partIndex the index of the first SelectFormat argument style part.
    352      * @param keyword a keyword to be matched to one of the SelectFormat argument's keywords.
    353      * @param ec Error code.
    354      * @return the sub-message start part index.
    355      */
    356     static int32_t findSubMessage(const MessagePattern& pattern, int32_t partIndex,
    357                                   const UnicodeString& keyword, UErrorCode& ec);
    358 
    359     MessagePattern msgPattern;
    360 };
    361 
    362 U_NAMESPACE_END
    363 
    364 #endif /* #if !UCONFIG_NO_FORMATTING */
    365 
    366 #endif // _SELFMT
    367 //eof
    368