diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1f32d01ad..ef87730a3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: CI +name: Build on: push: branches: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f40037f30..d04a65eb7 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,4 +1,4 @@ -name: CI +name: Lint on: push: branches: diff --git a/src/hooks/persisted/useNovel.ts b/src/hooks/persisted/useNovel.ts index d4f8a12cb..88cfe1da1 100644 --- a/src/hooks/persisted/useNovel.ts +++ b/src/hooks/persisted/useNovel.ts @@ -150,7 +150,7 @@ export const useNovel = (url: string, pluginId: string) => { novelSettings?.filter, ).then(chapters => setChapters(chapters)); } else { - throw new Error('Unable to get novel'); + throw new Error(getString('updatesScreen.unableToGetNovel')); } }); }; diff --git a/src/plugins/pluginManager.ts b/src/plugins/pluginManager.ts index e94aa6ab0..7fcda4064 100644 --- a/src/plugins/pluginManager.ts +++ b/src/plugins/pluginManager.ts @@ -12,6 +12,7 @@ import { isUrlAbsolute } from './helpers/isAbsoluteUrl'; import { fetchApi, fetchFile, fetchText } from './helpers/fetch'; import { defaultCover } from './helpers/constants'; import { encode, decode } from 'urlencode'; +import { getString } from '@strings/translations'; const packages: Record = { 'cheerio': { load }, @@ -122,7 +123,9 @@ const fetchPlugins = async () => { .then(res => res.json()) .catch(() => { throw new Error( - `Plugins host error: ${githubUsername}/${githubRepository}`, + `${getString( + 'browseScreen.pluginsHostError', + )}: ${githubUsername}/${githubRepository}`, ); }); return availablePlugins; diff --git a/src/services/backup/drive/index.ts b/src/services/backup/drive/index.ts index 88d71a6a9..b28e6bd2a 100644 --- a/src/services/backup/drive/index.ts +++ b/src/services/backup/drive/index.ts @@ -20,11 +20,11 @@ const driveBackupAction = async (taskData?: TaskData) => { try { MMKVStorage.set(BACKGROUND_ACTION, BackgoundAction.BACKUP); if (!taskData) { - throw new Error('No data provided'); + throw new Error(getString('backupScreen.noDataProvided')); } const { delay, backupFolder } = taskData; await BackgroundService.updateNotification({ - taskDesc: 'Preparing Data', + taskDesc: getString('backupScreen.preparingData'), progressBar: { indeterminate: true, value: 0, @@ -34,7 +34,7 @@ const driveBackupAction = async (taskData?: TaskData) => { .then(() => prepareBackupData(CACHE_DIR_PATH)) .then(() => BackgroundService.updateNotification({ - taskDesc: 'Uploading Data', + taskDesc: getString('backupScreen.uploadingData'), progressBar: { indeterminate: true, value: 1, @@ -57,7 +57,7 @@ const driveBackupAction = async (taskData?: TaskData) => { }) .then(() => BackgroundService.updateNotification({ - taskDesc: 'Uploading Downloaded files', + taskDesc: getString('backupScreen.uploadingDownloadedFiles'), progressBar: { indeterminate: true, value: 2, @@ -127,7 +127,7 @@ const driveRestoreAction = async (taskData?: TaskData) => { try { MMKVStorage.set(BACKGROUND_ACTION, BackgoundAction.RESTORE); if (!taskData) { - throw new Error('No data provided'); + throw new Error(getString('backupScreen.noDataProvided')); } const { delay, backupFolder } = taskData; await sleep(delay); @@ -143,10 +143,10 @@ const driveRestoreAction = async (taskData?: TaskData) => { backupFolder.id, ); if (!zipDataFile || !zipDownloadFile) { - throw new Error('Invalid backup folder'); + throw new Error(getString('backupScreen.invalidBackupFolder')); } await BackgroundService.updateNotification({ - taskDesc: 'Downloading Data', + taskDesc: getString('backupScreen.downloadingData'), progressBar: { indeterminate: true, value: 0, @@ -157,7 +157,7 @@ const driveRestoreAction = async (taskData?: TaskData) => { .then(() => sleep(delay)) .then(() => BackgroundService.updateNotification({ - taskDesc: 'Restoring Data', + taskDesc: getString('backupScreen.restoringData'), progressBar: { indeterminate: true, value: 1, @@ -169,7 +169,7 @@ const driveRestoreAction = async (taskData?: TaskData) => { .then(() => sleep(delay)) .then(() => BackgroundService.updateNotification({ - taskDesc: 'Downloading Downloaded files', + taskDesc: getString('backupScreen.downloadingDownloadedFiles'), progressBar: { indeterminate: true, value: 2, @@ -209,8 +209,8 @@ const driveRestoreAction = async (taskData?: TaskData) => { export const driveRestore = async (backupFolder: DriveFile) => { return BackgroundService.start(driveRestoreAction, { taskName: 'Drive Restore', - taskTitle: 'Drive Restore', - taskDesc: 'Preparing', + taskTitle: getString('backupScreen.drive.restore'), + taskDesc: getString('common.preparing'), taskIcon: { name: 'notification_icon', type: 'drawable' }, color: '#00adb5', parameters: { delay: 500, backupFolder }, diff --git a/src/services/backup/remote/index.ts b/src/services/backup/remote/index.ts index 271703f11..e3517dc7b 100644 --- a/src/services/backup/remote/index.ts +++ b/src/services/backup/remote/index.ts @@ -19,11 +19,11 @@ const remoteBackupAction = async (taskData?: TaskData) => { try { MMKVStorage.set(BACKGROUND_ACTION, BackgoundAction.BACKUP); if (!taskData) { - throw new Error('No data provided'); + throw new Error(getString('backupScreen.noDataProvided')); } const { delay, backupFolder, host } = taskData; await BackgroundService.updateNotification({ - taskDesc: 'Preparing Data', + taskDesc: getString('backupScreen.preparingData'), progressBar: { indeterminate: true, value: 0, @@ -33,7 +33,7 @@ const remoteBackupAction = async (taskData?: TaskData) => { .then(() => prepareBackupData(CACHE_DIR_PATH)) .then(() => BackgroundService.updateNotification({ - taskDesc: 'Uploading Data', + taskDesc: getString('backupScreen.uploadingData'), progressBar: { indeterminate: true, value: 1, @@ -47,7 +47,7 @@ const remoteBackupAction = async (taskData?: TaskData) => { ) .then(() => BackgroundService.updateNotification({ - taskDesc: 'Uploading Downloaded files', + taskDesc: getString('backupScreen.uploadingDownloadedFiles'), progressBar: { indeterminate: true, value: 2, @@ -112,11 +112,11 @@ const remoteRestoreAction = async (taskData?: TaskData) => { try { MMKVStorage.set(BACKGROUND_ACTION, BackgoundAction.RESTORE); if (!taskData) { - throw new Error('No data provided'); + throw new Error(getString('backupScreen.noDataProvided')); } const { delay, backupFolder, host } = taskData; await BackgroundService.updateNotification({ - taskDesc: 'Downloading Data', + taskDesc: getString('backupScreen.downloadingData'), progressBar: { indeterminate: true, value: 0, @@ -128,7 +128,7 @@ const remoteRestoreAction = async (taskData?: TaskData) => { ) .then(() => BackgroundService.updateNotification({ - taskDesc: 'Restoring Data', + taskDesc: getString('backupScreen.restoringData'), progressBar: { indeterminate: true, value: 1, @@ -140,7 +140,7 @@ const remoteRestoreAction = async (taskData?: TaskData) => { .then(() => restoreData(CACHE_DIR_PATH)) .then(() => BackgroundService.updateNotification({ - taskDesc: 'Downloading Downloaded files', + taskDesc: getString('backupScreen.downloadingDownloadedFiles'), progressBar: { indeterminate: true, value: 2, @@ -183,8 +183,8 @@ const remoteRestoreAction = async (taskData?: TaskData) => { export const remoteRestore = async (host: string, backupFolder: string) => { return BackgroundService.start(remoteRestoreAction, { taskName: 'Self Host Restore', - taskTitle: 'Self Host Restore', - taskDesc: 'Preparing', + taskTitle: getString('backupScreen.remote.restore'), + taskDesc: getString('common.preparing'), taskIcon: { name: 'notification_icon', type: 'drawable' }, color: '#00adb5', parameters: { delay: 200, backupFolder, host }, diff --git a/src/services/epub/import.ts b/src/services/epub/import.ts index c71dda80c..fa77bc5bb 100644 --- a/src/services/epub/import.ts +++ b/src/services/epub/import.ts @@ -58,7 +58,9 @@ const insertLocalNovel = ( }); resolve(resultSet.insertId); } else { - reject(new Error('novel insert failed')); + reject( + new Error(getString('advancedSettingsScreen.novelInsertFailed')), + ); } }, (txObj, error) => { @@ -112,7 +114,11 @@ const insertLocalChapter = ( ); resolve(staticPaths); } else { - reject(new Error('chapter insert failed')); + reject( + new Error( + getString('advancedSettingsScreen.chapterInsertFailed'), + ), + ); } }, (txObj, error) => { @@ -211,7 +217,7 @@ const parseNovelAndChapters = async ( const importEpubAction = async (taskData?: TaskData) => { try { if (!taskData) { - throw new Error('No data provided'); + throw new Error(getString('backupScreen.noDataProvided')); } const epubFilePath = RNFS.ExternalCachesDirectoryPath + '/novel.epub'; await RNFS.copyFile(taskData.sourceUri, epubFilePath); @@ -333,8 +339,8 @@ export const importEpub = async () => { } await BackgroundService.start(importEpubAction, { taskName: 'Import Epub', - taskTitle: 'Parse Epub', - taskDesc: 'Parsing', + taskTitle: getString('advancedSettingsScreen.parseEpub'), + taskDesc: getString('common.parsing'), taskIcon: { name: 'notification_icon', type: 'drawable' }, color: '#00adb5', parameters: { delay: 500, sourceUri: epubFile.uri }, diff --git a/src/services/updates/LibraryUpdateQueries.ts b/src/services/updates/LibraryUpdateQueries.ts index eda10d874..37731d46f 100644 --- a/src/services/updates/LibraryUpdateQueries.ts +++ b/src/services/updates/LibraryUpdateQueries.ts @@ -67,7 +67,7 @@ const updateNovel = async ( novel.chapters?.forEach(chapter => { const { name, url, releaseTime } = chapter; tx.executeSql( - "INSERT OR REPLACE INTO Chapter (url, name, releaseTime, novelId, updatedTime) values (?, ?, ?, ?, datetime('now','localtime'))", + "INSERT INTO Chapter (url, name, releaseTime, novelId, updatedTime) values (?, ?, ?, ?, datetime('now','localtime')) ON CONFLICT(url) DO UPDATE SET name=excluded.name, releaseTime=excluded.releaseTime, novelId=excluded.novelId, updatedTime=excluded.updatedTime", [url, name, releaseTime || '', novelId], (txObj, { insertId }) => { if (insertId && downloadNewChapters) { diff --git a/strings/languages/en/strings.json b/strings/languages/en/strings.json index a9da5abee..4ff3e5a5d 100644 --- a/strings/languages/en/strings.json +++ b/strings/languages/en/strings.json @@ -10,6 +10,7 @@ "advancedSettings": "Advanced", "advancedSettingsScreen": { "cachedNovelsDeletedToast": "Cached novels deleted", + "chapterInsertFailed": "chapter insert failed", "clearCachedNovels": "Clear cached novels", "clearCachedNovelsDesc": "Delete cached novels which not in your library", "clearDatabaseWarning": "Are you sure? Read and Downloaded chapters and progress of non-library novels will be lost.", @@ -24,6 +25,8 @@ "importError": "Import Error", "importNovel": "Import Novel", "importStaticFiles": "Import Static Files", + "novelInsertFailed": "novel insert failed", + "parseEpub": "Parse Epub", "useFAB": "Use FAB instead of button", "userAgent": "User Agent" }, @@ -56,6 +59,8 @@ "createBackup": "Create backup", "createBackupDesc": "Can be used to restore current library", "createBackupWarning": "Create backup may not work on devices with Android 9 or lower.", + "downloadingData": "Downloading Data", + "downloadingDownloadedFiles": "Downloading Downloaded files", "drive": { "backup": "Drive Backup", "backupInterruped": "Drive Backup Interruped", @@ -65,6 +70,7 @@ }, "googeDrive": "Googe Drive", "googeDriveDesc": "Backup to your Google Drive", + "invalidBackupFolder": "Invalid backup folder", "legacy": { "backupCreated": "Backup created %{fileName}", "libraryRestored": "Library Restored", @@ -76,6 +82,8 @@ }, "legacyBackup": "Legacy Backup", "noBackupFound": "No backup found", + "noDataProvided": "No data provided", + "preparingData": "Preparing Data", "remote": { "backup": "Self Host Backup", "backupInterruped": "Self Host Backup Interruped", @@ -91,8 +99,11 @@ "restoreErrorDesc": "Using this to restore the remaining. Save your time.", "restoreLargeBackupsWarning": "Restoring large backups may freeze the app until restoring is finished", "restorinBackup": "Restoring backup", + "restoringData": "Restoring Data", "selfHost": "Self Host", - "selfHostDesc": "Backup to your server" + "selfHostDesc": "Backup to your server", + "uploadingData": "Uploading Data", + "uploadingDownloadedFiles": "Uploading Downloaded files" }, "browse": "Browse", "browseScreen": { @@ -100,10 +111,10 @@ "available": "Available", "discover": "Discover", "globalSearch": "Global search", + "installFailed": "Installation failed: %{name}", "installed": "Installed", "installedPlugin": "Installed %{name}", "installedPlugins": "Installed plugins", - "installFailed": "Installation failed: %{name}", "lastUsed": "Last used", "latest": "Latest", "listEmpty": "Enable languages from settings", @@ -119,13 +130,14 @@ }, "noSource": "Your library does not have any novels from this source", "pinned": "Pinned", + "pluginsHostError": "Plugins host error", "removeFromLibrary": "Removed from Library", "searchbar": "Search sources", "selectNovel": "Select Novel", "tryAgain": "Try again in a moment", "uninstalledPlugin": "Uninstalled %{name}", - "updatedTo": "Updated to %{version}", - "updateFailed": "Update failed" + "updateFailed": "Update failed", + "updatedTo": "Updated to %{version}" }, "browseSettings": "Browse Settings", "browseSettingsScreen": { @@ -176,6 +188,7 @@ "name": "Name", "newUpdateAvailable": "New update available", "ok": "Ok", + "parsing": "Parsing", "pause": "Pause", "preparing": "Preparing", "remove": "Remove", @@ -474,6 +487,7 @@ "newChapters": "new Chapters", "novelsUpdated": "%{num} novels updated", "searchbar": "Search updates", + "unableToGetNovel": "Unable to get novel", "updatesLower": "updates", "updatingLibrary": "Updating library" } diff --git a/strings/languages/zh_CN/strings.json b/strings/languages/zh_CN/strings.json index e22e723ac..08a8fa918 100644 --- a/strings/languages/zh_CN/strings.json +++ b/strings/languages/zh_CN/strings.json @@ -2,7 +2,7 @@ "aboutScreen": { "discord": "Discord", "github": "Github", - "helpTranslate": "帮助翻译", + "helpTranslate": "协助翻译", "sources": "源", "version": "版本", "whatsNew": "新增内容" @@ -10,6 +10,7 @@ "advancedSettings": "高级", "advancedSettingsScreen": { "cachedNovelsDeletedToast": "缓存的小说已删除", + "chapterInsertFailed": "章节插入失败", "clearCachedNovels": "清除缓存的小说", "clearCachedNovelsDesc": "删除不在您的书库中的缓存小说", "clearDatabaseWarning": "您确定吗?非书库小说的阅读,已下载章节和进度将会丢失。", @@ -24,6 +25,8 @@ "importError": "导入出错", "importNovel": "导入小说", "importStaticFiles": "导入静态文件", + "novelInsertFailed": "小说插入失败", + "parseEpub": "解析 EPUB", "useFAB": "使用浮动操作按钮", "userAgent": "用户代理" }, @@ -38,7 +41,7 @@ "navbar": "导航栏", "novelInfo": "小说信息", "pureBlackDarkMode": "纯黑深色模式", - "showHistoryInTheNav": "在导航中显示历史记录", + "showHistoryInTheNav": "在导航中显示历史", "showUpdatesInTheNav": "在导航中显示更新", "theme": { "default": "默认", @@ -56,6 +59,8 @@ "createBackup": "创建备份", "createBackupDesc": "可用于恢复当前书库", "createBackupWarning": "创建备份可能无法在 Android 9 或更低版本的设备上运行。", + "downloadingData": "下载数据", + "downloadingDownloadedFiles": "下载已下载文件", "drive": { "backup": "云端硬盘备份", "backupInterruped": "云端硬盘备份中断", @@ -65,6 +70,7 @@ }, "googeDrive": "Google 云端硬盘", "googeDriveDesc": "备份到您的 Google 云端硬盘", + "invalidBackupFolder": "备份文件夹有误", "legacy": { "backupCreated": "备份已创建 %{fileName}", "libraryRestored": "书库已恢复", @@ -76,6 +82,8 @@ }, "legacyBackup": "旧版备份", "noBackupFound": "没有找到备份", + "noDataProvided": "未提供数据", + "preparingData": "准备数据", "remote": { "backup": "自托管备份", "backupInterruped": "自托管备份中断", @@ -91,8 +99,11 @@ "restoreErrorDesc": "用这个来恢复剩余的。节省您的时间。", "restoreLargeBackupsWarning": "恢复大量备份可能会冻结应用程序,直到恢复完成", "restorinBackup": "恢复备份", + "restoringData": "恢复数据", "selfHost": "自托管", - "selfHostDesc": "备份到您的服务器" + "selfHostDesc": "备份到您的服务器", + "uploadingData": "上传数据", + "uploadingDownloadedFiles": "上传已下载文件" }, "browse": "浏览", "browseScreen": { @@ -100,6 +111,7 @@ "available": "可用", "discover": "发现", "globalSearch": "全局搜索", + "installFailed": "安装失败:%{name}", "installed": "已安装", "installedPlugin": "已安装 %{name}", "installedPlugins": "已安装插件", @@ -118,10 +130,13 @@ }, "noSource": "您的图书馆没有该源的任何小说", "pinned": "已固定", + "pluginsHostError": "获取插件列表失败", "removeFromLibrary": "已从书库中删除", "searchbar": "搜索资源", "selectNovel": "选择小说", + "tryAgain": "请稍后再试", "uninstalledPlugin": "已卸载 %{name}", + "updateFailed": "更新失败", "updatedTo": "已更新至 %{version}" }, "browseSettings": "浏览设置", @@ -173,6 +188,7 @@ "name": "名称", "newUpdateAvailable": "新版本可用", "ok": "确定", + "parsing": "解析", "pause": "暂停", "preparing": "准备中", "remove": "移除", @@ -273,8 +289,8 @@ "downloadBadges": "下载徽章", "list": "列表", "noTitle": "仅封面网格", - "numberOfItems": "条目数量", - "showNoOfItems": "显示条目数量", + "numberOfItems": "小说数", + "showNoOfItems": "显示小说数", "unread": "未读", "unreadBadges": "未读徽章" }, @@ -294,13 +310,13 @@ "unread": "未读" } }, - "empty": "您的库是空的。从浏览添加丛书到您的库里。", + "empty": "您的书库是空的。请从浏览将小说添加到您的书库中。", "searchbar": "搜索书库" }, "more": "更多", "moreScreen": { "downloadOnly": "仅已下载", - "downloadOnlyDesc": "过滤您书库中的所有小说", + "downloadOnlyDesc": "筛选您书库中的全部小说", "downloadQueue": "下载队列", "incognitoMode": "无痕模式", "incognitoModeDesc": "暂停阅读历史记录" @@ -471,6 +487,7 @@ "newChapters": "新章节", "novelsUpdated": "已更新 %{num} 部小说", "searchbar": "搜索更新", + "unableToGetNovel": "无法获取小说", "updatesLower": "更新", "updatingLibrary": "更新书库" } diff --git a/strings/types/index.ts b/strings/types/index.ts index 637b5ddf7..a450bb074 100644 --- a/strings/types/index.ts +++ b/strings/types/index.ts @@ -11,6 +11,7 @@ export interface StringMap { 'aboutScreen.whatsNew': 'string'; 'advancedSettings': 'string'; 'advancedSettingsScreen.cachedNovelsDeletedToast': 'string'; + 'advancedSettingsScreen.chapterInsertFailed': 'string'; 'advancedSettingsScreen.clearCachedNovels': 'string'; 'advancedSettingsScreen.clearCachedNovelsDesc': 'string'; 'advancedSettingsScreen.clearDatabaseWarning': 'string'; @@ -25,6 +26,8 @@ export interface StringMap { 'advancedSettingsScreen.importError': 'string'; 'advancedSettingsScreen.importNovel': 'string'; 'advancedSettingsScreen.importStaticFiles': 'string'; + 'advancedSettingsScreen.novelInsertFailed': 'string'; + 'advancedSettingsScreen.parseEpub': 'string'; 'advancedSettingsScreen.useFAB': 'string'; 'advancedSettingsScreen.userAgent': 'string'; 'appearance': 'string'; @@ -51,6 +54,8 @@ export interface StringMap { 'backupScreen.createBackup': 'string'; 'backupScreen.createBackupDesc': 'string'; 'backupScreen.createBackupWarning': 'string'; + 'backupScreen.downloadingData': 'string'; + 'backupScreen.downloadingDownloadedFiles': 'string'; 'backupScreen.drive.backup': 'string'; 'backupScreen.drive.backupInterruped': 'string'; 'backupScreen.drive.googleDriveBackup': 'string'; @@ -58,6 +63,7 @@ export interface StringMap { 'backupScreen.drive.restoreInterruped': 'string'; 'backupScreen.googeDrive': 'string'; 'backupScreen.googeDriveDesc': 'string'; + 'backupScreen.invalidBackupFolder': 'string'; 'backupScreen.legacy.backupCreated': 'string'; 'backupScreen.legacy.libraryRestored': 'string'; 'backupScreen.legacy.noAvailableBackup': 'string'; @@ -67,6 +73,8 @@ export interface StringMap { 'backupScreen.legacy.pluginNotExist': 'string'; 'backupScreen.legacyBackup': 'string'; 'backupScreen.noBackupFound': 'string'; + 'backupScreen.noDataProvided': 'string'; + 'backupScreen.preparingData': 'string'; 'backupScreen.remote.backup': 'string'; 'backupScreen.remote.backupInterruped': 'string'; 'backupScreen.remote.host': 'string'; @@ -80,17 +88,20 @@ export interface StringMap { 'backupScreen.restoreErrorDesc': 'string'; 'backupScreen.restoreLargeBackupsWarning': 'string'; 'backupScreen.restorinBackup': 'string'; + 'backupScreen.restoringData': 'string'; 'backupScreen.selfHost': 'string'; 'backupScreen.selfHostDesc': 'string'; + 'backupScreen.uploadingData': 'string'; + 'backupScreen.uploadingDownloadedFiles': 'string'; 'browse': 'string'; 'browseScreen.addedToLibrary': 'string'; 'browseScreen.available': 'string'; 'browseScreen.discover': 'string'; 'browseScreen.globalSearch': 'string'; + 'browseScreen.installFailed': 'string'; 'browseScreen.installed': 'string'; 'browseScreen.installedPlugin': 'string'; 'browseScreen.installedPlugins': 'string'; - 'browseScreen.installFailed': 'string'; 'browseScreen.lastUsed': 'string'; 'browseScreen.latest': 'string'; 'browseScreen.listEmpty': 'string'; @@ -104,13 +115,14 @@ export interface StringMap { 'browseScreen.migration.selectSourceDesc': 'string'; 'browseScreen.noSource': 'string'; 'browseScreen.pinned': 'string'; + 'browseScreen.pluginsHostError': 'string'; 'browseScreen.removeFromLibrary': 'string'; 'browseScreen.searchbar': 'string'; 'browseScreen.selectNovel': 'string'; 'browseScreen.tryAgain': 'string'; 'browseScreen.uninstalledPlugin': 'string'; - 'browseScreen.updatedTo': 'string'; 'browseScreen.updateFailed': 'string'; + 'browseScreen.updatedTo': 'string'; 'browseSettings': 'string'; 'browseSettingsScreen.languages': 'string'; 'browseSettingsScreen.onlyShowPinnedSources': 'string'; @@ -153,6 +165,7 @@ export interface StringMap { 'common.name': 'string'; 'common.newUpdateAvailable': 'string'; 'common.ok': 'string'; + 'common.parsing': 'string'; 'common.pause': 'string'; 'common.preparing': 'string'; 'common.remove': 'string'; @@ -389,6 +402,7 @@ export interface StringMap { 'updatesScreen.newChapters': 'string'; 'updatesScreen.novelsUpdated': 'string'; 'updatesScreen.searchbar': 'string'; + 'updatesScreen.unableToGetNovel': 'string'; 'updatesScreen.updatesLower': 'string'; 'updatesScreen.updatingLibrary': 'string'; }