diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 6cd79fcf..16084aff 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,6 +1,12 @@
name: Build the Project
-on: [pull_request]
+on:
+ pull_request:
+ branches:
+ - "**"
+ push:
+ branches:
+ - master
jobs:
build:
@@ -15,5 +21,7 @@ jobs:
# validation
- name: Validate Dictionaries
run: ./gradlew validateDictionaries
+ - name: Lint
+ run: ./gradlew lint
- name: Build Release APK
- run: ./gradlew assemble
+ run: ./gradlew build
diff --git a/build.gradle b/build.gradle
index cbdbf9b8..d34fcad8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -81,6 +81,89 @@ def getReleaseVersion = { ->
return "${getVersionName()} (${getCurrentGitHash()})"
}
+task validateDictionaries {
+ inputs.dir fileTree(dir:'assets', excludes:['dict.properties'])
+ outputs.file "${project.buildDir}/dict.validation.txt"
+
+ doLast {
+ final String csvDelimiter = ' ' // TAB
+
+ String errors = ""
+ int errorCount = 0
+ final MAX_ERRORS = 50
+
+ outputs.files.singleFile.text = ""
+
+ inputs.getFiles().each {File file ->
+ if (errorCount >= MAX_ERRORS) {
+ return
+ }
+
+ println "Validating dictionary: " + file.name
+
+ def geographicalName = ~"[A-Z]\\w+-[^\\n]+"
+ def uniqueWords = [:]
+
+ int lineNumber = 0
+ boolean isFileValid = true
+
+ file.eachLine {line ->
+ if (errorCount >= MAX_ERRORS) {
+ return
+ }
+
+ lineNumber++
+
+ String[] parts = line.split(csvDelimiter, 2)
+ String word = parts[0]
+ String frequency = parts.length > 1 ? parts[1] : ""
+
+ if (frequency.length() > 0 && !frequency.matches("^\\d+\$")) {
+ isFileValid = false
+ errorCount++
+ errors += "Dictionary '" + file.name + "' is invalid. Found out-of-range word frequency: '" + frequency + "' on line " + lineNumber + ". Frequency must be a non-negative integer. \n"
+ }
+
+ if (word.matches("(\\d.+?|.+?\\d|\\d)")) {
+ isFileValid = false
+ errorCount++
+ errors += "Dictionary '" + file.name + "' is invalid. Found numbers on line " + lineNumber + ". Please, remove all numbers.\n"
+ }
+
+ if (word.matches("^\\P{L}+\$")) {
+ isFileValid = false
+ errorCount++
+ errors += "Dictionary '" + file.name + "' is invalid. Found a garbage word: '" + word + "' on line " + lineNumber + ".\n"
+ }
+
+ if (word.matches("^.\$") && !Character.isUpperCase(word.charAt(0))) {
+ isFileValid = false
+ errorCount++
+ errors += "Dictionary '" + file.name + "' is invalid. Found a single letter: '" + word + "' on line " + lineNumber + ". Only uppercase single letters are allowed. The rest of the alphabet will be added automatically.\n"
+ }
+
+ String uniqueWordKey = word ==~ geographicalName ? word : word.toLowerCase()
+ if (uniqueWords[uniqueWordKey] != null && uniqueWords[uniqueWordKey] == true) {
+ isFileValid = false
+ errorCount++
+ errors += "Dictionary '" + file.name + "' is invalid. Found a repeating word: '" + word + "' on line " + lineNumber + ". Ensure all words appear only once.\n"
+ } else {
+ uniqueWords[uniqueWordKey] = true
+ }
+
+ if (errorCount >= MAX_ERRORS ) {
+ errors += "Too many errors! Aborting.\n"
+ }
+ }
+
+ outputs.files.singleFile.text += file.name + " " + (isFileValid ? "OK" : "INVALID") + "\n"
+ }
+
+ if (errors != "") {
+ throw new GradleException(errors)
+ }
+ }
+}
android {
buildToolsVersion "33.0.0"
@@ -143,78 +226,8 @@ android {
// signingConfig android.signingConfigs.release
}
}
-}
-task validateDictionaries {
- inputs.dir fileTree(dir:'assets', excludes:['dict.properties'])
-
- doLast {
- final String csvDelimiter = ' '
-
- String errors = ""
- int errorCount = 0
- final MAX_ERRORS = 50
-
- inputs.getFiles().each {File file ->
- if (errorCount >= MAX_ERRORS) {
- return
- }
- println "Validating dictionary: " + file.name
-
- def geographicalName = ~"[A-Z]\\w+-[^\\n]+"
- def uniqueWords = [:]
-
- int lineNumber = 0
- file.eachLine {line ->
- if (errorCount >= MAX_ERRORS) {
- return
- }
-
- lineNumber++
-
- String[] parts = line.split(csvDelimiter, 2)
- String word = parts[0]
- String frequency = parts.length > 1 ? parts[1] : ""
-
- if (frequency.length() > 0 && !frequency.matches("^\\d+\$")) {
- errorCount++
- errors += "Dictionary '" + file.name + "' is invalid. Found out-of-range word frequency: '" + frequency + "' on line " + lineNumber + ". Frequency must be a non-negative integer. \n"
- }
-
- if (word.matches("(\\d.+?|.+?\\d|\\d)")) {
- errorCount++
- errors += "Dictionary '" + file.name + "' is invalid. Found numbers on line " + lineNumber + ". Please, remove all numbers.\n"
- }
-
- if (word.matches("^\\P{L}+\$")) {
- errorCount++
- errors += "Dictionary '" + file.name + "' is invalid. Found a garbage word: '" + word + "' on line " + lineNumber + ".\n"
- }
-
- if (word.matches("^.\$") && !Character.isUpperCase(word.charAt(0))) {
- errorCount++
- errors += "Dictionary '" + file.name + "' is invalid. Found a single letter: '" + word + "' on line " + lineNumber + ". Only uppercase single letters are allowed. The rest of the alphabet will be added automatically.\n"
- }
-
- String uniqueWordKey = word ==~ geographicalName ? word : word.toLowerCase()
- if (uniqueWords[uniqueWordKey] != null && uniqueWords[uniqueWordKey] == true) {
- errorCount++
- errors += "Dictionary '" + file.name + "' is invalid. Found a repeating word: '" + word + "' on line " + lineNumber + ". Ensure all words appear only once.\n"
- } else {
- uniqueWords[uniqueWordKey] = true
- }
-
- if (errorCount >= MAX_ERRORS ) {
- errors += "Too many errors! Aborting.\n"
- }
- }
- }
-
- if (errors != "") {
- throw new GradleException(errors)
- }
+ applicationVariants.all { variant ->
+ tasks["merge${variant.name.capitalize()}Assets"].dependsOn(validateDictionaries)
}
}
-
-preBuild.dependsOn validateDictionaries
-preBuild.mustRunAfter validateDictionaries
diff --git a/lint.xml b/lint.xml
new file mode 100644
index 00000000..d121ef63
--- /dev/null
+++ b/lint.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index a102776f..21152d10 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -49,5 +49,5 @@
Символ при многократно натисната \"0\"
Нов ред
Интервал
- Напишете дума...
+ Напишете дума…
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index c3620aed..1ee02445 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -40,5 +40,5 @@
Espace
Nouvelle ligne
Caractère lorsque «0» est appuyé plusieurs fois
- Tapez un mot...
+ Tapez un mot…
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index fbb246cb..144967b2 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -49,5 +49,5 @@
(зажать)
Назад
Позвонить
- Введите слово...
+ Введите слово…
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index e24847d5..6c57552b 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -49,5 +49,5 @@
Словник успішно очищено.
Немає словника для мови «%1$s». Перейдіть до Налаштувань, щоб завантажити його.
Помилка завантаження. Недійсне слово «%1$s» в рядку %2$d мови «%3$s».
- Введіть слово...
+ Введіть слово…
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e77bbcb6..bb0fcb02 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -11,7 +11,7 @@
Word \"%1$s\" already in the dictionary.
Cannot add a word when no language is selected.
Add Word
- Type a word...
+ Type a word…
About
Appearance