Package limn.i18n

Class PluralString

java.lang.Object
limn.i18n.PluralString

public final class PluralString extends Object
A localizable sentence with a count in it: "Documents, 12 items".

Its own type rather than a mode of I18nString, for a reason a caller feels. An I18nString is a value a widget holds and reads every frame, and its memo is built for exactly that; this cannot be held resolved, because it is not one string — it is one per grammatical form, chosen when the count is known. Declaring it separately is what keeps I18nString's own rule true: one key, one English, resolvable with no arguments.


 private static final PluralString LOADED = PluralString.of(
         "limn.tree.loadedAnnouncement", "{0}, {1} item", "{0}, {1} items");
 ...
 scene.announce(LOADED.format(children.size(), branchName), Politeness.POLITE);
 

The count is the last argument. Above, {0} is the branch name the caller passed and {1} is the count, inserted after the caller's arguments. It is last rather than first so that a sentence reads in the order a translator writes it and the caller's arguments keep the numbering they would have had without a count.

In the catalog, one key per form. The declared key gains a suffix — limn.tree.loadedAnnouncement.one, .few, .other — and a language carries exactly the forms it uses, which is PluralRules.integerCategories(java.util.Locale): one line for Japanese, three for Russian, six for Arabic. A form a catalog leaves out falls back to that language's other, and then to the English declared here, so a half-translated catalog degrades to a readable sentence rather than to a key name.

The number is written the way the locale writes numbers — grouped and in its own digits, through NumberFormats.number(), so a million reads "1,000,000" in English, "1.000.000" in Portuguese and "١٬٠٠٠٬٠٠٠" in Egyptian Arabic. It is inserted as text, so that MessageFormat does not format it again under a second set of rules; passing the raw digits instead would put an ungrouped "1000000" in the one sentence whose whole subject is a number. A number among the caller's own arguments is written in the same digits, as I18nString.format(java.lang.Object...) writes one.

See Also:
  • Method Details

    • of

      public static PluralString of(String key, String one, String other)
      Declares a counted sentence with the two forms English has.

      Every category is declared against the catalog, not only these two: a translation into a language with six forms has six keys to fill, and each of them must be a key some component declared or the catalog is carrying an orphan. The English for a form English does not have is its plural, which is the right thing for a catalog that answers nothing.

      Parameters:
      key - the lookup key, dotted and globally unique, without a form suffix
      one - the English singular, with {0}-style arguments and the count last
      other - the English plural, the same way
      Returns:
      the declaration
      Throws:
      IllegalStateException - if a key was already declared with different English
    • format

      public String format(long count, @Nullable Object @Nullable ... args)
      The sentence for count, in the locale in effect here.

      A pattern a translator got wrong falls back to the English of the same form rather than throwing in the middle of a paint, exactly as I18nString.format(java.lang.Object...) does.

      Parameters:
      count - how many; it chooses the form and is appended to args as text
      args - the caller's arguments, which keep their own positions
      Returns:
      the formatted sentence
    • forCount

      public I18nString forCount(long count, @Nullable Object @Nullable ... args)
      The sentence for count, as a text that follows the language: format(long, java.lang.Object...) formats it again, form and digits included, each time it is read in another language. What a label showing a count is given, so that a change of language reaches it; format(long, java.lang.Object...) answers the sentence of the moment as a String. An argument that is an I18nString is read in that language too. The count and the arguments are values taken at the call, as I18nString.withArguments(java.lang.Object...) says: for a new count, make a new text and set it again.
      Parameters:
      count - how many; it chooses the form and is appended to args as text
      args - the caller's arguments, which keep their own positions
      Returns:
      the sentence as a text that follows the language
    • key

      public String key()
      The lookup key, without a form suffix.
    • english

      public String english(PluralRules.Category category)
      The English for one form: the fallback, and never null.
      Parameters:
      category - the form
      Returns:
      its English