dbro
dbro

Reputation: 1728

Unifying enum.values() across multiple human languages

My Android app uses an enum type to define certain API endpoints.

public static enum API_ENDPOINT{
        MISSION, FEATURED_MEDIA
}

The enum type seems an appropriate argument for methods that are dependent on the API call type, but I'm unable to translate enums to consistent Strings (i.e for mapping to API endpoint urls) across devices configured with different languages.

In Turkish API_ENDPOINT.values() returns: mıssıon, featured_medıa

In English API_ENDPOINT.values() returns: mission, featured_media

An obvious solution is an additional data structure that maps API_ENDPOINT to hard-coded string endpoints, but I'm curious as to whether this behavior of enum.values() is intended and/or avoidable.

Solved: Thanks everyone for the insight. It turns out deeper in the logic to convert API_ENDPOINT to a URL string I used String.toLowerCase() without specifying a Locale, which resulted in the undesirable behavior. This has been replaced with String.toLowerCase(Locale.US)

Upvotes: 2

Views: 566

Answers (2)

blahdiblah
blahdiblah

Reputation: 34031

You can hard-code the strings as part of the enum, without any additional data structure:

public static enum API_ENDPOINT{
    MISSION("mission"), FEATURED_MEDIA("featured_media");
    private final String value;
    API_ENDPOINT(String value) { this.value = value; }
    public String value() { return value; }
}

but it would be nice if there were just a way to control the representation that's automatically generated.

The JLS enum section doesn't speak directly to language differences like this, but strongly suggests that the output would exactly match the enum identifiers; I'm surprised that you'd even get lower-case strings with upper-case identifiers.


After further testing, this isn't reproducible, something else must be going on in your code.

This minimal program displays the enum identifiers exactly as typed regardless of locale:

public class MainActivity extends Activity {
    public enum ENUM {
        MISSION, FEATURED_MEDIA
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView textView = (TextView) findViewById(R.id.text);
        String enums = "";
        for (ENUM e : ENUM.values()) {
            enums += e + " ";
        }
        textView.setText(enums);
    }
}

Upvotes: 2

L.Butz
L.Butz

Reputation: 2616

You can define two property-files. One for English and one for Turkish.
The Enum could then look like this:

public static enum API_ENDPOINT{
    MISSION("path.to.property.mission"), FEATURED_MEDIA("path.to.property.featured_media");

    private String propertyName;
    API_ENDPOINT(String propertyName){
        this.propertyName = propertyName;
    }

    // language could also be an enum which defines the language to be taken
    // and should contain the path to the file.
    public String getTranslatedText(Language language){
        Properties prop = new Properties();

        try {
            //load a properties file from class path
            prop.load(API_ENDPOINT.class.getClassLoader().getResourceAsStream(language.getPropertyFileName()));

            //get the translated value and raturn it.
            return prop.getProperty(propertyName);

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

The Property-File will look like this (English):

path.to.property.mission=Mission
path.to.property.featured_media=Featured Media

Same goes for Turkish. Hope that helps.

EDIT: Due to you are using Android, this might be the solution for your problem:

Upvotes: 2

Related Questions