ResourceBundle that defaults to English
Asked Answered
C

2

11

Setup

Let's say I have 2 strings files:

Strings_en.properties
Strings_fr.properties

Let's say English is the default language, and all the strings are present, while French lags behind and some strings are missing.

Desired behavior

I want to fall back to English in both of these cases:

  • When requesting a completely different locale, such as German.
    • ResourceBundle.getBundle("path/to/Strings", Locale.GERMAN);
  • When requesting a string missing from French.
    • ResourceBundle.getBundle("path/to/Strings", Locale.FRENCH).getString("only.in.english");

The first fallback is simple enough: as per the documentation, it's enough to have English as the default locale, for example by setting Locale.setDefault(Locale.ENGLISH);.

Problem

My problem is with the second fallback. If the string is not found in Strings_fr, the lookup continues to the "parent bundle": getObject() documentation. However, Strings_en is not the parent of Strings_fr and a MissingResourceException is thrown.

Workaround

A simple fix is to rename Strings_en.properties to Strings.properties. This makes it the parent bundle for Strings_fr (and for any other Strings_, for that matter) and looking up missing strings returns the default English versions.

Problem: the system now has a default localization, but it no longer understands that there is an English localization.

Workaround 2

When fetching a string, check if it's present in the bundle - if not, fetch it from the English one instead.

ResourceBundle bundle = ResourceBundle.getBundle("path/to/Strings", Locale.FRENCH);
if (bundle.containsKey(key)) { return bundle.getString(key); }
return ResourceBundle.getBundle("path/to/Strings", DEFAULT_WHICH_IS_ENGLISH).getString(key);

Problem: this is just a hack, I believe there is an "intended" way to do it.

Question

Is there a simple way to make Strings_en the parent of Strings_fr? If not, is it reasonable to for example hardlink Strings_en to Strings, so that I can keep English as an explicit localization and at the same time as the default one?

Citarella answered 15/3, 2016 at 12:46 Comment(3)
regarding solution 1: but it no longer understands that there is an English localization: ResourceBundle.getBundle("path/to/Strings", Locale.ENGLISH) will also give you a bundle based on Strings.propertiesWysocki
Yes, but the system does not know it's English. If I ask "what language strings are available?", it cannot include "English".Citarella
Good point, as a matter of fact no piece of code is enumerating the *.properties files to determine the supported languages. So I guess it's just a matter of personal preference: it's the English localization, it shouldn't be hidden under default.Citarella
W
14

You can rename Strings_en.properties to Strings.properties (making English the default localization) and add a new empty Strings_en.properties.

Then

ResourceBundle.getBundle("path/to/Strings", Locale.ENGLISH).getLocale()

also returns Locale.ENGLISH.

Wysocki answered 15/3, 2016 at 13:6 Comment(2)
Wow, cool! Did not think of that. Let me quickly evaluate how it fits into the code and get back to you.Citarella
So, it does the trick. Eclipse's ResourceBundleEditor has survived this correctly, Weblate is confused as hell but whatever, the code works fine. Thanks a lot, accepted.Citarella
C
1

Old thread, another solution: You can use ResourceBundle.Control and getCandidateLocales to add custom language candidates (file suffix)

ResourceBundle.getBundle(baseName, locale, new ResourceBundle.Control() {
    @Override
    public List<Locale> getCandidateLocales(String baseName, Locale locale) {
      List<Locale> list = super.getCandidateLocales(baseName, locale);
      list.add(new Locale("en"));
      return list;
    }
  }
Chadchadabe answered 25/2, 2021 at 18:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.