Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Enum.toString() localized

I'm developing an Android application and I want to know if I can set Enum.toString() multilanguage.

I'm going to use this Enum on a Spinner and I want to use multi language texts.

public class Types
{
    public enum Stature
    {
        tall (0, "tall"),
        average(1, "average"),
        small(2, "small");

        private final int stature;
        private final String statureString;

        Stature(int anStature, String anStatureString) { stature = anStature; statureString = anStatureString; }

        public int getValue() { return stature; }

        @Override
        public String toString() { return statureString; }
    }
}

I don't know how to use Context.getString() inside an Enum, and I have hardcoded "tall", "average" and "small" to test it. I have defined that enum inside on a helper class.

This how I use the enum on a Spinner:

mSpinStature.setAdapter(new ArrayAdapter<Stature>(mActivity, android.R.layout.simple_dropdown_item_1line, Stature.values()));

Do you know how can I do it?

like image 702
VansFannel Avatar asked Jun 18 '13 10:06

VansFannel


People also ask

How do you localize an enum?

So what we usually do for enums that need to be localized is to write an extension class that provides a method to obtain the translated name. You can just use a switch that returns strings from the usual resources. That way, you provide translated strings for enums via the resources just like you do for other strings.

Can you toString an enum?

The Java Enum has two methods that retrieve that value of an enum constant, name() and . toString(). The toString() method calls the name() method which returns the string representation of the enum constant.

How do you localize an enum in Java?

To localize the enumeration names and values, add messages with the following keys to the message pack located in the Java package of the enumeration class: Enumeration name key – simple class name (without package); Value key – simple class name, then the value name separated by period.

Can we override toString method in enum?

The toString() method of Enum class returns the name of this enum constant, as the declaration contains. The toString() method can be overridden, although it's not essential.


3 Answers

Assume this resource path

String resourceBundlePath = "my.package.bundles.messages"

In package my.package.bundles you may have messages.properties, messages_en_US.properties etc.

Then, using

ResourceBundle resourceBundle = ResourceBundle.getBundle(resourceBundlePath);
String messageKey = "myFirstMessage";
String message = resourceBundle.getMessage(messageKey);

message will contain the value of the messageKey property defined on messages.properties. If the current Locale is actually en_US you will get the value from messages_en_US.properties. If the current locale is something you do not have a properties file for the value will be from the default messages.properties

You can also call

ResourceBundle.getBundle(resourceBundlePath, myLocale);

but it is generally better to use the platform locale (have a look at jvm arguments -Duser.language, -Duser.country)

You can have a ResourceBundle for each enum you want to translate with keys the enum element names and use it in the toString() implementation of your enum:

@Override
public String toString() {
return resourceBudle.getString(super.toString());
}
like image 38
dkateros Avatar answered Oct 05 '22 06:10

dkateros


I created a simple library which is a part of my big project (Xdroid):

compile 'com.shamanland:xdroid-enum-format:0.2.4'

Now you can avoid the same monkey-job (declaring field, constructor, etc) for all enumetations by using annotations:

public enum State {
    @EnumString(R.string.state_idle)
    IDLE,

    @EnumString(R.string.state_pending)
    PENDING,

    @EnumString(R.string.state_in_progress)
    IN_PROGRESS,

    @EnumString(R.string.state_cancelled)
    CANCELLED,

    @EnumString(R.string.state_done)
    DONE;
}

And then use the common Java approach - use extensions of class java.text.Format:

public void onStateChanged(State state) {
    EnumFormat enumFormat = EnumFormat.getInstance();
    toast(enumFormat.format(state));
}

strings.xml

<string name="state_idle">Idle</string>
<string name="state_pending">Pending</string>
<string name="state_in_progress">In progress</string>
<string name="state_cancelled">Cancelled</string>
<string name="state_done">Done</string>

Look here how to show Toast simply.

You can also compile a demo app from github.

like image 193
Oleksii K. Avatar answered Oct 05 '22 04:10

Oleksii K.


I would leave enum as is and use the standard ResourceBundle approach http://docs.oracle.com/javase/tutorial/i18n/resbundle/concept.html using Enum.toString as the key

like image 24
Evgeniy Dorofeev Avatar answered Oct 05 '22 04:10

Evgeniy Dorofeev