org.gwtproject.i18n.client.Messages Maven / Gradle / Ivy
/*
* Copyright © 2018 The GWT Authors
*
* 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 org.gwtproject.i18n.client;
import java.lang.annotation.*;
/**
* 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
* org.gwtproject.i18n.shared.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 = "org.gwtproject.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();
* }
*
*
* 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 org.gwtproject.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.
*/
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 org.gwtproject.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 {}
}