mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-23 07:39:11 +00:00
add list of known dictionaries for more convenient links
This commit is contained in:
parent
b1eb33f6e2
commit
fd95b4dc87
10 changed files with 215 additions and 3 deletions
|
@ -124,6 +124,10 @@ See [layouts.md](layouts.md#adding-new-layouts--languages) for how to add new la
|
||||||
|
|
||||||
See make-emoji-keys tool [README](tools/make-emoji-keys/README.md).
|
See make-emoji-keys tool [README](tools/make-emoji-keys/README.md).
|
||||||
|
|
||||||
|
### Update List of Existing Dictionaries
|
||||||
|
|
||||||
|
See make-dict-list tool [README](tools/make-dict-list/README.md).
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
HeliBoard (as a fork of OpenBoard) is licensed under GNU General Public License v3.0.
|
HeliBoard (as a fork of OpenBoard) is licensed under GNU General Public License v3.0.
|
||||||
|
|
85
app/src/main/assets/dictionaries_in_dict_repo.csv
Normal file
85
app/src/main/assets/dictionaries_in_dict_repo.csv
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
main,ar,
|
||||||
|
main,hy,
|
||||||
|
main,as,
|
||||||
|
main,bn,
|
||||||
|
main,by,
|
||||||
|
main,bg,
|
||||||
|
main,ca,
|
||||||
|
main,hr,
|
||||||
|
main,cs,
|
||||||
|
main,da,
|
||||||
|
main,nl,
|
||||||
|
main,en_AU,
|
||||||
|
main,en_GB,
|
||||||
|
main,en_US,
|
||||||
|
emoji,en,
|
||||||
|
main,eo,
|
||||||
|
main,fi,
|
||||||
|
emoji,fr,
|
||||||
|
main,fr,
|
||||||
|
main,gl,
|
||||||
|
main,ka,
|
||||||
|
main,de,
|
||||||
|
main,gom,
|
||||||
|
main,el,
|
||||||
|
main,gu,
|
||||||
|
main,he,
|
||||||
|
main,iw,
|
||||||
|
main,hi,
|
||||||
|
main,hi_ZZ,
|
||||||
|
main,hu,
|
||||||
|
main,it,
|
||||||
|
main,kn,
|
||||||
|
main,ks,
|
||||||
|
main,lv,
|
||||||
|
main,lt,
|
||||||
|
main,lb,
|
||||||
|
main,mai,
|
||||||
|
main,ml,
|
||||||
|
main,mr,
|
||||||
|
main,nb,
|
||||||
|
main,or,
|
||||||
|
main,pl,
|
||||||
|
main,pt_BR,
|
||||||
|
main,pt_PT,
|
||||||
|
main,pa,
|
||||||
|
main,ro,
|
||||||
|
emoji,ru,
|
||||||
|
main,ru,
|
||||||
|
main,sa,
|
||||||
|
main,sat,
|
||||||
|
main,sr_ZZ,
|
||||||
|
main,sr,
|
||||||
|
main,sd,
|
||||||
|
main,sl,
|
||||||
|
main,es,
|
||||||
|
main,sv,
|
||||||
|
main,ta,
|
||||||
|
main,te,
|
||||||
|
main,tok,
|
||||||
|
main,tcy,
|
||||||
|
main,tr,
|
||||||
|
main,uk,
|
||||||
|
main,ur,
|
||||||
|
main,af,exp
|
||||||
|
main,ar,exp
|
||||||
|
main,bn,exp
|
||||||
|
main,bg,exp
|
||||||
|
main,cs,exp
|
||||||
|
main,en_GB,exp
|
||||||
|
main,en_US,exp
|
||||||
|
symbols,en,exp
|
||||||
|
symbols,fr,exp
|
||||||
|
main,fr,exp
|
||||||
|
main,de_AT,exp
|
||||||
|
main,de,exp
|
||||||
|
main,id,exp
|
||||||
|
main,it,exp
|
||||||
|
main,kab,exp
|
||||||
|
addon,ml_ZZ,exp
|
||||||
|
main,ru,exp
|
||||||
|
main,sk,exp
|
||||||
|
main,es,exp
|
||||||
|
main,uk,exp
|
||||||
|
main,vi,exp
|
||||||
|
|
|
|
@ -91,7 +91,7 @@ object LocaleUtils {
|
||||||
* @param tested the locale to test.
|
* @param tested the locale to test.
|
||||||
* @return a constant that measures how well the tested locale matches the reference locale.
|
* @return a constant that measures how well the tested locale matches the reference locale.
|
||||||
*/
|
*/
|
||||||
private fun getMatchLevel(reference: Locale, tested: Locale): Int {
|
fun getMatchLevel(reference: Locale, tested: Locale): Int {
|
||||||
if (reference == tested) return LOCALE_FULL_MATCH
|
if (reference == tested) return LOCALE_FULL_MATCH
|
||||||
if (reference.toString().isEmpty()) return LOCALE_ANY_MATCH
|
if (reference.toString().isEmpty()) return LOCALE_ANY_MATCH
|
||||||
if (reference.language != tested.language) return LOCALE_NO_MATCH
|
if (reference.language != tested.language) return LOCALE_NO_MATCH
|
||||||
|
|
|
@ -268,10 +268,41 @@ class LanguageSettingsDialog(
|
||||||
binding.secondaryLocales.addView(rowBinding.root)
|
binding.secondaryLocales.addView(rowBinding.root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createDictionaryText(locale: Locale, context: Context): String {
|
||||||
|
val link = "<a href='$DICTIONARY_URL'>" + context.getString(R.string.dictionary_link_text) + "</a>"
|
||||||
|
val message = context.getString(R.string.add_dictionary, link)
|
||||||
|
val knownDicts = mutableListOf<String>()
|
||||||
|
context.assets.open("dictionaries_in_dict_repo.csv").reader().forEachLine {
|
||||||
|
if (it.isBlank()) return@forEachLine
|
||||||
|
val (type, localeString, experimental) = it.split(",")
|
||||||
|
// we use a locale string here because that's in the dictionaries repo
|
||||||
|
// ideally the repo would switch to language tag, but not sure how this is handled in the dictionary header
|
||||||
|
// further, the dicts in the dictionaries repo should be compatible with other AOSP-based keyboards
|
||||||
|
val dictLocale = localeString.constructLocale()
|
||||||
|
if (LocaleUtils.getMatchLevel(locale, dictLocale) < 3) return@forEachLine
|
||||||
|
val rawDictString = "$type: ${dictLocale.getDisplayName(context.resources.configuration.locale())}"
|
||||||
|
val dictString = if (experimental.isEmpty()) rawDictString
|
||||||
|
else context.getString(R.string.available_dictionary_experimental, rawDictString)
|
||||||
|
val dictBaseUrl = DICTIONARY_URL + DICTIONARY_DOWNLOAD_SUFFIX +
|
||||||
|
if (experimental.isEmpty()) DICTIONARY_NORMAL_SUFFIX else DICTIONARY_EXPERIMENTAL_SUFFIX
|
||||||
|
val dictLink = dictBaseUrl + type + "_" + localeString.lowercase() + ".dict"
|
||||||
|
val fullText = "<li><a href='$dictLink'>$dictString</a></li>"
|
||||||
|
knownDicts.add(fullText)
|
||||||
|
}
|
||||||
|
if (knownDicts.isEmpty()) return message
|
||||||
|
return """
|
||||||
|
<p>$message</p>
|
||||||
|
<b>${context.getString(R.string.dictionary_available)}</b>
|
||||||
|
<ul>
|
||||||
|
${knownDicts.joinToString("\n")}
|
||||||
|
</ul>
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
private fun fillDictionariesView() {
|
private fun fillDictionariesView() {
|
||||||
binding.addDictionary.setOnClickListener {
|
binding.addDictionary.setOnClickListener {
|
||||||
val link = "<a href='$DICTIONARY_URL'>" + context.getString(R.string.dictionary_link_text) + "</a>"
|
val messageRawText = createDictionaryText(mainLocale, context)
|
||||||
val message = SpannableStringUtils.fromHtml(context.getString(R.string.add_dictionary, link))
|
val message = SpannableStringUtils.fromHtml(messageRawText)
|
||||||
val dialog = Builder(context)
|
val dialog = Builder(context)
|
||||||
.setTitle(R.string.add_new_dictionary_title)
|
.setTitle(R.string.add_new_dictionary_title)
|
||||||
.setMessage(message)
|
.setMessage(message)
|
||||||
|
|
|
@ -85,3 +85,6 @@ private fun hasAnythingOtherThanExtractedMainDictionary(dir: File) =
|
||||||
dir.listFiles()?.any { it.name != DictionaryInfoUtils.getExtractedMainDictFilename() } != false
|
dir.listFiles()?.any { it.name != DictionaryInfoUtils.getExtractedMainDictFilename() } != false
|
||||||
|
|
||||||
const val DICTIONARY_URL = "https://codeberg.org/Helium314/aosp-dictionaries"
|
const val DICTIONARY_URL = "https://codeberg.org/Helium314/aosp-dictionaries"
|
||||||
|
const val DICTIONARY_DOWNLOAD_SUFFIX = "/src/branch/main/"
|
||||||
|
const val DICTIONARY_NORMAL_SUFFIX = "dictionaries/"
|
||||||
|
const val DICTIONARY_EXPERIMENTAL_SUFFIX = "dictionaries_experimental/"
|
||||||
|
|
|
@ -547,6 +547,8 @@ New dictionary:
|
||||||
<string name="add_dictionary">"Select a dictionary to add. Dictionaries in .dict format can be downloaded %s."</string>
|
<string name="add_dictionary">"Select a dictionary to add. Dictionaries in .dict format can be downloaded %s."</string>
|
||||||
<!-- Title of the link to the download page inserted into messages (add_dictionary and no_dictionary_message) -->
|
<!-- Title of the link to the download page inserted into messages (add_dictionary and no_dictionary_message) -->
|
||||||
<string name="dictionary_link_text">"here"</string>
|
<string name="dictionary_link_text">"here"</string>
|
||||||
|
<!-- Title of an item in the list of available dictionaries when the dictionary is experimental. This string will be interpreted as HTML -->
|
||||||
|
<string name="available_dictionary_experimental">"%s (experimental)"</string>
|
||||||
<!-- Text shown when dictionary file could not be read -->
|
<!-- Text shown when dictionary file could not be read -->
|
||||||
<string name="dictionary_file_error">"Error: Selected file is not a valid dictionary file"</string>
|
<string name="dictionary_file_error">"Error: Selected file is not a valid dictionary file"</string>
|
||||||
<!-- Text shown when dictionary file is not for the selected locale -->
|
<!-- Text shown when dictionary file is not for the selected locale -->
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
include ':app'
|
include ':app'
|
||||||
include ':tools:make-emoji-keys'
|
include ':tools:make-emoji-keys'
|
||||||
|
include ':tools:make-dict-list'
|
||||||
|
|
5
tools/make-dict-list/README.md
Normal file
5
tools/make-dict-list/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# make-dict-list
|
||||||
|
|
||||||
|
This module takes care of generating a list of dictionaries available in the [dictionaries repository](https://codeberg.org/Helium314/aosp-dictionaries) for convenient linking when adding dictionaries in HeliBoard.
|
||||||
|
|
||||||
|
To use it, simply run `./gradlew tools:make-dict-list:makeDictList`
|
18
tools/make-dict-list/build.gradle
Normal file
18
tools/make-dict-list/build.gradle
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
apply plugin: "java"
|
||||||
|
apply plugin: 'kotlin'
|
||||||
|
|
||||||
|
ext {
|
||||||
|
javaMainClass = "tools.dict.MakeDictList"
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register('makeDictList', JavaExec) {
|
||||||
|
args project.rootProject.project('app').projectDir.path + File.separator + 'src' +
|
||||||
|
File.separator + 'main' + File.separator + 'assets'
|
||||||
|
classpath = sourceSets.main.runtimeClasspath
|
||||||
|
main = javaMainClass
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package tools.dict
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
class MakeDictList {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
@JvmStatic fun main(args: Array<String>) {
|
||||||
|
val readmeUrl = "https://codeberg.org/Helium314/aosp-dictionaries/raw/branch/main/README.md"
|
||||||
|
val readmeText = URL(readmeUrl).readText()
|
||||||
|
val fileText = doIt(readmeText)
|
||||||
|
val targetDir = args[0]
|
||||||
|
|
||||||
|
File(targetDir).mkdirs()
|
||||||
|
File("$targetDir/dictionaries_in_dict_repo.csv").writeText(fileText)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* extract dictionary list from README.md
|
||||||
|
* output format: <localeString>,<type>,<experimental>
|
||||||
|
* <experimental> is empty if dictionary is not experimental, no other check done
|
||||||
|
* requires README.md to have dicts in correct "# Dictionaries" or "# Experimental dictionaries" sections
|
||||||
|
*/
|
||||||
|
private fun doIt(readme: String): String {
|
||||||
|
// output format: <localeString>,<type>,<experimental>
|
||||||
|
// experimental is empty if dictionary is not experimental, no other check done
|
||||||
|
var mode = MODE_NOTHING
|
||||||
|
val outLines = mutableListOf<String>()
|
||||||
|
readme.split("\n").forEach { line ->
|
||||||
|
if (line.startsWith("#")) {
|
||||||
|
mode = if (line.trim() == "# Dictionaries")
|
||||||
|
MODE_NORMAL
|
||||||
|
else if (line.trim() == "# Experimental dictionaries")
|
||||||
|
MODE_EXPERIMENTAL
|
||||||
|
else
|
||||||
|
MODE_NOTHING
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
if (mode == MODE_NOTHING || !line.startsWith("*")) return@forEach
|
||||||
|
val dictName = line.substringAfter("]").substringAfter("(").substringBefore(")")
|
||||||
|
.substringAfterLast("/").substringBefore(".dict")
|
||||||
|
val type = dictName.substringBefore("_")
|
||||||
|
val rawLocale = dictName.substringAfter("_")
|
||||||
|
val locale = if ("_" !in rawLocale) rawLocale
|
||||||
|
else {
|
||||||
|
val split = rawLocale.split("_").toMutableList()
|
||||||
|
if (!split[1].startsWith("#"))
|
||||||
|
split[1] = split[1].uppercase()
|
||||||
|
split.joinToString("_")
|
||||||
|
}
|
||||||
|
outLines.add("$type,$locale,${if (mode == MODE_EXPERIMENTAL) "exp" else ""}")
|
||||||
|
}
|
||||||
|
return outLines.joinToString("\n") + "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val MODE_NOTHING = 0
|
||||||
|
private const val MODE_NORMAL = 1
|
||||||
|
private const val MODE_EXPERIMENTAL = 2
|
Loading…
Add table
Reference in a new issue