<NME> WaypointType.java
<BEF> package cgeo.geocaching.enumerations;

import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.R;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Enum listing waypoint types
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

/**
 * Enum listing waypoint types
 */

    public final String id;
    public final int stringId;
    private String l10n; // not final because the locale can be changed
    public final int markerId;

    private WaypointType(String id, int stringId, int markerId) {
        this.id = id;
        this.stringId = stringId;
        setL10n();
        this.markerId = markerId;
    }

    @NonNull
    public static final List<WaypointType> ALL_TYPES = orderedWaypointTypes(false, false);
     * non public so that <code>null</code> handling can be handled centrally in the enum type itself
     */
    private static final Map<String, WaypointType> FIND_BY_ID;
    public static final Map<WaypointType, String> ALL_TYPES_EXCEPT_OWN = new HashMap<WaypointType, String>();
    static {
        final HashMap<String, WaypointType> mapping = new HashMap<String, WaypointType>();
        for (WaypointType wt : values()) {
            mapping.put(wt.id, wt);
            if (wt != WaypointType.OWN) {
                ALL_TYPES_EXCEPT_OWN.put(wt, wt.getL10n());
            }
        }
        FIND_BY_ID = Collections.unmodifiableMap(mapping);
    public final int markerId;

    public final int order;
    public final int dotMarkerId;

    WaypointType(@NonNull final String id, @NonNull final String shortId, @NonNull final String gpx, @StringRes final int stringId, @StringRes final int stringIdNewWpt, @DrawableRes final int markerId, final int order, @DrawableRes final int dotMarkerId) {
        this.id = id;
        this.shortId = shortId;
        this.gpx = gpx;
        this.stringId = stringId;
        this.stringIdNewWpt = stringIdNewWpt;
        this.markerId = markerId;
        this.order = order;
        this.dotMarkerId = dotMarkerId;
    }
    }

    public final String getL10n() {
        return l10n;
    }

    public void setL10n() {
        this.l10n = cgeoapplication.getInstance().getBaseContext().getResources().getString(this.stringId);
        if (WaypointType.ALL_TYPES_EXCEPT_OWN != null && WaypointType.ALL_TYPES_EXCEPT_OWN.containsKey(this)) {
            WaypointType.ALL_TYPES_EXCEPT_OWN.put(this, this.getL10n());
        }
    }

    @Override
    public final String toString() {
            FIND_BY_ID.put(wt.id, wt);
        }
    }

    private static List<WaypointType> orderedWaypointTypes(final boolean excludeInternalTypes, final boolean excludeGenerated) {
        // enforce an order for these types
        final Set<WaypointType> waypointTypes = new LinkedHashSet<>();
        waypointTypes.addAll(Arrays.asList(PARKING, TRAILHEAD, PUZZLE, STAGE, FINAL));
        // then add all remaining except "internal" types
        waypointTypes.addAll(EnumSet.complementOf(EnumSet.of(OWN, ORIGINAL, GENERATED)));
        if (!excludeInternalTypes) {
            //if wanted, add internal types at the end
            waypointTypes.addAll(EnumSet.of(OWN, ORIGINAL));
        }
        if (!excludeGenerated) {
            waypointTypes.add(GENERATED);
        }
        return Collections.unmodifiableList(new ArrayList<>(waypointTypes));
    }

    /**
     * inverse lookup of waypoint IDs<br/>
     * here the {@code null} handling shall be done
     */
    @NonNull
    public static WaypointType findById(final String id) {
        if (id == null) {
            return WAYPOINT;
        }
        final WaypointType waypointType = FIND_BY_ID.get(id);
        if (waypointType == null) {
            return WAYPOINT;
        }
        return waypointType;
    }

    @NonNull
    public final String getL10n() {
        //enable local unit testing
        if (CgeoApplication.getInstance() == null) {
            return name();
        }
        return CgeoApplication.getInstance().getBaseContext().getString(stringId);
    }

    @NonNull
    public final String getNameForNewWaypoint() {
        //enable local unit testing
        if (CgeoApplication.getInstance() == null) {
            return name();
        }
        return CgeoApplication.getInstance().getBaseContext().getString(stringIdNewWpt);
    }

    @NonNull
    public final String getShortId() {
        return shortId;
    }

    @Override
    public final String toString() {
        return getL10n();
    }

    public boolean applyDistanceRule() {
        return this == FINAL || this == STAGE;
    }

    public static WaypointType fromGPXString(@NonNull final String sym) {
        return fromGPXString(sym, null);
    }

    public static WaypointType fromGPXString(@NonNull final String sym, final String subtype) {
        // first check the somewhat "official" sym types
        for (final WaypointType waypointType : WaypointType.values()) {
            if (waypointType.gpx.equalsIgnoreCase(sym)) {
                return waypointType;
            }
            // Maybe the <sym> element was used for a Garmin symbol (e.g. Opencaching GPX).
            // Try the subtype instead if defined
            if (waypointType.gpx.equalsIgnoreCase(subtype)) {
                return waypointType;
            }
        }

        // old names of multi cache stages
        if ("stages of a multicache".equalsIgnoreCase(sym)) {
            return WaypointType.STAGE;
        }
        if ("stage of a multicache".equalsIgnoreCase(sym)) {
            return WaypointType.STAGE;
        }
        if ("question to answer".equalsIgnoreCase(sym)) {
            return WaypointType.PUZZLE;
        }

        // this is not fully correct, but lets also look for localized waypoint types
        for (final WaypointType waypointType : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) {
            final String localized = waypointType.getL10n();
            if (StringUtils.isNotEmpty(localized) && localized.equalsIgnoreCase(sym)) {
                return waypointType;
            }
        }
        return WaypointType.WAYPOINT;
    }
}

<MSG> fix #1347: no more caching of localized texts in enums

<DFF> @@ -5,7 +5,9 @@ import cgeo.geocaching.cgeoapplication;
 
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Enum listing waypoint types
@@ -23,13 +25,11 @@ public enum WaypointType {
 
     public final String id;
     public final int stringId;
-    private String l10n; // not final because the locale can be changed
     public final int markerId;
 
     private WaypointType(String id, int stringId, int markerId) {
         this.id = id;
         this.stringId = stringId;
-        setL10n();
         this.markerId = markerId;
     }
 
@@ -38,13 +38,13 @@ public enum WaypointType {
      * non public so that <code>null</code> handling can be handled centrally in the enum type itself
      */
     private static final Map<String, WaypointType> FIND_BY_ID;
-    public static final Map<WaypointType, String> ALL_TYPES_EXCEPT_OWN = new HashMap<WaypointType, String>();
+    public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN = new HashSet<WaypointType>();
     static {
         final HashMap<String, WaypointType> mapping = new HashMap<String, WaypointType>();
         for (WaypointType wt : values()) {
             mapping.put(wt.id, wt);
             if (wt != WaypointType.OWN) {
-                ALL_TYPES_EXCEPT_OWN.put(wt, wt.getL10n());
+                ALL_TYPES_EXCEPT_OWN.add(wt);
             }
         }
         FIND_BY_ID = Collections.unmodifiableMap(mapping);
@@ -66,15 +66,9 @@ public enum WaypointType {
     }
 
     public final String getL10n() {
-        return l10n;
+        return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId);
     }
 
-    public void setL10n() {
-        this.l10n = cgeoapplication.getInstance().getBaseContext().getResources().getString(this.stringId);
-        if (WaypointType.ALL_TYPES_EXCEPT_OWN != null && WaypointType.ALL_TYPES_EXCEPT_OWN.containsKey(this)) {
-            WaypointType.ALL_TYPES_EXCEPT_OWN.put(this, this.getL10n());
-        }
-    }
 
     @Override
     public final String toString() {

fix #1347: no more caching of localized texts in enums