diff --git a/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt b/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt index 0acef84a9a..791e131807 100644 --- a/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt +++ b/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt @@ -1,12 +1,12 @@ package eu.kanade.domain.base import android.content.Context -import androidx.annotation.StringRes -import eu.kanade.tachiyomi.R +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.util.system.isPreviewBuildType import eu.kanade.tachiyomi.util.system.isReleaseBuildType import tachiyomi.core.preference.Preference import tachiyomi.core.preference.PreferenceStore +import tachiyomi.i18n.MR class BasePreferences( val context: Context, @@ -24,10 +24,10 @@ class BasePreferences( fun acraEnabled() = preferenceStore.getBoolean("acra.enable", isPreviewBuildType || isReleaseBuildType) - enum class ExtensionInstaller(@StringRes val titleResId: Int) { - LEGACY(R.string.ext_installer_legacy), - PACKAGEINSTALLER(R.string.ext_installer_packageinstaller), - SHIZUKU(R.string.ext_installer_shizuku), - PRIVATE(R.string.ext_installer_private), + enum class ExtensionInstaller(val titleRes: StringResource) { + LEGACY(MR.strings.ext_installer_legacy), + PACKAGEINSTALLER(MR.strings.ext_installer_packageinstaller), + SHIZUKU(MR.strings.ext_installer_shizuku), + PRIVATE(MR.strings.ext_installer_private), } } diff --git a/app/src/main/java/eu/kanade/domain/ui/model/AppTheme.kt b/app/src/main/java/eu/kanade/domain/ui/model/AppTheme.kt index 250188535f..2fdeb0e3c3 100644 --- a/app/src/main/java/eu/kanade/domain/ui/model/AppTheme.kt +++ b/app/src/main/java/eu/kanade/domain/ui/model/AppTheme.kt @@ -1,19 +1,20 @@ package eu.kanade.domain.ui.model -import eu.kanade.tachiyomi.R +import dev.icerock.moko.resources.StringResource +import tachiyomi.i18n.MR -enum class AppTheme(val titleResId: Int?) { - DEFAULT(R.string.label_default), - MONET(R.string.theme_monet), - GREEN_APPLE(R.string.theme_greenapple), - LAVENDER(R.string.theme_lavender), - MIDNIGHT_DUSK(R.string.theme_midnightdusk), - STRAWBERRY_DAIQUIRI(R.string.theme_strawberrydaiquiri), - TAKO(R.string.theme_tako), - TEALTURQUOISE(R.string.theme_tealturquoise), - TIDAL_WAVE(R.string.theme_tidalwave), - YINYANG(R.string.theme_yinyang), - YOTSUBA(R.string.theme_yotsuba), +enum class AppTheme(val titleRes: StringResource?) { + DEFAULT(MR.strings.label_default), + MONET(MR.strings.theme_monet), + GREEN_APPLE(MR.strings.theme_greenapple), + LAVENDER(MR.strings.theme_lavender), + MIDNIGHT_DUSK(MR.strings.theme_midnightdusk), + STRAWBERRY_DAIQUIRI(MR.strings.theme_strawberrydaiquiri), + TAKO(MR.strings.theme_tako), + TEALTURQUOISE(MR.strings.theme_tealturquoise), + TIDAL_WAVE(MR.strings.theme_tidalwave), + YINYANG(MR.strings.theme_yinyang), + YOTSUBA(MR.strings.theme_yotsuba), // Deprecated DARK_BLUE(null), diff --git a/app/src/main/java/eu/kanade/domain/ui/model/TabletUiMode.kt b/app/src/main/java/eu/kanade/domain/ui/model/TabletUiMode.kt index 71cee1264c..cf1e957b09 100644 --- a/app/src/main/java/eu/kanade/domain/ui/model/TabletUiMode.kt +++ b/app/src/main/java/eu/kanade/domain/ui/model/TabletUiMode.kt @@ -1,10 +1,11 @@ package eu.kanade.domain.ui.model -import eu.kanade.tachiyomi.R +import dev.icerock.moko.resources.StringResource +import tachiyomi.i18n.MR -enum class TabletUiMode(val titleResId: Int) { - AUTOMATIC(R.string.automatic_background), - ALWAYS(R.string.lock_always), - LANDSCAPE(R.string.landscape), - NEVER(R.string.lock_never), +enum class TabletUiMode(val titleRes: StringResource) { + AUTOMATIC(MR.strings.automatic_background), + ALWAYS(MR.strings.lock_always), + LANDSCAPE(MR.strings.landscape), + NEVER(MR.strings.lock_never), } diff --git a/app/src/main/java/eu/kanade/presentation/browse/BrowseSourceScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/BrowseSourceScreen.kt index abf3d3d218..2b9d2d9633 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/BrowseSourceScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/BrowseSourceScreen.kt @@ -14,7 +14,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.paging.LoadState import androidx.paging.compose.LazyPagingItems import eu.kanade.presentation.browse.components.BrowseSourceComfortableGrid @@ -22,14 +21,16 @@ import eu.kanade.presentation.browse.components.BrowseSourceCompactGrid import eu.kanade.presentation.browse.components.BrowseSourceList import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.util.formattedMessage -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.Source import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.flow.StateFlow +import tachiyomi.core.i18n.localize import tachiyomi.domain.library.model.LibraryDisplayMode import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.source.model.StubSource +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.EmptyScreenAction import tachiyomi.presentation.core.screens.LoadingScreen @@ -62,7 +63,7 @@ fun BrowseSourceContent( if (mangaList.itemCount > 0 && errorState != null && errorState is LoadState.Error) { val result = snackbarHostState.showSnackbar( message = getErrorMessage(errorState), - actionLabel = context.getString(R.string.action_retry), + actionLabel = context.localize(MR.strings.action_retry), duration = SnackbarDuration.Indefinite, ) when (result) { @@ -79,7 +80,7 @@ fun BrowseSourceContent( actions = if (source is LocalSource) { persistentListOf( EmptyScreenAction( - stringResId = R.string.local_source_help_guide, + stringRes = MR.strings.local_source_help_guide, icon = Icons.AutoMirrored.Outlined.HelpOutline, onClick = onLocalSourceHelpClick, ), @@ -87,17 +88,17 @@ fun BrowseSourceContent( } else { persistentListOf( EmptyScreenAction( - stringResId = R.string.action_retry, + stringRes = MR.strings.action_retry, icon = Icons.Outlined.Refresh, onClick = mangaList::refresh, ), EmptyScreenAction( - stringResId = R.string.action_open_in_web_view, + stringRes = MR.strings.action_open_in_web_view, icon = Icons.Outlined.Public, onClick = onWebViewClick, ), EmptyScreenAction( - stringResId = R.string.label_help, + stringRes = MR.strings.label_help, icon = Icons.AutoMirrored.Outlined.HelpOutline, onClick = onHelpClick, ), @@ -160,7 +161,7 @@ internal fun MissingSourceScreen( }, ) { paddingValues -> EmptyScreen( - message = stringResource(R.string.source_not_installed, source.toString()), + message = localize(MR.strings.source_not_installed, source.toString()), modifier = Modifier.padding(paddingValues), ) } diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt index 9679506038..0a34ad0a78 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt @@ -38,7 +38,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -50,15 +49,16 @@ import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.WarningBanner import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget import eu.kanade.presentation.more.settings.widget.TrailingWidgetBuffer -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreenModel import eu.kanade.tachiyomi.util.system.LocaleHelper import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen @Composable @@ -77,7 +77,7 @@ fun ExtensionDetailsScreen( Scaffold( topBar = { scrollBehavior -> AppBar( - title = stringResource(R.string.label_extension_info), + title = localize(MR.strings.label_extension_info), navigateUp = navigateUp, actions = { AppBarActions( @@ -86,14 +86,14 @@ fun ExtensionDetailsScreen( if (state.extension?.isUnofficial == false) { add( AppBar.Action( - title = stringResource(R.string.whats_new), + title = localize(MR.strings.whats_new), icon = Icons.Outlined.History, onClick = onClickWhatsNew, ), ) add( AppBar.Action( - title = stringResource(R.string.action_faq_and_guides), + title = localize(MR.strings.action_faq_and_guides), icon = Icons.AutoMirrored.Outlined.HelpOutline, onClick = onClickReadme, ), @@ -102,15 +102,15 @@ fun ExtensionDetailsScreen( addAll( listOf( AppBar.OverflowAction( - title = stringResource(R.string.action_enable_all), + title = localize(MR.strings.action_enable_all), onClick = onClickEnableAll, ), AppBar.OverflowAction( - title = stringResource(R.string.action_disable_all), + title = localize(MR.strings.action_disable_all), onClick = onClickDisableAll, ), AppBar.OverflowAction( - title = stringResource(R.string.pref_clear_cookies), + title = localize(MR.strings.pref_clear_cookies), onClick = onClickClearCookies, ), ), @@ -125,7 +125,7 @@ fun ExtensionDetailsScreen( ) { paddingValues -> if (state.extension == null) { EmptyScreen( - textResource = R.string.empty_screen, + stringRes = MR.strings.empty_screen, modifier = Modifier.padding(paddingValues), ) return@Scaffold @@ -160,11 +160,11 @@ private fun ExtensionDetails( when { extension.isUnofficial -> item { - WarningBanner(R.string.unofficial_extension_message) + WarningBanner(MR.strings.unofficial_extension_message) } extension.isObsolete -> item { - WarningBanner(R.string.obsolete_extension_message) + WarningBanner(MR.strings.obsolete_extension_message) } } @@ -260,7 +260,7 @@ private fun DetailsHeader( InfoText( modifier = Modifier.weight(1f), primaryText = extension.versionName, - secondaryText = stringResource(R.string.ext_info_version), + secondaryText = localize(MR.strings.ext_info_version), ) InfoDivider() @@ -268,7 +268,7 @@ private fun DetailsHeader( InfoText( modifier = Modifier.weight(if (extension.isNsfw) 1.5f else 1f), primaryText = LocaleHelper.getSourceDisplayName(extension.lang, context), - secondaryText = stringResource(R.string.ext_info_language), + secondaryText = localize(MR.strings.ext_info_language), ) if (extension.isNsfw) { @@ -276,12 +276,12 @@ private fun DetailsHeader( InfoText( modifier = Modifier.weight(1f), - primaryText = stringResource(R.string.ext_nsfw_short), + primaryText = localize(MR.strings.ext_nsfw_short), primaryTextStyle = MaterialTheme.typography.bodyLarge.copy( color = MaterialTheme.colorScheme.error, fontWeight = FontWeight.Medium, ), - secondaryText = stringResource(R.string.ext_info_age_rating), + secondaryText = localize(MR.strings.ext_info_age_rating), onClick = onClickAgeRating, ) } @@ -300,7 +300,7 @@ private fun DetailsHeader( modifier = Modifier.weight(1f), onClick = onClickUninstall, ) { - Text(stringResource(R.string.ext_uninstall)) + Text(localize(MR.strings.ext_uninstall)) } if (onClickAppInfo != null) { @@ -309,7 +309,7 @@ private fun DetailsHeader( onClick = onClickAppInfo, ) { Text( - text = stringResource(R.string.ext_app_info), + text = localize(MR.strings.ext_app_info), color = MaterialTheme.colorScheme.onPrimary, ) } @@ -387,7 +387,7 @@ private fun SourceSwitchPreference( IconButton(onClick = { onClickSourcePreferences(source.source.id) }) { Icon( imageVector = Icons.Outlined.Settings, - contentDescription = stringResource(R.string.label_settings), + contentDescription = localize(MR.strings.label_settings), tint = MaterialTheme.colorScheme.onSurface, ) } @@ -410,11 +410,11 @@ private fun NsfwWarningDialog( ) { AlertDialog( text = { - Text(text = stringResource(R.string.ext_nsfw_warning)) + Text(text = localize(MR.strings.ext_nsfw_warning)) }, confirmButton = { TextButton(onClick = onClickConfirm) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, onDismissRequest = onClickConfirm, diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionFilterScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionFilterScreen.kt index d660a7b924..1178e1e857 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionFilterScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionFilterScreen.kt @@ -7,13 +7,13 @@ import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.extension.ExtensionFilterState import eu.kanade.tachiyomi.util.system.LocaleHelper +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen @Composable @@ -25,7 +25,7 @@ fun ExtensionFilterScreen( Scaffold( topBar = { scrollBehavior -> AppBar( - title = stringResource(R.string.label_extensions), + title = localize(MR.strings.label_extensions), navigateUp = navigateUp, scrollBehavior = scrollBehavior, ) @@ -33,7 +33,7 @@ fun ExtensionFilterScreen( ) { contentPadding -> if (state.isEmpty) { EmptyScreen( - textResource = R.string.empty_screen, + stringRes = MR.strings.empty_screen, modifier = Modifier.padding(contentPadding), ) return@Scaffold diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt index 3072fa5fb0..adde67c29b 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt @@ -1,6 +1,5 @@ package eu.kanade.presentation.browse -import androidx.annotation.StringRes import androidx.compose.animation.core.animateDpAsState import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement @@ -33,22 +32,23 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import dev.icerock.moko.resources.StringResource import eu.kanade.presentation.browse.components.BaseBrowseItem import eu.kanade.presentation.browse.components.ExtensionIcon import eu.kanade.presentation.manga.components.DotSeparatorNoSpaceText -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.ui.browse.extension.ExtensionUiModel import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreenModel import eu.kanade.tachiyomi.util.system.LocaleHelper +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.material.PullRefresh import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.topSmallPaddingValues +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.theme.header @@ -79,12 +79,12 @@ fun ExtensionScreen( state.isLoading -> LoadingScreen(Modifier.padding(contentPadding)) state.isEmpty -> { val msg = if (!searchQuery.isNullOrEmpty()) { - R.string.no_results_found + MR.strings.no_results_found } else { - R.string.empty_screen + MR.strings.empty_screen } EmptyScreen( - textResource = msg, + stringRes = msg, modifier = Modifier.padding(contentPadding), ) } @@ -132,11 +132,11 @@ private fun ExtensionContent( when (header) { is ExtensionUiModel.Header.Resource -> { val action: @Composable RowScope.() -> Unit = - if (header.textRes == R.string.ext_updates_pending) { + if (header.textRes == MR.strings.ext_updates_pending) { { Button(onClick = { onClickUpdateAll() }) { Text( - text = stringResource(R.string.ext_update_all), + text = localize(MR.strings.ext_update_all), style = LocalTextStyle.current.copy( color = MaterialTheme.colorScheme.onPrimary, ), @@ -304,15 +304,15 @@ private fun ExtensionItemContent( } val warning = when { - extension is Extension.Untrusted -> R.string.ext_untrusted - extension is Extension.Installed && extension.isUnofficial -> R.string.ext_unofficial - extension is Extension.Installed && extension.isObsolete -> R.string.ext_obsolete - extension.isNsfw -> R.string.ext_nsfw_short + extension is Extension.Untrusted -> MR.strings.ext_untrusted + extension is Extension.Installed && extension.isUnofficial -> MR.strings.ext_unofficial + extension is Extension.Installed && extension.isObsolete -> MR.strings.ext_obsolete + extension.isNsfw -> MR.strings.ext_nsfw_short else -> null } if (warning != null) { Text( - text = stringResource(warning).uppercase(), + text = localize(warning).uppercase(), color = MaterialTheme.colorScheme.error, maxLines = 1, overflow = TextOverflow.Ellipsis, @@ -323,9 +323,9 @@ private fun ExtensionItemContent( DotSeparatorNoSpaceText() Text( text = when (installStep) { - InstallStep.Pending -> stringResource(R.string.ext_pending) - InstallStep.Downloading -> stringResource(R.string.ext_downloading) - InstallStep.Installing -> stringResource(R.string.ext_installing) + InstallStep.Pending -> localize(MR.strings.ext_pending) + InstallStep.Downloading -> localize(MR.strings.ext_downloading) + InstallStep.Installing -> localize(MR.strings.ext_installing) else -> error("Must not show non-install process text") }, ) @@ -351,19 +351,19 @@ private fun ExtensionItemActions( ) { Text( text = when (installStep) { - InstallStep.Installed -> stringResource(R.string.ext_installed) - InstallStep.Error -> stringResource(R.string.action_retry) + InstallStep.Installed -> localize(MR.strings.ext_installed) + InstallStep.Error -> localize(MR.strings.action_retry) InstallStep.Idle -> { when (extension) { is Extension.Installed -> { if (extension.hasUpdate) { - stringResource(R.string.ext_update) + localize(MR.strings.ext_update) } else { - stringResource(R.string.action_settings) + localize(MR.strings.action_settings) } } - is Extension.Untrusted -> stringResource(R.string.ext_trust) - is Extension.Available -> stringResource(R.string.ext_install) + is Extension.Untrusted -> localize(MR.strings.ext_trust) + is Extension.Available -> localize(MR.strings.ext_install) } } else -> error("Must not show install process text") @@ -374,7 +374,7 @@ private fun ExtensionItemActions( IconButton(onClick = { onClickItemCancel(extension) }) { Icon( imageVector = Icons.Outlined.Close, - contentDescription = stringResource(R.string.action_cancel), + contentDescription = localize(MR.strings.action_cancel), ) } } @@ -383,12 +383,12 @@ private fun ExtensionItemActions( @Composable private fun ExtensionHeader( - @StringRes textRes: Int, + textRes: StringResource, modifier: Modifier = Modifier, action: @Composable RowScope.() -> Unit = {}, ) { ExtensionHeader( - text = stringResource(textRes), + text = localize(textRes), modifier = modifier, action = action, ) @@ -423,19 +423,19 @@ private fun ExtensionTrustDialog( ) { AlertDialog( title = { - Text(text = stringResource(R.string.untrusted_extension)) + Text(text = localize(MR.strings.untrusted_extension)) }, text = { - Text(text = stringResource(R.string.untrusted_extension_message)) + Text(text = localize(MR.strings.untrusted_extension_message)) }, confirmButton = { TextButton(onClick = onClickConfirm) { - Text(text = stringResource(R.string.ext_trust)) + Text(text = localize(MR.strings.ext_trust)) } }, dismissButton = { TextButton(onClick = onClickDismiss) { - Text(text = stringResource(R.string.ext_uninstall)) + Text(text = localize(MR.strings.ext_uninstall)) } }, onDismissRequest = onDismissRequest, diff --git a/app/src/main/java/eu/kanade/presentation/browse/MigrateMangaScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/MigrateMangaScreen.kt index a1ffea4e19..0564eca211 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/MigrateMangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/MigrateMangaScreen.kt @@ -7,9 +7,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.manga.components.BaseMangaListItem -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrateMangaScreenModel import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.screens.EmptyScreen @@ -33,7 +33,7 @@ fun MigrateMangaScreen( ) { contentPadding -> if (state.isEmpty) { EmptyScreen( - textResource = R.string.empty_screen, + stringRes = MR.strings.empty_screen, modifier = Modifier.padding(contentPadding), ) return@Scaffold diff --git a/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt index 42b67ffad6..c208fc7928 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt @@ -20,21 +20,21 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import eu.kanade.domain.source.interactor.SetMigrateSorting import eu.kanade.presentation.browse.components.BaseSourceItem import eu.kanade.presentation.browse.components.SourceIcon -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.migration.sources.MigrateSourceScreenModel import eu.kanade.tachiyomi.util.system.copyToClipboard import tachiyomi.domain.source.model.Source +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.Badge import tachiyomi.presentation.core.components.BadgeGroup import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.Scroller.STICKY_HEADER_KEY_PREFIX import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.topSmallPaddingValues +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.theme.header @@ -53,7 +53,7 @@ fun MigrateSourceScreen( when { state.isLoading -> LoadingScreen(Modifier.padding(contentPadding)) state.isEmpty -> EmptyScreen( - textResource = R.string.information_empty_library, + stringRes = MR.strings.information_empty_library, modifier = Modifier.padding(contentPadding), ) else -> @@ -95,7 +95,7 @@ private fun MigrateSourceList( verticalAlignment = Alignment.CenterVertically, ) { Text( - text = stringResource(R.string.migration_selection_prompt), + text = localize(MR.strings.migration_selection_prompt), modifier = Modifier.weight(1f), style = MaterialTheme.typography.header, ) @@ -104,11 +104,11 @@ private fun MigrateSourceList( when (sortingMode) { SetMigrateSorting.Mode.ALPHABETICAL -> Icon( Icons.Outlined.SortByAlpha, - contentDescription = stringResource(R.string.action_sort_alpha), + contentDescription = localize(MR.strings.action_sort_alpha), ) SetMigrateSorting.Mode.TOTAL -> Icon( Icons.Outlined.Numbers, - contentDescription = stringResource(R.string.action_sort_count), + contentDescription = localize(MR.strings.action_sort_count), ) } } @@ -116,11 +116,11 @@ private fun MigrateSourceList( when (sortingDirection) { SetMigrateSorting.Direction.ASCENDING -> Icon( Icons.Outlined.ArrowUpward, - contentDescription = stringResource(R.string.action_asc), + contentDescription = localize(MR.strings.action_asc), ) SetMigrateSorting.Direction.DESCENDING -> Icon( Icons.Outlined.ArrowDownward, - contentDescription = stringResource(R.string.action_desc), + contentDescription = localize(MR.strings.action_desc), ) } } @@ -189,7 +189,7 @@ private fun MigrateSourceItem( if (source.isStub) { Text( modifier = Modifier.secondaryItemAlpha(), - text = stringResource(R.string.not_installed), + text = localize(MR.strings.not_installed), maxLines = 1, overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.bodySmall, diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt index c5cf9e310c..362a902cfb 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt @@ -7,16 +7,16 @@ import androidx.compose.material3.Checkbox import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import eu.kanade.presentation.browse.components.BaseSourceItem import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.source.SourcesFilterScreenModel import eu.kanade.tachiyomi.util.system.LocaleHelper import tachiyomi.domain.source.model.Source +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen @Composable @@ -29,7 +29,7 @@ fun SourcesFilterScreen( Scaffold( topBar = { scrollBehavior -> AppBar( - title = stringResource(R.string.label_sources), + title = localize(MR.strings.label_sources), navigateUp = navigateUp, scrollBehavior = scrollBehavior, ) @@ -37,7 +37,7 @@ fun SourcesFilterScreen( ) { contentPadding -> if (state.isEmpty) { EmptyScreen( - textResource = R.string.source_filter_empty_screen, + stringRes = MR.strings.source_filter_empty_screen, modifier = Modifier.padding(contentPadding), ) return@Scaffold diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt index 73237dacfc..a84f6b6ebc 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt @@ -19,19 +19,19 @@ import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import eu.kanade.presentation.browse.components.BaseSourceItem -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.source.SourcesScreenModel import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing import eu.kanade.tachiyomi.util.system.LocaleHelper import tachiyomi.domain.source.model.Pin import tachiyomi.domain.source.model.Source +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.material.SecondaryItemAlpha import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.topSmallPaddingValues +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.theme.header @@ -49,7 +49,7 @@ fun SourcesScreen( when { state.isLoading -> LoadingScreen(Modifier.padding(contentPadding)) state.isEmpty -> EmptyScreen( - textResource = R.string.source_empty_screen, + stringRes = MR.strings.source_empty_screen, modifier = Modifier.padding(contentPadding), ) else -> { @@ -121,7 +121,7 @@ private fun SourceItem( if (source.supportsLatest) { TextButton(onClick = { onClickItem(source, Listing.Latest) }) { Text( - text = stringResource(R.string.latest), + text = localize(MR.strings.latest), style = LocalTextStyle.current.copy( color = MaterialTheme.colorScheme.primary, ), @@ -149,12 +149,12 @@ private fun SourcePinButton( alpha = SecondaryItemAlpha, ) } - val description = if (isPinned) R.string.action_unpin else R.string.action_pin + val description = if (isPinned) MR.strings.action_unpin else MR.strings.action_pin IconButton(onClick = onClick) { Icon( imageVector = icon, tint = tint, - contentDescription = stringResource(description), + contentDescription = localize(description), ) } } @@ -172,9 +172,9 @@ fun SourceOptionsDialog( }, text = { Column { - val textId = if (Pin.Pinned in source.pin) R.string.action_unpin else R.string.action_pin + val textId = if (Pin.Pinned in source.pin) MR.strings.action_unpin else MR.strings.action_pin Text( - text = stringResource(textId), + text = localize(textId), modifier = Modifier .clickable(onClick = onClickPin) .fillMaxWidth() @@ -182,7 +182,7 @@ fun SourceOptionsDialog( ) if (!source.isLocal()) { Text( - text = stringResource(R.string.action_disable), + text = localize(MR.strings.action_disable), modifier = Modifier .clickable(onClick = onClickDisable) .fillMaxWidth() diff --git a/app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceDialogs.kt b/app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceDialogs.kt index aa349e0056..97e02abf17 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceDialogs.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceDialogs.kt @@ -4,11 +4,9 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.setValue -import androidx.compose.ui.res.stringResource -import eu.kanade.tachiyomi.R import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize @Composable fun RemoveMangaDialog( @@ -20,7 +18,7 @@ fun RemoveMangaDialog( onDismissRequest = onDismissRequest, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, confirmButton = { @@ -30,14 +28,14 @@ fun RemoveMangaDialog( onConfirm() }, ) { - Text(text = stringResource(R.string.action_remove)) + Text(text = localize(MR.strings.action_remove)) } }, title = { - Text(text = stringResource(R.string.are_you_sure)) + Text(text = localize(MR.strings.are_you_sure)) }, text = { - Text(text = stringResource(R.string.remove_manga, mangaToRemove.title)) + Text(text = localize(MR.strings.remove_manga, mangaToRemove.title)) }, ) } diff --git a/app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceToolbar.kt b/app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceToolbar.kt index 0e57fcdc71..62f5fb24e6 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceToolbar.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceToolbar.kt @@ -10,18 +10,18 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.res.stringResource import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.AppBarTitle import eu.kanade.presentation.components.DropdownMenu import eu.kanade.presentation.components.RadioMenuItem import eu.kanade.presentation.components.SearchToolbar -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.Source import kotlinx.collections.immutable.persistentListOf import tachiyomi.domain.library.model.LibraryDisplayMode +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import tachiyomi.source.local.LocalSource @Composable @@ -58,7 +58,7 @@ fun BrowseSourceToolbar( .apply { add( AppBar.Action( - title = stringResource(R.string.action_display_mode), + title = localize(MR.strings.action_display_mode), icon = if (displayMode == LibraryDisplayMode.List) { Icons.AutoMirrored.Filled.ViewList } else { @@ -70,14 +70,14 @@ fun BrowseSourceToolbar( if (isLocalSource) { add( AppBar.OverflowAction( - title = stringResource(R.string.label_help), + title = localize(MR.strings.label_help), onClick = onHelpClick, ), ) } else { add( AppBar.OverflowAction( - title = stringResource(R.string.action_open_in_web_view), + title = localize(MR.strings.action_open_in_web_view), onClick = onWebViewClick, ), ) @@ -85,7 +85,7 @@ fun BrowseSourceToolbar( if (isConfigurableSource) { add( AppBar.OverflowAction( - title = stringResource(R.string.action_settings), + title = localize(MR.strings.action_settings), onClick = onSettingsClick, ), ) @@ -99,21 +99,21 @@ fun BrowseSourceToolbar( onDismissRequest = { selectingDisplayMode = false }, ) { RadioMenuItem( - text = { Text(text = stringResource(R.string.action_display_comfortable_grid)) }, + text = { Text(text = localize(MR.strings.action_display_comfortable_grid)) }, isChecked = displayMode == LibraryDisplayMode.ComfortableGrid, ) { selectingDisplayMode = false onDisplayModeChange(LibraryDisplayMode.ComfortableGrid) } RadioMenuItem( - text = { Text(text = stringResource(R.string.action_display_grid)) }, + text = { Text(text = localize(MR.strings.action_display_grid)) }, isChecked = displayMode == LibraryDisplayMode.CompactGrid, ) { selectingDisplayMode = false onDisplayModeChange(LibraryDisplayMode.CompactGrid) } RadioMenuItem( - text = { Text(text = stringResource(R.string.action_display_list)) }, + text = { Text(text = localize(MR.strings.action_display_list)) }, isChecked = displayMode == LibraryDisplayMode.List, ) { selectingDisplayMode = false diff --git a/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchCardRow.kt b/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchCardRow.kt index 61d5b722fa..5d35fdebd2 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchCardRow.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchCardRow.kt @@ -13,15 +13,15 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import eu.kanade.presentation.library.components.CommonMangaItemDefaults import eu.kanade.presentation.library.components.MangaComfortableGridItem -import eu.kanade.tachiyomi.R import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.MangaCover import tachiyomi.domain.manga.model.asMangaCover +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize @Composable fun GlobalSearchCardRow( @@ -78,7 +78,7 @@ private fun MangaItem( @Composable private fun EmptyResultItem() { Text( - text = stringResource(R.string.no_results_found), + text = localize(MR.strings.no_results_found), modifier = Modifier .padding( horizontal = MaterialTheme.padding.medium, diff --git a/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchResultItems.kt b/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchResultItems.kt index 4661c304ca..11486a7e79 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchResultItems.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchResultItems.kt @@ -22,11 +22,11 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize @Composable fun GlobalSearchResultItem( @@ -93,7 +93,7 @@ fun GlobalSearchErrorResultItem(message: String?) { Icon(imageVector = Icons.Outlined.Error, contentDescription = null) Spacer(Modifier.height(4.dp)) Text( - text = message ?: stringResource(R.string.unknown_error), + text = message ?: localize(MR.strings.unknown_error), textAlign = TextAlign.Center, ) } diff --git a/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchToolbar.kt b/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchToolbar.kt index 965894af8c..e439e7da61 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchToolbar.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/components/GlobalSearchToolbar.kt @@ -26,11 +26,11 @@ import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import eu.kanade.presentation.components.SearchToolbar -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize @Composable fun GlobalSearchToolbar( @@ -85,7 +85,7 @@ fun GlobalSearchToolbar( ) }, label = { - Text(text = stringResource(id = R.string.pinned_sources)) + Text(text = localize(MR.strings.pinned_sources)) }, ) FilterChip( @@ -100,7 +100,7 @@ fun GlobalSearchToolbar( ) }, label = { - Text(text = stringResource(id = R.string.all)) + Text(text = localize(MR.strings.all)) }, ) @@ -118,7 +118,7 @@ fun GlobalSearchToolbar( ) }, label = { - Text(text = stringResource(id = R.string.has_results)) + Text(text = localize(MR.strings.has_results)) }, ) } diff --git a/app/src/main/java/eu/kanade/presentation/category/CategoryExtensions.kt b/app/src/main/java/eu/kanade/presentation/category/CategoryExtensions.kt index 0f2ade48e6..ce0f071c46 100644 --- a/app/src/main/java/eu/kanade/presentation/category/CategoryExtensions.kt +++ b/app/src/main/java/eu/kanade/presentation/category/CategoryExtensions.kt @@ -2,19 +2,20 @@ package eu.kanade.presentation.category import android.content.Context import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import eu.kanade.tachiyomi.R +import tachiyomi.core.i18n.localize import tachiyomi.domain.category.model.Category +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize val Category.visualName: String @Composable get() = when { - isSystemCategory -> stringResource(R.string.label_default) + isSystemCategory -> localize(MR.strings.label_default) else -> name } fun Category.visualName(context: Context): String = when { - isSystemCategory -> context.getString(R.string.label_default) + isSystemCategory -> context.localize(MR.strings.label_default) else -> name } diff --git a/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt b/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt index 26a536c287..831436e8d1 100644 --- a/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt @@ -12,18 +12,18 @@ import androidx.compose.material.icons.outlined.SortByAlpha import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import eu.kanade.presentation.category.components.CategoryFloatingActionButton import eu.kanade.presentation.category.components.CategoryListItem import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.category.CategoryScreenState import kotlinx.collections.immutable.persistentListOf import tachiyomi.domain.category.model.Category +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.topSmallPaddingValues +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.util.plus @@ -42,13 +42,13 @@ fun CategoryScreen( Scaffold( topBar = { scrollBehavior -> AppBar( - title = stringResource(R.string.action_edit_categories), + title = localize(MR.strings.action_edit_categories), navigateUp = navigateUp, actions = { AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.action_sort), + title = localize(MR.strings.action_sort), icon = Icons.Outlined.SortByAlpha, onClick = onClickSortAlphabetically, ), @@ -67,7 +67,7 @@ fun CategoryScreen( ) { paddingValues -> if (state.isEmpty) { EmptyScreen( - textResource = R.string.information_empty_category, + stringRes = MR.strings.information_empty_category, modifier = Modifier.padding(paddingValues), ) return@Scaffold diff --git a/app/src/main/java/eu/kanade/presentation/category/components/CategoryDialogs.kt b/app/src/main/java/eu/kanade/presentation/category/components/CategoryDialogs.kt index 684fc7dad7..1958e6e597 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/CategoryDialogs.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/CategoryDialogs.kt @@ -25,14 +25,14 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.res.stringResource import eu.kanade.core.preference.asToggleableState import eu.kanade.presentation.category.visualName -import eu.kanade.tachiyomi.R import kotlinx.coroutines.delay import tachiyomi.core.preference.CheckboxState import tachiyomi.domain.category.model.Category +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import kotlin.time.Duration.Companion.seconds @Composable @@ -56,30 +56,30 @@ fun CategoryCreateDialog( onDismissRequest() }, ) { - Text(text = stringResource(R.string.action_add)) + Text(text = localize(MR.strings.action_add)) } }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, title = { - Text(text = stringResource(R.string.action_add_category)) + Text(text = localize(MR.strings.action_add_category)) }, text = { OutlinedTextField( modifier = Modifier.focusRequester(focusRequester), value = name, onValueChange = { name = it }, - label = { Text(text = stringResource(R.string.name)) }, + label = { Text(text = localize(MR.strings.name)) }, supportingText = { val msgRes = if (name.isNotEmpty() && nameAlreadyExists) { - R.string.error_category_exists + MR.strings.error_category_exists } else { - R.string.information_required_plain + MR.strings.information_required_plain } - Text(text = stringResource(msgRes)) + Text(text = localize(msgRes)) }, isError = name.isNotEmpty() && nameAlreadyExists, singleLine = true, @@ -117,16 +117,16 @@ fun CategoryRenameDialog( onDismissRequest() }, ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, title = { - Text(text = stringResource(R.string.action_rename_category)) + Text(text = localize(MR.strings.action_rename_category)) }, text = { OutlinedTextField( @@ -136,14 +136,14 @@ fun CategoryRenameDialog( valueHasChanged = name != it name = it }, - label = { Text(text = stringResource(R.string.name)) }, + label = { Text(text = localize(MR.strings.name)) }, supportingText = { val msgRes = if (valueHasChanged && nameAlreadyExists) { - R.string.error_category_exists + MR.strings.error_category_exists } else { - R.string.information_required_plain + MR.strings.information_required_plain } - Text(text = stringResource(msgRes)) + Text(text = localize(msgRes)) }, isError = valueHasChanged && nameAlreadyExists, singleLine = true, @@ -171,19 +171,19 @@ fun CategoryDeleteDialog( onDelete() onDismissRequest() }) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, title = { - Text(text = stringResource(R.string.delete_category)) + Text(text = localize(MR.strings.delete_category)) }, text = { - Text(text = stringResource(R.string.delete_category_confirmation, category.name)) + Text(text = localize(MR.strings.delete_category_confirmation, category.name)) }, ) } @@ -200,19 +200,19 @@ fun CategorySortAlphabeticallyDialog( onSort() onDismissRequest() }) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, title = { - Text(text = stringResource(R.string.action_sort_category)) + Text(text = localize(MR.strings.action_sort_category)) }, text = { - Text(text = stringResource(R.string.sort_category_confirmation)) + Text(text = localize(MR.strings.sort_category_confirmation)) }, ) } @@ -234,14 +234,14 @@ fun ChangeCategoryDialog( onEditCategories() }, ) { - Text(text = stringResource(R.string.action_edit_categories)) + Text(text = localize(MR.strings.action_edit_categories)) } }, title = { - Text(text = stringResource(R.string.action_move_category)) + Text(text = localize(MR.strings.action_move_category)) }, text = { - Text(text = stringResource(R.string.information_empty_category_dialog)) + Text(text = localize(MR.strings.information_empty_category_dialog)) }, ) return @@ -255,11 +255,11 @@ fun ChangeCategoryDialog( onDismissRequest() onEditCategories() }) { - Text(text = stringResource(R.string.action_edit)) + Text(text = localize(MR.strings.action_edit)) } Spacer(modifier = Modifier.weight(1f)) tachiyomi.presentation.core.components.material.TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } tachiyomi.presentation.core.components.material.TextButton( onClick = { @@ -274,12 +274,12 @@ fun ChangeCategoryDialog( ) }, ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } } }, title = { - Text(text = stringResource(R.string.action_move_category)) + Text(text = localize(MR.strings.action_move_category)) }, text = { Column( diff --git a/app/src/main/java/eu/kanade/presentation/category/components/CategoryFloatingActionButton.kt b/app/src/main/java/eu/kanade/presentation/category/components/CategoryFloatingActionButton.kt index b2bd560577..bbb17095c6 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/CategoryFloatingActionButton.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/CategoryFloatingActionButton.kt @@ -6,9 +6,9 @@ import androidx.compose.material.icons.outlined.Add import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.isScrolledToEnd import tachiyomi.presentation.core.util.isScrollingUp @@ -18,7 +18,7 @@ fun CategoryFloatingActionButton( onCreate: () -> Unit, ) { ExtendedFloatingActionButton( - text = { Text(text = stringResource(R.string.action_add)) }, + text = { Text(text = localize(MR.strings.action_add)) }, icon = { Icon(imageVector = Icons.Outlined.Add, contentDescription = null) }, onClick = onCreate, expanded = lazyListState.isScrollingUp() || lazyListState.isScrolledToEnd(), diff --git a/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt b/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt index e2cebe25d1..07b4c4fba2 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt @@ -20,10 +20,10 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import eu.kanade.tachiyomi.R import tachiyomi.domain.category.model.Category +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize @Composable fun CategoryListItem( @@ -74,11 +74,11 @@ fun CategoryListItem( IconButton(onClick = onRename) { Icon( imageVector = Icons.Outlined.Edit, - contentDescription = stringResource(R.string.action_rename_category), + contentDescription = localize(MR.strings.action_rename_category), ) } IconButton(onClick = onDelete) { - Icon(imageVector = Icons.Outlined.Delete, contentDescription = stringResource(R.string.action_delete)) + Icon(imageVector = Icons.Outlined.Delete, contentDescription = localize(MR.strings.action_delete)) } } } diff --git a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt index 72fc17a30f..be162175b1 100644 --- a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt +++ b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt @@ -52,6 +52,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import eu.kanade.tachiyomi.R import kotlinx.collections.immutable.ImmutableList +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.clearFocusOnSoftKeyboardHide import tachiyomi.presentation.core.util.runOnEnterKeyPressed import tachiyomi.presentation.core.util.secondaryItemAlpha @@ -133,7 +135,7 @@ fun AppBar( IconButton(onClick = onCancelActionMode) { Icon( imageVector = Icons.Outlined.Close, - contentDescription = stringResource(R.string.action_cancel), + contentDescription = localize(MR.strings.action_cancel), ) } } else { @@ -253,7 +255,7 @@ fun AppBarActions( /** * @param searchEnabled Set to false if you don't want to show search action. * @param searchQuery If null, use normal toolbar. - * @param placeholderText If null, [R.string.action_search_hint] is used. + * @param placeholderText If null, [MR.strings.action_search_hint] is used. */ @Composable fun SearchToolbar( @@ -317,7 +319,7 @@ fun SearchToolbar( placeholder = { Text( modifier = Modifier.secondaryItemAlpha(), - text = (placeholderText ?: stringResource(R.string.action_search_hint)), + text = (placeholderText ?: localize(MR.strings.action_search_hint)), maxLines = 1, overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.titleMedium.copy( @@ -342,7 +344,7 @@ fun SearchToolbar( positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(), tooltip = { PlainTooltip { - Text(stringResource(R.string.action_search)) + Text(localize(MR.strings.action_search)) } }, state = rememberTooltipState(), @@ -352,7 +354,7 @@ fun SearchToolbar( ) { Icon( Icons.Outlined.Search, - contentDescription = stringResource(R.string.action_search), + contentDescription = localize(MR.strings.action_search), ) } } @@ -361,7 +363,7 @@ fun SearchToolbar( positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(), tooltip = { PlainTooltip { - Text(stringResource(R.string.action_reset)) + Text(localize(MR.strings.action_reset)) } }, state = rememberTooltipState(), @@ -374,7 +376,7 @@ fun SearchToolbar( ) { Icon( Icons.Outlined.Close, - contentDescription = stringResource(R.string.action_reset), + contentDescription = localize(MR.strings.action_reset), ) } } diff --git a/app/src/main/java/eu/kanade/presentation/components/Banners.kt b/app/src/main/java/eu/kanade/presentation/components/Banners.kt index 14525e137b..070cc9a696 100644 --- a/app/src/main/java/eu/kanade/presentation/components/Banners.kt +++ b/app/src/main/java/eu/kanade/presentation/components/Banners.kt @@ -1,6 +1,5 @@ package eu.kanade.presentation.components -import androidx.annotation.StringRes import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.expandVertically import androidx.compose.animation.shrinkVertically @@ -26,13 +25,14 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.layout.SubcomposeLayout import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastMap import androidx.compose.ui.util.fastMaxBy -import eu.kanade.tachiyomi.R +import dev.icerock.moko.resources.StringResource +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize val DownloadedOnlyBannerBackgroundColor @Composable get() = MaterialTheme.colorScheme.tertiary @@ -43,11 +43,11 @@ val IndexingBannerBackgroundColor @Composable fun WarningBanner( - @StringRes textRes: Int, + textRes: StringResource, modifier: Modifier = Modifier, ) { Text( - text = stringResource(textRes), + text = localize(textRes), modifier = modifier .fillMaxWidth() .background(MaterialTheme.colorScheme.error) @@ -127,7 +127,7 @@ fun AppStateBanners( @Composable private fun DownloadedOnlyModeBanner(modifier: Modifier = Modifier) { Text( - text = stringResource(R.string.label_downloaded_only), + text = localize(MR.strings.label_downloaded_only), modifier = Modifier .background(DownloadedOnlyBannerBackgroundColor) .fillMaxWidth() @@ -142,7 +142,7 @@ private fun DownloadedOnlyModeBanner(modifier: Modifier = Modifier) { @Composable private fun IncognitoModeBanner(modifier: Modifier = Modifier) { Text( - text = stringResource(R.string.pref_incognito_mode), + text = localize(MR.strings.pref_incognito_mode), modifier = Modifier .background(IncognitoModeBannerBackgroundColor) .fillMaxWidth() @@ -173,7 +173,7 @@ private fun IndexingDownloadBanner(modifier: Modifier = Modifier) { ) Spacer(modifier = Modifier.width(8.dp)) Text( - text = stringResource(R.string.download_notifier_cache_renewal), + text = localize(MR.strings.download_notifier_cache_renewal), color = MaterialTheme.colorScheme.onSecondary, textAlign = TextAlign.Center, style = MaterialTheme.typography.labelMedium, diff --git a/app/src/main/java/eu/kanade/presentation/components/DownloadDropdownMenu.kt b/app/src/main/java/eu/kanade/presentation/components/DownloadDropdownMenu.kt index ccf0b72f0e..8eb83b9f43 100644 --- a/app/src/main/java/eu/kanade/presentation/components/DownloadDropdownMenu.kt +++ b/app/src/main/java/eu/kanade/presentation/components/DownloadDropdownMenu.kt @@ -3,10 +3,10 @@ package eu.kanade.presentation.components import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.res.pluralStringResource -import androidx.compose.ui.res.stringResource import eu.kanade.presentation.manga.DownloadAction -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize +import tachiyomi.presentation.core.i18n.localizePlural @Composable fun DownloadDropdownMenu( @@ -19,11 +19,11 @@ fun DownloadDropdownMenu( onDismissRequest = onDismissRequest, ) { listOfNotNull( - DownloadAction.NEXT_1_CHAPTER to pluralStringResource(R.plurals.download_amount, 1, 1), - DownloadAction.NEXT_5_CHAPTERS to pluralStringResource(R.plurals.download_amount, 5, 5), - DownloadAction.NEXT_10_CHAPTERS to pluralStringResource(R.plurals.download_amount, 10, 10), - DownloadAction.NEXT_25_CHAPTERS to pluralStringResource(R.plurals.download_amount, 25, 25), - DownloadAction.UNREAD_CHAPTERS to stringResource(R.string.download_unread), + DownloadAction.NEXT_1_CHAPTER to localizePlural(MR.plurals.download_amount, 1, 1), + DownloadAction.NEXT_5_CHAPTERS to localizePlural(MR.plurals.download_amount, 5, 5), + DownloadAction.NEXT_10_CHAPTERS to localizePlural(MR.plurals.download_amount, 10, 10), + DownloadAction.NEXT_25_CHAPTERS to localizePlural(MR.plurals.download_amount, 25, 25), + DownloadAction.UNREAD_CHAPTERS to localize(MR.strings.download_unread), ).map { (downloadAction, string) -> DropdownMenuItem( text = { Text(text = string) }, diff --git a/app/src/main/java/eu/kanade/presentation/components/DropdownMenu.kt b/app/src/main/java/eu/kanade/presentation/components/DropdownMenu.kt index ba6cdd341e..5097515049 100644 --- a/app/src/main/java/eu/kanade/presentation/components/DropdownMenu.kt +++ b/app/src/main/java/eu/kanade/presentation/components/DropdownMenu.kt @@ -15,11 +15,11 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.PopupProperties -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import androidx.compose.material3.DropdownMenu as ComposeDropdownMenu @Composable @@ -54,13 +54,13 @@ fun RadioMenuItem( if (isChecked) { Icon( imageVector = Icons.Outlined.RadioButtonChecked, - contentDescription = stringResource(R.string.selected), + contentDescription = localize(MR.strings.selected), tint = MaterialTheme.colorScheme.primary, ) } else { Icon( imageVector = Icons.Outlined.RadioButtonUnchecked, - contentDescription = stringResource(R.string.not_selected), + contentDescription = localize(MR.strings.not_selected), ) } }, diff --git a/app/src/main/java/eu/kanade/presentation/components/EmptyScreen.kt b/app/src/main/java/eu/kanade/presentation/components/EmptyScreen.kt index 47efe2abaf..ddcf22cb43 100644 --- a/app/src/main/java/eu/kanade/presentation/components/EmptyScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/components/EmptyScreen.kt @@ -2,14 +2,13 @@ package eu.kanade.presentation.components import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.HelpOutline -import androidx.compose.material.icons.outlined.HelpOutline import androidx.compose.material.icons.outlined.Refresh import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.PreviewLightDark import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.EmptyScreenAction @@ -19,7 +18,7 @@ private fun NoActionPreview() { TachiyomiTheme { Surface { EmptyScreen( - textResource = R.string.empty_screen, + stringRes = MR.strings.empty_screen, ) } } @@ -31,15 +30,15 @@ private fun WithActionPreview() { TachiyomiTheme { Surface { EmptyScreen( - textResource = R.string.empty_screen, + stringRes = MR.strings.empty_screen, actions = persistentListOf( EmptyScreenAction( - stringResId = R.string.action_retry, + stringRes = MR.strings.action_retry, icon = Icons.Outlined.Refresh, onClick = {}, ), EmptyScreenAction( - stringResId = R.string.getting_started_guide, + stringRes = MR.strings.getting_started_guide, icon = Icons.AutoMirrored.Outlined.HelpOutline, onClick = {}, ), diff --git a/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt b/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt index 70a6b48aac..9a62b42f0f 100644 --- a/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt @@ -24,14 +24,14 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEachIndexed -import eu.kanade.tachiyomi.R import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.launch +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.HorizontalPager import tachiyomi.presentation.core.components.material.TabText +import tachiyomi.presentation.core.i18n.localize object TabbedDialogPaddings { val Horizontal = 24.dp @@ -94,7 +94,7 @@ private fun MoreMenu( IconButton(onClick = { expanded = true }) { Icon( imageVector = Icons.Default.MoreVert, - contentDescription = stringResource(R.string.label_more), + contentDescription = localize(MR.strings.label_more), ) } DropdownMenu( diff --git a/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt b/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt index 18221cbdd1..0e276a1597 100644 --- a/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt @@ -1,6 +1,5 @@ package eu.kanade.presentation.components -import androidx.annotation.StringRes import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.calculateEndPadding @@ -20,17 +19,18 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.res.stringResource +import dev.icerock.moko.resources.StringResource import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.launch import tachiyomi.presentation.core.components.HorizontalPager import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.TabText +import tachiyomi.presentation.core.i18n.localize @Composable fun TabbedScreen( - @StringRes titleRes: Int, + titleRes: StringResource, tabs: ImmutableList, startIndex: Int? = null, searchQuery: String? = null, @@ -52,7 +52,7 @@ fun TabbedScreen( val searchEnabled = tab.searchEnabled SearchToolbar( - titleContent = { AppBarTitle(stringResource(titleRes)) }, + titleContent = { AppBarTitle(localize(titleRes)) }, searchEnabled = searchEnabled, searchQuery = if (searchEnabled) searchQuery else null, onChangeSearchQuery = onChangeSearchQuery, @@ -75,7 +75,7 @@ fun TabbedScreen( Tab( selected = state.currentPage == index, onClick = { scope.launch { state.animateScrollToPage(index) } }, - text = { TabText(text = stringResource(tab.titleRes), badgeCount = tab.badgeNumber) }, + text = { TabText(text = localize(tab.titleRes), badgeCount = tab.badgeNumber) }, unselectedContentColor = MaterialTheme.colorScheme.onSurface, ) } @@ -96,7 +96,7 @@ fun TabbedScreen( } data class TabContent( - @StringRes val titleRes: Int, + val titleRes: StringResource, val badgeNumber: Int? = null, val searchEnabled: Boolean = false, val actions: ImmutableList = persistentListOf(), diff --git a/app/src/main/java/eu/kanade/presentation/crash/CrashScreen.kt b/app/src/main/java/eu/kanade/presentation/crash/CrashScreen.kt index 932f02e16f..d61600f3f3 100644 --- a/app/src/main/java/eu/kanade/presentation/crash/CrashScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/crash/CrashScreen.kt @@ -13,13 +13,13 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.CrashLogUtil import kotlinx.coroutines.launch +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.InfoScreen @Composable @@ -32,15 +32,15 @@ fun CrashScreen( InfoScreen( icon = Icons.Outlined.BugReport, - headingText = stringResource(R.string.crash_screen_title), - subtitleText = stringResource(R.string.crash_screen_description, stringResource(R.string.app_name)), - acceptText = stringResource(R.string.pref_dump_crash_logs), + headingText = localize(MR.strings.crash_screen_title), + subtitleText = localize(MR.strings.crash_screen_description, localize(MR.strings.app_name)), + acceptText = localize(MR.strings.pref_dump_crash_logs), onAcceptClick = { scope.launch { CrashLogUtil(context).dumpLogs() } }, - rejectText = stringResource(R.string.crash_screen_restart_application), + rejectText = localize(MR.strings.crash_screen_restart_application), onRejectClick = onRestartClick, ) { Box( diff --git a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt index 9a40ab98d5..9613f0f4c8 100644 --- a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt @@ -10,7 +10,6 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewParameter import eu.kanade.domain.ui.UiPreferences @@ -21,13 +20,14 @@ import eu.kanade.presentation.components.RelativeDateHeader import eu.kanade.presentation.components.SearchToolbar import eu.kanade.presentation.history.components.HistoryItem import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.history.HistoryScreenModel import kotlinx.collections.immutable.persistentListOf import tachiyomi.core.preference.InMemoryPreferenceStore import tachiyomi.domain.history.model.HistoryWithRelations +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen import uy.kohesive.injekt.Injekt @@ -47,14 +47,14 @@ fun HistoryScreen( Scaffold( topBar = { scrollBehavior -> SearchToolbar( - titleContent = { AppBarTitle(stringResource(R.string.history)) }, + titleContent = { AppBarTitle(localize(MR.strings.history)) }, searchQuery = state.searchQuery, onChangeSearchQuery = onSearchQueryChange, actions = { AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.pref_clear_history), + title = localize(MR.strings.pref_clear_history), icon = Icons.Outlined.DeleteSweep, onClick = { onDialogChange(HistoryScreenModel.Dialog.DeleteAll) @@ -73,12 +73,12 @@ fun HistoryScreen( LoadingScreen(Modifier.padding(contentPadding)) } else if (it.isEmpty()) { val msg = if (!state.searchQuery.isNullOrEmpty()) { - R.string.no_results_found + MR.strings.no_results_found } else { - R.string.information_no_recent_manga + MR.strings.information_no_recent_manga } EmptyScreen( - textResource = msg, + stringRes = msg, modifier = Modifier.padding(contentPadding), ) } else { diff --git a/app/src/main/java/eu/kanade/presentation/history/components/HistoryDialogs.kt b/app/src/main/java/eu/kanade/presentation/history/components/HistoryDialogs.kt index 5e9027ba02..e97bdbcc7e 100644 --- a/app/src/main/java/eu/kanade/presentation/history/components/HistoryDialogs.kt +++ b/app/src/main/java/eu/kanade/presentation/history/components/HistoryDialogs.kt @@ -10,12 +10,12 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.LabeledCheckbox +import tachiyomi.presentation.core.i18n.localize @Composable fun HistoryDeleteDialog( @@ -26,16 +26,16 @@ fun HistoryDeleteDialog( AlertDialog( title = { - Text(text = stringResource(R.string.action_remove)) + Text(text = localize(MR.strings.action_remove)) }, text = { Column( verticalArrangement = Arrangement.spacedBy(8.dp), ) { - Text(text = stringResource(R.string.dialog_with_checkbox_remove_description)) + Text(text = localize(MR.strings.dialog_with_checkbox_remove_description)) LabeledCheckbox( - label = stringResource(R.string.dialog_with_checkbox_reset), + label = localize(MR.strings.dialog_with_checkbox_reset), checked = removeEverything, onCheckedChange = { removeEverything = it }, ) @@ -47,12 +47,12 @@ fun HistoryDeleteDialog( onDelete(removeEverything) onDismissRequest() }) { - Text(text = stringResource(R.string.action_remove)) + Text(text = localize(MR.strings.action_remove)) } }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, ) @@ -65,10 +65,10 @@ fun HistoryDeleteAllDialog( ) { AlertDialog( title = { - Text(text = stringResource(R.string.action_remove_everything)) + Text(text = localize(MR.strings.action_remove_everything)) }, text = { - Text(text = stringResource(R.string.clear_history_confirmation)) + Text(text = localize(MR.strings.clear_history_confirmation)) }, onDismissRequest = onDismissRequest, confirmButton = { @@ -76,12 +76,12 @@ fun HistoryDeleteAllDialog( onDelete() onDismissRequest() }) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, ) diff --git a/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt b/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt index 12808941d2..1cb3034dce 100644 --- a/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt +++ b/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt @@ -17,7 +17,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewLightDark @@ -26,10 +25,11 @@ import androidx.compose.ui.unit.dp import eu.kanade.presentation.manga.components.MangaCover import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.util.formatChapterNumber -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.lang.toTimestampString import tachiyomi.domain.history.model.HistoryWithRelations +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize private val HistoryItemHeight = 96.dp @@ -69,8 +69,8 @@ fun HistoryItem( val readAt = remember { history.readAt?.toTimestampString() ?: "" } Text( text = if (history.chapterNumber > -1) { - stringResource( - R.string.recent_manga_time, + localize( + MR.strings.recent_manga_time, formatChapterNumber(history.chapterNumber), readAt, ) @@ -85,7 +85,7 @@ fun HistoryItem( IconButton(onClick = onClickDelete) { Icon( imageVector = Icons.Outlined.Delete, - contentDescription = stringResource(R.string.action_delete), + contentDescription = localize(MR.strings.action_delete), tint = MaterialTheme.colorScheme.onSurface, ) } diff --git a/app/src/main/java/eu/kanade/presentation/library/DeleteLibraryMangaDialog.kt b/app/src/main/java/eu/kanade/presentation/library/DeleteLibraryMangaDialog.kt index 49a9a8360b..539392b6ae 100644 --- a/app/src/main/java/eu/kanade/presentation/library/DeleteLibraryMangaDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/library/DeleteLibraryMangaDialog.kt @@ -9,10 +9,11 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.res.stringResource -import eu.kanade.tachiyomi.R +import dev.icerock.moko.resources.StringResource import tachiyomi.core.preference.CheckboxState +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.LabeledCheckbox +import tachiyomi.presentation.core.i18n.localize @Composable fun DeleteLibraryMangaDialog( @@ -22,10 +23,10 @@ fun DeleteLibraryMangaDialog( ) { var list by remember { mutableStateOf( - buildList> { - add(CheckboxState.State.None(R.string.manga_from_library)) + buildList> { + add(CheckboxState.State.None(MR.strings.manga_from_library)) if (!containsLocalManga) { - add(CheckboxState.State.None(R.string.downloaded_chapters)) + add(CheckboxState.State.None(MR.strings.downloaded_chapters)) } }, ) @@ -34,7 +35,7 @@ fun DeleteLibraryMangaDialog( onDismissRequest = onDismissRequest, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, confirmButton = { @@ -48,23 +49,23 @@ fun DeleteLibraryMangaDialog( ) }, ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, title = { - Text(text = stringResource(R.string.action_remove)) + Text(text = localize(MR.strings.action_remove)) }, text = { Column { list.forEach { state -> LabeledCheckbox( - label = stringResource(state.value), + label = localize(state.value), checked = state.isChecked, onCheckedChange = { val index = list.indexOf(state) if (index != -1) { val mutableList = list.toMutableList() - mutableList[index] = state.next() as CheckboxState.State + mutableList[index] = state.next() as CheckboxState.State list = mutableList.toList() } }, diff --git a/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt b/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt index 2c58b0e605..59d27b2bf1 100644 --- a/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt @@ -13,10 +13,8 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.res.stringResource import eu.kanade.presentation.components.TabbedDialog import eu.kanade.presentation.components.TabbedDialogPaddings -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.library.LibrarySettingsScreenModel import kotlinx.collections.immutable.persistentListOf import tachiyomi.core.preference.TriState @@ -25,12 +23,14 @@ import tachiyomi.domain.library.model.LibraryDisplayMode import tachiyomi.domain.library.model.LibrarySort import tachiyomi.domain.library.model.sort import tachiyomi.domain.library.service.LibraryPreferences +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.CheckboxItem import tachiyomi.presentation.core.components.HeadingItem import tachiyomi.presentation.core.components.SettingsChipRow import tachiyomi.presentation.core.components.SliderItem import tachiyomi.presentation.core.components.SortItem import tachiyomi.presentation.core.components.TriStateItem +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.collectAsState @Composable @@ -42,9 +42,9 @@ fun LibrarySettingsDialog( TabbedDialog( onDismissRequest = onDismissRequest, tabTitles = persistentListOf( - stringResource(R.string.action_filter), - stringResource(R.string.action_sort), - stringResource(R.string.action_display), + localize(MR.strings.action_filter), + localize(MR.strings.action_sort), + localize(MR.strings.action_display), ), ) { page -> Column( @@ -75,7 +75,7 @@ private fun ColumnScope.FilterPage( val filterDownloaded by screenModel.libraryPreferences.filterDownloaded().collectAsState() val downloadedOnly by screenModel.preferences.downloadedOnly().collectAsState() TriStateItem( - label = stringResource(R.string.label_downloaded), + label = localize(MR.strings.label_downloaded), state = if (downloadedOnly) { TriState.ENABLED_IS } else { @@ -86,25 +86,25 @@ private fun ColumnScope.FilterPage( ) val filterUnread by screenModel.libraryPreferences.filterUnread().collectAsState() TriStateItem( - label = stringResource(R.string.action_filter_unread), + label = localize(MR.strings.action_filter_unread), state = filterUnread, onClick = { screenModel.toggleFilter(LibraryPreferences::filterUnread) }, ) val filterStarted by screenModel.libraryPreferences.filterStarted().collectAsState() TriStateItem( - label = stringResource(R.string.label_started), + label = localize(MR.strings.label_started), state = filterStarted, onClick = { screenModel.toggleFilter(LibraryPreferences::filterStarted) }, ) val filterBookmarked by screenModel.libraryPreferences.filterBookmarked().collectAsState() TriStateItem( - label = stringResource(R.string.action_filter_bookmarked), + label = localize(MR.strings.action_filter_bookmarked), state = filterBookmarked, onClick = { screenModel.toggleFilter(LibraryPreferences::filterBookmarked) }, ) val filterCompleted by screenModel.libraryPreferences.filterCompleted().collectAsState() TriStateItem( - label = stringResource(R.string.completed), + label = localize(MR.strings.completed), state = filterCompleted, onClick = { screenModel.toggleFilter(LibraryPreferences::filterCompleted) }, ) @@ -118,13 +118,13 @@ private fun ColumnScope.FilterPage( val service = trackers[0] val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState() TriStateItem( - label = stringResource(R.string.action_filter_tracked), + label = localize(MR.strings.action_filter_tracked), state = filterTracker, onClick = { screenModel.toggleTracker(service.id.toInt()) }, ) } else -> { - HeadingItem(R.string.action_filter_tracked) + HeadingItem(MR.strings.action_filter_tracked) trackers.map { service -> val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState() TriStateItem( @@ -149,21 +149,21 @@ private fun ColumnScope.SortPage( if (screenModel.trackers.isEmpty()) { emptyList() } else { - listOf(R.string.action_sort_tracker_score to LibrarySort.Type.TrackerMean) + listOf(MR.strings.action_sort_tracker_score to LibrarySort.Type.TrackerMean) } listOf( - R.string.action_sort_alpha to LibrarySort.Type.Alphabetical, - R.string.action_sort_total to LibrarySort.Type.TotalChapters, - R.string.action_sort_last_read to LibrarySort.Type.LastRead, - R.string.action_sort_last_manga_update to LibrarySort.Type.LastUpdate, - R.string.action_sort_unread_count to LibrarySort.Type.UnreadCount, - R.string.action_sort_latest_chapter to LibrarySort.Type.LatestChapter, - R.string.action_sort_chapter_fetch_date to LibrarySort.Type.ChapterFetchDate, - R.string.action_sort_date_added to LibrarySort.Type.DateAdded, + MR.strings.action_sort_alpha to LibrarySort.Type.Alphabetical, + MR.strings.action_sort_total to LibrarySort.Type.TotalChapters, + MR.strings.action_sort_last_read to LibrarySort.Type.LastRead, + MR.strings.action_sort_last_manga_update to LibrarySort.Type.LastUpdate, + MR.strings.action_sort_unread_count to LibrarySort.Type.UnreadCount, + MR.strings.action_sort_latest_chapter to LibrarySort.Type.LatestChapter, + MR.strings.action_sort_chapter_fetch_date to LibrarySort.Type.ChapterFetchDate, + MR.strings.action_sort_date_added to LibrarySort.Type.DateAdded, ).plus(trackerSortOption).map { (titleRes, mode) -> SortItem( - label = stringResource(titleRes), + label = localize(titleRes), sortDescending = sortDescending.takeIf { sortingMode == mode }, onClick = { val isTogglingDirection = sortingMode == mode @@ -186,10 +186,10 @@ private fun ColumnScope.SortPage( } private val displayModes = listOf( - R.string.action_display_grid to LibraryDisplayMode.CompactGrid, - R.string.action_display_comfortable_grid to LibraryDisplayMode.ComfortableGrid, - R.string.action_display_cover_only_grid to LibraryDisplayMode.CoverOnlyGrid, - R.string.action_display_list to LibraryDisplayMode.List, + MR.strings.action_display_grid to LibraryDisplayMode.CompactGrid, + MR.strings.action_display_comfortable_grid to LibraryDisplayMode.ComfortableGrid, + MR.strings.action_display_cover_only_grid to LibraryDisplayMode.CoverOnlyGrid, + MR.strings.action_display_list to LibraryDisplayMode.List, ) @Composable @@ -197,12 +197,12 @@ private fun ColumnScope.DisplayPage( screenModel: LibrarySettingsScreenModel, ) { val displayMode by screenModel.libraryPreferences.displayMode().collectAsState() - SettingsChipRow(R.string.action_display_mode) { + SettingsChipRow(MR.strings.action_display_mode) { displayModes.map { (titleRes, mode) -> FilterChip( selected = displayMode == mode, onClick = { screenModel.setDisplayMode(mode) }, - label = { Text(stringResource(titleRes)) }, + label = { Text(localize(titleRes)) }, ) } } @@ -219,43 +219,43 @@ private fun ColumnScope.DisplayPage( val columns by columnPreference.collectAsState() SliderItem( - label = stringResource(R.string.pref_library_columns), + label = localize(MR.strings.pref_library_columns), max = 10, value = columns, valueText = if (columns > 0) { - stringResource(R.string.pref_library_columns_per_row, columns) + localize(MR.strings.pref_library_columns_per_row, columns) } else { - stringResource(R.string.label_default) + localize(MR.strings.label_default) }, onChange = columnPreference::set, ) } - HeadingItem(R.string.overlay_header) + HeadingItem(MR.strings.overlay_header) CheckboxItem( - label = stringResource(R.string.action_display_download_badge), + label = localize(MR.strings.action_display_download_badge), pref = screenModel.libraryPreferences.downloadBadge(), ) CheckboxItem( - label = stringResource(R.string.action_display_local_badge), + label = localize(MR.strings.action_display_local_badge), pref = screenModel.libraryPreferences.localBadge(), ) CheckboxItem( - label = stringResource(R.string.action_display_language_badge), + label = localize(MR.strings.action_display_language_badge), pref = screenModel.libraryPreferences.languageBadge(), ) CheckboxItem( - label = stringResource(R.string.action_display_show_continue_reading_button), + label = localize(MR.strings.action_display_show_continue_reading_button), pref = screenModel.libraryPreferences.showContinueReadingButton(), ) - HeadingItem(R.string.tabs_header) + HeadingItem(MR.strings.tabs_header) CheckboxItem( - label = stringResource(R.string.action_display_show_tabs), + label = localize(MR.strings.action_display_show_tabs), pref = screenModel.libraryPreferences.categoryTabs(), ) CheckboxItem( - label = stringResource(R.string.action_display_show_number_of_items), + label = localize(MR.strings.action_display_show_number_of_items), pref = screenModel.libraryPreferences.categoryNumberOfItems(), ) } diff --git a/app/src/main/java/eu/kanade/presentation/library/components/CommonMangaItem.kt b/app/src/main/java/eu/kanade/presentation/library/components/CommonMangaItem.kt index 6cffebe8bc..47f215f4e0 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/CommonMangaItem.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/CommonMangaItem.kt @@ -33,14 +33,14 @@ import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shadow -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import eu.kanade.presentation.manga.components.MangaCover -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.BadgeGroup +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.selectedBackground object CommonMangaItemDefaults { @@ -378,7 +378,7 @@ private fun ContinueReadingButton( ) { Icon( imageVector = Icons.Filled.PlayArrow, - contentDescription = stringResource(R.string.action_resume), + contentDescription = localize(MR.strings.action_resume), modifier = Modifier.size(16.dp), ) } diff --git a/app/src/main/java/eu/kanade/presentation/library/components/GlobalSearchItem.kt b/app/src/main/java/eu/kanade/presentation/library/components/GlobalSearchItem.kt index 93b5143ff6..f5e60539b0 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/GlobalSearchItem.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/GlobalSearchItem.kt @@ -4,9 +4,9 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.zIndex -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize @Composable internal fun GlobalSearchItem( @@ -19,7 +19,7 @@ internal fun GlobalSearchItem( onClick = onClick, ) { Text( - text = stringResource(R.string.action_global_search_query, searchQuery), + text = localize(MR.strings.action_global_search_query, searchQuery), modifier = Modifier.zIndex(99f), ) } diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt index ace52a11c5..db7af58752 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt @@ -18,10 +18,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.unit.dp import eu.kanade.core.preference.PreferenceMutableState -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.library.LibraryItem import tachiyomi.domain.library.model.LibraryDisplayMode import tachiyomi.domain.library.model.LibraryManga +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.HorizontalPager import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.util.plus @@ -124,9 +124,9 @@ private fun LibraryPagerEmptyScreen( onGlobalSearchClicked: () -> Unit, ) { val msg = when { - !searchQuery.isNullOrEmpty() -> R.string.no_results_found - hasActiveFilters -> R.string.error_no_match - else -> R.string.information_no_manga_category + !searchQuery.isNullOrEmpty() -> MR.strings.no_results_found + hasActiveFilters -> MR.strings.error_no_match + else -> MR.strings.information_no_manga_category } Column( @@ -146,7 +146,7 @@ private fun LibraryPagerEmptyScreen( } EmptyScreen( - textResource = msg, + stringRes = msg, modifier = Modifier.weight(1f), ) } diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryToolbar.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryToolbar.kt index 18a332d1ff..1c660cb0c0 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryToolbar.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryToolbar.kt @@ -14,15 +14,15 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.sp import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.SearchToolbar -import eu.kanade.tachiyomi.R import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.Pill +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.theme.active @Composable @@ -98,21 +98,21 @@ private fun LibraryRegularToolbar( AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.action_filter), + title = localize(MR.strings.action_filter), icon = Icons.Outlined.FilterList, iconTint = filterTint, onClick = onClickFilter, ), AppBar.OverflowAction( - title = stringResource(R.string.action_update_library), + title = localize(MR.strings.action_update_library), onClick = onClickGlobalUpdate, ), AppBar.OverflowAction( - title = stringResource(R.string.action_update_category), + title = localize(MR.strings.action_update_category), onClick = onClickRefresh, ), AppBar.OverflowAction( - title = stringResource(R.string.action_open_random_manga), + title = localize(MR.strings.action_open_random_manga), onClick = onClickOpenRandomManga, ), ), @@ -135,12 +135,12 @@ private fun LibrarySelectionToolbar( AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.action_select_all), + title = localize(MR.strings.action_select_all), icon = Icons.Outlined.SelectAll, onClick = onClickSelectAll, ), AppBar.Action( - title = stringResource(R.string.action_select_inverse), + title = localize(MR.strings.action_select_inverse), icon = Icons.Outlined.FlipToBack, onClick = onClickInvertSelection, ), diff --git a/app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt b/app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt index b4fed1b73d..6463ab7851 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt @@ -25,20 +25,20 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import eu.kanade.domain.manga.model.downloadedFilter import eu.kanade.domain.manga.model.forceDownloaded import eu.kanade.presentation.components.TabbedDialog import eu.kanade.presentation.components.TabbedDialogPaddings -import eu.kanade.tachiyomi.R import kotlinx.collections.immutable.persistentListOf import tachiyomi.core.preference.TriState import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.components.RadioItem import tachiyomi.presentation.core.components.SortItem import tachiyomi.presentation.core.components.TriStateItem +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.theme.active @Composable @@ -66,20 +66,20 @@ fun ChapterSettingsDialog( TabbedDialog( onDismissRequest = onDismissRequest, tabTitles = persistentListOf( - stringResource(R.string.action_filter), - stringResource(R.string.action_sort), - stringResource(R.string.action_display), + localize(MR.strings.action_filter), + localize(MR.strings.action_sort), + localize(MR.strings.action_display), ), tabOverflowMenuContent = { closeMenu -> DropdownMenuItem( - text = { Text(stringResource(R.string.set_chapter_settings_as_default)) }, + text = { Text(localize(MR.strings.set_chapter_settings_as_default)) }, onClick = { showSetAsDefaultDialog = true closeMenu() }, ) DropdownMenuItem( - text = { Text(stringResource(R.string.action_reset)) }, + text = { Text(localize(MR.strings.action_reset)) }, onClick = { onResetToDefault() closeMenu() @@ -136,17 +136,17 @@ private fun ColumnScope.FilterPage( onScanlatorFilterClicked: (() -> Unit), ) { TriStateItem( - label = stringResource(R.string.label_downloaded), + label = localize(MR.strings.label_downloaded), state = downloadFilter, onClick = onDownloadFilterChanged, ) TriStateItem( - label = stringResource(R.string.action_filter_unread), + label = localize(MR.strings.action_filter_unread), state = unreadFilter, onClick = onUnreadFilterChanged, ) TriStateItem( - label = stringResource(R.string.action_filter_bookmarked), + label = localize(MR.strings.action_filter_bookmarked), state = bookmarkedFilter, onClick = onBookmarkedFilterChanged, ) @@ -179,7 +179,7 @@ fun ScanlatorFilterItem( }, ) Text( - text = stringResource(R.string.scanlator), + text = localize(MR.strings.scanlator), style = MaterialTheme.typography.bodyMedium, ) } @@ -192,13 +192,13 @@ private fun ColumnScope.SortPage( onItemSelected: (Long) -> Unit, ) { listOf( - R.string.sort_by_source to Manga.CHAPTER_SORTING_SOURCE, - R.string.sort_by_number to Manga.CHAPTER_SORTING_NUMBER, - R.string.sort_by_upload_date to Manga.CHAPTER_SORTING_UPLOAD_DATE, - R.string.action_sort_alpha to Manga.CHAPTER_SORTING_ALPHABET, + MR.strings.sort_by_source to Manga.CHAPTER_SORTING_SOURCE, + MR.strings.sort_by_number to Manga.CHAPTER_SORTING_NUMBER, + MR.strings.sort_by_upload_date to Manga.CHAPTER_SORTING_UPLOAD_DATE, + MR.strings.action_sort_alpha to Manga.CHAPTER_SORTING_ALPHABET, ).map { (titleRes, mode) -> SortItem( - label = stringResource(titleRes), + label = localize(titleRes), sortDescending = sortDescending.takeIf { sortingMode == mode }, onClick = { onItemSelected(mode) }, ) @@ -211,11 +211,11 @@ private fun ColumnScope.DisplayPage( onItemSelected: (Long) -> Unit, ) { listOf( - R.string.show_title to Manga.CHAPTER_DISPLAY_NAME, - R.string.show_chapter_number to Manga.CHAPTER_DISPLAY_NUMBER, + MR.strings.show_title to Manga.CHAPTER_DISPLAY_NAME, + MR.strings.show_chapter_number to Manga.CHAPTER_DISPLAY_NUMBER, ).map { (titleRes, mode) -> RadioItem( - label = stringResource(titleRes), + label = localize(titleRes), selected = displayMode == mode, onClick = { onItemSelected(mode) }, ) @@ -231,15 +231,15 @@ private fun SetAsDefaultDialog( AlertDialog( onDismissRequest = onDismissRequest, - title = { Text(text = stringResource(R.string.chapter_settings)) }, + title = { Text(text = localize(MR.strings.chapter_settings)) }, text = { Column( verticalArrangement = Arrangement.spacedBy(12.dp), ) { - Text(text = stringResource(R.string.confirm_set_chapter_settings)) + Text(text = localize(MR.strings.confirm_set_chapter_settings)) LabeledCheckbox( - label = stringResource(R.string.also_set_chapter_settings_for_library), + label = localize(MR.strings.also_set_chapter_settings_for_library), checked = optionalChecked, onCheckedChange = { optionalChecked = it }, ) @@ -247,7 +247,7 @@ private fun SetAsDefaultDialog( }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, confirmButton = { @@ -257,7 +257,7 @@ private fun SetAsDefaultDialog( onDismissRequest() }, ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, ) diff --git a/app/src/main/java/eu/kanade/presentation/manga/DuplicateMangaDialog.kt b/app/src/main/java/eu/kanade/presentation/manga/DuplicateMangaDialog.kt index 8552364993..afb8458334 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/DuplicateMangaDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/DuplicateMangaDialog.kt @@ -8,9 +8,9 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize @Composable fun DuplicateMangaDialog( @@ -21,10 +21,10 @@ fun DuplicateMangaDialog( AlertDialog( onDismissRequest = onDismissRequest, title = { - Text(text = stringResource(R.string.are_you_sure)) + Text(text = localize(MR.strings.are_you_sure)) }, text = { - Text(text = stringResource(R.string.confirm_add_duplicate_manga)) + Text(text = localize(MR.strings.confirm_add_duplicate_manga)) }, confirmButton = { FlowRow( @@ -36,13 +36,13 @@ fun DuplicateMangaDialog( onOpenManga() }, ) { - Text(text = stringResource(R.string.action_show_manga)) + Text(text = localize(MR.strings.action_show_manga)) } Spacer(modifier = Modifier.weight(1f)) TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } TextButton( onClick = { @@ -50,7 +50,7 @@ fun DuplicateMangaDialog( onConfirm() }, ) { - Text(text = stringResource(R.string.action_add)) + Text(text = localize(MR.strings.action_add)) } } }, diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt index 6d5ebc39eb..7b52f39317 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt @@ -44,7 +44,6 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.res.stringResource import androidx.compose.ui.util.fastAll import androidx.compose.ui.util.fastAny import androidx.compose.ui.util.fastMap @@ -58,7 +57,6 @@ import eu.kanade.presentation.manga.components.MangaInfoBox import eu.kanade.presentation.manga.components.MangaToolbar import eu.kanade.presentation.manga.components.MissingChapterCountListItem import eu.kanade.presentation.util.formatChapterNumber -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.source.getNameForMangaInfo import eu.kanade.tachiyomi.ui.manga.ChapterList @@ -70,11 +68,13 @@ import tachiyomi.domain.chapter.service.missingChaptersCount import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.source.model.StubSource +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.TwoPanelBox import tachiyomi.presentation.core.components.VerticalFastScroller import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton import tachiyomi.presentation.core.components.material.PullRefresh import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.isScrolledToEnd import tachiyomi.presentation.core.util.isScrollingUp import java.text.DateFormat @@ -349,7 +349,7 @@ private fun MangaScreenSmallImpl( val isReading = remember(state.chapters) { state.chapters.fastAny { it.chapter.read } } - Text(text = stringResource(if (isReading) R.string.action_resume else R.string.action_start)) + Text(text = localize(if (isReading) MR.strings.action_resume else MR.strings.action_start)) }, icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) }, onClick = onContinueReading, @@ -608,7 +608,7 @@ fun MangaScreenLargeImpl( state.chapters.fastAny { it.chapter.read } } Text( - text = stringResource(if (isReading) R.string.action_resume else R.string.action_start), + text = localize(if (isReading) MR.strings.action_resume else MR.strings.action_start), ) }, icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) }, @@ -787,8 +787,8 @@ private fun LazyListScope.sharedChapterItems( is ChapterList.Item -> { MangaChapterListItem( title = if (manga.displayMode == Manga.CHAPTER_DISPLAY_NUMBER) { - stringResource( - R.string.display_mode_chapter, + localize( + MR.strings.display_mode_chapter, formatChapterNumber(item.chapter.chapterNumber), ) } else { @@ -806,8 +806,8 @@ private fun LazyListScope.sharedChapterItems( readProgress = item.chapter.lastPageRead .takeIf { !item.chapter.read && it > 0L } ?.let { - stringResource( - R.string.chapter_progress, + localize( + MR.strings.chapter_progress, it + 1, ) }, diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/ChapterDownloadIndicator.kt b/app/src/main/java/eu/kanade/presentation/manga/components/ChapterDownloadIndicator.kt index ce9fb64bf6..9d7eab2631 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/ChapterDownloadIndicator.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/ChapterDownloadIndicator.kt @@ -29,13 +29,14 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp import eu.kanade.presentation.components.DropdownMenu import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.model.Download +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.IconButtonTokens +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.secondaryItemAlpha enum class ChapterDownloadAction { @@ -98,7 +99,7 @@ private fun NotDownloadedIndicator( ) { Icon( painter = painterResource(R.drawable.ic_download_chapter_24dp), - contentDescription = stringResource(R.string.manga_download), + contentDescription = localize(MR.strings.manga_download), modifier = Modifier.size(IndicatorSize), tint = MaterialTheme.colorScheme.onSurfaceVariant, ) @@ -156,14 +157,14 @@ private fun DownloadingIndicator( } DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) { DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_start_downloading_now)) }, + text = { Text(text = localize(MR.strings.action_start_downloading_now)) }, onClick = { onClick(ChapterDownloadAction.START_NOW) isMenuExpanded = false }, ) DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_cancel)) }, + text = { Text(text = localize(MR.strings.action_cancel)) }, onClick = { onClick(ChapterDownloadAction.CANCEL) isMenuExpanded = false @@ -204,7 +205,7 @@ private fun DownloadedIndicator( ) DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) { DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_delete)) }, + text = { Text(text = localize(MR.strings.action_delete)) }, onClick = { onClick(ChapterDownloadAction.DELETE) isMenuExpanded = false @@ -232,7 +233,7 @@ private fun ErrorIndicator( ) { Icon( imageVector = Icons.Outlined.ErrorOutline, - contentDescription = stringResource(R.string.chapter_error), + contentDescription = localize(MR.strings.chapter_error), modifier = Modifier.size(IndicatorSize), tint = MaterialTheme.colorScheme.error, ) diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/ChapterHeader.kt b/app/src/main/java/eu/kanade/presentation/manga/components/ChapterHeader.kt index e047fb0367..ef7d5a9231 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/ChapterHeader.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/ChapterHeader.kt @@ -9,12 +9,12 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.pluralStringResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.SecondaryItemAlpha +import tachiyomi.presentation.core.i18n.localize +import tachiyomi.presentation.core.i18n.localizePlural @Composable fun ChapterHeader( @@ -35,9 +35,9 @@ fun ChapterHeader( ) { Text( text = if (chapterCount == null) { - stringResource(R.string.chapters) + localize(MR.strings.chapters) } else { - pluralStringResource(id = R.plurals.manga_num_chapters, count = chapterCount, chapterCount) + localizePlural(MR.plurals.manga_num_chapters, count = chapterCount, chapterCount) }, style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.onBackground, @@ -54,7 +54,7 @@ private fun MissingChaptersWarning(count: Int) { } Text( - text = pluralStringResource(id = R.plurals.missing_chapters, count = count, count), + text = localizePlural(MR.plurals.missing_chapters, count = count, count), maxLines = 1, overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.bodySmall, diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaBottomActionMenu.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaBottomActionMenu.kt index 6f31d5a1f1..6ced3000bf 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaBottomActionMenu.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaBottomActionMenu.kt @@ -48,7 +48,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback -import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -59,6 +58,8 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import kotlin.time.Duration.Companion.seconds @Composable @@ -107,7 +108,7 @@ fun MangaBottomActionMenu( ) { if (onBookmarkClicked != null) { Button( - title = stringResource(R.string.action_bookmark), + title = localize(MR.strings.action_bookmark), icon = Icons.Outlined.BookmarkAdd, toConfirm = confirm[0], onLongClick = { onLongClickItem(0) }, @@ -116,7 +117,7 @@ fun MangaBottomActionMenu( } if (onRemoveBookmarkClicked != null) { Button( - title = stringResource(R.string.action_remove_bookmark), + title = localize(MR.strings.action_remove_bookmark), icon = Icons.Outlined.BookmarkRemove, toConfirm = confirm[1], onLongClick = { onLongClickItem(1) }, @@ -125,7 +126,7 @@ fun MangaBottomActionMenu( } if (onMarkAsReadClicked != null) { Button( - title = stringResource(R.string.action_mark_as_read), + title = localize(MR.strings.action_mark_as_read), icon = Icons.Outlined.DoneAll, toConfirm = confirm[2], onLongClick = { onLongClickItem(2) }, @@ -134,7 +135,7 @@ fun MangaBottomActionMenu( } if (onMarkAsUnreadClicked != null) { Button( - title = stringResource(R.string.action_mark_as_unread), + title = localize(MR.strings.action_mark_as_unread), icon = Icons.Outlined.RemoveDone, toConfirm = confirm[3], onLongClick = { onLongClickItem(3) }, @@ -143,7 +144,7 @@ fun MangaBottomActionMenu( } if (onMarkPreviousAsReadClicked != null) { Button( - title = stringResource(R.string.action_mark_previous_as_read), + title = localize(MR.strings.action_mark_previous_as_read), icon = ImageVector.vectorResource(R.drawable.ic_done_prev_24dp), toConfirm = confirm[4], onLongClick = { onLongClickItem(4) }, @@ -152,7 +153,7 @@ fun MangaBottomActionMenu( } if (onDownloadClicked != null) { Button( - title = stringResource(R.string.action_download), + title = localize(MR.strings.action_download), icon = Icons.Outlined.Download, toConfirm = confirm[5], onLongClick = { onLongClickItem(5) }, @@ -161,7 +162,7 @@ fun MangaBottomActionMenu( } if (onDeleteClicked != null) { Button( - title = stringResource(R.string.action_delete), + title = localize(MR.strings.action_delete), icon = Icons.Outlined.Delete, toConfirm = confirm[6], onLongClick = { onLongClickItem(6) }, @@ -258,21 +259,21 @@ fun LibraryBottomActionMenu( .padding(horizontal = 8.dp, vertical = 12.dp), ) { Button( - title = stringResource(R.string.action_move_category), + title = localize(MR.strings.action_move_category), icon = Icons.AutoMirrored.Outlined.Label, toConfirm = confirm[0], onLongClick = { onLongClickItem(0) }, onClick = onChangeCategoryClicked, ) Button( - title = stringResource(R.string.action_mark_as_read), + title = localize(MR.strings.action_mark_as_read), icon = Icons.Outlined.DoneAll, toConfirm = confirm[1], onLongClick = { onLongClickItem(1) }, onClick = onMarkAsReadClicked, ) Button( - title = stringResource(R.string.action_mark_as_unread), + title = localize(MR.strings.action_mark_as_unread), icon = Icons.Outlined.RemoveDone, toConfirm = confirm[2], onLongClick = { onLongClickItem(2) }, @@ -281,7 +282,7 @@ fun LibraryBottomActionMenu( if (onDownloadClicked != null) { var downloadExpanded by remember { mutableStateOf(false) } Button( - title = stringResource(R.string.action_download), + title = localize(MR.strings.action_download), icon = Icons.Outlined.Download, toConfirm = confirm[3], onLongClick = { onLongClickItem(3) }, @@ -296,7 +297,7 @@ fun LibraryBottomActionMenu( } } Button( - title = stringResource(R.string.action_delete), + title = localize(MR.strings.action_delete), icon = Icons.Outlined.Delete, toConfirm = confirm[4], onLongClick = { onLongClickItem(4) }, diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaChapterListItem.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaChapterListItem.kt index 1fb0abb52d..ba63a94080 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaChapterListItem.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaChapterListItem.kt @@ -42,23 +42,22 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalViewConfiguration import androidx.compose.ui.platform.ViewConfiguration -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.model.Download import me.saket.swipe.SwipeableActionsBox import me.saket.swipe.rememberSwipeableActionsState import tachiyomi.domain.library.service.LibraryPreferences +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.ReadItemAlpha import tachiyomi.presentation.core.components.material.SecondaryItemAlpha +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.selectedBackground import kotlin.math.absoluteValue @Composable fun MangaChapterListItem( - modifier: Modifier = Modifier, title: String, date: String?, readProgress: String?, @@ -75,6 +74,7 @@ fun MangaChapterListItem( onClick: () -> Unit, onDownloadClick: ((ChapterDownloadAction) -> Unit)?, onChapterSwipe: (LibraryPreferences.ChapterSwipeAction) -> Unit, + modifier: Modifier = Modifier, ) { val haptic = LocalHapticFeedback.current val density = LocalDensity.current @@ -143,7 +143,7 @@ fun MangaChapterListItem( if (!read) { Icon( imageVector = Icons.Filled.Circle, - contentDescription = stringResource(R.string.unread), + contentDescription = localize(MR.strings.unread), modifier = Modifier .height(8.dp) .padding(end = 4.dp), @@ -153,7 +153,7 @@ fun MangaChapterListItem( if (bookmark) { Icon( imageVector = Icons.Filled.Bookmark, - contentDescription = stringResource(R.string.action_filter_bookmarked), + contentDescription = localize(MR.strings.action_filter_bookmarked), modifier = Modifier .sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }), tint = MaterialTheme.colorScheme.primary, diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaCoverDialog.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaCoverDialog.kt index e8f7a77140..0dc88296c9 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaCoverDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaCoverDialog.kt @@ -32,7 +32,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView @@ -47,11 +46,12 @@ import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.DropdownMenu import eu.kanade.presentation.manga.EditCoverAction -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView import kotlinx.collections.immutable.persistentListOf import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.clickableNoIndication @Composable @@ -85,7 +85,7 @@ fun MangaCoverDialog( IconButton(onClick = onDismissRequest) { Icon( imageVector = Icons.Outlined.Close, - contentDescription = stringResource(R.string.action_close), + contentDescription = localize(MR.strings.action_close), ) } } @@ -94,12 +94,12 @@ fun MangaCoverDialog( AppBarActions( actions = persistentListOf( AppBar.Action( - title = stringResource(R.string.action_share), + title = localize(MR.strings.action_share), icon = Icons.Outlined.Share, onClick = onShareClick, ), AppBar.Action( - title = stringResource(R.string.action_save), + title = localize(MR.strings.action_save), icon = Icons.Outlined.Save, onClick = onSaveClick, ), @@ -119,7 +119,7 @@ fun MangaCoverDialog( ) { Icon( imageVector = Icons.Outlined.Edit, - contentDescription = stringResource(R.string.action_edit_cover), + contentDescription = localize(MR.strings.action_edit_cover), ) } DropdownMenu( @@ -128,14 +128,14 @@ fun MangaCoverDialog( offset = DpOffset(8.dp, 0.dp), ) { DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_edit)) }, + text = { Text(text = localize(MR.strings.action_edit)) }, onClick = { onEditClick(EditCoverAction.EDIT) expanded = false }, ) DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_delete)) }, + text = { Text(text = localize(MR.strings.action_delete)) }, onClick = { onEditClick(EditCoverAction.DELETE) expanded = false diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaDialogs.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaDialogs.kt index 30817579c0..d6d2ede8d2 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaDialogs.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaDialogs.kt @@ -12,13 +12,13 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp -import eu.kanade.tachiyomi.R import kotlinx.collections.immutable.toImmutableList import tachiyomi.domain.manga.interactor.FetchInterval +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.WheelTextPicker +import tachiyomi.presentation.core.i18n.localize @Composable fun DeleteChaptersDialog( @@ -29,7 +29,7 @@ fun DeleteChaptersDialog( onDismissRequest = onDismissRequest, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, confirmButton = { @@ -39,14 +39,14 @@ fun DeleteChaptersDialog( onConfirm() }, ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, title = { - Text(text = stringResource(R.string.are_you_sure)) + Text(text = localize(MR.strings.are_you_sure)) }, text = { - Text(text = stringResource(R.string.confirm_delete_chapters)) + Text(text = localize(MR.strings.confirm_delete_chapters)) }, ) } @@ -61,7 +61,7 @@ fun SetIntervalDialog( AlertDialog( onDismissRequest = onDismissRequest, - title = { Text(text = stringResource(R.string.manga_modify_calculated_interval_title)) }, + title = { Text(text = localize(MR.strings.manga_modify_calculated_interval_title)) }, text = { BoxWithConstraints( modifier = Modifier.fillMaxWidth(), @@ -71,7 +71,7 @@ fun SetIntervalDialog( val items = (0..FetchInterval.MAX_INTERVAL) .map { if (it == 0) { - stringResource(R.string.label_default) + localize(MR.strings.label_default) } else { it.toString() } @@ -87,7 +87,7 @@ fun SetIntervalDialog( }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, confirmButton = { @@ -95,7 +95,7 @@ fun SetIntervalDialog( onValueChanged(selectedInterval) onDismissRequest() }) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, ) diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt index cbe3f9b28a..8d19564680 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt @@ -66,8 +66,6 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.Layout import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.pluralStringResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Constraints @@ -80,8 +78,11 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.util.system.copyToClipboard import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.TextButton import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize +import tachiyomi.presentation.core.i18n.localizePlural import tachiyomi.presentation.core.util.clickableNoIndication import tachiyomi.presentation.core.util.secondaryItemAlpha import kotlin.math.absoluteValue @@ -178,9 +179,9 @@ fun MangaActionRow( Row(modifier = modifier.padding(start = 16.dp, top = 8.dp, end = 16.dp)) { MangaActionButton( title = if (favorite) { - stringResource(R.string.in_library) + localize(MR.strings.in_library) } else { - stringResource(R.string.add_to_library) + localize(MR.strings.add_to_library) }, icon = if (favorite) Icons.Filled.Favorite else Icons.Outlined.FavoriteBorder, color = if (favorite) MaterialTheme.colorScheme.primary else defaultActionButtonColor, @@ -189,8 +190,8 @@ fun MangaActionRow( ) if (onEditIntervalClicked != null && fetchInterval != null) { MangaActionButton( - title = pluralStringResource( - id = R.plurals.day, + title = localizePlural( + MR.plurals.day, count = fetchInterval.absoluteValue, fetchInterval.absoluteValue, ), @@ -202,9 +203,9 @@ fun MangaActionRow( if (onTrackingClicked != null) { MangaActionButton( title = if (trackingCount == 0) { - stringResource(R.string.manga_tracking_tab) + localize(MR.strings.manga_tracking_tab) } else { - pluralStringResource(id = R.plurals.num_trackers, count = trackingCount, trackingCount) + localizePlural(MR.plurals.num_trackers, count = trackingCount, trackingCount) }, icon = if (trackingCount == 0) Icons.Outlined.Sync else Icons.Outlined.Done, color = if (trackingCount == 0) defaultActionButtonColor else MaterialTheme.colorScheme.primary, @@ -213,7 +214,7 @@ fun MangaActionRow( } if (onWebViewClicked != null) { MangaActionButton( - title = stringResource(R.string.action_web_view), + title = localize(MR.strings.action_web_view), icon = Icons.Outlined.Public, color = defaultActionButtonColor, onClick = onWebViewClicked, @@ -237,7 +238,7 @@ fun ExpandableMangaDescription( mutableStateOf(defaultExpandState) } val desc = - description.takeIf { !it.isNullOrBlank() } ?: stringResource(R.string.description_placeholder) + description.takeIf { !it.isNullOrBlank() } ?: localize(MR.strings.description_placeholder) val trimmedDescription = remember(desc) { desc .replace(whitespaceLineRegex, "\n") @@ -267,14 +268,14 @@ fun ExpandableMangaDescription( onDismissRequest = { showMenu = false }, ) { DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_search)) }, + text = { Text(text = localize(MR.strings.action_search)) }, onClick = { onTagSearch(tagSelected) showMenu = false }, ) DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_copy_to_clipboard)) }, + text = { Text(text = localize(MR.strings.action_copy_to_clipboard)) }, onClick = { onCopyTagToClipboard(tagSelected) showMenu = false @@ -341,7 +342,7 @@ private fun MangaAndSourceTitlesLarge( MangaCover.Book( modifier = Modifier.fillMaxWidth(0.65f), data = coverDataProvider(), - contentDescription = stringResource(R.string.manga_cover), + contentDescription = localize(MR.strings.manga_cover), onClick = onCoverClick, ) Spacer(modifier = Modifier.height(16.dp)) @@ -383,7 +384,7 @@ private fun MangaAndSourceTitlesSmall( .sizeIn(maxWidth = 100.dp) .align(Alignment.Top), data = coverDataProvider(), - contentDescription = stringResource(R.string.manga_cover), + contentDescription = localize(MR.strings.manga_cover), onClick = onCoverClick, ) Column( @@ -415,7 +416,7 @@ private fun MangaContentInfo( ) { val context = LocalContext.current Text( - text = title.ifBlank { stringResource(R.string.unknown_title) }, + text = title.ifBlank { localize(MR.strings.unknown_title) }, style = MaterialTheme.typography.titleLarge, modifier = Modifier.clickableNoIndication( onLongClick = { @@ -445,7 +446,7 @@ private fun MangaContentInfo( ) Text( text = author?.takeIf { it.isNotBlank() } - ?: stringResource(R.string.unknown_author), + ?: localize(MR.strings.unknown_author), style = MaterialTheme.typography.titleSmall, modifier = Modifier .clickableNoIndication( @@ -511,13 +512,13 @@ private fun MangaContentInfo( ProvideTextStyle(MaterialTheme.typography.bodyMedium) { Text( text = when (status) { - SManga.ONGOING.toLong() -> stringResource(R.string.ongoing) - SManga.COMPLETED.toLong() -> stringResource(R.string.completed) - SManga.LICENSED.toLong() -> stringResource(R.string.licensed) - SManga.PUBLISHING_FINISHED.toLong() -> stringResource(R.string.publishing_finished) - SManga.CANCELLED.toLong() -> stringResource(R.string.cancelled) - SManga.ON_HIATUS.toLong() -> stringResource(R.string.on_hiatus) - else -> stringResource(R.string.unknown) + SManga.ONGOING.toLong() -> localize(MR.strings.ongoing) + SManga.COMPLETED.toLong() -> localize(MR.strings.completed) + SManga.LICENSED.toLong() -> localize(MR.strings.licensed) + SManga.PUBLISHING_FINISHED.toLong() -> localize(MR.strings.publishing_finished) + SManga.CANCELLED.toLong() -> localize(MR.strings.cancelled) + SManga.ON_HIATUS.toLong() -> localize(MR.strings.on_hiatus) + else -> localize(MR.strings.unknown) }, overflow = TextOverflow.Ellipsis, maxLines = 1, @@ -591,8 +592,8 @@ private fun MangaSummary( val image = AnimatedImageVector.animatedVectorResource(R.drawable.anim_caret_down) Icon( painter = rememberAnimatedVectorPainter(image, !expanded), - contentDescription = stringResource( - if (expanded) R.string.manga_info_collapse else R.string.manga_info_expand, + contentDescription = localize( + if (expanded) MR.strings.manga_info_collapse else MR.strings.manga_info_expand, ), tint = MaterialTheme.colorScheme.onBackground, modifier = Modifier.background(Brush.radialGradient(colors = colors.asReversed())), diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt index 3b55c595c9..36631d3158 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt @@ -21,7 +21,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import eu.kanade.presentation.components.AppBar @@ -29,8 +28,9 @@ import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.DownloadDropdownMenu import eu.kanade.presentation.components.UpIcon import eu.kanade.presentation.manga.DownloadAction -import eu.kanade.tachiyomi.R import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.theme.active @Composable @@ -75,12 +75,12 @@ fun MangaToolbar( AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.action_select_all), + title = localize(MR.strings.action_select_all), icon = Icons.Outlined.SelectAll, onClick = onSelectAll, ), AppBar.Action( - title = stringResource(R.string.action_select_inverse), + title = localize(MR.strings.action_select_inverse), icon = Icons.Outlined.FlipToBack, onClick = onInvertSelection, ), @@ -104,7 +104,7 @@ fun MangaToolbar( if (onClickDownload != null) { add( AppBar.Action( - title = stringResource(R.string.manga_download), + title = localize(MR.strings.manga_download), icon = Icons.Outlined.Download, onClick = { downloadExpanded = !downloadExpanded }, ), @@ -112,7 +112,7 @@ fun MangaToolbar( } add( AppBar.Action( - title = stringResource(R.string.action_filter), + title = localize(MR.strings.action_filter), icon = Icons.Outlined.FilterList, iconTint = filterTint, onClick = onClickFilter, @@ -120,14 +120,14 @@ fun MangaToolbar( ) add( AppBar.OverflowAction( - title = stringResource(R.string.action_webview_refresh), + title = localize(MR.strings.action_webview_refresh), onClick = onClickRefresh, ), ) if (onClickEditCategory != null) { add( AppBar.OverflowAction( - title = stringResource(R.string.action_edit_categories), + title = localize(MR.strings.action_edit_categories), onClick = onClickEditCategory, ), ) @@ -135,7 +135,7 @@ fun MangaToolbar( if (onClickMigrate != null) { add( AppBar.OverflowAction( - title = stringResource(R.string.action_migrate), + title = localize(MR.strings.action_migrate), onClick = onClickMigrate, ), ) @@ -143,7 +143,7 @@ fun MangaToolbar( if (onClickShare != null) { add( AppBar.OverflowAction( - title = stringResource(R.string.action_share), + title = localize(MR.strings.action_share), onClick = onClickShare, ), ) diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MissingChapterCountListItem.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MissingChapterCountListItem.kt index deebaf8e33..557b051a51 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MissingChapterCountListItem.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MissingChapterCountListItem.kt @@ -10,11 +10,11 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localizePlural import tachiyomi.presentation.core.util.secondaryItemAlpha @Composable @@ -34,7 +34,7 @@ fun MissingChapterCountListItem( ) { HorizontalDivider(modifier = Modifier.weight(1f)) Text( - text = pluralStringResource(id = R.plurals.missing_chapters, count = count, count), + text = localizePlural(MR.plurals.missing_chapters, count = count, count), style = MaterialTheme.typography.labelMedium, ) HorizontalDivider(modifier = Modifier.weight(1f)) diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/ScanlatorFilterDialog.kt b/app/src/main/java/eu/kanade/presentation/manga/components/ScanlatorFilterDialog.kt index dd19e13611..b5500b3e87 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/ScanlatorFilterDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/ScanlatorFilterDialog.kt @@ -27,12 +27,12 @@ import androidx.compose.runtime.toMutableStateList import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.TextButton import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.isScrolledToEnd import tachiyomi.presentation.core.util.isScrolledToStart @@ -49,10 +49,10 @@ fun ScanlatorFilterDialog( val mutableExcludedScanlators = remember(excludedScanlators) { excludedScanlators.toMutableStateList() } AlertDialog( onDismissRequest = onDismissRequest, - title = { Text(text = stringResource(R.string.exclude_scanlators)) }, + title = { Text(text = localize(MR.strings.exclude_scanlators)) }, text = textFunc@{ if (sortedAvailableScanlators.isEmpty()) { - Text(text = stringResource(R.string.no_scanlators_found)) + Text(text = localize(MR.strings.no_scanlators_found)) return@textFunc } Box { @@ -108,16 +108,16 @@ fun ScanlatorFilterDialog( confirmButton = { if (sortedAvailableScanlators.isEmpty()) { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } } else { FlowRow { TextButton(onClick = mutableExcludedScanlators::clear) { - Text(text = stringResource(R.string.action_reset)) + Text(text = localize(MR.strings.action_reset)) } Spacer(modifier = Modifier.weight(1f)) TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } TextButton( onClick = { @@ -125,7 +125,7 @@ fun ScanlatorFilterDialog( onDismissRequest() }, ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } } } diff --git a/app/src/main/java/eu/kanade/presentation/more/MoreScreen.kt b/app/src/main/java/eu/kanade/presentation/more/MoreScreen.kt index bbc6833719..08bedc3e90 100644 --- a/app/src/main/java/eu/kanade/presentation/more/MoreScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/MoreScreen.kt @@ -13,9 +13,7 @@ import androidx.compose.material.icons.automirrored.outlined.HelpOutline import androidx.compose.material.icons.automirrored.outlined.Label import androidx.compose.material.icons.outlined.CloudOff import androidx.compose.material.icons.outlined.GetApp -import androidx.compose.material.icons.outlined.HelpOutline import androidx.compose.material.icons.outlined.Info -import androidx.compose.material.icons.outlined.Label import androidx.compose.material.icons.outlined.QueryStats import androidx.compose.material.icons.outlined.Settings import androidx.compose.material.icons.outlined.Storage @@ -24,8 +22,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.pluralStringResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import eu.kanade.presentation.components.WarningBanner import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget @@ -33,8 +29,11 @@ import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.more.DownloadQueueState import tachiyomi.core.Constants +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize +import tachiyomi.presentation.core.i18n.localizePlural @Composable fun MoreScreen( @@ -62,7 +61,7 @@ fun MoreScreen( ) { if (isFDroid) { WarningBanner( - textRes = R.string.fdroid_warning, + textRes = MR.strings.fdroid_warning, modifier = Modifier.clickable { uriHandler.openUri( "https://tachiyomi.org/docs/faq/general#how-do-i-update-from-the-f-droid-builds", @@ -81,8 +80,8 @@ fun MoreScreen( } item { SwitchPreferenceWidget( - title = stringResource(R.string.label_downloaded_only), - subtitle = stringResource(R.string.downloaded_only_summary), + title = localize(MR.strings.label_downloaded_only), + subtitle = localize(MR.strings.downloaded_only_summary), icon = Icons.Outlined.CloudOff, checked = downloadedOnly, onCheckedChanged = onDownloadedOnlyChange, @@ -90,8 +89,8 @@ fun MoreScreen( } item { SwitchPreferenceWidget( - title = stringResource(R.string.pref_incognito_mode), - subtitle = stringResource(R.string.pref_incognito_mode_summary), + title = localize(MR.strings.pref_incognito_mode), + subtitle = localize(MR.strings.pref_incognito_mode_summary), icon = ImageVector.vectorResource(R.drawable.ic_glasses_24dp), checked = incognitoMode, onCheckedChanged = onIncognitoModeChange, @@ -103,17 +102,17 @@ fun MoreScreen( item { val downloadQueueState = downloadQueueStateProvider() TextPreferenceWidget( - title = stringResource(R.string.label_download_queue), + title = localize(MR.strings.label_download_queue), subtitle = when (downloadQueueState) { DownloadQueueState.Stopped -> null is DownloadQueueState.Paused -> { val pending = downloadQueueState.pending if (pending == 0) { - stringResource(R.string.paused) + localize(MR.strings.paused) } else { - "${stringResource(R.string.paused)} • ${ - pluralStringResource( - id = R.plurals.download_queue_summary, + "${localize(MR.strings.paused)} • ${ + localizePlural( + MR.plurals.download_queue_summary, count = pending, pending, ) @@ -122,7 +121,7 @@ fun MoreScreen( } is DownloadQueueState.Downloading -> { val pending = downloadQueueState.pending - pluralStringResource(id = R.plurals.download_queue_summary, count = pending, pending) + localizePlural(MR.plurals.download_queue_summary, count = pending, pending) } }, icon = Icons.Outlined.GetApp, @@ -131,21 +130,21 @@ fun MoreScreen( } item { TextPreferenceWidget( - title = stringResource(R.string.categories), + title = localize(MR.strings.categories), icon = Icons.AutoMirrored.Outlined.Label, onPreferenceClick = onClickCategories, ) } item { TextPreferenceWidget( - title = stringResource(R.string.label_stats), + title = localize(MR.strings.label_stats), icon = Icons.Outlined.QueryStats, onPreferenceClick = onClickStats, ) } item { TextPreferenceWidget( - title = stringResource(R.string.label_data_storage), + title = localize(MR.strings.label_data_storage), icon = Icons.Outlined.Storage, onPreferenceClick = onClickDataAndStorage, ) @@ -155,21 +154,21 @@ fun MoreScreen( item { TextPreferenceWidget( - title = stringResource(R.string.label_settings), + title = localize(MR.strings.label_settings), icon = Icons.Outlined.Settings, onPreferenceClick = onClickSettings, ) } item { TextPreferenceWidget( - title = stringResource(R.string.pref_category_about), + title = localize(MR.strings.pref_category_about), icon = Icons.Outlined.Info, onPreferenceClick = onClickAbout, ) } item { TextPreferenceWidget( - title = stringResource(R.string.label_help), + title = localize(MR.strings.label_help), icon = Icons.AutoMirrored.Outlined.HelpOutline, onPreferenceClick = { uriHandler.openUri(Constants.URL_HELP) }, ) diff --git a/app/src/main/java/eu/kanade/presentation/more/NewUpdateScreen.kt b/app/src/main/java/eu/kanade/presentation/more/NewUpdateScreen.kt index 887583c91f..ff584e2a94 100644 --- a/app/src/main/java/eu/kanade/presentation/more/NewUpdateScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/NewUpdateScreen.kt @@ -14,7 +14,6 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.tooling.preview.PreviewLightDark import com.halilibo.richtext.markdown.Markdown @@ -22,8 +21,9 @@ import com.halilibo.richtext.ui.RichTextStyle import com.halilibo.richtext.ui.material3.Material3RichText import com.halilibo.richtext.ui.string.RichTextStringStyle import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.InfoScreen @Composable @@ -36,11 +36,11 @@ fun NewUpdateScreen( ) { InfoScreen( icon = Icons.Outlined.NewReleases, - headingText = stringResource(R.string.update_check_notification_update_available), + headingText = localize(MR.strings.update_check_notification_update_available), subtitleText = versionName, - acceptText = stringResource(R.string.update_check_confirm), + acceptText = localize(MR.strings.update_check_confirm), onAcceptClick = onAcceptUpdate, - rejectText = stringResource(R.string.action_not_now), + rejectText = localize(MR.strings.action_not_now), onRejectClick = onRejectUpdate, ) { Material3RichText( @@ -59,7 +59,7 @@ fun NewUpdateScreen( onClick = onOpenInBrowser, modifier = Modifier.padding(top = MaterialTheme.padding.small), ) { - Text(text = stringResource(R.string.update_check_open)) + Text(text = localize(MR.strings.update_check_open)) Spacer(modifier = Modifier.width(MaterialTheme.padding.tiny)) Icon(imageVector = Icons.AutoMirrored.Outlined.OpenInNew, contentDescription = null) } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt b/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt index c852e03a3b..afb12287b9 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt @@ -3,9 +3,9 @@ package eu.kanade.presentation.more.settings import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.stringResource -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.track.Tracker +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import tachiyomi.core.preference.Preference as PreferenceData sealed class Preference { @@ -109,7 +109,7 @@ sealed class Preference { v.map { e[it] } .takeIf { it.isNotEmpty() } ?.joinToString() - } ?: stringResource(R.string.none) + } ?: localize(MR.strings.none) subtitle?.format(combined) }, override val icon: ImageVector? = null, diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceScaffold.kt b/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceScaffold.kt index 7db2933794..541dd6a532 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceScaffold.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceScaffold.kt @@ -1,15 +1,15 @@ package eu.kanade.presentation.more.settings -import androidx.annotation.StringRes import androidx.compose.foundation.layout.RowScope import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource +import dev.icerock.moko.resources.StringResource import eu.kanade.presentation.components.AppBar import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize @Composable fun PreferenceScaffold( - @StringRes titleRes: Int, + titleRes: StringResource, actions: @Composable RowScope.() -> Unit = {}, onBackPressed: (() -> Unit)? = null, itemsProvider: @Composable () -> List, @@ -17,7 +17,7 @@ fun PreferenceScaffold( Scaffold( topBar = { AppBar( - title = stringResource(titleRes), + title = localize(titleRes), navigateUp = onBackPressed, actions = actions, scrollBehavior = it, diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/Commons.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/Commons.kt index 44cc49ef2b..a5acb0fb18 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/Commons.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/Commons.kt @@ -3,10 +3,10 @@ package eu.kanade.presentation.more.settings.screen import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import eu.kanade.presentation.category.visualName -import eu.kanade.tachiyomi.R import tachiyomi.domain.category.model.Category +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize /** * Returns a string of categories name for settings subtitle @@ -34,15 +34,15 @@ fun getCategoriesLabel( includedCategories.isNotEmpty() && includedCategories.size != allCategories.size -> includedCategories.joinToString { it.visualName(context) } // All explicitly selected - includedCategories.size == allCategories.size -> stringResource(R.string.all) - allExcluded -> stringResource(R.string.none) - else -> stringResource(R.string.all) + includedCategories.size == allCategories.size -> localize(MR.strings.all) + allExcluded -> localize(MR.strings.none) + else -> localize(MR.strings.all) } val excludedItemsText = when { - excludedCategories.isEmpty() -> stringResource(R.string.none) - allExcluded -> stringResource(R.string.all) + excludedCategories.isEmpty() -> localize(MR.strings.none) + allExcluded -> localize(MR.strings.all) else -> excludedCategories.joinToString { it.visualName(context) } } - return stringResource(R.string.include, includedItemsText) + "\n" + - stringResource(R.string.exclude, excludedItemsText) + return localize(MR.strings.include, includedItemsText) + "\n" + + localize(MR.strings.exclude, excludedItemsText) } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SearchableSettings.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SearchableSettings.kt index 3ea1bdc64f..5652ace76c 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SearchableSettings.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SearchableSettings.kt @@ -1,10 +1,10 @@ package eu.kanade.presentation.more.settings.screen -import androidx.annotation.StringRes import androidx.compose.foundation.layout.RowScope import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import cafe.adriel.voyager.core.screen.Screen +import dev.icerock.moko.resources.StringResource import eu.kanade.presentation.more.settings.Preference import eu.kanade.presentation.more.settings.PreferenceScaffold import eu.kanade.presentation.util.LocalBackPress @@ -13,8 +13,7 @@ interface SearchableSettings : Screen { @Composable @ReadOnlyComposable - @StringRes - fun getTitleRes(): Int + fun getTitleRes(): StringResource @Composable fun getPreferences(): List diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt index 97d852e50f..c384b010b5 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt @@ -7,7 +7,6 @@ import android.os.Build import android.provider.Settings import android.webkit.WebStorage import android.webkit.WebView -import androidx.annotation.StringRes import androidx.compose.material3.AlertDialog import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -21,7 +20,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource import androidx.core.net.toUri import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow @@ -29,9 +27,8 @@ import eu.kanade.domain.base.BasePreferences import eu.kanade.presentation.more.settings.Preference import eu.kanade.presentation.more.settings.screen.advanced.ClearDatabaseScreen import eu.kanade.presentation.more.settings.screen.debug.DebugInfoScreen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.DownloadCache -import eu.kanade.tachiyomi.data.library.LibraryUpdateJob +import eu.kanade.tachiyomi.data.library.MetadataUpdateJob import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.network.PREF_DOH_360 @@ -60,6 +57,8 @@ import tachiyomi.core.util.lang.launchNonCancellable import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.manga.interactor.ResetViewerFlags +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -69,8 +68,7 @@ object SettingsAdvancedScreen : SearchableSettings { @ReadOnlyComposable @Composable - @StringRes - override fun getTitleRes() = R.string.pref_category_advanced + override fun getTitleRes() = MR.strings.pref_category_advanced @Composable override fun getPreferences(): List { @@ -86,13 +84,13 @@ object SettingsAdvancedScreen : SearchableSettings { listOf( Preference.PreferenceItem.SwitchPreference( pref = basePreferences.acraEnabled(), - title = stringResource(R.string.pref_enable_acra), - subtitle = stringResource(R.string.pref_acra_summary), + title = localize(MR.strings.pref_enable_acra), + subtitle = localize(MR.strings.pref_acra_summary), enabled = isPreviewBuildType || isReleaseBuildType, ), Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_dump_crash_logs), - subtitle = stringResource(R.string.pref_dump_crash_logs_summary), + title = localize(MR.strings.pref_dump_crash_logs), + subtitle = localize(MR.strings.pref_dump_crash_logs_summary), onClick = { scope.launch { CrashLogUtil(context).dumpLogs() @@ -101,15 +99,15 @@ object SettingsAdvancedScreen : SearchableSettings { ), Preference.PreferenceItem.SwitchPreference( pref = networkPreferences.verboseLogging(), - title = stringResource(R.string.pref_verbose_logging), - subtitle = stringResource(R.string.pref_verbose_logging_summary), + title = localize(MR.strings.pref_verbose_logging), + subtitle = localize(MR.strings.pref_verbose_logging_summary), onValueChanged = { - context.toast(R.string.requires_app_restart) + context.toast(MR.strings.requires_app_restart) true }, ), Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_debug_info), + title = localize(MR.strings.pref_debug_info), onClick = { navigator.push(DebugInfoScreen()) }, ), ), @@ -117,7 +115,7 @@ object SettingsAdvancedScreen : SearchableSettings { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { add( Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_manage_notifications), + title = localize(MR.strings.pref_manage_notifications), onClick = { val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) @@ -145,11 +143,11 @@ object SettingsAdvancedScreen : SearchableSettings { val uriHandler = LocalUriHandler.current return Preference.PreferenceGroup( - title = stringResource(R.string.label_background_activity), + title = localize(MR.strings.label_background_activity), preferenceItems = listOf( Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_disable_battery_optimization), - subtitle = stringResource(R.string.pref_disable_battery_optimization_summary), + title = localize(MR.strings.pref_disable_battery_optimization), + subtitle = localize(MR.strings.pref_disable_battery_optimization_summary), onClick = { val packageName: String = context.packageName if (!context.powerManager.isIgnoringBatteryOptimizations(packageName)) { @@ -162,16 +160,16 @@ object SettingsAdvancedScreen : SearchableSettings { } context.startActivity(intent) } catch (e: ActivityNotFoundException) { - context.toast(R.string.battery_optimization_setting_activity_not_found) + context.toast(MR.strings.battery_optimization_setting_activity_not_found) } } else { - context.toast(R.string.battery_optimization_disabled) + context.toast(MR.strings.battery_optimization_disabled) } }, ), Preference.PreferenceItem.TextPreference( title = "Don't kill my app!", - subtitle = stringResource(R.string.about_dont_kill_my_app), + subtitle = localize(MR.strings.about_dont_kill_my_app), onClick = { uriHandler.openUri("https://dontkillmyapp.com/") }, ), ), @@ -184,19 +182,19 @@ object SettingsAdvancedScreen : SearchableSettings { val navigator = LocalNavigator.currentOrThrow return Preference.PreferenceGroup( - title = stringResource(R.string.label_data), + title = localize(MR.strings.label_data), preferenceItems = listOf( Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_invalidate_download_cache), - subtitle = stringResource(R.string.pref_invalidate_download_cache_summary), + title = localize(MR.strings.pref_invalidate_download_cache), + subtitle = localize(MR.strings.pref_invalidate_download_cache_summary), onClick = { Injekt.get().invalidateCache() - context.toast(R.string.download_cache_invalidated) + context.toast(MR.strings.download_cache_invalidated) }, ), Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_clear_database), - subtitle = stringResource(R.string.pref_clear_database_summary), + title = localize(MR.strings.pref_clear_database), + subtitle = localize(MR.strings.pref_clear_database_summary), onClick = { navigator.push(ClearDatabaseScreen()) }, ), ), @@ -214,17 +212,17 @@ object SettingsAdvancedScreen : SearchableSettings { val userAgent by userAgentPref.collectAsState() return Preference.PreferenceGroup( - title = stringResource(R.string.label_network), + title = localize(MR.strings.label_network), preferenceItems = listOf( Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_clear_cookies), + title = localize(MR.strings.pref_clear_cookies), onClick = { networkHelper.cookieJar.removeAll() - context.toast(R.string.cookies_cleared) + context.toast(MR.strings.cookies_cleared) }, ), Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_clear_webview_data), + title = localize(MR.strings.pref_clear_webview_data), onClick = { try { WebView(context).run { @@ -236,18 +234,18 @@ object SettingsAdvancedScreen : SearchableSettings { } WebStorage.getInstance().deleteAllData() context.applicationInfo?.dataDir?.let { File("$it/app_webview/").deleteRecursively() } - context.toast(R.string.webview_data_deleted) + context.toast(MR.strings.webview_data_deleted) } catch (e: Throwable) { logcat(LogPriority.ERROR, e) - context.toast(R.string.cache_delete_error) + context.toast(MR.strings.cache_delete_error) } }, ), Preference.PreferenceItem.ListPreference( pref = networkPreferences.dohProvider(), - title = stringResource(R.string.pref_dns_over_https), + title = localize(MR.strings.pref_dns_over_https), entries = mapOf( - -1 to stringResource(R.string.disabled), + -1 to localize(MR.strings.disabled), PREF_DOH_CLOUDFLARE to "Cloudflare", PREF_DOH_GOOGLE to "Google", PREF_DOH_ADGUARD to "AdGuard", @@ -262,30 +260,30 @@ object SettingsAdvancedScreen : SearchableSettings { PREF_DOH_SHECAN to "Shecan", ), onValueChanged = { - context.toast(R.string.requires_app_restart) + context.toast(MR.strings.requires_app_restart) true }, ), Preference.PreferenceItem.EditTextPreference( pref = userAgentPref, - title = stringResource(R.string.pref_user_agent_string), + title = localize(MR.strings.pref_user_agent_string), onValueChanged = { try { // OkHttp checks for valid values internally Headers.Builder().add("User-Agent", it) } catch (_: IllegalArgumentException) { - context.toast(R.string.error_user_agent_string_invalid) + context.toast(MR.strings.error_user_agent_string_invalid) return@EditTextPreference false } true }, ), Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_reset_user_agent_string), + title = localize(MR.strings.pref_reset_user_agent_string), enabled = remember(userAgent) { userAgent != userAgentPref.defaultValue() }, onClick = { userAgentPref.delete() - context.toast(R.string.requires_app_restart) + context.toast(MR.strings.requires_app_restart) }, ), ), @@ -298,23 +296,23 @@ object SettingsAdvancedScreen : SearchableSettings { val context = LocalContext.current return Preference.PreferenceGroup( - title = stringResource(R.string.label_library), + title = localize(MR.strings.label_library), preferenceItems = listOf( Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_refresh_library_covers), - onClick = { LibraryUpdateJob.startNow(context, target = LibraryUpdateJob.Target.COVERS) }, + title = localize(MR.strings.pref_refresh_library_covers), + onClick = { MetadataUpdateJob.startNow(context) }, ), Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_reset_viewer_flags), - subtitle = stringResource(R.string.pref_reset_viewer_flags_summary), + title = localize(MR.strings.pref_reset_viewer_flags), + subtitle = localize(MR.strings.pref_reset_viewer_flags_summary), onClick = { scope.launchNonCancellable { val success = Injekt.get().await() withUIContext { val message = if (success) { - R.string.pref_reset_viewer_flags_success + MR.strings.pref_reset_viewer_flags_success } else { - R.string.pref_reset_viewer_flags_error + MR.strings.pref_reset_viewer_flags_error } context.toast(message) } @@ -338,11 +336,11 @@ object SettingsAdvancedScreen : SearchableSettings { val dismiss = { shizukuMissing = false } AlertDialog( onDismissRequest = dismiss, - title = { Text(text = stringResource(R.string.ext_installer_shizuku)) }, - text = { Text(text = stringResource(R.string.ext_installer_shizuku_unavailable_dialog)) }, + title = { Text(text = localize(MR.strings.ext_installer_shizuku)) }, + text = { Text(text = localize(MR.strings.ext_installer_shizuku_unavailable_dialog)) }, dismissButton = { TextButton(onClick = dismiss) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, confirmButton = { @@ -352,19 +350,19 @@ object SettingsAdvancedScreen : SearchableSettings { uriHandler.openUri("https://shizuku.rikka.app/download") }, ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, ) } return Preference.PreferenceGroup( - title = stringResource(R.string.label_extensions), + title = localize(MR.strings.label_extensions), preferenceItems = listOf( Preference.PreferenceItem.ListPreference( pref = extensionInstallerPref, - title = stringResource(R.string.ext_installer_pref), + title = localize(MR.strings.ext_installer_pref), entries = extensionInstallerPref.entries - .associateWith { stringResource(it.titleResId) }, + .associateWith { localize(it.titleRes) }, onValueChanged = { if (it == BasePreferences.ExtensionInstaller.SHIZUKU && !context.isShizukuInstalled diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAppearanceScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAppearanceScreen.kt index 4c7243a5cd..7875008ac5 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAppearanceScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAppearanceScreen.kt @@ -3,7 +3,6 @@ package eu.kanade.presentation.more.settings.screen import android.app.Activity import android.content.Context import android.os.Build -import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatDelegate import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -13,7 +12,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.core.app.ActivityCompat import androidx.core.os.LocaleListCompat import eu.kanade.domain.ui.UiPreferences @@ -29,6 +27,9 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.merge import org.xmlpull.v1.XmlPullParser +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -38,8 +39,7 @@ object SettingsAppearanceScreen : SearchableSettings { @ReadOnlyComposable @Composable - @StringRes - override fun getTitleRes() = R.string.pref_category_appearance + override fun getTitleRes() = MR.strings.pref_category_appearance @Composable override fun getPreferences(): List { @@ -76,26 +76,26 @@ object SettingsAppearanceScreen : SearchableSettings { } return Preference.PreferenceGroup( - title = stringResource(R.string.pref_category_theme), + title = localize(MR.strings.pref_category_theme), preferenceItems = listOf( Preference.PreferenceItem.ListPreference( pref = themeModePref, - title = stringResource(R.string.pref_theme_mode), + title = localize(MR.strings.pref_theme_mode), entries = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { mapOf( - ThemeMode.SYSTEM to stringResource(R.string.theme_system), - ThemeMode.LIGHT to stringResource(R.string.theme_light), - ThemeMode.DARK to stringResource(R.string.theme_dark), + ThemeMode.SYSTEM to localize(MR.strings.theme_system), + ThemeMode.LIGHT to localize(MR.strings.theme_light), + ThemeMode.DARK to localize(MR.strings.theme_dark), ) } else { mapOf( - ThemeMode.LIGHT to stringResource(R.string.theme_light), - ThemeMode.DARK to stringResource(R.string.theme_dark), + ThemeMode.LIGHT to localize(MR.strings.theme_light), + ThemeMode.DARK to localize(MR.strings.theme_dark), ) }, ), Preference.PreferenceItem.CustomPreference( - title = stringResource(R.string.pref_app_theme), + title = localize(MR.strings.pref_app_theme), ) { item -> val value by appThemePref.collectAsState() AppThemePreferenceWidget( @@ -107,7 +107,7 @@ object SettingsAppearanceScreen : SearchableSettings { }, Preference.PreferenceItem.SwitchPreference( pref = amoledPref, - title = stringResource(R.string.pref_dark_theme_pure_black), + title = localize(MR.strings.pref_dark_theme_pure_black), enabled = themeMode != ThemeMode.LIGHT, ), ), @@ -140,11 +140,11 @@ object SettingsAppearanceScreen : SearchableSettings { } return Preference.PreferenceGroup( - title = stringResource(R.string.pref_category_display), + title = localize(MR.strings.pref_category_display), preferenceItems = listOf( Preference.PreferenceItem.BasicListPreference( value = currentLanguage, - title = stringResource(R.string.pref_app_language), + title = localize(MR.strings.pref_app_language), entries = langs, onValueChanged = { newValue -> currentLanguage = newValue @@ -153,28 +153,28 @@ object SettingsAppearanceScreen : SearchableSettings { ), Preference.PreferenceItem.ListPreference( pref = uiPreferences.tabletUiMode(), - title = stringResource(R.string.pref_tablet_ui_mode), - entries = TabletUiMode.entries.associateWith { stringResource(it.titleResId) }, + title = localize(MR.strings.pref_tablet_ui_mode), + entries = TabletUiMode.entries.associateWith { localize(it.titleRes) }, onValueChanged = { - context.toast(R.string.requires_app_restart) + context.toast(MR.strings.requires_app_restart) true }, ), Preference.PreferenceItem.ListPreference( pref = uiPreferences.dateFormat(), - title = stringResource(R.string.pref_date_format), + title = localize(MR.strings.pref_date_format), entries = DateFormats .associateWith { val formattedDate = UiPreferences.dateFormat(it).format(now) - "${it.ifEmpty { stringResource(R.string.label_default) }} ($formattedDate)" + "${it.ifEmpty { localize(MR.strings.label_default) }} ($formattedDate)" }, ), Preference.PreferenceItem.SwitchPreference( pref = uiPreferences.relativeTime(), - title = stringResource(R.string.pref_relative_format), - subtitle = stringResource( - R.string.pref_relative_format_summary, - stringResource(R.string.relative_time_today), + title = localize(MR.strings.pref_relative_format), + subtitle = localize( + MR.strings.pref_relative_format_summary, + localize(MR.strings.relative_time_today), formattedNow, ), ), @@ -201,7 +201,7 @@ object SettingsAppearanceScreen : SearchableSettings { } langs.sortBy { it.second } - langs.add(0, Pair("", context.getString(R.string.label_default))) + langs.add(0, Pair("", context.localize(MR.strings.label_default))) return langs.toMap() } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt index 5b3ab28cf3..d5390ddb8d 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt @@ -1,16 +1,16 @@ package eu.kanade.presentation.more.settings.screen -import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.fragment.app.FragmentActivity import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.presentation.more.settings.Preference -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -18,8 +18,7 @@ object SettingsBrowseScreen : SearchableSettings { @ReadOnlyComposable @Composable - @StringRes - override fun getTitleRes() = R.string.browse + override fun getTitleRes() = MR.strings.browse @Composable override fun getPreferences(): List { @@ -27,28 +26,28 @@ object SettingsBrowseScreen : SearchableSettings { val sourcePreferences = remember { Injekt.get() } return listOf( Preference.PreferenceGroup( - title = stringResource(R.string.label_sources), + title = localize(MR.strings.label_sources), preferenceItems = listOf( Preference.PreferenceItem.SwitchPreference( pref = sourcePreferences.hideInLibraryItems(), - title = stringResource(R.string.pref_hide_in_library_items), + title = localize(MR.strings.pref_hide_in_library_items), ), ), ), Preference.PreferenceGroup( - title = stringResource(R.string.pref_category_nsfw_content), + title = localize(MR.strings.pref_category_nsfw_content), preferenceItems = listOf( Preference.PreferenceItem.SwitchPreference( pref = sourcePreferences.showNsfwSource(), - title = stringResource(R.string.pref_show_nsfw_source), - subtitle = stringResource(R.string.requires_app_restart), + title = localize(MR.strings.pref_show_nsfw_source), + subtitle = localize(MR.strings.requires_app_restart), onValueChanged = { (context as FragmentActivity).authenticate( - title = context.getString(R.string.pref_category_nsfw_content), + title = context.localize(MR.strings.pref_category_nsfw_content), ) }, ), - Preference.PreferenceItem.InfoPreference(stringResource(R.string.parental_controls_info)), + Preference.PreferenceItem.InfoPreference(localize(MR.strings.parental_controls_info)), ), ), ) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDataScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDataScreen.kt index b6a866f3d8..49b42931e3 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDataScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDataScreen.kt @@ -8,7 +8,6 @@ import android.text.format.Formatter import android.widget.Toast import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts -import androidx.annotation.StringRes import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding @@ -27,7 +26,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.more.settings.Preference @@ -36,7 +34,6 @@ import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding import eu.kanade.presentation.permissions.PermissionRequestHelper import eu.kanade.presentation.util.relativeTimeSpanString -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.backup.BackupCreateJob import eu.kanade.tachiyomi.data.backup.BackupFileValidator import eu.kanade.tachiyomi.data.backup.BackupRestoreJob @@ -46,11 +43,14 @@ import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.toast import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.util.lang.launchNonCancellable import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.backup.service.BackupPreferences import tachiyomi.domain.library.service.LibraryPreferences +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -59,8 +59,7 @@ object SettingsDataScreen : SearchableSettings { @ReadOnlyComposable @Composable - @StringRes - override fun getTitleRes() = R.string.label_data_storage + override fun getTitleRes() = MR.strings.label_data_storage @Composable override fun getPreferences(): List { @@ -82,7 +81,7 @@ object SettingsDataScreen : SearchableSettings { val lastAutoBackup by backupPreferences.lastAutoBackupTimestamp().collectAsState() return Preference.PreferenceGroup( - title = stringResource(R.string.label_backup), + title = localize(MR.strings.label_backup), preferenceItems = listOf( // Manual actions getCreateBackupPref(), @@ -91,14 +90,14 @@ object SettingsDataScreen : SearchableSettings { // Automatic backups Preference.PreferenceItem.ListPreference( pref = backupIntervalPref, - title = stringResource(R.string.pref_backup_interval), + title = localize(MR.strings.pref_backup_interval), entries = mapOf( - 0 to stringResource(R.string.off), - 6 to stringResource(R.string.update_6hour), - 12 to stringResource(R.string.update_12hour), - 24 to stringResource(R.string.update_24hour), - 48 to stringResource(R.string.update_48hour), - 168 to stringResource(R.string.update_weekly), + 0 to localize(MR.strings.off), + 6 to localize(MR.strings.update_6hour), + 12 to localize(MR.strings.update_12hour), + 24 to localize(MR.strings.update_24hour), + 48 to localize(MR.strings.update_48hour), + 168 to localize(MR.strings.update_weekly), ), onValueChanged = { BackupCreateJob.setupTask(context, it) @@ -108,12 +107,12 @@ object SettingsDataScreen : SearchableSettings { Preference.PreferenceItem.ListPreference( pref = backupPreferences.numberOfBackups(), enabled = backupInterval != 0, - title = stringResource(R.string.pref_backup_slots), + title = localize(MR.strings.pref_backup_slots), entries = listOf(2, 3, 4, 5).associateWith { it.toString() }, ), Preference.PreferenceItem.InfoPreference( - stringResource(R.string.backup_info) + "\n\n" + - stringResource(R.string.last_auto_backup_info, relativeTimeSpanString(lastAutoBackup)), + localize(MR.strings.backup_info) + "\n\n" + + localize(MR.strings.last_auto_backup_info, relativeTimeSpanString(lastAutoBackup)), ), ), ) @@ -123,8 +122,8 @@ object SettingsDataScreen : SearchableSettings { private fun getCreateBackupPref(): Preference.PreferenceItem.TextPreference { val navigator = LocalNavigator.currentOrThrow return Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_create_backup), - subtitle = stringResource(R.string.pref_create_backup_summ), + title = localize(MR.strings.pref_create_backup), + subtitle = localize(MR.strings.pref_create_backup_summ), onClick = { navigator.push(CreateBackupScreen()) }, ) } @@ -139,7 +138,7 @@ object SettingsDataScreen : SearchableSettings { is InvalidRestore -> { AlertDialog( onDismissRequest = onDismissRequest, - title = { Text(text = stringResource(R.string.invalid_backup_file)) }, + title = { Text(text = localize(MR.strings.invalid_backup_file)) }, text = { Text(text = listOfNotNull(err.uri, err.message).joinToString("\n\n")) }, dismissButton = { TextButton( @@ -148,12 +147,12 @@ object SettingsDataScreen : SearchableSettings { onDismissRequest() }, ) { - Text(text = stringResource(R.string.action_copy_to_clipboard)) + Text(text = localize(MR.strings.action_copy_to_clipboard)) } }, confirmButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, ) @@ -161,15 +160,15 @@ object SettingsDataScreen : SearchableSettings { is MissingRestoreComponents -> { AlertDialog( onDismissRequest = onDismissRequest, - title = { Text(text = stringResource(R.string.pref_restore_backup)) }, + title = { Text(text = localize(MR.strings.pref_restore_backup)) }, text = { Column( modifier = Modifier.verticalScroll(rememberScrollState()), ) { val msg = buildString { - append(stringResource(R.string.backup_restore_content_full)) + append(localize(MR.strings.backup_restore_content_full)) if (err.sources.isNotEmpty()) { - append("\n\n").append(stringResource(R.string.backup_restore_missing_sources)) + append("\n\n").append(localize(MR.strings.backup_restore_missing_sources)) err.sources.joinTo( this, separator = "\n- ", @@ -177,7 +176,7 @@ object SettingsDataScreen : SearchableSettings { ) } if (err.trackers.isNotEmpty()) { - append("\n\n").append(stringResource(R.string.backup_restore_missing_trackers)) + append("\n\n").append(localize(MR.strings.backup_restore_missing_trackers)) err.trackers.joinTo( this, separator = "\n- ", @@ -195,7 +194,7 @@ object SettingsDataScreen : SearchableSettings { onDismissRequest() }, ) { - Text(text = stringResource(R.string.action_restore)) + Text(text = localize(MR.strings.action_restore)) } }, ) @@ -208,12 +207,12 @@ object SettingsDataScreen : SearchableSettings { object : ActivityResultContracts.GetContent() { override fun createIntent(context: Context, input: String): Intent { val intent = super.createIntent(context, input) - return Intent.createChooser(intent, context.getString(R.string.file_select_backup)) + return Intent.createChooser(intent, context.localize(MR.strings.file_select_backup)) } }, ) { if (it == null) { - context.toast(R.string.file_null_uri_error) + context.toast(MR.strings.file_null_uri_error) return@rememberLauncherForActivityResult } @@ -233,17 +232,17 @@ object SettingsDataScreen : SearchableSettings { } return Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_restore_backup), - subtitle = stringResource(R.string.pref_restore_backup_summ), + title = localize(MR.strings.pref_restore_backup), + subtitle = localize(MR.strings.pref_restore_backup_summ), onClick = { if (!BackupRestoreJob.isRunning(context)) { if (DeviceUtil.isMiui && DeviceUtil.isMiuiOptimizationDisabled()) { - context.toast(R.string.restore_miui_warning, Toast.LENGTH_LONG) + context.toast(MR.strings.restore_miui_warning, Toast.LENGTH_LONG) } // no need to catch because it's wrapped with a chooser chooseBackup.launch("*/*") } else { - context.toast(R.string.restore_in_progress) + context.toast(MR.strings.restore_in_progress) } }, ) @@ -260,31 +259,31 @@ object SettingsDataScreen : SearchableSettings { val cacheReadableSize = remember(cacheReadableSizeSema) { chapterCache.readableSize } return Preference.PreferenceGroup( - title = stringResource(R.string.label_data), + title = localize(MR.strings.label_data), preferenceItems = listOf( getStorageInfoPref(cacheReadableSize), Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.pref_clear_chapter_cache), - subtitle = stringResource(R.string.used_cache, cacheReadableSize), + title = localize(MR.strings.pref_clear_chapter_cache), + subtitle = localize(MR.strings.used_cache, cacheReadableSize), onClick = { scope.launchNonCancellable { try { val deletedFiles = chapterCache.clear() withUIContext { - context.toast(context.getString(R.string.cache_deleted, deletedFiles)) + context.toast(context.localize(MR.strings.cache_deleted, deletedFiles)) cacheReadableSizeSema++ } } catch (e: Throwable) { logcat(LogPriority.ERROR, e) - withUIContext { context.toast(R.string.cache_delete_error) } + withUIContext { context.toast(MR.strings.cache_delete_error) } } } }, ), Preference.PreferenceItem.SwitchPreference( pref = libraryPreferences.autoClearChapterCache(), - title = stringResource(R.string.pref_auto_clear_chapter_cache), + title = localize(MR.strings.pref_auto_clear_chapter_cache), ), ), ) @@ -303,10 +302,10 @@ object SettingsDataScreen : SearchableSettings { } return Preference.PreferenceItem.CustomPreference( - title = stringResource(R.string.pref_storage_usage), + title = localize(MR.strings.pref_storage_usage), ) { BasePreferenceWidget( - title = stringResource(R.string.pref_storage_usage), + title = localize(MR.strings.pref_storage_usage), subcomponent = { // TODO: downloads, SD cards, bar representation?, i18n Box(modifier = Modifier.padding(horizontal = PrefsHorizontalPadding)) { diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDownloadScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDownloadScreen.kt index 172a962a65..888e47681f 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDownloadScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDownloadScreen.kt @@ -4,7 +4,6 @@ import android.content.Intent import android.os.Environment import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts -import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.collectAsState @@ -14,19 +13,19 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.pluralStringResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.util.fastMap import androidx.core.net.toUri import com.hippo.unifile.UniFile import eu.kanade.presentation.category.visualName import eu.kanade.presentation.more.settings.Preference import eu.kanade.presentation.more.settings.widget.TriStateListDialog -import eu.kanade.tachiyomi.R import kotlinx.coroutines.runBlocking import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.model.Category import tachiyomi.domain.download.service.DownloadPreferences +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize +import tachiyomi.presentation.core.i18n.localizePlural import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -36,8 +35,7 @@ object SettingsDownloadScreen : SearchableSettings { @ReadOnlyComposable @Composable - @StringRes - override fun getTitleRes() = R.string.pref_category_downloads + override fun getTitleRes() = MR.strings.pref_category_downloads @Composable override fun getPreferences(): List { @@ -49,16 +47,16 @@ object SettingsDownloadScreen : SearchableSettings { getDownloadLocationPreference(downloadPreferences = downloadPreferences), Preference.PreferenceItem.SwitchPreference( pref = downloadPreferences.downloadOnlyOverWifi(), - title = stringResource(R.string.connected_to_wifi), + title = localize(MR.strings.connected_to_wifi), ), Preference.PreferenceItem.SwitchPreference( pref = downloadPreferences.saveChaptersAsCBZ(), - title = stringResource(R.string.save_chapter_as_cbz), + title = localize(MR.strings.save_chapter_as_cbz), ), Preference.PreferenceItem.SwitchPreference( pref = downloadPreferences.splitTallImages(), - title = stringResource(R.string.split_tall_images), - subtitle = stringResource(R.string.split_tall_images_summary), + title = localize(MR.strings.split_tall_images), + subtitle = localize(MR.strings.split_tall_images_summary), ), getDeleteChaptersGroup( downloadPreferences = downloadPreferences, @@ -99,15 +97,15 @@ object SettingsDownloadScreen : SearchableSettings { return Preference.PreferenceItem.ListPreference( pref = currentDirPref, - title = stringResource(R.string.pref_download_directory), + title = localize(MR.strings.pref_download_directory), subtitleProvider = { value, _ -> remember(value) { UniFile.fromUri(context, value.toUri())?.filePath - } ?: stringResource(R.string.invalid_location, value) + } ?: localize(MR.strings.invalid_location, value) }, entries = mapOf( defaultDirPair, - customDirEntryKey to stringResource(R.string.custom_dir), + customDirEntryKey to localize(MR.strings.custom_dir), ), onValueChanged = { val default = it == defaultDirPair.first @@ -121,7 +119,7 @@ object SettingsDownloadScreen : SearchableSettings { @Composable private fun rememberDefaultDownloadDir(): Pair { - val appName = stringResource(R.string.app_name) + val appName = localize(MR.strings.app_name) return remember { val file = UniFile.fromFile( File( @@ -139,27 +137,27 @@ object SettingsDownloadScreen : SearchableSettings { categories: List, ): Preference.PreferenceGroup { return Preference.PreferenceGroup( - title = stringResource(R.string.pref_category_delete_chapters), + title = localize(MR.strings.pref_category_delete_chapters), preferenceItems = listOf( Preference.PreferenceItem.SwitchPreference( pref = downloadPreferences.removeAfterMarkedAsRead(), - title = stringResource(R.string.pref_remove_after_marked_as_read), + title = localize(MR.strings.pref_remove_after_marked_as_read), ), Preference.PreferenceItem.ListPreference( pref = downloadPreferences.removeAfterReadSlots(), - title = stringResource(R.string.pref_remove_after_read), + title = localize(MR.strings.pref_remove_after_read), entries = mapOf( - -1 to stringResource(R.string.disabled), - 0 to stringResource(R.string.last_read_chapter), - 1 to stringResource(R.string.second_to_last), - 2 to stringResource(R.string.third_to_last), - 3 to stringResource(R.string.fourth_to_last), - 4 to stringResource(R.string.fifth_to_last), + -1 to localize(MR.strings.disabled), + 0 to localize(MR.strings.last_read_chapter), + 1 to localize(MR.strings.second_to_last), + 2 to localize(MR.strings.third_to_last), + 3 to localize(MR.strings.fourth_to_last), + 4 to localize(MR.strings.fifth_to_last), ), ), Preference.PreferenceItem.SwitchPreference( pref = downloadPreferences.removeBookmarkedChapters(), - title = stringResource(R.string.pref_remove_bookmarked_chapters), + title = localize(MR.strings.pref_remove_bookmarked_chapters), ), getExcludedCategoriesPreference( downloadPreferences = downloadPreferences, @@ -176,7 +174,7 @@ object SettingsDownloadScreen : SearchableSettings { ): Preference.PreferenceItem.MultiSelectListPreference { return Preference.PreferenceItem.MultiSelectListPreference( pref = downloadPreferences.removeExcludeCategories(), - title = stringResource(R.string.pref_remove_exclude_categories), + title = localize(MR.strings.pref_remove_exclude_categories), entries = categories().associate { it.id.toString() to it.visualName }, ) } @@ -197,8 +195,8 @@ object SettingsDownloadScreen : SearchableSettings { var showDialog by rememberSaveable { mutableStateOf(false) } if (showDialog) { TriStateListDialog( - title = stringResource(R.string.categories), - message = stringResource(R.string.pref_download_new_categories_details), + title = localize(MR.strings.categories), + message = localize(MR.strings.pref_download_new_categories_details), items = allCategories, initialChecked = included.mapNotNull { id -> allCategories.find { it.id.toString() == id } }, initialInversed = excluded.mapNotNull { id -> allCategories.find { it.id.toString() == id } }, @@ -213,14 +211,14 @@ object SettingsDownloadScreen : SearchableSettings { } return Preference.PreferenceGroup( - title = stringResource(R.string.pref_category_auto_download), + title = localize(MR.strings.pref_category_auto_download), preferenceItems = listOf( Preference.PreferenceItem.SwitchPreference( pref = downloadNewChaptersPref, - title = stringResource(R.string.pref_download_new), + title = localize(MR.strings.pref_download_new), ), Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.categories), + title = localize(MR.strings.categories), subtitle = getCategoriesLabel( allCategories = allCategories, included = included, @@ -238,20 +236,20 @@ object SettingsDownloadScreen : SearchableSettings { downloadPreferences: DownloadPreferences, ): Preference.PreferenceGroup { return Preference.PreferenceGroup( - title = stringResource(R.string.download_ahead), + title = localize(MR.strings.download_ahead), preferenceItems = listOf( Preference.PreferenceItem.ListPreference( pref = downloadPreferences.autoDownloadWhileReading(), - title = stringResource(R.string.auto_download_while_reading), + title = localize(MR.strings.auto_download_while_reading), entries = listOf(0, 2, 3, 5, 10).associateWith { if (it == 0) { - stringResource(R.string.disabled) + localize(MR.strings.disabled) } else { - pluralStringResource(id = R.plurals.next_unread_chapters, count = it, it) + localizePlural(MR.plurals.next_unread_chapters, count = it, it) } }, ), - Preference.PreferenceItem.InfoPreference(stringResource(R.string.download_ahead_info)), + Preference.PreferenceItem.InfoPreference(localize(MR.strings.download_ahead_info)), ), ) } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt index 0f978b5738..db81e7bc58 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt @@ -1,6 +1,5 @@ package eu.kanade.presentation.more.settings.screen -import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.collectAsState @@ -11,8 +10,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.pluralStringResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.util.fastMap import androidx.core.content.ContextCompat import cafe.adriel.voyager.navigator.LocalNavigator @@ -21,7 +18,6 @@ import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.category.visualName import eu.kanade.presentation.more.settings.Preference import eu.kanade.presentation.more.settings.widget.TriStateListDialog -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.ui.category.CategoryScreen import kotlinx.coroutines.launch @@ -37,6 +33,9 @@ import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_HAS_U import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_OUTSIDE_RELEASE_PERIOD +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize +import tachiyomi.presentation.core.i18n.localizePlural import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -45,8 +44,7 @@ object SettingsLibraryScreen : SearchableSettings { @Composable @ReadOnlyComposable - @StringRes - override fun getTitleRes() = R.string.pref_category_library + override fun getTitleRes() = MR.strings.pref_category_library @Composable override fun getPreferences(): List { @@ -77,16 +75,16 @@ object SettingsLibraryScreen : SearchableSettings { // For default category val ids = listOf(libraryPreferences.defaultCategory().defaultValue()) + allCategories.fastMap { it.id.toInt() } - val labels = listOf(stringResource(R.string.default_category_summary)) + + val labels = listOf(localize(MR.strings.default_category_summary)) + allCategories.fastMap { it.visualName(context) } return Preference.PreferenceGroup( - title = stringResource(R.string.categories), + title = localize(MR.strings.categories), preferenceItems = listOf( Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.action_edit_categories), - subtitle = pluralStringResource( - id = R.plurals.num_categories, + title = localize(MR.strings.action_edit_categories), + subtitle = localizePlural( + MR.plurals.num_categories, count = userCategoriesCount, userCategoriesCount, ), @@ -94,13 +92,13 @@ object SettingsLibraryScreen : SearchableSettings { ), Preference.PreferenceItem.ListPreference( pref = libraryPreferences.defaultCategory(), - title = stringResource(R.string.default_category), - subtitle = selectedCategory?.visualName ?: stringResource(R.string.default_category_summary), + title = localize(MR.strings.default_category), + subtitle = selectedCategory?.visualName ?: localize(MR.strings.default_category_summary), entries = ids.zip(labels).toMap(), ), Preference.PreferenceItem.SwitchPreference( pref = libraryPreferences.categorizedDisplaySettings(), - title = stringResource(R.string.categorized_display_settings), + title = localize(MR.strings.categorized_display_settings), onValueChanged = { if (!it) { scope.launch { @@ -132,8 +130,8 @@ object SettingsLibraryScreen : SearchableSettings { var showCategoriesDialog by rememberSaveable { mutableStateOf(false) } if (showCategoriesDialog) { TriStateListDialog( - title = stringResource(R.string.categories), - message = stringResource(R.string.pref_library_update_categories_details), + title = localize(MR.strings.categories), + message = localize(MR.strings.pref_library_update_categories_details), items = allCategories, initialChecked = included.mapNotNull { id -> allCategories.find { it.id.toString() == id } }, initialInversed = excluded.mapNotNull { id -> allCategories.find { it.id.toString() == id } }, @@ -148,18 +146,18 @@ object SettingsLibraryScreen : SearchableSettings { } return Preference.PreferenceGroup( - title = stringResource(R.string.pref_category_library_update), + title = localize(MR.strings.pref_category_library_update), preferenceItems = listOf( Preference.PreferenceItem.ListPreference( pref = autoUpdateIntervalPref, - title = stringResource(R.string.pref_library_update_interval), + title = localize(MR.strings.pref_library_update_interval), entries = mapOf( - 0 to stringResource(R.string.update_never), - 12 to stringResource(R.string.update_12hour), - 24 to stringResource(R.string.update_24hour), - 48 to stringResource(R.string.update_48hour), - 72 to stringResource(R.string.update_72hour), - 168 to stringResource(R.string.update_weekly), + 0 to localize(MR.strings.update_never), + 12 to localize(MR.strings.update_12hour), + 24 to localize(MR.strings.update_24hour), + 48 to localize(MR.strings.update_48hour), + 72 to localize(MR.strings.update_72hour), + 168 to localize(MR.strings.update_weekly), ), onValueChanged = { LibraryUpdateJob.setupTask(context, it) @@ -169,12 +167,12 @@ object SettingsLibraryScreen : SearchableSettings { Preference.PreferenceItem.MultiSelectListPreference( pref = libraryPreferences.autoUpdateDeviceRestrictions(), enabled = autoUpdateInterval > 0, - title = stringResource(R.string.pref_library_update_restriction), - subtitle = stringResource(R.string.restrictions), + title = localize(MR.strings.pref_library_update_restriction), + subtitle = localize(MR.strings.restrictions), entries = mapOf( - DEVICE_ONLY_ON_WIFI to stringResource(R.string.connected_to_wifi), - DEVICE_NETWORK_NOT_METERED to stringResource(R.string.network_not_metered), - DEVICE_CHARGING to stringResource(R.string.charging), + DEVICE_ONLY_ON_WIFI to localize(MR.strings.connected_to_wifi), + DEVICE_NETWORK_NOT_METERED to localize(MR.strings.network_not_metered), + DEVICE_CHARGING to localize(MR.strings.charging), ), onValueChanged = { // Post to event looper to allow the preference to be updated. @@ -183,7 +181,7 @@ object SettingsLibraryScreen : SearchableSettings { }, ), Preference.PreferenceItem.TextPreference( - title = stringResource(R.string.categories), + title = localize(MR.strings.categories), subtitle = getCategoriesLabel( allCategories = allCategories, included = included, @@ -193,22 +191,22 @@ object SettingsLibraryScreen : SearchableSettings { ), Preference.PreferenceItem.SwitchPreference( pref = libraryPreferences.autoUpdateMetadata(), - title = stringResource(R.string.pref_library_update_refresh_metadata), - subtitle = stringResource(R.string.pref_library_update_refresh_metadata_summary), + title = localize(MR.strings.pref_library_update_refresh_metadata), + subtitle = localize(MR.strings.pref_library_update_refresh_metadata_summary), ), Preference.PreferenceItem.MultiSelectListPreference( pref = libraryPreferences.autoUpdateMangaRestrictions(), - title = stringResource(R.string.pref_library_update_manga_restriction), + title = localize(MR.strings.pref_library_update_manga_restriction), entries = mapOf( - MANGA_HAS_UNREAD to stringResource(R.string.pref_update_only_completely_read), - MANGA_NON_READ to stringResource(R.string.pref_update_only_started), - MANGA_NON_COMPLETED to stringResource(R.string.pref_update_only_non_completed), - MANGA_OUTSIDE_RELEASE_PERIOD to stringResource(R.string.pref_update_only_in_release_period), + MANGA_HAS_UNREAD to localize(MR.strings.pref_update_only_completely_read), + MANGA_NON_READ to localize(MR.strings.pref_update_only_started), + MANGA_NON_COMPLETED to localize(MR.strings.pref_update_only_non_completed), + MANGA_OUTSIDE_RELEASE_PERIOD to localize(MR.strings.pref_update_only_in_release_period), ), ), Preference.PreferenceItem.SwitchPreference( pref = libraryPreferences.newShowUpdatesCount(), - title = stringResource(R.string.pref_library_update_show_tab_badge), + title = localize(MR.strings.pref_library_update_show_tab_badge), ), ), ) @@ -219,34 +217,34 @@ object SettingsLibraryScreen : SearchableSettings { libraryPreferences: LibraryPreferences, ): Preference.PreferenceGroup { return Preference.PreferenceGroup( - title = stringResource(R.string.pref_chapter_swipe), + title = localize(MR.strings.pref_chapter_swipe), preferenceItems = listOf( Preference.PreferenceItem.ListPreference( pref = libraryPreferences.swipeToStartAction(), - title = stringResource(R.string.pref_chapter_swipe_start), + title = localize(MR.strings.pref_chapter_swipe_start), entries = mapOf( LibraryPreferences.ChapterSwipeAction.Disabled to - stringResource(R.string.disabled), + localize(MR.strings.disabled), LibraryPreferences.ChapterSwipeAction.ToggleBookmark to - stringResource(R.string.action_bookmark), + localize(MR.strings.action_bookmark), LibraryPreferences.ChapterSwipeAction.ToggleRead to - stringResource(R.string.action_mark_as_read), + localize(MR.strings.action_mark_as_read), LibraryPreferences.ChapterSwipeAction.Download to - stringResource(R.string.action_download), + localize(MR.strings.action_download), ), ), Preference.PreferenceItem.ListPreference( pref = libraryPreferences.swipeToEndAction(), - title = stringResource(R.string.pref_chapter_swipe_end), + title = localize(MR.strings.pref_chapter_swipe_end), entries = mapOf( LibraryPreferences.ChapterSwipeAction.Disabled to - stringResource(R.string.disabled), + localize(MR.strings.disabled), LibraryPreferences.ChapterSwipeAction.ToggleBookmark to - stringResource(R.string.action_bookmark), + localize(MR.strings.action_bookmark), LibraryPreferences.ChapterSwipeAction.ToggleRead to - stringResource(R.string.action_mark_as_read), + localize(MR.strings.action_mark_as_read), LibraryPreferences.ChapterSwipeAction.Download to - stringResource(R.string.action_download), + localize(MR.strings.action_download), ), ), ), diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsMainScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsMainScreen.kt index 2209e104b5..d832331c81 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsMainScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsMainScreen.kt @@ -1,6 +1,5 @@ package eu.kanade.presentation.more.settings.screen -import androidx.annotation.StringRes import androidx.compose.foundation.background import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.padding @@ -10,7 +9,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.ChromeReaderMode -import androidx.compose.material.icons.outlined.ChromeReaderMode import androidx.compose.material.icons.outlined.Code import androidx.compose.material.icons.outlined.CollectionsBookmark import androidx.compose.material.icons.outlined.Explore @@ -34,21 +32,22 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.core.graphics.ColorUtils import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.currentOrThrow +import dev.icerock.moko.resources.StringResource import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.more.settings.screen.about.AboutScreen import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget import eu.kanade.presentation.util.LocalBackPress import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import cafe.adriel.voyager.core.screen.Screen as VoyagerScreen object SettingsMainScreen : Screen() { @@ -85,13 +84,13 @@ object SettingsMainScreen : Screen() { topBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(topBarState), topBar = { scrollBehavior -> AppBar( - title = stringResource(R.string.label_settings), + title = localize(MR.strings.label_settings), navigateUp = backPress::invoke, actions = { AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.action_search), + title = localize(MR.strings.action_search), icon = Icons.Outlined.Search, onClick = { navigator.navigate(SettingsSearchScreen(), twoPane) }, ), @@ -148,7 +147,7 @@ object SettingsMainScreen : Screen() { CompositionLocalProvider(LocalContentColor provides contentColor) { TextPreferenceWidget( modifier = modifier, - title = stringResource(item.titleRes), + title = localize(item.titleRes), subtitle = item.formatSubtitle(), icon = item.icon, onPreferenceClick = { navigator.navigate(item.screen, twoPane) }, @@ -165,73 +164,72 @@ object SettingsMainScreen : Screen() { } private data class Item( - @StringRes val titleRes: Int, - @StringRes val subtitleRes: Int, - val formatSubtitle: @Composable () -> String = { stringResource(subtitleRes) }, + val titleRes: StringResource, + val subtitleRes: StringResource? = null, + val formatSubtitle: @Composable () -> String? = { subtitleRes?.let { localize(it) } }, val icon: ImageVector, val screen: VoyagerScreen, ) private val items = listOf( Item( - titleRes = R.string.pref_category_appearance, - subtitleRes = R.string.pref_appearance_summary, + titleRes = MR.strings.pref_category_appearance, + subtitleRes = MR.strings.pref_appearance_summary, icon = Icons.Outlined.Palette, screen = SettingsAppearanceScreen, ), Item( - titleRes = R.string.pref_category_library, - subtitleRes = R.string.pref_library_summary, + titleRes = MR.strings.pref_category_library, + subtitleRes = MR.strings.pref_library_summary, icon = Icons.Outlined.CollectionsBookmark, screen = SettingsLibraryScreen, ), Item( - titleRes = R.string.pref_category_reader, - subtitleRes = R.string.pref_reader_summary, + titleRes = MR.strings.pref_category_reader, + subtitleRes = MR.strings.pref_reader_summary, icon = Icons.AutoMirrored.Outlined.ChromeReaderMode, screen = SettingsReaderScreen, ), Item( - titleRes = R.string.pref_category_downloads, - subtitleRes = R.string.pref_downloads_summary, + titleRes = MR.strings.pref_category_downloads, + subtitleRes = MR.strings.pref_downloads_summary, icon = Icons.Outlined.GetApp, screen = SettingsDownloadScreen, ), Item( - titleRes = R.string.pref_category_tracking, - subtitleRes = R.string.pref_tracking_summary, + titleRes = MR.strings.pref_category_tracking, + subtitleRes = MR.strings.pref_tracking_summary, icon = Icons.Outlined.Sync, screen = SettingsTrackingScreen, ), Item( - titleRes = R.string.browse, - subtitleRes = R.string.pref_browse_summary, + titleRes = MR.strings.browse, + subtitleRes = MR.strings.pref_browse_summary, icon = Icons.Outlined.Explore, screen = SettingsBrowseScreen, ), Item( - titleRes = R.string.label_data_storage, - subtitleRes = R.string.pref_backup_summary, + titleRes = MR.strings.label_data_storage, + subtitleRes = MR.strings.pref_backup_summary, icon = Icons.Outlined.Storage, screen = SettingsDataScreen, ), Item( - titleRes = R.string.pref_category_security, - subtitleRes = R.string.pref_security_summary, + titleRes = MR.strings.pref_category_security, + subtitleRes = MR.strings.pref_security_summary, icon = Icons.Outlined.Security, screen = SettingsSecurityScreen, ), Item( - titleRes = R.string.pref_category_advanced, - subtitleRes = R.string.pref_advanced_summary, + titleRes = MR.strings.pref_category_advanced, + subtitleRes = MR.strings.pref_advanced_summary, icon = Icons.Outlined.Code, screen = SettingsAdvancedScreen, ), Item( - titleRes = R.string.pref_category_about, - subtitleRes = 0, + titleRes = MR.strings.pref_category_about, formatSubtitle = { - "${stringResource(R.string.app_name)} ${AboutScreen.getVersionName(withBuildDate = false)}" + "${localize(MR.strings.app_name)} ${AboutScreen.getVersionName(withBuildDate = false)}" }, icon = Icons.Outlined.Info, screen = AboutScreen, diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt index ab2759c39c..c5b8a0018f 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt @@ -1,18 +1,17 @@ package eu.kanade.presentation.more.settings.screen import android.os.Build -import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.res.stringResource import eu.kanade.presentation.more.settings.Preference -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -22,8 +21,7 @@ object SettingsReaderScreen : SearchableSettings { @ReadOnlyComposable @Composable - @StringRes - override fun getTitleRes() = R.string.pref_category_reader + override fun getTitleRes() = MR.strings.pref_category_reader @Composable override fun getPreferences(): List { @@ -31,43 +29,43 @@ object SettingsReaderScreen : SearchableSettings { return listOf( Preference.PreferenceItem.ListPreference( pref = readerPref.defaultReadingMode(), - title = stringResource(R.string.pref_viewer_type), + title = localize(MR.strings.pref_viewer_type), entries = ReadingMode.entries.drop(1) - .associate { it.flagValue to stringResource(it.stringRes) }, + .associate { it.flagValue to localize(it.stringRes) }, ), Preference.PreferenceItem.ListPreference( pref = readerPref.doubleTapAnimSpeed(), - title = stringResource(R.string.pref_double_tap_anim_speed), + title = localize(MR.strings.pref_double_tap_anim_speed), entries = mapOf( - 1 to stringResource(R.string.double_tap_anim_speed_0), - 500 to stringResource(R.string.double_tap_anim_speed_normal), - 250 to stringResource(R.string.double_tap_anim_speed_fast), + 1 to localize(MR.strings.double_tap_anim_speed_0), + 500 to localize(MR.strings.double_tap_anim_speed_normal), + 250 to localize(MR.strings.double_tap_anim_speed_fast), ), ), Preference.PreferenceItem.SwitchPreference( pref = readerPref.showReadingMode(), - title = stringResource(R.string.pref_show_reading_mode), - subtitle = stringResource(R.string.pref_show_reading_mode_summary), + title = localize(MR.strings.pref_show_reading_mode), + subtitle = localize(MR.strings.pref_show_reading_mode_summary), ), Preference.PreferenceItem.SwitchPreference( pref = readerPref.showNavigationOverlayOnStart(), - title = stringResource(R.string.pref_show_navigation_mode), - subtitle = stringResource(R.string.pref_show_navigation_mode_summary), + title = localize(MR.strings.pref_show_navigation_mode), + subtitle = localize(MR.strings.pref_show_navigation_mode_summary), ), Preference.PreferenceItem.SwitchPreference( pref = readerPref.trueColor(), - title = stringResource(R.string.pref_true_color), - subtitle = stringResource(R.string.pref_true_color_summary), + title = localize(MR.strings.pref_true_color), + subtitle = localize(MR.strings.pref_true_color_summary), enabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O, ), Preference.PreferenceItem.SwitchPreference( pref = readerPref.pageTransitions(), - title = stringResource(R.string.pref_page_transitions), + title = localize(MR.strings.pref_page_transitions), ), Preference.PreferenceItem.SwitchPreference( pref = readerPref.flashOnPageChange(), - title = stringResource(R.string.pref_flash_page), - subtitle = stringResource(R.string.pref_flash_page_summ), + title = localize(MR.strings.pref_flash_page), + subtitle = localize(MR.strings.pref_flash_page_summ), ), getDisplayGroup(readerPreferences = readerPref), getReadingGroup(readerPreferences = readerPref), @@ -83,42 +81,42 @@ object SettingsReaderScreen : SearchableSettings { val fullscreenPref = readerPreferences.fullscreen() val fullscreen by fullscreenPref.collectAsState() return Preference.PreferenceGroup( - title = stringResource(R.string.pref_category_display), + title = localize(MR.strings.pref_category_display), preferenceItems = listOf( Preference.PreferenceItem.ListPreference( pref = readerPreferences.defaultOrientationType(), - title = stringResource(R.string.pref_rotation_type), + title = localize(MR.strings.pref_rotation_type), entries = ReaderOrientation.entries.drop(1) - .associate { it.flagValue to stringResource(it.stringRes) }, + .associate { it.flagValue to localize(it.stringRes) }, ), Preference.PreferenceItem.ListPreference( pref = readerPreferences.readerTheme(), - title = stringResource(R.string.pref_reader_theme), + title = localize(MR.strings.pref_reader_theme), entries = mapOf( - 1 to stringResource(R.string.black_background), - 2 to stringResource(R.string.gray_background), - 0 to stringResource(R.string.white_background), - 3 to stringResource(R.string.automatic_background), + 1 to localize(MR.strings.black_background), + 2 to localize(MR.strings.gray_background), + 0 to localize(MR.strings.white_background), + 3 to localize(MR.strings.automatic_background), ), ), Preference.PreferenceItem.SwitchPreference( pref = fullscreenPref, - title = stringResource(R.string.pref_fullscreen), + title = localize(MR.strings.pref_fullscreen), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.cutoutShort(), - title = stringResource(R.string.pref_cutout_short), + title = localize(MR.strings.pref_cutout_short), enabled = fullscreen && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && LocalView.current.rootWindowInsets?.displayCutout != null, // has cutout ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.keepScreenOn(), - title = stringResource(R.string.pref_keep_screen_on), + title = localize(MR.strings.pref_keep_screen_on), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.showPageNumber(), - title = stringResource(R.string.pref_show_page_number), + title = localize(MR.strings.pref_show_page_number), ), ), ) @@ -127,23 +125,23 @@ object SettingsReaderScreen : SearchableSettings { @Composable private fun getReadingGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { return Preference.PreferenceGroup( - title = stringResource(R.string.pref_category_reading), + title = localize(MR.strings.pref_category_reading), preferenceItems = listOf( Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.skipRead(), - title = stringResource(R.string.pref_skip_read_chapters), + title = localize(MR.strings.pref_skip_read_chapters), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.skipFiltered(), - title = stringResource(R.string.pref_skip_filtered_chapters), + title = localize(MR.strings.pref_skip_filtered_chapters), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.skipDupe(), - title = stringResource(R.string.pref_skip_dupe_chapters), + title = localize(MR.strings.pref_skip_dupe_chapters), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.alwaysShowChapterTransition(), - title = stringResource(R.string.pref_always_show_chapter_transition), + title = localize(MR.strings.pref_always_show_chapter_transition), ), ), ) @@ -162,57 +160,57 @@ object SettingsReaderScreen : SearchableSettings { val rotateToFit by rotateToFitPref.collectAsState() return Preference.PreferenceGroup( - title = stringResource(R.string.pager_viewer), + title = localize(MR.strings.pager_viewer), preferenceItems = listOf( Preference.PreferenceItem.ListPreference( pref = navModePref, - title = stringResource(R.string.pref_viewer_nav), + title = localize(MR.strings.pref_viewer_nav), entries = ReaderPreferences.TapZones - .mapIndexed { index, it -> index to stringResource(it) } + .mapIndexed { index, it -> index to localize(it) } .toMap(), ), Preference.PreferenceItem.ListPreference( pref = readerPreferences.pagerNavInverted(), - title = stringResource(R.string.pref_read_with_tapping_inverted), + title = localize(MR.strings.pref_read_with_tapping_inverted), entries = listOf( ReaderPreferences.TappingInvertMode.NONE, ReaderPreferences.TappingInvertMode.HORIZONTAL, ReaderPreferences.TappingInvertMode.VERTICAL, ReaderPreferences.TappingInvertMode.BOTH, - ).associateWith { stringResource(it.titleResId) }, + ).associateWith { localize(it.titleRes) }, enabled = navMode != 5, ), Preference.PreferenceItem.ListPreference( pref = imageScaleTypePref, - title = stringResource(R.string.pref_image_scale_type), + title = localize(MR.strings.pref_image_scale_type), entries = ReaderPreferences.ImageScaleType - .mapIndexed { index, it -> index + 1 to stringResource(it) } + .mapIndexed { index, it -> index + 1 to localize(it) } .toMap(), ), Preference.PreferenceItem.ListPreference( pref = readerPreferences.zoomStart(), - title = stringResource(R.string.pref_zoom_start), + title = localize(MR.strings.pref_zoom_start), entries = ReaderPreferences.ZoomStart - .mapIndexed { index, it -> index + 1 to stringResource(it) } + .mapIndexed { index, it -> index + 1 to localize(it) } .toMap(), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.cropBorders(), - title = stringResource(R.string.pref_crop_borders), + title = localize(MR.strings.pref_crop_borders), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.landscapeZoom(), - title = stringResource(R.string.pref_landscape_zoom), + title = localize(MR.strings.pref_landscape_zoom), enabled = imageScaleType == 1, ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.navigateToPan(), - title = stringResource(R.string.pref_navigate_pan), + title = localize(MR.strings.pref_navigate_pan), enabled = navMode != 5, ), Preference.PreferenceItem.SwitchPreference( pref = dualPageSplitPref, - title = stringResource(R.string.pref_dual_page_split), + title = localize(MR.strings.pref_dual_page_split), onValueChanged = { rotateToFitPref.set(false) true @@ -220,13 +218,13 @@ object SettingsReaderScreen : SearchableSettings { ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.dualPageInvertPaged(), - title = stringResource(R.string.pref_dual_page_invert), - subtitle = stringResource(R.string.pref_dual_page_invert_summary), + title = localize(MR.strings.pref_dual_page_invert), + subtitle = localize(MR.strings.pref_dual_page_invert_summary), enabled = dualPageSplit, ), Preference.PreferenceItem.SwitchPreference( pref = rotateToFitPref, - title = stringResource(R.string.pref_page_rotate), + title = localize(MR.strings.pref_page_rotate), onValueChanged = { dualPageSplitPref.set(false) true @@ -234,7 +232,7 @@ object SettingsReaderScreen : SearchableSettings { ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.dualPageRotateToFitInvert(), - title = stringResource(R.string.pref_page_rotate_invert), + title = localize(MR.strings.pref_page_rotate_invert), enabled = rotateToFit, ), ), @@ -254,29 +252,29 @@ object SettingsReaderScreen : SearchableSettings { val webtoonSidePadding by webtoonSidePaddingPref.collectAsState() return Preference.PreferenceGroup( - title = stringResource(R.string.webtoon_viewer), + title = localize(MR.strings.webtoon_viewer), preferenceItems = listOf( Preference.PreferenceItem.ListPreference( pref = navModePref, - title = stringResource(R.string.pref_viewer_nav), + title = localize(MR.strings.pref_viewer_nav), entries = ReaderPreferences.TapZones - .mapIndexed { index, it -> index to stringResource(it) } + .mapIndexed { index, it -> index to localize(it) } .toMap(), ), Preference.PreferenceItem.ListPreference( pref = readerPreferences.webtoonNavInverted(), - title = stringResource(R.string.pref_read_with_tapping_inverted), + title = localize(MR.strings.pref_read_with_tapping_inverted), entries = listOf( ReaderPreferences.TappingInvertMode.NONE, ReaderPreferences.TappingInvertMode.HORIZONTAL, ReaderPreferences.TappingInvertMode.VERTICAL, ReaderPreferences.TappingInvertMode.BOTH, - ).associateWith { stringResource(it.titleResId) }, + ).associateWith { localize(it.titleRes) }, enabled = navMode != 5, ), Preference.PreferenceItem.SliderPreference( value = webtoonSidePadding, - title = stringResource(R.string.pref_webtoon_side_padding), + title = localize(MR.strings.pref_webtoon_side_padding), subtitle = numberFormat.format(webtoonSidePadding / 100f), min = ReaderPreferences.WEBTOON_PADDING_MIN, max = ReaderPreferences.WEBTOON_PADDING_MAX, @@ -287,31 +285,31 @@ object SettingsReaderScreen : SearchableSettings { ), Preference.PreferenceItem.ListPreference( pref = readerPreferences.readerHideThreshold(), - title = stringResource(R.string.pref_hide_threshold), + title = localize(MR.strings.pref_hide_threshold), entries = mapOf( - ReaderPreferences.ReaderHideThreshold.HIGHEST to stringResource(R.string.pref_highest), - ReaderPreferences.ReaderHideThreshold.HIGH to stringResource(R.string.pref_high), - ReaderPreferences.ReaderHideThreshold.LOW to stringResource(R.string.pref_low), - ReaderPreferences.ReaderHideThreshold.LOWEST to stringResource(R.string.pref_lowest), + ReaderPreferences.ReaderHideThreshold.HIGHEST to localize(MR.strings.pref_highest), + ReaderPreferences.ReaderHideThreshold.HIGH to localize(MR.strings.pref_high), + ReaderPreferences.ReaderHideThreshold.LOW to localize(MR.strings.pref_low), + ReaderPreferences.ReaderHideThreshold.LOWEST to localize(MR.strings.pref_lowest), ), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.cropBordersWebtoon(), - title = stringResource(R.string.pref_crop_borders), + title = localize(MR.strings.pref_crop_borders), ), Preference.PreferenceItem.SwitchPreference( pref = dualPageSplitPref, - title = stringResource(R.string.pref_dual_page_split), + title = localize(MR.strings.pref_dual_page_split), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.dualPageInvertWebtoon(), - title = stringResource(R.string.pref_dual_page_invert), - subtitle = stringResource(R.string.pref_dual_page_invert_summary), + title = localize(MR.strings.pref_dual_page_invert), + subtitle = localize(MR.strings.pref_dual_page_invert_summary), enabled = dualPageSplit, ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.webtoonDoubleTapZoomEnabled(), - title = stringResource(R.string.pref_double_tap_zoom), + title = localize(MR.strings.pref_double_tap_zoom), enabled = true, ), ), @@ -323,15 +321,15 @@ object SettingsReaderScreen : SearchableSettings { val readWithVolumeKeysPref = readerPreferences.readWithVolumeKeys() val readWithVolumeKeys by readWithVolumeKeysPref.collectAsState() return Preference.PreferenceGroup( - title = stringResource(R.string.pref_reader_navigation), + title = localize(MR.strings.pref_reader_navigation), preferenceItems = listOf( Preference.PreferenceItem.SwitchPreference( pref = readWithVolumeKeysPref, - title = stringResource(R.string.pref_read_with_volume_keys), + title = localize(MR.strings.pref_read_with_volume_keys), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.readWithVolumeKeysInverted(), - title = stringResource(R.string.pref_read_with_volume_keys_inverted), + title = localize(MR.strings.pref_read_with_volume_keys_inverted), enabled = readWithVolumeKeys, ), ), @@ -341,16 +339,16 @@ object SettingsReaderScreen : SearchableSettings { @Composable private fun getActionsGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { return Preference.PreferenceGroup( - title = stringResource(R.string.pref_reader_actions), + title = localize(MR.strings.pref_reader_actions), preferenceItems = listOf( Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.readWithLongTap(), - title = stringResource(R.string.pref_read_with_long_tap), + title = localize(MR.strings.pref_read_with_long_tap), ), Preference.PreferenceItem.SwitchPreference( pref = readerPreferences.folderPerManga(), - title = stringResource(R.string.pref_create_folder_per_manga), - subtitle = stringResource(R.string.pref_create_folder_per_manga_summary), + title = localize(MR.strings.pref_create_folder_per_manga), + subtitle = localize(MR.strings.pref_create_folder_per_manga_summary), ), ), ) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSearchScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSearchScreen.kt index adf184a9f8..d92c8bb484 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSearchScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSearchScreen.kt @@ -41,7 +41,6 @@ import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.TextFieldValue @@ -53,8 +52,9 @@ import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.components.UpIcon import eu.kanade.presentation.more.settings.Preference import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.util.runOnEnterKeyPressed import cafe.adriel.voyager.core.screen.Screen as VoyagerScreen @@ -118,7 +118,7 @@ class SettingsSearchScreen : Screen() { decorationBox = { if (textFieldValue.text.isEmpty()) { Text( - text = stringResource(R.string.action_search_settings), + text = localize(MR.strings.action_search_settings), color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyLarge, ) @@ -222,7 +222,7 @@ private fun SearchResult( when { it == null -> {} it.isEmpty() -> { - EmptyScreen(stringResource(R.string.no_results_found)) + EmptyScreen(localize(MR.strings.no_results_found)) } else -> { LazyColumn( @@ -268,7 +268,7 @@ private fun SearchResult( private fun getIndex() = settingScreens .map { screen -> SettingsData( - title = stringResource(screen.getTitleRes()), + title = localize(screen.getTitleRes()), route = screen, contents = screen.getPreferences(), ) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSecurityScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSecurityScreen.kt index 6dcbaa1ed0..e4abad1e19 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSecurityScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSecurityScreen.kt @@ -1,19 +1,19 @@ package eu.kanade.presentation.more.settings.screen -import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.pluralStringResource -import androidx.compose.ui.res.stringResource import androidx.fragment.app.FragmentActivity import eu.kanade.presentation.more.settings.Preference -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.core.security.SecurityPreferences import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize +import tachiyomi.presentation.core.i18n.localizePlural import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -22,8 +22,7 @@ object SettingsSecurityScreen : SearchableSettings { @ReadOnlyComposable @Composable - @StringRes - override fun getTitleRes() = R.string.pref_category_security + override fun getTitleRes() = MR.strings.pref_category_security @Composable override fun getPreferences(): List { @@ -37,43 +36,43 @@ object SettingsSecurityScreen : SearchableSettings { return listOf( Preference.PreferenceItem.SwitchPreference( pref = useAuthPref, - title = stringResource(R.string.lock_with_biometrics), + title = localize(MR.strings.lock_with_biometrics), enabled = authSupported, onValueChanged = { (context as FragmentActivity).authenticate( - title = context.getString(R.string.lock_with_biometrics), + title = context.localize(MR.strings.lock_with_biometrics), ) }, ), Preference.PreferenceItem.ListPreference( pref = securityPreferences.lockAppAfter(), - title = stringResource(R.string.lock_when_idle), + title = localize(MR.strings.lock_when_idle), enabled = authSupported && useAuth, entries = LockAfterValues .associateWith { when (it) { - -1 -> stringResource(R.string.lock_never) - 0 -> stringResource(R.string.lock_always) - else -> pluralStringResource(id = R.plurals.lock_after_mins, count = it, it) + -1 -> localize(MR.strings.lock_never) + 0 -> localize(MR.strings.lock_always) + else -> localizePlural(MR.plurals.lock_after_mins, count = it, it) } }, onValueChanged = { (context as FragmentActivity).authenticate( - title = context.getString(R.string.lock_when_idle), + title = context.localize(MR.strings.lock_when_idle), ) }, ), Preference.PreferenceItem.SwitchPreference( pref = securityPreferences.hideNotificationContent(), - title = stringResource(R.string.hide_notification_content), + title = localize(MR.strings.hide_notification_content), ), Preference.PreferenceItem.ListPreference( pref = securityPreferences.secureScreen(), - title = stringResource(R.string.secure_screen), + title = localize(MR.strings.secure_screen), entries = SecurityPreferences.SecureScreenMode.entries - .associateWith { stringResource(it.titleResId) }, + .associateWith { localize(it.titleRes) }, ), - Preference.PreferenceItem.InfoPreference(stringResource(R.string.secure_screen_summary)), + Preference.PreferenceItem.InfoPreference(localize(MR.strings.secure_screen_summary)), ) } } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt index eebcaa22c8..0762701503 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt @@ -1,7 +1,6 @@ package eu.kanade.presentation.more.settings.screen import android.content.Context -import androidx.annotation.StringRes import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -13,7 +12,6 @@ import androidx.compose.material.icons.automirrored.outlined.HelpOutline import androidx.compose.material.icons.filled.Visibility import androidx.compose.material.icons.filled.VisibilityOff import androidx.compose.material.icons.outlined.Close -import androidx.compose.material.icons.outlined.HelpOutline import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults @@ -34,7 +32,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation @@ -42,9 +39,9 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import dev.icerock.moko.resources.StringResource import eu.kanade.domain.track.service.TrackPreferences import eu.kanade.presentation.more.settings.Preference -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.track.EnhancedTracker import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.TrackerManager @@ -57,7 +54,9 @@ import eu.kanade.tachiyomi.util.system.toast import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.lang.withUIContext import tachiyomi.domain.source.service.SourceManager +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -65,8 +64,7 @@ object SettingsTrackingScreen : SearchableSettings { @ReadOnlyComposable @Composable - @StringRes - override fun getTitleRes() = R.string.pref_category_tracking + override fun getTitleRes() = MR.strings.pref_category_tracking @Composable override fun RowScope.AppBarAction() { @@ -74,7 +72,7 @@ object SettingsTrackingScreen : SearchableSettings { IconButton(onClick = { uriHandler.openUri("https://tachiyomi.org/docs/guides/tracking") }) { Icon( imageVector = Icons.AutoMirrored.Outlined.HelpOutline, - contentDescription = stringResource(R.string.tracking_guide), + contentDescription = localize(MR.strings.tracking_guide), ) } } @@ -111,10 +109,10 @@ object SettingsTrackingScreen : SearchableSettings { val acceptedSources = (service as EnhancedTracker).getAcceptedSources() sourceManager.getCatalogueSources().any { it::class.qualifiedName in acceptedSources } } - var enhancedTrackerInfo = stringResource(R.string.enhanced_tracking_info) + var enhancedTrackerInfo = localize(MR.strings.enhanced_tracking_info) if (enhancedTrackers.second.isNotEmpty()) { - val missingSourcesInfo = stringResource( - R.string.enhanced_services_not_installed, + val missingSourcesInfo = localize( + MR.strings.enhanced_services_not_installed, enhancedTrackers.second.joinToString { it.name }, ) enhancedTrackerInfo += "\n\n$missingSourcesInfo" @@ -123,10 +121,10 @@ object SettingsTrackingScreen : SearchableSettings { return listOf( Preference.PreferenceItem.SwitchPreference( pref = trackPreferences.autoUpdateTrack(), - title = stringResource(R.string.pref_auto_update_manga_sync), + title = localize(MR.strings.pref_auto_update_manga_sync), ), Preference.PreferenceGroup( - title = stringResource(R.string.services), + title = localize(MR.strings.services), preferenceItems = listOf( Preference.PreferenceItem.TrackerPreference( title = trackerManager.myAnimeList.name, @@ -143,13 +141,13 @@ object SettingsTrackingScreen : SearchableSettings { Preference.PreferenceItem.TrackerPreference( title = trackerManager.kitsu.name, tracker = trackerManager.kitsu, - login = { dialog = LoginDialog(trackerManager.kitsu, R.string.email) }, + login = { dialog = LoginDialog(trackerManager.kitsu, MR.strings.email) }, logout = { dialog = LogoutDialog(trackerManager.kitsu) }, ), Preference.PreferenceItem.TrackerPreference( title = trackerManager.mangaUpdates.name, tracker = trackerManager.mangaUpdates, - login = { dialog = LoginDialog(trackerManager.mangaUpdates, R.string.username) }, + login = { dialog = LoginDialog(trackerManager.mangaUpdates, MR.strings.username) }, logout = { dialog = LogoutDialog(trackerManager.mangaUpdates) }, ), Preference.PreferenceItem.TrackerPreference( @@ -164,11 +162,11 @@ object SettingsTrackingScreen : SearchableSettings { login = { context.openInBrowser(BangumiApi.authUrl(), forceDefaultBrowser = true) }, logout = { dialog = LogoutDialog(trackerManager.bangumi) }, ), - Preference.PreferenceItem.InfoPreference(stringResource(R.string.tracking_info)), + Preference.PreferenceItem.InfoPreference(localize(MR.strings.tracking_info)), ), ), Preference.PreferenceGroup( - title = stringResource(R.string.enhanced_services), + title = localize(MR.strings.enhanced_services), preferenceItems = enhancedTrackers.first .map { service -> Preference.PreferenceItem.TrackerPreference( @@ -185,7 +183,7 @@ object SettingsTrackingScreen : SearchableSettings { @Composable private fun TrackingLoginDialog( tracker: Tracker, - @StringRes uNameStringRes: Int, + uNameStringRes: StringResource, onDismissRequest: () -> Unit, ) { val context = LocalContext.current @@ -201,13 +199,13 @@ object SettingsTrackingScreen : SearchableSettings { title = { Row(verticalAlignment = Alignment.CenterVertically) { Text( - text = stringResource(R.string.login_title, tracker.name), + text = localize(MR.strings.login_title, tracker.name), modifier = Modifier.weight(1f), ) IconButton(onClick = onDismissRequest) { Icon( imageVector = Icons.Outlined.Close, - contentDescription = stringResource(R.string.action_close), + contentDescription = localize(MR.strings.action_close), ) } } @@ -218,7 +216,7 @@ object SettingsTrackingScreen : SearchableSettings { modifier = Modifier.fillMaxWidth(), value = username, onValueChange = { username = it }, - label = { Text(text = stringResource(uNameStringRes)) }, + label = { Text(text = localize(uNameStringRes)) }, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), singleLine = true, isError = inputError && !processing, @@ -229,7 +227,7 @@ object SettingsTrackingScreen : SearchableSettings { modifier = Modifier.fillMaxWidth(), value = password, onValueChange = { password = it }, - label = { Text(text = stringResource(R.string.password)) }, + label = { Text(text = localize(MR.strings.password)) }, trailingIcon = { IconButton(onClick = { hidePassword = !hidePassword }) { Icon( @@ -275,8 +273,8 @@ object SettingsTrackingScreen : SearchableSettings { } }, ) { - val id = if (processing) R.string.loading else R.string.login - Text(text = stringResource(id)) + val id = if (processing) MR.strings.loading else MR.strings.login + Text(text = localize(id)) } }, ) @@ -290,7 +288,7 @@ object SettingsTrackingScreen : SearchableSettings { ): Boolean { return try { tracker.login(username, password) - withUIContext { context.toast(R.string.login_success) } + withUIContext { context.toast(MR.strings.login_success) } true } catch (e: Throwable) { tracker.logout() @@ -309,7 +307,7 @@ object SettingsTrackingScreen : SearchableSettings { onDismissRequest = onDismissRequest, title = { Text( - text = stringResource(R.string.logout_title, tracker.name), + text = localize(MR.strings.logout_title, tracker.name), textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth(), ) @@ -320,21 +318,21 @@ object SettingsTrackingScreen : SearchableSettings { modifier = Modifier.weight(1f), onClick = onDismissRequest, ) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } Button( modifier = Modifier.weight(1f), onClick = { tracker.logout() onDismissRequest() - context.toast(R.string.logout_success) + context.toast(MR.strings.logout_success) }, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.error, contentColor = MaterialTheme.colorScheme.onError, ), ) { - Text(text = stringResource(R.string.logout)) + Text(text = localize(MR.strings.logout)) } } }, @@ -344,7 +342,7 @@ object SettingsTrackingScreen : SearchableSettings { private data class LoginDialog( val tracker: Tracker, - @StringRes val uNameStringRes: Int, + val uNameStringRes: StringResource, ) private data class LogoutDialog( diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/AboutScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/AboutScreen.kt index 6ae3bba162..fb537fd06c 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/AboutScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/AboutScreen.kt @@ -19,7 +19,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow @@ -30,7 +29,6 @@ import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget import eu.kanade.presentation.util.LocalBackPress import eu.kanade.presentation.util.Screen import eu.kanade.tachiyomi.BuildConfig -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.updater.AppUpdateChecker import eu.kanade.tachiyomi.data.updater.RELEASE_URL import eu.kanade.tachiyomi.ui.more.NewUpdateScreen @@ -44,9 +42,11 @@ import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.release.interactor.GetApplicationRelease +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.LinkIcon import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.icons.CustomIcons import tachiyomi.presentation.core.icons.Discord import tachiyomi.presentation.core.icons.Facebook @@ -74,7 +74,7 @@ object AboutScreen : Screen() { Scaffold( topBar = { scrollBehavior -> AppBar( - title = stringResource(R.string.pref_category_about), + title = localize(MR.strings.pref_category_about), navigateUp = if (handleBack != null) handleBack::invoke else null, scrollBehavior = scrollBehavior, ) @@ -89,7 +89,7 @@ object AboutScreen : Screen() { item { TextPreferenceWidget( - title = stringResource(R.string.version), + title = localize(MR.strings.version), subtitle = getVersionName(withBuildDate = true), onPreferenceClick = { val deviceInfo = CrashLogUtil(context).getDebugInfo() @@ -101,7 +101,7 @@ object AboutScreen : Screen() { if (BuildConfig.INCLUDE_UPDATER) { item { TextPreferenceWidget( - title = stringResource(R.string.check_for_updates), + title = localize(MR.strings.check_for_updates), widget = { AnimatedVisibility(visible = isCheckingUpdates) { CircularProgressIndicator( @@ -140,7 +140,7 @@ object AboutScreen : Screen() { if (!BuildConfig.DEBUG) { item { TextPreferenceWidget( - title = stringResource(R.string.whats_new), + title = localize(MR.strings.whats_new), onPreferenceClick = { uriHandler.openUri(RELEASE_URL) }, ) } @@ -148,21 +148,21 @@ object AboutScreen : Screen() { item { TextPreferenceWidget( - title = stringResource(R.string.help_translate), + title = localize(MR.strings.help_translate), onPreferenceClick = { uriHandler.openUri("https://tachiyomi.org/docs/contribute#translation") }, ) } item { TextPreferenceWidget( - title = stringResource(R.string.licenses), + title = localize(MR.strings.licenses), onPreferenceClick = { navigator.push(OpenSourceLicensesScreen()) }, ) } item { TextPreferenceWidget( - title = stringResource(R.string.privacy_policy), + title = localize(MR.strings.privacy_policy), onPreferenceClick = { uriHandler.openUri("https://tachiyomi.org/privacy/") }, ) } @@ -175,7 +175,7 @@ object AboutScreen : Screen() { horizontalArrangement = Arrangement.Center, ) { LinkIcon( - label = stringResource(R.string.website), + label = localize(MR.strings.website), icon = Icons.Outlined.Public, url = "https://tachiyomi.org", ) @@ -226,10 +226,10 @@ object AboutScreen : Screen() { onAvailableUpdate(result) } is GetApplicationRelease.Result.NoNewUpdate -> { - context.toast(R.string.update_check_no_new_updates) + context.toast(MR.strings.update_check_no_new_updates) } is GetApplicationRelease.Result.OsTooOld -> { - context.toast(R.string.update_check_eol) + context.toast(MR.strings.update_check_eol) } else -> {} } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/OpenSourceLibraryLicenseScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/OpenSourceLibraryLicenseScreen.kt index 9b0da494c4..27f7185bb2 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/OpenSourceLibraryLicenseScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/OpenSourceLibraryLicenseScreen.kt @@ -9,7 +9,6 @@ import androidx.compose.material.icons.filled.Public import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.core.text.HtmlCompat @@ -19,9 +18,10 @@ import com.google.android.material.textview.MaterialTextView import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize class OpenSourceLibraryLicenseScreen( private val name: String, @@ -44,7 +44,7 @@ class OpenSourceLibraryLicenseScreen( AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.website), + title = localize(MR.strings.website), icon = Icons.Default.Public, onClick = { uriHandler.openUri(website) }, ), diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/OpenSourceLicensesScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/OpenSourceLicensesScreen.kt index f1a8ae47c8..12f4b62905 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/OpenSourceLicensesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/about/OpenSourceLicensesScreen.kt @@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer @@ -12,8 +11,9 @@ import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults import com.mikepenz.aboutlibraries.ui.compose.util.htmlReadyLicenseContent import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize class OpenSourceLicensesScreen : Screen() { @@ -23,7 +23,7 @@ class OpenSourceLicensesScreen : Screen() { Scaffold( topBar = { scrollBehavior -> AppBar( - title = stringResource(R.string.licenses), + title = localize(MR.strings.licenses), navigateUp = navigator::pop, scrollBehavior = scrollBehavior, ) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt index 036926f1ac..fc681d1900 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt @@ -27,7 +27,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastMap import cafe.adriel.voyager.core.model.StateScreenModel @@ -39,7 +38,6 @@ import eu.kanade.presentation.browse.components.SourceIcon import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.system.toast import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.flow.collectLatest @@ -51,7 +49,9 @@ import tachiyomi.data.Database import tachiyomi.domain.source.interactor.GetSourcesWithNonLibraryManga import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.SourceWithCount +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.util.selectedBackground @@ -81,20 +81,20 @@ class ClearDatabaseScreen : Screen() { model.removeMangaBySourceId() model.clearSelection() model.hideConfirmation() - context.toast(R.string.clear_database_completed) + context.toast(MR.strings.clear_database_completed) } }, ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, dismissButton = { TextButton(onClick = model::hideConfirmation) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, text = { - Text(text = stringResource(R.string.clear_database_confirmation)) + Text(text = localize(MR.strings.clear_database_confirmation)) }, ) } @@ -102,19 +102,19 @@ class ClearDatabaseScreen : Screen() { Scaffold( topBar = { scrollBehavior -> AppBar( - title = stringResource(R.string.pref_clear_database), + title = localize(MR.strings.pref_clear_database), navigateUp = navigator::pop, actions = { if (s.items.isNotEmpty()) { AppBarActions( actions = persistentListOf( AppBar.Action( - title = stringResource(R.string.action_select_all), + title = localize(MR.strings.action_select_all), icon = Icons.Outlined.SelectAll, onClick = model::selectAll, ), AppBar.Action( - title = stringResource(R.string.action_select_all), + title = localize(MR.strings.action_select_all), icon = Icons.Outlined.FlipToBack, onClick = model::invertSelection, ), @@ -128,7 +128,7 @@ class ClearDatabaseScreen : Screen() { ) { contentPadding -> if (s.items.isEmpty()) { EmptyScreen( - message = stringResource(R.string.database_clean), + message = localize(MR.strings.database_clean), modifier = Modifier.padding(contentPadding), ) } else { @@ -160,7 +160,7 @@ class ClearDatabaseScreen : Screen() { enabled = s.selection.isNotEmpty(), ) { Text( - text = stringResource(R.string.action_delete), + text = localize(MR.strings.action_delete), color = MaterialTheme.colorScheme.onPrimary, ) } @@ -196,7 +196,7 @@ class ClearDatabaseScreen : Screen() { text = source.visualName, style = MaterialTheme.typography.bodyMedium, ) - Text(text = stringResource(R.string.clear_database_source_item_count, count)) + Text(text = localize(MR.strings.clear_database_source_item_count, count)) } Checkbox( checked = isSelected, diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/data/CreateBackupScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/data/CreateBackupScreen.kt index b1a5d9502f..9117f04df1 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/data/CreateBackupScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/data/CreateBackupScreen.kt @@ -22,7 +22,6 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel @@ -30,7 +29,6 @@ import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.backup.BackupCreateFlags import eu.kanade.tachiyomi.data.backup.BackupCreateJob import eu.kanade.tachiyomi.data.backup.models.Backup @@ -41,9 +39,11 @@ import kotlinx.collections.immutable.minus import kotlinx.collections.immutable.plus import kotlinx.collections.immutable.toPersistentSet import kotlinx.coroutines.flow.update +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize class CreateBackupScreen : Screen() { @@ -71,7 +71,7 @@ class CreateBackupScreen : Screen() { Scaffold( topBar = { AppBar( - title = stringResource(R.string.pref_create_backup), + title = localize(MR.strings.pref_create_backup), navigateUp = navigator::pop, scrollBehavior = it, ) @@ -89,7 +89,7 @@ class CreateBackupScreen : Screen() { ) { item { LabeledCheckbox( - label = stringResource(R.string.manga), + label = localize(MR.strings.manga), checked = true, onCheckedChange = {}, enabled = false, @@ -98,7 +98,7 @@ class CreateBackupScreen : Screen() { BackupChoices.forEach { (k, v) -> item { LabeledCheckbox( - label = stringResource(v), + label = localize(v), checked = state.flags.contains(k), onCheckedChange = { model.toggleFlag(k) @@ -117,20 +117,20 @@ class CreateBackupScreen : Screen() { onClick = { if (!BackupCreateJob.isManualJobRunning(context)) { if (DeviceUtil.isMiui && DeviceUtil.isMiuiOptimizationDisabled()) { - context.toast(R.string.restore_miui_warning, Toast.LENGTH_LONG) + context.toast(MR.strings.restore_miui_warning, Toast.LENGTH_LONG) } try { chooseBackupDir.launch(Backup.getFilename()) } catch (e: ActivityNotFoundException) { - context.toast(R.string.file_picker_error) + context.toast(MR.strings.file_picker_error) } } else { - context.toast(R.string.backup_in_progress) + context.toast(MR.strings.backup_in_progress) } }, ) { Text( - text = stringResource(R.string.action_create), + text = localize(MR.strings.action_create), color = MaterialTheme.colorScheme.onPrimary, ) } @@ -163,10 +163,10 @@ private class CreateBackupScreenModel : StateScreenModel ListPreferenceWidget( }, confirmButton = { TextButton(onClick = { isDialogShown = false }) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, ) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/widget/MultiSelectListPreferenceWidget.kt b/app/src/main/java/eu/kanade/presentation/more/settings/widget/MultiSelectListPreferenceWidget.kt index 3059be939e..be4fbe9a04 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/widget/MultiSelectListPreferenceWidget.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/widget/MultiSelectListPreferenceWidget.kt @@ -10,11 +10,11 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.runtime.toMutableStateList -import androidx.compose.ui.res.stringResource import androidx.compose.ui.window.DialogProperties import eu.kanade.presentation.more.settings.Preference -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.LabeledCheckbox +import tachiyomi.presentation.core.i18n.localize @Composable fun MultiSelectListPreferenceWidget( @@ -70,12 +70,12 @@ fun MultiSelectListPreferenceWidget( isDialogShown = false }, ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, dismissButton = { TextButton(onClick = { isDialogShown = false }) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, ) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt b/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt index d8544d156e..02e9de53f4 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/widget/TrackingPreferenceWidget.kt @@ -15,12 +15,12 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted import eu.kanade.presentation.track.components.TrackLogoIcon -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.track.Tracker +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize @Composable fun TrackingPreferenceWidget( @@ -55,7 +55,7 @@ fun TrackingPreferenceWidget( .padding(4.dp) .size(32.dp), tint = Color(0xFF4CAF50), - contentDescription = stringResource(R.string.login_success), + contentDescription = localize(MR.strings.login_success), ) } } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/widget/TriStateListDialog.kt b/app/src/main/java/eu/kanade/presentation/more/settings/widget/TriStateListDialog.kt index 220c9a3187..0014f5dc54 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/widget/TriStateListDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/widget/TriStateListDialog.kt @@ -27,9 +27,9 @@ import androidx.compose.runtime.toMutableStateList import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.isScrolledToEnd import tachiyomi.presentation.core.util.isScrolledToStart @@ -102,11 +102,11 @@ fun TriStateListDialog( } else { MaterialTheme.colorScheme.primary }, - contentDescription = stringResource( + contentDescription = localize( when (state) { - State.UNCHECKED -> R.string.not_selected - State.CHECKED -> R.string.selected - State.INVERSED -> R.string.disabled + State.UNCHECKED -> MR.strings.not_selected + State.CHECKED -> MR.strings.selected + State.INVERSED -> MR.strings.disabled }, ), ) @@ -130,7 +130,7 @@ fun TriStateListDialog( }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, confirmButton = { @@ -145,7 +145,7 @@ fun TriStateListDialog( onValueChanged(included, excluded) }, ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, ) diff --git a/app/src/main/java/eu/kanade/presentation/more/stats/StatsScreenContent.kt b/app/src/main/java/eu/kanade/presentation/more/stats/StatsScreenContent.kt index 6134b8f572..71bbb73b96 100644 --- a/app/src/main/java/eu/kanade/presentation/more/stats/StatsScreenContent.kt +++ b/app/src/main/java/eu/kanade/presentation/more/stats/StatsScreenContent.kt @@ -13,14 +13,14 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import eu.kanade.presentation.more.stats.components.StatsItem import eu.kanade.presentation.more.stats.components.StatsOverviewItem import eu.kanade.presentation.more.stats.components.StatsSection import eu.kanade.presentation.more.stats.data.StatsData import eu.kanade.presentation.util.toDurationString -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import java.util.Locale import kotlin.time.DurationUnit import kotlin.time.toDuration @@ -55,28 +55,28 @@ fun StatsScreenContent( private fun OverviewSection( data: StatsData.Overview, ) { - val none = stringResource(R.string.none) + val none = localize(MR.strings.none) val context = LocalContext.current val readDurationString = remember(data.totalReadDuration) { data.totalReadDuration .toDuration(DurationUnit.MILLISECONDS) .toDurationString(context, fallback = none) } - StatsSection(R.string.label_overview_section) { + StatsSection(MR.strings.label_overview_section) { Row { StatsOverviewItem( title = data.libraryMangaCount.toString(), - subtitle = stringResource(R.string.in_library), + subtitle = localize(MR.strings.in_library), icon = Icons.Outlined.CollectionsBookmark, ) StatsOverviewItem( title = data.completedMangaCount.toString(), - subtitle = stringResource(R.string.label_completed_titles), + subtitle = localize(MR.strings.label_completed_titles), icon = Icons.Outlined.LocalLibrary, ) StatsOverviewItem( title = readDurationString, - subtitle = stringResource(R.string.label_read_duration), + subtitle = localize(MR.strings.label_read_duration), icon = Icons.Outlined.Schedule, ) } @@ -87,19 +87,19 @@ private fun OverviewSection( private fun TitlesStats( data: StatsData.Titles, ) { - StatsSection(R.string.label_titles_section) { + StatsSection(MR.strings.label_titles_section) { Row { StatsItem( data.globalUpdateItemCount.toString(), - stringResource(R.string.label_titles_in_global_update), + localize(MR.strings.label_titles_in_global_update), ) StatsItem( data.startedMangaCount.toString(), - stringResource(R.string.label_started), + localize(MR.strings.label_started), ) StatsItem( data.localMangaCount.toString(), - stringResource(R.string.label_local), + localize(MR.strings.label_local), ) } } @@ -109,19 +109,19 @@ private fun TitlesStats( private fun ChapterStats( data: StatsData.Chapters, ) { - StatsSection(R.string.chapters) { + StatsSection(MR.strings.chapters) { Row { StatsItem( data.totalChapterCount.toString(), - stringResource(R.string.label_total_chapters), + localize(MR.strings.label_total_chapters), ) StatsItem( data.readChapterCount.toString(), - stringResource(R.string.label_read_chapters), + localize(MR.strings.label_read_chapters), ) StatsItem( data.downloadCount.toString(), - stringResource(R.string.label_downloaded), + localize(MR.strings.label_downloaded), ) } } @@ -131,7 +131,7 @@ private fun ChapterStats( private fun TrackerStats( data: StatsData.Trackers, ) { - val notApplicable = stringResource(R.string.not_applicable) + val notApplicable = localize(MR.strings.not_applicable) val meanScoreStr = remember(data.trackedTitleCount, data.meanScore) { if (data.trackedTitleCount > 0 && !data.meanScore.isNaN()) { // All other numbers are localized in English @@ -140,19 +140,19 @@ private fun TrackerStats( notApplicable } } - StatsSection(R.string.label_tracker_section) { + StatsSection(MR.strings.label_tracker_section) { Row { StatsItem( data.trackedTitleCount.toString(), - stringResource(R.string.label_tracked_titles), + localize(MR.strings.label_tracked_titles), ) StatsItem( meanScoreStr, - stringResource(R.string.label_mean_score), + localize(MR.strings.label_mean_score), ) StatsItem( data.trackerCount.toString(), - stringResource(R.string.label_used), + localize(MR.strings.label_used), ) } } diff --git a/app/src/main/java/eu/kanade/presentation/more/stats/components/StatsSection.kt b/app/src/main/java/eu/kanade/presentation/more/stats/components/StatsSection.kt index 329b04702c..cb4596bfdb 100644 --- a/app/src/main/java/eu/kanade/presentation/more/stats/components/StatsSection.kt +++ b/app/src/main/java/eu/kanade/presentation/more/stats/components/StatsSection.kt @@ -1,6 +1,5 @@ package eu.kanade.presentation.more.stats.components -import androidx.annotation.StringRes import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -9,17 +8,18 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource +import dev.icerock.moko.resources.StringResource import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize @Composable fun StatsSection( - @StringRes titleRes: Int, + titleRes: StringResource, content: @Composable () -> Unit, ) { Text( modifier = Modifier.padding(horizontal = MaterialTheme.padding.extraLarge), - text = stringResource(titleRes), + text = localize(titleRes), style = MaterialTheme.typography.titleSmall, ) ElevatedCard( diff --git a/app/src/main/java/eu/kanade/presentation/reader/ChapterTransition.kt b/app/src/main/java/eu/kanade/presentation/reader/ChapterTransition.kt index cb6ca9a8bf..4f94b3e3d6 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/ChapterTransition.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/ChapterTransition.kt @@ -26,8 +26,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.pluralStringResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.Placeholder import androidx.compose.ui.text.PlaceholderVerticalAlign import androidx.compose.ui.text.buildAnnotatedString @@ -36,13 +34,15 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.ChapterImpl import eu.kanade.tachiyomi.data.database.models.toDomainChapter import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import tachiyomi.domain.chapter.service.calculateChapterGap +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize +import tachiyomi.presentation.core.i18n.localizePlural import tachiyomi.presentation.core.util.secondaryItemAlpha @Composable @@ -58,25 +58,25 @@ fun ChapterTransition( when (transition) { is ChapterTransition.Prev -> { TransitionText( - topLabel = stringResource(R.string.transition_previous), + topLabel = localize(MR.strings.transition_previous), topChapter = goingToChapter, topChapterDownloaded = goingToChapterDownloaded, - bottomLabel = stringResource(R.string.transition_current), + bottomLabel = localize(MR.strings.transition_current), bottomChapter = currChapter, bottomChapterDownloaded = currChapterDownloaded, - fallbackLabel = stringResource(R.string.transition_no_previous), + fallbackLabel = localize(MR.strings.transition_no_previous), chapterGap = calculateChapterGap(currChapter.toDomainChapter(), goingToChapter?.toDomainChapter()), ) } is ChapterTransition.Next -> { TransitionText( - topLabel = stringResource(R.string.transition_finished), + topLabel = localize(MR.strings.transition_finished), topChapter = currChapter, topChapterDownloaded = currChapterDownloaded, - bottomLabel = stringResource(R.string.transition_next), + bottomLabel = localize(MR.strings.transition_next), bottomChapter = goingToChapter, bottomChapterDownloaded = goingToChapterDownloaded, - fallbackLabel = stringResource(R.string.transition_no_next), + fallbackLabel = localize(MR.strings.transition_no_next), chapterGap = calculateChapterGap(goingToChapter?.toDomainChapter(), currChapter.toDomainChapter()), ) } @@ -191,7 +191,7 @@ private fun ChapterGapWarning( ) Text( - text = pluralStringResource(R.plurals.missing_chapters_warning, count = gapCount, gapCount), + text = localizePlural(MR.plurals.missing_chapters_warning, count = gapCount, gapCount), style = MaterialTheme.typography.bodyMedium, ) } @@ -245,7 +245,7 @@ private fun ChapterText( ) { Icon( imageVector = Icons.Filled.CheckCircle, - contentDescription = stringResource(R.string.label_downloaded), + contentDescription = localize(MR.strings.label_downloaded), ) }, ), diff --git a/app/src/main/java/eu/kanade/presentation/reader/OrientationSelectDialog.kt b/app/src/main/java/eu/kanade/presentation/reader/OrientationSelectDialog.kt index 9d3b734cb3..27f4173c9f 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/OrientationSelectDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/OrientationSelectDialog.kt @@ -12,18 +12,19 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.PreviewLightDark +import dev.icerock.moko.resources.StringResource import eu.kanade.domain.manga.model.readerOrientation import eu.kanade.presentation.components.AdaptiveSheet import eu.kanade.presentation.reader.components.ModeSelectionDialog import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.SettingsIconGrid import tachiyomi.presentation.core.components.material.IconToggleButton +import tachiyomi.presentation.core.i18n.localize private val ReaderOrientationsWithoutDefault = ReaderOrientation.entries - ReaderOrientation.DEFAULT @@ -31,7 +32,7 @@ private val ReaderOrientationsWithoutDefault = ReaderOrientation.entries - Reade fun OrientationSelectDialog( onDismissRequest: () -> Unit, screenModel: ReaderSettingsScreenModel, - onChange: (Int) -> Unit, + onChange: (StringResource) -> Unit, ) { val manga by screenModel.mangaFlow.collectAsState() val orientation = remember(manga) { ReaderOrientation.fromPreference(manga?.readerOrientation?.toInt()) } @@ -63,7 +64,7 @@ private fun DialogContent( }.takeIf { orientation != ReaderOrientation.DEFAULT }, onApply = { onChangeOrientation(selected) }, ) { - SettingsIconGrid(R.string.rotation_type) { + SettingsIconGrid(MR.strings.rotation_type) { items(ReaderOrientationsWithoutDefault) { mode -> IconToggleButton( checked = mode == selected, @@ -72,7 +73,7 @@ private fun DialogContent( }, modifier = Modifier.fillMaxWidth(), imageVector = ImageVector.vectorResource(mode.iconRes), - title = stringResource(mode.stringRes), + title = localize(mode.stringRes), ) } } diff --git a/app/src/main/java/eu/kanade/presentation/reader/ReaderPageActionsDialog.kt b/app/src/main/java/eu/kanade/presentation/reader/ReaderPageActionsDialog.kt index 4c488cf91c..5120a7de2f 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/ReaderPageActionsDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/ReaderPageActionsDialog.kt @@ -17,12 +17,12 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import eu.kanade.presentation.components.AdaptiveSheet -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.ActionButton import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize @Composable fun ReaderPageActionsDialog( @@ -42,13 +42,13 @@ fun ReaderPageActionsDialog( ) { ActionButton( modifier = Modifier.weight(1f), - title = stringResource(R.string.set_as_cover), + title = localize(MR.strings.set_as_cover), icon = Icons.Outlined.Photo, onClick = { showSetCoverDialog = true }, ) ActionButton( modifier = Modifier.weight(1f), - title = stringResource(R.string.action_share), + title = localize(MR.strings.action_share), icon = Icons.Outlined.Share, onClick = { onShare() @@ -57,7 +57,7 @@ fun ReaderPageActionsDialog( ) ActionButton( modifier = Modifier.weight(1f), - title = stringResource(R.string.action_save), + title = localize(MR.strings.action_save), icon = Icons.Outlined.Save, onClick = { onSave() @@ -85,16 +85,16 @@ private fun SetCoverDialog( ) { AlertDialog( text = { - Text(stringResource(R.string.confirm_set_image_as_cover)) + Text(localize(MR.strings.confirm_set_image_as_cover)) }, confirmButton = { TextButton(onClick = onConfirm) { - Text(stringResource(R.string.action_ok)) + Text(localize(MR.strings.action_ok)) } }, dismissButton = { TextButton(onClick = onDismiss) { - Text(stringResource(R.string.action_cancel)) + Text(localize(MR.strings.action_cancel)) } }, onDismissRequest = onDismiss, diff --git a/app/src/main/java/eu/kanade/presentation/reader/ReadingModeSelectDialog.kt b/app/src/main/java/eu/kanade/presentation/reader/ReadingModeSelectDialog.kt index a34d14e5f5..3590f4601a 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/ReadingModeSelectDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/ReadingModeSelectDialog.kt @@ -12,18 +12,19 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.PreviewLightDark +import dev.icerock.moko.resources.StringResource import eu.kanade.domain.manga.model.readingMode import eu.kanade.presentation.components.AdaptiveSheet import eu.kanade.presentation.reader.components.ModeSelectionDialog import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.SettingsIconGrid import tachiyomi.presentation.core.components.material.IconToggleButton +import tachiyomi.presentation.core.i18n.localize private val ReadingModesWithoutDefault = ReadingMode.entries - ReadingMode.DEFAULT @@ -31,7 +32,7 @@ private val ReadingModesWithoutDefault = ReadingMode.entries - ReadingMode.DEFAU fun ReadingModeSelectDialog( onDismissRequest: () -> Unit, screenModel: ReaderSettingsScreenModel, - onChange: (Int) -> Unit, + onChange: (StringResource) -> Unit, ) { val manga by screenModel.mangaFlow.collectAsState() val readingMode = remember(manga) { ReadingMode.fromPreference(manga?.readingMode?.toInt()) } @@ -59,7 +60,7 @@ private fun DialogContent( onUseDefault = { onChangeReadingMode(ReadingMode.DEFAULT) }.takeIf { readingMode != ReadingMode.DEFAULT }, onApply = { onChangeReadingMode(selected) }, ) { - SettingsIconGrid(R.string.pref_category_reading_mode) { + SettingsIconGrid(MR.strings.pref_category_reading_mode) { items(ReadingModesWithoutDefault) { mode -> IconToggleButton( checked = mode == selected, @@ -68,7 +69,7 @@ private fun DialogContent( }, modifier = Modifier.fillMaxWidth(), imageVector = ImageVector.vectorResource(mode.iconRes), - title = stringResource(mode.stringRes), + title = localize(mode.stringRes), ) } } diff --git a/app/src/main/java/eu/kanade/presentation/reader/appbars/BottomReaderBar.kt b/app/src/main/java/eu/kanade/presentation/reader/appbars/BottomReaderBar.kt index 726095a537..7c9faa988f 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/appbars/BottomReaderBar.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/appbars/BottomReaderBar.kt @@ -14,11 +14,12 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize @Composable fun BottomReaderBar( @@ -42,28 +43,28 @@ fun BottomReaderBar( IconButton(onClick = onClickReadingMode) { Icon( painter = painterResource(readingMode.iconRes), - contentDescription = stringResource(R.string.viewer), + contentDescription = localize(MR.strings.viewer), ) } IconButton(onClick = onClickOrientation) { Icon( painter = painterResource(orientation.iconRes), - contentDescription = stringResource(R.string.rotation_type), + contentDescription = localize(MR.strings.rotation_type), ) } IconButton(onClick = onClickCropBorder) { Icon( painter = painterResource(if (cropEnabled) R.drawable.ic_crop_24dp else R.drawable.ic_crop_off_24dp), - contentDescription = stringResource(R.string.pref_crop_borders), + contentDescription = localize(MR.strings.pref_crop_borders), ) } IconButton(onClick = onClickSettings) { Icon( imageVector = Icons.Outlined.Settings, - contentDescription = stringResource(R.string.action_settings), + contentDescription = localize(MR.strings.action_settings), ) } } diff --git a/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt b/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt index a57d63cc93..dfc9969b85 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt @@ -18,18 +18,18 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.reader.components.ChapterNavigator -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode import eu.kanade.tachiyomi.ui.reader.viewer.Viewer import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize private val animationSpec = tween(200) @@ -103,11 +103,11 @@ fun ReaderAppBars( .apply { add( AppBar.Action( - title = stringResource( + title = localize( if (bookmarked) { - R.string.action_remove_bookmark + MR.strings.action_remove_bookmark } else { - R.string.action_bookmark + MR.strings.action_bookmark }, ), icon = if (bookmarked) { @@ -121,7 +121,7 @@ fun ReaderAppBars( onOpenInWebView?.let { add( AppBar.OverflowAction( - title = stringResource(R.string.action_open_in_web_view), + title = localize(MR.strings.action_open_in_web_view), onClick = it, ), ) @@ -129,7 +129,7 @@ fun ReaderAppBars( onShare?.let { add( AppBar.OverflowAction( - title = stringResource(R.string.action_share), + title = localize(MR.strings.action_share), onClick = it, ), ) diff --git a/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt b/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt index a2a3a5c782..d18915c5aa 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt @@ -30,11 +30,11 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import eu.kanade.presentation.util.isTabletUi -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import kotlin.math.roundToInt @Composable @@ -77,8 +77,8 @@ fun ChapterNavigator( ) { Icon( imageVector = Icons.Outlined.SkipPrevious, - contentDescription = stringResource( - if (isRtl) R.string.action_next_chapter else R.string.action_previous_chapter, + contentDescription = localize( + if (isRtl) MR.strings.action_next_chapter else MR.strings.action_previous_chapter, ), ) } @@ -129,8 +129,8 @@ fun ChapterNavigator( ) { Icon( imageVector = Icons.Outlined.SkipNext, - contentDescription = stringResource( - if (isRtl) R.string.action_previous_chapter else R.string.action_next_chapter, + contentDescription = localize( + if (isRtl) MR.strings.action_previous_chapter else MR.strings.action_next_chapter, ), ) } diff --git a/app/src/main/java/eu/kanade/presentation/reader/components/ModeSelectionDialog.kt b/app/src/main/java/eu/kanade/presentation/reader/components/ModeSelectionDialog.kt index 045155b692..d519e31773 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/components/ModeSelectionDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/components/ModeSelectionDialog.kt @@ -16,12 +16,12 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.SettingsItemsPaddings +import tachiyomi.presentation.core.i18n.localize @Composable fun ModeSelectionDialog( @@ -40,7 +40,7 @@ fun ModeSelectionDialog( ) { onUseDefault?.let { OutlinedButton(onClick = it) { - Text(text = stringResource(R.string.action_revert_to_default)) + Text(text = localize(MR.strings.action_revert_to_default)) } } @@ -57,7 +57,7 @@ fun ModeSelectionDialog( imageVector = Icons.Outlined.Check, contentDescription = null, ) - Text(text = stringResource(R.string.action_apply)) + Text(text = localize(MR.strings.action_apply)) } } } diff --git a/app/src/main/java/eu/kanade/presentation/reader/settings/ColorFilterPage.kt b/app/src/main/java/eu/kanade/presentation/reader/settings/ColorFilterPage.kt index d38220d9b7..3b8d39b788 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/settings/ColorFilterPage.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/settings/ColorFilterPage.kt @@ -6,17 +6,17 @@ import androidx.compose.material3.FilterChip import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.ui.res.stringResource import androidx.core.graphics.alpha import androidx.core.graphics.blue import androidx.core.graphics.green import androidx.core.graphics.red -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel import tachiyomi.core.preference.getAndSet +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.CheckboxItem import tachiyomi.presentation.core.components.SettingsChipRow import tachiyomi.presentation.core.components.SliderItem +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.collectAsState @Composable @@ -24,25 +24,25 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) val colorFilterModes = buildList { addAll( listOf( - R.string.label_default, - R.string.filter_mode_multiply, - R.string.filter_mode_screen, + MR.strings.label_default, + MR.strings.filter_mode_multiply, + MR.strings.filter_mode_screen, ), ) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { addAll( listOf( - R.string.filter_mode_overlay, - R.string.filter_mode_lighten, - R.string.filter_mode_darken, + MR.strings.filter_mode_overlay, + MR.strings.filter_mode_lighten, + MR.strings.filter_mode_darken, ), ) } - }.map { stringResource(it) } + }.map { localize(it) } val customBrightness by screenModel.preferences.customBrightness().collectAsState() CheckboxItem( - label = stringResource(R.string.pref_custom_brightness), + label = localize(MR.strings.pref_custom_brightness), pref = screenModel.preferences.customBrightness(), ) @@ -55,7 +55,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) if (customBrightness) { val customBrightnessValue by screenModel.preferences.customBrightnessValue().collectAsState() SliderItem( - label = stringResource(R.string.pref_custom_brightness), + label = localize(MR.strings.pref_custom_brightness), min = -75, max = 100, value = customBrightnessValue, @@ -66,13 +66,13 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) val colorFilter by screenModel.preferences.colorFilter().collectAsState() CheckboxItem( - label = stringResource(R.string.pref_custom_color_filter), + label = localize(MR.strings.pref_custom_color_filter), pref = screenModel.preferences.colorFilter(), ) if (colorFilter) { val colorFilterValue by screenModel.preferences.colorFilterValue().collectAsState() SliderItem( - label = stringResource(R.string.color_filter_r_value), + label = localize(MR.strings.color_filter_r_value), max = 255, value = colorFilterValue.red, valueText = colorFilterValue.red.toString(), @@ -83,7 +83,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) }, ) SliderItem( - label = stringResource(R.string.color_filter_g_value), + label = localize(MR.strings.color_filter_g_value), max = 255, value = colorFilterValue.green, valueText = colorFilterValue.green.toString(), @@ -94,7 +94,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) }, ) SliderItem( - label = stringResource(R.string.color_filter_b_value), + label = localize(MR.strings.color_filter_b_value), max = 255, value = colorFilterValue.blue, valueText = colorFilterValue.blue.toString(), @@ -105,7 +105,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) }, ) SliderItem( - label = stringResource(R.string.color_filter_a_value), + label = localize(MR.strings.color_filter_a_value), max = 255, value = colorFilterValue.alpha, valueText = colorFilterValue.alpha.toString(), @@ -117,7 +117,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) ) val colorFilterMode by screenModel.preferences.colorFilterMode().collectAsState() - SettingsChipRow(R.string.pref_color_filter_mode) { + SettingsChipRow(MR.strings.pref_color_filter_mode) { colorFilterModes.mapIndexed { index, it -> FilterChip( selected = colorFilterMode == index, @@ -129,11 +129,11 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) } CheckboxItem( - label = stringResource(R.string.pref_grayscale), + label = localize(MR.strings.pref_grayscale), pref = screenModel.preferences.grayscale(), ) CheckboxItem( - label = stringResource(R.string.pref_inverted_colors), + label = localize(MR.strings.pref_inverted_colors), pref = screenModel.preferences.invertedColors(), ) } diff --git a/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt b/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt index 5fe65eb2f0..1b236feb42 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt @@ -5,72 +5,72 @@ import androidx.compose.material3.FilterChip import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.ui.res.stringResource -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.CheckboxItem import tachiyomi.presentation.core.components.SettingsChipRow +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.collectAsState private val themes = listOf( - R.string.black_background to 1, - R.string.gray_background to 2, - R.string.white_background to 0, - R.string.automatic_background to 3, + MR.strings.black_background to 1, + MR.strings.gray_background to 2, + MR.strings.white_background to 0, + MR.strings.automatic_background to 3, ) @Composable internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) { val readerTheme by screenModel.preferences.readerTheme().collectAsState() - SettingsChipRow(R.string.pref_reader_theme) { + SettingsChipRow(MR.strings.pref_reader_theme) { themes.map { (labelRes, value) -> FilterChip( selected = readerTheme == value, onClick = { screenModel.preferences.readerTheme().set(value) }, - label = { Text(stringResource(labelRes)) }, + label = { Text(localize(labelRes)) }, ) } } CheckboxItem( - label = stringResource(R.string.pref_show_page_number), + label = localize(MR.strings.pref_show_page_number), pref = screenModel.preferences.showPageNumber(), ) CheckboxItem( - label = stringResource(R.string.pref_fullscreen), + label = localize(MR.strings.pref_fullscreen), pref = screenModel.preferences.fullscreen(), ) if (screenModel.hasDisplayCutout) { CheckboxItem( - label = stringResource(R.string.pref_cutout_short), + label = localize(MR.strings.pref_cutout_short), pref = screenModel.preferences.cutoutShort(), ) } CheckboxItem( - label = stringResource(R.string.pref_keep_screen_on), + label = localize(MR.strings.pref_keep_screen_on), pref = screenModel.preferences.keepScreenOn(), ) CheckboxItem( - label = stringResource(R.string.pref_read_with_long_tap), + label = localize(MR.strings.pref_read_with_long_tap), pref = screenModel.preferences.readWithLongTap(), ) CheckboxItem( - label = stringResource(R.string.pref_always_show_chapter_transition), + label = localize(MR.strings.pref_always_show_chapter_transition), pref = screenModel.preferences.alwaysShowChapterTransition(), ) CheckboxItem( - label = stringResource(R.string.pref_page_transitions), + label = localize(MR.strings.pref_page_transitions), pref = screenModel.preferences.pageTransitions(), ) CheckboxItem( - label = stringResource(R.string.pref_flash_page), + label = localize(MR.strings.pref_flash_page), pref = screenModel.preferences.flashOnPageChange(), ) } diff --git a/app/src/main/java/eu/kanade/presentation/reader/settings/ReaderSettingsDialog.kt b/app/src/main/java/eu/kanade/presentation/reader/settings/ReaderSettingsDialog.kt index 08dc5ae5e2..7360a1c0a5 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/settings/ReaderSettingsDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/settings/ReaderSettingsDialog.kt @@ -11,13 +11,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.res.stringResource import androidx.compose.ui.window.DialogWindowProvider import eu.kanade.presentation.components.TabbedDialog import eu.kanade.presentation.components.TabbedDialogPaddings -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize @Composable fun ReaderSettingsDialog( @@ -27,9 +27,9 @@ fun ReaderSettingsDialog( screenModel: ReaderSettingsScreenModel, ) { val tabTitles = persistentListOf( - stringResource(R.string.pref_category_reading_mode), - stringResource(R.string.pref_category_general), - stringResource(R.string.custom_filter), + localize(MR.strings.pref_category_reading_mode), + localize(MR.strings.pref_category_general), + localize(MR.strings.custom_filter), ) val pagerState = rememberPagerState { tabTitles.size } diff --git a/app/src/main/java/eu/kanade/presentation/reader/settings/ReadingModePage.kt b/app/src/main/java/eu/kanade/presentation/reader/settings/ReadingModePage.kt index 8bf1d0079f..6e0fc893e9 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/settings/ReadingModePage.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/settings/ReadingModePage.kt @@ -7,45 +7,45 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember -import androidx.compose.ui.res.stringResource import eu.kanade.domain.manga.model.readerOrientation import eu.kanade.domain.manga.model.readingMode -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.CheckboxItem import tachiyomi.presentation.core.components.HeadingItem import tachiyomi.presentation.core.components.SettingsChipRow import tachiyomi.presentation.core.components.SliderItem +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.collectAsState import java.text.NumberFormat @Composable internal fun ColumnScope.ReadingModePage(screenModel: ReaderSettingsScreenModel) { - HeadingItem(R.string.pref_category_for_this_series) + HeadingItem(MR.strings.pref_category_for_this_series) val manga by screenModel.mangaFlow.collectAsState() val readingMode = remember(manga) { ReadingMode.fromPreference(manga?.readingMode?.toInt()) } - SettingsChipRow(R.string.pref_category_reading_mode) { + SettingsChipRow(MR.strings.pref_category_reading_mode) { ReadingMode.entries.map { FilterChip( selected = it == readingMode, onClick = { screenModel.onChangeReadingMode(it) }, - label = { Text(stringResource(it.stringRes)) }, + label = { Text(localize(it.stringRes)) }, ) } } val orientation = remember(manga) { ReaderOrientation.fromPreference(manga?.readerOrientation?.toInt()) } - SettingsChipRow(R.string.rotation_type) { + SettingsChipRow(MR.strings.rotation_type) { ReaderOrientation.entries.map { FilterChip( selected = it == orientation, onClick = { screenModel.onChangeOrientation(it) }, - label = { Text(stringResource(it.stringRes)) }, + label = { Text(localize(it.stringRes)) }, ) } } @@ -60,7 +60,7 @@ internal fun ColumnScope.ReadingModePage(screenModel: ReaderSettingsScreenModel) @Composable private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenModel) { - HeadingItem(R.string.pager_viewer) + HeadingItem(MR.strings.pager_viewer) val navigationModePager by screenModel.preferences.navigationModePager().collectAsState() val pagerNavInverted by screenModel.preferences.pagerNavInverted().collectAsState() @@ -72,64 +72,64 @@ private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenMod ) val imageScaleType by screenModel.preferences.imageScaleType().collectAsState() - SettingsChipRow(R.string.pref_image_scale_type) { + SettingsChipRow(MR.strings.pref_image_scale_type) { ReaderPreferences.ImageScaleType.mapIndexed { index, it -> FilterChip( selected = imageScaleType == index + 1, onClick = { screenModel.preferences.imageScaleType().set(index + 1) }, - label = { Text(stringResource(it)) }, + label = { Text(localize(it)) }, ) } } val zoomStart by screenModel.preferences.zoomStart().collectAsState() - SettingsChipRow(R.string.pref_zoom_start) { + SettingsChipRow(MR.strings.pref_zoom_start) { ReaderPreferences.ZoomStart.mapIndexed { index, it -> FilterChip( selected = zoomStart == index + 1, onClick = { screenModel.preferences.zoomStart().set(index + 1) }, - label = { Text(stringResource(it)) }, + label = { Text(localize(it)) }, ) } } CheckboxItem( - label = stringResource(R.string.pref_crop_borders), + label = localize(MR.strings.pref_crop_borders), pref = screenModel.preferences.cropBorders(), ) CheckboxItem( - label = stringResource(R.string.pref_landscape_zoom), + label = localize(MR.strings.pref_landscape_zoom), pref = screenModel.preferences.landscapeZoom(), ) CheckboxItem( - label = stringResource(R.string.pref_navigate_pan), + label = localize(MR.strings.pref_navigate_pan), pref = screenModel.preferences.navigateToPan(), ) val dualPageSplitPaged by screenModel.preferences.dualPageSplitPaged().collectAsState() CheckboxItem( - label = stringResource(R.string.pref_dual_page_split), + label = localize(MR.strings.pref_dual_page_split), pref = screenModel.preferences.dualPageSplitPaged(), ) if (dualPageSplitPaged) { CheckboxItem( - label = stringResource(R.string.pref_dual_page_invert), + label = localize(MR.strings.pref_dual_page_invert), pref = screenModel.preferences.dualPageInvertPaged(), ) } val dualPageRotateToFit by screenModel.preferences.dualPageRotateToFit().collectAsState() CheckboxItem( - label = stringResource(R.string.pref_page_rotate), + label = localize(MR.strings.pref_page_rotate), pref = screenModel.preferences.dualPageRotateToFit(), ) if (dualPageRotateToFit) { CheckboxItem( - label = stringResource(R.string.pref_page_rotate_invert), + label = localize(MR.strings.pref_page_rotate_invert), pref = screenModel.preferences.dualPageRotateToFitInvert(), ) } @@ -139,7 +139,7 @@ private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenMod private fun ColumnScope.WebtoonViewerSettings(screenModel: ReaderSettingsScreenModel) { val numberFormat = remember { NumberFormat.getPercentInstance() } - HeadingItem(R.string.webtoon_viewer) + HeadingItem(MR.strings.webtoon_viewer) val navigationModeWebtoon by screenModel.preferences.navigationModeWebtoon().collectAsState() val webtoonNavInverted by screenModel.preferences.webtoonNavInverted().collectAsState() @@ -152,7 +152,7 @@ private fun ColumnScope.WebtoonViewerSettings(screenModel: ReaderSettingsScreenM val webtoonSidePadding by screenModel.preferences.webtoonSidePadding().collectAsState() SliderItem( - label = stringResource(R.string.pref_webtoon_side_padding), + label = localize(MR.strings.pref_webtoon_side_padding), min = ReaderPreferences.WEBTOON_PADDING_MIN, max = ReaderPreferences.WEBTOON_PADDING_MAX, value = webtoonSidePadding, @@ -163,25 +163,25 @@ private fun ColumnScope.WebtoonViewerSettings(screenModel: ReaderSettingsScreenM ) CheckboxItem( - label = stringResource(R.string.pref_crop_borders), + label = localize(MR.strings.pref_crop_borders), pref = screenModel.preferences.cropBordersWebtoon(), ) val dualPageSplitWebtoon by screenModel.preferences.dualPageSplitWebtoon().collectAsState() CheckboxItem( - label = stringResource(R.string.pref_dual_page_split), + label = localize(MR.strings.pref_dual_page_split), pref = screenModel.preferences.dualPageSplitWebtoon(), ) if (dualPageSplitWebtoon) { CheckboxItem( - label = stringResource(R.string.pref_dual_page_invert), + label = localize(MR.strings.pref_dual_page_invert), pref = screenModel.preferences.dualPageInvertWebtoon(), ) } CheckboxItem( - label = stringResource(R.string.pref_double_tap_zoom), + label = localize(MR.strings.pref_double_tap_zoom), pref = screenModel.preferences.webtoonDoubleTapZoomEnabled(), ) } @@ -193,23 +193,23 @@ private fun ColumnScope.TapZonesItems( invertMode: ReaderPreferences.TappingInvertMode, onSelectInvertMode: (ReaderPreferences.TappingInvertMode) -> Unit, ) { - SettingsChipRow(R.string.pref_viewer_nav) { + SettingsChipRow(MR.strings.pref_viewer_nav) { ReaderPreferences.TapZones.mapIndexed { index, it -> FilterChip( selected = selected == index, onClick = { onSelect(index) }, - label = { Text(stringResource(it)) }, + label = { Text(localize(it)) }, ) } } if (selected != 5) { - SettingsChipRow(R.string.pref_read_with_tapping_inverted) { + SettingsChipRow(MR.strings.pref_read_with_tapping_inverted) { ReaderPreferences.TappingInvertMode.entries.map { FilterChip( selected = it == invertMode, onClick = { onSelectInvertMode(it) }, - label = { Text(stringResource(it.titleResId)) }, + label = { Text(localize(it.titleRes)) }, ) } } diff --git a/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogHome.kt b/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogHome.kt index a04f9de7e4..3a05bc31ca 100644 --- a/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogHome.kt +++ b/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogHome.kt @@ -1,6 +1,5 @@ package eu.kanade.presentation.track -import androidx.annotation.StringRes import androidx.compose.animation.animateContentSize import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -42,20 +41,21 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp +import dev.icerock.moko.resources.StringResource import eu.kanade.domain.track.model.toDbTrack import eu.kanade.presentation.components.DropdownMenu import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.track.components.TrackLogoIcon -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.util.system.copyToClipboard +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import java.text.DateFormat private const val UnsetStatusTextAlpha = 0.5F @@ -131,7 +131,7 @@ fun TrackInfoDialogHome( private fun TrackInfoItem( title: String, tracker: Tracker, - @StringRes status: Int?, + status: StringResource?, onStatusClick: () -> Unit, chapters: String, onChaptersClick: () -> Unit, @@ -194,7 +194,7 @@ private fun TrackInfoItem( Row(modifier = Modifier.height(IntrinsicSize.Min)) { TrackDetailsItem( modifier = Modifier.weight(1f), - text = status?.let { stringResource(it) } ?: "", + text = status?.let { localize(it) } ?: "", onClick = onStatusClick, ) VerticalDivider() @@ -209,7 +209,7 @@ private fun TrackInfoItem( modifier = Modifier .weight(1f) .alpha(if (score == null) UnsetStatusTextAlpha else 1f), - text = score ?: stringResource(R.string.score), + text = score ?: localize(MR.strings.score), onClick = onScoreClick, ) } @@ -221,14 +221,14 @@ private fun TrackInfoItem( TrackDetailsItem( modifier = Modifier.weight(1F), text = startDate, - placeholder = stringResource(R.string.track_started_reading_date), + placeholder = localize(MR.strings.track_started_reading_date), onClick = onStartDateClick, ) VerticalDivider() TrackDetailsItem( modifier = Modifier.weight(1F), text = endDate, - placeholder = stringResource(R.string.track_finished_reading_date), + placeholder = localize(MR.strings.track_finished_reading_date), onClick = onEndDateClick, ) } @@ -279,7 +279,7 @@ private fun TrackInfoItemEmpty( .padding(start = 16.dp) .weight(1f), ) { - Text(text = stringResource(R.string.add_tracking)) + Text(text = localize(MR.strings.add_tracking)) } } } @@ -294,7 +294,7 @@ private fun TrackInfoItemMenu( IconButton(onClick = { expanded = true }) { Icon( imageVector = Icons.Default.MoreVert, - contentDescription = stringResource(R.string.label_more), + contentDescription = localize(MR.strings.label_more), ) } DropdownMenu( @@ -302,14 +302,14 @@ private fun TrackInfoItemMenu( onDismissRequest = { expanded = false }, ) { DropdownMenuItem( - text = { Text(stringResource(R.string.action_open_in_browser)) }, + text = { Text(localize(MR.strings.action_open_in_browser)) }, onClick = { onOpenInBrowser() expanded = false }, ) DropdownMenuItem( - text = { Text(stringResource(R.string.action_remove)) }, + text = { Text(localize(MR.strings.action_remove)) }, onClick = { onRemoved() expanded = false diff --git a/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogSelector.kt b/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogSelector.kt index 0fcde4faf6..38488d9f68 100644 --- a/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogSelector.kt +++ b/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogSelector.kt @@ -29,18 +29,19 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp +import dev.icerock.moko.resources.StringResource import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.WheelNumberPicker import tachiyomi.presentation.core.components.WheelTextPicker import tachiyomi.presentation.core.components.material.AlertDialogContent import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.isScrolledToEnd import tachiyomi.presentation.core.util.isScrolledToStart @@ -48,12 +49,12 @@ import tachiyomi.presentation.core.util.isScrolledToStart fun TrackStatusSelector( selection: Int, onSelectionChange: (Int) -> Unit, - selections: Map, + selections: Map, onConfirm: () -> Unit, onDismissRequest: () -> Unit, ) { BaseSelector( - title = stringResource(R.string.status), + title = localize(MR.strings.status), content = { val state = rememberLazyListState() ScrollbarLazyColumn(state = state) { @@ -76,7 +77,7 @@ fun TrackStatusSelector( onClick = null, ) Text( - text = value?.let { stringResource(it) } ?: "", + text = value?.let { localize(it) } ?: "", style = MaterialTheme.typography.bodyLarge.merge(), modifier = Modifier.padding(start = 24.dp), ) @@ -101,7 +102,7 @@ fun TrackChapterSelector( onDismissRequest: () -> Unit, ) { BaseSelector( - title = stringResource(R.string.chapters), + title = localize(MR.strings.chapters), content = { WheelNumberPicker( items = range.toImmutableList(), @@ -124,7 +125,7 @@ fun TrackScoreSelector( onDismissRequest: () -> Unit, ) { BaseSelector( - title = stringResource(R.string.score), + title = localize(MR.strings.score), content = { WheelTextPicker( items = selections, @@ -171,15 +172,15 @@ fun TrackDateSelector( ) { if (onRemove != null) { TextButton(onClick = onRemove) { - Text(text = stringResource(R.string.action_remove)) + Text(text = localize(MR.strings.action_remove)) } Spacer(modifier = Modifier.weight(1f)) } TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } TextButton(onClick = { onConfirm(pickerState.selectedDateMillis!!) }) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } } } @@ -214,10 +215,10 @@ private fun BaseSelector( Spacer(modifier = Modifier.weight(1f)) } TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } TextButton(onClick = onConfirm) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } } }, @@ -234,12 +235,12 @@ private fun TrackStatusSelectorPreviews() { onSelectionChange = {}, selections = mapOf( // Anilist values - 1 to R.string.reading, - 2 to R.string.plan_to_read, - 3 to R.string.completed, - 4 to R.string.on_hold, - 5 to R.string.dropped, - 6 to R.string.repeating, + 1 to MR.strings.reading, + 2 to MR.strings.plan_to_read, + 3 to MR.strings.completed, + 4 to MR.strings.on_hold, + 5 to MR.strings.dropped, + 6 to MR.strings.repeating, ), onConfirm = {}, onDismissRequest = {}, diff --git a/app/src/main/java/eu/kanade/presentation/track/TrackerSearch.kt b/app/src/main/java/eu/kanade/presentation/track/TrackerSearch.kt index d42766799c..f26af7c108 100644 --- a/app/src/main/java/eu/kanade/presentation/track/TrackerSearch.kt +++ b/app/src/main/java/eu/kanade/presentation/track/TrackerSearch.kt @@ -29,7 +29,6 @@ import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.ArrowBack -import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.Close import androidx.compose.material3.Button @@ -50,7 +49,6 @@ import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.capitalize import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.TextFieldValue @@ -62,11 +60,12 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import eu.kanade.presentation.manga.components.MangaCover import eu.kanade.presentation.theme.TachiyomiTheme -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.track.model.TrackSearch +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.util.plus @@ -121,7 +120,7 @@ fun TrackerSearch( decorationBox = { if (query.text.isEmpty()) { Text( - text = stringResource(R.string.action_search_hint), + text = localize(MR.strings.action_search_hint), color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodyLarge, ) @@ -164,7 +163,7 @@ fun TrackerSearch( .fillMaxWidth(), elevation = ButtonDefaults.elevatedButtonElevation(), ) { - Text(text = stringResource(R.string.action_track)) + Text(text = localize(MR.strings.action_track)) } } }, @@ -177,7 +176,7 @@ fun TrackerSearch( if (availableTracks.isEmpty()) { EmptyScreen( modifier = Modifier.padding(innerPadding), - textResource = R.string.no_results_found, + stringRes = MR.strings.no_results_found, ) } else { ScrollbarLazyColumn( @@ -205,7 +204,7 @@ fun TrackerSearch( EmptyScreen( modifier = Modifier.padding(innerPadding), message = queryResult.exceptionOrNull()?.message - ?: stringResource(R.string.unknown_error), + ?: localize(MR.strings.unknown_error), ) } } @@ -264,19 +263,19 @@ private fun SearchResultItem( ) if (type.isNotBlank()) { SearchResultItemDetails( - title = stringResource(R.string.track_type), + title = localize(MR.strings.track_type), text = type, ) } if (startDate.isNotBlank()) { SearchResultItemDetails( - title = stringResource(R.string.label_started), + title = localize(MR.strings.label_started), text = startDate, ) } if (status.isNotBlank()) { SearchResultItemDetails( - title = stringResource(R.string.track_status), + title = localize(MR.strings.track_status), text = status, ) } diff --git a/app/src/main/java/eu/kanade/presentation/updates/UpdatesDialog.kt b/app/src/main/java/eu/kanade/presentation/updates/UpdatesDialog.kt index b5210916ec..4c2c24acc9 100644 --- a/app/src/main/java/eu/kanade/presentation/updates/UpdatesDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/updates/UpdatesDialog.kt @@ -4,8 +4,8 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize @Composable fun UpdatesDeleteConfirmationDialog( @@ -14,7 +14,7 @@ fun UpdatesDeleteConfirmationDialog( ) { AlertDialog( text = { - Text(text = stringResource(R.string.confirm_delete_chapters)) + Text(text = localize(MR.strings.confirm_delete_chapters)) }, onDismissRequest = onDismissRequest, confirmButton = { @@ -22,12 +22,12 @@ fun UpdatesDeleteConfirmationDialog( onConfirm() onDismissRequest() }) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } }, ) diff --git a/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt b/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt index 492d6a3965..0f042e0dae 100644 --- a/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt @@ -18,23 +18,23 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.util.fastAll import androidx.compose.ui.util.fastAny import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.manga.components.ChapterDownloadAction import eu.kanade.presentation.manga.components.MangaBottomActionMenu -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.ui.updates.UpdatesItem import eu.kanade.tachiyomi.ui.updates.UpdatesScreenModel import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.material.PullRefresh import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen import kotlin.time.Duration.Companion.seconds @@ -85,7 +85,7 @@ fun UpdateScreen( when { state.isLoading -> LoadingScreen(Modifier.padding(contentPadding)) state.items.isEmpty() -> EmptyScreen( - textResource = R.string.information_no_recent, + stringRes = MR.strings.information_no_recent, modifier = Modifier.padding(contentPadding), ) else -> { @@ -140,12 +140,12 @@ private fun UpdatesAppBar( ) { AppBar( modifier = modifier, - title = stringResource(R.string.label_recent_updates), + title = localize(MR.strings.label_recent_updates), actions = { AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.action_update_library), + title = localize(MR.strings.action_update_library), icon = Icons.Outlined.Refresh, onClick = onUpdateLibrary, ), @@ -158,12 +158,12 @@ private fun UpdatesAppBar( AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.action_select_all), + title = localize(MR.strings.action_select_all), icon = Icons.Outlined.SelectAll, onClick = onSelectAll, ), AppBar.Action( - title = stringResource(R.string.action_select_inverse), + title = localize(MR.strings.action_select_inverse), icon = Icons.Outlined.FlipToBack, onClick = onInvertSelection, ), diff --git a/app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt b/app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt index fdbc87203f..5766a9bec9 100644 --- a/app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt +++ b/app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt @@ -29,7 +29,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalHapticFeedback -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -38,13 +37,14 @@ import eu.kanade.presentation.manga.components.ChapterDownloadIndicator import eu.kanade.presentation.manga.components.DotSeparatorText import eu.kanade.presentation.manga.components.MangaCover import eu.kanade.presentation.util.relativeTimeSpanString -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.ui.updates.UpdatesItem import tachiyomi.domain.updates.model.UpdatesWithRelations +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.ListGroupHeader import tachiyomi.presentation.core.components.material.ReadItemAlpha import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.selectedBackground internal fun LazyListScope.updatesLastUpdatedItem( @@ -56,7 +56,7 @@ internal fun LazyListScope.updatesLastUpdatedItem( .padding(horizontal = MaterialTheme.padding.medium, vertical = MaterialTheme.padding.small), ) { Text( - text = stringResource(R.string.updates_last_update_info, relativeTimeSpanString(lastUpdated)), + text = localize(MR.strings.updates_last_update_info, relativeTimeSpanString(lastUpdated)), fontStyle = FontStyle.Italic, ) } @@ -100,8 +100,8 @@ internal fun LazyListScope.updatesUiItems( readProgress = updatesItem.update.lastPageRead .takeIf { !updatesItem.update.read && it > 0L } ?.let { - stringResource( - R.string.chapter_progress, + localize( + MR.strings.chapter_progress, it + 1, ) }, @@ -183,7 +183,7 @@ private fun UpdatesUiItem( if (!update.read) { Icon( imageVector = Icons.Filled.Circle, - contentDescription = stringResource(R.string.unread), + contentDescription = localize(MR.strings.unread), modifier = Modifier .height(8.dp) .padding(end = 4.dp), @@ -193,7 +193,7 @@ private fun UpdatesUiItem( if (update.bookmark) { Icon( imageVector = Icons.Filled.Bookmark, - contentDescription = stringResource(R.string.action_filter_bookmarked), + contentDescription = localize(MR.strings.action_filter_bookmarked), modifier = Modifier .sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }), tint = MaterialTheme.colorScheme.primary, diff --git a/app/src/main/java/eu/kanade/presentation/util/ExceptionFormatter.kt b/app/src/main/java/eu/kanade/presentation/util/ExceptionFormatter.kt index 9b4d4286f3..4b91347962 100644 --- a/app/src/main/java/eu/kanade/presentation/util/ExceptionFormatter.kt +++ b/app/src/main/java/eu/kanade/presentation/util/ExceptionFormatter.kt @@ -1,30 +1,31 @@ package eu.kanade.presentation.util import android.content.Context -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.network.HttpException import eu.kanade.tachiyomi.source.online.LicensedMangaChaptersException import eu.kanade.tachiyomi.util.system.isOnline +import tachiyomi.core.i18n.localize import tachiyomi.data.source.NoResultsException import tachiyomi.domain.source.model.SourceNotInstalledException +import tachiyomi.i18n.MR import java.net.UnknownHostException context(Context) val Throwable.formattedMessage: String get() { when (this) { - is HttpException -> return getString(R.string.exception_http, code) + is HttpException -> return localize(MR.strings.exception_http, code) is UnknownHostException -> { return if (!isOnline()) { - getString(R.string.exception_offline) + localize(MR.strings.exception_offline) } else { - getString(R.string.exception_unknown_host, message) + localize(MR.strings.exception_unknown_host, message ?: "") } } - is NoResultsException -> return getString(R.string.no_results_found) - is SourceNotInstalledException -> return getString(R.string.loader_not_implemented_error) - is LicensedMangaChaptersException -> return getString(R.string.licensed_manga_chapters_error) + is NoResultsException -> return localize(MR.strings.no_results_found) + is SourceNotInstalledException -> return localize(MR.strings.loader_not_implemented_error) + is LicensedMangaChaptersException -> return localize(MR.strings.licensed_manga_chapters_error) } return when (val className = this::class.simpleName) { "Exception", "IOException" -> message ?: className diff --git a/app/src/main/java/eu/kanade/presentation/util/TimeUtils.kt b/app/src/main/java/eu/kanade/presentation/util/TimeUtils.kt index e98374fd87..8eaff72a9d 100644 --- a/app/src/main/java/eu/kanade/presentation/util/TimeUtils.kt +++ b/app/src/main/java/eu/kanade/presentation/util/TimeUtils.kt @@ -4,8 +4,9 @@ import android.content.Context import android.text.format.DateUtils import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable -import androidx.compose.ui.res.stringResource -import eu.kanade.tachiyomi.R +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import java.util.Date import kotlin.time.Duration import kotlin.time.Duration.Companion.minutes @@ -13,10 +14,10 @@ import kotlin.time.Duration.Companion.minutes fun Duration.toDurationString(context: Context, fallback: String): String { return toComponents { days, hours, minutes, seconds, _ -> buildList(4) { - if (days != 0L) add(context.getString(R.string.day_short, days)) - if (hours != 0) add(context.getString(R.string.hour_short, hours)) - if (minutes != 0 && (days == 0L || hours == 0)) add(context.getString(R.string.minute_short, minutes)) - if (seconds != 0 && days == 0L && hours == 0) add(context.getString(R.string.seconds_short, seconds)) + if (days != 0L) add(context.localize(MR.strings.day_short, days)) + if (hours != 0) add(context.localize(MR.strings.hour_short, hours)) + if (minutes != 0 && (days == 0L || hours == 0)) add(context.localize(MR.strings.minute_short, minutes)) + if (seconds != 0 && days == 0L && hours == 0) add(context.localize(MR.strings.seconds_short, seconds)) }.joinToString(" ").ifBlank { fallback } } } @@ -26,8 +27,8 @@ fun Duration.toDurationString(context: Context, fallback: String): String { fun relativeTimeSpanString(epochMillis: Long): String { val now = Date().time return when { - epochMillis <= 0L -> stringResource(R.string.relative_time_span_never) - now - epochMillis < 1.minutes.inWholeMilliseconds -> stringResource(R.string.updates_last_update_info_just_now) + epochMillis <= 0L -> localize(MR.strings.relative_time_span_never) + now - epochMillis < 1.minutes.inWholeMilliseconds -> localize(MR.strings.updates_last_update_info_just_now) else -> DateUtils.getRelativeTimeSpanString(epochMillis, now, DateUtils.MINUTE_IN_MILLIS).toString() } } diff --git a/app/src/main/java/eu/kanade/presentation/webview/WebViewScreenContent.kt b/app/src/main/java/eu/kanade/presentation/webview/WebViewScreenContent.kt index 1ca4af791a..f994b75d49 100644 --- a/app/src/main/java/eu/kanade/presentation/webview/WebViewScreenContent.kt +++ b/app/src/main/java/eu/kanade/presentation/webview/WebViewScreenContent.kt @@ -13,8 +13,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.ArrowBack import androidx.compose.material.icons.automirrored.outlined.ArrowForward -import androidx.compose.material.icons.outlined.ArrowBack -import androidx.compose.material.icons.outlined.ArrowForward import androidx.compose.material.icons.outlined.Close import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.MaterialTheme @@ -29,7 +27,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.google.accompanist.web.AccompanistWebViewClient import com.google.accompanist.web.LoadingState @@ -40,12 +37,13 @@ import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.WarningBanner import eu.kanade.tachiyomi.BuildConfig -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.system.getHtml import eu.kanade.tachiyomi.util.system.setDefaultSettings import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.launch +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize @Composable fun WebViewScreenContent( @@ -127,7 +125,7 @@ fun WebViewScreenContent( AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.action_webview_back), + title = localize(MR.strings.action_webview_back), icon = Icons.AutoMirrored.Outlined.ArrowBack, onClick = { if (navigator.canGoBack) { @@ -137,7 +135,7 @@ fun WebViewScreenContent( enabled = navigator.canGoBack, ), AppBar.Action( - title = stringResource(R.string.action_webview_forward), + title = localize(MR.strings.action_webview_forward), icon = Icons.AutoMirrored.Outlined.ArrowForward, onClick = { if (navigator.canGoForward) { @@ -147,19 +145,19 @@ fun WebViewScreenContent( enabled = navigator.canGoForward, ), AppBar.OverflowAction( - title = stringResource(R.string.action_webview_refresh), + title = localize(MR.strings.action_webview_refresh), onClick = { navigator.reload() }, ), AppBar.OverflowAction( - title = stringResource(R.string.action_share), + title = localize(MR.strings.action_share), onClick = { onShare(currentUrl) }, ), AppBar.OverflowAction( - title = stringResource(R.string.action_open_in_browser), + title = localize(MR.strings.action_open_in_browser), onClick = { onOpenInBrowser(currentUrl) }, ), AppBar.OverflowAction( - title = stringResource(R.string.pref_clear_cookies), + title = localize(MR.strings.pref_clear_cookies), onClick = { onClearCookies(currentUrl) }, ), ), @@ -172,7 +170,7 @@ fun WebViewScreenContent( modifier = Modifier.padding(8.dp), ) { WarningBanner( - textRes = R.string.information_cloudflare_help, + textRes = MR.strings.information_cloudflare_help, modifier = Modifier .clip(MaterialTheme.shapes.small) .clickable { diff --git a/app/src/main/java/eu/kanade/tachiyomi/App.kt b/app/src/main/java/eu/kanade/tachiyomi/App.kt index 2619a073b6..65acfe186b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/App.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/App.kt @@ -55,7 +55,9 @@ import org.acra.config.httpSender import org.acra.ktx.initAcra import org.acra.sender.HttpSender import org.conscrypt.Conscrypt +import tachiyomi.core.i18n.localize import tachiyomi.core.util.system.logcat +import tachiyomi.i18n.MR import tachiyomi.presentation.widget.WidgetManager import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -104,8 +106,8 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { Notifications.ID_INCOGNITO_MODE, Notifications.CHANNEL_INCOGNITO_MODE, ) { - setContentTitle(getString(R.string.pref_incognito_mode)) - setContentText(getString(R.string.notification_incognito_text)) + setContentTitle(localize(MR.strings.pref_incognito_mode)) + setContentText(localize(MR.strings.notification_incognito_text)) setSmallIcon(R.drawable.ic_glasses_24dp) setOngoing(true) diff --git a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt index b3889f2e71..93d2c0d04d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt @@ -27,6 +27,7 @@ import tachiyomi.core.preference.plusAssign import tachiyomi.domain.backup.service.BackupPreferences import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED +import tachiyomi.i18n.MR import java.io.File object Migrations { @@ -146,7 +147,7 @@ object Migrations { // v53: switched from WebView to OAuth if (trackerManager.myAnimeList.isLoggedIn) { trackerManager.myAnimeList.logout() - context.toast(R.string.myanimelist_relogin) + context.toast(MR.strings.myanimelist_relogin) } } if (oldVersion < 57) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreator.kt index a843a3b0ca..a6590fa011 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreator.kt @@ -4,7 +4,6 @@ import android.Manifest import android.content.Context import android.net.Uri import com.hippo.unifile.UniFile -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.backup.BackupCreateFlags.BACKUP_APP_PREFS import eu.kanade.tachiyomi.data.backup.BackupCreateFlags.BACKUP_CATEGORY import eu.kanade.tachiyomi.data.backup.BackupCreateFlags.BACKUP_CHAPTER @@ -38,6 +37,7 @@ import logcat.LogPriority import okio.buffer import okio.gzip import okio.sink +import tachiyomi.core.i18n.localize import tachiyomi.core.preference.Preference import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.util.system.logcat @@ -49,6 +49,7 @@ import tachiyomi.domain.history.interactor.GetHistory import tachiyomi.domain.manga.interactor.GetFavorites import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.source.service.SourceManager +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.FileOutputStream @@ -75,7 +76,7 @@ class BackupCreator( */ suspend fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String { if (!context.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - throw IllegalStateException(context.getString(R.string.missing_storage_permission)) + throw IllegalStateException(context.localize(MR.strings.missing_storage_permission)) } val databaseManga = getFavorites.await() @@ -110,7 +111,7 @@ class BackupCreator( UniFile.fromUri(context, uri) } ) - ?: throw Exception(context.getString(R.string.create_backup_file_error)) + ?: throw Exception(context.localize(MR.strings.create_backup_file_error)) if (!file.isFile) { throw IllegalStateException("Failed to get handle on a backup file") @@ -118,7 +119,7 @@ class BackupCreator( val byteArray = parser.encodeToByteArray(BackupSerializer, backup) if (byteArray.isEmpty()) { - throw IllegalStateException(context.getString(R.string.empty_backup_error)) + throw IllegalStateException(context.localize(MR.strings.empty_backup_error)) } file.openOutputStream().also { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt index 8450ab3677..e883360e03 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupFileValidator.kt @@ -2,10 +2,11 @@ package eu.kanade.tachiyomi.data.backup import android.content.Context import android.net.Uri -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.util.BackupUtil +import tachiyomi.core.i18n.localize import tachiyomi.domain.source.service.SourceManager +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -28,7 +29,7 @@ class BackupFileValidator( } if (backup.backupManga.isEmpty()) { - throw IllegalStateException(context.getString(R.string.invalid_backup_file_missing_manga)) + throw IllegalStateException(context.localize(MR.strings.invalid_backup_file_missing_manga)) } val sources = backup.backupSources.associate { it.sourceId to it.name } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt index 49b7ee0dd6..a3020c3b32 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt @@ -12,6 +12,9 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.system.cancelNotification import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notify +import tachiyomi.core.i18n.localize +import tachiyomi.core.i18n.localizePlural +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy import java.io.File import java.util.concurrent.TimeUnit @@ -44,7 +47,7 @@ class BackupNotifier(private val context: Context) { fun showBackupProgress(): NotificationCompat.Builder { val builder = with(progressNotificationBuilder) { - setContentTitle(context.getString(R.string.creating_backup)) + setContentTitle(context.localize(MR.strings.creating_backup)) setProgress(0, 0, true) } @@ -58,7 +61,7 @@ class BackupNotifier(private val context: Context) { context.cancelNotification(Notifications.ID_BACKUP_PROGRESS) with(completeNotificationBuilder) { - setContentTitle(context.getString(R.string.creating_backup_error)) + setContentTitle(context.localize(MR.strings.creating_backup_error)) setContentText(error) show(Notifications.ID_BACKUP_COMPLETE) @@ -69,13 +72,13 @@ class BackupNotifier(private val context: Context) { context.cancelNotification(Notifications.ID_BACKUP_PROGRESS) with(completeNotificationBuilder) { - setContentTitle(context.getString(R.string.backup_created)) + setContentTitle(context.localize(MR.strings.backup_created)) setContentText(unifile.filePath ?: unifile.name) clearActions() addAction( R.drawable.ic_share_24dp, - context.getString(R.string.action_share), + context.localize(MR.strings.action_share), NotificationReceiver.shareBackupPendingBroadcast( context, unifile.uri, @@ -89,8 +92,8 @@ class BackupNotifier(private val context: Context) { fun showRestoreProgress( content: String = "", - contentTitle: String = context.getString( - R.string.restoring_backup, + contentTitle: String = context.localize( + MR.strings.restoring_backup, ), progress: Int = 0, maxAmount: Int = 100, @@ -108,7 +111,7 @@ class BackupNotifier(private val context: Context) { clearActions() addAction( R.drawable.ic_close_24dp, - context.getString(R.string.action_cancel), + context.localize(MR.strings.action_cancel), NotificationReceiver.cancelRestorePendingBroadcast(context, Notifications.ID_RESTORE_PROGRESS), ) } @@ -122,7 +125,7 @@ class BackupNotifier(private val context: Context) { context.cancelNotification(Notifications.ID_RESTORE_PROGRESS) with(completeNotificationBuilder) { - setContentTitle(context.getString(R.string.restoring_backup_error)) + setContentTitle(context.localize(MR.strings.restoring_backup_error)) setContentText(error) show(Notifications.ID_RESTORE_COMPLETE) @@ -134,14 +137,14 @@ class BackupNotifier(private val context: Context) { errorCount: Int, path: String?, file: String?, - contentTitle: String = context.getString( - R.string.restore_completed, + contentTitle: String = context.localize( + MR.strings.restore_completed, ), ) { context.cancelNotification(Notifications.ID_RESTORE_PROGRESS) - val timeString = context.getString( - R.string.restore_duration, + val timeString = context.localize( + MR.strings.restore_duration, TimeUnit.MILLISECONDS.toMinutes(time), TimeUnit.MILLISECONDS.toSeconds(time) - TimeUnit.MINUTES.toSeconds( TimeUnit.MILLISECONDS.toMinutes(time), @@ -151,8 +154,8 @@ class BackupNotifier(private val context: Context) { with(completeNotificationBuilder) { setContentTitle(contentTitle) setContentText( - context.resources.getQuantityString( - R.plurals.restore_completed_message, + context.localizePlural( + MR.plurals.restore_completed_message, errorCount, timeString, errorCount, @@ -168,7 +171,7 @@ class BackupNotifier(private val context: Context) { setContentIntent(errorLogIntent) addAction( R.drawable.ic_folder_24dp, - context.getString(R.string.action_show_errors), + context.localize(MR.strings.action_show_errors), errorLogIntent, ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreJob.kt index 170ddb80fa..b05bbb6890 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreJob.kt @@ -9,14 +9,15 @@ import androidx.work.ForegroundInfo import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkerParameters import androidx.work.workDataOf -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.util.system.cancelNotification import eu.kanade.tachiyomi.util.system.isRunning import eu.kanade.tachiyomi.util.system.workManager import kotlinx.coroutines.CancellationException import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.util.system.logcat +import tachiyomi.i18n.MR class BackupRestoreJob(private val context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) { @@ -40,7 +41,7 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet Result.success() } catch (e: Exception) { if (e is CancellationException) { - notifier.showRestoreError(context.getString(R.string.restoring_backup_canceled)) + notifier.showRestoreError(context.localize(MR.strings.restoring_backup_canceled)) Result.success() } else { logcat(LogPriority.ERROR, e) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt index f78cdceca7..ebd6e07ef8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.backup import android.content.Context import android.net.Uri import eu.kanade.domain.manga.interactor.UpdateManga -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.backup.models.BackupCategory import eu.kanade.tachiyomi.data.backup.models.BackupHistory import eu.kanade.tachiyomi.data.backup.models.BackupManga @@ -23,6 +22,7 @@ import eu.kanade.tachiyomi.util.BackupUtil import eu.kanade.tachiyomi.util.system.createFileInCacheDir import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.isActive +import tachiyomi.core.i18n.localize import tachiyomi.core.preference.AndroidPreferenceStore import tachiyomi.core.preference.PreferenceStore import tachiyomi.data.DatabaseHandler @@ -37,6 +37,7 @@ import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.manga.interactor.FetchInterval import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.track.model.Track +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.File @@ -93,7 +94,7 @@ class BackupRestorer( errors.size, logFile.parent, logFile.name, - contentTitle = context.getString(R.string.library_sync_complete), + contentTitle = context.localize(MR.strings.library_sync_complete), ) } else { notifier.showRestoreComplete(time, errors.size, logFile.parent, logFile.name) @@ -192,8 +193,8 @@ class BackupRestorer( showRestoreProgress( restoreProgress, restoreAmount, - context.getString(R.string.categories), - context.getString(R.string.restoring_backup), + context.localize(MR.strings.categories), + context.localize(MR.strings.restoring_backup), ) } @@ -229,14 +230,14 @@ class BackupRestorer( restoreProgress, restoreAmount, manga.title, - context.getString(R.string.syncing_library), + context.localize(MR.strings.syncing_library), ) } else { showRestoreProgress( restoreProgress, restoreAmount, manga.title, - context.getString(R.string.restoring_backup), + context.localize(MR.strings.restoring_backup), ) } } @@ -633,8 +634,8 @@ class BackupRestorer( showRestoreProgress( restoreProgress, restoreAmount, - context.getString(R.string.app_settings), - context.getString(R.string.restoring_backup), + context.localize(MR.strings.app_settings), + context.localize(MR.strings.restoring_backup), ) } @@ -648,8 +649,8 @@ class BackupRestorer( showRestoreProgress( restoreProgress, restoreAmount, - context.getString(R.string.source_settings), - context.getString(R.string.restoring_backup), + context.localize(MR.strings.source_settings), + context.localize(MR.strings.restoring_backup), ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt index 184269ea0e..7f82fdfa19 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.data.download import android.content.Context -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.model.Page @@ -15,6 +14,7 @@ import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.runBlocking import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.system.logcat import tachiyomi.domain.category.interactor.GetCategories @@ -22,6 +22,7 @@ import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.download.service.DownloadPreferences import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.source.service.SourceManager +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -158,7 +159,7 @@ class DownloadManager( .filter { "image" in it.type.orEmpty() } if (files.isEmpty()) { - throw Exception(context.getString(R.string.page_list_empty_error)) + throw Exception(context.localize(MR.strings.page_list_empty_error)) } return files.sortedBy { it.name } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt index bfbf3117d2..aac539e073 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt @@ -14,6 +14,8 @@ import eu.kanade.tachiyomi.util.lang.chop import eu.kanade.tachiyomi.util.system.cancelNotification import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notify +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy import java.util.regex.Pattern @@ -78,13 +80,13 @@ internal class DownloadNotifier(private val context: Context) { // Pause action addAction( R.drawable.ic_pause_24dp, - context.getString(R.string.action_pause), + context.localize(MR.strings.action_pause), NotificationReceiver.pauseDownloadsPendingBroadcast(context), ) } - val downloadingProgressText = context.getString( - R.string.chapter_downloading_progress, + val downloadingProgressText = context.localize( + MR.strings.chapter_downloading_progress, download.downloadedImages, download.pages!!.size, ) @@ -115,8 +117,8 @@ internal class DownloadNotifier(private val context: Context) { */ fun onPaused() { with(progressNotificationBuilder) { - setContentTitle(context.getString(R.string.chapter_paused)) - setContentText(context.getString(R.string.download_notifier_download_paused)) + setContentTitle(context.localize(MR.strings.chapter_paused)) + setContentText(context.localize(MR.strings.download_notifier_download_paused)) setSmallIcon(R.drawable.ic_pause_24dp) setProgress(0, 0, false) setOngoing(false) @@ -126,13 +128,13 @@ internal class DownloadNotifier(private val context: Context) { // Resume action addAction( R.drawable.ic_play_arrow_24dp, - context.getString(R.string.action_resume), + context.localize(MR.strings.action_resume), NotificationReceiver.resumeDownloadsPendingBroadcast(context), ) // Clear action addAction( R.drawable.ic_close_24dp, - context.getString(R.string.action_cancel_all), + context.localize(MR.strings.action_cancel_all), NotificationReceiver.clearDownloadsPendingBroadcast(context), ) @@ -162,7 +164,7 @@ internal class DownloadNotifier(private val context: Context) { */ fun onWarning(reason: String, timeout: Long? = null, contentIntent: PendingIntent? = null) { with(errorNotificationBuilder) { - setContentTitle(context.getString(R.string.download_notifier_downloader_title)) + setContentTitle(context.localize(MR.strings.download_notifier_downloader_title)) setStyle(NotificationCompat.BigTextStyle().bigText(reason)) setSmallIcon(R.drawable.ic_warning_white_24dp) setAutoCancel(true) @@ -190,9 +192,9 @@ internal class DownloadNotifier(private val context: Context) { // Create notification with(errorNotificationBuilder) { setContentTitle( - mangaTitle?.plus(": $chapter") ?: context.getString(R.string.download_notifier_downloader_title), + mangaTitle?.plus(": $chapter") ?: context.localize(MR.strings.download_notifier_downloader_title), ) - setContentText(error ?: context.getString(R.string.download_notifier_unknown_error)) + setContentText(error ?: context.localize(MR.strings.download_notifier_unknown_error)) setSmallIcon(R.drawable.ic_warning_white_24dp) clearActions() setContentIntent(NotificationHandler.openDownloadManagerPendingActivity(context)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt index 2c0b796dfb..ef31b88fcf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt @@ -3,17 +3,18 @@ package eu.kanade.tachiyomi.data.download import android.content.Context import androidx.core.net.toUri import com.hippo.unifile.UniFile -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.util.storage.DiskUtil import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.util.system.logcat import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.download.service.DownloadPreferences import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -58,7 +59,7 @@ class DownloadProvider( .createDirectory(getMangaDirName(mangaTitle)) } catch (e: Throwable) { logcat(LogPriority.ERROR, e) { "Invalid download directory" } - throw Exception(context.getString(R.string.invalid_location, downloadsDir)) + throw Exception(context.localize(MR.strings.invalid_location, downloadsDir)) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt index a79295ab95..315a51cdf7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt @@ -6,9 +6,8 @@ import android.content.Context import android.content.Intent import android.os.IBinder import android.os.PowerManager -import androidx.annotation.StringRes import androidx.core.content.ContextCompat -import eu.kanade.tachiyomi.R +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.isConnectedToWifi @@ -27,9 +26,11 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import logcat.LogPriority import ru.beryukhov.reactivenetwork.ReactiveNetwork +import tachiyomi.core.i18n.localize import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.download.service.DownloadPreferences +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy /** @@ -111,8 +112,8 @@ class DownloadService : Service() { return null } - private fun downloaderStop(@StringRes string: Int) { - downloadManager.downloaderStop(getString(string)) + private fun downloaderStop(string: StringResource) { + downloadManager.downloaderStop(localize(string)) } private fun listenNetworkChanges() { @@ -122,20 +123,20 @@ class DownloadService : Service() { withUIContext { if (isOnline()) { if (downloadPreferences.downloadOnlyOverWifi().get() && !isConnectedToWifi()) { - downloaderStop(R.string.download_notifier_text_only_wifi) + downloaderStop(MR.strings.download_notifier_text_only_wifi) } else { val started = downloadManager.downloaderStart() if (!started) stopSelf() } } else { - downloaderStop(R.string.download_notifier_no_network) + downloaderStop(MR.strings.download_notifier_no_network) } } } .catch { error -> withUIContext { logcat(LogPriority.ERROR, error) - toast(R.string.download_queue_error) + toast(MR.strings.download_queue_error) stopSelf() } } @@ -144,7 +145,7 @@ class DownloadService : Service() { private fun getPlaceholderNotification(): Notification { return notificationBuilder(Notifications.CHANNEL_DOWNLOADER_PROGRESS) { - setContentTitle(getString(R.string.download_notifier_downloader_title)) + setContentTitle(localize(MR.strings.download_notifier_downloader_title)) }.build() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt index 9af19d77ec..bcd7460094 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt @@ -4,7 +4,6 @@ import android.content.Context import com.hippo.unifile.UniFile import eu.kanade.domain.chapter.model.toSChapter import eu.kanade.domain.manga.model.getComicInfo -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.library.LibraryUpdateNotifier @@ -41,6 +40,7 @@ import kotlinx.coroutines.supervisorScope import logcat.LogPriority import nl.adaptivity.xmlutil.serialization.XML import okhttp3.Response +import tachiyomi.core.i18n.localize import tachiyomi.core.metadata.comicinfo.COMIC_INFO_FILE import tachiyomi.core.metadata.comicinfo.ComicInfo import tachiyomi.core.util.lang.launchIO @@ -54,6 +54,7 @@ import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.download.service.DownloadPreferences import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.source.service.SourceManager +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.BufferedOutputStream @@ -302,7 +303,7 @@ class Downloader( ) { withUIContext { notifier.onWarning( - context.getString(R.string.download_queue_size_warning), + context.localize(MR.strings.download_queue_size_warning), WARNING_NOTIF_TIMEOUT_MS, NotificationHandler.openUrl(context, LibraryUpdateNotifier.HELP_WARNING_URL), ) @@ -325,7 +326,7 @@ class Downloader( if (availSpace != -1L && availSpace < MIN_DISK_SPACE) { download.status = Download.State.ERROR notifier.onError( - context.getString(R.string.download_insufficient_space), + context.localize(MR.strings.download_insufficient_space), download.chapter.name, download.manga.title, ) @@ -342,7 +343,7 @@ class Downloader( val pages = download.source.getPageList(download.chapter.toSChapter()) if (pages.isEmpty()) { - throw Exception(context.getString(R.string.page_list_empty_error)) + throw Exception(context.localize(MR.strings.page_list_empty_error)) } // Don't trust index from source val reIndexedPages = pages.mapIndexed { index, page -> Page(index, page.url, page.imageUrl, page.uri) } @@ -546,7 +547,7 @@ class Downloader( try { val filenamePrefix = String.format("%03d", page.number) val imageFile = tmpDir.listFiles()?.firstOrNull { it.name.orEmpty().startsWith(filenamePrefix) } - ?: error(context.getString(R.string.download_notifier_split_page_not_found, page.number)) + ?: error(context.localize(MR.strings.download_notifier_split_page_not_found, page.number)) // If the original page was previously split, then skip if (imageFile.name.orEmpty().startsWith("${filenamePrefix}__")) return diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt index 5822015a6c..408ab67c46 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt @@ -16,16 +16,13 @@ import androidx.work.WorkerParameters import androidx.work.workDataOf import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.manga.interactor.UpdateManga -import eu.kanade.domain.manga.model.copyFrom import eu.kanade.domain.manga.model.toSManga -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.source.UnmeteredSource import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.UpdateStrategy -import eu.kanade.tachiyomi.util.prepUpdateCover import eu.kanade.tachiyomi.util.shouldDownloadNewChapters import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.system.createFileInCacheDir @@ -41,6 +38,7 @@ import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.preference.getAndSet import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.system.logcat @@ -62,9 +60,9 @@ import tachiyomi.domain.manga.interactor.FetchInterval import tachiyomi.domain.manga.interactor.GetLibraryManga import tachiyomi.domain.manga.interactor.GetManga import tachiyomi.domain.manga.model.Manga -import tachiyomi.domain.manga.model.toMangaUpdate import tachiyomi.domain.source.model.SourceNotInstalledException import tachiyomi.domain.source.service.SourceManager +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.File @@ -114,22 +112,14 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet logcat(LogPriority.ERROR, e) { "Not allowed to set foreground job" } } - val target = inputData.getString(KEY_TARGET)?.let { Target.valueOf(it) } ?: Target.CHAPTERS - - // If this is a chapter update, set the last update time to now - if (target == Target.CHAPTERS) { - libraryPreferences.lastUpdatedTimestamp().set(Date().time) - } + libraryPreferences.lastUpdatedTimestamp().set(Date().time) val categoryId = inputData.getLong(KEY_CATEGORY, -1L) addMangaToQueue(categoryId) return withIOContext { try { - when (target) { - Target.CHAPTERS -> updateChapterList() - Target.COVERS -> updateCovers() - } + updateChapterList() Result.success() } catch (e: Exception) { if (e is CancellationException) { @@ -191,29 +181,32 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet .filter { when { it.manga.updateStrategy != UpdateStrategy.ALWAYS_UPDATE -> { - skippedUpdates.add(it.manga to context.getString(R.string.skipped_reason_not_always_update)) + skippedUpdates.add(it.manga to context.localize(MR.strings.skipped_reason_not_always_update)) false } MANGA_NON_COMPLETED in restrictions && it.manga.status.toInt() == SManga.COMPLETED -> { - skippedUpdates.add(it.manga to context.getString(R.string.skipped_reason_completed)) + skippedUpdates.add(it.manga to context.localize(MR.strings.skipped_reason_completed)) false } MANGA_HAS_UNREAD in restrictions && it.unreadCount != 0L -> { - skippedUpdates.add(it.manga to context.getString(R.string.skipped_reason_not_caught_up)) + skippedUpdates.add(it.manga to context.localize(MR.strings.skipped_reason_not_caught_up)) false } MANGA_NON_READ in restrictions && it.totalChapters > 0L && !it.hasStarted -> { - skippedUpdates.add(it.manga to context.getString(R.string.skipped_reason_not_started)) + skippedUpdates.add(it.manga to context.localize(MR.strings.skipped_reason_not_started)) false } MANGA_OUTSIDE_RELEASE_PERIOD in restrictions && it.manga.nextUpdate > fetchWindow.second -> { - skippedUpdates.add(it.manga to context.getString(R.string.skipped_reason_not_in_release_period)) + skippedUpdates.add( + it.manga to context.localize(MR.strings.skipped_reason_not_in_release_period), + ) false } + else -> true } } @@ -294,10 +287,10 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet } } catch (e: Throwable) { val errorMessage = when (e) { - is NoChaptersException -> context.getString(R.string.no_chapters_error) + is NoChaptersException -> context.localize(MR.strings.no_chapters_error) // failedUpdates will already have the source, don't need to copy it into the message - is SourceNotInstalledException -> context.getString( - R.string.loader_not_implemented_error, + is SourceNotInstalledException -> context.localize( + MR.strings.loader_not_implemented_error, ) else -> e.message } @@ -359,51 +352,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet return syncChaptersWithSource.await(chapters, dbManga, source, false, fetchWindow) } - private suspend fun updateCovers() { - val semaphore = Semaphore(5) - val progressCount = AtomicInteger(0) - val currentlyUpdatingManga = CopyOnWriteArrayList() - - coroutineScope { - mangaToUpdate.groupBy { it.manga.source } - .values - .map { mangaInSource -> - async { - semaphore.withPermit { - mangaInSource.forEach { libraryManga -> - val manga = libraryManga.manga - ensureActive() - - withUpdateNotification( - currentlyUpdatingManga, - progressCount, - manga, - ) { - val source = sourceManager.get(manga.source) ?: return@withUpdateNotification - try { - val networkManga = source.getMangaDetails(manga.toSManga()) - val updatedManga = manga.prepUpdateCover(coverCache, networkManga, true) - .copyFrom(networkManga) - try { - updateManga.await(updatedManga.toMangaUpdate()) - } catch (e: Exception) { - logcat(LogPriority.ERROR) { "Manga doesn't exist anymore" } - } - } catch (e: Throwable) { - // Ignore errors and continue - logcat(LogPriority.ERROR, e) - } - } - } - } - } - } - .awaitAll() - } - - notifier.cancelProgressNotification() - } - private suspend fun withUpdateNotification( updatingManga: CopyOnWriteArrayList, completed: AtomicInteger, @@ -440,7 +388,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet if (errors.isNotEmpty()) { val file = context.createFileInCacheDir("tachiyomi_update_errors.txt") file.bufferedWriter().use { out -> - out.write(context.getString(R.string.library_errors_help, ERROR_LOG_HELP_URL) + "\n\n") + out.write(context.localize(MR.strings.library_errors_help, ERROR_LOG_HELP_URL) + "\n\n") // Error file format: // ! Error // # Source @@ -462,14 +410,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet return File("") } - /** - * Defines what should be updated within a service execution. - */ - enum class Target { - CHAPTERS, // Manga chapters - COVERS, // Manga covers - } - companion object { private const val TAG = "LibraryUpdate" private const val WORK_NAME_AUTO = "LibraryUpdate-auto" @@ -484,11 +424,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet */ private const val KEY_CATEGORY = "category" - /** - * Key that defines what should be updated. - */ - private const val KEY_TARGET = "target" - fun cancelAllWorks(context: Context) { context.workManager.cancelAllWorkByTag(TAG) } @@ -534,7 +469,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet fun startNow( context: Context, category: Category? = null, - target: Target = Target.CHAPTERS, ): Boolean { val wm = context.workManager if (wm.isRunning(TAG)) { @@ -544,7 +478,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet val inputData = workDataOf( KEY_CATEGORY to category?.id, - KEY_TARGET to target.name, ) val request = OneTimeWorkRequestBuilder() .addTag(TAG) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt index e590d7f4f7..65ee7ee06a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt @@ -26,9 +26,12 @@ import eu.kanade.tachiyomi.util.system.getBitmapOrNull import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notify import tachiyomi.core.Constants +import tachiyomi.core.i18n.localize +import tachiyomi.core.i18n.localizePlural import tachiyomi.core.util.lang.launchUI import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy import java.text.NumberFormat @@ -58,12 +61,12 @@ class LibraryUpdateNotifier(private val context: Context) { */ val progressNotificationBuilder by lazy { context.notificationBuilder(Notifications.CHANNEL_LIBRARY_PROGRESS) { - setContentTitle(context.getString(R.string.app_name)) + setContentTitle(context.localize(MR.strings.app_name)) setSmallIcon(R.drawable.ic_refresh_24dp) setLargeIcon(notificationBitmap) setOngoing(true) setOnlyAlertOnce(true) - addAction(R.drawable.ic_close_24dp, context.getString(R.string.action_cancel), cancelIntent) + addAction(R.drawable.ic_close_24dp, context.localize(MR.strings.action_cancel), cancelIntent) } } @@ -77,14 +80,14 @@ class LibraryUpdateNotifier(private val context: Context) { fun showProgressNotification(manga: List, current: Int, total: Int) { if (preferences.hideNotificationContent().get()) { progressNotificationBuilder - .setContentTitle(context.getString(R.string.notification_check_updates)) + .setContentTitle(context.localize(MR.strings.notification_check_updates)) .setContentText("($current/$total)") } else { val updatingText = manga.joinToString("\n") { it.title.chop(40) } progressNotificationBuilder .setContentTitle( - context.getString( - R.string.notification_updating_progress, + context.localize( + MR.strings.notification_updating_progress, percentFormatter.format(current.toFloat() / total), ), ) @@ -104,8 +107,8 @@ class LibraryUpdateNotifier(private val context: Context) { Notifications.ID_LIBRARY_SIZE_WARNING, Notifications.CHANNEL_LIBRARY_PROGRESS, ) { - setContentTitle(context.getString(R.string.label_warning)) - setStyle(NotificationCompat.BigTextStyle().bigText(context.getString(R.string.notification_size_warning))) + setContentTitle(context.localize(MR.strings.label_warning)) + setStyle(NotificationCompat.BigTextStyle().bigText(context.localize(MR.strings.notification_size_warning))) setSmallIcon(R.drawable.ic_warning_white_24dp) setTimeoutAfter(Downloader.WARNING_NOTIF_TIMEOUT_MS) setContentIntent(NotificationHandler.openUrl(context, HELP_WARNING_URL)) @@ -127,8 +130,8 @@ class LibraryUpdateNotifier(private val context: Context) { Notifications.ID_LIBRARY_ERROR, Notifications.CHANNEL_LIBRARY_ERROR, ) { - setContentTitle(context.resources.getString(R.string.notification_update_error, failed)) - setContentText(context.getString(R.string.action_show_errors)) + setContentTitle(context.localize(MR.strings.notification_update_error, failed)) + setContentText(context.localize(MR.strings.action_show_errors)) setSmallIcon(R.drawable.ic_tachi) setContentIntent(NotificationReceiver.openErrorLogPendingActivity(context, uri)) @@ -149,8 +152,8 @@ class LibraryUpdateNotifier(private val context: Context) { Notifications.ID_LIBRARY_SKIPPED, Notifications.CHANNEL_LIBRARY_SKIPPED, ) { - setContentTitle(context.resources.getString(R.string.notification_update_skipped, skipped)) - setContentText(context.getString(R.string.learn_more)) + setContentTitle(context.localize(MR.strings.notification_update_skipped, skipped)) + setContentText(context.localize(MR.strings.learn_more)) setSmallIcon(R.drawable.ic_tachi) setContentIntent(NotificationHandler.openUrl(context, HELP_SKIPPED_URL)) } @@ -167,13 +170,13 @@ class LibraryUpdateNotifier(private val context: Context) { Notifications.ID_NEW_CHAPTERS, Notifications.CHANNEL_NEW_CHAPTERS, ) { - setContentTitle(context.getString(R.string.notification_new_chapters)) + setContentTitle(context.localize(MR.strings.notification_new_chapters)) if (updates.size == 1 && !preferences.hideNotificationContent().get()) { setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN)) } else { setContentText( - context.resources.getQuantityString( - R.plurals.notification_new_chapters_summary, + context.localizePlural( + MR.plurals.notification_new_chapters_summary, updates.size, updates.size, ), @@ -243,7 +246,7 @@ class LibraryUpdateNotifier(private val context: Context) { // Mark chapters as read action addAction( R.drawable.ic_glasses_24dp, - context.getString(R.string.action_mark_as_read), + context.localize(MR.strings.action_mark_as_read), NotificationReceiver.markAsReadPendingBroadcast( context, manga, @@ -254,7 +257,7 @@ class LibraryUpdateNotifier(private val context: Context) { // View chapters action addAction( R.drawable.ic_book_24dp, - context.getString(R.string.action_view_chapters), + context.localize(MR.strings.action_view_chapters), NotificationReceiver.openChapterPendingActivity( context, manga, @@ -266,7 +269,7 @@ class LibraryUpdateNotifier(private val context: Context) { if (chapters.size <= Downloader.CHAPTERS_PER_SOURCE_QUEUE_WARNING_THRESHOLD) { addAction( android.R.drawable.stat_sys_download_done, - context.getString(R.string.action_download), + context.localize(MR.strings.action_download), NotificationReceiver.downloadChaptersPendingBroadcast( context, manga, @@ -306,8 +309,8 @@ class LibraryUpdateNotifier(private val context: Context) { // No sensible chapter numbers to show (i.e. no chapters have parsed chapter number) 0 -> { // "1 new chapter" or "5 new chapters" - context.resources.getQuantityString( - R.plurals.notification_chapters_generic, + context.localizePlural( + MR.plurals.notification_chapters_generic, chapters.size, chapters.size, ) @@ -317,14 +320,14 @@ class LibraryUpdateNotifier(private val context: Context) { val remaining = chapters.size - displayableChapterNumbers.size if (remaining == 0) { // "Chapter 2.5" - context.resources.getString( - R.string.notification_chapters_single, + context.localize( + MR.strings.notification_chapters_single, displayableChapterNumbers.first(), ) } else { // "Chapter 2.5 and 10 more" - context.resources.getString( - R.string.notification_chapters_single_and_more, + context.localize( + MR.strings.notification_chapters_single_and_more, displayableChapterNumbers.first(), remaining, ) @@ -339,16 +342,16 @@ class LibraryUpdateNotifier(private val context: Context) { val joinedChapterNumbers = displayableChapterNumbers .take(NOTIF_MAX_CHAPTERS) .joinToString(", ") - context.resources.getQuantityString( - R.plurals.notification_chapters_multiple_and_more, + context.localizePlural( + MR.plurals.notification_chapters_multiple_and_more, remaining, joinedChapterNumbers, remaining, ) } else { // "Chapters 1, 2.5, 3" - context.resources.getString( - R.string.notification_chapters_multiple, + context.localize( + MR.strings.notification_chapters_multiple, displayableChapterNumbers.joinToString(", "), ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/MetadataUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/MetadataUpdateJob.kt new file mode 100644 index 0000000000..c2121ccf99 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/MetadataUpdateJob.kt @@ -0,0 +1,210 @@ +package eu.kanade.tachiyomi.data.library + +import android.content.Context +import androidx.work.CoroutineWorker +import androidx.work.ExistingWorkPolicy +import androidx.work.ForegroundInfo +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.WorkInfo +import androidx.work.WorkQuery +import androidx.work.WorkerParameters +import eu.kanade.domain.manga.interactor.UpdateManga +import eu.kanade.domain.manga.model.copyFrom +import eu.kanade.domain.manga.model.toSManga +import eu.kanade.tachiyomi.data.cache.CoverCache +import eu.kanade.tachiyomi.data.notification.Notifications +import eu.kanade.tachiyomi.source.UnmeteredSource +import eu.kanade.tachiyomi.util.prepUpdateCover +import eu.kanade.tachiyomi.util.system.isRunning +import eu.kanade.tachiyomi.util.system.workManager +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.ensureActive +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Semaphore +import kotlinx.coroutines.sync.withPermit +import logcat.LogPriority +import tachiyomi.core.util.lang.withIOContext +import tachiyomi.core.util.system.logcat +import tachiyomi.domain.library.model.LibraryManga +import tachiyomi.domain.manga.interactor.GetLibraryManga +import tachiyomi.domain.manga.model.Manga +import tachiyomi.domain.manga.model.toMangaUpdate +import tachiyomi.domain.source.service.SourceManager +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import java.util.concurrent.CopyOnWriteArrayList +import java.util.concurrent.atomic.AtomicInteger + +class MetadataUpdateJob(private val context: Context, workerParams: WorkerParameters) : + CoroutineWorker(context, workerParams) { + + private val sourceManager: SourceManager = Injekt.get() + private val coverCache: CoverCache = Injekt.get() + private val getLibraryManga: GetLibraryManga = Injekt.get() + private val updateManga: UpdateManga = Injekt.get() + + private val notifier = LibraryUpdateNotifier(context) + + private var mangaToUpdate: List = mutableListOf() + + override suspend fun doWork(): Result { + try { + setForeground(getForegroundInfo()) + } catch (e: IllegalStateException) { + logcat(LogPriority.ERROR, e) { "Not allowed to set foreground job" } + } + + addMangaToQueue() + + return withIOContext { + try { + updateMetadata() + Result.success() + } catch (e: Exception) { + if (e is CancellationException) { + // Assume success although cancelled + Result.success() + } else { + logcat(LogPriority.ERROR, e) + Result.failure() + } + } finally { + notifier.cancelProgressNotification() + } + } + } + + override suspend fun getForegroundInfo(): ForegroundInfo { + val notifier = LibraryUpdateNotifier(context) + return ForegroundInfo( + Notifications.ID_LIBRARY_PROGRESS, + notifier.progressNotificationBuilder.build(), + ) + } + + /** + * Adds list of manga to be updated. + */ + private fun addMangaToQueue() { + mangaToUpdate = runBlocking { getLibraryManga.await() } + + // Warn when excessively checking a single source + val maxUpdatesFromSource = mangaToUpdate + .groupBy { it.manga.source } + .filterKeys { sourceManager.get(it) !is UnmeteredSource } + .maxOfOrNull { it.value.size } ?: 0 + if (maxUpdatesFromSource > MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD) { + notifier.showQueueSizeWarningNotification() + } + } + + private suspend fun updateMetadata() { + val semaphore = Semaphore(5) + val progressCount = AtomicInteger(0) + val currentlyUpdatingManga = CopyOnWriteArrayList() + + coroutineScope { + mangaToUpdate.groupBy { it.manga.source } + .values + .map { mangaInSource -> + async { + semaphore.withPermit { + mangaInSource.forEach { libraryManga -> + val manga = libraryManga.manga + ensureActive() + + withUpdateNotification( + currentlyUpdatingManga, + progressCount, + manga, + ) { + val source = sourceManager.get(manga.source) ?: return@withUpdateNotification + try { + val networkManga = source.getMangaDetails(manga.toSManga()) + val updatedManga = manga.prepUpdateCover(coverCache, networkManga, true) + .copyFrom(networkManga) + try { + updateManga.await(updatedManga.toMangaUpdate()) + } catch (e: Exception) { + logcat(LogPriority.ERROR) { "Manga doesn't exist anymore" } + } + } catch (e: Throwable) { + // Ignore errors and continue + logcat(LogPriority.ERROR, e) + } + } + } + } + } + } + .awaitAll() + } + + notifier.cancelProgressNotification() + } + + private suspend fun withUpdateNotification( + updatingManga: CopyOnWriteArrayList, + completed: AtomicInteger, + manga: Manga, + block: suspend () -> Unit, + ) = coroutineScope { + ensureActive() + + updatingManga.add(manga) + notifier.showProgressNotification( + updatingManga, + completed.get(), + mangaToUpdate.size, + ) + + block() + + ensureActive() + + updatingManga.remove(manga) + completed.getAndIncrement() + notifier.showProgressNotification( + updatingManga, + completed.get(), + mangaToUpdate.size, + ) + } + + companion object { + private const val TAG = "MetadataUpdate" + private const val WORK_NAME_MANUAL = "MetadataUpdate" + + private const val MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD = 60 + + fun startNow(context: Context): Boolean { + val wm = context.workManager + if (wm.isRunning(TAG)) { + // Already running either as a scheduled or manual job + return false + } + val request = OneTimeWorkRequestBuilder() + .addTag(TAG) + .addTag(WORK_NAME_MANUAL) + .build() + wm.enqueueUniqueWork(WORK_NAME_MANUAL, ExistingWorkPolicy.KEEP, request) + + return true + } + + fun stop(context: Context) { + val wm = context.workManager + val workQuery = WorkQuery.Builder.fromTags(listOf(TAG)) + .addStates(listOf(WorkInfo.State.RUNNING)) + .build() + wm.getWorkInfos(workQuery).get() + // Should only return one work but just in case + .forEach { + wm.cancelWorkById(it.id) + } + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt index 8f33a63665..db72f71adc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt @@ -7,7 +7,6 @@ import android.content.Intent import android.net.Uri import android.os.Build import androidx.core.net.toUri -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.backup.BackupRestoreJob import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.library.LibraryUpdateJob @@ -32,6 +31,7 @@ import tachiyomi.domain.download.service.DownloadPreferences import tachiyomi.domain.manga.interactor.GetManga import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.source.service.SourceManager +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy @@ -173,7 +173,7 @@ class NotificationReceiver : BroadcastReceiver() { } context.startActivity(intent) } else { - context.toast(R.string.chapter_error) + context.toast(MR.strings.chapter_error) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt index 2559795dbf..a2a5d49c49 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt @@ -5,9 +5,10 @@ import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat.IMPORTANCE_DEFAULT import androidx.core.app.NotificationManagerCompat.IMPORTANCE_HIGH import androidx.core.app.NotificationManagerCompat.IMPORTANCE_LOW -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.system.buildNotificationChannel import eu.kanade.tachiyomi.util.system.buildNotificationChannelGroup +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR /** * Class to manage the basic information of all the notifications used in the app. @@ -102,16 +103,16 @@ object Notifications { notificationManager.createNotificationChannelGroupsCompat( listOf( buildNotificationChannelGroup(GROUP_BACKUP_RESTORE) { - setName(context.getString(R.string.label_backup)) + setName(context.localize(MR.strings.label_backup)) }, buildNotificationChannelGroup(GROUP_DOWNLOADER) { - setName(context.getString(R.string.download_notifier_downloader_title)) + setName(context.localize(MR.strings.download_notifier_downloader_title)) }, buildNotificationChannelGroup(GROUP_LIBRARY) { - setName(context.getString(R.string.label_library)) + setName(context.localize(MR.strings.label_library)) }, buildNotificationChannelGroup(GROUP_APK_UPDATES) { - setName(context.getString(R.string.label_recent_updates)) + setName(context.localize(MR.strings.label_recent_updates)) }, ), ) @@ -119,57 +120,57 @@ object Notifications { notificationManager.createNotificationChannelsCompat( listOf( buildNotificationChannel(CHANNEL_COMMON, IMPORTANCE_LOW) { - setName(context.getString(R.string.channel_common)) + setName(context.localize(MR.strings.channel_common)) }, buildNotificationChannel(CHANNEL_LIBRARY_PROGRESS, IMPORTANCE_LOW) { - setName(context.getString(R.string.channel_progress)) + setName(context.localize(MR.strings.channel_progress)) setGroup(GROUP_LIBRARY) setShowBadge(false) }, buildNotificationChannel(CHANNEL_LIBRARY_ERROR, IMPORTANCE_LOW) { - setName(context.getString(R.string.channel_errors)) + setName(context.localize(MR.strings.channel_errors)) setGroup(GROUP_LIBRARY) setShowBadge(false) }, buildNotificationChannel(CHANNEL_LIBRARY_SKIPPED, IMPORTANCE_LOW) { - setName(context.getString(R.string.channel_skipped)) + setName(context.localize(MR.strings.channel_skipped)) setGroup(GROUP_LIBRARY) setShowBadge(false) }, buildNotificationChannel(CHANNEL_NEW_CHAPTERS, IMPORTANCE_DEFAULT) { - setName(context.getString(R.string.channel_new_chapters)) + setName(context.localize(MR.strings.channel_new_chapters)) }, buildNotificationChannel(CHANNEL_DOWNLOADER_PROGRESS, IMPORTANCE_LOW) { - setName(context.getString(R.string.channel_progress)) + setName(context.localize(MR.strings.channel_progress)) setGroup(GROUP_DOWNLOADER) setShowBadge(false) }, buildNotificationChannel(CHANNEL_DOWNLOADER_ERROR, IMPORTANCE_LOW) { - setName(context.getString(R.string.channel_errors)) + setName(context.localize(MR.strings.channel_errors)) setGroup(GROUP_DOWNLOADER) setShowBadge(false) }, buildNotificationChannel(CHANNEL_BACKUP_RESTORE_PROGRESS, IMPORTANCE_LOW) { - setName(context.getString(R.string.channel_progress)) + setName(context.localize(MR.strings.channel_progress)) setGroup(GROUP_BACKUP_RESTORE) setShowBadge(false) }, buildNotificationChannel(CHANNEL_BACKUP_RESTORE_COMPLETE, IMPORTANCE_HIGH) { - setName(context.getString(R.string.channel_complete)) + setName(context.localize(MR.strings.channel_complete)) setGroup(GROUP_BACKUP_RESTORE) setShowBadge(false) setSound(null, null) }, buildNotificationChannel(CHANNEL_INCOGNITO_MODE, IMPORTANCE_LOW) { - setName(context.getString(R.string.pref_incognito_mode)) + setName(context.localize(MR.strings.pref_incognito_mode)) }, buildNotificationChannel(CHANNEL_APP_UPDATE, IMPORTANCE_DEFAULT) { setGroup(GROUP_APK_UPDATES) - setName(context.getString(R.string.channel_app_updates)) + setName(context.localize(MR.strings.channel_app_updates)) }, buildNotificationChannel(CHANNEL_EXTENSIONS_UPDATE, IMPORTANCE_DEFAULT) { setGroup(GROUP_APK_UPDATES) - setName(context.getString(R.string.channel_ext_updates)) + setName(context.localize(MR.strings.channel_ext_updates)) }, ), ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt index 3cdce975dc..2da5ccfd15 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt @@ -10,14 +10,15 @@ import android.provider.MediaStore import androidx.annotation.RequiresApi import androidx.core.content.contentValuesOf import androidx.core.net.toUri -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.cacheImageDir import eu.kanade.tachiyomi.util.storage.getUriCompat import logcat.LogPriority import okio.IOException +import tachiyomi.core.i18n.localize import tachiyomi.core.util.system.ImageUtil import tachiyomi.core.util.system.logcat +import tachiyomi.i18n.MR import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File @@ -70,7 +71,7 @@ class ImageSaver( val imageLocation = (image.location as Location.Pictures).relativePath val relativePath = listOf( Environment.DIRECTORY_PICTURES, - context.getString(R.string.app_name), + context.localize(MR.strings.app_name), imageLocation, ).joinToString(File.separator) @@ -85,7 +86,7 @@ class ImageSaver( context.contentResolver.insert( pictureDir, contentValues, - ) ?: throw IOException(context.getString(R.string.error_saving_picture)) + ) ?: throw IOException(context.localize(MR.strings.error_saving_picture)) } try { @@ -96,7 +97,7 @@ class ImageSaver( } } catch (e: Exception) { logcat(LogPriority.ERROR, e) - throw IOException(context.getString(R.string.error_saving_picture)) + throw IOException(context.localize(MR.strings.error_saving_picture)) } DiskUtil.scanMedia(context, picture) @@ -184,7 +185,7 @@ sealed interface Location { is Pictures -> { val file = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), - context.getString(R.string.app_name), + context.localize(MR.strings.app_name), ) if (relativePath.isNotEmpty()) { return File( diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt index 732b25cac7..3b3223de9d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/Tracker.kt @@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.data.track import androidx.annotation.CallSuper import androidx.annotation.ColorInt import androidx.annotation.DrawableRes -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.model.TrackSearch import kotlinx.collections.immutable.ImmutableList @@ -28,8 +28,7 @@ interface Tracker { fun getStatusList(): List - @StringRes - fun getStatus(status: Int): Int? + fun getStatus(status: Int): StringResource? fun getReadingStatus(): Int diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt index 6fef751d60..95191bc003 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/Anilist.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.data.track.anilist import android.graphics.Color -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.BaseTracker @@ -12,6 +12,7 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy import tachiyomi.domain.track.model.Track as DomainTrack @@ -60,14 +61,13 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker { return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ, REREADING) } - @StringRes - override fun getStatus(status: Int): Int? = when (status) { - READING -> R.string.reading - PLAN_TO_READ -> R.string.plan_to_read - COMPLETED -> R.string.completed - ON_HOLD -> R.string.on_hold - DROPPED -> R.string.dropped - REREADING -> R.string.repeating + override fun getStatus(status: Int): StringResource? = when (status) { + READING -> MR.strings.reading + PLAN_TO_READ -> MR.strings.plan_to_read + COMPLETED -> MR.strings.completed + ON_HOLD -> MR.strings.on_hold + DROPPED -> MR.strings.dropped + REREADING -> MR.strings.repeating else -> null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt index 8434b3db63..bac2bba6d0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/Bangumi.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.data.track.bangumi import android.graphics.Color -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.BaseTracker @@ -10,6 +10,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy class Bangumi(id: Long) : BaseTracker(id, "Bangumi") { @@ -89,13 +90,12 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") { return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ) } - @StringRes - override fun getStatus(status: Int): Int? = when (status) { - READING -> R.string.reading - PLAN_TO_READ -> R.string.plan_to_read - COMPLETED -> R.string.completed - ON_HOLD -> R.string.on_hold - DROPPED -> R.string.dropped + override fun getStatus(status: Int): StringResource? = when (status) { + READING -> MR.strings.reading + PLAN_TO_READ -> MR.strings.plan_to_read + COMPLETED -> MR.strings.completed + ON_HOLD -> MR.strings.on_hold + DROPPED -> MR.strings.dropped else -> null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt index bee854afde..0fff84efa7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kavita/Kavita.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.data.track.kavita import android.graphics.Color -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.BaseTracker @@ -14,6 +14,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.source.service.SourceManager +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy import java.security.MessageDigest import tachiyomi.domain.track.model.Track as DomainTrack @@ -39,11 +40,10 @@ class Kavita(id: Long) : BaseTracker(id, "Kavita"), EnhancedTracker { override fun getStatusList() = listOf(UNREAD, READING, COMPLETED) - @StringRes - override fun getStatus(status: Int): Int? = when (status) { - UNREAD -> R.string.unread - READING -> R.string.reading - COMPLETED -> R.string.completed + override fun getStatus(status: Int): StringResource? = when (status) { + UNREAD -> MR.strings.unread + READING -> MR.strings.reading + COMPLETED -> MR.strings.completed else -> null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt index 5763b735eb..86fc808adf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.data.track.kitsu import android.graphics.Color -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.BaseTracker @@ -11,6 +11,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy import java.text.DecimalFormat @@ -40,13 +41,12 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker { return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ) } - @StringRes - override fun getStatus(status: Int): Int? = when (status) { - READING -> R.string.reading - PLAN_TO_READ -> R.string.plan_to_read - COMPLETED -> R.string.completed - ON_HOLD -> R.string.on_hold - DROPPED -> R.string.dropped + override fun getStatus(status: Int): StringResource? = when (status) { + READING -> MR.strings.reading + PLAN_TO_READ -> MR.strings.plan_to_read + COMPLETED -> MR.strings.completed + ON_HOLD -> MR.strings.on_hold + DROPPED -> MR.strings.dropped else -> null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt index 5c9d3e6d28..76eabfda96 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/komga/Komga.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.data.track.komga import android.graphics.Color -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.BaseTracker @@ -13,6 +13,7 @@ import kotlinx.collections.immutable.persistentListOf import okhttp3.Dns import okhttp3.OkHttpClient import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import tachiyomi.domain.track.model.Track as DomainTrack class Komga(id: Long) : BaseTracker(id, "Komga"), EnhancedTracker { @@ -36,11 +37,10 @@ class Komga(id: Long) : BaseTracker(id, "Komga"), EnhancedTracker { override fun getStatusList() = listOf(UNREAD, READING, COMPLETED) - @StringRes - override fun getStatus(status: Int): Int? = when (status) { - UNREAD -> R.string.unread - READING -> R.string.reading - COMPLETED -> R.string.completed + override fun getStatus(status: Int): StringResource? = when (status) { + UNREAD -> MR.strings.unread + READING -> MR.strings.reading + COMPLETED -> MR.strings.completed else -> null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt index 86826bb073..698ad123ce 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.data.track.mangaupdates import android.graphics.Color -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.BaseTracker @@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.data.track.mangaupdates.dto.toTrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList +import tachiyomi.i18n.MR class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker { @@ -40,13 +41,12 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker return listOf(READING_LIST, COMPLETE_LIST, ON_HOLD_LIST, UNFINISHED_LIST, WISH_LIST) } - @StringRes - override fun getStatus(status: Int): Int? = when (status) { - READING_LIST -> R.string.reading_list - WISH_LIST -> R.string.wish_list - COMPLETE_LIST -> R.string.complete_list - ON_HOLD_LIST -> R.string.on_hold_list - UNFINISHED_LIST -> R.string.unfinished_list + override fun getStatus(status: Int): StringResource? = when (status) { + READING_LIST -> MR.strings.reading_list + WISH_LIST -> MR.strings.wish_list + COMPLETE_LIST -> MR.strings.complete_list + ON_HOLD_LIST -> MR.strings.on_hold_list + UNFINISHED_LIST -> MR.strings.unfinished_list else -> null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt index bce0e1d0ba..5ab94265c4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeList.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.data.track.myanimelist import android.graphics.Color -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.BaseTracker @@ -11,6 +11,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker { @@ -46,14 +47,13 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker { return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ, REREADING) } - @StringRes - override fun getStatus(status: Int): Int? = when (status) { - READING -> R.string.reading - PLAN_TO_READ -> R.string.plan_to_read - COMPLETED -> R.string.completed - ON_HOLD -> R.string.on_hold - DROPPED -> R.string.dropped - REREADING -> R.string.repeating + override fun getStatus(status: Int): StringResource? = when (status) { + READING -> MR.strings.reading + PLAN_TO_READ -> MR.strings.plan_to_read + COMPLETED -> MR.strings.completed + ON_HOLD -> MR.strings.on_hold + DROPPED -> MR.strings.dropped + REREADING -> MR.strings.repeating else -> null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt index 6a589511c4..d8e2bdd97b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/shikimori/Shikimori.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.data.track.shikimori import android.graphics.Color -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.BaseTracker @@ -11,6 +11,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker { @@ -103,14 +104,13 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker { return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ, REREADING) } - @StringRes - override fun getStatus(status: Int): Int? = when (status) { - READING -> R.string.reading - PLAN_TO_READ -> R.string.plan_to_read - COMPLETED -> R.string.completed - ON_HOLD -> R.string.on_hold - DROPPED -> R.string.dropped - REREADING -> R.string.repeating + override fun getStatus(status: Int): StringResource? = when (status) { + READING -> MR.strings.reading + PLAN_TO_READ -> MR.strings.plan_to_read + COMPLETED -> MR.strings.completed + ON_HOLD -> MR.strings.on_hold + DROPPED -> MR.strings.dropped + REREADING -> MR.strings.repeating else -> null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt index 6e4539ff70..dedafe4864 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/suwayomi/Suwayomi.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.data.track.suwayomi import android.graphics.Color -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.BaseTracker @@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.source.Source import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR import tachiyomi.domain.manga.model.Manga as DomainManga import tachiyomi.domain.track.model.Track as DomainTrack @@ -29,11 +30,10 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker { override fun getStatusList() = listOf(UNREAD, READING, COMPLETED) - @StringRes - override fun getStatus(status: Int): Int? = when (status) { - UNREAD -> R.string.unread - READING -> R.string.reading - COMPLETED -> R.string.completed + override fun getStatus(status: Int): StringResource? = when (status) { + UNREAD -> MR.strings.unread + READING -> MR.strings.reading + COMPLETED -> MR.strings.completed else -> null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateDownloadJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateDownloadJob.kt index 60d5e71ecc..5c54e38c02 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateDownloadJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateDownloadJob.kt @@ -9,7 +9,6 @@ import androidx.work.NetworkType import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkerParameters import androidx.work.workDataOf -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.NetworkHelper @@ -22,8 +21,10 @@ import eu.kanade.tachiyomi.util.system.workManager import logcat.LogPriority import okhttp3.internal.http2.ErrorCode import okhttp3.internal.http2.StreamResetException +import tachiyomi.core.i18n.localize import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.system.logcat +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy import java.io.File import kotlin.coroutines.cancellation.CancellationException @@ -36,7 +37,7 @@ class AppUpdateDownloadJob(private val context: Context, workerParams: WorkerPar override suspend fun doWork(): Result { val url = inputData.getString(EXTRA_DOWNLOAD_URL) - val title = inputData.getString(EXTRA_DOWNLOAD_TITLE) ?: context.getString(R.string.app_name) + val title = inputData.getString(EXTRA_DOWNLOAD_TITLE) ?: context.localize(MR.strings.app_name) if (url.isNullOrEmpty()) { return Result.failure() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateNotifier.kt index afd1479b4f..234532afdf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateNotifier.kt @@ -13,7 +13,9 @@ import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notify +import tachiyomi.core.i18n.localize import tachiyomi.domain.release.model.Release +import tachiyomi.i18n.MR internal class AppUpdateNotifier(private val context: Context) { @@ -51,7 +53,7 @@ internal class AppUpdateNotifier(private val context: Context) { } with(notificationBuilder) { - setContentTitle(context.getString(R.string.update_check_notification_update_available)) + setContentTitle(context.localize(MR.strings.update_check_notification_update_available)) setContentText(release.version) setSmallIcon(android.R.drawable.stat_sys_download_done) setContentIntent(updateIntent) @@ -59,12 +61,12 @@ internal class AppUpdateNotifier(private val context: Context) { clearActions() addAction( android.R.drawable.stat_sys_download_done, - context.getString(R.string.action_download), + context.localize(MR.strings.action_download), updateIntent, ) addAction( R.drawable.ic_info_24dp, - context.getString(R.string.whats_new), + context.localize(MR.strings.whats_new), releaseIntent, ) } @@ -79,14 +81,14 @@ internal class AppUpdateNotifier(private val context: Context) { fun onDownloadStarted(title: String? = null): NotificationCompat.Builder { with(notificationBuilder) { title?.let { setContentTitle(title) } - setContentText(context.getString(R.string.update_check_notification_download_in_progress)) + setContentText(context.localize(MR.strings.update_check_notification_download_in_progress)) setSmallIcon(android.R.drawable.stat_sys_download) setOngoing(true) clearActions() addAction( R.drawable.ic_close_24dp, - context.getString(R.string.action_cancel), + context.localize(MR.strings.action_cancel), NotificationReceiver.cancelDownloadAppUpdatePendingBroadcast(context), ) } @@ -115,7 +117,7 @@ internal class AppUpdateNotifier(private val context: Context) { fun promptInstall(uri: Uri) { val installIntent = NotificationHandler.installApkPendingActivity(context, uri) with(notificationBuilder) { - setContentText(context.getString(R.string.update_check_notification_download_complete)) + setContentText(context.localize(MR.strings.update_check_notification_download_complete)) setSmallIcon(android.R.drawable.stat_sys_download_done) setOnlyAlertOnce(false) setProgress(0, 0, false) @@ -125,12 +127,12 @@ internal class AppUpdateNotifier(private val context: Context) { clearActions() addAction( R.drawable.ic_system_update_alt_white_24dp, - context.getString(R.string.action_install), + context.localize(MR.strings.action_install), installIntent, ) addAction( R.drawable.ic_close_24dp, - context.getString(R.string.action_cancel), + context.localize(MR.strings.action_cancel), NotificationReceiver.dismissNotificationPendingBroadcast(context, Notifications.ID_APP_UPDATE_PROMPT), ) } @@ -145,8 +147,8 @@ internal class AppUpdateNotifier(private val context: Context) { */ fun promptFdroidUpdate() { with(notificationBuilder) { - setContentTitle(context.getString(R.string.update_check_notification_update_available)) - setContentText(context.getString(R.string.update_check_fdroid_migration_info)) + setContentTitle(context.localize(MR.strings.update_check_notification_update_available)) + setContentText(context.localize(MR.strings.update_check_fdroid_migration_info)) setSmallIcon(R.drawable.ic_tachi) setContentIntent( NotificationHandler.openUrl( @@ -165,7 +167,7 @@ internal class AppUpdateNotifier(private val context: Context) { */ fun onDownloadError(url: String) { with(notificationBuilder) { - setContentText(context.getString(R.string.update_check_notification_download_error)) + setContentText(context.localize(MR.strings.update_check_notification_download_error)) setSmallIcon(R.drawable.ic_warning_white_24dp) setOnlyAlertOnce(false) setProgress(0, 0, false) @@ -173,12 +175,12 @@ internal class AppUpdateNotifier(private val context: Context) { clearActions() addAction( R.drawable.ic_refresh_24dp, - context.getString(R.string.action_retry), + context.localize(MR.strings.action_retry), NotificationReceiver.downloadAppUpdatePendingBroadcast(context, url), ) addAction( R.drawable.ic_close_24dp, - context.getString(R.string.action_cancel), + context.localize(MR.strings.action_cancel), NotificationReceiver.dismissNotificationPendingBroadcast(context, Notifications.ID_APP_UPDATER), ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt index 49ca43c89d..58ffe1111b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.extension import android.content.Context import android.graphics.drawable.Drawable import eu.kanade.domain.source.service.SourcePreferences -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi import eu.kanade.tachiyomi.extension.api.ExtensionUpdateNotifier import eu.kanade.tachiyomi.extension.model.Extension @@ -24,6 +23,7 @@ import tachiyomi.core.util.lang.launchNow import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.source.model.StubSource +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.util.Locale @@ -121,7 +121,7 @@ class ExtensionManager( api.findExtensions() } catch (e: Exception) { logcat(LogPriority.ERROR, e) - withUIContext { context.toast(R.string.extension_api_error) } + withUIContext { context.toast(MR.strings.extension_api_error) } emptyList() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionUpdateNotifier.kt index 9080c0c62c..de9739ddef 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionUpdateNotifier.kt @@ -7,6 +7,8 @@ import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.util.system.cancelNotification import eu.kanade.tachiyomi.util.system.notify +import tachiyomi.core.i18n.localizePlural +import tachiyomi.i18n.MR class ExtensionUpdateNotifier(private val context: Context) { @@ -16,8 +18,8 @@ class ExtensionUpdateNotifier(private val context: Context) { Notifications.CHANNEL_EXTENSIONS_UPDATE, ) { setContentTitle( - context.resources.getQuantityString( - R.plurals.update_check_notification_ext_updates, + context.localizePlural( + MR.plurals.update_check_notification_ext_updates, names.size, names.size, ), diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/installer/ShizukuInstaller.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/installer/ShizukuInstaller.kt index 6cc4efd330..68eacd9d66 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/installer/ShizukuInstaller.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/installer/ShizukuInstaller.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.extension.installer import android.app.Service import android.content.pm.PackageManager import android.os.Build -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.util.system.getUriSize import eu.kanade.tachiyomi.util.system.toast @@ -15,6 +14,7 @@ import kotlinx.coroutines.launch import logcat.LogPriority import rikka.shizuku.Shizuku import tachiyomi.core.util.system.logcat +import tachiyomi.i18n.MR import java.io.BufferedReader import java.io.InputStream @@ -116,7 +116,7 @@ class ShizukuInstaller(private val service: Service) : Installer(service) { } } else { logcat(LogPriority.ERROR) { "Shizuku is not ready to use" } - service.toast(R.string.ext_installer_shizuku_stopped) + service.toast(MR.strings.ext_installer_shizuku_stopped) service.stopSelf() false } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstallService.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstallService.kt index e5cf5465d3..f75c9e9512 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstallService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstallService.kt @@ -15,7 +15,9 @@ import eu.kanade.tachiyomi.extension.util.ExtensionInstaller.Companion.EXTRA_DOW import eu.kanade.tachiyomi.util.system.getSerializableExtraCompat import eu.kanade.tachiyomi.util.system.notificationBuilder import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.util.system.logcat +import tachiyomi.i18n.MR class ExtensionInstallService : Service() { @@ -27,7 +29,7 @@ class ExtensionInstallService : Service() { setAutoCancel(false) setOngoing(true) setShowWhen(false) - setContentTitle(getString(R.string.ext_install_service_notif)) + setContentTitle(localize(MR.strings.ext_install_service_notif)) setProgress(100, 100, true) }.build() startForeground(Notifications.ID_EXTENSION_INSTALLER, notification) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt index 1b8fa97696..7e23ca9a30 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt @@ -8,7 +8,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.tab.LocalTabNavigator @@ -24,6 +23,8 @@ import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchScreen import eu.kanade.tachiyomi.ui.browse.source.sourcesTab import eu.kanade.tachiyomi.ui.main.MainActivity import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize data class BrowseTab( private val toExtensions: Boolean = false, @@ -36,7 +37,7 @@ data class BrowseTab( val image = AnimatedImageVector.animatedVectorResource(R.drawable.anim_browse_enter) return TabOptions( index = 3u, - title = stringResource(R.string.browse), + title = localize(MR.strings.browse), icon = rememberAnimatedVectorPainter(image, isSelected), ) } @@ -54,7 +55,7 @@ data class BrowseTab( val extensionsState by extensionsScreenModel.state.collectAsState() TabbedScreen( - titleRes = R.string.browse, + titleRes = MR.strings.browse, tabs = persistentListOf( sourcesTab(), extensionsTab(extensionsScreenModel), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterScreen.kt index 53e709528a..f332424da1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterScreen.kt @@ -10,9 +10,9 @@ import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.browse.ExtensionFilterScreen import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.util.system.toast import kotlinx.coroutines.flow.collectLatest +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR import tachiyomi.presentation.core.screens.LoadingScreen class ExtensionFilterScreen : Screen() { @@ -41,7 +41,7 @@ class ExtensionFilterScreen : Screen() { screenModel.events.collectLatest { when (it) { ExtensionFilterEvent.FailedFetchingLanguages -> { - context.toast(R.string.internal_error) + context.localize(MR.strings.internal_error) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt index 04a2b408d5..13374b28d7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt @@ -1,14 +1,13 @@ package eu.kanade.tachiyomi.ui.browse.extension import android.app.Application -import androidx.annotation.StringRes import androidx.compose.runtime.Immutable import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.screenModelScope +import dev.icerock.moko.resources.StringResource import eu.kanade.domain.extension.interactor.GetExtensionsByType import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.presentation.components.SEARCH_DEBOUNCE_MILLIS -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.InstallStep @@ -28,6 +27,7 @@ import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update import tachiyomi.core.util.lang.launchIO +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import kotlin.time.Duration.Companion.seconds @@ -86,13 +86,13 @@ class ExtensionsScreenModel( val updates = _updates.filter(queryFilter(searchQuery)).map(extensionMapper(downloads)) if (updates.isNotEmpty()) { - itemsGroups[ExtensionUiModel.Header.Resource(R.string.ext_updates_pending)] = updates + itemsGroups[ExtensionUiModel.Header.Resource(MR.strings.ext_updates_pending)] = updates } val installed = _installed.filter(queryFilter(searchQuery)).map(extensionMapper(downloads)) val untrusted = _untrusted.filter(queryFilter(searchQuery)).map(extensionMapper(downloads)) if (installed.isNotEmpty() || untrusted.isNotEmpty()) { - itemsGroups[ExtensionUiModel.Header.Resource(R.string.ext_installed)] = installed + untrusted + itemsGroups[ExtensionUiModel.Header.Resource(MR.strings.ext_installed)] = installed + untrusted } val languagesWithExtensions = _available @@ -209,7 +209,7 @@ typealias ItemGroups = MutableMap 0 }, searchEnabled = true, actions = persistentListOf( AppBar.Action( - title = stringResource(R.string.action_filter), + title = localize(MR.strings.action_filter), icon = Icons.Outlined.Translate, onClick = { navigator.push(ExtensionFilterScreen()) }, ), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationFlags.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationFlags.kt index b03de69b6e..c79c111fc7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationFlags.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationFlags.kt @@ -1,20 +1,21 @@ package eu.kanade.tachiyomi.ui.browse.migration +import dev.icerock.moko.resources.StringResource import eu.kanade.domain.manga.model.hasCustomCover -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.download.DownloadCache import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy data class MigrationFlag( val flag: Int, val isDefaultSelected: Boolean, - val titleId: Int, + val titleId: StringResource, ) { companion object { - fun create(flag: Int, defaultSelectionMap: Int, titleId: Int): MigrationFlag { + fun create(flag: Int, defaultSelectionMap: Int, titleId: StringResource): MigrationFlag { return MigrationFlag( flag = flag, isDefaultSelected = defaultSelectionMap and flag != 0, @@ -53,15 +54,15 @@ object MigrationFlags { /** Returns information about applicable flags with default selections. */ fun getFlags(manga: Manga?, defaultSelectedBitMap: Int): List { val flags = mutableListOf() - flags += MigrationFlag.create(CHAPTERS, defaultSelectedBitMap, R.string.chapters) - flags += MigrationFlag.create(CATEGORIES, defaultSelectedBitMap, R.string.categories) + flags += MigrationFlag.create(CHAPTERS, defaultSelectedBitMap, MR.strings.chapters) + flags += MigrationFlag.create(CATEGORIES, defaultSelectedBitMap, MR.strings.categories) if (manga != null) { if (manga.hasCustomCover(coverCache)) { - flags += MigrationFlag.create(CUSTOM_COVER, defaultSelectedBitMap, R.string.custom_cover) + flags += MigrationFlag.create(CUSTOM_COVER, defaultSelectedBitMap, MR.strings.custom_cover) } if (downloadCache.getDownloadCount(manga) > 0) { - flags += MigrationFlag.create(DELETE_DOWNLOADED, defaultSelectedBitMap, R.string.delete_downloaded) + flags += MigrationFlag.create(DELETE_DOWNLOADED, defaultSelectedBitMap, MR.strings.delete_downloaded) } } return flags diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreen.kt index 8f4de4d95a..6f26c559b3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreen.kt @@ -10,11 +10,11 @@ import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.browse.MigrateMangaScreen import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateSearchScreen import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.util.system.toast import kotlinx.coroutines.flow.collectLatest +import tachiyomi.i18n.MR import tachiyomi.presentation.core.screens.LoadingScreen data class MigrateMangaScreen( @@ -46,7 +46,7 @@ data class MigrateMangaScreen( screenModel.events.collectLatest { event -> when (event) { MigrationMangaEvent.FailedFetchingFavorites -> { - context.toast(R.string.internal_error) + context.toast(MR.strings.internal_error) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt index 1eddff26d7..d9ddc97a20 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt @@ -19,14 +19,12 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.toMutableStateList import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import cafe.adriel.voyager.core.model.StateScreenModel import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.hasCustomCover import eu.kanade.domain.manga.model.toSManga -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.track.EnhancedTracker @@ -49,7 +47,9 @@ import tachiyomi.domain.manga.model.MangaUpdate import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.interactor.InsertTrack +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.LabeledCheckbox +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.LoadingScreen import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -79,7 +79,7 @@ internal fun MigrateDialog( AlertDialog( onDismissRequest = onDismissRequest, title = { - Text(text = stringResource(R.string.migration_dialog_what_to_include)) + Text(text = localize(MR.strings.migration_dialog_what_to_include)) }, text = { Column( @@ -87,7 +87,7 @@ internal fun MigrateDialog( ) { flags.forEachIndexed { index, flag -> LabeledCheckbox( - label = stringResource(flag.titleId), + label = localize(flag.titleId), checked = selectedFlags[index], onCheckedChange = { selectedFlags[index] = it }, ) @@ -104,7 +104,7 @@ internal fun MigrateDialog( onClickTitle() }, ) { - Text(text = stringResource(R.string.action_show_manga)) + Text(text = localize(MR.strings.action_show_manga)) } Spacer(modifier = Modifier.weight(1f)) @@ -122,7 +122,7 @@ internal fun MigrateDialog( } }, ) { - Text(text = stringResource(R.string.copy)) + Text(text = localize(MR.strings.copy)) } TextButton( onClick = { @@ -138,7 +138,7 @@ internal fun MigrateDialog( } }, ) { - Text(text = stringResource(R.string.migrate)) + Text(text = localize(MR.strings.migrate)) } } }, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt index 1a7b039fa2..b3eacd5287 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt @@ -14,7 +14,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource import androidx.paging.compose.collectAsLazyPagingItems import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator @@ -22,7 +21,6 @@ import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.browse.BrowseSourceContent import eu.kanade.presentation.components.SearchToolbar import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel import eu.kanade.tachiyomi.ui.browse.source.browse.SourceFilterDialog @@ -32,8 +30,10 @@ import eu.kanade.tachiyomi.ui.webview.WebViewScreen import kotlinx.coroutines.launch import tachiyomi.core.Constants import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.source.local.LocalSource data class SourceSearchScreen( @@ -66,7 +66,7 @@ data class SourceSearchScreen( floatingActionButton = { AnimatedVisibility(visible = state.filters.isNotEmpty()) { ExtendedFloatingActionButton( - text = { Text(text = stringResource(R.string.action_filter)) }, + text = { Text(text = localize(MR.strings.action_filter)) }, icon = { Icon(Icons.Outlined.FilterList, contentDescription = null) }, onClick = screenModel::openFilterSheet, ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceTab.kt index 3807c802e9..eb36ce6ffd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceTab.kt @@ -2,12 +2,10 @@ package eu.kanade.tachiyomi.ui.browse.migration.sources import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.HelpOutline -import androidx.compose.material.icons.outlined.HelpOutline import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.navigator.LocalNavigator @@ -15,9 +13,10 @@ import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.browse.MigrateSourceScreen import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.TabContent -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrateMangaScreen import kotlinx.collections.immutable.persistentListOf +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize @Composable fun Screen.migrateSourceTab(): TabContent { @@ -27,10 +26,10 @@ fun Screen.migrateSourceTab(): TabContent { val state by screenModel.state.collectAsState() return TabContent( - titleRes = R.string.label_migration, + titleRes = MR.strings.label_migration, actions = persistentListOf( AppBar.Action( - title = stringResource(R.string.migration_help_guide), + title = localize(MR.strings.migration_help_guide), icon = Icons.AutoMirrored.Outlined.HelpOutline, onClick = { uriHandler.openUri("https://tachiyomi.org/docs/guides/source-migration") diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt index f3480242da..f225b397a4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt @@ -10,8 +10,8 @@ import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.browse.SourcesFilterScreen import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.util.system.toast +import tachiyomi.i18n.MR import tachiyomi.presentation.core.screens.LoadingScreen class SourcesFilterScreen : Screen() { @@ -30,7 +30,7 @@ class SourcesFilterScreen : Screen() { if (state is SourcesFilterScreenModel.State.Error) { val context = LocalContext.current LaunchedEffect(Unit) { - context.toast(R.string.internal_error) + context.toast(MR.strings.internal_error) navigator.pop() } return diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt index 9720af18ec..5fdd9d7fbf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt @@ -7,7 +7,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.navigator.LocalNavigator @@ -16,12 +15,13 @@ import eu.kanade.presentation.browse.SourceOptionsDialog import eu.kanade.presentation.browse.SourcesScreen import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.TabContent -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchScreen import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize @Composable fun Screen.sourcesTab(): TabContent { @@ -30,15 +30,15 @@ fun Screen.sourcesTab(): TabContent { val state by screenModel.state.collectAsState() return TabContent( - titleRes = R.string.label_sources, + titleRes = MR.strings.label_sources, actions = persistentListOf( AppBar.Action( - title = stringResource(R.string.action_global_search), + title = localize(MR.strings.action_global_search), icon = Icons.Outlined.TravelExplore, onClick = { navigator.push(GlobalSearchScreen()) }, ), AppBar.Action( - title = stringResource(R.string.action_filter), + title = localize(MR.strings.action_filter), icon = Icons.Outlined.FilterList, onClick = { navigator.push(SourcesFilterScreen()) }, ), @@ -70,7 +70,7 @@ fun Screen.sourcesTab(): TabContent { ) } - val internalErrString = stringResource(R.string.internal_error) + val internalErrString = localize(MR.strings.internal_error) LaunchedEffect(Unit) { screenModel.events.collectLatest { event -> when (event) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt index 99c4545372..69b4d20cbb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt @@ -31,7 +31,6 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource import androidx.paging.compose.collectAsLazyPagingItems import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator @@ -44,7 +43,6 @@ import eu.kanade.presentation.category.components.ChangeCategoryDialog import eu.kanade.presentation.manga.DuplicateMangaDialog import eu.kanade.presentation.util.AssistContentScreen import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen @@ -58,8 +56,10 @@ import kotlinx.coroutines.flow.receiveAsFlow import tachiyomi.core.Constants import tachiyomi.core.util.lang.launchIO import tachiyomi.domain.source.model.StubSource +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import tachiyomi.source.local.LocalSource data class BrowseSourceScreen( @@ -150,7 +150,7 @@ data class BrowseSourceScreen( ) }, label = { - Text(text = stringResource(R.string.popular)) + Text(text = localize(MR.strings.popular)) }, ) if ((screenModel.source as CatalogueSource).supportsLatest) { @@ -169,7 +169,7 @@ data class BrowseSourceScreen( ) }, label = { - Text(text = stringResource(R.string.latest)) + Text(text = localize(MR.strings.latest)) }, ) } @@ -186,7 +186,7 @@ data class BrowseSourceScreen( ) }, label = { - Text(text = stringResource(R.string.action_filter)) + Text(text = localize(MR.strings.action_filter)) }, ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterDialog.kt index 5ec0769dca..6a73bbd8ad 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterDialog.kt @@ -14,13 +14,12 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import eu.kanade.presentation.components.AdaptiveSheet -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.FilterList import tachiyomi.core.preference.TriState +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.CheckboxItem import tachiyomi.presentation.core.components.CollapsibleBox import tachiyomi.presentation.core.components.HeadingItem @@ -29,6 +28,7 @@ import tachiyomi.presentation.core.components.SortItem import tachiyomi.presentation.core.components.TextItem import tachiyomi.presentation.core.components.TriStateItem import tachiyomi.presentation.core.components.material.Button +import tachiyomi.presentation.core.i18n.localize @Composable fun SourceFilterDialog( @@ -52,7 +52,7 @@ fun SourceFilterDialog( ) { TextButton(onClick = onReset) { Text( - text = stringResource(R.string.action_reset), + text = localize(MR.strings.action_reset), style = LocalTextStyle.current.copy( color = MaterialTheme.colorScheme.primary, ), @@ -65,7 +65,7 @@ fun SourceFilterDialog( onFilter() onDismissRequest() }) { - Text(stringResource(R.string.action_filter)) + Text(localize(MR.strings.action_filter)) } } HorizontalDivider() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreenModel.kt index 33b7ea1483..2fb78342fd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreenModel.kt @@ -1,10 +1,9 @@ package eu.kanade.tachiyomi.ui.category -import androidx.annotation.StringRes import androidx.compose.runtime.Immutable import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.screenModelScope -import eu.kanade.tachiyomi.R +import dev.icerock.moko.resources.StringResource import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.channels.Channel @@ -18,6 +17,7 @@ import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.RenameCategory import tachiyomi.domain.category.interactor.ReorderCategory import tachiyomi.domain.category.model.Category +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -128,8 +128,8 @@ sealed interface CategoryDialog { } sealed interface CategoryEvent { - sealed class LocalizedMessage(@StringRes val stringRes: Int) : CategoryEvent - data object InternalError : LocalizedMessage(R.string.internal_error) + sealed class LocalizedMessage(val stringRes: StringResource) : CategoryEvent + data object InternalError : LocalizedMessage(MR.strings.internal_error) } sealed interface CategoryScreenState { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/DeepLinkScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/DeepLinkScreen.kt index 87e75f46b3..c4b166cb75 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/DeepLinkScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/DeepLinkScreen.kt @@ -6,17 +6,17 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchScreen import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.ui.reader.ReaderActivity +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.LoadingScreen class DeepLinkScreen( @@ -35,7 +35,7 @@ class DeepLinkScreen( Scaffold( topBar = { scrollBehavior -> AppBar( - title = stringResource(R.string.action_search_hint), + title = localize(MR.strings.action_search_hint), navigateUp = navigator::pop, scrollBehavior = scrollBehavior, ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadQueueScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadQueueScreen.kt index f0807d5de3..938b49e88a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadQueueScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadQueueScreen.kt @@ -13,7 +13,6 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.Sort import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.outlined.Pause -import androidx.compose.material.icons.outlined.Sort import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -36,7 +35,6 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.dp @@ -53,13 +51,14 @@ import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.DropdownMenu import eu.kanade.presentation.components.NestedMenuItem import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.databinding.DownloadListBinding import kotlinx.collections.immutable.persistentListOf import tachiyomi.core.util.lang.launchUI +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.Pill import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import kotlin.math.roundToInt @@ -105,7 +104,7 @@ object DownloadQueueScreen : Screen() { titleContent = { Row(verticalAlignment = Alignment.CenterVertically) { Text( - text = stringResource(R.string.label_download_queue), + text = localize(MR.strings.label_download_queue), maxLines = 1, modifier = Modifier.weight(1f, false), overflow = TextOverflow.Ellipsis, @@ -132,10 +131,10 @@ object DownloadQueueScreen : Screen() { onDismissRequest = onDismissRequest, ) { NestedMenuItem( - text = { Text(text = stringResource(R.string.action_order_by_upload_date)) }, + text = { Text(text = localize(MR.strings.action_order_by_upload_date)) }, children = { closeMenu -> DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_newest)) }, + text = { Text(text = localize(MR.strings.action_newest)) }, onClick = { screenModel.reorderQueue( { it.download.chapter.dateUpload }, @@ -145,7 +144,7 @@ object DownloadQueueScreen : Screen() { }, ) DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_oldest)) }, + text = { Text(text = localize(MR.strings.action_oldest)) }, onClick = { screenModel.reorderQueue( { it.download.chapter.dateUpload }, @@ -157,10 +156,10 @@ object DownloadQueueScreen : Screen() { }, ) NestedMenuItem( - text = { Text(text = stringResource(R.string.action_order_by_chapter_number)) }, + text = { Text(text = localize(MR.strings.action_order_by_chapter_number)) }, children = { closeMenu -> DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_asc)) }, + text = { Text(text = localize(MR.strings.action_asc)) }, onClick = { screenModel.reorderQueue( { it.download.chapter.chapterNumber }, @@ -170,7 +169,7 @@ object DownloadQueueScreen : Screen() { }, ) DropdownMenuItem( - text = { Text(text = stringResource(R.string.action_desc)) }, + text = { Text(text = localize(MR.strings.action_desc)) }, onClick = { screenModel.reorderQueue( { it.download.chapter.chapterNumber }, @@ -186,12 +185,12 @@ object DownloadQueueScreen : Screen() { AppBarActions( persistentListOf( AppBar.Action( - title = stringResource(R.string.action_sort), + title = localize(MR.strings.action_sort), icon = Icons.AutoMirrored.Outlined.Sort, onClick = { sortExpanded = true }, ), AppBar.OverflowAction( - title = stringResource(R.string.action_cancel_all), + title = localize(MR.strings.action_cancel_all), onClick = { screenModel.clearQueue() }, ), ), @@ -211,11 +210,11 @@ object DownloadQueueScreen : Screen() { ExtendedFloatingActionButton( text = { val id = if (isRunning) { - R.string.action_pause + MR.strings.action_pause } else { - R.string.action_resume + MR.strings.action_resume } - Text(text = stringResource(id)) + Text(text = localize(id)) }, icon = { val icon = if (isRunning) { @@ -239,7 +238,7 @@ object DownloadQueueScreen : Screen() { ) { contentPadding -> if (downloadList.isEmpty()) { EmptyScreen( - textResource = R.string.information_no_downloads, + stringRes = MR.strings.information_no_downloads, modifier = Modifier.padding(contentPadding), ) return@Scaffold diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt index 2306216a7d..c813343eea 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt @@ -10,7 +10,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.Navigator @@ -28,7 +27,10 @@ import eu.kanade.tachiyomi.ui.reader.ReaderActivity import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.receiveAsFlow +import tachiyomi.core.i18n.localize import tachiyomi.domain.chapter.model.Chapter +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize object HistoryTab : Tab { @@ -43,7 +45,7 @@ object HistoryTab : Tab { val image = AnimatedImageVector.animatedVectorResource(R.drawable.anim_history_enter) return TabOptions( index = 2u, - title = stringResource(R.string.label_recent_manga), + title = localize(MR.strings.label_recent_manga), icon = rememberAnimatedVectorPainter(image, isSelected), ) } @@ -101,9 +103,9 @@ object HistoryTab : Tab { screenModel.events.collectLatest { e -> when (e) { HistoryScreenModel.Event.InternalError -> - snackbarHostState.showSnackbar(context.getString(R.string.internal_error)) + snackbarHostState.showSnackbar(context.localize(MR.strings.internal_error)) HistoryScreenModel.Event.HistoryCleared -> - snackbarHostState.showSnackbar(context.getString(R.string.clear_history_completed)) + snackbarHostState.showSnackbar(context.localize(MR.strings.clear_history_completed)) is HistoryScreenModel.Event.OpenChapter -> openChapter(context, e.chapter) } } @@ -121,7 +123,7 @@ object HistoryTab : Tab { val intent = ReaderActivity.newIntent(context, chapter.mangaId, chapter.id) context.startActivity(intent) } else { - snackbarHostState.showSnackbar(context.getString(R.string.no_next_chapter)) + snackbarHostState.showSnackbar(context.localize(MR.strings.no_next_chapter)) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt index 2eb992478e..c4aecb8c4e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt @@ -25,7 +25,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.produceState import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier -import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextOverflow @@ -37,7 +36,6 @@ import cafe.adriel.voyager.navigator.tab.TabNavigator import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.isTabletUi -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.BrowseTab import eu.kanade.tachiyomi.ui.download.DownloadQueueScreen import eu.kanade.tachiyomi.ui.history.HistoryTab @@ -53,9 +51,11 @@ import kotlinx.coroutines.launch import soup.compose.material.motion.animation.materialFadeThroughIn import soup.compose.material.motion.animation.materialFadeThroughOut import tachiyomi.domain.library.service.LibraryPreferences +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.NavigationBar import tachiyomi.presentation.core.components.material.NavigationRail import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localizePlural import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -241,8 +241,8 @@ object HomeScreen : Screen() { } if (count > 0) { Badge { - val desc = pluralStringResource( - id = R.plurals.notification_chapters_generic, + val desc = localizePlural( + MR.plurals.notification_chapters_generic, count = count, count, ) @@ -260,8 +260,8 @@ object HomeScreen : Screen() { } if (count > 0) { Badge { - val desc = pluralStringResource( - id = R.plurals.update_check_notification_ext_updates, + val desc = localizePlural( + MR.plurals.update_check_notification_ext_updates, count = count, count, ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt index d6f0afc4df..e6a79582e7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt @@ -7,7 +7,6 @@ import androidx.compose.animation.graphics.vector.AnimatedImageVector import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.HelpOutline -import androidx.compose.material.icons.outlined.HelpOutline import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable @@ -21,7 +20,6 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource import androidx.compose.ui.util.fastAll import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator @@ -49,11 +47,14 @@ import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch +import tachiyomi.core.i18n.localize import tachiyomi.core.util.lang.launchIO import tachiyomi.domain.category.model.Category import tachiyomi.domain.library.model.LibraryManga import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.EmptyScreenAction import tachiyomi.presentation.core.screens.LoadingScreen @@ -68,7 +69,7 @@ object LibraryTab : Tab { val image = AnimatedImageVector.animatedVectorResource(R.drawable.anim_library_enter) return TabOptions( index = 0u, - title = stringResource(R.string.label_library), + title = localize(MR.strings.label_library), icon = rememberAnimatedVectorPainter(image, isSelected), ) } @@ -94,11 +95,11 @@ object LibraryTab : Tab { val started = LibraryUpdateJob.startNow(context, category) scope.launch { val msgRes = when { - !started -> R.string.update_already_running - category != null -> R.string.updating_category - else -> R.string.updating_library + !started -> MR.strings.update_already_running + category != null -> MR.strings.updating_category + else -> MR.strings.updating_library } - snackbarHostState.showSnackbar(context.getString(msgRes)) + snackbarHostState.showSnackbar(context.localize(msgRes)) } started } @@ -106,8 +107,8 @@ object LibraryTab : Tab { Scaffold( topBar = { scrollBehavior -> val title = state.getToolbarTitle( - defaultTitle = stringResource(R.string.label_library), - defaultCategoryTitle = stringResource(R.string.label_default), + defaultTitle = localize(MR.strings.label_library), + defaultCategoryTitle = localize(MR.strings.label_default), page = screenModel.activeCategoryIndex, ) val tabVisible = state.showCategoryTabs && state.categories.size > 1 @@ -127,7 +128,9 @@ object LibraryTab : Tab { if (randomItem != null) { navigator.push(MangaScreen(randomItem.libraryManga.manga.id)) } else { - snackbarHostState.showSnackbar(context.getString(R.string.information_no_entries_found)) + snackbarHostState.showSnackbar( + context.localize(MR.strings.information_no_entries_found), + ) } } }, @@ -154,11 +157,11 @@ object LibraryTab : Tab { state.searchQuery.isNullOrEmpty() && !state.hasActiveFilters && state.isLibraryEmpty -> { val handler = LocalUriHandler.current EmptyScreen( - textResource = R.string.information_empty_library, + stringRes = MR.strings.information_empty_library, modifier = Modifier.padding(contentPadding), actions = persistentListOf( EmptyScreenAction( - stringResId = R.string.getting_started_guide, + stringRes = MR.strings.getting_started_guide, icon = Icons.AutoMirrored.Outlined.HelpOutline, onClick = { handler.openUri("https://tachiyomi.org/docs/guides/getting-started") }, ), @@ -184,7 +187,7 @@ object LibraryTab : Tab { ReaderActivity.newIntent(context, chapter.mangaId, chapter.id), ) } else { - snackbarHostState.showSnackbar(context.getString(R.string.no_next_chapter)) + snackbarHostState.showSnackbar(context.localize(MR.strings.no_next_chapter)) } } Unit diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 51ee88cf12..4ebf3891f7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -34,7 +34,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.luminance import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.core.animation.doOnEnd import androidx.core.net.toUri @@ -61,7 +60,6 @@ import eu.kanade.presentation.util.AssistContentScreen import eu.kanade.presentation.util.DefaultNavigatorScreenTransition import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.Migrations -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.download.DownloadCache import eu.kanade.tachiyomi.data.notification.NotificationReceiver @@ -93,7 +91,9 @@ import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.system.logcat import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.release.interactor.GetApplicationRelease +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -257,15 +257,15 @@ class MainActivity : BaseActivity() { if (showChangelog) { AlertDialog( onDismissRequest = { showChangelog = false }, - title = { Text(text = stringResource(R.string.updated_version, BuildConfig.VERSION_NAME)) }, + title = { Text(text = localize(MR.strings.updated_version, BuildConfig.VERSION_NAME)) }, dismissButton = { TextButton(onClick = { openInBrowser(RELEASE_URL) }) { - Text(text = stringResource(R.string.whats_new)) + Text(text = localize(MR.strings.whats_new)) } }, confirmButton = { TextButton(onClick = { showChangelog = false }) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } }, ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaCoverScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaCoverScreenModel.kt index 67b98556f3..1bf3738667 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaCoverScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaCoverScreenModel.kt @@ -9,7 +9,6 @@ import coil.imageLoader import coil.request.ImageRequest import coil.size.Size import eu.kanade.domain.manga.interactor.UpdateManga -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.saver.Image import eu.kanade.tachiyomi.data.saver.ImageSaver @@ -20,12 +19,14 @@ import eu.kanade.tachiyomi.util.system.toShareIntent import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.manga.interactor.GetManga import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -51,13 +52,13 @@ class MangaCoverScreenModel( try { saveCoverInternal(context, temp = false) snackbarHostState.showSnackbar( - context.getString(R.string.cover_saved), + context.localize(MR.strings.cover_saved), withDismissAction = true, ) } catch (e: Throwable) { logcat(LogPriority.ERROR, e) snackbarHostState.showSnackbar( - context.getString(R.string.error_saving_cover), + context.localize(MR.strings.error_saving_cover), withDismissAction = true, ) } @@ -74,7 +75,7 @@ class MangaCoverScreenModel( } catch (e: Throwable) { logcat(LogPriority.ERROR, e) snackbarHostState.showSnackbar( - context.getString(R.string.error_sharing_cover), + context.localize(MR.strings.error_sharing_cover), withDismissAction = true, ) } @@ -145,7 +146,7 @@ class MangaCoverScreenModel( private fun notifyCoverUpdated(context: Context) { screenModelScope.launch { snackbarHostState.showSnackbar( - context.getString(R.string.cover_updated), + context.localize(MR.strings.cover_updated), withDismissAction = true, ) } @@ -154,7 +155,7 @@ class MangaCoverScreenModel( private fun notifyFailedCoverUpdate(context: Context, e: Throwable) { screenModelScope.launch { snackbarHostState.showSnackbar( - context.getString(R.string.notification_cover_update_failed), + context.localize(MR.strings.notification_cover_update_failed), withDismissAction = true, ) logcat(LogPriority.ERROR, e) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt index 0931ea1fe3..60065bae5a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt @@ -37,7 +37,6 @@ import eu.kanade.presentation.manga.components.SetIntervalDialog import eu.kanade.presentation.util.AssistContentScreen import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.isTabletUi -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.isLocalOrStub import eu.kanade.tachiyomi.source.online.HttpSource @@ -54,10 +53,12 @@ import eu.kanade.tachiyomi.util.system.toShareIntent import eu.kanade.tachiyomi.util.system.toast import kotlinx.coroutines.launch import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import tachiyomi.presentation.core.screens.LoadingScreen class MangaScreen( @@ -291,7 +292,7 @@ class MangaScreen( context.startActivity( Intent.createChooser( intent, - context.getString(R.string.action_share), + context.localize(MR.strings.action_share), ), ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt index 3f084c9169..68c674299e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt @@ -25,7 +25,6 @@ import eu.kanade.domain.ui.UiPreferences import eu.kanade.presentation.manga.DownloadAction import eu.kanade.presentation.manga.components.ChapterDownloadAction import eu.kanade.presentation.util.formattedMessage -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.DownloadCache import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.model.Download @@ -50,6 +49,7 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.preference.CheckboxState import tachiyomi.core.preference.TriState import tachiyomi.core.preference.mapAsCheckboxState @@ -78,6 +78,7 @@ import tachiyomi.domain.manga.model.applyFilter import tachiyomi.domain.manga.repository.MangaRepository import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.track.interactor.GetTracks +import tachiyomi.i18n.MR import tachiyomi.source.local.isLocal import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -281,8 +282,8 @@ class MangaScreenModel( screenModelScope.launch { if (!hasDownloads()) return@launch val result = snackbarHostState.showSnackbar( - message = context.getString(R.string.delete_downloads_for_manga), - actionLabel = context.getString(R.string.action_delete), + message = context.localize(MR.strings.delete_downloads_for_manga), + actionLabel = context.localize(MR.strings.action_delete), withDismissAction = true, ) if (result == SnackbarResult.ActionPerformed) { @@ -550,7 +551,7 @@ class MangaScreenModel( } } catch (e: Throwable) { val message = if (e is NoChaptersException) { - context.getString(R.string.no_chapters_error) + context.localize(MR.strings.no_chapters_error) } else { logcat(LogPriority.ERROR, e) with(context) { e.formattedMessage } @@ -647,8 +648,8 @@ class MangaScreenModel( } screenModelScope.launch { val result = snackbarHostState.showSnackbar( - message = context.getString(R.string.snack_add_to_library), - actionLabel = context.getString(R.string.action_add), + message = context.localize(MR.strings.snack_add_to_library), + actionLabel = context.localize(MR.strings.action_add), withDismissAction = true, ) if (result == SnackbarResult.ActionPerformed && !isFavorited) { @@ -869,7 +870,7 @@ class MangaScreenModel( if (applyToExisting) { setMangaDefaultChapterFlags.awaitAll() } - snackbarHostState.showSnackbar(message = context.getString(R.string.chapter_settings_updated)) + snackbarHostState.showSnackbar(message = context.localize(MR.strings.chapter_settings_updated)) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt index 3f33b96516..64d281f7c9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt @@ -28,7 +28,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -39,6 +38,7 @@ import cafe.adriel.voyager.core.model.screenModelScope import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.currentOrThrow +import dev.icerock.moko.resources.StringResource import eu.kanade.domain.track.interactor.RefreshTracks import eu.kanade.domain.track.model.toDbTrack import eu.kanade.domain.ui.UiPreferences @@ -49,7 +49,6 @@ import eu.kanade.presentation.track.TrackScoreSelector import eu.kanade.presentation.track.TrackStatusSelector import eu.kanade.presentation.track.TrackerSearch import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.track.DeletableTracker import eu.kanade.tachiyomi.data.track.EnhancedTracker import eu.kanade.tachiyomi.data.track.Tracker @@ -66,6 +65,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.util.lang.launchNonCancellable import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withUIContext @@ -75,9 +75,11 @@ import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.track.interactor.DeleteTrack import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.model.Track +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.components.material.AlertDialogContent import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.time.Instant @@ -210,7 +212,7 @@ data class TrackInfoDialogHomeScreen( val matchResult = item.tracker.match(manga) ?: throw Exception() item.tracker.register(matchResult, mangaId) } catch (e: Exception) { - withUIContext { Injekt.get().toast(R.string.error_no_match) } + withUIContext { Injekt.get().toast(MR.strings.error_no_match) } } } } @@ -227,10 +229,10 @@ data class TrackInfoDialogHomeScreen( } withUIContext { context.toast( - context.getString( - R.string.track_error, + context.localize( + MR.strings.track_error, track!!.name, - e.message, + e.message ?: "", ), ) } @@ -286,7 +288,7 @@ private data class TrackStatusSelectorScreen( private val tracker: Tracker, ) : StateScreenModel(State(track.status.toInt())) { - fun getSelections(): Map { + fun getSelections(): Map { return tracker.getStatusList().associateWith { tracker.getStatus(it) } } @@ -500,9 +502,9 @@ private data class TrackDateSelectorScreen( } TrackDateSelector( title = if (start) { - stringResource(R.string.track_started_reading_date) + localize(MR.strings.track_started_reading_date) } else { - stringResource(R.string.track_finished_reading_date) + localize(MR.strings.track_finished_reading_date) }, initialSelectedDateMillis = screenModel.initialSelection, selectableDates = selectableDates, @@ -575,7 +577,7 @@ private data class TrackDateRemoverScreen( }, title = { Text( - text = stringResource(R.string.track_remove_date_conf_title), + text = localize(MR.strings.track_remove_date_conf_title), textAlign = TextAlign.Center, ) }, @@ -583,9 +585,9 @@ private data class TrackDateRemoverScreen( val serviceName = screenModel.getServiceName() Text( text = if (start) { - stringResource(R.string.track_remove_start_date_conf_text, serviceName) + localize(MR.strings.track_remove_start_date_conf_text, serviceName) } else { - stringResource(R.string.track_remove_finish_date_conf_text, serviceName) + localize(MR.strings.track_remove_finish_date_conf_text, serviceName) }, ) }, @@ -595,7 +597,7 @@ private data class TrackDateRemoverScreen( horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small, Alignment.End), ) { TextButton(onClick = navigator::pop) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } FilledTonalButton( onClick = { @@ -607,7 +609,7 @@ private data class TrackDateRemoverScreen( contentColor = MaterialTheme.colorScheme.onErrorContainer, ), ) { - Text(text = stringResource(R.string.action_remove)) + Text(text = localize(MR.strings.action_remove)) } } }, @@ -751,7 +753,7 @@ private data class TrackerRemoveScreen( }, title = { Text( - text = stringResource(R.string.track_delete_title, serviceName), + text = localize(MR.strings.track_delete_title, serviceName), textAlign = TextAlign.Center, ) }, @@ -760,12 +762,12 @@ private data class TrackerRemoveScreen( verticalArrangement = Arrangement.spacedBy(8.dp), ) { Text( - text = stringResource(R.string.track_delete_text, serviceName), + text = localize(MR.strings.track_delete_text, serviceName), ) if (screenModel.isDeletable()) { LabeledCheckbox( - label = stringResource(R.string.track_delete_remote_text, serviceName), + label = localize(MR.strings.track_delete_remote_text, serviceName), checked = removeRemoteTrack, onCheckedChange = { removeRemoteTrack = it }, ) @@ -781,7 +783,7 @@ private data class TrackerRemoveScreen( ), ) { TextButton(onClick = navigator::pop) { - Text(text = stringResource(R.string.action_cancel)) + Text(text = localize(MR.strings.action_cancel)) } FilledTonalButton( onClick = { @@ -794,7 +796,7 @@ private data class TrackerRemoveScreen( contentColor = MaterialTheme.colorScheme.onErrorContainer, ), ) { - Text(text = stringResource(R.string.action_ok)) + Text(text = localize(MR.strings.action_ok)) } } }, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt index 8179fe68d4..28bc495839 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt @@ -8,7 +8,6 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.screenModelScope @@ -34,6 +33,8 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import tachiyomi.core.util.lang.launchIO +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -46,7 +47,7 @@ object MoreTab : Tab { val image = AnimatedImageVector.animatedVectorResource(R.drawable.anim_more_enter) return TabOptions( index = 4u, - title = stringResource(R.string.label_more), + title = localize(MR.strings.label_more), icon = rememberAnimatedVectorPainter(image, isSelected), ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index 108b9dcefb..0a931611a6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -27,7 +27,6 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.core.graphics.ColorUtils import androidx.core.net.toUri @@ -85,11 +84,13 @@ import kotlinx.coroutines.flow.sample import kotlinx.coroutines.launch import logcat.LogPriority import tachiyomi.core.Constants +import tachiyomi.core.i18n.localize import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.lang.launchNonCancellable import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -372,7 +373,7 @@ class ReaderActivity : BaseActivity() { onClickCropBorder = { val enabled = viewModel.toggleCropBorders() menuToggleToast?.cancel() - menuToggleToast = toast(if (enabled) R.string.on else R.string.off) + menuToggleToast = toast(if (enabled) MR.strings.on else MR.strings.off) }, onClickSettings = viewModel::openSettingsDialog, ) @@ -399,7 +400,7 @@ class ReaderActivity : BaseActivity() { verticalAlignment = Alignment.CenterVertically, ) { CircularProgressIndicator() - Text(stringResource(R.string.loading)) + Text(localize(MR.strings.loading)) } }, ) @@ -536,7 +537,7 @@ class ReaderActivity : BaseActivity() { private fun shareChapter() { assistUrl?.let { val intent = it.toUri().toShareIntent(this, type = "text/plain") - startActivity(Intent.createChooser(intent, getString(R.string.action_share))) + startActivity(Intent.createChooser(intent, localize(MR.strings.action_share))) } } @@ -683,9 +684,9 @@ class ReaderActivity : BaseActivity() { val intent = uri.toShareIntent( context = applicationContext, - message = getString(R.string.share_page_info, manga.title, chapter.name, page.number), + message = localize(MR.strings.share_page_info, manga.title, chapter.name, page.number), ) - startActivity(Intent.createChooser(intent, getString(R.string.action_share))) + startActivity(Intent.createChooser(intent, localize(MR.strings.action_share))) } /** @@ -695,7 +696,7 @@ class ReaderActivity : BaseActivity() { private fun onSaveImageResult(result: ReaderViewModel.SaveImageResult) { when (result) { is ReaderViewModel.SaveImageResult.Success -> { - toast(R.string.picture_saved) + toast(MR.strings.picture_saved) } is ReaderViewModel.SaveImageResult.Error -> { logcat(LogPriority.ERROR, result.error) @@ -710,9 +711,9 @@ class ReaderActivity : BaseActivity() { private fun onSetAsCoverResult(result: ReaderViewModel.SetAsCoverResult) { toast( when (result) { - Success -> R.string.cover_updated - AddToLibraryFirst -> R.string.notification_first_add_to_library - Error -> R.string.notification_cover_update_failed + Success -> MR.strings.cover_updated + AddToLibraryFirst -> MR.strings.notification_first_add_to_library + Error -> MR.strings.notification_cover_update_failed }, ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderNavigationOverlayView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderNavigationOverlayView.kt index f96242b69f..af121a27cc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderNavigationOverlayView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderNavigationOverlayView.kt @@ -13,6 +13,7 @@ import androidx.core.graphics.withTranslation import androidx.core.view.isVisible import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation import eu.kanade.tachiyomi.ui.reader.viewer.navigation.DisabledNavigation +import tachiyomi.core.i18n.localize import kotlin.math.abs class ReaderNavigationOverlayView(context: Context, attributeSet: AttributeSet) : View(context, attributeSet) { @@ -79,8 +80,8 @@ class ReaderNavigationOverlayView(context: Context, attributeSet: AttributeSet) // Calculate center of rect height on screen val y = height * (abs(rect.top - rect.bottom) / 2) - drawText(context.getString(region.type.nameRes), x, y, textBorderPaint) - drawText(context.getString(region.type.nameRes), x, y, textPaint) + drawText(context.localize(region.type.nameRes), x, y, textBorderPaint) + drawText(context.localize(region.type.nameRes), x, y, textPaint) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/SaveImageNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/SaveImageNotifier.kt index 6e1e8fafa4..2ea8b319f9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/SaveImageNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/SaveImageNotifier.kt @@ -15,6 +15,8 @@ import eu.kanade.tachiyomi.util.system.cancelNotification import eu.kanade.tachiyomi.util.system.getBitmapOrNull import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notify +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR /** * Class used to show BigPictureStyle notifications @@ -56,8 +58,8 @@ class SaveImageNotifier(private val context: Context) { fun onError(error: String?) { // Create notification with(notificationBuilder) { - setContentTitle(context.getString(R.string.download_notifier_title_error)) - setContentText(error ?: context.getString(R.string.unknown_error)) + setContentTitle(context.localize(MR.strings.download_notifier_title_error)) + setContentText(error ?: context.localize(MR.strings.unknown_error)) setSmallIcon(android.R.drawable.ic_menu_report_image) } updateNotification() @@ -65,7 +67,7 @@ class SaveImageNotifier(private val context: Context) { private fun showCompleteNotification(uri: Uri, image: Bitmap?) { with(notificationBuilder) { - setContentTitle(context.getString(R.string.picture_saved)) + setContentTitle(context.localize(MR.strings.picture_saved)) setSmallIcon(R.drawable.ic_photo_24dp) image?.let { setStyle(NotificationCompat.BigPictureStyle().bigPicture(it)) } setLargeIcon(image) @@ -78,13 +80,13 @@ class SaveImageNotifier(private val context: Context) { // Share action addAction( R.drawable.ic_share_24dp, - context.getString(R.string.action_share), + context.localize(MR.strings.action_share), NotificationReceiver.shareImagePendingBroadcast(context, uri.path!!, notificationId), ) // Delete action addAction( R.drawable.ic_delete_24dp, - context.getString(R.string.action_delete), + context.localize(MR.strings.action_delete), NotificationReceiver.deleteImagePendingBroadcast(context, uri.path!!, notificationId), ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ChapterLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ChapterLoader.kt index 897d137557..942e7542c7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ChapterLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ChapterLoader.kt @@ -2,16 +2,17 @@ package eu.kanade.tachiyomi.ui.reader.loader import android.content.Context import com.github.junrar.exception.UnsupportedRarV5Exception -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadProvider import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter +import tachiyomi.core.i18n.localize import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.source.model.StubSource +import tachiyomi.i18n.MR import tachiyomi.source.local.LocalSource import tachiyomi.source.local.io.Format @@ -46,7 +47,7 @@ class ChapterLoader( .onEach { it.chapter = chapter } if (pages.isEmpty()) { - throw Exception(context.getString(R.string.page_list_empty_error)) + throw Exception(context.localize(MR.strings.page_list_empty_error)) } // If the chapter is partially read, set the starting page to the last the user read @@ -91,14 +92,14 @@ class ChapterLoader( is Format.Rar -> try { RarPageLoader(format.file) } catch (e: UnsupportedRarV5Exception) { - error(context.getString(R.string.loader_rar5_error)) + error(context.localize(MR.strings.loader_rar5_error)) } is Format.Epub -> EpubPageLoader(format.file) } } source is HttpSource -> HttpPageLoader(chapter, source) - source is StubSource -> error(context.getString(R.string.source_not_installed, source.toString())) - else -> error(context.getString(R.string.loader_not_implemented_error)) + source is StubSource -> error(context.localize(MR.strings.source_not_installed, source.toString())) + else -> error(context.localize(MR.strings.loader_not_implemented_error)) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderOrientation.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderOrientation.kt index c1d2e9b2db..01073cd606 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderOrientation.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderOrientation.kt @@ -2,54 +2,55 @@ package eu.kanade.tachiyomi.ui.reader.setting import android.content.pm.ActivityInfo import androidx.annotation.DrawableRes -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR enum class ReaderOrientation( val flag: Int, - @StringRes val stringRes: Int, + val stringRes: StringResource, @DrawableRes val iconRes: Int, val flagValue: Int, ) { DEFAULT( ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, - R.string.label_default, + MR.strings.label_default, R.drawable.ic_screen_rotation_24dp, 0x00000000, ), FREE( ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, - R.string.rotation_free, + MR.strings.rotation_free, R.drawable.ic_screen_rotation_24dp, 0x00000008, ), PORTRAIT( ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT, - R.string.rotation_portrait, + MR.strings.rotation_portrait, R.drawable.ic_stay_current_portrait_24dp, 0x00000010, ), LANDSCAPE( ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE, - R.string.rotation_landscape, + MR.strings.rotation_landscape, R.drawable.ic_stay_current_landscape_24dp, 0x00000018, ), LOCKED_PORTRAIT( ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, - R.string.rotation_force_portrait, + MR.strings.rotation_force_portrait, R.drawable.ic_screen_lock_portrait_24dp, 0x00000020, ), LOCKED_LANDSCAPE( ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, - R.string.rotation_force_landscape, + MR.strings.rotation_force_landscape, R.drawable.ic_screen_lock_landscape_24dp, 0x00000028, ), REVERSE_PORTRAIT( ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT, - R.string.rotation_reverse_portrait, + MR.strings.rotation_reverse_portrait, R.drawable.ic_stay_current_portrait_24dp, 0x00000030, ), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt index 9389a89e9b..ec47364e14 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt @@ -1,9 +1,9 @@ package eu.kanade.tachiyomi.ui.reader.setting -import androidx.annotation.StringRes -import eu.kanade.tachiyomi.R +import dev.icerock.moko.resources.StringResource import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.getEnum +import tachiyomi.i18n.MR class ReaderPreferences( private val preferenceStore: PreferenceStore, @@ -129,14 +129,14 @@ class ReaderPreferences( // endregion enum class TappingInvertMode( - @StringRes val titleResId: Int, + val titleRes: StringResource, val shouldInvertHorizontal: Boolean = false, val shouldInvertVertical: Boolean = false, ) { - NONE(R.string.tapping_inverted_none), - HORIZONTAL(R.string.tapping_inverted_horizontal, shouldInvertHorizontal = true), - VERTICAL(R.string.tapping_inverted_vertical, shouldInvertVertical = true), - BOTH(R.string.tapping_inverted_both, shouldInvertHorizontal = true, shouldInvertVertical = true), + NONE(MR.strings.tapping_inverted_none), + HORIZONTAL(MR.strings.tapping_inverted_horizontal, shouldInvertHorizontal = true), + VERTICAL(MR.strings.tapping_inverted_vertical, shouldInvertVertical = true), + BOTH(MR.strings.tapping_inverted_both, shouldInvertHorizontal = true, shouldInvertVertical = true), } enum class ReaderHideThreshold(val threshold: Int) { @@ -151,28 +151,28 @@ class ReaderPreferences( const val WEBTOON_PADDING_MAX = 25 val TapZones = listOf( - R.string.label_default, - R.string.l_nav, - R.string.kindlish_nav, - R.string.edge_nav, - R.string.right_and_left_nav, - R.string.disabled_nav, + MR.strings.label_default, + MR.strings.l_nav, + MR.strings.kindlish_nav, + MR.strings.edge_nav, + MR.strings.right_and_left_nav, + MR.strings.disabled_nav, ) val ImageScaleType = listOf( - R.string.scale_type_fit_screen, - R.string.scale_type_stretch, - R.string.scale_type_fit_width, - R.string.scale_type_fit_height, - R.string.scale_type_original_size, - R.string.scale_type_smart_fit, + MR.strings.scale_type_fit_screen, + MR.strings.scale_type_stretch, + MR.strings.scale_type_fit_width, + MR.strings.scale_type_fit_height, + MR.strings.scale_type_original_size, + MR.strings.scale_type_smart_fit, ) val ZoomStart = listOf( - R.string.zoom_start_automatic, - R.string.zoom_start_left, - R.string.zoom_start_right, - R.string.zoom_start_center, + MR.strings.zoom_start_automatic, + MR.strings.zoom_start_left, + MR.strings.zoom_start_right, + MR.strings.zoom_start_center, ) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReadingMode.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReadingMode.kt index d042795eb1..8c97ed818b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReadingMode.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReadingMode.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.ui.reader.setting import androidx.annotation.DrawableRes -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.viewer.Viewer @@ -9,45 +9,46 @@ import eu.kanade.tachiyomi.ui.reader.viewer.pager.L2RPagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.pager.VerticalPagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer +import tachiyomi.i18n.MR enum class ReadingMode( - @StringRes val stringRes: Int, + val stringRes: StringResource, @DrawableRes val iconRes: Int, val flagValue: Int, val direction: Direction? = null, val type: ViewerType? = null, ) { - DEFAULT(R.string.label_default, R.drawable.ic_reader_default_24dp, 0x00000000), + DEFAULT(MR.strings.label_default, R.drawable.ic_reader_default_24dp, 0x00000000), LEFT_TO_RIGHT( - R.string.left_to_right_viewer, + MR.strings.left_to_right_viewer, R.drawable.ic_reader_ltr_24dp, 0x00000001, Direction.Horizontal, ViewerType.Pager, ), RIGHT_TO_LEFT( - R.string.right_to_left_viewer, + MR.strings.right_to_left_viewer, R.drawable.ic_reader_rtl_24dp, 0x00000002, Direction.Horizontal, ViewerType.Pager, ), VERTICAL( - R.string.vertical_viewer, + MR.strings.vertical_viewer, R.drawable.ic_reader_vertical_24dp, 0x00000003, Direction.Vertical, ViewerType.Pager, ), WEBTOON( - R.string.webtoon_viewer, + MR.strings.webtoon_viewer, R.drawable.ic_reader_webtoon_24dp, 0x00000004, Direction.Vertical, ViewerType.Webtoon, ), CONTINUOUS_VERTICAL( - R.string.vertical_plus_viewer, + MR.strings.vertical_plus_viewer, R.drawable.ic_reader_continuous_vertical_24dp, 0x00000005, Direction.Vertical, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerNavigation.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerNavigation.kt index be27506c42..48e4b680b2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerNavigation.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerNavigation.kt @@ -3,19 +3,19 @@ package eu.kanade.tachiyomi.ui.reader.viewer import android.graphics.Color import android.graphics.PointF import android.graphics.RectF -import androidx.annotation.StringRes -import eu.kanade.tachiyomi.R +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.util.lang.invert +import tachiyomi.i18n.MR abstract class ViewerNavigation { - sealed class NavigationRegion(@StringRes val nameRes: Int, val color: Int) { - data object MENU : NavigationRegion(R.string.action_menu, Color.argb(0xCC, 0x95, 0x81, 0x8D)) - data object PREV : NavigationRegion(R.string.nav_zone_prev, Color.argb(0xCC, 0xFF, 0x77, 0x33)) - data object NEXT : NavigationRegion(R.string.nav_zone_next, Color.argb(0xCC, 0x84, 0xE2, 0x96)) - data object LEFT : NavigationRegion(R.string.nav_zone_left, Color.argb(0xCC, 0x7D, 0x11, 0x28)) - data object RIGHT : NavigationRegion(R.string.nav_zone_right, Color.argb(0xCC, 0xA6, 0xCF, 0xD5)) + sealed class NavigationRegion(val nameRes: StringResource, val color: Int) { + data object MENU : NavigationRegion(MR.strings.action_menu, Color.argb(0xCC, 0x95, 0x81, 0x8D)) + data object PREV : NavigationRegion(MR.strings.nav_zone_prev, Color.argb(0xCC, 0xFF, 0x77, 0x33)) + data object NEXT : NavigationRegion(MR.strings.nav_zone_next, Color.argb(0xCC, 0x84, 0xE2, 0x96)) + data object LEFT : NavigationRegion(MR.strings.nav_zone_left, Color.argb(0xCC, 0x7D, 0x11, 0x28)) + data object RIGHT : NavigationRegion(MR.strings.nav_zone_right, Color.argb(0xCC, 0xA6, 0xCF, 0xD5)) } data class Region( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt index 7ba46f5e00..f4a406056a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt @@ -10,7 +10,6 @@ import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.widget.LinearLayout import androidx.appcompat.widget.AppCompatTextView import com.google.android.material.progressindicator.CircularProgressIndicator -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.viewer.ReaderButton @@ -21,6 +20,8 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR /** * View of the ViewPager that contains a chapter transition. @@ -104,7 +105,7 @@ class PagerTransitionHolder( val textView = AppCompatTextView(context).apply { wrapContent() - setText(R.string.transition_pages_loading) + text = context.localize(MR.strings.transition_pages_loading) } pagesContainer.addView(progress) @@ -117,13 +118,13 @@ class PagerTransitionHolder( private fun setError(error: Throwable) { val textView = AppCompatTextView(context).apply { wrapContent() - text = context.getString(R.string.transition_pages_error, error.message) + text = context.localize(MR.strings.transition_pages_error, error.message ?: "") } val retryBtn = ReaderButton(context).apply { viewer = this@PagerTransitionHolder.viewer wrapContent() - setText(R.string.action_retry) + text = context.localize(MR.strings.action_retry) setOnClickListener { val toChapter = transition.to if (toChapter != null) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt index 6ac3c9813d..e9b62a93be 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt @@ -9,7 +9,6 @@ import androidx.appcompat.widget.AppCompatTextView import androidx.core.view.isNotEmpty import androidx.core.view.isVisible import com.google.android.material.progressindicator.CircularProgressIndicator -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.viewer.ReaderTransitionView @@ -18,6 +17,8 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR /** * Holder of the webtoon viewer that contains a chapter transition. @@ -106,7 +107,7 @@ class WebtoonTransitionHolder( val textView = AppCompatTextView(context).apply { wrapContent() - setText(R.string.transition_pages_loading) + text = context.localize(MR.strings.transition_pages_loading) } pagesContainer.addView(progress) @@ -119,12 +120,12 @@ class WebtoonTransitionHolder( private fun setError(error: Throwable, transition: ChapterTransition) { val textView = AppCompatTextView(context).apply { wrapContent() - text = context.getString(R.string.transition_pages_error, error.message) + text = context.localize(MR.strings.transition_pages_error, error.message ?: "") } val retryBtn = AppCompatButton(context).apply { wrapContent() - setText(R.string.action_retry) + text = context.localize(MR.strings.action_retry) setOnClickListener { val toChapter = transition.to if (toChapter != null) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/security/UnlockActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/security/UnlockActivity.kt index 09ec00169a..1fb2f47474 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/security/UnlockActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/security/UnlockActivity.kt @@ -3,13 +3,14 @@ package eu.kanade.tachiyomi.ui.security import android.os.Bundle import androidx.biometric.BiometricPrompt import androidx.fragment.app.FragmentActivity -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.base.activity.BaseActivity import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate import eu.kanade.tachiyomi.util.system.AuthenticatorUtil import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.startAuthentication import logcat.LogPriority +import tachiyomi.core.i18n.localize import tachiyomi.core.util.system.logcat +import tachiyomi.i18n.MR /** * Blank activity with a BiometricPrompt. @@ -19,7 +20,7 @@ class UnlockActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) startAuthentication( - getString(R.string.unlock_app_title, getString(R.string.app_name)), + localize(MR.strings.unlock_app_title, localize(MR.strings.app_name)), confirmationRequired = false, callback = object : AuthenticatorUtil.AuthenticationCallback() { override fun onAuthenticationError( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreen.kt index c5a728e911..ba1100ec9a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreen.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.stats import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow @@ -11,8 +10,9 @@ import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.more.stats.StatsScreenContent import eu.kanade.presentation.more.stats.StatsScreenState import eu.kanade.presentation.util.Screen -import eu.kanade.tachiyomi.R +import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Scaffold +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.screens.LoadingScreen class StatsScreen : Screen() { @@ -27,7 +27,7 @@ class StatsScreen : Screen() { Scaffold( topBar = { scrollBehavior -> AppBar( - title = stringResource(R.string.label_stats), + title = localize(MR.strings.label_stats), navigateUp = navigator::pop, scrollBehavior = scrollBehavior, ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt index 9aef16026a..ace03d0280 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt @@ -9,7 +9,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.Navigator @@ -27,6 +26,9 @@ import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.updates.UpdatesScreenModel.Event import kotlinx.coroutines.flow.collectLatest +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize object UpdatesTab : Tab { @@ -37,7 +39,7 @@ object UpdatesTab : Tab { val image = AnimatedImageVector.animatedVectorResource(R.drawable.anim_updates_enter) return TabOptions( index = 1u, - title = stringResource(R.string.label_recent_updates), + title = localize(MR.strings.label_recent_updates), icon = rememberAnimatedVectorPainter(image, isSelected), ) } @@ -88,15 +90,15 @@ object UpdatesTab : Tab { screenModel.events.collectLatest { event -> when (event) { Event.InternalError -> screenModel.snackbarHostState.showSnackbar( - context.getString(R.string.internal_error), + context.localize(MR.strings.internal_error), ) is Event.LibraryUpdateTriggered -> { val msg = if (event.started) { - R.string.updating_library + MR.strings.updating_library } else { - R.string.update_already_running + MR.strings.update_already_running } - screenModel.snackbarHostState.showSnackbar(context.getString(msg)) + screenModel.snackbarHostState.showSnackbar(context.localize(msg)) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/webview/WebViewActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/webview/WebViewActivity.kt index 195e6702ae..61d09dc796 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/webview/WebViewActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/webview/WebViewActivity.kt @@ -20,6 +20,7 @@ import logcat.LogPriority import okhttp3.HttpUrl.Companion.toHttpUrl import tachiyomi.core.util.system.logcat import tachiyomi.domain.source.service.SourceManager +import tachiyomi.i18n.MR import uy.kohesive.injekt.injectLazy class WebViewActivity : BaseActivity() { @@ -38,7 +39,7 @@ class WebViewActivity : BaseActivity() { super.onCreate(savedInstanceState) if (!WebViewUtil.supportsWebView(this)) { - toast(R.string.information_webview_required, Toast.LENGTH_LONG) + toast(MR.strings.information_webview_required, Toast.LENGTH_LONG) finish() return } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt index 797890ef58..bf1207c005 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt @@ -1,7 +1,9 @@ package eu.kanade.tachiyomi.util.lang import android.content.Context -import eu.kanade.tachiyomi.R +import tachiyomi.core.i18n.localize +import tachiyomi.core.i18n.localizePlural +import tachiyomi.i18n.MR import java.text.DateFormat import java.time.Instant import java.time.LocalDateTime @@ -61,9 +63,9 @@ fun Date.toRelativeString( val days = difference.floorDiv(MILLISECONDS_IN_DAY).toInt() return when { difference < 0 -> dateFormat.format(this) - difference < MILLISECONDS_IN_DAY -> context.getString(R.string.relative_time_today) - difference < MILLISECONDS_IN_DAY.times(7) -> context.resources.getQuantityString( - R.plurals.relative_time, + difference < MILLISECONDS_IN_DAY -> context.localize(MR.strings.relative_time_today) + difference < MILLISECONDS_IN_DAY.times(7) -> context.localizePlural( + MR.plurals.relative_time, days, days, ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/AuthenticatorUtil.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/AuthenticatorUtil.kt index 1de4158189..6de909fadf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/AuthenticatorUtil.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/AuthenticatorUtil.kt @@ -10,8 +10,9 @@ import androidx.biometric.auth.AuthPromptCallback import androidx.biometric.auth.startClass2BiometricOrCredentialAuthentication import androidx.core.content.ContextCompat import androidx.fragment.app.FragmentActivity -import eu.kanade.tachiyomi.R import kotlinx.coroutines.suspendCancellableCoroutine +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR import kotlin.coroutines.resume object AuthenticatorUtil { @@ -48,7 +49,7 @@ object AuthenticatorUtil { suspend fun FragmentActivity.authenticate( title: String, - subtitle: String? = getString(R.string.confirm_lock_change), + subtitle: String? = localize(MR.strings.confirm_lock_change), ): Boolean = suspendCancellableCoroutine { cont -> if (!isAuthenticationSupported()) { cont.resume(true) diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt index 7917c6db33..644c7f1021 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt @@ -24,7 +24,9 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.util.lang.truncateCenter import logcat.LogPriority import rikka.sui.Sui +import tachiyomi.core.i18n.localize import tachiyomi.core.util.system.logcat +import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.File @@ -45,11 +47,11 @@ fun Context.copyToClipboard(label: String, content: String) { // Android 13 and higher shows a visual confirmation of copied contents // https://developer.android.com/about/versions/13/features/copy-paste if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { - toast(getString(R.string.copied_to_clipboard, content.truncateCenter(50))) + toast(localize(MR.strings.copied_to_clipboard, content.truncateCenter(50))) } } catch (e: Throwable) { logcat(LogPriority.ERROR, e) - toast(R.string.clipboard_copy_error) + toast(MR.strings.clipboard_copy_error) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/IntentExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/IntentExtensions.kt index ac26265cd8..0388392d7e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/IntentExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/IntentExtensions.kt @@ -6,7 +6,8 @@ import android.content.Intent import android.net.Uri import android.os.Build import androidx.core.content.IntentCompat -import eu.kanade.tachiyomi.R +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR import java.io.Serializable fun Uri.toShareIntent(context: Context, type: String = "image/*", message: String? = null): Intent { @@ -27,7 +28,7 @@ fun Uri.toShareIntent(context: Context, type: String = "image/*", message: Strin flags = Intent.FLAG_GRANT_READ_URI_PERMISSION } - return Intent.createChooser(shareIntent, context.getString(R.string.action_share)).apply { + return Intent.createChooser(shareIntent, context.localize(MR.strings.action_share)).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/LocaleHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/LocaleHelper.kt index 75e9b54209..3afa3069ce 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/LocaleHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/LocaleHelper.kt @@ -2,8 +2,9 @@ package eu.kanade.tachiyomi.util.system import android.content.Context import androidx.core.os.LocaleListCompat -import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.browse.source.SourcesScreenModel +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR import java.util.Locale /** @@ -29,10 +30,10 @@ object LocaleHelper { */ fun getSourceDisplayName(lang: String?, context: Context): String { return when (lang) { - SourcesScreenModel.LAST_USED_KEY -> context.getString(R.string.last_used_source) - SourcesScreenModel.PINNED_KEY -> context.getString(R.string.pinned_sources) - "other" -> context.getString(R.string.other_source) - "all" -> context.getString(R.string.multi_lang) + SourcesScreenModel.LAST_USED_KEY -> context.localize(MR.strings.last_used_source) + SourcesScreenModel.PINNED_KEY -> context.localize(MR.strings.pinned_sources) + "other" -> context.localize(MR.strings.other_source) + "all" -> context.localize(MR.strings.multi_lang) else -> getDisplayName(lang) } } diff --git a/app/src/main/java/eu/kanade/test/DummyTracker.kt b/app/src/main/java/eu/kanade/test/DummyTracker.kt index 2e20ebb4dd..10d9bd9575 100644 --- a/app/src/main/java/eu/kanade/test/DummyTracker.kt +++ b/app/src/main/java/eu/kanade/test/DummyTracker.kt @@ -1,6 +1,7 @@ package eu.kanade.test import android.graphics.Color +import dev.icerock.moko.resources.StringResource import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.model.TrackSearch @@ -8,6 +9,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import okhttp3.OkHttpClient import tachiyomi.domain.track.model.Track +import tachiyomi.i18n.MR data class DummyTracker( override val id: Long, @@ -34,13 +36,13 @@ data class DummyTracker( override fun getStatusList(): List = valStatuses - override fun getStatus(status: Int): Int? = when (status) { - 1 -> R.string.reading - 2 -> R.string.plan_to_read - 3 -> R.string.completed - 4 -> R.string.on_hold - 5 -> R.string.dropped - 6 -> R.string.repeating + override fun getStatus(status: Int): StringResource? = when (status) { + 1 -> MR.strings.reading + 2 -> MR.strings.plan_to_read + 3 -> MR.strings.completed + 4 -> MR.strings.on_hold + 5 -> MR.strings.dropped + 6 -> MR.strings.repeating else -> null } diff --git a/build.gradle.kts b/build.gradle.kts index 2de38cbab0..ad3a21a2ed 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,6 +9,7 @@ buildscript { classpath(libs.google.services.gradle) classpath(libs.aboutLibraries.gradle) classpath(libs.sqldelight.gradle) + classpath(libs.moko.gradle) } } @@ -32,6 +33,7 @@ subprojects { plugins.withType { plugins.apply("tachiyomi.lint") + configure { compileSdkVersion(AndroidConfig.compileSdk) defaultConfig { diff --git a/buildSrc/src/main/kotlin/LocalesConfigPlugin.kt b/buildSrc/src/main/kotlin/LocalesConfigPlugin.kt index 2c352f1319..a641ef5c5a 100644 --- a/buildSrc/src/main/kotlin/LocalesConfigPlugin.kt +++ b/buildSrc/src/main/kotlin/LocalesConfigPlugin.kt @@ -4,23 +4,23 @@ import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.TaskContainerScope private val emptyResourcesElement = "\\s*|".toRegex() -private val valuesPrefix = "values(-(b\\+)?)?".toRegex() fun TaskContainerScope.registerLocalesConfigTask(project: Project): TaskProvider { return with(project) { register("generateLocalesConfig") { - val languages = fileTree("$projectDir/src/main/res/") + val languages = fileTree("$projectDir/src/commonMain/resources/MR/") .matching { include("**/strings.xml") } .filterNot { it.readText().contains(emptyResourcesElement) } - .map { it.parentFile.name } - .sorted() - .joinToString(separator = "\n") { - val language = it - .replace(valuesPrefix, "") + .map { + it.parentFile.name + .replace("base", "en") .replace("-r", "-") .replace("+", "-") .takeIf(String::isNotBlank) ?: "en" - " " + } + .sorted() + .joinToString(separator = "\n") { + " " } val content = """ @@ -30,7 +30,7 @@ $languages """.trimIndent() - val localeFile = file("$projectDir/src/main/res/xml/locales_config.xml") + val localeFile = file("$projectDir/src/androidMain/res/xml/locales_config.xml") localeFile.parentFile.mkdirs() localeFile.writeText(content) } diff --git a/buildSrc/src/main/kotlin/tachiyomi.lint.gradle.kts b/buildSrc/src/main/kotlin/tachiyomi.lint.gradle.kts index a89d885924..5216d49627 100644 --- a/buildSrc/src/main/kotlin/tachiyomi.lint.gradle.kts +++ b/buildSrc/src/main/kotlin/tachiyomi.lint.gradle.kts @@ -10,5 +10,13 @@ extensions.configure("ktlint") { filter { exclude("**/generated/**") + + // For some reason this is needed for Kotlin MPP + exclude { tree -> + val path = tree.file.path + listOf("/generated/").any { + path.contains(it) + } + } } } diff --git a/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt b/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt index f27b1a44c4..faf2683146 100644 --- a/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt @@ -1,9 +1,10 @@ package eu.kanade.tachiyomi.core.security -import eu.kanade.tachiyomi.core.R +import dev.icerock.moko.resources.StringResource import tachiyomi.core.preference.Preference import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.getEnum +import tachiyomi.i18n.MR class SecurityPreferences( private val preferenceStore: PreferenceStore, @@ -26,9 +27,9 @@ class SecurityPreferences( 0, ) - enum class SecureScreenMode(val titleResId: Int) { - ALWAYS(R.string.lock_always), - INCOGNITO(R.string.pref_incognito_mode), - NEVER(R.string.lock_never), + enum class SecureScreenMode(val titleRes: StringResource) { + ALWAYS(MR.strings.lock_always), + INCOGNITO(MR.strings.pref_incognito_mode), + NEVER(MR.strings.lock_never), } } diff --git a/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt index d5893bb058..989621375d 100644 --- a/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt @@ -5,7 +5,6 @@ import android.content.Context import android.webkit.WebView import android.widget.Toast import androidx.core.content.ContextCompat -import eu.kanade.tachiyomi.core.R import eu.kanade.tachiyomi.network.AndroidCookieJar import eu.kanade.tachiyomi.util.system.WebViewClientCompat import eu.kanade.tachiyomi.util.system.isOutdated @@ -15,6 +14,8 @@ import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Interceptor import okhttp3.Request import okhttp3.Response +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR import java.io.IOException import java.util.concurrent.CountDownLatch @@ -48,7 +49,7 @@ class CloudflareInterceptor( // Because OkHttp's enqueue only handles IOExceptions, wrap the exception so that // we don't crash the entire app catch (e: CloudflareBypassException) { - throw IOException(context.getString(R.string.information_cloudflare_bypass_failure), e) + throw IOException(context.localize(MR.strings.information_cloudflare_bypass_failure), e) } catch (e: Exception) { throw IOException(e) } @@ -130,7 +131,7 @@ class CloudflareInterceptor( if (!cloudflareBypassed) { // Prompt user to update WebView if it seems too outdated if (isWebViewOutdated) { - context.toast(R.string.information_webview_outdated, Toast.LENGTH_LONG) + context.toast(MR.strings.information_webview_outdated, Toast.LENGTH_LONG) } throw CloudflareBypassException() diff --git a/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt index ff1ca3fac8..cd1ffb14c4 100644 --- a/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt @@ -5,7 +5,6 @@ import android.os.Build import android.webkit.WebSettings import android.webkit.WebView import android.widget.Toast -import eu.kanade.tachiyomi.core.R import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.WebViewUtil import eu.kanade.tachiyomi.util.system.setDefaultSettings @@ -15,6 +14,7 @@ import okhttp3.Interceptor import okhttp3.Request import okhttp3.Response import tachiyomi.core.util.lang.launchUI +import tachiyomi.i18n.MR import java.util.Locale import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit @@ -57,7 +57,7 @@ abstract class WebViewInterceptor( if (!WebViewUtil.supportsWebView(context)) { launchUI { - context.toast(R.string.information_webview_required, Toast.LENGTH_LONG) + context.toast(MR.strings.information_webview_required, Toast.LENGTH_LONG) } return response } diff --git a/core/src/main/java/eu/kanade/tachiyomi/util/system/ToastExtensions.kt b/core/src/main/java/eu/kanade/tachiyomi/util/system/ToastExtensions.kt index 9e4554cb4a..48dca9a96f 100644 --- a/core/src/main/java/eu/kanade/tachiyomi/util/system/ToastExtensions.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/util/system/ToastExtensions.kt @@ -2,7 +2,8 @@ package eu.kanade.tachiyomi.util.system import android.content.Context import android.widget.Toast -import androidx.annotation.StringRes +import dev.icerock.moko.resources.StringResource +import tachiyomi.core.i18n.localize /** * Display a toast in this context. @@ -11,11 +12,11 @@ import androidx.annotation.StringRes * @param duration the duration of the toast. Defaults to short. */ fun Context.toast( - @StringRes resource: Int, + resource: StringResource, duration: Int = Toast.LENGTH_SHORT, block: (Toast) -> Unit = {}, ): Toast { - return toast(getString(resource), duration, block) + return toast(localize(resource), duration, block) } /** diff --git a/core/src/main/java/tachiyomi/core/i18n/Localize.kt b/core/src/main/java/tachiyomi/core/i18n/Localize.kt new file mode 100644 index 0000000000..07e2878ddc --- /dev/null +++ b/core/src/main/java/tachiyomi/core/i18n/Localize.kt @@ -0,0 +1,26 @@ +package tachiyomi.core.i18n + +import android.content.Context +import dev.icerock.moko.resources.PluralsResource +import dev.icerock.moko.resources.StringResource +import dev.icerock.moko.resources.desc.Plural +import dev.icerock.moko.resources.desc.PluralFormatted +import dev.icerock.moko.resources.desc.Resource +import dev.icerock.moko.resources.desc.ResourceFormatted +import dev.icerock.moko.resources.desc.StringDesc + +fun Context.localize(resource: StringResource): String { + return StringDesc.Resource(resource).toString(this) +} + +fun Context.localize(resource: StringResource, vararg args: Any): String { + return StringDesc.ResourceFormatted(resource, *args).toString(this) +} + +fun Context.localizePlural(resource: PluralsResource, count: Int): String { + return StringDesc.Plural(resource, count).toString(this) +} + +fun Context.localizePlural(resource: PluralsResource, count: Int, vararg args: Any): String { + return StringDesc.PluralFormatted(resource, count, *args).toString(this) +} diff --git a/core/src/main/java/tachiyomi/core/provider/AndroidBackupFolderProvider.kt b/core/src/main/java/tachiyomi/core/provider/AndroidBackupFolderProvider.kt index aa87b930d1..7e7d223858 100644 --- a/core/src/main/java/tachiyomi/core/provider/AndroidBackupFolderProvider.kt +++ b/core/src/main/java/tachiyomi/core/provider/AndroidBackupFolderProvider.kt @@ -3,7 +3,8 @@ package tachiyomi.core.provider import android.content.Context import android.os.Environment import androidx.core.net.toUri -import eu.kanade.tachiyomi.core.R +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR import java.io.File class AndroidBackupFolderProvider( @@ -13,7 +14,7 @@ class AndroidBackupFolderProvider( override fun directory(): File { return File( Environment.getExternalStorageDirectory().absolutePath + File.separator + - context.getString(R.string.app_name), + context.localize(MR.strings.app_name), "backup", ) } diff --git a/core/src/main/java/tachiyomi/core/provider/AndroidDownloadFolderProvider.kt b/core/src/main/java/tachiyomi/core/provider/AndroidDownloadFolderProvider.kt index 042a586c21..899c826cf7 100644 --- a/core/src/main/java/tachiyomi/core/provider/AndroidDownloadFolderProvider.kt +++ b/core/src/main/java/tachiyomi/core/provider/AndroidDownloadFolderProvider.kt @@ -3,7 +3,8 @@ package tachiyomi.core.provider import android.content.Context import android.os.Environment import androidx.core.net.toUri -import eu.kanade.tachiyomi.core.R +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR import java.io.File class AndroidDownloadFolderProvider( @@ -13,7 +14,7 @@ class AndroidDownloadFolderProvider( override fun directory(): File { return File( Environment.getExternalStorageDirectory().absolutePath + File.separator + - context.getString(R.string.app_name), + context.localize(MR.strings.app_name), "downloads", ) } diff --git a/data/src/main/java/tachiyomi/data/manga/MangaRepositoryImpl.kt b/data/src/main/java/tachiyomi/data/manga/MangaRepositoryImpl.kt index 5d8364f319..1e5a50273f 100644 --- a/data/src/main/java/tachiyomi/data/manga/MangaRepositoryImpl.kt +++ b/data/src/main/java/tachiyomi/data/manga/MangaRepositoryImpl.kt @@ -24,7 +24,7 @@ class MangaRepositoryImpl( } override suspend fun getMangaByUrlAndSourceId(url: String, sourceId: Long): Manga? { - return handler.awaitOneOrNull(inTransaction = true) { + return handler.awaitOneOrNull { mangasQueries.getMangaByUrlAndSource( url, sourceId, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 934797ad03..7c72d2304c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,6 @@ [versions] aboutlib_version = "10.9.2" +moko = "0.23.0" okhttp_version = "5.0.0-alpha.11" shizuku_version = "12.2.0" sqlite = "2.4.0" @@ -62,6 +63,9 @@ compose-materialmotion = "io.github.fornewid:material-motion-compose-core:1.1.0" swipe = "me.saket.swipe:swipe:1.2.0" +moko-core = { module = "dev.icerock.moko:resources", version.ref = "moko" } +moko-gradle = { module = "dev.icerock.moko:resources-generator", version.ref = "moko" } + logcat = "com.squareup.logcat:logcat:0.1" acra-http = "ch.acra:acra-http:5.11.3" diff --git a/i18n/.gitignore b/i18n/.gitignore index 13d1ad6973..601f2b1cd0 100644 --- a/i18n/.gitignore +++ b/i18n/.gitignore @@ -1,5 +1,2 @@ -# Hebrew assets are copied on build -/src/main/res/values-iw/ - # Generated locales_config.xml \ No newline at end of file diff --git a/i18n/build.gradle.kts b/i18n/build.gradle.kts index 95af9a2d04..542afc3597 100644 --- a/i18n/build.gradle.kts +++ b/i18n/build.gradle.kts @@ -1,27 +1,45 @@ plugins { + kotlin("multiplatform") id("com.android.library") - kotlin("android") + id("dev.icerock.mobile.multiplatform-resources") +} + +kotlin { + androidTarget() + sourceSets { + val commonMain by getting { + dependencies { + api(libs.moko.core) + } + } + val androidMain by getting { + dependsOn(commonMain) // https://github.com/icerockdev/moko-resources/issues/562 + } + } } android { namespace = "tachiyomi.i18n" + sourceSets { + named("main") { + res.srcDir("src/commonMain/resources") + } + } + lint { disable.addAll(listOf("MissingTranslation", "ExtraTranslation")) } } +multiplatformResources { + multiplatformResourcesPackage = "tachiyomi.i18n" +} + tasks { val localesConfigTask = registerLocalesConfigTask(project) - // Duplicating Hebrew string assets due to some locale code issues on different devices - val copyHebrewStrings by registering(Copy::class) { - from("./src/main/res/values-he") - into("./src/main/res/values-iw") - include("**/*") - } - preBuild { - dependsOn(copyHebrewStrings, localesConfigTask) + dependsOn(localesConfigTask) } } diff --git a/i18n/src/main/AndroidManifest.xml b/i18n/src/androidMain/AndroidManifest.xml similarity index 100% rename from i18n/src/main/AndroidManifest.xml rename to i18n/src/androidMain/AndroidManifest.xml diff --git a/i18n/src/commonMain/resources/MR/am/plurals.xml b/i18n/src/commonMain/resources/MR/am/plurals.xml new file mode 100644 index 0000000000..651a93e011 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/am/plurals.xml @@ -0,0 +1,15 @@ + + + + %d ምድብ + %d ምድቦች + + + ከ 1 ደቂቃ በኋላ + ከ %1$s ደቂቃዎች በኋላ + + + ከ %2$s ስህተት ጋር በ %1$s ውስጥ ተከናውኗል + ከ %2$s ስህተት ጋር በ %1$s ውስጥ ተከናውኗል + + \ No newline at end of file diff --git a/i18n/src/main/res/values-am/strings.xml b/i18n/src/commonMain/resources/MR/am/strings.xml similarity index 97% rename from i18n/src/main/res/values-am/strings.xml rename to i18n/src/commonMain/resources/MR/am/strings.xml index 07486c308c..4a07d01ac3 100644 --- a/i18n/src/main/res/values-am/strings.xml +++ b/i18n/src/commonMain/resources/MR/am/strings.xml @@ -21,10 +21,6 @@ አዘምን ዝመናዎች በመጠባበቅ ላይ ናቸው ሁሉም - - %d ምድብ - %d ምድቦች - ሁል ጊዜም ይጠይቁ ነባሪ ምድብ ቤተ-መጽሐፍትን ሲያዘምኑ አዲስ ሽፋን እና ዝርዝሮችን ይፈልጉ @@ -48,10 +44,6 @@ የማሳወቂያ ይዘትን ደብቅ መተግበሪያዎችን ሲቀይሩ የመተግበሪያ ይዘቶችን ደብቅ እና ቅጽበታዊ ገጽ እይታዎችን ያግዳል ደህንነቱ የተጠበቀ ማያ ገጽ - - ከ 1 ደቂቃ በኋላ - ከ %1$s ደቂቃዎች በኋላ - በጭራሽ ሁል ጊዜ ስራ ሲፈታ ቆልፍ @@ -287,10 +279,6 @@ ምትኬን መፍጠር ምትኬ ለማስቀመጥ ምን ይፈልጋሉ\? ምትኬ ቀድሞውኑ በሂደት ላይ ነው - - ከ %2$s ስህተት ጋር በ %1$s ውስጥ ተከናውኗል - ከ %2$s ስህተት ጋር በ %1$s ውስጥ ተከናውኗል - %02d ደቂቃ ፣ %02d ሰከንድ እነበረበት መልስ ተጠናቅቋል መከታተያዎች አልገቡም: diff --git a/i18n/src/commonMain/resources/MR/ar/plurals.xml b/i18n/src/commonMain/resources/MR/ar/plurals.xml new file mode 100644 index 0000000000..64f4492f9d --- /dev/null +++ b/i18n/src/commonMain/resources/MR/ar/plurals.xml @@ -0,0 +1,131 @@ + + + + لايوجد تحديث للإضافة + يتوفر تحديث لإضافة + يتوفر تحديث لإضافتان + يتوفر تحديث %d إضافات + يتوفر تحديث %d إضافات + يتوفر تحديث %d إضافات + + + الفصول %1$s + الفصول %1$s وفصل آخر + الفصول %1$s و%2$d فصول أخرى + الفصول %1$s و%2$d فصول أخرى + الفصول %1$s و%2$d فصول أخرى + الفصول %1$s و%2$d فصول أخرى + + + لا توجد فصول جديدة + فصل جديد + فصلان جديدان + %1$d فصول جديدة + %1$d فصول جديدة + %1$d فصول جديدة + + + لا شيء + إدخال واحد + إدخالين + ادخالات %d ل + ادخالات %d ل + ادخالات %d ل + + + %1$s عنصر متبقي + عنصر واحد متبقي + عنصران متبقيان + %1$s عناصر متبقية + %1$s عناصر متبقية + %1$s عناصر متبقية + + + بعد أقل من دقيقة + بعد دقيقة + بعد دقيقتين + بعد %1$s دقائق + بعد %1$s دقائق + بعد %1$s دقائق + + + لا يوجد فئات + فئة + فئتان + %d فئات + %d فئات + %d فئات + + + تمَّ في %1$s وبدون أخطاء + تمَّ في %1$s وفيه خطأ + تمَّ في %1$s وفيه خطآن + تمَّ في %1$s وفيه %2$s أخطاء + تمَّ في %1$s وفيه %2$s خطأً + تمَّ في %1$s وفيه %2$s خطأ + + + لا متتبّع + متتبّع واحد + متتبعان + بضعة متتبّعين (%d) + عدّة متتبّعين (%d) + %d متتبّعاً + + + لا فصول + فصل واحد + فصلين + %1$s فصول + %1$s فصول + %1$s فصول + + + لا يُتخطَّى أيُّ فصل + يُتخطَّى فصل، وذلك إما لأن المصدر مفقود أو لأنه مصفًّى + يُتخطَّى فصلان، وذلك إما لأن المصدر مفقود أو لأنهما مصفَّان + تُتخطَّى %d فصول، وذلك إما لأن المصدر مفقود أو لأنهم مصفَّون + يُتخطَّى %d فصلًا، وذلك إما لأن المصدر مفقود أو لأنهم مصفَّون + يُتخطَّى %d فصل، وذلك إما لأن المصدر مفقود أو لأنهم مصفَّون + + + الأمس + منذ %1$d أيام + منذ %1$d أيام + منذ %1$d أيام + منذ %1$d أيام + منذ %1$d أيام + + + لا يوجد فصل تالٍ لم يُقرأ + الفصل غير المقروء التالي + الفصلان غير المقروءين التاليان + %d فصول تالية لم تُقرأ + %d فصلًا تاليًا لم يُقرؤوا + %d فصل تالٍ لم يُقرؤوا + + + الفصل التالي + الفصل التالي + %d فصول تالية + %d فصول تالية + %d فصل تالي + %d فصل تالي + + + لا يوجد أيُّ فصل مفقود + فصل واحد مفقود + فصلان مفقودان + %1$s فصول مفقودة + %1$s فصلًا مفقودًا + %1$s فصل مفقود + + + لا يوم + يوم واحد + يومان + %d أيام + %d يومًا + %d يوم + + \ No newline at end of file diff --git a/i18n/src/main/res/values-ar/strings.xml b/i18n/src/commonMain/resources/MR/ar/strings.xml similarity index 89% rename from i18n/src/main/res/values-ar/strings.xml rename to i18n/src/commonMain/resources/MR/ar/strings.xml index fc0fb15b68..ec72042781 100644 --- a/i18n/src/main/res/values-ar/strings.xml +++ b/i18n/src/commonMain/resources/MR/ar/strings.xml @@ -347,41 +347,9 @@ يرجى تحديث تطبيق WebView لتوافق أفضل إن وجود WebView لازم ليعمل التطبيق فشل في تجاوز Cloudflare - - لايوجد تحديث للإضافة - يتوفر تحديث لإضافة - يتوفر تحديث لإضافتان - يتوفر تحديث %d إضافات - يتوفر تحديث %d إضافات - يتوفر تحديث %d إضافات - - - الفصول %1$s - الفصول %1$s وفصل آخر - الفصول %1$s و%2$d فصول أخرى - الفصول %1$s و%2$d فصول أخرى - الفصول %1$s و%2$d فصول أخرى - الفصول %1$s و%2$d فصول أخرى - الفصول %1$s الفصل %1$s و%2$d فصول أخرى الفصل %1$s - - لا توجد فصول جديدة - فصل جديد - فصلان جديدان - %1$d فصول جديدة - %1$d فصول جديدة - %1$d فصول جديدة - - - لا شيء - إدخال واحد - إدخالين - ادخالات %d ل - ادخالات %d ل - ادخالات %d ل - جارٍ التحقق من وجود فصول جديدة الفصل %1$s - %2$s تُحدَّث المكتبة @@ -400,35 +368,11 @@ تسجيل الخروج تسجيل الخروج من %1$s؟ البريد الإلكتروني - - %1$s عنصر متبقي - عنصر واحد متبقي - عنصران متبقيان - %1$s عناصر متبقية - %1$s عناصر متبقية - %1$s عناصر متبقية - تصفية جميع الإدخالات في مكتبتك الإزاحة الجانبية شريط طويل بين أجزائه فجوات رمادي يزيد من سلاسة تدرج الالوان بالصور، ولكن قد يؤثر على الأداء - - بعد أقل من دقيقة - بعد دقيقة - بعد دقيقتين - بعد %1$s دقائق - بعد %1$s دقائق - بعد %1$s دقائق - - - لا يوجد فئات - فئة - فئتان - %d فئات - %d فئات - %d فئات - تعذر فتح إعدادات الجهاز نقل البيانات @@ -440,14 +384,6 @@ غير رسمي تحقق من وجود غلاف جديد وتفاصيل جديدة عند تحديث المكتبة تحديث البيانات الوصفية تلقائياً - - تمَّ في %1$s وبدون أخطاء - تمَّ في %1$s وفيه خطأ - تمَّ في %1$s وفيه خطآن - تمَّ في %1$s وفيه %2$s أخطاء - تمَّ في %1$s وفيه %2$s خطأً - تمَّ في %1$s وفيه %2$s خطأ - حسب تاريخ الرفع حدّث صور اغلفة المكتبة شبكة مريحة @@ -482,35 +418,11 @@ التقدّم تعذّر تنزيل الفصول بسبب انخفاض مساحة التخزين لم يتم العثور على المصدر - - لا متتبّع - متتبّع واحد - متتبعان - بضعة متتبّعين (%d) - عدّة متتبّعين (%d) - %d متتبّعاً - - - لا فصول - فصل واحد - فصلين - %1$s فصول - %1$s فصول - %1$s فصول - حالة غير معروفة مؤلّف غير معروف لا تمتلك أيّة مصادر مثبّتة إبحث عن \"%1$s\" بشكلٍ شامل حُدِّث إلى الإصدار v%1$s - - لا يُتخطَّى أيُّ فصل - يُتخطَّى فصل، وذلك إما لأن المصدر مفقود أو لأنه مصفًّى - يُتخطَّى فصلان، وذلك إما لأن المصدر مفقود أو لأنهما مصفَّان - تُتخطَّى %d فصول، وذلك إما لأن المصدر مفقود أو لأنهم مصفَّون - يُتخطَّى %d فصلًا، وذلك إما لأن المصدر مفقود أو لأنهم مصفَّون - يُتخطَّى %d فصل، وذلك إما لأن المصدر مفقود أو لأنهم مصفَّون - لم يُعثر على فصول %1$s: %2$s, صفحة %3$d إعدادات الفصل الإفتراضية المُحدثة @@ -622,14 +534,6 @@ المصادقة لتأكيد التغيير الافتراضي الأنشطة التي تعمل في الخلفية - - الأمس - منذ %1$d أيام - منذ %1$d أيام - منذ %1$d أيام - منذ %1$d أيام - منذ %1$d أيام - تتبع معكوس ازرق مخضر و فيروز @@ -738,14 +642,6 @@ سلسلة وكيل المستخدم لا يمكن أن تكون فارغة شائع أنت على وشك أن تحذف \"%s\" من مكتبتك - - لا يوجد فصل تالٍ لم يُقرأ - الفصل غير المقروء التالي - الفصلان غير المقروءين التاليان - %d فصول تالية لم تُقرأ - %d فصلًا تاليًا لم يُقرؤوا - %d فصل تالٍ لم يُقرؤوا - لم يتم منح أذن التخزين بحث… تُخُطِّيت لأن السلسلة لا تتطلب تحديثات @@ -808,26 +704,10 @@ %1$s خطأ: %2$s *مطلوب نسخ إلى الحافظة - - الفصل التالي - الفصل التالي - %d فصول تالية - %d فصول تالية - %d فصل تالي - %d فصل تالي - إخفاء الإدخالات الموجودة بالفعل في المكتبة تحديث الفئة افصل الصور الطويلة التراكب - - لا يوجد أيُّ فصل مفقود - فصل واحد مفقود - فصلان مفقودان - %1$s فصول مفقودة - %1$s فصلًا مفقودًا - %1$s فصل مفقود - دوِّر الصفحات العريضة لتلائم الشاشة اعكس اتِّجاه الصفحات العريضة المدوَّرة معلومات التنقيح @@ -847,14 +727,6 @@ خصِّص المدة تُخُطِّيت بسبب عدم توقع صدور اليوم عيِّن التحديث كلَّ - - لا يوم - يوم واحد - يومان - %d أيام - %d يومًا - %d يوم - المدة التحديث المتوقع القادم أأزيل تتبع %s؟ diff --git a/i18n/src/commonMain/resources/MR/base/plurals.xml b/i18n/src/commonMain/resources/MR/base/plurals.xml new file mode 100644 index 0000000000..21b5446182 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/base/plurals.xml @@ -0,0 +1,83 @@ + + + + After %1$s minute + After %1$s minutes + + + + Yesterday + %1$d days ago + + + + %d category + %d categories + + + + Next unread chapter + Next %d unread chapters + + + + Done in %1$s with %2$s error + Done in %1$s with %2$s errors + + + + %1$s remaining + %1$s remaining + + + + 1 day + %d days + + + + + Missing %1$s chapter + Missing %1$s chapters + + + + %1$s chapter + %1$s chapters + + + + Next chapter + Next %d chapters + + + + %d tracker + %d trackers + + + + Skipping %d chapter, either the source is missing it or it has been filtered out + Skipping %d chapters, either the source is missing them or they have been filtered out + + + + For %d entry + For %d entries + + + %1$d new chapter + %1$d new chapters + + + + Chapters %1$s and 1 more + Chapters %1$s and %2$d more + + + + + Extension update available + %d extension updates available + + diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/commonMain/resources/MR/base/strings.xml similarity index 95% rename from i18n/src/main/res/values/strings.xml rename to i18n/src/commonMain/resources/MR/base/strings.xml index 47b7a9efa2..3ff18662cb 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/commonMain/resources/MR/base/strings.xml @@ -39,6 +39,9 @@ Local Downloaded + Selected + Not selected + Unlock %s Authenticate to confirm change @@ -221,10 +224,6 @@ Lock when idle Always Never - - After %1$s minute - After %1$s minutes - Hide notification content Secure screen Secure screen hides app contents when switching apps and block screenshots @@ -234,10 +233,6 @@ This does not prevent unofficial or potentially incorrectly flagged extensions from surfacing NSFW (18+) content within the app. Today - - Yesterday - %1$d days ago - Display @@ -274,10 +269,6 @@ Default category Always ask Per-category settings for sort - - %d category - %d categories - Entries in excluded categories will not be updated even if they are also in included categories. All None @@ -453,10 +444,6 @@ Entries in excluded categories will not be downloaded even if they are also in included categories. Download ahead Auto download while reading - - Next unread chapter - Next %d unread chapters - Only works if the current chapter + the next one are already downloaded. Save as CBZ archive Split tall images @@ -493,10 +480,6 @@ Data from the backup file will be restored.\n\nYou will need to install any missing extensions and log in to tracking services afterwards to use them. Restore completed %02d min, %02d sec - - Done in %1$s with %2$s error - Done in %1$s with %2$s errors - Backup is already in progress What do you want to backup? App settings @@ -586,10 +569,6 @@ Pauses reading history Disable incognito mode Filters all entries in your library - - %1$s remaining - %1$s remaining - @@ -634,16 +613,8 @@ Invalid chapter format Order by Date - - 1 day - %d days - - - Missing %1$s chapter - Missing %1$s chapters - Ongoing Unknown Unknown author @@ -663,10 +634,6 @@ Removed from library More Less - - %1$s chapter - %1$s chapters - Delete downloaded chapters? Copied to clipboard Copied to clipboard:\n%1$s @@ -689,10 +656,6 @@ By chapter number By upload date Download - - Next chapter - Next %d chapters - Unread Custom cover Cover @@ -711,10 +674,6 @@ Tracking - - %d tracker - %d trackers - Add tracking Unread Reading @@ -782,10 +741,6 @@ No pages found Source not found RARv5 format is not supported - - Skipping %d chapter, either the source is missing it or it has been filtered out - Skipping %d chapters, either the source is missing them or they have been filtered out - Updating library @@ -850,21 +805,9 @@ Updating library… (%s) Large updates harm sources and may lead to slower updates and also increased battery usage. Tap to learn more. New chapters found - - For %d entry - For %d entries - - - %1$d new chapter - %1$d new chapters - Chapter %1$s Chapter %1$s and %2$d more Chapters %1$s - - Chapters %1$s and 1 more - Chapters %1$s and %2$d more - %1$d update(s) failed %1$d update(s) skipped Tap to learn more @@ -897,12 +840,6 @@ New version available! A new version is available from the official releases. Tap to learn how to migrate from unofficial F-Droid releases. - - - Extension update available - %d extension updates available - - No downloads No recent updates diff --git a/i18n/src/commonMain/resources/MR/be/plurals.xml b/i18n/src/commonMain/resources/MR/be/plurals.xml new file mode 100644 index 0000000000..d7e2ca31ed --- /dev/null +++ b/i18n/src/commonMain/resources/MR/be/plurals.xml @@ -0,0 +1,21 @@ + + + + %d катэгорыя + %d катэгорыі + %d катэгорый + %d катэгорый + + + Пасля %1$s хвіліны + Пасля %1$s хвілін + Пасля %1$s хвілін + Пасля %1$s хвілін + + + Учора + %1$d дні таму + %1$d дзён таму + %1$d дзён таму + + \ No newline at end of file diff --git a/i18n/src/main/res/values-be/strings.xml b/i18n/src/commonMain/resources/MR/be/strings.xml similarity index 97% rename from i18n/src/main/res/values-be/strings.xml rename to i18n/src/commonMain/resources/MR/be/strings.xml index 09af8aa0e4..2e94d68975 100644 --- a/i18n/src/main/res/values-be/strings.xml +++ b/i18n/src/commonMain/resources/MR/be/strings.xml @@ -104,12 +104,6 @@ Ніхто Усе Манга ў выключаных катэгорыях не будзе абнаўляцца, нават калі яны таксама знаходзяцца ў уключаных катэгорыях. - - %d катэгорыя - %d катэгорыі - %d катэгорый - %d катэгорый - Налады для кожнай катэгорыі для сартавання і адлюстравання Заўсёды пытацца Катэгорыя па змаўчанні @@ -137,12 +131,6 @@ Схаваць змесціва апавяшчэнняў Схаваць змесціва прыкладання пры пераключэнні на іншыя прыкладання і блакаваць скрыншоты Абарона экрана - - Пасля %1$s хвіліны - Пасля %1$s хвілін - Пасля %1$s хвілін - Пасля %1$s хвілін - Ніколі Заўсёды Блакаванне пры бяздзейнасці @@ -276,12 +264,6 @@ Змясціць у экран Маштабаванне Колеры наадварот - - Учора - %1$d дні таму - %1$d дзён таму - %1$d дзён таму - Сёння Бірузовы Знешнасць diff --git a/i18n/src/commonMain/resources/MR/bg/plurals.xml b/i18n/src/commonMain/resources/MR/bg/plurals.xml new file mode 100644 index 0000000000..2f6165169a --- /dev/null +++ b/i18n/src/commonMain/resources/MR/bg/plurals.xml @@ -0,0 +1,55 @@ + + + + 1 наличен ъпдейт за разширение + %d налични ъпдейта за разширения + + + Глави %1$s и още 1 + Глави %1$s и още %2$d + + + 1 нова глава + %1$d нови глави + + + За 1 заглавие + За %d заглавия + + + 1 оставаща + %1$s оставащи + + + След 1 минута + След %1$s минути + + + Направено за %1$s с %2$s грешка + Направено за %1$s с %2$s грешки + + + %d категория + %d категории + + + 1 глава + %1$s глави + + + 1 тракер + %d тракери + + + Има 1 липсваща глава, източникът липса или е филтриран + Има %d липсващи глави, източникът липса или е филтриран + + + Вчера + Преди %1$d дни + + + Следващата непрочетена глава + Следващите %d непрочетени глави + + \ No newline at end of file diff --git a/i18n/src/main/res/values-bg/strings.xml b/i18n/src/commonMain/resources/MR/bg/strings.xml similarity index 94% rename from i18n/src/main/res/values-bg/strings.xml rename to i18n/src/commonMain/resources/MR/bg/strings.xml index b6c2744e6b..2ff68ca604 100644 --- a/i18n/src/main/res/values-bg/strings.xml +++ b/i18n/src/commonMain/resources/MR/bg/strings.xml @@ -1,14 +1,12 @@ Име - Настройки Изтегляния Библиотека История Нови глави Запази и възстанови - Настройки Филтрирай Отбелязани @@ -51,17 +49,13 @@ Запази Изчисти Върни - Зареждане… - - Основни настройки Четец Изтегляния Следене Разширени настройки За приложението - Манга на ред Портретно Пейзажно @@ -76,7 +70,6 @@ На зарядно устройство Със статус \"Завършена\" Обнови прогреса след прочитане - Цял екран Анимирани преходи Номер на страница @@ -113,7 +106,6 @@ G B A - Директория на изтеглянията След маркиране като прочетено След прочитане автоматично изтрийте @@ -125,9 +117,7 @@ Четвърта предпоследна прочетена глава Пета предпоследна прочетена глава Изтегляй нови глави - Услуги - Изчисти кеша на главите Използвани: %1$s Кеш изчистен. %1$d файла бяха изчистени @@ -138,29 +128,21 @@ Изтрий историята на манги, които не са запазени в библиотеката Сигурни ли сте\? Прочетените глави и напредъкът на манги, които не са в библиотеката Ви, ще бъдат изгубени Базата данни изчистена - Версия - Изпращай данни за сривове Помага за оправянето на бъгове. Няма да се изпращат лични данни - Влизане в %1$s Потребителско име Парола Влез Влязохте Неизвестна грешка - Обновяване на категорията - Няма повече резултати - - Излизаща Неизвестно Лицензирана Премахни от библиотеката - Глава %1$s Изтегляне (%1$d/%2$d) Грешка @@ -171,7 +153,6 @@ Изтегли Непрочетени Сигурни ли сте, че искате да изтриете избраните глави? - Следене Чета Завършена @@ -182,17 +163,12 @@ Заглавие Статус Глави - Категория със същото име вече съществува! Категориите бяха изтрити - Това ще премахне датата на прочитане на главата. Сигурни ли сте? Изчисти всички дати за тази манга - Добавяне на мангата към библиотеката\? - Изображението запазено - Персонализиран филтър Постави за корица Корицата обновена @@ -200,32 +176,22 @@ Не беше намерена следваща глава Неуспешно декодиране на изображението Желаете ли да използвате това изображение за корица? - - - Не можахме да изтеглим главите. Може да опитате пак в секцията на изтеглянията - Нови глави Грешка при обновяването на корицата Моля, добавете мангата в библиотеката си, преди да направите това - Изберете корица Изберете резервно копие - Изтегли Няма налични актуализации - Изтегля се… Изтегляне завършено Грешка при изтегляне Има нова версия! - - Нямате изтегляния Нямате нови глави Не сте чели нищо наскоро Библиотеката Ви е празна - Изтегли Грешка Получи се неочаквана грешка при изтеглянето на главата @@ -341,25 +307,9 @@ Моля, обновете WebView за по-добра съвместимост WebView е необходим за Tachiyomi Грешка при минаването през Cloudflare - - 1 наличен ъпдейт за разширение - %d налични ъпдейта за разширения - - - Глави %1$s и още 1 - Глави %1$s и още %2$d - Глави %1$s Глава %1$s и %2$d още Глава %1$s - - 1 нова глава - %1$d нови глави - - - За 1 заглавие - За %d заглавия - Проверяване за нови глави Гл. %1$s - %2$s Обновяване на библиотеката @@ -372,10 +322,6 @@ Закачени Последно използвани Имейл адрес - - 1 оставаща - %1$s оставащи - Филтрира мангата в цялата Ви библиотека Само изтеглени Провери за ъпдейт @@ -400,10 +346,6 @@ Показване Скривай съдържанието на уведомленията Скрий съдържанието на приложението и блокирай снимките на екрана - - След 1 минута - След %1$s минути - Никога Винаги Заключи при неактивност @@ -431,25 +373,13 @@ За тази поредица Системните настройки не бяха отворени Обнови кориците - - Направено за %1$s с %2$s грешка - Направено за %1$s с %2$s грешки - Еднопосочна синхронизация на прочетените глави. Установи проследяване за отделни манги от индивидуалния бутон за проследяване. Сиво Намалява бандинга, но се отразява на производителността - - %d категория - %d категории - Мигрирай Източникът не е намерен Няма намерени страници По дата на качване - - 1 глава - %1$s глави - Раздели Данни Изисква рестартиране, за да влезе в сила @@ -477,10 +407,6 @@ Готово Прогрес Главите не можаха да бъдат изтеглени поради недостатъчно място - - 1 тракер - %d тракери - Неизвестен статус Неизвестен автор Нямате отметнати източници @@ -497,10 +423,6 @@ Тема Добавено на Не са намерени глави - - Има 1 липсваща глава, източникът липса или е филтриран - Има %d липсващи глави, източникът липса или е филтриран - NSFW (18+) източници Низходящ Възходящ @@ -552,10 +474,6 @@ Чувствителност за скриване на менюто при превъртане Най-висока Непрочетена - - Вчера - Преди %1$d дни - Корица Предупреждение Удостоверете, за да потвърдите промяната @@ -705,10 +623,6 @@ Лавандула Език на приложението Изтрий категория - - Следващата непрочетена глава - Следващите %d непрочетени глави - Възрастово ограничение Списък с желания Запази като CBZ архив diff --git a/i18n/src/commonMain/resources/MR/bn/plurals.xml b/i18n/src/commonMain/resources/MR/bn/plurals.xml new file mode 100644 index 0000000000..77fb973bcc --- /dev/null +++ b/i18n/src/commonMain/resources/MR/bn/plurals.xml @@ -0,0 +1,55 @@ + + + + %1$s অধ্যায়সমূহ এবং ১টি আরও + %1$s অধ্যায়সমূহ এবং %2$dটি আরও + + + %1$s সময়ে %2$s ত্রুটি সম্পন্ন + %1$s সময়ে %2$sটি ত্রুটি সম্পন্ন + + + %dটি বিভাগ + %dটি বিভাগসমূহ + + + ১ মিনিট পর + %1$s মিনিট পর + + + এক্সটেনশন হালনাগাদ উপলব্ধ + %d এক্সটেনশন হালনাগাদ উপলব্ধ + + + ১টি নতুন অধ্যায় + %1$dটি নতুন অধ্যায় + + + ১টি শিরোনামের জন্য + %dটি শিরোনামের জন্য + + + 1 অধ্যায় এড়িয়ে জাছি, হয় উৎসটি অনুপস্থিত বা এটি ফিল্টার করা হয়েছে + %d অধ্যায় কিপ করা হচ্ছে, হয় উৎসটি তাদের অনুপস্থিত অথবা সেগুলি ফিল্টার করা হয়েছে + + + 1টি ট্র্যাকার + %dটি ট্র্যাকার + + + ১টি অধ্যায় + %1$sটি অধ্যায় + + + ১টি বাকি আছে + %1$sটি বাকি আছে + + + গতকাল + %1$d দিন আগে + + + পরবর্তী অপঠিত অধ্যায় + পরবর্তী %d টি অপঠিত অধ্যায় + + \ No newline at end of file diff --git a/i18n/src/main/res/values-bn/strings.xml b/i18n/src/commonMain/resources/MR/bn/strings.xml similarity index 95% rename from i18n/src/main/res/values-bn/strings.xml rename to i18n/src/commonMain/resources/MR/bn/strings.xml index 400caa4024..8605763b01 100644 --- a/i18n/src/main/res/values-bn/strings.xml +++ b/i18n/src/commonMain/resources/MR/bn/strings.xml @@ -374,25 +374,9 @@ অনুমোদনহীন অনিষ্পন্ন হালনাগাদ সংগ্রহশালা হালনাগেদের সময় নতুন মোড়ক এবং বর্ণনা খুঁজুন - - %1$s অধ্যায়সমূহ এবং ১টি আরও - %1$s অধ্যায়সমূহ এবং %2$dটি আরও - গাঁথুনিকৃত - - %1$s সময়ে %2$s ত্রুটি সম্পন্ন - %1$s সময়ে %2$sটি ত্রুটি সম্পন্ন - ট্র্যাকারগুলিতে প্রবেশ হয়নি: রিডার খোলা থাকলে বর্তমান মোড সংক্ষেপে দেখান - - %dটি বিভাগ - %dটি বিভাগসমূহ - - - ১ মিনিট পর - %1$s মিনিট পর - উভয় উল্লম্ব অনুভূমিক @@ -406,29 +390,13 @@ অনুগ্রহ করে উন্নততর সামঞ্জস্যতার জন্য ওয়েবভিউ অ্যাপটি হালনাগাদ করুন টাচিয়ামির জন্য ওয়েবভিউ প্রয়োজন ক্লাউডফ্লেয়ার বাইপাস করতে ব্যর্থ - - এক্সটেনশন হালনাগাদ উপলব্ধ - %d এক্সটেনশন হালনাগাদ উপলব্ধ - অধ্যায়গুলি %1$s অধ্যায় %1$s এবং %2$d আরও অধ্যায় %1$s - - ১টি নতুন অধ্যায় - %1$dটি নতুন অধ্যায় - - - ১টি শিরোনামের জন্য - %dটি শিরোনামের জন্য - নতুন অধ্যায়ের জন্য অনুসন্ধান করা হচ্ছে কম সঞ্চয়স্থানের কারণে অধ্যায়গুলি ডাউনলোড করা যায়নি অঃ %1$s - %2$s সংগ্রহশালার হালনাগাদ হচ্ছে - - 1 অধ্যায় এড়িয়ে জাছি, হয় উৎসটি অনুপস্থিত বা এটি ফিল্টার করা হয়েছে - %d অধ্যায় কিপ করা হচ্ছে, হয় উৎসটি তাদের অনুপস্থিত অথবা সেগুলি ফিল্টার করা হয়েছে - উৎস খুঁজে পাওয়া যায়নি কোনও পৃষ্ঠা পাওয়া যায় নি পঠন ধরন @@ -436,19 +404,11 @@ %1$s: %2$s, পৃষ্ঠা %3$d বিরতি ট্র্যাকিং যোগ করুন - - 1টি ট্র্যাকার - %dটি ট্র্যাকার - কোনও অধ্যায় পাওয়া যায় নি এছাড়াও আমার সংগ্রহশালার মাঙ্গাতে প্রয়োগ করুন অধ্যায় সেটিংস আপলোডের তারিখ অনুযায়ী সংগ্রহশালার মাঙ্গার মোড়ক হালনাগাদ করুন - - ১টি অধ্যায় - %1$sটি অধ্যায় - অজানা অবস্থা অজানা লেখক আপনার কোন পিন করা উৎস নেই @@ -461,10 +421,6 @@ আপনি এখন প্রস্থান করেছেন প্রস্থান প্রস্থান করবেন %1$s থেকে\? - - ১টি বাকি আছে - %1$sটি বাকি আছে - আপনার লাইব্রেরীর সব মাঙ্গা ফিলটার করে পড়ার ইতিহাসে বিরতি দেয় ছদ্মবেশী মোড @@ -561,10 +517,6 @@ বাদ দেওয়া ক্যাটাগরিতে মঙ্গা আপডেট করা হবে না যদিও সেগুলি অন্তর্ভুক্ত ক্যাটাগরিতেও থাকে। সাজানোর এবং প্রদর্শনের জন্য প্রতি শ্রেণীর সেটিংস বিধিনিষেধ: %s - - গতকাল - %1$d দিন আগে - সম্প্রতি বিশুদ্ধ কালো অন্ধকার মোড চার পাতা @@ -623,10 +575,6 @@ আপনি কি \"%s\" বিভাগটি মুছে ফেলতে চান\? সম্প্রতি আপনার হালনাগাদকৃত মাঙ্গা দেখুন আপনি কি নিশ্চিত\? - - পরবর্তী অপঠিত অধ্যায় - পরবর্তী %d টি অপঠিত অধ্যায় - অপঠিত সংখ্যা সবকিছু মুছুন লেখা দেখান diff --git a/i18n/src/commonMain/resources/MR/ca/plurals.xml b/i18n/src/commonMain/resources/MR/ca/plurals.xml new file mode 100644 index 0000000000..0309ac347c --- /dev/null +++ b/i18n/src/commonMain/resources/MR/ca/plurals.xml @@ -0,0 +1,67 @@ + + + + Després d’%1$s minut + Després de %1$s minuts + + + %1$d capítol nou + %1$d capítols nous + + + Capítols %1$s i 1 més + Capítols %1$s i %2$d més + + + Per a %d element + Per a %d elements + + + Hi ha una actualització d’una extensió + Hi ha actualitzacions de %d extensions + + + En resta %1$s + En resten %1$s + + + Fet en %1$s amb %2$s error + Fet en %1$s amb %2$s errors + + + %d categoria + %d categories + + + %1$s capítol + %1$s capítols + + + %d servei de seguiment + %d serveis de seguiment + + + S’ha omès %d capítol. És possible que manqui a la font o que hagi estat filtrat + S’han omès %d capítols. És possible que manquin a la font o que hagin estat filtrats + + + Ahir + Fa %1$d dies + + + El següent capítol no llegit + Els següents %d capítols no llegits + + + El següent capítol + Els següents %d capítols + + + Manca %1$s capítol + Manquen %1$s capítols + + + 1 dia + %d dies + + \ No newline at end of file diff --git a/i18n/src/main/res/values-ca/strings.xml b/i18n/src/commonMain/resources/MR/ca/strings.xml similarity index 95% rename from i18n/src/main/res/values-ca/strings.xml rename to i18n/src/commonMain/resources/MR/ca/strings.xml index 2f2206d76a..3740982d91 100644 --- a/i18n/src/main/res/values-ca/strings.xml +++ b/i18n/src/commonMain/resources/MR/ca/strings.xml @@ -315,10 +315,6 @@ Bloca per inactivitat Sempre Mai - - Després d’%1$s minut - Després de %1$s minuts - Mode discret Actualitzacions pendents Mostra el contingut a l’àrea de retall @@ -327,17 +323,9 @@ Novetats de capítols El mode discret amaga el contingut de l’aplicació en canviar entre aplicacions i bloca les captures de pantalla Visualització - - %1$d capítol nou - %1$d capítols nous - Capítol %1$s Capítol %1$s i %2$d més Capítols %1$s - - Capítols %1$s i 1 més - Capítols %1$s i %2$d més - Amaga el contingut de les notificacions S’està comprovant si hi ha capítols nous Desactiva l’optimització de la bateria @@ -345,19 +333,11 @@ L’optimització de la bateria ja està desactivada Adreça electrònica Mostra sempre la transició de capítol - - Per a %d element - Per a %d elements - Menú Els més nous Els més antics Mou a dalt de tot Mou a sota de tot - - Hi ha una actualització d’una extensió - Hi ha actualitzacions de %d extensions - Actualitzacions d’extensions S’està actualitzant la biblioteca Lectura @@ -389,23 +369,11 @@ Comprova si hi ha actualitzacions %02d min i %02d s Filtra tots els elements de la vostra biblioteca - - En resta %1$s - En resten %1$s - Gris Mode de lectura Per a aquesta sèrie No s’ha pogut obrir la configuració del dispositiu - - Fet en %1$s amb %2$s error - Fet en %1$s amb %2$s errors - Redueix les bandes de colors, però pot afectar el rendiment - - %d categoria - %d categories - La sincronització és unidireccional per a actualitzar el progrés dels capítols als serveis de seguiment externs. Configureu el seguiment d’elements individuals al seu botó de seguiment. Refresca les portades de la biblioteca Aquesta extensió no pertany a la llista d’extensions oficials. @@ -431,10 +399,6 @@ Inverteix les zones de toc No s’han pogut baixar els capítols perquè hi ha poc espai d’emmagatzematge No s’ha trobat la font - - %1$s capítol - %1$s capítols - Estat desconegut Autor desconegut Cerca «%1$s» globalment @@ -449,10 +413,6 @@ Desactiva Inicia Data d’incorporació - - %d servei de seguiment - %d serveis de seguiment - No teniu cap origen fixat Completada Progrés @@ -463,10 +423,6 @@ Les fonts d’aquesta extensió poden contenir contingut NSFW (+18) +18 Això no evita que les extensions no oficials o possiblement mal etiquetades puguin mostrar contingut NSFW (+18) a l’aplicació. - - S’ha omès %d capítol. És possible que manqui a la font o que hagi estat filtrat - S’han omès %d capítols. És possible que manquin a la font o que hagin estat filtrats - No s’ha trobat cap capítol S’ha actualitzat la configuració per defecte dels capítols Estableix com a per defecte @@ -561,10 +517,6 @@ Categories excloses Encara no teniu cap categoria. Serveis de seguiment millorats - - Ahir - Fa %1$d dies - Avui Per defecte Advertència @@ -690,10 +642,6 @@ Només funciona si el capítol actual i el següent ja estan baixats. Ups! S’ha produït un error inesperat al %s. Us suggerim que compartiu el registre d’errors al nostre canal d’assistència al Discord. - - El següent capítol no llegit - Els següents %d capítols no llegits - No s’han concedit permisos d’emmagatzematge Populars Còpies de seguretat automàtiques i manuals i espai d’emmagatzematge @@ -748,10 +696,6 @@ Elements seguits Puntuació mitjana *obligatori - - El següent capítol - Els següents %d capítols - La categoria és buida En ús N/A @@ -771,18 +715,10 @@ Superposició Inverteix l’orientació de les pàgines amples rotades Rota les pàgines amples perquè s’ajustin a la pantalla - - Manca %1$s capítol - Manquen %1$s capítols - Informació de depuració Estableix l’interval Interval d’obtenció personalitzat Pròxima actualització prevista - - 1 dia - %d dies - Obtén mensualment (28 dies) Endarrerit 10 o més dies Abandonat\? Endarrerit 20 o més dies i 2 mesos diff --git a/i18n/src/commonMain/resources/MR/ceb/plurals.xml b/i18n/src/commonMain/resources/MR/ceb/plurals.xml new file mode 100644 index 0000000000..431598699c --- /dev/null +++ b/i18n/src/commonMain/resources/MR/ceb/plurals.xml @@ -0,0 +1,23 @@ + + + + %d Kategoriya + %d Mga kategoriya + + + Human sa %1$s ka minuto + Human sa %1$s ka minuto + + + Kagahapon + %1$d ka adlaw ang milabay + + + Nabuhat sa %1$s nga adunay %2$s nga sayup + Nabuhat sa %1$s nga adunay %2$s nga mga sayop + + + %1$s ang nahibilin + %1$s ang nahibilin + + \ No newline at end of file diff --git a/i18n/src/main/res/values-ceb/strings.xml b/i18n/src/commonMain/resources/MR/ceb/strings.xml similarity index 97% rename from i18n/src/main/res/values-ceb/strings.xml rename to i18n/src/commonMain/resources/MR/ceb/strings.xml index 75f208b1ad..2ab18919fb 100644 --- a/i18n/src/main/res/values-ceb/strings.xml +++ b/i18n/src/commonMain/resources/MR/ceb/strings.xml @@ -46,10 +46,6 @@ Pinakabag-o nga kapitulo Kuhaa ang filter Katapusan nga update sa manga - - %d Kategoriya - %d Mga kategoriya - Tanan Walay bag-o nga mga update Matag-kategorya nga mga setting alang sa paghan-ay ug pagpakita @@ -154,14 +150,6 @@ Wala pa kana nagsugod Awtomatikong i-refresh ang metadata Pangutana kanunay - - Human sa %1$s ka minuto - Human sa %1$s ka minuto - - - Kagahapon - %1$d ka adlaw ang milabay - Nagpaubos Pinaagi sa petsa sa pag-upload Pinaagi sa numero sa kapitulo @@ -388,10 +376,6 @@ Nakompleto ang pag-uli Paghimo og backup Ang mga tracker wala naka-log in: - - Nabuhat sa %1$s nga adunay %2$s nga sayup - Nabuhat sa %1$s nga adunay %2$s nga mga sayop - Pag-uli sa backup Gilimpyohan ang mga cookies Data @@ -449,10 +433,6 @@ Susiha ang mga update Mga update sa v%1$s Ipadala ang mga taho sa pagkahagsa - - %1$s ang nahibilin - %1$s ang nahibilin - Naka-log out ka na karon Password Login diff --git a/i18n/src/commonMain/resources/MR/cs/plurals.xml b/i18n/src/commonMain/resources/MR/cs/plurals.xml new file mode 100644 index 0000000000..c2e6fa6a8c --- /dev/null +++ b/i18n/src/commonMain/resources/MR/cs/plurals.xml @@ -0,0 +1,83 @@ + + + + Po %1$s minutě + Po %1$s minutách + Po %1$s minutách + + + %1$s kapitola + %1$s kapitoly + %1$s kapitol + + + %1$s zbývá + %1$s zbývají + %1$s zbývá + + + Dokončeno za %1$s s %2$s chybou + Dokončeno za %1$s s %2$s chybami + Dokončeno za %1$s s %2$s chybami + + + %d kategorie + %d kategorie + %d kategorií + + + Je dostupná aktualizace rozšíření + Jsou dostupné %d aktualizace rozšíření + Je dostupných %d aktualizací rozšíření + + + Kapitoly %1$s a 1 další + Kapitoly %1$s a %2$d další + Kapitoly %1$s a %2$d dalších + + + %1$d nová kapitola + %1$d nové kapitoly + %1$d nových kapitol + + + Pro %d položku + Pro %d položky + Pro %d položek + + + Přeskočena %d kapitola, buď chybí ve zdroji nebo byla vyfiltrována + Přeskočeny %d kapitoly, buď chybí ve zdroji nebo byly vyfiltrovány + Přeskočeno %d kapitol, buď chybí ve zdroji nebo byly vyfiltrovány + + + %d sledovač + %d sledovače + %d sledovačů + + + Včera + Před %1$d dny + Před %1$d dny + + + Další nepřečtená kapitola + Další %d nepřečtené kapitoly + Dalších %d nepřečtených kapitol + + + Další kapitola + Další %d kapitoly + Dalších %d kapitol + + + Chybí %1$s kapitola + Chybí %1$s kapitoly + Chybí %1$s kapitol + + + 1 den + %d dny + %d dní + + \ No newline at end of file diff --git a/i18n/src/main/res/values-cs/strings.xml b/i18n/src/commonMain/resources/MR/cs/strings.xml similarity index 93% rename from i18n/src/main/res/values-cs/strings.xml rename to i18n/src/commonMain/resources/MR/cs/strings.xml index e009387623..a770c0c642 100644 --- a/i18n/src/main/res/values-cs/strings.xml +++ b/i18n/src/commonMain/resources/MR/cs/strings.xml @@ -307,11 +307,6 @@ Předchozí stránka Následující stránka Skrýt obsah oznámení - - Po %1$s minutě - Po %1$s minutách - Po %1$s minutách - Nikdy Vždy Uzamknout při nečinnosti @@ -327,11 +322,6 @@ Jsi si jistý, že chceš tato nastavení uložit jako výchozí\? Nastavení kapitoly Podle data nahrání - - %1$s kapitola - %1$s kapitoly - %1$s kapitol - Méně Více V knihovně @@ -347,11 +337,6 @@ Stažené kapitoly Z knihovny Emailová adresa - - %1$s zbývá - %1$s zbývají - %1$s zbývá - Pozastaví historii čtení Anonymní režim Pouze staženo @@ -376,11 +361,6 @@ Obnovení již probíhá Zálohování selhalo Zálohování již probíhá - - Dokončeno za %1$s s %2$s chybou - Dokončeno za %1$s s %2$s chybami - Dokončeno za %1$s s %2$s chybami - %02d minut, %02d sekund Data ze zálohy budou obnovena. \n @@ -406,11 +386,6 @@ 18+ Toto rozšíření není z oficiálního seznamu rozšíření. Neoficiální - - %d kategorie - %d kategorie - %d kategorií - Kontrolovat dostupnost nových přebalů a detailů při aktualizaci knihovny Automaticky obnovovat metadata Toto nastavení nemůže zamezit neoficiálním nebo špatně označeným rozšířením v zobrazování NSFW (18+) obsahu v aplikaci. @@ -442,29 +417,9 @@ Prosím aktualizujte aplikaci WebView pro lepší kompatibilitu Je nutné mít nainstalovanou aplikaci WebView pro správné fungování aplikace Nastala chyba při obcházení služby Cloudflare - - Je dostupná aktualizace rozšíření - Jsou dostupné %d aktualizace rozšíření - Je dostupných %d aktualizací rozšíření - - - Kapitoly %1$s a 1 další - Kapitoly %1$s a %2$d další - Kapitoly %1$s a %2$d dalších - Kapitoly %1$s Kapitola %1$s a %2$d dalších Kapitola %1$s - - %1$d nová kapitola - %1$d nové kapitoly - %1$d nových kapitol - - - Pro %d položku - Pro %d položky - Pro %d položek - Hledám nové kapitoly Nelze stáhnout kapitoly kvůli nedostatku místa Návod k přesunu zdrojů @@ -473,11 +428,6 @@ Historie vymazána Kap. %1$s - %2$s Aktualizuji knihovnu - - Přeskočena %d kapitola, buď chybí ve zdroji nebo byla vyfiltrována - Přeskočeny %d kapitoly, buď chybí ve zdroji nebo byly vyfiltrovány - Přeskočeno %d kapitol, buď chybí ve zdroji nebo byly vyfiltrovány - Zdroj nenalezen Žádné stránky nenalezeny Prosím přihlašte se do MAL znovu @@ -498,11 +448,6 @@ Ukazovat režim čtení Pro tuto sérii %1$s: %2$s, strana %3$d - - %d sledovač - %d sledovače - %d sledovačů - Také nastavit pro všechny položky v mé knihovně Čtení Při otevření čtečky krátce zobrazí aktuální režim @@ -587,11 +532,6 @@ Příručka Začínáme Uživatelské rozhraní tabletu Sledovat - - Včera - Před %1$d dny - Před %1$d dny - Dnes Modrozelená a Tyrkysová Vzhled @@ -695,11 +635,6 @@ Řetězec uživatelského agenta nemůže být prázdný Přílivová Vlna Stáhování dopředu - - Další nepřečtená kapitola - Další %d nepřečtené kapitoly - Dalších %d nepřečtených kapitol - Automatické stahování při čtení Funguje pouze v případě, že aktuální kapitola + následující kapitola jsou již staženy. Jste si jistí\? @@ -769,22 +704,12 @@ %1$s chyba: %2$s *vyžadováno Skrýt položky, které jsou již v knihovně - - Další kapitola - Další %d kapitoly - Dalších %d kapitol - Zkopírovat do schránky Aktualizovat kategorii Rozdělit vysoké obrázky Překrytí Překlopení orientace otočených širokých stránek Otočení širokých stránek tak, aby se vešly - - Chybí %1$s kapitola - Chybí %1$s kapitoly - Chybí %1$s kapitol - Ladící informace Přejetí po kapitole Přejetí prstem doprava @@ -801,11 +726,6 @@ Nastavit aktualizaci každých Nastavit interval Opuštěný\? Pozdě 20+ a 2 měsíce - - 1 den - %d dny - %d dní - Mimo očekávané období vydání Intervaly Přeskočeno, protože dnes nebylo očekáváno žádné vydání diff --git a/i18n/src/commonMain/resources/MR/cv/plurals.xml b/i18n/src/commonMain/resources/MR/cv/plurals.xml new file mode 100644 index 0000000000..612cb2ab5a --- /dev/null +++ b/i18n/src/commonMain/resources/MR/cv/plurals.xml @@ -0,0 +1,51 @@ + + + + %d пухмӑш + %d пухмӑш + + + 1 минут хыҫҫӑн + %1$s минут хыҫҫӑн + + + %1$s,%2$s йӑнӑшпа тӑвӑннӑ + %1$s, %2$s йӑнӑшпа тӑвӑннӑ + + + Хушма валли ҫӗнетӳ пур + %d хушма валли ҫӗнетӳ пур + + + %1$s сыпӑкӗсем + %1$s сыпӑкӗсем тата ытти %2$d + + + 1 ҫӗнӗ сыпӑк + %1$d ҫӗнӗ сыпӑк + + + Ҫӗнӗ сыпӑксем 1 хайлав валли тупӑннӑ + Ҫӗнӗ сыпӑксем %d хайлав валли тупӑннӑ + + + 1 сыпӑк + %1$s сыпӑк + + + 1 юлчӗ + %1$s юлчӗ + + + 1 сӑнану + %d сӑнану + + + 1 сыпӑк ҫук + %d сыпӑк ҫук + + + Ӗнер + %1$d кун кайалла + + \ No newline at end of file diff --git a/i18n/src/main/res/values-cv/strings.xml b/i18n/src/commonMain/resources/MR/cv/strings.xml similarity index 95% rename from i18n/src/main/res/values-cv/strings.xml rename to i18n/src/commonMain/resources/MR/cv/strings.xml index b85cc91d78..9ded14d5d2 100644 --- a/i18n/src/main/res/values-cv/strings.xml +++ b/i18n/src/commonMain/resources/MR/cv/strings.xml @@ -36,10 +36,6 @@ Ларт Ҫӗнет Пурне те - - %d пухмӑш - %d пухмӑш - Кашнинчех ыйтмалла Петтерей тулнӑ чух Хатӗр валли хӑй-хальлӗн ҫӗнетӳ чарӑвӗсем @@ -52,10 +48,6 @@ Пӗтӗмӗшле ҫӗнетӳ Кӑтарт Ыкран сыхлавӗ - - 1 минут хыҫҫӑн - %1$s минут хыҫҫӑн - Сыхлав тата вӑрттӑнлӑх Систерӳсене ӗнер Ҫул-кун хармачӗ @@ -255,10 +247,6 @@ \nСийенлӗ хушма упранакан кирек мӗнле шут пӗлӗмӗсене шута илме йе хӑй ирӗклӗ йума пурнӑҫлама пултарать. \n \nҪак ӗнентерӳ хутне шаннипе есӗ ҫав теветкеле йышӑнатӑн. - - %1$s,%2$s йӑнӑшпа тӑвӑннӑ - %1$s, %2$s йӑнӑшпа тӑвӑннӑ - Сӑнану хуш Сӑна Усӑҫ али @@ -279,10 +267,6 @@ Кӗтмен йӑнӑша пула сыпӑксене тийесе илеймест Тийевҫӗ Tachiyomi валли WebView кирлӗ - - Хушма валли ҫӗнетӳ пур - %d хушма валли ҫӗнетӳ пур - Тийев… Ҫӗнетӳсем тупӑнман Тиесе ил @@ -291,18 +275,6 @@ Хуплашкана ҫӗнетеймерӗ %1$s сыпӑкӗ тата ытти %2$d %1$s сыпӑкӗсем - - %1$s сыпӑкӗсем - %1$s сыпӑкӗсем тата ытти %2$d - - - 1 ҫӗнӗ сыпӑк - %1$d ҫӗнӗ сыпӑк - - - Ҫӗнӗ сыпӑксем 1 хайлав валли тупӑннӑ - Ҫӗнӗ сыпӑксем %d хайлав валли тупӑннӑ - Ҫӗнӗ сыпӑксен пуррине тӗрӗслени Сыпӑксене тийесе илме пулмасть. Тийевсем пайӗнче ҫӗнӗрен хӑтланса пӑхма пултаратӑн Ӑтавла @@ -361,10 +333,6 @@ Пайлашу буфере ӑтавланӑ: \n%1$s Тиенӗ сыпӑксене катертмелле-и\? - - 1 сыпӑк - %1$s сыпӑк - Сахалрах Ытларах Вулавӑшран катерт @@ -400,10 +368,6 @@ Ылӑккӑтрунлӑ пуштӑ тӗлӗ Усӑҫ ячӗ %1$s кӗр - - 1 юлчӗ - %1$s юлчӗ - Санӑн вулавӑшри манкка алат Ӳкнисем ҫинчен тишереревсем ямалла Ҫӗнетӳсем пуррине тӗрӗсле @@ -449,10 +413,6 @@ Тиск ҫинче вырӑн ҫитмен пирки сыпӑксем тийенеймерӗҫ \"%1$s\" пур ҫӗрте шыра Вулав тытӑмӗ - - 1 сӑнану - %d сӑнану - Санӑн ҫакнӑ ҫӑл куҫ ҫук Вӗҫленӗ Ӳсӗм @@ -463,10 +423,6 @@ NSFW (18+) шалаш пулма пултарать 18+ Ҫакӑ апра чӑнлавлӑ мар йе тӗрӗс мар палӑртнӑ хушмасен NSFW (18+) шалашне кӑтартма чӑрмантармасть. - - 1 сыпӑк ҫук - %d сыпӑк ҫук - Сыпӑксем ҫук Тата манӑн вулавăшри пур манкӑ валли усӑ кур Яланхилле сыпӑк ӗнерлев ҫӗнетнӗ @@ -575,10 +531,6 @@ Симӗс пан улми Йутсупа Серилӗхсене ҫӗнетнине сиктер - - Ӗнер - %1$d кун кайалла - Чараксӑр тетел урлӑ ҫеҫ Серилӗхе пуҫламан Такку diff --git a/i18n/src/commonMain/resources/MR/da/plurals.xml b/i18n/src/commonMain/resources/MR/da/plurals.xml new file mode 100644 index 0000000000..7f24d8b750 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/da/plurals.xml @@ -0,0 +1,19 @@ + + + + I går + %1$d dage siden + + + Efter %1$s minut + Efter %1$s minutter + + + %d kategori + %d kategorier + + + Næste ulæste kapitel + Næste %d ulæste kapitler + + \ No newline at end of file diff --git a/i18n/src/main/res/values-da/strings.xml b/i18n/src/commonMain/resources/MR/da/strings.xml similarity index 96% rename from i18n/src/main/res/values-da/strings.xml rename to i18n/src/commonMain/resources/MR/da/strings.xml index 86782c5745..3362db563d 100644 --- a/i18n/src/main/res/values-da/strings.xml +++ b/i18n/src/commonMain/resources/MR/da/strings.xml @@ -144,18 +144,10 @@ Håndter notifikationer Sikkerhed Kræv oplåsning - - I går - %1$d dage siden - NSFW (18+) kilder Vis i kilder og udvidelsesliste Dette forhindrer ikke uofficielle eller potentielt ukorrekt markerede udvidelser fra at vise NSFW (18+) indhold i appen. I dag - - Efter %1$s minut - Efter %1$s minutter - Lås ved inaktivitet Altid Aldrig @@ -192,10 +184,6 @@ Nyeste manga opdateringer Antal ulæst Slet kategori - - %d kategori - %d kategorier - Ekskluder: %s Lavendel Spørg altid @@ -299,10 +287,6 @@ Udvidelsesopdateringer Sikkerhedskopiering mislykkedes Placering af sikkerhedskopi - - Næste ulæste kapitel - Næste %d ulæste kapitler - Fri Fejl Gendannelse fuldført diff --git a/i18n/src/commonMain/resources/MR/de/plurals.xml b/i18n/src/commonMain/resources/MR/de/plurals.xml new file mode 100644 index 0000000000..f7d3181d7b --- /dev/null +++ b/i18n/src/commonMain/resources/MR/de/plurals.xml @@ -0,0 +1,67 @@ + + + + Nach %1$s Minute + Nach %1$s Minuten + + + %1$d neues Kapitel + %1$d neue Kapitel + + + Kapitel %1$s und 1 mehr + Kapitel %1$s und %2$d mehr + + + Für %d Eintrag + Für %d Einträge + + + Erweiterungsaktualisierung verfügbar + %d Erweiterungsaktualisierungen verfügbar + + + %1$s verbleibend + %1$s verbleibend + + + %d Kategorie + %d Kategorien + + + Erledigt in %1$s mit %2$s Fehler + Erledigt in %1$s mit %2$s Fehlern + + + %1$s Kapitel + %1$s Kapitel + + + %d Tracker + %d Tracker + + + %d Kapitel wird übersprungen, da die Quelle dieses entweder nicht besitzt, oder weil es rausgefiltert wurde + %d Kapitel werden übersprungen, da die Quelle diese entweder nicht besitzt, oder weil sie rausgefiltert wurden + + + Gestern + Vor %1$d Tagen + + + Nächstes ungelesenes Kapitel + Nächste %d ungelesene Kapitel + + + Nächstes Kapitel + Nächste %d Kapitel + + + %1$s Kapitel fehlt + %1$s Kapitel fehlen + + + 1 Tag + %d Tage + + \ No newline at end of file diff --git a/i18n/src/main/res/values-de/strings.xml b/i18n/src/commonMain/resources/MR/de/strings.xml similarity index 95% rename from i18n/src/main/res/values-de/strings.xml rename to i18n/src/commonMain/resources/MR/de/strings.xml index b41e0ce278..58231342e4 100644 --- a/i18n/src/main/res/values-de/strings.xml +++ b/i18n/src/commonMain/resources/MR/de/strings.xml @@ -315,10 +315,6 @@ Während Inaktivität sperren Immer Nie - - Nach %1$s Minute - Nach %1$s Minuten - Sicherer Bildschirm Aktualisierungen ausstehend Inhalt im Ausschnittbereich anzeigen @@ -327,17 +323,9 @@ Kapitelaktualisierungen Sicherer Bildschirm verbirgt App-Inhalte beim Wechseln von Apps und blockiert Screenshots Anzeige - - %1$d neues Kapitel - %1$d neue Kapitel - Kapitel %1$s Kapitel %1$s und %2$d mehr Kapitel %1$s - - Kapitel %1$s und 1 mehr - Kapitel %1$s und %2$d mehr - Benachrichtigungsinhalt verbergen Überprüfe auf neue Kapitel Akkuverbrauch-Optimierung deaktivieren @@ -345,19 +333,11 @@ Akkuverbrauch-Optimierung ist bereits deaktiviert E-Mail-Adresse Kapitelübergang immer anzeigen - - Für %d Eintrag - Für %d Einträge - Menü Neueste Älteste Nach oben verschieben Nach unten verschieben - - Erweiterungsaktualisierung verfügbar - %d Erweiterungsaktualisierungen verfügbar - Erweiterungsaktualisierungen Bibliothek wird aktualisiert Gefilterte Kapitel überspringen @@ -389,23 +369,11 @@ Anleitung für lokale Quellen %02d min, %02d s Filtert alle Einträge in deiner Bibliothek - - %1$s verbleibend - %1$s verbleibend - Grau Lesemodus Für diese Serie Reduziert Streifenbildung, könnte aber die Leistung beeinflussen - - %d Kategorie - %d Kategorien - Geräteeinstellungen konnten nicht geöffnet werden - - Erledigt in %1$s mit %2$s Fehler - Erledigt in %1$s mit %2$s Fehlern - Einweg-Synchronisation zum Aktualisieren der Kapitelfortschritte in den externen Trackingdiensten. Richte Tracking für einzelne Einträge über deren jeweiligen Trackingbutton ein. Bibliothekscover aktualisieren Diese Erweiterung stammt nicht aus der offiziellen Liste. @@ -429,10 +397,6 @@ Starten Quelle nicht gefunden Deaktivieren - - %1$s Kapitel - %1$s Kapitel - Erfordert einen Neustart der App, um wirksam zu werden Vernetzung Tippzonen umkehren @@ -449,10 +413,6 @@ Hinzufügedatum Lesemodus Thema - - %d Tracker - %d Tracker - Du hast keine angehefteten Quellen Abgeschlossen Fortschritt @@ -463,10 +423,6 @@ Quellen dieser Erweiterung könnten NSFW/Ü18-Inhalte enthalten Ü18 Dies verhindert nicht, dass inoffizielle oder möglicherweise falsch gekennzeichnete Erweiterungen NSFW/Ü18-Inhalte in der App anzeigen. - - %d Kapitel wird übersprungen, da die Quelle dieses entweder nicht besitzt, oder weil es rausgefiltert wurde - %d Kapitel werden übersprungen, da die Quelle diese entweder nicht besitzt, oder weil sie rausgefiltert wurden - Keine Kapitel gefunden Standard-Kapiteleinstellungen aktualisiert Als Standard setzen @@ -576,10 +532,6 @@ Höchste Empfindlichkeit für das Menü-Ausblenden beim Scrollen Invertiert - - Gestern - Vor %1$d Tagen - Heute Blaugrün & Türkis Erscheinungsbild @@ -684,10 +636,6 @@ Flutwelle Im Voraus herunterladen Automatisch während dem Lesen herunterladen - - Nächstes ungelesenes Kapitel - Nächste %d ungelesene Kapitel - Funktioniert nur, wenn das aktuelle Kapitel sowie das darauf folgende bereits heruntergeladen sind. Bist du dir sicher\? Du bist gerade dabei, „%s“ aus deiner Bibliothek zu entfernen @@ -756,19 +704,11 @@ %1$s-Fehler: %2$s *erforderlich Einträge verbergen, die bereits in der Bibliothek sind - - Nächstes Kapitel - Nächste %d Kapitel - In die Zwischenablage kopieren Kategorie aktualisieren Hohe Bilder teilen Overlay Breite Seiten drehen, damit sie passen - - %1$s Kapitel fehlt - %1$s Kapitel fehlen - Ausrichtung gedrehter breiter Seiten spiegeln Debug-Info Kapitelaktionen @@ -777,10 +717,6 @@ Zum Zoomen doppeltippen %d pro Zeile Intervalle - - 1 Tag - %d Tage - Benutzerdefiniertes Abrufintervall Intervall einstellen Monatlich abrufen (28 Tage) diff --git a/i18n/src/commonMain/resources/MR/el/plurals.xml b/i18n/src/commonMain/resources/MR/el/plurals.xml new file mode 100644 index 0000000000..9431ff6b80 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/el/plurals.xml @@ -0,0 +1,67 @@ + + + + %1$d νέο κεφάλαιο + %1$d νέα κεφάλαια + + + Για %d καταχώριση + Για %d καταχωρίσεις + + + Διαθέσιμη ενημέρωση επέκτασης + %d διαθέσιμες ενημερώσεις επεκτάσεων + + + Μετά από %1$s λεπτό + Μετά από %1$s λεπτά + + + Κεφάλαια %1$s και 1 ακόμη + Κεφάλαια %1$s και %2$d ακόμη + + + %1$s που απομένει + %1$s που απομένουν + + + %d κατηγορία + %d κατηγορίες + + + Έγινε σε %1$s με %2$s σφάλμα + Έγινε σε %1$s με %2$s σφάλματα + + + %1$s κεφάλαιο + %1$s κεφάλαια + + + %d ιχνηλάτης + %d ιχνηλάτες + + + Παραλείπεται %d κεφάλαιο, είτε λείπει από την πηγή είτε έχει φιλτραριστεί + Παραλείπονται %d κεφάλαια, είτε λείπουν από την πηγή είτε έχουν φιλτραριστεί + + + Εχθές + %1$d μέρες πριν + + + Επόμενο αδιάβαστο κεφάλαιο + Επόμενα %d αδιάβαστα κεφάλαια + + + Επόμενο κεφάλαιο + Επόμενα %d κεφάλαια + + + Λείπει %1$s κεφάλαιο + Λείπουν %1$s κεφάλαια + + + 1 ημέρα + %d ημέρες + + \ No newline at end of file diff --git a/i18n/src/main/res/values-el/strings.xml b/i18n/src/commonMain/resources/MR/el/strings.xml similarity index 95% rename from i18n/src/main/res/values-el/strings.xml rename to i18n/src/commonMain/resources/MR/el/strings.xml index 1c1663b0a5..9d086ba05c 100644 --- a/i18n/src/main/res/values-el/strings.xml +++ b/i18n/src/commonMain/resources/MR/el/strings.xml @@ -308,14 +308,6 @@ Κεφάλαιο %1$s και %2$d ακόμη Κεφάλαια %1$s Κεφάλαιο %1$s - - %1$d νέο κεφάλαιο - %1$d νέα κεφάλαια - - - Για %d καταχώριση - Για %d καταχωρίσεις - Έλεγχος για νέα κεφάλαια Κεφ. %1$s - %2$s Ενημέρωση βιβλιοθήκης @@ -326,10 +318,6 @@ Προσθήκη στη βιβλιοθήκη Οδηγός τοπικής πηγής Αποτυχία παράκαμψης του Cloudflare - - Διαθέσιμη ενημέρωση επέκτασης - %d διαθέσιμες ενημερώσεις επεκτάσεων - Έχετε αποσυνδεθεί Αποσύνδεση Αποσύνδεση από %1$s; @@ -357,10 +345,6 @@ Απόκρυψη περιεχομένου ειδοποιήσεων Η ασφαλής οθόνη αποκρύπτει τα περιεχόμενα εφαρμογών κατά την εναλλαγή εφαρμογών και εμποδίζει τα στιγμιότυπα οθόνης Ασφάλισε την οθόνη - - Μετά από %1$s λεπτό - Μετά από %1$s λεπτά - Ποτέ Πάντα Κλείδωμα όταν είναι αδρανής @@ -384,28 +368,12 @@ Πηγές Παλαιότερο Νεότερο - - Κεφάλαια %1$s και 1 ακόμη - Κεφάλαια %1$s και %2$d ακόμη - Φιλτράρει όλες τις καταχωρήσεις στη βιβλιοθήκη σας - - %1$s που απομένει - %1$s που απομένουν - Γκρι Μειώνει το banding, αλλά μπορεί να επηρεάσει την απόδοση Λειτουργία ανάγνωσης Για αυτήν τη σειρά - - %d κατηγορία - %d κατηγορίες - Δεν ήταν δυνατό το άνοιγμα των ρυθμίσεων της συσκευής - - Έγινε σε %1$s με %2$s σφάλμα - Έγινε σε %1$s με %2$s σφάλματα - Μονόδρομος συγχρονισμός για ενημέρωση των υπηρεσιών εξωτερικής παρακολούθησης προόδου κεφαλαίων. Ρυθμίστε την παρακολούθηση για μεμονωμένες καταχωρήσεις από το κουμπί παρακολούθησης τους. Ανανέωση εξώφυλλων βιβλιοθήκης Αυτή η επέκταση δεν προέρχεται από την επίσημη λίστα. @@ -429,10 +397,6 @@ Έναρξη Δεν βρέθηκε πηγή Απενεργοποίηση - - %1$s κεφάλαιο - %1$s κεφάλαια - Απαιτείται επανεκκίνηση της εφαρμογής για να τεθεί σε ισχύ Δίκτυο Και τα δυο @@ -449,10 +413,6 @@ Λειτουργία ανάγνωσης Θέμα Ημερομηνία προσθήκης - - %d ιχνηλάτης - %d ιχνηλάτες - Δεν έχετε καρφιτσωμένες πηγές Ολοκληρωμένο Η λήψη ολοκληρώθηκε @@ -463,10 +423,6 @@ 18+ Να επιτρέπεται η διαγραφή κεφαλαίων με σελιδοδείκτη Αυτό δεν εμποδίζει τις ανεπίσημες ή ενδεχομένως εσφαλμένα επισημασμένες επεκτάσεις να εμφανίζουν περιεχόμενο NSFW (18+) μέσα στην εφαρμογή. - - Παραλείπεται %d κεφάλαιο, είτε λείπει από την πηγή είτε έχει φιλτραριστεί - Παραλείπονται %d κεφάλαια, είτε λείπουν από την πηγή είτε έχουν φιλτραριστεί - Δεν βρέθηκαν κεφάλαια Ενημερώθηκαν οι προεπιλεγμένες ρυθμίσεις κεφαλαίου Ορισμός ως προεπιλογής @@ -575,10 +531,6 @@ Ύψιστη Υψηλή Ευαισθησία για την απόκρυψη του μενού κατά την κύλιση - - Εχθές - %1$d μέρες πριν - Αντεστραμμένο Σήμερα Teal & Τιρκουάζ @@ -684,10 +636,6 @@ Παλιρροϊκό κύμα Λήψη εκ των προτέρων Αυτόματη λήψη κατά την ανάγνωση - - Επόμενο αδιάβαστο κεφάλαιο - Επόμενα %d αδιάβαστα κεφάλαια - Λειτουργεί μόνο εάν το τρέχον κεφάλαιο + το επόμενο έχουν ήδη ληφθεί. Είστε σίγουροι; Πολλαπλό @@ -755,19 +703,11 @@ Διαθέσιμο αλλά η πηγή δεν έχει εγκατασταθεί: %s %1$s σφάλμα: %2$s *απαιτούμενο - - Επόμενο κεφάλαιο - Επόμενα %d κεφάλαια - Απόκρυψη καταχωρήσεων που βρίσκονται ήδη στη βιβλιοθήκη Αντιγραφή στο πρόχειρο Ενημέρωση κατηγορίας Διαχωρισμός ψηλών εικόνων Επικάλυψη - - Λείπει %1$s κεφάλαιο - Λείπουν %1$s κεφάλαια - Περιστροφή πλατιών σελίδων για να χωρέσουν Αναστροφή του προσανατολισμού των πλατιών σελίδων που έχουν περιστραφεί Πληροφορίες εντοπισμού σφαλμάτων @@ -783,10 +723,6 @@ Πέρασε την περίοδο ελέγχου Εκτός αναμενόμενης περιόδου κυκλοφορίας Διαστήματα - - 1 ημέρα - %d ημέρες - Εκτίμηση κάθε Ρύθμιση για ενημέρωση κάθε Ανάκτηση μηνιαίως (28 ημέρες) diff --git a/i18n/src/commonMain/resources/MR/eo/plurals.xml b/i18n/src/commonMain/resources/MR/eo/plurals.xml new file mode 100644 index 0000000000..fd983fa8fc --- /dev/null +++ b/i18n/src/commonMain/resources/MR/eo/plurals.xml @@ -0,0 +1,47 @@ + + + + Post 1 minuto + Post %1$s minutoj + + + %d kategorio + %d kategorioj + + + 1 ĉapitro + %1$s ĉapitroj + + + Ĉapitroj %1$s kaj 1 pli + Ĉapitroj %1$s kaj %2$d pli + + + 1 nova ĉapitro + %1$d novaj ĉapitroj + + + Por 1 titolo + Por %d titoloj + + + Mankas 1 ĉapitron + Mankas %d ĉapitrojn + + + 1 ŝanĝspurilo + %d ŝanĝspuriloj + + + 1 restas + %1$s restas + + + Farita en %1$s kun %2$s eraro + Farita en %1$s kun %2$s eraroj + + + Hieraŭ + Antaŭ %1$d tagoj + + \ No newline at end of file diff --git a/i18n/src/main/res/values-eo/strings.xml b/i18n/src/commonMain/resources/MR/eo/strings.xml similarity index 94% rename from i18n/src/main/res/values-eo/strings.xml rename to i18n/src/commonMain/resources/MR/eo/strings.xml index 0de7976c8d..ef4cf570f3 100644 --- a/i18n/src/main/res/values-eo/strings.xml +++ b/i18n/src/commonMain/resources/MR/eo/strings.xml @@ -54,10 +54,6 @@ Via biblioteko malplenas Neniu legita laste Kaŝi enhavon de sciigoj - - Post 1 minuto - Post %1$s minutoj - Neniam Ĉiam Sekureco @@ -106,10 +102,6 @@ Ekskluzivi: %s Inkluzivi: %s Nenio - - %d kategorio - %d kategorioj - Ĉiam demandi Defaŭlta kategorio Ĉiusemajne @@ -136,10 +128,6 @@ Sekv\' Antaŭ\' Foliumi - - 1 ĉapitro - %1$s ĉapitroj - Elŝutitaj ĉapitroj En biblioteko Aldonita al biblioteko @@ -231,21 +219,9 @@ Neniu nova ĝisdatigo disponebla Elŝuti Elekti savkopian dosieron - - Ĉapitroj %1$s kaj 1 pli - Ĉapitroj %1$s kaj %2$d pli - Ĉapitroj %1$s Ĉapitro %1$s kaj %2$d pli Ĉapitro %1$s - - 1 nova ĉapitro - %1$d novaj ĉapitroj - - - Por 1 titolo - Por %d titoloj - Novaj ĉapitroj trovitaj Kopii Migri @@ -254,10 +230,6 @@ Viŝi historion Ĉap. %1$s - %2$s Ĝisdatigas bibliotekon - - Mankas 1 ĉapitron - Mankas %d ĉapitrojn - Fonto ne trovita Neniu paĝo trovita Ne estas antaŭa ĉapitro @@ -283,10 +255,6 @@ Finitaj Legata Aldoni ŝanospuron - - 1 ŝanĝspurilo - %d ŝanĝspuriloj - Ŝanĝspurado Neniu ĉapitro trovita Agordi kiel defaŭlta @@ -335,10 +303,6 @@ Ensalutita Ensaluti Ensaluti al %1$s - - 1 restas - %1$s restas - Nur elŝutitaj Ĝisdatigita al v%1$s Malfermitkodaj permesiloj @@ -358,10 +322,6 @@ Kreado de savkopio fiaskis Kreas savkopion Kion vi volas savkopii\? - - Farita en %1$s kun %2$s eraro - Farita en %1$s kun %2$s eraroj - %02d min, %02d sek Mankantaj fontoj: Aŭtomata elŝuto @@ -383,10 +343,6 @@ Malŝaltita Ŝaltita Elementoj vice - - Hieraŭ - Antaŭ %1$d tagoj - Hodiaŭ Jino kaj Jango Verda pomo diff --git a/i18n/src/commonMain/resources/MR/es/plurals.xml b/i18n/src/commonMain/resources/MR/es/plurals.xml new file mode 100644 index 0000000000..6c760f9545 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/es/plurals.xml @@ -0,0 +1,83 @@ + + + + Tras %1$s minuto + Tras %1$s minutos + Tras %1$s minutos + + + %1$d nuevo capítulo + %1$d nuevos capítulos + %1$d nuevos capítulos + + + Capítulos %1$s y 1 más + Capítulos %1$s y %2$d más + Capítulos %1$s y %2$d más + + + Para %d título + Para %d títulos + Para %d títulos + + + Actualización de extensión disponible + %d actualizaciones de extensiones disponibles + %d actualizaciones de extensiones disponibles + + + Queda %1$s + Quedan %1$s + Quedan %1$s + + + %d categoría + %d categorías + %d categorías + + + Completada en %1$s con %2$s error + Completada en %1$s con %2$s errores + Completada en %1$s con %2$s errores + + + %1$s capítulo + %1$s capítulos + %1$s capítulos + + + %d servicio de seguimiento + %d servicios de seguimiento + %d servicios de seguimiento + + + Se omite %d capítulo, o bien falta en la fuente o ha sido filtrado + Se omiten %d capítulos, o bien faltan en la fuente o han sido filtrados + Se omiten %d capítulos, o bien faltan en la fuente o han sido filtrados + + + Ayer + Hace %1$d días + Hace %1$d días + + + El siguiente capítulo sin leer + Los siguientes %d capítulos sin leer + Los siguientes %d capítulos sin leer + + + El siguiente capítulo + Los siguientes %d capítulos + Los siguientes %d capítulos + + + Falta %1$s capítulo + Faltan %1$s capítulos + Faltan %1$s capítulos + + + Un día + %d días + %d días + + \ No newline at end of file diff --git a/i18n/src/main/res/values-es/strings.xml b/i18n/src/commonMain/resources/MR/es/strings.xml similarity index 92% rename from i18n/src/main/res/values-es/strings.xml rename to i18n/src/commonMain/resources/MR/es/strings.xml index 7f17ec314e..764824f214 100644 --- a/i18n/src/main/res/values-es/strings.xml +++ b/i18n/src/commonMain/resources/MR/es/strings.xml @@ -1,14 +1,12 @@ Nombre - Ajustes Cola de descargas Biblioteca Historial Actualizaciones Copia de seguridad y restauración - Ajustes Filtrar Sin leer @@ -38,17 +36,13 @@ Cancelar Ordenar Instalar - Cargando… - - General Lector Descargas Seguimiento Avanzado Acerca de - Tamaño de cuadrícula En vertical En horizontal @@ -62,7 +56,6 @@ Mientras se carga la batería Marcadas como completadas Actualizar progreso al terminar un capítulo - Pantalla completa Transiciones de página animadas Mostrar el número de página @@ -94,15 +87,11 @@ Cualquier dirección Forzar en vertical Forzar en horizontal - Carpeta de descarga Borrarlos tras marcarlos como leídos de forma manual Borrar capítulos terminados de forma automática Ubicación personalizada - - Servicios de seguimiento - Vaciar la caché de capítulos Usado: %1$s Se vació la caché. Se han eliminado %1$d archivos @@ -113,27 +102,20 @@ Borrar el historial de los elementos que no estén guardados en tu biblioteca ¿Está seguro\? Se perderán los capítulos leídos y el progreso de las entradas que no pertenezcan a la biblioteca Entradas eliminadas - Versión - Enviar informes de fallos Ayuda a corregir cualquier error. No se enviará ninguna información personal - Iniciar sesión en %1$s Nombre de usuario Contraseña Iniciar sesión Conectado Error desconocido - Actualizando categoría - - En publicación Desconocido Con licencia Eliminar de biblioteca - Capítulo %1$s Descargando (%1$d/%2$d) Error @@ -145,7 +127,6 @@ Descargar Sin leer ¿Seguro que quieres eliminar los capítulos seleccionados\? - Leyendo Completado Abandonado @@ -155,38 +136,26 @@ Título Estado Capítulos - Esto eliminará la fecha de lectura de este capítulo. ¿Estás seguro? Reiniciar todos los capítulos de este manga - Pág: %1$d Siguiente capítulo no encontrado No se pudo cargar la imagen - - - No se pudieron descargar los capítulos. Puedes volver a intentarlo en la sección de descargas - Nuevos capítulos encontrados Primero tienes que añadir el manga a tu biblioteca - Elige una imagen de portada Elige una copia de respaldo - Descargar No hay nuevas actualizaciones disponibles - Descargando… Toca aquí para instalar la actualización Error de descarga ¡Nueva versión disponible! - - No hay descargas No hay actualizaciones recientes No has leído nada últimamente Tu biblioteca está vacía - Error No se ha podido descargar el capítulo debido a un error inesperado No estás conectado a ninguna red Wi-Fi @@ -347,11 +316,6 @@ Bloquear por inactividad Siempre Nunca - - Tras %1$s minuto - Tras %1$s minutos - Tras %1$s minutos - Pantalla segura Actualizaciones pendientes Mostrar contenido en el área recortada @@ -360,19 +324,9 @@ Nuevos capítulos Pantalla segura oculta el contenido al cambiar de aplicación y bloquea las capturas de pantalla Visualización - - %1$d nuevo capítulo - %1$d nuevos capítulos - %1$d nuevos capítulos - Capítulo %1$s Capítulo %1$s y %2$d más Capítulos %1$s - - Capítulos %1$s y 1 más - Capítulos %1$s y %2$d más - Capítulos %1$s y %2$d más - Ocultar el contenido de las notificaciones Buscando nuevos capítulos Desactivar la optimización de batería @@ -380,21 +334,11 @@ Mejora la cadencia de las actualizaciones y las copias de respaldo que se hagan en segundo plano La optimización de la batería ya está desactivada Hacer transición entre capítulos - - Para %d título - Para %d títulos - Para %d títulos - Menú Lo más nuevo Lo más antiguo Mover al principio Mover al final - - Actualización de extensión disponible - %d actualizaciones de extensiones disponibles - %d actualizaciones de extensiones disponibles - Actualizando biblioteca Actualizaciones de extensiones Saltar capítulos excluidos por filtros @@ -425,28 +369,13 @@ Usado recientemente Buscar actualizaciones Guía de fuente local - - Queda %1$s - Quedan %1$s - Quedan %1$s - Filtra todos los elementos de tu biblioteca para ver solo los que estén disponibles sin conexión Modo de lectura Para esta serie Gris Reduce el efecto anillado en los degradados y mejora la calidad de los grises, pero puede afectar al rendimiento - - %d categoría - %d categorías - %d categorías - No se pudieron abrir los ajustes del dispositivo Volver a descargar las portadas en la biblioteca - - Completada en %1$s con %2$s error - Completada en %1$s con %2$s errores - Completada en %1$s con %2$s errores - La sincronización de estos servicios solo funciona en un solo sentido. Cada elemento en tu biblioteca tiene un botón de seguimiento y tendrás que configurarlo a mano, uno a uno. Esta extensión no es de la lista oficial de extensiones. No oficial @@ -467,11 +396,6 @@ Mostrar modo de lectura Empezar No se ha encontrado la fuente - - %1$s capítulo - %1$s capítulos - %1$s capítulos - Desactivar Es necesario reiniciar la aplicación para que surja efecto Networking @@ -489,11 +413,6 @@ Modo de lectura Tema de colores Por fecha en la biblioteca - - %d servicio de seguimiento - %d servicios de seguimiento - %d servicios de seguimiento - Todavía no has anclado ninguna fuente Terminadas En progreso @@ -504,11 +423,6 @@ Puede contener contenido para adultos (+18) 18+ Esto no evita que las extensiones extraoficiales o que estén mal clasificadas muestren contenido para mayores de 18 años en la aplicación. - - Se omite %d capítulo, o bien falta en la fuente o ha sido filtrado - Se omiten %d capítulos, o bien faltan en la fuente o han sido filtrados - Se omiten %d capítulos, o bien faltan en la fuente o han sido filtrados - No hay capítulos Se han actualizado los ajustes predeterminados de capítulo Establecer como predeterminado @@ -621,11 +535,6 @@ Más alta Sensibilidad para ocultar automáticamente el menú al desplazarse Invertido - - Ayer - Hace %1$d días - Hace %1$d días - Hoy Azul marino y turquesa Apariencia @@ -728,11 +637,6 @@ Solo funciona si el capítulo actual y el que va después ya están descargados. Descargar por adelantado Descarga los capítulos siguientes mientras lees - - El siguiente capítulo sin leer - Los siguientes %d capítulos sin leer - Los siguientes %d capítulos sin leer - ¿Estás seguro\? La biblioteca se actualizó: %s Estás a punto de borrar «%s» de tu biblioteca @@ -799,21 +703,11 @@ \n¿Seguro que quieres continuar\? %1$s error: %2$s *necesaria - - El siguiente capítulo - Los siguientes %d capítulos - Los siguientes %d capítulos - Saltar elementos que ya estén en la biblioteca Copiar al portapapeles Actualizar categoría Dividir las imágenes altas Superposición - - Falta %1$s capítulo - Faltan %1$s capítulos - Faltan %1$s capítulos - Girar las páginas anchas para adaptarlas a la pantalla Girar las páginas anchas en la dirección opuesta Información sobre la depuración @@ -828,11 +722,6 @@ Intervalos Ha pasado el período de comprobación Estimar cada - - Un día - %d días - %d días - Personalizar intervalo ¿Abandonado\? Tras más de 20 días y 2 meses Forzar actualización cada diff --git a/i18n/src/commonMain/resources/MR/eu/plurals.xml b/i18n/src/commonMain/resources/MR/eu/plurals.xml new file mode 100644 index 0000000000..d510178849 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/eu/plurals.xml @@ -0,0 +1,51 @@ + + + + %1$s-n egin da errore %2$s-ekin + %1$s-n egin da %2$s errorerekin + + + Atzo + Duela %1$d egun + + + Minutu baten ostean + %1$s minuturen ostean + + + Kapitulu bat saltatzen, iturria falta da edo iragazia izan da + %d kapitulu saltatzen, iturria falta da edo iragaziak izan dira + + + Titulu baterako + %d titulurako + + + 1 geratzen da + %1$s geratzen dira + + + kategoria %d + %d kategoria + + + kapitulu 1 + %1$s kapitulu + + + jarraitzaile 1 + %d jarraitzaile + + + Kapitulu berri bat + %1$d kapitulu berri + + + Luzapen baten eguneraketa eskuragarri + %d luzapenen eguneraketak eskuragarri + + + %1$s kapituluak eta bat gehiago + %1$s kapituluak eta %2$d gehiago + + \ No newline at end of file diff --git a/i18n/src/main/res/values-eu/strings.xml b/i18n/src/commonMain/resources/MR/eu/strings.xml similarity index 95% rename from i18n/src/main/res/values-eu/strings.xml rename to i18n/src/commonMain/resources/MR/eu/strings.xml index dc140017b1..9d5e9a0b37 100644 --- a/i18n/src/main/res/values-eu/strings.xml +++ b/i18n/src/commonMain/resources/MR/eu/strings.xml @@ -56,10 +56,6 @@ Instalatu eta abiarazi Shizuku luzapen instalatzaile gisa erabiltzeko. Shizuku ez dago martxan Berreskuratu egin da - - %1$s-n egin da errore %2$s-ekin - %1$s-n egin da %2$s errorerekin - Cookieak garbitu dira Alde batera utzia Egoera @@ -193,10 +189,6 @@ Ez dago aurreko kapitulurik Kopiatu Android bertsio hau jada ez da onartzen - - Atzo - Duela %1$d egun - Zaharkitua Desinstalatu Erakutsi orrialdearen zenbakia @@ -264,10 +256,6 @@ Beltza Hurrengoa Orrikaldekatua - - Minutu baten ostean - %1$s minuturen ostean - Automatikoa Sakaketa bikoitzaren animazioaren abiadura Automatikoa @@ -347,10 +335,6 @@ Honi buruz Gaia Sortu erroreen erregistroak - - Kapitulu bat saltatzen, iturria falta da edo iragazia izan da - %d kapitulu saltatzen, iturria falta da edo iragaziak izan dira - %1$s Kapitulua %1$s Kapituluak Mantendu pantaila piztuta @@ -546,10 +530,6 @@ Babeskopiak ez du mangarik. Jarraipena Berrirakurtzen - - Titulu baterako - %d titulurako - Erakutsi erabilitako irakurketa modua laburki irakurlea irekitzen denean Jarraipen gida Eguneratu aurrerapena irakurri ondoren @@ -558,39 +538,15 @@ Atzeko planoko ekintzak Liburutegiaren eguneraketak eta babeskopiak atzeko planoan egiten laguntzen du Ezin izan dira gailuaren ezarpenak ireki - - 1 geratzen da - %1$s geratzen dira - Ordenatu honen arabera - - kategoria %d - %d kategoria - - - kapitulu 1 - %1$s kapitulu - Eguneraketak egiteke Erakutsi edukia eremu ebakian - - jarraitzaile 1 - %d jarraitzaile - Ezin izan dira kapituluak deskargatu. Berriro saia zaitezke deskargen atalean - - Kapitulu berri bat - %1$d kapitulu berri - Gorde CBZ artxibo gisa Eguneratu liburutegiko manga azalak Tablet interfazea %1$s: %2$s, %3$d orrialdea Oraindik ez duzu kategoriarik sortu. - - Luzapen baten eguneraketa eskuragarri - %d luzapenen eguneraketak eskuragarri - Ezin izan da luzapenen zerrenda lortu Bilatu azal eta xehetasun berriak liburutegia eguneratzean Baztertutako kategorietako mangak ez dira eguneratuko, sarturiko kategorietan egon arren. @@ -605,10 +561,6 @@ Etenaldian Liburutegi eguneraketen akatsak nola konpondu jakiteko, ikusi %1$s Manga lokala - - %1$s kapituluak eta bat gehiago - %1$s kapituluak eta %2$d gehiago - %1$s kapitulua eta %2$d gehiago Norabide bakarreko sinkronizazioa jarraipen-zerbitzuetan kapituluaren aurrerapena eguneratzeko. Konfiguratu manga bakoitzaren jarraipena haien jarraipen botoia erabilita. Nabigazio-diseinuaren geruza erakutsi diff --git a/i18n/src/commonMain/resources/MR/fa/plurals.xml b/i18n/src/commonMain/resources/MR/fa/plurals.xml new file mode 100644 index 0000000000..560caa806e --- /dev/null +++ b/i18n/src/commonMain/resources/MR/fa/plurals.xml @@ -0,0 +1,55 @@ + + + + آپدیت برای یک افرونه موجود است + آپدیت برای %d افرونه موجود است + + + قسمت های %1$s و 1 قسمت دیگر + ‬قسمت های %1$s و %2$d قسمت دیگر‬ + + + 1 قسمت جدید + %1$d قسمت جدید + + + برای ۱ مانگا + برای %d مانگا + + + %d دسته + %d دسته + + + بعد از %1$s دقیقه + بعد از %1$s دقیقه + + + ۱ عدد باقی مانده + %1$s عدد باقی مانده + + + در %1$s با %2$s خطا انجام شد + در %1$s با %2$s خطا انجام شد + + + ۱ ردیاب + %d ردیاب + + + 1 قسمت + %1$s قسمت + + + 1 قسمت جا افتاده است + %d قسمت جا افتاده است + + + دیروز + %1$d روز پیش + + + قسمت خوانده نشده بعدی + %d قسمت خوانده نشده بعدی + + \ No newline at end of file diff --git a/i18n/src/main/res/values-fa/strings.xml b/i18n/src/commonMain/resources/MR/fa/strings.xml similarity index 95% rename from i18n/src/main/res/values-fa/strings.xml rename to i18n/src/commonMain/resources/MR/fa/strings.xml index de2928aa18..48505584cd 100644 --- a/i18n/src/main/res/values-fa/strings.xml +++ b/i18n/src/commonMain/resources/MR/fa/strings.xml @@ -1,9 +1,5 @@ - - آپدیت برای یک افرونه موجود است - آپدیت برای %d افرونه موجود است - نسخه جدید موجود است! خطا در دانلود دانلود کامل شد @@ -14,10 +10,6 @@ عکس روی جلد را انتخاب کنید لطفا قبل این کار مانگای موردنظر را به کتابخانه اضافه کنید آپدیت عکس روی جلد با خطا مواجه شد - - قسمت های %1$s و 1 قسمت دیگر - ‬قسمت های %1$s و %2$d قسمت دیگر‬ - قسمت های %1$s قسمت %1$s و %2$d قسمت دیگر قسمت %1$s @@ -149,14 +141,6 @@ فاصله از کنار صفحه درحال خواندن همیشه انتقال قسمت را نشان داده شود - - 1 قسمت جدید - %1$d قسمت جدید - - - برای ۱ مانگا - برای %d مانگا - برای این مجموعه بازکردن عکس با خطا مواجه شد قصد خواندن دارم(Plan to read) @@ -168,10 +152,6 @@ نوار نوار بودن صفحه را کاهش می‌دهد، ولی ممکن است در عملکرد تاثیر بگذارد Double tap animation speed نصب - - %d دسته - %d دسته - نشانک قسمت آپدیت افزونه‌ها به روزرسانی قسمت‌ها @@ -276,10 +256,6 @@ مخفی کردن اعلان‌ها \"صفحه نمایش امن\" محتویات برنامه را هنگام عوض کردن برنامه‌ها مخفی می‌کند و همچنین اسکرین‌شات را مسدود می‌کند صفحه نمایش امن - - بعد از %1$s دقیقه - بعد از %1$s دقیقه - هرگز همیشه قفل صفحه هنگام بیکاری @@ -348,10 +324,6 @@ آدرس ایمیل نام کاربری ورود به %1$s - - ۱ عدد باقی مانده - %1$s عدد باقی مانده - همه مانگاهای موجود در کتابخانه را فیلتر می کند فقط دانلود شده ها به رفع اشکالات برنامه کمک می کند. هیچ گونه داده حساسی ارسال نخواهد شد @@ -384,10 +356,6 @@ درحال ایجاد نسخه پشتیبان چه چیزی را می خواهید پشتیبان گیری کنید ؟ پشتیبان گیری هنوز در حال انجام است - - در %1$s با %2$s خطا انجام شد - در %1$s با %2$s خطا انجام شد - %02d دقیقه, %02d ثانیه بازیابی کامل شد منابع ناموجود: @@ -432,14 +400,6 @@ پیشرفت به دلیل فضای کم دیسک امکان دانلود قسمت ها وجود ندارد منبع یافت نشد - - ۱ ردیاب - %d ردیاب - - - 1 قسمت - %1$s قسمت - وضعیت ناشناخته نویسنده ناشناخته شما هیچ منبع پین‌شده‌ای ندارید @@ -482,10 +442,6 @@ لطفا دوباره به MAL وارد شوید تنظیمات قسمت ها هیچ نرم افزار انتخاب فایلی یافت نشد - - 1 قسمت جا افتاده است - %d قسمت جا افتاده است - راهنمای تعویض منبع پاک کردن سابقه نمایش در لیست منابع و افزونه‌ها @@ -547,10 +503,6 @@ فقط روی شبکه‌ی نامحدود که شروع نشده‌اند محدودیت‌ها: %s - - دیروز - %1$d روز پیش - با قسمت‌(های) خوانده‌نشده از به‌روزرسانی ورودی‌ها صرف‌نظر کنید امروز @@ -634,10 +586,6 @@ الان نه نمایش دکمه ادامه خواندن بهبود کارکرد ابزار خواندن - - قسمت خوانده نشده بعدی - %d قسمت خوانده نشده بعدی - اگر قسمت فعلی و بعدی دانلود شده باشند، تنها برای ورودی‌های کتابخانه کار می‌کند اجازه دسترسی به حافظه داده نشده. داده ها از فایل پشتیبان برگردانده میشوند. diff --git a/i18n/src/commonMain/resources/MR/fi/plurals.xml b/i18n/src/commonMain/resources/MR/fi/plurals.xml new file mode 100644 index 0000000000..3c6adea0bc --- /dev/null +++ b/i18n/src/commonMain/resources/MR/fi/plurals.xml @@ -0,0 +1,55 @@ + + + + Minuutin jälkeen + %1$s minuutin jälkeen + + + 1 uusi luku + %1$d uutta lukua + + + Luku %1$s ja 1 lisää + Luvut %1$s ja %2$d lisää + + + Yhdelle sarjalle + %d sarjalle + + + Laajennuspäivitys saatavilla + %d laajennuspäivitystä saatavilla + + + 1 jäljellä + %1$s jäljellä + + + %d kategoria + %d kategoriaa + + + Valmistui %1$s virheitä löytyi %2$s + Valmistui %1$s virheitä löytyi %2$s + + + 1 luku + %1$s lukua + + + 1 seurantapalvelin + %d seurantapalvelinta + + + 1 puuttuva luku + %d puuttuvaa lukua + + + Eilen + %1$d päivää sitten + + + Seuraava lukematon luku + Seuraavat %d lukematonta lukua + + \ No newline at end of file diff --git a/i18n/src/main/res/values-fi/strings.xml b/i18n/src/commonMain/resources/MR/fi/strings.xml similarity index 95% rename from i18n/src/main/res/values-fi/strings.xml rename to i18n/src/commonMain/resources/MR/fi/strings.xml index 86444f7e0e..ac27efe690 100644 --- a/i18n/src/main/res/values-fi/strings.xml +++ b/i18n/src/commonMain/resources/MR/fi/strings.xml @@ -314,26 +314,14 @@ Vaadi lukituksen avaaminen Aina Ei koskaan - - Minuutin jälkeen - %1$s minuutin jälkeen - Cloudflaren ohittaminen epäonnistui Lukujen päivitykset Näyttö Päivitettävät Päivitä WebView-sovellus yhteensopivuuden parantamiseksi - - 1 uusi luku - %1$d uutta lukua - Luku %1$s Luku %1$s ja %2$d lisää Luvut %1$s - - Luku %1$s ja 1 lisää - Luvut %1$s ja %2$d lisää - Piilota ilmoitusten sisältö Etsitään uusia lukuja Lukitse käyttämättömänä @@ -345,19 +333,11 @@ Sähköpostiosoite Näytä sisältö leikkausalueella Näytä aina luvun vaihdos - - Yhdelle sarjalle - %d sarjalle - Valikko Uusin Vanhin Siirrä alkuun Siirrä loppuun - - Laajennuspäivitys saatavilla - %d laajennuspäivitystä saatavilla - Laajennuspäivitykset Palautus peruttu Varmuuskopion palautus epäonnistui @@ -389,20 +369,8 @@ Paikallinen lähdeopas %02d min, %02d sek Suodattaa kaikki sarjat kirjastossasi - - 1 jäljellä - %1$s jäljellä - Harmaa Tälle sarjalle - - %d kategoria - %d kategoriaa - - - Valmistui %1$s virheitä löytyi %2$s - Valmistui %1$s virheitä löytyi %2$s - Vähentää juovia, mutta vaikuttaa suorituskykyyn Lukutila Laiteasetuksia ei voitu avata @@ -429,10 +397,6 @@ Aloita Lähdettä ei löytynyt Poista käytöstä - - 1 luku - %1$s lukua - Edellyttää sovelluksen käynnisstämisen uudelleen Verkko Molemmat @@ -449,10 +413,6 @@ Lukutila Teema Lisäyspäivämäärä - - 1 seurantapalvelin - %d seurantapalvelinta - Sinulla ei ole kiinnitettyjä lähteitä Valmis Edistyminen @@ -463,10 +423,6 @@ Voi sisältää NSFW (18+) -sisältöä 18+ Tämä ei estä epävirallisia tai mahdollisesti väärin merkittyjä laajennuksia näyttämästä NSFW 18+ sisältöä sovelluksessa. - - 1 puuttuva luku - %d puuttuvaa lukua - Lukuja ei löytynyt Päivitetyt luvun oletusasetukset Aseta oletukseksi @@ -548,10 +504,6 @@ Päällä Aloitusopas Varoitus: massalataukset voivat johtaa siihen, että lähteet muuttuvat hitaammiksi käyttää ja/tai ne estävät Tachiyomin käytön. Napauta saadaksesi lisätietoja. - - Eilen - %1$d päivää sitten - Näytä manga Kansikuva ruudukko Dynaaminen @@ -597,10 +549,6 @@ Lukemattomien määrä Poista kategoria Jäljitä - - Seuraava lukematon luku - Seuraavat %d lukematonta lukua - Alhainen Poissuljetut kategoriat Alhaisin diff --git a/i18n/src/commonMain/resources/MR/fil/plurals.xml b/i18n/src/commonMain/resources/MR/fil/plurals.xml new file mode 100644 index 0000000000..2a3677be43 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/fil/plurals.xml @@ -0,0 +1,67 @@ + + + + Pagkatapos ng %1$s minuto + Pagkatapos ng %1$s (na) minuto + + + %d kategorya + %d (na) kategorya + + + Ang extension ay available upang i-update + Ang mga %d (na) extension ay available upang i-update + + + Mga kabanata %1$s at isa pa + Mga kabanata %1$s at %2$d pa + + + %1$d bagong kabanata + %1$d (na) bagong kabanata + + + Para sa %d na entry + Para sa %d na mga entry + + + %1$s kabanata + %1$s (na) kabanata + + + %1$s na lang + %1$s pa ang nasa queue + + + Na-restore sa loob ng %1$s na may %2$s error + Na-restore sa loob ng %1$s na may %2$s (na) error + + + %d tracker + %d na mga tracker + + + Nilaktawan ang %d na kabanata, maaaring ito ay wala sa source o na-filter ang mga ito + Nilaktawan ang %d na mga kabanata, maaaring wala sa source o na-filter ang mga ito + + + Kahapon + %1$d araw na ang makalipas + + + Susunod na hindi pa nababasa na kabanata + Susunod na %d di pa nababasa na kabanata + + + Sunod na kabanata + Susunod na %d kabanata + + + Nawawalang %1$s na kabanata + Nawawalang %1$s mga kabanata + + + 1 araw + %d (mga) araw + + \ No newline at end of file diff --git a/i18n/src/main/res/values-fil/strings.xml b/i18n/src/commonMain/resources/MR/fil/strings.xml similarity index 94% rename from i18n/src/main/res/values-fil/strings.xml rename to i18n/src/commonMain/resources/MR/fil/strings.xml index 26157d64ab..c1c0b0be92 100644 --- a/i18n/src/main/res/values-fil/strings.xml +++ b/i18n/src/commonMain/resources/MR/fil/strings.xml @@ -92,10 +92,6 @@ Mga Setting Higit pa Pangalan - - Pagkatapos ng %1$s minuto - Pagkatapos ng %1$s (na) minuto - Hindi Palagi Isara kung nakatambay @@ -206,10 +202,6 @@ I-update Nakabinbin ang mga update Lahat - - %d kategorya - %d (na) kategorya - Palaging tanungin Default na kategorya Maghanap ng mga bagong cover at detalye kapag nag-a-update ng Aklatan @@ -270,10 +262,6 @@ Paki-update po ang WebView app para sa mas maayos na paggana Kinakailangan ng app ang WebView upang gumana ito Bigong ma-bypass ang Cloudflare - - Ang extension ay available upang i-update - Ang mga %d (na) extension ay available upang i-update - May bagong bersyon! Nagka-error sa pag-download I-tap upang ma-install ang update @@ -284,21 +272,9 @@ Pumili ng cover Maaaring ilagay ang entry sa iyong library bago ito gawin Bigong mapalitan ang cover - - Mga kabanata %1$s at isa pa - Mga kabanata %1$s at %2$d pa - Mga kabanata %1$s Kabanata %1$s at karagdagang %2$d pa Kabanata %1$s - - %1$d bagong kabanata - %1$d (na) bagong kabanata - - - Para sa %d na entry - Para sa %d na mga entry - May mga bagong kabanata Naghahanap ng mga bagong kabanata Di ma-download ang mga kabanata dahil sa mababang espasyo @@ -364,10 +340,6 @@ Kinopya sa clipboard: \n%1$s Burahin ang mga na-download na kabanata\? - - %1$s kabanata - %1$s (na) kabanata - Palawakin Bawasan Tinanggal sa Aklatan @@ -403,10 +375,6 @@ Email address Username (pangalan) Mag-login sa %1$s - - %1$s na lang - %1$s pa ang nasa queue - Pini-filter ang lahat ng mga entry sa iyong akalatan Mga na-download lang Nakatutulong sa pag-ayos sa mga bug. Walang sensitibong data ang ipapadala @@ -438,10 +406,6 @@ Bigong ma-restore ang backup Kinansela ang pag-restore Inire-restore na - - Na-restore sa loob ng %1$s na may %2$s error - Na-restore sa loob ng %1$s na may %2$s (na) error - Na-restore na Rine-restore ang backup Bigong ma-backup @@ -449,10 +413,6 @@ Anong iba-backup mo\? Bina-backup na %02d (na) min, %02d (na) seg - - %d tracker - %d na mga tracker - Wala kang naka-pin na source Tapos na Mga error @@ -463,10 +423,6 @@ Hindi nito naiiwasan ang pagpapakita ng mga NSFW (18+) sa mga di-opisyal o posibleng maling naka-flag na extension sa loob ng app. Posibleng may NSFW (18+) content ang mga source mula sa extension na ito 18+ - - Nilaktawan ang %d na kabanata, maaaring ito ay wala sa source o na-filter ang mga ito - Nilaktawan ang %d na mga kabanata, maaaring wala sa source o na-filter ang mga ito - Walang nakitang kabanata Gusto mo bang i-save at ipagpaubaya ang pagsasaayos na ito\? Ipagpaubaya @@ -576,10 +532,6 @@ Pinakamataas Sensitivity para sa pagtatago ng menu sa scroll Baligtad - - Kahapon - %1$d araw na ang makalipas - Ngayon Teal at Turquoise Hitsura @@ -686,10 +638,6 @@ Kusang mag-download habang nagbabasa Gumagana lamang sa kasalukuyang kabanata + ang susunod ay na-download na. Sigurado ka ba\? - - Susunod na hindi pa nababasa na kabanata - Susunod na %d di pa nababasa na kabanata - Marami Tatanggalin mo na ang \"%s\" mula sa aklatan mo Huling update sa aklatan: %s @@ -757,15 +705,7 @@ %ds Kopyahin sa clipboard Itago ang mga entry na nasa aklatan na - - Sunod na kabanata - Susunod na %d kabanata - I-update ang kategorya - - Nawawalang %1$s na kabanata - Nawawalang %1$s mga kabanata - I-rotate ang malalawak na pahina upang magkasya I-flip ang oryentasyon ng mga pinaikot na malalawak na pahina Nakapatong (Overlay) @@ -783,10 +723,6 @@ Itinigil\? Huli ng 20+ at 2 buwan Lumipas ang check period Kunin kada buwan (kada ika-28 na araw) - - 1 araw - %d (mga) araw - Tantyahin bawat Itakdang i-update bawat Sa labas ng inaasahang release period diff --git a/i18n/src/commonMain/resources/MR/fr/plurals.xml b/i18n/src/commonMain/resources/MR/fr/plurals.xml new file mode 100644 index 0000000000..e3c52a33d7 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/fr/plurals.xml @@ -0,0 +1,83 @@ + + + + Après %1$s minute + Après %1$s minutes + Après %1$s minutes + + + %1$d nouveau chapitre + %1$d nouveaux chapitres + %1$d nouveaux chapitres + + + Chapitre %1$s et 1 autre + Chapitres %1$s et %2$d autres + Chapitres %1$s et %2$d autres + + + Pour %d titre + Pour %d titres + Pour %d titres + + + Mise à jour d\'extension disponible + %d mises à jour d\'extensions disponibles + %d mises à jour d\'extensions disponibles + + + %1$s restant + %1$s restants + %1$s restants + + + %d catégorie + %d catégories + %d catégories + + + Effectuée en %1$s avec %2$s erreur + Effectuée en %1$s avec %2$s erreurs + Effectuée en %1$s avec %2$s erreurs + + + %1$s chapitre + %1$s chapitres + %1$s chapitres + + + Suivi par %d service + Suivi par %d services + Suivi par %d services + + + %d chapitre a été sauté, soit la source ne l\'a pas, soit il a été filtré + %d chapitres ont été sautés, soit la source ne les a pas, soit ils ont été filtrés + %d chapitres ont été sautés, soit la source ne les a pas, soit il ont été filtrés + + + Hier + Il y a %1$d jours + Il y a %1$d jours + + + Chapitre suivant non lu + Les %d suivants non lus + Les %d suivants non lus + + + Chapitre suivant + %d chapitres suivants + %d chapitres suivants + + + %1$s chapitre manquant + %1$s chapitres manquants + %1$s chapitres manquants + + + 1 jour + %d jours + %d jours + + \ No newline at end of file diff --git a/i18n/src/main/res/values-fr/strings.xml b/i18n/src/commonMain/resources/MR/fr/strings.xml similarity index 91% rename from i18n/src/main/res/values-fr/strings.xml rename to i18n/src/commonMain/resources/MR/fr/strings.xml index 8a7248055a..11311ee496 100644 --- a/i18n/src/main/res/values-fr/strings.xml +++ b/i18n/src/commonMain/resources/MR/fr/strings.xml @@ -1,14 +1,12 @@ Nom - Paramètres File de téléchargement Bibliothèque Historique Mises à jour Sauvegarder et restaurer - Paramètres Filtre Favori @@ -50,17 +48,13 @@ Partager Télécharger la page Réinitialiser - Chargement… - - Général Lecteur Téléchargements Suivi Avancé À propos - Taille de grille Portrait Paysage @@ -75,7 +69,6 @@ Lors de la charge Ayant comme statut « Terminé » Synchroniser la progression après lecture - Plein écran Activer les transitions Afficher le numéro des pages @@ -112,7 +105,6 @@ V B O - Répertoire de téléchargement Suppression automatique après lecture Désactivé @@ -121,9 +113,7 @@ Troisième chapitre avant le dernier lu Quatrième chapitre avant le dernier lu Télécharger les nouveaux chapitres - Services - Utilisé : %1$s Cache effacé. %1$d fichiers ont été supprimés Une erreur est survenue lors de l\'effacement du cache @@ -132,26 +122,18 @@ Effacer la base de données Supprimer l\'historique des entrées qui ne sont pas enregistrées dans votre bibliothèque Entrées supprimées - Version - Envoyer des rapports de plantage Aident à corriger les bugs. Aucune donnée sensible ne sera envoyée - Connexion à %1$s Nom d\'utilisateur Mot de passe Se connecter Erreur inconnue - - - - En cours Inconnu Licencié Retirer de la bibliothèque - Chapitre %1$s En téléchargement (%1$d/%2$d) Erreur @@ -160,7 +142,6 @@ Par numéro de chapitre Télécharger Non lus - Suivi En cours Terminé @@ -171,16 +152,11 @@ Titre Statut Chapitres - Une catégorie avec ce nom existe déjà ! - Ceci enlèvera la date de lecture de ce chapitre. Êtes-vous sûr(e) \? Réinitialiser tous les chapitres de ce titre - Ajouter à la bibliothèque \? - Image sauvegardée - Filtre personnalisé Ajouter comme couverture Couverture mise à jour @@ -188,32 +164,22 @@ Chapitre suivant non trouvé L\'image n\'a pas pu être chargée Voulez-vous mettre cette image comme couverture ? - - - Une erreur est survenue lors du téléchargement des chapitres. Vous pouvez réessayer dans la section téléchargements - Des nouveaux chapitres ont été trouvés La mise à jour de la couverture a échoué Veuillez ajouter ce titre à votre bibliothèque avant de faire cela - Sélectionner l\'image de couverture Sélectionner fichier de sauvegarde - Télécharger Aucune mise à jour disponible - Téléchargement en cours… Appuyer pour installer Erreur lors du téléchargement Mise à jour disponible ! - - Aucun téléchargement en cours Pas de mises à jour récentes Rien de lu récemment Votre bibliothèque est vide - Téléchargement Erreur Aucune connexion disponible @@ -349,11 +315,6 @@ Verrouiller en cas d\'inactivité Toujours Jamais - - Après %1$s minute - Après %1$s minutes - Après %1$s minutes - Mode discret Mises à jour en attente Utiliser la zone de l\'encoche @@ -362,19 +323,9 @@ Mises à jour des chapitres L\'écran sécurisé cache le contenu lors du changement d\'application et bloque les captures d\'écran Affichage - - %1$d nouveau chapitre - %1$d nouveaux chapitres - %1$d nouveaux chapitres - Chapitre %1$s Chapitre %1$s et %2$d autres Chapitres %1$s - - Chapitre %1$s et 1 autre - Chapitres %1$s et %2$d autres - Chapitres %1$s et %2$d autres - Cacher le contenu des notifications Recherche de nouveaux chapitres Désactiver la fonction d\'optimisation de la batterie @@ -382,22 +333,12 @@ La fonction d\'optimisation de la batterie est déjà désactivée Adresse courriel Toujours afficher la transition entre les chapitres - - Pour %d titre - Pour %d titres - Pour %d titres - Menu Plus récent Plus ancien Déplacer au début Déplacer à la fin Mises à jour d\'extensions - - Mise à jour d\'extension disponible - %d mises à jour d\'extensions disponibles - %d mises à jour d\'extensions disponibles - Mise à jour de la bibliothèque Sources En cours @@ -427,26 +368,11 @@ %02d min, %02d s WebView est requis pour le fonctionnement l\'application Guide des sources locales - - %1$s restant - %1$s restants - %1$s restants - Filtrer toutes les entrées dans la bibliothèque Gris Pour cette série Réduit les bandes de couleur, mais peut impacter les performances - - %d catégorie - %d catégories - %d catégories - Mode de lecture - - Effectuée en %1$s avec %2$s erreur - Effectuée en %1$s avec %2$s erreurs - Effectuée en %1$s avec %2$s erreurs - Impossible d\'ouvrir les paramètres de l\'appareil Actualiser les couvertures de la bibliothèque Synchronisation à sens unique pour mettre à jour la progression du chapitre dans les services de suivi. Configurez le suivi des entrées individuelles à partir de leur bouton de suivi. @@ -470,11 +396,6 @@ Afficher le mode de lecture Commencer Source non trouvée - - %1$s chapitre - %1$s chapitres - %1$s chapitres - Désactiver Nécessite un redémarrage de l\'application pour prendre effet Réseau @@ -492,11 +413,6 @@ Date ajoutée Mode de lecture Thème - - Suivi par %d service - Suivi par %d services - Suivi par %d services - Vous n\'avez aucune source épinglée Compléter Progression @@ -507,11 +423,6 @@ Les sources de cette extension peuvent contenir du contenu NSFW (18+) 18+ Ceci n\'empêche pas les extensions non officielles ou potentiellement mal signalées de diffuser du contenu +18 dans l\'application. - - %d chapitre a été sauté, soit la source ne l\'a pas, soit il a été filtré - %d chapitres ont été sautés, soit la source ne les a pas, soit ils ont été filtrés - %d chapitres ont été sautés, soit la source ne les a pas, soit il ont été filtrés - Aucun chapitre trouvé Appliquer ce paramétrage par défaut \? Paramètres du chapitre @@ -621,11 +532,6 @@ Maximale Sensibilité pour masquer le menu lors du défilement Inversé - - Hier - Il y a %1$d jours - Il y a %1$d jours - Aujourd\'hui Bleu canard et turquoise Authentifiez-vous pour confirmer les changements @@ -730,11 +636,6 @@ Raz-de-marée Téléchargement anticipé Téléchargement anticipé pendant la lecture - - Chapitre suivant non lu - Les %d suivants non lus - Les %d suivants non lus - Fonctionne seulement si le chapitre actuel et le suivant sont déjà téléchargés. Êtes-vous sûr(e) \? Populaire @@ -803,20 +704,10 @@ Disponible mais la source n\'est pas installée : %s *obligatoire Masquer les entrées déjà présentes dans la bibliothèque - - Chapitre suivant - %d chapitres suivants - %d chapitres suivants - Copier dans le presse-papier Mettre à jour la catégorie Diviser les grandes images Superposition - - %1$s chapitre manquant - %1$s chapitres manquants - %1$s chapitres manquants - Inverser l\'orientation des pages larges retournées Tourner les pages larges pour qu\'elles rentrent Informations de débogage @@ -846,11 +737,6 @@ A des résultats Estimer chaque HTTP %d, consulter le site Web dans WebView - - 1 jour - %d jours - %d jours - Configurer pour mettre à jour tous les Personnaliser l\'intervalle Déplacer la série vers le bas diff --git a/i18n/src/commonMain/resources/MR/gl/plurals.xml b/i18n/src/commonMain/resources/MR/gl/plurals.xml new file mode 100644 index 0000000000..0c75de0e05 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/gl/plurals.xml @@ -0,0 +1,63 @@ + + + + %d categoría + %d categorías + + + Despois de 1 minuto + Despois de %1$s minutos + + + Seguinte capítulo sen ler + Seguintes %d capítulos sen ler + + + Queda %1$s + Quedan %1$s + + + Onte + Fai %1$d días + + + Feito en %1$s con %2$s erro + Feito en %1$s con %2$s erros + + + %d servizo de seguemento + %d servizos de seguemento + + + Hai unha actualización dunha extensión + Hai actualizacións de %d extensións + + + %1$s capítulo + %1$s capítulos + + + Capítulos %1$s e 1 máis + Capítulos %1$s e %2$d máis + + + Saltouse %d capítulo: falta na fonte ou ignorouse + Saltáronse %d capítulos: faltan na fonte ou ignoráronse + + + Por %d elemento + Por %d elementos + + + %1$d capítulo novo + %1$d capítulos novos + + + O seguinte capítulo + Os seguintes %d capítulos + + + Falta %1$s capítulo + Faltan %1$s capítulos + + \ No newline at end of file diff --git a/i18n/src/main/res/values-gl/strings.xml b/i18n/src/commonMain/resources/MR/gl/strings.xml similarity index 95% rename from i18n/src/main/res/values-gl/strings.xml rename to i18n/src/commonMain/resources/MR/gl/strings.xml index 37f61c5bd6..0babeef680 100644 --- a/i18n/src/main/res/values-gl/strings.xml +++ b/i18n/src/commonMain/resources/MR/gl/strings.xml @@ -102,10 +102,6 @@ Actualizar Actualizacións pendentes Todas - - %d categoría - %d categorías - Preguntar sempre Categoría por defecto Procurar novas portadas e detalles cando se actualice a biblioteca @@ -129,10 +125,6 @@ Esconde os contidos das notificacións O modo discreto esconde os contidos da app ao cambiar de app e bloquea as capturas de pantalla Modo discreto - - Despois de 1 minuto - Despois de %1$s minutos - Nunca Sempre Bloquear por inactividade @@ -299,10 +291,6 @@ Eliminar categoría Dispoñible, mais a fonte non se instalou: %s Fixados - - Seguinte capítulo sen ler - Seguintes %d capítulos sen ler - Amosar o número de capítulos por ler na icona de actualizacións Excluír: %s Saltar os capítulos duplicados @@ -433,10 +421,6 @@ Inverter as zonas de toque Dereita Guía de seguemento - - Queda %1$s - Quedan %1$s - En pausa Por número de capítulo Preguntas frecuentes e guías @@ -503,10 +487,6 @@ Cancelar todo para esta serie Por data de subida Preme para ver os detalles do erro - - Onte - Fai %1$d días - Omitir actualizacións Restricións: %s Opcións de ordenación e visualización por categoría @@ -524,10 +504,6 @@ Restaurar a biblioteca dende unha copia de seguridade Creouse a copia de seguridade Fallou a restauración da copia de seguridade - - Feito en %1$s con %2$s erro - Feito en %1$s con %2$s erros - Servizos de seguemento sen conectar: Restaurando a copia de seguridade Xa se está facendo a restauración @@ -573,10 +549,6 @@ Isto eliminará a data de comezo seleccionada de %s Está dispoñible unha nova versión oficial. Preme para saber como migrar das versións non oficiais de F-Droid. Páxina seguinte - - %d servizo de seguemento - %d servizos de seguemento - Migrar Eliminado da biblioteca Máis @@ -627,10 +599,6 @@ Non se atopou ninguna fonte instalada Advertencia: As baixadas grandes poden facer que as fontes se volvan máis lentas e/ou bloqueen Tachiyomi. Preme para saber máis. Abrir no GitHub - - Hai unha actualización dunha extensión - Hai actualizacións de %d extensións - Xestor de descargas Erro Descargas en pausa @@ -651,19 +619,11 @@ Esta versión de Android xa non ten soporte Non hai ningunha conexión de rede dispoñible Eliminar da biblioteca - - %1$s capítulo - %1$s capítulos - Actualizáronse os axustes por defecto dos capítulos Ver os elementos da biblioteca actualizados recentemente Vas eliminar \"%s\" da túa biblioteca Non se atopou a o capítulo seguinte Cargando páxinas… - - Capítulos %1$s e 1 máis - Capítulos %1$s e %2$d máis - Rematado: Páxina: %1$d Produciuse un erro ao gardar a imaxe @@ -723,10 +683,6 @@ Reiniciar tódolos capítulos deste elemento Modo de lectura O formato RARv5 non está soportado - - Saltouse %d capítulo: falta na fonte ou ignorouse - Saltáronse %d capítulos: faltan na fonte ou ignoráronse - Actualizando a biblioteca Última actualización da biblioteca: %s Cap. %1$s - %2$s @@ -736,16 +692,8 @@ %dseg Elementos en seguimento Puntuación media - - Por %d elemento - Por %d elementos - Actualizacións omitidas: %1$d Omitiuse porque non hai capítulos lidos - - %1$d capítulo novo - %1$d capítulos novos - Capítulo %1$s e %2$d máis Capítulos %1$s Omitiuse porque esta serie non require actualizarse @@ -759,14 +707,6 @@ Actualizar categoría Ocultar elementos que xa estén na biblioteca Copiar ao portapapeis - - O seguinte capítulo - Os seguintes %d capítulos - - - Falta %1$s capítulo - Faltan %1$s capítulos - Xirar as páxinas anchas para adaptalas á pantalla Voltear a orientación das páxinas anchas xiradas Superposición diff --git a/i18n/src/commonMain/resources/MR/he/plurals.xml b/i18n/src/commonMain/resources/MR/he/plurals.xml new file mode 100644 index 0000000000..548c4564c2 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/he/plurals.xml @@ -0,0 +1,99 @@ + + + + עדכון לתוסף זמין + עדכונים ל-%d תוספים זמינים + עדכונים ל-%d תוספים זמינים + עדכונים ל-%d תוספים זמינים + + + פרקים %1$s ואחד נוסף + פרקים %1$s ו-%2$d נוספים + פרקים %1$s ו-%2$d נוספים + פרקים %1$s ו-%2$d נוספים + + + פרק אחד חדש + %1$d פרקים חדשים + %1$d פרקים חדשים + %1$d פרקים חדשים + + + עבור כותר אחד + עבור %d כותרים + עבור %d כותרים + עבור %d כותרים + + + לאחר דקה אחת + לאחר שתי דקות + לאחר %1$s דקות + לאחר %1$s דקות + + + קטגורייה אחת + שתי קטגוריות + %d קטגוריות + %d קטגוריות + + + אתמול + לפני יומיים + לפני %1$d ימים + לפני %1$d ימים + + + פרק אחד + שני פרקים + %1$s פרקים + %1$s פרקים + + + 1 נשאר + 2 נשארו + %1$s נשארו + + + + הושלם ב %1$s עם שגיאה אחת + הושלם ב %1$s עם שתי שגיאות + הושלם ב %1$s עם %2$s שגיאות + + + + דולג פרק אחד, המקור חסר או שהוא סונן החוצה + דולגו שני פרקים, המקור חסר או שהם סוננו החוצה + דולגו %d פרקים, המקור חסר או שהם סוננו החוצה + + + + הפרק הבא + שני הפרקים הבאים + %d הפרקים הבאים + + + + מעקב אחד + שני מעקבים + %d מעקבים + + + + הפרק הבא שלא נקרא + שני הפרקים הבאים שלא נקראו + %d הפרקים הבאים שלא נקראו + + + + יום אחד + יומיים + %d ימים + + + + חסר פרק אחד + חסרים שני פרקים + חסרים %1$s פרקים + + + \ No newline at end of file diff --git a/i18n/src/main/res/values-he/strings.xml b/i18n/src/commonMain/resources/MR/he/strings.xml similarity index 92% rename from i18n/src/main/res/values-he/strings.xml rename to i18n/src/commonMain/resources/MR/he/strings.xml index daf3a27285..0b08ea4971 100644 --- a/i18n/src/main/res/values-he/strings.xml +++ b/i18n/src/commonMain/resources/MR/he/strings.xml @@ -13,12 +13,6 @@ אין לך קטגוריות. לחץ על כפתור הפלוס כדי ליצור אחד לארגון הספרייה שלך. הספרייה שלך ריקה אין הורדות - - עדכון לתוסף זמין - עדכונים ל-%d תוספים זמינים - עדכונים ל-%d תוספים זמינים - עדכונים ל-%d תוספים זמינים - גרסה חדשה זמינה! שגיאה בהורדה לחץ כדי להתקין עדכון @@ -29,27 +23,9 @@ בחר תמונת כריכה אנא הוסף את הפריט לספרייה שלך לפני שתעשה זאת עדכון הכריכה נכשל - - פרקים %1$s ואחד נוסף - פרקים %1$s ו-%2$d נוספים - פרקים %1$s ו-%2$d נוספים - פרקים %1$s ו-%2$d נוספים - פרקים %1$s פרק %1$s ו-%2$d נוספים פרק %1$s - - פרק אחד חדש - %1$d פרקים חדשים - %1$d פרקים חדשים - %1$d פרקים חדשים - - - עבור כותר אחד - עבור %d כותרים - עבור %d כותרים - עבור %d כותרים - נמצאו פרקים חדשים מחפש פרקים חדשים לא ניתן להוריד פרקים. אפשר לנסות שוב בדף ההורדות @@ -157,12 +133,6 @@ מאונך הסתר תוכן התראות מסך מאובטח מסתיר את תוכן האפליקציה בעת החלפת אפליקציות וחוסם צילומי מסך - - לאחר דקה אחת - לאחר שתי דקות - לאחר %1$s דקות - לאחר %1$s דקות - לעולם לא תמיד נעילה כאשר אינו פעיל @@ -410,12 +380,6 @@ ההרחבה הזאת לא נמצאת ברשימת ההרחבות הרשמיות של Tachiyomi. עלול להכיל תוכן שלא מתאים למקום העבודה (18+) מתקין הרחבה… - - קטגורייה אחת - שתי קטגוריות - %d קטגוריות - %d קטגוריות - כלול: %s הראה לזמן קצר כשפותחים את מצב הקריאה הראה מצב קריאה @@ -424,12 +388,6 @@ דלג על עדכוני פריטים נכשל בקבלת רשימת ההרחבות שו\"ת ומדריכים - - אתמול - לפני יומיים - לפני %1$d ימים - לפני %1$d ימים - 18+ אין כל 3 ימים @@ -490,12 +448,6 @@ מצב לא ידוע מורשה, בעל רישיון הפרסום הסתיים - - פרק אחד - שני פרקים - %1$s פרקים - %1$s פרקים - נכשלה ההעתקה ללוח לפי תאריך העלאה הכריכה נשמרה @@ -533,12 +485,6 @@ דפדפן לא נקרא קריאה - - 1 נשאר - 2 נשארו - %1$s נשארו - - התחברות נעוץ %02d דקות, %02d שניות @@ -558,12 +504,6 @@ עוצר את קריאת ההיסטוריה ביטול מצב פרטי הורדה - - הושלם ב %1$s עם שגיאה אחת - הושלם ב %1$s עם שתי שגיאות - הושלם ב %1$s עם %2$s שגיאות - - רשת בוטל/ה בתוך הספרייה @@ -606,12 +546,6 @@ דולג בגלל שאין פרקים שנקראו סגור דולגו - - דולג פרק אחד, המקור חסר או שהוא סונן החוצה - דולגו שני פרקים, המקור חסר או שהם סוננו החוצה - דולגו %d פרקים, המקור חסר או שהם סוננו החוצה - - מפחית פסים, אך עשוי להשפיע על הביצועים שגיאות אפס את הגדרות מצב הקריאה של כל סדרה בנפרד @@ -681,12 +615,6 @@ הורד קבצי קריסה, אופטימיזציה לסוללה לבנדר %d בכל שורה - - הפרק הבא - שני הפרקים הבאים - %d הפרקים הבאים - - לחץ כאן לעזרה עם Cloudflare עמוד %d לא נמצא בעת פיצול צפה בפריטי הספריה העדכניים ביותר @@ -701,12 +629,6 @@ מדריך וגיבויים אוטומטיים לא נמצאו פריטים בקטגוריה זו בסדר - - מעקב אחד - שני מעקבים - %d מעקבים - - ספריה עודכנה לאחרונה ב: %s שטח תמונה רחבה הסתר פריטים שכבר בספרייה @@ -797,27 +719,9 @@ תוקף אינדקס ההורדות בוטל מידע של WebView נוקה בהצלחה אפס מצב קריאה ואוריינטציה לכל הסדרות - - הפרק הבא שלא נקרא - שני הפרקים הבאים שלא נקראו - %d הפרקים הבאים שלא נקראו - - מידע דיבוג רישיונות מקורות פתוחים פופולרי - - יום אחד - יומיים - %d ימים - - - - חסר פרק אחד - חסרים שני פרקים - חסרים %1$s פרקים - - הוסף מעקב לחלק מהיצרנים יש הגבלות אפליקציה שהורגות תהליכים ברקע. באתר הזה יש עוד מידע לגבי איך לתקן את זה. פעולה זו תסיר את תאריך הסיום הקודם שלך מ-%s diff --git a/i18n/src/commonMain/resources/MR/hi/plurals.xml b/i18n/src/commonMain/resources/MR/hi/plurals.xml new file mode 100644 index 0000000000..d399e52c5e --- /dev/null +++ b/i18n/src/commonMain/resources/MR/hi/plurals.xml @@ -0,0 +1,63 @@ + + + + %1$s मिनट के बाद + %1$s मिनटो के बाद + + + %1$d नया अध्याय + %1$d नए अध्याय + + + अध्याय %1$s और 1 अधिक + अध्याय %1$s और %2$d अधिक + + + %d आइटम के लिए + %d आइटम के लिए + + + एक्सटेंशन अपडेट उपलब्ध + %d एक्सटेंशन अपडेट उपलब्ध + + + %1$s बचा हुआ + %1$s बचे हुए + + + %d श्रेणी + %d श्रेणियाँ + + + %1$s में %2$s त्रुटि के साथ किया गया + %1$s में %2$s त्रुटियों के साथ किया गया + + + अध्याय %1$s + %1$s अध्याय + + + %d ट्रैकर + %d ट्रैकरस + + + %d अध्याय को छोड़ा जा रहा है, या तो स्रोत में यह नहीं है या इसे फ़िल्टर कर दिया गया है + %d अध्यायों को छोड़ा जा रहा है, या तो स्रोत उन्हें याद कर रहा है या उन्हें फ़िल्टर कर दिया गया है + + + कल + %1$d दिन पहले + + + अगला अपठित अध्याय + अगले %d अपठित अध्याय + + + 1 दिन + %d दिन + + + अगला अध्याय + अगले %d अध्याय + + \ No newline at end of file diff --git a/i18n/src/main/res/values-hi/strings.xml b/i18n/src/commonMain/resources/MR/hi/strings.xml similarity index 95% rename from i18n/src/main/res/values-hi/strings.xml rename to i18n/src/commonMain/resources/MR/hi/strings.xml index 080f72fd4c..040bb7f722 100644 --- a/i18n/src/main/res/values-hi/strings.xml +++ b/i18n/src/commonMain/resources/MR/hi/strings.xml @@ -315,10 +315,6 @@ निष्क्रिय होने पर लॉक करें हमेशा कभी नहीँ - - %1$s मिनट के बाद - %1$s मिनटो के बाद - स्क्रीन सुरक्षित करें अपडेट लंबित हैं कटआउट क्षेत्र में सामग्री दिखाएं @@ -327,17 +323,9 @@ अध्याय अद्यतन सुरक्षित स्क्रीन एप्लिकेशन स्विच करते समय एप्लिकेशन सामग्री छिपाता हैं और स्क्रीनशॉट ब्लॉक करता हैं प्रदर्शन - - %1$d नया अध्याय - %1$d नए अध्याय - अध्याय %1$s अध्याय %1$s और %2$d अधिक अध्याय %1$s - - अध्याय %1$s और 1 अधिक - अध्याय %1$s और %2$d अधिक - अधिसूचना सामग्री छुपाएं नए अध्यायों के लिए जांच बैटरी अनुकूलन को अक्षम करना @@ -345,19 +333,11 @@ बैटरी अनुकूलन पहले से ही अक्षम है ईमेल पता हमेशा अध्याय संक्रमण दिखाएं - - %d आइटम के लिए - %d आइटम के लिए - मेन्यू नवीनतम सबसे पुराना शीर्ष पर ले जाएँ नीचे की ओर ले जाएं - - एक्सटेंशन अपडेट उपलब्ध - %d एक्सटेंशन अपडेट उपलब्ध - एक्सटेंशन अपडेट अद्यतन पुस्तकालय पठन @@ -389,23 +369,11 @@ स्थानीय स्रोत गाइड %02d मिनट,%02d सेकंड आपकी पुस्तकालय में सभी आइटम को फ़िल्टर करता है - - %1$s बचा हुआ - %1$s बचे हुए - पढ़न मोड इस श्रृंखला के लिए ग्रे बैंडिंग को कम करता है, लेकिन प्रदर्शन को प्रभावित कर सकता है - - %d श्रेणी - %d श्रेणियाँ - डिवाइस सेटिंग नहीं खोल सका - - %1$s में %2$s त्रुटि के साथ किया गया - %1$s में %2$s त्रुटियों के साथ किया गया - ट्रैकिंग सेवाओं में अध्याय की प्रगति को अद्यतन करने के लिए एकतरफा सिंक। अपने ट्रैकिंग बटन से व्यक्तिगत प्रविष्टियों के लिए ट्रैकिंग सेट अप करें। रिफ्रेश पुस्तकालय मंगा कवर यह एक्सटेंशन आधिकारिक ताचियोमी एक्सटेंशन सूची से नहीं है। @@ -429,10 +397,6 @@ स्रोत नहीं मिला बंद करें प्रारंभ - - अध्याय %1$s - %1$s अध्याय - नेटवर्क दोनों शीर्ष से असंतत @@ -449,10 +413,6 @@ पढ़न मोड थीम तारीख को जोड़ा गया - - %d ट्रैकर - %d ट्रैकरस - कोई पिन किया हुआ सोर्स नही है पूर्ण प्रगती @@ -463,10 +423,6 @@ इसमें NSFW (18+) सामग्री हो सकती है 18+ यह अनौपचारिक या संभावित रूप से फ़्लैग किए गए एक्सटेंशन को ऐप के भीतर NSFW (18+) सामग्री के सामने आने से नहीं रोकता है। - - %d अध्याय को छोड़ा जा रहा है, या तो स्रोत में यह नहीं है या इसे फ़िल्टर कर दिया गया है - %d अध्यायों को छोड़ा जा रहा है, या तो स्रोत उन्हें याद कर रहा है या उन्हें फ़िल्टर कर दिया गया है - अपडेट किए गए डिफ़ॉल्ट अध्याय सेटिंग्स कोई अध्याय नहीं मिला डिफ़ॉल्ट के रूप में सेट करें @@ -567,10 +523,6 @@ MIUI ऑप्टिमाइज़ेशन अक्षम होने पर बैकअप/पुनर्स्थापना ठीक से काम नहीं कर सकता है। पृष्ठभूमि गतिविधि कुछ निर्माताओं के पास अतिरिक्त ऐप प्रतिबंध हैं जो पृष्ठभूमि सेवाओं को मारते हैं। इस वेबसाइट में इसे ठीक करने के बारे में अधिक जानकारी है। - - कल - %1$d दिन पहले - अमान्य अध्याय प्रारूप के अनुसार ऑर्डर करें क्लिपबोर्ड पर कॉपी करने में विफल @@ -678,10 +630,6 @@ चूक यूजर एजेंट स्ट्रिंग (User agent string) आगे डाउनलोड करें पढ़ते समय ऑटो डाउनलोड करे - - अगला अपठित अध्याय - अगले %d अपठित अध्याय - सब कुछ हटा दें लोकप्रिय टाइडल वेव्ह @@ -733,14 +681,6 @@ डाउनलोड अनुक्रमणिका अमान्य ठीक है डाउनलोड अनुक्रमणिका अमान्य करें - - 1 दिन - %d दिन - - - अगला अध्याय - अगले %d अध्याय - क्लिपबोर्ड पर कॉपी हो गया है %s से भी हटा दें \ No newline at end of file diff --git a/i18n/src/commonMain/resources/MR/hr/plurals.xml b/i18n/src/commonMain/resources/MR/hr/plurals.xml new file mode 100644 index 0000000000..66fa95de15 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/hr/plurals.xml @@ -0,0 +1,83 @@ + + + + Nakon %1$s minute + Nakon %1$s minute + Nakon %1$s minuta + + + %d kategorija + %d kategorije + %d kategorija + + + Poglavlja %1$s i još jedno + Poglavlja %1$s i još %2$d + Poglavlja %1$s i još %2$d + + + Za %d stavku + Za %d stavke + Za %d stavku + + + %1$s preostalo + %1$s preostala + %1$s preostalih + + + Dostupna je %d nova verzija proširenja + Dostupne su %d nove verzije proširenja + Dostupno je %d novih verzija proširenja + + + %1$d novo poglavlje + %1$d nova poglavlja + %1$d novih poglavlja + + + Obavljeno u %1$s s %2$s greškom + Obavljeno u %1$s s %2$s greške + Obavljeno u %1$s s %2$s grešaka + + + %1$s poglavlje + %1$s poglavlja + %1$s poglavlja + + + %d usluga praćenja + %d usluge praćenja + %d usluga praćenja + + + Preskače se %d poglavlje. Ne postoji u izvoru ili je filtrirano + Preskaču se %d poglavlja. Ne postoje u izvoru ili su filtrirana + Preskače se %d poglavlja. Ne postoje u izvoru ili su filtrirana + + + Prije %1$d dan + Prije %1$d dana + Prije %1$d dana + + + Sljedeće nepročitano poglavlje + Sljedeća %d nepročitana poglavlja + Sljedećih %d nepročitanih poglavlja + + + Sljedeće poglavlje + Sljedeća %d poglavlja + Sljedećih %d poglavlja + + + Nedostaje %1$s poglavlje + Nedostaju %1$s poglavlja + Nedostaje %1$s poglavlja + + + %d dan + %d dana + %d dana + + \ No newline at end of file diff --git a/i18n/src/main/res/values-hr/strings.xml b/i18n/src/commonMain/resources/MR/hr/strings.xml similarity index 93% rename from i18n/src/main/res/values-hr/strings.xml rename to i18n/src/commonMain/resources/MR/hr/strings.xml index bcdf28a68d..4f4aa45325 100644 --- a/i18n/src/main/res/values-hr/strings.xml +++ b/i18n/src/commonMain/resources/MR/hr/strings.xml @@ -1,10 +1,5 @@ - - Nakon %1$s minute - Nakon %1$s minute - Nakon %1$s minuta - Nikada Uvijek Cjeloekranski prikaz @@ -27,11 +22,6 @@ Aktualiziraj Aktualiziranja na čekanju Sve - - %d kategorija - %d kategorije - %d kategorija - Uvijek pitaj Standardna kategorija Sa stanjem „Završeno“ @@ -247,19 +237,9 @@ Odaberi sliku naslovnice Prije toga, dodajte stavku u biblioteku Neuspjelo ažuriranje naslovnice - - Poglavlja %1$s i još jedno - Poglavlja %1$s i još %2$d - Poglavlja %1$s i još %2$d - Poglavlja %1$s Poglavlje %1$s i još %2$d Poglavlje %1$s - - Za %d stavku - Za %d stavke - Za %d stavku - Pronađena su nova poglavlja Traženje novih poglavlja Neuspjelo preuzimanje poglavlja. Pokušaj ponovo u odjeljku preuzimanja @@ -352,11 +332,6 @@ Adresa e-pošte Korisničko ime Prijavi se na %1$s - - %1$s preostalo - %1$s preostala - %1$s preostalih - Filtrira sve unose u biblioteci Samo preuzeto Pomaže pri ispravljanju grešaka. Ne šalju se nikoji privatni podaci @@ -388,17 +363,7 @@ Što želiš spremiti kao sigurnosnu kopiju\? Spremanje sigurnosne kopije je već u tijeku Neuspjelo zaobilaženje Cloudflare-a - - Dostupna je %d nova verzija proširenja - Dostupne su %d nove verzije proširenja - Dostupno je %d novih verzija proširenja - Za funkcioniranje programa je potreban WebView - - %1$d novo poglavlje - %1$d nova poglavlja - %1$d novih poglavlja - Ažuriranja proširenja Ažuriranja poglavlja Opće @@ -412,11 +377,6 @@ Aktualiziraj naslovnice biblioteke Po datumu prijenosa Podaci - - Obavljeno u %1$s s %2$s greškom - Obavljeno u %1$s s %2$s greške - Obavljeno u %1$s s %2$s grešaka - Nedostaju izvori: Sigurnosna kopija ne sadrži unose u biblioteci. Neispravna datoteka sigurnosne kopije @@ -437,11 +397,6 @@ Pokreni Deaktiviraj Izvor nije pronađen - - %1$s poglavlje - %1$s poglavlja - %1$s poglavlja - Zahtijeva ponovno pokretanje programa Umreženi rad Oboje @@ -458,11 +413,6 @@ Modus čitanja Tema Datum dodavanja - - %d usluga praćenja - %d usluge praćenja - %d usluga praćenja - Nemaš označenih izvora Gotovo Napredak @@ -473,11 +423,6 @@ 18+ Usluge praćenja bez prijave: To ne sprečava neslužbene ili potencijalno krivo označena proširenja prikazati neprikladan sadržaj (18+) unutar aplikacije. - - Preskače se %d poglavlje. Ne postoji u izvoru ili je filtrirano - Preskaču se %d poglavlja. Ne postoje u izvoru ili su filtrirana - Preskače se %d poglavlja. Ne postoje u izvoru ili su filtrirana - Nema poglavlja Standardne postavke poglavlja su aktualizirane %1$s: %2$s, %3$d. stranica @@ -576,11 +521,6 @@ Yotsuba Jin i Jang Invertirano - - Prije %1$d dan - Prije %1$d dana - Prije %1$d dana - Danas Potpuno crna tamna tema Strawberry Daiquiri @@ -660,11 +600,6 @@ Stranica %d nije pronađena tijekom rastavljanja RARv5 format nije podržan Radi samo ako je trenutačno i sljedeće poglavlje već preuzeto. - - Sljedeće nepročitano poglavlje - Sljedeća %d nepročitana poglavlja - Sljedećih %d nepročitanih poglavlja - Zadnja provjera aktualiziranja Samo na mrežom bez ograničenja Broj nepročitanih @@ -770,19 +705,9 @@ *obavezno Sakrij unose koji se već nalaze u biblioteci Kopiraj u međuspremnik - - Sljedeće poglavlje - Sljedeća %d poglavlja - Sljedećih %d poglavlja - Aktualiziraj katogoriju Rastavi visoke slike Oznake - - Nedostaje %1$s poglavlje - Nedostaju %1$s poglavlja - Nedostaje %1$s poglavlja - Prilagodi prikaz širokih stranica okretanjem Preokreni položaj širokih stranica Informacije o otklanjanju grešaka @@ -803,11 +728,6 @@ Intervali Ukloniti praćenje %s\? Preskočeno, jer se danas nije očekivalo izdanje - - %d dan - %d dana - %d dana - Ovo će ukloniti lokalno praćenje. Također ukloni iz %s Izbriši preuzete diff --git a/i18n/src/commonMain/resources/MR/hu/plurals.xml b/i18n/src/commonMain/resources/MR/hu/plurals.xml new file mode 100644 index 0000000000..1ed5bf5a5c --- /dev/null +++ b/i18n/src/commonMain/resources/MR/hu/plurals.xml @@ -0,0 +1,63 @@ + + + + Egy új bővítményfrissítés érhető el + %d bővítményfrissítés érhető el + + + 1 perc után + %1$s percek után + + + %d kategória + %d kategóriák + + + 1 fejezet + %1$s fejezet + + + 1 új fejezet + %1$d új fejezet + + + Tegnap + %1$d napja + + + %d tracker + %d trackerek + + + %d-nak/nek + %d-nak/nek + + + %d fejezet kihagyása, hiányzik a forrás, vagy ki lett szűrve + %d fejezet kihagyása, hiányoznak a források, vagy ki lettek szűrve + + + %1$s van hátra + %1$s van hátra + + + Befejezve %1$s alatt, %2$s hibával + Befejezve %1$s alatt, %2$s hibával + + + %1$s fejezet és még 1 + %1$s fejezet és még %2$d + + + Következő olvasatlan fejezet + Következő %d olvasatlan fejezet + + + Következő fejezet + Következő %d fejezetek + + + Hiányzó %1$s fejezet + Hiányzó %1$s fejezetek + + \ No newline at end of file diff --git a/i18n/src/main/res/values-hu/strings.xml b/i18n/src/commonMain/resources/MR/hu/strings.xml similarity index 95% rename from i18n/src/main/res/values-hu/strings.xml rename to i18n/src/commonMain/resources/MR/hu/strings.xml index a0fad7fd47..3d0cc6ccdd 100644 --- a/i18n/src/main/res/values-hu/strings.xml +++ b/i18n/src/commonMain/resources/MR/hu/strings.xml @@ -159,10 +159,6 @@ Egy váratlan hiba miatt nem sikerült letölteni a fejezetet Hiba A jobb kompatibilitás érdekében kérlek, frissítsd a WebView alkalmazást - - Egy új bővítményfrissítés érhető el - %d bővítményfrissítés érhető el - Új verzió érhető el! Letöltési hiba Érints meg a telepítéshez @@ -177,10 +173,6 @@ Kevesebb Értesítés tartalmának elrejtése Az alkalmazás tartalmának elrejtése az alkalmazások közötti váltáskor és a képernyőképek készítésének blokkolása - - 1 perc után - %1$s percek után - Mindig Biztonság Értesítések kezelése @@ -195,10 +187,6 @@ Nem hivatalos Elavult Függőben lévő frissítések - - %d kategória - %d kategóriák - Új borító és részletek keresése a könyvtár frissítésekor Metaadatokat frissítse automatikusan Minden frissítése @@ -229,10 +217,6 @@ Vágólapra másolva: \n%1$s Törli a kijelölt fejezeteket\? - - 1 fejezet - %1$s fejezet - Előző oldal Hiba Weboldal @@ -242,10 +226,6 @@ Manga a könyvtárból Előző %1$s. fejezet - - 1 új fejezet - %1$d új fejezet - Borító frissítve Beállítás borítóként Egyedi szűrő @@ -336,10 +316,6 @@ Kategóriakénti beállítások rendezéshez Polip Eper koktél - - Tegnap - %1$d napja - Ma Teljesen fekete sötét mód Yotsuba @@ -439,10 +415,6 @@ Egyirányú szinkronizálás, hogy a fejezetben való előrehaladás frissítve legyen a követési szolgáltatásokban. Állíts be követést egyéni bejegyzésekre, a követési gomb lenyomásával. 3 naponta Csak Wi-Fi-n keresztül - - %d tracker - %d trackerek - Ajánlott az automatikus biztonsági mentése. Ezen kívül máshol is legyenek másolatok. Nincs könyvtári elem, amit menteni lehetne Helyi forrás @@ -488,10 +460,6 @@ Gyorsítótár törölve: %1$d fájl lett törölve Hiba történt törlés közben Biztos benne\? Nem könyvtári elemek olvasott fejezetei elvesznek - - %d-nak/nek - %d-nak/nek - Nem található fájl választó alkalmazás Nincsenek még kategóriáid. Nem sikerült megkerülni a Cloudflare-t @@ -519,10 +487,6 @@ Jelentkezz be %1$s-ba/be Típus A forrás nem található - - %d fejezet kihagyása, hiányzik a forrás, vagy ki lett szűrve - %d fejezet kihagyása, hiányoznak a források, vagy ki lettek szűrve - Utolsó frissítés megtekintése Olvasatlanok száma Bejegyzés mutatása @@ -574,10 +538,6 @@ Feljegyzi a hibát egy fájlba, hogy meg lehessen osztani a fejlesztővel A biztonsági mentés nem tartalmaza a bejegyzéseket. Megszakított helyreállítás - - %1$s van hátra - %1$s van hátra - Letöltés Befejezett Nincs leírás @@ -638,10 +598,6 @@ Biztonsági mentés visszaállítása Könyvtár visszaállítása biztonsági mentésről Biztonsági mentések gyakorisága - - Befejezve %1$s alatt, %2$s hibával - Befejezve %1$s alatt, %2$s hibával - Biztonsági mentés helyreállítása Nem sikerült a biztonsági mentés helyreállítása Elemek törölve @@ -668,10 +624,6 @@ %d oldal nem található felosztás közben Nem található az útvonal a %d-ik oldalhoz Ez a kép legyen a fedlap\? - - %1$s fejezet és még 1 - %1$s fejezet és még %2$d - Biztonsági mentési fájl kiválasztása Alap hálózati kliens szöveg Alap hálózati kliens szöveg visszaállítása @@ -710,10 +662,6 @@ Egyirányú haladás szinkronizálás, fejlesztett szinkronizálás Manuális és automatikus biztonsági mentés Több - - Következő olvasatlan fejezet - Következő %d olvasatlan fejezet - Források, bővítmények, globális keresés Másolás a vágólapra Kategória frissítése @@ -728,18 +676,10 @@ Hoppá! Elérhető de a forrás nincs telepítve: %s Tárhely engedély nincs megadva - - Következő fejezet - Következő %d fejezetek - Használt %1$s error: %2$s Biztos vagy benne\? Kategória üres - - Hiányzó %1$s fejezet - Hiányzó %1$s fejezetek - Ez eltávolítja az eddig kiválasztott befejezési dátumot a/az %s Olvasási idő Nem található bejegyzés ebben a kategóriában diff --git a/i18n/src/commonMain/resources/MR/in/plurals.xml b/i18n/src/commonMain/resources/MR/in/plurals.xml new file mode 100644 index 0000000000..e661939a07 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/in/plurals.xml @@ -0,0 +1,51 @@ + + + + Setelah %1$s menit + + + %1$d bab baru + + + Bab %1$s dan %2$d lainnya + + + Untuk entri %d + + + Terdapat %d perbaruan ekstensi + + + %1$s lagi + + + %d kategori + + + Selesai dalam %1$s dengan %2$s kesalahan + + + %1$s bab + + + %d pelacak + + + Melewati %d bab, entah sumbernya hilang atau telah difilter + + + %1$d hari yang lalu + + + Selanjutnya chapter %d yang belum dibaca + + + berikutnya %d chapter + + + Bab %1$s yang hilang + + + %d hari + + \ No newline at end of file diff --git a/i18n/src/main/res/values-in/strings.xml b/i18n/src/commonMain/resources/MR/in/strings.xml similarity index 96% rename from i18n/src/main/res/values-in/strings.xml rename to i18n/src/commonMain/resources/MR/in/strings.xml index e3e72bc571..2424833ee9 100644 --- a/i18n/src/main/res/values-in/strings.xml +++ b/i18n/src/commonMain/resources/MR/in/strings.xml @@ -314,9 +314,6 @@ Kunci saat diam Selalu Tidak pernah - - Setelah %1$s menit - Pembaruan tertunda Tampilkan konten di area yang terpotong Sembunyikan konten aplikasi saat berpindah aplikasi dan blokir tangkapan layar @@ -335,26 +332,14 @@ Amankan layar Keluar dari %1$s\? Tampilan - - %1$d bab baru - Bab %1$s Bab %1$s dan %2$d lainnya Bab %1$s - - Bab %1$s dan %2$d lainnya - Membantu pembaruan pustaka dan pencadangan di latar belakang - - Untuk entri %d - Sumber Pembaruan ekstensi Membaca WebView diperlukan agar aplikasi dapat berfungsi - - Terdapat %d perbaruan ekstensi - Bab %1$s - %2$s Memperbarui pustaka Tambahkan pelacak @@ -376,9 +361,6 @@ Strip panjang dengan celah Petunjuk sumber lokal Terakhir digunakan - - %1$s lagi - Saring semua entri di perpustakaan Anda Periksa pembaruan Pemulihan dibatalkan @@ -387,16 +369,10 @@ %02d menit, %02d detik Mode membaca Mengurangi banding, namun berdampak pada performa - - %d kategori - Abu-abu Untuk seri ini Tidak dapat membuka pengaturan perangkat Muat ulang sampul pustaka - - Selesai dalam %1$s dengan %2$s kesalahan - Sinkronisasi satu arah untuk memperbarui kemajuan bab di layanan pelacak eksternal. Siapkan pelacakan untuk setiap entri dari tombol pelacaknya. Ekstensi ini bukan dari daftar resmi. Tidak resmi @@ -418,9 +394,6 @@ Tampilkan mode membaca Mulai Sumber tidak ditemukan - - %1$s bab - Mulai ulang aplikasi untuk menerapkan pengaturan Jaringan Matikan @@ -438,9 +411,6 @@ Mode membaca Tema Tanggal ditambahkan - - %d pelacak - Anda tidak memiliki sumber yang disematkan Lengkap Kemajuan @@ -451,9 +421,6 @@ Hapus bab yang ditandai Hapus bab Hal ini tidak mencegah ekstensi yang tidak resmi atau berpotensi salah ditandai untuk menampilkan konten NSFW (18+) di dalam aplikasi. - - Melewati %d bab, entah sumbernya hilang atau telah difilter - Tidak ada bab yang ditemukan Pengaturan bab bawaan diperbarui Tetapkan sebagai bawaan @@ -563,9 +530,6 @@ Tinggi Tertinggi Terbalik - - %1$d hari yang lalu - Hari Ini Panduan awal mulai Lacak @@ -672,9 +636,6 @@ Gelombang pasang Unduh di depan Unduh otomatis ketika sedang membaca - - Selanjutnya chapter %d yang belum dibaca - Hanya berfungsi jika bab saat ini + bab berikutnya sudah diunduh. Kamu akan menghapus \"%s\" dari pustaka Pustaka terakhir diperbarui: %s @@ -743,27 +704,18 @@ %1$seror%2$s *dibutuhkan Semua catatan tersembunyi sudah ada di perpustakaan - - berikutnya %d chapter - Salin ke papan klip Perbarui kategori Potong gambar tinggi Lapisan awal Memutar halaman lebar agar pas Orientasi balik halaman lebar yang diputar - - Bab %1$s yang hilang - Info debug Geser chapter Geser kekanan Geser kekiri Ketuk dua kali untuk memperbesar %d per baris - - %d hari - Tetapkan jeda waktu Interval pengambilan disesuaikan Ambil bulanan (28 hari) diff --git a/i18n/src/commonMain/resources/MR/it/plurals.xml b/i18n/src/commonMain/resources/MR/it/plurals.xml new file mode 100644 index 0000000000..29e0d9b291 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/it/plurals.xml @@ -0,0 +1,83 @@ + + + + Dopo %1$s minuto + Dopo %1$s minuti + Dopo %1$s minuti + + + Aggiornamento estensione disponibile + %d estensioni hanno aggiornamenti disponibili + %d estensioni hanno aggiornamenti disponibili + + + Capitoli %1$s e un altro + Capitoli %1$s e altri %2$d + Capitoli %1$s e altri %2$d + + + %1$d nuovo capitolo + %1$d nuovi capitoli + %1$d nuovi capitoli + + + Per %d voce + Per %d voci + Per %d voci + + + %1$s rimanente + %1$s rimanenti + %1$s rimanenti + + + Completato in %1$s con %2$s errore + Completato in %1$s con %2$s errori + Completato in %1$s con %2$s errori + + + %d categoria + %d categorie + %d categorie + + + %1$s capitolo + %1$s capitoli + %1$s capitoli + + + %d tracker + %d trackers + %d trackers + + + %d capitolo saltato, la fonte non ce l\'ha o è stato filtrato + %d capitoli saltati, la fonte non li ha o sono stati filtrati + %d capitoli saltati, la fonte non li ha o sono stati filtrati + + + Ieri + %1$d giorni fa + %1$d giorni fa + + + Il prossimo capitolo non letto + I prossimi %d capitoli non letti + I prossimi %d capitoli non letti + + + Prossimo capitolo + Prossimo %d capitoli + Prossimo %d capitoli + + + Manca %1$s capitolo + Mancano %1$s capitoli + Mancano %1$s capitoli + + + Un giorno + %d giorni + %d giorni + + \ No newline at end of file diff --git a/i18n/src/main/res/values-it/strings.xml b/i18n/src/commonMain/resources/MR/it/strings.xml similarity index 91% rename from i18n/src/main/res/values-it/strings.xml rename to i18n/src/commonMain/resources/MR/it/strings.xml index f4f86e7913..f9191305f5 100644 --- a/i18n/src/main/res/values-it/strings.xml +++ b/i18n/src/commonMain/resources/MR/it/strings.xml @@ -1,14 +1,12 @@ Nome - Impostazioni Coda download Libreria Cronologia Novità Backup e ripristino - Impostazioni Filtro Segnalibri @@ -48,16 +46,12 @@ Installa Condividi Salva - Caricamento… - - Generale Lettore Download Avanzate Info - Dimensione della griglia Verticale Orizzontale @@ -72,7 +66,6 @@ Quando si carica Con stato «Completata» Aggiorna il tracking dopo la lettura - Schermo Intero Animare le transizioni di pagina Mostra numero pagina @@ -109,7 +102,6 @@ G B A - Posizione dei download Dopo averli contrassegnati manualmente come letti Cancella automaticamente dopo la lettura @@ -121,9 +113,7 @@ Quartultimo capitolo letto Quintultimo capitolo letto Scarica nuovi capitoli - Servizi di tracking - Cancella cache capitoli Usati: %1$s Cache cancellata. %1$d file sono stati cancellati @@ -134,28 +124,20 @@ Elimina la cronologia delle voci che non sono presenti nella libreria Sei sicuro\? I capitoli letti e i progressi di lettura di voci fuori dalla libreria verranno persi Elementi eliminati - Versione - Invia segnalazioni crash Aiuta a correggere eventuali bug. Non verranno inviati dati sensibili - Accedi a %1$s Nome utente Password Accedi Accesso riuscito Errore sconosciuto - Aggiornamento categoria - - - In corso Sconosciuto Concesso in licenza Rimuovi dalla libreria - Capitolo %1$s Scaricando (%1$d/%2$d) Errore @@ -166,7 +148,6 @@ Scarica Non letti Sei sicuro di voler eliminare i capitoli selezionati\? - In lettura Completato Abbandonato @@ -176,14 +157,10 @@ Titolo Stato Capitoli - Esiste già una categoria con questo nome! - Questo rimuoverà la data lettura di questo capitolo. Sei sicuro\? Reimposta tutti i capitoli di questa voce - Immagine salvata - Filtro personalizzato Imposta come copertina Copertina aggiornata @@ -191,32 +168,22 @@ Capitolo successivo non trovato Non è stato possibile caricare l\'immagine Usare questa immagine come copertina\? - - - Impossibile scaricare i capitoli. Puoi riprovare nella sezione download - Nuovi capitoli trovati Impossibile aggiornare la copertina Prima di compiere questa azione per favore aggiungi la voce alla libreria - Seleziona immagine di copertina Seleziona file di backup - Scarica Non ci sono nuovi aggiornamenti disponibili - Download in corso… Tocca per installare l\'aggiornamento Errore di scaricamento Nuova versione disponibile! - - Nessun download Nessuna novità recente Nessuna lettura recente La tua libreria è vuota - Gestione Download Errore Impossibile scaricare il capitolo a causa di un errore imprevisto @@ -348,11 +315,6 @@ Blocca quando inattivo Sempre Mai - - Dopo %1$s minuto - Dopo %1$s minuti - Dopo %1$s minuti - Schermo sicuro Aggiornamenti in sospeso Mostra il contenuto dell\'area ritagliata @@ -362,29 +324,9 @@ Schermo sicuro nasconde i contenuti dell\'app quando cambi applicazione e blocca gli screenshot Visualizzazione Aggiornamenti estensione - - Aggiornamento estensione disponibile - %d estensioni hanno aggiornamenti disponibili - %d estensioni hanno aggiornamenti disponibili - - - Capitoli %1$s e un altro - Capitoli %1$s e altri %2$d - Capitoli %1$s e altri %2$d - Capitoli %1$s Capitolo %1$s e altri %2$d Capitolo %1$s - - %1$d nuovo capitolo - %1$d nuovi capitoli - %1$d nuovi capitoli - - - Per %d voce - Per %d voci - Per %d voci - Cercando nuovi capitoli Indirizzo e-mail Ottimizzazione batteria già disattivata @@ -426,28 +368,13 @@ Per questa serie Guida alle fonti locali Ultimo usato - - %1$s rimanente - %1$s rimanenti - %1$s rimanenti - Filtra tutte le voci nella tua libreria Controlla aggiornamenti Impossibile aprire le impostazioni del dispositivo Aggiorna le copertine della libreria - - Completato in %1$s con %2$s errore - Completato in %1$s con %2$s errori - Completato in %1$s con %2$s errori - %02d min, %02d sec Sincronizzazione a senso unico per aggiornare l\'avanzamento dei capitoli sui servizi di tracking. Imposta il tracking per le singole voci dai loro pulsanti di tracking. Riduce il banding, ma potrebbe influire sulle prestazioni - - %d categoria - %d categorie - %d categorie - Grigio Nessuna pagina trovata Per data di aggiunta @@ -471,11 +398,6 @@ Nessuno Inverti le zone di tocco Fonte non trovata - - %1$s capitolo - %1$s capitoli - %1$s capitoli - Stato sconosciuto Autore sconosciuto Aggiornato alla v%1$s @@ -491,11 +413,6 @@ Modalità di lettura Tema Data di aggiunta - - %d tracker - %d trackers - %d trackers - Progresso Errori Completo @@ -504,11 +421,6 @@ Elimina capitoli Fonti di questa estensione potrebbero contenere materiale NSFW (18+) 18+ - - %d capitolo saltato, la fonte non ce l\'ha o è stato filtrato - %d capitoli saltati, la fonte non li ha o sono stati filtrati - %d capitoli saltati, la fonte non li ha o sono stati filtrati - Tracker non collegati: Nessun capitolo trovato Questo non impedisce a estensioni non ufficiali oppure incorrettamente segnalate di mostrare contenuti 18+ all\'interno dell\'applicazione. @@ -607,11 +519,6 @@ Più alto Sensibilità per nascondere il menù allo scorrimento Inversa - - Ieri - %1$d giorni fa - %1$d giorni fa - Oggi Modalità scura con nero puro Yotsuba @@ -728,11 +635,6 @@ La sringa «user agent» non può essere vuota Maremoto Scarica i prossimi - - Il prossimo capitolo non letto - I prossimi %d capitoli non letti - I prossimi %d capitoli non letti - Download automatico durante la lettura Funziona se il capitolo corrente e quello successivo sono già stati scaricati. Sei sicuro\? @@ -801,11 +703,6 @@ \nVuoi comunque continuare\? %1$s errore: %2$s *obbligatorio - - Prossimo capitolo - Prossimo %d capitoli - Prossimo %d capitoli - Nascondi le voci già in libreria Copia negli appunti Aggiorna categoria @@ -813,11 +710,6 @@ Sovrimpressione Ruota le pagine larghe per adattarle allo schermo Capovolgi l\'orientamento delle pagine larghe ruotate - - Manca %1$s capitolo - Mancano %1$s capitoli - Mancano %1$s capitoli - Informazioni di debug Scorrimento capitolo Doppio tocco per ingrandire @@ -830,11 +722,6 @@ Fuori dal periodo di rilascio previsto Personalizza intervallo Intervalli - - Un giorno - %d giorni - %d giorni - Stima ogni Intervallo di recupero personalizzato Periodo di controllo superato diff --git a/i18n/src/commonMain/resources/MR/ja/plurals.xml b/i18n/src/commonMain/resources/MR/ja/plurals.xml new file mode 100644 index 0000000000..8c6bfcfacb --- /dev/null +++ b/i18n/src/commonMain/resources/MR/ja/plurals.xml @@ -0,0 +1,51 @@ + + + + %1$s分後 + + + %1$d新しい章 + + + 残り%1$s件 + + + %1$sで完成済み %2$s件のエラーが発生しました + + + %d件のカテゴリー + + + %d件の拡張機能の更新が利用可能 + + + 第%1$s章とその他%2$d章 + + + %d件の項目 + + + %1$s章 + + + %d個のトラッカー + + + ソースには存在しないか、フィルターによって排除されたため、%d章がスキップされました + + + %1$d日前 + + + 次の未読の%d章 + + + 次の%d章 + + + %1$s章が欠けています + + + %d日 + + \ No newline at end of file diff --git a/i18n/src/main/res/values-ja/strings.xml b/i18n/src/commonMain/resources/MR/ja/strings.xml similarity index 96% rename from i18n/src/main/res/values-ja/strings.xml rename to i18n/src/commonMain/resources/MR/ja/strings.xml index 22c76b21f6..e78c821612 100644 --- a/i18n/src/main/res/values-ja/strings.xml +++ b/i18n/src/commonMain/resources/MR/ja/strings.xml @@ -310,22 +310,13 @@ タイムアウトロック 常時 しない - - %1$s分後 - セキュア画面 - - %1$d新しい章 - 第%1$s章 最新 ソース ローカルソース タブ メールアドレス - - 残り%1$s件 - ライブラリにある項目はフィルターされます ダウンロード済みのみ 更新を確認 @@ -342,9 +333,6 @@ 既に復元中です バックアップできませんでした 既にバックアップ中です - - %1$sで完成済み %2$s件のエラーが発生しました - %02d分%02d秒 ソースがありません: バックアップにはライブラリの項目が含まれません。 @@ -364,9 +352,6 @@ この拡張機能は公式リストに含まれていません。 非公式 更新あり - - %d件のカテゴリー - ライブラリを更新時、新しい表紙と情報を確認します メタデータを自動で更新 グリッドの項目数 @@ -388,23 +373,14 @@ 章の更新 WebViewアプリを更新して互換性を向上させてください WebViewが必要です - - %d件の拡張機能の更新が利用可能 - 新しい章を確認中 ライブラリを更新中 ビューアモード 詳細を非表示 拡張機能の更新 Cloudflareをバイパスできませんでした - - 第%1$s章とその他%2$d章 - 第%1$s章とその他%2$d章 第%1$s章 - - %d件の項目 - 第%1$s章 - %2$s ページが見つかりません このシリーズでは @@ -419,9 +395,6 @@ 現在のビューアモードを、ビューアが立ち上がるとしばらく表示します ビューアモードを表示 ソースが見つかりませんでした - - %1$s章 - 無効化 開始 両方 @@ -439,9 +412,6 @@ 完了 プログレス 空き領域不足のため、章をダウンロードできませんでした - - %d個のトラッカー - ピンソースがありません グローバルで「%1$s」を探す テーマ @@ -453,9 +423,6 @@ この拡張機能のソースには成人向けのコンテンツが含まれる可能性があります 成人向け 非公式や誤ってフラグ付けされた可能性のある拡張機能の成人向けのコンテンツはこれからも表示される恐れがあります。 - - ソースには存在しないか、フィルターによって排除されたため、%d章がスキップされました - 章が見つかりません デフォルトの章設定を更新しました %1$s: %2$s、第%3$dページ @@ -562,9 +529,6 @@ 高い 最高 反転配色 - - %1$d日前 - 今日 翻訳に協力 入門ガイド @@ -672,9 +636,6 @@ 津波 事前ダウンロード 読書中に自動でダウンロード - - 次の未読の%d章 - 現在のと次の章は既にダウンロード済みの場合のみ有効です 本当に実行しますか? 多言語 @@ -744,17 +705,11 @@ *必須 クリップボードにコピー ライブラリにある項目を非表示 - - 次の%d章 - カテゴリを更新 長い画像を分割 オーバーレイ 画面に合わせるように幅広いページを回転 回転した幅広いページの向きを反転 - - %1$s章が欠けています - デバッグ情報 左へスワイプ時の操作 右へスワイプ時の操作 @@ -767,9 +722,6 @@ 次の更新予定 更新予定時間外 間隔 - - %d日 - 今日、連載更新が予想されていないためスキップしました 間隔を設定 結果あり diff --git a/i18n/src/commonMain/resources/MR/jv/plurals.xml b/i18n/src/commonMain/resources/MR/jv/plurals.xml new file mode 100644 index 0000000000..e06b9c6b69 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/jv/plurals.xml @@ -0,0 +1,12 @@ + + + + %1$d dinten kala-wingi + + + Sawise %1$s menit + + + %d kategori + + \ No newline at end of file diff --git a/i18n/src/main/res/values-jv/strings.xml b/i18n/src/commonMain/resources/MR/jv/strings.xml similarity index 98% rename from i18n/src/main/res/values-jv/strings.xml rename to i18n/src/commonMain/resources/MR/jv/strings.xml index 6f33de6b80..743d80f424 100644 --- a/i18n/src/main/res/values-jv/strings.xml +++ b/i18n/src/commonMain/resources/MR/jv/strings.xml @@ -180,18 +180,12 @@ Takon jawab lan panduan Iki ora nyegah ekstensi kang ora resmi utawa salah dilabeli kanggo nampilake konten NSFW (18+) ing aplikasi. Dinten puniki - - %1$d dinten kala-wingi - Mati Kaamanan Tansah Sumber NSFW (18+) Tampilaken ing sumber lan dhaptar ekstensi Karo bab durung diwaca - - Sawise %1$s menit - Kelola notifikasi Amanaken layar sembunikan konten aplikasi wektu ngaleh aplikasi lan blokir tangkapan layar Surup wengi @@ -206,9 +200,6 @@ Amanaken layar Saben 3 dinten Namung ing Wi-Fi - - %d kategori - Ora kapracaya Iku durung diwiwiti periksa sampul lan rinci anyar wektu memerbarui pustaka diff --git a/i18n/src/commonMain/resources/MR/ka-rGE/plurals.xml b/i18n/src/commonMain/resources/MR/ka-rGE/plurals.xml new file mode 100644 index 0000000000..4eec3c155f --- /dev/null +++ b/i18n/src/commonMain/resources/MR/ka-rGE/plurals.xml @@ -0,0 +1,39 @@ + + + + ნაპოვნია გაფართოების განახლება + ნაპოვნია %d გაფართოების განახლება + + + თავები %1$s და კიდევ 1 + თავები %1$s და კიდევ %2$d + + + ნაპოვნია ახალი თავი + ნაპოვნია %1$d ახალი თავი + + + %d ჩანაწერისთვის + %d ჩანაწერისთვის + + + 1 თავი + %1$s თავი + + + დარჩა 1 + დარჩა %1$s + + + დასრულების დრო %1$s. %2$s შეცდომა + დასრულების დრო %1$s. %2$s შეცდომა + + + %d კატეგორია + %d კატეგორიები + + + 1 წუთის შემდეგ + %1$s წუთის შემდეგ + + \ No newline at end of file diff --git a/i18n/src/main/res/values-ka-rGE/strings.xml b/i18n/src/commonMain/resources/MR/ka-rGE/strings.xml similarity index 95% rename from i18n/src/main/res/values-ka-rGE/strings.xml rename to i18n/src/commonMain/resources/MR/ka-rGE/strings.xml index 874be7bdd6..a34b277fce 100644 --- a/i18n/src/main/res/values-ka-rGE/strings.xml +++ b/i18n/src/commonMain/resources/MR/ka-rGE/strings.xml @@ -399,52 +399,16 @@ ჰორიზონტალური არცერთი დაჭერის ინვერსია - - ნაპოვნია გაფართოების განახლება - ნაპოვნია %d გაფართოების განახლება - - - თავები %1$s და კიდევ 1 - თავები %1$s და კიდევ %2$d - - - ნაპოვნია ახალი თავი - ნაპოვნია %1$d ახალი თავი - - - %d ჩანაწერისთვის - %d ჩანაწერისთვის - შეუძლებელია თავების გადმოწერა დისკზე ადგილის უკმარისობის გამო წყარო ვერ მოიძებნა - - 1 თავი - %1$s თავი - უცნობი სტატუსი უცნობი ავტორი მოიძებნოს \"%1$s\"-თვის გლობალურად - - დარჩა 1 - დარჩა %1$s - განახლებულია v%1$s-მდე რა არის ახალი ასამოქმედებლად საჭიროა აპლიკაციის გადატვირთვა ქსელი - - დასრულების დრო %1$s. %2$s შეცდომა - დასრულების დრო %1$s. %2$s შეცდომა - კითხვის რეჟიმი - - %d კატეგორია - %d კატეგორიები - - - 1 წუთის შემდეგ - %1$s წუთის შემდეგ - თემა გამორთვა დაწყება diff --git a/i18n/src/commonMain/resources/MR/kk/plurals.xml b/i18n/src/commonMain/resources/MR/kk/plurals.xml new file mode 100644 index 0000000000..e5edb4f2dc --- /dev/null +++ b/i18n/src/commonMain/resources/MR/kk/plurals.xml @@ -0,0 +1,63 @@ + + + + Кеше + %1$d күн бұрын + + + %1$s минуттан кейін + %1$s минуттан кейін + + + %d санат + %d санаттар + + + %1$s дегеннен кейін %2$s қателікпен орындалды + %1$s дегеннен кейін %2$s қателікпен орындалды + + + Келесі оқылмаған тарау + Келесі %d оқылмаған тарау + + + %1$s тарау қалды + %1$s тарау қалды + + + %d бақылау + %d бақылаулар + + + %1$s тарау + %1$s тарау + + + %1$s тарау және біреу + %1$s тарау мен %2$d + + + Дереккөзі жоқ немесе сүзілген %d тарау өткізіліп жіберілді + Дереккөзі жоқ немесе сүзілген %d тарау өткізіліп жіберілді + + + %1$d жаңа тарау + %1$d жаңа тарау + + + Кеңейту үшін жаңарту бар + %d кеңейту үшін жаңарту бар + + + %d жазбасы үшін + %d жазбасы үшін + + + Келесі тарау + Келесі %d тарау + + + + Жоқ %1$s тараулары + + \ No newline at end of file diff --git a/i18n/src/main/res/values-kk/strings.xml b/i18n/src/commonMain/resources/MR/kk/strings.xml similarity index 95% rename from i18n/src/main/res/values-kk/strings.xml rename to i18n/src/commonMain/resources/MR/kk/strings.xml index ad9b5e4351..6721346ce2 100644 --- a/i18n/src/main/res/values-kk/strings.xml +++ b/i18n/src/commonMain/resources/MR/kk/strings.xml @@ -39,10 +39,6 @@ Бет (солдан оңға қарай) Санаттарыңыз жоқ. Жаңа санат жасау үшін және кітапханаңызды ұйымдастыру үшін қосу батырмасын басыңыз. Келесі - - Кеше - %1$d күн бұрын - Соңғы жаңартуды тексеру Оқылмаған тараулар Тізім @@ -83,10 +79,6 @@ Тек Wi-Fi болғанда Қуаттандыру кездінде Шектеулер: %s - - %1$s минуттан кейін - %1$s минуттан кейін - Қауіпсіз экран қолданбаларды ауыстырған кезде қолданба мазмұнын жасырады және скриншот жасауды бұғаттайды NSFW (18+) дереккөздері Дереккөздер мен кеңейтулер тізімінде көрсету @@ -232,10 +224,6 @@ Жарықты сүзу режимі Оқылмаған тарау(лар)мен «Аяқталған» күйімен - - %d санат - %d санаттар - Қос бетті бөлуді инверттеу Ықшам кесте Оқыма ашылғаннан кейін оқу түрін қысқаша көрсету @@ -328,10 +316,6 @@ К Ақ %02d мин, %02d сек - - %1$s дегеннен кейін %2$s қателікпен орындалды - %1$s дегеннен кейін %2$s қателікпен орындалды - Тараулардың ауысуын әрдайым көрсету Құлыпталған портрет Жоғары @@ -376,10 +360,6 @@ Екеуі де Оқыманың өнімділігін жақсартады Кең суретті басқанда панорамалау - - Келесі оқылмаған тарау - Келесі %d оқылмаған тарау - L тәріздес Іздеу… Айналдырғандағы мәзірді жасыру сезгіштігі @@ -444,10 +424,6 @@ Сақтық көшірмесін қалпына келтіру Сақтық көшірмесі әлдеқашан орындалуда Оқыма баптауы қалпына келтірілмеді - - %1$s тарау қалды - %1$s тарау қалды - Оқыманың барлық баптауы қалпына келді Не жаңалық Аудармамен көмектесу @@ -533,24 +509,12 @@ Оқылуда Тараулар жоқ Сенімдісіз бе\? - - %d бақылау - %d бақылаулар - Оқылмаған Кітапхана жаңаруда Ақырғы оқылған тарау ашылмай тұр Кітапхананың ақырғы жаңаруы: %s Дереккөз табылмады RARv5 пішімі қолжетімсіз - - %1$s тарау - %1$s тарау - - - %1$s тарау және біреу - %1$s тарау мен %2$d - MyAnimeList-ке қайтадан кіріңіз Ұқсастық табылмады Дереккөз қолжетімсіз @@ -564,10 +528,6 @@ Жаңа нұсқа қолжетімді! %d бет табылмады, бөлінгенде Аяқталды - - Дереккөзі жоқ немесе сүзілген %d тарау өткізіліп жіберілді - Дереккөзі жоқ немесе сүзілген %d тарау өткізіліп жіберілді - Оқу түрі, көрсету, навигация Дереккөздер, кеңейтулер, ауқымды іздеу Қолданбаны бұғаттау, экранды қорғау @@ -582,10 +542,6 @@ Мұқаба жіберілмеді Мұқаба сақталды Бұл баптауды әдепкі қылып сақтағыңыз келеді ме\? - - %1$d жаңа тарау - %1$d жаңа тарау - Көбірек білу үшін басу Жүктеп алу Ортақ @@ -637,10 +593,6 @@ Туынды аяқталған үшін өткізіп жіберілді GitHub-та ашу Бұл Android нұсқасы қолжетімсіз - - Кеңейту үшін жаңарту бар - %d кеңейту үшін жаңарту бар - Белгісіз қателіктің кесірінен тарау жүктеп алынбады Бет файлының жолы %d табылмады Өткізуп жіберілді @@ -689,10 +641,6 @@ Биометриялық бұғаттау қосылып тұрғанда виджет қолжетімді емес Жеке сүзгі Көп жаңалтулар саны дереккөздер жұмысын баяулата және батарея жұмысын өтімін көбейте алады. Көбірек білу үшін басыңыз. - - %d жазбасы үшін - %d жазбасы үшін - %1$s-Тарау Ескерту: Көп жүктеулер саны дереккөздер жұмысын баяулата алады және/немесе Tachiyomi бұғатталына алады. Толығырақ оқу үшін басыңыз. Жаңа тараулар табылды @@ -756,10 +704,6 @@ %1$s қателік: %2$s *қажетті Санатты жаңарту - - Келесі тарау - Келесі %d тарау - Айырбастау буферіне көшіріп алу Кітапханада бар туындыларды жасыру Ұзын суреттерді бөлу @@ -767,8 +711,4 @@ Кең беттерді сыйғызу үшін бұрыңыз Бұрылған кең беттерді аудару бағдары Дебаг туралы ақпарат - - - Жоқ %1$s тараулары - \ No newline at end of file diff --git a/i18n/src/commonMain/resources/MR/km/plurals.xml b/i18n/src/commonMain/resources/MR/km/plurals.xml new file mode 100644 index 0000000000..d11a96e548 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/km/plurals.xml @@ -0,0 +1,9 @@ + + + + %1$d ថ្ងៃមុន + + + %d ភាគបន្ទាប់ដែលមិនទាន់អាន + + \ No newline at end of file diff --git a/i18n/src/main/res/values-km/strings.xml b/i18n/src/commonMain/resources/MR/km/strings.xml similarity index 98% rename from i18n/src/main/res/values-km/strings.xml rename to i18n/src/commonMain/resources/MR/km/strings.xml index 85cbee0ce6..16626c1d4e 100644 --- a/i18n/src/main/res/values-km/strings.xml +++ b/i18n/src/commonMain/resources/MR/km/strings.xml @@ -142,9 +142,6 @@ ប្រភពមិនល្អ(១៨+) បង្ហាញនៅក្នុងបញ្ចីប្រភព ថ្ងៃនេះ - - %1$d ថ្ងៃមុន - ការបង្ហាញ ធាតុក្នុងមួយជួ បញ្ឈរ @@ -186,9 +183,6 @@ ម​គ្គុ​ទេស​ក៍​ ស្វែងរក ទាំងអស់ - - %d ភាគបន្ទាប់ដែលមិនទាន់អាន - កំពុងទាញយក… ស្ថិតិ បានទាញយក diff --git a/i18n/src/commonMain/resources/MR/kn/plurals.xml b/i18n/src/commonMain/resources/MR/kn/plurals.xml new file mode 100644 index 0000000000..4dc9745333 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/kn/plurals.xml @@ -0,0 +1,47 @@ + + + + 1 ನಿಮಿಷದ ನಂತರ + %1$s ನಿಮಿಷಗಳ ನಂತರ + + + %2$s ದೋಷದೊಂದಿಗೆ %1$s ನಲ್ಲಿ ಮುಗಿದಿದೆ + %2$s ದೋಷಗಳೊಂದಿಗೆ %1$s ನಲ್ಲಿ ಮುಗಿದಿದೆ + + + %d ವರ್ಗ + %d ವರ್ಗಗಳು + + + ವಿಸ್ತರಣೆ ನವೀಕರಣ ಲಭ್ಯವಿದೆ + %d ವಿಸ್ತರಣೆ ನವೀಕರಣಗಳು ಲಭ್ಯವಿದೆ + + + ಅಧ್ಯಾಯಗಳು %1$s ಮತ್ತು 1 ಹೆಚ್ಚು + ಅಧ್ಯಾಯಗಳು %1$s ಮತ್ತು %2$d ಹೆಚ್ಚು + + + 1 ಹೊಸ ಅಧ್ಯಾಯ + %1$d ಹೊಸ ಅಧ್ಯಾಯಗಳು + + + 1 ಶೀರ್ಷಿಕೆಗಾಗಿ + %d ಶೀರ್ಷಿಕೆಗಳಿಗಾಗಿ + + + 1 ಉಳಿದಿದೆ + %1$s ಉಳಿದಿದೆ + + + 1 ಚಾಪ್ಟರ್ + %1$s ಚಾಪ್ಟರಗಳು + + + 1 ಟ್ರಾಕರ್ + %d ಟ್ರಾಕರ್ ಗಳು + + + 1 ಅಧ್ಯಾಯ ಕಾಣೆಯಾಗಿದೆ + %d ಅಧ್ಯಾಯ ಕಾಣೆಯಾಗಿವೆ + + \ No newline at end of file diff --git a/i18n/src/main/res/values-kn/strings.xml b/i18n/src/commonMain/resources/MR/kn/strings.xml similarity index 95% rename from i18n/src/main/res/values-kn/strings.xml rename to i18n/src/commonMain/resources/MR/kn/strings.xml index ec5f2f09b4..8e7407d7ba 100644 --- a/i18n/src/main/res/values-kn/strings.xml +++ b/i18n/src/commonMain/resources/MR/kn/strings.xml @@ -7,10 +7,6 @@ ಸೂಚನೆ ವಿಷಯವನ್ನು ಮರೆಮಾಡಿ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಬದಲಾಯಿಸುವಾಗ ಮತ್ತು ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳನ್ನು ನಿರ್ಬಂಧಿಸುವಾಗ ಅಪ್ಲಿಕೇಶನ್ ವಿಷಯಗಳನ್ನು ಮರೆಮಾಡಿ ಸುರಕ್ಷಿತ ಪುಟ - - 1 ನಿಮಿಷದ ನಂತರ - %1$s ನಿಮಿಷಗಳ ನಂತರ - ಎಂದಿಗೂ ಇಲ್ಲ ಯಾವಾಗಲೂ ನಿಷ್ಕ್ರಿಯವಾಗಿದ್ದಾಗ ಲಾಕ್ ಮಾಡಿ @@ -116,10 +112,6 @@ ಸಂಯೋಜನೆಗಳು ಇನ್ನಷ್ಟು ಹೆಸರು - - %2$s ದೋಷದೊಂದಿಗೆ %1$s ನಲ್ಲಿ ಮುಗಿದಿದೆ - %2$s ದೋಷಗಳೊಂದಿಗೆ %1$s ನಲ್ಲಿ ಮುಗಿದಿದೆ - %02d ನಿಮಿಷ, %02d ಸೆಕೆಂಡು ಮರುಸ್ಥಾಪನೆ ಪೂರ್ಣಗೊಂಡಿದೆ ಬ್ಯಾಕಪ್ ರಚಿಸಲಾಗಿದೆ @@ -223,10 +215,6 @@ ನವೀಕರಿಸಿ ಬಾಕಿ ಉಳಿದಿರುವ ನವೀಕರಣಗಳು ಎಲ್ಲಾ - - %d ವರ್ಗ - %d ವರ್ಗಗಳು - ಯಾವಾಗಲೂ ಕೇಳಿ ಡೀಫಾಲ್ಟ್ ವರ್ಗ ಚಾಲ್ತಿಯಿರುವ ಮಾಂಗಾವನ್ನು ಮಾತ್ರ ನವೀಕರಿಸಿ @@ -252,10 +240,6 @@ ಉತ್ತಮ ಹೊಂದಾಣಿಕೆಗಾಗಿ ದಯವಿಟ್ಟು ವೆಬ್‌ವೀಕ್ಷಣೆ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ನವೀಕರಿಸಿ ತಚಿಯೋಮಿಗೆ ವೆಬ್‌ವೀಕ್ಷಣೆ ಅಗತ್ಯವಿದೆ ಕ್ಲೌಡ್‌ಫ್ಲೇರ್ ಅನ್ನು ಬೈಪಾಸ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ - - ವಿಸ್ತರಣೆ ನವೀಕರಣ ಲಭ್ಯವಿದೆ - %d ವಿಸ್ತರಣೆ ನವೀಕರಣಗಳು ಲಭ್ಯವಿದೆ - ಹೊಸ ಆವೃತ್ತಿ ಲಭ್ಯವಿದೆ! ಡೌನ್‌ಲೋಡ್ ದೋಷ ಡೌನ್‌ಲೋಡ್ ಪೂರ್ಣಗೊಂಡಿದೆ @@ -266,21 +250,9 @@ ಕವರ್ ಇಮೇಜ್ ಆಯ್ಕೆಮಾಡಿ ಇದನ್ನು ಮಾಡುವ ಮೊದಲು ದಯವಿಟ್ಟು ನಿಮ್ಮ ಗ್ರಂಥಾಲಯಕ್ಕೆ ಮಾಂಗಾವನ್ನು ಸೇರಿಸಿ ಕವರ್ ನವೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ - - ಅಧ್ಯಾಯಗಳು %1$s ಮತ್ತು 1 ಹೆಚ್ಚು - ಅಧ್ಯಾಯಗಳು %1$s ಮತ್ತು %2$d ಹೆಚ್ಚು - ಅಧ್ಯಾಯಗಳು %1$s ಅಧ್ಯಾಯ %1$s ಮತ್ತು %2$d ಹೆಚ್ಚು ಅಧ್ಯಾಯ %1$s - - 1 ಹೊಸ ಅಧ್ಯಾಯ - %1$d ಹೊಸ ಅಧ್ಯಾಯಗಳು - - - 1 ಶೀರ್ಷಿಕೆಗಾಗಿ - %d ಶೀರ್ಷಿಕೆಗಳಿಗಾಗಿ - ಹೊಸ ಅಧ್ಯಾಯಗಳು ಕಂಡುಬಂದಿವೆ ಹೊಸ ಅಧ್ಯಾಯಗಳಿಗಾಗಿ ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ ಅಧ್ಯಾಯಗಳನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ಡೌನ್‌ಲೋಡ್‌ಗಳ ವಿಭಾಗದಲ್ಲಿ ನೀವು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಬಹುದು @@ -373,10 +345,6 @@ ಇಮೇಲ್ ವಿಳಾಸ ಬಳಕೆದಾರ ಹೆಸರು %1$s ಗೆ ಲಾಗ್ ಇನ್ ಮಾಡಿ - - 1 ಉಳಿದಿದೆ - %1$s ಉಳಿದಿದೆ - ನಿಮ್ಮ ಗ್ರಂಥಾಲಯದ ಎಲ್ಲಾ ಮಾಂಗಾವನ್ನು ಫಿಲ್ಟರ್ ಮಾಡುತ್ತದೆ ಡೌನ್ಲೋಡ್ ಮಾಡಿದ ಯಾವುದೇ ದೋಷಗಳನ್ನು ಸರಿಪಡಿಸಲು ಸಹಾಯ ಮಾಡುತ್ತದೆ. ಯಾವುದೇ ಸೂಕ್ಷ್ಮ ಡೇಟಾವನ್ನು ಕಳುಹಿಸಲಾಗುವುದಿಲ್ಲ @@ -435,10 +403,6 @@ ಯಾವುದು ಅಲ್ಲ ಟ್ಯಾಪಿಂಗ ಅನ್ನು ತಿರುಗಿಸಿ ಕಡಿಮೆ ಶೇಖರಣಾ ಸ್ಥಳದ ಕಾರಣ ಅಧ್ಯಾಯಗಳನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ - - 1 ಚಾಪ್ಟರ್ - %1$s ಚಾಪ್ಟರಗಳು - ಅಜ್ಞಾತ ಸ್ಥಿತಿ ಅಜ್ಞಾತ ಲೇಖಕ \"%1$s\" ಅನ್ನು ಗ್ಲೋಬಲ್ ಸರ್ಚ್ ಮಾಡಿ @@ -449,20 +413,12 @@ ಓದುವ ಮೊಡ್ ಜನರಲ್ ಸೆಲೆಕ್ಷನ್ ಹಾಕಿದ್ದ ದಿನಾಂಕ - - 1 ಟ್ರಾಕರ್ - %d ಟ್ರಾಕರ್ ಗಳು - ಯಾವುದೆ ಪಿನ್ ಮಾಡಿರುವ ಸೋರ್ಸ್ ಗಳು ಇಲ್ಲ ಪೂರ್ಣ ಪ್ರಗತಿ ಇದು ಅನಧಿಕೃತ ಮತ್ತು ತಪ್ಪಾಗಿ ಚಿಹ್ನಿಸಿದ ವಿಸ್ತರಣೆಗಳಿಂದ 18+ ಮೂಲಗಳನ್ನು ಮರೆಮಾಚಲಾಗುವುದಿಲ್ಲ. ದೋಷಗಳು ಅಧ್ಯಾಯದ ಡೀಫಾಲ್ಟ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ನವೀಕರಿಸಲಾಗಿದೆ - - 1 ಅಧ್ಯಾಯ ಕಾಣೆಯಾಗಿದೆ - %d ಅಧ್ಯಾಯ ಕಾಣೆಯಾಗಿವೆ - %1$s: %2$s, ಪುಟ %3$d ಯಾವುದೇ ಅಧ್ಯಾಯಗಳು ಕಂಡುಬಂದಿಲ್ಲ ಡೀಫಾಲ್ಟ್ ಆಗಿ ಹೊಂದಿಸಿ diff --git a/i18n/src/commonMain/resources/MR/ko/plurals.xml b/i18n/src/commonMain/resources/MR/ko/plurals.xml new file mode 100644 index 0000000000..03c6fcff6c --- /dev/null +++ b/i18n/src/commonMain/resources/MR/ko/plurals.xml @@ -0,0 +1,51 @@ + + + + %1$s 개 남음 + + + 총 %1$s화 + + + %1$d일 전 + + + 소요 시간: %1$s, 발생한 오류: %2$s + + + %1$s분 후 + + + 항목 %d개 + + + %d개의 트래커 + + + 소스에 존재하지 않거나 필터링되어 있는 %d개의 회차를 건너뛰었습니다 + + + %d개의 확장 앱 업데이트가 있습니다 + + + %d개의 항목 + + + %1$d개의 새로운 회차 + + + %1$s화와 그 외 %2$d화 + + + 읽지 않은 다음 %d 회차 + + + 다음 %d화 + + + 누락된 회차 %1$s개 + + + %d일 + + \ No newline at end of file diff --git a/i18n/src/main/res/values-ko/strings.xml b/i18n/src/commonMain/resources/MR/ko/strings.xml similarity index 96% rename from i18n/src/main/res/values-ko/strings.xml rename to i18n/src/commonMain/resources/MR/ko/strings.xml index ee976315de..371f76e508 100644 --- a/i18n/src/main/res/values-ko/strings.xml +++ b/i18n/src/commonMain/resources/MR/ko/strings.xml @@ -303,9 +303,6 @@ 로그아웃 되었습니다 로그아웃 %1$s 에서 로그아웃 하시겠습니까\? - - %1$s 개 남음 - 시크릿 모드 끄기 다운로드가 완료된 항목만 표시 시크릿 모드 @@ -366,9 +363,6 @@ 빈 공간 채우기 회차 변경 항상 표시 작가 미상 - - 총 %1$s화 - 읽기 모드 업데이트 내역 마지막으로 사용 @@ -383,9 +377,6 @@ 현재 만화에만 적용 읽기 모드 서재의 모든 항목에 적용됩니다 - - %1$d일 전 - 모서리 여백 앱 정보 초기 설정 도움말 @@ -399,9 +390,6 @@ 서재 서재에 추가 CBZ 파일로 저장 - - 소요 시간: %1$s, 발생한 오류: %2$s - 항목 업데이트 건너뛰기 화면 보안을 켜면 앱을 전환할 때 내용이 숨겨지며 스크린샷을 찍을 수 없습니다 서재에 추가됨 @@ -413,18 +401,12 @@ 오늘 전역 업데이트 보안 및 개인정보 보호 - - %1$s분 후 - 항상 끄기 자동 잠금 알림 내용 숨기기 제외된 카테고리 세로 (거꾸로 보기) - - 항목 %d개 - Wi-Fi 에서만 활성화 서재 업데이트 중 @@ -485,17 +467,11 @@ 상세정보 표시 상세정보 숨김 클립보드로 복사에 실패하였습니다 - - %d개의 트래커 - 트래커 추가 일시정지 MAL에 다시 로그인해 주세요 소스를 찾을 수 없습니다 페이지를 찾을 수 없습니다 - - 소스에 존재하지 않거나 필터링되어 있는 %d개의 회차를 건너뛰었습니다 - 내역 삭제 기록이 삭제되었습니다 저장 공간이 부족하여 회차를 다운로드 할 수 없습니다 @@ -509,9 +485,6 @@ 완결된 만화를 건너 뛰었습니다 읽지 않은 만화를 건너 뛰었습니다 이 안드로이드 버전은 더이상 지원되지 않습니다 - - %d개의 확장 앱 업데이트가 있습니다 - Cloudflare를 통과하지 못했습니다 Tachiyomi 앱의 기능을 사용하려면 WebView가 필요합니다 호환성을 위해 WebView 어플리케이션을 업데이트 해 주세요 @@ -581,12 +554,6 @@ 정렬 읽기 시작한 날짜 다 읽은 날짜 - - %d개의 항목 - - - %1$d개의 새로운 회차 - 읽지 않은 회차가 있는 만화를 건너 뛰었습니다 등록된 카테고리가 없습니다. 항목 제목에 따라 폴더 생성 @@ -620,9 +587,6 @@ 서재 업데이트 시 새로운 표지와 설명 확인 %1$s화와 그 외 %2$d화 %1$s화 - - %1$s화와 그 외 %2$d화 - 파일 선택 어플리케이션이 없습니다 백업할 서재 항목이 없습니다 새로운 공식 업데이트가 있습니다. F-Droid의 비공식 버전에서 이전을 원하시면 터치해서 방법을 확인하세요. @@ -674,9 +638,6 @@ 다언어 서재에서 \"%s\"을(를) 제거하려고 합니다 저장공간 사용 권한이 없음 - - 읽지 않은 다음 %d 회차 - 읽을 때 자동 다운로드 마지막 서재 업데이트: %s 현재 회차 + 다음 회차가 이미 다운로드된 경우에만 작동됩니다. @@ -744,26 +705,17 @@ *필수 클립보드에 복사 이미 서재에 있는 항목 숨기기 - - 다음 %d화 - 카테고리 업데이트 긴 이미지 분할 오버레이 화면에 맞게 넓은 페이지 회전 회전된 넓은 페이지의 회전 방향 - - 누락된 회차 %1$s개 - 디버그 정보 행당 %d개 왼쪽으로 스와이프 액션 오른쪽으로 스와이프 액션 회차 스와이프 두 번 탭하여 줌 - - %d일 - 간격 설정 사용자 지정 가져오기 간격 매월 가져오기 (28일) diff --git a/i18n/src/commonMain/resources/MR/lt/plurals.xml b/i18n/src/commonMain/resources/MR/lt/plurals.xml new file mode 100644 index 0000000000..5fa7faf23a --- /dev/null +++ b/i18n/src/commonMain/resources/MR/lt/plurals.xml @@ -0,0 +1,68 @@ + + + + Vakar + Prieš %1$d dienas + Prieš %1$d dienų + + + Po %1$s minutės + Po %1$s minučių + Po %1$s minučių + + + %d kategorija + %d kategorijos + %d kategorijos + + + Skyrius %1$s ir 1 daugiau + Skyriai %1$s ir %2$d daugiau + Skyriai %1$s ir %2$d daugiau + + + %1$d naujas skyrius + %1$d nauji skyriai + %1$d nauji skyriai + + + Atlikta %1$s su %2$s klaida + Atlikta %1$s su %2$s klaidomis + Atlikta %1$s su %2$s klaidomis + + + %d įrašui + %d įrašams + %d įrašų + + + %d plėtinio atnaujinimas pasiekiamas + %d plėtinių atnaujinimai pasiekiami + %d plėtinių atnaujinimai pasiekiami + + + %1$s skyrius + %1$s skyriai + %1$s skyriai + + + Liko vienas + Liko %1$s + Liko %1$s + + + %d stebėjimo įrenginys + %d stebėjimo įrenginiai + %d stebėjimo įrenginių + + + Praleidžiamas %d skyrius, arba jo nėra šaltinyje, arba jis buvo nepasirinktas + Praleidžiami %d skyriai, arba jų nėra šaltinyje, arba jie buvo nepasirinkti + Praleidžiamia %d skyrių, arba jų nėra šaltinyje, arba jie buvo nepasirinkti + + + Kitas neskaitytas skyrius + Kiti %d neskaityti skyriai + Kiti %d neskaitytų skyrių + + \ No newline at end of file diff --git a/i18n/src/main/res/values-lt/strings.xml b/i18n/src/commonMain/resources/MR/lt/strings.xml similarity index 94% rename from i18n/src/main/res/values-lt/strings.xml rename to i18n/src/commonMain/resources/MR/lt/strings.xml index 792cfab3b6..92c7f2bf24 100644 --- a/i18n/src/main/res/values-lt/strings.xml +++ b/i18n/src/commonMain/resources/MR/lt/strings.xml @@ -46,11 +46,6 @@ Portretas Elementai eilutėje Rodinys - - Vakar - Prieš %1$d dienas - Prieš %1$d dienų - Šiandien Tai nesustabdo neoficialių ar potencialiai neteisingai pažymėtų plėtinių nuo N18+ turinio rodymo programoje. Rodyti šaltiniuose ir plėtinių sąrašuose @@ -58,11 +53,6 @@ Slėpti pranešimo turinį Slėpti programos turinį, kai įjungiama kita programa ir neleisti daryti ekrano nuotraukų Saugus užraktas - - Po %1$s minutės - Po %1$s minučių - Po %1$s minučių - Niekada Visada Užrakinti kai neveiksnus @@ -221,11 +211,6 @@ Nėra Visi Įrašai, kurie yra įtraukti į neįtraukiamas kategorijas, nebus atnaujinami, net jei yra įtraukti į įtrauktąsias kategorijas. - - %d kategorija - %d kategorijos - %d kategorijos - Atsiuntimo klaida Nauja versija pasiekiama! Pagal aukštį talpinimas @@ -356,11 +341,6 @@ Paskiausiai skaitytas skyrius Įrašai neįtrauktose kategorijose nebus atsisiųsti, net jei jie taip pat yra įtraukti į kategorijas. Palieskite, kad sužinotumėte daugiau - - Skyrius %1$s ir 1 daugiau - Skyriai %1$s ir %2$d daugiau - Skyriai %1$s ir %2$d daugiau - Pasirinkti atsarginės kopijos failą Įkeliami puslapiai… Kito skyriaus nėra @@ -370,11 +350,6 @@ Atnaujinama biblioteka Atnaujinkite „WebView“ programą dėl geresnio suderinamumo Skyrius %1$s - - %1$d naujas skyrius - %1$d nauji skyriai - %1$d nauji skyriai - Istorija ištrinta Nepavyko pakrauti paveikslėlio Puslapių nerasta @@ -476,11 +451,6 @@ Tinklo ryšis nepasiekiamas Nepavyko atsisiųsti skyriaus dėl netikėtos klaidos Valdiklis nepasiekiamas, kai įjungtas programėlės užraktas - - Atlikta %1$s su %2$s klaida - Atlikta %1$s su %2$s klaidomis - Atlikta %1$s su %2$s klaidomis - Peržiūrėkite neseniai atnaujintus bibliotekos įrašus Talpykla išvalyta. %1$d failai buvo ištrinti Išvalyti duomenų bazę @@ -513,18 +483,8 @@ Iš naujo nustatyti kiekvienos serijos skaitytuvo nustatymus Išmeskite strigčių žurnalus Nepavyko atsisiųsti skyrių. Galite pabandyti dar kartą atsisiųsti - - %d įrašui - %d įrašams - %d įrašų - Numatytoji vartotojo agento eilutė Neįdiegtas - - %d plėtinio atnaujinimas pasiekiamas - %d plėtinių atnaujinimai pasiekiami - %d plėtinių atnaujinimai pasiekiami - Atnaujinti numatytus skyrių nustatymus Parsisiuntėjas Klaida @@ -622,11 +582,6 @@ Nežinomas autorius Nežinoma būsena Nebepublikuojamas - - %1$s skyrius - %1$s skyriai - %1$s skyriai - Nėra aprašymo Inkognito režimas Naršyti @@ -656,17 +611,7 @@ Sulaikytas Norimų sąrašas Pilnas sąrašas - - Liko vienas - Liko %1$s - Liko %1$s - Pavadinimas - - %d stebėjimo įrenginys - %d stebėjimo įrenginiai - %d stebėjimo įrenginių - Klaidą išsaugojant paveikslą Būsena Rezultatas @@ -677,11 +622,6 @@ Būsena Užlaikytų sąrašas Nebaigtų sąrašas - - Praleidžiamas %d skyrius, arba jo nėra šaltinyje, arba jis buvo nepasirinktas - Praleidžiami %d skyriai, arba jų nėra šaltinyje, arba jie buvo nepasirinkti - Praleidžiamia %d skyrių, arba jų nėra šaltinyje, arba jie buvo nepasirinkti - %1$s: %2$s, puslapis %3$d Kitas skyrius nerastas Šaltinis nerastas @@ -693,11 +633,6 @@ Įdiegtų šaltinių nerasta Potvynio banga Ieškoti… - - Kitas neskaitytas skyrius - Kiti %d neskaityti skyriai - Kiti %d neskaitytų skyrių - Vartotojo agento eilutė negali būti tuščia Atnaujinimas jau vykdomas Biblioteka paskutinį kartą atnaujinta: %s diff --git a/i18n/src/commonMain/resources/MR/lv/plurals.xml b/i18n/src/commonMain/resources/MR/lv/plurals.xml new file mode 100644 index 0000000000..9ee680f4a9 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/lv/plurals.xml @@ -0,0 +1,83 @@ + + + + Pabeigts %1$s ar %2$s kļūdām + Pabeigts %1$s ar %2$s kļūdu + Pabeigts %1$s ar %2$s kļūdām + + + Pēc %1$s minūtēm + Pēc %1$s minūtes + Pēc %1$s minūtēm + + + %d kategoriju + %d kategorija + %d kategorijas + + + Šodien + Vakar + Pirms %1$d dienām + + + %1$s atlikušas + %1$s atlikusi + %1$s atlikušas + + + %d izsekotāju + %d izsekotājs + %d izsekotāji + + + Priekš %d ierakstiem + Priekš %d ieraksta + Priekš %d ierakstiem + + + Izlaisti %d nodaļu, vai nu to nav avotā, vai arī tie ir izfiltrēti + Izlaists %d nodaļa, vai nu tā nav avotā, vai arī tā ir izfiltrēta + Izlaistas %d nodaļas, vai nu tās nav avotā, vai arī tās ir izfiltrētas + + + %1$d jaunu nodaļu + %1$d jauna nodaļa + %1$d jaunas nodaļas + + + %1$s nodaļu + %1$s nodaļa + %1$s nodaļas + + + Pieejami %d paplašinājumi atjaunināšanai + Pieejams %d paplašinājums atjaunināšanai + Pieejami %d paplašinājumi atjaunināšanai + + + Nodaļu %1$s + Nodaļa %1$s un vēl 1 + Nodaļa %1$s un vēl %2$d + + + Trūkst %1$s nodaļu + Trūkst %1$s nodaļa + Trūkst %1$s nodaļas + + + Nākošā %d nodaļa + Nākošā %d nodaļa + Nākošās %d nodaļās + + + Nākamā nelasītā nodaļa + Nākamā nelasītā nodaļa + Nākamās %d nelasītas nodaļas + + + %d dienas + %d diena + %d dienas + + \ No newline at end of file diff --git a/i18n/src/main/res/values-lv/strings.xml b/i18n/src/commonMain/resources/MR/lv/strings.xml similarity index 93% rename from i18n/src/main/res/values-lv/strings.xml rename to i18n/src/commonMain/resources/MR/lv/strings.xml index 1aea15e5c8..e1686922c7 100644 --- a/i18n/src/main/res/values-lv/strings.xml +++ b/i18n/src/commonMain/resources/MR/lv/strings.xml @@ -79,11 +79,6 @@ Izveido dublējumu Ko vēlaties dublēt\? Dublēšana jau notiek - - Pabeigts %1$s ar %2$s kļūdām - Pabeigts %1$s ar %2$s kļūdu - Pabeigts %1$s ar %2$s kļūdām - %02d min, %02d sec Atjaunošana pabeigta Trūkstošie avoti: @@ -134,11 +129,6 @@ Slēpt paziņojumu saturu Drošs ekrāns paslēpj saturu mainot lietotnes, un bloķē ekrānuzņēmumus Drošs ekrāns - - Pēc %1$s minūtēm - Pēc %1$s minūtes - Pēc %1$s minūtēm - Nekad Vienmēr Bloķēt, ja dīkstāvē @@ -214,18 +204,8 @@ NSFW (18+) avoti Rādīt avotos un paplašinājumu sarakstos Izslēgts - - %d kategoriju - %d kategorija - %d kategorijas - Valoda Nodaļas ieneses datums - - Šodien - Vakar - Pirms %1$d dienām - Izlaist ierakstu atjaunināšanu Biežāk uzdotie jautājumi un rokasgrāmatas Aizvērt @@ -488,11 +468,6 @@ Lejupielādētās nodaļas Izslēgt inkognito režīmu Atjaunina kategoriju - - %1$s atlikušas - %1$s atlikusi - %1$s atlikušas - Piektā pirmspēdējā izlasītā nodaļa Globālā meklēšana… Neizdevās apiet Cloudflare @@ -528,11 +503,6 @@ Nezināms statuss Publicēšana pabeigta Izsekošana - - %d izsekotāju - %d izsekotājs - %d izsekotāji - Neizdevās atjaunināt vāku Izlaists, jo sērija ir pabeigta Nevar atrast lapas %d faila ceļu @@ -554,11 +524,6 @@ Vai izmantot šo attēlu kā vāku\? Priekš šīs sērijas Pamests - - Priekš %d ierakstiem - Priekš %d ieraksta - Priekš %d ierakstiem - Brīdinājums: liela apjoma lejupielāde var izraisīt to, ka avoti kļūst lēnāki un/vai bloķē Tachiyomi. Pieskarieties, lai uzzinātu vairāk. Izlaists, jo neviena nodaļa nav izlasīta Atlasiet vāka attēlu @@ -599,21 +564,11 @@ \n%1$s Kļūda saglabājot vāku Lasīšanas saraksts - - Izlaisti %d nodaļu, vai nu to nav avotā, vai arī tie ir izfiltrēti - Izlaists %d nodaļa, vai nu tā nav avotā, vai arī tā ir izfiltrēta - Izlaistas %d nodaļas, vai nu tās nav avotā, vai arī tās ir izfiltrētas - Nodaļas %1$s Atrastas jaunas nodaļas Nodaļa %1$s un vēl %2$d Nav atrasta failu atlases programma Lūdzu, pievienojiet ierakstu savai bibliotēkai, pirms to darāt - - %1$d jaunu nodaļu - %1$d jauna nodaļa - %1$d jaunas nodaļas - Nodaļa %1$s Sadalīšanas laikā netika atrasta lapa %d Izlaists, jo ir nelasītas nodaļas @@ -630,26 +585,11 @@ Vai dzēst lejupielādētās nodaļas\? Datums Pārtraukumā - - %1$s nodaļu - %1$s nodaļa - %1$s nodaļas - - - Pieejami %d paplašinājumi atjaunināšanai - Pieejams %d paplašinājums atjaunināšanai - Pieejami %d paplašinājumi atjaunināšanai - Nodaļa %1$s Vāks saglabāts Vai esat pārliecināts\? Visa vēsture tiks pazaudēta. Nav atrasts avots Neviens instalēts avots nav atrasts - - Nodaļu %1$s - Nodaļa %1$s un vēl 1 - Nodaļa %1$s un vēl %2$d - Pieskarieties, lai instalētu atjauninājumu Pielāgots vāks Nepabeigto saraksts @@ -741,16 +681,6 @@ %dh InternalError: Par plašāku informāciju skatiet avārijas žurnālu Vai vēlaties dzēst kategoriju \"%s\"\? - - Trūkst %1$s nodaļu - Trūkst %1$s nodaļa - Trūkst %1$s nodaļas - - - Nākošā %d nodaļa - Nākošā %d nodaļa - Nākošās %d nodaļās - %1$s kļūda: %2$s Atjauninājums jau darbojas %s radās neparedzēta kļūda. Mēs iesakām dalīties ar avārijas žurnālu mūsu atbalsta kanālā Discord lietotnē. @@ -762,11 +692,6 @@ Kategorija ir tukša Skatiet savus nesen atjauninātos bibliotēkas ierakstus Jūs gatavojaties noņemt \"%s\" no savas bibliotēkas - - Nākamā nelasītā nodaļa - Nākamā nelasītā nodaļa - Nākamās %d nelasītas nodaļas - Ne tagad Meklē… F-Droid versijas netiek oficiāli atbalstītas. @@ -805,11 +730,6 @@ Sinhronizē bibliotēku Bibliotēkas sinhronizācija ir pabeigta Intervāli - - %d dienas - %d diena - %d dienas - Šis noņems locālo izsekošanu. Izdzēst lejupielādētos Vai noņemt %s izsekošanu\? diff --git a/i18n/src/commonMain/resources/MR/mr/plurals.xml b/i18n/src/commonMain/resources/MR/mr/plurals.xml new file mode 100644 index 0000000000..92dab4cd2c --- /dev/null +++ b/i18n/src/commonMain/resources/MR/mr/plurals.xml @@ -0,0 +1,11 @@ + + + + %d श्रेणी + %d श्रेण्या + + + 1 मिनीटानंतर + %1$s मिनीटांनंतर + + \ No newline at end of file diff --git a/i18n/src/main/res/values-mr/strings.xml b/i18n/src/commonMain/resources/MR/mr/strings.xml similarity index 97% rename from i18n/src/main/res/values-mr/strings.xml rename to i18n/src/commonMain/resources/MR/mr/strings.xml index 9ae0f9de65..b3c2c1d29e 100644 --- a/i18n/src/main/res/values-mr/strings.xml +++ b/i18n/src/commonMain/resources/MR/mr/strings.xml @@ -86,15 +86,7 @@ व्यस्त निवडा जागतिक शोध अ‍ॅप्स स्विच करताना अॅप मधील सामग्री लपवा व स्क्रीनशॉट अवरोधित करा - - %d श्रेणी - %d श्रेण्या - स्क्रीन सुरक्षित करा - - 1 मिनीटानंतर - %1$s मिनीटांनंतर - कधीही नाही नेहमी निष्क्रिय झाल्यावर लॉक करा diff --git a/i18n/src/commonMain/resources/MR/ms/plurals.xml b/i18n/src/commonMain/resources/MR/ms/plurals.xml new file mode 100644 index 0000000000..ea46560d96 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/ms/plurals.xml @@ -0,0 +1,51 @@ + + + + Selepas %1$s minit + + + %1$d bab baharu + + + Bab %1$s dan %2$d lagi + + + Untuk entri %d + + + %d kemas kini sambungan tersedia + + + %1$s baki + + + %d kategori + + + Selesai dalam %1$s dengan %2$s ralat + + + Jumlah bab: %1$s + + + %d penjejak + + + Melangkau %d bab, sama ada sumber tidak mempunyai bab tersebut, atau ia ditapis keluar + + + %1$d hari lalu + + + %d bab tidak dibaca seterusnya + + + %d bab seterusnya + + + Hilang %1$s bab + + + %d hari + + \ No newline at end of file diff --git a/i18n/src/main/res/values-ms/strings.xml b/i18n/src/commonMain/resources/MR/ms/strings.xml similarity index 96% rename from i18n/src/main/res/values-ms/strings.xml rename to i18n/src/commonMain/resources/MR/ms/strings.xml index f90cabf8ad..1cb6c1a599 100644 --- a/i18n/src/main/res/values-ms/strings.xml +++ b/i18n/src/commonMain/resources/MR/ms/strings.xml @@ -315,9 +315,6 @@ Kunci apabila terbiar Selalu Tidak - - Selepas %1$s minit - Skrin keselamatan Kemas kini baharu Tunjuk kandungan dalam kawasan bertakuk @@ -326,15 +323,9 @@ Pengemaskinian bab Skrin keselamatan menyembunyikan kandungan aplikasi apabila menukar aplikasi dan sekat tangkapan skrin Paparan - - %1$d bab baharu - Bab %1$s Bab %1$s dan %2$d lagi Bab %1$s - - Bab %1$s dan %2$d lagi - Sembunyikan kandungan pemberitahuan Mencari bab baharu Nyahdaya pengoptimuman bateri @@ -342,17 +333,11 @@ Pengoptimuman bateri sudah dinyahdayakan Alamat e-mel Sentiasa tunjuk peralihan bab - - Untuk entri %d - Menu Terbaru Terlama Naik ke atas Turun ke bawah - - %d kemas kini sambungan tersedia - Kemas kini sambungan Mengemas kini pustaka Membaca @@ -384,20 +369,11 @@ Panduan penggunaan sumber setempat %02d minit, %02d saat Tapis semua entri di dalam pustaka anda - - %1$s baki - Kelabu Mod membaca Untuk siri ini Kurangkan jalinan, tapi memberi kesan kepada prestasi - - %d kategori - Tetapan peranti tidak dapat dibuka - - Selesai dalam %1$s dengan %2$s ralat - Menyelaras satu hala untuk kemas kini bab kemajuan dalam sistem penjejakan. Sediakan penjejakan untuk entri individu daripada butang penjejakan mereka. Segar semula muka hadapan pustaka Mengikut tarikh muat naik @@ -420,9 +396,6 @@ Tunjuk mod membaca Sumber tidak dijumpai Mula - - Jumlah bab: %1$s - Matikan Mulakan semula aplikasi diperlukan untuk berkesan Rangkaian @@ -440,9 +413,6 @@ Cari untuk \"%1$s\" menggunakan carian keseluruhan Mod membaca Tema - - %d penjejak - Tiada sumber yang disematkan Kemajuan Selesai @@ -453,9 +423,6 @@ Sumber daripada sambungan ini mungkin mengandungi kandungan 18+ tahun keatas 18+ Ini tidak menghalang sambungan yang tidak rasmi atau berpotensi tidak menggunakan tetapan yang betul daripada menayangkan kandungan 18+ tahun keatas dalam aplikasi. - - Melangkau %d bab, sama ada sumber tidak mempunyai bab tersebut, atau ia ditapis keluar - Tiada bab dijumpai Tetapan bab lalai dikemas kini Tetapkan sebagai lalai @@ -565,9 +532,6 @@ Sensitiviti menyembunyikan menu apabila skrol Aktiviti latar belakang Songsang - - %1$d hari lalu - Hari ini Teal & Turquoise Sahkan untuk mengesahkan perubahan @@ -673,9 +637,6 @@ Tidal Wave Muat turun maju Hanya berguna sekiranya bab sekarang + seterusnya telah dimuat turun. - - %d bab tidak dibaca seterusnya - Adakah anda pasti\? Pelbagai Terakhir pustaka dikemas kini: %s @@ -742,17 +703,11 @@ \n \nAdakah anda ingin meneruskan\? *diperlukan - - %d bab seterusnya - Sembunyikan entri yang sudah ada di dalam pustaka Salin ke papan keratan Kemas kini kategori Memisah imej yang tinggi Tindanan - - Hilang %1$s bab - Terbalikkan orientasi muka surat lebar yang diputarkan Putar muka surat lebar agar muat Maklumat nyahpepijat @@ -770,9 +725,6 @@ Tetapkan untuk kemas kini setiap Dilangkau kerana tiada keluaran yang dijangkakan hari ini Jarak masa - - %d hari - Tersuai jarak masa Diluar jangkaan masa keluaran Anggaran setiap diff --git a/i18n/src/commonMain/resources/MR/nb-rNO/plurals.xml b/i18n/src/commonMain/resources/MR/nb-rNO/plurals.xml new file mode 100644 index 0000000000..26ad5c366f --- /dev/null +++ b/i18n/src/commonMain/resources/MR/nb-rNO/plurals.xml @@ -0,0 +1,67 @@ + + + + Etter %1$s minutt + Etter %1$s minutter + + + %d kategori + %d kateogrier + + + %1$d nytt kapittel + %1$d nye kapitler + + + For %d oppføring + For %d oppføringer + + + %1$s kapittel + %1$s kapitler + + + %1$s gjenstående + %1$s gjenstående + + + Gjort på %1$s med %2$s feil + Gjort på %1$s med %2$s feil + + + %d tracker + %d trackere + + + Hopper over %d kapittel, enten så mangler kilden den eller så har den blitt filtrert ut + Hopper over %d kapitler, enten så mangler kilden de eller så har de blitt filtrert ut + + + Utvidelsesoppdatering tilgjengelig + %d utvidelsesoppdateringer tilgjengelige + + + Kapittel %1$s og 1 til + Kapitler %1$s og %2$d til + + + I går + %1$d dager siden + + + Neste uleste kapittel + Neste %d uleste kapitler + + + Neste kapittel + Neste %d kapitler + + + Mangler %1$s kapittel + Mangler %1$s kapitler + + + %d dag + %d dager + + \ No newline at end of file diff --git a/i18n/src/main/res/values-nb-rNO/strings.xml b/i18n/src/commonMain/resources/MR/nb-rNO/strings.xml similarity index 94% rename from i18n/src/main/res/values-nb-rNO/strings.xml rename to i18n/src/commonMain/resources/MR/nb-rNO/strings.xml index 038c4d66a8..71d9d6e9ca 100644 --- a/i18n/src/main/res/values-nb-rNO/strings.xml +++ b/i18n/src/commonMain/resources/MR/nb-rNO/strings.xml @@ -314,10 +314,6 @@ Lås ved lediggang Alltid Aldri - - Etter %1$s minutt - Etter %1$s minutter - Sikker skjerm Kapitteloppdateringer Kapittel %1$s @@ -359,10 +355,6 @@ %02d min, %02d sek Manglende kilder: Grå - - %d kategori - %d kateogrier - Vis kategorifaner Komfortabelt rutenett Flytt @@ -371,28 +363,12 @@ Loddrett vannrett Ingen - - %1$d nytt kapittel - %1$d nye kapitler - - - For %d oppføring - For %d oppføringer - Søker etter nye kapitler Kilden ikke funnet For denne serien - - %1$s kapittel - %1$s kapitler - Ukjent status Ukjent forfatter Lokal kildeguide - - %1$s gjenstående - %1$s gjenstående - Filtrerer alle oppføringer i biblioteket ditt Se etter oppdateringer Kunne ikke åpne enhetens innstillinger @@ -403,10 +379,6 @@ Nettverk Avbrutt gjenoppretting Gjenoppretting allerede underveis - - Gjort på %1$s med %2$s feil - Gjort på %1$s med %2$s feil - Vis lesemodus Denne utvidelsen kommer ikke fra den offisielle listen. deaktivere @@ -441,26 +413,10 @@ Kapittelinnstillinger Sett som standard Fant ingen kapitler - - %d tracker - %d trackere - - - Hopper over %d kapittel, enten så mangler kilden den eller så har den blitt filtrert ut - Hopper over %d kapitler, enten så mangler kilden de eller så har de blitt filtrert ut - Oppdater WebView-programmet for bedre kompabilitet Oppdaterte standard kapittelinnstillinger Er du sikker på at du vil lagre disse innstillingene som standard\? Søkeinnstillinger - - Utvidelsesoppdatering tilgjengelig - %d utvidelsesoppdateringer tilgjengelige - - - Kapittel %1$s og 1 til - Kapitler %1$s og %2$d til - Kapitler %1$s Ikke nok lagringsplass til å laste ned kapitler Anvend også for allle oppføringer i biblioteket @@ -561,10 +517,6 @@ Av Begrensninger: %s - - I går - %1$d dager siden - I dag Dynamisk Programdrakt @@ -682,10 +634,6 @@ Last ned automatisk mens du leser Forbedrer leserytelsen Tilbakestiller lesemodus og orientering for alle serier - - Neste uleste kapittel - Neste %d uleste kapitler - Antall uleste Ønsker du å slette kategorien \"%s\"\? Slett kategori @@ -755,27 +703,15 @@ Hopp over dupliserte kapitler %1$s feil: %2$s *påkrevd - - Neste kapittel - Neste %d kapitler - Skjul oppføringer som allerede er i biblioteket Kopier til utklippstavle Oppdater kategori Del opp høye bilder Elementer - - Mangler %1$s kapittel - Mangler %1$s kapitler - Vend orienteringen av roterte brede sider Roter brede sider slik at de passer Debug info %d per rad - - %d dag - %d dager - Sett til å oppdatere hver Hoppet over fordi ingen utgivelse var forventet i dag Kapittelsveip diff --git a/i18n/src/commonMain/resources/MR/ne/plurals.xml b/i18n/src/commonMain/resources/MR/ne/plurals.xml new file mode 100644 index 0000000000..1de3f8432a --- /dev/null +++ b/i18n/src/commonMain/resources/MR/ne/plurals.xml @@ -0,0 +1,67 @@ + + + + हिजो + %1$d दिन अघि + + + %1$s मिनेट पछि + %1$s मिनेट पछि + + + %d वर्ग + %d वर्गहरू + + + %2$s त्रुटिको साथ %1$s मा सम्पन्न भयो + %2$s त्रुटिहरूसँग %1$s मा सम्पन्न भयो + + + %1$d नयाँ अध्याय + %1$d नयाँ अध्यायहरू + + + एक्सटेन्शन अपडेट उपलब्ध छ + %d एक्सटेन्शन अपडेटहरू उपलब्ध छन् + + + अध्याय %1$s र 1 थप + अध्याय %1$s र %2$d थप + + + %d इन्ट्रीको लागि + %d इन्ट्रीहरूको लागि + + + %1$s बाँकी + %1$s बाँकी + + + %1$s अध्याय + %1$s अध्यायहरू + + + %d अध्याय छोड्दै, या त स्रोत सँग छैन वा यसलाई फिल्टर गरिएको छ + %d अध्यायहरू छोड्दै, या त स्रोत सँग छैन वा यसलाई फिल्टर गरिएको छ + + + %d ट्र्याकर + %d ट्र्याकरहरू + + + अर्को नपढिएको अध्याय + अर्को %d नपढिएका अध्यायहरू + + + अर्को अध्याय + अर्को %d अध्यायहरू + + + %1$s अध्याय छुटेको छ + %1$s अध्यायहरू छुटेका छन् + + + १ दिन + %d दिन + + \ No newline at end of file diff --git a/i18n/src/main/res/values-ne/strings.xml b/i18n/src/commonMain/resources/MR/ne/strings.xml similarity index 95% rename from i18n/src/main/res/values-ne/strings.xml rename to i18n/src/commonMain/resources/MR/ne/strings.xml index e6b8328e0f..5e977a0220 100644 --- a/i18n/src/main/res/values-ne/strings.xml +++ b/i18n/src/commonMain/resources/MR/ne/strings.xml @@ -130,20 +130,12 @@ ल्याण्डस्केप ग्रिड साइज प्रदर्शन - - हिजो - %1$d दिन अघि - आज स्रोत र एक्सटेन्शन सूची मा देखाउनुहोस् NSFW (१८+) स्रोतहरू सूचना को सामग्री लुकाउनुहोस् एपहरू स्विच गर्दा \"स्क्रिन सुरक्षित गर्नुहोस्\" ले एप सामग्रीहरू लुकाउँछ र स्क्रिनसटहरू रोक्छ स्क्रिन सुरक्षित गर्नुहोस् - - %1$s मिनेट पछि - %1$s मिनेट पछि - कहिल्यै हैन सधैं निष्क्रिय रहेमा लक होस् @@ -246,10 +238,6 @@ स्क्रिन अन राख्नुहोस् इन्ट्रीहरूको शीर्षक अनुसार फोल्डरहरू सिर्जना गर्दछ कुल इन्ट्रीहरू - - %d वर्ग - %d वर्गहरू - सावधान भाषा यसले अनौपचारिक वा सम्भावित रूपमा गलत रूपमा फ्ल्याग गरिएका एक्सटेन्शनहरूलाई एप भित्र NSFW (१८+) सामग्री आउन बाट रोक्दैन। @@ -317,10 +305,6 @@ विशिष्ट स्रोतहरूको लागि परिष्कृत सुविधाहरू प्रदान गर्दछ। तपाईंको पुस्तकालयमा थप्दा इन्ट्री स्वचालित रूपमा ट्र्याक गरिन्छ। ट्र्याक रिस्टोर सम्पन्न भयो - - %2$s त्रुटिको साथ %1$s मा सम्पन्न भयो - %2$s त्रुटिहरूसँग %1$s मा सम्पन्न भयो - कुकीहरू खाली गर्नुहोस् तपाई के ब्याकअप गर्न चाहनुहुन्छ\? ब्याकअप असफल भयो @@ -346,10 +330,6 @@ ब्याकअप रिस्टोर असफल भयो तपाईंले ब्याकअपको प्रतिलिपिहरू अन्य ठाउँहरूमा पनि राख्नु पर्छ। ब्याकअपहरूमा कुनै पनि भण्डारण गरिएका पासवर्डहरू सहित संवेदनशील डेटा समावेश हुन सक्छ; साझा गर्दा होसियार । नयाँ अध्यायहरू फेला पर्यो - - %1$d नयाँ अध्याय - %1$d नयाँ अध्यायहरू - सबैभन्दा उच्च असक्षम परिष्कृत ट्र्याकरहरू @@ -375,10 +355,6 @@ अन्तिम पढिएको अध्याय भन्दा ३ अध्याय अघि नयाँ अध्यायहरू डाउनलोड गर्नुहोस् अध्यायहरू %1$s - - एक्सटेन्शन अपडेट उपलब्ध छ - %d एक्सटेन्शन अपडेटहरू उपलब्ध छन् - कुनै Wi-Fi जडान उपलब्ध छैन डाउनलोडहरू रोकियो कुनै नेटवर्क जडान उपलब्ध छैन @@ -389,10 +365,6 @@ बहिष्कृत वर्गहरू अन्तिम पढिएको अध्याय भन्दा ४ अध्याय अघि \"बहिष्कृत\" वर्गहरूमा इन्ट्री \"समावेश गरिएका\" वर्गहरूमा भए पनि डाउनलोड गरिने छैन। - - अध्याय %1$s र 1 थप - अध्याय %1$s र %2$d थप - ब्याकअप सिर्जना गर्नुहोस् हालको पुस्तकालय रिस्टोर गर्न प्रयोग गर्न सकिन्छ कुकीहरू खाली गरियो @@ -426,10 +398,6 @@ स्वचालित ब्याकअप फ्रिक्वेन्सी अधिकतम स्वचालित ब्याकअपहरू प्रयोग गरिएको: %1$s - - %d इन्ट्रीको लागि - %d इन्ट्रीहरूको लागि - क्यास खाली गरियो। %1$d फाइलहरू हटाएका छन् अध्याय %1$s र %2$d अरू डाउनलोड त्रुटि @@ -469,10 +437,6 @@ पिन गरिएको ग्लोबल रूपमा \"%1$s\" खोज्नुहोस् अज्ञात लेखक - - %1$s बाँकी - %1$s बाँकी - डेटाबेस खाली गर्नुहोस् वर्बोज लगिङ युजरनेम @@ -508,10 +472,6 @@ थप थोरै अध्याय %1$s - - %1$s अध्याय - %1$s अध्यायहरू - अध्याय संख्या शीर्षक मूल्याङ्कन @@ -527,10 +487,6 @@ डाउनलोड गर्दै (%1$d/%2$d) अध्याय संख्या द्वारा अपलोड मिति द्वारा - - %d अध्याय छोड्दै, या त स्रोत सँग छैन वा यसलाई फिल्टर गरिएको छ - %d अध्यायहरू छोड्दै, या त स्रोत सँग छैन वा यसलाई फिल्टर गरिएको छ - स्रोत स्थानान्तरण गाइड स्थानान्तरण गर्नको लागि स्रोत चयन गर्नुहोस् आवरण सेभ गर्दा त्रुटि भयो @@ -574,10 +530,6 @@ त्रुटि स्रोत शीर्षक स्रोत द्वारा - - %d ट्र्याकर - %d ट्र्याकरहरू - फेरी पढ्दै हालको: कुनै मेल फेला परेन @@ -701,10 +653,6 @@ F-Droid निर्माणहरू आधिकारिक रूपमा समर्थित छैनन्। \nथप जान्न ट्याप गर्नुहोस्। उफ्! - - अर्को नपढिएको अध्याय - अर्को %d नपढिएका अध्यायहरू - पढेको अवधि रिडर सेटिङहरू रिसेट गर्न सकिएन WebView डेटा खाली गरियो @@ -750,10 +698,6 @@ पूर्वनिर्धारित युजर एजेन्ट स्ट्रिङ रिसेट गर्नुहोस् %dसे %dमि - - अर्को अध्याय - अर्को %d अध्यायहरू - पहिले नै पुस्तकालयमा रहेका इन्ट्रीहरू लुकाउनुहोस् क्लिपबोर्डमा प्रतिलिपि गर्नुहोस् डाउनलोड इन्डेक्स अमान्य गर्नुहोस् @@ -766,10 +710,6 @@ ओभरले फिट गर्न चौडा पृष्ठहरू घुमाउनुहोस् घुमाइएका चौडा पृष्ठहरूको अभिमुखीकरण फ्लिप गर्नुहोस् - - %1$s अध्याय छुटेको छ - %1$s अध्यायहरू छुटेका छन् - Debug जानकारी अध्याय स्वाइप दायाँ स्वाइप @@ -783,10 +723,6 @@ अन्तराल कस्टम गर्नुहोस् छोडियो किनभने आज कुनै रिलीज अपेक्षित थिएन अन्तरालहरू - - १ दिन - %d दिन - ढिलो १०+ जाँच जाँच अवधि पार भयो अर्को अपेक्षित अपडेट diff --git a/i18n/src/commonMain/resources/MR/nl/plurals.xml b/i18n/src/commonMain/resources/MR/nl/plurals.xml new file mode 100644 index 0000000000..426f1662aa --- /dev/null +++ b/i18n/src/commonMain/resources/MR/nl/plurals.xml @@ -0,0 +1,67 @@ + + + + Na %1$s minuut + Na %1$s minuten + + + Extensie-update beschikbaar + %d extensie-updates beschikbaar + + + Hoofdstukken %1$s en 1 meer + Hoofdstukken %1$s en %2$d meer + + + %1$d nieuw hoofdstuk + %1$d nieuwe hoofdstukken + + + Voor %d titel + Voor %d titels + + + %1$s resterend + %1$s resterende + + + Voltooid in %1$s met %2$s foutmelding + Voltooid in %1$s met %2$s foutmeldingen + + + %d categorie + %d categorieën + + + %1$s hoofdstuk + %1$s hoofdstukken + + + %d tracker + %d trackers + + + 1 hoofdstuk is overgeslagen, de bron mist 1 hoofdstuk of het is uitgefilterd + %d hoofdstukken zijn overgeslagen, de bron mist ze of ze zijn uitgefilterd + + + Gisteren + %1$d dagen geleden + + + Volgende ongelezen hoofdstuk + Volgende aantal %d ongelezen hoofdstukken + + + Volgend hoofdstuk + Volgende %d hoofdstukken + + + 1 dag + %d dagen + + + %1$s hoofdstuk mist + %1$s hoofdstukken missen + + \ No newline at end of file diff --git a/i18n/src/main/res/values-nl/strings.xml b/i18n/src/commonMain/resources/MR/nl/strings.xml similarity index 95% rename from i18n/src/main/res/values-nl/strings.xml rename to i18n/src/commonMain/resources/MR/nl/strings.xml index bf05a08f21..cf5c4d9d79 100644 --- a/i18n/src/main/res/values-nl/strings.xml +++ b/i18n/src/commonMain/resources/MR/nl/strings.xml @@ -315,10 +315,6 @@ Vergrendelen indien niet in gebruik Altijd Nooit - - Na %1$s minuut - Na %1$s minuten - Scherm beveiligen Updates in de wachtrij Kon Cloudflare niet omzeilen @@ -338,25 +334,9 @@ Er wordt al een back-up hersteld Extensie-updates WebView is vereist voor Tachiyomi - - Extensie-update beschikbaar - %d extensie-updates beschikbaar - - - Hoofdstukken %1$s en 1 meer - Hoofdstukken %1$s en %2$d meer - Hoofdstukken %1$s Hoofdstuk %1$s en %2$d meer Hoofdstuk %1$s - - %1$d nieuw hoofdstuk - %1$d nieuwe hoofdstukken - - - Voor %d titel - Voor %d titels - Zoeken naar nieuwe hoofdstukken Hfst. %1$s - %2$s Bibliotheek bijwerken @@ -369,10 +349,6 @@ Vastgepind Laatst gebruikt E-mailadres - - %1$s resterend - %1$s resterende - Filtert alle items in de bibliotheek Alleen gedownloade Controleer op updates @@ -395,17 +371,9 @@ Leesmodus Voor deze serie Kon de apparaatinstellingen niet openen - - Voltooid in %1$s met %2$s foutmelding - Voltooid in %1$s met %2$s foutmeldingen - Opvulling zijkant Grijs Vermindert kleurstrepen, maar beïnvloedt de prestaties - - %d categorie - %d categorieën - Omslagen van manga in bibliotheek bijwerken Eenzijdige synchronisatie om voortang van hoofdstukken bij te werken bij externe trackerdiensten. Stel tracking in bij individuele items via de \"Tracking\"-knop. Deze extensie behoort niet tot de officiële Tachiyomi extensielijst. @@ -429,10 +397,6 @@ Beginnen Alles uitzetten Alles aanzetten - - %1$s hoofdstuk - %1$s hoofdstukken - Herstart van de app nodig om van kracht te worden Netwerken Beiden @@ -449,10 +413,6 @@ Leesmodus Thema Datum toegevoegd - - %d tracker - %d trackers - Je hebt geen vastgepinde bronnen Voltooid Voortgang @@ -463,10 +423,6 @@ Kan NSFW-inhoud (18+) bevatten 18+ Dit voorkomt niet dat onofficiële of mogelijk incorrect gemarkeerde extensies NSFW-inhoud (18+) kunnen laten zien in de app. - - 1 hoofdstuk is overgeslagen, de bron mist 1 hoofdstuk of het is uitgefilterd - %d hoofdstukken zijn overgeslagen, de bron mist ze of ze zijn uitgefilterd - Geen hoofdstukken gevonden Standaard hoofdstukinstellingen bijgewerkt Instellen als standaard @@ -581,10 +537,6 @@ Hoogste Sensitiviteit voor het verbergen van het menu tijdens scrollen Omgekeerd - - Gisteren - %1$d dagen geleden - Vandaag Blauwgroen & Turkoois Uiterlijk @@ -663,10 +615,6 @@ Ongelezen aantal Werkt alleen bij vermeldingen in de bibliotheek en als het huidige hoofdstuk en het volgende alreeds gedownload zijn Standaard \'user-agent-string\' - - Volgende ongelezen hoofdstuk - Volgende aantal %d ongelezen hoofdstukken - Zoek… Opslag bevoegdheden niet verleent Knop om lezen te hervatten weergeven @@ -729,10 +677,6 @@ Geen bron gevonden Oops! 1-directie voortgang sync - - Volgend hoofdstuk - Volgende %d hoofdstukken - Dit gaat je eerder geselcteerde startdatum %s verwijderen Download verwijderen Overgeslagen omdat serie geen updates vereist. @@ -762,15 +706,7 @@ Herstart de applicatie Interval aanpassen Download Index geïnvalideerd - - 1 dag - %d dagen - Maak de downloadindex ongeldig - - %1$s hoofdstuk mist - %1$s hoofdstukken missen - OK Swipe naar de linker actie Intervallen diff --git a/i18n/src/commonMain/resources/MR/nn/plurals.xml b/i18n/src/commonMain/resources/MR/nn/plurals.xml new file mode 100644 index 0000000000..8dc9ba50d6 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/nn/plurals.xml @@ -0,0 +1,19 @@ + + + + Etter %1$s minutt + Etter %1$s minuttar + + + I går + %1$d dagar sidan + + + %d kategori + %d kategoriar + + + Gjort på %1$s med %2$s feil + Gjort på %1$s med %2$s feil + + \ No newline at end of file diff --git a/i18n/src/main/res/values-nn/strings.xml b/i18n/src/commonMain/resources/MR/nn/strings.xml similarity index 96% rename from i18n/src/main/res/values-nn/strings.xml rename to i18n/src/commonMain/resources/MR/nn/strings.xml index 2d60827fdf..71ca74d363 100644 --- a/i18n/src/main/res/values-nn/strings.xml +++ b/i18n/src/commonMain/resources/MR/nn/strings.xml @@ -101,16 +101,8 @@ Sikkerheit Alltid Aldri - - Etter %1$s minutt - Etter %1$s minuttar - NSFW (18+) kjeder I dag - - I går - %1$d dagar sidan - Skjerm Element per rad Automatisk oppdateringar @@ -122,10 +114,6 @@ Sjå etter nye omslag og detaljar ved oppdatering av bibliotek Standard kategori Alltid spør - - %d kategori - %d kategoriar - Manga i utelatne kategoriar vil ikkje bli oppdatert sjølv om dei òg er i inkluderte kategoriar. Alle Ingen @@ -209,10 +197,6 @@ Gjenopprett bibliotek frå reservekopifil Gjenoppretting fullført %02d min, %02d sek - - Gjort på %1$s med %2$s feil - Gjort på %1$s med %2$s feil - Kva ønskjer du å ta reservekopi av\? Lagar reservekopi Gjenoppretter reservekopi diff --git a/i18n/src/commonMain/resources/MR/pl/plurals.xml b/i18n/src/commonMain/resources/MR/pl/plurals.xml new file mode 100644 index 0000000000..da0ed4cb59 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/pl/plurals.xml @@ -0,0 +1,99 @@ + + + + Po %1$s minucie + Po %1$s minutach + Po %1$s minutach + Po %1$s minutach + + + %d kategoria + %d kategorie + %d kategorii + %d kategorii + + + Dostępna aktualizacja rozszerzenia + Dostępne %d aktualizacje rozszerzeń + Dostępne %d aktualizacji rozszerzeń + Dostępne %d aktualizacji rozszerzeń + + + Rozdziały %1$s i jeden więcej + Rozdziały %1$s i %2$d + Rozdziały %1$s i %2$d + Rozdziały %1$s i %2$d + + + %1$d nowy rozdział + %1$d nowe rozdziały + %1$d nowych rozdziałów + %1$d nowych rozdziałów + + + Dla %d wpisu + Dla %d wpisów + Dla %d wpisów + Dla %d wpisów + + + Pozostał %1$s + Pozostało %1$s + Pozostało %1$s + Pozostało %1$s + + + Wykonano w %1$s z %2$s błędem + Wykonano w %1$s z %2$s błędami + Wykonano w %1$s z %2$s błędami + Wykonano w %1$s z %2$s błędami + + + %1$s rozdział + %1$s rozdziały + %1$s rozdziałów + %1$s rozdziałów + + + %d brakujący rozdział + %d brakujące rozdziały + %d brakujących rozdziałów + %d brakujących rozdziałów + + + 1 serwis śledzący + %d serwisy śledzące + %d serwisów śledzących + %d serwisów śledzących + + + Wczoraj + %1$d dni temu + %1$d dni temu + %1$d dni temu + + + Następny nieprzeczytany rozdział + Następne %d nieprzeczytane rozdziały + Następne %d nieprzeczytanych rozdziałów + Następne %d nieprzeczytanych rozdziałów + + + Następny rozdział + Następne %d rozdziały + Następne %d rozdziałów + Następne %d rozdziałów + + + Brakujący %1$s rozdział + Brakujące %1$s rozdziały + Brakuje %1$s rozdziałów + Brakuje %1$s rozdziałów + + + 1 dzień + %d dni + %d dni + %d dni + + \ No newline at end of file diff --git a/i18n/src/main/res/values-pl/strings.xml b/i18n/src/commonMain/resources/MR/pl/strings.xml similarity index 91% rename from i18n/src/main/res/values-pl/strings.xml rename to i18n/src/commonMain/resources/MR/pl/strings.xml index 84c62b5f5e..9e28dfc11e 100644 --- a/i18n/src/main/res/values-pl/strings.xml +++ b/i18n/src/commonMain/resources/MR/pl/strings.xml @@ -312,12 +312,6 @@ Nie udało się obejść Cloudflare Więcej Ukrywa zawartość ekranu przy przełączaniu między aplikacjami i blokuj zrzuty ekranu - - Po %1$s minucie - Po %1$s minutach - Po %1$s minutach - Po %1$s minutach - Nigdy Zawsze Wymagaj odblokowania @@ -358,12 +352,6 @@ Szary Ogranicza banding, ale może mieć wpływ na wydajność Dostępne aktualizacje - - %d kategoria - %d kategorie - %d kategorii - %d kategorii - Ukryj ekran Odepnij Przypnij @@ -375,41 +363,11 @@ Przesyłanie postępu czytania do zewnętrznego serwisu. Ustaw śledzenie guzikiem \"Śledzenie\" w wybranych tytułach. Aktualizacje rozszerzeń WebView jest wymagany do poprawnego działania aplikacji - - Dostępna aktualizacja rozszerzenia - Dostępne %d aktualizacje rozszerzeń - Dostępne %d aktualizacji rozszerzeń - Dostępne %d aktualizacji rozszerzeń - - - Rozdziały %1$s i jeden więcej - Rozdziały %1$s i %2$d - Rozdziały %1$s i %2$d - Rozdziały %1$s i %2$d - Rozdziały %1$s Rozdział %1$s i %2$d więcej - - %1$d nowy rozdział - %1$d nowe rozdziały - %1$d nowych rozdziałów - %1$d nowych rozdziałów - - - Dla %d wpisu - Dla %d wpisów - Dla %d wpisów - Dla %d wpisów - Poszukiwanie nowych rozdziałów Tryb czytania Źródła lokalne - poradnik - - Pozostał %1$s - Pozostało %1$s - Pozostało %1$s - Pozostało %1$s - Pokazuj zawartość w strefie odcięcia Przeglądaj rozdziały Dodaj śledzenie @@ -417,12 +375,6 @@ Odśwież okładki w bibliotece Przywracanie kopii zapasowej zakończone niepowodzeniem Tworzenie kopii zapasowej zakończone niepowodzeniem - - Wykonano w %1$s z %2$s błędem - Wykonano w %1$s z %2$s błędami - Wykonano w %1$s z %2$s błędami - Wykonano w %1$s z %2$s błędami - Czytane Te rozszerzenie nie jest na liście oficjalnych rozszerzeń. Nieoficjalne @@ -453,12 +405,6 @@ Brak Odwróć strefy kliknięcia Nie udało się pobrać rozdziałów z powodu braku miejsca na urządzeniu - - %1$s rozdział - %1$s rozdziały - %1$s rozdziałów - %1$s rozdziałów - Nieznany status Nieznany autor Szukaj \"%1$s\" globalnie @@ -475,19 +421,7 @@ Postęp Zaktualizowano domyślne ustawienia rozdziałów Instrukcja przenoszenia źródeł - - %d brakujący rozdział - %d brakujące rozdziały - %d brakujących rozdziałów - %d brakujących rozdziałów - %1$s: %2$s, strona %3$d - - 1 serwis śledzący - %d serwisy śledzące - %d serwisów śledzących - %d serwisów śledzących - Nie znaleziono rozdziałów Ustaw jako domyślne Dodatkowo zastosuj do wszystkich wpisów w mojej bibliotece @@ -589,12 +523,6 @@ Truskawkowe daiquiri Czułość ukrywania dolnego paska podczas przewijania Tako - - Wczoraj - %1$d dni temu - %1$d dni temu - %1$d dni temu - Aktywność w tle Śledź Wygląd @@ -708,12 +636,6 @@ Pobieraj podczas czytania Zobacz ostatnio zaktualizowane wpisy Widżet nie jest dostępny kiedy blokada aplikacji jest włączona - - Następny nieprzeczytany rozdział - Następne %d nieprzeczytane rozdziały - Następne %d nieprzeczytanych rozdziałów - Następne %d nieprzeczytanych rozdziałów - Jesteś pewien\? Działa tylko, jeśli aktualny i następny rozdział są już pobrane. Wielojęzyczne @@ -783,24 +705,12 @@ *wymagane Ukryj pozycje znajdujące się już w bibliotece Kopiuj do schowka - - Następny rozdział - Następne %d rozdziały - Następne %d rozdziałów - Następne %d rozdziałów - Aktualizuj kategorię Dziel długie obrazy Nakładka Dopasuj szerokie strony Zmień orientację obróconych obrazów Informacje debugowania - - Brakujący %1$s rozdział - Brakujące %1$s rozdziały - Brakuje %1$s rozdziałów - Brakuje %1$s rozdziałów - %d na rząd Dotknij dwukrotnie, aby powiększyć Przesuń palcem w prawo @@ -809,12 +719,6 @@ Ustaw interwał Następna spodziewana aktualizacja Aktualizuj co - - 1 dzień - %d dni - %d dni - %d dni - Synchronizowanie biblioteki Nie można wykonać kopi zapasowej Interwały diff --git a/i18n/src/commonMain/resources/MR/pt-rBR/plurals.xml b/i18n/src/commonMain/resources/MR/pt-rBR/plurals.xml new file mode 100644 index 0000000000..8e6c0c1072 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/pt-rBR/plurals.xml @@ -0,0 +1,83 @@ + + + + Por %1$s minuto + Por %1$s minutos + Por %1$s minutos + + + %1$d capítulo novo + %1$d capítulos novos + %1$d capítulos novos + + + Capítulos %1$s e mais 1 + Capítulos %1$s e mais %2$d + Capítulos %1$s e mais %2$d + + + Para %d item + Para %d itens + Para %d itens + + + Atualização de extensão disponível + %d atualizações de extensão disponíveis + %d atualizações de extensão disponíveis + + + %1$s restante + %1$s restantes + %1$s restantes + + + %d categoria + %d categorias + %d categorias + + + Concluído em %1$s com %2$s erro + Concluído em %1$s com %2$s erros + Concluído em %1$s com %2$s erros + + + %1$s capítulo + %1$s capítulos + %1$s capítulos + + + %d monitorador + %d monitoradores + %d monitoradores + + + Pulando %d capítulo, ou ele está faltando na fonte, ou ele foi filtrado + Pulando %d capítulos, ou eles estão faltando na fonte, ou eles foram filtrados + Pulando %d capítulos, ou eles estão faltando na fonte, ou eles foram filtrados + + + Ontem + %1$d dias atrás + %1$d dias atrás + + + Próximo capítulo não lido + Próximos %d capítulos não lidos + Próximos %d capítulos não lidos + + + Próximo capítulo + Próximos %d capítulos + Próximos %d capítulos + + + Faltando %1$s capítulo + Faltando %1$s capítulos + Faltando %1$s capítulos + + + %d dia(s) + %d dias + %d dias + + \ No newline at end of file diff --git a/i18n/src/main/res/values-pt-rBR/strings.xml b/i18n/src/commonMain/resources/MR/pt-rBR/strings.xml similarity index 93% rename from i18n/src/main/res/values-pt-rBR/strings.xml rename to i18n/src/commonMain/resources/MR/pt-rBR/strings.xml index 1aeba797d4..861bb7a70e 100644 --- a/i18n/src/main/res/values-pt-rBR/strings.xml +++ b/i18n/src/commonMain/resources/MR/pt-rBR/strings.xml @@ -315,11 +315,6 @@ Bloquear quando ocioso Sempre Nunca - - Por %1$s minuto - Por %1$s minutos - Por %1$s minutos - Tela segura Atualizações pendentes Mostrar conteúdo na área de recorte da tela @@ -328,19 +323,9 @@ Atualizações de capítulos A tela segura oculta os conteúdos do aplicativo durante a troca de aplicativos e impede capturas de tela Visualização - - %1$d capítulo novo - %1$d capítulos novos - %1$d capítulos novos - Capítulo %1$s Capítulo %1$s e mais %2$d Capítulos %1$s - - Capítulos %1$s e mais 1 - Capítulos %1$s e mais %2$d - Capítulos %1$s e mais %2$d - Ocultar conteúdo da notificação Verificando por novos capítulos Desativar a otimização de bateria @@ -348,21 +333,11 @@ A otimização de bateria já está desativada Endereço de email Sempre mostrar a transição entre capítulos - - Para %d item - Para %d itens - Para %d itens - Menu Mais novos Mais antigos Mover para o começo Mover para o final - - Atualização de extensão disponível - %d atualizações de extensão disponíveis - %d atualizações de extensão disponíveis - Atualizações de extensões Atualizando a biblioteca Leitura @@ -394,26 +369,11 @@ Guia sobre a fonte local %02d min e %02d seg Filtra todos os itens em sua biblioteca - - %1$s restante - %1$s restantes - %1$s restantes - Cinza Modo de leitura Para esta série Reduz o efeito de anéis nos degradês, mas pode afetar o desempenho - - %d categoria - %d categorias - %d categorias - Não foi possível abrir as configurações do dispositivo - - Concluído em %1$s com %2$s erro - Concluído em %1$s com %2$s erros - Concluído em %1$s com %2$s erros - Sincronização unidirecional para atualizar o progresso dos capítulos nos serviços monitoradores externos. Configure o monitoramento para itens individuais a partir de seus botões de monitoramento. Atualizar as capas da biblioteca Esta extensão não é da lista oficial. @@ -437,11 +397,6 @@ Iniciar Fonte não encontrada Desativar - - %1$s capítulo - %1$s capítulos - %1$s capítulos - Requer o reinício do aplicativo para ter efeito Rede Nenhum @@ -458,11 +413,6 @@ Pesquisar por \"%1$s\" globalmente Modo de leitura Tema - - %d monitorador - %d monitoradores - %d monitoradores - Você não tem fontes fixadas Andamento Concluído @@ -473,11 +423,6 @@ As fontes desta extensão podem ter conteúdo NSFW (+18) +18 Isso não impede que extensões não oficiais ou potencialmente sinalizadas de maneira incorreta apresentem conteúdo NSFW (+18) no aplicativo. - - Pulando %d capítulo, ou ele está faltando na fonte, ou ele foi filtrado - Pulando %d capítulos, ou eles estão faltando na fonte, ou eles foram filtrados - Pulando %d capítulos, ou eles estão faltando na fonte, ou eles foram filtrados - Nenhum capítulo encontrado Configurações padrões de capítulo atualizadas Definir como padrão @@ -587,11 +532,6 @@ Mais alta Sensibilidade para ocultar o menu na rolagem Invertido - - Ontem - %1$d dias atrás - %1$d dias atrás - Hoje Azul-petróleo & Turquesa Autentique-se para confirmar a mudança @@ -697,11 +637,6 @@ Fazer download a frente Download automático durante a leitura Funciona somente se o capítulo atual e próximo já estão disponíveis offline. - - Próximo capítulo não lido - Próximos %d capítulos não lidos - Próximos %d capítulos não lidos - Você tem certeza\? Múltiplos Última atualização da biblioteca: %s @@ -768,11 +703,6 @@ \nVocê ainda deseja continuar\? Erro em %1$s: %2$s *obrigatório - - Próximo capítulo - Próximos %d capítulos - Próximos %d capítulos - Ocultar títulos que já estão na biblioteca Copiar para a área de transferência Atualizar categoria @@ -780,11 +710,6 @@ Sobreposição Rotacionar páginas largas para caber Inverter a orientação das páginas largas rotacionadas - - Faltando %1$s capítulo - Faltando %1$s capítulos - Faltando %1$s capítulos - Informações de depuração Ações do capítulo Ação de deslizar para a direita @@ -800,11 +725,6 @@ Abandonado\? Últimos 20+ e 2 meses Intervalo de verificação aprovado Personalizar intervalo - - %d dia(s) - %d dias - %d dias - Pulado porque nenhum lançamento era esperado hoje Intervalos Definido para atualizar todo diff --git a/i18n/src/commonMain/resources/MR/pt/plurals.xml b/i18n/src/commonMain/resources/MR/pt/plurals.xml new file mode 100644 index 0000000000..ff2ef60efe --- /dev/null +++ b/i18n/src/commonMain/resources/MR/pt/plurals.xml @@ -0,0 +1,83 @@ + + + + Após %1$s minuto + Após %1$s minutos + Após %1$s minutos + + + Capítulos %1$s e 1 mais + Capítulos %1$s e %2$d mais + Capítulos %1$s e %2$d mais + + + Para %d entrada + Para %d entradas + Para %d o acesso + + + %1$d novo capítulo + %1$d novos capítulos + %1$d novos capítulos + + + Atualização de extensão disponível + %d atualizações de extensão disponíveis + %d atualizações de extensão disponíveis + + + %1$s restante + %1$s restantes + %1$s restantes + + + %d categoria + %d categorias + %d categorias + + + Concluído em %1$s com %2$s erro + Concluído em %1$s com %2$s erros + Concluído em %1$s com %2$s erros + + + %1$s capítulo + %1$s capítulos + %1$s capítulos + + + %d rastreador + %d rastreadores + %d rastreadores + + + Ignorando %d capítulo, ou a fonte está em falta ou foi filtrado + Ignorando %d capítulos, ou a fonte está em falta ou foi filtrado + Capítulos %d ignorados, ou a fonte está em falta ou foi filtrado + + + Ontem + Há %1$d dias + Há %1$d dias + + + Próximo capítulo não lido + Próximos %d capítulos não lidos + Próximos %d capítulos não lidos + + + Próximo capítulo + Próximos %d capítulos + Próximos %d capítulos + + + Falta %1$s capítulo + Faltam %1$s capítulos + Faltam %1$s capítulos + + + Um dia + %d dias + %d dias + + \ No newline at end of file diff --git a/i18n/src/main/res/values-pt/strings.xml b/i18n/src/commonMain/resources/MR/pt/strings.xml similarity index 91% rename from i18n/src/main/res/values-pt/strings.xml rename to i18n/src/commonMain/resources/MR/pt/strings.xml index 421f7a4559..1ee6c095e3 100644 --- a/i18n/src/main/res/values-pt/strings.xml +++ b/i18n/src/commonMain/resources/MR/pt/strings.xml @@ -1,14 +1,12 @@ Nome - Definições Fila de Transferências Biblioteca Histórico Atualizações Cópia de segurança e restauração - Definições Filtro Não Lido @@ -38,16 +36,12 @@ Cancelar Ordenar Instalar - A carregar… - - Geral Leitor Transferências Avançado Sobre - Tamanho da grade Vertical Horizontal @@ -62,7 +56,6 @@ Ao carregar Com estado \'\'Terminado\'\' Atualizar progresso após a leitura - Ecrã inteiro Animar transições de página Mostrar número de página @@ -94,7 +87,6 @@ Livre Vertical bloqueado Horizontal bloqueado - Localização das Transferências Após marcado como lido manualmente Eliminar automaticamente após a leitura @@ -105,9 +97,7 @@ Antepenúltimo capítulo lido Quarto capítulo lido antes do último Quinto capítulo lido antes do último - Serviços - Limpar a cache dos capítulos Usado: %1$s Cache limpa. %1$d ficheiros foram eliminados @@ -118,27 +108,20 @@ Exclui o histórico de itens que não estão salvos nasua biblioteca Tem certeza\? Os capítulos lidos e o progresso em itens que não estão na sua biblioteca serão perdidos Eliminar entradas - Versão - Enviar relatórios de erro Ajuda a corrigir qualquer erro. Não serão enviados dados sensíveis - Iniciar sessão em %1$s Nome de utilizador Palavra-passe Iniciar sessão Sessão iniciada Erro desconhecido - A atualizar categoria - - Em curso Desconhecido Licenciado Remover da biblioteca - Capítulo %1$s A Transferir (%1$d/%2$d) Erro @@ -149,7 +132,6 @@ Transferir Não lidos Tem certeza de que deseja eliminar os capítulos selecionados\? - A ler Completo Abandonado @@ -159,38 +141,26 @@ Título Estado Capítulos - Esta ação irá remover a data de leitura deste capítulo. Continuar? Redefinir todos os capítulos para esta entrada - Página: %1$d Capítulo seguinte não encontrado A imagem não pôde ser carregada - - - Não foi possível transferir capítulos. Poderá tentar novamente na secção das transferências - Novos capítulos encontrados Por favor adicione à sua biblioteca antes de fazer isto - Selecionar imagem de capa Selecionar ficheiro de cópia de segurança - Transferir Sem atualizações disponíveis - A transferir… Toque para instalar a atualização Erro na transferência Nova versão disponível! - - Sem transferências Sem atualizações recentes Nada lido recentemente A sua biblioteca está vazia - Erro Não foi possível transferir o capítulo devido a um erro inesperado A ligação Wi-Fi está indisponível @@ -345,11 +315,6 @@ Bloquear quando inativo Sempre Nunca - - Após %1$s minuto - Após %1$s minutos - Após %1$s minutos - Ecrã seguro Atualizações pendentes Mostrar conteúdo na área de corte @@ -360,11 +325,6 @@ Visualização Capítulo %1$s e %2$d mais Capítulos %1$s - - Capítulos %1$s e 1 mais - Capítulos %1$s e %2$d mais - Capítulos %1$s e %2$d mais - Esconder conteúdo das notificações Verificando por novos capítulos Desativar otimização de bateria @@ -372,28 +332,13 @@ A otimização de bateria já está desativada Endereço de e-mail Mostrar sempre transição entre capítulos - - Para %d entrada - Para %d entradas - Para %d o acesso - Menu Mais novos Mais antigos Mover para o topo Mover para o final - - %1$d novo capítulo - %1$d novos capítulos - %1$d novos capítulos - Capítulo %1$s Atualizações de extensão - - Atualização de extensão disponível - %d atualizações de extensão disponíveis - %d atualizações de extensão disponíveis - Atualizando biblioteca Fixado Preenchimento lateral @@ -424,26 +369,11 @@ Licenças de código aberto Filtra todos os itens nasua biblioteca %02d min, %02d seg - - %1$s restante - %1$s restantes - %1$s restantes - Cinza Modo de leitura Para esta série Reduz bandas de cor, mas pode impactar a performance - - %d categoria - %d categorias - %d categorias - Não foi possível abrir as definições do aparelho - - Concluído em %1$s com %2$s erro - Concluído em %1$s com %2$s erros - Concluído em %1$s com %2$s erros - Atualizar capas da biblioteca Sincronização unidirecional para atualizar o progresso dos capítulos nos serviços de monitoramento. Configure o monitoramento para itens individuais a partir dos botões de monitoramento deles. Esta extensão não vem da lista oficial de extensões do Tachiyomi. @@ -472,11 +402,6 @@ Nenhum Inverter zonas toque Fonte não encontrada - - %1$s capítulo - %1$s capítulos - %1$s capítulos - Estado desconhecido Autor desconhecido Requer reinício da app para ter efeito @@ -488,11 +413,6 @@ Modo de leitura Tema Data de adição - - %d rastreador - %d rastreadores - %d rastreadores - Você não possui fontes fixadas Completo Progresso @@ -503,11 +423,6 @@ Fontes desta extensão poderão conter conteúdo NSFW (18+) 18+ Isto não impede extensões não oficiais ou incorretamente marcadas de mostrarem conteúdo NSFW (18+) dentro da app. - - Ignorando %d capítulo, ou a fonte está em falta ou foi filtrado - Ignorando %d capítulos, ou a fonte está em falta ou foi filtrado - Capítulos %d ignorados, ou a fonte está em falta ou foi filtrado - Nenhum capítulo encontrado Definições padrão de capítulo atualizadas Tem certeza de que quer guardar estas definições como padrão\? @@ -611,11 +526,6 @@ Serviços melhorados Guia de introdução Azul-petróleo e Turquesa - - Ontem - Há %1$d dias - Há %1$d dias - Hoje Dinâmico Aviso @@ -704,11 +614,6 @@ Apagar categoria InternalError: Verifique registos de falhas para mais informações Cadeia de agente de utilizador não pode estar em branco - - Próximo capítulo não lido - Próximos %d capítulos não lidos - Próximos %d capítulos não lidos - Tem a certeza\? Última atualização da biblioteca: %s Veja os seus itens da biblioteca atualizados recentemente @@ -800,21 +705,11 @@ Nenhum item encontrado nesta categoria Copiar para a área de transferência Ocultar entradas existentes na biblioteca - - Próximo capítulo - Próximos %d capítulos - Próximos %d capítulos - Atualizar categoria Dividir Imagens altas Sobreposição Girar páginas largas para caber Virar a orientação de páginas largas giradas - - Falta %1$s capítulo - Faltam %1$s capítulos - Faltam %1$s capítulos - %d por linha Ação de deslizar para a esquerda Toque duplo para aproximar @@ -822,11 +717,6 @@ Buscar mensalmente (28 dias) Fora do período esperado de lançamento Informações de depuração - - Um dia - %d dias - %d dias - Customizar intervalo Trocar de capítulo Ação de deslizar para a direita diff --git a/i18n/src/commonMain/resources/MR/ro/plurals.xml b/i18n/src/commonMain/resources/MR/ro/plurals.xml new file mode 100644 index 0000000000..99aa8b4136 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/ro/plurals.xml @@ -0,0 +1,68 @@ + + + + După %1$s minut + După %1$s minute + După %1$s minute + + + %1$d capitol nou + %1$d capitole noi + %1$d capitole noi + + + Capitolele %1$s și încă unul + Capitolele %1$s și încă %2$d în plus + Capitolele %1$s și încă %2$d mai multe + + + Pentru %d intrare + Pentru %d intrări + Pentru %d intrări + + + Actualizare de extensie disponibilă + %d actualizări de extensii sunt disponibile + %d actualizări de extensii sunt disponibile + + + %1$s rămasă + %1$s rămase + %1$s rămase + + + %d categorie + %d categorii + %d categorii + + + Gata în %1$s cu eroarea %2$s + Gata în %1$s cu %2$s erori + Gata în %1$s cu %2$s erori + + + %1$s capitol + %1$s capitole + %1$s de capitole + + + %d tracker + %d trackere + %d trackere + + + Omiterea %d capitol, fie că sursa lipsește, fie că a fost filtrată + Omiterea a %d capitole, fie că sursa nu le are, fie că au fost filtrate + Omiterea a %d capitole, fie că sursa nu le are, fie că au fost filtrate + + + Ieri + Acum %1$d zile + Acum %1$d zile + + + Următorul capitol necitit + Următoarele %d capitole necitite + Următoarele %d capitole necitite + + \ No newline at end of file diff --git a/i18n/src/main/res/values-ro/strings.xml b/i18n/src/commonMain/resources/MR/ro/strings.xml similarity index 94% rename from i18n/src/main/res/values-ro/strings.xml rename to i18n/src/commonMain/resources/MR/ro/strings.xml index 3b20dade56..c0ce88489f 100644 --- a/i18n/src/main/res/values-ro/strings.xml +++ b/i18n/src/commonMain/resources/MR/ro/strings.xml @@ -315,11 +315,6 @@ Blocați când este inactiv Întotdeauna Niciodată - - După %1$s minut - După %1$s minute - După %1$s minute - Securizează ecran Actualizări în așteptare Afișare conținut în zona decupată @@ -328,19 +323,9 @@ Actualizări de capitole Ecranul securizat ascunde conținutul aplicațiilor la schimbarea aplicațiilor și blochează capturile de ecran Afișare - - %1$d capitol nou - %1$d capitole noi - %1$d capitole noi - Capitolul %1$s Capitolul %1$s și %2$d în plus Capitolele %1$s - - Capitolele %1$s și încă unul - Capitolele %1$s și încă %2$d în plus - Capitolele %1$s și încă %2$d mai multe - Ascunde conținutul notificării Verificând pentru capitole noi Dezactivați optimizarea bateriei @@ -348,22 +333,12 @@ Optimizarea bateriei este deja dezactivată Adresa de e-mail Arată întotdeauna tranziția capitolului - - Pentru %d intrare - Pentru %d intrări - Pentru %d intrări - Meniu Cele mai recente Cele mai vechi Mută pe primă poziție Mută pe ultima poziție Actualizări de extensie - - Actualizare de extensie disponibilă - %d actualizări de extensii sunt disponibile - %d actualizări de extensii sunt disponibile - Se actualizează biblioteca Citind Săriți peste capitolele filtrate @@ -394,26 +369,11 @@ Verifică pentru actualizări %02d minute, %02d secunde Filtrează toate intrările din bibliotecă - - %1$s rămasă - %1$s rămase - %1$s rămase - Mod de citire Pentru această serie Gri Reduce banding-ul, dar poate avea un impact asupra performanței - - %d categorie - %d categorii - %d categorii - Imposibil de deschis setările dispozitivului - - Gata în %1$s cu eroarea %2$s - Gata în %1$s cu %2$s erori - Gata în %1$s cu %2$s erori - Sincronizare unidirecțională pentru actualizarea progresului capitolului în cadrul serviciilor de urmărire. Configurați urmărirea pentru intrările individuale din butonul de urmărire al acestora. Reîmprospătarea coperților bibliotecii După data încărcării @@ -436,11 +396,6 @@ Arată modul de citire Reţea Nu s-a găsit sursa - - %1$s capitol - %1$s capitole - %1$s de capitole - Necesită repornirea aplicației pentru a avea efect Dezactivați Start @@ -461,11 +416,6 @@ Erori Terminat Progresul - - %d tracker - %d trackere - %d trackere - Trackerele nu sunt conectate la: Permite ștergerea capitolelor marcate Ștergeți capitole @@ -474,11 +424,6 @@ Acest lucru nu împiedică extensiile neoficiale sau potențial semnalizate incorect să iasă la suprafață cu conținut 18+ în cadrul aplicației. Nu aveți surse fixate Nu a fost găsit niciun capitol - - Omiterea %d capitol, fie că sursa lipsește, fie că a fost filtrată - Omiterea a %d capitole, fie că sursa nu le are, fie că au fost filtrate - Omiterea a %d capitole, fie că sursa nu le are, fie că au fost filtrate - S-au actualizat setările implicite ale capitolului %1$s: %2$s, pagina %3$d Setați ca implicit @@ -644,19 +589,9 @@ Nu s-a putut obține lista de extensii Se instalează extensia… Program instalare - - Ieri - Acum %1$d zile - Acum %1$d zile - Creează dosare în funcție de titlul intrărilor Automat Pornit - - Următorul capitol necitit - Următoarele %d capitole necitite - Următoarele %d capitole necitite - Ești sigur\? Eroare la salvarea imaginii Actualizează tot diff --git a/i18n/src/commonMain/resources/MR/ru/plurals.xml b/i18n/src/commonMain/resources/MR/ru/plurals.xml new file mode 100644 index 0000000000..490b4bc85c --- /dev/null +++ b/i18n/src/commonMain/resources/MR/ru/plurals.xml @@ -0,0 +1,99 @@ + + + + После %1$s минуты + После %1$s минут + После %1$s минут + После %1$s минут + + + Главы %1$s и ещё одна + Главы %1$s и ещё %2$d + Главы %1$s и ещё %2$d + Главы %1$s и ещё %2$d + + + %1$d новая глава + %1$d новые главы + %1$d новых глав + %1$d новых глав + + + Для %d серии + Для %d серий + Для %d серий + Для %d серий + + + Доступно обновление для %d расширения + Доступны обновления для %d расширений + Доступны обновления для %d расширений + Доступны обновления для %d расширений + + + Осталась %1$s глава + Осталось %1$s главы + Осталось %1$s глав + Осталось %1$s глав + + + %d категория + %d категории + %d категорий + %d категорий + + + Выполнено за %1$s с %2$s ошибкой + Выполнено за %1$s с %2$s ошибками + Выполнено за %1$s с %2$s ошибками + Выполнено за %1$s с %2$s ошибками + + + %1$s глава + %1$s главы + %1$s глав + %1$s глав + + + %d отслеживание + %d отслеживания + %d отслеживаний + %d отслеживаний + + + Отсутствует %d глава + Отсутствуют %d главы + Отсутствуют %d глав + Отсутствуют %d глав + + + Вчера + %1$d дня назад + %1$d дней назад + %1$d дней назад + + + Следующая непрочитанная глава + Следующие %d непрочитанные главы + Следующие %d непрочитанных глав + Следующие %d непрочитанных глав + + + Следующая глава + Следующие %d главы + Следующие %d глав + Следующие %d глав + + + Отсутствует %1$s глава + Отсутствуют %1$s главы + Отсутствуют %1$s глав + Отсутствуют %1$s глав + + + 1 день + %d дня + %d дней + %d дней + + \ No newline at end of file diff --git a/i18n/src/main/res/values-ru/strings.xml b/i18n/src/commonMain/resources/MR/ru/strings.xml similarity index 92% rename from i18n/src/main/res/values-ru/strings.xml rename to i18n/src/commonMain/resources/MR/ru/strings.xml index c119024583..1eb0b2e283 100644 --- a/i18n/src/main/res/values-ru/strings.xml +++ b/i18n/src/commonMain/resources/MR/ru/strings.xml @@ -315,51 +315,21 @@ Блокировать при бездействии Всегда Никогда - - После %1$s минуты - После %1$s минут - После %1$s минут - После %1$s минут - Защита экрана приложения Доступны обновления Показывать содержимое в вырезанной области Не удалось обойти Cloudflare Пожалуйста, обновите WebView для лучшей совместимости Обновления глав - - Главы %1$s и ещё одна - Главы %1$s и ещё %2$d - Главы %1$s и ещё %2$d - Главы %1$s и ещё %2$d - Глава %1$s и ещё %2$d Главы %1$s Глава %1$s Отображение - - %1$d новая глава - %1$d новые главы - %1$d новых глав - %1$d новых глав - - - Для %d серии - Для %d серий - Для %d серий - Для %d серий - Проверка наличия новых глав Обновление библиотеки Оптимизация батареи уже выключена Помогает с обновлением библиотеки и резервной копией в фоне Отключить оптимизацию батареи - - Доступно обновление для %d расширения - Доступны обновления для %d расширений - Доступны обновления для %d расширений - Доступны обновления для %d расширений - Адрес электронной почты Переход между главами Скрыть содержимое уведомлений @@ -399,30 +369,12 @@ Не удалось создать резервную копию Резервная копия уже выполняется %02d мин, %02d сек - - Осталась %1$s глава - Осталось %1$s главы - Осталось %1$s глав - Осталось %1$s глав - Режим чтения Для этой серии Серый Уменьшает полосатость, но может влиять на производительность - - %d категория - %d категории - %d категорий - %d категорий - Не удалось открыть настройки устройства Обновить обложки серий - - Выполнено за %1$s с %2$s ошибкой - Выполнено за %1$s с %2$s ошибками - Выполнено за %1$s с %2$s ошибками - Выполнено за %1$s с %2$s ошибками - Односторонняя синхронизация для обновления прогресса в сторонних сервисах отслеживания. Настройте отслеживание при помощи кнопки «Отслеживание». Это расширение не входит в официальный список расширений. Неофициальное @@ -445,12 +397,6 @@ Начать Источник не найден Отключить - - %1$s глава - %1$s главы - %1$s глав - %1$s глав - Для вступления в силу требуется перезапуск приложения Сеть Обе оси @@ -467,12 +413,6 @@ Режим чтения Тема Последнее добавление серии - - %d отслеживание - %d отслеживания - %d отслеживаний - %d отслеживаний - У вас нет закреплённых источников Завершено Прогресс @@ -483,12 +423,6 @@ Источики из этого расширения могут содержать контент NSFW (18+) 18+ Это не предотвращает появление внутри приложения контента NSFW (18+) из неофициальных или потенциально неправильно помеченных расширений. - - Отсутствует %d глава - Отсутствуют %d главы - Отсутствуют %d глав - Отсутствуют %d глав - Нет глав Настройки главы по умолчанию были обновлены Установить по умолчанию @@ -598,12 +532,6 @@ Самая высокая Чувствительность скрытия меню при прокрутке Цвета наоборот - - Вчера - %1$d дня назад - %1$d дней назад - %1$d дней назад - Сегодня Бирюзовая Выполните аутентификацию, чтобы подтвердить изменение @@ -706,12 +634,6 @@ Обновление уже запущено User agent не может быть пустым Приливная Волна - - Следующая непрочитанная глава - Следующие %d непрочитанные главы - Следующие %d непрочитанных глав - Следующие %d непрочитанных глав - Загрузить наперёд При чтении Работает только если текущая + следующая главы уже загружены. @@ -781,24 +703,12 @@ \nВы всё ещё хотите продолжить\? %1$s ошибка: %2$s *необходимо - - Следующая глава - Следующие %d главы - Следующие %d глав - Следующие %d глав - Скрывать серии, уже находящиеся в библиотеке Копировать в буфер обмена Обновить категорию Разделять длинные изображения Наложение Развернуть широкие страницы под размер экрана - - Отсутствует %1$s глава - Отсутствуют %1$s главы - Отсутствуют %1$s глав - Отсутствуют %1$s глав - Отразить ориентацию развёрнутых широких страниц Отладочная информация Перелистывание глав @@ -818,12 +728,6 @@ Следующее ожидамое обновление За пределами ожидаемого периода выпуска Задать обновления каждые - - 1 день - %d дня - %d дней - %d дней - Пропущено, т.к сегодня не ожидается выпуска Удалить отслеживание %s\? Это удалит отслеживание в приложении. diff --git a/i18n/src/commonMain/resources/MR/sa/plurals.xml b/i18n/src/commonMain/resources/MR/sa/plurals.xml new file mode 100644 index 0000000000..de9efef9df --- /dev/null +++ b/i18n/src/commonMain/resources/MR/sa/plurals.xml @@ -0,0 +1,51 @@ + + + + एकनिमेषानन्तरम् + द्विनिमेषानन्तरम् + + + ह्यः + द्विदिनपूर्वम् + + + %d वर्गः + %d वर्गौ + + + %1$s समये %2$s दोषेण कृतम् + %1$s समये %2$s दोषाभ्यां कृतम् + + + १ अध्यायः + २ अध्यायौ + + + १ ट्राकर्तन्त्रांशः + २ ट्राकर्तन्त्रांशौ + + + १ शेषम् + २ शेषे + + + विस्तारनवीकरणम् उपलभ्यम् + द्वे विस्तारनवीकरणे उपलभ्ये + + + एकः नूतनाध्यायः + द्वौ नूतनाध्यायौ + + + एकाय शीर्षकाय + द्वाभ्यां शीर्षकाभ्याम् + + + अध्यायाः %1$s च इतोऽपि १ च + अध्यायाः %1$s च इतोऽपि २ च + + + १ अध्यायं लङ्घयति यतः मूले सः अनुपस्थितः अस्ति उत सः बहिः सम्मृष्टः कृतः + २ अध्यायौ लङ्घयति यतः मूले तौ अनुपस्थितौ स्तः उत तौ बहिः सम्मृष्टौ कृतौ + + \ No newline at end of file diff --git a/i18n/src/main/res/values-sa/strings.xml b/i18n/src/commonMain/resources/MR/sa/strings.xml similarity index 95% rename from i18n/src/main/res/values-sa/strings.xml rename to i18n/src/commonMain/resources/MR/sa/strings.xml index 115d2bdfed..a5e057ba01 100644 --- a/i18n/src/main/res/values-sa/strings.xml +++ b/i18n/src/commonMain/resources/MR/sa/strings.xml @@ -145,18 +145,10 @@ आवेदनवस्तु वृणोतु तिथिसंरूपम् कार्याभावे अपिदधातु - - एकनिमेषानन्तरम् - द्विनिमेषानन्तरम् - अभिरक्षणपटलम् अनुप्रयोगाणां परिवर्तने अनुप्रयोगवस्तु वृणोति पटलप्रतिकृतीनां च सृष्टिं निवारयति॥ प्रौढानां कृते एव (१८+) वस्तुमूलानि मूलानां विस्ताराणां च सूचीषु दर्शयतु अद्य - - ह्यः - द्विदिनपूर्वम् - प्रतिपङ्क्तौ वस्तूनि अनुप्रस्थम् प्रदर्शनम् @@ -196,10 +188,6 @@ विस्तारं प्रतिष्ठापयति … क्रमगतम् पूर्णपटलम् - - %d वर्गः - %d वर्गौ - प्रदत्तांशं स्वयञ्चालितं नवीकरोतु प्रतिवर्गं विन्यासस्य प्रदर्शनस्य च कृते समायोजनानि अविश्वस्तविस्तारः @@ -349,10 +337,6 @@ प्रतिलेखनं समाददाति प्रतिसंस्कारः अलोप्यत प्रतिसंस्कारं समापितम् - - %1$s समये %2$s दोषेण कृतम् - %1$s समये %2$s दोषाभ्यां कृतम् - यदि MIUI वृद्धिकरणम् अशक्तं कृतं तर्हि प्रतिलेखनम्/प्रतिसंस्कारः क्रियां युक्तं न कुर्यात्। स्वयङ्कृतप्रतिलेखनानि अतीव निर्दिशितानि। त्वया अन्यस्थानेषु अपि प्रतिकृतीनां स्थापनम् उचितं भविष्यति॥ प्रतिलेखनसञ्चिकायाः ग्रन्थालयं समाददातु @@ -447,10 +431,6 @@ दोषाः अवारोपितानि एव प्रगतिः - - १ अध्यायः - २ अध्यायौ - अवारोपणसाधनम् सामान्यम् प्रच्छन्ननामदशा @@ -478,10 +458,6 @@ फलितानि न लभ्यानि अध्यायसंरूपम् अनाप्तम् अनुप्रज्ञानं योजयतु - - १ ट्राकर्तन्त्रांशः - २ ट्राकर्तन्त्रांशौ - वर्गाः नाशिताः चित्रं रक्षितम् स्वकृतशोधकम् @@ -496,10 +472,6 @@ अध्यायनवीकरणानि अनुप्रयोगनवीकरणानि विस्तारनवीकरणानि - - १ शेषम् - २ शेषे - HTTPS उपरि DNS (DoH) प्रारम्भिकमार्गदर्शनम् साधनसमायोजनानि उद्घाटयितुं न अशक्नोम् @@ -508,14 +480,6 @@ पुटाः न लभ्याः मूलं न लभ्यम् नूतनसंस्करणम् उपलभ्यम् - - विस्तारनवीकरणम् उपलभ्यम् - द्वे विस्तारनवीकरणे उपलभ्ये - - - एकः नूतनाध्यायः - द्वौ नूतनाध्यायौ - माङ्गां दर्शयतु नूतनाध्यायाः लभ्याः केवलं मुखचित्रेण इष्टिकाविन्यासः @@ -532,10 +496,6 @@ प्रतिलेखनसञ्चिकां चिनोतु पुटान्तरे प्लवतु अनुप्रस्थचित्रं सर्पकं करोतु - - एकाय शीर्षकाय - द्वाभ्यां शीर्षकाभ्याम् - ग्रन्थालयमाङ्गामुखचित्राणि नवीकरोतु ध्वंसेतिवृत्तानि पातयतु उपारोपिततिथ्या @@ -571,10 +531,6 @@ जालसम्पर्कः न उपलभ्यः प्रतिलेखः अंशफलकान्ते कृतः - \n%1$s - - अध्यायाः %1$s च इतोऽपि १ च - अध्यायाः %1$s च इतोऽपि २ च - अध्यायः %1$s च इतोऽपि %2$d च सञ्चिकाग्राही अनुप्रयोगः न लभ्यः धारावाहिकः पूर्णः अतः लङ्घितः @@ -596,10 +552,6 @@ त्वं निश्चितरूपेण सङ्गृहीतान् अध्यायान् नाशयितुम् इच्छसि किम् \? त्वं निश्चितं किम्। पर-ग्रन्थालय-माङ्गानाम् अपिठाध्यायाः नष्टाः भविष्यन्ते पूर्वसूचना -- महद्भाराणि अवारोपणानि कुर्यात् मूलानि मन्दानि। अपि च टाचीयोमिं निवारयेत्॥ - - १ अध्यायं लङ्घयति यतः मूले सः अनुपस्थितः अस्ति उत सः बहिः सम्मृष्टः कृतः - २ अध्यायौ लङ्घयति यतः मूले तौ अनुपस्थितौ स्तः उत तौ बहिः सम्मृष्टौ कृतौ - व्युत्पादकेभ्यः प्रसारयितुं दोषदत्तम् एकस्यां सञ्चिकायां रक्षति इमानि समायोजनानि प्राथमिकानि इव रक्षितुं त्वं निश्चितं किम् स्खलितानां परिहरणे साहाय्यं करिष्यति। संवेदनशीलदत्तांशाः न प्रेषिष्यते॥ diff --git a/i18n/src/commonMain/resources/MR/sah/plurals.xml b/i18n/src/commonMain/resources/MR/sah/plurals.xml new file mode 100644 index 0000000000..3f3fe03ad8 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/sah/plurals.xml @@ -0,0 +1,24 @@ + + + + %d бөлөхтөр + + + %1$s мүнүүтэ кэннэ + + + Туолла %1$sҕа %2$s сыаһалаах + + + %1$s хаалла + + + %1$s түһүмэх + + + %d трэкэр + + + Манна %d түһүмэх суох + + \ No newline at end of file diff --git a/i18n/src/main/res/values-sah/strings.xml b/i18n/src/commonMain/resources/MR/sah/strings.xml similarity index 97% rename from i18n/src/main/res/values-sah/strings.xml rename to i18n/src/commonMain/resources/MR/sah/strings.xml index 99b6014626..e33dbadb30 100644 --- a/i18n/src/main/res/values-sah/strings.xml +++ b/i18n/src/commonMain/resources/MR/sah/strings.xml @@ -50,9 +50,6 @@ Түстэл Эбии Аат - - %d бөлөхтөр - Наар ыйыт Куолутунан бөлөх Саҥа тас уонна кыра чаастар баалларын, бэрэбиэркэлээ @@ -75,9 +72,6 @@ Биллэрии иһин кистээ Атын эбиликкэ көһөргөр, скриншоту сабаргар, эбилик иһин кистээ Көмүскэл экрана - - %1$s мүнүүтэ кэннэ - Хаһан да Наар Күүтү эрэһиимигэр сап @@ -236,9 +230,6 @@ Хаппаас куопуйа оҥоһуута Тугу куопуйалаары гынннын\? Хаппаас куопуйа оҥоруута туола турар - - Туолла %1$sҕа %2$s сыаһалаах - %02d мүнүүтэ %02d сөкүүндэ Төнүҥнэри бүттэ Трэкэрдар киирбэтилэр: @@ -309,17 +300,11 @@ Эл.пуoчта аадырыһа Туттааччы аата %1$s\'га киири - - %1$s хаалла - Бэбэлэтиэкэҕэ баар маанганы барытын биилтирдээһин Хачайдаммыт эрэ Ханнык баҕар сыаһалары көннөрөргө көмөлөһөр. Бэйэ дааннайдар ылыллыбаттар Охтуу туһунан отчуоту ыытыы Хачайдаммыт түһүмэхтэри сотторобут\? - - %1$s түһүмэх - Кырата Эбии Бэбэлэтиэкэттэн ылылынна @@ -378,9 +363,6 @@ Бүппүт Ааҕабын эбии кэтээһини киллэрии - - %d трэкэр - Бу сиэриэҕэ Бу ойууну тас курдук туттаҕын дуо\? Ойуу кыайан хачайдаммата @@ -390,9 +372,6 @@ Тас курдук туруор %1$s-%2$s Түһ. Бэбэлэтиэкэ саҥардыыта - - Манна %d түһүмэх суох - Төрүт булуллубата Сирэйдэр булуллубатылар Сирэйдэр хачайдааһыннара сатаммата: %1$s diff --git a/i18n/src/commonMain/resources/MR/sc/plurals.xml b/i18n/src/commonMain/resources/MR/sc/plurals.xml new file mode 100644 index 0000000000..5153328218 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/sc/plurals.xml @@ -0,0 +1,67 @@ + + + + A pustis de %1$s minutu + A pustis de %1$s minutos + + + %1$d capìtulu nou + %1$d capìtulos noos + + + Capìtulos %1$s e 1 àteru + Capìtulos %1$s e àteros %2$d + + + Pro %d elementu + Pro %d elementos + + + B\'at un\'agiornamentu disponìbile pro un\'estensione + B\'ant agiornamentos disponìbiles pro %d estensiones + + + Nd\'abarrat %1$s + Nd\'abarrant %1$s + + + %d categoria + %d categorias + + + Fatu in %1$s cun %2$s errore + Fatu in %1$s cun %2$s errores + + + %1$s capìtulu + %1$s capìtulos + + + %d arrastadore + %d arrastadores + + + Brinchende %d capìtulu, sa fonte non lu tenet o est istadu bogadu cun unu filtru + Brinchende %d capìtulos, sa fonte non los tenet o sunt istados bogados cun unu filtru + + + Eris + %1$d dies a oe + + + Su capìtulu non lèghidu imbeniente + Sos %d capìtulos non lèghidos imbenientes + + + Su capìtulu imbeniente + Sos %d capìtulos imbenientes + + + Mancat %1$s capìtulu + Mancant %1$s capìtulos + + + 1 die + %d dies + + \ No newline at end of file diff --git a/i18n/src/main/res/values-sc/strings.xml b/i18n/src/commonMain/resources/MR/sc/strings.xml similarity index 95% rename from i18n/src/main/res/values-sc/strings.xml rename to i18n/src/commonMain/resources/MR/sc/strings.xml index 8480f152dd..c54c10a42f 100644 --- a/i18n/src/main/res/values-sc/strings.xml +++ b/i18n/src/commonMain/resources/MR/sc/strings.xml @@ -315,10 +315,6 @@ Bloca cando no est ativu Semper Mai - - A pustis de %1$s minutu - A pustis de %1$s minutos - Ischermu seguru Agiornamentos in suspesu Ammustra sos cuntenutos in s\'àrea de retàlliu @@ -327,17 +323,9 @@ Agiornamentos de sos capìtulos S\'ischermu seguru cuat sos cuntenutos de s\'aplicatzione cando mudas de aplicatzione e blocat sas ischermadas Visualizatzione - - %1$d capìtulu nou - %1$d capìtulos noos - Capìtulu %1$s Capìtulu %1$s e àteros %2$d Capìtulos %1$s - - Capìtulos %1$s e 1 àteru - Capìtulos %1$s e àteros %2$d - Cua su cuntenutu de sas notìficas Chirchende capìtulos noos Disabìlita s\'otimizatzione de sa bateria @@ -345,19 +333,11 @@ S\'otimizatzione de sa bateria est giai disabilitada Indiritzu de posta eletrònica Ammustra semper sa transitzione de capìtulu - - Pro %d elementu - Pro %d elementos - Menù Prus noos Prus betzos Manda a pitzus Manda a fundu - - B\'at un\'agiornamentu disponìbile pro un\'estensione - B\'ant agiornamentos disponìbiles pro %d estensiones - Agiornamentos de sas estensiones Agiornende sa biblioteca Leghende @@ -389,23 +369,11 @@ %02d min e %02d seg Ghia a sas fontes locales Filtrat totu sos elementos in sa biblioteca tua - - Nd\'abarrat %1$s - Nd\'abarrant %1$s - Pro custa sèrie Murru - - %d categoria - %d categorias - Mìnimat sa creatzione de bandas, ma diat pòdere influentzare sas prestatziones Modalidade de leghidura Abertura de sas impostatziones de sistema fallida - - Fatu in %1$s cun %2$s errore - Fatu in %1$s cun %2$s errores - Sincronizatzione a una diretzione ebbia pro agiornare su progressu in sos capìtulos in servìtzios de arrastamentu esternos. Imposta s\'arrastamentu pro sos elementos dae su butone de arrastamentu issoro. Annoa sas coberteddas de sa biblioteca Custa estensione non benit dae sa lista ufitziale. @@ -429,10 +397,6 @@ Incumintza Fonte no agatada Disabìlita - - %1$s capìtulu - %1$s capìtulos - Tenet bisòngiu chi torres a allùghere s\'aplicatzione pro tènnere efetu Retza Ambos @@ -449,10 +413,6 @@ Modalidade de leghidura Tema Data de annanghidura - - %d arrastadore - %d arrastadores - Non tenes fontes apicadas Acabada Progressu @@ -463,10 +423,6 @@ Sas fontes de custa estensione diant pòdere cuntènnere cuntenutos NSFW (18+) 18+ Custu no impedit a estensiones no ufitziales o potentzialmente non curretas de ammustrare cuntenutos NSFW (18+) in s\'aplicatzione. - - Brinchende %d capìtulu, sa fonte non lu tenet o est istadu bogadu cun unu filtru - Brinchende %d capìtulos, sa fonte non los tenet o sunt istados bogados cun unu filtru - Perunu capìtulu agatadu Impostatziones predefinidas de sos capìtulos agiornadas Imposta comente predefinidu @@ -576,10 +532,6 @@ Sensibilidade pro cuare su menù cun s\'iscurrimentu Atividade in s\'isfundu Furriada - - Eris - %1$d dies a oe - Oe Birde abba e turchesu Autèntica·ti pro cunfirmare sa modìfica @@ -684,10 +636,6 @@ S\'istringa de s\'agente de s\'utente non podet èssere bòida Iscàrriga sos imbenientes Iscàrriga in automàticu durante sa letura - - Su capìtulu non lèghidu imbeniente - Sos %d capìtulos non lèghidos imbenientes - Funtzionat petzi si su capìtulu atuale e s\'imbeniente sunt giai iscarrigados. Seguru ses\? As a bogare \"%s\" dae sa biblioteca tua @@ -755,10 +703,6 @@ A disponimentu ma sa fonte no est installada: %s Errore %1$s: %2$s *netzessàriu - - Su capìtulu imbeniente - Sos %d capìtulos imbenientes - Cua sos elementos giai in sa biblioteca Còpia in punta de billete Agiorna sa categoria @@ -766,10 +710,6 @@ Istratu superiore Gira sas pàginas largas pro las adatare Fùrria s\'orientamentu de sas pàginas largas giradas - - Mancat %1$s capìtulu - Mancant %1$s capìtulos - %d pro riga Tocu dòpiu pro ismanniare Atzione de iscurrimentu a destra @@ -793,10 +733,6 @@ Bogare s\'arrastadore de %s\? Custu at a bogare s\'arrastamentu locale. Boga fintzas dae %s - - 1 die - %d dies - Iscantzella sos iscarrigados Toca inoghe pro agiudu cun Cloudflare Isbloca %s diff --git a/i18n/src/commonMain/resources/MR/sdh/plurals.xml b/i18n/src/commonMain/resources/MR/sdh/plurals.xml new file mode 100644 index 0000000000..b60744cc2f --- /dev/null +++ b/i18n/src/commonMain/resources/MR/sdh/plurals.xml @@ -0,0 +1,11 @@ + + + + پاش 1 خولەک + پاش %1$s خولەک + + + دوێنێ + %1$d ڕۆژ پێش ئێستا + + \ No newline at end of file diff --git a/i18n/src/main/res/values-sdh/strings.xml b/i18n/src/commonMain/resources/MR/sdh/strings.xml similarity index 98% rename from i18n/src/main/res/values-sdh/strings.xml rename to i18n/src/commonMain/resources/MR/sdh/strings.xml index bda3063c93..6172e7469f 100644 --- a/i18n/src/main/res/values-sdh/strings.xml +++ b/i18n/src/commonMain/resources/MR/sdh/strings.xml @@ -185,14 +185,6 @@ شێوازی دوو ‌هێندە داونلۆدی ئۆتۆماتیکی داونلۆدکردنی چاپتەری نوێ - - پاش 1 خولەک - پاش %1$s خولەک - - - دوێنێ - %1$d ڕۆژ پێش ئێستا - بەدواداچوون زیاد بکە کردنە ناو کۆکراوەکان تکایە مانگا بۆ کۆکراوەکان زیاد بکە پێش کردنی ئەمە diff --git a/i18n/src/commonMain/resources/MR/sk/plurals.xml b/i18n/src/commonMain/resources/MR/sk/plurals.xml new file mode 100644 index 0000000000..b58084ecf3 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/sk/plurals.xml @@ -0,0 +1,68 @@ + + + + Pre %d titul + Pre %d tituly + Pre %d titulov + + + Dostupná aktualizácia rozšírenia + %d dostupných aktualizácii rozšírenia + %d dostupné aktualizácie rozšírenia + + + %1$d nová kapitola + %1$d nové kapitoly + %1$d nových kapitol + + + Po %1$s minute + Po %1$s minútach + Po %1$s minútach + + + Včera + Pred %1$d dňami + Pred %1$d dňami + + + %d sledovač + %d sledovače + %d sledovačov + + + Ďalšia neprečítaná kapitola + Ďalšie %d neprečítané kapitoly + Ďalších %d neprečítaných kapitol + + + %1$s zostáva + %1$s zostávajúce + %1$s zostávajúcich + + + Kapitoly %1$s a 1 ďalšia + Kapitoly %1$s a %2$d ďalšie + Kapitoly %1$s a %2$d ďalších + + + %1$s kapitola + %1$s kapitoly + %1$s kapitol + + + Preskočenie %d kapitoly, buď zdroj chýba, alebo bol odfiltrovaný + Preskočenie %d kapitol, buď zdroj chýba, alebo bol odfiltrovaný + Zložky %d kapitoly, buď zdroj chýba, alebo boli filtrované + + + Dokončené za %1$s s %2$s chybou + Dokončené za %1$s s %2$s chybami + Dokončené za %1$s s %2$s chybami + + + %d kategória + %d kategórie + %d kegórií + + \ No newline at end of file diff --git a/i18n/src/main/res/values-sk/strings.xml b/i18n/src/commonMain/resources/MR/sk/strings.xml similarity index 93% rename from i18n/src/main/res/values-sk/strings.xml rename to i18n/src/commonMain/resources/MR/sk/strings.xml index 1068368260..b095dc1f17 100644 --- a/i18n/src/main/res/values-sk/strings.xml +++ b/i18n/src/commonMain/resources/MR/sk/strings.xml @@ -306,11 +306,6 @@ Nepodarilo sa obísť službu Cloudflare Pozastavené Neprečítané - - Pre %d titul - Pre %d tituly - Pre %d titulov - Hľadám nové kapitoly Skryť obsah upozornení Zakázať všetko @@ -323,19 +318,9 @@ Predvolené Zdroje Viac - - Dostupná aktualizácia rozšírenia - %d dostupných aktualizácii rozšírenia - %d dostupné aktualizácie rozšírenia - Kapitoly %1$s Kapitola %1$s a %2$d ďalšie Kapitola %1$s - - %1$d nová kapitola - %1$d nové kapitoly - %1$d nových kapitol - Zabezpečená obrazovka Ťuknutím zobrazíte podrobnosti Podľa systému @@ -360,11 +345,6 @@ Vzostupne Zostupne Presunúť na spodok - - Po %1$s minute - Po %1$s minútach - Po %1$s minútach - Zakázať Odopnúť Upozornenie @@ -398,11 +378,6 @@ S neprečítanými kapitolami Ktoré sa ešte nezačali Toto nastavenie avšak nebráni tomu, aby sa v aplikácii objavil neoficiálny alebo potenciálne nesprávne označený obsah NSFW (18+). - - Včera - Pred %1$d dňami - Pred %1$d dňami - Globálna aktualizácia Automatický obnoviť metadata Pri aktualizácii knižnice skontrolujte nový obal a podrobnosti @@ -447,11 +422,6 @@ Pomôžte s prekladom Licencia Open Source Chyba pri zdieľaní obalu - - %d sledovač - %d sledovače - %d sledovačov - Zdroj sa nenašiel No, toto je trápne WebView je potrebné pre Tachiyomi @@ -533,11 +503,6 @@ Nastaviť ako predvolené Jednosmerná synchronizácia na aktualizáciu priebehu kapitol v službách sledovania. Nastavte sledovanie pre jednotlivé položky mangy z ich tlačidla sledovania. Režim čítania - - Ďalšia neprečítaná kapitola - Ďalšie %d neprečítané kapitoly - Ďalších %d neprečítaných kapitol - Vynechané Aktualizácie kapitol V databáze je manga %1$d, ktorá sa nenachádza v knižnici @@ -546,11 +511,6 @@ Obnovenie režimu čítania a orientácie pre všetky série Podrobné logovanie Skontrolovať aktualizácie - - %1$s zostáva - %1$s zostávajúce - %1$s zostávajúcich - Kap. %1$s - %2$s Strana %d sa pri rozdeľovaní nenašla Publikovanie ukončené @@ -597,11 +557,6 @@ Zdroj nie je podporovaný Nenainštalované %1$s: %2$s, strana %3$d - - Kapitoly %1$s a 1 ďalšia - Kapitoly %1$s a %2$d ďalšie - Kapitoly %1$s a %2$d ďalších - Typ rotácie Zatvoriť Záznamy vo vylúčených kategóriách nebudú aktualizované, aj keď sú tiež v zahrnutých kategóriách. @@ -643,16 +598,6 @@ Nepodarilo sa otvoriť nastavenia zariadenia Niektorí výrobcovia majú ďalšie obmedzenia aplikácií, ktoré vypínajú služby na pozadí. Na tejto webovej stránke nájdete viac informácií o tom, ako to opraviť. Režim čítania - - %1$s kapitola - %1$s kapitoly - %1$s kapitol - - - Preskočenie %d kapitoly, buď zdroj chýba, alebo bol odfiltrovaný - Preskočenie %d kapitol, buď zdroj chýba, alebo bol odfiltrovaný - Zložky %d kapitoly, buď zdroj chýba, alebo boli filtrované - Chyba pri ukladaní obrázka Aktualizácie aplikácie Widget nie je k dispozícii, keď je povolený zámok aplikácie @@ -678,16 +623,6 @@ Sledovať Webová stránka Akcie - - Dokončené za %1$s s %2$s chybou - Dokončené za %1$s s %2$s chybami - Dokončené za %1$s s %2$s chybami - - - %d kategória - %d kategórie - %d kegórií - Vlastný obal Presunúť sériu na začiatok Zásady ochrany osobných údajov diff --git a/i18n/src/commonMain/resources/MR/sq/plurals.xml b/i18n/src/commonMain/resources/MR/sq/plurals.xml new file mode 100644 index 0000000000..afe747db76 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/sq/plurals.xml @@ -0,0 +1,59 @@ + + + + Pas %1$s minutë + Pas %1$s minutash + + + Dje + %1$d ditë më parë + + + %d kategori + %d kategoritë + + + Kapitulli tjetër i palexuar + %d kapitujt e ardhshëm të palexuar + + + %1$s e mbetur + %1$s kanë mbetur + + + Përfunduar në %1$s me %2$s gabim + Përfunduar në %1$s me %2$s gabime + + + Ofrohet përditësim i shtesës + Ofrohen %d përditësime shtesë + + + Po kalon %d kapitull, ose i mungon burimi ose është filtruar + Po kalon %d kapituj, ose i mungon burimi ose është filtruar + + + %1$d kapitull i ri + %1$d kapituj të rinj + + + Kapitujt %1$s dhe 1 më shumë + Kapitujt %1$s dhe %2$d të tjerë + + + Për %d hyrje + Për %d hyrjet + + + %d gjurmues + %d gjurmuesit + + + %1$s kapitull + %1$s kapituj + + + Kapitulli i rradhës + %d kapituj të rradhës + + \ No newline at end of file diff --git a/i18n/src/main/res/values-sq/strings.xml b/i18n/src/commonMain/resources/MR/sq/strings.xml similarity index 95% rename from i18n/src/main/res/values-sq/strings.xml rename to i18n/src/commonMain/resources/MR/sq/strings.xml index e8578d4773..eeed53f501 100644 --- a/i18n/src/main/res/values-sq/strings.xml +++ b/i18n/src/commonMain/resources/MR/sq/strings.xml @@ -41,19 +41,11 @@ Kyç kur është i papunë Gjithmonë Kurrë - - Pas %1$s minutë - Pas %1$s minutash - Fshih përmbajtjen e njoftimit Ekran i sigurt Burimet NSFW (18+) Shfaq në listat e burimeve dhe shtesave Sot - - Dje - %1$d ditë më parë - Shfaqja Artikuj për rresht Përditësim global @@ -68,10 +60,6 @@ Me kapituj të palexuar Kontrolloni për kopertinë dhe detaje të reja kur përditësoni bibliotekën Kategoria e parazgjedhur - - %d kategori - %d kategoritë - Regjistrimet në kategoritë e përjashtuara nuk do të përditësohen edhe nëse janë gjithashtu në kategoritë e përfshira. Të gjitha Asnje @@ -367,10 +355,6 @@ Ruaje si arkiv CBZ Udhëzues gjurmimi Shërbime të përmirësuara - - Kapitulli tjetër i palexuar - %d kapitujt e ardhshëm të palexuar - Nuk ka kapitull tjetër Krijon dosje sipas titullit të hyrjeve E zezë @@ -453,14 +437,6 @@ Hapni në GitHub Shkarko Prekni për të instaluar përditësimin - - %1$s e mbetur - %1$s kanë mbetur - - - Përfunduar në %1$s me %2$s gabim - Përfunduar në %1$s me %2$s gabime - Nuk ka kapitull të mëparshëm Asgjë për të pastruar Çaktivizo modalitetin e fshehtë @@ -523,10 +499,6 @@ %1$d përditësim(e) u anashkalua Për ndihmë se si të rregulloni gabimet e përditësimit të bibliotekës, shihni %1$s Një version i ri është në dispozicion nga publikimet zyrtare. Prekni për të mësuar se si të migroni nga publikimet jozyrtare të F-Droid. - - Ofrohet përditësim i shtesës - Ofrohen %d përditësime shtesë - Krijo kopje rezervë Mund të përdoret për të rivendosur bibliotekën aktuale Rivendos kopjen rezervë @@ -643,10 +615,6 @@ Nuk u gjet asnjë faqe Burimi nuk u gjet Një përditësim po funksionon tashmë - - Po kalon %d kapitull, ose i mungon burimi ose është filtruar - Po kalon %d kapituj, ose i mungon burimi ose është filtruar - Biblioteka po përditësohet Biblioteka e përditësuar së fundi: %s Vetëm tani @@ -663,20 +631,8 @@ Paralajmërim: shkarkimet e mëdha me shumicë mund të çojnë në ngadalësimin e burimeve dhe/ose bllokimin e Tachiyomi. Trokit për të mësuar më shumë. Duke kontrolluar për kapituj të rinj U gjetën kapituj të rinj - - %1$d kapitull i ri - %1$d kapituj të rinj - - - Kapitujt %1$s dhe 1 më shumë - Kapitujt %1$s dhe %2$d të tjerë - Trokit për të mësuar më shumë Përditësimi i kopertinës dështoi - - Për %d hyrje - Për %d hyrjet - U anashkalua sepse ka kapituj të palexuar U anashkalua sepse nuk lexohet asnjë kapitull U anashkalua sepse seritë nuk kërkojnë përditësime @@ -685,15 +641,7 @@ Po shkarkohet… Versioni i ri në dispozicion! Cilësimet e kapitullit të parazgjedhur të përditësuara - - %d gjurmues - %d gjurmuesit - Perëndim Mesnate - - %1$s kapitull - %1$s kapituj - Rivendosni bibliotekën nga skedari rezervë Të dhënat nga skedari rezervë do të rikthehen. \n @@ -754,10 +702,6 @@ Ju keni një hyrje në librarni me të njëjtin emër. \n \nDëshironi të vazhdoni\? - - Kapitulli i rradhës - %d kapituj të rradhës - Përditëso kategorinë %1$s gabim: %2$s *kërkohet diff --git a/i18n/src/commonMain/resources/MR/sr/plurals.xml b/i18n/src/commonMain/resources/MR/sr/plurals.xml new file mode 100644 index 0000000000..3559f7cf86 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/sr/plurals.xml @@ -0,0 +1,83 @@ + + + + Након %1$s минут + Након %1$s минута + Након %1$s минута + + + %1$d ново поглавље + %1$d нова поглавља + %1$d нових поглавља + + + За %d наслов + За %d наслова + За %d наслова + + + Доступно је %d ново ажурирање додатака + Доступна су %d нова ажурирања додатака + Доступно је %d нових ажурирања додатака + + + %d категорија + %d категорије + %d категорија + + + Pre %1$d dan + Pre %1$d dana + Pre %1$d dana + + + Прескаче се %d поглавље, или не постоји у извору или је филтером издвојено + Прескаче се %d поглавља, или не постоји у извору или је филтером издвојено + Прескаче се %d поглавља, или не постоји у извору или је филтером издвојено + + + Завршено у %1$s са %2$s грешком + Завршено у %1$s са %2$s грешке + Завршено у %1$s са %2$s грешака + + + %d трекер + %d трекера + %d трекера + + + %1$s поглавље + %1$s поглавља + %1$s поглавља + + + Поглавља %1$s и још једно + Поглавља %1$s и још %2$d + Поглавља %1$s и још %2$d + + + %1$s преостао + %1$s преостала + %1$s преосталих + + + Следеће непрочитано поглавље + Следећа %d непрочитана поглавља + Следећих %d непрочитаних поглавља + + + Следеће поглавље + Следећа %d поглавља + Следећих %d поглавља + + + Недостаје %1$s поглавље + Недостају %1$s поглавља + Недостаје %1$s поглавља + + + 1 дан + %d дана + %d дана + + \ No newline at end of file diff --git a/i18n/src/main/res/values-sr/strings.xml b/i18n/src/commonMain/resources/MR/sr/strings.xml similarity index 93% rename from i18n/src/main/res/values-sr/strings.xml rename to i18n/src/commonMain/resources/MR/sr/strings.xml index 075ce92ec5..8106d435be 100644 --- a/i18n/src/main/res/values-sr/strings.xml +++ b/i18n/src/commonMain/resources/MR/sr/strings.xml @@ -247,11 +247,6 @@ Закључај приликом мировања Увек Никада - - Након %1$s минут - Након %1$s минута - Након %1$s минута - Безбедносни екран Ажурирања на чекању Прикажи @@ -279,17 +274,7 @@ Немате категорија. Додирните дугме плус да бисте направили нову категорију за организовање колекције. Поглавља %1$s Поглавље %1$s и још %2$d - - %1$d ново поглавље - %1$d нова поглавља - %1$d нових поглавља - Поглавље %1$s - - За %d наслов - За %d наслова - За %d наслова - Пронађена су нова поглавља Тражење нових поглавља Неуспешно преузимање поглавља. Покушајте поново у секцији за преузимања @@ -361,11 +346,6 @@ Ажурирајте WebView за бољу компатибилност WebView је потребан како би апликација функционисала Неуспешно заобилажење Cloudflare-а - - Доступно је %d ново ажурирање додатака - Доступна су %d нова ажурирања додатака - Доступно је %d нових ажурирања додатака - Доступно је ново ажурирање! Грешка током преузимања Додирните за инсталирање ажурирања @@ -391,11 +371,6 @@ 18+ Овај додатак није из званичне листе. Незванично - - %d категорија - %d категорије - %d категорија - Провери да ли постоје нови омоти при ажурирању колекције Аутоматски освежи метаподатке Ово не спречава незваничне или потенцијално погрешно означене додатке да прикажу садржај за одрасле (18+) унутар апликације. @@ -428,25 +403,10 @@ Потпуно црна тема NSFW - извори за одрасле (18+) Показати у листи за изворе и додатке - - Pre %1$d dan - Pre %1$d dana - Pre %1$d dana - Начин читања Инсталер - - Прескаче се %d поглавље, или не постоји у извору или је филтером издвојено - Прескаче се %d поглавља, или не постоји у извору или је филтером издвојено - Прескаче се %d поглавља, или не постоји у извору или је филтером издвојено - Аутоматско преузимање Прати - - Завршено у %1$s са %2$s грешком - Завршено у %1$s са %2$s грешке - Завршено у %1$s са %2$s грешака - Резервна копија/враћање можда неће радити исправно ако није омогућена MIUI оптимизација. Чувајте резервне копије и на другим местима. DNS преко HTTPS-а (DoH) @@ -468,11 +428,6 @@ Картице Непознат статус Поређај по - - %d трекер - %d трекера - %d трекера - Побољшани сервиси Неисправна датотека резервне копије Недостају извори: @@ -496,11 +451,6 @@ Немате закачених извора Поглавље није пронађено Неважећи формат поглавља - - %1$s поглавље - %1$s поглавља - %1$s поглавља - Неуспешно копирање Према датуму поставке Грешка при чувању омота @@ -536,11 +486,6 @@ Посветли (Dodge) Водич за праћење Осетљивост за сакривање менија при померању - - Поглавља %1$s и још једно - Поглавља %1$s и још %2$d - Поглавља %1$s и још %2$d - Прикажи начин навигације Датум завршетка Аутоматски @@ -554,11 +499,6 @@ Начин навигације Непознат аутор Није пронађен програм за бирање датотека - - %1$s преостао - %1$s преостала - %1$s преосталих - Грешке Подешавања поглавља Данас @@ -742,11 +682,6 @@ Прескочено јер наслов не захтева ажурирање Страница %d није пронађена током раздвајања Провера преузимања - - Следеће непрочитано поглавље - Следећа %d непрочитана поглавља - Следећих %d непрочитаних поглавља - Не сада Формат теме, датума и времена Закључавање апликације, сигуран екран @@ -777,20 +712,10 @@ Превуци улево Прелистај поглавље Додирни двапут за зумирање - - Следеће поглавље - Следећа %d поглавља - Следећих %d поглавља - Копирај Окрени положај широких страница Прилагоди широке странице ротирањем Информације за отклањање грешака - - Недостаје %1$s поглавље - Недостају %1$s поглавља - Недостаје %1$s поглавља - Није могуће створити датотеку резервне копије Лиценцирано - Нема поглавља за приказ Има резултата @@ -798,11 +723,6 @@ Изван очекиваног периода изласка Постави интервалу Испуштено\? Задњих 20+ и 2 месеца - - 1 дан - %d дана - %d дана - Интервали Подеси интервал Такође уклони из %s diff --git a/i18n/src/commonMain/resources/MR/sv/plurals.xml b/i18n/src/commonMain/resources/MR/sv/plurals.xml new file mode 100644 index 0000000000..1e7f8b9372 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/sv/plurals.xml @@ -0,0 +1,67 @@ + + + + Efter %1$s minut + Efter %1$s minuter + + + %1$d nytt kapitel + %1$d nya kapitel + + + Kapitel %1$s och 1 till + Kapitlen %1$s och %2$d till + + + För %d post + För %d poster + + + Tilläggsuppdatering tillgänglig + %d tilläggsuppdateringar tillgängliga + + + %1$s återstående + %1$s återstående + + + %d kategori + %d kategorier + + + Klar på %1$s med %2$s fel + Klar på %1$s med %2$s fel + + + %1$s kapitel + %1$s kapitel + + + %d spårare + %d spårare + + + Hoppar över %d kapitel, antingen saknar källan det eller så har det filtrerats bort + Hoppar över %d kapitel, antingen saknar källan dem eller så har de filtrerats bort + + + Igår + För %1$d dagar sedan + + + Nästa olästa kapitel + Nästa %d olästa kapitel + + + Saknar %1$s kapitel + Saknar %1$s kapitel + + + 1 dag + %d dagar + + + Nästa kapitel + Nästa %d kapitel + + \ No newline at end of file diff --git a/i18n/src/main/res/values-sv/strings.xml b/i18n/src/commonMain/resources/MR/sv/strings.xml similarity index 95% rename from i18n/src/main/res/values-sv/strings.xml rename to i18n/src/commonMain/resources/MR/sv/strings.xml index ec88cded11..d871040a1b 100644 --- a/i18n/src/main/res/values-sv/strings.xml +++ b/i18n/src/commonMain/resources/MR/sv/strings.xml @@ -315,10 +315,6 @@ Lås vid inaktivitet Alltid Aldrig - - Efter %1$s minut - Efter %1$s minuter - Säker skärm Uppdateringar väntar Visa innehåll i utskärningsområdet @@ -327,17 +323,9 @@ Kapiteluppdateringar Säker skärm döljer appinnehållet när du byter app och blockerar skärmdumpar Skärmvisning - - %1$d nytt kapitel - %1$d nya kapitel - Kapitel %1$s Kapitel %1$s och %2$d till Kapitlen %1$s - - Kapitel %1$s och 1 till - Kapitlen %1$s och %2$d till - Dölj notisinnehåll Letar efter nya kapitel Inaktivera batterioptimering @@ -345,20 +333,12 @@ Batterioptimering är redan inaktiverat E-postadress Visa alltid kapitelövergång - - För %d post - För %d poster - Meny Nyaste Äldsta Flytta till toppen Flytta till botten Tilläggsuppdateringar - - Tilläggsuppdatering tillgänglig - %d tilläggsuppdateringar tillgängliga - Uppdaterar biblioteket Läser Hoppa över filtrerade kapitel @@ -389,22 +369,10 @@ %02d minuter, %02d sekunder Endast nedladdat Filtrerar alla poster i ditt bibliotek - - %1$s återstående - %1$s återstående - Läsläge För denna serie Grå Minskar bandning, men kan påverka prestandan - - %d kategori - %d kategorier - - - Klar på %1$s med %2$s fel - Klar på %1$s med %2$s fel - Det gick inte att öppna enhetsinställningarna Uppdatera bibliotekets omslag Envägssynkronisering för att uppdatera kapitlets framsteg i externa spårningstjänster. Ställ in spårning för enskilda poster från deras spårningsknapp. @@ -433,10 +401,6 @@ Ingen Invertera tryckzoner Källan hittades inte - - %1$s kapitel - %1$s kapitel - Okänd status Okänd författare Kräver omstart av appen för att börja gälla @@ -451,10 +415,6 @@ Datum tillagd Färdig Förlopp - - %d spårare - %d spårare - Du har inga fästa källor Tillåt att radera bokmärkta kapitel Ta bort kapitel @@ -465,10 +425,6 @@ Fel Uppdaterade standardinställningar för kapitel Vill du spara de här inställningarna som standard\? - - Hoppar över %d kapitel, antingen saknar källan det eller så har det filtrerats bort - Hoppar över %d kapitel, antingen saknar källan dem eller så har de filtrerats bort - %1$s: %2$s, sida %3$d Inga kapitel hittades Ange som standard @@ -576,10 +532,6 @@ Högsta Känslighet för att dölja menyn vid rullning Omvänd - - Igår - För %1$d dagar sedan - Idag Teal och turkos Utseende @@ -679,10 +631,6 @@ RARv5 formatet stöds inte Se dina nyligen uppdaterade biblioteket inlägg Widget är inte tillgänglig när applåset är aktiverat - - Nästa olästa kapitel - Nästa %d olästa kapitel - En uppdatering pågår redan Multi Strängen för användaragent kan inte vara tom @@ -733,10 +681,6 @@ Dölja poster som redan finns i biblioteket Kontrollerar nedladdningar Överlägg - - Saknar %1$s kapitel - Saknar %1$s kapitel - Rotera breda sidor så att de passar Vänd orientering av roterade breda sidor *krävs @@ -744,10 +688,6 @@ Genomsnittlig poäng %dm %ds - - 1 dag - %d dagar - Använd N/A Du har en post i ditt bibliotek med samma namn. @@ -768,10 +708,6 @@ Spårade inlägg %dd Anpassa intervall - - Nästa kapitel - Nästa %d kapitel - %1$s fel: %2$s Avhoppad\? Sen 20+ och 2 månader Godkänd kontrollperiod diff --git a/i18n/src/commonMain/resources/MR/te/plurals.xml b/i18n/src/commonMain/resources/MR/te/plurals.xml new file mode 100644 index 0000000000..c09f50b58e --- /dev/null +++ b/i18n/src/commonMain/resources/MR/te/plurals.xml @@ -0,0 +1,7 @@ + + + + ఒక నిమిషము తరువాత + %1$s నిమిషముల తరువాత + + \ No newline at end of file diff --git a/i18n/src/main/res/values-te/strings.xml b/i18n/src/commonMain/resources/MR/te/strings.xml similarity index 98% rename from i18n/src/main/res/values-te/strings.xml rename to i18n/src/commonMain/resources/MR/te/strings.xml index 1ee8a80af9..afa2fba6d3 100644 --- a/i18n/src/main/res/values-te/strings.xml +++ b/i18n/src/commonMain/resources/MR/te/strings.xml @@ -132,10 +132,6 @@ యిన్ మరియు యాంగ్ ఎప్పుడూ వద్దు సందెచీకటి - - ఒక నిమిషము తరువాత - %1$s నిమిషముల తరువాత - తెరను సంరక్షించుము అనువర్తనములను మారునపుడు వర్తక విషయములను దాయుము మరియు తెర యొక్క చిత్రములను తీయుటను నిరోధించుము సూచన విషయములను దాయుము diff --git a/i18n/src/commonMain/resources/MR/th/plurals.xml b/i18n/src/commonMain/resources/MR/th/plurals.xml new file mode 100644 index 0000000000..efa8857ea0 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/th/plurals.xml @@ -0,0 +1,51 @@ + + + + หมวดหมู่ %d + + + หลังจาก %1$s นาที + + + ข้ามตอนที่ %d อาจเป็นเพราะหายมาจากแหล่งที่มาหรือถูกกรองออก + + + %d ตัวติดตาม + + + %1$s ตอน + + + เหลืออีก %1$s รายการ + + + ใช้เวลาไป %1$s โดยมีข้อผิดพลาด %2$s รายการ + + + ตอนที่ %1$s และอีก %2$d ตอน + + + %1$d ตอนใหม่ + + + มี %d รายการ + + + มีการอัปเดตส่วนขยาย %d รายการพร้อมใช้งาน + + + %1$d วันที่ผ่านมา + + + %d ตอนที่ยังไม่ได้อ่านถัดไป + + + %d ตอนถัดไป + + + ไม่พบ %1$s ตอน + + + %d วัน + + \ No newline at end of file diff --git a/i18n/src/main/res/values-th/strings.xml b/i18n/src/commonMain/resources/MR/th/strings.xml similarity index 97% rename from i18n/src/main/res/values-th/strings.xml rename to i18n/src/commonMain/resources/MR/th/strings.xml index 058815f116..ea8c8cdb49 100644 --- a/i18n/src/main/res/values-th/strings.xml +++ b/i18n/src/commonMain/resources/MR/th/strings.xml @@ -331,9 +331,6 @@ ที่รวมไว้: %s ไม่มี รายการในหมวดหมู่ที่ยกเว้นจะไม่ได้รับการอัปเดตแม้ว่าจะอยู่ในหมวดหมู่ที่รวมอยู่ด้วยก็ตาม - - หมวดหมู่ %d - ตรวจสอบหน้าปกและรายละเอียดใหม่เมื่ออัปเดตคลัง โหลดข้อมูลเมตาใหม่โดยอัตโนมัติ อัปเดตทั้งหมด @@ -344,9 +341,6 @@ ซ่อนเนื้อหาการแจ้งเตือน หน้าจอปลอดภัยจะซ่อนเนื้อหาของแอปเมื่อสลับแอปและกันไม่ให้ถ่ายภาพหน้าจอ หน้าจอความปลอดภัย - - หลังจาก %1$s นาที - ไม่เลย ตลอด ล็อกเมื่อไม่ได้ใช้งาน @@ -409,9 +403,6 @@ ล้างประวัติ ตอน %1$s - %2$s กำลังอัปเดตคลัง - - ข้ามตอนที่ %d อาจเป็นเพราะหายมาจากแหล่งที่มาหรือถูกกรองออก - ไม่พบแหล่งที่มา ไม่พบหน้า โหมดการอ่าน @@ -422,9 +413,6 @@ วันที่เริ่มอ่าน หยุดชั่วคราว เพิ่มการติดตาม - - %d ตัวติดตาม - ไม่พบตอน ตั้งเป็นค่าเริ่มต้น นําไปใช้กับรายการทั้งหมดในคลังด้วย @@ -432,9 +420,6 @@ การตั้งค่าตอน ตามวันที่อัปโหลด ไม่สามารถคัดลอกไปยังคลิปบอร์ด - - %1$s ตอน - น้อยลง เพิ่มเติม อยู่ในคลัง @@ -453,9 +438,6 @@ ออกจากระบบ ออกจากระบบจาก %1$s\? ที่อยู่อีเมล - - เหลืออีก %1$s รายการ - กรองรายการทั้งหมดในคลังของคุณ ปิดใช้งานโหมดไม่ระบุตัวตน หยุดประวัติการอ่านชั่วคราว @@ -482,9 +464,6 @@ การคืนค่ากําลังดําเนินการอยู่แล้ว การสำรองข้อมูลล้มเหลว การสำรองข้อมูลกําลังดําเนินการอยู่แล้ว - - ใช้เวลาไป %1$s โดยมีข้อผิดพลาด %2$s รายการ - %02d นาที %02d วินาที ข้อมูลจากแฟ้มข้อมูลสำรองจะถูกคืนค่า \n @@ -500,18 +479,9 @@ ไม่สามารถดาวน์โหลดตอนได้เนื่องจากพื้นที่จัดเก็บเหลือน้อย ไม่รองรับ Android เวอร์ชันนี้อีกต่อไป ไม่พบแอปเลือกแฟ้ม - - ตอนที่ %1$s และอีก %2$d ตอน - ตอนที่ %1$s ตอนที่ %1$s และอีก %2$d ตอน ตอนที่ %1$s - - %1$d ตอนใหม่ - - - มี %d รายการ - หน้าก่อน การอัปเดตส่วนขยาย อัปเดตตอน @@ -522,9 +492,6 @@ โปรดอัปเดตแอพ WebView เพื่อความเข้ากันได้ที่ดีขึ้น แอปจำเป็นต้องใช้ WebView เพื่อให้ทำงานได้ ไม่สามารถเลี่ยงผ่าน Cloudflare ได้ - - มีการอัปเดตส่วนขยาย %d รายการพร้อมใช้งาน - คุณยังไม่มีหมวดหมู่ ยืนยันการเปลี่ยนแปลง วันนี้ @@ -558,9 +525,6 @@ ค่าเริ่มต้น ผิดพลาดในการแบ่งปันปก เริ่มดาวน์โหลดเลย - - %1$d วันที่ผ่านมา - ตัวติดตามขั้นสูง ควรเก็บสำเนาของข้อมูลสำรองไว้ที่อื่นด้วยเช่นกัน การสำรองข้อมูลอาจมีข้อมูลที่ละเอียดอ่อนรวมถึงรหัสผ่านที่เก็บไว้ ควรระวังหากแบ่งปันสำเนา บันทึกบันทึกอย่างละเอียดไปยังบันทึกของระบบ (ลดประสิทธิภาพของแอป) @@ -673,9 +637,6 @@ ดาวน์โหลดล่วงหน้า ดาวน์โหลดอัตโนมัติขณะกำลังอ่าน ใช้ได้เฉพาะกับตอนปัจจุบัน + ตอนถัด ๆ ไปดาวน์โหลดไว้อยู่แล้ว - - %d ตอนที่ยังไม่ได้อ่านถัดไป - แน่ใจแล้วใช่หรือไม่\? หลายภาษา อัปเดตคลังล่าสุด: %s @@ -742,17 +703,11 @@ \nต้องการดำเนินการต่อหรือไม่\? %1$s ข้อผิดพลาด: %2$s *จำเป็น - - %d ตอนถัดไป - ซ่อนรายการที่มีอยู่ในคลังอยู่แล้ว คัดลอกไปยังคลิปบอร์ด อัปเดตหมวดหมู่ แยกภาพสูงยาว โอเวอร์เลย์ - - ไม่พบ %1$s ตอน - หมุนหน้ากว้างให้พอดี พลิกการวางแนวของหน้ากว้างที่หมุน ข้อมูลดีบัก @@ -769,9 +724,6 @@ การตรวจสอบที่ผ่านมา การอัปเดตที่คาดไว้ต่อไป ระยะเวลาการออกที่คาดไว้จากภายนอก - - %d วัน - ข้ามไปเนื่องจากคาดว่าจะไม่มีการออกในวันนี้ ประมาณทุกๆ ตั้งค่าให้อัพเดตทุกๆ diff --git a/i18n/src/commonMain/resources/MR/tr/plurals.xml b/i18n/src/commonMain/resources/MR/tr/plurals.xml new file mode 100644 index 0000000000..d00eb3c4a1 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/tr/plurals.xml @@ -0,0 +1,67 @@ + + + + %1$s dakika sonra + %1$s dakika sonra + + + %1$d yeni bölüm + %1$d yeni bölüm + + + Bölüm %1$s ve 1 daha + Bölüm %1$s ve %2$d daha + + + %d girdi için + %d girdi için + + + Uzantı güncellemesi var + %d uzantı güncellemesi var + + + %1$s kaldı + %1$s kaldı + + + %d ulam + %d ulam + + + %1$s içinde %2$s hatayla tamamlandı + %1$s içinde %2$s hatayla tamamlandı + + + %1$s bölüm + %1$s bölüm + + + %d izleyici + %d izleyici + + + %d bölüm atlanıyor, ya kaynakta yok ya da süzgeçlenmiş + %d bölüm atlanıyor, ya kaynakta yok ya da süzgeçlenmiş + + + Dün + %1$d gün önce + + + Sonraki okunmayan bölüm + Sonraki %d okunmayan bölüm + + + Sonraki bölüm + Sonraki %d bölüm + + + %1$s bölüm eksik + %1$s bölüm eksik + + + 1 gün + %d gün + + \ No newline at end of file diff --git a/i18n/src/main/res/values-tr/strings.xml b/i18n/src/commonMain/resources/MR/tr/strings.xml similarity index 95% rename from i18n/src/main/res/values-tr/strings.xml rename to i18n/src/commonMain/resources/MR/tr/strings.xml index f1f07dac14..1dadacd745 100644 --- a/i18n/src/main/res/values-tr/strings.xml +++ b/i18n/src/commonMain/resources/MR/tr/strings.xml @@ -315,10 +315,6 @@ Boştayken kilitle Her zaman Asla - - %1$s dakika sonra - %1$s dakika sonra - Güvenli ekran Bekleyen güncellemeler İçeriği kesme alanında göster @@ -327,17 +323,9 @@ Bölüm güncellemeleri Güvenli ekran, uygulamalar arasında geçiş yaparken uygulama içeriğini gizler ve ekran görüntüsü alınmasını engeller Ekran - - %1$d yeni bölüm - %1$d yeni bölüm - Bölüm %1$s Bölüm %1$s ve %2$d daha Bölüm %1$s - - Bölüm %1$s ve 1 daha - Bölüm %1$s ve %2$d daha - Bildirim içeriğini gizle Yeni bölümler aranıyor Pil iyileştirmeyi devre dışı bırak @@ -345,19 +333,11 @@ Pil iyileştirme zaten devre dışı E-posta adresi Bölüm geçişini her zaman göster - - %d girdi için - %d girdi için - Komut-Seçenek Dizelgesi En yeni En eski En üste taşı En alta taşı - - Uzantı güncellemesi var - %d uzantı güncellemesi var - Uzantı güncellemeleri Kitaplık güncelleniyor Okunan @@ -389,23 +369,11 @@ Yerel kaynak kılavuzu %02d dk, %02d sn Kitaplığınızdaki tüm girdileri süzer - - %1$s kaldı - %1$s kaldı - Gri Renk şeritlerini azaltır, ancak başarımı etkileyebilir Okuma kipi Bu dizi için - - %d ulam - %d ulam - Aygıt ayarları açılamadı - - %1$s içinde %2$s hatayla tamamlandı - %1$s içinde %2$s hatayla tamamlandı - Bölüm ilerlemesini, harici izleme hizmetlerinde güncellemek için tek yönlü eşitleme. Her girdinin izleme düğmesinden, izlemeyi ayarlayın. Kitaplıktakilerin kapaklarını yenile Bu uzantı resmi dizelgeden değil. @@ -429,10 +397,6 @@ Başlat Kaynak bulunamadı Devre dışı bırak - - %1$s bölüm - %1$s bölüm - Etkili olması için uygulamanın yeniden başlatılmasını gerektirir Ağ oluşturma Yok @@ -449,10 +413,6 @@ \"%1$s\" için genel arama Okuma kipi Tema - - %d izleyici - %d izleyici - İğnelenmiş kaynağınız yok Bitirildi İlerleme @@ -463,10 +423,6 @@ Bu uzantıdaki kaynaklar yetişkin (18+) içerik içerebilir 18+ Bu, resmi olmayan veya yanlış imlenmiş uzantıların, uygulama içinde yetişkin (18+) içeriği göstermesini engellemez. - - %d bölüm atlanıyor, ya kaynakta yok ya da süzgeçlenmiş - %d bölüm atlanıyor, ya kaynakta yok ya da süzgeçlenmiş - Bölüm bulunamadı Öntanımlı bölüm ayarları güncellendi Öntanımlı olarak ayarla @@ -576,10 +532,6 @@ En yüksek Kaydırmada komut-seçenek dizelgesini gizleme duyarlılığı Ters Çevrilmiş - - Dün - %1$d gün önce - Bugün Deniz kökçesi & Türk kökçesi Değişikliği onaylamak için kimlik doğrula @@ -684,10 +636,6 @@ Gelgit Dalgası Önceden indir Okurken kendiliğinden indir - - Sonraki okunmayan bölüm - Sonraki %d okunmayan bölüm - Yalnızca geçerli bölüm ile bir sonraki bölüm zaten indirildiyse çalışır. Emin misiniz\? \"%s\"yi kitaplığınızdan kaldırmak üzeresiniz @@ -756,18 +704,10 @@ %1$s hatası: %2$s *gerekli Zaten kitaplıkta bulunan girdileri gizle - - Sonraki bölüm - Sonraki %d bölüm - Panoya kopyala Ulamı güncelle Uzun görselleri otomatik böl Kaplama - - %1$s bölüm eksik - %1$s bölüm eksik - Geniş sayfaları sığdırmak için döndür Döndürülen geniş sayfaların yönünü çevir Hata ayıklama bilgisi @@ -785,10 +725,6 @@ Geçmiş denetim süresi Sonraki beklenen güncelleme Beklenen yayınlanma dönemi dışında - - 1 gün - %d gün - TAMAM Hepsini tahmin et %s izlemesi kaldırılsın mı\? diff --git a/i18n/src/commonMain/resources/MR/uk/plurals.xml b/i18n/src/commonMain/resources/MR/uk/plurals.xml new file mode 100644 index 0000000000..ef8ddc5861 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/uk/plurals.xml @@ -0,0 +1,98 @@ + + + + Після %1$s хвилини + Після %1$s хвилин + Після %1$s хвилин + Після %1$s хвилин + + + %1$d новий розділ + %1$d нових розділів + %1$d нових розділів + %1$d нових розділів + + + Розділ %1$s та 1 більше + Розділи %1$s та %2$d більше + Розділи %1$s та %2$d більше + Розділи %1$s та %2$d більше + + + Для %d запису + Для %d записів + Для %d записів + Для %d записів + + + Наявне оновлення для розширення + %d наявних оновлень розширень + %d наявних оновлень розширень + + + %d категорія + %d категорії + %d категорій + %d категорій + + + %1$s залишилось + %1$s залишилось + %1$s залишилось + %1$s залишилось + + + Зроблено за %1$s з %2$s помилкою + Зроблено за %1$s з %2$s помилками + Зроблено за %1$s з %2$s помилками + Зроблено за %1$s з %2$s помилками + + + %1$s розділ + %1$s розділів + %1$s розділів + %1$s розділів + + + %d трекер + %d трекери + %d трекерів + %d трекерів + + + Пропускається %d розділ, тому що джерело не має його, або він був відфільтрований + Пропускаються %d розділи, тому що джерело не має їх, або вони були відфільтровані + Пропускання %d розділів, тому що джерело не має їх, або вони були відфільтровані + Пропускання %d розділів, тому що джерело не має їх, або вони були відфільтровані + + + Учора + %1$d днів тому + %1$d днів тому + %1$d днів тому + + + Наступний непрочитаний розділ + Наступні %d непрочитані розділи + Наступні %d непрочитані розділи + Наступні %d непрочитані розділи + + + Наступний розділ + Наступних %d розділи + Наступних %d розділів + Наступних %d розділів + + + Відсутній %1$s розділ + Відсутні %1$s розділи + Відсутні %1$s розділів + Відсутні %1$s розділів + + + 1 день + %d дні + %d днів + %d днів + + \ No newline at end of file diff --git a/i18n/src/main/res/values-uk/strings.xml b/i18n/src/commonMain/resources/MR/uk/strings.xml similarity index 92% rename from i18n/src/main/res/values-uk/strings.xml rename to i18n/src/commonMain/resources/MR/uk/strings.xml index 4d4c973305..b2ebae4be7 100644 --- a/i18n/src/main/res/values-uk/strings.xml +++ b/i18n/src/commonMain/resources/MR/uk/strings.xml @@ -315,12 +315,6 @@ Блокувати в режимі очікування Завжди Ніколи - - Після %1$s хвилини - Після %1$s хвилин - Після %1$s хвилин - Після %1$s хвилин - Захистити екран додатку Очікуються оновлення Відображати вміст обітнутої області @@ -329,21 +323,9 @@ Оновлення розділів Ховати вміст застосунку при перемиканні застосунків та блокувати скріншоти Відображення - - %1$d новий розділ - %1$d нових розділів - %1$d нових розділів - %1$d нових розділів - Розділ %1$s Розділ %1$s та ще %2$d Розділи %1$s - - Розділ %1$s та 1 більше - Розділи %1$s та %2$d більше - Розділи %1$s та %2$d більше - Розділи %1$s та %2$d більше - Приховати вміст сповіщень Перевірка нових розділів Вимкнути збереження батареї @@ -351,22 +333,11 @@ Збереження батареї вже вимкнено Електропошта Завжди показувати перехід розділу - - Для %d запису - Для %d записів - Для %d записів - Для %d записів - Меню Найновіші Найстаріші Перемістити догори Перемістити додолу - - Наявне оновлення для розширення - %d наявних оновлень розширень - %d наявних оновлень розширень - Оновлення розширень Читання Джерела @@ -391,12 +362,6 @@ Зменшує смугастість, але може вплинути на продуктивність Це розширення не з офіційного списку. Неофіційне - - %d категорія - %d категорії - %d категорій - %d категорій - Перевірити наявність нової обкладинки та подробиць при оновленні бібліотеки Автоматично оновлювати метадані Мігрувати @@ -404,12 +369,6 @@ Посібник місцевого джерела Останній використаний Вкладки - - %1$s залишилось - %1$s залишилось - %1$s залишилось - %1$s залишилось - Фільтрувати усі записи в вашій бібліотеці Перевірити оновлення Не вдалось відкрити налаштування пристрою @@ -420,12 +379,6 @@ Відновлення вже відбувається Помилка резервування Резервне копіювання вже виконується - - Зроблено за %1$s з %2$s помилкою - Зроблено за %1$s з %2$s помилками - Зроблено за %1$s з %2$s помилками - Зроблено за %1$s з %2$s помилками - %02d хв, %02d сек Відсутні джерела: Бекап не містить жодних записів бібліотеки. @@ -443,12 +396,6 @@ Показати режим читання Розпочати Джерело не знайдено - - %1$s розділ - %1$s розділів - %1$s розділів - %1$s розділів - Відключити Обоє Вертикально @@ -466,12 +413,6 @@ Режим читання Тема Дата додавання - - %d трекер - %d трекери - %d трекерів - %d трекерів - У вас немає закріплених джерел Помилки Завершено @@ -482,12 +423,6 @@ Джерела з цього розширення можуть містити контент NSFW (18+) 18+ Це не заважає неофіційним або потенційно невірним розширенням розміщувати вміст NSFW (18+) у застосунку. - - Пропускається %d розділ, тому що джерело не має його, або він був відфільтрований - Пропускаються %d розділи, тому що джерело не має їх, або вони були відфільтровані - Пропускання %d розділів, тому що джерело не має їх, або вони були відфільтровані - Пропускання %d розділів, тому що джерело не має їх, або вони були відфільтровані - Немає розділів Налаштування розділу оновлено %1$s: %2$s, сторінка %3$d @@ -597,12 +532,6 @@ Тема застосунку Розпочати завантаження зараз Інвертовано - - Учора - %1$d днів тому - %1$d днів тому - %1$d днів тому - Сьогодні Бірюзова Виконайте автентифікацію, щоб підтвердити зміну @@ -705,12 +634,6 @@ Багатомовне Останнє оновлення бібліотеки: %s Доступ до файлової системи не надано - - Наступний непрочитаний розділ - Наступні %d непрочитані розділи - Наступні %d непрочитані розділи - Наступні %d непрочитані розділи - Завантажувати наперед Працює, якщо поточний розділ + наступний вже завантажені. Ви збираєтесь видалити \"%s\" з вашої бібліотеки @@ -782,23 +705,11 @@ *необхідно Приховати записи, які вже є в бібліотеці Копіювати в буфер обміну - - Наступний розділ - Наступних %d розділи - Наступних %d розділів - Наступних %d розділів - Оновити категорію Розділяти довгі зображення Оверлей Повернути широкі сторінки за розміром Перевернути орієнтацію обернутих широких сторінок - - Відсутній %1$s розділ - Відсутні %1$s розділи - Відсутні %1$s розділів - Відсутні %1$s розділів - Інформація для відлагодження Гортання розділів Проведіть пальцем праворуч @@ -810,12 +721,6 @@ Покинуто\? Останні 20+ і 2 місяці Пройдено період перевірки Оцініть кожну - - 1 день - %d дні - %d днів - %d днів - Отримувати щомісяця (28 днів) Налаштувати інтервал отримання Поза очікуваним періодом випуску diff --git a/i18n/src/commonMain/resources/MR/uz/plurals.xml b/i18n/src/commonMain/resources/MR/uz/plurals.xml new file mode 100644 index 0000000000..35f4fc44e2 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/uz/plurals.xml @@ -0,0 +1,15 @@ + + + + %d toifa + %d toifa + + + Kecha + %1$d kun oldin + + + %1$s daqiqadan so\'ng + %1$s daqiqadan so\'ng + + \ No newline at end of file diff --git a/i18n/src/main/res/values-uz/strings.xml b/i18n/src/commonMain/resources/MR/uz/strings.xml similarity index 98% rename from i18n/src/main/res/values-uz/strings.xml rename to i18n/src/commonMain/resources/MR/uz/strings.xml index 19729811cb..f7e264530f 100644 --- a/i18n/src/main/res/values-uz/strings.xml +++ b/i18n/src/commonMain/resources/MR/uz/strings.xml @@ -230,10 +230,6 @@ Har hafta HAr 3 kunda Quvvatlanayotganda - - %d toifa - %d toifa - Qismlar yangilanishini o\'tkazib yuborish Shizuku ishlamayapti Filtrlangan boblarni o\'tkazib yuborish @@ -244,10 +240,6 @@ O\'qish boshlanganida o\'qish rejimini birozga ko\'rsatish Qism yakunlangan Kengaytma o\'rnatilmoqda… - - Kecha - %1$d kun oldin - Global yangilanish Metama\'lumotlarni yangilash Istisno qilish: %s @@ -285,10 +277,6 @@ Qoplama Ko\'paytirish Ekran - - %1$s daqiqadan so\'ng - %1$s daqiqadan so\'ng - Uskuna uchun avtomatik yangilanishlarni cheklash Takrorlanuvchi boblarni o\'tkazib yuborish Sahifalarni alohida papkalarga saqlash diff --git a/i18n/src/commonMain/resources/MR/vi/plurals.xml b/i18n/src/commonMain/resources/MR/vi/plurals.xml new file mode 100644 index 0000000000..18fc85c641 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/vi/plurals.xml @@ -0,0 +1,48 @@ + + + + Có %d bản cập nhật cho các tiện ích mở rộng sẵn sàng + + + %1$d chương mới có + + + Cho %d chương + + + Sau %1$s phút + + + %d danh mục + + + Chương %1$s và %2$d + + + Đã bỏ qua %d chương, vì nguồn đang bị thiếu hoặc đã bị lọc ra + + + %d bộ theo dõi + + + %1$s chương + + + Còn lại %1$s + + + Hoàn tất trong %1$s với %2$s lỗi + + + %1$d ngày trước + + + %d chương chưa đọc tiếp + + + %d Chương tiếp theo + + + Đang thiếu %1$s + + \ No newline at end of file diff --git a/i18n/src/main/res/values-vi/strings.xml b/i18n/src/commonMain/resources/MR/vi/strings.xml similarity index 95% rename from i18n/src/main/res/values-vi/strings.xml rename to i18n/src/commonMain/resources/MR/vi/strings.xml index 23f49b3c8a..c2d0ad1641 100644 --- a/i18n/src/main/res/values-vi/strings.xml +++ b/i18n/src/commonMain/resources/MR/vi/strings.xml @@ -1,14 +1,12 @@ Tên - Cài đặt Hàng chờ tải xuống Thư viện Lịch sử Cập nhật Sao lưu và khôi phục - Cài đặt Bộ lọc Đã đánh dấu @@ -51,17 +49,13 @@ Lưu lại Làm mới Hoàn tác - Đang tải… - - Chung Trình đọc Tải xuống Theo dõi Nâng cao Giới thiệu - Cỡ lưới Dọc Ngang @@ -76,7 +70,6 @@ Khi đang sạc Đã có trạng thái \"Hoàn Thành\" Cập nhật tiến triển sau khi đọc - Toàn màn hình Hoạt ảnh chuyển trang Hiện số trang @@ -113,7 +106,6 @@ G B A - Đường dẫn tải xuống Sau khi đánh dấu thủ công là đã đọc Tự động xóa sau khi đọc @@ -125,9 +117,7 @@ Bốn chương đã đọc gần nhất Năm chương đã đọc gần nhất Tải chương mới - Dịch vụ - Dọn dẹp bộ nhớ đệm Đã sử dụng: %1$s Bộ nhớ đệm đã được dọn dẹp. %1$d tập tin đã bị xóa @@ -138,29 +128,21 @@ Xóa lịch sử đọc truyện và các chương không nằm trong thư viện Bạn có chắc không\? Các chương đã đọc và tiến độ đọc các truyện không nằm trong thư viện sẽ bị mất Các mục đã bị xóa - Phiên bản - Gửi báo cáo lỗi Giúp đỡ sửa lỗi. Sẽ không có thông tin nhạy cảm nào được gửi đi - Đăng nhập vào %1$s Tên đăng nhập Mật khẩu Đăng nhập Đăng nhập thành công Lỗi không xác định - Cập nhật danh mục - Không có thêm kết quả nào - - Đang tiến hành Không rõ Đã được mua bản quyền Gỡ bỏ khỏi thư viện - Chương %1$s Đang tải xuống (%1$d/%2$d) Lỗi @@ -172,7 +154,6 @@ Tải xuống Chưa đọc Bạn có chắc muốn xóa các chương đã chọn? - Theo dõi Đang đọc Đã hoàn thành @@ -183,17 +164,12 @@ Tiêu đề Trạng thái Các chương - Tên danh mục này đã tồn tại! Danh mục đã bị xóa - Sẽ xóa ngày đọc các chương. Bạn chắc chứ? Làm mới mọi chương của truyện này - Thêm truyện vào thư viện\? - Đã lưu ảnh - Bộ lọc tùy chỉnh Đặt làm ảnh bìa Đã cập nhật ảnh bìa @@ -201,32 +177,22 @@ Không tìm thấy chương kế tiếp Hình ảnh không thể hiển thị được Bạn có chắc muốn đặt ảnh này làm ảnh bìa? - - - Có lỗi đã xảy ra khi đang tải các chương. Bạn có thể thử lại trong phần Tải xuống - Đã tìm thấy chương mới Cập nhật ảnh bìa thất bại Hãy thêm truyện vào thư viện trước khi thực hiện - Chọn ảnh bìa Chọn file sao lưu - Tải xuống Không có cập nhật mới - Đang tải xuống… Nhấn để cập nhật Lỗi khi tải xuống Có cập nhật mới! - - Không có Không có cập nhật mới Không có truyện đã đọc gần đây Thư viện trống - Trình tải xuống Lỗi Đã xảy ra lỗi khi tải xuống chương này @@ -323,16 +289,7 @@ Cập nhật tiện ích mở rộng Vui lòng cập nhật WebView để tương thích tốt hơn Bỏ qua Cloudflare thất bại - - Có %d bản cập nhật cho các tiện ích mở rộng sẵn sàng - Chương %1$s - - %1$d chương mới có - - - Cho %d chương - Kiểm tra các chương cập nhật mới Đang cập nhật thư viện Đã tạm ngưng @@ -356,9 +313,6 @@ Ẩn nội dung thông báo Bảo vệ màn hình sẽ ẩn nội dung khi chuyển đổi ứng dụng và chặn chụp màn hình Bảo vệ màn hình - - Sau %1$s phút - Không bao giờ Luôn luôn Khóa khi chạy nền @@ -392,9 +346,6 @@ Hiển thị chế độ đọc Tiện ích mở rộng này không nằm trong danh sách tiện ích mở rộng chính thức của Tachiyomi. Không chính thức - - %d danh mục - Kiểm tra ảnh bìa và chi tiết khi cập nhật thư viện Chủ đề Bỏ ghim @@ -449,25 +400,16 @@ Quá trình Tachiyomi yêu cầu phải có WebView Phiên bản Android này không còn được hỗ trợ - - Chương %1$s và %2$d - Chương %1$s Chương %1$s và thêm %2$d Không thể tãi chương vì dung lượng bộ nhớ xuống thấp Ch.%1$s-%2$s - - Đã bỏ qua %d chương, vì nguồn đang bị thiếu hoặc đã bị lọc ra - Nguồn không tìm thấy Trang không tìm thấy Chế độ đọc Dành cho phần truyện này %1$s:%2$s,trang %3$d Thêm theo dõi - - %d bộ theo dõi - Không tìm thấy chương Đặt mặc định Ngoài ra có hiệu lực với tất cả truyện trong thư viện @@ -475,9 +417,6 @@ Tuỳ chỉnh chương Bởi ngày đăng Sao chép vào bảng tạm thất bại - - %1$s chương - Hiện bớt Xem thêm Trong thư viện @@ -489,9 +428,6 @@ Hướng dẫn nguồn cục bộ Tìm kiếm \"%1$s\" toàn bộ Mục - - Còn lại %1$s - Lọc tất cả truyện trong thư viện Tắt chế độ ẩn danh Được cập nhật đến phiên bản v%1$s @@ -507,9 +443,6 @@ Khôi phục thất bại Đang trong quá trình phục hồi Lưu trữ thất bại - - Hoàn tất trong %1$s với %2$s lỗi - %02d phút, %02d giây Dữ liệu từ tệp sao lưu sẽ được khôi phục. \n @@ -607,9 +540,6 @@ Cao Cao nhất Đảo màu - - %1$d ngày trước - Hôm nay Hỗ trợ dịch thuật Thông tin ứng dụng @@ -704,9 +634,6 @@ Có một cập nhật đang chạy sẵn Sóng Thủy Triều Chuỗi đại diện người dùng không thể bỏ trống - - %d chương chưa đọc tiếp - Tự động tải khi đang đọc Quyền truy cập lưu trữ không được thông qua Nổi Tiếng @@ -773,18 +700,12 @@ \n \nBạn có muốn thêm lại không\? Đã sao chép vào bảng tạm - - %d Chương tiếp theo - Sao chép vào bảng tạm %d giây %d giờ Quay những trang rộng để vừa màn hình Lật hướng của các trang rộng đã xoay Phủ lên - - Đang thiếu %1$s - Loại bỏ ngày\? %1$s Lỗi: %2$s N/A diff --git a/i18n/src/commonMain/resources/MR/zh-rCN/plurals.xml b/i18n/src/commonMain/resources/MR/zh-rCN/plurals.xml new file mode 100644 index 0000000000..3b2ec70053 --- /dev/null +++ b/i18n/src/commonMain/resources/MR/zh-rCN/plurals.xml @@ -0,0 +1,51 @@ + + + + %1$s 分钟后 + + + %1$d 个新章节 + + + 第 %1$s 章及另外 %2$d 章 + + + 共 %d 部作品 + + + %d 个插件可更新 + + + 剩余 %1$s 本 + + + %d 个分类 + + + 耗时 %1$s,出现 %2$s 个错误 + + + 共 %1$s 章 + + + %d 个记录平台 + + + 跳过了 %d 章,可能是图源没有这些章节,或者被筛选规则排除了 + + + %1$d 天前 + + + 后续 %d 个未读章节 + + + 后续 %d 章 + + + 缺少 %1$s 章 + + + %d 天 + + \ No newline at end of file diff --git a/i18n/src/main/res/values-zh-rCN/strings.xml b/i18n/src/commonMain/resources/MR/zh-rCN/strings.xml similarity index 96% rename from i18n/src/main/res/values-zh-rCN/strings.xml rename to i18n/src/commonMain/resources/MR/zh-rCN/strings.xml index 37ce0c2772..15b8411744 100644 --- a/i18n/src/main/res/values-zh-rCN/strings.xml +++ b/i18n/src/commonMain/resources/MR/zh-rCN/strings.xml @@ -314,9 +314,6 @@ 切后台时锁定 始终开启 关闭 - - %1$s 分钟后 - 隐私界面 待更新 无法绕过 Cloudflare @@ -327,32 +324,20 @@ 隐藏通知内容 应用锁 在刘海屏区域显示内容 - - %1$d 个新章节 - 第 %1$s 章 第 %1$s 章及另外 %2$d 章 第 %1$s 章 - - 第 %1$s 章及另外 %2$d 章 - 正在检查新章节 关闭电池优化 有助于后台更新书架和备份 电池优化已被关闭 电子邮件地址 始终显示章节间的过渡页面 - - 共 %d 部作品 - 菜单 最新 最旧 移到顶部 移到底部 - - %d 个插件可更新 - 插件更新 图源 正在更新书架 @@ -381,21 +366,12 @@ 第 %1$s 章 - %2$s 本地图源指南 上次浏览 - - 剩余 %1$s 本 - 筛选书架里的全部作品 检查更新 %02d 分,%02d 秒 灰色 本作品 阅读模式 - - %d 个分类 - - - 耗时 %1$s,出现 %2$s 个错误 - 无法打开设备设置 缓解色带问题,但可能会影响性能 刷新书架封面 @@ -421,9 +397,6 @@ 开始阅读 未找到图源 关闭 - - 共 %1$s 章 - 需要重启应用才能生效 网络 水平 + 垂直 @@ -439,9 +412,6 @@ 阅读模式 主题 收藏日期 - - %d 个记录平台 - 反转点按区域 没有置顶图源 完成 @@ -453,9 +423,6 @@ 来自此插件的图源可能包含 NSFW (18+) 内容 18+ 这并不能防止非官方或可能被错误标记的插件在应用中显示 NSFW (18+) 内容。 - - 跳过了 %d 章,可能是图源没有这些章节,或者被筛选规则排除了 - 未找到章节 已更新默认章节设置 设为默认 @@ -566,9 +533,6 @@ 滑动时隐藏菜单的灵敏度 反色 今天 - - %1$d 天前 - 青色与绿松色 验证以确认更改 默认 @@ -672,9 +636,6 @@ 浪潮 预先下载 阅读时自动下载 - - 后续 %d 个未读章节 - 要求当前章节和下一章节都已下载。 你确定吗? 多语言 @@ -742,18 +703,12 @@ \n要继续添加吗? %1$s 发生错误:%2$s *必填 - - 后续 %d 章 - 隐藏已添加到书架的作品 复制到剪贴板 更新分类 分割长图 标记和按钮 旋转横向图片 - - 缺少 %1$s 章 - 旋转横向图片时反转方向 调试信息 目录左右滑动 @@ -775,9 +730,6 @@ 每月更新(28天) 延迟10+检查 间隔 - - %d 天 - 估计每个 设定更新为每 自定义间隔 diff --git a/i18n/src/commonMain/resources/MR/zh-rTW/plurals.xml b/i18n/src/commonMain/resources/MR/zh-rTW/plurals.xml new file mode 100644 index 0000000000..24dd4b894d --- /dev/null +++ b/i18n/src/commonMain/resources/MR/zh-rTW/plurals.xml @@ -0,0 +1,51 @@ + + + + %1$s 分鐘後 + + + %d 個擴充套件可更新 + + + 剩餘 %1$s 本 + + + 共 %1$s 章 + + + %d 個類別 + + + 歷時 %1$s,出現 %2$s 個錯誤 + + + %1$d 篇新章節 + + + 第 %1$s 章以及另外 %2$d 章 + + + %d 個歷程平台 + + + 略過了 %d 章,也許是來源沒有這些章節,或其已被篩選規則排除 + + + 共 %d 部作品 + + + %1$d 天前 + + + 接下來未讀的 %d 章 + + + 後續 %d 章 + + + 缺漏 %1$s 章 + + + %d 天 + + \ No newline at end of file diff --git a/i18n/src/main/res/values-zh-rTW/strings.xml b/i18n/src/commonMain/resources/MR/zh-rTW/strings.xml similarity index 96% rename from i18n/src/main/res/values-zh-rTW/strings.xml rename to i18n/src/commonMain/resources/MR/zh-rTW/strings.xml index 05de0e56a7..59a113b815 100644 --- a/i18n/src/main/res/values-zh-rTW/strings.xml +++ b/i18n/src/commonMain/resources/MR/zh-rTW/strings.xml @@ -307,9 +307,6 @@ 檢查更新 其他 更多 - - %1$s 分鐘後 - 永不 立即 閒置時鎖定 @@ -320,9 +317,6 @@ 隱藏通知內容 管理通知設定 擴充套件更新 - - %d 個擴充套件可更新 - 類別索引 頁籤 灰色 @@ -389,16 +383,7 @@ 還原失敗 備份失敗 登出 %1$s? - - 剩餘 %1$s 本 - - - 共 %1$s 章 - 將閱讀進度單向同步至外部歷程平台。請逕行前往個別作品的「歷程」專區以設置。 - - %d 個類別 - 需要重新啟動應用程式以套用 網路 全部 @@ -408,31 +393,19 @@ 正在檢查是否有新章節 捲動式 (頁間留空) - - 歷時 %1$s,出現 %2$s 個錯誤 - %02d 分 %02d 秒 此擴充功能不在官方清單中。 非官方 第 %1$s 章 - %2$s - - %1$d 篇新章節 - 第 %1$s 章 第 %1$s 章 第 %1$s 章以及另外 %2$d 章 - - 第 %1$s 章以及另外 %2$d 章 - 更新日誌 連載狀態不明 佚名 在所有範圍內搜尋「%1$s」 由於儲存空間不足,無法下載章節 已更新至 v%1$s - - %d 個歷程平台 - 閱讀模式 主題 收藏日期 @@ -451,9 +424,6 @@ 允許刪除有書籤的章節 刪除章節 已更新章節設定預設值 - - 略過了 %d 章,也許是來源沒有這些章節,或其已被篩選規則排除 - 搜尋設定 章節設定 同時套用至其餘在書櫃中的作品 @@ -472,9 +442,6 @@ 上一頁 請重新登入 MAL 未滿十八歲之人不宜瀏覽的來源 - - 共 %d 部作品 - 在來源和擴充套件清單中顯示 閱讀完畢日期 開始閱讀日期 @@ -569,9 +536,6 @@ 驗證以確認變更 外觀 今天 - - %1$d 天前 - 預設 平板電腦介面 入門指南 @@ -672,9 +636,6 @@ 潮浪 預先下載 閱讀時自動下載 - - 接下來未讀的 %d 章 - 僅於目前章節及下一章節皆已下載時生效。 你確定嗎? 多語 @@ -744,15 +705,9 @@ *必填 隱藏已在書櫃的作品 複製到剪貼簿 - - 後續 %d 章 - 更新類別 分割過高的圖片 封面附加元素 - - 缺漏 %1$s 章 - 旋轉寬頁以符合螢幕 調換旋轉寬頁方向 偵錯資訊 @@ -776,9 +731,6 @@ 刊期 預計每個 未臨出刊日 - - %d 天 - 設定為每個 自訂刊期 由於未臨出刊日,因此略過 diff --git a/i18n/src/main/res/values-b+es+419/strings.xml b/i18n/src/main/res/values-b+es+419/strings.xml deleted file mode 100644 index 6c46a1970f..0000000000 --- a/i18n/src/main/res/values-b+es+419/strings.xml +++ /dev/null @@ -1,851 +0,0 @@ - - - Cancelar - Invertir selección - Capítulo más reciente - Capítulos totales - Información de la extensión - Copia de seguridad y restauración - Historial - Historial - Lista - Migrar - Abrir en WebView - Abrir en el navegador - Reanudar - Remover - Capítulo siguiente - Capítulo anterior - Pausar - Renombrar categoría - Editar categorías - Agregar categoría - Agregar - Editar - Actualizar biblioteca - Borrar - Descargar - Marcar anteriores como leído - Marcar como no leído - Marcar como leído - Seleccionar todo - Búsqueda global - Buscar - Ultimo leído - Alfabéticamente - Remover filtro - Filtrar - Menú - Ajustes - Capítulos - Manga - Categorías - No hay categorías. Presione el botón de más para crear una y organizar tu biblioteca. - Tu biblioteca está vacía - Ninguna lectura reciente - Sin actualizaciones recientes - No hay descargas - Ayuda - Extensiones - Migrar - Actualizaciones - Biblioteca - Ajustes - Nombre - Fuentes - Quitar capítulo de favoritos - Agregar capítulo a favoritos - No leído - Favoritos - Cola de descargas - Más - Siguiendo - Deshacer - Reiniciar - Guardar - Compartir - Instalar - Mover al final - Mover al principio - Menos reciente - Cancelar todo - Desactivar - Mostrar pestañas de categoría - Mostrar - Modo de visualización - Actualice la aplicación WebView para mejor compatibilidad - ¡Nueva versión disponible! - Asignar categorías - Ver capítulos - Editar portada - Desactivar todo - Activar todo - Restaurar copia de seguridad - Se puede utilizar para restaurar la biblioteca actual - Crear copia de seguridad - Sincronización unidireccional para actualizar el progreso del capítulo en servicios de sincronización externos. Configure el seguimiento de las entradas de manga individuales desde su botón de seguimiento. - Rastreadores - Actualizar el progreso después de leer - Descargar capítulos nuevos - Quinto al último capítulo - Cuarto al último capítulo - Tercer al último capítulo leído - Penúltimo capítulo leido - Último capítulo leído - Deshabilitado - Directorio personalizado - Borrar automáticamente después de leer - Después de marcar como leído manualmente - Ubicación de descargas - Relleno lateral - Leyendo - Mostrar siempre la transición del capítulo - A - B - G - R - Forzar horizontal - Forzar vertical - Libre - Rotación predeterminada - Rápido - Normal - Sin animación - Centro - Derecha - Izquierda - Automático - Posición de zoom inicial - Ajuste inteligente - Tamaño original - Ajustar altura - Ajustar ancho - Estirado - Ajustar pantalla - Tipo de escalado - Por páginas - Tira vertical discontinua - Tira vertical continua - Por páginas (vertical) - Por páginas (derecha a izquierda) - Por páginas (izquierda a derecha) - Modo de lectura por defecto - Negro - Gris - Blanco - Color de fondo - Mostrar acciones de toque largo - Invertir teclas de volumen - Teclas de volumen - Navegación - Saltar capítulos filtrados - Saltar capítulos marcados como leídos - Mantener la pantalla encendida - Quemar / Oscurecer - Subexponer / Aclarar - Pantalla - Multiplicar - Superponer - Modo de mezcla del filtro de color - Filtro de color personalizado - Brillo personalizado - Cortar bordes - Reduce las bandas, pero podría afectar el rendimiento - Color 32 bits - Mostrar brevemente el modo actual cuándo el lector está abierto - Mostrar modo de lectura - Mostrar el número de página - Velocidad de animación de doble toque - Animar las transiciones de página - Mostrar contenido en el área recortada - Pantalla completa - Esta extensión no es de la lista oficial. - Esta extensión ya no está disponible. Esta puede no funcionar apropiadamente y puede causar problemas en la aplicación. Es recomendable desintalar. - Esta extensión fue firmada por una fuente no certificada y no fue activada. -\n -\nUna extensión maliciosa puede leer cualquier credencial de inicio guardada o ejecutar código arbitrario. -\n -\nAl confiar en este certificado aceptas estos riesgos. - Extensión no confiable - Desinstalar - No confiable - No oficial - Confiar - Instalada - Instalando - Descargando - Pendiente - Instalar - Obsoleta - Actualizar - Actualizaciones pendientes - Todos - - %d categoría - %d categorías - %d categorías - - Preguntar siempre - Categoría por defecto - Buscar nueva portada y detalles al actualizar la biblioteca - Actualizar metadatos automáticamente - Con estado \"Finalizado\" - Mientras se carga - Restricciones de actualización automática - Cada semana - Cada 2 días - A diario - Cada 12 horas - Cada 6 horas - Desactivado - Actualizaciones automáticas - Actualización global - Horizontal - Ambos - Vertical - Horizontal - Ninguno - Invertir zonas de toque - Actualizaciones de extensión - Actualizaciones de capítulos - Común - Descargas pausadas - No hay ninguna conexión de red disponible - No hay ninguna conexión Wi-Fi disponible - No se pudo descargar el capítulo debido a un error inesperado - Error - Descargador - Se requiere WebView para que la aplicación funcione - Fallo al evitar Cloudflare - - Actualización de extensión disponible - %d actualizaciones de extensiones disponibles - %d actualizaciones de extensiones disponibles - - Error al descargar - Toca para instalar la actualización - Descargando… - Vertical - Tamaño de cuadrícula - Mostrar - Ocultar contenido de la notificación - Pantalla segura oculta el contenido de la aplicación al cambiar entre aplicaciones y bloquea las capturas de pantalla - Pantalla segura - - Después de %1$s minuto - Después de %1$s minutos - Después de %1$s minutos - - Nunca - Siempre - Bloquear cuando está inactivo - Desbloqueo requerido - Seguridad y privacidad - Gestionar notificaciones - Formato de fecha - Activado - Desactivado - Usar el del sistema - Modo oscuro - Acerca de - Avanzado - Seguimiento - Descargas - Lector - Biblioteca - General - Aplicación no disponible - Cargando… - Actualizar - Adelante - Atrás - Restaurar - Abrir registro - Más reciente - Ordenar - Desfijar - Fijar - Capítulos descargados - Cuadrícula cómoda - Cuadrícula compacta - Iniciar - Reintentar - Borrar cookies - Redes - Se canceló la restauración - La restauración de la copia de seguridad falló - Restaurando copia de seguridad - La restauración ya está en curso - La copia de seguridad falló - Creando copia de seguridad - ¿De qué quieres hacer copia de seguridad\? - La copia de seguridad ya está en curso - - Hecho en %1$s con %2$s error - Hecho en %1$s con %2$s errores - Hecho en %1$s con %2$s errores - - %02d min, %02d seg - Restauración completada - Fuentes que faltan: - La copia de seguridad no contiene ningún manga. - Archivo de copia de seguridad invalido - Copia de seguridad creada - Máximo de copias de seguridad automáticas - Frecuencia de respaldo automático - Directorio de copia de seguridad - Restaurar biblioteca desde archivo de copia de seguridad - Caché borrada. %1$d archivos se han eliminado - Usado: %1$s - Borrar caché de los capítulos - Datos - Cookies borradas - Requiere reiniciar la aplicación para que surta efecto - La optimización de la batería ya está desactivada - Ayuda con las actualizaciones y las copias de seguridad de biblioteca en segundo plano - Desactivar optimización de batería - Actualizar portadas de la biblioteca - Entradas eliminadas - ¿Estas seguro\? Los capítulos leídos y el progreso del manga que no estén en la biblioteca se perderán - Borrar el historial de manga que no están guardados en la biblioteca - Borrar base de datos - Se ha producido un error mientras se limpiaba - No se pudo abrir la configuración del dispositivo - Fijadas - Última usada - Otro - Fuente local - No se han encontrado resultados - No hay más resultados - Pestañas - Actualizando categoría - Error desconocido - Has cerrado sesión - Cerrar sesión - ¿Cerrar sesión de %1$s\? - Conectado - Iniciar sesión - Contraseña - Correo electrónico - Nombre de usuario - Iniciar sesión en %1$s - - Queda %1$s - Quedan %1$s - Quedan %1$s - - Filtrar todos los manga en tu libreria - Solo descargado - Ayuda a corregir cualquier error. No se enviarán datos sensibles - Enviar informes de errores - Actualizado a v%1$s - Buscar actualizaciones - Licencias de código abierto - Qué hay de nuevo - Versión - Sitio web - Guía de fuente local - Explorar - Recientes - Búsqueda global… - Por número de capítulo - Leer después - Pausado - En espera - Abandonado - Completado - Leyendo - Añadir seguimiento - Seguimiento - ¿Estás seguro de que deseas eliminar los capítulos seleccionados\? - No leídos - Descargar - Por fecha de subida - Por fuente - Número de capítulo - Título de la fuente - Pausado - Error - Descargando (%1$d/%2$d) - Capítulo %1$s - ¿Añadir a la biblioteca\? - Fuente no instalada: %1$s - Copiado en el portapapeles: -\n\"%1$s\" - ¿Eliminar capítulos descargados\? - - %1$s capítulo - %1$s capítulos - %1$s capítulos - - Menos - Más - Eliminado de la biblioteca - Añadido a la biblioteca - Eliminar de la biblioteca - En biblioteca - Añadir a biblioteca - Con licencia - Estado desconocido - Autor desconocido - Desconocido - En curso - No hay nuevas actualizaciones disponibles - Descargar - Seleccionar archivo de copia de seguridad - Seleccionar imagen de portada - Por favor agregue el manga a la biblioteca antes de hacer esto - Error al actualizar la portada - - Capítulos %1$s y 1 más - Capítulos %1$s y %2$d más - Capítulos %1$s y %2$d más - - Capítulos %1$s - Capítulo %1$s y %2$d más - Capítulo %1$s - - %1$d nuevo capítulo - %1$d nuevos capítulos - %1$d nuevos capítulos - - - Para %d título - Para %d títulos - Para %d títulos - - Nuevos capítulos encontrados - Buscando nuevos capítulos - No se pudieron descargar capítulos. Puedes volver a intentarlo en la sección de descargas - Copiar - Migrar - Selecciona una fuente para migrar - Selecciona datos a incluir - Caps. %1$s-%2$s - Actualizando biblioteca - Fuente no encontrada - No hay páginas - Error al cargar páginas: %1$s - Cargando páginas… - No hay capítulo anterior - No hay capítulo siguiente - Anterior: - Siguiente: - Actual: - Finalizado: - Modo de lectura - Para esta serie - ¿Usar esta imagen como portada\? - La imagen no se pudo cargar - Capítulo siguiente no encontrado - Página: %1$d - Portada actualizada - Establecer como portada - Filtro personalizado - Imagen guardada - Reiniciar todos los capítulos de este manga - Esto eliminará la fecha de lectura de este capítulo. ¿Estás seguro\? - Categorías eliminadas - ¡Ya existe una categoría con este nombre! - Tipo - Estado - Estado - Título - Puntuación - Releyendo - Buscar \"%1$s\" Globalmente - Fecha de agregado - No se pudieron descargar los capítulos debido al poco espacio de almacenamiento - Modo de lectura - Tema - - %d rastreador - %d rastreadores - %d rastreadores - - Errores - Completo - Progreso - No tienes fuentes fijadas - Páginas de seguimiento donde no has iniciado sesion: - Permitir el borrado de capítulos en favoritos - Eliminar capítulos - Las fuentes de esta extensión pueden contener contenido NSFW (18+) - 18+ - Esto no evita que las extensiones no oficiales o potencialmente marcadas incorrectamente muestren contenido NSFW (+18) dentro de la aplicación. - - Omitiendo %d capítulo, fuente no encontrada o ha sido filtrado - Omitiendo %d capítulos, fuente no encontrada o han sido filtrados - Omitiendo %d capítulos, fuente no encontrada o han sido filtrados - - %1$s: %2$s, página %3$d - Las configuraciones predeterminadas del capítulo han sido actualizadas - No se encontraron capitulos - Establecer predeterminado - Aplicar también a todos los manga en mi biblioteca - ¿Estás seguro de que quieres guardar como predeterminadas estas configuraciones\? - Ajustes del capítulo - Capítulos descargardos - Manga en la biblioteca - Ajustes de búsqueda - Pausar historial de lectura - Modo incógnito - Limpiar historial - ¿Estás seguro\? Todo el historial se perderá. - Historial borrado - Siguiente página - Página previa - Guía de migración de fuentes - Fuentes NSFW (+18) - No se encontró ninguna aplicación de selección de archivos - Por favor iniciar sesión con MAL de nuevo - Mostrar en la lista de fuentes y extensiones - Fecha de lectura terminada - Fecha de inicio de lectura - Guarda los registros de errores en un archivo para compartirlos con los desarrolladores - Compartir los registros de errores - Zona de toque - Borde - Kindle-ish - En forma de L - Descendiente - Ascendiente - Por número de capítulo - Por fecha de subida - Siguiendo - Derecha e izquierda - Mostrar cantidad de elementos - Ninguno - Presione para ver detalles - Descarga automática - Horizontal - En vertical - Rotación - Derecha - Izquierda - Crear carpetas según el título del manga - Escala de grises - Está versión de Android ya no está soportada - Falló al copiar en el portapapeles - Deshabilitar modo incógnito - DNS sobre HTTPS (DoH) - Los datos de la copia de seguridad se restaurarán. -\n -\nNecesitarás instalar cualquier extensión que falte e iniciar sesión en los servicios de seguimiento para utilizarlos. - Anterior - Siguiente - Guardar páginas en carpetas separadas - Acciones - Partir en dos las páginas anchas - Mostrar brevemente cuando se abre el lector - Excluir: %s - Incluir: %s - Dividir la página partida en la dirección contraria - Mostrar el diseño de la zona de toque - Los manga en categorías excluidas no se actualizarán aún cuando estén en categorías incluidas. - No leído - Fuente incompatible - Descargar ahora - Manga local - Por defecto - Autenticar para confirmar cambios - Los manga en categorías excluidas no se descargara, incluso si estos tambien están en las categorías incluidas. - La copia de seguridad y restauración pueden no funcionar correctamente si la Optimización de MIUI está deshabilitada. - Manzana Verde - Cancelar todo para esta serie - Ajustes de orden por categoría - Todavía no tienes categorias. - Guía de inicio rápido - No se ha encontrado ninguna coincidencia - Error al compartir la portada - Error al guardar la portada - Portada guardada - Portada - Fecha - Ordenar por - Formato de capítulo invalido - Capítulo no encontrado - Ayuda con las traducciones - Interfaz Tablet - Algunos fabricantes tienen restricciones adicionales que cierran de forma forzada los servicios en segundo plano. Este sitio web tiene más información sobre cómo arreglarlo. - Actividad en segundo plano - Rastrear - Ofrece funciones mejoradas para ciertas fuentes. Se hace un seguimiento automático del manga al añadirlo a la biblioteca. - Rastreadores mejorados - Guia de rastreo - Categorías excluidas - Más alto - Más bajo - Bajo - Alto - Sensibilidad para ocultar menú al desplazarse - Automático - Invertido - Desactivado - Activado - Si la partición de la página ancha no coincide con la dirección de lectura - Restricciones: %s - - Ayer - Hace %1$d dias - Hace %1$d dias - - Hoy - Modo oscuro (negro puro) - Yotsuba - Yin y Yang - Turquesa - Tako - Daiquirí de Fresa - Medianoche - Dinámico - Tema de la aplicación - Apariencia - Fecha de obtención del capítulo - Información de la aplicación - Instalador - Shizuku no se está ejecutando - Instale e inicie Shizuku para poder usarlo como instalador de extensiones. - Manga totales - Instalando extensión… - Legado - Alerta - Idioma - Cada 3 días - Registro detallado - Imprimir registros detallados al registro del sistema (reduce el rendimiento de la aplicación) - Actualizaciones de la aplicación - Borrar la caché de capítulos al abrir la aplicación - Base de datos limpia - Actualizar todo - Solo con Wi-Fi - Política de privacidad - Deberías tener copias de seguridad guardadas en otros sitios también. Las copias de seguridad pueden contener datos sensibles incluyendo contraseñas guardadas; tenga cuidado si lo comparte. - Publicación terminada - Cancelado - En hiatus - Si necesitas ayuda arreglando errores en la actualización de la biblioteca, ve a %1$s - Guardar como archivo CBZ - Con capitulo(s) sin leer - Omitir actualizar manga - Error al obtener la lista de extensiones - Advertencia: las descargas en masa pueden causar lentitud en las fuentes y/o bloquear Tachiyomi. Toca para conocer más. - Advertencia: las actualizaciones grandes afectan las fuentes y podría hacerlas más lentas, además de un mayor uso de batería. Toca para conocer más. - Mostrar manga - Solo portadas - Preguntas frecuentes y guías - %1$d manga que no pertenece a la biblioteca en la base de datos - Imagenes panorámicas - Ampliar imágenes anchas automáticamente - Que no han sido iniciados - Omitido porque la serie está completa - Omitido porque hay capítulos sin leer - Omitido porque no hay capítulos leídos - Toca para conocer más - Omitido - %1$d actualización(es) fallida(s) - %1$d actualización(es) omitida(s) - Retrato inverso - Mover serie al principio - Desactivado - No hay entradas para respaldar en la biblioteca - Se han limpiado los datos del WebView - Limpiar datos del WebView - Una nueva versión esta disponible desde los lanzamientos oficiales, Toca para aprender a emigrar de lanzamientos F-droid no oficiales. - Error al guardar imagen - Cerrar - Abrir en GitHub - Ninguna fuente encontrada - No se encontró ninguna fuente instalada - Contador de no leídos - Última actualización de manga - Bueno, esto es incomodo - Todas las configuraciones del lector se restablecen - No se pudo restablecer la configuración del lector - Restablecer la configuración del lector por serie - Mejora rendimiento del lector al ajustar imágenes altas descargadas - Página %d no encontrada durante la división - No se encontró la ruta del archivo de la página %d - Reinicie el modo de lectura y la orientación de toda serie - Versión - Idioma - Clasificación por edades - Lista de deseos - Lista completa - Lista inconclusa - Lista de espera - Lista de lectura - Solo en conexiones no medidas - Portada Personalizada - Imposible abrir el último capítulo leído - Error interno: Revisa los registros de fallos para más información - Borrar categoría - ¿Quieres borrar la categoría %s\? - Lavanda - Idioma de la aplicación - Sin descripción - No instalada - Descargar por adelantado - Remover todo - - El siguiente capítulo sin leer - Los siguientes %d capítulos sin leer - Los siguientes %d capítulos sin leer - - Descargar automáticamente mientras se lee - Buscar… - Botón de continuar leyendo - Tema, formato fecha y hora - Estadísticas - Empezados - Local - Descargados - Ahora no - Abrir manga aleatorio - Saltado porque el manga no requiere actualización - No se encontraron entradas en esta categoría - Categorías, actualización global y acciones al deslizar el dedo - Modo lectura, apariencia, navegación - Descargas automáticas y por adelantado - Fuentes, extensiones, búsqueda global - Respaldo manual y automático, espacio de almacenamiento - Bloqueo de aplicación, pantalla de seguridad - Guardar registros de fallo, optimizaciones de bateria - Sincronización de progreso unidireccional, sincronización mejorada - Varios idiomas - Permiso de almacenamiento no garantizado - ¡Ups! - Marea - Total - Manga completado - Tiempo de lectura - Sumario - Leidos - Con seguimiento - Manga en servicios de seguimiento - %dd - %dh - No disponible - Widget no disponible cuando el bloqueo de aplicación está activado - Estás apunto de remover \"%s\" de tu librería - Reiniciar la aplicación - %s se ha cerrado por un problema inesperado. Sugerimos que compartas los registros de errores en nuestro canal de soporte en Discord. - Populares - Última actualización de librería: %s - ¿Quitar fecha\? - Esto eliminará la fecha de inicio previamente seleccionada de %s - Esto eliminará la fecha de finalización previamente seleccionada de %s - La cadena con el agente de usuario no puede estar vacía - Solo funciona si el capítulo actual y el siguiente ya están descargados. - El nombre de agente de usuario es inválido - Índice de descargas inválido - Forzar la aplicación para comprobar los capítulos descargados - Ver el manga actualizado de forma reciente - Compilación F-Droid no están oficialmente soportadas. -\nPresionar para más información. - Justo ahora - Título desconocido - Comprobando descargas - Ubicación incorrecta: %s - Restablecer el nombre del navegador - Una actualización está actualmente en curso - ¿Estás seguro\? - Manga - Actualización global - En uso - %dm - %ds - Puntuación media - Nombre de navegador a usar - El formato RARv5 no es soportado - Categoría vacía - Mostrar conteo de no leídos en el ícono de actualizaciones - Copiado al portapapeles - Saltar capítulos duplicados - - Siguiente capítulo - Siguiente %d capítulos - Siguiente %d capítulos - - Ocultar entradas que ya están en la biblioteca - %1$s error: %2$s - Tienes una entrada en tu librería con el mismo nombre. -\n -\n¿Deseas continuar\? - *requerido - Disponible, pero la fuente no está instalada: %s - Copiar al portapapeles - Eliminar descargados - Fuera del período de publicación esperado - Deslizar a la izquierda - Personalizar intervalo - Tocar dos veces para ampliar - Obtención mensual (28 días) - Establecer intervalo - Intervalo de obtención personalizado - Próxima actualización prevista - %d por fila - Intervalos - Omitido porque no se espera ninguna actualización hoy - Dividir imágenes largas - Girar las páginas anchas para adaptarlas a la pantalla - Girar las páginas anchas en la dirección opuesta - ¿Abandonado\? Tras más de 20 días y 2 meses - Tras más de 10 días - Ha pasado el período de comprobación - Actualizar categoría - Deslizamiento de dedo en capítulos - Deslizar a la derecha - Superposición - Información de depuración - - Falta %1$s capítulo - Faltan %1$s capítulos - Faltan %1$s capítulos - - Estimar cada - Establecer la actualización cada - Aceptar - ¿Quitar el rastreo de %s\? - Esto eliminará el seguimiento localmente. - Quitar también de %s - - Un día - %d días - %d días - - Con resultados - Licenciado - No hay capítulos para mostrar - HTTP %d, comprueba la página web en WebView - Sin conexión a Internet - Índice de descargas invalidado - No se pudo crear un archivo de respaldo - Sincronizando biblioteca - Se completó la sincronización de la biblioteca - Toque aquí para obtener ayuda con Cloudflare - Inicio de sesión del rastreador - No se pudo acceder a %s - Desbloquear %s - Mover serie al final - Marcas de tiempo relativas - \"%1$s\" en lugar de \"%2$s\" - Ordenar categorías - Actualizando biblioteca… (%s) - ¿Quieres ordenar las categorías de forma alfabética\? - Configuraciónes de fuente - Configuraciones - Ningún archivo seleccionado - Crear - Nunca - Reducir el ghosting en pantallas de tinta electrónica - Aplicar - Restablecer configuración predeterminada - Última copia de seguridad automática: %s - No se encontraron scanlators - Scanlator - Destello blanco al cambiar de página - Uso de almacenamiento - Puntuación del rastreador - Datos y almacenamiento - Excluir scanlators - \ No newline at end of file diff --git a/presentation-core/build.gradle.kts b/presentation-core/build.gradle.kts index 4727dbed8d..31d10bdbd8 100644 --- a/presentation-core/build.gradle.kts +++ b/presentation-core/build.gradle.kts @@ -21,7 +21,8 @@ android { } dependencies { - implementation(project(":core")) + api(project(":core")) + api(project(":i18n")) // Compose implementation(platform(compose.bom)) diff --git a/presentation-core/src/main/java/tachiyomi/presentation/core/components/SettingsItems.kt b/presentation-core/src/main/java/tachiyomi/presentation/core/components/SettingsItems.kt index c949fa7ce4..a4a17ba3ae 100644 --- a/presentation-core/src/main/java/tachiyomi/presentation/core/components/SettingsItems.kt +++ b/presentation-core/src/main/java/tachiyomi/presentation/core/components/SettingsItems.kt @@ -1,6 +1,5 @@ package tachiyomi.presentation.core.components -import androidx.annotation.StringRes import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -42,12 +41,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import dev.icerock.moko.resources.StringResource import tachiyomi.core.preference.Preference import tachiyomi.core.preference.TriState import tachiyomi.core.preference.toggle import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.theme.header import tachiyomi.presentation.core.util.collectAsState @@ -57,8 +57,8 @@ object SettingsItemsPaddings { } @Composable -fun HeadingItem(@StringRes labelRes: Int) { - HeadingItem(stringResource(labelRes)) +fun HeadingItem(labelRes: StringResource) { + HeadingItem(localize(labelRes)) } @Composable @@ -318,7 +318,7 @@ fun TextItem(label: String, value: String, onChange: (String) -> Unit) { } @Composable -fun SettingsChipRow(@StringRes labelRes: Int, content: @Composable FlowRowScope.() -> Unit) { +fun SettingsChipRow(labelRes: StringResource, content: @Composable FlowRowScope.() -> Unit) { Column { HeadingItem(labelRes) FlowRow( @@ -335,7 +335,7 @@ fun SettingsChipRow(@StringRes labelRes: Int, content: @Composable FlowRowScope. } @Composable -fun SettingsIconGrid(@StringRes labelRes: Int, content: LazyGridScope.() -> Unit) { +fun SettingsIconGrid(labelRes: StringResource, content: LazyGridScope.() -> Unit) { Column { HeadingItem(labelRes) LazyVerticalGrid( diff --git a/presentation-core/src/main/java/tachiyomi/presentation/core/i18n/Localize.kt b/presentation-core/src/main/java/tachiyomi/presentation/core/i18n/Localize.kt new file mode 100644 index 0000000000..cb85f9aa35 --- /dev/null +++ b/presentation-core/src/main/java/tachiyomi/presentation/core/i18n/Localize.kt @@ -0,0 +1,33 @@ +package tachiyomi.presentation.core.i18n + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.ui.platform.LocalContext +import dev.icerock.moko.resources.PluralsResource +import dev.icerock.moko.resources.StringResource +import tachiyomi.core.i18n.localize +import tachiyomi.core.i18n.localizePlural + +@Composable +@ReadOnlyComposable +fun localize(resource: StringResource): String { + return LocalContext.current.localize(resource) +} + +@Composable +@ReadOnlyComposable +fun localize(resource: StringResource, vararg args: Any): String { + return LocalContext.current.localize(resource, *args) +} + +@Composable +@ReadOnlyComposable +fun localizePlural(resource: PluralsResource, count: Int): String { + return LocalContext.current.localizePlural(resource, count) +} + +@Composable +@ReadOnlyComposable +fun localizePlural(resource: PluralsResource, count: Int, vararg args: Any): String { + return LocalContext.current.localizePlural(resource, count, *args) +} diff --git a/presentation-core/src/main/java/tachiyomi/presentation/core/screens/EmptyScreen.kt b/presentation-core/src/main/java/tachiyomi/presentation/core/screens/EmptyScreen.kt index f7de6a9316..b858f3f146 100644 --- a/presentation-core/src/main/java/tachiyomi/presentation/core/screens/EmptyScreen.kt +++ b/presentation-core/src/main/java/tachiyomi/presentation/core/screens/EmptyScreen.kt @@ -1,6 +1,5 @@ package tachiyomi.presentation.core.screens -import androidx.annotation.StringRes import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -18,31 +17,32 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach +import dev.icerock.moko.resources.StringResource import kotlinx.collections.immutable.ImmutableList import tachiyomi.presentation.core.components.ActionButton import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.core.util.secondaryItemAlpha import kotlin.random.Random data class EmptyScreenAction( - @StringRes val stringResId: Int, + val stringRes: StringResource, val icon: ImageVector, val onClick: () -> Unit, ) @Composable fun EmptyScreen( - @StringRes textResource: Int, + stringRes: StringResource, modifier: Modifier = Modifier, actions: ImmutableList? = null, ) { EmptyScreen( - message = stringResource(textResource), + message = localize(stringRes), modifier = modifier, actions = actions, ) @@ -89,7 +89,7 @@ fun EmptyScreen( actions.fastForEach { ActionButton( modifier = Modifier.weight(1f), - title = stringResource(it.stringResId), + title = localize(it.stringRes), icon = it.icon, onClick = it.onClick, ) diff --git a/presentation-widget/build.gradle.kts b/presentation-widget/build.gradle.kts index e41d7be3d4..b5124f50ba 100644 --- a/presentation-widget/build.gradle.kts +++ b/presentation-widget/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { implementation(project(":core")) implementation(project(":domain")) implementation(project(":presentation-core")) + api(project(":i18n")) implementation(compose.glance) lintChecks(compose.lintchecks) diff --git a/presentation-widget/src/main/java/tachiyomi/presentation/widget/components/LockedWidget.kt b/presentation-widget/src/main/java/tachiyomi/presentation/widget/components/LockedWidget.kt index 6acb8d7ecb..ce41fe7c60 100644 --- a/presentation-widget/src/main/java/tachiyomi/presentation/widget/components/LockedWidget.kt +++ b/presentation-widget/src/main/java/tachiyomi/presentation/widget/components/LockedWidget.kt @@ -16,8 +16,8 @@ import androidx.glance.text.TextAlign import androidx.glance.text.TextStyle import androidx.glance.unit.ColorProvider import tachiyomi.core.Constants -import tachiyomi.presentation.widget.R -import tachiyomi.presentation.widget.util.stringResource +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize @Composable fun LockedWidget( @@ -34,7 +34,7 @@ fun LockedWidget( contentAlignment = Alignment.Center, ) { Text( - text = stringResource(R.string.appwidget_unavailable_locked), + text = localize(MR.strings.appwidget_unavailable_locked), style = TextStyle( color = foreground, fontSize = 12.sp, diff --git a/presentation-widget/src/main/java/tachiyomi/presentation/widget/components/UpdatesWidget.kt b/presentation-widget/src/main/java/tachiyomi/presentation/widget/components/UpdatesWidget.kt index 95beae7867..460d209f51 100644 --- a/presentation-widget/src/main/java/tachiyomi/presentation/widget/components/UpdatesWidget.kt +++ b/presentation-widget/src/main/java/tachiyomi/presentation/widget/components/UpdatesWidget.kt @@ -23,9 +23,9 @@ import androidx.glance.text.TextStyle import androidx.glance.unit.ColorProvider import kotlinx.collections.immutable.ImmutableList import tachiyomi.core.Constants -import tachiyomi.presentation.widget.R +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.localize import tachiyomi.presentation.widget.util.calculateRowAndColumnCount -import tachiyomi.presentation.widget.util.stringResource @Composable fun UpdatesWidget( @@ -43,7 +43,7 @@ fun UpdatesWidget( CircularProgressIndicator(color = contentColor) } else if (data.isEmpty()) { Text( - text = stringResource(R.string.information_no_recent), + text = localize(MR.strings.information_no_recent), style = TextStyle(color = contentColor), ) } else { diff --git a/presentation-widget/src/main/java/tachiyomi/presentation/widget/util/GlanceUtils.kt b/presentation-widget/src/main/java/tachiyomi/presentation/widget/util/GlanceUtils.kt index 51710a1be2..d6d545c315 100644 --- a/presentation-widget/src/main/java/tachiyomi/presentation/widget/util/GlanceUtils.kt +++ b/presentation-widget/src/main/java/tachiyomi/presentation/widget/util/GlanceUtils.kt @@ -1,11 +1,8 @@ package tachiyomi.presentation.widget.util -import androidx.annotation.StringRes -import androidx.compose.runtime.Composable import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize import androidx.glance.GlanceModifier -import androidx.glance.LocalContext import androidx.glance.appwidget.cornerRadius import tachiyomi.presentation.widget.R @@ -17,11 +14,6 @@ fun GlanceModifier.appWidgetInnerRadius(): GlanceModifier { return this.cornerRadius(R.dimen.appwidget_inner_radius) } -@Composable -fun stringResource(@StringRes id: Int): String { - return LocalContext.current.getString(id) -} - /** * Calculates row-column count. * diff --git a/source-api/src/commonMain/AndroidManifest.xml b/source-api/src/androidMain/AndroidManifest.xml similarity index 100% rename from source-api/src/commonMain/AndroidManifest.xml rename to source-api/src/androidMain/AndroidManifest.xml diff --git a/source-local/build.gradle.kts b/source-local/build.gradle.kts index 758f0a8643..71d88804cc 100644 --- a/source-local/build.gradle.kts +++ b/source-local/build.gradle.kts @@ -9,6 +9,8 @@ kotlin { val commonMain by getting { dependencies { implementation(project(":source-api")) + api(project(":i18n")) + implementation(libs.unifile) implementation(libs.junrar) } diff --git a/source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt b/source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt index 951b163b6a..96e882d234 100644 --- a/source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt +++ b/source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt @@ -16,6 +16,7 @@ import kotlinx.serialization.json.decodeFromStream import logcat.LogPriority import nl.adaptivity.xmlutil.AndroidXmlReader import nl.adaptivity.xmlutil.serialization.XML +import tachiyomi.core.i18n.localize import tachiyomi.core.metadata.comicinfo.COMIC_INFO_FILE import tachiyomi.core.metadata.comicinfo.ComicInfo import tachiyomi.core.metadata.comicinfo.copyFromComicInfo @@ -26,6 +27,7 @@ import tachiyomi.core.util.system.ImageUtil import tachiyomi.core.util.system.logcat import tachiyomi.domain.chapter.service.ChapterRecognition import tachiyomi.domain.manga.model.Manga +import tachiyomi.i18n.MR import tachiyomi.source.local.filter.OrderBy import tachiyomi.source.local.image.LocalCoverManager import tachiyomi.source.local.io.Archive @@ -55,7 +57,7 @@ actual class LocalSource( private val POPULAR_FILTERS = FilterList(OrderBy.Popular(context)) private val LATEST_FILTERS = FilterList(OrderBy.Latest(context)) - override val name: String = context.getString(R.string.local_source) + override val name: String = context.localize(MR.strings.local_source) override val id: Long = ID @@ -310,9 +312,9 @@ actual class LocalSource( .map { dir -> File(dir, chapter.url) } .find { it.exists() } ?.let(Format.Companion::valueOf) - ?: throw Exception(context.getString(R.string.chapter_not_found)) + ?: throw Exception(context.localize(MR.strings.chapter_not_found)) } catch (e: Format.UnknownFormatException) { - throw Exception(context.getString(R.string.local_invalid_format)) + throw Exception(context.localize(MR.strings.local_invalid_format)) } catch (e: Exception) { throw e } diff --git a/source-local/src/androidMain/kotlin/tachiyomi/source/local/filter/OrderBy.kt b/source-local/src/androidMain/kotlin/tachiyomi/source/local/filter/OrderBy.kt index 39e91cc6f1..58f039f879 100644 --- a/source-local/src/androidMain/kotlin/tachiyomi/source/local/filter/OrderBy.kt +++ b/source-local/src/androidMain/kotlin/tachiyomi/source/local/filter/OrderBy.kt @@ -2,11 +2,12 @@ package tachiyomi.source.local.filter import android.content.Context import eu.kanade.tachiyomi.source.model.Filter -import tachiyomi.source.local.R +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR sealed class OrderBy(context: Context, selection: Selection) : Filter.Sort( - context.getString(R.string.local_filter_order_by), - arrayOf(context.getString(R.string.title), context.getString(R.string.date)), + context.localize(MR.strings.local_filter_order_by), + arrayOf(context.localize(MR.strings.title), context.localize(MR.strings.date)), selection, ) { class Popular(context: Context) : OrderBy(context, Selection(0, true)) diff --git a/source-local/src/androidMain/kotlin/tachiyomi/source/local/io/LocalSourceFileSystem.kt b/source-local/src/androidMain/kotlin/tachiyomi/source/local/io/LocalSourceFileSystem.kt index a986b5a172..617ed5f3df 100644 --- a/source-local/src/androidMain/kotlin/tachiyomi/source/local/io/LocalSourceFileSystem.kt +++ b/source-local/src/androidMain/kotlin/tachiyomi/source/local/io/LocalSourceFileSystem.kt @@ -2,14 +2,15 @@ package tachiyomi.source.local.io import android.content.Context import eu.kanade.tachiyomi.util.storage.DiskUtil -import tachiyomi.source.local.R +import tachiyomi.core.i18n.localize +import tachiyomi.i18n.MR import java.io.File actual class LocalSourceFileSystem( private val context: Context, ) { - private val baseFolderLocation = "${context.getString(R.string.app_name)}${File.separator}local" + private val baseFolderLocation = "${context.localize(MR.strings.app_name)}${File.separator}local" actual fun getBaseDirectories(): Sequence { return DiskUtil.getExternalStorages(context)