| /* |
| * Copyright 2008 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| package com.google.gwt.i18n.client; |
| |
| import java.lang.annotation.Documented; |
| import java.lang.annotation.ElementType; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.annotation.Target; |
| |
| /** |
| * A tag interface that facilitates locale-sensitive, compile-time binding of |
| * messages supplied from various sources.Using |
| * <code>GWT.create(<i>class</i>)</code> to "instantiate" an interface that |
| * extends <code>Messages</code> returns an instance of an automatically |
| * generated subclass that is implemented using message templates selected based |
| * on locale. Message templates are based on a subset of the format used by <a |
| * href="http://download.oracle.com/javase/1.5.0/docs/api/java/text/MessageFormat.html"> |
| * <code>MessageFormat</code></a>. Note in particular that single quotes are |
| * used to quote other characters, and should be doubled for a literal single |
| * quote. |
| * |
| * <p> |
| * Locale is specified at run time using a meta tag or query string as described |
| * for {@link com.google.gwt.i18n.client.Localizable}. |
| * </p> |
| * |
| * <h3>Extending <code>Messages</code></h3> |
| * To use <code>Messages</code>, begin by defining an interface that extends |
| * it. Each interface method is referred to as a <i>message accessor</i>, and |
| * its corresponding message template is loaded based on the key for that |
| * method. The default key is simply the unqualified name of the method, but can |
| * be specified directly with an {@code @Key} annotation or a different |
| * generation method using {@code @GenerateKeys}. Additionally, if |
| * plural forms are used on a given method the plural form is added as a suffix |
| * to the key, such as <code>widgets[one]</code> for the singular version of |
| * the <code>widgets</code> message. The resulting key is used to find |
| * translated versions of the message from any supported input file, such as |
| * Java properties files. For example, |
| * |
| * {@example com.google.gwt.examples.i18n.GameStatusMessages} |
| * |
| * expects to find properties named <code>turnsLeft</code> and |
| * <code>currentScore</code> in an associated properties file, formatted as |
| * message templates taking two arguments and one argument, respectively. For |
| * example, the following properties would correctly bind to the |
| * <code>GameStatusMessages</code> interface: |
| * |
| * {@gwt.include com/google/gwt/examples/i18n/GameStatusMessages.properties} |
| * |
| * <p> |
| * The following example demonstrates how to use constant accessors defined in |
| * the interface above: |
| * |
| * {@example com.google.gwt.examples.i18n.GameStatusMessagesExample#beginNewGameRound(String)} |
| * </p> |
| * |
| * <p>The following example shows how to use annotations to store the default strings |
| * in the source file itself, rather than needing a properties file (you still need |
| * properties files for the translated strings): |
| * |
| * {@example com.google.gwt.examples.i18n.GameStatusMessagesAnnot} |
| * </p> |
| * |
| * <p>In this example, calling <code>msg.turnsLeft("John", 13)</code> would |
| * return the string <code>"Turns left for player 'John': 13"</code>. |
| * </p> |
| * |
| * <h3>Defining Message Accessors</h3> |
| * Message accessors must be of the form |
| * |
| * <pre>String methodName(<i>optional-params</i>)</pre> |
| * |
| * and parameters may be of any type. Arguments are converted into strings at |
| * runtime using Java string concatenation syntax (the '+' operator), which |
| * uniformly handles primitives, <code>null</code>, and invoking |
| * <code>toString()</code> to format objects. |
| * |
| * <p> |
| * Compile-time checks are performed to ensure that the number of placeholders |
| * in a message template (e.g. <code>{0}</code>) matches the number of |
| * parameters supplied. |
| * </p> |
| * |
| * <p> |
| * Integral arguments may be used to select the proper plural form to use for |
| * different locales. To do this, mark the particular argument with |
| * {@code @PluralCount} (a plural rule may be specified with |
| * {@code @PluralCount} if necessary, but you will almost never need to |
| * do this). The actual plural forms for the default locale can be supplied in a |
| * {@code @PluralText} annotation on the method, such as |
| * <code>@PluralText({"one", "You have one widget"})</code>, or they can be |
| * supplied in the properties file as {@code methodkey[one]=You have one widget}. Note |
| * that non-default plural forms are not inherited between locales, because the |
| * different locales may have different plural rules (especially {@code default} and |
| * anything else and those which use different scripts such as {@code sr_Cyrl} and |
| * {@code sr_Latn} [one of which would likely be the default], but also subtle cases |
| * like {@code pt} and {@code pt_BR}). |
| * </p> |
| * |
| * <p> |
| * Additionally, individual arguments can be marked as optional (ie, GWT will |
| * not give an error if a particular translation does not reference the |
| * argument) with the {@code @Optional} annotation, and an example may be supplied to |
| * the translator with the {@code @Example(String)} annotation. |
| * </p> |
| * |
| * <h3>Complete Annotations Example</h3> |
| * In addition to the default properties file, default text and additional |
| * metadata may be stored in the source file itself using annotations. A |
| * complete example of using annotations in this way is: |
| * |
| * <code><pre> |
| * @Generate(format = "com.google.gwt.i18n.rebind.format.PropertiesFormat") |
| * @DefaultLocale("en_US") |
| * public interface MyMessages extends Messages { |
| * @Key("1234") |
| * @DefaultMessage("This is a plain string.") |
| * String oneTwoThreeFour(); |
| * |
| * @DefaultMessage("You have {0} widgets") |
| * @PluralText({"one", "You have one widget") |
| * String widgetCount(@PluralCount int count); |
| * |
| * @DefaultMessage("No reference to the argument") |
| * String optionalArg(@Optional String ignored); |
| * |
| * @DefaultMessage("Your cart total is {0,number,currency}") |
| * @Description("The total value of the items in the shopping cart in local currency") |
| * String totalAmount(@Example("$5.00") double amount); |
| * |
| * @Meaning("the color") |
| * @DefaultMessage("orange") |
| * String orangeColor(); |
| * |
| * @Meaning("the fruit") |
| * @DefaultMessage("orange") |
| * String orangeFruit(); |
| * } |
| * </pre></code> |
| * |
| * <h3>Binding to Properties Files</h3> |
| * Interfaces extending <code>Messages</code> are bound to resource files |
| * using the same algorithm as interfaces extending <code>Constants</code>. |
| * See the documentation for {@link Constants} for a description of the |
| * algorithm. |
| * |
| * <h3>Required Module</h3> |
| * Modules that use this interface should inherit |
| * <code>com.google.gwt.i18n.I18N</code>. |
| * |
| * {@gwt.include com/google/gwt/examples/i18n/InheritsExample.gwt.xml} |
| * |
| * <h3>Note</h3> |
| * You should not directly implement this interface or interfaces derived from |
| * it since an implementation is generated automatically when message interfaces |
| * are created using {@link com.google.gwt.core.client.GWT#create(Class)}. |
| */ |
| public interface Messages extends LocalizableResource { |
| |
| /** |
| * Provides alternate forms of a message, such as are needed when plural |
| * forms are used or a placeholder has known gender. The selection of which |
| * form to use is based on the value of the arguments marked |
| * PluralCount and/or Select. |
| * |
| * <p>Example: |
| * <code><pre> |
| * @DefaultMessage("You have {0} widgets.") |
| * @AlternateMessage({"one", "You have one widget.") |
| * String example(@PluralCount int count); |
| * </pre></code> |
| * </p> |
| * |
| * <p>If multiple {@link PluralCount} or {@link Select} parameters are |
| * supplied, the forms for each, in the order they appear in the parameter |
| * list, are supplied separated by a vertical bar ("|"). Example: |
| * <code><pre> |
| * @DefaultMessage("You have {0} messages and {1} notifications.") |
| * @AlternateMessage({ |
| * "=0|=0", "You have no messages or notifications." |
| * "=0|one", "You have a notification." |
| * "one|=0", "You have a message." |
| * "one|one", "You have one message and one notification." |
| * "other|one", "You have {0} messages and one notification." |
| * "one|other", "You have one message and {1} notifications." |
| * }) |
| * String messages(@PluralCount int msgCount, |
| * @PluralCount int notifyCount); |
| * </pre></code> |
| * |
| * Note that the number of permutations can grow quickly, and that the default |
| * message is used when every {@link PluralCount} or {@link Select} would use |
| * the "other" value. |
| * </p> |
| */ |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target(ElementType.METHOD) |
| @Documented |
| public @interface AlternateMessage { |
| |
| /** |
| * An array of pairs of strings containing the strings for different forms. |
| * |
| * Each pair is the name of a form followed by the string in the source |
| * locale for that form. Each form name is the name of a plural form if |
| * {@link PluralCount} is used, or the matching value if {@link Select} is |
| * used. An example for a locale that has "none", "one", and "other" plural |
| * forms: |
| * |
| * <code><pre> |
| * @DefaultMessage("{0} widgets") |
| * @AlternateMessage({"none", "No widgets", "one", "One widget"}) |
| * </pre> |
| * |
| * Note that the plural form "other" gets the translation specified in |
| * {@code @DefaultMessage}, as does any {@code @Select} value not |
| * listed. |
| * |
| * If more than one way of selecting a translation exists, they will be |
| * combined, separated with {@code |}, in the order they are supplied as |
| * arguments in the method. For example: |
| * <code><pre> |
| * @DefaultMessage("{0} gave away their {2} widgets") |
| * @AlternateMesssage({ |
| * "MALE|other", "{0} gave away his {2} widgets", |
| * "FEMALE|other", "{0} gave away her {2} widgets", |
| * "MALE|one", "{0} gave away his widget", |
| * "FEMALE|one", "{0} gave away her widget", |
| * "other|one", "{0} gave away their widget", |
| * }) |
| * String giveAway(String name, @Select Gender gender, |
| * @PluralCount int count); |
| * </pre></code> |
| */ |
| String[] value(); |
| } |
| |
| /** |
| * Default text to be used if no translation is found (and also used as the |
| * source for translation). Format should be that expected by |
| * {@link java.text.MessageFormat}. |
| * |
| * <p>Example: |
| * <code><pre> |
| * @DefaultMessage("Don''t panic - you have {0} widgets left") |
| * String example(int count) |
| * </pre></code> |
| * </p> |
| */ |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target(ElementType.METHOD) |
| @Documented |
| public @interface DefaultMessage { |
| String value(); |
| } |
| |
| /** |
| * An example of the annotated parameter to assist translators. |
| * |
| * <p>Example: |
| * <code><pre> |
| * String example(@Example("/etc/passwd") String fileName) |
| * </pre></code> |
| * </p> |
| */ |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target(ElementType.PARAMETER) |
| public @interface Example { |
| String value(); |
| } |
| |
| /** |
| * Ignored except on parameters also tagged with {@link PluralCount}, and |
| * provides an offset to be subtracted from the value before a plural rule |
| * is chosen or the value is formatted. Note that "=n" forms are evaluated |
| * before this offset is applied. |
| * |
| * <p>Example: |
| * <code><pre> |
| * @PluralText({"=0", "No one has recommended this movie", |
| * "=1", "{0} has recommended this movie", |
| * "=2", "{0} and {1} have recommended this movie", |
| * "one", "{0}, {1} and one other have recommended this movie"}) |
| * @DefaultMessage("{0}, {1} and {2,number} others have recommended this movie") |
| * String recommenders(@Optional String rec1, @Optional String rec2, |
| * @PluralCount @Offset(2) int count); |
| * </pre></code> |
| * would result in |
| * <code><pre> |
| * recommenders("John", null, 1) => "John has..." |
| * recommenders("John", "Jane", 3) => "John, Jane, and one other..." |
| * recommenders("John", "Jane", 1402) => "John, Jane, and 1,400 others..." |
| * </pre></code> |
| * </p> |
| */ |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target(ElementType.PARAMETER) |
| public @interface Offset { |
| int value(); |
| } |
| |
| /** |
| * Indicates the specified parameter is optional and need not appear in a |
| * particular translation of this message. |
| * |
| * <p>Example: |
| * <code><pre> |
| * String example(@Optional int count) |
| * </pre></code> |
| * </p> |
| */ |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target(ElementType.PARAMETER) |
| public @interface Optional { |
| } |
| |
| /** |
| * Provides multiple plural forms based on a count. The selection of which |
| * plural form is performed by a PluralRule implementation. |
| * |
| * This annotation is applied to a single parameter of a Messages subinterface |
| * and indicates that parameter is to be used to choose the proper plural form |
| * of the message. The parameter chosen must be of type short or int. |
| * |
| * Optionally, a class literal referring to a PluralRule implementation can be |
| * supplied as the argument if the standard implementation is insufficient. |
| * |
| * <p>Example: |
| * <code><pre> |
| * @DefaultMessage("You have {0} widgets.") |
| * @AlternateMessage({"one", "You have one widget."}) |
| * String example(@PluralCount int count) |
| * </pre></code> |
| * </p> |
| */ |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target(ElementType.PARAMETER) |
| public @interface PluralCount { |
| |
| /** |
| * The PluralRule implementation to use for this message. If not specified, |
| * the GWT-supplied one is used instead, which should cover most use cases. |
| * |
| * <p>{@code PluralRule.class} is used as a default value here, which will |
| * be replaced during code generation with the default implementation. |
| * </p> |
| */ |
| // http://bugs.sun.com/view_bug.do?bug_id=6512707 |
| Class<? extends PluralRule> value() default com.google.gwt.i18n.client.PluralRule.class; |
| } |
| |
| /** |
| * Provides multiple plural forms based on a count. The selection of which |
| * plural form to use is based on the value of the argument marked |
| * PluralCount, which may also specify an alternate plural rule to use. |
| * |
| * <p>Example: |
| * <code><pre> |
| * @DefaultMessage("You have {0} widgets.") |
| * @PluralText({"one", "You have one widget.") |
| * String example(@PluralCount int count) |
| * </pre></code> |
| * </p> |
| * |
| * @deprecated use {@link AlternateMessage} instead |
| */ |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target(ElementType.METHOD) |
| @Documented |
| @Deprecated |
| public @interface PluralText { |
| |
| /** |
| * An array of pairs of strings containing the strings for different plural |
| * forms. |
| * |
| * Each pair is the name of the plural form (as returned by |
| * PluralForm.toString) followed by the string for that plural form. An |
| * example for a locale that has "none", "one", and "other" plural forms: |
| * |
| * <code><pre> |
| * @DefaultMessage("{0} widgets") |
| * @PluralText({"none", "No widgets", "one", "One widget"}) |
| * </pre> |
| * |
| * "other" must not be included in this array as it will map to the |
| * DefaultMessage value. |
| */ |
| String[] value(); |
| } |
| |
| /** |
| * Provides multiple forms based on a dynamic parameter. |
| * |
| * This annotation is applied to a single parameter of a Messages subinterface |
| * and indicates that parameter is to be used to choose the proper form of the |
| * message. The parameter chosen must be of type Enum, String, boolean, or a |
| * primitive integral type. This is frequently used to get proper gender for |
| * translations to languages where surrounding words depend on the gender of |
| * a person or noun. This also marks the parameter as {@link Optional}. |
| * |
| * <p>Example: |
| * <code><pre> |
| * @DefaultMessage("{0} likes their widgets.") |
| * @AlternateMessage({ |
| * "FEMALE", "{0} likes her widgets.", |
| * "MALE", "{0} likes his widgets.", |
| * }) |
| * String example(String name, @Select Gender gender) |
| * </pre></code> |
| * </p> |
| */ |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target(ElementType.PARAMETER) |
| public @interface Select { |
| } |
| } |