1 package org.djunits.locale;
2
3 import java.io.Serializable;
4 import java.util.Locale;
5 import java.util.MissingResourceException;
6 import java.util.ResourceBundle;
7
8 import org.djutils.exceptions.Throw;
9
10 /**
11 * Localization object for language specific reporting of units.
12 * <p>
13 * Copyright (c) 2013-2025 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
14 * BSD-style license. See <a href="https://djunits.org/docs/license.html">DJUNITS License</a>
15 * </p>
16 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
17 * @author <a href="https://tudelft.nl/pknoppers">Peter Knoppers</a>
18 */
19 public class UnitLocale implements Serializable
20 {
21 /** */
22 private static final long serialVersionUID = 20200118L;
23
24 /** filename without .properties, to be found in the /resources folder. */
25 private final String bundleNamePrefix;
26
27 /** the resource bundle. */
28 private transient ResourceBundle resourceBundle;
29
30 /** current locale. */
31 private Locale currentLocale = null;
32
33 /** the fallback resource bundle. */
34 private final transient ResourceBundle fallbackResourceBundle;
35
36 /** fallback locale. */
37 private final Locale fallbackLocale;
38
39 /**
40 * Create a localization object for units and unit systems. The prefix is right now either "unit" or "unitsystem".
41 * @param prefix the prefix of the properties files to use.
42 */
43 public UnitLocale(final String prefix)
44 {
45 Throw.whenNull(prefix, "prefix cannot be null");
46 this.bundleNamePrefix = prefix;
47 this.fallbackLocale = new Locale("en");
48 this.fallbackResourceBundle = ResourceBundle.getBundle("resources/locale/" + prefix, this.fallbackLocale);
49 }
50
51 /**
52 * Reload the resource bundle if necessary.
53 */
54 public void checkReload()
55 {
56 if (this.currentLocale == null || !this.currentLocale.equals(Locale.getDefault(Locale.Category.DISPLAY)))
57 {
58 this.currentLocale = Locale.getDefault(Locale.Category.DISPLAY);
59 try
60 {
61 this.resourceBundle = ResourceBundle.getBundle("resources/locale/" + this.bundleNamePrefix, this.currentLocale);
62 }
63 catch (MissingResourceException e)
64 {
65 this.resourceBundle = null;
66 }
67 }
68 }
69
70 /**
71 * Retrieve a string from a resource bundle. If retrieval fails, try the fallbackLocale. If that fails as well, return the
72 * value of key string, surrounded by exclamation marks. When the DefaultLocale has changed, load a new ResourceBundle.
73 * @param key the key for the locale in the currently valid resource bundle
74 * @return localized string, or, if the key could not be found, the key surrounded by exclamation marks
75 */
76 public final String getString(final String key)
77 {
78 checkReload();
79 if (null == this.resourceBundle)
80 {
81 // Failed to find the resourceBundle (on a previous call to getString)
82 return getFallbackString(key);
83 }
84 try
85 {
86 return this.resourceBundle.getString(key);
87 }
88 catch (MissingResourceException e)
89 {
90 return getFallbackString(key);
91 }
92 }
93
94 /**
95 * Retrieve a string from the falback bundle. If retrieval fails, return the value of key string, surrounded by exclamation
96 * marks.
97 * @param key the key for the fallback locale to look up in the resource bundle
98 * @return localized string, or, if the key could not be found, the key surrounded by exclamation marks
99 */
100 public final String getFallbackString(final String key)
101 {
102 try
103 {
104 return this.fallbackResourceBundle.getString(key);
105 }
106 catch (MissingResourceException e)
107 {
108 return '!' + key.substring(key.indexOf('.') + 1) + '!';
109 }
110 }
111
112 @Override
113 public String toString()
114 {
115 return "Localization [bundleNamePrefix=" + this.bundleNamePrefix + ", currentLocale=" + this.currentLocale
116 + ", fallbackLocale=" + this.fallbackLocale + "]";
117 }
118
119 }