use dictionaries with wrong country rather than none

now e.g. pt_BR locale with also use pt_PT if only pt_BR dictionary is available
This commit is contained in:
Helium314 2023-08-19 19:12:01 +02:00
parent cee6bf65a2
commit 707a7bf48b
4 changed files with 39 additions and 22 deletions

View file

@ -33,6 +33,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.BufferUnderflowException; import java.nio.BufferUnderflowException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
@ -166,16 +167,17 @@ final public class BinaryDictionaryGetter {
* @param context the context on which to open the files upon. * @param context the context on which to open the files upon.
* @return an array of binary dictionary files, which may be empty but may not be null. * @return an array of binary dictionary files, which may be empty but may not be null.
*/ */
public static File[] getCachedWordLists(final String locale, final Context context) { public static File[] getCachedWordLists(final String locale, final Context context, final boolean weakMatchAcceptable) {
final File[] directoryList = DictionaryInfoUtils.getCachedDirectoryList(context); final File[] directoryList = DictionaryInfoUtils.getCachedDirectoryList(context);
if (null == directoryList) return EMPTY_FILE_ARRAY; if (null == directoryList) return EMPTY_FILE_ARRAY;
Arrays.sort(directoryList);
final HashMap<String, FileAndMatchLevel> cacheFiles = new HashMap<>(); final HashMap<String, FileAndMatchLevel> cacheFiles = new HashMap<>();
for (File directory : directoryList) { for (File directory : directoryList) {
if (!directory.isDirectory()) continue; if (!directory.isDirectory()) continue;
final String dirLocale = final String dirLocale =
DictionaryInfoUtils.getWordListIdFromFileName(directory.getName()).toLowerCase(Locale.ENGLISH); DictionaryInfoUtils.getWordListIdFromFileName(directory.getName()).toLowerCase(Locale.ENGLISH);
final int matchLevel = LocaleUtils.getMatchLevel(dirLocale, locale.toLowerCase(Locale.ENGLISH)); final int matchLevel = LocaleUtils.getMatchLevel(dirLocale, locale.toLowerCase(Locale.ENGLISH));
if (LocaleUtils.isMatch(matchLevel)) { if (weakMatchAcceptable ? LocaleUtils.isMatchWeak(matchLevel) : LocaleUtils.isMatch(matchLevel)) {
final File[] wordLists = directory.listFiles(); final File[] wordLists = directory.listFiles();
if (null != wordLists) { if (null != wordLists) {
for (File wordList : wordLists) { for (File wordList : wordLists) {
@ -243,8 +245,8 @@ final public class BinaryDictionaryGetter {
* @return The list of addresses of valid dictionary files, or null. * @return The list of addresses of valid dictionary files, or null.
*/ */
public static ArrayList<AssetFileAddress> getDictionaryFiles(final Locale locale, public static ArrayList<AssetFileAddress> getDictionaryFiles(final Locale locale,
final Context context, boolean notifyDictionaryPackForUpdates) { final Context context, boolean notifyDictionaryPackForUpdates, final boolean weakMatchAcceptable) {
final File[] cachedWordLists = getCachedWordLists(locale.toString(), context); final File[] cachedWordLists = getCachedWordLists(locale.toString(), context, weakMatchAcceptable);
final String mainDictId = DictionaryInfoUtils.getMainDictId(locale); final String mainDictId = DictionaryInfoUtils.getMainDictId(locale);
final DictPackSettings dictPackSettings = new DictPackSettings(context); final DictPackSettings dictPackSettings = new DictPackSettings(context);
@ -271,7 +273,7 @@ final public class BinaryDictionaryGetter {
} }
if (!foundMainDict && dictPackSettings.isWordListActive(mainDictId)) { if (!foundMainDict && dictPackSettings.isWordListActive(mainDictId)) {
final File dict = loadDictionaryFromAssets(locale.toString(), context); final File dict = loadDictionaryFromAssets(locale.toString(), context, weakMatchAcceptable);
final AssetFileAddress fallbackAsset; final AssetFileAddress fallbackAsset;
if (dict == null) { if (dict == null) {
// fall back to the old way (maybe remove? will not work if files are compressed) // fall back to the old way (maybe remove? will not work if files are compressed)
@ -298,7 +300,7 @@ final public class BinaryDictionaryGetter {
* *
* Returns null on IO errors or if no matching dictionary is found * Returns null on IO errors or if no matching dictionary is found
*/ */
public static File loadDictionaryFromAssets(final String locale, final Context context) { public static File loadDictionaryFromAssets(final String locale, final Context context, final boolean weakMatchAcceptable) {
final String[] dictionaryList = getAssetsDictionaryList(context); final String[] dictionaryList = getAssetsDictionaryList(context);
if (null == dictionaryList) return null; if (null == dictionaryList) return null;
String bestMatchName = null; String bestMatchName = null;
@ -310,8 +312,9 @@ final public class BinaryDictionaryGetter {
// assets files may contain the locale in lowercase, but dictionary headers usually // assets files may contain the locale in lowercase, but dictionary headers usually
// have an upper case country code, so we compare lowercase here // have an upper case country code, so we compare lowercase here
final int matchLevel = LocaleUtils.getMatchLevel(dictLocale.toLowerCase(Locale.ENGLISH), locale.toLowerCase(Locale.ENGLISH)); final int matchLevel = LocaleUtils.getMatchLevel(dictLocale.toLowerCase(Locale.ENGLISH), locale.toLowerCase(Locale.ENGLISH));
if (LocaleUtils.isMatch(matchLevel) && matchLevel > bestMatchLevel) { if ((weakMatchAcceptable ? LocaleUtils.isMatchWeak(matchLevel) : LocaleUtils.isMatch(matchLevel)) && matchLevel > bestMatchLevel) {
bestMatchName = dictionary; bestMatchName = dictionary;
bestMatchLevel = matchLevel;
} }
} }
if (bestMatchName == null) return null; if (bestMatchName == null) return null;

View file

@ -52,9 +52,19 @@ public final class DictionaryFactory {
} }
final LinkedList<Dictionary> dictList = new LinkedList<>(); final LinkedList<Dictionary> dictList = new LinkedList<>();
final ArrayList<AssetFileAddress> assetFileList = ArrayList<AssetFileAddress> assetFileList =
BinaryDictionaryGetter.getDictionaryFiles(locale, context, true); BinaryDictionaryGetter.getDictionaryFiles(locale, context, true, false);
if (null != assetFileList) {
boolean mainFound = false;
for (AssetFileAddress fileAddress : assetFileList) {
if (fileAddress.mFilename.contains("main")) {
mainFound = true;
break;
}
}
if (!mainFound) // try again and allow weaker match
assetFileList = BinaryDictionaryGetter.getDictionaryFiles(locale, context, true, true);
for (final AssetFileAddress f : assetFileList) { for (final AssetFileAddress f : assetFileList) {
final ReadOnlyBinaryDictionary readOnlyBinaryDictionary = final ReadOnlyBinaryDictionary readOnlyBinaryDictionary =
new ReadOnlyBinaryDictionary(f.mFilename, f.mOffset, f.mLength, new ReadOnlyBinaryDictionary(f.mFilename, f.mOffset, f.mLength,
@ -67,7 +77,6 @@ public final class DictionaryFactory {
killDictionary(context, f); killDictionary(context, f);
} }
} }
}
// If the list is empty, that means we should not use any dictionary (for example, the user // If the list is empty, that means we should not use any dictionary (for example, the user
// explicitly disabled the main dictionary), so the following is okay. dictList is never // explicitly disabled the main dictionary), so the following is okay. dictList is never

View file

@ -161,6 +161,11 @@ public final class LocaleUtils {
return LOCALE_MATCH <= level; return LOCALE_MATCH <= level;
} }
/** similar to isMatch, but returns true if there is anything matching (used for fallback) */
public static boolean isMatchWeak(final int level) {
return level > LOCALE_NO_MATCH;
}
private static final HashMap<String, Locale> sLocaleCache = new HashMap<>(); private static final HashMap<String, Locale> sLocaleCache = new HashMap<>();
/** /**

View file

@ -426,7 +426,7 @@ public class DictionaryInfoUtils {
for (final File directory : directoryList) { for (final File directory : directoryList) {
final String localeString = getWordListIdFromFileName(directory.getName()); final String localeString = getWordListIdFromFileName(directory.getName());
final File[] dicts = BinaryDictionaryGetter.getCachedWordLists( final File[] dicts = BinaryDictionaryGetter.getCachedWordLists(
localeString, context); localeString, context, false);
for (final File dict : dicts) { for (final File dict : dicts) {
final String wordListId = getWordListIdFromFileName(dict.getName()); final String wordListId = getWordListIdFromFileName(dict.getName());
if (!DictionaryInfoUtils.isMainWordListId(wordListId)) { if (!DictionaryInfoUtils.isMainWordListId(wordListId)) {