com.google.gwt.i18n.client.Messages Maven / Gradle / Ivy
/*
* 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
* GWT.create(class)
to "instantiate" an interface that
* extends Messages
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
* MessageFormat
. Note in particular that single quotes are
* used to quote other characters, and should be doubled for a literal single
* quote.
*
*
* Locale is specified at run time using a meta tag or query string as described
* for {@link com.google.gwt.i18n.client.Localizable}.
*
*
* Extending Messages
* To use Messages
, begin by defining an interface that extends
* it. Each interface method is referred to as a message accessor, 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 widgets[one]
for the singular version of
* the widgets
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 turnsLeft
and
* currentScore
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
* GameStatusMessages
interface:
*
* {@gwt.include com/google/gwt/examples/i18n/GameStatusMessages.properties}
*
*
* The following example demonstrates how to use constant accessors defined in
* the interface above:
*
* {@example com.google.gwt.examples.i18n.GameStatusMessagesExample#beginNewGameRound(String)}
*
*
* 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}
*
*
* In this example, calling msg.turnsLeft("John", 13)
would
* return the string "Turns left for player 'John': 13"
.
*
*
* Defining Message Accessors
* Message accessors must be of the form
*
* String methodName(optional-params)
*
* 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, null
, and invoking
* toString()
to format objects.
*
*
* Compile-time checks are performed to ensure that the number of placeholders
* in a message template (e.g. {0}
) matches the number of
* parameters supplied.
*
*
*
* 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
* @PluralText({"one", "You have one widget"})
, 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}).
*
*
*
* 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.
*
*
* Complete Annotations Example
* 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:
*
*
* @Generate(format = "com.google.gwt.i18n.rebind.format.PropertiesFormat")
* @DefaultLocale("en_US")
* public interface MyMessages extends Messages {
* @Key("1234")
* @DefaultText("This is a plain string.")
* String oneTwoThreeFour();
*
* @DefaultText("You have {0} widgets")
* @PluralText({"one", "You have one widget")
* String widgetCount(@PluralCount int count);
*
* @DefaultText("No reference to the argument")
* String optionalArg(@Optional String ignored);
*
* @DefaultText("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();
* }
*
*
* Binding to Properties Files
* Interfaces extending Messages
are bound to resource files
* using the same algorithm as interfaces extending Constants
.
* See the documentation for {@link Constants} for a description of the
* algorithm.
*
* Required Module
* Modules that use this interface should inherit
* com.google.gwt.i18n.I18N
.
*
* {@gwt.include com/google/gwt/examples/i18n/InheritsExample.gwt.xml}
*
* Note
* 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.
*
* Example:
*
* @DefaultMessage("You have {0} widgets.")
* @AlternateMessage({"one", "You have one widget.")
* String example(@PluralCount int count);
*
*
*
* 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:
*
* @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);
*
*
* 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.
*
*/
@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:
*
*
* @DefaultMessage("{0} widgets")
* @AlternateMessage({"none", "No widgets", "one", "One widget"})
*
*
* 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:
*
* @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);
*
*/
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}.
*
* Example:
*
* @DefaultMessage("Don''t panic - you have {0} widgets left")
* String example(int count)
*
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DefaultMessage {
String value();
}
/**
* An example of the annotated parameter to assist translators.
*
* Example:
*
* String example(@Example("/etc/passwd") String fileName)
*
*
*/
@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.
*
* Example:
*
* @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);
*
* would result in
*
* 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..."
*
*
*/
@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.
*
* Example:
*
* String example(@Optional int count)
*
*
*/
@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.
*
* Example:
*
* @DefaultMessage("You have {0} widgets.")
* @AlternateMessage({"one", "You have one widget."})
* String example(@PluralCount int count)
*
*
*/
@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.
*
* {@code PluralRule.class} is used as a default value here, which will
* be replaced during code generation with the default implementation.
*
*/
// 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.
*
* Example:
*
* @DefaultMessage("You have {0} widgets.")
* @PluralText({"one", "You have one widget.")
* String example(@PluralCount int count)
*
*
*
* @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:
*
*
* @DefaultMessage("{0} widgets")
* @PluralText({"none", "No widgets", "one", "One widget"})
*
*
* "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}.
*
* Example:
*
* @DefaultMessage("{0} likes their widgets.")
* @AlternateMessage({
* "FEMALE", "{0} likes her widgets.",
* "MALE", "{0} likes his widgets.",
* })
* String example(String name, @Select Gender gender)
*
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Select {
}
}