Created
January 14, 2023 20:45
-
-
Save ktprezes/c295f374328948d0af2630583499eca4 to your computer and use it in GitHub Desktop.
Kotlin - reading resource bundle from the XML file(s) instead of '.properties' file(s)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> | |
<properties> | |
<comment>default locales related file</comment> | |
<entry key="app_name">My App</entry> | |
<entry key="prop1">Example 1</entry> | |
</properties> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> | |
<properties> | |
<comment>polish locales related file</comment> | |
<entry key="app_name">Moja apka</entry> | |
<entry key="prop1">Przykład 1</entry> | |
</properties> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import utils.XMLResourceBundle | |
import utils.XMLResourceBundleControl | |
import java.util.* | |
fun main() { | |
val resBndl1 = ResourceBundle.getBundle("props", Locale.forLanguageTag("pl"), XMLResourceBundleControl()) | |
println(resBndl1.getString("app_name") // prints: "Moja apka" | |
val resBndl2 = XMLResourceBundle.getBundle("props") // gets default Locale | |
println(resBndl2.getString("prop1") // prints: "Example 1" | |
} // fun main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package utils | |
import java.io.InputStream | |
import java.util.* | |
// see also: | |
// https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/util/ResourceBundle.Control.html | |
// https://gist.github.com/asicfr/1b76ea60029264d7be15d019a866e1a4 | |
/** | |
* Represents ResourceBundle read from the XML file instead of the '.properties' file | |
*/ | |
class XMLResourceBundle(stream: InputStream?) : ResourceBundle() { | |
private val props: Properties = Properties() | |
private val selfKeys: Set<String> | |
get() = props.keys.map { it.toString() }.toSet() | |
init { props.loadFromXML(stream) } | |
public override fun handleKeySet(): Set<String> = selfKeys | |
// implementation of abstract methods of the parent class ResourceBundle | |
override fun handleGetObject(key: String): Any? = props.getProperty(key) | |
override fun getKeys(): Enumeration<String> = | |
Collections.enumeration(selfKeys union if (parent != null) parent.keySet() else emptySet()) | |
companion object { | |
fun getBundle( | |
baseName: String, | |
locale: Locale = Locale.getDefault(), | |
loader: ClassLoader? = null | |
): XMLResourceBundle = ( | |
if (loader == null) | |
ResourceBundle.getBundle(baseName, locale, XMLResourceBundleControl()) | |
else | |
ResourceBundle.getBundle(baseName, locale, loader, XMLResourceBundleControl()) | |
) as XMLResourceBundle | |
} // companion object | |
} // class XMLResourceBundle(stream:InputStream?) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package utils | |
import java.io.BufferedInputStream | |
import java.io.IOException | |
import java.util.* | |
// see also: | |
// https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/util/ResourceBundle.Control.html | |
// https://gist.github.com/asicfr/1b76ea60029264d7be15d019a866e1a4 | |
class XMLResourceBundleControl : ResourceBundle.Control() { | |
@Throws(IllegalAccessException::class, InstantiationException::class, IOException::class) | |
override fun newBundle( | |
baseName: String?, | |
locale: Locale?, | |
format: String?, | |
loader: ClassLoader?, | |
reload: Boolean | |
): ResourceBundle? { | |
require(!(baseName == null || locale == null || format == null || loader == null)) { | |
"baseName, locale, format and loader cannot be all null" | |
} | |
require(format == XML) { "format must be xml" } | |
val bundleName: String = toBundleName(baseName, locale) | |
val resourceName = toResourceName(bundleName, format) | |
val url = loader.getResource(resourceName) ?: return null | |
val urlConn = url.openConnection() ?: return null | |
if (reload) { urlConn.useCaches = false } | |
return urlConn.getInputStream()?.use { stream -> BufferedInputStream(stream).use (::XMLResourceBundle) } | |
} // override fun newBundle(...): ResourceBundle? | |
override fun getFormats(baseName: String?): List<String> = SINGLETON_LIST | |
companion object { | |
private const val XML = "xml" | |
private val SINGLETON_LIST = listOf(XML) | |
} | |
} // class XMLResourceBundleControl |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment