1

I have an enum class, but I want to display string based on user system language. For example, If the system is English , it should display 1 , 2 ,3 . But if the System is Chinese, the display should totally be different like "一", “二”, “三”. (一 means 1 in Chinese, 二 means 2 in Chinese).

Here is my code

public enum OrderType {


    ONE("1"), TWO("2"), THREE("3")

    private String name;

    private OrderType(String name) {
        this.name = name;
    }

    public String toString() {
        return name;
    }

    public static String getEnumByString(String code) {
        for (OrderType e : OrderType.values()) {
            if (code.equals(e.name)) {
                return e.name();
            }
        }
        return null;
    }

}

The enum works fine in android, Can I define the String in the value folder,

Like values-iw, values-ru... And how can I use that?

UPDATE: I also want to use constructor to initialize the enum string. Just like

private OrderType(String name) {
    String temp = getResources().getString(R.string.name);
    this.name = temp ;
}

But I do not know how to pass parameter of R.string.parameter.. Second, how Can I use getResources() function in enum class

typeof programmer
  • 1,509
  • 4
  • 22
  • 34

5 Answers5

4

Just provide the String resource ID as a parameter to your Enum:

public enum OrderType {
    ONE(R.string.order_type_one),
    TWO(R.string.order_type_two)

    private final int mTextResourceId;

    OrderType(int resourceId) {
        mTextResourceId = resourceId;
    }

    public int getTextResourceId() {
        return mTextResourceId;
    }
}

Provide these strings in each desired resource folder, e.g.:

res/values/strings.xml
res/values-es/strings.xml
res/values-fr/string.xml

Then, when you want to consume this in a TextView somewhere:

myTextView.setText(myOrderType.getTextResourceId()); 

No Context passing required, and it is determined at runtime based on the current locale.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • +1. Can you please explain what @StringRes annotation does? Also, I wonder if enums give any particular advantage in this case. – kiruwka Oct 27 '14 at 22:48
  • Oh yes, the `@StringRes` annotation is part of the Android Support Annotations package (`com.android.support:support-annotations:+`) that basically hints to the compiler that an `R.string` reference is expected. So if you were to pass in an `R.id` value (which is also an int so technically valid) the compiler would warn that it is an unexpected type. If you're not using the support annotations dependency those can be omitted. – Kevin Coppock Oct 27 '14 at 23:02
  • I've edited that out of the answer since it's not strictly relevant. – Kevin Coppock Oct 27 '14 at 23:03
  • Thank you so much for your replay, but it is not TextView, it is Spinner. How can I set the spinner value; I need overwrite toString function in the enum class. Thank you so much`~~ – Urchin Oct 28 '14 at 15:16
  • It still is a TextView -- you're just letting the default spinner adapter handle it. I'd suggest just writing a custom Spinner adapter and handling the text display on your own. – Kevin Coppock Oct 28 '14 at 15:21
  • One(mActivity.getString(R.string.one)), is this possible? In the normal class, it works. but How can i getActivity() at enum class. Thank you so much..~~ – Urchin Oct 28 '14 at 17:12
  • You absolutely cannot do that as you don't have an initialized Context reference at the time that the enums are initialized. Besides, that would be a broken implementation that would never update the strings if the user's language changes. Either change your implementation (don't use an enum here) or write a custom adapter. – Kevin Coppock Oct 28 '14 at 17:23
  • @user1729577 You can refer to my answer to see why you can't pass context (such as activity) in your enums. Indeed, either use kcoppock's solution with custom adapter or don't use enums as I suggested. – kiruwka Oct 28 '14 at 19:23
  • I show you a link, which I think it the best way http://www.androidanalyse.com/android-spinner-externalize-user-strings-mapped-to-system-enum/ – Urchin Oct 29 '14 at 20:43
2

You must know that enums are initialized statically. Each of ONE, TWO, THREE is static.

In android to use resources, such as strings, you need a context.

Generally, you can not access Android context in static methods or initializes, therefore you can't use them with enums.

Even if you could use a hack to make android context statically available you would still have issues :

  • you'd need to ensure none of your OrderType enums accessed before Application#onCreate
  • strings in your enums won't reflect runtime language changes

Edit
I hope it is clear that you can not reliably initialize your enums with string resources.
You could, however, associate static id of a string (R.string.string_name) with your enum and obtain needed resource string later using a context, as proposed in kcoppock's answer.

Community
  • 1
  • 1
kiruwka
  • 9,250
  • 4
  • 30
  • 41
1

You should keep the strings in your string xml resource. That way you can get it from there into your code. For example like this:

String one = getResources().getString(R.string.num_one);

Then you just put a strings.xml file with overloading values in the language folders you want (values-ru, values-sv etc.)

Christoffer
  • 7,470
  • 9
  • 39
  • 55
0

For tasks of that kind use localizations.

"google on i18n java"

and

"android app localization"
vusan
  • 5,221
  • 4
  • 46
  • 81
Puh
  • 305
  • 1
  • 10
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient [reputation](http://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](http://stackoverflow.com/help/privileges/comment). – vusan Oct 27 '14 at 18:51
  • Great, but i don't have enough reputation to comment his post... and actually it's complete answer, because author asks how to fix bad approach... and my answer is : "don't even try to make it in this way". – Puh Oct 27 '14 at 19:02
  • Please add some more detail or code to your answer. Informing you it was on the way of deletion. – vusan Oct 27 '14 at 19:15
  • Ok you can format your answer or add some text so that it looks like an answer. Otherwise it just looks like commentary to the question. – vusan Oct 27 '14 at 19:27
-1
public enum OrderType {

    One(mActivity.getString(R.string.One)), Two(mActivity.getString(R.string.Two));

    private String name;

    private OrderType(String name) {
        this.name = name;
    }

    public String toString() {
        return name;
    }

    public static String getEnumByString(String code) {
        for (OrderType e : OrderType.values()) {
            if (code.equals(e.name)) {
                return e.name();
            }
        }
        return null;
    }
}

also Here is the link, which I think is best way solve the porblem. This developing for API level 11 currently, however this code should run on higher versions. After a quick review in API 16 I did not see an existing core Android solution to this problem, if you know of one please post below and share.

Urchin
  • 464
  • 1
  • 4
  • 14