New dictionary loader (#89)
* new, simpler (and hopefully, more efficient) dictionary loader * no more dict.properties * dictionaries are now validated during the build process * TraditionalT9Settings code cleanup and code style improvements * removed English, French, Italian, Russian repeating words * removed invalid and repeating German words
This commit is contained in:
parent
0ac7ec1790
commit
10099f1c37
24 changed files with 534 additions and 1855 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -24,7 +24,6 @@ local.properties
|
|||
*.log
|
||||
|
||||
#Other
|
||||
assets/dict.properties
|
||||
t9build.properties
|
||||
*.keystore
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -25,7 +25,6 @@ ma
|
|||
md
|
||||
mi
|
||||
mo
|
||||
ms
|
||||
may
|
||||
mr
|
||||
mrs
|
||||
|
|
@ -145,7 +144,6 @@ cow
|
|||
cox
|
||||
coy
|
||||
cry
|
||||
cs
|
||||
cub
|
||||
cue
|
||||
cum
|
||||
|
|
@ -236,7 +234,6 @@ gin
|
|||
gnu
|
||||
go
|
||||
gob
|
||||
god
|
||||
goo
|
||||
got
|
||||
gum
|
||||
|
|
@ -278,7 +275,6 @@ hum
|
|||
hut
|
||||
ice
|
||||
icy
|
||||
id
|
||||
if
|
||||
ifs
|
||||
ilk
|
||||
|
|
@ -336,14 +332,12 @@ lot
|
|||
low
|
||||
lug
|
||||
lye
|
||||
ma
|
||||
mad
|
||||
man
|
||||
map
|
||||
mar
|
||||
mas
|
||||
mat
|
||||
may
|
||||
me
|
||||
men
|
||||
mes
|
||||
|
|
@ -356,7 +350,6 @@ mom
|
|||
moo
|
||||
mop
|
||||
mow
|
||||
ms
|
||||
mu
|
||||
mud
|
||||
mug
|
||||
|
|
@ -396,7 +389,6 @@ old
|
|||
on
|
||||
one
|
||||
opt
|
||||
or
|
||||
ore
|
||||
our
|
||||
out
|
||||
|
|
@ -405,7 +397,6 @@ owe
|
|||
owl
|
||||
own
|
||||
ox
|
||||
pa
|
||||
pad
|
||||
pal
|
||||
pan
|
||||
|
|
|
|||
|
|
@ -141541,9 +141541,7 @@ esquilles
|
|||
Esquimau
|
||||
esquimaud
|
||||
esquimaude
|
||||
Esquimaude
|
||||
esquimaudes
|
||||
Esquimaudes
|
||||
esquimauds
|
||||
esquimautage
|
||||
esquimautages
|
||||
|
|
@ -186709,7 +186707,6 @@ interneront
|
|||
internes
|
||||
internés
|
||||
internet
|
||||
Internet
|
||||
internez
|
||||
interniez
|
||||
internions
|
||||
|
|
@ -215758,7 +215755,6 @@ naphtes
|
|||
naphtol
|
||||
naphtols
|
||||
napoléon
|
||||
Napoléon
|
||||
napoléonien
|
||||
napoléonienne
|
||||
napoléoniennes
|
||||
|
|
|
|||
|
|
@ -1707,7 +1707,6 @@ Courmayeur
|
|||
Cremona
|
||||
Cristina
|
||||
Cristoforo
|
||||
DOS
|
||||
DVI
|
||||
Daniele
|
||||
Dante
|
||||
|
|
@ -1740,7 +1739,6 @@ Euripide
|
|||
Europa
|
||||
Eusebio
|
||||
Eva
|
||||
FAQ
|
||||
FSF
|
||||
Fabio
|
||||
Faenza
|
||||
|
|
@ -102310,7 +102308,6 @@ tosavano
|
|||
tosavate
|
||||
tosavi
|
||||
tosavo
|
||||
toscana
|
||||
toscane
|
||||
toscani
|
||||
toscano
|
||||
|
|
|
|||
|
|
@ -1,33 +1,25 @@
|
|||
и
|
||||
в
|
||||
не
|
||||
на
|
||||
я
|
||||
что
|
||||
быть
|
||||
с
|
||||
он
|
||||
а
|
||||
это
|
||||
как
|
||||
то
|
||||
этот
|
||||
по
|
||||
к
|
||||
но
|
||||
они
|
||||
мы
|
||||
она
|
||||
который
|
||||
из
|
||||
у
|
||||
свой
|
||||
вы
|
||||
весь
|
||||
за
|
||||
для
|
||||
от
|
||||
о
|
||||
так
|
||||
мочь
|
||||
все
|
||||
|
|
@ -167,7 +159,6 @@
|
|||
поэтому
|
||||
почему
|
||||
понимать
|
||||
москва
|
||||
любой
|
||||
однако
|
||||
хорошо
|
||||
|
|
@ -351,7 +342,6 @@
|
|||
появиться
|
||||
хотеться
|
||||
нельзя
|
||||
д
|
||||
белый
|
||||
центр
|
||||
опять
|
||||
|
|
@ -400,7 +390,6 @@
|
|||
быстро
|
||||
черный
|
||||
сильный
|
||||
н
|
||||
порядок
|
||||
чувствовать
|
||||
создать
|
||||
|
|
@ -487,7 +476,6 @@
|
|||
возможно
|
||||
принимать
|
||||
рубль
|
||||
б
|
||||
миллион
|
||||
целый
|
||||
приходить
|
||||
|
|
@ -529,7 +517,6 @@
|
|||
пара
|
||||
квартира
|
||||
забыть
|
||||
е
|
||||
значение
|
||||
внутренний
|
||||
связать
|
||||
|
|
@ -577,7 +564,6 @@
|
|||
команда
|
||||
добрый
|
||||
поле
|
||||
г
|
||||
сша
|
||||
исследование
|
||||
общественный
|
||||
|
|
@ -591,7 +577,6 @@
|
|||
сон
|
||||
уходить
|
||||
служба
|
||||
ж
|
||||
население
|
||||
воздух
|
||||
словно
|
||||
|
|
@ -616,7 +601,6 @@
|
|||
орган
|
||||
доллар
|
||||
держать
|
||||
т
|
||||
название
|
||||
похожий
|
||||
дорогой
|
||||
|
|
@ -703,7 +687,6 @@
|
|||
поздний
|
||||
песня
|
||||
лучше
|
||||
п
|
||||
случиться
|
||||
ум
|
||||
выбор
|
||||
|
|
@ -785,7 +768,6 @@
|
|||
чтоб
|
||||
прошлый
|
||||
столько
|
||||
л
|
||||
понятие
|
||||
длинный
|
||||
поддержка
|
||||
|
|
@ -963,7 +945,6 @@
|
|||
хватать
|
||||
вчера
|
||||
режим
|
||||
р
|
||||
очередной
|
||||
отдать
|
||||
здоровье
|
||||
|
|
@ -1145,7 +1126,6 @@
|
|||
утверждать
|
||||
позвонить
|
||||
реклама
|
||||
николай
|
||||
революция
|
||||
явление
|
||||
отдел
|
||||
|
|
@ -1405,7 +1385,6 @@
|
|||
бедный
|
||||
появление
|
||||
издание
|
||||
э
|
||||
резко
|
||||
поговорить
|
||||
еврей
|
||||
|
|
@ -1436,7 +1415,6 @@
|
|||
достигнуть
|
||||
сохранить
|
||||
встретиться
|
||||
ю
|
||||
предполагать
|
||||
глубина
|
||||
приказ
|
||||
|
|
@ -1552,7 +1530,6 @@
|
|||
понятно
|
||||
уважение
|
||||
последствие
|
||||
ф
|
||||
буква
|
||||
изображение
|
||||
творческий
|
||||
|
|
@ -1595,7 +1572,6 @@
|
|||
обед
|
||||
переходить
|
||||
изучение
|
||||
олег
|
||||
обеспечивать
|
||||
заставлять
|
||||
подниматься
|
||||
|
|
@ -1826,7 +1802,6 @@
|
|||
публикация
|
||||
кивнуть
|
||||
обсуждать
|
||||
х
|
||||
наверняка
|
||||
напомнить
|
||||
логика
|
||||
|
|
@ -1865,7 +1840,6 @@
|
|||
кошка
|
||||
саша
|
||||
характерный
|
||||
мария
|
||||
толстый
|
||||
общаться
|
||||
пятый
|
||||
|
|
@ -2591,7 +2565,6 @@
|
|||
набрать
|
||||
защитить
|
||||
остановка
|
||||
з
|
||||
дорого
|
||||
какую-то
|
||||
жестокий
|
||||
|
|
@ -2779,7 +2752,6 @@
|
|||
разнообразный
|
||||
отойти
|
||||
разделить
|
||||
ы
|
||||
сборник
|
||||
глобальный
|
||||
кафе
|
||||
|
|
@ -2816,7 +2788,6 @@
|
|||
великолепный
|
||||
доходить
|
||||
образовать
|
||||
наталья
|
||||
разрушить
|
||||
отражать
|
||||
лезть
|
||||
|
|
@ -3781,10 +3752,8 @@
|
|||
симпатичный
|
||||
сделаться
|
||||
продаваться
|
||||
ш
|
||||
направляться
|
||||
предупреждать
|
||||
ч
|
||||
благоприятный
|
||||
палка
|
||||
выдающийся
|
||||
|
|
@ -4016,7 +3985,6 @@
|
|||
рыцарь
|
||||
дежурный
|
||||
отрицать
|
||||
светлана
|
||||
выделяться
|
||||
частица
|
||||
динамика
|
||||
|
|
@ -4276,7 +4244,6 @@
|
|||
рецепт
|
||||
сан
|
||||
махнуть
|
||||
соня
|
||||
смесь
|
||||
творение
|
||||
кредитный
|
||||
|
|
@ -4967,7 +4934,6 @@
|
|||
привязать
|
||||
издатель
|
||||
предать
|
||||
й
|
||||
отставка
|
||||
заголовок
|
||||
отступать
|
||||
|
|
@ -5538,7 +5504,6 @@
|
|||
как-нибудь
|
||||
превосходство
|
||||
конфета
|
||||
ь
|
||||
преподавать
|
||||
ла
|
||||
грамотный
|
||||
|
|
@ -6238,7 +6203,6 @@
|
|||
даша
|
||||
армянский
|
||||
замерзнуть
|
||||
вячеслав
|
||||
фракция
|
||||
разноцветный
|
||||
гроза
|
||||
|
|
@ -6250,7 +6214,6 @@
|
|||
хрупкий
|
||||
выпивать
|
||||
напиться
|
||||
будда
|
||||
октябрьский
|
||||
невыносимый
|
||||
сертификат
|
||||
|
|
@ -6601,7 +6564,6 @@
|
|||
грант
|
||||
выраженный
|
||||
слушаться
|
||||
ц
|
||||
расстроить
|
||||
веселье
|
||||
жюри
|
||||
|
|
@ -7004,7 +6966,6 @@
|
|||
алена
|
||||
подсчет
|
||||
профессионально
|
||||
оксана
|
||||
погладить
|
||||
рассыпаться
|
||||
перебирать
|
||||
|
|
@ -7631,7 +7592,6 @@
|
|||
несомненный
|
||||
многократно
|
||||
выгодно
|
||||
санкт-петербург
|
||||
украинец
|
||||
коварный
|
||||
аккумулятор
|
||||
|
|
@ -8657,7 +8617,6 @@
|
|||
авраам
|
||||
мэрия
|
||||
фуражка
|
||||
ё
|
||||
прикол
|
||||
минуть
|
||||
яростно
|
||||
|
|
@ -11523,7 +11482,6 @@
|
|||
кабинка
|
||||
сатурн
|
||||
байт
|
||||
м
|
||||
прямоугольный
|
||||
остыть
|
||||
смягчить
|
||||
|
|
@ -12768,7 +12726,6 @@
|
|||
разделяться
|
||||
конфликтный
|
||||
лыжи
|
||||
ванька
|
||||
обосноваться
|
||||
активизация
|
||||
основополагающий
|
||||
|
|
@ -13204,7 +13161,6 @@
|
|||
затащить
|
||||
терапевтический
|
||||
чернокожий
|
||||
ъ
|
||||
челнок
|
||||
моделировать
|
||||
ограбление
|
||||
|
|
@ -13526,7 +13482,6 @@
|
|||
видеокарта
|
||||
выключатель
|
||||
росток
|
||||
щ
|
||||
ослаблять
|
||||
безошибочно
|
||||
заикаться
|
||||
|
|
@ -14528,7 +14483,6 @@
|
|||
акцентировать
|
||||
высокотехнологичный
|
||||
невозмутимый
|
||||
Нина
|
||||
железнодорожник
|
||||
амулет
|
||||
дилемма
|
||||
|
|
@ -15852,7 +15806,6 @@
|
|||
никитич
|
||||
заманить
|
||||
вмещать
|
||||
жигули
|
||||
цыганский
|
||||
поразиться
|
||||
обсерватория
|
||||
|
|
@ -22020,7 +21973,6 @@
|
|||
лицезреть
|
||||
никулин
|
||||
неукоснительно
|
||||
нельсон
|
||||
понапрасну
|
||||
фанатичный
|
||||
модернизм
|
||||
|
|
@ -22864,7 +22816,6 @@
|
|||
гадина
|
||||
провиант
|
||||
лещ
|
||||
мекка
|
||||
флагманский
|
||||
адресоваться
|
||||
внешнеторговый
|
||||
|
|
@ -32494,7 +32445,6 @@
|
|||
холодить
|
||||
исцелиться
|
||||
дарвиновский
|
||||
оКсана
|
||||
шайтан
|
||||
алешин
|
||||
объёме
|
||||
|
|
@ -32893,7 +32843,6 @@
|
|||
аркадьевна
|
||||
овсяный
|
||||
обвешать
|
||||
мАксвелл
|
||||
сплетничать
|
||||
узнаваемость
|
||||
улать
|
||||
|
|
@ -32995,7 +32944,6 @@
|
|||
сомать
|
||||
пунктуальный
|
||||
фотокорреспондент
|
||||
бояРин
|
||||
отвержение
|
||||
философствование
|
||||
дыгать
|
||||
|
|
@ -38746,7 +38694,6 @@
|
|||
мет
|
||||
кинохроника
|
||||
подложка
|
||||
бойфренд
|
||||
очиститель
|
||||
лёгкостью
|
||||
голубовато
|
||||
|
|
@ -38934,7 +38881,6 @@
|
|||
петраков
|
||||
трип
|
||||
маттиас
|
||||
кондрат
|
||||
пинг
|
||||
отписка
|
||||
фукс
|
||||
|
|
@ -40162,7 +40108,6 @@
|
|||
апример
|
||||
чейни
|
||||
отшатываться
|
||||
серБия
|
||||
столыпинский
|
||||
смердеть
|
||||
физкультурник
|
||||
|
|
@ -40898,7 +40843,6 @@
|
|||
сворачивание
|
||||
дикобраз
|
||||
родин
|
||||
Макар
|
||||
переговорщик
|
||||
чметр
|
||||
валуй
|
||||
|
|
@ -41894,7 +41838,6 @@
|
|||
просечь
|
||||
ярик
|
||||
генуэзский
|
||||
Стеб
|
||||
глазастый
|
||||
рпг
|
||||
цыганов
|
||||
|
|
@ -44210,7 +44153,6 @@
|
|||
шпангоут
|
||||
плебисцит
|
||||
наркомафия
|
||||
Бойфренд
|
||||
лавчонка
|
||||
джеми
|
||||
проверенный
|
||||
|
|
@ -45721,7 +45663,6 @@
|
|||
стройно
|
||||
неход
|
||||
несоизмеримый
|
||||
Спорткомплекс
|
||||
усреднение
|
||||
конвульсии
|
||||
саров
|
||||
|
|
@ -45832,7 +45773,6 @@
|
|||
авитаминоз
|
||||
прополоскать
|
||||
порыбачить
|
||||
Понт
|
||||
топологический
|
||||
хромовый
|
||||
аутотренинг
|
||||
|
|
@ -47174,7 +47114,6 @@
|
|||
пятикратный
|
||||
интеллектуальность
|
||||
пва
|
||||
евроремонт
|
||||
маканин
|
||||
окопчик
|
||||
твердышев
|
||||
|
|
@ -54281,7 +54220,6 @@
|
|||
карканье
|
||||
пасторский
|
||||
виан
|
||||
перегРин
|
||||
тоить
|
||||
окунев
|
||||
юхан
|
||||
|
|
@ -54906,7 +54844,6 @@
|
|||
измор
|
||||
трый
|
||||
шляхетский
|
||||
бРин
|
||||
лима
|
||||
нестроевой
|
||||
суннитский
|
||||
|
|
@ -55758,7 +55695,6 @@
|
|||
пиноккио
|
||||
идиотический
|
||||
ереть
|
||||
Клава
|
||||
послепродажный
|
||||
бревна
|
||||
несомнить
|
||||
|
|
@ -56484,7 +56420,6 @@
|
|||
жосслить
|
||||
полтонна
|
||||
комбо
|
||||
Метрострой
|
||||
мелеть
|
||||
руга
|
||||
антропософия
|
||||
|
|
@ -59199,7 +59134,6 @@
|
|||
зульфия
|
||||
фотокросс
|
||||
провинциализм
|
||||
кордицеПС
|
||||
комендантша
|
||||
луковский
|
||||
аудить
|
||||
|
|
@ -61891,7 +61825,6 @@
|
|||
хайти
|
||||
кворт
|
||||
пупка
|
||||
Таврия
|
||||
мирье
|
||||
исподний
|
||||
видеопрокат
|
||||
|
|
@ -63203,7 +63136,7 @@
|
|||
флорентино
|
||||
сагитировать
|
||||
долан
|
||||
санкт-Петербург
|
||||
Санкт-Петербург
|
||||
салаг
|
||||
засека
|
||||
батюшок
|
||||
|
|
@ -63405,7 +63338,6 @@
|
|||
пакля
|
||||
заартачиться
|
||||
лайдекер
|
||||
гРин
|
||||
агатовый
|
||||
микросекунда
|
||||
брыззать
|
||||
|
|
@ -63460,7 +63392,6 @@
|
|||
субара
|
||||
пожестче
|
||||
омоним
|
||||
Евроремонт
|
||||
амбиз
|
||||
йцукен
|
||||
долби
|
||||
|
|
@ -69811,7 +69742,6 @@
|
|||
еврисфей
|
||||
браунли
|
||||
возьаться
|
||||
Казанцев
|
||||
задержки
|
||||
портфельчик
|
||||
неумолимость
|
||||
|
|
@ -74213,7 +74143,6 @@
|
|||
социобиология
|
||||
взбрыкивать
|
||||
чёткость
|
||||
Экспоцентр
|
||||
засекречивание
|
||||
бомжик
|
||||
хамар
|
||||
|
|
@ -78233,7 +78162,6 @@
|
|||
войт
|
||||
эндорэ
|
||||
окк
|
||||
Автосервис
|
||||
бандеровский
|
||||
правдин
|
||||
обрисовываться
|
||||
|
|
@ -81985,7 +81913,6 @@
|
|||
цаостров
|
||||
гафгарьон
|
||||
астрорунет
|
||||
мэйРин
|
||||
промаркировать
|
||||
дегтяренко
|
||||
четвёрки
|
||||
|
|
@ -84423,7 +84350,6 @@
|
|||
оршанский
|
||||
карачевский
|
||||
неизменять
|
||||
Минздрав
|
||||
чулка
|
||||
трехосный
|
||||
четать
|
||||
|
|
|
|||
41
build.gradle
41
build.gradle
|
|
@ -106,20 +106,47 @@ android {
|
|||
// }
|
||||
}
|
||||
|
||||
task getDictSizes {
|
||||
task validateDictionaries {
|
||||
inputs.dir fileTree(dir:'assets', excludes:['dict.properties'])
|
||||
outputs.file "t9build.properties"
|
||||
doLast {
|
||||
println "Calculating dict size..."
|
||||
String errors = "";
|
||||
|
||||
inputs.getFiles().each {File file ->
|
||||
println "dict: "+ file.name
|
||||
ant.propertyfile(file:"assets/dict.properties") {
|
||||
entry(key: "size."+ file.name, value: file.length())
|
||||
println "Validating dictionary: " + file.name
|
||||
|
||||
def geographicalName = ~"[A-Z]\\w+-[^\\n]+"
|
||||
def uniqueWords = [:]
|
||||
|
||||
int lineNumber = 0
|
||||
file.eachLine {line ->
|
||||
lineNumber++
|
||||
if (line.matches("\\d")) {
|
||||
errors += "Dictionary '" + file.name + "' is invalid. Found numbers on line " + lineNumber + ". Please, remove all numbers.\n"
|
||||
}
|
||||
|
||||
if (line.matches("^\\P{L}+\$")) {
|
||||
errors += "Dictionary '" + file.name + "' is invalid. Found a garbage word: '" + line + "' on line " + lineNumber + ".\n"
|
||||
}
|
||||
|
||||
if (line.matches("^.\$")) {
|
||||
errors += "Dictionary '" + file.name + "' is invalid. Found a single letter: '" + line + "' on line " + lineNumber + ". Remove all single letters. The alphabet will be added automatically.\n"
|
||||
}
|
||||
|
||||
String uniqueWordKey = line ==~ geographicalName ? line : line.toLowerCase()
|
||||
if (uniqueWords[uniqueWordKey] != null && uniqueWords[uniqueWordKey] == true) {
|
||||
errors += "Dictionary '" + file.name + "' is invalid. Found a repeating word: '" + line + "' on line " + lineNumber + ". Ensure all words appear only once.\n"
|
||||
} else {
|
||||
uniqueWords[uniqueWordKey] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errors != "") {
|
||||
throw new GradleException(errors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preBuild.dependsOn getDictSizes
|
||||
preBuild.mustRunAfter getDictSizes
|
||||
preBuild.dependsOn validateDictionaries
|
||||
preBuild.mustRunAfter validateDictionaries
|
||||
|
|
|
|||
|
|
@ -17,9 +17,11 @@
|
|||
<string name="pref_loaduserdict">Зареди свой речник</string>
|
||||
<string name="pref_truncatedict">Изтрий речник</string>
|
||||
|
||||
<string name="dictionary_loading">Зареждане на речник…</string>
|
||||
<string name="dictionary_import_bad_char">Неуспешно зареждане. Невалидна дума \"%1$s\" на ред %2$d за език \"%3$s\".</string>
|
||||
<string name="dictionary_import_error">Несупешно зареждане на речник за език \"%1$s\" (%2$s).</string>
|
||||
<string name="dictionary_loading">Зареждане на речник (%1$s)…</string>
|
||||
<string name="dictionary_loading_user_dict">Зареждане на вашия речник…</string>
|
||||
<string name="dictionary_load_title">Зареди речник</string>
|
||||
<string name="dictionary_not_found">Неуспешно зареждане. Липсва речник за %1$s.</string>
|
||||
<string name="dictionary_load_title">Зареждане на речник</string>
|
||||
<string name="dictionary_not_found">Неуспешно зареждане. Липсва речник за \"%1$s\".</string>
|
||||
<string name="dictionary_truncated">Речникът е изтрит успешно</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@
|
|||
<string name="pref_choose_languages">Sprachen</string>
|
||||
<string name="pref_loaddict">Wörterbuch laden</string>
|
||||
<string name="pref_loaduserdict">Benutzerwörterbuch laden</string>
|
||||
<string name="pref_truncatedict">Wörterbuch löschen</string>
|
||||
|
||||
<string name="dictionary_loading">Lade Wörterbuch…</string>
|
||||
<string name="dictionary_loading">Lade Wörterbuch (%1$s)…</string>
|
||||
<string name="dictionary_loading_user_dict">Lade Benutzerwörterbuch…</string>
|
||||
<string name="dictionary_load_title">Wörterbuch laden</string>
|
||||
<string name="dictionary_not_found">Wird nicht geladen. Wörterbuch für %1$s nicht gefunden.</string>
|
||||
<string name="pref_truncatedict">Wörterbuch löschen</string>
|
||||
<string name="dictionary_not_found">Wird nicht geladen. Wörterbuch für \"%1$s\" nicht gefunden.</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@
|
|||
<string name="pref_choose_languages">Choisir langues</string>
|
||||
<string name="pref_loaddict">Charger le dictionnaire</string>
|
||||
<string name="pref_loaduserdict">Charger le dictionnaire utilisateur</string>
|
||||
<string name="pref_truncatedict">Supprimer le dictionaire</string>
|
||||
|
||||
<string name="dictionary_loading">Chargement du dictionnaire…</string>
|
||||
<string name="dictionary_import_error">Echec du chargement de dictionnaire pour langue «%1$s» (%2$s).</string>
|
||||
<string name="dictionary_loading">Chargement du dictionnaire (%1$s)…</string>
|
||||
<string name="dictionary_loading_user_dict">Chargement du dictionnaire utilisateur…</string>
|
||||
<string name="dictionary_load_title">Charger le dictionnaire</string>
|
||||
<string name="dictionary_not_found">Echec du chargement. Dictionnaire %1$s introuvable.</string>
|
||||
<string name="pref_truncatedict">Supprimer le dictionaire</string>
|
||||
<string name="dictionary_not_found">Echec du chargement. Dictionnaire «%1$s» introuvable.</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
<string name="pref_choose_languages">Le lingue</string>
|
||||
<string name="pref_loaddict">Carica dizionario</string>
|
||||
<string name="pref_loaduserdict">Carica dizionario utente</string>
|
||||
<string name="pref_truncatedict">Eliminare il dizionario</string>
|
||||
|
||||
<string name="dictionary_loading">Caricamento dizionario…</string>
|
||||
<string name="dictionary_loading">Caricamento dizionario (%1$s)…</string>
|
||||
<string name="dictionary_loading_user_dict">Caricamento dizionario utente…</string>
|
||||
<string name="dictionary_load_title">Caricamento dizionario</string>
|
||||
<string name="dictionary_not_found">Impossibile caricare. Dizionario per %1$s non trovato.</string>
|
||||
<string name="pref_truncatedict">Eliminare il dizionario</string>
|
||||
<string name="dictionary_not_found">Impossibile caricare. Dizionario per “%1$s” non trovato.</string>
|
||||
</resources>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@
|
|||
<string name="pref_loaduserdict">Загрузить свой словарь</string>
|
||||
<string name="pref_truncatedict">Очистить словарь</string>
|
||||
|
||||
<string name="dictionary_loading">Загрузка словаря…</string>
|
||||
<string name="dictionary_import_error">Ошибка загрузки словаря для языка «%1$s» (%2$s).</string>
|
||||
<string name="dictionary_loading">Загрузка словаря (%1$s)…</string>
|
||||
<string name="dictionary_loading_user_dict">Загрузка пользовательского словаря…</string>
|
||||
<string name="dictionary_load_title">Загрузить словарь</string>
|
||||
<string name="dictionary_not_found">Ошибка загрузки. Словарь %1$s не найден.</string>
|
||||
<string name="dictionary_not_found">Ошибка загрузки. Словарь «%1$s» не найден.</string>
|
||||
<string name="dictionary_truncated">Словарь успешно очищен.</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@
|
|||
<string name="pref_choose_languages">Вибір мови</string>
|
||||
<string name="pref_loaddict">Завантажити словник</string>
|
||||
<string name="pref_loaduserdict">Завантажити свій словник</string>
|
||||
<string name="pref_truncatedict">Очистити словник</string>
|
||||
|
||||
<string name="dictionary_loading">Завантаження словника…</string>
|
||||
<string name="dictionary_import_error">Помилка завантаження словника для мови «%1$s» (%2$s).</string>
|
||||
<string name="dictionary_loading">Завантаження словника (%1$s)…</string>
|
||||
<string name="dictionary_loading_user_dict">Завантаження словника користувача…</string>
|
||||
<string name="dictionary_load_title">Завантажити словник</string>
|
||||
<string name="dictionary_not_found">Помилка завантаження. Словник %1$s не знайдено.</string>
|
||||
<string name="pref_truncatedict">Очистити словник</string>
|
||||
<string name="dictionary_not_found">Помилка завантаження. Словник «%1$s» не знайдено.</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -21,9 +21,11 @@
|
|||
<string translatable="false" name="pref_loaduserdictdesc">SDcard/traditionalt9/user.lang.dict (lang: en/ru/de/fr)</string>
|
||||
<string name="pref_truncatedict">Clear dictionary</string>
|
||||
|
||||
<string name="dictionary_loading">Loading dictionary…</string>
|
||||
<string name="dictionary_import_bad_char">Loading failed. Invalid word \"%1$s\" on line %2$d of language \"%3$s\".</string>
|
||||
<string name="dictionary_import_error">Failed importing dictionary for language \"%1$s\" (%2$s).</string>
|
||||
<string name="dictionary_loading">Loading dictionary (%1$s)…</string>
|
||||
<string name="dictionary_loading_user_dict">Loading user dictionary…</string>
|
||||
<string name="dictionary_load_title">Load dictionary</string>
|
||||
<string name="dictionary_not_found">Loading failed. Dictionary for %1$s not found.</string>
|
||||
<string name="dictionary_not_found">Loading failed. Dictionary for \"%1$s\" not found.</string>
|
||||
<string name="dictionary_truncated">Dictionary successfully cleared.</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ const { basename } = require('path');
|
|||
const { createReadStream, existsSync } = require('fs');
|
||||
|
||||
|
||||
const GEO_NAME = /[A-Z]\w+\-[^\n]+/;
|
||||
|
||||
|
||||
function printHelp() {
|
||||
console.log(`Usage ${basename(process.argv[1])} LOCALE FILENAME.txt `);
|
||||
|
|
@ -28,17 +30,44 @@ function validateInput() {
|
|||
|
||||
|
||||
|
||||
function getRegularWordKey(locale, word) {
|
||||
if (typeof word !== 'string' || word.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return GEO_NAME.test(word) ? word : word.toLocaleLowerCase(locale);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getWordKeyPreservingCaptialization(locale, word, wordMap) {
|
||||
if (typeof word !== 'string' || word.length === 0 || typeof wordMap !== 'object') {
|
||||
return '';
|
||||
}
|
||||
|
||||
let wordKey = word.toLocaleLowerCase(locale);
|
||||
|
||||
if (GEO_NAME.test(word) || word.toLocaleLowerCase(locale) !== word) {
|
||||
wordKey = word;
|
||||
if (wordMap[word.toLocaleLowerCase(locale)]) {
|
||||
delete wordMap[word.toLocaleLowerCase(locale)];
|
||||
}
|
||||
}
|
||||
|
||||
return wordKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function removeRepeatingWords({ fileName, locale }) {
|
||||
const lineReader = require('readline').createInterface({
|
||||
input: createReadStream(fileName)
|
||||
});
|
||||
|
||||
const geographicalName = /[A-Z]\w+\-[^\n]+/;
|
||||
const wordMap = {};
|
||||
|
||||
for await (const line of lineReader) {
|
||||
const wordKey = geographicalName.test(line) ? line : line.toLocaleLowerCase(locale);
|
||||
wordMap[wordKey] = true
|
||||
wordMap[getWordKeyPreservingCaptialization(locale, line, wordMap)] = true;
|
||||
}
|
||||
|
||||
return Object.keys(wordMap);
|
||||
|
|
@ -57,4 +86,6 @@ function printWords(wordList) {
|
|||
|
||||
|
||||
/** main **/
|
||||
removeRepeatingWords(validateInput()).then(words => printWords(words));
|
||||
removeRepeatingWords(validateInput())
|
||||
.then(words => printWords(words))
|
||||
.catch(e => console.error(e));
|
||||
|
|
|
|||
|
|
@ -1,315 +0,0 @@
|
|||
/* ____________________________________________________________________________
|
||||
*
|
||||
* File: UnicodeBOMInputStream.java
|
||||
* Author: Gregory Pakosz.
|
||||
* Date: 02 - November - 2005
|
||||
* ____________________________________________________________________________
|
||||
*/
|
||||
package com.stackoverflow.answer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
|
||||
/**
|
||||
* The <code>UnicodeBOMInputStream</code> class wraps any
|
||||
* <code>InputStream</code> and detects the presence of any Unicode BOM
|
||||
* (Byte Order Mark) at its beginning, as defined by
|
||||
* <a href="http://www.faqs.org/rfcs/rfc3629.html">RFC 3629 - UTF-8, a transformation format of ISO 10646</a>
|
||||
*
|
||||
* <p>The
|
||||
* <a href="http://www.unicode.org/unicode/faq/utf_bom.html">Unicode FAQ</a>
|
||||
* defines 5 types of BOMs:<ul>
|
||||
* <li><pre>00 00 FE FF = UTF-32, big-endian</pre></li>
|
||||
* <li><pre>FF FE 00 00 = UTF-32, little-endian</pre></li>
|
||||
* <li><pre>FE FF = UTF-16, big-endian</pre></li>
|
||||
* <li><pre>FF FE = UTF-16, little-endian</pre></li>
|
||||
* <li><pre>EF BB BF = UTF-8</pre></li>
|
||||
* </ul></p>
|
||||
*
|
||||
* <p>Use the {@link #getBOM()} method to know whether a BOM has been detected
|
||||
* or not.
|
||||
* </p>
|
||||
* <p>Use the {@link #skipBOM()} method to remove the detected BOM from the
|
||||
* wrapped <code>InputStream</code> object.</p>
|
||||
*/
|
||||
public class UnicodeBOMInputStream extends InputStream
|
||||
{
|
||||
/**
|
||||
* Type safe enumeration class that describes the different types of Unicode
|
||||
* BOMs.
|
||||
*/
|
||||
public static final class BOM
|
||||
{
|
||||
/**
|
||||
* NONE.
|
||||
*/
|
||||
public static final BOM NONE = new BOM(new byte[]{},"NONE");
|
||||
|
||||
/**
|
||||
* UTF-8 BOM (EF BB BF).
|
||||
*/
|
||||
public static final BOM UTF_8 = new BOM(new byte[]{(byte)0xEF,
|
||||
(byte)0xBB,
|
||||
(byte)0xBF},
|
||||
"UTF-8");
|
||||
|
||||
/**
|
||||
* UTF-16, little-endian (FF FE).
|
||||
*/
|
||||
public static final BOM UTF_16_LE = new BOM(new byte[]{ (byte)0xFF,
|
||||
(byte)0xFE},
|
||||
"UTF-16 little-endian");
|
||||
|
||||
/**
|
||||
* UTF-16, big-endian (FE FF).
|
||||
*/
|
||||
public static final BOM UTF_16_BE = new BOM(new byte[]{ (byte)0xFE,
|
||||
(byte)0xFF},
|
||||
"UTF-16 big-endian");
|
||||
|
||||
/**
|
||||
* UTF-32, little-endian (FF FE 00 00).
|
||||
*/
|
||||
public static final BOM UTF_32_LE = new BOM(new byte[]{ (byte)0xFF,
|
||||
(byte)0xFE,
|
||||
(byte)0x00,
|
||||
(byte)0x00},
|
||||
"UTF-32 little-endian");
|
||||
|
||||
/**
|
||||
* UTF-32, big-endian (00 00 FE FF).
|
||||
*/
|
||||
public static final BOM UTF_32_BE = new BOM(new byte[]{ (byte)0x00,
|
||||
(byte)0x00,
|
||||
(byte)0xFE,
|
||||
(byte)0xFF},
|
||||
"UTF-32 big-endian");
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representation of this <code>BOM</code>
|
||||
* value.
|
||||
*/
|
||||
public final String toString()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bytes corresponding to this <code>BOM</code> value.
|
||||
*/
|
||||
public final byte[] getBytes()
|
||||
{
|
||||
final int length = bytes.length;
|
||||
final byte[] result = new byte[length];
|
||||
|
||||
// Make a defensive copy
|
||||
System.arraycopy(bytes,0,result,0,length);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private BOM(final byte bom[], final String description)
|
||||
{
|
||||
assert(bom != null) : "invalid BOM: null is not allowed";
|
||||
assert(description != null) : "invalid description: null is not allowed";
|
||||
assert(description.length() != 0) : "invalid description: empty string is not allowed";
|
||||
|
||||
this.bytes = bom;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
final byte bytes[];
|
||||
private final String description;
|
||||
|
||||
} // BOM
|
||||
|
||||
/**
|
||||
* Constructs a new <code>UnicodeBOMInputStream</code> that wraps the
|
||||
* specified <code>InputStream</code>.
|
||||
*
|
||||
* @param inputStream an <code>InputStream</code>.
|
||||
*
|
||||
* @throws NullPointerException when <code>inputStream</code> is
|
||||
* <code>null</code>.
|
||||
* @throws IOException on reading from the specified <code>InputStream</code>
|
||||
* when trying to detect the Unicode BOM.
|
||||
*/
|
||||
public UnicodeBOMInputStream(final InputStream inputStream) throws NullPointerException,
|
||||
IOException
|
||||
|
||||
{
|
||||
if (inputStream == null)
|
||||
throw new NullPointerException("invalid input stream: null is not allowed");
|
||||
|
||||
in = new PushbackInputStream(inputStream,4);
|
||||
|
||||
final byte bom[] = new byte[4];
|
||||
final int read = in.read(bom);
|
||||
|
||||
switch(read)
|
||||
{
|
||||
case 4:
|
||||
if ((bom[0] == (byte)0xFF) &&
|
||||
(bom[1] == (byte)0xFE) &&
|
||||
(bom[2] == (byte)0x00) &&
|
||||
(bom[3] == (byte)0x00))
|
||||
{
|
||||
this.bom = BOM.UTF_32_LE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if ((bom[0] == (byte)0x00) &&
|
||||
(bom[1] == (byte)0x00) &&
|
||||
(bom[2] == (byte)0xFE) &&
|
||||
(bom[3] == (byte)0xFF))
|
||||
{
|
||||
this.bom = BOM.UTF_32_BE;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
if ((bom[0] == (byte)0xEF) &&
|
||||
(bom[1] == (byte)0xBB) &&
|
||||
(bom[2] == (byte)0xBF))
|
||||
{
|
||||
this.bom = BOM.UTF_8;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
if ((bom[0] == (byte)0xFF) &&
|
||||
(bom[1] == (byte)0xFE))
|
||||
{
|
||||
this.bom = BOM.UTF_16_LE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if ((bom[0] == (byte)0xFE) &&
|
||||
(bom[1] == (byte)0xFF))
|
||||
{
|
||||
this.bom = BOM.UTF_16_BE;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
this.bom = BOM.NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (read > 0)
|
||||
in.unread(bom,0,read);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>BOM</code> that was detected in the wrapped
|
||||
* <code>InputStream</code> object.
|
||||
*
|
||||
* @return a <code>BOM</code> value.
|
||||
*/
|
||||
public final BOM getBOM()
|
||||
{
|
||||
// BOM type is immutable.
|
||||
return bom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips the <code>BOM</code> that was found in the wrapped
|
||||
* <code>InputStream</code> object.
|
||||
*
|
||||
* @return this <code>UnicodeBOMInputStream</code>.
|
||||
*
|
||||
* @throws IOException when trying to skip the BOM from the wrapped
|
||||
* <code>InputStream</code> object.
|
||||
*/
|
||||
public final synchronized UnicodeBOMInputStream skipBOM() throws IOException
|
||||
{
|
||||
if (!skipped)
|
||||
{
|
||||
in.skip(bom.bytes.length);
|
||||
skipped = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int read() throws IOException
|
||||
{
|
||||
return in.read();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int read(final byte b[]) throws IOException,
|
||||
NullPointerException
|
||||
{
|
||||
return in.read(b,0,b.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int read(final byte b[],
|
||||
final int off,
|
||||
final int len) throws IOException,
|
||||
NullPointerException
|
||||
{
|
||||
return in.read(b,off,len);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long skip(final long n) throws IOException
|
||||
{
|
||||
return in.skip(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int available() throws IOException
|
||||
{
|
||||
return in.available();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void close() throws IOException
|
||||
{
|
||||
in.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public synchronized void mark(final int readlimit)
|
||||
{
|
||||
in.mark(readlimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public synchronized void reset() throws IOException
|
||||
{
|
||||
in.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean markSupported()
|
||||
{
|
||||
return in.markSupported();
|
||||
}
|
||||
|
||||
private final PushbackInputStream in;
|
||||
private final BOM bom;
|
||||
private boolean skipped = false;
|
||||
|
||||
} // UnicodeBOMInputStream
|
||||
|
|
@ -59,16 +59,8 @@ public class DictionaryDb {
|
|||
}
|
||||
|
||||
|
||||
public static void beginTransaction() {
|
||||
getInstance().beginTransaction();
|
||||
}
|
||||
|
||||
|
||||
public static void endTransaction(boolean success) {
|
||||
if (success) {
|
||||
getInstance().setTransactionSuccessful();
|
||||
}
|
||||
getInstance().endTransaction();
|
||||
public static void runInTransaction(Runnable r) {
|
||||
getInstance().runInTransaction(r);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package io.github.sspanak.tt9.db;
|
||||
|
||||
public class DictionaryImportAbortedException extends Exception{
|
||||
public DictionaryImportAbortedException() {
|
||||
super("Dictionary import stopped by request.");
|
||||
}
|
||||
}
|
||||
14
src/io/github/sspanak/tt9/db/DictionaryImportException.java
Normal file
14
src/io/github/sspanak/tt9/db/DictionaryImportException.java
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package io.github.sspanak.tt9.db;
|
||||
|
||||
public class DictionaryImportException extends Exception {
|
||||
public final String file;
|
||||
public final String word;
|
||||
public final long line;
|
||||
|
||||
DictionaryImportException(String file, String word, long line) {
|
||||
super("Dictionary import failed");
|
||||
this.file = file;
|
||||
this.word = word;
|
||||
this.line = line;
|
||||
}
|
||||
}
|
||||
259
src/io/github/sspanak/tt9/db/DictionaryLoader.java
Normal file
259
src/io/github/sspanak/tt9/db/DictionaryLoader.java
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
package io.github.sspanak.tt9.db;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.languages.InvalidLanguageCharactersException;
|
||||
import io.github.sspanak.tt9.languages.InvalidLanguageException;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.preferences.T9Preferences;
|
||||
|
||||
public class DictionaryLoader {
|
||||
private final AssetManager assets;
|
||||
private final T9Preferences prefs;
|
||||
|
||||
private boolean isStopped = true;
|
||||
private int currentFile = 0;
|
||||
private long lastProgressUpdate = 0;
|
||||
|
||||
private final Pattern containsPunctuation = Pattern.compile("\\p{Punct}(?<!-)");
|
||||
|
||||
public DictionaryLoader(Context context) {
|
||||
assets = context.getAssets();
|
||||
prefs = T9Preferences.getInstance();
|
||||
}
|
||||
|
||||
|
||||
public void load(Handler handler, ArrayList<Language> languages) {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
currentFile = 0;
|
||||
isStopped = false;
|
||||
// SQLite does not support parallel queries, so let's import them one by one
|
||||
for (Language lang : languages) {
|
||||
if (isStopped) {
|
||||
break;
|
||||
}
|
||||
importAll(handler, lang);
|
||||
currentFile++;
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
|
||||
public void stop() {
|
||||
isStopped = true;
|
||||
}
|
||||
|
||||
|
||||
private void importAll(Handler handler, Language language) {
|
||||
final String logTag = "tt9.DictionaryLoader.importAll";
|
||||
|
||||
if (language == null) {
|
||||
Logger.e(logTag, "Failed loading a dictionary for NULL language.");
|
||||
sendError(handler, InvalidLanguageException.class.getSimpleName(), -1);
|
||||
return;
|
||||
}
|
||||
|
||||
DictionaryDb.runInTransaction(() -> {
|
||||
long start = System.currentTimeMillis();
|
||||
importLetters(language);
|
||||
Logger.i(
|
||||
logTag,
|
||||
"Loaded letters for '" + language.getName() + "' language in: " + (System.currentTimeMillis() - start) + " ms"
|
||||
);
|
||||
|
||||
try {
|
||||
start = System.currentTimeMillis();
|
||||
importWords(handler, language);
|
||||
Logger.i(
|
||||
logTag,
|
||||
"Dictionary: '" + language.getDictionaryFile() + "'" +
|
||||
" processing time: " + (System.currentTimeMillis() - start) + " ms"
|
||||
);
|
||||
} catch (DictionaryImportAbortedException e) {
|
||||
stop();
|
||||
|
||||
Logger.i(
|
||||
logTag,
|
||||
e.getMessage() + ". File '" + language.getDictionaryFile() + "' not imported."
|
||||
);
|
||||
} catch (DictionaryImportException e) {
|
||||
stop();
|
||||
sendImportError(handler, DictionaryImportException.class.getSimpleName(), language.getId(), e.line, e.word);
|
||||
|
||||
Logger.e(
|
||||
logTag,
|
||||
" Invalid word: '" + e.word
|
||||
+ "' in dictionary: '" + language.getDictionaryFile() + "'"
|
||||
+ " on line " + e.line
|
||||
+ " of language '" + language.getName() + "'. "
|
||||
+ e.getMessage()
|
||||
);
|
||||
} catch (Exception e) {
|
||||
stop();
|
||||
sendError(handler, e.getClass().getSimpleName(), language.getId());
|
||||
|
||||
Logger.e(
|
||||
logTag,
|
||||
"Failed loading dictionary: " + language.getDictionaryFile() +
|
||||
" for language '" + language.getName() + "'. "
|
||||
+ e.getMessage()
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void importLetters(Language language) {
|
||||
ArrayList<Word> letters = new ArrayList<>();
|
||||
|
||||
for (int key = 0; key <= 9; key++) {
|
||||
for (String langChar : language.getKeyCharacters(key)) {
|
||||
if (langChar.length() == 1 && langChar.charAt(0) >= '0' && langChar.charAt(0) <= '9') {
|
||||
// We do not want 0-9 as "word suggestions" in Predictive mode. It looks confusing
|
||||
// when trying to type a word and also, one can type them by holding the respective
|
||||
// key.
|
||||
continue;
|
||||
}
|
||||
|
||||
Word word = new Word();
|
||||
word.langId = language.getId();
|
||||
word.frequency = 0;
|
||||
word.sequence = String.valueOf(key);
|
||||
word.word = langChar;
|
||||
|
||||
letters.add(word);
|
||||
}
|
||||
}
|
||||
|
||||
DictionaryDb.insertWordsSync(letters);
|
||||
}
|
||||
|
||||
|
||||
private void importWords(Handler handler, Language language) throws Exception {
|
||||
importWords(handler, language, language.getDictionaryFile());
|
||||
}
|
||||
|
||||
|
||||
private void importWords(Handler handler, Language language, String dictionaryFile) throws Exception {
|
||||
long totalWords = countWords(dictionaryFile);
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(assets.open(dictionaryFile), StandardCharsets.UTF_8));
|
||||
|
||||
ArrayList<Word> dbWords = new ArrayList<>();
|
||||
long line = 0;
|
||||
|
||||
sendProgressMessage(handler, language, 0, 0);
|
||||
|
||||
for (String word; (word = br.readLine()) != null; line++) {
|
||||
if (isStopped) {
|
||||
br.close();
|
||||
sendProgressMessage(handler, language, 0, 0);
|
||||
throw new DictionaryImportAbortedException();
|
||||
}
|
||||
|
||||
validateWord(language, word, line);
|
||||
dbWords.add(stringToWord(language, word));
|
||||
|
||||
if (line % prefs.getDictionaryImportWordChunkSize() == 0) {
|
||||
DictionaryDb.insertWordsSync(dbWords);
|
||||
dbWords.clear();
|
||||
}
|
||||
|
||||
if (totalWords > 0) {
|
||||
int progress = (int) Math.floor(100.0 * line / totalWords);
|
||||
sendProgressMessage(handler, language, progress, prefs.getDictionaryImportProgressUpdateInterval());
|
||||
}
|
||||
}
|
||||
|
||||
br.close();
|
||||
sendProgressMessage(handler, language, 100, 0);
|
||||
}
|
||||
|
||||
|
||||
private long countWords(String filename) {
|
||||
try (LineNumberReader reader = new LineNumberReader(new InputStreamReader(assets.open(filename), StandardCharsets.UTF_8))) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
reader.skip(Long.MAX_VALUE);
|
||||
long lines = reader.getLineNumber();
|
||||
reader.close();
|
||||
|
||||
return lines;
|
||||
} catch (Exception e) {
|
||||
Logger.w("DictionaryLoader.countWords", "Could not count the lines of file: " + filename + ". " + e.getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void validateWord(Language language, String word, long line) throws DictionaryImportException {
|
||||
if (!language.isPunctuationPartOfWords() && containsPunctuation.matcher(word).find()) {
|
||||
throw new DictionaryImportException(language.getDictionaryFile(), word, line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Word stringToWord(Language language, String word) throws InvalidLanguageCharactersException {
|
||||
Word dbWord = new Word();
|
||||
dbWord.langId = language.getId();
|
||||
dbWord.frequency = 0;
|
||||
dbWord.sequence = language.getDigitSequenceForWord(word);
|
||||
dbWord.word = word;
|
||||
|
||||
return dbWord;
|
||||
}
|
||||
|
||||
|
||||
private void sendProgressMessage(Handler handler, Language language, int progress, int progressUpdateInterval) {
|
||||
long now = System.currentTimeMillis();
|
||||
if (now - lastProgressUpdate < progressUpdateInterval) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastProgressUpdate = now;
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt("languageId", language.getId());
|
||||
bundle.putInt("progress", progress);
|
||||
bundle.putInt("currentFile", currentFile);
|
||||
Message msg = new Message();
|
||||
msg.setData(bundle);
|
||||
handler.sendMessage(msg);
|
||||
}
|
||||
|
||||
|
||||
private void sendError(Handler handler, String message, int langId) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("error", message);
|
||||
bundle.putInt("languageId", langId);
|
||||
Message msg = new Message();
|
||||
msg.setData(bundle);
|
||||
handler.sendMessage(msg);
|
||||
}
|
||||
|
||||
|
||||
private void sendImportError(Handler handler, String message, int langId, long fileLine, String word) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("error", message);
|
||||
bundle.putLong("fileLine", fileLine);
|
||||
bundle.putInt("languageId", langId);
|
||||
bundle.putString("word", word);
|
||||
Message msg = new Message();
|
||||
msg.setData(bundle);
|
||||
handler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package io.github.sspanak.tt9.languages;
|
||||
|
||||
public class InvalidLanguageCharactersException extends Exception {
|
||||
private Language language;
|
||||
|
||||
public InvalidLanguageCharactersException(Language language, String extraMessage) {
|
||||
super("Some characters are not supported in language: " + language.getName() + ". " + extraMessage);
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public Language getLanguage() {
|
||||
return language;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ public class Language {
|
|||
return chars;
|
||||
}
|
||||
|
||||
public String getDigitSequenceForWord(String word) throws Exception {
|
||||
public String getDigitSequenceForWord(String word) throws InvalidLanguageCharactersException {
|
||||
StringBuilder sequence = new StringBuilder();
|
||||
String lowerCaseWord = word.toLowerCase(locale);
|
||||
|
||||
|
|
@ -83,9 +83,7 @@ public class Language {
|
|||
}
|
||||
|
||||
if (word.length() != sequence.length()) {
|
||||
throw new Exception(
|
||||
"Failed generating digit sequence for word: '" + word + "'. Some characters are not supported in language: " + name
|
||||
);
|
||||
throw new InvalidLanguageCharactersException(this, "Failed generating digit sequence for word: '" + word);
|
||||
}
|
||||
|
||||
return sequence.toString();
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ package io.github.sspanak.tt9.preferences;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
|
@ -23,11 +23,13 @@ public class T9Preferences {
|
|||
private final SharedPreferences prefs;
|
||||
private final SharedPreferences.Editor prefsEditor;
|
||||
|
||||
|
||||
public T9Preferences (Context context) {
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
prefsEditor = prefs.edit();
|
||||
}
|
||||
|
||||
|
||||
public static T9Preferences getInstance() {
|
||||
if (self == null) {
|
||||
self = new T9Preferences(TraditionalT9.getMainContext());
|
||||
|
|
@ -36,7 +38,8 @@ public class T9Preferences {
|
|||
return self;
|
||||
}
|
||||
|
||||
/************* VALIDATORS *************/
|
||||
|
||||
/************* validators *************/
|
||||
|
||||
private boolean doesLanguageExist(int langId) {
|
||||
return LanguageCollection.getLanguage(langId) != null;
|
||||
|
|
@ -70,7 +73,7 @@ public class T9Preferences {
|
|||
}
|
||||
|
||||
|
||||
/************* PREFERENCES OPERATIONS *************/
|
||||
/************* input settings *************/
|
||||
|
||||
public ArrayList<Integer> getEnabledLanguages() {
|
||||
int languageMask = prefs.getInt("pref_enabled_languages", 1);
|
||||
|
|
@ -101,6 +104,7 @@ public class T9Preferences {
|
|||
prefsEditor.apply();
|
||||
}
|
||||
|
||||
|
||||
public int getTextCase() {
|
||||
return prefs.getInt("pref_text_case", InputMode.CASE_LOWER);
|
||||
}
|
||||
|
|
@ -131,6 +135,7 @@ public class T9Preferences {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public int getInputMode() {
|
||||
return prefs.getInt("pref_input_mode", InputMode.MODE_PREDICTIVE);
|
||||
}
|
||||
|
|
@ -146,18 +151,24 @@ public class T9Preferences {
|
|||
}
|
||||
|
||||
|
||||
/************* hotkey settings *************/
|
||||
|
||||
public int getKeyBackspace() {
|
||||
return prefs.getInt("pref_key_backspace", KeyEvent.KEYCODE_BACK);
|
||||
}
|
||||
|
||||
public int getKeyInputMode() { return prefs.getInt("pref_key_input_mode", KeyEvent.KEYCODE_POUND); }
|
||||
|
||||
public int getKeyOtherActions() { return prefs.getInt("pref_key_other_actions", KeyEvent.KEYCODE_STAR); }
|
||||
|
||||
|
||||
public int getSuggestionsMin() { return 8; }
|
||||
public int getSuggestionsMax() { return 20; }
|
||||
/************* internal settings *************/
|
||||
|
||||
public int getDictionaryImportProgressUpdateInterval() { return 100; /* ms */ }
|
||||
public int getDictionaryImportWordChunkSize() { return 1000; /* words */ }
|
||||
public int getSuggestionsMax() { return 20; }
|
||||
public int getSuggestionsMin() { return 8; }
|
||||
|
||||
|
||||
/************* add word, last word *************/
|
||||
|
||||
public String getLastWord() {
|
||||
return prefs.getString("last_word", "");
|
||||
|
|
@ -173,5 +184,4 @@ public class T9Preferences {
|
|||
public void clearLastWord() {
|
||||
this.saveLastWord("");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package io.github.sspanak.tt9.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ListActivity;
|
||||
import android.app.ProgressDialog;
|
||||
|
|
@ -8,38 +7,24 @@ import android.content.Context;
|
|||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.stackoverflow.answer.UnicodeBOMInputStream;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||
import io.github.sspanak.tt9.db.Word;
|
||||
import io.github.sspanak.tt9.db.DictionaryImportException;
|
||||
import io.github.sspanak.tt9.db.DictionaryLoader;
|
||||
import io.github.sspanak.tt9.languages.InvalidLanguageCharactersException;
|
||||
import io.github.sspanak.tt9.languages.InvalidLanguageException;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.preferences.T9Preferences;
|
||||
|
|
@ -49,365 +34,11 @@ import io.github.sspanak.tt9.settings_legacy.SettingAdapter;
|
|||
|
||||
public class TraditionalT9Settings extends ListActivity implements DialogInterface.OnCancelListener {
|
||||
|
||||
AsyncTask<String, Integer, Reply> task = null;
|
||||
final static String userdictname = "user.%s.dict";
|
||||
final static String sddir = "tt9";
|
||||
private DictionaryLoader loader;
|
||||
ProgressDialog progressDialog;
|
||||
|
||||
Context mContext = null;
|
||||
|
||||
public static class LoadException extends Exception {
|
||||
private static final long serialVersionUID = 3323913652550046354L;
|
||||
|
||||
public LoadException() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
private static class Reply {
|
||||
public boolean status;
|
||||
private final List<String> msgs;
|
||||
|
||||
protected Reply() {
|
||||
this.status = true;
|
||||
this.msgs = new ArrayList<>(4);
|
||||
}
|
||||
|
||||
protected void addMsg(String msg) throws LoadException {
|
||||
msgs.add(msg);
|
||||
if (msgs.size() > 6) {
|
||||
msgs.add("Too many errors, bailing.");
|
||||
throw new LoadException();
|
||||
}
|
||||
}
|
||||
protected void forceMsg(String msg) {
|
||||
msgs.add(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void finishAndShowError(ProgressDialog pd, Reply result, int title){
|
||||
if (pd != null) {
|
||||
// Logger.d("onPostExecute", "pd");
|
||||
if (pd.isShowing()) {
|
||||
pd.dismiss();
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
// bad thing happened
|
||||
Logger.e("onPostExecute", "Bad things happen?");
|
||||
} else {
|
||||
String msg = TextUtils.join("\n", result.msgs);
|
||||
Logger.d("onPostExecute", "Result: " + result.status + " " + msg);
|
||||
if (!result.status) {
|
||||
showErrorDialog(getResources().getString(title), msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void closeStream(Closeable is, Reply reply) {
|
||||
if (is == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
reply.forceMsg("Couldn't close stream: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private class LoadDictTask extends AsyncTask<String, Integer, Reply> {
|
||||
/**
|
||||
* The system calls this to perform work in a worker thread and delivers
|
||||
* it the parameters given to AsyncTask.execute()
|
||||
*/
|
||||
ProgressDialog pd;
|
||||
long size;
|
||||
long pos;
|
||||
boolean internal;
|
||||
String[] dicts;
|
||||
ArrayList<Language> mSupportedLanguages;
|
||||
|
||||
LoadDictTask(int msgid, boolean intern, ArrayList<Language> supportedLanguages) {
|
||||
internal = intern;
|
||||
|
||||
dicts = new String[supportedLanguages.size()];
|
||||
int x = 0;
|
||||
for (Language language : supportedLanguages) {
|
||||
if (intern) {
|
||||
dicts[x++] = language.getDictionaryFile();
|
||||
} else {
|
||||
dicts[x++] = String.format(userdictname, language.getName().toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
}
|
||||
mSupportedLanguages = supportedLanguages;
|
||||
|
||||
pd = new ProgressDialog(TraditionalT9Settings.this);
|
||||
pd.setMessage(getResources().getString(msgid));
|
||||
pd.setOnCancelListener(TraditionalT9Settings.this);
|
||||
}
|
||||
|
||||
private long getDictSizes(boolean internal, String[] dicts) {
|
||||
if (internal) {
|
||||
InputStream input;
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
input = getAssets().open("dict.properties");
|
||||
props.load(input);
|
||||
long total = 0;
|
||||
for (String dict : dicts) {
|
||||
total += Long.parseLong(props.getProperty("size." + dict));
|
||||
}
|
||||
return total;
|
||||
|
||||
} catch (IOException e) {
|
||||
Logger.e("getDictSizes", "Unable to get dict sizes");
|
||||
e.printStackTrace();
|
||||
return -1;
|
||||
} catch (NumberFormatException e) {
|
||||
Logger.e("getDictSizes", "Unable to parse sizes");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
File backupfile = new File(Environment.getExternalStorageDirectory(), sddir);
|
||||
long total = 0;
|
||||
File f;
|
||||
for (String dict : dicts) {
|
||||
f = new File(backupfile, dict);
|
||||
if (f.exists() && f.isFile()) {
|
||||
total = total + f.length();
|
||||
} else {
|
||||
total = total + 0;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
@Override protected void onPreExecute() {
|
||||
size = getDictSizes(internal, dicts);
|
||||
pos = 0;
|
||||
if ( size >= 0 ) {
|
||||
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
pd.setMax(10000);
|
||||
} else {
|
||||
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
}
|
||||
pd.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Reply doInBackground(String... mode) {
|
||||
Reply reply = new Reply();
|
||||
|
||||
long startnow, endnow;
|
||||
startnow = SystemClock.uptimeMillis();
|
||||
|
||||
// add characters first, then dictionary:
|
||||
Logger.d("doInBackground", "Adding characters...");
|
||||
processChars(mSupportedLanguages);
|
||||
Logger.d("doInBackground", "Characters added.");
|
||||
|
||||
Logger.d("doInBackground", "Adding dict(s)...");
|
||||
|
||||
InputStream dictstream = null;
|
||||
|
||||
try {
|
||||
for (int x=0; x<dicts.length; x++) {
|
||||
if (internal) {
|
||||
try {
|
||||
dictstream = getAssets().open(dicts[x]);
|
||||
reply = processFile(dictstream, reply, mSupportedLanguages.get(x), dicts[x]);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
reply.status = false;
|
||||
reply.forceMsg("IO Error: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
dictstream = new FileInputStream(new File(
|
||||
new File(Environment.getExternalStorageDirectory(), sddir), dicts[x]));
|
||||
reply = processFile(dictstream, reply, mSupportedLanguages.get(x), dicts[x]);
|
||||
} catch (FileNotFoundException e) {
|
||||
reply.status = false;
|
||||
reply.forceMsg("File not found: " + e.getMessage());
|
||||
final String msg = mContext.getString(R.string.dictionary_not_found, dicts[x]);
|
||||
//Logger.d("T9Setting.load", "Built string. Calling Toast.");
|
||||
((Activity) mContext).runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UI.toast(mContext, msg);
|
||||
}
|
||||
});
|
||||
|
||||
closeStream(dictstream, reply); // this is silly but it
|
||||
// stops IDE nagging at me.
|
||||
} catch (IOException e) {
|
||||
reply.status = false;
|
||||
reply.forceMsg("IO Error: " + e.getMessage());
|
||||
closeStream(dictstream, reply); // this is silly but it
|
||||
return reply; // stops IDE nagging at me.
|
||||
}
|
||||
}
|
||||
closeStream(dictstream, reply);
|
||||
}
|
||||
} catch (LoadException e) {
|
||||
// too many errors, bail
|
||||
closeStream(dictstream, reply);
|
||||
}
|
||||
endnow = SystemClock.uptimeMillis();
|
||||
Logger.d("TIMING", "Execution time: " + (endnow - startnow) + " ms");
|
||||
return reply;
|
||||
}
|
||||
|
||||
/**
|
||||
* processChars
|
||||
* Inserts single characters.
|
||||
*/
|
||||
private void processChars(List<Language> allLanguages) {
|
||||
ArrayList<Word> list = new ArrayList<>();
|
||||
|
||||
try {
|
||||
for (Language lang : allLanguages) {
|
||||
for (int key = 0; key <= 9; key++) {
|
||||
for (String langChar : lang.getKeyCharacters(key)) {
|
||||
if (langChar.length() == 1 && langChar.charAt(0) >= '0' && langChar.charAt(0) <= '9') {
|
||||
// We do not want 0-9 as "word suggestions" in Predictive mode. It looks confusing
|
||||
// when trying to type a word and also, one can type them by holding the respective
|
||||
// key.
|
||||
continue;
|
||||
}
|
||||
|
||||
Word word = new Word();
|
||||
word.langId = lang.getId();
|
||||
word.sequence = String.valueOf(key);
|
||||
word.word = langChar;
|
||||
word.frequency = 0;
|
||||
|
||||
list.add(word);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DictionaryDb.insertWordsSync(list);
|
||||
} catch (Exception e) {
|
||||
Logger.e("processChars", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private String getLine(BufferedReader br, Reply rpl, String fname) throws LoadException {
|
||||
try {
|
||||
return br.readLine();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
rpl.status = false;
|
||||
rpl.addMsg("IO Error ("+fname+"): " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Reply processFile(InputStream is, Reply rpl, Language lang, String fname)
|
||||
throws LoadException, IOException {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
UnicodeBOMInputStream ubis = new UnicodeBOMInputStream(is);
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(ubis));
|
||||
ubis.skipBOM();
|
||||
|
||||
int freq;
|
||||
String seq;
|
||||
int linecount = 1;
|
||||
int wordlen;
|
||||
String fileWord = getLine(br, rpl, fname);
|
||||
ArrayList<Word> dbWords = new ArrayList<>();
|
||||
int insertChunkSize = 1000;
|
||||
int progressUpdateInterval = 100; // ms
|
||||
long lastProgressUpdate = 0;
|
||||
|
||||
try {
|
||||
|
||||
DictionaryDb.beginTransaction();
|
||||
|
||||
while (fileWord != null) {
|
||||
if (isCancelled()) {
|
||||
rpl.status = false;
|
||||
rpl.addMsg("User cancelled.");
|
||||
break;
|
||||
}
|
||||
if (fileWord.contains(" ")) {
|
||||
rpl.status = false;
|
||||
rpl.addMsg("Cannot parse word with spaces: " + fileWord);
|
||||
break;
|
||||
}
|
||||
|
||||
freq = 0;
|
||||
wordlen = fileWord.getBytes(StandardCharsets.UTF_8).length;
|
||||
pos += wordlen;
|
||||
// replace junk characters:
|
||||
fileWord = fileWord.replace("\uFEFF", "");
|
||||
try {
|
||||
seq = lang.getDigitSequenceForWord(fileWord);
|
||||
} catch (Exception e) {
|
||||
rpl.status = false;
|
||||
rpl.addMsg("Error on word ("+fileWord+") line "+
|
||||
linecount+" in (" + fname+"): "+
|
||||
getResources().getString(R.string.add_word_badchar, lang.getName(), fileWord));
|
||||
break;
|
||||
}
|
||||
linecount++;
|
||||
|
||||
Word word = new Word();
|
||||
word.sequence = seq;
|
||||
word.langId = lang.getId();
|
||||
word.word = fileWord;
|
||||
word.frequency = freq;
|
||||
dbWords.add(word);
|
||||
|
||||
if (linecount % insertChunkSize == 0) {
|
||||
DictionaryDb.insertWordsSync(dbWords);
|
||||
dbWords.clear();
|
||||
}
|
||||
|
||||
if (size >= 0 && System.currentTimeMillis() - lastProgressUpdate > progressUpdateInterval) {
|
||||
publishProgress((int) ((float) pos / size * 10000));
|
||||
lastProgressUpdate = System.currentTimeMillis();
|
||||
}
|
||||
fileWord = getLine(br, rpl, fname);
|
||||
}
|
||||
|
||||
DictionaryDb.insertWordsSync(dbWords);
|
||||
DictionaryDb.endTransaction(true);
|
||||
dbWords.clear();
|
||||
|
||||
publishProgress((int) ((float) pos / size * 10000));
|
||||
} catch (Exception e) {
|
||||
DictionaryDb.endTransaction(false);
|
||||
Logger.e("processFile", e.getMessage());
|
||||
} finally {
|
||||
br.close();
|
||||
is.close();
|
||||
ubis.close();
|
||||
is.close();
|
||||
|
||||
Logger.d("processFile", "Inserted: " + fname + " in: " + (System.currentTimeMillis() - start) + "ms");
|
||||
}
|
||||
return rpl;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Integer... progress) {
|
||||
if (pd.isShowing()) {
|
||||
pd.setProgress(progress[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Reply result) {
|
||||
finishAndShowError(pd, result, R.string.dictionary_load_title);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
|
@ -433,21 +64,32 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dint) {
|
||||
if (loader != null) {
|
||||
loader.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
Setting s = (Setting)getListView().getItemAtPosition(position);
|
||||
if (s.id.equals("help"))
|
||||
switch (s.id) {
|
||||
case "help":
|
||||
openHelp();
|
||||
else if (s.id.equals("loaddict"))
|
||||
preloader(R.string.dictionary_loading, true);
|
||||
else if (s.id.equals("truncatedict")) {
|
||||
break;
|
||||
case "loaddict":
|
||||
loadDictionaries();
|
||||
break;
|
||||
case "truncatedict":
|
||||
truncateWords();
|
||||
}
|
||||
else if (s.id.equals("loaduserdict"))
|
||||
preloader(R.string.dictionary_loading_user_dict, false);
|
||||
else
|
||||
break;
|
||||
default:
|
||||
s.clicked(mContext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void openHelp() {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
|
|
@ -465,50 +107,106 @@ public class TraditionalT9Settings extends ListActivity implements DialogInterfa
|
|||
DictionaryDb.truncateWords(afterTruncate);
|
||||
}
|
||||
|
||||
private void loadDictionaries() {
|
||||
ArrayList<Language> languages = LanguageCollection.getAll(T9Preferences.getInstance().getEnabledLanguages());
|
||||
initProgress(100 * languages.size());
|
||||
|
||||
private void preloader(int msgid, boolean internal) {
|
||||
Handler loadHandler = new Handler(Looper.getMainLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
String error = msg.getData().getString("error", null);
|
||||
|
||||
|
||||
task = new LoadDictTask(
|
||||
msgid,
|
||||
internal,
|
||||
LanguageCollection.getAll(T9Preferences.getInstance().getEnabledLanguages())
|
||||
if (error != null) {
|
||||
hideProgress();
|
||||
handleError(
|
||||
error,
|
||||
msg.getData().getInt("languageId", -1),
|
||||
msg.getData().getLong("fileLine", -1),
|
||||
msg.getData().getString("word", "")
|
||||
);
|
||||
task.execute();
|
||||
} else {
|
||||
int langId = msg.getData().getInt("languageId", -1);
|
||||
Language lang = LanguageCollection.getLanguage(langId);
|
||||
String langName = lang != null ? lang.getName() : "???";
|
||||
|
||||
String title = getResources().getString(R.string.dictionary_loading, langName);
|
||||
showProgress(
|
||||
msg.getData().getInt("currentFile", 0),
|
||||
msg.getData().getInt("progress", 0),
|
||||
title
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
loader = new DictionaryLoader(this);
|
||||
loader.load(loadHandler, languages);
|
||||
}
|
||||
|
||||
|
||||
private void initProgress(int max) {
|
||||
if (progressDialog == null) {
|
||||
progressDialog = new ProgressDialog(this);
|
||||
progressDialog.setOnCancelListener(TraditionalT9Settings.this);
|
||||
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
}
|
||||
|
||||
progressDialog.setMax(max);
|
||||
}
|
||||
|
||||
private void showProgress(int currentFile, int currentFileProgress, String title) {
|
||||
if (progressDialog == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (title != null) {
|
||||
progressDialog.setMessage(title);
|
||||
}
|
||||
|
||||
int totalProgress = 100 * currentFile + currentFileProgress;
|
||||
if (totalProgress <= 0 || totalProgress >= progressDialog.getMax()) {
|
||||
progressDialog.dismiss();
|
||||
} else {
|
||||
progressDialog.setProgress(totalProgress);
|
||||
if (!progressDialog.isShowing()) {
|
||||
progressDialog.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hideProgress() {
|
||||
if (progressDialog != null) {
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleError(String errorType, int langId, long line, String word) {
|
||||
Language lang = LanguageCollection.getLanguage(langId);
|
||||
String message;
|
||||
|
||||
if (lang == null || errorType.equals(InvalidLanguageException.class.getSimpleName())) {
|
||||
message = getString(R.string.add_word_invalid_language);
|
||||
} else if (errorType.equals(DictionaryImportException.class.getSimpleName()) || errorType.equals(InvalidLanguageCharactersException.class.getSimpleName())) {
|
||||
String languageName = lang.getName();
|
||||
message = getString(R.string.dictionary_import_bad_char, word, line, languageName);
|
||||
} else if (errorType.equals(IOException.class.getSimpleName()) || errorType.equals(FileNotFoundException.class.getSimpleName())) {
|
||||
String languageName = lang.getName();
|
||||
message = getString(R.string.dictionary_not_found, languageName);
|
||||
} else {
|
||||
String languageName = lang.getName();
|
||||
message = getString(R.string.dictionary_import_error, languageName, errorType);
|
||||
}
|
||||
|
||||
showErrorDialog(getString(R.string.dictionary_load_title), message);
|
||||
}
|
||||
|
||||
private void showErrorDialog(CharSequence title, CharSequence msg) {
|
||||
showErrorDialog(new AlertDialog.Builder(this), title, msg);
|
||||
}
|
||||
|
||||
private void showErrorDialog(AlertDialog.Builder builder, CharSequence title, CharSequence msg) {
|
||||
builder.setMessage(msg).setTitle(title)
|
||||
.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder
|
||||
.setMessage(msg)
|
||||
.setTitle(title)
|
||||
.setNeutralButton(android.R.string.ok, (dialog, id) -> dialog.dismiss());
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void showErrorDialogID(AlertDialog.Builder builder, int titleid, int msgid) {
|
||||
builder.setMessage(msgid).setTitle(titleid)
|
||||
.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dint) {
|
||||
task.cancel(false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue