Migrate to multiplatform string resources (#10147)

* Migrate to multiplatform string resources

* Move plurals translations into separate files

* Fix lint check on generated files
This commit is contained in:
arkon
2023-11-18 13:54:56 -05:00
committed by GitHub
parent c39ae21f4a
commit 46e734fc8e
340 changed files with 5741 additions and 6292 deletions
@@ -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),
@@ -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)
}
}
}
@@ -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<ExtensionUiModel.Header, List<ExtensionUiModel
object ExtensionUiModel {
sealed interface Header {
data class Resource(@StringRes val textRes: Int) : Header
data class Resource(val textRes: StringResource) : Header
data class Text(val text: String) : Header
}
@@ -5,16 +5,16 @@ import androidx.compose.material.icons.outlined.Translate
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.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.presentation.browse.ExtensionScreen
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.TabContent
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreen
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.localize
@Composable
fun extensionsTab(
@@ -24,12 +24,12 @@ fun extensionsTab(
val state by extensionsScreenModel.state.collectAsState()
return TabContent(
titleRes = R.string.label_extensions,
titleRes = MR.strings.label_extensions,
badgeNumber = state.updates.takeIf { it > 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()) },
),
@@ -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<MigrationFlag> {
val flags = mutableListOf<MigrationFlag>()
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
@@ -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)
}
}
}
@@ -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))
}
}
},
@@ -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,
)
@@ -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")
@@ -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
@@ -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) {
@@ -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))
},
)
}
@@ -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()