Translate for your Language

[[PrettyTime]] supports many languages already, but if your language -or a language you need- is not supported, it’s easy to add support for even the most unique dialects you might need. These translation features can also be used to provide completely custom formats and dialects for technical or other purposes. For further time unit format customization beyond the internationalization features provided below, it is recommended that you implement your own TimeUnit or TimeFormat instances using the provided interfaces.


If you have finished a translation for a new language or dialect that PrettyTime does not currently support, we would love to add it to our supported translations. Just fork our repository on github, and send a pull request with your translation, and a test-case.

Get started

If you are already familiar with the Java resource bundle API, then you can skip this section and dig right in; otherwise, the java.util.ResourceBundle API at its most basic level, is a strategy for loading different files or classes based on the current or requested system java.util.Locale. To use it, your file must end with XX_yy, where `XX` is the primary Country code, and `yy` is the secodary dialect or region code.

PrettyTime bundles by example

Now, lets look at part of the translation file for the English language. Notice that we are using the ResourceBundle API to load java Classes by Locale, not text property files. This is important because it is possible for ResourceBundles to implement several interfaces, allowing further customization of behavior for features like: custom pluralization and grammar rules, and more.

In this and the next sections, we’ll inspect the following resource bundle, and explain each entry in detail.

org/ocpsoft/prettytime/i18n/Resources_en.java
package org.ocpsoft.prettytime.i18n;

import java.util.ListResourceBundle;

public class Resources extends ListResourceBundle
{
    private static final Object[][] OBJECTS = new Object[][] {

    ...
        { "DayPattern", "%n %u" },
        { "DayFuturePrefix", "" },
        { "DayFutureSuffix", " from now" },
        { "DayPastPrefix", "" },
        { "DayPastSuffix", " ago" },
        { "DayName", "day" },
        { "DayPluralName", "days" },
    ...

    @Override
    public Object[][] getContents()
    {
        return OBJECTS;
    }
}

Contents of the resource bundle

public Object[][] getContents()

This is the method that must return the contents of the resource bundle, including all patterns, names, prefixes, and suffixes.

  • *FuturePrefix The grammatically correct word or phrase that one would use before the quantity in a formatted date occurring in the future. For instance, if the fully formatted result is “in 3 days from now”, the future prefix would be “in”.
  • *FutureSuffix – The grammatically correct word or phrase that one would use after the quantity in a formatted date occurring in the future. For instance, if the fully formatted result is “in 3 days from now”, the future prefix would be “from now”.
  • *PastPrefix – The grammatically correct word or phrase that one would use before the quantity in a formatted date occurring in the past. For instance, if the fully formatted result is “before 3 days ago”, the future prefix would be “before”.
  • *PastSuffix – The grammatically correct word or phrase that one would use after the quantity in a formatted date occurring in the past. For instance, if the fully formatted result is “before 3 days ago”, the future prefix would be “ago”.
  • *SingularName – The grammatically correct word or phrase that describing the singular quantity of a given time unit. For instance, if the fully formatted result is “before 1 day ago”, the singular name would be “day”.
  • *PluralName – The grammatically correct word or phrase that describing the plural quantity of a given time unit. For instance, if the fully formatted result is “in 2 days, the plural name would be “days”.
  • *FutureSingularName – (optional) Overrides SingularName if the date to format is in the future. The grammatically correct word or phrase that describing the singular quantity of a given time unit. For instance, if the fully formatted result is “in 1 day”, the future singular name would be “day”.
  • *FuturePluralName – (optional) Overrides PluralName if the date to format is in the future. The grammatically correct word or phrase that describing the plural quantity of a given time unit. For instance, if the fully formatted result is “in 2 days”, the future plural name would be “days”.
  • *PastSingularName – (optional) Overrides SingularName if the date to format is in the past. The grammatically correct word or phrase that describing the singular quantity of a given time unit. For instance, if the fully formatted result is “before 1 day ago”, the past singular name would be “day”.
  • *PastPluralName – (optional) Overrides PluralName if the date to format is in the past. The grammatically correct word or phrase that describing the plural quantity of a given time unit. For instance, if the fully formatted result is “in 2 days, the past plural name would be “days”.
  • *Pattern – In the example above, the bundle contains an entry for "DayPattern", "%n %u". This entry is responsible for setting the pattern with which a given time unit should be formatted. You can control ordering and formatting for each time unit by manipulating the pattern.


    {prefix} {pattern} {suffix} – where {pattern} is created through the following codes:


    %n = number of units (the actual number that will show up) %u = name of the unit (either singular or plural, depending on run time conditions)


    Most languages (using the standard %n %u pattern) will render something like: {prefix} {number} {unitName} {suffix}.

    There are two exceptions to the general rule. The “Just Now” unit, doesn’t use a number; simply “moments from now” or “moments ago”. The “Abstract Time” block is currently unused, so keep it blank. You probably want to keep the default pattern %n %u unless your language needs something different.


    You could also do something wacky like:

    Exhibit 1
    public class Resources extends ListResourceBundle
    {
        private static final Object[][] OBJECTS = new Object[][] {
        ...
            { "DayPattern", "%n freakin' %u" }
        ...
    }
    This would effectively print 5 freakin' days ago. Fun!

Putting it all together

You should now be ready to implement your own custom translation for PrettyTime. Don’t forget to write a test-case to prove that everything works!

Required bundle keys

PrettyTime resource bundles require that all keys be provided, otherwise, languages and dialects may be incorrectly blended together. For reference, please look at one of the existing supported bundles.

One Comment

Leave a Comment




Please note: In order to submit code or special characters, wrap it in

[code lang="xml"][/code]
(for your language) - or your tags will be eaten.

Please note: Comment moderation is enabled and may delay your comment from appearing. There is no need to resubmit your comment.