diff --git a/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/JVMLocale.kt b/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/JVMLocale.kt index 9aab28ae..479724cc 100644 --- a/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/JVMLocale.kt +++ b/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/JVMLocale.kt @@ -3,7 +3,7 @@ package eu.iamgio.quarkdown.document.locale /** * [Locale] implementation using [java.util.Locale]. */ -internal class JVMLocale(private val jvmLocale: java.util.Locale) : Locale { +internal data class JVMLocale(private val jvmLocale: java.util.Locale) : Locale { override val code: String get() = jvmLocale.language diff --git a/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/JVMLocaleLoader.kt b/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/JVMLocaleLoader.kt index a04ca626..5d53a06b 100644 --- a/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/JVMLocaleLoader.kt +++ b/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/JVMLocaleLoader.kt @@ -1,14 +1,22 @@ package eu.iamgio.quarkdown.document.locale +private typealias JLocale = java.util.Locale + /** * Loader of [JVMLocale]s. */ internal object JVMLocaleLoader : LocaleLoader { override val all: Iterable - get() = java.util.Locale.getAvailableLocales().map(::JVMLocale) + get() = JLocale.getAvailableLocales().map(::JVMLocale) - override fun fromTag(tag: String): Locale? = - java.util.Locale.forLanguageTag(tag) - ?.let(::JVMLocale) + private fun JLocale?.toLocale() = + this?.let(::JVMLocale) ?.takeIf { it.code.isNotBlank() } + + override fun fromTag(tag: String): Locale? = JLocale.forLanguageTag(tag)?.toLocale() + + override fun fromName(name: String): Locale? = + JLocale.getAvailableLocales() + .find { it.getDisplayName(JLocale.ENGLISH).equals(name, ignoreCase = true) } + ?.toLocale() } diff --git a/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/LocaleLoader.kt b/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/LocaleLoader.kt index cf02f085..d7301219 100644 --- a/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/LocaleLoader.kt +++ b/core/src/main/kotlin/eu/iamgio/quarkdown/document/locale/LocaleLoader.kt @@ -16,6 +16,20 @@ interface LocaleLoader { */ fun fromTag(tag: String): Locale? + /** + * @param name English name of the locale. + * Example: `English`, `Italian`, `French` + * @return [Locale] with the given name, or `null` if not found + */ + fun fromName(name: String): Locale? + + /** + * Finds a locale by its tag or name. + * @param identifier tag (`en`, `it`, `fr-CA`) or English name (`English`, `Italian`, `French (Canada)`) of the locale + * @return [Locale] with the given tag or name, or `null` if not found + */ + fun find(identifier: String): Locale? = fromName(identifier) ?: fromTag(identifier) + companion object { /** * Default system [LocaleLoader] implementation. diff --git a/core/src/test/kotlin/eu/iamgio/quarkdown/MiscTest.kt b/core/src/test/kotlin/eu/iamgio/quarkdown/MiscTest.kt index 5e2414bb..c5a8d615 100644 --- a/core/src/test/kotlin/eu/iamgio/quarkdown/MiscTest.kt +++ b/core/src/test/kotlin/eu/iamgio/quarkdown/MiscTest.kt @@ -17,6 +17,9 @@ class MiscTest { with(retriever.fromTag("en")) { assertNotNull(this) + assertEquals(this, retriever.fromName("English")) + assertEquals(this, retriever.find("English")) + assertEquals(this, retriever.find("eNgLiSh")) assertEquals("en", code) assertEquals("en", tag) assertEquals("English", localizedName) @@ -24,8 +27,11 @@ class MiscTest { assertNull(localizedCountryName) } - with(retriever.fromTag("it")) { + with(retriever.find("it")) { assertNotNull(this) + assertEquals(this, retriever.fromName("Italian")) + assertEquals(this, retriever.find("Italian")) + assertEquals(this, retriever.find("iTaLiAn")) assertEquals("it", code) assertEquals("it", tag) assertEquals("italiano", localizedName) @@ -33,8 +39,10 @@ class MiscTest { assertNull(localizedCountryName) } - with(retriever.fromTag("en-US")) { + with(retriever.find("en-US")) { assertNotNull(this) + assertEquals(this, retriever.find("English (United States)")) + assertEquals(this, retriever.find("En-us")) assertEquals("en", code) assertEquals("en-US", tag) assertEquals("English (United States)", localizedName) @@ -42,17 +50,9 @@ class MiscTest { assertEquals("United States", localizedCountryName) } - with(retriever.fromTag("En-us")) { - assertNotNull(this) - assertEquals("en", code) - assertEquals("en-US", tag) - assertEquals("English (United States)", localizedName) - assertEquals("US", countryCode) - assertEquals("United States", localizedCountryName) - } - - with(retriever.fromTag("fr-CA")) { + with(retriever.find("fr-CA")) { assertNotNull(this) + assertEquals(this, retriever.find("French (Canada)")) assertEquals("fr", code) assertEquals("fr-CA", tag) assertEquals("français (Canada)", localizedName) @@ -61,6 +61,8 @@ class MiscTest { } assertNull(retriever.fromTag("nonexistent")) + assertNull(retriever.fromName("nonexistent")) + assertNull(retriever.find("nonexistent")) assertTrue(retriever.all.iterator().hasNext()) } diff --git a/stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Document.kt b/stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Document.kt index 662e6e3b..f8df58fc 100644 --- a/stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Document.kt +++ b/stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Document.kt @@ -118,23 +118,26 @@ fun docAuthor( ) /** - * If [localeTag] is not `null`, it sets the document locale to its value. + * If [locale] is not `null`, it sets the document locale to its value. * If it's `null`, the localized name of the current document locale is returned. - * @param localeTag (optional) well-formed, case-insensitive, locale tag to assign to the document. Example: `en-US`, `it`, `fr-CA` - * @return the localized name of the current document locale if [localeTag] is `null` + * @param locale (optional) case-insensitive, + * either a locale tag (e.g. `en`, `en-US`, `it`, `fr-CA`) + * or an English name of a locale (e.g. `English`, `English (United States)`, `Italian`, `French (Canada)`) + * to assign to the document + * @return the localized name of the current document locale if [locale] is `null` * @throws IllegalArgumentException if the locale tag is not invalid or not found */ @Name("doclang") fun docLanguage( @Injected context: Context, - @Name("locale") localeTag: String? = null, + locale: String? = null, ): OutputValue<*> = context.modifyOrEchoDocumentInfo( - localeTag, + locale, get = { this.locale?.localizedName ?: "" }, set = { this.locale = - LocaleLoader.SYSTEM.fromTag(it) + LocaleLoader.SYSTEM.find(it) ?: throw IllegalArgumentException("Locale $it not found") }, )