Arabic Language
fixed custom ABC string not being displayed simplified the Arabic numbers code simplified displaying the Arabic question mark on the virtual keyboard Arabic numbers are properly displayed on the virtual keyboard injected word frequencies and sorted the dictionary updated the readme
This commit is contained in:
parent
ec87ce080c
commit
79902e4e95
15 changed files with 1272521 additions and 26 deletions
7
docs/dictionaries/arWordlistReadme.txt
Normal file
7
docs/dictionaries/arWordlistReadme.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Arabic word list by: Amchart Jamal
|
||||
Version: 90ff427 (2020-10-29)
|
||||
Source: https://github.com/jamalamch/Arabic-Words/blob/master/AllListWordArabic.txt
|
||||
|
||||
Frequency list by: AnySoftKeyboard
|
||||
Version: 082f145 (2020-01-29)
|
||||
Source: https://github.com/AnySoftKeyboard/AnySoftKeyboard/blob/main/addons/languages/arabic/pack/dictionary/lulua.combined.gz
|
||||
16
languages/definitions/Arabic.yml
Normal file
16
languages/definitions/Arabic.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
locale: ar-JO
|
||||
dictionaryFile: ar-utf8.csv
|
||||
abcString: أﺏﺕ
|
||||
hasUpperCase: no
|
||||
layout:
|
||||
- [SPECIAL] # 0
|
||||
- [PUNCTUATION_AR] # 1
|
||||
- [ب,ت,ة,ث] # 2
|
||||
- [ا,أ,إ,آ,ى,ؤ,ئ,ء] # 3
|
||||
- [س,ش,ص,ض] # 4
|
||||
- [د,ذ,ر,ز] # 5
|
||||
- [ج,ح,خ] # 6
|
||||
- [ن,ه,و,ي] # 7
|
||||
- [ف,ق,ك,ل,م] # 8
|
||||
- [ط,ظ,ع,غ] # 9
|
||||
1272407
languages/dictionaries/ar-utf8.csv
Normal file
1272407
languages/dictionaries/ar-utf8.csv
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -11,7 +11,7 @@ public class TextTools {
|
|||
private static final Pattern previousIsLetter = Pattern.compile("\\p{L}$");
|
||||
private static final Pattern nextIsPunctuation = Pattern.compile("^\\p{Punct}");
|
||||
private static final Pattern nextToWord = Pattern.compile("\\b$");
|
||||
private static final Pattern startOfSentence = Pattern.compile("(?<!\\.)(^|[.?!¿¡])\\s+$");
|
||||
private static final Pattern startOfSentence = Pattern.compile("(?<!\\.)(^|[.?!؟¿¡])\\s+$");
|
||||
|
||||
public static boolean containsOtherThan1(String str) {
|
||||
return str != null && containsOtherThan1.matcher(str).find();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public class ModeABC extends InputMode {
|
|||
public boolean onNumber(int number, boolean hold, int repeat) {
|
||||
if (hold) {
|
||||
reset();
|
||||
suggestions.add(String.valueOf(number));
|
||||
suggestions.add(language.getKeyNumber(number));
|
||||
autoAcceptTimeout = 0;
|
||||
} else if (repeat > 0) {
|
||||
shouldSelectNextLetter = true;
|
||||
|
|
@ -70,11 +70,16 @@ public class ModeABC extends InputMode {
|
|||
return textCase == CASE_LOWER ? "abc" : "ABC";
|
||||
}
|
||||
|
||||
String langCode = language.getLocale().getCountry();
|
||||
langCode = langCode.isEmpty() ? language.getLocale().getLanguage() : langCode;
|
||||
langCode = langCode.isEmpty() ? language.getName() : langCode;
|
||||
|
||||
String modeString = language.getAbcString() + " / " + langCode.toUpperCase();
|
||||
String langCode = "";
|
||||
if (language.isLatinBased() || language.isCyrillic()) {
|
||||
// There are many languages written using the same alphabet, so if the user has enabled multiple,
|
||||
// make it clear which one is it, by appending the country code to "ABC" or "АБВ".
|
||||
langCode = language.getLocale().getCountry();
|
||||
langCode = langCode.isEmpty() ? language.getLocale().getLanguage() : langCode;
|
||||
langCode = langCode.isEmpty() ? language.getName() : langCode;
|
||||
langCode = " / " + langCode;
|
||||
}
|
||||
String modeString = language.getAbcString() + langCode.toUpperCase();
|
||||
|
||||
return (textCase == CASE_LOWER) ? modeString.toLowerCase(language.getLocale()) : modeString.toUpperCase(language.getLocale());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ public class ModePredictive extends InputMode {
|
|||
reset();
|
||||
autoAcceptTimeout = 0;
|
||||
disablePredictions = true;
|
||||
suggestions.add(String.valueOf(number));
|
||||
suggestions.add(language.getKeyNumber(number));
|
||||
} else {
|
||||
// words
|
||||
super.reset();
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ public class AutoSpace {
|
|||
|| previousChar == ']'
|
||||
|| previousChar == '%'
|
||||
|| previousChar == '»'
|
||||
|| previousChar == '؟'
|
||||
|| previousChar == '“'
|
||||
|| previousChars.endsWith(" -")
|
||||
|| previousChars.endsWith(" /")
|
||||
|
|
@ -118,6 +119,7 @@ public class AutoSpace {
|
|||
|| lastWord.equals(":")
|
||||
|| lastWord.equals("!")
|
||||
|| lastWord.equals("?")
|
||||
|| lastWord.equals("؟")
|
||||
|| lastWord.equals(")")
|
||||
|| lastWord.equals("]")
|
||||
|| lastWord.equals("'")
|
||||
|
|
|
|||
|
|
@ -7,6 +7,14 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
|
||||
public class Characters {
|
||||
final public static ArrayList<String> ArabicNumbers = new ArrayList<>(Arrays.asList(
|
||||
"٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"
|
||||
));
|
||||
|
||||
final public static ArrayList<String> PunctuationArabic = new ArrayList<>(Arrays.asList(
|
||||
"،", ".", "-", "(", ")", "[", "]", "&", "~", "`", "\"", "'", "؛", ":", "!", "؟"
|
||||
));
|
||||
|
||||
final public static ArrayList<String> PunctuationEnglish = new ArrayList<>(Arrays.asList(
|
||||
",", ".", "-", "(", ")", "[", "]", "&", "~", "`", "'", ";", ":", "\"", "!", "?"
|
||||
));
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public class Language {
|
|||
}
|
||||
|
||||
Language lang = new Language();
|
||||
lang.abcString = definition.abcString.isEmpty() ? lang.abcString : definition.abcString;
|
||||
lang.abcString = definition.abcString.isEmpty() ? null : definition.abcString;
|
||||
lang.dictionaryFile = definition.getDictionaryFile();
|
||||
lang.hasUpperCase = definition.hasUpperCase;
|
||||
lang.locale = definitionLocale;
|
||||
|
|
@ -74,8 +74,9 @@ public class Language {
|
|||
|
||||
final String specialCharsPlaceholder = "SPECIAL";
|
||||
final String punctuationPlaceholder = "PUNCTUATION";
|
||||
final String frenchStylePlaceholder = punctuationPlaceholder + "_FR";
|
||||
final String arabicStylePlaceholder = punctuationPlaceholder + "_AR";
|
||||
final String germanStylePlaceholder = punctuationPlaceholder + "_DE";
|
||||
final String frenchStylePlaceholder = punctuationPlaceholder + "_FR";
|
||||
|
||||
ArrayList<String> keyChars = new ArrayList<>();
|
||||
for (String defChar : definitionChars) {
|
||||
|
|
@ -86,12 +87,15 @@ public class Language {
|
|||
case punctuationPlaceholder:
|
||||
keyChars.addAll(Characters.PunctuationEnglish);
|
||||
break;
|
||||
case frenchStylePlaceholder:
|
||||
keyChars.addAll(Characters.PunctuationFrench);
|
||||
case arabicStylePlaceholder:
|
||||
keyChars.addAll(Characters.PunctuationArabic);
|
||||
break;
|
||||
case germanStylePlaceholder:
|
||||
keyChars.addAll(Characters.PunctuationGerman);
|
||||
break;
|
||||
case frenchStylePlaceholder:
|
||||
keyChars.addAll(Characters.PunctuationFrench);
|
||||
break;
|
||||
default:
|
||||
keyChars.add(defChar);
|
||||
break;
|
||||
|
|
@ -134,7 +138,6 @@ public class Language {
|
|||
for (int i = 0; i < lettersList.size() && i < 3; i++) {
|
||||
sb.append(lettersList.get(i));
|
||||
}
|
||||
|
||||
abcString = sb.toString();
|
||||
}
|
||||
|
||||
|
|
@ -154,10 +157,18 @@ public class Language {
|
|||
return getKeyCharacters(2, false).contains("a");
|
||||
}
|
||||
|
||||
public boolean isCyrillic() {
|
||||
return getKeyCharacters(2, false).contains("а");
|
||||
}
|
||||
|
||||
public boolean isGreek() {
|
||||
return getKeyCharacters(2, false).contains("α");
|
||||
}
|
||||
|
||||
public boolean isArabic() {
|
||||
return getKeyCharacters(3, false).contains("ا");
|
||||
}
|
||||
|
||||
public boolean isUkrainian() {
|
||||
return getKeyCharacters(3, false).contains("є");
|
||||
}
|
||||
|
|
@ -243,7 +254,7 @@ public class Language {
|
|||
|
||||
ArrayList<String> chars = new ArrayList<>(layout.get(key));
|
||||
if (includeDigit && chars.size() > 0) {
|
||||
chars.add(String.valueOf(key));
|
||||
chars.add(getKeyNumber(key));
|
||||
}
|
||||
|
||||
return chars;
|
||||
|
|
@ -253,6 +264,14 @@ public class Language {
|
|||
return getKeyCharacters(key, true);
|
||||
}
|
||||
|
||||
public String getKeyNumber(int key) {
|
||||
if (key > 10 || key < 0) {
|
||||
return null;
|
||||
} else {
|
||||
return isArabic() ? Characters.ArabicNumbers.get(key) : String.valueOf(key);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDigitSequenceForWord(String word) throws InvalidLanguageCharactersException {
|
||||
StringBuilder sequence = new StringBuilder();
|
||||
String lowerCaseWord = word.toLowerCase(locale);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ public class LanguageCollection {
|
|||
return self;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Language getLanguage(Context context, int langId) {
|
||||
if (getInstance(context).languages.containsKey(langId)) {
|
||||
return getInstance(context).languages.get(langId);
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ public class LanguageDefinition {
|
|||
LanguageDefinition definition = new LanguageDefinition();
|
||||
String value;
|
||||
|
||||
value = getPropertyFromYaml(yaml, "absString");
|
||||
value = getPropertyFromYaml(yaml, "abcString");
|
||||
definition.abcString = value != null ? value : definition.abcString;
|
||||
|
||||
value = getPropertyFromYaml(yaml, "dictionaryFile");
|
||||
|
|
|
|||
|
|
@ -278,6 +278,10 @@ public class SettingsStore {
|
|||
public final static int PREFERENCES_CLICK_DEBOUNCE_TIME = 250; // ms
|
||||
public final static byte SLOW_QUERY_TIME = 50; // ms
|
||||
public final static int SOFT_KEY_REPEAT_DELAY = 40; // ms
|
||||
public final static float SOFT_KEY_COMPLEX_LABEL_TITLE_SIZE = 0.55f;
|
||||
public final static float SOFT_KEY_COMPLEX_LABEL_ARABIC_TITLE_SIZE = 0.72f;
|
||||
public final static float SOFT_KEY_COMPLEX_LABEL_SUB_TITLE_SIZE = 0.8f;
|
||||
|
||||
public final static int SUGGESTIONS_MAX = 20;
|
||||
public final static int SUGGESTIONS_MIN = 8;
|
||||
public final static int SUGGESTIONS_SELECT_ANIMATION_DURATION = 66;
|
||||
|
|
|
|||
|
|
@ -12,18 +12,21 @@ import android.util.AttributeSet;
|
|||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||
|
||||
public class SoftKey extends androidx.appcompat.widget.AppCompatButton implements View.OnTouchListener, View.OnLongClickListener {
|
||||
protected TraditionalT9 tt9;
|
||||
|
||||
protected float COMPLEX_LABEL_TITLE_SIZE = 0.55f;
|
||||
protected float COMPLEX_LABEL_SUB_TITLE_SIZE = 0.8f;
|
||||
protected float complexLabelTitleSize = SettingsStore.SOFT_KEY_COMPLEX_LABEL_TITLE_SIZE;
|
||||
protected float complexLabelSubTitleSize = SettingsStore.SOFT_KEY_COMPLEX_LABEL_SUB_TITLE_SIZE;
|
||||
|
||||
private boolean hold = false;
|
||||
private boolean repeat = false;
|
||||
|
|
@ -160,6 +163,10 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
|||
return true;
|
||||
}
|
||||
|
||||
@Nullable protected Language getCurrentLanguage() {
|
||||
return LanguageCollection.getLanguage(tt9.getApplicationContext(), tt9.getSettings().getInputLanguage());
|
||||
}
|
||||
|
||||
/**
|
||||
* getTitle
|
||||
* Generates the name of the key, for example: "OK", "Backspace", "1", etc...
|
||||
|
|
@ -203,9 +210,15 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
|||
sb.append('\n');
|
||||
sb.append(subtitle);
|
||||
|
||||
sb.setSpan(new RelativeSizeSpan(COMPLEX_LABEL_TITLE_SIZE), 0, 2, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
sb.setSpan(new StyleSpan(Typeface.ITALIC), 0, 2, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
|
||||
sb.setSpan(new RelativeSizeSpan(COMPLEX_LABEL_SUB_TITLE_SIZE), 1, sb.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
float padding = SettingsStore.SOFT_KEY_COMPLEX_LABEL_TITLE_SIZE;
|
||||
if (complexLabelTitleSize == SettingsStore.SOFT_KEY_COMPLEX_LABEL_ARABIC_TITLE_SIZE) {
|
||||
padding /= 10;
|
||||
}
|
||||
|
||||
sb.setSpan(new RelativeSizeSpan(complexLabelTitleSize), 0, 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
sb.setSpan(new StyleSpan(Typeface.ITALIC), 0, 1, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
|
||||
sb.setSpan(new RelativeSizeSpan(padding), 1, 2, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
sb.setSpan(new RelativeSizeSpan(complexLabelSubTitleSize), 2, sb.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
|
||||
setText(sb);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import io.github.sspanak.tt9.R;
|
|||
import io.github.sspanak.tt9.ime.helpers.Key;
|
||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||
|
||||
public class SoftNumberKey extends SoftKey {
|
||||
public SoftNumberKey(Context context) {
|
||||
|
|
@ -53,7 +53,16 @@ public class SoftNumberKey extends SoftKey {
|
|||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return String.valueOf(getNumber(getId()));
|
||||
int number = getNumber(getId());
|
||||
|
||||
Language language = getCurrentLanguage();
|
||||
if (language != null && language.isArabic() && tt9 != null && !tt9.isInputModeNumeric()) {
|
||||
complexLabelTitleSize = SettingsStore.SOFT_KEY_COMPLEX_LABEL_ARABIC_TITLE_SIZE;
|
||||
return language.getKeyNumber(number);
|
||||
} else {
|
||||
complexLabelTitleSize = SettingsStore.SOFT_KEY_COMPLEX_LABEL_TITLE_SIZE;
|
||||
return String.valueOf(number);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -73,7 +82,7 @@ public class SoftNumberKey extends SoftKey {
|
|||
} else if (tt9.isInputModeNumeric()) {
|
||||
return "+";
|
||||
} else {
|
||||
COMPLEX_LABEL_SUB_TITLE_SIZE = 1;
|
||||
complexLabelSubTitleSize = 1;
|
||||
return "␣";
|
||||
}
|
||||
}
|
||||
|
|
@ -89,7 +98,7 @@ public class SoftNumberKey extends SoftKey {
|
|||
}
|
||||
|
||||
// 2-9
|
||||
Language language = LanguageCollection.getLanguage(tt9.getApplicationContext(), tt9.getSettings().getInputLanguage());
|
||||
Language language = getCurrentLanguage();
|
||||
if (language == null) {
|
||||
Logger.d("SoftNumberKey.getLabel", "Cannot generate a label when the language is NULL.");
|
||||
return "";
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
|||
import android.util.AttributeSet;
|
||||
|
||||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.languages.Language;
|
||||
|
||||
public class SoftPunctuationKey extends SoftKey {
|
||||
public SoftPunctuationKey(Context context) {
|
||||
|
|
@ -50,7 +51,10 @@ public class SoftPunctuationKey extends SoftKey {
|
|||
if (keyId == R.id.soft_key_punctuation_2) return ".";
|
||||
} else {
|
||||
if (keyId == R.id.soft_key_punctuation_1) return "!";
|
||||
if (keyId == R.id.soft_key_punctuation_2) return "?";
|
||||
if (keyId == R.id.soft_key_punctuation_2) {
|
||||
Language language = getCurrentLanguage();
|
||||
return language != null && language.isArabic() ? "؟" : "?";
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue