1
0
Fork 0

added support for custom numerals in the language definitions

This commit is contained in:
sspanak 2025-02-17 15:26:07 +02:00 committed by Dimo Karaivanov
parent afa509cee0
commit c28c9f053e
11 changed files with 56 additions and 34 deletions

View file

@ -3,6 +3,7 @@ currency: ﷼
dictionaryFile: ar-utf8.csv
abcString: أﺏﺕ
hasUpperCase: no
numerals: [٠,١,٢,٣,٤,٥,٦,٧,٨,٩]
layout:
- [SPECIAL] # 0
- [PUNCTUATION_AR] # 1

View file

@ -46,7 +46,7 @@ class ModeABC extends InputMode {
autoAcceptTimeout = 0;
digitSequence = String.valueOf(number);
shouldSelectNextLetter = false;
suggestions.add(language.getKeyNumber(number));
suggestions.add(language.getKeyNumeral(number));
} else if (repeat > 0) {
autoAcceptTimeout = settings.getAbcAutoAcceptTimeout();
shouldSelectNextLetter = true;
@ -56,7 +56,7 @@ class ModeABC extends InputMode {
digitSequence = String.valueOf(number);
shouldSelectNextLetter = false;
suggestions.addAll(KEY_CHARACTERS.size() > number ? KEY_CHARACTERS.get(number) : settings.getOrderedKeyChars(language, number));
suggestions.add(language.getKeyNumber(number));
suggestions.add(language.getKeyNumeral(number));
}
return true;
@ -86,7 +86,7 @@ class ModeABC extends InputMode {
return false;
}
suggestions.add(language.getKeyNumber(digitSequence.charAt(0) - '0'));
suggestions.add(language.getKeyNumeral(digitSequence.charAt(0) - '0'));
return true;
}

View file

@ -143,7 +143,7 @@ class ModeCheonjiin extends InputMode {
digitSequence = PUNCTUATION_SEQUENCE;
} else {
autoAcceptTimeout = 0;
suggestions.add(language.getKeyNumber(number));
suggestions.add(language.getKeyNumeral(number));
}
}

View file

@ -94,7 +94,7 @@ class ModeWords extends ModeCheonjiin {
@Override
protected void onNumberHold(int number) {
autoAcceptTimeout = 0;
suggestions.add(language.getKeyNumber(number));
suggestions.add(language.getKeyNumeral(number));
}

View file

@ -55,7 +55,7 @@ abstract public class Language {
return getKeyCharacters(key, 0);
}
@NonNull public String getKeyNumber(int key) {
@NonNull public String getKeyNumeral(int key) {
return String.valueOf(key);
}

View file

@ -8,6 +8,7 @@ import androidx.annotation.Nullable;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import io.github.sspanak.tt9.BuildConfig;
import io.github.sspanak.tt9.util.AssetFile;
@ -29,6 +30,7 @@ public class LanguageDefinition {
public ArrayList<ArrayList<String>> layout = new ArrayList<>();
public String locale = "";
public String name = "";
@NonNull public HashMap<Integer, String> numerals = new HashMap<>();
private boolean inLayout = false;
@ -125,28 +127,31 @@ public class LanguageDefinition {
switch (key) {
case "abcString":
abcString = value;
break;
return;
case "currency":
currency = value;
break;
return;
case "dictionaryFile":
dictionaryFile = value.replaceFirst("\\.\\w+$", "." + BuildConfig.DICTIONARY_EXTENSION);
break;
return;
case "hasSpaceBetweenWords":
hasSpaceBetweenWords = parseYamlBoolean(value);
break;
return;
case "hasUpperCase":
hasUpperCase = parseYamlBoolean(value);
break;
return;
case "sounds":
isSyllabary = true;
break;
return;
case "locale":
locale = value;
break;
return;
case "name":
name = value;
break;
return;
case "numerals":
setNumerals(value);
return;
}
}
@ -159,7 +164,7 @@ public class LanguageDefinition {
return inLayout = "layout:".equals(line);
}
ArrayList<String> layoutEntry = getLayoutEntryFromYamlLine(line);
ArrayList<String> layoutEntry = parseList(line);
if (layoutEntry == null) {
inLayout = false;
} else {
@ -171,13 +176,25 @@ public class LanguageDefinition {
}
private void setNumerals(@NonNull String yamlList) {
ArrayList<String> numberList = parseList(yamlList);
if (numberList == null || numberList.size() != 10) {
return;
}
for (int i = 0; i < 10; i++) {
numerals.put(i, numberList.get(i));
}
}
/**
* getLayoutEntryFromYamlLine
* Validates a YAML line as an array and returns the character list to be assigned to a given key (a layout entry).
* If the YAML line is invalid, NULL will be returned.
*/
@Nullable
private ArrayList<String> getLayoutEntryFromYamlLine(@NonNull String yamlLine) {
private ArrayList<String> parseList(@NonNull String yamlLine) {
int start = yamlLine.indexOf('[');
int end = yamlLine.indexOf(']');
if (start == -1 || end == -1 || start >= end) {

View file

@ -22,6 +22,7 @@ public class NaturalLanguage extends Language implements Comparable<NaturalLangu
protected final ArrayList<ArrayList<String>> layout = new ArrayList<>();
private final HashMap<Character, String> characterKeyMap = new HashMap<>();
@NonNull private HashMap<Integer, String> numerals = new HashMap<>();
public static NaturalLanguage fromDefinition(LanguageDefinition definition) throws Exception {
@ -37,6 +38,7 @@ public class NaturalLanguage extends Language implements Comparable<NaturalLangu
lang.hasUpperCase = definition.hasUpperCase;
lang.isSyllabary = definition.isSyllabary;
lang.name = definition.name.isEmpty() ? lang.name : definition.name;
lang.numerals = definition.numerals;
lang.setLocale(definition);
lang.setLayout(definition);
@ -195,7 +197,7 @@ public class NaturalLanguage extends Language implements Comparable<NaturalLangu
private void generateCharacterKeyMap() {
characterKeyMap.clear();
for (int digit = 0; digit <= 9; digit++) {
characterKeyMap.put(getKeyNumber(digit).charAt(0), String.valueOf(digit));
characterKeyMap.put(getKeyNumeral(digit).charAt(0), String.valueOf(digit));
for (String keyChar : getKeyCharacters(digit)) {
characterKeyMap.put(keyChar.charAt(0), String.valueOf(digit));
}
@ -224,8 +226,9 @@ public class NaturalLanguage extends Language implements Comparable<NaturalLangu
@NonNull
public String getKeyNumber(int key) {
return key >= 0 && key < 10 && LanguageKind.isArabic(this) ? Characters.ArabicNumbers.get(key) : super.getKeyNumber(key);
public String getKeyNumeral(int key) {
String digit = numerals.containsKey(key) ? numerals.get(key) : null;
return digit != null ? digit : super.getKeyNumeral(key);
}

View file

@ -85,8 +85,8 @@ public class SoftKeyNumber extends BaseSoftKeyWithIcons {
protected String getLocalizedNumber(int number) {
if (isArabicNumber() && tt9 != null && tt9.getLanguage() != null) {
return tt9.getLanguage().getKeyNumber(number);
if (tt9 != null && !tt9.isInputModeNumeric() && tt9.getLanguage() != null) {
return tt9.getLanguage().getKeyNumeral(number);
} else {
return String.valueOf(number);
}
@ -98,9 +98,4 @@ public class SoftKeyNumber extends BaseSoftKeyWithIcons {
float defaultScale = super.getHoldElementScale();
return tt9 != null && LanguageKind.isArabic(tt9.getLanguage()) ? defaultScale * 1.25f : defaultScale;
}
private boolean isArabicNumber() {
return tt9 != null && !tt9.isInputModeNumeric() && LanguageKind.isArabic(tt9.getLanguage());
}
}

View file

@ -17,10 +17,6 @@ class Punctuation {
public static final String ZWNJ = "\u200C";
public static final String ZWNJ_GRAPHIC = "ZWNJ";
final public static ArrayList<String> ArabicNumbers = new ArrayList<>(Arrays.asList(
"٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"
));
final public static ArrayList<Character> CombiningPunctuation = new ArrayList<>(Arrays.asList(
',', '-', '\'', ':', ';', '!', '?', '.'
));

View file

@ -54,7 +54,7 @@ ext.parseLanguageDefintion = { File languageFile, String dictionariesDir ->
boolean hasLayout = false
boolean hasSounds = false
boolean isLocaleValid = false
boolean areNumeralsValid = true
String localeString = ""
String dictionaryFileName = ""
@ -69,6 +69,7 @@ ext.parseLanguageDefintion = { File languageFile, String dictionariesDir ->
&& !rawLine.startsWith("layout")
&& !rawLine.startsWith("locale")
&& !rawLine.startsWith("name")
&& !rawLine.startsWith("numerals")
&& !rawLine.startsWith("sounds")
) {
def parts = rawLine.split(":")
@ -90,6 +91,10 @@ ext.parseLanguageDefintion = { File languageFile, String dictionariesDir ->
errorMsg += "Language '${languageFile.name}' is invalid. Unrecognized '${property}' value: '${invalidVal}'. Only 'yes' and 'no' are allowed.\n"
}
if (line.startsWith("numerals")) {
areNumeralsValid = line.matches("^numerals:\\s*\\[(.,\\s*?){9}.\\]")
}
if (line.startsWith("layout")) {
hasLayout = true
}
@ -100,7 +105,6 @@ ext.parseLanguageDefintion = { File languageFile, String dictionariesDir ->
if (line.startsWith("locale")) {
localeString = line.replace("locale:", "").trim()
isLocaleValid = localeString.matches("^[a-z]{2,3}(?:-[A-Z]{2})?\$")
}
if (line.startsWith("dictionaryFile")) {
@ -146,12 +150,17 @@ ext.parseLanguageDefintion = { File languageFile, String dictionariesDir ->
errorMsg += "Language '${languageFile.name}' is invalid. 'sounds' property must contain series of phonetic transcriptions per digit sequence in the format: ' - [Yae,1221]' and so on.\n"
}
if (!isLocaleValid) {
if (!localeString.matches("^[a-z]{2,3}(?:-[A-Z]{2})?\$")) {
errorCount++
def msg = localeString.isEmpty() ? "Missing 'locale' property." : "Unrecognized locale format: '${localeString}'"
errorMsg += "Language '${languageFile.name}' is invalid. ${msg}\n"
}
if (!areNumeralsValid) {
errorCount++
errorMsg += "Language '${languageFile.name}' is invalid. 'numerals' property must contain a comma-separated list of 10 characters representing the digits from 0 to 9.\n"
}
dictionaryFile = new File("$dictionariesDir/${dictionaryFileName}")
if (dictionaryFileName.isEmpty() || !dictionaryFile.exists()) {
errorCount++