Skip to content

Commit

Permalink
Allow searching locale by name or tag
Browse files Browse the repository at this point in the history
  • Loading branch information
iamgio committed Aug 1, 2024
1 parent 86c4b19 commit 1f1e5e7
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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<Locale>
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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
26 changes: 14 additions & 12 deletions core/src/test/kotlin/eu/iamgio/quarkdown/MiscTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,42 @@ 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)
assertNull(countryCode)
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)
assertNull(countryCode)
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)
assertEquals("US", countryCode)
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)
Expand All @@ -61,6 +61,8 @@ class MiscTest {
}

assertNull(retriever.fromTag("nonexistent"))
assertNull(retriever.fromName("nonexistent"))
assertNull(retriever.find("nonexistent"))

assertTrue(retriever.all.iterator().hasNext())
}
Expand Down
15 changes: 9 additions & 6 deletions stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Document.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
},
)
Expand Down

0 comments on commit 1f1e5e7

Please sign in to comment.