From a434be9fe2d07c1609ebdcfd1781d5f0df55e785 Mon Sep 17 00:00:00 2001 From: Balazs Perlaki-Horvath Date: Sat, 24 Feb 2024 15:52:52 +0100 Subject: [PATCH 1/2] Revert to 2 letter lang codes in DB --- Model/CategoriesToLanguage.swift | 12 ++--- .../ZimFileMetaData/ZimFileMetaData.mm | 8 +++- Tests/LibraryRefreshViewModelTest.swift | 2 +- Tests/OPDSParserTests.swift | 2 +- ViewModel/LibraryViewModel.swift | 44 +++++++------------ Views/Settings/Settings.swift | 2 - 6 files changed, 32 insertions(+), 38 deletions(-) diff --git a/Model/CategoriesToLanguage.swift b/Model/CategoriesToLanguage.swift index acff5a81..d3839dfb 100644 --- a/Model/CategoriesToLanguage.swift +++ b/Model/CategoriesToLanguage.swift @@ -7,23 +7,23 @@ import Foundation import Defaults struct CategoriesToLanguages { - + private let dictionary: [Category: Set] = Defaults[.categoriesToLanguages] - + func has(category: Category, inLanguages langCodes: Set) -> Bool { - guard !langCodes.isEmpty else { - return true // no languages provided, do not filter + guard !langCodes.isEmpty, !dictionary.isEmpty else { + return true // no languages or category filters provided, do not filter } guard let languages = dictionary[category] else { return false } return !languages.isDisjoint(with: langCodes) } - + static func save(_ dictionary: [Category: Set]) { Defaults[.categoriesToLanguages] = dictionary } - + static func allCategories() -> [Category] { let categoriesToLanguages = CategoriesToLanguages() let contentLanguages = Defaults[.libraryLanguageCodes] diff --git a/Model/Entities/ZimFileMetaData/ZimFileMetaData.mm b/Model/Entities/ZimFileMetaData/ZimFileMetaData.mm index d051aa82..1c38310b 100644 --- a/Model/Entities/ZimFileMetaData/ZimFileMetaData.mm +++ b/Model/Entities/ZimFileMetaData/ZimFileMetaData.mm @@ -63,7 +63,13 @@ } - (NSString *)getLanguageCodesFromBook:(kiwix::Book *)book { - return [NSString stringWithUTF8String:book->getCommaSeparatedLanguages().c_str()]; + NSString* string = [NSString stringWithUTF8String:book->getCommaSeparatedLanguages().c_str()]; + NSArray* components = [string componentsSeparatedByString: @","]; + NSMutableArray* langCodes = [NSMutableArray array]; + [components enumerateObjectsUsingBlock:^(id _Nonnull codeString, NSUInteger idx, BOOL * _Nonnull stop) { + [langCodes addObject:[NSLocale canonicalLanguageIdentifierFromString: codeString]]; + }]; + return [langCodes componentsJoinedByString: @","]; } - (NSString *)getCategoryFromBook:(kiwix::Book *)book { diff --git a/Tests/LibraryRefreshViewModelTest.swift b/Tests/LibraryRefreshViewModelTest.swift index caf90117..7e2d6242 100644 --- a/Tests/LibraryRefreshViewModelTest.swift +++ b/Tests/LibraryRefreshViewModelTest.swift @@ -193,7 +193,7 @@ final class LibraryRefreshViewModelTest: XCTestCase { XCTAssertEqual(zimFile.hasVideos, false) XCTAssertEqual(zimFile.includedInSearch, true) XCTAssertEqual(zimFile.isMissing, false) - XCTAssertEqual(zimFile.languageCode, "eng") + XCTAssertEqual(zimFile.languageCode, "en") XCTAssertEqual(zimFile.mediaCount, 566835) XCTAssertEqual(zimFile.name, "Best of Wikipedia") XCTAssertEqual(zimFile.persistentID, "wikipedia_en_top") diff --git a/Tests/OPDSParserTests.swift b/Tests/OPDSParserTests.swift index 501beedd..5e9ad471 100644 --- a/Tests/OPDSParserTests.swift +++ b/Tests/OPDSParserTests.swift @@ -70,7 +70,7 @@ final class OPDSParserTests: XCTestCase { XCTAssertEqual(metadata.groupIdentifier, "wikipedia_en_top") XCTAssertEqual(metadata.title, "Best of Wikipedia") XCTAssertEqual(metadata.fileDescription, "A selection of the best 50,000 Wikipedia articles") - XCTAssertEqual(metadata.languageCodes, "eng") + XCTAssertEqual(metadata.languageCodes, "en") XCTAssertEqual(metadata.category, "wikipedia") XCTAssertEqual(metadata.creationDate, try! Date("2023-01-07T00:00:00Z", strategy: .iso8601)) XCTAssertEqual(metadata.size, 6515656704) diff --git a/ViewModel/LibraryViewModel.swift b/ViewModel/LibraryViewModel.swift index f94f9d70..5d6b00c5 100644 --- a/ViewModel/LibraryViewModel.swift +++ b/ViewModel/LibraryViewModel.swift @@ -89,46 +89,36 @@ public class LibraryViewModel: ObservableObject { CategoriesToLanguages.save(dictionary) } - /// Make sure we remove the incompatible "en" if it was already set - static func cleanUpDefaultLanguages() { - Defaults[.libraryLanguageCodes] = Defaults[.libraryLanguageCodes].filter { langCode in - langCode != "en" - } - } - /// The fetched content is filtered by the languages set in settings. /// Try to set it to the device language, making sure we have content to display. /// Falls back to English, where most of the content is. /// This is only affecting the "fresh-install" defaults. /// The user can always set the prefered content languages in settings. private func setDefaultContentFilterLanguage() async { - Self.cleanUpDefaultLanguages() guard Defaults[.libraryLanguageCodes].isEmpty else { return // it was already set earlier (either by default or the user) } - - let defaultLangCode: String - + let fallbackToEnglish = "en" + let deviceLang: String? + // In both cases we store the 2 letter version in DB, that is our current + // standard, even though the feed values are 3 letter, those are also converted to 2 letter values if #available(iOS 16, macOS 13, *) { - let languages = await Languages.fetch() - // Double check if the current device language is on the list of languages, - // and there is content in that language - if let deviceLang = Locale.current.language.languageCode?.identifier(.alpha3), - languages.contains(where: { (lang: Language) in - lang.code == deviceLang && lang.count > 0 - }) { - defaultLangCode = deviceLang - } else { - defaultLangCode = "eng" - } + deviceLang = Locale.current.language.languageCode?.identifier(.alpha2) } else { - // Locale.current.languageCode is returning a 2 char lang code, eg: "en" - // we want a 3 char value, eg: "eng", otherwise we filter out every results - // and end up with an empty list in the categories - defaultLangCode = "eng" + deviceLang = Locale.current.languageCode } + // if the device language code cannot be determined, we fall back to English + let defaultLangCode: String = deviceLang ?? fallbackToEnglish + let languages = await Languages.fetch() - Defaults[.libraryLanguageCodes] = [defaultLangCode] + // make sure the language we default to is on the list of Languages comming from the feed + if languages.contains(where: { (lang: Language) in + lang.code == defaultLangCode + }) { + Defaults[.libraryLanguageCodes] = [defaultLangCode] + } else { + Defaults[.libraryLanguageCodes] = [fallbackToEnglish] + } } private func fetchData() async throws -> Data? { diff --git a/Views/Settings/Settings.swift b/Views/Settings/Settings.swift index 3d7847e8..036a2dd8 100644 --- a/Views/Settings/Settings.swift +++ b/Views/Settings/Settings.swift @@ -247,8 +247,6 @@ private struct SelectedLanaguageLabel: View { } else if languageCodes.count > 1 { Text("\(languageCodes.count)").foregroundColor(.secondary) } - }.task { - LibraryViewModel.cleanUpDefaultLanguages() } } } From 55291b9bf4aab1fa1deb3f6b591d7e0b4bc4e24e Mon Sep 17 00:00:00 2001 From: Balazs Perlaki-Horvath Date: Sat, 24 Feb 2024 16:01:55 +0100 Subject: [PATCH 2/2] Add more comments --- Tests/LibraryRefreshViewModelTest.swift | 1 + Tests/OPDSParserTests.swift | 1 + 2 files changed, 2 insertions(+) diff --git a/Tests/LibraryRefreshViewModelTest.swift b/Tests/LibraryRefreshViewModelTest.swift index 7e2d6242..79d4efad 100644 --- a/Tests/LibraryRefreshViewModelTest.swift +++ b/Tests/LibraryRefreshViewModelTest.swift @@ -193,6 +193,7 @@ final class LibraryRefreshViewModelTest: XCTestCase { XCTAssertEqual(zimFile.hasVideos, false) XCTAssertEqual(zimFile.includedInSearch, true) XCTAssertEqual(zimFile.isMissing, false) + // !important make sure the language code is put into the DB as a 2 letter string XCTAssertEqual(zimFile.languageCode, "en") XCTAssertEqual(zimFile.mediaCount, 566835) XCTAssertEqual(zimFile.name, "Best of Wikipedia") diff --git a/Tests/OPDSParserTests.swift b/Tests/OPDSParserTests.swift index 5e9ad471..0b4ab64a 100644 --- a/Tests/OPDSParserTests.swift +++ b/Tests/OPDSParserTests.swift @@ -70,6 +70,7 @@ final class OPDSParserTests: XCTestCase { XCTAssertEqual(metadata.groupIdentifier, "wikipedia_en_top") XCTAssertEqual(metadata.title, "Best of Wikipedia") XCTAssertEqual(metadata.fileDescription, "A selection of the best 50,000 Wikipedia articles") + // !important make sure the language code is put into the DB as a 2 letter string XCTAssertEqual(metadata.languageCodes, "en") XCTAssertEqual(metadata.category, "wikipedia") XCTAssertEqual(metadata.creationDate, try! Date("2023-01-07T00:00:00Z", strategy: .iso8601))