From f6110d6f2c627e0ab40b30e04d901557f4dec0e9 Mon Sep 17 00:00:00 2001 From: AE Date: Thu, 27 Aug 2026 01:58:25 +0300 Subject: [PATCH 1/2] fix(i18n): add quantity-aware plural resources --- .../flow/notification/NotificationHelper.kt | 26 +- .../ui/components/FlowCommentsBottomSheet.kt | 7 +- .../aedev/flow/ui/components/PlaylistCard.kt | 3 +- .../flow/ui/components/SleepTimerSheet.kt | 301 ++++++----- .../aedev/flow/ui/screens/home/HomeScreen.kt | 3 +- .../ui/screens/library/DownloadsScreen.kt | 6 +- .../flow/ui/screens/music/LibraryScreen.kt | 3 +- .../screens/music/MusicPlaylistsViewModel.kt | 23 +- .../flow/ui/screens/music/PlaylistPage.kt | 5 +- .../ui/screens/onboarding/ChannelsStep.kt | 8 +- .../ui/screens/onboarding/OnboardingScreen.kt | 448 +++++++++-------- .../PersonalityDashboardSections.kt | 472 +++++++++--------- .../screens/playlists/PlaylistDetailScreen.kt | 60 ++- .../ui/screens/settings/AppearanceScreen.kt | 7 +- .../settings/DownloadSettingsScreen.kt | 10 +- .../ui/screens/settings/ImportDataScreen.kt | 7 +- .../screens/settings/PlayerSettingsScreen.kt | 21 +- .../settings/SearchHistorySettingsScreen.kt | 24 +- .../ui/screens/settings/SettingsScreen.kt | 48 +- .../screens/settings/TimeManagementScreen.kt | 5 +- .../settings/TimeManagementViewModel.kt | 13 +- .../screens/settings/UserPreferencesScreen.kt | 22 +- .../subscriptions/SubscriptionsScreen.kt | 10 +- .../flow/ui/screens/sync/SyncSetupContent.kt | 9 +- .../ui/tv/player/panels/TvPlayerPanelsHost.kt | 10 +- .../ui/tv/screens/TvPlaylistDetailScreen.kt | 17 +- .../ui/tv/screens/TvSubscriptionsScreen.kt | 6 +- app/src/main/res/values-ar/strings.xml | 56 --- app/src/main/res/values-az/strings.xml | 53 -- app/src/main/res/values-bs/strings.xml | 9 - app/src/main/res/values-cs/strings.xml | 1 - app/src/main/res/values-de/strings.xml | 47 -- app/src/main/res/values-es/strings.xml | 56 --- app/src/main/res/values-et/strings.xml | 10 - app/src/main/res/values-fr/strings.xml | 56 --- app/src/main/res/values-hi/strings.xml | 39 -- app/src/main/res/values-in/strings.xml | 56 --- app/src/main/res/values-it/strings.xml | 51 -- app/src/main/res/values-ja/strings.xml | 8 - app/src/main/res/values-ko/strings.xml | 53 -- app/src/main/res/values-pl/strings.xml | 47 -- app/src/main/res/values-pt-rBR/strings.xml | 55 -- app/src/main/res/values-pt/strings.xml | 9 - app/src/main/res/values-ru/strings.xml | 56 --- app/src/main/res/values-si/strings.xml | 3 - app/src/main/res/values-sr/strings.xml | 2 - app/src/main/res/values-tr/strings.xml | 53 -- app/src/main/res/values-uk/strings.xml | 56 --- app/src/main/res/values-vi/strings.xml | 56 --- app/src/main/res/values-zh-rCN/strings.xml | 49 -- app/src/main/res/values-zh-rTW/strings.xml | 3 - app/src/main/res/values/strings.xml | 216 +++++--- 52 files changed, 1096 insertions(+), 1578 deletions(-) diff --git a/app/src/main/java/io/github/aedev/flow/notification/NotificationHelper.kt b/app/src/main/java/io/github/aedev/flow/notification/NotificationHelper.kt index ca088b34b..8d2076342 100644 --- a/app/src/main/java/io/github/aedev/flow/notification/NotificationHelper.kt +++ b/app/src/main/java/io/github/aedev/flow/notification/NotificationHelper.kt @@ -534,7 +534,13 @@ object NotificationHelper { val inboxStyle = NotificationCompat .InboxStyle() - .setBigContentTitle(context.getString(R.string.notification_new_videos_from_subscriptions, videos.size)) + .setBigContentTitle( + context.resources.getQuantityString( + R.plurals.notification_new_videos_from_subscriptions, + videos.size, + videos.size, + ), + ) videos.take(6).forEach { v -> inboxStyle.addLine("${v.channelName}: ${v.videoTitle}") } @@ -547,8 +553,13 @@ object NotificationHelper { .Builder(context, CHANNEL_SUBSCRIPTIONS) .setSmallIcon(R.drawable.ic_notification_logo) .setContentTitle(context.getString(R.string.notification_new_videos)) - .setContentText(context.getString(R.string.notification_new_videos_from_subscriptions, videos.size)) - .setContentIntent(summaryPendingIntent) + .setContentText( + context.resources.getQuantityString( + R.plurals.notification_new_videos_from_subscriptions, + videos.size, + videos.size, + ), + ).setContentIntent(summaryPendingIntent) .setAutoCancel(true) .setOnlyAlertOnce(true) .setPriority(NotificationCompat.PRIORITY_DEFAULT) @@ -651,8 +662,13 @@ object NotificationHelper { .Builder(context, CHANNEL_SUBSCRIPTIONS) .setSmallIcon(R.drawable.ic_notification_logo) .setContentTitle(context.getString(R.string.notification_new_videos)) - .setContentText(context.getString(R.string.notification_new_videos_from_subscriptions, videoCount)) - .setGroup("new_videos") + .setContentText( + context.resources.getQuantityString( + R.plurals.notification_new_videos_from_subscriptions, + videoCount, + videoCount, + ), + ).setGroup("new_videos") .setGroupSummary(true) .setAutoCancel(true) .setPriority(NotificationCompat.PRIORITY_DEFAULT) diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/FlowCommentsBottomSheet.kt b/app/src/main/java/io/github/aedev/flow/ui/components/FlowCommentsBottomSheet.kt index 183781b00..5bfb66b63 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/FlowCommentsBottomSheet.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/FlowCommentsBottomSheet.kt @@ -76,6 +76,7 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextLayoutResult import androidx.compose.ui.text.font.FontWeight @@ -724,7 +725,11 @@ fun FlowCommentItem( R.string.hide_replies, ) } else { - stringResource(R.string.view_replies_template, comment.replyCount) + pluralStringResource( + R.plurals.view_replies_template, + comment.replyCount, + comment.replyCount, + ) }, color = MaterialTheme.colorScheme.primary, style = MaterialTheme.typography.labelMedium, diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/PlaylistCard.kt b/app/src/main/java/io/github/aedev/flow/ui/components/PlaylistCard.kt index af1588a27..3b0c61566 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/PlaylistCard.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/PlaylistCard.kt @@ -36,6 +36,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.blur import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow @@ -113,7 +114,7 @@ private fun PlaylistCardContent( it, stringResource(R.string.playlist), ) - } ?: stringResource(R.string.videos_count_template, videoCount) + } ?: pluralStringResource(R.plurals.videos_count_template, videoCount, videoCount) if (layout == PlaylistCardLayout.SHELF) { Column( diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/SleepTimerSheet.kt b/app/src/main/java/io/github/aedev/flow/ui/components/SleepTimerSheet.kt index 6cbbafce3..c35a34db9 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/SleepTimerSheet.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/SleepTimerSheet.kt @@ -44,6 +44,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.SideEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf @@ -52,7 +53,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberUpdatedState -import androidx.compose.runtime.SideEffect import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -62,6 +62,7 @@ import androidx.compose.ui.input.pointer.util.addPointerInputChange import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType @@ -82,7 +83,7 @@ fun SleepTimerSheet( enableVerticalDismiss: Boolean = true, asBottomSheet: Boolean = true, onSheetProgressChange: (Float) -> Unit = {}, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { val isActive = SleepTimerManager.isActive val pauseAtEndOfMedia = SleepTimerManager.pauseAtEndOfMedia @@ -91,7 +92,7 @@ fun SleepTimerSheet( val context = LocalContext.current val playerPreferences = remember(context) { PlayerPreferences(context) } val preferredCloseAppOnExpiry by playerPreferences.sleepTimerCloseAppOnExpiry.collectAsState( - initial = SleepTimerManager.preferredCloseAppOnExpiry + initial = SleepTimerManager.preferredCloseAppOnExpiry, ) val coroutineScope = rememberCoroutineScope() @@ -113,7 +114,7 @@ fun SleepTimerSheet( var inputError by remember { mutableStateOf(false) } var closeApp by remember { mutableStateOf( - if (isActive) activeCloseAppOnExpiry else SleepTimerManager.preferredCloseAppOnExpiry + if (isActive) activeCloseAppOnExpiry else SleepTimerManager.preferredCloseAppOnExpiry, ) } @@ -164,10 +165,12 @@ fun SleepTimerSheet( customInput.isNotEmpty() && (minutes == null || minutes < 1 || minutes > 1440) -> { inputError = true } + customInput.isNotEmpty() && minutes != null -> { SleepTimerManager.start(minutes, closeApp) onDismiss() } + else -> { SleepTimerManager.start(sliderValue.roundToInt(), closeApp) onDismiss() @@ -189,7 +192,7 @@ fun SleepTimerSheet( SleepTimerManager.cancel() onDismiss() }, - modifier = contentModifier + modifier = contentModifier, ) } @@ -201,26 +204,26 @@ fun SleepTimerSheet( enableVerticalDismiss = enableVerticalDismiss, onSheetProgressChange = onSheetProgressChange, modifier = modifier, - content = content + content = content, ) } else { Surface( modifier = modifier.fillMaxSize(), color = MaterialTheme.colorScheme.surface, - tonalElevation = 0.dp + tonalElevation = 0.dp, ) { Column(modifier = Modifier.fillMaxSize()) { SleepTimerHeader( onDismiss = onDismiss, showDragHandle = false, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) content( Modifier .fillMaxWidth() .weight(1f) .verticalScroll(rememberScrollState()) - .padding(horizontal = 20.dp, vertical = 18.dp) + .padding(horizontal = 20.dp, vertical = 18.dp), ) } } @@ -235,7 +238,7 @@ private fun FlowSleepTimerBottomSheet( enableVerticalDismiss: Boolean, onSheetProgressChange: (Float) -> Unit, modifier: Modifier, - content: @Composable (Modifier) -> Unit + content: @Composable (Modifier) -> Unit, ) { val configuration = LocalConfiguration.current val density = LocalDensity.current @@ -248,11 +251,12 @@ private fun FlowSleepTimerBottomSheet( val dismissThresholdPx = collapsedHeightPx + sheetProgressRangePx * 0.55f val sheetHeightPx = remember { Animatable(0f) } var isAnimatingOut by remember { mutableStateOf(false) } - val sheetProgress = if (expandedHeightPx > 0f) { - ((sheetHeightPx.value - collapsedHeightPx) / sheetProgressRangePx).coerceIn(0f, 1f) - } else { - 0f - } + val sheetProgress = + if (expandedHeightPx > 0f) { + ((sheetHeightPx.value - collapsedHeightPx) / sheetProgressRangePx).coerceIn(0f, 1f) + } else { + 0f + } SideEffect { onSheetProgressChange(sheetProgress) } @@ -265,10 +269,11 @@ private fun FlowSleepTimerBottomSheet( coroutineScope.launch { sheetHeightPx.animateTo( targetValue = expandedHeightPx, - animationSpec = spring( - dampingRatio = Spring.DampingRatioNoBouncy, - stiffness = Spring.StiffnessLow - ) + animationSpec = + spring( + dampingRatio = Spring.DampingRatioNoBouncy, + stiffness = Spring.StiffnessLow, + ), ) } } @@ -283,10 +288,11 @@ private fun FlowSleepTimerBottomSheet( coroutineScope.launch { sheetHeightPx.animateTo( targetValue = collapsedHeightPx, - animationSpec = spring( - dampingRatio = Spring.DampingRatioNoBouncy, - stiffness = Spring.StiffnessLow - ) + animationSpec = + spring( + dampingRatio = Spring.DampingRatioNoBouncy, + stiffness = Spring.StiffnessLow, + ), ) latestOnDismiss() } @@ -304,70 +310,79 @@ private fun FlowSleepTimerBottomSheet( } sheetHeightPx.animateTo( targetValue = expandedHeightPx, - animationSpec = spring( - dampingRatio = Spring.DampingRatioNoBouncy, - stiffness = Spring.StiffnessLow - ) + animationSpec = + spring( + dampingRatio = Spring.DampingRatioNoBouncy, + stiffness = Spring.StiffnessLow, + ), ) } BackHandler(onBack = ::animateToDismiss) - val headerDragModifier = if (enableVerticalDismiss) Modifier.pointerInput(expandedHeightPx, collapsedHeightPx, dismissThresholdPx, isAnimatingOut) { - val velocityTracker = VelocityTracker() - detectVerticalDragGestures( - onVerticalDrag = { change, dragAmount -> - if (isAnimatingOut) return@detectVerticalDragGestures - velocityTracker.addPointerInputChange(change) - coroutineScope.launch { - val nextValue = (sheetHeightPx.value - dragAmount).coerceIn(collapsedHeightPx, expandedHeightPx) - sheetHeightPx.snapTo(nextValue) - } - }, - onDragCancel = { - velocityTracker.resetTracking() - if (!isAnimatingOut) animateToExpanded() - }, - onDragEnd = { - val velocityY = velocityTracker.calculateVelocity().y - velocityTracker.resetTracking() - when { - velocityY > 1200f || sheetHeightPx.value < dismissThresholdPx -> animateToDismiss() - else -> animateToExpanded() - } + val headerDragModifier = + if (enableVerticalDismiss) { + Modifier.pointerInput(expandedHeightPx, collapsedHeightPx, dismissThresholdPx, isAnimatingOut) { + val velocityTracker = VelocityTracker() + detectVerticalDragGestures( + onVerticalDrag = { change, dragAmount -> + if (isAnimatingOut) return@detectVerticalDragGestures + velocityTracker.addPointerInputChange(change) + coroutineScope.launch { + val nextValue = (sheetHeightPx.value - dragAmount).coerceIn(collapsedHeightPx, expandedHeightPx) + sheetHeightPx.snapTo(nextValue) + } + }, + onDragCancel = { + velocityTracker.resetTracking() + if (!isAnimatingOut) animateToExpanded() + }, + onDragEnd = { + val velocityY = velocityTracker.calculateVelocity().y + velocityTracker.resetTracking() + when { + velocityY > 1200f || sheetHeightPx.value < dismissThresholdPx -> animateToDismiss() + else -> animateToExpanded() + } + }, + ) } - ) - } else Modifier + } else { + Modifier + } Box( modifier = modifier.fillMaxSize(), - contentAlignment = Alignment.BottomCenter + contentAlignment = Alignment.BottomCenter, ) { Surface( - modifier = Modifier - .fillMaxWidth() - .height(with(density) { sheetHeightPx.value.toDp() }), + modifier = + Modifier + .fillMaxWidth() + .height(with(density) { sheetHeightPx.value.toDp() }), color = MaterialTheme.colorScheme.surface, - tonalElevation = 0.dp + tonalElevation = 0.dp, ) { Column( - modifier = Modifier - .fillMaxWidth() - .navigationBarsPadding() + modifier = + Modifier + .fillMaxWidth() + .navigationBarsPadding(), ) { SleepTimerHeader( onDismiss = ::animateToDismiss, showDragHandle = true, - modifier = Modifier - .fillMaxWidth() - .then(headerDragModifier) + modifier = + Modifier + .fillMaxWidth() + .then(headerDragModifier), ) content( Modifier .fillMaxWidth() .weight(1f) .verticalScroll(rememberScrollState()) - .padding(horizontal = 20.dp, vertical = 18.dp) + .padding(horizontal = 20.dp, vertical = 18.dp), ) } } @@ -379,38 +394,40 @@ private fun FlowSleepTimerBottomSheet( private fun SleepTimerHeader( onDismiss: () -> Unit, showDragHandle: Boolean, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Column(modifier = modifier) { if (showDragHandle) { Box( - modifier = Modifier - .fillMaxWidth() - .padding(top = 4.dp), - contentAlignment = Alignment.Center + modifier = + Modifier + .fillMaxWidth() + .padding(top = 4.dp), + contentAlignment = Alignment.Center, ) { BottomSheetDefaults.DragHandle() } } Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 20.dp, end = 8.dp, top = if (showDragHandle) 4.dp else 10.dp, bottom = 8.dp), + modifier = + Modifier + .fillMaxWidth() + .padding(start = 20.dp, end = 8.dp, top = if (showDragHandle) 4.dp else 10.dp, bottom = 8.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp) + horizontalArrangement = Arrangement.spacedBy(12.dp), ) { Icon( imageVector = Icons.Outlined.Bedtime, contentDescription = null, tint = MaterialTheme.colorScheme.primary, - modifier = Modifier.size(24.dp) + modifier = Modifier.size(24.dp), ) Text( text = stringResource(R.string.sleep_timer), style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) IconButton(onClick = onDismiss) { Icon(Icons.Filled.Close, contentDescription = stringResource(R.string.close)) @@ -437,11 +454,11 @@ private fun SleepTimerSheetContent( onCloseAppToggle: (Boolean) -> Unit, onReset: () -> Unit, onCancelTimer: () -> Unit, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Column( modifier = modifier.animateContentSize(), - verticalArrangement = Arrangement.spacedBy(16.dp) + verticalArrangement = Arrangement.spacedBy(16.dp), ) { AnimatedContent(targetState = isActive, label = "sleepTimerContent") { active -> if (active) { @@ -450,7 +467,7 @@ private fun SleepTimerSheetContent( remainingMs = remainingMs, closeAppOnExpiry = closeAppOnExpiry, onReset = onReset, - onCancel = onCancelTimer + onCancel = onCancelTimer, ) } else { InactiveTimerContent( @@ -463,7 +480,7 @@ private fun SleepTimerSheetContent( onCancel = onCancel, onStart = onStart, closeAppOnExpiry = closeAppOnExpiry, - onCloseAppToggle = onCloseAppToggle + onCloseAppToggle = onCloseAppToggle, ) } } @@ -476,39 +493,42 @@ private fun ActiveTimerContent( remainingMs: Long, onReset: () -> Unit, onCancel: () -> Unit, - closeAppOnExpiry: Boolean = false + closeAppOnExpiry: Boolean = false, ) { Column( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Card( - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.primaryContainer, - contentColor = MaterialTheme.colorScheme.onPrimaryContainer - ), - modifier = Modifier.fillMaxWidth() + colors = + CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + contentColor = MaterialTheme.colorScheme.onPrimaryContainer, + ), + modifier = Modifier.fillMaxWidth(), ) { Column( - modifier = Modifier - .fillMaxWidth() - .padding(20.dp), + modifier = + Modifier + .fillMaxWidth() + .padding(20.dp), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(6.dp) + verticalArrangement = Arrangement.spacedBy(6.dp), ) { Text( text = stringResource(R.string.sleep_timer_stops_in), - style = MaterialTheme.typography.bodyMedium + style = MaterialTheme.typography.bodyMedium, ) Text( - text = if (pauseAtEndOfMedia) { - stringResource(R.string.sleep_timer_end_of_media) - } else { - formatCountdown(remainingMs) - }, + text = + if (pauseAtEndOfMedia) { + stringResource(R.string.sleep_timer_end_of_media) + } else { + formatCountdown(remainingMs) + }, style = MaterialTheme.typography.displaySmall, - fontWeight = FontWeight.Bold + fontWeight = FontWeight.Bold, ) } } @@ -517,24 +537,24 @@ private fun ActiveTimerContent( Text( text = stringResource(R.string.sleep_timer_will_close_app), style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.secondary + color = MaterialTheme.colorScheme.secondary, ) } Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(12.dp) + horizontalArrangement = Arrangement.spacedBy(12.dp), ) { OutlinedButton( onClick = onReset, modifier = Modifier.weight(1f), - enabled = !pauseAtEndOfMedia + enabled = !pauseAtEndOfMedia, ) { Text(stringResource(R.string.sleep_timer_reset)) } Button( onClick = onCancel, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) { Text(stringResource(R.string.sleep_timer_cancel_timer)) } @@ -553,36 +573,42 @@ private fun InactiveTimerContent( onCancel: () -> Unit, onStart: () -> Unit, closeAppOnExpiry: Boolean, - onCloseAppToggle: (Boolean) -> Unit + onCloseAppToggle: (Boolean) -> Unit, ) { Column( modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(16.dp) + verticalArrangement = Arrangement.spacedBy(16.dp), ) { Card( - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceContainerHighest.copy(alpha = 0.7f) - ) + colors = + CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainerHighest.copy(alpha = 0.7f), + ), ) { Column( modifier = Modifier.padding(16.dp), - verticalArrangement = Arrangement.spacedBy(4.dp) + verticalArrangement = Arrangement.spacedBy(4.dp), ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Text( text = stringResource(R.string.sleep_timer_duration), style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) Text( - text = stringResource(R.string.sleep_timer_minutes, sliderValue.roundToInt()), + text = + pluralStringResource( + R.plurals.sleep_timer_minutes, + sliderValue.roundToInt(), + sliderValue.roundToInt(), + ), style = MaterialTheme.typography.labelLarge, fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.primary + color = MaterialTheme.colorScheme.primary, ) } @@ -591,22 +617,22 @@ private fun InactiveTimerContent( onValueChange = onSliderChange, valueRange = 5f..120f, steps = 22, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween + horizontalArrangement = Arrangement.SpaceBetween, ) { Text( text = stringResource(R.string.sleep_timer_min_label), style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) Text( text = stringResource(R.string.sleep_timer_max_label), style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) } } @@ -616,9 +642,12 @@ private fun InactiveTimerContent( value = customInput, onValueChange = onCustomInputChange, label = { Text(stringResource(R.string.sleep_timer_custom_label)) }, - supportingText = if (inputError) { - { Text(stringResource(R.string.sleep_timer_input_error)) } - } else null, + supportingText = + if (inputError) { + { Text(stringResource(R.string.sleep_timer_input_error)) } + } else { + null + }, isError = inputError, singleLine = true, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), @@ -627,20 +656,20 @@ private fun InactiveTimerContent( text = stringResource(R.string.sleep_timer_unit), style = MaterialTheme.typography.bodyMedium, modifier = Modifier.padding(end = 12.dp), - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) }, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) OutlinedButton( onClick = onEndOfMedia, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) { Icon( imageVector = Icons.Outlined.Bedtime, contentDescription = null, - modifier = Modifier.size(18.dp) + modifier = Modifier.size(18.dp), ) Spacer(Modifier.width(8.dp)) Text(stringResource(R.string.sleep_timer_end_of_song)) @@ -648,33 +677,35 @@ private fun InactiveTimerContent( Card( modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceContainerHighest.copy(alpha = 0.7f) - ) + colors = + CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainerHighest.copy(alpha = 0.7f), + ), ) { Row( - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 64.dp) - .padding(horizontal = 16.dp, vertical = 10.dp), + modifier = + Modifier + .fillMaxWidth() + .heightIn(min = 64.dp) + .padding(horizontal = 16.dp, vertical = 10.dp), horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Column(modifier = Modifier.weight(1f)) { Text( text = stringResource(R.string.sleep_timer_close_app), style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurface + color = MaterialTheme.colorScheme.onSurface, ) Text( text = stringResource(R.string.sleep_timer_close_app_desc), style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) } Switch( checked = closeAppOnExpiry, - onCheckedChange = onCloseAppToggle + onCheckedChange = onCloseAppToggle, ) } } @@ -683,17 +714,17 @@ private fun InactiveTimerContent( Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(12.dp) + horizontalArrangement = Arrangement.spacedBy(12.dp), ) { TextButton( onClick = onCancel, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) { Text(stringResource(R.string.cancel)) } Button( onClick = onStart, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) { Text(stringResource(R.string.sleep_timer_start)) } diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/home/HomeScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/home/HomeScreen.kt index fee21ee8c..2516174d7 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/home/HomeScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/home/HomeScreen.kt @@ -36,6 +36,7 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId @@ -519,7 +520,7 @@ private fun FlowFeedFooter( color = MaterialTheme.colorScheme.onSurface, ) Text( - text = stringResource(R.string.videos_curated_template, videoCount), + text = pluralStringResource(R.plurals.videos_curated_template, videoCount, videoCount), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/library/DownloadsScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/library/DownloadsScreen.kt index 59b064655..3269acd20 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/library/DownloadsScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/library/DownloadsScreen.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalHapticFeedback +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.contentDescription @@ -204,8 +205,9 @@ fun DownloadsScreen( title = { Text(stringResource(R.string.remove_incomplete_downloads)) }, text = { Text( - stringResource( - R.string.remove_incomplete_downloads_message, + pluralStringResource( + R.plurals.remove_incomplete_downloads_message, + uiState.incompleteDownloadCount, uiState.incompleteDownloadCount, ), ) diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/music/LibraryScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/music/LibraryScreen.kt index f1453e2a0..bbfb8bfcd 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/music/LibraryScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/music/LibraryScreen.kt @@ -21,6 +21,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -250,7 +251,7 @@ private fun FavoritesTab( ) Spacer(Modifier.width(8.dp)) Text( - stringResource(R.string.favorites_count_template, favorites.size), + pluralStringResource(R.plurals.favorites_count_template, favorites.size, favorites.size), style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold, ) diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/music/MusicPlaylistsViewModel.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/music/MusicPlaylistsViewModel.kt index fc6a5ebad..d9c0714f5 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/music/MusicPlaylistsViewModel.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/music/MusicPlaylistsViewModel.kt @@ -220,7 +220,12 @@ class MusicPlaylistsViewModel Toast .makeText( context, - context.getString(R.string.toast_downloaded_tracks_from_playlist, successCount, playlist.name), + context.resources.getQuantityString( + R.plurals.toast_downloaded_tracks_from_playlist, + successCount, + successCount, + playlist.name, + ), Toast.LENGTH_LONG, ).show() } else { @@ -301,7 +306,16 @@ class MusicPlaylistsViewModel successCount = tracks.size if (successCount > 0) { - Toast.makeText(context, context.getString(R.string.toast_downloaded_tracks, successCount), Toast.LENGTH_LONG).show() + Toast + .makeText( + context, + context.resources.getQuantityString( + R.plurals.toast_downloaded_tracks, + successCount, + successCount, + ), + Toast.LENGTH_LONG, + ).show() } } catch (e: Exception) { Log.e("MusicViewModel", "Error downloading playlist details", e) @@ -505,8 +519,9 @@ class MusicPlaylistsViewModel Toast .makeText( context, - context.getString( - io.github.aedev.flow.R.string.merge_playlist_success, + context.resources.getQuantityString( + io.github.aedev.flow.R.plurals.merge_playlist_success, + tracks.size, tracks.size, targetInfo?.name ?: "", ), diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/music/PlaylistPage.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/music/PlaylistPage.kt index 4d4ea4cfd..6672395c6 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/music/PlaylistPage.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/music/PlaylistPage.kt @@ -1161,8 +1161,9 @@ private fun MusicMergeIntoPlaylistDialog( ) Text( text = - androidx.compose.ui.res.stringResource( - io.github.aedev.flow.R.string.songs_count_template, + androidx.compose.ui.res.pluralStringResource( + io.github.aedev.flow.R.plurals.songs_count_template, + playlist.videoCount, playlist.videoCount, ), style = MaterialTheme.typography.bodySmall, diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/onboarding/ChannelsStep.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/onboarding/ChannelsStep.kt index 0a113cf75..f1322bd41 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/onboarding/ChannelsStep.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/onboarding/ChannelsStep.kt @@ -49,6 +49,7 @@ import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction @@ -169,7 +170,12 @@ internal fun ChannelsStep( if (subscribedInSession.isNotEmpty()) { item { Text( - text = stringResource(R.string.onboarding_channels_added_count, subscribedInSession.size), + text = + pluralStringResource( + R.plurals.onboarding_channels_added_count, + subscribedInSession.size, + subscribedInSession.size, + ), style = MaterialTheme.typography.labelLarge, fontWeight = FontWeight.SemiBold, color = MaterialTheme.colorScheme.primary, diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/onboarding/OnboardingScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/onboarding/OnboardingScreen.kt index 1ea4869b0..64fbf5899 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/onboarding/OnboardingScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/onboarding/OnboardingScreen.kt @@ -68,16 +68,19 @@ fun OnboardingScreen(onComplete: () -> Unit) { LaunchedEffect(importState) { when (val s = importState) { is ImportViewModel.State.Success -> { - importMessage = s.message ?: if ((s.count ?: 0) > 0) + importMessage = s.message ?: if ((s.count ?: 0) > 0) { "Imported ${s.count} ${s.label.lowercase()}" - else + } else { "${s.label} imported" + } importViewModel.dismiss() } + is ImportViewModel.State.Error -> { importMessage = context.getString(R.string.onboarding_import_failed_template, s.message) importViewModel.dismiss() } + else -> {} } } @@ -89,120 +92,150 @@ fun OnboardingScreen(onComplete: () -> Unit) { } } - val flowImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> - uri?.let { - scope.launch { - val result = backupRepo.importData(it) - importMessage = if (result.isSuccess) { - context.getString(R.string.import_flow_backup_success) - } else { - context.getString( - R.string.import_flow_backup_failed_template, - result.exceptionOrNull()?.message ?: "unknown" - ) + val flowImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> + uri?.let { + scope.launch { + val result = backupRepo.importData(it) + importMessage = + if (result.isSuccess) { + context.getString(R.string.import_flow_backup_success) + } else { + context.getString( + R.string.import_flow_backup_failed_template, + result.exceptionOrNull()?.message ?: "unknown", + ) + } } } } - } - val newPipeImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importNewPipe(it) } } + val newPipeImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importNewPipe(it) } } - val youtubeImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importYouTube(it) } } + val youtubeImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importYouTube(it) } } - val youtubeHistoryLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importYouTubeWatchHistory(it) } } + val youtubeHistoryLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importYouTubeWatchHistory(it) } } - val freeTubeHistoryLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importFreeTubeWatchHistory(it) } } + val freeTubeHistoryLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importFreeTubeWatchHistory(it) } } - val newPipeHistoryLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importNewPipeWatchHistory(it) } } + val newPipeHistoryLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importNewPipeWatchHistory(it) } } - val libreTubeImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importLibreTube(it) } } + val libreTubeImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importLibreTube(it) } } - val masterBackupImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importMasterBackup(it) } } + val masterBackupImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importMasterBackup(it) } } - val metrolistImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importMetrolist(it) } } + val metrolistImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importMetrolist(it) } } - val newPipePlaylistImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importNewPipePlaylists(it) } } + val newPipePlaylistImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importNewPipePlaylists(it) } } - val libreTubePlaylistImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importLibreTubePlaylists(it) } } + val libreTubePlaylistImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importLibreTubePlaylists(it) } } - val youtubeTakeoutImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> uri?.let { importViewModel.importYouTubeTakeout(it) } } + val youtubeTakeoutImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> uri?.let { importViewModel.importYouTubeTakeout(it) } } - val youtubePlaylistImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> - uri?.let { - scope.launch { - val result = backupRepo.importYouTubePlaylist(it) - importMessage = if (result.isSuccess) { - val (name, count) = result.getOrNull()!! - context.getString(R.string.import_yt_playlist_success_template, name, count) - } else { - context.getString( - R.string.import_yt_playlist_failed_template, - result.exceptionOrNull()?.message ?: "unknown" - ) + val youtubePlaylistImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> + uri?.let { + scope.launch { + val result = backupRepo.importYouTubePlaylist(it) + importMessage = + if (result.isSuccess) { + val (name, count) = result.getOrNull()!! + context.resources.getQuantityString( + R.plurals.import_yt_playlist_success_template, + count, + name, + count, + ) + } else { + context.getString( + R.string.import_yt_playlist_failed_template, + result.exceptionOrNull()?.message ?: "unknown", + ) + } } } } - } - val youtubeMusicPlaylistImportLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> - uri?.let { - scope.launch { - val result = backupRepo.importYouTubePlaylist(it, isMusic = true) - importMessage = if (result.isSuccess) { - val (name, count) = result.getOrNull()!! - context.getString(R.string.import_yt_playlist_success_template, name, count) - } else { - context.getString( - R.string.import_yt_playlist_failed_template, - result.exceptionOrNull()?.message ?: "unknown" - ) + val youtubeMusicPlaylistImportLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> + uri?.let { + scope.launch { + val result = backupRepo.importYouTubePlaylist(it, isMusic = true) + importMessage = + if (result.isSuccess) { + val (name, count) = result.getOrNull()!! + context.resources.getQuantityString( + R.plurals.import_yt_playlist_success_template, + count, + name, + count, + ) + } else { + context.getString( + R.string.import_yt_playlist_failed_template, + result.exceptionOrNull()?.message ?: "unknown", + ) + } } } } - } - val importEngineLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.OpenDocument() - ) { uri -> - uri?.let { - scope.launch { - val success = context.contentResolver.openInputStream(it)?.use { input -> - FlowNeuroEngine.importBrainFromStream(context, input) - } ?: false - importMessage = context.getString( - if (success) R.string.import_engine_success else R.string.import_engine_failed - ) + val importEngineLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.OpenDocument(), + ) { uri -> + uri?.let { + scope.launch { + val success = + context.contentResolver.openInputStream(it)?.use { input -> + FlowNeuroEngine.importBrainFromStream(context, input) + } ?: false + importMessage = + context.getString( + if (success) R.string.import_engine_success else R.string.import_engine_failed, + ) + } } } - } fun finish() { scope.launch { @@ -224,10 +257,11 @@ fun OnboardingScreen(onComplete: () -> Unit) { OnboardingBottomBar( isFirstStep = currentStep == OnboardingStep.INTERESTS, isLastStep = currentStep == OnboardingStep.IMPORT, - canAdvance = when (currentStep) { - OnboardingStep.INTERESTS -> selectedTopics.size >= MIN_TOPICS - else -> true - }, + canAdvance = + when (currentStep) { + OnboardingStep.INTERESTS -> selectedTopics.size >= MIN_TOPICS + else -> true + }, onBack = { OnboardingStep.entries.getOrNull(currentStep.index - 1)?.let { currentStep = it } }, @@ -235,122 +269,138 @@ fun OnboardingScreen(onComplete: () -> Unit) { haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) advance() }, - onSkip = { advance() } + onSkip = { advance() }, ) - } + }, ) { innerPadding -> AnimatedContent( targetState = currentStep, transitionSpec = { val forward = targetState.index > initialState.index - val enter = if (forward) - slideInHorizontally(tween(300)) { it / 4 } + fadeIn(tween(250)) - else - slideInHorizontally(tween(300)) { -it / 4 } + fadeIn(tween(250)) - val exit = if (forward) - slideOutHorizontally(tween(250)) { -it / 4 } + fadeOut(tween(200)) - else - slideOutHorizontally(tween(250)) { it / 4 } + fadeOut(tween(200)) + val enter = + if (forward) { + slideInHorizontally(tween(300)) { it / 4 } + fadeIn(tween(250)) + } else { + slideInHorizontally(tween(300)) { -it / 4 } + fadeIn(tween(250)) + } + val exit = + if (forward) { + slideOutHorizontally(tween(250)) { -it / 4 } + fadeOut(tween(200)) + } else { + slideOutHorizontally(tween(250)) { it / 4 } + fadeOut(tween(200)) + } enter togetherWith exit }, - modifier = Modifier - .fillMaxSize() - .padding(innerPadding), - label = "step_content" + modifier = + Modifier + .fillMaxSize() + .padding(innerPadding), + label = "step_content", ) { step -> when (step) { - OnboardingStep.INTERESTS -> InterestsStep( - selectedTopics = selectedTopics, - onTopicToggle = { topic -> - haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) - selectedTopics = if (selectedTopics.contains(topic)) - selectedTopics - topic - else - selectedTopics + topic - } - ) - OnboardingStep.CHANNELS -> ChannelsStep( - searchQuery = searchQuery, - searchResults = searchResults, - isSearching = isSearching, - subscribedInSession = subscribedInSession, - onQueryChange = { q -> - searchQuery = q - searchJob?.cancel() - if (q.isBlank()) { - searchResults = emptyList() - isSearching = false - return@ChannelsStep - } - searchJob = scope.launch { - delay(400) - isSearching = true - searchResults = searchChannels(q) - isSearching = false - } - }, - onSubscribeToggle = { result -> - haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) - scope.launch { - if (subscribedInSession.contains(result.channelId)) { - subscriptionRepo.unsubscribe(result.channelId) - subscribedInSession = subscribedInSession - result.channelId - } else { - subscriptionRepo.subscribe( - ChannelSubscription( - channelId = result.channelId, - channelName = result.name, - channelThumbnail = result.thumbnailUrl, - subscribedAt = System.currentTimeMillis() + OnboardingStep.INTERESTS -> { + InterestsStep( + selectedTopics = selectedTopics, + onTopicToggle = { topic -> + haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) + selectedTopics = + if (selectedTopics.contains(topic)) { + selectedTopics - topic + } else { + selectedTopics + topic + } + }, + ) + } + + OnboardingStep.CHANNELS -> { + ChannelsStep( + searchQuery = searchQuery, + searchResults = searchResults, + isSearching = isSearching, + subscribedInSession = subscribedInSession, + onQueryChange = { q -> + searchQuery = q + searchJob?.cancel() + if (q.isBlank()) { + searchResults = emptyList() + isSearching = false + return@ChannelsStep + } + searchJob = + scope.launch { + delay(400) + isSearching = true + searchResults = searchChannels(q) + isSearching = false + } + }, + onSubscribeToggle = { result -> + haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) + scope.launch { + if (subscribedInSession.contains(result.channelId)) { + subscriptionRepo.unsubscribe(result.channelId) + subscribedInSession = subscribedInSession - result.channelId + } else { + subscriptionRepo.subscribe( + ChannelSubscription( + channelId = result.channelId, + channelName = result.name, + channelThumbnail = result.thumbnailUrl, + subscribedAt = System.currentTimeMillis(), + ), ) - ) - subscribedInSession = subscribedInSession + result.channelId + subscribedInSession = subscribedInSession + result.channelId + } } - } - } - ) - OnboardingStep.IMPORT -> ImportStep( - importState = importState, - onImportFlowBackup = { flowImportLauncher.launch(arrayOf("application/json")) }, - onImportMasterBackup = { - masterBackupImportLauncher.launch(arrayOf("application/zip", "application/octet-stream")) - }, - onImportEngineData = { importEngineLauncher.launch(arrayOf("application/json")) }, - onImportNewPipe = { newPipeImportLauncher.launch(arrayOf("application/json")) }, - onImportYouTube = { - youtubeImportLauncher.launch(arrayOf("text/comma-separated-values", "text/csv", "text/plain")) - }, - onImportYouTubeHistory = { - youtubeHistoryLauncher.launch(arrayOf("text/html", "application/octet-stream", "*/*")) - }, - onImportFreeTubeHistory = { - freeTubeHistoryLauncher.launch( - arrayOf("application/json", "text/plain", "application/octet-stream", "*/*") - ) - }, - onImportNewPipeHistory = { - newPipeHistoryLauncher.launch( - arrayOf("application/zip", "application/octet-stream", "application/x-sqlite3", "*/*") - ) - }, - onImportLibreTube = { libreTubeImportLauncher.launch(arrayOf("application/json")) }, - onImportMetrolist = { - metrolistImportLauncher.launch(arrayOf("application/zip", "application/octet-stream", "*/*")) - }, - onImportNewPipePlaylists = { - newPipePlaylistImportLauncher.launch(arrayOf("application/zip", "application/octet-stream", "*/*")) - }, - onImportLibreTubePlaylists = { libreTubePlaylistImportLauncher.launch(arrayOf("application/json")) }, - onImportYouTubeTakeout = { - youtubeTakeoutImportLauncher.launch(arrayOf("application/zip", "application/octet-stream", "*/*")) - }, - onImportYouTubePlaylist = { - youtubePlaylistImportLauncher.launch(arrayOf("text/comma-separated-values", "text/csv", "text/plain")) - }, - onImportYouTubeMusicPlaylist = { - youtubeMusicPlaylistImportLauncher.launch(arrayOf("text/comma-separated-values", "text/csv", "text/plain")) - } - ) + }, + ) + } + + OnboardingStep.IMPORT -> { + ImportStep( + importState = importState, + onImportFlowBackup = { flowImportLauncher.launch(arrayOf("application/json")) }, + onImportMasterBackup = { + masterBackupImportLauncher.launch(arrayOf("application/zip", "application/octet-stream")) + }, + onImportEngineData = { importEngineLauncher.launch(arrayOf("application/json")) }, + onImportNewPipe = { newPipeImportLauncher.launch(arrayOf("application/json")) }, + onImportYouTube = { + youtubeImportLauncher.launch(arrayOf("text/comma-separated-values", "text/csv", "text/plain")) + }, + onImportYouTubeHistory = { + youtubeHistoryLauncher.launch(arrayOf("text/html", "application/octet-stream", "*/*")) + }, + onImportFreeTubeHistory = { + freeTubeHistoryLauncher.launch( + arrayOf("application/json", "text/plain", "application/octet-stream", "*/*"), + ) + }, + onImportNewPipeHistory = { + newPipeHistoryLauncher.launch( + arrayOf("application/zip", "application/octet-stream", "application/x-sqlite3", "*/*"), + ) + }, + onImportLibreTube = { libreTubeImportLauncher.launch(arrayOf("application/json")) }, + onImportMetrolist = { + metrolistImportLauncher.launch(arrayOf("application/zip", "application/octet-stream", "*/*")) + }, + onImportNewPipePlaylists = { + newPipePlaylistImportLauncher.launch(arrayOf("application/zip", "application/octet-stream", "*/*")) + }, + onImportLibreTubePlaylists = { libreTubePlaylistImportLauncher.launch(arrayOf("application/json")) }, + onImportYouTubeTakeout = { + youtubeTakeoutImportLauncher.launch(arrayOf("application/zip", "application/octet-stream", "*/*")) + }, + onImportYouTubePlaylist = { + youtubePlaylistImportLauncher.launch(arrayOf("text/comma-separated-values", "text/csv", "text/plain")) + }, + onImportYouTubeMusicPlaylist = { + youtubeMusicPlaylistImportLauncher.launch(arrayOf("text/comma-separated-values", "text/csv", "text/plain")) + }, + ) + } } } } diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/personality/PersonalityDashboardSections.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/personality/PersonalityDashboardSections.kt index ade42155a..8810ced14 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/personality/PersonalityDashboardSections.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/personality/PersonalityDashboardSections.kt @@ -54,11 +54,12 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -72,7 +73,7 @@ import io.github.aedev.flow.data.recommendation.UserBrain @Composable internal fun PersonalityOverviewSection( brain: UserBrain, - persona: FlowPersona? + persona: FlowPersona?, ) { val displayPersona = persona ?: FlowPersona.INITIATE @@ -80,38 +81,40 @@ internal fun PersonalityOverviewSection( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(18.dp), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface), - elevation = CardDefaults.cardElevation(defaultElevation = 0.dp) + elevation = CardDefaults.cardElevation(defaultElevation = 0.dp), ) { Box( - modifier = Modifier - .fillMaxWidth() - .background( - Brush.linearGradient( - colors = listOf( - MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.46f), - MaterialTheme.colorScheme.surface - ) - ) - ) - .padding(20.dp) + modifier = + Modifier + .fillMaxWidth() + .background( + Brush.linearGradient( + colors = + listOf( + MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.46f), + MaterialTheme.colorScheme.surface, + ), + ), + ).padding(20.dp), ) { Text( text = displayPersona.icon, fontSize = 100.sp, textAlign = TextAlign.Center, - modifier = Modifier - .align(Alignment.TopEnd) - .alpha(0.18f) + modifier = + Modifier + .align(Alignment.TopEnd) + .alpha(0.18f), ) Column( modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(18.dp) + verticalArrangement = Arrangement.spacedBy(18.dp), ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(14.dp), - verticalAlignment = Alignment.Top + verticalAlignment = Alignment.Top, ) { Column(modifier = Modifier.weight(1f)) { Text( @@ -119,14 +122,14 @@ internal fun PersonalityOverviewSection( style = MaterialTheme.typography.headlineSmall, fontWeight = FontWeight.Bold, maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, ) Text( text = stringResource(displayPersona.descriptionRes), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, maxLines = 2, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, ) } } @@ -134,7 +137,7 @@ internal fun PersonalityOverviewSection( MetricBar( label = stringResource(R.string.profile_maturity_label), value = brain.profileMaturity(), - detail = stringResource(R.string.profile_maturity_detail) + detail = stringResource(R.string.profile_maturity_detail), ) } } @@ -146,59 +149,60 @@ internal fun LearningStatsSection(brain: UserBrain) { DashboardSection( title = stringResource(R.string.learning_stats_title), subtitle = stringResource(R.string.learning_stats_subtitle), - icon = Icons.Outlined.TrackChanges + icon = Icons.Outlined.TrackChanges, ) { MetricGrid( - metrics = listOf( - DashboardMetric( - label = stringResource(R.string.metric_interactions), - value = compactCount(brain.totalInteractions), - detail = stringResource(R.string.metric_interactions_detail), - icon = Icons.Outlined.TouchApp - ), - DashboardMetric( - label = stringResource(R.string.metric_topics), - value = compactCount(brain.globalVector.topics.size), - detail = stringResource(R.string.metric_topics_detail), - icon = Icons.Outlined.Category - ), - DashboardMetric( - label = stringResource(R.string.metric_evidence), - value = compactCount(brain.topicEvidence.size), - detail = stringResource(R.string.metric_evidence_detail), - icon = Icons.Outlined.TrackChanges - ), - DashboardMetric( - label = stringResource(R.string.metric_channels), - value = compactCount(brain.channelScores.size), - detail = stringResource(R.string.metric_channels_detail), - icon = Icons.Outlined.Subscriptions - ), - DashboardMetric( - label = stringResource(R.string.metric_history), - value = compactCount(brain.watchHistoryMap.size), - detail = stringResource(R.string.metric_history_detail), - icon = Icons.Outlined.VideoLibrary - ), - DashboardMetric( - label = stringResource(R.string.metric_feed_memory), - value = compactCount(brain.feedHistory.size), - detail = stringResource(R.string.metric_feed_memory_detail), - icon = Icons.Outlined.Equalizer - ), - DashboardMetric( - label = stringResource(R.string.metric_filters), - value = compactCount(brain.blockedFilterCount()), - detail = stringResource(R.string.metric_filters_detail), - icon = Icons.Outlined.Block + metrics = + listOf( + DashboardMetric( + label = stringResource(R.string.metric_interactions), + value = compactCount(brain.totalInteractions), + detail = stringResource(R.string.metric_interactions_detail), + icon = Icons.Outlined.TouchApp, + ), + DashboardMetric( + label = stringResource(R.string.metric_topics), + value = compactCount(brain.globalVector.topics.size), + detail = stringResource(R.string.metric_topics_detail), + icon = Icons.Outlined.Category, + ), + DashboardMetric( + label = stringResource(R.string.metric_evidence), + value = compactCount(brain.topicEvidence.size), + detail = stringResource(R.string.metric_evidence_detail), + icon = Icons.Outlined.TrackChanges, + ), + DashboardMetric( + label = stringResource(R.string.metric_channels), + value = compactCount(brain.channelScores.size), + detail = stringResource(R.string.metric_channels_detail), + icon = Icons.Outlined.Subscriptions, + ), + DashboardMetric( + label = stringResource(R.string.metric_history), + value = compactCount(brain.watchHistoryMap.size), + detail = stringResource(R.string.metric_history_detail), + icon = Icons.Outlined.VideoLibrary, + ), + DashboardMetric( + label = stringResource(R.string.metric_feed_memory), + value = compactCount(brain.feedHistory.size), + detail = stringResource(R.string.metric_feed_memory_detail), + icon = Icons.Outlined.Equalizer, + ), + DashboardMetric( + label = stringResource(R.string.metric_filters), + value = compactCount(brain.blockedFilterCount()), + detail = stringResource(R.string.metric_filters_detail), + icon = Icons.Outlined.Block, + ), + DashboardMetric( + label = stringResource(R.string.metric_suppressed), + value = compactCount(brain.suppressedItemCount()), + detail = stringResource(R.string.metric_suppressed_detail), + icon = Icons.Outlined.Explore, + ), ), - DashboardMetric( - label = stringResource(R.string.metric_suppressed), - value = compactCount(brain.suppressedItemCount()), - detail = stringResource(R.string.metric_suppressed_detail), - icon = Icons.Outlined.Explore - ) - ) ) } } @@ -210,55 +214,61 @@ internal fun TasteShapeSection(brain: UserBrain) { DashboardSection( title = stringResource(R.string.taste_shape_title), subtitle = stringResource(R.string.taste_shape_subtitle), - icon = Icons.Outlined.Equalizer + icon = Icons.Outlined.Equalizer, ) { TasteRadarChart( globalVector = brain.globalVector, currentVector = currentVector, - breadth = brain.breadthScore() + breadth = brain.breadthScore(), ) MetricBar( label = stringResource(R.string.taste_pacing), value = brain.globalVector.pacing, - detail = stringResource(R.string.taste_pacing_context, currentVector.pacing.percentLabel()) + detail = stringResource(R.string.taste_pacing_context, currentVector.pacing.percentLabel()), ) MetricBar( label = stringResource(R.string.taste_complexity), value = brain.globalVector.complexity, detail = stringResource(R.string.taste_pacing_context, currentVector.complexity.percentLabel()), - color = MaterialTheme.colorScheme.secondary + color = MaterialTheme.colorScheme.secondary, ) MetricBar( label = stringResource(R.string.taste_duration), value = brain.globalVector.duration, detail = stringResource(R.string.taste_duration_detail), - color = MaterialTheme.colorScheme.tertiary + color = MaterialTheme.colorScheme.tertiary, ) MetricBar( label = stringResource(R.string.taste_live_affinity), value = brain.globalVector.isLive, - detail = stringResource(R.string.taste_live_affinity_detail) + detail = stringResource(R.string.taste_live_affinity_detail), ) MetricBar( label = stringResource(R.string.taste_topic_breadth), value = brain.breadthScore(), - detail = stringResource(R.string.taste_topic_breadth_detail, brain.globalVector.topics.size), - color = MaterialTheme.colorScheme.secondary + detail = + pluralStringResource( + R.plurals.taste_topic_breadth_detail, + brain.globalVector.topics.size, + brain.globalVector.topics.size, + ), + color = MaterialTheme.colorScheme.secondary, ) } } @Composable internal fun InterestWeightsSection(brain: UserBrain) { - val topics = remember(brain.globalVector.topics, brain.topicEvidence) { - brain.topTopicInsights(limit = 12) - } + val topics = + remember(brain.globalVector.topics, brain.topicEvidence) { + brain.topTopicInsights(limit = 12) + } val maxScore = topics.maxOfOrNull { it.score }?.takeIf { it > 0.0 } ?: 1.0 DashboardSection( title = stringResource(R.string.interest_weights_title), subtitle = stringResource(R.string.interest_weights_subtitle), - icon = Icons.Outlined.Category + icon = Icons.Outlined.Category, ) { if (topics.isEmpty()) { EmptyPanelMessage(stringResource(R.string.interest_weights_empty)) @@ -270,11 +280,12 @@ internal fun InterestWeightsSection(brain: UserBrain) { title = topic.name.readableTopic(), subtitle = topic.evidenceLabel(scoreLabel = stringResource(R.string.topic_score_prefix)), value = topic.score / maxScore, - color = when { - index < 3 -> MaterialTheme.colorScheme.primary - index < 7 -> MaterialTheme.colorScheme.secondary - else -> MaterialTheme.colorScheme.tertiary - } + color = + when { + index < 3 -> MaterialTheme.colorScheme.primary + index < 7 -> MaterialTheme.colorScheme.secondary + else -> MaterialTheme.colorScheme.tertiary + }, ) } } @@ -288,12 +299,12 @@ internal fun TimePatternsSection(brain: UserBrain) { DashboardSection( title = stringResource(R.string.time_patterns_title), subtitle = stringResource(R.string.time_patterns_subtitle), - icon = Icons.Outlined.Schedule + icon = Icons.Outlined.Schedule, ) { LazyRow(horizontalArrangement = Arrangement.spacedBy(10.dp)) { items( items = buckets, - key = { it.bucket.name } + key = { it.bucket.name }, ) { bucket -> TimeBucketCard(bucket = bucket) } @@ -306,24 +317,26 @@ private fun TimeBucketCard(bucket: TimeBucketInsight) { val topics = bucket.vector.topTopicLabels(limit = 4) Surface( - modifier = Modifier - .width(252.dp) - .height(282.dp), + modifier = + Modifier + .width(252.dp) + .height(282.dp), shape = RoundedCornerShape(10.dp), - color = if (bucket.isCurrent) { - MaterialTheme.colorScheme.primary.copy(alpha = 0.12f) - } else { - MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.34f) - } + color = + if (bucket.isCurrent) { + MaterialTheme.colorScheme.primary.copy(alpha = 0.12f) + } else { + MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.34f) + }, ) { Column( modifier = Modifier.padding(14.dp), - verticalArrangement = Arrangement.spacedBy(9.dp) + verticalArrangement = Arrangement.spacedBy(9.dp), ) { Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween + horizontalArrangement = Arrangement.SpaceBetween, ) { Text( text = bucket.title, @@ -331,7 +344,7 @@ private fun TimeBucketCard(bucket: TimeBucketInsight) { fontWeight = FontWeight.Medium, maxLines = 1, overflow = TextOverflow.Ellipsis, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) if (bucket.isCurrent) { StatusChip(label = stringResource(R.string.time_bucket_label_now), color = MaterialTheme.colorScheme.primary) @@ -340,19 +353,19 @@ private fun TimeBucketCard(bucket: TimeBucketInsight) { Text( text = bucket.window, style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { TimeBucketStat( label = stringResource(R.string.time_bucket_topics_count), value = compactCount(bucket.vector.topics.size), - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) TimeBucketStat( label = stringResource(R.string.time_bucket_pace), value = bucket.vector.pacing.percentLabel(), - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) } @@ -363,13 +376,13 @@ private fun TimeBucketCard(bucket: TimeBucketInsight) { Text( text = stringResource(R.string.time_bucket_top_topics), style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) if (topics.isEmpty()) { Text( text = stringResource(R.string.time_bucket_no_topics), style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) } else { topics.forEach { topic -> @@ -377,7 +390,7 @@ private fun TimeBucketCard(bucket: TimeBucketInsight) { text = topic, style = MaterialTheme.typography.bodySmall, maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, ) } } @@ -390,28 +403,28 @@ private fun TimeBucketCard(bucket: TimeBucketInsight) { private fun TimeBucketStat( label: String, value: String, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Surface( modifier = modifier.height(50.dp), shape = RoundedCornerShape(8.dp), - color = MaterialTheme.colorScheme.surface.copy(alpha = 0.72f) + color = MaterialTheme.colorScheme.surface.copy(alpha = 0.72f), ) { Column( modifier = Modifier.padding(horizontal = 8.dp, vertical = 6.dp), - verticalArrangement = Arrangement.SpaceBetween + verticalArrangement = Arrangement.SpaceBetween, ) { Text( text = label, style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant, - maxLines = 1 + maxLines = 1, ) Text( text = value, style = MaterialTheme.typography.labelMedium, fontWeight = FontWeight.Bold, - maxLines = 1 + maxLines = 1, ) } } @@ -420,39 +433,41 @@ private fun TimeBucketStat( @Composable private fun SmallMetricLine( label: String, - value: Double + value: Double, ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Text( text = label, style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.width(68.dp), - maxLines = 1 + maxLines = 1, ) Box( - modifier = Modifier - .weight(1f) - .height(7.dp) - .clip(RoundedCornerShape(4.dp)) - .background(MaterialTheme.colorScheme.surface) + modifier = + Modifier + .weight(1f) + .height(7.dp) + .clip(RoundedCornerShape(4.dp)) + .background(MaterialTheme.colorScheme.surface), ) { Box( - modifier = Modifier - .fillMaxHeight() - .fillMaxWidth(value.coerceIn(0.0, 1.0).toFloat()) - .background(MaterialTheme.colorScheme.primary) + modifier = + Modifier + .fillMaxHeight() + .fillMaxWidth(value.coerceIn(0.0, 1.0).toFloat()) + .background(MaterialTheme.colorScheme.primary), ) } Text( text = value.percentLabel(), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.width(36.dp) + modifier = Modifier.width(36.dp), ) } } @@ -460,18 +475,19 @@ private fun SmallMetricLine( @Composable internal fun ChannelMemorySection( brain: UserBrain, - channelNames: Map + channelNames: Map, ) { - val channels = remember(brain.channelScores, channelNames) { - brain.channelScores.entries - .sortedByDescending { it.value } - .take(10) - } + val channels = + remember(brain.channelScores, channelNames) { + brain.channelScores.entries + .sortedByDescending { it.value } + .take(10) + } DashboardSection( title = stringResource(R.string.channel_memory), subtitle = stringResource(R.string.channel_memory_subtitle), - icon = Icons.Outlined.Subscriptions + icon = Icons.Outlined.Subscriptions, ) { if (channels.isEmpty()) { EmptyPanelMessage(stringResource(R.string.channel_memory_empty)) @@ -479,7 +495,7 @@ internal fun ChannelMemorySection( channels.forEachIndexed { index, (channelId, score) -> ChannelRow( name = channelNames[channelId] ?: shortChannelId(channelId), - score = score + score = score, ) if (index < channels.lastIndex) { HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)) @@ -492,18 +508,19 @@ internal fun ChannelMemorySection( @Composable private fun ChannelRow( name: String, - score: Double + score: Double, ) { - val (label, color) = when { - score >= 0.68 -> stringResource(R.string.channel_affinity_strong) to MaterialTheme.colorScheme.primary - score >= 0.48 -> stringResource(R.string.channel_affinity_balanced) to MaterialTheme.colorScheme.secondary - else -> stringResource(R.string.channel_affinity_cooling) to MaterialTheme.colorScheme.tertiary - } + val (label, color) = + when { + score >= 0.68 -> stringResource(R.string.channel_affinity_strong) to MaterialTheme.colorScheme.primary + score >= 0.48 -> stringResource(R.string.channel_affinity_balanced) to MaterialTheme.colorScheme.secondary + else -> stringResource(R.string.channel_affinity_cooling) to MaterialTheme.colorScheme.tertiary + } Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp) + horizontalArrangement = Arrangement.spacedBy(12.dp), ) { Column(modifier = Modifier.weight(1f)) { Text( @@ -511,14 +528,14 @@ private fun ChannelRow( style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Medium, maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, ) Spacer(Modifier.height(6.dp)) CompactProgressRow( title = score.percentLabel(), subtitle = stringResource(R.string.channel_affinity_score), value = score, - color = color + color = color, ) } StatusChip(label = label, color = color) @@ -529,46 +546,47 @@ private fun ChannelRow( @Composable internal fun DiscoveryStatusSection( brain: UserBrain, - queries: List + queries: List, ) { DashboardSection( title = stringResource(R.string.discovery_status_title), subtitle = stringResource(R.string.discovery_status_subtitle), - icon = Icons.Outlined.Code + icon = Icons.Outlined.Code, ) { MetricGrid( - metrics = listOf( - DashboardMetric( - label = stringResource(R.string.discovery_queries), - value = compactCount(queries.size), - detail = stringResource(R.string.discovery_queries_detail), - icon = Icons.Outlined.Code - ), - DashboardMetric( - label = stringResource(R.string.discovery_query_memory), - value = compactCount(brain.recentQueryTokens.size), - detail = stringResource(R.string.discovery_query_memory_detail), - icon = Icons.Outlined.TrackChanges - ), - DashboardMetric( - label = stringResource(R.string.discovery_rejections), - value = compactCount(brain.rejectionPatterns.size), - detail = stringResource(R.string.discovery_rejections_detail), - icon = Icons.Outlined.Block + metrics = + listOf( + DashboardMetric( + label = stringResource(R.string.discovery_queries), + value = compactCount(queries.size), + detail = stringResource(R.string.discovery_queries_detail), + icon = Icons.Outlined.Code, + ), + DashboardMetric( + label = stringResource(R.string.discovery_query_memory), + value = compactCount(brain.recentQueryTokens.size), + detail = stringResource(R.string.discovery_query_memory_detail), + icon = Icons.Outlined.TrackChanges, + ), + DashboardMetric( + label = stringResource(R.string.discovery_rejections), + value = compactCount(brain.rejectionPatterns.size), + detail = stringResource(R.string.discovery_rejections_detail), + icon = Icons.Outlined.Block, + ), + DashboardMetric( + label = stringResource(R.string.discovery_shorts_seen), + value = compactCount(brain.seenShortsHistory.size), + detail = stringResource(R.string.discovery_shorts_seen_detail), + icon = Icons.Outlined.VideoLibrary, + ), ), - DashboardMetric( - label = stringResource(R.string.discovery_shorts_seen), - value = compactCount(brain.seenShortsHistory.size), - detail = stringResource(R.string.discovery_shorts_seen_detail), - icon = Icons.Outlined.VideoLibrary - ) - ) ) if (queries.isNotEmpty()) { FlowRow( horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(8.dp), ) { queries.take(10).forEach { query -> AssistChip( @@ -577,9 +595,9 @@ internal fun DiscoveryStatusSection( Text( text = query, maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, ) - } + }, ) } } @@ -593,7 +611,7 @@ internal fun BlockedContentSection( brain: UserBrain, channelNames: Map, onUnblockTopic: (String) -> Unit, - onUnblockChannel: (String) -> Unit + onUnblockChannel: (String) -> Unit, ) { val visibleTopics = remember(brain.blockedTopics) { brain.blockedTopics.sorted() } val visibleChannels = remember(brain.blockedChannels) { brain.blockedChannels.sorted() } @@ -601,29 +619,30 @@ internal fun BlockedContentSection( DashboardSection( title = stringResource(R.string.blocked_content_title), subtitle = stringResource(R.string.blocked_content_subtitle), - icon = Icons.Outlined.Block + icon = Icons.Outlined.Block, ) { if (brain.blockedTopics.isNotEmpty()) { FilterHeader( title = stringResource(R.string.blocked_topics_header), visibleCount = visibleTopics.size, - totalCount = brain.blockedTopics.size + totalCount = brain.blockedTopics.size, ) LazyColumn( - modifier = Modifier - .fillMaxWidth() - .heightIn(max = 230.dp), - verticalArrangement = Arrangement.spacedBy(6.dp) + modifier = + Modifier + .fillMaxWidth() + .heightIn(max = 230.dp), + verticalArrangement = Arrangement.spacedBy(6.dp), ) { items( items = visibleTopics, - key = { it } + key = { it }, ) { topic -> FilterItemRow( title = topic.readableTopic(), icon = Icons.Outlined.Block, onRemove = { onUnblockTopic(topic) }, - removeDescription = stringResource(R.string.blocked_item_unblock_topic) + removeDescription = stringResource(R.string.blocked_item_unblock_topic), ) } } @@ -633,23 +652,24 @@ internal fun BlockedContentSection( FilterHeader( title = stringResource(R.string.blocked_channels_header), visibleCount = visibleChannels.size, - totalCount = brain.blockedChannels.size + totalCount = brain.blockedChannels.size, ) LazyColumn( - modifier = Modifier - .fillMaxWidth() - .heightIn(max = 230.dp), - verticalArrangement = Arrangement.spacedBy(6.dp) + modifier = + Modifier + .fillMaxWidth() + .heightIn(max = 230.dp), + verticalArrangement = Arrangement.spacedBy(6.dp), ) { items( items = visibleChannels, - key = { it } + key = { it }, ) { channelId -> FilterItemRow( title = channelNames[channelId] ?: shortChannelId(channelId), icon = Icons.Outlined.Subscriptions, onRemove = { onUnblockChannel(channelId) }, - removeDescription = stringResource(R.string.blocked_item_unblock_channel) + removeDescription = stringResource(R.string.blocked_item_unblock_channel), ) } } @@ -661,23 +681,23 @@ internal fun BlockedContentSection( private fun FilterHeader( title: String, visibleCount: Int, - totalCount: Int + totalCount: Int, ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Text( text = title, style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold + fontWeight = FontWeight.SemiBold, ) if (visibleCount < totalCount) { Text( text = stringResource(R.string.blocked_item_showing_count, visibleCount, totalCount), style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) } } @@ -688,39 +708,39 @@ private fun FilterItemRow( title: String, icon: ImageVector, onRemove: () -> Unit, - removeDescription: String + removeDescription: String, ) { Surface( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(8.dp), - color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.34f) + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.34f), ) { Row( modifier = Modifier.padding(start = 12.dp, top = 6.dp, end = 4.dp, bottom = 6.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { Icon( imageVector = icon, contentDescription = null, tint = MaterialTheme.colorScheme.error, - modifier = Modifier.size(18.dp) + modifier = Modifier.size(18.dp), ) Text( text = title, style = MaterialTheme.typography.bodyMedium, maxLines = 1, overflow = TextOverflow.Ellipsis, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) IconButton( onClick = onRemove, - modifier = Modifier.size(32.dp) + modifier = Modifier.size(32.dp), ) { Icon( imageVector = Icons.Default.Close, contentDescription = removeDescription, - modifier = Modifier.size(16.dp) + modifier = Modifier.size(16.dp), ) } } @@ -731,31 +751,31 @@ private fun FilterItemRow( internal fun ProfileDataSection( onExport: () -> Unit, onImport: () -> Unit, - onReset: () -> Unit + onReset: () -> Unit, ) { DashboardSection( title = stringResource(R.string.profile_data_title), subtitle = stringResource(R.string.profile_data_subtitle), - icon = Icons.Outlined.VideoLibrary + icon = Icons.Outlined.VideoLibrary, ) { ProfileActionRow( title = stringResource(R.string.profile_action_export), subtitle = stringResource(R.string.profile_action_export_detail), icon = Icons.Default.FileDownload, - onClick = onExport + onClick = onExport, ) ProfileActionRow( title = stringResource(R.string.profile_action_import), subtitle = stringResource(R.string.profile_action_import_detail), icon = Icons.Default.FileUpload, - onClick = onImport + onClick = onImport, ) ProfileActionRow( title = stringResource(R.string.profile_action_reset), subtitle = stringResource(R.string.profile_action_reset_detail), icon = Icons.Default.DeleteForever, isDestructive = true, - onClick = onReset + onClick = onReset, ) } } @@ -766,44 +786,46 @@ private fun ProfileActionRow( subtitle: String, icon: ImageVector, isDestructive: Boolean = false, - onClick: () -> Unit + onClick: () -> Unit, ) { - val tint = if (isDestructive) { - MaterialTheme.colorScheme.error - } else { - MaterialTheme.colorScheme.primary - } + val tint = + if (isDestructive) { + MaterialTheme.colorScheme.error + } else { + MaterialTheme.colorScheme.primary + } Row( - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onClick) - .padding(vertical = 4.dp), + modifier = + Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(vertical = 4.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp) + horizontalArrangement = Arrangement.spacedBy(12.dp), ) { Surface( modifier = Modifier.size(40.dp), shape = CircleShape, - color = tint.copy(alpha = 0.12f) + color = tint.copy(alpha = 0.12f), ) { Icon( imageVector = icon, contentDescription = null, tint = tint, - modifier = Modifier.padding(10.dp) + modifier = Modifier.padding(10.dp), ) } Column(modifier = Modifier.weight(1f)) { Text( text = title, style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.Medium + fontWeight = FontWeight.Medium, ) Text( text = subtitle, style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) } } @@ -812,7 +834,7 @@ private fun ProfileActionRow( @Composable internal fun ResetProfileDialog( onDismiss: () -> Unit, - onConfirm: () -> Unit + onConfirm: () -> Unit, ) { AlertDialog( onDismissRequest = onDismiss, @@ -820,7 +842,7 @@ internal fun ResetProfileDialog( Icon( imageVector = Icons.Default.DeleteForever, contentDescription = null, - tint = MaterialTheme.colorScheme.error + tint = MaterialTheme.colorScheme.error, ) }, title = { Text(stringResource(R.string.reset_profile_dialog_title)) }, @@ -836,7 +858,7 @@ internal fun ResetProfileDialog( TextButton(onClick = onDismiss) { Text(stringResource(R.string.cancel)) } - } + }, ) } diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/playlists/PlaylistDetailScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/playlists/PlaylistDetailScreen.kt index 02bfaff0d..254c5166f 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/playlists/PlaylistDetailScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/playlists/PlaylistDetailScreen.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.positionInRoot +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow @@ -375,7 +376,15 @@ fun PlaylistDetailScreen( onDismissRequest = { showDownloadAllDialog = false }, icon = { Icon(Icons.Default.Download, null) }, title = { Text(stringResource(R.string.download_all)) }, - text = { Text(stringResource(R.string.download_all_confirmation, uiState.videos.size)) }, + text = { + Text( + pluralStringResource( + R.plurals.download_all_confirmation, + uiState.videos.size, + uiState.videos.size, + ), + ) + }, confirmButton = { TextButton( onClick = { @@ -399,7 +408,13 @@ fun PlaylistDetailScreen( onDismissRequest = { showRemoveSelectedDialog = false }, icon = { Icon(Icons.Default.Delete, null, tint = MaterialTheme.colorScheme.error) }, title = { - Text(stringResource(R.string.remove_selected_videos_title, selectedIds.size)) + Text( + pluralStringResource( + R.plurals.remove_selected_videos_title, + selectedIds.size, + selectedIds.size, + ), + ) }, text = { Text( @@ -507,7 +522,12 @@ private fun PlaylistDetailTopBar( Box(modifier = Modifier.weight(1f)) { if (inSelectionMode || showTitle) { Text( - text = if (inSelectionMode) stringResource(R.string.selected_count_template, selectedCount) else title, + text = + if (inSelectionMode) { + pluralStringResource(R.plurals.selected_count_template, selectedCount, selectedCount) + } else { + title + }, style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.Bold), maxLines = 1, overflow = TextOverflow.Ellipsis, @@ -691,8 +711,13 @@ private fun PlaylistHeader( // Metadata Row Text( text = - stringResource( - if (isPrivate) R.string.playlist_metadata_private_template else R.string.playlist_metadata_public_template, + pluralStringResource( + if (isPrivate) { + R.plurals.playlist_metadata_private_template + } else { + R.plurals.playlist_metadata_public_template + }, + videoCount, videoCount, ), style = MaterialTheme.typography.bodySmall, @@ -1354,7 +1379,12 @@ private fun MergeIntoPlaylistDialog( overflow = TextOverflow.Ellipsis, ) Text( - text = stringResource(R.string.songs_count_template, playlist.videoCount), + text = + pluralStringResource( + R.plurals.songs_count_template, + playlist.videoCount, + playlist.videoCount, + ), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) @@ -1438,7 +1468,16 @@ class PlaylistDetailViewModel _isDownloadingPlaylist.value = true _playlistDownloadProgress.value = 0f - Toast.makeText(context, context.getString(R.string.ui_downloading_videos, videos.size), Toast.LENGTH_SHORT).show() + Toast + .makeText( + context, + context.resources.getQuantityString( + R.plurals.ui_downloading_videos, + videos.size, + videos.size, + ), + Toast.LENGTH_SHORT, + ).show() var successCount = 0 var processedCount = 0 @@ -1814,7 +1853,12 @@ class PlaylistDetailViewModel Toast .makeText( context, - context.getString(R.string.merge_playlist_success, videos.size, targetInfo?.name ?: ""), + context.resources.getQuantityString( + R.plurals.merge_playlist_success, + videos.size, + videos.size, + targetInfo?.name ?: "", + ), Toast.LENGTH_SHORT, ).show() } catch (e: Exception) { diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/AppearanceScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/AppearanceScreen.kt index c098bdf56..ab023a403 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/AppearanceScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/AppearanceScreen.kt @@ -421,7 +421,12 @@ fun AppearanceScreen( } item(span = { GridItemSpan(maxLineSpan) }) { - val countText = context.getString(R.string.appearance_themes_count_all, allThemes.size) + val countText = + context.resources.getQuantityString( + R.plurals.appearance_themes_count_all, + allThemes.size, + allThemes.size, + ) Text( text = countText, style = MaterialTheme.typography.labelLarge, diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/DownloadSettingsScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/DownloadSettingsScreen.kt index 9ce913f64..749addb1f 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/DownloadSettingsScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/DownloadSettingsScreen.kt @@ -40,6 +40,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow @@ -522,7 +523,12 @@ fun DownloadSettingsScreen(onNavigateBack: () -> Unit) { SettingsItem( icon = Icons.Outlined.Speed, title = stringResource(R.string.concurrent_threads_title), - subtitle = stringResource(R.string.threads_per_download_template, threadCount), + subtitle = + pluralStringResource( + R.plurals.threads_per_download_template, + threadCount, + threadCount, + ), onClick = { showThreadDialog = true }, ) } @@ -563,7 +569,7 @@ fun DownloadSettingsScreen(onNavigateBack: () -> Unit) { modifier = Modifier.fillMaxWidth(), ) Text( - text = stringResource(R.string.threads_count_label, threadCount), + text = pluralStringResource(R.plurals.threads_count_label, threadCount, threadCount), style = MaterialTheme.typography.titleLarge, modifier = Modifier.align(Alignment.CenterHorizontally), fontWeight = FontWeight.Bold, diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/ImportDataScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/ImportDataScreen.kt index a9a83da4e..e31ef4f7c 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/ImportDataScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/ImportDataScreen.kt @@ -483,7 +483,12 @@ private fun rememberTakeoutCsvImportLauncher( val message = result.fold( onSuccess = { (name, count) -> - context.getString(R.string.import_yt_playlist_success_template, name, count) + context.resources.getQuantityString( + R.plurals.import_yt_playlist_success_template, + count, + name, + count, + ) }, onFailure = { error -> when (error.message) { diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/PlayerSettingsScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/PlayerSettingsScreen.kt index 8ed6a1623..0b299e062 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/PlayerSettingsScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/PlayerSettingsScreen.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType @@ -376,8 +377,9 @@ fun PlayerSettingsScreen(onNavigateBack: () -> Unit) { } "auto_interval" -> { - stringResource( - R.string.player_settings_shorts_playback_mode_auto_interval_summary, + pluralStringResource( + R.plurals.player_settings_shorts_playback_mode_auto_interval_summary, + shortsAutoScrollSeconds, shortsAutoScrollSeconds, ) } @@ -430,8 +432,9 @@ fun PlayerSettingsScreen(onNavigateBack: () -> Unit) { if (autoplayCountdownSeconds <= 0) { stringResource(R.string.player_settings_autoplay_countdown_none) } else { - stringResource( - R.string.player_settings_autoplay_countdown_seconds_template, + pluralStringResource( + R.plurals.player_settings_autoplay_countdown_seconds_template, + autoplayCountdownSeconds, autoplayCountdownSeconds, ) }, @@ -957,8 +960,9 @@ fun PlayerSettingsScreen(onNavigateBack: () -> Unit) { ) { Text( text = - stringResource( - R.string.player_settings_shorts_auto_scroll_seconds_template, + pluralStringResource( + R.plurals.player_settings_shorts_auto_scroll_seconds_template, + shortsAutoScrollSeconds, shortsAutoScrollSeconds, ), style = MaterialTheme.typography.labelLarge, @@ -1028,8 +1032,9 @@ fun PlayerSettingsScreen(onNavigateBack: () -> Unit) { if (seconds == 0) { stringResource(R.string.player_settings_autoplay_countdown_none) } else { - stringResource( - R.string.player_settings_autoplay_countdown_seconds_template, + pluralStringResource( + R.plurals.player_settings_autoplay_countdown_seconds_template, + seconds, seconds, ) }, diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/SearchHistorySettingsScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/SearchHistorySettingsScreen.kt index 3baca079c..4fc2e5d32 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/SearchHistorySettingsScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/SearchHistorySettingsScreen.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp @@ -82,7 +83,12 @@ fun SearchHistorySettingsScreen(onNavigateBack: () -> Unit) { SettingsItem( icon = Icons.Outlined.Storage, title = stringResource(R.string.max_history_size_title), - subtitle = stringResource(R.string.currently_searches_template, maxHistorySize), + subtitle = + pluralStringResource( + R.plurals.currently_searches_template, + maxHistorySize, + maxHistorySize, + ), onClick = { showHistorySizeDialog = true }, ) HorizontalDivider(Modifier.padding(start = 56.dp), color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)) @@ -91,8 +97,9 @@ fun SearchHistorySettingsScreen(onNavigateBack: () -> Unit) { title = stringResource(R.string.auto_delete_history_title), subtitle = if (autoDeleteHistory) { - stringResource( - R.string.delete_after_days_template, + pluralStringResource( + R.plurals.delete_after_days_template, + historyRetentionDays, historyRetentionDays, ) } else { @@ -110,7 +117,12 @@ fun SearchHistorySettingsScreen(onNavigateBack: () -> Unit) { SettingsItem( icon = Icons.Outlined.Schedule, title = stringResource(R.string.retention_period_title), - subtitle = stringResource(R.string.delete_older_than_template, historyRetentionDays), + subtitle = + pluralStringResource( + R.plurals.delete_older_than_template, + historyRetentionDays, + historyRetentionDays, + ), onClick = { showRetentionDaysDialog = true }, ) } @@ -165,7 +177,7 @@ fun SearchHistorySettingsScreen(onNavigateBack: () -> Unit) { ) { RadioButton(selected = selectedSize == size, onClick = { selectedSize = size }) Spacer(Modifier.width(8.dp)) - Text(stringResource(R.string.searches_count_template, size)) + Text(pluralStringResource(R.plurals.searches_count_template, size, size)) } } } @@ -212,7 +224,7 @@ fun SearchHistorySettingsScreen(onNavigateBack: () -> Unit) { 90 -> stringResource(R.string.period_three_months) 180 -> stringResource(R.string.period_six_months) 365 -> stringResource(R.string.period_one_year) - else -> stringResource(R.string.days_count_template, days) + else -> pluralStringResource(R.plurals.days_count_template, days, days) }, ) } diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/SettingsScreen.kt index ae4a15d63..dc0442013 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/SettingsScreen.kt @@ -847,15 +847,45 @@ fun SettingsScreen( R.string.deep_flow_expire_duration_subtitle, deepFlowExpireHours.let { hours -> when (hours) { - DEEP_FLOW_NEVER_EXPIRES_HOURS -> context.getString(R.string.deep_flow_duration_never) - 1 -> context.getString(R.string.deep_flow_duration_1h) - 2 -> context.getString(R.string.deep_flow_duration_2h) - 4 -> context.getString(R.string.deep_flow_duration_4h) - 6 -> context.getString(R.string.deep_flow_duration_6h) - 8 -> context.getString(R.string.deep_flow_duration_8h) - 12 -> context.getString(R.string.deep_flow_duration_12h) - 24 -> context.getString(R.string.deep_flow_duration_24h) - else -> context.getString(R.string.deep_flow_duration_hours, hours) + DEEP_FLOW_NEVER_EXPIRES_HOURS -> { + context.getString(R.string.deep_flow_duration_never) + } + + 1 -> { + context.getString(R.string.deep_flow_duration_1h) + } + + 2 -> { + context.getString(R.string.deep_flow_duration_2h) + } + + 4 -> { + context.getString(R.string.deep_flow_duration_4h) + } + + 6 -> { + context.getString(R.string.deep_flow_duration_6h) + } + + 8 -> { + context.getString(R.string.deep_flow_duration_8h) + } + + 12 -> { + context.getString(R.string.deep_flow_duration_12h) + } + + 24 -> { + context.getString(R.string.deep_flow_duration_24h) + } + + else -> { + context.resources.getQuantityString( + R.plurals.deep_flow_duration_hours, + hours, + hours, + ) + } } }, ), diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/TimeManagementScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/TimeManagementScreen.kt index 5650ed896..c8bfdb5c4 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/TimeManagementScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/TimeManagementScreen.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathEffect import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -918,7 +919,7 @@ private fun FrequencySelector( verticalAlignment = Alignment.CenterVertically, ) { Text( - stringResource(R.string.every_min_template, currentMinutes), + pluralStringResource(R.plurals.every_min_template, currentMinutes, currentMinutes), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.primary, fontWeight = FontWeight.Bold, @@ -1032,7 +1033,7 @@ private fun FrequencyPickerDialog( Spacer(Modifier.width(12.dp)) Column { Text( - stringResource(R.string.every_minutes_template, minutes), + pluralStringResource(R.plurals.every_minutes_template, minutes, minutes), fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal, ) if (minutes >= 60) { diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/TimeManagementViewModel.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/TimeManagementViewModel.kt index 6a9f09d86..352b1efbf 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/TimeManagementViewModel.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/TimeManagementViewModel.kt @@ -28,7 +28,12 @@ class TimeManagementViewModel private val localDataManager: LocalDataManager, @ApplicationContext private val applicationContext: Context, ) : ViewModel() { - private val initialDuration = applicationContext.getString(R.string.duration_minutes, 0) + private val initialDuration = + applicationContext.resources.getQuantityString( + R.plurals.duration_minutes, + 0, + 0, + ) private val _uiState = MutableStateFlow( TimeManagementState( @@ -146,7 +151,11 @@ class TimeManagementViewModel return if (hours > 0) { applicationContext.getString(R.string.duration_hours_minutes, hours, minutes) } else { - applicationContext.getString(R.string.duration_minutes, minutes) + applicationContext.resources.getQuantityString( + R.plurals.duration_minutes, + minutes.toInt(), + minutes, + ) } } diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/UserPreferencesScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/UserPreferencesScreen.kt index 70eac04d0..45a282a7b 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/settings/UserPreferencesScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/settings/UserPreferencesScreen.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction @@ -171,7 +172,12 @@ fun UserPreferencesScreen(onNavigateBack: () -> Unit) { item { PreferencesSectionHeader( title = stringResource(R.string.currently_following), - subtitle = stringResource(R.string.topics_count_template, preferredTopics.size), + subtitle = + pluralStringResource( + R.plurals.topics_count_template, + preferredTopics.size, + preferredTopics.size, + ), ) } @@ -446,10 +452,10 @@ fun UserPreferencesScreen(onNavigateBack: () -> Unit) { PreferencesSectionHeader( title = stringResource(R.string.currently_blocked), subtitle = - stringResource( - R.string.topics_blocked_count_plural, + pluralStringResource( + R.plurals.topics_blocked_count_plural, + blockedTopics.size, blockedTopics.size, - if (blockedTopics.size > 1) "s" else "", ), ) } @@ -648,9 +654,13 @@ private fun TopicCategoryExpandableCard( Text( text = if (selectedCount > 0) { - stringResource(R.string.selected_count_template, selectedCount) + pluralStringResource(R.plurals.selected_count_template, selectedCount, selectedCount) } else { - stringResource(R.string.topics_count_template, category.topics.size) + pluralStringResource( + R.plurals.topics_count_template, + category.topics.size, + category.topics.size, + ) }, style = MaterialTheme.typography.labelSmall, color = diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/subscriptions/SubscriptionsScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/subscriptions/SubscriptionsScreen.kt index 191666fcd..f2b0ee099 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/subscriptions/SubscriptionsScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/subscriptions/SubscriptionsScreen.kt @@ -578,8 +578,9 @@ fun SubscriptionsScreen( ) Text( text = - stringResource( - R.string.subscriptions_refresh_progress_template, + pluralStringResource( + R.plurals.subscriptions_refresh_progress_template, + uiState.refreshTotalChannels, uiState.refreshProcessedChannels, uiState.refreshTotalChannels, ), @@ -591,8 +592,9 @@ fun SubscriptionsScreen( Text( text = if (uiState.showLastRefreshVideoCount) { - stringResource( - R.string.subscriptions_last_refreshed_template, + pluralStringResource( + R.plurals.subscriptions_last_refreshed_template, + uiState.lastRefreshVideoCount, uiState.lastRefreshText!!, uiState.lastRefreshVideoCount, ) diff --git a/app/src/main/java/io/github/aedev/flow/ui/screens/sync/SyncSetupContent.kt b/app/src/main/java/io/github/aedev/flow/ui/screens/sync/SyncSetupContent.kt index f8cda2be5..acb2725e7 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/screens/sync/SyncSetupContent.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/screens/sync/SyncSetupContent.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp @@ -85,7 +86,13 @@ internal fun SyncSelectContent( verticalAlignment = Alignment.CenterVertically, ) { Text( - text = stringResource(R.string.sync_selected_count, selected.size, COLLECTION_KEYS.size), + text = + pluralStringResource( + R.plurals.sync_selected_count, + selected.size, + selected.size, + COLLECTION_KEYS.size, + ), style = MaterialTheme.typography.titleMedium, ) TextButton(onClick = { onSelectedChange(if (allSelected) emptySet() else COLLECTION_KEYS.toSet()) }) { diff --git a/app/src/main/java/io/github/aedev/flow/ui/tv/player/panels/TvPlayerPanelsHost.kt b/app/src/main/java/io/github/aedev/flow/ui/tv/player/panels/TvPlayerPanelsHost.kt index 57b6a941b..766f700fc 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/tv/player/panels/TvPlayerPanelsHost.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/tv/player/panels/TvPlayerPanelsHost.kt @@ -45,6 +45,7 @@ import androidx.compose.ui.input.key.onKeyEvent import androidx.compose.ui.input.key.type import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext +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 @@ -414,7 +415,7 @@ private fun TvSavePanelContent(video: Video) { val added = info.id in membership TvSelectionRow( label = info.name, - supportingText = stringResource(R.string.videos_count_template, info.videoCount), + supportingText = pluralStringResource(R.plurals.videos_count_template, info.videoCount, info.videoCount), selected = added, onClick = { scope.launch { @@ -622,7 +623,12 @@ private fun TvCommentRow( } if (comment.replyCount > 0) { Text( - text = stringResource(R.string.view_replies_template, comment.replyCount), + text = + pluralStringResource( + R.plurals.view_replies_template, + comment.replyCount, + comment.replyCount, + ), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.primary, ) diff --git a/app/src/main/java/io/github/aedev/flow/ui/tv/screens/TvPlaylistDetailScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/tv/screens/TvPlaylistDetailScreen.kt index 68802fd8a..7baebb71b 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/tv/screens/TvPlaylistDetailScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/tv/screens/TvPlaylistDetailScreen.kt @@ -12,6 +12,7 @@ import androidx.compose.material.icons.outlined.Shuffle import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel @@ -46,7 +47,7 @@ fun TvPlaylistDetailScreen( TvScreenScaffold( title = state.playlistName.ifBlank { stringResource(R.string.tv_library_playlists) }, modifier = modifier, - subtitle = stringResource(R.string.videos_count_template, videos.size), + subtitle = pluralStringResource(R.plurals.videos_count_template, videos.size, videos.size), ) { Column( modifier = Modifier.fillMaxSize(), @@ -54,9 +55,10 @@ fun TvPlaylistDetailScreen( ) { if (videos.isNotEmpty()) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = dimens.overscanHorizontal), + modifier = + Modifier + .fillMaxWidth() + .padding(horizontal = dimens.overscanHorizontal), horizontalArrangement = Arrangement.spacedBy(12.dp), ) { TvButton( @@ -76,9 +78,10 @@ fun TvPlaylistDetailScreen( if (videos.isEmpty()) { TvMessageState( title = stringResource(R.string.tv_library_empty), - modifier = Modifier - .fillMaxSize() - .padding(horizontal = dimens.overscanHorizontal), + modifier = + Modifier + .fillMaxSize() + .padding(horizontal = dimens.overscanHorizontal), ) } else { val indexed = videos.mapIndexed { index, video -> index to video } diff --git a/app/src/main/java/io/github/aedev/flow/ui/tv/screens/TvSubscriptionsScreen.kt b/app/src/main/java/io/github/aedev/flow/ui/tv/screens/TvSubscriptionsScreen.kt index 8538eb28f..e6e1016f9 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/tv/screens/TvSubscriptionsScreen.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/tv/screens/TvSubscriptionsScreen.kt @@ -21,6 +21,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -105,8 +106,9 @@ fun TvSubscriptionsScreen( ) Text( text = - stringResource( - R.string.subscriptions_refresh_progress_template, + pluralStringResource( + R.plurals.subscriptions_refresh_progress_template, + state.refreshTotalChannels, state.refreshProcessedChannels, state.refreshTotalChannels, ), diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 4f80f933f..547c000bc 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -109,10 +109,6 @@ بحث الإشتراكات تفعيل وضع العرض إلغاء الإشتراك من %1$s - %1$d فيديوهات - %1$d قوائم التشغيل - %1$d مقاطع قصيرة - %1$d أغاني لا يوجد تحميلات بعد تشغيل الكل الإزالة من المشاهدة لاحقا @@ -241,8 +237,6 @@ فاتح غامق خاص - %1$d المواضيع - %1$d %2$s المواضيع محدد: %1$s اختر نمط أيقونة المشغل. سيتم تطبيق التغيير فورًا وسيتم تحديث المشغل لفترة وجيزة. تنبيه: تغيير الأيقونات يستخدم آلية في نظام أندرويد و التي تؤدي إلى إزالة إختصار التطبيق من شاشتك الرئيسية. اضغط مطولاً على مشغل التطبيقات لإعادتها مرة أخري إذا لزم الأمر. @@ -526,8 +520,6 @@ خصّص ما تراه الإهتمامات محظور - %1$d موضوع - %1$d مخفي إهتماماتك تساعد المواضيع التي اخترتها Flow في اقتراح محتوى أفضل. انقر على المواضيع أدناه لإضافتها أو إزالتها. تُتابع حالياً @@ -543,10 +535,8 @@ إضافة سريعة المواضيع الشائعة لحظرها محظور حاليا - %1$d موضوع%2$s إزالة %1$s إلغاء حظر %1$s - %1$d محدد إدارة الوقت تتبع وقت استخدامك للشاشة و تحكم فيه تستند الإحصائيات إلى سجل المشاهدة الخاص بك عبر هذا التطبيق. قد يختلف الاستخدام الفعلي. @@ -557,12 +547,10 @@ سيتم إرسال إشعار عندما يحين وقت النوم. ذكرني بأخذ استراحة عدد مرات التذكير - كل %1$d دقيقة المتوسط اليومي اليوم أخر 7 أيام معدل التكرار - كل %1$d دقيقة هذا الأسبوع المجموع: %s ساعة لا يوجد بيانات للمشاهدات حتى الآن @@ -578,7 +566,6 @@ تأكيد مؤقت النوم المدة - %1$d دقيقة 5 دقائق 120 دقيقة وقت مخصص @@ -600,31 +587,24 @@ اقتراحات البحث إظهار الإقتراحات أثناء الكتابة الحجم الأقصى للسجل - حاليا: %1$d عملية بحث حذف السجل تلقائيا - الحذف بعد %1$d يوم لا تحذف تلقائياً أبداً فترة الاحتفاظ - حذف عمليات البحث الأقدم من %1$d يوم مسح سجل البحث إزالة كافة عمليات البحث هل تريد مسح سجل البحث؟ حذف كل سجل البحث نهائياً. اختر عدد عمليات البحث التي تريد الاحتفاظ بها: - %1$d عملية بحث حذف عمليات البحث الأقدم من: 1 أسبوع 1 شهر 3 أشهر 6 أشهر 1 سنة - %1$d أيام استيراد البيانات تم استيراد النسخة الاحتياطية من Flow بنجاح فشل استيراد نسخة Flow الاحتياطية: %1$s - تم استرداد %1$d اشتراك من NewPipe فشل في استرداد نسخة NewPipe الاحتياطية: %1$s - تم استرداد %1$d اشتراكات من YouTube فشل في استيراد نسخة احتياطية من يوتيوب: %1$s استيراد نسخة احتياطية من Flow استرد سجلك، إعداداتك و إشتراكاتك من ملف النسخ الاحتياطي لـ Flow. @@ -646,9 +626,7 @@ استورد قائمة تشغيل من ملف CSV الخاص بـ YouTube Takeout (Playlist-<name>.csv). استيراد قائمة تشغيل YouTube Music استورد قائمة تشغيل موسيقية من ملف CSV الخاص بخدمة YouTube Music Takeout. تظهر القائمة ضمن قوائم تشغيل الموسيقى. - تم استيراد %1$d فيديوهات من سجل مشاهدة YouTube الخاص بك فشل استيراد سجل المشاهدة: %1$s - قائمة التشغيل المستوردة \"%1$s\" مع %2$d فيديوهات فشل استيراد قائمة التشغيل: %1$s لم يتم العثور على أي سجلات مشاهدة في هذا الملف. تأكد من أنه ملف watch-history.html خاص بـ YouTube Takeout. لم يتم العثور على أي فيديوهات في ملف CSV هذا. تأكد من أنه ملف CSV لقائمة تشغيل YouTube Takeout. @@ -667,7 +645,6 @@ التنزيل المتوازي قم بتنزيل الملفات على دفعات متعددة للحصول على أقصى سرعة. عدد تقسيمات الفيديو المتزامنة - %1$d تقسيم لكل تحميل إستخدام المزيد من التقسيمات يمكن أن يزيد السرعة ولكنه قد يستهلك المزيد من البطارية ويرفع درجة حرارة الجهاز. اختر مكان حفظ الملفات التي تم تنزيلها على جهازك. المواقع المحددة مسبقًا @@ -686,7 +663,6 @@ مستحسن نشط ‍حدد عدد التقسيمات (1-8): - %1$d تقسيمات الدعم والتبرعات إدعم تطوير Flow إذا وجدتَ تطبيق Flow مفيدًا وترغب في دعم تطويره، يمكنك دعمه عبر منصة Patreon أو التبرع عبر عناوين العملات الرقمية الموضحة أدناه. دعمكم يُسهم في استمرار المشروع! @@ -741,12 +717,9 @@ أضف مقاطع الفيديو من مشغل الفيديو\nلإنشاء قائمة التشغيل الخاصة بك هل تريد حذف قائمة التشغيل؟ سيؤدي هذا إلى حذف \'%1$s\' وجميع مقاطع الفيديو فيه بشكل دائم. - قائمة تشغيل • خاصة • فيديوهات %1$d - ‎قائمة تشغيل • عامة • فيديوهات %1$d مرحبا بك في Flow أخبرنا بما يثير اهتمامك إختر 3 مواضيع على الأقل لتخصيص تجربتك - تم اختيار %1$d (يلزم اختيار %2$d إضافي) تخطي الآن إستمرار تصغير @@ -783,7 +756,6 @@ التفاعلات المواضيع شاهد بعض الفيديوهات لتوسيع دائرة اهتمامك! - %1$d التفاعلات • المستوي %2$d تصدير بيانات الملف الشخصي تصدير ملف تعريف التدفق العصبي لFlow مكتبة الموسيقى @@ -798,8 +770,6 @@ %1$s • %2$s مشاهدات عرض الكل بحث - %1$s مشاهدات - %1$d مسارات • %2$s خطأ غير معروف إعادة المحاولة تصفح @@ -864,7 +834,6 @@ قائمة تشغيل • %1$s تم التشغيل • %1$s مرة ألبوم • %1$s • %2$s - الفنان • %1$s مستمع شهرياً بحث: %1$s الفنان: %1$s أفضل الخيارات لك @@ -876,7 +845,6 @@ أنشئ قائمة تشغيلك الأولى لتنظيم أغانيك المفضلة لا يوجد عناصر مفضلة بعد انقر على أيقونة القلب الموجودة على أي اغنية لإضافته إلى مفضلاتك - %1$d اغاني مفضلة لا يوجد سجل بعد ابدأ الإستماع للموسيقى للاطلاع على سجلاتك هنا لا تنزيلات بعد @@ -1023,7 +991,6 @@ تم نسخ التقرير إلى الحافظة أضف إلى قائمة التشغيل الخاصة بي أضف جميع الأغاني إلى… - تمت إضافة أغاني %1$d إلي “%2$s” لا توجد قوائم تشغيل حتى الآن. أنشئ واحدة أولاً! Flow قوائم تشغيل الموسيقى @@ -1077,7 +1044,6 @@ الأحدث لا تعليقات بعد اقرأ المزيد - عرض %1$d رد تعليق مثبت تم التثبيت بواسطة منشئ المحتوى مقاطع قصيرة @@ -1088,8 +1054,6 @@ أضف إلى بداية قائمة الانتظار FLOW 9+ - %1$d فيديوهات مختارة خصيصاً لك - قوائم التشغيل• خاص • %1$d فيديوهات صريحة HD 4K @@ -1389,7 +1353,6 @@ تفضيلات مدة المشاهدة القيم الأعلى تميل نحو مقاطع الفيديو الأطول إتساع الموضوع - ‎%1$d موضوع في المتجه العام أوزان الإهتمامات المواضيع ذات الأهمية القصوى بعد فترة مراقبة الإستخدام و التأكد من الأدلة علي الإهتمام بذلك الموضوع لم يتم تحديد أوزان للمواضيع بعد. @@ -1441,7 +1404,6 @@ إستيراد الملف الشخصي إستعادة نسخة احتياطية للملف الشخصي تحميل الكل - هل تريد تنزيل جميع فيديوهات %1$d؟ قد يستهلك هذا مساحة تخزين كبيرة. تم نسخ العنوان إلى الحافظة تمكين الإشعارات إسمح لتطبيق Flow بالعمل في الخلفية لإجراء عمليات فحص الإشعارات والتنبيهات @@ -1459,13 +1421,10 @@ تنزيلات غير مكتملة تم الإلغاء إزالة التنزيلات غير المكتملة - هل تريد حذف %1$d من التنزيلات المتوقفة أو الفاشلة أو الجزئية؟ لن يتم المساس بالتنزيلات المكتملة. قفل التحكم إلغاء قفل التحكم زر وضع الغلق أظهر زر قفل المشغل لمنع اللمسات الغير مقصودة - إعادة تحديث %1$d من %2$d قناة - أخر تحديث %1$s - %2$d فيديو تم فحصه سمات النظام الإفتراضية إختر السمة التي سيتم استخدامها عند تبديل جهازك بين الوضع الفاتح والوضع الداكن. الوضع الفاتح @@ -1495,8 +1454,6 @@ أظهر الفيديوهات القصيرة للقناة قم بتهيئة وكيل HTTP أو SOCKS5 اختياري للطلبات البعيدة. يبقى Local casting و LAN discovery مباشر. التمرير التلقائي بعد وقت محدد - التمرير التلقائي كل %1$d ثانية - %1$d ثانية تلقائي %1$ds Suppressed عناصر فترة الهدوء @@ -1522,12 +1479,10 @@ الأكثر رواجاً وقت النشر (الأحدث) وقت النشر (الأقدم) - هل تريد حذف %1$d فيديو؟ سيتم حذفها من قائمة التشغيل هذه. سيتم حذفها من المشاهدة لاحقاً. ستظهر الأغاني التي تعجبك هنا لا يوجد موسيقى أعجبتك - %1$d إعجاب ‏خيارات فرز قائمة التشغيل يدوي تاريخ الإضافة (الأحدث) @@ -1692,7 +1647,6 @@ تشغيل الفيديو التالي في قائمة التشغيل أو قائمة المشاهدة لاحقًا تلقائيًا. عند إيقاف هذه الخاصية، يمكنك تخطي الفيديوهات يدويًا. تأخير التشغيل التلقائي لا يوجد (قم بالتبديل فوراً) - %1$d ثانية يعرض عدًا تنازليًا قبل الانتقال تلقائيا إلى الفيديو التالي. خلال العد التنازلي، يمكنك إعادة تشغيل الفيديو الحالي، أو إلغاء الانتقال، أو تشغيل الفيديو التالي مباشرةً. التالي الفيديو التالي @@ -1806,7 +1760,6 @@ ابحث عن القنوات… اكتب إسم القناة لبدء البحث لم يتم العثور على قنوات لـ \"%1$s\" - تمت إضافة %1$d قناة ‏بدأت للتو. لا يزال ملفك الشخصي قيد الإنشاء. ‎عُشاق الصوت ‎تستخدم تطبيق Flow في الغالب للموسيقى. فالأجواء هي كل شيء. @@ -1832,7 +1785,6 @@ استورد بياناتك يمكنك نقل اشتراكاتك وسجلّك من التطبيقات الأخرى. كل شيء اختياري. النسخ الاحتياطي و الاستعادة - تم تحديد %1$d مُحدد غير مُحدد فشل الاستيراد: %1$s @@ -2005,7 +1957,6 @@ الإصدار %1$s يتوفر إصدار جديد من Flow (%1$s). هل تريد تنزيل أحدث ملف APK؟ قائمة التشغيل فارغة - جاري تنزيل %1$d فيديو… تم حفظ قائمة التشغيل في المكتبة ‎تمت إزالة قائمة التشغيل من المكتبة جاري تنزيل الصوت: %1$skbps %2$s @@ -2024,10 +1975,8 @@ تم حذف قائمة التشغيل تمت إعادة تسمية قائمة التشغيل بدء التنزيل لـ %1$s… - تم تنزيل %1$d مساراً من %2$s فشل تنزيل قائمة التشغيل خطأ في تنزيل قائمة التشغيل - تم تنزيل %1$d مساراً تمت إضافته إلى قائمة التشغيل فشل إضافة المسار تمت إزالته من قائمة التشغيل @@ -2052,7 +2001,6 @@ فشل التنزيل +%1$d المزيد فيديوهات جديدة - %1$d فيديو جديد من اشتراكاتك التحديث متاح: %1$s انقر للتحديث لأحدث إصدار. تذكير بالمشاهدة لاحقاً @@ -2123,7 +2071,6 @@ إدارة نُسخ Flow الإحتياطية خدمات خارجية الاستيراد من تطبيقات YouTube الأخرى - تم استيراد %1$d %2$s تم استيراد %1$s بنجاح استيراد %1$s… مستورد من Google Takeout @@ -2316,7 +2263,6 @@ إعادة ترتيب عنصر قائمة الانتظار تم تعديله %1$s (%2$s) - %1$d ساعة تخضع عمليات التحقق من الخلفية لقيود يمنع نظام أندرويد تطبيق Flow من التحقق من وجود فيديوهات جديدة أثناء إغلاقه، لذا لن تصلك التنبيهات إلا عند فتح التطبيق. انقر للسماح بنشاط التطبيق في الخلفية دون قيود. أصلي @@ -2331,7 +2277,6 @@ لم يتم العثور على أي محتوى قابل للاستيراد في هذه النسخة الاحتياطية تنسيق النسخة الاحتياطية غير معروف — تأكد من تحديد الملف الصحيح فشل الاستيراد: %1$s - %1$d دقيقة %1$d ساعة و %2$d دقيقة %1$dساعة %1$dدقيقة @@ -2380,7 +2325,6 @@ قم بدمج مكتبة جهاز آخر إلي جهازك. تحديد الكل مسح - تم اختيار %1$d من %2$d قوائم التشغيل والألبومات وقائمة المشاهدة لاحقًا. ما شاهدته وإلى أي مدى وصلت. مقاطع الفيديو والموسيقى التي أعجبتني والتي لم تعجبني. diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index ba23929e4..45b393d92 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -12,8 +12,6 @@ Hələ abunəlik yoxdur Ən son videoları burada görmək üçün\nkanallara abunə olun Lenti yenilə - %2$d kanaldan %1$d-i yenilənir - Son yenilənmə: %1$s — %2$d video yoxlanıldı Son yenilənmə: %1$s Yenidən sına Jurnalları kopyala @@ -84,7 +82,6 @@ Endirildi Endir Hamısını endir - %1$d videonun hamısı endirilsin? Bu, xeyli yaddaş sahəsi tuta bilər. Yadda saxla Yadda saxlanıldı Sizə məxsus @@ -239,7 +236,6 @@ Davamını oxu Cavabla Cavabları gizlət - %1$d cavaba bax Daha çox cavab göstər Mətni seç Bərkidilmiş şərh @@ -297,7 +293,6 @@ FLOW 9+ Fərdiləşdirilmiş lentiniz - Sizin üçün seçilmiş %1$d video NewPipe ehtiyat nüsxəsini idxal et Abunəliklər NewPipe ehtiyat nüsxəsindən idxal edilir... Abunəliklərdə axtar @@ -313,15 +308,9 @@ %1$s kanalından abunəlik ləğv edildi Bu kanalın Shorts videolarını gizlət Bu kanalın Shorts videolarını göstər - %1$d video - %1$d bəyənmə - %1$d pleylist - %1$d Shorts videosu - %1$d mahnı Hələ endirmə yoxdur Hamısını oxut “Sonra bax”dan sil - Pleylist • Gizli • %1$d video E Yadda saxlanmış video yoxdur Sonra baxmaq üçün yadda saxladığınız videolar burada görünəcək @@ -504,8 +493,6 @@ Tünd Fərdi Xüsusi - Cəmi %1$d tema - %1$d %2$s tema Tətbiq edildi: %1$s Temanı fərdiləşdir Fərdi tema redaktoru @@ -842,17 +829,14 @@ Dövrə (cari Shorts videosunu təkrarla) Növbətini avtomatik oxut (növbəti Shorts videosuna keç) Fərdi müddətdən sonra avtomatik sürüşdür - Hər %1$d saniyədən bir avtomatik sürüşdür Shorts oxutma rejimi Cari Shorts videosu bitdikdə nə baş verəcəyini seçin: - %1$d saniyə Əlaqəli videoları avtomatik oxut Növbə boş olduqda növbəti təklif olunan videonu avtomatik oxudun Növbədəki videoları avtomatik oxut Pleylistdə və ya “Sonra bax” növbəsində növbəti videonu avtomatik oxudun. Söndürüldükdə yenə də əl ilə keçə bilərsiniz. Avtomatik oxutma gecikməsi Yoxdur (dərhal keç) - %1$d saniyə Növbəti videoya avtomatik keçməzdən əvvəl geri sayım göstərin. Geri sayım zamanı cari videonu yenidən başlada, keçidi ləğv edə və ya növbəti videonu dərhal oxuda bilərsiniz. Növbəti Növbəti video @@ -1028,8 +1012,6 @@ Gördüyünüz məzmunu fərdiləşdirin Maraqlar Bloklanmışlar - %1$d mövzu - %1$d gizlədilib Maraqlarınız Seçdiyiniz mövzular Flow-a daha yaxşı məzmun tövsiyə etməyə kömək edir. Mövzuları əlavə etmək və ya silmək üçün aşağıdakılara toxunun. Hazırda izlədikləriniz @@ -1045,10 +1027,8 @@ Sürətli əlavə Tez-tez bloklanan mövzular Hazırda bloklananlar - %1$d mövzu %1$s mövzusunu sil %1$s mövzusunun blokunu aç - %1$d seçilib Seç Seçimi ləğv et Hamısını seç @@ -1064,12 +1044,10 @@ Başlama vaxtında bildiriş göndəriləcək. Fasilə verməyi xatırlat Xatırlatma tezliyi - Hər %1$d dəqiqədən bir Gündəlik orta Bu gün Son 7 gün Tezlik - Hər %1$d dəqiqədən bir Bu həftə Cəmi: %s saat Hələ baxış məlumatı yoxdur @@ -1085,7 +1063,6 @@ Təsdiqlə Yuxu taymeri Müddət - %1$d dəqiqə 5 dəqiqə 120 dəqiqə Fərdi vaxt @@ -1107,31 +1084,24 @@ Axtarış təklifləri Yazarkən təklifləri göstərin Maksimum tarixçə ölçüsü - Hazırda: %1$d axtarış Tarixçəni avtomatik sil - %1$d gündən sonra sil Heç vaxt avtomatik silmə Saxlanma müddəti - %1$d gündən köhnə axtarışları sil Axtarış tarixçəsini təmizlə Bütün axtarış sorğularını sil Axtarış tarixçəsi təmizlənsin? Bütün axtarış tarixçəsini həmişəlik silin. Saxlanılacaq axtarış sayını seçin: - %1$d axtarış Bundan köhnə axtarışları sil: 1 həftə 1 ay 3 ay 6 ay 1 il - %1$d gün Məlumatları idxal et Flow ehtiyat nüsxəsi uğurla idxal edildi Flow ehtiyat nüsxəsini idxal etmək mümkün olmadı: %1$s - NewPipe-dan %1$d abunəlik idxal edildi NewPipe ehtiyat nüsxəsini idxal etmək mümkün olmadı: %1$s - YouTube-dan %1$d abunəlik idxal edildi YouTube ehtiyat nüsxəsini idxal etmək mümkün olmadı: %1$s Flow ehtiyat nüsxəsini idxal et Tarixçənizi, parametrlərinizi və abunəliklərinizi Flow ehtiyat nüsxəsi faylından bərpa edin. @@ -1167,9 +1137,7 @@ YouTube Takeout CSV faylından (Playlist-<name>.csv) pleylist idxal edin. YouTube Music pleylistini idxal et YouTube Music Takeout CSV faylından musiqi pleylisti idxal edin. Musiqi pleylistləri bölməsində görünür. - YouTube baxış tarixçənizdən %1$d qeyd idxal edildi Baxış tarixçəsini idxal etmək mümkün olmadı: %1$s - “%1$s” pleylisti %2$d video ilə idxal edildi Pleylisti idxal etmək mümkün olmadı: %1$s Bu faylda baxış tarixçəsi qeydi tapılmadı. Bunun YouTube Takeout watch-history.html faylı olduğuna əmin olun. Bu CSV faylında video tapılmadı. Bunun YouTube Takeout pleylist CSV faylı olduğuna əmin olun. @@ -1202,7 +1170,6 @@ Paralel endirmə Maksimum sürət üçün faylları bir neçə hissədə endirin. Paralel iş axınları - Hər endirmə üçün %1$d iş axını Daha çox axın sürəti artıra bilər, lakin batareya sərfini və cihazın isinməsini də artıra bilər. Endirilən faylların cihazınızda harada saxlanılacağını seçin. Hazır məkanlar @@ -1221,7 +1188,6 @@ Tövsiyə olunur Aktiv İş axınlarının sayını seçin (1–8): - %1$d iş axını Dəstək və ianələr Flow-un hazırlanmasına dəstək olun Flow-u faydalı hesab edir və hazırlanmasına dəstək olmaq istəyirsinizsə, Patreon-da dəstək verə və ya aşağıdakı kriptovalyuta ünvanlarına ianə göndərə bilərsiniz. Dəstəyiniz layihənin yaşamasına kömək edir! @@ -1283,8 +1249,6 @@ Pleylistinizi yaratmaq üçün\npleyerdən videolar əlavə edin Pleylist silinsin? Bu əməl “%1$s” pleylistini və daxilindəki bütün videoları həmişəlik siləcək. - Pleylist • Gizli • %1$d video - Pleylist • Hamıya açıq • %1$d video Pleylist sıralama seçimləri Əl ilə Əlavə olunma tarixi (ən yeni) @@ -1292,13 +1256,11 @@ Ən populyar Yayımlanma tarixi (ən yeni) Yayımlanma tarixi (ən köhnə) - %1$d video silinsin? Onlar bu pleylistdən silinəcək. Onlar “Sonra bax”dan silinəcək. Flow-a xoş gəlmisiniz Maraqlandığınız mövzuları bizə bildirin Təcrübənizi fərdiləşdirmək üçün ən azı 3 mövzu seçin - %1$d seçilib (daha %2$d lazımdır) Nələrdən zövq alırsınız? Lentinizi fərdiləşdirmək üçün ən azı %1$d mövzu seçin. Daha %2$d mövzu lazımdır. Əla seçimdir. Bunu sonra istənilən vaxt parametrlərdə yeniləyə bilərsiniz. @@ -1307,14 +1269,12 @@ Kanallarda axtar… Axtarmaq üçün kanal adı yazın “%1$s” üçün kanal tapılmadı - %1$d kanal əlavə edildi %1$s abunəçi Abunə olundu Abunə ol Məlumatlarınızı idxal edin Abunəliklərinizi və tarixçənizi başqa tətbiqlərdən gətirin. Hər şey istəyə bağlıdır. Ehtiyat nüsxə və bərpa - %1$d seçilib Seçilib Seçilməyib İdxal uğursuz oldu: %1$s @@ -1378,7 +1338,6 @@ Qarşılıqlı əlaqələr Mövzular Maraq dumanlığınızı doldurmaq üçün bir neçə videoya baxın! - %1$d qarşılıqlı əlaqə • Səviyyə %2$d Profil məlumatlarını ixrac et Flow neyron profilinin ixracı Musiqi kitabxanası @@ -1398,8 +1357,6 @@ %1$s • %2$s baxış Hamısına bax Axtar - %1$s baxış - %1$d trek • %2$s Naməlum xəta Yenidən sına Əhval və janrlar əlçatan deyil @@ -1488,7 +1445,6 @@ Pleylist • %1$s • %1$s oxutma Albom • %1$s • %2$s - İfaçı • aylıq %1$s dinləyici Axtarış: %1$s İfaçı: %1$s Sizin üçün ən yaxşı seçimlər @@ -1500,7 +1456,6 @@ Sevimli treklərinizi nizamlamaq üçün ilk pleylistinizi yaradın Hələ seçilmiş yoxdur Treki seçilmişlərə əlavə etmək üçün ürək nişanına toxunun - %1$d seçilmiş trek Hələ tarixçə yoxdur Tarixçəni burada görmək üçün musiqi dinləməyə başlayın Hələ endirmə yoxdur @@ -1558,7 +1513,6 @@ Uğursuz Ləğv edilib Tamamlanmamış endirmələri sil - %1$d dayandırılmış, alınmamış və ya natamam endirmə silinsin? Tamamlanmış endirmələrə toxunulmayacaq. Audio trek %1$s %2$d %1$s (%2$s) @@ -1792,7 +1746,6 @@ Hesabat mübadilə buferinə kopyalandı Pleylistimə əlavə et Bütün mahnıları buraya əlavə et… - %1$d mahnı “%2$s” pleylistinə əlavə edildi Hələ pleylist yoxdur. Əvvəlcə birini yaradın! Profil uğurla ixrac edildi İxrac uğursuz oldu @@ -1828,7 +1781,6 @@ Canlı yayım uyğunluğu Canlı məzmunun profilə nə qədər uyğun olduğu Mövzu genişliyi - Qlobal vektorda %1$d mövzu Maraq çəkiləri Sınaq müddəti və sübut yoxlamalarından sonra ən yüksək çəkili mövzular Hələ mövzu çəkisi yoxdur. @@ -2002,7 +1954,6 @@ Flow-un yeni versiyası mövcuddur (%1$s). Ən son APK endirilsin? İ N S T R U M E N T A L Pleylist boşdur - %1$d video endirilir… Pleylist kitabxanada yadda saxlanıldı Pleylist kitabxanadan silindi Audio endirilir: %1$skbps %2$s @@ -2024,10 +1975,8 @@ Pleylist silindi Pleylistin adı dəyişdirildi %1$s üçün endirmə başladılır… - %2$s pleylistindən %1$d trek endirildi Pleylisti endirmək mümkün olmadı Pleylist endirilərkən xəta baş verdi - %1$d trek endirildi Pleylistə əlavə edildi Treki əlavə etmək mümkün olmadı Pleylistdən silindi @@ -2044,7 +1993,6 @@ Endirmə uğursuz oldu +%1$d daha Yeni videolar - Abunəliklərinizdən %1$d yeni video Yeniləmə mövcuddur: %1$s Ən son versiyaya yeniləmək üçün toxunun. “Sonra bax” xatırlatması @@ -2115,7 +2063,6 @@ Flow ehtiyat nüsxələrinizi idarə edin Xarici xidmətlər Başqa YouTube müştərilərindən idxal et - %1$d %2$s idxal edildi %1$s uğurla idxal edildi %1$s idxal edilir… Google Takeout-dan idxal edildi diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml index 34065f904..f5f27c366 100644 --- a/app/src/main/res/values-bs/strings.xml +++ b/app/src/main/res/values-bs/strings.xml @@ -160,7 +160,6 @@ Pročitaj više Odgovori Sakrij odgovore - Pogledaj %1$d odgovora Zakačeni komentar Zakačio autor Novo ažuriranje dostupno @@ -203,20 +202,14 @@ FLOW 9+ Vaš personalizirani feed - >%1$d videozapisa prilagođenih vama Uvezi sigurnosnu kopiju iz NewPipe-a Uvoz pretplata iz NewPipe sigurnosne kopije… Pretraži pretplate Prebaci način pregleda %1$s otpreplaćen - %1$d videozapisa - %1$d lista za reprodukciju - %1$d shorts - %1$d pjesama Još nema preuzimanja Reproduciraj sve Ukloni iz Gledaj kasnije - %1$d videozapisa • Privatno E Nema sačuvanih videa Videi koje sačuvaš za Gledaj kasnije pojavit će se ovdje @@ -387,8 +380,6 @@ Tamno Prilagođeno Posebno - %1$d tema - %1$d %2$s teme Primijenjeno: %1$s Prilagodi Temu Postavite svaku ulogu s heks vrijednostima i odmah je pregledajte diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index c4749c7b1..cdcf74bad 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -115,7 +115,6 @@ A další Není nalezeno Povolte přístup k médiím, aby Flow mohl vyhledávat a přehrávat místní videa a hudbu. - Stáhnout všechna videa? To může zabrat značné množství úložného prostoru. "Nepovedlo se uložit do knihovny" karaoke SOUVISEJÍCÍ diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 46211c5aa..fe22966af 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -155,7 +155,6 @@ Lesen Sie mehr Antworten Antworten ausblenden - Antworten anzeigen %1$d Mehr Antworten laden Angepinnter Kommentar Vom Ersteller angepinnt @@ -201,7 +200,6 @@ FLOW 9+ Dein persönlicher Feed - %1$d Videos, speziell für dich ausgewählt NewPipe-Backup importieren Abonnements aus dem NewPipe-Backup werden importiert... Text auswählen @@ -216,14 +214,9 @@ Kanäle suchen… Ansichtsmodus umschalten Abmeldung von %1$s - %1$d Videos - %1$d playlists - %1$d shorts - %1$d Songs Noch keine Downloads Alle abspielen Aus „Später ansehen“ entfernen - Playlist • Privat • %1$d Videos e Keine Videos gespeichert Videos, die Sie speichern, um sie später anzusehen, werden hier angezeigt @@ -390,8 +383,6 @@ Dunkel Benutzerdefiniert Speziell - %1$d Design - %1$d %2$s Designs Angewandt: %1$s Design anpassen Benutzerdefinierter Design-Editor @@ -569,8 +560,6 @@ Shorts-Player deaktivieren Zeige die horizontalen Shorts im Feed-Raster des Abonnements an. Shorts auf dem Startbildschirm - Aktualisierung von %1$d von %2$d Kanälen - Zuletzt aktualisiert am %1$s – %2$d Videos geprüft Suchverlauf durchsuchen Alle Jahre Neueste zuerst @@ -581,7 +570,6 @@ Shorts Hier werden die Songs angezeigt, die Sie liken Alle herunterladen - Alle %1$d Videos herunterladen? Dies kann viel Speicherplatz beanspruchen. Gespeichert Vorschlag für den Spielmodus Speicherung aufheben – Später ansehen @@ -699,7 +687,6 @@ Erinnerungen an bevorstehende Veröffentlichung Der Download wurde gestartet… Download-Fehler: %1$s - %1$d likes Mag ich nicht Hintergrund des Musik-Players Unschärfe + Farbverlauf @@ -718,10 +705,8 @@ Schleife (aktuellen Abschnitt wiederholen) „Nächsten Titel automatisch abspielen“ (zum nächsten Short springen) Automatisches Scrollen nach einer festgelegten Zeit - Alle %1$d Sekunden automatisch scrollen Wiedergabemodus für Shorts Wähle aus, wie sich „Shorts“ verhalten soll, wenn der aktuelle Short zu Ende ist: - %1$d Sekunden Automatische Wiedergabe von verwandten Videos Wenn nichts in der Warteschlange vorhanden ist, wird automatisch ein vorgeschlagenes Video als Nächstes abgespielt Stille überspringen @@ -899,7 +884,6 @@ Passen Sie die Anzeige an Interessen Gesperrt - %1$d Themen Deine Interessen Die von dir ausgewählten Themen helfen Flow dabei, dir passendere Inhalte vorzuschlagen. Tippe unten auf die Themen, um sie hinzuzufügen oder zu entfernen. Derzeit abonniert @@ -912,36 +896,30 @@ Derzeit gesperrt %1$s entfernen %1$s entsperren - %1$d ausgewählt Zeitmanagement Verfolgen und kontrollieren Sie Ihre Bildschirmzeit Die Statistiken basieren auf Ihrem Sehverhalten in dieser App. Die tatsächliche Nutzung kann davon abweichen. Tools zur Verwaltung Ihrer Zeit Erinnere mich daran, wenn es Zeit fürs Bett ist - %1$d ausgeblendet Nach Kategorie durchsuchen Ausgeblendeter Inhalt Videos zu diesen Themen werden nicht in deinen Empfehlungen angezeigt. Du kannst bei Videos auch auf die Schaltfläche „Nicht interessiert“ klicken. Thema blockieren Geben Sie Suchbegriffe ein, um sie auszublenden - %1$d Thema%2$s Beginn Ende Zum Startzeitpunkt wird eine Benachrichtigung versendet. Erinnere mich daran, eine Pause zu machen Häufigkeit der Erinnerungen - Alle %1$d Minuten Tagesdurchschnitt Heute Letzte 7 Tage Häufigkeit - alle %1$d Minuten Diese Woche Insgesamt: %s Stunden Bestätigen Schlaftimer Dauer - %1$d Minuten 5 Minuten 120 Minuten Benutzerdefinierte Zeit @@ -981,7 +959,6 @@ Das nächste Video in einer Wiedergabeliste oder in der Warteschlange „Später ansehen“ wird automatisch abgespielt. Wenn diese Funktion deaktiviert ist, kannst du die Videos weiterhin manuell überspringen. Verzögerung bei der automatischen Wiedergabe Keine (sofort wechseln) - %1$d Sekunden Zeige einen Countdown an, bevor automatisch zum nächsten Video gewechselt wird. Während des Countdowns kannst du das aktuelle Video erneut starten, den Wechsel abbrechen oder das nächste Video sofort abspielen. Als Nächstes Nächstes Video @@ -1002,18 +979,14 @@ Suchvorschläge Vorschläge während der Eingabe anzeigen Maximale Größe des Verlaufs - Derzeit: %1$d Suchanfragen Verlauf automatisch löschen - Nach %1$d Tagen löschen Niemals automatisch löschen Aufbewahrungsfrist - Suchanfragen löschen, die älter als %1$d Tage sind Suchverlauf löschen Alle Suchanfragen löschen Suchverlauf löschen? Den gesamten Suchverlauf dauerhaft löschen. Wählen Sie aus, wie viele Suchanfragen Sie behalten möchten: - %1$d Suchanfragen Suchanfragen löschen, die älter sind als: 1 Woche 1 Monat @@ -1029,16 +1002,13 @@ Short, nicht gespeichert Flow-Backup erfolgreich importiert Der Import des Flow-Backups ist fehlgeschlagen: %1$s - %1$d Abonnements aus NewPipe importiert Der Import des NewPipe-Backups ist fehlgeschlagen: %1$s - %1$d Abonnements von YouTube importiert Der Import des YouTube-Backups ist fehlgeschlagen: %1$s Flow-Backup importieren Stellen Sie Ihren Verlauf, Ihre Einstellungen und Ihre Abonnements aus einer Flow-Backup wieder her. Aus NewPipe importieren Anzeige Schaltet sich nach - %1$d Tage Daten importieren NewPipe-Exportdatei (JSON). Aus LibreTube importieren @@ -1149,7 +1119,6 @@ Veröffentlichen Benutzerdefiniert Beliebtest - %1$d Video(s) entfernen? Sag uns was dich interessiert Wähle mindestens 3 Themen aus um deine Erfahrung zu personalisieren Gute Auswahl. Du kannst dies später immer in den Einstellungen aktualisieren. @@ -1157,13 +1126,11 @@ Suche nach Kanälen denen du bereits folgst und abonniere sie mit einem Klick. Suche Kanäle… Keine Kanäle für \"%1$s\" gefunden - %1$d Kanäle hinzugefügt %1$s Abonnenten Abonniert Abonnieren Deine Daten importieren Sichern & Wiederherstellen - %1$d ausgewählt Ausgewählt Nicht ausgewählt Überspringen @@ -1467,9 +1434,7 @@ Importiere eine Playlist aus einer YouTube Takeout-CSV-Datei (Playlist-<Name>.csv). YouTube-Musik-Playlist importieren Importieren Sie eine Musik-Playlist aus einer YouTube Music Takeout-CSV-Datei. Diese wird unter „Musik-Playlists“ angezeigt. - %1$d Einträge aus Ihrem YouTube-Wiedergabeverlauf wurden importiert Der Import des Wiedergabesverlaufs ist fehlgeschlagen: %1$s - Die Playlist „%1$s“ mit %2$d Videos wurde importiert Flow Kanal-Fehlerprotokoll Vielen Dank für eure Unterstützung! ❤️ Adresse für Spenden @@ -1506,8 +1471,6 @@ Füge Videos aus dem Videoplayer hinzu, um deine Playlist zusammenzustellen Playlist löschen? Dadurch werden „%1$s“ und alle darin enthaltenen Videos endgültig gelöscht. - Playlist • Privat • %1$d Videos - Playlist • Öffentlich • %1$d Videos Sortieroptionen für Playlists Hinzufügungsdatum (neueste) Hinzufügungsdatum (ältestes) @@ -1516,7 +1479,6 @@ Sie werden aus dieser Playlist entfernt. Sie werden aus „Später ansehen“ entfernt. Willkommen bei Flow - %1$d ausgewählt (%2$d weitere erforderlich) Was macht dir Spaß? Wähle mindestens %1$d Themen aus, um deinen Feed individuell anzupassen. Es fehlen noch %2$d. Gib einen Kanalnamen ein, um danach zu suchen @@ -1540,7 +1502,6 @@ Verwendet die zuletzt gewählte Einstellung oder den Codec des aktuellen Videos Laden Sie Dateien in mehreren Teilen herunter, um die maximale Geschwindigkeit zu erreichen. Parallele Threads - %1$d Threads pro Download Die Verwendung von mehr Threads kann die Geschwindigkeit erhöhen, führt jedoch möglicherweise zu einem höheren Akkuverbrauch und einer stärkeren Erwärmung des Geräts. Wählen Sie aus, wo die heruntergeladenen Dateien auf Ihrem Gerät gespeichert werden sollen. Voreingestellte Standorte @@ -1570,7 +1531,6 @@ Neuralprofil zurücksetzen? Dadurch werden folgende Daten dauerhaft gelöscht:\n\n\n\n• Alle gespeicherten Einstellungen\n\n• Der langfristige Persönlichkeitsvektor\n\n• Zeitkontextmuster\n\n• Kanal-Affinitätswerte\n\n\n\nIhr Feed wird in den Kalt-Start-Zustand zurückversetzt. Schau dir ein paar Videos an, um deinen Interessenhorizont zu erweitern! - %1$d Interaktionen • Stufe %2$d Explizit Playlist erstellen Name der Playlist @@ -1602,8 +1562,6 @@ Fans mögen auch %1$s • %2$s Aufrufe Alle anzeigen - %1$s Aufrufe - %1$d Titel • %2$s Keine Stimmungen und Genres verfügbar Aktuelle Künstler Speziell für dich zusammengestellt @@ -1629,7 +1587,6 @@ Community-Playlists Top-Ergebnis Playlist • %1$s - Künstler • %1$s monatliche Zuschauerzahl Top-Empfehlungen für Sie Es sind keine Titel verfügbar Organisiere deine Musik @@ -1637,7 +1594,6 @@ Erstelle deine erste Playlist, um deine Lieblings-Songs zu ordnen Noch keine Favoriten Tippe bei einem beliebigen Titel auf das Herz-Symbol, um ihn zu deinen Favoriten hinzuzufügen - %1$d Lieblings-Songs Hör dir Musik an, um hier deinen Verlauf anzuzeigen Noch keine Downloads Songs für die Offline-Wiedergabe herunterladen @@ -1660,7 +1616,6 @@ Abgeschlossen In der Warteschlange Unvollständige Downloads entfernen - Sollen %1$d angehaltene, fehlgeschlagene oder unvollständige Downloads entfernt werden? Abgeschlossene Downloads bleiben davon unberührt. Aus An Player Einstellungen @@ -1693,12 +1648,10 @@ Verwenden Sie diese Option, um Daten an ein Gerät ohne Kamera (z. B. einen Desktop-Computer) zu senden, auf dem ein Empfangs-Code angezeigt wird. Verwenden Sie diese Option, wenn dieses Gerät über eine Kamera verfügt und auf dem anderen Gerät ein Sendecode angezeigt wird. Im Besitz - %1$d Stunden Hintergrund Prüfungen sind beschränkt Android verbietet Flow im Hintergrund nach neuen Videos zu suchen, dadurch kommen Benachrichtigungen erst nach öffnen der App. Klicke hier um uneingeschränkte Hintergrundaktivitäten zuzulassen Wiedergabetempo beim gedrückthalten Wähle die Anzahl der Threads (1-8): - %1$d Threads Unterstützte die Flow Entwicklung Volle Transparenz wodurch dein Feed beeinflusst wird Lamge Videobeiträge und Dokumentationen sind deine Welt diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 325b04b96..2842a058f 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -178,8 +178,6 @@ Oscuro Personalizado Especial - %1$d temas - %1$d%2$s temas Aplicado: %1$s Personalizar temas Editor de temas personalizados @@ -232,7 +230,6 @@ Capítulos FLOW 9+ - %1$d videos seleccionados especialmente para ti Tu feed personal Importar copia de seguridad de NewPipe Buscar suscripciones @@ -241,8 +238,6 @@ Importando suscripciones desde la copia de seguridad de NewPipe... Vídeo Fijado por el creador - Actualizando %1$d de %2$d canales - Última actualización %1$s - %2$d vídeos comprobados Buscar en el historial de reproducción Todos los años Más recientes primero @@ -250,7 +245,6 @@ Prueba una nueva búsqueda o filtro Vídeos Shorts - Descargar los %1$d vídeos? Esto puede usar bastante almacenamiento. Las canciones que te gusten aparecerán aquí Sin coincidencias en el historial No hay vídeos que te gusten @@ -284,7 +278,6 @@ NOTAS DE VERSIÓN Comentario fijado Actualizar Flow - Ver %1$d respuestas Inicio Nueva actualización disponible Suscripciones @@ -306,15 +299,10 @@ Ver Artista Añadir a la cola Lista - %1$d vídeos - %1$d shorts - %1$d canciones - %1$d listas Alternar modo de visualización Aún no hay descargas Reproducir todo Quitar de Ver más tarde - Lista de reproducción • Privada • %1$d vídeos E Los vídeos que guardes para verlos más tarde aparecerán aquí No hay vídeos guardados @@ -425,14 +413,12 @@ Reanudar después del Rebuffer: %1$ds Mira este corto: https://youtu.be/%1$s Me gusta - %1$d oculto Agregar rápido Se enviará una notificación a la hora de inicio. Esta semana Duración Reiniciar Sugerencias de búsqueda - %1$d búsquedas Importar datos Importar desde NewPipe Importar historial de visualización @@ -805,7 +791,6 @@ Buscar Intereses Personaliza lo que ves - %1$d temas Bloqueado Tus intereses Los temas que has seleccionado ayudan a Flow a recomendar mejor contenido. Toque los temas a continuación para agregarlos o eliminarlos. @@ -823,8 +808,6 @@ Agregar tema Eliminar %1$s Desbloquear %1$s - %1$d seleccionado - %1$d tema%2$s Realice un seguimiento y controle su tiempo frente a la pantalla Las estadísticas se basan en tu historial de reproducciones en esta aplicación. El uso real puede variar. Herramientas para gestionar tu tiempo @@ -838,11 +821,9 @@ Hoy últimos 7 días Frecuencia - Cada %1$d minutos Total: %s horas Aún no hay datos de visualización Recordatorio de hora de dormir - Cada %1$d min Recordatorio de descanso Tome descansos regulares mientras mira Ventana de suspensión: @@ -852,7 +833,6 @@ Hora de despertarse Recibe una notificación cuando sea hora de dormir Confirmar - %1$d mínimo 5 minutos 120 minutos hora personalizada @@ -875,12 +855,9 @@ Tamaño máximo del historial Historial de eliminación automática Nunca eliminar automáticamente - Actualmente: %1$d búsquedas - Eliminar después de %1$d días Período de retención Borrar historial de búsqueda Eliminar todas las consultas de búsqueda - Eliminar búsquedas anteriores a %1$d días ¿Borrar historial de búsqueda? Eliminar permanentemente todo el historial de búsqueda. Elija cuántas búsquedas desea conservar: @@ -889,12 +866,9 @@ 1 semana 3 meses 1 año - %1$d días No se pudo importar la copia de seguridad de Flow: %1$s Copia de seguridad de Flow importada correctamente 6 meses - %1$d suscripciones importadas de YouTube - %1$d suscripciones importadas de NewPipe No se pudo importar la copia de seguridad de NewPipe: %1$s No se pudo importar la copia de seguridad de YouTube: %1$s Importar copia de seguridad de Flow @@ -916,8 +890,6 @@ Importe una lista de reproducción de música desde YouTube Music Takeout CSV. Aparece en Listas de reproducción de música. No se pudo importar el historial de reproducciones: %1$s Importar lista de reproducción de música de YouTube - Lista de reproducción importada “%1$s” con %2$d videos - Importaste %1$d entradas de tu historial de reproducciones de YouTube No se encontraron entradas del historial de reproducciones en este archivo. Asegúrate de que sea un archivo watch-history.html de YouTube Takeout. Configuración de descargas No se pudo importar la lista de reproducción: %1$s @@ -936,7 +908,6 @@ Hilos concurrentes Usar más hilos puede aumentar la velocidad, pero puede consumir más batería y calentar el dispositivo. Elija dónde se guardan los archivos descargados en su dispositivo. - %1$d hilos por descarga Ubicación personalizada Ubicaciones preestablecidas Descargas / Flow @@ -952,7 +923,6 @@ Activo Ahorrar Seleccionar número de hilos (1-8): - %1$d hilos Apoyo y donaciones Dirección copiada al portapapeles Si encuentra útil Flow y le gustaría apoyar su desarrollo, puede hacerlo en Patreon o donar a través de las direcciones criptográficas a continuación. ¡Tu apoyo ayuda a mantener vivo el proyecto! @@ -1001,15 +971,12 @@ Esta lista de reproducción está vacía ¿Eliminar lista de reproducción? Esto eliminará permanentemente \'%1$s\' y todos sus videos. - Lista de reproducción • Privada • %1$d vídeos - Lista de reproducción • Pública • %1$d vídeos Bienvenido a Fluir Cuéntanos en qué estás interesado Selecciona al menos 3 temas para personalizar tu experiencia Saltar por ahora Continuar Colapsar - %1$d seleccionados (%2$d más necesarios) Música Tecnología Entretenimiento @@ -1039,7 +1006,6 @@ Temas y canales bloqueados Temas ¡Mira algunos videos para poblar tu nebulosa de interés! - %1$d interacciones • Nivel %2$d Exportación de perfil neuronal de Flow Exportar datos de perfil Biblioteca de música @@ -1056,8 +1022,6 @@ Buscar Ver todo A los fans también les gusta - %1$s vistas - %1$d pistas • %2$s Error desconocido Rever Navegar @@ -1126,7 +1090,6 @@ Álbum • %1$s • %2$s Canciones Buscar: %1$s - Artista • %1$s audiencia mensual Artista: %1$s No hay pistas disponibles No se encontraron resultados @@ -1135,7 +1098,6 @@ Aún no hay listas de reproducción Crea tu primera lista de reproducción para organizar tus pistas favoritas Toca el ícono del corazón en cualquier pista para agregarla a tus favoritos - %1$d pistas favoritas Aún no hay historia Empieza a escuchar música para ver tu historial aquí Aún no hay descargas @@ -1265,7 +1227,6 @@ Agregar a mi lista de reproducción Sin informes de fallos: ¡genial! Añade todas las canciones a… - Se agregaron %1$d canciones a “%2$s” Líneas de título de vídeo Cuántas líneas mostrar para los títulos de los vídeos en el reproductor 1 linea @@ -1440,7 +1401,6 @@ Afinidad en vivo Los valores más altos se inclinan hacia videos más largos Amplitud del tema - %1$d temas en el vector global Ponderaciones de intereses Temas con mayor ponderación después de la libertad condicional y los controles de pruebas Patrones de tiempo @@ -1513,7 +1473,6 @@ Desbloquear controles Descargas incompletas Eliminar descargas incompletas - ¿Eliminar %1$d descargas pausadas, fallidas o parciales? Las descargas completadas no se modificarán. Actualizar suscripciones al inicio Cancelado Verifique su feed de suscripción cuando se abra la aplicación @@ -1536,21 +1495,17 @@ En vivo de tus suscripciones Ocultar Shorts de este canal Mostrar Shorts en el feed de suscripciones - Desplazamiento automático cada %1$d segundos Mostrar Shorts de este canal - %1$d segundos Desplazamiento automático después del tiempo personalizado Opciones de clasificación de listas de reproducción Manual %1$ds automático - %1$d me gusta Fecha agregada (más antigua) mas popular Fecha de publicación (más antigua) Fecha agregada (más reciente) Serán eliminados de esta lista de reproducción. Indicador de velocidad de reproducción - ¿Quitar %1$d vídeo(s)? Mostrar la velocidad actual en la superposición del reproductor de video Se eliminarán de Watch más tarde. Ancho completo @@ -1669,7 +1624,6 @@ 90% reproducido 95% reproducido 99% reproducido - %1$d segundos Siguiente vídeo Cancelar Reiniciar @@ -1733,8 +1687,6 @@ Contenedor terciario Sobre contenedor terciario Elige al menos %1$d temas para personalizar tu feed. Faltan %2$d. - Se agregaron %1$d canales - %1$d seleccionados Expira en %1$ds %1$d / %2$d Contenedor de error @@ -2006,7 +1958,6 @@ Hay una nueva versión de Flow disponible (%1$s). ¿Descargar el APK más reciente? I N S T R U M E N T A L La lista está vacía - Descargando %1$d vídeos… Lista guardada en la biblioteca Lista borrada de la biblioteca Descargando audio: %1$skbps %2$s @@ -2028,10 +1979,8 @@ Lista borrada Lista renombrada Iniciando descarga de %1$s… - %1$d pistas descargadas de %2$s No se pudo descargar la lista Error descargando la lista - %1$d pistas descargadas Agregado a la lista No se pudo agregar la pista Borrado de la lista @@ -2048,7 +1997,6 @@ La descarga falló +%1$d más Videos nuevos - %1$d videos nuevos de tus suscripciones Actualización disponible: %1$s Pulsa para actualizar a la última versión. Recordatorio de \"Ver más tarde\" @@ -2286,7 +2234,6 @@ Gestiona tus copias de seguridad de Flow Servicios externos Importar desde otros clientes de YouTube - Importados %1$d %2$s %1$s importado correctamente Importando %1$s… Importado desde Google Takeout @@ -2311,7 +2258,6 @@ Sus últimos vídeos no aparecen en este feed: %1$s %1$s y %2$d más Editado - %1$d horas Las verificaciones en segundo plano están restringidas Android impide que Flow busque videos nuevos mientras está cerrada, por lo que las alertas solo llegarán al abrir la aplicación. Toca para permitir la actividad en segundo plano sin restricciones. Original @@ -2327,7 +2273,6 @@ Formato de respaldo no reconocido; asegúrate de haber seleccionado el archivo correcto Error de importación: %1$s %1$d hr %2$d min - %1$d min %1$d h %1$dm Quitar de la cola @@ -2358,7 +2303,6 @@ Fusiona la librería de otro dispositivo en esta. Seleccionar todo Limpiar - %1$d de %2$d seleccionados Tus listas de reproducción, álbumes y Ver Luego. Qué has visto y dónde los has dejado. Likes y dislikes en vídeos y música. diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index a01a170c2..84c402ee2 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -60,7 +60,6 @@ Vaatamiste ajalugu on tühi Sinu vaadatud videod saavad olema siin näha Laadi kõik alla - Kas laadid alla kõik %1$d videot? See võib hõivata märgatava osa andmeruumist. Salvestatud ESITAMISEL JÄRGMISENA Lisavalikud @@ -143,7 +142,6 @@ Esitusrežiimi soovitus Selle video kestus jääb alla 2 minuti. Kas tahaksid kasutada asjakohast esitusvaadet? Lühivideote esitaja - %1$d lühivideot Lühivideod Lühivideoid ei leidu Ära kasuta lühivideote esitajajat @@ -217,7 +215,6 @@ Sulge meediaesitaja %1$s vaatamist Sinu isiklik sisuvoog - %1$d videot valitud just sinu jaoks Impordi NewPipe\'i varukoopia Impordin tellimusi NewPipe\'i varukoopiast… Otsi tellimusi @@ -227,17 +224,10 @@ Muuda gruppi Kustuta grupp Grupi nimi - %1$d videot - %1$d esitusloendit - %1$d lugu Allalaadimisi veel pole Esita kõik Eemalda hilisemate vaatamiste loendist - Esitusloend • Privaatne • %1$d videot - Uuendan kanaleid: %1$d / %2$d - Viimati uuendatud %1$s - %2$d videot on kontrollitud Esilinastus %1$s - Vaata %1$d vastust VERSIOONI MÄRKUSED Otsi kanaleid… Ühtegi videot pole salvestatud diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index ba873b198..4161f5a47 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -157,7 +157,6 @@ Lire la suite Répondre Masquer les réponses - Voir %1$d réponses Mise à jour disponible %1$s est maintenant disponible @@ -196,18 +195,13 @@ FLOW 9+ Votre fil personnalisé - %1$d vidéos sélectionnées rien que pour vous Importer la sauvegarde NewPipe Importation des abonnements depuis la sauvegarde NewPipe... Rechercher des Abonnements Changer de mode d\'affichage Désabonné de %1$s - %1$d vidéos - %1$d playlists - %1$d shorts Tout lire Retirer de À regarder plus tard - Playlist • Privée • %1$d vidéos E Aucune vidéo enregistrée Les vidéos que vous enregistrez pour les regarder plus tard apparaîtront ici @@ -318,8 +312,6 @@ Clair Sombre Spécial - %1$d thèmes - %1$d thèmes %2$s Appliqué : %1$s Apparence du Lecteur @@ -486,8 +478,6 @@ Personnalisez ce que vous voyez Intérêts Bloqués - %1$d sujets - %1$d masqués Vos Intérêts Les thèmes que vous avez sélectionnés aident Flow à vous recommander des contenus plus pertinents. Appuyez sur les thèmes ci-dessous pour en ajouter ou en supprimer. Actuellement Suivis @@ -503,10 +493,8 @@ Ajout rapide Sujets courants à bloquer Actuellement Bloqués - %1$d sujet%2$s Supprimer %1$s Débloquer %1$s - %1$d sélectionnés Gestion du temps Les statistiques sont basées sur votre historique de visionnage dans cette application. L\'utilisation réelle peut varier. @@ -517,12 +505,10 @@ Une notification sera envoyée à l\'heure de début. Me rappeler de faire une pause Fréquence des rappels - Toutes les %1$d min Moyenne Quotidienne Aujourd\'hui 7 derniers jours Fréquence - Toutes les %1$d minutes Recherche & Historique Enregistrer l\'historique de recherche @@ -530,32 +516,25 @@ Suggestions de recherche Afficher les suggestions pendant la saisie Taille Max de l\'Historique - Actuellement : %1$d recherches Suppression auto. de l\'historique - Supprimer après %1$d jours Ne jamais supprimer automatiquement Période de conservation - Supprimer les recherches plus anciennes que %1$d jours Effacer l\'historique de recherche Supprimer toutes les requêtes de recherche Effacer l\'Historique de Recherche ? Supprimer définitivement tout l\'historique de recherche. Choisissez combien de recherches conserver : - %1$d recherches Supprimer les recherches plus anciennes que : 1 semaine 1 mois 3 mois 6 mois 1 an - %1$d jours Importer des données Sauvegarde Flow importée avec succès Échec de l\'importation de la sauvegarde Flow : %1$s - %1$d abonnements importés depuis NewPipe Échec de l\'importation de la sauvegarde NewPipe : %1$s - %1$d abonnements importés depuis YouTube Échec de l\'importation de la sauvegarde YouTube : %1$s Importer une sauvegarde Flow Restaurez votre historique, vos paramètres et vos abonnements depuis un fichier de sauvegarde Flow. @@ -581,7 +560,6 @@ Téléchargement parallèle Télécharger les fichiers en plusieurs parties pour une vitesse maximale. Threads concurrentiels - %1$d threads par téléchargement Utiliser plus de threads peut augmenter la vitesse mais peut utiliser plus de batterie et chauffer l\'appareil. Choisissez où les fichiers téléchargés sont enregistrés sur votre appareil. Emplacements prédéfinis @@ -600,7 +578,6 @@ Recommandé Actif Sélectionnez le nombre de threads (1-8) : - %1$d threads Soutien et dons Soutenir le développement de Flow @@ -653,13 +630,10 @@ Ajoutez des vidéos depuis le lecteur vidéo\npour construire votre playlist Supprimer la playlist ? Cela supprimera définitivement \'%1$s\' et toutes ses vidéos. - Playlist • Privée • %1$d vidéos - Playlist • Publique • %1$d vidéos Bienvenue dans Flow Dites-nous ce qui vous intéresse Sélectionnez au moins 3 sujets pour personnaliser votre expérience - %1$d sélectionnés (%2$d de plus nécessaires) Passer pour l\'instant Continuer Réduire @@ -698,7 +672,6 @@ Interactions Sujets Regardez quelques vidéos pour remplir votre nébuleuse d\'intérêts ! - %1$d interactions • Niveau %2$d Exporter les données de profil Exportation du Profil Neural de Flow @@ -717,8 +690,6 @@ %1$s • %2$s vues Voir tout Rechercher - %1$s vues - %1$d pistes • %2$s Erreur inconnue Réessayer Aucune humeur & genre disponible @@ -798,7 +769,6 @@ Playlist • %1$s • %1$s lectures Album • %1$s • %2$s - Artiste • %1$s audience mensuelle Recherche : %1$s Artiste : %1$s Nos meilleures suggestions pour vous @@ -811,7 +781,6 @@ Créez votre première playlist pour organiser vos morceaux préférés Aucun Favoris Pour l\'Instant Appuyez sur l\'icône de cœur sur n\'importe quelle piste pour l\'ajouter à vos favoris - %1$d morceaux favoris Aucun Historique Pour l\'Instant Commencez à écouter de la musique pour voir votre historique ici Aucun Téléchargement Pour l\'Instant @@ -887,7 +856,6 @@ Nom du groupe Pas encore de groupes. Créez-en un pour filtrer vos recommandations. Recherche de chaînes… - %1$d titres Fin de la file d\'attente Rechercher dans la chaîne Rechercher dans la chaîne @@ -1141,7 +1109,6 @@ Retour Plus d\'options Durée - %1$d min 5 min 120 min Heure personnalisée @@ -1172,9 +1139,7 @@ Importez une playlist à partir d\'un fichier CSV YouTube Takeout (Playlist-<nom>.csv). Importer une playlist YouTube Music Importez une playlist depuis un fichier CSV YouTube Music Takeout. Elle apparaîtra dans la section « Playlists ». - Importation de %1$d éléments depuis votre historique de visionnage YouTube Échec de l\'importation de l\'historique de visionnage : %1$s - Playlist « %1$s » importée, contenant %2$d vidéos Échec de l\'importation de la playlist : %1$s Aucune entrée d\'historique de visionnage n\'a été trouvée dans ce fichier. Vérifiez qu\'il s\'agit bien d\'un fichier « watch-history.html » issu de YouTube Takeout. Aucune vidéo n\'a été trouvée dans ce fichier CSV. Vérifiez qu\'il s\'agit bien d\'un fichier CSV de playlist YouTube Takeout. @@ -1262,9 +1227,7 @@ Le rapport a été copié dans le presse-papiers Ajouter à ma playlist Ajouter tous les titres à… - %1$d titres ont été ajoutés à « %2$s » Tout télécharger - Télécharger les %1$d vidéos ? Cela risque de prendre beaucoup d\'espace de stockage. Enregistré Le plus ancien Le titre a été copié dans le presse-papiers @@ -1441,7 +1404,6 @@ Affinité en direct La part de contenu en direct qui correspond au profil Étendue du sujet - %1$d sujets dans le vecteur global Pondérations des taux d\'intérêt Sujets les plus importants après la période d\'essai et la vérification des antécédents Aucune pondération des sujets n\'a encore été définie. @@ -1512,13 +1474,10 @@ Téléchargements incomplets Annulé Supprimer les téléchargements incomplets - Souhaitez-vous supprimer %1$d téléchargements en pause, ayant échoué ou partiels ? Les téléchargements terminés ne seront pas affectés. Commandes de verrouillage Commandes de déverrouillage Bouton de verrouillage Afficher un bouton de verrouillage du lecteur pour empêcher les touches accidentelles - Actualisation de %1$d chaînes sur %2$d - Dernière mise à jour le %1$s - %2$d vidéos vérifiées Aperçu des commentaires Afficher le dernier commentaire dans la carte des commentaires Actualiser les abonnements au démarrage @@ -1547,8 +1506,6 @@ Masquer les Shorts de cette chaîne Afficher les Shorts de cette chaîne Défilement automatique après une durée personnalisée - Défilement automatique toutes les %1$d secondes - %1$d secondes Auto %1$ds Consulter l\'historique des recherches Tous les ans @@ -1559,7 +1516,6 @@ Aucune vidéo aimée Aucune musique préférée Les titres que vous aimez s\'afficheront ici - %1$d mentions « J\'aime » Options de tri des playlists Manuel Date d\'ajout (la plus récente) @@ -1567,7 +1523,6 @@ Les plus populaires Date de publication (la plus récente) Date de publication (la plus ancienne) - Supprimer %1$d vidéo(s) ? Ils seront supprimés de cette playlist. Ils seront supprimés de la playlist « À regarder plus tard ». Indicateur de vitesse de lecture @@ -1722,7 +1677,6 @@ Affichez les commandes de lecture avant la fin du chargement de la vidéo afin de pouvoir régler le volume immédiatement Délai de lecture automatique Aucun (changer immédiatement) - %1$d secondes Affichez un compte à rebours avant de passer automatiquement à la vidéo suivante. Pendant le compte à rebours, vous pouvez relancer la vidéo en cours, annuler le passage à la suivante ou lancer immédiatement la vidéo suivante. À suivre Vidéo suivante @@ -1847,14 +1801,12 @@ Recherche de chaînes… Saisissez le nom d\'une chaîne pour lancer la recherche Aucune chaîne trouvée pour « %1$s » - %1$d chaînes ajoutées %1$s abonnés Abonné S\'abonner Importez vos données Importez vos abonnements et votre historique depuis d\'autres applications. Tout est facultatif. Sauvegarde & Restauration - %1$d sélectionnés Sélectionné Non sélectionné Échec de l\'importation : %1$s @@ -2053,7 +2005,6 @@ Égaliseur Enregistrer le préréglage Nom du préréglage - Téléchargement de %1$d vidéos… Playlist enregistrée dans la bibliothèque Playlist supprimée de la bibliothèque Téléchargement du fichier audio : %1$skbps %2$s @@ -2075,10 +2026,8 @@ Playlist supprimée Playlist renommée Début du téléchargement de %1$s… - %1$d titres téléchargés depuis %2$s Échec du téléchargement de la playlist Erreur lors du téléchargement de la playlist - %1$d titres téléchargés Ajouté à la playlist Échec de l\'ajout du titre Supprimé de la playlist @@ -2095,7 +2044,6 @@ Échec du téléchargement +%1$d de plus Nouvelles vidéos - %1$d nouvelles vidéos issues de vos abonnements Mise à jour disponible : %1$s Appuyez ici pour effectuer la mise à jour vers la dernière version. Rappel « À regarder plus tard » @@ -2260,7 +2208,6 @@ Gérer vos sauvegardes Flow Services externes Importer depuis d\'autres clients YouTube - %1$d %2$s importé Vos shorts enregistrés Joué dans Flow A-EDev @@ -2360,11 +2307,9 @@ %1$s et %2$d de plus modifié %1$s (%2$s) - %1$d heures Original Surnommé %1$d h %2$d min - %1$d min %1$dh %1$dm Aucun court métrage enregistré pour l\'instant @@ -2429,5 +2374,4 @@ Fusionner la bibliothèque d\'un autre appareil avec celle-ci. Tout sélectionner Effacer - %1$d sur %2$d sélectionnés diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 211db73d5..bb4f978bf 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -161,7 +161,6 @@ और पढ़ें जवाब जवाब छुपाएँ - %1$d जवाब देखें नया अपडेट उपलब्ध %1$s अब उपलब्ध है रिलीज़ नोट्स @@ -202,20 +201,14 @@ FLOW 9+ आपकी व्यक्तिगत फ़ीड - आपके लिए %1$d वीडियो चुने गए न्यूपाइप बैकअप आयात करें NewPipe बैकअप से सब्सक्रिप्शनें इंपोर्ट की जा रही हैं..। सब्सक्रिप्शनस खोजें दृश्य मोड टॉगल करें %1$s से अनसब्सक्राइब किया - %1$d वीडियो - %1$d प्लेलिस्ट - %1$d शॉर्ट्स - %1$d गाने अभी तक कोई डाउनलोड नहीं सभी चलाएँ बाद में देखें सूची से हटाएं - प्लेलिस्ट • निजी • %1$d वीडियो अश्लील कोई वीडियो सहेजा नहीं गया बाद में देखने के लिए सहेजे गए वीडियो यहाँ दिखेंगे @@ -352,8 +345,6 @@ हल्का गहरा विशेष - %1$d थीम - %1$d %2$s थीम लागू किया गया: %1$s लॉन्चर आइकन शैली चुनें। परिवर्तन तुरंत प्रभावी होगा और लॉन्चर संक्षेप में ताज़ा होगा। ⚠ ध्यान दें: आइकन बदलने पर Android सिस्टम तंत्र का उपयोग होता है जो होम स्क्रीन से ऐप शॉर्टकट को अस्थायी रूप से हटा सकता है। यदि आवश्यक हो तो इसे वापस जोड़ने के लिए लॉन्चर को लंबे समय तक दबाएँ। @@ -642,8 +633,6 @@ आप जो देखते हैं उसे अनुकूलित करें रुचियाँ अवरुद्ध - %1$d विषय - %1$d छिपा हुआ आपकी रुचियाँ आपके द्वारा चुने गए विषय फ्लो को बेहतर सामग्री अनुशंसित करने में मदद करते हैं। विषयों को जोड़ने या हटाने के लिए नीचे टैप करें। वर्तमान में फॉलो कर रहे हैं @@ -659,10 +648,8 @@ त्वरित जोड़ें ब्लॉक करने के लिए सामान्य विषय वर्तमान में अवरुद्ध - %1$d विषय%2$s %1$s हटाएँ %1$s अनब्लॉक करें - %1$d चयनित समय प्रबंधन अपने स्क्रीन समय को ट्रैक और नियंत्रित करें आँकड़े इस ऐप में आपके देखने के इतिहास पर आधारित हैं। वास्तविक उपयोग भिन्न हो सकता है। @@ -673,12 +660,10 @@ प्रारंभ समय पर एक सूचना भेजी जाएगी। मुझे ब्रेक लेने की याद दिलाएँ अनुस्मारक आवृत्ति - प्रत्येक %1$d मिनट दैनिक औसत आज पिछले 7 दिन आवृत्ति - प्रत्येक %1$d मिनट में इस सप्ताह कुल: %s घंटे अभी तक कोई देखने का डेटा नहीं @@ -694,7 +679,6 @@ पुष्टि करें स्लीप टाइमर अवधि - %1$d मिनट 5 मिनट 120 मिनट कस्टम समय @@ -716,31 +700,24 @@ खोज सुझाव टाइप करते समय सुझाव दिखाएँ अधिकतम इतिहास आकार - वर्तमान में: %1$d खोजें स्वतः इतिहास हटाएँ - %1$d दिनों के बाद हटाएँ स्वतः कभी न हटाएँ अवधारण अवधि - %1$d दिनों से पुरानी खोजें हटाएँ खोज इतिहास साफ़ करें सभी खोज क्वेरी हटाएँ खोज इतिहास साफ़ करें? सभी खोज इतिहास स्थायी रूप से हटाएँ। चुनें कि कितनी खोजें रखनी हैं: - %1$d खोजें इससे पुरानी खोजें हटाएँ: 1 सप्ताह 1 महीना 3 महीने 6 महीने 1 वर्ष - %1$d दिन डेटा आयात करें फ्लो बैकअप सफलतापूर्वक आयात किया गया फ्लो बैकअप आयात करने में विफल: %1$s - NewPipe से %1$d सब्सक्रिप्शनस इंपोर्ट की गईं न्यूपाइप बैकअप आयात करने में विफल: %1$s - YouTube से %1$d सब्सक्रिप्शनें इंपोर्ट की गई यूट्यूब बैकअप आयात करने में विफल: %1$s फ्लो बैकअप आयात करें Flow बैकअप फ़ाइल से अपना इतिहास, सेटिंग्स और सब्सक्रिप्शनस पुनर्स्थापित करें। @@ -762,9 +739,7 @@ यूट्यूब टेकआउट CSV (Playlist-<name>.csv) से एक प्लेलिस्ट आयात करें। यूट्यूब म्यूजिक प्लेलिस्ट आयात करें यूट्यूब म्यूजिक टेकआउट CSV से एक संगीत प्लेलिस्ट आयात करें। संगीत प्लेलिस्ट के अंतर्गत दिखाई देगी। - आपके यूट्यूब देखने के इतिहास से %1$d प्रविष्टियाँ आयात की गईं देखने का इतिहास आयात करने में विफल: %1$s - प्लेलिस्ट \"%1$s\" %2$d वीडियो के साथ आयात की गई प्लेलिस्ट आयात करने में विफल: %1$s इस फ़ाइल में देखने के इतिहास की कोई प्रविष्टि नहीं मिली। सुनिश्चित करें कि यह यूट्यूब टेकआउट watch-history.html फ़ाइल है। इस CSV में कोई वीडियो नहीं मिला। सुनिश्चित करें कि यह यूट्यूब टेकआउट प्लेलिस्ट CSV फ़ाइल है। @@ -783,7 +758,6 @@ समानांतर डाउनलोडिंग अधिकतम गति के लिए फ़ाइलों को कई भागों में डाउनलोड करें। समवर्ती थ्रेड्स - प्रति डाउनलोड %1$d थ्रेड अधिक थ्रेड का उपयोग करने से गति बढ़ सकती है लेकिन बैटरी अधिक उपयोग हो सकती है और डिवाइस गर्म हो सकता है। चुनें कि डाउनलोड की गई फ़ाइलें आपके डिवाइस पर कहाँ सहेजी जाएँ। पूर्वनिर्धारित स्थान @@ -802,7 +776,6 @@ अनुशंसित सक्रिय थ्रेड्स की संख्या चुनें (1-8): - %1$d थ्रेड सहायता और दान फ्लो विकास का समर्थन करें यदि आप फ्लो को उपयोगी पाते हैं और इसके विकास का समर्थन करना चाहते हैं, तो आप निम्न पतों पर दान कर सकते हैं। आपका समर्थन परियोजना को जीवित रखने में मदद करता है! @@ -857,12 +830,9 @@ अपनी प्लेलिस्ट बनाने के लिए\nवीडियो प्लेयर से वीडियो जोड़ें प्लेलिस्ट हटाएँ? यह \'%1$s\' और उसके सभी वीडियो को स्थायी रूप से हटा देगा। - प्लेलिस्ट • निजी • %1$d वीडियो - प्लेलिस्ट • पब्लिक • %1$d वीडियोज फ्लो में आपका स्वागत है हमें बताएँ कि आप किस चीज़ में रुचि रखते हैं अपने अनुभव को निजीकृत करने के लिए कम से कम 3 विषय चुनें - %1$d चयनित (%2$d और चाहिए) अभी के लिए छोड़ें जारी रखें संक्षिप्त करें @@ -899,7 +869,6 @@ अंतःक्रियाएँ विषय अपने इंटरेस्ट नेबुला को आबाद करने के लिए कुछ वीडियो देखें! - %1$d अंतःक्रियाएँ • स्तर %2$d प्रोफ़ाइल डेटा निर्यात करें फ्लो तंत्रिका प्रोफ़ाइल निर्यात संगीत लाइब्रेरी @@ -917,8 +886,6 @@ %1$s • %2$s विऊज़ सभी देखें खोजें - %1$s विऊज़ - %1$d ट्रैक • %2$s अज्ञात त्रुटि पुनः प्रयास करें कोई मूड और शैली उपलब्ध नहीं @@ -993,7 +960,6 @@ प्लेलिस्ट • %1$s • %1$s बार चला एल्बम • %1$s • %2$s - कलाकार • %1$s मासिक श्रोता खोज: %1$s कलाकार: %1$s आपके लिए शीर्ष चयन @@ -1005,7 +971,6 @@ अपने पसंदीदा ट्रैक व्यवस्थित करने के लिए अपनी पहली प्लेलिस्ट बनाएँ अभी तक कोई पसंदीदा नहीं किसी भी ट्रैक पर दिल का आइकन टैप करके उसे अपने पसंदीदा में जोड़ें - %1$d पसंदीदा ट्रैक अभी तक कोई इतिहास नहीं अपना इतिहास यहाँ देखने के लिए संगीत सुनना शुरू करें अभी तक कोई डाउनलोड नहीं @@ -1135,7 +1100,6 @@ प्लेलिस्ट या \'बाद में देखें\' कतार में अगला वीडियो स्वचालित रूप से चलाएं। बंद होने पर भी, आप मैन्युअली स्किप कर सकते हैं। ऑटोप्ले डिलेअ कोई नहीं (तुरंत स्विच करें) - %1$d सेकंड अगले वीडियो पर अपने आप स्विच होने से पहले काउंटडाउन दिखाएं। काउंटडाउन के दौरान आप मौजूदा वीडियो को फिर से शुरू कर सकते हैं, स्विच रद्द कर सकते हैं, या अगला वीडियो तुरंत चला सकते हैं। आगे है अगला वीडियो @@ -1147,8 +1111,6 @@ डिफ़ॉल्ट नाम (A-Z) हाल ही में अपडेट - %2$d में से %1$d चैनल रिफ्रेश किए जा रहे हैं - अंतिम रिफ्रेश %1$s - %2$d वीडियो चेक किए गए अंतिम रिफ्रेश %1$s लॉग कॉपी करें लॉग कॉपी किए गए @@ -1177,7 +1139,6 @@ स्थानीय वीडियो स्थानीय संगीत सभी डाउनलोड करें - सभी %1$d वीडियो डाउनलोड करें? इसमें काफ़ी स्टोरेज लग सकती है। प्लेलिस्ट बनाएं प्लेलिस्ट बनाने का मेनू बंद करें लाइब्ररी में जोड़ें diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 9230f3753..6dae27d03 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -43,9 +43,6 @@ Lihat Artis Lihat Album Artis - %1$d video - %1$d lagu - %1$d shorts E HD 4K @@ -124,8 +121,6 @@ Terang Gelap Spesial - %1$d tema - %1$d tema %2$s Ikon diperbarui - launcher Anda akan disegarkan Flow Merah AMOLED Gelap @@ -173,7 +168,6 @@ Konten yang Anda sukai akan muncul di sini Diunduh Unduh semua - Unduh semua %1$d video? Ini mungkin menggunakan ruang penyimpanan yang cukup besar. Disimpan SELANJUTNYA TERKAIT @@ -269,7 +263,6 @@ Baca selengkapnya Balas Sembunyikan balasan - Lihat %1$d balasan Muat lebih banyak balasan Pilih Teks Komentar yang disematkan @@ -297,7 +290,6 @@ Bab Daftar Putar Umpan personal Anda - %1$d video yang dikurasi khusus untuk Anda Impor Cadangan NewPipe Mengimpor langganan dari cadangan NewPipe... Cari Langganan @@ -311,11 +303,9 @@ Cari saluran… Alihkan Mode Tampilan Berhenti berlangganan dari %1$s - %1$d daftar putar Belum ada unduhan Putar semua Hapus dari Tonton Nanti - "Daftar putar - Pribadi - %1$d video" Tidak ada video yang disimpan Video yang Anda simpan untuk ditonton nanti akan muncul di sini Cari @@ -790,8 +780,6 @@ Sesuaikan apa yang Anda lihat Minat Diblokir - %1$d topik - %1$d disembunyikan Minat Anda Topik yang Anda pilih membantu Flow merekomendasikan konten yang lebih baik. Ketuk topik di bawah untuk menambah atau menghapusnya. Sedang Diikuti @@ -807,10 +795,8 @@ Tambah Cepat Topik umum untuk diblokir Sedang Diblokir - %1$d topik%2$s Hapus %1$s Buka blokir %1$s - %1$d dipilih Manajemen waktu Lacak dan kendalikan waktu layar Anda Statistik didasarkan pada riwayat tontonan Anda di aplikasi ini. Penggunaan sebenarnya mungkin berbeda. @@ -821,12 +807,10 @@ Notifikasi akan dikirim pada waktu mulai. Ingatkan saya untuk beristirahat Frekuensi pengingat - Setiap %1$d menit Rata-rata Harian Hari ini 7 hari terakhir Frekuensi - Setiap %1$d menit Minggu Ini Total: %s jam Belum ada data tontonan @@ -842,7 +826,6 @@ Konfirmasi Timer Tidur Durasi - %1$d menit 5 menit 120 menit Waktu kustom @@ -864,31 +847,24 @@ Saran Pencarian Tampilkan saran saat mengetik Ukuran Riwayat Maksimum - Saat ini: %1$d pencarian Hapus Otomatis Riwayat - Hapus setelah %1$d hari Jangan pernah hapus otomatis Periode Penyimpanan - Hapus pencarian yang lebih lama dari %1$d hari Hapus Riwayat Pencarian Hapus semua kueri pencarian Hapus Riwayat Pencarian? Hapus permanen semua riwayat pencarian. Pilih berapa banyak pencarian yang disimpan: - %1$d pencarian Hapus pencarian yang lebih lama dari: 1 minggu 1 bulan 3 bulan 6 bulan 1 tahun - %1$d hari Impor Data Cadangan Flow berhasil diimpor Gagal mengimpor cadangan Flow: %1$s - Berhasil mengimpor %1$d langganan dari NewPipe Gagal mengimpor cadangan NewPipe: %1$s - Berhasil mengimpor %1$d langganan dari YouTube Gagal mengimpor cadangan YouTube: %1$s Impor Cadangan Flow Pulihkan riwayat, pengaturan, dan langganan Anda dari file cadangan Flow. @@ -924,9 +900,7 @@ Impor daftar putar dari CSV YouTube Takeout (Playlist-<nama>.csv). Impor Daftar Putar YouTube Music Impor daftar putar musik dari CSV YouTube Music Takeout. Muncul di bawah Daftar Putar Musik. - Berhasil mengimpor %1$d entri dari riwayat tontonan YouTube Anda Gagal mengimpor riwayat tontonan: %1$s - Berhasil mengimpor daftar putar \"%1$s\" dengan %2$d video Gagal mengimpor daftar putar: %1$s Tidak ada entri riwayat tontonan yang ditemukan dalam file ini. Pastikan file tersebut adalah file watch-history.html dari YouTube Takeout. Tidak ada video yang ditemukan dalam CSV ini. Pastikan file tersebut adalah file CSV daftar putar YouTube Takeout. @@ -955,7 +929,6 @@ Unduhan Paralel Unduh file dalam beberapa bagian untuk kecepatan maksimal. Thread Bersamaan - %1$d thread per unduhan Menggunakan lebih banyak thread dapat meningkatkan kecepatan tetapi mungkin menggunakan lebih banyak baterai dan membuat perangkat panas. Pilih tempat penyimpanan file yang diunduh di perangkat Anda. Lokasi Prasetel @@ -974,7 +947,6 @@ Direkomendasikan Aktif Pilih jumlah thread (1-8): - %1$d thread Dukungan & Donasi Dukung Pengembangan Flow Jika Anda merasa Flow bermanfaat dan ingin mendukung pengembangannya, Anda dapat mendukungnya di Patreon atau berdonasi melalui alamat kripto di bawah. Dukungan Anda membantu menjaga proyek ini tetap hidup! @@ -1030,12 +1002,9 @@ Tambahkan video dari pemutar video\nuntuk membangun daftar putar Anda Hapus daftar putar? Ini akan menghapus secara permanen \'%1$s\' beserta semua videonya. - "Daftar putar - Pribadi - %1$d video" - "Daftar putar - Publik - %1$d video" Selamat Datang di Flow Ceritakan apa yang Anda minati Pilih minimal 3 topik untuk mempersonalisasi pengalaman Anda - %1$d dipilih (%2$d lagi diperlukan) Lewati untuk sekarang Lanjutkan Ciutkan @@ -1073,7 +1042,6 @@ Interaksi Topik Tonton beberapa video untuk mengisi nebula minat Anda! - "%1$d interaksi - Level %2$d" Ekspor Data Profil Ekspor Profil Neural Flow Pustaka Musik @@ -1093,8 +1061,6 @@ "%1$s - %2$s penayangan" Lihat semua Cari - %1$s penayangan - "%1$d lagu - %2$s" Kesalahan tidak diketahui Coba Lagi Tidak ada suasana & genre yang tersedia @@ -1169,7 +1135,6 @@ "Daftar putar - %1$s" "- %1$s pemutaran" "Album - %1$s - %2$s" - "Artis - %1$s pendengar bulanan" Pencarian: %1$s Artis: %1$s Pilihan Terbaik untuk Anda @@ -1181,7 +1146,6 @@ Buat daftar putar pertama Anda untuk mengatur lagu favorit Belum Ada Favorit Ketuk ikon hati pada lagu mana saja untuk menambahkannya ke favorit Anda - %1$d lagu favorit Belum Ada Riwayat Mulai mendengarkan musik untuk melihat riwayat Anda di sini Belum Ada Unduhan @@ -1367,7 +1331,6 @@ Laporan disalin ke papan klip Tambahkan ke daftar putar saya Tambahkan semua lagu ke… - %1$d lagu ditambahkan ke \"%2$s\" Belum ada daftar putar. Buat satu terlebih dahulu! Profil berhasil diekspor Ekspor gagal @@ -1403,7 +1366,6 @@ Afinitas siaran langsung Seberapa cocok konten siaran langsung dengan profil Keluasan topik - %1$d topik dalam vektor global Bobot Minat Topik dengan bobot tertinggi setelah pemeriksaan probasi dan bukti Belum ada bobot topik. @@ -1463,8 +1425,6 @@ Profil Sekarang Skor - Menyegarkan %1$d dari %2$d channel - Terakhir disegarkan %1$s - %2$d video diperiksa Cari riwayat tonton Semua tahun Terbaru terlebih dahulu @@ -1478,7 +1438,6 @@ Lagu yang Anda sukai akan muncul di sini Sembunyikan Shorts dari channel ini Tampilkan Shorts dari channel ini - %1$d suka Tema Default Sistem Pilih tema yang digunakan saat perangkat Anda beralih antara mode terang dan gelap. Tema mode terang @@ -1505,8 +1464,6 @@ Urutan tab dan default Gunakan panah untuk menyusun ulang tab. Pilih tab default dengan tombol radio. Gulir otomatis setelah waktu kustom - Gulir otomatis setiap %1$d detik - %1$d detik Opsi urut playlist Manual Tanggal ditambahkan (terbaru) @@ -1514,14 +1471,12 @@ Paling populer Tanggal dipublikasikan (terbaru) Tanggal dipublikasikan (terlama) - Hapus %1$d video? Video akan dihapus dari playlist ini. Video akan dihapus dari Tonton nanti. Otomatis %1$ds Unduhan belum selesai Dibatalkan Hapus unduhan yang belum selesai - Hapus %1$d unduhan yang dijeda, gagal, atau sebagian? Unduhan yang sudah selesai tidak akan diubah. Kunci kontrol Buka kunci kontrol Tombol Mode Kunci @@ -1678,7 +1633,6 @@ Tampilkan kontrol pemutar sebelum video selesai memuat sehingga Anda dapat menyesuaikan volume segera Jeda putar otomatis Nihil (langsung ganti) - %1$d detik Tampilkan hitungan mundur sebelum secara otomatis beralih ke video berikutnya. Selama hitungan mundur Anda dapat me-restart video saat ini, membatalkan saklar, atau memutar yang berikutnya segera. Berikutnya Video selanjutnya @@ -1809,14 +1763,12 @@ Cari channel… Ketik nama channel untuk mencari Tidak ada channel yang ditemukan untuk \"%1$s\" - %1$d channel ditambahkan %1$s subscriber Sudah subscribe Subscribe Impor data Anda Bawa subscription dan riwayat Anda dari aplikasi lain. Semuanya bersifat opsional. Backup & Restore - %1$d dipilih Dipilih Tidak dipilih Impor gagal: %1$s @@ -2168,7 +2120,6 @@ Versi baru Flow tersedia (%1$s). Unduh APK terbaru? I N S T R U M E N T A L Playlist kosong - Mengunduh %1$d video… Playlist disimpan ke koleksi Playlist dihapus dari koleksi Mengunduh audio: %1$skbps %2$s @@ -2190,10 +2141,8 @@ Playlist dihapus Playlist diubah namanya Memulai unduhan untuk %1$s… - Mengunduh %1$d trek dari %2$s Gagal mengunduh playlist Kesalahan saat mengunduh playlist - Mengunduh %1$d trek Ditambahkan ke playlist Gagal menambahkan trek Dihapus dari playlist @@ -2210,7 +2159,6 @@ Unduhan gagal +%1$d lainnya Video baru - %1$d video baru dari langganan Anda Pembaruan Tersedia: %1$s Ketuk untuk memperbarui ke versi terbaru. Pengingat Tonton Nanti @@ -2281,7 +2229,6 @@ Kelola cadangan Flow Anda Layanan Eksternal Impor dari klien YouTube lain - Mengimpor %1$d %2$s %1$s berhasil diimpor Mengimpor %1$s… Diimpor dari Google Takeout @@ -2309,7 +2256,6 @@ diedit %1$s (%2$s) ...lebih lanjut - %1$d jam Pemeriksaan latar belakang dibatasi Android memblokir Flow untuk memeriksa video baru saat aplikasi ditutup, sehingga peringatan hanya muncul saat Anda membuka aplikasi. Ketuk untuk mengizinkan aktivitas latar belakang tanpa batasan. Kami akan menampilkan lebih banyak seperti ini @@ -2347,7 +2293,6 @@ Gabungkan perpustakaan perangkat lain ke dalam perangkat ini. Pilih semua Hapus - %1$d dari %2$d dipilih Daftar putar, album, dan Tonton Nanti Anda. Apa yang telah Anda tonton dan sejauh mana Anda menonton. Video dan musik yang disukai dan tidak disukai. @@ -2378,7 +2323,6 @@ Format cadangan tidak dikenali — pastikan Anda memilih file yang benar Pengimporan gagal: %1$s %1$d jam %2$d mnt - %1$d mnt %1$dh %1$dm diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 21f3aa481..80cadd159 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -146,7 +146,6 @@ Leggi tutto Rispondi Nascondi risposte - Visualizza %1$d risposte Commento in primo piano Messo in primo piano dal creator Nuovo aggiornamento disponibile @@ -189,20 +188,14 @@ FLOW 9+ Il tuo feed personalizzato - %1$d video selezionati apposta per te Importa backup di NewPipe Importazione delle iscrizioni dal backup di NewPipe in corso… Cerca iscrizioni Cambia modalità di visualizzazione Disiscritto da %1$s - %1$d video - %1$d playlist - %1$d shorts - %1$d brani Ancora nessun download Riproduci tutto Rimuovi da Guarda più tardi - Playlist • Privata • %1$d video E Nessun video salvato I video salvati da guardare più tardi appariranno qui @@ -355,8 +348,6 @@ Scuri Personalizzati Speciali - %1$d temi - %1$d %2$s temi Applicato: %1$s Personalizza tema Editor tema personalizzato @@ -710,8 +701,6 @@ Personalizza cosa visualizzi Interessi Bloccati - %1$d argomenti - %1$d nascosti I tuoi interessi Gli argomenti selezionati aiutano Flow a suggerire contenuti migliori. Tocca gli argomenti per aggiungerli o rimuoverli. Seguiti attualmente @@ -725,10 +714,8 @@ Aggiunta rapida Argomenti comuni da bloccare Attualmente bloccati - %1$d argoment%2$s Rimuovi %1$s Sblocca %1$s - %1$d selezionati Gestione del tempo di utilizzo Monitora e controlla il tuo tempo di utilizzo Le statistiche si basano sulla cronologia delle visualizzazioni in questa app. L\'utilizzo effettivo potrebbe variare. @@ -755,12 +742,10 @@ Verrà inviata una notifica all\'ora di inizio. Ricordami di prendere una pausa Frequenza del promemoria - Ogni %1$d min Media giornaliera Oggi Ultimi 7 giorni Frequenza - Ogni %1$d minuti Questa settimana Totale: %s ore Ancora nessun dato di visualizzazione @@ -775,7 +760,6 @@ Imposta dei promemoria per regolare le tue abitudini di visione Conferma Durata - %1$d min 5 min 120 min Durata personalizzata @@ -794,31 +778,24 @@ Suggerimenti di ricerca Mostra suggerimenti di ricerca durante la digitazione Dimensione massima della cronologia - Attualmente: %1$d ricerche Elimina automaticamente la cronologia - Elimina dopo %1$d giorni Non eliminare mai automaticamente Periodo di conservazione - Elimina le ricerche più vecchie di %1$d giorni Cancella cronologia delle ricerche Rimuovi tutte le query di ricerca Cancellare la cronologia delle ricerche? Elimina definitivamente tutta la cronologia delle ricerche. Scegli quante ricerche conservare: - %1$d ricerche Elimina ricerche più vecchie di: 1 settimana 1 mese 3 mesi 6 mesi 1 anno - %1$d giorni Importazione dei dati Backup di Flow importato correttamente Impossibile importare il backup di Flow: %1$s - %1$d iscrizioni importate da NewPipe Impossibile importare il backup di NewPipe: %1$s - %1$d iscrizioni importate da YouTube Impossibile importare il backup di YouTube: %1$s Importa backup di Flow Ripristina la tua cronologia, le impostazioni e le iscrizioni da un file di backup di Flow. @@ -840,9 +817,7 @@ Importa una playlist da YouTube Takeout CSV (Playlist-<name>.csv). Importa playlist di YouTube Music Importa una playlist musicale da YouTube Music Takeout CSV. Appariranno sotto Playlist musicali. - Importati %1$d elementi dalla cronologia delle visualizzazioni di YouTube Impossibile importare la cronologia delle visualizzazioni: %1$s - Playlist \"%1$s\" importata con %2$d video Impossibile importare la playlist: %1$s Nessun elemento di cronologia trovato in questo file. Assicurati che si tratti di un file watch-history.html esportato da YouTube Takeout. Nessun video trovato in questo CSV. Assicurati che si tratti di un file CSV di playlist esportato da YouTube Takeout. @@ -871,7 +846,6 @@ Download parallelo Scarica i file in più parti per la massima velocità. Thread simultanei - %1$d thread per download L\'utilizzo di più thread può aumentare la velocità, ma potrebbe consumare più batteria e surriscaldare il dispositivo. Scegli dove salvare i file scaricati nel dispositivo. Posizioni predefinite @@ -890,7 +864,6 @@ Consigliato Attivo Seleziona numero dei thread (1-8): - %1$d thread Supporto e donazioni Supporta lo sviluppo di Flow Se trovi Flow utile e desideri supportarne lo sviluppo, puoi sostenerlo su Patreon o donare tramite gli indirizzi crypto qui sotto. Il tuo supporto aiuta a mantenere vivo il progetto! @@ -945,12 +918,9 @@ Aggiungi video dal player video\nper creare la tua playlist Eliminare la playlist? Questa operazione eliminerà definitivamente \"%1$s\" e tutti i suoi video. - Playlist • Privata • %1$d video - Playlist • Pubblica • %1$d video Benvenuto in Flow Dicci cosa ti interessa Seleziona almeno 3 argomenti per personalizzare la tua esperienza - %1$d selezionati (%2$d ancora necessari) Salta per ora Continua Comprimi @@ -990,7 +960,6 @@ Interazioni Argomenti Guarda qualche video per popolare la tua nebulosa di interessi! - %1$d interazione • Livello %2$d Esporta dati profilo Esportazione del profilo neurale di Flow Libreria musicale @@ -1007,8 +976,6 @@ %1$s • %2$s visualizzazioni Visualizza tutto Ricerca - %1$s visualizzazioni - %1$d tracce • %2$s Errore sconosciuto Riorova Nessun mood e genere disponibile @@ -1083,7 +1050,6 @@ Playlist • %1$s • %1$s riproduzioni Album • %1$s • %2$s - Artista • %1$s ascoltatori mensili Ricerca: %1$s Artista: %1$s Migliori risultati per te @@ -1100,7 +1066,6 @@ Si ferma tra Crea la tua prima playlist per organizzare i tuoi brani preferiti Tocca l\'icona cuore su qualsiasi brano per aggiungerlo ai preferiti - %1$d brani preferiti Inizia ad ascoltare musica per vedere qui la tua cronologia Scarica i brani per ascoltarli offline Dimensione totale @@ -1282,7 +1247,6 @@ Report copiato negli appunti Aggiungi alla mia playlist Aggiungi tutti i brani a… - Aggiunti %1$d brani a “%2$s” Tutti Gestisci gruppi Nuovo gruppo @@ -1392,7 +1356,6 @@ Affinità delle live Quanto il contenuti live si adatta al profilo Ampiezza degli argomenti - %1$d argomenti nel vettore globale Pesi degli interessi Argomenti con peso maggiore dopo i controlli di prova e verifica Ancora nessun peso degli argomenti. @@ -1454,7 +1417,6 @@ Meno recenti In raffreddamento Scarica tutto - Scaricare tutti i %1$d video? Potrebbe occupare spazio di archiviazione significativo. Titolo copiato negli appunti Iscrizioni Cronologia @@ -1472,13 +1434,10 @@ Download non completati Annullato Rimuovi download non completati - Rimuovere %1$d download interrotti, falliti o parziali? I download completati non verranno coinvolti. Blocca controlli Sblocca controlli Pulsante della modalità di blocco Mostra un pulsante di blocco nel player per evitare tocchi accidentali - Aggiornando %1$d di %2$d canali - Ultimo aggiornamento %1$s - %2$d video verificati Temi predefiniti di sistema Scegli quale tema viene utilizzato quando il dispositivo passa dalla modalità chiara a quella scura. Tema modalità chiara @@ -1507,7 +1466,6 @@ I brano che ti piacciono appariranno qui Nascondi gli Short di questo canale Mostra gli Short di questo canale - %1$d mi piace Commenti Carica e mostra la sezione commenti nella schermata del player video Video delle iscrizioni @@ -1517,8 +1475,6 @@ Live delle iscrizioni Mostra le live e quelle terminate di recente nel feed delle iscrizioni Scorrimento automatico dopo un tempo personalizzato - Scorri automaticamente ogni %1$d secondi - %1$d secondi Opzioni di ordinamento playlist Manuale Data di aggiunta (più recente) @@ -1526,7 +1482,6 @@ Più popolari Data di pubblicazione (più recente) Data di pubblicazione (meno recente) - Rimuovere %1$d video? Verranno rimossi da questa playlist. Verranno rimossi da Guarda più tardi. Auto %1$ds @@ -1681,7 +1636,6 @@ Mostra i controlli del player prima che il video finisca di caricarsi, così puoi regolare il volume immediatamente Ritardo della riproduzione automatica Nessuno (cambia immediatamente) - %1$d secondi Mostra un conto alla rovescia prima del passaggio automatico al video successivo. Durante il conto alla rovescia puoi ricominciare il video attuale, annullare il passaggio, oppure riprodurre il video successivo immediatamente. Flow Play A seguire @@ -1815,14 +1769,12 @@ Cerca canali… Digita un nome di un canale da cercare Nessun canale trovato per \"%1$s\" - %1$d canali aggiunti %1$s iscritti Iscritto Iscriviti Importa i tuoi dati Porta le tue iscrizioni e la tua cronologia da altre app. Tutto è facoltativo. Backup e ripristino - %1$d selezionati Selezionati Non selezionati Importazione non riuscita: %1$s @@ -2004,7 +1956,6 @@ Log errori del canale Flow modificato %1$s (%2$s) - %1$d ore I controlli in background sono limitati Android impedisce a Flow di verificare la presenza di nuovi video quando l\'app è chiusa, quindi gli avvisi arrivano solo quando la apri. Tocca per consentire l\'attività in background senza restrizioni. Connessione al Gateway di Discord non riuscita. @@ -2173,7 +2124,6 @@ Mostra altro Download non riuscito Nuovi video - %1$d nuovi video dalle tue iscrizioni Aggiornamento disponibile: %1$s Tocca per aggiornare all\'ultima versione. Promemoria di Guarda più tardi @@ -2204,7 +2154,6 @@ Unisci la libreria di un altro dispositivo in questo. Seleziona tutto Cancella - %1$d di %2$d selezionati Le tue playlist, i tuoi album e Guarda più tardi. Cos\'hai guardato e per quanto tempo. Video e musica piaciuti e non piaciuti. diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index acf44507d..4c3696cc3 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -36,7 +36,6 @@ %1$s回視聴 %1$s回視聴 %1$s • %2$s回視聴 - %1$s回視聴 Flow ショート 高く評価した動画 @@ -51,7 +50,6 @@ 高評価 高評価 低評価 - 高評価 %1$d 件 Return YouTube Dislike 高評価 高評価 @@ -73,7 +71,6 @@ 人気の動画 古い順 新しい順 - %1$d 時間 6 時間 (デフォルト) 12 時間 24 時間 @@ -88,7 +85,6 @@ 24 時間 2 時間 3 時間 - %1$d 日 2 倍速 続きを見る @@ -105,15 +101,11 @@ 説明 (オプション) 再生リスト %1$s • %2$s - %1$d 件の再生リスト - 再生リスト • 非公開 • %1$d 本の動画 非公開 - 再生リスト • 非公開 • %1$d 本の動画 非公開動画 公開 公開する 非公開にする - 再生リスト • 公開 • %1$d 本の動画 登録チャンネル すべて 登録したチャンネルがありません diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 146c7fb83..b828af072 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -12,8 +12,6 @@ 아직 구독한 채널이 없습니다 채널을 구독하면 최신 동영상이\n여기에 표시됩니다 피드 새로고침 - %2$d개 채널 중 %1$d개 새로고침 중 - 마지막 새로고침: %1$s · 동영상 %2$d개 확인 마지막 새로고침: %1$s 다시 시도 채널을 불러오지 못했습니다 @@ -71,7 +69,6 @@ 다운로드됨 다운로드 모두 다운로드 - 동영상 %1$d개를 모두 다운로드할까요? 저장 공간을 많이 사용할 수 있습니다. 저장 저장됨 라이브러리에 추가 @@ -238,7 +235,6 @@ 더보기 답글 답글 숨기기 - 답글 %1$d개 보기 답글 더 불러오기 텍스트 선택 고정된 댓글 @@ -296,7 +292,6 @@ FLOW 9+ 맞춤 피드 - 나를 위해 선별한 동영상 %1$d개 NewPipe 백업 가져오기 NewPipe 백업에서 구독을 가져오는 중... 구독 검색 @@ -312,15 +307,9 @@ %1$s 구독을 취소했습니다 이 채널의 Shorts 숨기기 이 채널의 Shorts 표시 - 동영상 %1$d개 - 좋아요 %1$d개 - 재생목록 %1$d개 - Shorts %1$d개 - 노래 %1$d곡 아직 다운로드한 항목이 없습니다 모두 재생 나중에 볼 동영상에서 삭제 - 재생목록 • 비공개 • 동영상 %1$d개 E 저장한 동영상이 없습니다 나중에 보려고 저장한 동영상이 여기에 표시됩니다 @@ -503,8 +492,6 @@ 다크 사용자 지정 특별 - 테마 %1$d개 - %2$s 테마 %1$d개 적용됨: %1$s 테마 맞춤설정 사용자 지정 테마 편집기 @@ -841,17 +828,14 @@ 반복(현재 Shorts 반복 재생) 다음 항목 자동 재생(다음 Shorts로 이동) 사용자 지정 시간 후 자동 스크롤 - %1$d초마다 자동 스크롤 Shorts 재생 모드 현재 Shorts 재생이 끝났을 때의 동작을 선택하세요: - %1$d초 관련 동영상 자동재생 대기열이 비어 있으면 추천 동영상을 자동으로 다음에 재생합니다 대기열 동영상 자동재생 재생목록이나 나중에 볼 동영상 대기열의 다음 동영상을 자동으로 재생합니다. 꺼도 직접 건너뛸 수 있습니다. 자동재생 지연 시간 없음(즉시 전환) - %1$d초 다음 동영상으로 자동 전환하기 전에 카운트다운을 표시합니다. 카운트다운 중에 현재 동영상을 다시 시작하거나 전환을 취소하거나 다음 동영상을 즉시 재생할 수 있습니다. 다음 재생 다음 동영상 @@ -1027,8 +1011,6 @@ 표시할 콘텐츠를 맞춤설정하세요 관심사 차단됨 - 주제 %1$d개 - 숨김 %1$d개 내 관심사 선택한 주제는 Flow가 더 나은 콘텐츠를 추천하는 데 도움이 됩니다. 아래 주제를 탭하여 추가하거나 삭제하세요. 현재 팔로우 중 @@ -1044,10 +1026,8 @@ 빠른 추가 자주 차단하는 주제 현재 차단됨 - 주제 %1$d개%2$s %1$s 삭제 %1$s 차단 해제 - %1$d개 선택됨 선택 선택 취소 모두 선택 @@ -1063,12 +1043,10 @@ 시작 시간에 알림을 보냅니다. 휴식 시간 알림 알림 빈도 - %1$d분마다 일일 평균 오늘 최근 7일 빈도 - %1$d분마다 이번 주 합계: %s시간 아직 시청 데이터가 없습니다 @@ -1084,7 +1062,6 @@ 확인 취침 타이머 시간 - %1$d분 5분 120분 사용자 지정 시간 @@ -1106,31 +1083,24 @@ 검색어 추천 입력하는 동안 추천을 표시합니다 최대 기록 수 - 현재: 검색어 %1$d개 기록 자동 삭제 - %1$d일 후 삭제 자동으로 삭제하지 않음 보관 기간 - %1$d일보다 오래된 검색어 삭제 검색 기록 지우기 모든 검색어 삭제 검색 기록을 지울까요? 모든 검색 기록을 영구적으로 삭제합니다. 보관할 검색어 수를 선택하세요: - 검색어 %1$d개 다음 기간보다 오래된 검색어 삭제: 1주 1개월 3개월 6개월 1년 - %1$d일 데이터 가져오기 Flow 백업을 가져왔습니다 Flow 백업을 가져오지 못했습니다: %1$s - NewPipe에서 구독 %1$d개를 가져왔습니다 NewPipe 백업을 가져오지 못했습니다: %1$s - YouTube에서 구독 %1$d개를 가져왔습니다 YouTube 백업을 가져오지 못했습니다: %1$s Flow 백업 가져오기 Flow 백업 파일에서 기록, 설정 및 구독을 복원합니다. @@ -1166,9 +1136,7 @@ YouTube Takeout CSV(Playlist-<name>.csv)에서 재생목록을 가져옵니다. YouTube Music 재생목록 가져오기 YouTube Music Takeout CSV에서 음악 재생목록을 가져옵니다. 음악 재생목록 아래에 표시됩니다. - YouTube 시청 기록에서 항목 %1$d개를 가져왔습니다 시청 기록을 가져오지 못했습니다: %1$s - 동영상 %2$d개가 포함된 재생목록 “%1$s”을(를) 가져왔습니다 재생목록을 가져오지 못했습니다: %1$s 이 파일에서 시청 기록 항목을 찾을 수 없습니다. YouTube Takeout의 watch-history.html 파일인지 확인하세요. 이 CSV에서 동영상을 찾을 수 없습니다. YouTube Takeout 재생목록 CSV 파일인지 확인하세요. @@ -1201,7 +1169,6 @@ 병렬 다운로드 최대 속도를 위해 파일을 여러 조각으로 나누어 다운로드합니다. 동시 스레드 - 다운로드당 스레드 %1$d개 스레드를 많이 사용하면 속도가 빨라질 수 있지만 배터리 사용량과 기기 온도가 높아질 수 있습니다. 다운로드한 파일을 기기에 저장할 위치를 선택하세요. 미리 설정된 위치 @@ -1220,7 +1187,6 @@ 권장 사용 중 스레드 수 선택(1~8): - 스레드 %1$d개 후원 및 기부 Flow 개발 후원 Flow가 유용하고 개발을 후원하고 싶다면 Patreon 또는 아래 암호화폐 주소로 지원할 수 있습니다. 여러분의 후원은 프로젝트를 계속 유지하는 데 큰 도움이 됩니다! @@ -1282,8 +1248,6 @@ 동영상 플레이어에서 동영상을 추가하여\n재생목록을 만들어 보세요 재생목록을 삭제할까요? ‘%1$s’ 및 포함된 모든 동영상이 영구적으로 삭제됩니다. - 재생목록 • 비공개 • 동영상 %1$d개 - 재생목록 • 공개 • 동영상 %1$d개 재생목록 정렬 옵션 수동 추가 날짜(최신순) @@ -1291,13 +1255,11 @@ 인기순 게시 날짜(최신순) 게시 날짜(오래된순) - 동영상 %1$d개를 삭제할까요? 이 재생목록에서 삭제됩니다. 나중에 볼 동영상에서 삭제됩니다. Flow에 오신 것을 환영합니다 관심사를 알려 주세요 맞춤 환경을 위해 주제를 3개 이상 선택하세요 - %1$d개 선택됨(%2$d개 더 필요) 무엇을 좋아하시나요? 피드 맞춤설정을 위해 주제를 %1$d개 이상 선택하세요. %2$d개 더 선택하면 됩니다. 좋은 선택입니다. 나중에 설정에서 언제든 변경할 수 있습니다. @@ -1306,14 +1268,12 @@ 채널 검색… 검색할 채널 이름을 입력하세요 “%1$s”에 대한 채널을 찾을 수 없습니다 - 채널 %1$d개 추가됨 구독자 %1$s명 구독 중 구독 데이터 가져오기 다른 앱의 구독과 기록을 가져오세요. 모든 단계는 선택사항입니다. 백업 및 복원 - %1$d개 선택됨 선택됨 선택되지 않음 가져오기 실패: %1$s @@ -1377,7 +1337,6 @@ 상호작용 주제 동영상을 시청하여 관심사 성운을 채워 보세요! - 상호작용 %1$d회 • 레벨 %2$d 프로필 데이터 내보내기 Flow 신경 프로필 내보내기 음악 라이브러리 @@ -1397,8 +1356,6 @@ %1$s • 조회수 %2$s회 모두 보기 검색 - 조회수 %1$s회 - 트랙 %1$d개 • %2$s 알 수 없는 오류 다시 시도 사용 가능한 분위기 및 장르가 없습니다 @@ -1487,7 +1444,6 @@ 재생목록 • %1$s • 재생 %1$s회 앨범 • %1$s • %2$s - 아티스트 • 월간 청취자 %1$s명 검색: %1$s 아티스트: %1$s 나를 위한 인기 추천 @@ -1499,7 +1455,6 @@ 첫 재생목록을 만들어 좋아하는 트랙을 정리하세요 아직 즐겨찾기가 없습니다 트랙의 하트 아이콘을 탭하여 즐겨찾기에 추가하세요 - 즐겨찾기 트랙 %1$d개 아직 기록이 없습니다 음악을 들으면 감상 기록이 여기에 표시됩니다 아직 다운로드가 없습니다 @@ -1557,7 +1512,6 @@ 실패 취소됨 미완료 다운로드 삭제 - 일시중지, 실패 또는 일부만 받은 다운로드 %1$d개를 삭제할까요? 완료된 다운로드는 삭제되지 않습니다. 오디오 트랙 %1$s %2$d %1$s(%2$s) @@ -1791,7 +1745,6 @@ 보고서를 클립보드에 복사했습니다 내 재생목록에 모두 추가 모든 노래를 추가할 재생목록… - “%2$s”에 노래 %1$d곡을 추가했습니다 아직 재생목록이 없습니다. 먼저 하나 만들어 주세요! 프로필을 내보냈습니다 내보내기 실패 @@ -1827,7 +1780,6 @@ 실시간 콘텐츠 선호도 실시간 콘텐츠가 프로필에 얼마나 잘 맞는지 나타냅니다 주제 범위 - 전체 벡터의 주제 %1$d개 관심사 가중치 검증 기간과 근거 확인을 거친 가중치가 가장 높은 주제 아직 주제 가중치가 없습니다. @@ -2001,7 +1953,6 @@ 새 Flow 버전(%1$s)을 사용할 수 있습니다. 최신 APK를 다운로드할까요? 연 주 곡 재생목록이 비어 있습니다 - 동영상 %1$d개 다운로드 중… 재생목록을 라이브러리에 저장했습니다 재생목록을 라이브러리에서 삭제했습니다 오디오 다운로드 중: %1$s kbps %2$s @@ -2023,10 +1974,8 @@ 재생목록을 삭제했습니다 재생목록 이름을 변경했습니다 %1$s 다운로드를 시작하는 중… - %2$s에서 트랙 %1$d개를 다운로드했습니다 재생목록을 다운로드하지 못했습니다 재생목록 다운로드 중 오류가 발생했습니다 - 트랙 %1$d개를 다운로드했습니다 재생목록에 추가했습니다 트랙을 추가하지 못했습니다 재생목록에서 삭제했습니다 @@ -2043,7 +1992,6 @@ 다운로드 실패 외 %1$d개 새 동영상 - 구독 채널의 새 동영상 %1$d개 업데이트 사용 가능: %1$s 탭하여 최신 버전으로 업데이트하세요. 나중에 볼 동영상 알림 @@ -2114,7 +2062,6 @@ Flow 백업 관리 외부 서비스 다른 YouTube 클라이언트에서 가져오기 - %2$s %1$d개를 가져왔습니다 %1$s을(를) 가져왔습니다 %1$s 가져오는 중… Google Takeout에서 가져왔습니다 diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 7b130de98..086e1a215 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -45,8 +45,6 @@ To usunie wszystkie filmy z twojej historii oglądania. Ta akcja nie może zostać cofnięta. Wyczyść Wszystko - Odświeżanie %1$d z %2$d kanałów - Ostatnie odświeżenie: %1$s - Sprawdzono filmów: %2$d Brak historii oglądania Filmy, które obejrzałeś pojawią się tutaj Szukaj w historii oglądania @@ -68,7 +66,6 @@ Film Pobrane Pobierz wszystko - Pobrać wszystkie %1$d filmów? To może zająć dużo miejsca na dysku. Dodaj do biblioteki Zapisano do biblioteki Nie udało się zapisać do biblioteki @@ -188,7 +185,6 @@ Pokaż więcej Odpowiedz Ukryj odpowiedzi - Zobacz odpowiedzi: %1$d Załaduj więcej odpowiedzi Zaznacz Tekst Przypięty komentarz @@ -254,7 +250,6 @@ FLOW 9+ Twoja spersonalizowana zawartość - %1$d filmów znalezionych właśnie dla Ciebie Importuj kopię zapasową z NewPipe Importowanie subskrybcji z kopii zapasowej z NewPipe... Szukaj Subskrypcji @@ -268,15 +263,9 @@ Odsubskrybowano kanał %1$s Ukryj filmy Shorts z tego kanału Pokazuj filmy Shorts z tego kanału - %1$d filmów - %1$d polubień - %1$d playlist - %1$d filmów Shorts - %1$d utworów Brak pobranych Odtwórz wszystko Usuń z Obejrzyj Później - Playlista • Prywatna • %1$d filmów E Brak zapisanych filmów Filmy, które zapiszesz do późniejszego obejrzenia pojawią się tutaj @@ -443,8 +432,6 @@ Ciemny Niestandardowy Specjalny - %1$d motywów - %1$d %2$s motywów Zastosowano: %1$s Dostosuj Motyw Niestandardowy Edytor Motywów @@ -608,7 +595,6 @@ 3 miesiące 6 miesięcy 1 rok - %1$d dni Kontynuuj Gry Muzyka @@ -668,9 +654,7 @@ Import Danych Kopia zapasowa Flow importowana pomyślnie Importowanie kopii zapasowej Flow nie powiodło się: %1$s - Ilość subskrypcji importowanych z NewPipe: %1$d Importowanie kopii zapasowej NewPipe nie powiodło się: %1$s - Ilość subskrypcji importowanych z Youtube: %1$d Importowanie kopii zapasowej Youtube nie powiodło się: %1$s Importuj kopię zapasową Flow Przywróć swoją historię, ustawienia i subskrypcje z pliku kopii zapasowej Flow. @@ -811,8 +795,6 @@ Dokładna data Wyświetlanie czasu Oba - Usuń wyniki wyszukiwania starsze niż %1$d dni - Usuń po %1$d dniach Ostatnie 7 dni Format dokładnej daty Dokładna @@ -992,10 +974,8 @@ Wydajność Pobieraj wielowątkowo, by przyspieszyć pobieranie do maksimum. Liczba Wątków - %1$d wątków na pobranie Zwiększenie liczby wątków może przyspieszyć działanie, ale może też spowodować większe zużycie baterii i przegrzanie urządzenia. Wybierz liczbę wątków (1–8): - %1$d wąt. Wątki Zaimportuj historię oglądania z pliku JSON wyeksportowanego z serwisu FreeTube. Sprawdzanie Powiadomień @@ -1005,9 +985,7 @@ Sugestie Wyszukiwania Wyświetlaj sugestie podczas wpisywania Maksymalny Rozmiar Historii - Obecnie: %1$d wyszukiwań Wybierz, ile wyników wyszukiwania chcesz zachować: - %1$d wyszukiwań Automatyczne Usuwanie Historii Nigdy nie usuwaj automatycznie Okres Przechowywania @@ -1035,8 +1013,6 @@ Podczas oglądania rób regularne przerwy Częstotliwość przypomnień Jak często Ci przypominać - Co %1$d minut - Co %1$d minut Częstotliwość Eksport Danych Wybierz Typ Eksportu @@ -1067,7 +1043,6 @@ Importuj Dane Silnika Flow Twoje urządzenie nie mogło odtworzyć tego strumienia. Spróbuj wybrać niższą jakość. Zaimportuj historię oglądania z serwisu YouTube Takeout (watch-history.html). - Zaimportowano %1$d pozycji z historii oglądania serwisu YouTube Zaimportuj historię oglądania z pliku ZIP zawierającego kopię zapasową NewPipe lub z pliku newpipe.db. Zaimportuj Historie Oglądania W tym pliku nie znaleziono żadnych wpisów dotyczących historii oglądania. Upewnij się, że jest to plik „watch-history.html” z serwisu YouTube Takeout. @@ -1089,7 +1064,6 @@ Następny w kolejce Wyłącznik Czasowy Czas trwania - %1$d min 5 min 120 min Czas niestandardowy @@ -1174,7 +1148,6 @@ Wybierz tematy (min.%1$d), aby spersonalizować wyświetlane treści. Zostało:%2$d. Świetny wybór. Zawsze możesz to później zmienić w ustawieniach. Obecnie Obserwowane - %1$d tematów Dodaj Tematy Przeglądaj według kategorii MUZYKA @@ -1199,7 +1172,6 @@ Znajdź kanały Wpisz nazwę kanału, który chcesz wyszukać Nie znaleziono kanału o nazwie „%1$s” - Liczba dodanych kanałów: %1$d %1$s subskrybentów Subskrybowany Zasubskrybuj @@ -1208,7 +1180,6 @@ Powróć Zakończ Import nie powiódł się: %1$s - Wybrane tematy: %1$d Wybrane Nie wybrane Wyższa dojrzałość gwarantuje pełną stabilność profilu silnika AI @@ -1290,7 +1261,6 @@ Pomyślnie wyeksportowano profil Pomyślnie zaimportowano profil Import nieudany – nieprawidłowy plik - %2$s” dodano następującą liczbę utworów:%1$d Przycisk Komentarzy Wyświetl przycisk komentarzy w pełnym ekranie i otwieraj je w panelu bocznym Skopiuj link @@ -1401,7 +1371,6 @@ Autoodtwarzanie Polecanych Filmów Opóźnienie autoodtwarzania Żadne (przełącz od razu) - %1$d s Wyświetlaj odliczanie przed autoodtwarzaniem kolejnego filmu. W tym czasie możesz uruchomić film od nowa, anulować przejście lub natychmiast włączyć następny. Wyszukuj filmy, muzykę i więcej Wszystko @@ -1489,8 +1458,6 @@ TV Zawsze używaj wygodnego dla pilota interfejsu TV Dodaj zainteresowania - Automatyczne przewijanie co %1$d s - %1$d sekund Stworzone Przez Społeczność Ukryj Niedostępne Filmy z Subskrypcji Ukrywaj filmy usunięte, prywatne, z ograniczeniem wieku oraz tylko dla wspierających, jeśli nie da się ich odtworzyć @@ -1620,12 +1587,10 @@ Polubione Dźwięk Oryginalny - %1$s bln. - %1$d ukryte Dotknij by usunąć Dodaj temat Usuń %1$s Odblokuj %1$s - %1$d zaznaczone Anuluj zaznaczenie Zaznacz wszystko Odznacz wszystkie @@ -1641,7 +1606,6 @@ Zaimportuj dodatkowe dane z serwisu YouTube Takeout Zaimportuj listę odtwarzania z YouTube Zaimportuj listę odtwarzania z pliku CSV z serwisu YouTube Takeout (Playlist-<nazwa>.csv). - Zaimportowano listę odtwarzania \"%1$s\" z %2$d filmami Nie udało się zaimportować listy odtwarzania: %1$s W tym pliku CSV nie znaleziono żadnych filmów. Upewnij się, że jest to plik CSV zawierający listę odtwarzania z serwisu YouTube Takeout. Pobrane / Flow @@ -1666,8 +1630,6 @@ Usuń z listy odtwarzania Ta lista odtwarzania jest pusta Dodaj filmy z odtwarzacza, by zbudować\nswoją listę odtwarzania - Lista odtwarzania • Prywatna • %1$d filmów - Lista odtwarzania • Publiczna • %1$d filmów Opcje sortowania listy odtwarzania Ręcznie Data dodania (najnowsze) @@ -1677,7 +1639,6 @@ Zostaną usunięte z listy odtwarzania. Zostaną usunięte z „Na później”. Witamy w Flow - %1$d zaznaczone (%2$d więcej potrzebnych) Zwiń Rozwiń Odśwież @@ -1714,7 +1675,6 @@ Spowoduje to trwałe usunięcie:\n\n• Wszystkich zapamiętanych preferencji\n• Długoterminowego wektora osobowości\n• Wzorców związanych z kontekstem czasowym\n• Wyników zgodności z kanałami\n\nTwój strumień treści powróci do stanu początkowego. Wymaż Wszystko Obejrzyj kilka filmów, aby wzbogacić swoją mgławicę zainteresowań! - %1$d interakcji • Poziom %2$d Eksportuj Dane Profilu Eksport Neuralnego Profilu Flow Biblioteka muzyczna @@ -1727,8 +1687,6 @@ Fani lubią także %1$s • %2$s wyświetleń Szukaj - %1$s wyświetleń - %1$d utworów • %2$s Nieznany błąd Brak dostępnych nastrojów i gatunków Przeglądaj @@ -1777,7 +1735,6 @@ Brak wyników wyszukiwania Nie znaleziono utworów Ulubione - %1$d ulubionych utworów Brak Historii Brak Pobranych Łączny Rozmiar @@ -1999,12 +1956,10 @@ ...więcej edytowany %1$s (%2$s) - %1$d godz. Usuń z kolejki Czy na pewno chcesz usunąć ten film z kolejki? Więcej wyników %1$d godz %2$d min - %1$d min %1$dgodz %1$dmin Wersja %1$s @@ -2023,7 +1978,6 @@ Łączenie z urządzeniem… Włącz Wstrzymane - Usunąć wstrzymane, nieudane lub częściowo pobrane (%1$d)? Zakończone pobrania nie zostaną naruszone. Brak aktywnej kolejki filmów. Najpierw odtwórz film. Łączenie z Discordem… Funkcja Discord Rich Presence nie została uruchomiona. @@ -2133,7 +2087,6 @@ Kanały, które obserwujesz. Ustawienia odtwarzania, wyglądu i pobierania. Wyczyść - Wybrano %1$d z %2$d Wybierz wszystko Foldery w których porządkujesz obserwowane kanały. Grupy subskrypcji diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 98b295c8b..8bc81936b 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -149,7 +149,6 @@ Ainda não há comentários Leia mais Ocultar respostas - Ver %1$d respostas Comentário fixado Fixado pelo criador Nova atualização disponível @@ -186,18 +185,12 @@ Artista 9+ Seu feed personalizado - %1$d vídeos selecionados especialmente para você Importar Backup do NewPipe Importando inscrições do backup do NewPipe... Alternar modo de visualização Inscrição cancelada em %1$s - %1$d vídeos - %1$d Playlists - %1$d Shorts - %1$d músicas Ainda não há downloads Remover da playlist Assistir mais tarde - Playlist • Privada • %1$d vídeos E Nenhum vídeo salvo Os vídeos que você salvar para assistir mais tarde aparecerão aqui @@ -285,8 +278,6 @@ EM BREVE Responder Shorts - Atualizando %1$d de %2$d canais - Última atualização %1$s - %2$d vídeos verificados Mídia local Vídeos e músicas armazenados neste dispositivo aparecerão aqui. Permissão necessária @@ -297,7 +288,6 @@ Mais recentes primeiro Mais antigos primeiro Baixar todos - Baixar todos os %1$d vídeos? Isso pode consumir uma quantidade significativa de armazenamento. Salvo Adicionar à biblioteca Salvo na biblioteca @@ -315,7 +305,6 @@ Não há vídeos curtidos Não há músicas curtidas As músicas que você curtir irão aparecer aqui - %1$d Curtidas Atualizado pela última vez %1$s Escaneando seu dispositivo… Escanear novamente @@ -393,8 +382,6 @@ Selecione o Idioma do Aplicativo Padrão do sistema Especial - %1$d temas - %1$d%2$s temas Aplicado: %1$s Salvar Tema Primário @@ -542,9 +529,7 @@ Usuário Senha Configurações de proxy salvas - %1$d segundos Nenhum (muda imediatamente) - %1$d segundos Cancelar Reiniciar Ex.: 1,35 @@ -936,7 +921,6 @@ Loop (repetir shorts atual) Reproduzir automaticamente (avançar para o próximo shorts) Rolar automaticamente após um tempo definido - Rolar automaticamente a cada %1$d segundos Modo de Reprodução de Shorts Escolher como os Shorts deve se comportar quando o Short atual terminar de ser reproduzido: Reproduzir automaticamente vídeos relacionados @@ -1062,8 +1046,6 @@ Procurar Preferências de Conteúdo Personalizar o que você vê - %1$d tópicos - %1$d oculto Seus Interesses Os tópicos que você selecionou ajudam o Flow a recomendar conteúdo melhor. Toque nos tópicos abaixo para adicioná-los ou removê-los. Atualmente seguindo @@ -1079,10 +1061,8 @@ Adicionar rapidamente Tópicos comuns a serem bloqueados Atualmente bloqueado - %1$d tópico%2$s Remover %1$s Desbloquear %1$s - %1$d selecionado Selecionar Cancelar seleção Selecionar tudo @@ -1098,12 +1078,10 @@ Uma notificação será enviada no horário de início. Lembre-me de fazer uma pausa Frequência de lembretes - A cada %1$d min Média diária Hoje Últimos 7 dias Frequência - A cada %1$d minutos Essa semana Total: %s horas Ainda não há dados de visualização @@ -1119,7 +1097,6 @@ Confirmar Temporizador de sono Duração - %1$d mínimo 5 min 120 min Horário personalizado @@ -1141,31 +1118,24 @@ Sugestões de Pesquisa Mostrar sugestões enquanto digito Tamanho Máximo do Histórico - Atualmente: %1$d pesquisas Excluir automaticamente histórico - Excluir após %1$d dias Nunca exclua automaticamente Período de Retenção - Excluir pesquisas com mais de %1$d dias Limpar Histórico de Pesquisa Remover todas as consultas de pesquisa Limpar Histórico de Pesquisa? Apagar permanentemente todo o histórico de pesquisa. Escolha quantas pesquisas deseja manter: - %1$d pesquisas Excluir pesquisas mais antigas que: 1 semana 1 mês 3 meses 6 meses 1 ano - %1$d dias Importar Dados Backup do Flow importado com sucesso Falha ao importar o backup do Flow: %1$s - %1$d Inscrições importadas do NewPipe Falha ao importar o backup do NewPipe: %1$s - %1$d inscrições importadas do YouTube Falha ao importar o backup do YouTube: %1$s Importar Backup do Flow A verificação em segundo plano esta restrita @@ -1203,9 +1173,7 @@ Importar uma playlist do YouTube Takeout em formato CSV (Playlist-<nome>.csv). Importar playlist de músicas do YouTube Importar uma playlist de músicas do YouTube Music Takeout em formato CSV. Ela aparecerá em playlists de músicas. - Importar %1$d entradas do seu histórico de visualização do YouTube Falha ao importar o histórico de visualização: %1$s - Playlist “%1$s” importada com %2$d vídeos Falha ao importar a playlist: %1$s Nenhum registro de histórico de visualização encontrado neste arquivo. Certifique-se de que seja um arquivo watch-history.html do YouTube Takeout. Nenhum vídeo encontrado neste arquivo CSV. Certifique-se de que se trata de um arquivo CSV de uma playlist do YouTube Takeout. @@ -1238,7 +1206,6 @@ Baixando Paralelamente Baixar os arquivos em várias partes para obter a velocidade máxima. Núcleos Concorrentes - %1$d núcleos por download Usar mais núcleos aumenta a velocidade, mas também pode consumir mais bateria e aquecer o dispositivo. Escolher onde os arquivos baixados serão salvos no seu dispositivo. Locais predefinidos @@ -1257,7 +1224,6 @@ Recomendado Ativo Selecione a quantidade de núcleos (1-8): - %1$d núcleos Apoio e Doações Apoie o Desenvolvimento do Flow Se você considera o Flow útil e gostaria de apoiar seu desenvolvimento, pode fazê-lo no Patreon ou doar através dos endereços de criptomoedas abaixo. Seu apoio ajuda a manter o projeto ativo! @@ -1324,18 +1290,14 @@ Adicionar vídeos ao reprodutor\npara construir sua playlist Excluir playlist? Isso excluirá permanentemente \'%1$s\' e todos os seus vídeos. - Playlist • Privada • %1$d vídeos - Playlist • Pública • %1$d vídeos Opções de ordem da playlist Manual Mais popular - Remover vídeo(s) %1$d? Eles serão removidos desta playlist. Eles serão removidos da lista de Assistir mais tarde. Bem-vindo ao Flow Conte-nos o que lhe interessa Selecione pelo menos 3 tópicos para personalizar sua experiência - %1$d selecionado (%2$d adicionais necessários) Do que você gosta? Escolha pelo menos %1$d tópicos para personalizar seu feed. Faltam %2$d. Ótima seleção. Você sempre pode atualizar isso mais tarde nas configurações. @@ -1344,14 +1306,12 @@ Pesquisar canais… Digite o nome de um canal para pesquisar Nenhum canal encontrado para \"%1$s\" - %1$d canais adicionados %1$s inscrições Inscrito Inscreva-se Importar seus dados Importar suas inscrições e histórico de outros aplicativos. Tudo é opcional. Copiar e Restaurar - %1$d selecionado Selecionado Não selecionado Falha ao importar: %1$s @@ -1414,7 +1374,6 @@ Interações Tópicos Assista a alguns vídeos para expandir seus horizontes de interesse! - Interações %1$d • Nível %2$d Exportar dados de perfil Exportar Perfil Neural do Flow Biblioteca de Música @@ -1434,8 +1393,6 @@ %1$s • %2$s visualizações Ver tudo Procurar - %1$s visualizações - %1$d faixas • %2$s Erro desconhecido Tentar novamente Não há opções de humor ou gênero disponíveis @@ -1525,7 +1482,6 @@ Playlist • %1$s • %1$s reproduzidos Álbum • %1$s • %2$s - Artista • %1$s audiência mensal Pesquisar: %1$s Artista: %1$s Melhores escolhas para você @@ -1537,7 +1493,6 @@ Crie sua primeira playlist para organizar suas faixas favoritas Sem Favoritos ainda Toque no ícone do coração em qualquer faixa para adicioná-lo aos seus favoritos - %1$d faixas favoritas Nenhum Histórico Ainda Começar a ouvir música para ver sua história aqui Nenhum Download Ainda @@ -1595,7 +1550,6 @@ Falhou Cancelado Remover baixados incompletos - Remover %1$d pausado, falhado ou baixado parcialmente (s)? Os baixados concluídos não serão alterados. Faixa de áudio %1$s %2$d %1$s (%2$s) @@ -1719,7 +1673,6 @@ editado %1$s (%2$s) ...mais - %1$d horas O código de sincronização está faltando um endereço de rede válido. Cópias Automáticas Agendar cópias automáticas para uma pasta @@ -1837,7 +1790,6 @@ Relatório copiado para área de transferencia Adicionar à minha playlist Adicionar todas as músicas à… - %1$d músicas foram adicionadas à “%2$s” Ainda não há playlists. Crie uma primeiro! Perfil exportado com sucesso Falha ao exportar @@ -1872,7 +1824,6 @@ Afinidade ao vivo Quanto conteúdo ao vivo se encaixa no perfil Abrangência do tema - %1$d tópicos no vetor global Pesos de Interesse Tópicos mais ponderados depois de verificações de probabilidade e evidências Ainda não há pesos de tópicos. @@ -2174,7 +2125,6 @@ Uma nova versão do Flow está disponível (%1$s). Baixar o APK mais recente? I N S T R U M E N T A L Playlist vazia - Baixando %1$d vídeos… Playlist salva na biblioteca Playlist removida da biblioteca Baixando áudio: %1$skbps %2$s @@ -2198,10 +2148,8 @@ Playlist excluída Playlist renomeada Começando download para %1$s… - %1$d foram baixadas de %2$s Não foi possível baixar a playlist Erro ao baixar a playlist - %1$d faixas foram baixadas Adicionada à playlist Falha ao adicionar faixa Removida da playlist @@ -2219,7 +2167,6 @@ Não foi possível baixar +%1$d mais Vídeos novos - %1$d novos vídeos das suas inscrições Atualização disponível: %1$s Toque para atualizar para a versão mais recente. Lembrete de Assistir Mais Tarde @@ -2287,7 +2234,6 @@ Gerencie seus backups do Flow Serviço externo Importe de outros clientes YouTube - %1$d %2$s importado %1$s foi importado com êxito Importando %1$s… Importado do Google Takeout @@ -2303,7 +2249,6 @@ Formato de backup não reconhecido — certifique-se que selecionou o arquivo correto A importação falhou: %1$s %1$d h %2$d min - %1$d min %1$dh %1$dm Título desconhecido diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 97357357b..a73df8369 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -138,7 +138,6 @@ Ainda não há comentários Leia mais Ocultar respostas - Ver %1$d respostas Comentário fixado Fixado pelo criador Nova atualização disponível @@ -175,18 +174,12 @@ Artista 9+ O seu feed personalizado - %1$d vídeos selecionados especialmente para si Importar Backup do NewPipe A importar assinaturas do backup do NewPipe... Alternar modo de visualização Inscrição cancelada em %1$s - %1$d vídeos - %1$d Playlists - %1$d Calções - %1$d músicas Ainda não há downloads Remover da lista de Assistir mais tarde - Playlist • Privada • %1$d vídeos E Nenhum vídeo gravado Os vídeos que gravar para assistir mais tarde aparecerão aqui @@ -271,7 +264,6 @@ Padrão Nome (A-Z) Atualizado recentemente - Atualizando %1$d de %2$d canais Último atualizado %1$s Copiar registros Registros copiados @@ -302,7 +294,6 @@ Vídeos locais Músicas locais Baixar tudo - Baixar todos os %1$d vídeos? Isso pode ocupar uma grande quantidade de armazenamento. Salvo Criar playlist Fechar menu de criação de playlist diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index bb3544b84..22dd2379a 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -163,7 +163,6 @@ Читать дальше Ответить Скрыть ответы - Посмотреть ответы (%1$d) Доступно обновление Версия %1$s уже доступна ПРИМЕЧАНИЯ К ВЫПУСКУ @@ -204,20 +203,14 @@ FLOW 9+ Ваша персональная лента - %1$d видео специально для вас Импорт резервной копии NewPipe Импорт подписок из резервной копии NewPipe... Поиск в подписках Переключить режим просмотра Вы отписались от %1$s - %1$d видео - Плейлистов: %1$d - Shorts: %1$d - Треков: %1$d Скачанных файлов пока нет Воспроизвести все Удалить из «Смотреть позже» - Плейлист • Ограниченный доступ • %1$d видео E Нет сохраненных видео Здесь появятся видео для отложенного просмотра @@ -354,8 +347,6 @@ Светлые Темные Особые - Тем: %1$d - Тем (%2$s): %1$d Применено: %1$s Выберите стиль значка. Изменения вступят в силу сразу, а рабочий стол перезапустится. Внимание: смена значка использует системный механизм Android, который может временно удалить ярлык приложения с главного экрана. Зажмите свободное место на рабочем столе, чтобы добавить его снова при необходимости. @@ -665,8 +656,6 @@ Настройте видимое Предпочтения Заблокировано - Тем: %1$d - Скрыто: %1$d Ваши предпочтения Выбранные темы помогают Flow лучше рекомендовать контент. Нажмите на темы ниже, чтобы добавить или удалить их. Нажмите для удаления @@ -697,7 +686,6 @@ Пока нет групп. Создайте группу, чтобы настроить фильтр ленты. Поиск каналов… Скачать все - Скачать %1$d видео? Это может занять много места на устройстве. Сохранено Возобновить Старые @@ -769,8 +757,6 @@ Импорт данных движка Flow Восстановите свой профиль личности ИИ из файла резервной копии Контент с возрастными ограничениями - Обновление каналов: %1$d из %2$d - Последнее обновление: %1$s - %2$d видео проверено Ошибка На ошибке Контур @@ -807,7 +793,6 @@ Здесь появятся понравившиеся вам треки Скрывать Shorts с этого канала Показывать Shorts с этого канала - Нравится: %1$d На первичном На вторичном На третичном @@ -841,10 +826,8 @@ Пароль Настройки прокси сохранены Автопрокрутка через заданное время - Автопрокрутка каждые %1$d сек Режим воспроизведения Shorts Выберите действие по окончании видео Shorts: - %1$d сек Зациклить (повтор текущего Shorts) Вернуть дизлайки YouTube Получать счетчик дизлайков через сервис Return YouTube Dislike @@ -863,7 +846,6 @@ Исполнитель Посмотреть все Поиск - %1$s просмотров Неизвестная ошибка Повторить Обзор @@ -966,7 +948,6 @@ Видеокодек по умолчанию По окончании трека / видео Продолжительность - %1$d мин 5 мин 120 мин мин @@ -1054,34 +1035,27 @@ Удалить выбранное Напоминать мне делать перерыв Частота напоминаний - Каждые %1$d мин - Каждые %1$d мин На этой неделе Подтвердить В конце текущего трека Таймер сна активен Показывать подсказки при вводе Срок хранения - Удалять поисковые запросы старше %1$d дней Очистить историю поиска Удалить все поисковые запросы Очистить историю поиска? Безвозвратно удалить всю историю поиска. Выберите, сколько поисковых запросов сохранять: - %1$d поисковых запросов Удалять запросы старше чем: 1 неделя 1 месяц 3 месяца 6 месяцев 1 год - %1$d дней Импорт данных Резервная копия Flow импортирована Ошибка импорта резервной копии Flow: %1$s - Импортировано %1$d подписок из NewPipe Ошибка импорта резервной копии NewPipe: %1$s» - Импортировано подписок из YouTube: %1$d» Ошибка импорта резервной копии YouTube: %1$s» Импорт резервной копии Flow Восстановление истории, настроек и подписок из файла резервной копии Flow. @@ -1106,7 +1080,6 @@ Параллельная загрузка Загрузка файлов в несколько потоков для максимальной скорости. Количество потоков - Потоков на загрузку: %1$d Увеличение числа потоков ускоряет загрузку, но может приводить к повышенному расходу батареи и нагреву устройства. Выбор места для сохранения скачанных файлов. Предустановленные папки @@ -1141,9 +1114,7 @@ Удалить плейлист? Введите название канала для поиска Каналы по запросу «%1$s» не найдены - Добавлено каналов: %1$d Подписчики: %1$s - Выбрано: %1$d Ошибка импорта: %1$s Завершить Продолжить @@ -1174,7 +1145,6 @@ Взаимодействия Темы Смотрите видео, чтобы сформировать карту предпочтений! - %1$d взаимодействий • Уровень %2$d Экспорт нейропрофиля Flow Музыкальная библиотека Ваша коллекция @@ -1209,7 +1179,6 @@ Создай свой первый плейлист, чтобы собрать любимые треки В избранном пока пусто Нажмите на иконку сердечка у любого трека, чтобы добавить его в избранное - Любимых треков: %1$d Здесь пока нет истории Начните слушать музыку, чтобы здесь появилась история прослушиваний Здесь пока нет скачанных треков @@ -1226,7 +1195,6 @@ Приостановлено Сбой загрузки Удалить незавершенные загрузки - Удалить приостановленные, прерванные или незавершенные загрузки (%1$d)? Скачанные треки не будут затронуты. Трансляция Трансляция отключена Установлена последняя версия Flow! @@ -1426,7 +1394,6 @@ Автоматически включать следующее видео в плейлисте или очереди «Смотреть позже». Когда опция отключена, переключать ролики можно вручную. Задержка автовоспроизведения Нет (сразу переключать) - %1$d сек Показать обратный отсчет перед автоматическим переключением. Во время отсчета можно перезапустить текущий ролик, отменить переход или сразу включить следующий. Далее Следующее видео @@ -1470,7 +1437,6 @@ Рекомендовано Активный Выберите количество потоков (1-8): - Количество потоков: %1$d Адрес скопирован в буфер обмена Адрес для пожертвований Похоже на @@ -1495,21 +1461,17 @@ Параметры сортировки плейлиста Дата публикации (сначала новые) Дата публикации (сначала старые) - Удалить %1$d видео? Они будут удалены из этого плейлиста. Они будут удалены из «Смотреть позже». Добро пожаловать в Flow Расскажите нам о ваших предпочтениях Выберите как минимум 3 темы для персонализации - Выбрано: %1$d (еще требуется: %2$d) Что вам нравится? Импорт музыкальной библиотеки из других плееров Short сохранен Short не сохранен Максимальный размер истории - Сейчас: %1$d поисковых запросов Автоматическое удаление истории - Удалять через %1$d дней Не удалять автоматически Экспорт данных Выберите тип экспорта @@ -1546,9 +1508,7 @@ Импорт плейлиста из CSV-файла YouTube Архиватора (Playlist-<name>.csv). Импорт плейлиста YouTube Импорт плейлиста YouTube Music - Импортировано записей из истории просмотра YouTube: %1$d Не удалось импортировать историю просмотра: %1$s - Импортирован плейлист «%1$s» с %2$d видео Не удалось импортировать плейлист: %1$s Резервное копирование и восстановление Выбрано @@ -1593,7 +1553,6 @@ Никаких предупреждений или ошибок в этом сеансе. Отчет скопирован в буфер обмена Чтение журналов… - В «%2$s» добавлено треков: %1$d Профиль успешно экспортирован Экспорт не удался Профиль успешно импортирован @@ -1609,9 +1568,7 @@ Ожидание сообщений… Показать чат Данных о просмотрах пока нет - Плейлист • Ограниченный доступ • %1$d видео Видео с ограниченным доступом - Плейлист • Публичный • %1$d видео Нет совместимого аудиопотока – загрузка невозможна Трек • %1$s Поиск распознанных треков @@ -1653,10 +1610,8 @@ %1$d dp LyricsPlus В данный момент заблокировано - Тем: %1$d Удалить %1$s Разблокировать %1$s - %1$d выбрано Выбор Контроль времени Отслеживайте и контролируйте экранное время @@ -1710,7 +1665,6 @@ Косвенные предпочтения из вашей истории просмотра Фильтры Экспорт данных профиля - Треков: %1$d • %2$s %1$s • %2$s Explicit • %1$s @@ -1743,7 +1697,6 @@ Плейлист • %1$s • %1$s прослушиваний Альбом • %1$s • %2$s - Исполнитель • %1$s слушателей за месяц Поиск: %1$s Исполнитель: %1$s Полный экран @@ -1837,7 +1790,6 @@ Интерес к стримам Какое количество стримов подходит вашему профилю Разнообразие тем - Тем в глобальном векторе: %1$d Значимость предпочтений Самые значимые темы после проверки испытательного срока и исходных данных Значимость тем еще не рассчитана. @@ -2149,7 +2101,6 @@ Версия %1$s Доступна новая версия Flow (%1$s). Скачать последнюю версию APK? Плейлист пуст - Скачивается %1$d видео… Плейлист добавлен в библиотеку Плейлист удален из библиотеки Скачивание аудио: %1$s кбит/с (%2$s) @@ -2173,10 +2124,8 @@ Плейлист удален Плейлист переименован Начинается скачивание: %1$s… - Из плейлиста «%2$s» скачано треков: %1$d Не удалось скачать плейлист Ошибка скачивания плейлиста - Скачано треков: %1$d Добавлено в плейлист Не удалось добавить трек Удалено из плейлиста @@ -2193,7 +2142,6 @@ Сбой скачивания Еще %1$d Новые видео - Новых видео в подписках: %1$d Доступно обновление: %1$s Нажмите для обновления до последней версии. Напоминание «Смотреть позже» @@ -2263,7 +2211,6 @@ Управление резервными копиями Flow Сторонние сервисы Импорт из других клиентов YouTube - Импорт (%2$s): %1$d Успешно импортировано: %1$s Импорт: %1$s… Импортировано из Google Архиватора @@ -2320,7 +2267,6 @@ Не удалось загрузить новые видео с этих каналов: %1$s изменено %1$s (%2$s) - %1$d ч Оригинал Дубляж Нет сохраненных Shorts @@ -2334,7 +2280,6 @@ Неподдерживаемый формат – убедитесь, что выбрали корректный файл Ошибка импорта: %1$s %1$d ч %2$d мин - %1$d мин %1$dч %1$dмин Жест перемотки @@ -2377,7 +2322,6 @@ Объединить библиотеку другого устройства с текущей. Выбрать все Сбросить выбор - Выбрано: %1$d из %2$d Ваши плейлисты, альбомы и отложенные видео. История просмотра и прогресс воспроизведения. «Нравится» и «Не нравится» для видео и музыки. diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si/strings.xml index 390089692..7bc947431 100644 --- a/app/src/main/res/values-si/strings.xml +++ b/app/src/main/res/values-si/strings.xml @@ -12,8 +12,6 @@ තවම දායකත්වයන් නොමැත නාලිකා නැරඹීමට දායක වන්න\nනවතම වීඩියෝ නරඹන්න ෆීඩ් එක අලුත් කරන්න - නැවුම් කරමින් %1$d වල %2$d නාලිකා - අවසන් වරට නැවුම් කළේ %1$s-%2$d වීඩියෝ පරීක්ෂා කරන ලදී අවසන් වරට නැවුම් කළේ %1$s නැවත උත්සාහ කරන්න ලොග් පිටපත් කරන්න @@ -84,7 +82,6 @@ බාගත කරන ලද බාගත කරන්න සියල්ල බාගත කරන්න - සියලු %1$dවීඩියෝ බගත කරන්නද ? මෙය සැලකිය යුතු ඉඩක් වැයකරයි. සුරකින්න සුරකින ලද හිමිකාරීත්වය දරන diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index c0a2af239..6f4038d78 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -11,8 +11,6 @@ Нема претплата Претплатите се на канале да видите\nњихове најновије снимке овде Освежи фид - Освежује се %1$d од %2$d канала - Последњи пут освежено %1$s - %2$d снимака проверених Последњи пут освежено %1$s Покушај поново Копирај логове diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 3c1165b66..e0e88db04 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -123,7 +123,6 @@ Beğenilen müzik yok Beğendiğin şarkılar burada görünecek Hepsini indir - %1$d videonun tümünü indirmek istiyor musun? Bu işlem önemli miktarda depolama alanı kaplayabilir. Kaydedildi Devam et Şuradan oynatılıyor @@ -143,7 +142,6 @@ Gizli Görüntülemeler Son videoları görmek için\nkanala abone ol - Son yenilenme %1$s - %2$d video kontrol edildi Şu parçaya göz at: %1$s - %2$s\nhttps://music.youtube.com/watch?v=%3$s Herkese açık Yeni oynatma listesi oluştur @@ -186,7 +184,6 @@ Devamını oku Yanıtla Yanıtları gizle - %1$d yanıtı gör Daha fazla yanıt gör Metin seç Sabitlenmiş yorum @@ -204,7 +201,6 @@ Bildirimler Ara Ayarlar - %1$d / %2$d kanal yenileniyor Açıklama Açıklamayı kopyala Açıklama panoya kopyalandı @@ -218,11 +214,6 @@ 9+ NewPipe Yedeğini içe aktar NewPipe yedeğinden abonelikler içe aktarılıyor... - %1$d video - %1$d beğeni - %1$d oynatma listesi - %1$d shorts - %1$d şarkı İçerik üretici tarafından sabitlendi Sanatçı seç Albüm kapağı @@ -332,7 +323,6 @@ Daha fazla Bölümler Kişiselleştirilmiş akışınız - %1$d video senin için özenle seçildi Hepsi Grupları Yönet Yeni Grup @@ -344,7 +334,6 @@ Henüz indirme yok Hepsini oynat Daha Sonra İzle\'den kaldır - Oynatma listesi • Özel • %1$d video E Sırala Beğeniyi Kaldır @@ -470,8 +459,6 @@ Gördüklerini özelleştir İlgi alanları Engellendi - %1$d konu - %1$d gizli İlgi Alanların Seçtiğin konular Flow\'un daha iyi içerik önermesine yardımcı olur. Eklemek veya kaldırmak için aşağıdaki konulara dokun. Takip Edilenler @@ -487,10 +474,8 @@ Hızlı Ekle Sık engellenen konular Şu anda Engelli - %1$d konu %1$s Konusunu kaldır %1$s için engellemeyi kaldır - %1$d seçildi Zaman yönetimi Ekran süreni takip ve kontrol et İstatistikler, bu uygulamadaki izleme geçmişine dayanır... @@ -501,12 +486,10 @@ Başlangıç saatinde bildirim gönderilecek. Ara vermem gerektiğini hatırlat Hatırlatma sıklığı - Her %1$d dakikada bir Günlük Ortalama Bugün Son 7 gün Sıklık - Her %1$d dakikada bir Bu Hafta Toplam: %s saat Henüz hiçbir şey izlenmedi @@ -522,7 +505,6 @@ Onayla Uyku Zamanlayıcısı Zamanlayıcı Süresi - %1$d dakika 5 dakika 120 dakika Özel süre @@ -544,31 +526,24 @@ Arama Önerileri Yazma esnasında önerileri görüntüle Maksimum Geçmiş Boyutu - Şu anda: %1$d arama Geçmişi Otomatik Sil - %1$d gün geçince sil Asla otomatik silme Saklama Süresi - %1$d günden eski aramaları sil Arama Geçmişini Temizle Tüm arama geçmişini temizle Arama Geçmişini Temizle? Tüm arama geçmişini kalıcı olarak sil. Kaç arama sonucunu saklamak istediğini seç: - %1$d arama Şundan daha eski aramaları sil: 1 hafta 1 ay 3 ay 6 ay 1 yıl - %1$d gün Verileri İçe Aktar Flow yedeği başarıyla içe aktardı Flow yedeği içe aktarılamadı: %1$s - NewPipe\'tan %1$d abonelik içe aktarıldı NewPipe yedeklemesi içe aktarılamadı: %1$s - YouTube\'dan %1$d abonelik içe aktarıldı YouTube yedeklemesi içe aktarılamadı: %1$s Flow yedeğini içe aktar Geçmişini, ayarlarını ve aboneliklerini bir Flow yedeğinden geri yükle. @@ -609,8 +584,6 @@ Karanlık Kişiselleştirilmiş Özel - Toplam %1$d tema - %1$d %2$s tema Uygulandı: %1$s Temayı Kişiselleştir Kişiselleştirilmiş Tema Düzenleyicisi @@ -884,10 +857,8 @@ Döngü (mevcut videoyu tekrarla) Sonrakini Otomatik Oynat (bir sonraki Shorts\'a geç) Belirlenen süre sonrası otomatik kaydırma - Her %1$d saniyede bir otomatik kaydır Shorts Oynatma Modu İzlenen Shorts videosu bittiğinde uygulamanın ne yapacağını seç: - %1$d saniye Otomatik Oynatma Sonraki videoyu otomatik oynat Sessiz Bölümleri Atla @@ -1025,9 +996,7 @@ YouTube Takeout\'un CSV\'sinden (Playlist-.csv) bir oynatma listesini içe aktar. YouTube Music Oynatma Listesini İçe Aktar YouTube Music Takeout\'un CSV\'sinden bir müzik oynatma listesini içe aktar. Müzik Oynatma Listeleri altında görünür. - YouTube izleme geçmişinden %1$d kayıt içe aktarıldı İzleme geçmişi içe aktarılamadı: %1$s - %2$d videodan oluşan “%1$s” isimli oynatma listesi içe aktarıldı Oynatma listesi içe aktarılamadı: %1$s Dosyada hiçbir izleme geçmişi kaydı bulunamadı. YouTube Takeout\'tan watch-history.html dosyası olduğundan emin ol. Bu CSV\'de hiç video bulunamadı. YouTube Takeout\'tan oynatma listesi CSV dosyası olduğundan emin ol. @@ -1058,7 +1027,6 @@ Paralel İndirme Maksimum hız için dosyaları birden fazla parça halinde indir. Eşzamanlı İş Parçacıkları - İndirme başına %1$d iş parçacığı Daha fazla iş parçacığı kullanmak hızı artırabilir ancak daha fazla pil tüketebilir ve cihazı ısıtabilir. İndirilen dosyaların cihazında nereye kaydedileceğini seç. Ön Ayarlı Konumlar @@ -1077,7 +1045,6 @@ Önerilen Etkin İş parçacığı sayısını seç (1-8): - %1$d iş parçacığı Destek & Bağışlar Flow\'un Geliştirilmesine Destek Olun Flow\'u yararlı buluyorsan ve projenin geliştirilmesine destek olmak istiyorsan, Patreon üzerinden destek verebilir veya aşağıdaki kripto adreslerine bağışta bulunabilirsin. Desteğin, projenin devam etmesine önayak olur! @@ -1133,8 +1100,6 @@ Oynatıcıdan videolar ekleyerek\noynatma listeni oluştur Oynatma listesi silinsin mi? Bu işlem, \'%1$s\' oynatma listesini ve içindeki tüm videoları kalıcı olarak silecek. - Oynatma Listesi • Gizli • %1$d video - Oynatma Listesi • Herkese Açık • %1$d video Oynatma listesi sıralama seçenekleri Manuel Eklenme tarihi (en yeni) @@ -1142,13 +1107,11 @@ En popüler Yayınlanma tarihi (en yeni) Yayınlanma tarihi (en eski) - %1$d video kaldırılsın mı? Bu oynatma listesinden kaldırılacaklar. Daha sonra izle listesinden kaldırılacaklar. Flow\'a Hoş Geldin Bize ilgi alanlarını söyle Deneyimini kişiselleştirmek için en az 3 konu seç - %1$d seçildi (%2$d daha gerekli) Şimdilik geç Devam et Daralt @@ -1186,7 +1149,6 @@ Etkileşimler Konular İlgi alanı uzayını doldurmak için birkaç video izle! - %1$d etkileşimler • Seviye %2$d Profil Verilerini Dışa Aktar Flow Sinir Profili Dışa Aktarımı Müzik Kitaplığı @@ -1206,8 +1168,6 @@ %1$s • %2$s görüntüleme Tümünü gör Ara - %1$s görüntüleme - %1$d parça• %2$s Bilinmeyen hata Tekrar dene Ruh hali ve türler mevcut değil @@ -1296,7 +1256,6 @@ Oynatma Listesi • %1$s • %1$s çalma Albüm • %1$s • %2$s - Sanatçı • Aylık %1$s dinleyici Arama: %1$s Sanatçı: %1$s Sizin için en iyi seçimler @@ -1309,7 +1268,6 @@ Henüz Favori Yok Favorilerine eklemek için herhangi bir parçadaki kalp simgesine dokun Henüz Geçmiş Yok - %1$d favori parça Geçmişini burada görmek için müzik dinlemeye başla Henüz indirme yok Çevrimdışı dinlemek için parçaları indir @@ -1355,7 +1313,6 @@ Başarısız İptal edildi Tamamlanmamış indirmeleri kaldır - %1$d duraklatılmış, başarısız veya kısmi indirme kaldırılsın mı? Tamamlanan indirmeler etkilenmez. Ses Parçası Kapalı Açık @@ -1510,7 +1467,6 @@ Rapor panoya kopyalandı Oynatma listeme ekle Tüm şarkıları şuraya ekle… - %1$d şarkı “%2$s” listesine eklendi Henüz oynatma listesi yok. Önce bir tane oluştur! Profil başarıyla dışa aktarıldı Dışa aktarma başarısız oldu @@ -1546,7 +1502,6 @@ Canlı yayın ilgisi Canlı içeriğin profile ne kadar uyduğu Konu genişliği - Küresel vektörde %1$d konu İlgi Ağırlıkları Gözlem ve kanıtlardan sonra en yüksek ağırlığa sahip konular Henüz konu ağırlığı yok. @@ -1778,7 +1733,6 @@ Oynatma listesindeki veya Daha Sonra İzle kuyruğundaki sonraki videoyu otomatik olarak oynat. Kapalıyken de elle sonraki videoya geçebilirsin. Otomatik oynatma gecikmesi Yok (hemen geç) - %1$d saniye Sonraki videoya otomatik geçmeden önce geri sayım göster. Geri sayım sırasında mevcut videoyu baştan başlatabilir, geçişi iptal edebilir veya sonraki videoyu hemen oynatabilirsin. Sıradaki Sonraki video @@ -1807,14 +1761,12 @@ Kanallarda ara… Aramak için bir kanal adı yaz %1$s için kanal bulunamadı - %1$d kanal eklendi %1$s abone Abone olundu Abone ol Verilerini içe aktar Aboneliklerini ve geçmişini diğer uygulamalardan getir. Tüm adımlar isteğe bağlıdır. Yedekleme ve geri yükleme - %1$d seçildi Seçili Seçili değil İçe aktarma başarısız: %1$s @@ -2004,7 +1956,6 @@ Flow\'un yeni bir sürümü mevcut (%1$s). En son APK indirilsin mi? E N S T R Ü M A N T A L Oynatma listesi boş - %1$d video indiriliyor… Oynatma listesi kitaplığa kaydedildi Oynatma listesi kitaplıktan kaldırıldı Ses indiriliyor: %1$skbps %2$s @@ -2026,10 +1977,8 @@ Oynatma listesi silindi Oynatma listesinin adı değiştirildi %1$s için indirme başlatılıyor… - %2$s listesinden %1$d parça indirildi Oynatma listesi indirilemedi Oynatma listesi indirilirken hata oluştu - %1$d parça indirildi Oynatma listesine eklendi Parça eklenemedi Oynatma listesinden kaldırıldı @@ -2046,7 +1995,6 @@ İndirme başarısız +%1$d daha Yeni videolar - Aboneliklerinden %1$d yeni video Güncelleme mevcut: %1$s En son sürüme güncellemek için dokun. Daha Sonra İzle hatırlatıcısı @@ -2117,7 +2065,6 @@ Flow yedeklerini yönet Harici hizmetler Diğer YouTube istemcilerinden içe aktar - %1$d %2$s içe aktarıldı %1$s başarıyla içe aktarıldı %1$s içe aktarılıyor… Google Takeout\'tan içe aktarıldı diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index e6be7d71a..a74ab6201 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -101,7 +101,6 @@ Читати більше Відповісти Сховати відповіді - Переглянути %1$d відповідей Закріплений коментар Закріплено автором Нове оновлення доступне @@ -143,15 +142,10 @@ Список відтворення 9+ Ваша персоналізована стрічка - %1$d відео, підібраних спеціально для вас Імпорт резервної копії NewPipe Імпорт підписок з резервної копії NewPipe... Пошук підписок Перемикання режиму перегляду - %1$d відео - %1$d списків відтворення - %1$d shorts - %1$d пісень Завантажень поки що немає Відтворити все Видалити з «Переглянути пізніше» @@ -332,7 +326,6 @@ Частини FLOW Відписано від %1$s - Список відтворення • Приватний • %1$d відео Нещодавні пошуки Кінець результатів Аватарка каналу @@ -406,8 +399,6 @@ Темна Власна Спеціальна - %1$d тем - %1$d %2$s тем Застосовано: %1$s Редактор тем Скинути @@ -746,8 +737,6 @@ Налаштуйте те, що бачите Інтереси Заблоковано - %1$d тем - %1$d приховано Ваші інтереси Вибрані теми допомагають Flow краще рекомендувати контент. Натисніть на теми нижче, щоб додати або видалити їх. Поточні підписки @@ -763,10 +752,8 @@ Швидке додавання Теми для блоку Зараз заблоковано - %1$d тема %2$s Видалити %1$s Розблокувати %1$s - %1$d вибрано Керування часом Відстежуйте й контролюйте кранний час Статистика базується на історії переглядів у цьому застосунку. Фактичні дані можуть відрізнятися. @@ -777,12 +764,10 @@ Сповіщення надійде в момент початку. Нагадувати ро перерву Періодичність нагадувань - Кожні %1$d хвилин Середньодобовий показник Сьогодні Останні 7 днів Частота - Кожні %1$d хвилин Цього тижня Загалом: %s год Дані перегляду відсутні @@ -797,7 +782,6 @@ Час пробудження Таймер сну Тривалість - %1$d хвилин 5 хвилин 120 хвилин Власний час @@ -859,31 +843,24 @@ Вкладка пошуку в навігації Вкладка «Дослідити» в навігації Продовжити перегляд в мініпрогравачі - Зараз: %1$d пошуків Автовидалення історії - Видалити після %1$d днів Ніколи не видаляти автоматично Термін зберігання - Видалити пошуки старіші за %1$d днів Очистити історію пошуку Видалити всі пошукові запити Очистити історію пошуку? Назавжди видалити всю іторію пошуку. Виберіть скільки пошуків залишити: - %1$d пошуків Видалити пошуки старші за: 1 тиждень 1 місяць 3 місяці 6 місяців 1 рік - %1$d днів Імпортувати дані Резервна копію Flow успішно імпортована Не вдалось імпортувтаи резервну копію Flow: %1$s - Імпортовано %1$d відписок з NewPipe Не вдалось імпортувати резервну копію NewPipe: %1$s - Імпортовано %1$d підписок з YouTube Не вдалось імпортувати резервну копію YouTube: %1$s Імпортувати резервну копію Flow Відновіть історію, налаштування та підписки з файлу резервної копії Flow. @@ -913,8 +890,6 @@ Імпортуйте плейліст із YouTube Takeout CSV (Playlist-<назва>.csv). Імопртувати списки відтворення YouTube Music Імпортуйте музичний список відтворення із YouTube Music Takeout CSV. Він з’явиться у розділі «Списки музики». - Імпортовано %1$d записів з вашої історії переглядів YouTube - Імпортовано список відтворення «%1$s» з %2$d відео Продовжити Дозволи Доступ до файлів @@ -945,7 +920,6 @@ Паралельне завантаження Завантажуйте файли кількома частинами для максимальної швидкості. Паралельні потоки - %1$d потоків на завантаження Використання більшої кількості потоків може збільшити швидкість, але може споживати більше акумулятора та нагрівати пристрій. Виберіть місце збереження завантажених файлів на вашому пристрої. Стандартні розташування @@ -960,7 +934,6 @@ Введіть абсолютний шлях, наприклад /storage/emulated/0/MyFolder Активно Виберіть кількість потоків (1–8): - %1$d потоків Підтримка та пожертви Підтримайте розробку Flow Якщо Flow є корисним для вас і ви хочете підтримати його розробку, ви можете зробити це на Patreon або за допомогою криптовалют за адресами нижче. Ваша підтримка допомагає проєкту жити! @@ -1016,12 +989,9 @@ Додавайте відео прямо з програвача,\nщоб створити свій список відтворення Видалити список відтворення? Це назавжди видалить «%1$s» і всі його відео. - Список відтворення • Приватний • %1$d відео - Список відтворення • Приватний • %1$d відео Вітаємо у Flow Розкажіть нам, що вас цікавить Оберіть принаймні 3 теми, щоб персоналізувати досвід - Вибрано: %1$d (потрібно ще %2$d) Пропустити Продовжити Згорнути @@ -1059,7 +1029,6 @@ Взаємодії Теми Перегляньте кілька відео, щоб сформувати ваш профіль інтересів! - %1$d взаємодій • Рівень %2$d Експортувати дані профілю Експорт нейронного профілю Flow Музична бібліотека @@ -1079,8 +1048,6 @@ %1$s • %2$s переглядів Показати все Пошук - %1$s переглядів - %1$d пісень • %2$s Невідома помилка Повторити Немає доступних настроїв та жанрів @@ -1155,7 +1122,6 @@ Список відтворення • %1$s • %1$s грає Альбом • %1$s • %2$s - Артист • %1$s слухачів за місяць Пошук: %1$s Виконавець: %1$s Найкраще для вас @@ -1167,7 +1133,6 @@ Створіть ваш перший список, щоб впорядкувати ваші обрані пісні Обрані пісні відсутні Тисни на «значок серця», щоб додати пісню до «Обраного» - %1$d обраних пісень Історія відсутня Почніть прослуховувати музику, щоб побачити історію тут Завантаження відсутні @@ -1255,15 +1220,12 @@ Зберегти Рекомендовано Завантажити все - Завантажити всі %1$d відео? Це може зайняти багато місця. Назва скопійована Увімкнути сповіщення Дозволити Flow працювати і фоні для перевірки сповіщень Фонові перевірки сповіщень вимкнені Адаптивний розмір програвача Отримати кількість дизлайків з Return YouTube Dislike - Оновлення %1$d з %2$d каналів - Останнє оновлення %1$s: перевірено %2$d відео Пошук в історії переглядів Всі роки Спочатку найновіші @@ -1277,7 +1239,6 @@ Вподобані пісні з’являться тут Сховати Shorts з цього каналу Показати Shorts з цього каналу - %1$d лайків Тема системи Виберіть тему, яка використовуватиметься під час перемикання пристрою між світлим і темним режимами. Світла тема @@ -1309,8 +1270,6 @@ Порядок вкладок і типова вкладка Змінюйте порядок вкладок стрілками. Виберіть головну вкладку перемикачем. Автогортання через заданий час - Автогортання кожні %1$d - %1$d секунд Return YouTube Dislike Підписки Історія @@ -1372,7 +1331,6 @@ Запам’ятати яскравість Повторно використати останній рівень яскравості програвача для наступних відео Дата публікації (найстаріші) - Видалити %1$d відео? Вони будуть видалені зі списку. Вони будуть видалені з «Переглянути пізніше». Автоматично %1$d секунд @@ -1426,7 +1384,6 @@ Живі виступи Настрій та жанри Свіжа добірка з ваших прослуховувань - Видалити %1$d призупинених, невдалих або часткових завантажень? Завершені завантаження залишаться незмінними. Потрібна CAPTCHA YouTube YouTube запитує перевірку бота. Відкрийте YouTube у браузері та розв’яжіть CAPTCHA, а потім спробуйте ще раз. Тип контенту не підтримується @@ -1498,7 +1455,6 @@ Звіт скопійований до буферу Додати до списку Додати всі пісні до… - Додано %1$d пісень до «%2$s» Списки відтворення відсутні. Створіть перший! Профіль успішно експортовано Експорт не вдався @@ -1562,7 +1518,6 @@ Прихильність до трансляцій Скільки прямих трансляцій відповідає профілю Широта тем - %1$d тем у глобальному векторі Вага інтересів Найвагоміші теми після випробувального терміну та перевірки ознак Ваги тем відсутні. @@ -1683,7 +1638,6 @@ Показувати елементи керування програвачем до завершення завантаження відео, аби ви мали змогу відразу налаштувати гучність Затримка автовідтворення Немає (миттєвий перехід) - %1$d с Показувати зворотний відлік перед автоматичним переходом до наступного відео. Під час відліку ви можете перезапустити поточне відео, скасувати перехід або одразу ввімкнути наступне. Наступне Наступне відео @@ -1814,14 +1768,12 @@ Пошук каналів… Введіть ім\'я каналу для пошуку Збігів з \"%1$s\" не знайдено - %1$d каналів додано %1$s підписників Підписано Підписатись Імпортуйте ваші дані Перенесіть ваші підписки та історію з інших додатків. Все необов\'язкове. Резервне копіювання та відновлення - %1$d вибрано Вибрано Не вибрано Імпорт не вдався: %1$s @@ -2178,7 +2130,6 @@ Доступна нова версія Flow (%1$s). Завантажити останній APK-файл? І Н С Т Р У М Е Н Т А Л Список відтворення пустий - Завантаження %1$d відео… Список відтворення збережено до бібліотеки Список відтворення вилучено з бібліотеки Завантаження аудіо: %1$s кбіт/с %2$s @@ -2200,10 +2151,8 @@ Список відтворення видалено Список відтворення перейменовано Початок завантаження %1$s… - Завантажено %1$d треків з %2$s Не вдалося завантажити список Помилка завантаження списку - Завантажено %1$d треків Додано до списку відтворення Не вдалося додати трек Видалено зі списку відтворення @@ -2220,7 +2169,6 @@ Завантаження не вдалося + %1$d Нові відео - %1$d нових відео з ваших підписок Доступне оновлення: %1$s Натисніть, щоб оновити до останньої версії. Нагадування «Переглянути пізніше» @@ -2291,7 +2239,6 @@ Керуйте резервними копіями Flow Зовнішні сервіси Імпорт з інших клієнтів YouTube - Імпортовано (%2$s): %1$d %1$s успішно імпортовано Імпортування %1$s… Імпортовано з Google Takeout @@ -2323,7 +2270,6 @@ %1$s та ще %2$d редаговано %1$s (%2$s) - %1$d годин Оригінал Дубльовано Збережених Shorts ще немає @@ -2337,7 +2283,6 @@ Нерозпізнаний формат резервної копії — переконайтеся, що ви вибрали правильний файл Помилка імпорту: %1$s %1$d год %2$d хв - %1$d хв %1$d год %1$d хв Жест перемотування @@ -2380,7 +2325,6 @@ Об’єднати бібліотеку іншого пристрою з цією. Вибрати все Очистити - Вибрано %1$d з %2$d Ваші списки відтворення, альбоми та «Переглянути пізніше». Що ви подивилися і на якому моменті зупинилися. Відео та музика, які сподобалися або не сподобалися. diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index b7b5283a9..941c7cac4 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -12,8 +12,6 @@ Chưa có kênh nào Đăng ký kênh để xem video\nmới nhất tại đây Làm mới - Đang làm mới %1$d/%2$d kênh - Làm mới lần cuối %1$s - %2$d video được kiểm tra Làm mới lần cuối %1$s Thử lại Sao chép nhật ký @@ -81,7 +79,6 @@ Đã tải xuống Tải xuống Tải tất cả - Tải xuống tất cả %1$d video? Có thể tốn nhiều bộ nhớ. Lưu Đã lưu Thêm vào thư viện @@ -238,7 +235,6 @@ Xem thêm Trả lời Ẩn trả lời - Xem %1$d trả lời Tải thêm trả lời Chọn văn bản Bình luận ghim @@ -296,7 +292,6 @@ FLOW 9+ Nguồn cấp cá nhân hóa - %1$d video được tuyển chọn riêng cho bạn Nhập sao lưu NewPipe Đang nhập danh sách đăng ký từ NewPipe… Tìm kênh đã đăng ký @@ -312,15 +307,9 @@ Đã hủy đăng ký %1$s Ẩn Shorts từ kênh này Hiện Shorts từ kênh này - %1$d video - %1$d lượt thích - %1$d danh sách phát - %1$d shorts - %1$d bài hát Chưa có tải xuống Phát tất cả Xóa khỏi Xem sau - Danh sách phát • Riêng tư • %1$d video E Chưa có video lưu Video bạn lưu để xem sau sẽ xuất hiện tại đây @@ -503,8 +492,6 @@ Tối Tùy chỉnh Đặc biệt - %1$d chủ đề - %1$d chủ đề %2$s Đã áp dụng: %1$s Tùy chỉnh chủ đề Trình chỉnh sửa chủ đề @@ -842,17 +829,14 @@ Lặp lại Tự động phát tiếp Tự động cuộn sau khoảng thời gian tùy chỉnh - Tự động cuộn mỗi %1$d giây Chế độ phát Shorts Chọn hành vi của Shorts sau khi kết thúc: - %1$d giây Tự động phát video liên quan Khi không có hàng chờ, tự động phát video gợi ý tiếp theo Tự động phát video trong hàng chờ Tự động phát video tiếp theo trong danh sách phát hoặc Xem sau. Khi tắt, bạn vẫn có thể tua thủ công. Độ trễ tự động phát Không (chuyển ngay) - %1$d giây Hiển thị đếm ngược trước khi chuyển video tự động. Trong thời gian đó bạn có thể khởi động lại, hủy hoặc phát ngay. Tiếp theo Video tiếp @@ -1029,8 +1013,6 @@ Tùy chỉnh những gì bạn thấy Sở thích Đã chặn - %1$d chủ đề - %1$d ẩn Sở thích của bạn Chủ đề bạn chọn giúp Flow gợi ý tốt hơn. Chạm để thêm hoặc bớt. Đang theo dõi @@ -1046,10 +1028,8 @@ Thêm nhanh Chủ đề thường chặn Đang chặn - %1$d chủ đề%2$s Xóa %1$s Bỏ chặn %1$s - Đã chọn %1$d Chọn Hủy chọn Chọn tất cả @@ -1065,12 +1045,10 @@ Thông báo sẽ được gửi vào giờ bắt đầu. Nhắc nhở nghỉ giải lao Tần suất nhắc - Mỗi %1$d phút Trung bình ngày Hôm nay 7 ngày qua Tần suất - Mỗi %1$d phút Tuần này Tổng: %s giờ Chưa có dữ liệu xem @@ -1086,7 +1064,6 @@ Xác nhận Hẹn giờ ngủ Thời lượng - %1$d phút 5 phút 120 phút Tùy chỉnh @@ -1108,31 +1085,24 @@ Gợi ý tìm kiếm Hiện gợi ý khi đang nhập Số lượng tìm kiếm tối đa - Hiện: %1$d tìm kiếm Tự động xóa lịch sử - Xóa sau %1$d ngày Không bao giờ tự xóa Thời gian lưu - Xóa tìm kiếm cũ hơn %1$d ngày Xóa lịch sử tìm kiếm Xóa tất cả truy vấn Xóa lịch sử tìm kiếm? Xóa vĩnh viễn tất cả lịch sử tìm kiếm. Chọn số lượng tìm kiếm cần giữ: - %1$d tìm kiếm Xóa tìm kiếm cũ hơn: 1 tuần 1 tháng 3 tháng 6 tháng 1 năm - %1$d ngày Nhập dữ liệu Đã nhập sao lưu Flow Không nhập được sao lưu: %1$s - Đã nhập %1$d kênh từ NewPipe Không nhập được từ NewPipe: %1$s - Đã nhập %1$d kênh từ YouTube Không nhập được từ YouTube: %1$s Nhập sao lưu Flow Phục hồi lịch sử, cài đặt và đăng ký từ file sao lưu Flow. @@ -1168,9 +1138,7 @@ Nhập danh sách phát từ file CSV YouTube Takeout (Playlist-<tên>.csv). Nhập danh sách phát YouTube Music Nhập danh sách phát nhạc từ file CSV YouTube Music Takeout. Xuất hiện trong Danh sách phát nhạc. - Đã nhập %1$d mục từ lịch sử YouTube Không nhập được lịch sử: %1$s - Đã nhập danh sách %1$s với %2$d video Không nhập được danh sách: %1$s Không tìm thấy mục lịch sử nào trong file. Hãy chắc chắn đây là file watch-history.html của YouTube Takeout. Không tìm thấy video nào trong CSV. Hãy chắc chắn đây là file CSV danh sách phát YouTube Takeout. @@ -1203,7 +1171,6 @@ Tải song song Tải nhiều phần để tăng tốc. Số luồng đồng thời - %1$d luồng mỗi tải Nhiều luồng có thể tăng tốc nhưng tốn pin và nóng máy. Chọn nơi lưu tệp tải xuống. Vị trí có sẵn @@ -1222,7 +1189,6 @@ Đề xuất Đang dùng Chọn số luồng (1-8): - %1$d luồng Hỗ trợ & Quyên góp Hỗ trợ phát triển Flow Nếu bạn thấy Flow hữu ích và muốn hỗ trợ phát triển, bạn có thể ủng hộ qua Patreon hoặc quyên góp qua địa chỉ tiền mã hóa bên dưới. Sự hỗ trợ của bạn giúp dự án tồn tại! @@ -1289,8 +1255,6 @@ Thêm video từ trình phát\nto build your playlist Xóa danh sách phát? Thao tác này xóa vĩnh viễn \'%1$s\' và tất cả video trong đó. - Danh sách phát • Riêng tư • %1$d video - Danh sách phát • Công khai • %1$d video Tùy chọn sắp xếp Thủ công Ngày thêm (mới nhất) @@ -1298,13 +1262,11 @@ Phổ biến nhất Ngày đăng (mới nhất) Ngày đăng (cũ nhất) - Xóa %1$d video? Chúng sẽ bị xóa khỏi danh sách này. Chúng sẽ bị xóa khỏi Xem sau. Chào mừng đến Flow Cho chúng tôi biết bạn thích gì Chọn ít nhất 3 chủ đề để cá nhân hóa - Đã chọn %1$d (cần thêm %2$d) Bạn thích gì? Chọn ít nhất %1$d chủ đề để cá nhân hóa. Cần thêm %2$d. Lựa chọn tuyệt vời. Bạn có thể thay đổi sau trong cài đặt. @@ -1313,14 +1275,12 @@ Tìm kênh… Nhập tên kênh để tìm Không tìm thấy kênh cho %1$s - Đã thêm %1$d kênh %1$s người đăng ký Đã đăng ký Đăng ký Nhập dữ liệu Mang đăng ký và lịch sử từ ứng dụng khác. Mọi thứ đều tùy chọn. Sao lưu & Phục hồi - Đã chọn %1$d Đã chọn Chưa chọn Nhập thất bại: %1$s @@ -1384,7 +1344,6 @@ Tương tác Chủ đề Xem một số video để xây dựng đám mây sở thích! - %1$d tương tác • Cấp %2$d Xuất dữ liệu hồ sơ Xuất hồ sơ thần kinh Flow Thư viện nhạc @@ -1404,8 +1363,6 @@ %1$s • %2$s lượt xem Xem tất cả Tìm kiếm - %1$s lượt xem - %1$d bài hát • %2$s Lỗi không xác định Thử lại Không có tâm trạng & thể loại @@ -1497,7 +1454,6 @@ Danh sách • %1$s • %1$s lượt phát Album • %1$s • %2$s - Nghệ sĩ • %1$s người nghe Tìm: %1$s Nghệ sĩ: %1$s Lựa chọn hàng đầu cho bạn @@ -1509,7 +1465,6 @@ Tạo danh sách phát đầu tiên để sắp xếp bài hát yêu thích Chưa có yêu thích Chạm biểu tượng trái tim trên bài hát để thêm vào yêu thích - %1$d bài hát yêu thích Chưa có lịch sử Bắt đầu nghe nhạc để xem lịch sử ở đây Chưa có tải xuống @@ -1567,7 +1522,6 @@ Thất bại Đã hủy Xóa tải chưa hoàn tất - Xóa %1$d tải đang tạm dừng, thất bại hoặc chưa hoàn tất? Các tải hoàn tất sẽ không bị ảnh hưởng. Luồng âm thanh %1$s %2$d %1$s (%2$s) @@ -1800,7 +1754,6 @@ Đã sao chép báo cáo Thêm vào danh sách của tôi Thêm tất cả bài hát vào… - Đã thêm %1$d bài hát vào %2$s Chưa có danh sách phát. Hãy tạo một cái! Xuất hồ sơ thành công Xuất thất bại @@ -1836,7 +1789,6 @@ Thích phát trực tiếp Mức độ phù hợp của nội dung trực tiếp Bề rộng chủ đề - %1$d chủ đề trong vectơ toàn cục Trọng số chủ đề Chủ đề có trọng số cao nhất sau khi kiểm tra Chưa có trọng số. @@ -2165,7 +2117,6 @@ Đã có phiên bản mới của Flow (%1$s). Tải APK? G I A I Đ I Ệ U Danh sách phát trống - Đang tải %1$d video… Đã lưu danh sách phát vào thư viện Đã xóa danh sách phát khỏi thư viện Đang tải âm thanh: %1$skbps %2$s @@ -2187,10 +2138,8 @@ Đã xóa danh sách phát Đã đổi tên danh sách phát Bắt đầu tải %1$s… - Đã tải %1$d bài hát từ %2$s Không tải được danh sách Lỗi tải danh sách - Đã tải %1$d bài hát Đã thêm vào danh sách Không thêm được Đã xóa khỏi danh sách @@ -2207,7 +2156,6 @@ Tải thất bại +%1$d Video mới - %1$d video mới từ kênh đã đăng ký Cập nhật: %1$s Chạm để cập nhật bản mới. Nhắc nhở Xem sau @@ -2278,7 +2226,6 @@ Quản lý bản sao lưu Flow Dịch vụ bên ngoài Nhập từ ứng dụng YouTube khác - Đã nhập %1$d %2$s %1$s đã nhập thành công Đang nhập %1$s… Đã nhập từ Google Takeout @@ -2309,7 +2256,6 @@ đã chỉnh sửa %1$s (%2$s) ...thêm - %1$d giờ Gốc Lồng tiếng Chưa có Shorts nào được lưu @@ -2323,7 +2269,6 @@ Không đọc được bản sao lưu — hãy đảm bảo bạn đã chọn đúng tệp Nhập thất bại: %1$s %1$d giờ %2$d phút - %1$d phút %1$dg %1$dp Thao tác tìm @@ -2366,7 +2311,6 @@ Gộp thư viện của một thiết bị khác vào thiết bị này. Chọn hết Dọn - Đã chọn %1$d trên %2$d Danh sách phát, album và Xem sau của bạn. Những gì bạn đã xem và tiến độ xem của bạn. Video và nhạc đã thích và không thích. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 36b52c564..e844489a1 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -12,8 +12,6 @@ 尚未订阅 订阅频道\n在此查看其最新视频 刷新订阅源 - 正在刷新 %1$d 个频道(共 %2$d 个) - 上次刷新于 %1$s - 已检查 %2$d 个视频 上次刷新于 %1$s 重试 复制日志 @@ -84,7 +82,6 @@ 已下载 下载 下载全部 - 下载所有 %1$d 视频?这可能会使用大量存储空间。 保存 已保存 我创建的 @@ -239,7 +236,6 @@ 了解更多 回复 隐藏回复 - 查看%1$d的回复 加载更多回复 选择文本 置顶评论 @@ -297,7 +293,6 @@ FLOW 9+ 您的个性化信息流 - %1$d 专为您策划的视频 导入NewPipe备份 正在从 NewPipe 备份导入订阅... 搜索订阅 @@ -313,15 +308,9 @@ 取消订阅 %1$s 从此频道隐藏 Shorts 从该频道显示 Shorts - %1$d 视频 - %1$d 次点赞 - %1$d 播放列表 - %1$d 个 Shorts - %1$d 歌曲 还没有下载 播放全部 从稍后观看中删除 - 播放列表 • 私密 • %1$d 个视频 E 没有保存视频 您保存以供稍后观看的视频将显示在此处 @@ -504,8 +493,6 @@ 深色 定制 特别 - %1$d 主题 - %1$d %2$s 主题 已应用:%1$s 定制主题 自定义主题编辑器 @@ -842,17 +829,14 @@ 循环(重复当前 Shorts) 自动播放下一个(前往下一个 Shorts) 自定义时间后自动滚动 - 每 %1$d 秒自动滚动一次 Shorts 播放模式 选择当前 Shorts 播放结束后的行为: - %1$d秒 自动播放相关视频 队列为空时,自动播放下一个推荐视频 自动播放排队的视频 自动播放播放列表或稍后观看队列中的下一个视频。关闭后,您仍然可以手动跳过。 自动播放延迟 无(立即切换) - %1$d秒 自动切换到下一个视频之前显示倒计时。在倒计时期间,您可以重新开始当前视频、取消切换或立即播放下一个视频。 接下来 下一个视频 @@ -1028,8 +1012,6 @@ 自定义您所看到的内容 兴趣 被阻止 - %1$d 主题 - %1$d隐藏 你的兴趣 您选择的主题有助于 Flow 推荐更好的内容。点击下面的主题可添加或删除它们。 目前正在关注 @@ -1045,10 +1027,8 @@ 快速添加 要阻止的常见主题 目前被阻止 - %1$d 主题%2$s 删除%1$s 解锁%1$s - %1$d 已选择 选择 取消选择 选择全部 @@ -1064,12 +1044,10 @@ 将在开始时间发送通知。 提醒我休息一下 提醒频率 - 每 %1$d 分钟 每日平均 今天 过去 7 天 频率 - 每 %1$d 分钟 本周 总计:%s 小时 还没有观看数据 @@ -1085,7 +1063,6 @@ 确认 睡眠定时器 持续时间 - %1$d 分钟 5分钟 120分钟 自定义时间 @@ -1107,31 +1084,24 @@ 搜索建议 输入时显示建议 最大历史记录大小 - 当前:%1$d 搜索 自动删除历史记录 - %1$d 天后删除 永不自动删除 保留期限 - 删除早于 %1$d 天的搜索 清除搜索历史记录 删除所有搜索查询 清除搜索历史记录? 永久删除所有搜索历史记录。 选择要保留的搜索数量: - %1$d 搜索 删除早于以下时间的搜索: 1周 1个月 3个月 6个月 1年 - %1$d天 导入数据 Flow 备份导入成功 无法导入 Flow 备份:%1$s - 从 NewPipe 导入 %1$d 订阅 无法导入 NewPipe 备份:%1$s - 从 YouTube 导入 %1$d 订阅 无法导入 YouTube 备份:%1$s 导入Flow备份 从 Flow 备份文件恢复您的历史记录、设置和订阅。 @@ -1167,9 +1137,7 @@ 从 YouTube Takeout CSV(Playlist-<名称>.csv)导入播放列表。 导入 YouTube Music 播放列表 从 YouTube Music Takeout CSV 导入音乐播放列表,并显示在“音乐播放列表”中。 - 从您的 YouTube 观看历史记录中导入了 %1$d 条目 导入观看记录失败:%1$s - 导入播放列表“%1$s”,其中包含 %2$d 视频 导入播放列表失败:%1$s 在此文件中找不到观看历史记录条目。确保它是 YouTube Takeout watch-history.html 文件。 在此 CSV 中未找到视频。确保它是 YouTube Takeout 播放列表 CSV 文件。 @@ -1202,7 +1170,6 @@ 并行下载 以多个块的形式下载文件以获得最大速度。 并发线程 - %1$d 每次下载线程数 使用更多线程可以提高速度,但可能会使用更多电池并导致设备升温。 选择下载的文件在设备上的保存位置。 预设位置 @@ -1221,7 +1188,6 @@ 推荐 活跃 选择线程数 (1-8): - %1$d 个线程 支持与捐赠 支持Flow开发 如果您发现 Flow 有用并愿意支持其开发,您可以在 Patreon 上支持它或通过下面的加密地址进行捐赠。您的支持有助于使项目保持活力! @@ -1283,8 +1249,6 @@ 从视频播放器 \n 添加视频来构建您的播放列表 删除播放列表? 这将永久删除“%1$s”及其所有视频。 - 播放列表 • 私密 • %1$d 个视频 - 播放列表 • 公开 • %1$d 个视频 播放列表排序选项 手动 添加日期(最新) @@ -1292,13 +1256,11 @@ 最受欢迎 发布日期(最新) 发布日期(最旧) - 删除 %1$d 视频吗? 它们将从该播放列表中删除。 它们将从“稍后观看”中移除。 欢迎来到Flow 告诉我们您对什么感兴趣 选择至少 3 个主题来个性化您的体验 - 已选择 %1$d 个(还需 %2$d 个) 你喜欢什么? 至少选择 %1$d 个主题来个性化您的信息流,还需选择 %2$d 个。 很棒的选择。您稍后可以随时在设置中更新此内容。 @@ -1307,14 +1269,12 @@ 搜索频道... 输入频道名称进行搜索 没有找到 \"%1$s\" 的频道 - 添加 %1$d 频道 %1$s订阅者 已订阅 订阅 导入您的数据 从其他应用程序获取您的订阅和历史记录。一切都是可选的。 备份与恢复 - %1$d 已选择 已选择 未选择 导入失败:%1$s @@ -1378,7 +1338,6 @@ 互动 主题 观看一些视频来填充您的兴趣星云! - %1$d 交互 • 级别 %2$d 导出画像数据 Flow 神经画像导出 音乐库 @@ -1398,8 +1357,6 @@ %1$s • %2$s 次观看 查看全部 搜索 - %1$s 浏览次数 - %1$d 首曲目 • %2$s 未知错误 重试 没有可用的情绪和流派 @@ -1488,7 +1445,6 @@ 播放列表 • %1$s • %1$s 次播放 专辑•%1$s•%2$s - 艺术家 • %1$s 每月观众 搜索:%1$s 艺术家:%1$s 您的热门精选 @@ -1500,7 +1456,6 @@ 创建您的第一个播放列表来整理您最喜爱的曲目 还没有收藏夹 点击任意曲目上的心形图标即可将其添加到您的收藏夹 - %1$d 首收藏曲目 还没有历史记录 在这里开始听音乐以查看您的历史记录 尚未下载 @@ -1558,7 +1513,6 @@ 失败 取消 删除不完整的下载 - 删除 %1$d 已暂停、失败或部分下载?已完成的下载将不会受到影响。 音轨 %1$s %2$d %1$s (%2$s) @@ -1792,7 +1746,6 @@ 报告已复制到剪贴板 添加到我的播放列表 将所有歌曲添加到... - 将%1$d歌曲添加到“%2$s” 还没有播放列表。先创建一个吧! 画像导出成功 导出失败 @@ -1828,7 +1781,6 @@ 直播偏好 直播内容与画像的匹配程度 主题广度 - %1$d 全局向量中的主题 兴趣权重 通过观察期和证据检查后,权重最高的主题 还没有主题权重。 @@ -1962,7 +1914,6 @@ 我理解,连接 订阅_失败_频道_正文 编辑 - deep flow花费 背景调查已经被限制 在全屏模式下水平滑动以浏览视频 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 2c3a48c36..afe78132c 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -7,8 +7,6 @@ 未訂閲 訂閲頻道,在此觀看最新影片 刷新訂閱 - 正在刷新 %1$d 個頻道(共 %2$d 個) - 最後刷新 %1$s ——已檢查 %2$d 個影片 重試 Shorts 頻道加載失敗 @@ -60,7 +58,6 @@ 已下載 下載 下載全部 - 確定下載全部 %1$d 條影片?這會佔用不少儲存空間。 儲存 已儲存 加入媒體庫 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ff1c1f265..f95597632 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,8 +14,14 @@ No Subscriptions Yet Subscribe to channels to see their\nlatest videos here Refresh Feed - Refreshing %1$d of %2$d channels - Last refreshed %1$s - %2$d videos checked + + Refreshing %1$d of %2$d channel + Refreshing %1$d of %2$d channels + + + Last refreshed %1$s - %2$d video checked + Last refreshed %1$s - %2$d videos checked + Last refreshed %1$s %d channel couldn\'t be loaded @@ -92,7 +98,10 @@ Downloaded Download Download all - Download all %1$d videos? This may use significant storage. + + Download %1$d video? This may use significant storage. + Download all %1$d videos? This may use significant storage. + Save Saved Owned @@ -256,7 +265,10 @@ ...more Reply Hide replies - View %1$d replies + + View %1$d reply + View %1$d replies + Load more replies Select Text Pinned comment @@ -316,7 +328,10 @@ FLOW 9+ Your personalized feed - %1$d videos curated just for you + + %1$d video curated just for you + %1$d videos curated just for you + Import NewPipe Backup Importing subscriptions from NewPipe backup... Search Subscriptions @@ -333,15 +348,17 @@ Unsubscribed from %1$s Hide Shorts from this channel Show Shorts from this channel - %1$d videos - %1$d likes - %1$d playlists - %1$d shorts - %1$d songs + + %1$d video + %1$d videos + + + %1$d song + %1$d songs + No downloads yet Play all Remove from Watch Later - Playlist • Private • %1$d videos E No videos saved Videos you save to watch later will appear here @@ -450,7 +467,10 @@ 8 hours 12 hours 24 hours - %1$d hours + + %1$d hour + %1$d hours + Appearance Content & Playback Data Management @@ -535,8 +555,10 @@ Dark Custom Special - %1$d themes - %1$d %2$s themes + + %1$d theme + %1$d themes + Applied: %1$s Customize Theme Custom Theme Editor @@ -894,17 +916,26 @@ Loop (repeat current short) Auto Play Next (advance to next short) Auto-scroll after custom time - Auto-scroll every %1$d seconds + + Auto-scroll every %1$d second + Auto-scroll every %1$d seconds + Shorts Playback Mode Choose how Shorts should behave when the current short finishes playing: - %1$d seconds + + %1$d second + %1$d seconds + Autoplay related videos When nothing is queued, automatically play a suggested video next Autoplay queued videos Automatically play the next video in a playlist or Watch Later queue. When off, you can still skip manually. Autoplay delay None (switch immediately) - %1$d seconds + + %1$d second + %1$d seconds + Show a countdown before automatically switching to the next video. During the countdown you can restart the current video, cancel the switch, or play the next one right away. Up next Next video @@ -1099,8 +1130,10 @@ Customize what you see Interests Blocked - %1$d topics - %1$d hidden + + %1$d topic + %1$d topics + Your Interests Topics you\'ve selected help Flow recommend better content. Tap topics below to add or remove them. Currently Following @@ -1116,10 +1149,16 @@ Quick Add Common topics to block Currently Blocked - %1$d topic%2$s + + %1$d topic + %1$d topics + Remove %1$s Unblock %1$s - %1$d selected + + %1$d selected + %1$d selected + Select Cancel selection Select all @@ -1136,12 +1175,18 @@ A notification will be sent at start time. Remind me to take a break Reminder frequency - Every %1$d min + + Every %1$d min + Every %1$d min + Daily Average Today Last 7 days Frequency - Every %1$d minutes + + Every %1$d minute + Every %1$d minutes + This Week Total: %s hours No watch data yet @@ -1158,7 +1203,10 @@ Sleep Timer Duration - %1$d min + + %1$d min + %1$d min + 5 min 120 min Custom time @@ -1181,32 +1229,45 @@ Search Suggestions Show suggestions while typing Max History Size - Currently: %1$d searches + + Currently: %1$d search + Currently: %1$d searches + Auto-Delete History - Delete after %1$d days + + Delete after %1$d day + Delete after %1$d days + Never delete automatically Retention Period - Delete searches older than %1$d days + + Delete searches older than %1$d day + Delete searches older than %1$d days + Clear Search History Remove all search queries Clear Search History? Permanently delete all search history. Choose how many searches to keep: - %1$d searches + + %1$d search + %1$d searches + Delete searches older than: 1 week 1 month 3 months 6 months 1 year - %1$d days + + %1$d day + %1$d days + Import Data Flow backup imported successfully Failed to import Flow backup: %1$s - Imported %1$d subscriptions from NewPipe Failed to import NewPipe backup: %1$s - Imported %1$d subscriptions from YouTube Failed to import YouTube backup: %1$s Import Flow Backup Restore your history, settings, and subscriptions from a Flow backup file. @@ -1246,9 +1307,11 @@ Import a YouTube Takeout CSV straight into your Watch Later list, whatever the file is named. Import YouTube Music Playlist Import a music playlist from YouTube Music Takeout CSV. Appears under Music Playlists. - Imported %1$d entries from your YouTube watch history Failed to import watch history: %1$s - Imported playlist “%1$s” with %2$d videos + + Imported playlist “%1$s” with %2$d video + Imported playlist “%1$s” with %2$d videos + Failed to import playlist: %1$s No watch history entries found in this file. Make sure it is a YouTube Takeout watch-history.html file. No videos found in this CSV. Make sure it is a YouTube Takeout playlist CSV file. @@ -1282,7 +1345,10 @@ Parallel Downloading Download files in multiple chunks for max speed. Concurrent Threads - %1$d threads per download + + %1$d thread per download + %1$d threads per download + Using more threads can increase speed but may use more battery and heat up the device. Choose where downloaded files are saved on your device. Preset Locations @@ -1301,7 +1367,10 @@ Recommended Active Select threads count (1-8): - %1$d threads + + %1$d thread + %1$d threads + Support & Donations Support Flow Development @@ -1372,8 +1441,14 @@ Add videos from the video player\nto build your playlist Delete playlist? This will permanently delete \'%1$s\' and all its videos. - Playlist • Private • %1$d videos - Playlist • Public • %1$d videos + + Playlist • Private • %1$d video + Playlist • Private • %1$d videos + + + Playlist • Public • %1$d video + Playlist • Public • %1$d videos + Playlist sort options Manual Date added (newest) @@ -1381,14 +1456,16 @@ Most popular Date published (newest) Date published (oldest) - Remove %1$d video(s)? + + Remove %1$d video? + Remove %1$d videos? + They will be removed from this playlist. They will be removed from Watch later. Welcome to Flow Tell us what you\'re interested in Select at least 3 topics to personalize your experience - %1$d selected (%2$d more needed) What do you enjoy? Pick at least %1$d topics to personalise your feed. %2$d more to go. Great selection. You can always update this later in settings. @@ -1397,14 +1474,16 @@ Search channels… Type a channel name to search No channels found for \"%1$s\" - %1$d channels added + + %1$d channel added + %1$d channels added + %1$s subscribers Subscribed Subscribe Import your data Bring your subscriptions and history from other apps. Everything is optional. Backup & Restore - %1$d selected Selected Not selected Import failed: %1$s @@ -1470,7 +1549,6 @@ Interactions Topics Watch some videos to populate your interest nebula! - %1$d interactions • Level %2$d Export Profile Data Flow Neural Profile Export @@ -1491,8 +1569,6 @@ %1$s • %2$s views View all Search - %1$s views - %1$d tracks • %2$s Unknown error Retry No moods & genres available @@ -1589,7 +1665,6 @@ Playlist • %1$s • %1$s plays Album • %1$s • %2$s - Artist • %1$s monthly audience Search: %1$s Artist: %1$s Top Picks for You @@ -1602,7 +1677,10 @@ Create your first playlist to organize your favorite tracks No Favorites Yet Tap the heart icon on any track to add it to your favorites - %1$d favorite tracks + + %1$d favorite track + %1$d favorite tracks + No History Yet Start listening to music to see your history here No Downloads Yet @@ -1670,7 +1748,10 @@ Failed Cancelled Remove incomplete downloads - Remove %1$d paused, failed, or partial download(s)? Completed downloads will not be touched. + + Remove %1$d paused, failed, or partial download? Completed downloads will not be touched. + Remove %1$d paused, failed, or partial downloads? Completed downloads will not be touched. + Audio Track %1$s %2$d %1$s (%2$s) @@ -1805,7 +1886,10 @@ Merge another device\'s library into this one. Select all Clear - %1$d of %2$d selected + + %1$d of %2$d selected + %1$d of %2$d selected + Your playlists, albums and Watch Later. What you have watched and how far you got. Liked and disliked videos and music. @@ -1949,7 +2033,10 @@ Add to my playlist Add all songs to… - Added %1$d songs to “%2$s” + + Added %1$d song to “%2$s” + Added %1$d songs to “%2$s” + No playlists yet. Create one first! Profile exported successfully @@ -1989,7 +2076,10 @@ Live affinity How much live content fits the profile Topic breadth - %1$d topics in the global vector + + %1$d topic in the global vector + %1$d topics in the global vector + Interest Weights Highest weighted topics after probation and evidence checks @@ -2340,7 +2430,10 @@ A new version of Flow is available (%1$s). Download the latest APK? I N S T R U M E N T A L Playlist is empty - Downloading %1$d videos… + + Downloading %1$d video… + Downloading %1$d videos… + Playlist saved to library Playlist removed from library Downloading audio: %1$skbps %2$s @@ -2366,10 +2459,16 @@ Playlist deleted Playlist renamed Starting download for %1$s… - Downloaded %1$d tracks from %2$s + + Downloaded %1$d track from %2$s + Downloaded %1$d tracks from %2$s + Failed to download playlist Error downloading playlist - Downloaded %1$d tracks + + Downloaded %1$d track + Downloaded %1$d tracks + Added to playlist Failed to add track Removed from playlist @@ -2401,7 +2500,10 @@ +%1$d more New videos - %1$d new videos from your subscriptions + + %1$d new video from your subscriptions + %1$d new videos from your subscriptions + Update Available: %1$s Tap to update to the latest version. Watch Later Reminder @@ -2474,7 +2576,6 @@ Manage your Flow backups External Services Import from other YouTube clients - Imported %1$d %2$s %1$s imported successfully Importing %1$s… Imported from Google Takeout @@ -2491,7 +2592,10 @@ Unrecognised backup format — make sure you selected the correct file Import failed: %1$s %1$d hr %2$d min - %1$d min + + %1$d min + %1$d min + %1$dh %1$dm Unknown Title From 014305e8b697fa38993ec79ea82d214ef4eb06fa Mon Sep 17 00:00:00 2001 From: AE Date: Thu, 27 Aug 2026 13:44:03 +0300 Subject: [PATCH 2/2] `fix(i18n): localize hardcoded component strings` --- .../aedev/flow/ui/components/BadgeIcon.kt | 2 +- .../components/FlowDescriptionBottomSheet.kt | 2 +- .../FlowPlaylistQueueBottomSheet.kt | 7 +- .../flow/ui/components/PlaylistQueueDock.kt | 82 +++--- .../aedev/flow/ui/components/UpdateDialog.kt | 276 ++++++++++-------- .../aedev/flow/ui/components/VideoCard.kt | 12 +- .../ui/components/VideoPlayerComponents.kt | 15 +- .../ui/components/audio/EqualizerEditor.kt | 108 ++++--- app/src/main/res/values/strings.xml | 7 + 9 files changed, 301 insertions(+), 210 deletions(-) diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/BadgeIcon.kt b/app/src/main/java/io/github/aedev/flow/ui/components/BadgeIcon.kt index 3430797e8..4502ad375 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/BadgeIcon.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/BadgeIcon.kt @@ -39,7 +39,7 @@ object BadgeIcon { .background(MaterialTheme.colorScheme.surfaceVariant), ) { Text( - text = "E", + text = stringResource(R.string.explicit_badge), style = MaterialTheme.typography.labelSmall, fontWeight = FontWeight.Bold, fontSize = 9.sp, diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/FlowDescriptionBottomSheet.kt b/app/src/main/java/io/github/aedev/flow/ui/components/FlowDescriptionBottomSheet.kt index 0d4c3df9e..5f9cacabf 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/FlowDescriptionBottomSheet.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/FlowDescriptionBottomSheet.kt @@ -366,7 +366,7 @@ fun FlowDescriptionBottomSheet( ) VerticalHorizontalDivider() StatItem( - value = formatViewCount(video.viewCount).replace(" views", ""), + value = formatViewCount(video.viewCount), label = stringResource(R.string.views), ) VerticalHorizontalDivider() diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/FlowPlaylistQueueBottomSheet.kt b/app/src/main/java/io/github/aedev/flow/ui/components/FlowPlaylistQueueBottomSheet.kt index a37619052..093fde21f 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/FlowPlaylistQueueBottomSheet.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/FlowPlaylistQueueBottomSheet.kt @@ -269,7 +269,12 @@ fun FlowPlaylistQueueBottomSheet( overflow = TextOverflow.Ellipsis, ) Text( - text = "${currentQueueIndex + 1} / ${queueVideos.size}", + text = + stringResource( + R.string.queue_position_template, + currentQueueIndex + 1, + queueVideos.size, + ), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, ) diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/PlaylistQueueDock.kt b/app/src/main/java/io/github/aedev/flow/ui/components/PlaylistQueueDock.kt index fb5183e5e..a9975b9b3 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/PlaylistQueueDock.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/PlaylistQueueDock.kt @@ -28,7 +28,7 @@ fun PlaylistQueueDock( currentIndex: Int, queueSize: Int, onClick: () -> Unit, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { val containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.95f) val contentColor = MaterialTheme.colorScheme.onSurface @@ -43,35 +43,38 @@ fun PlaylistQueueDock( shadowElevation = 4.dp, shape = RoundedCornerShape(16.dp), border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.55f)), - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 12.dp) - .safeDrawingPadding() - .height(68.dp) - .clickable(onClick = onClick) + modifier = + modifier + .fillMaxWidth() + .padding(horizontal = 12.dp) + .safeDrawingPadding() + .height(68.dp) + .clickable(onClick = onClick), ) { Row( - modifier = Modifier - .fillMaxSize() - .padding(start = 12.dp, end = 8.dp), - verticalAlignment = Alignment.CenterVertically + modifier = + Modifier + .fillMaxSize() + .padding(start = 12.dp, end = 8.dp), + verticalAlignment = Alignment.CenterVertically, ) { Box( - modifier = Modifier - .size(42.dp) - .background(accentContainerColor, RoundedCornerShape(12.dp)) - .border( - width = 1.dp, - color = MaterialTheme.colorScheme.primary.copy(alpha = 0.18f), - shape = RoundedCornerShape(12.dp) - ), - contentAlignment = Alignment.Center + modifier = + Modifier + .size(42.dp) + .background(accentContainerColor, RoundedCornerShape(12.dp)) + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.primary.copy(alpha = 0.18f), + shape = RoundedCornerShape(12.dp), + ), + contentAlignment = Alignment.Center, ) { Icon( imageVector = Icons.AutoMirrored.Outlined.PlaylistPlay, contentDescription = null, tint = accentContentColor, - modifier = Modifier.size(24.dp) + modifier = Modifier.size(24.dp), ) } @@ -79,23 +82,28 @@ fun PlaylistQueueDock( Column( modifier = Modifier.weight(1f), - verticalArrangement = Arrangement.Center + verticalArrangement = Arrangement.Center, ) { Text( - text = if (nextVideoTitle != null) { - stringResource(R.string.next_up) + ": " + nextVideoTitle - } else { - stringResource(R.string.playlist_queue) - }, + text = + if (nextVideoTitle != null) { + stringResource( + R.string.next_up_template, + stringResource(R.string.next_up), + nextVideoTitle, + ) + } else { + stringResource(R.string.playlist_queue) + }, style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, color = contentColor, maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, ) - + Spacer(modifier = Modifier.height(2.dp)) - + Row(verticalAlignment = Alignment.CenterVertically) { Text( text = playlistName, @@ -103,28 +111,28 @@ fun PlaylistQueueDock( color = secondaryContentColor, maxLines = 1, overflow = TextOverflow.Ellipsis, - modifier = Modifier.weight(1f, fill = false) + modifier = Modifier.weight(1f, fill = false), ) - + Text( text = " • ", style = MaterialTheme.typography.labelMedium, - color = secondaryContentColor + color = secondaryContentColor, ) - + Text( text = "${currentIndex + 1}/$queueSize", style = MaterialTheme.typography.labelMedium, - color = secondaryContentColor + color = secondaryContentColor, ) } } - + IconButton(onClick = onClick) { Icon( imageVector = Icons.Default.ExpandLess, contentDescription = stringResource(R.string.playlist_queue), - tint = contentColor + tint = contentColor, ) } } diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/UpdateDialog.kt b/app/src/main/java/io/github/aedev/flow/ui/components/UpdateDialog.kt index 63338f926..ad96f9943 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/UpdateDialog.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/UpdateDialog.kt @@ -12,7 +12,6 @@ import androidx.compose.material.icons.filled.CloudDownload import androidx.compose.material.icons.filled.Hexagon import androidx.compose.material.icons.rounded.Bolt import androidx.compose.material3.* -import androidx.compose.ui.res.stringResource import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -21,6 +20,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight @@ -36,120 +36,137 @@ import io.github.aedev.flow.utils.UpdateInfo fun UpdateDialog( updateInfo: UpdateInfo, onDismiss: () -> Unit, - onUpdate: () -> Unit + onUpdate: () -> Unit, ) { val context = LocalContext.current - - val displayedChangelog = remember(updateInfo.changelog, updateInfo.version) { - if (updateInfo.version.contains("1.4.0") || updateInfo.changelog.isBlank()) { - try { - val filename = if (updateInfo.version.startsWith("v")) updateInfo.version else "v${updateInfo.version}" + + val displayedChangelog = + remember(updateInfo.changelog, updateInfo.version) { + if (updateInfo.version.contains("1.4.0") || updateInfo.changelog.isBlank()) { try { - context.assets.open("changelog/$filename.txt").bufferedReader().use { it.readText() } - } catch (e: Exception) { - // If specific version file not found, try to find the latest - val files = context.assets.list("changelog") ?: emptyArray() - val latestFile = files.filter { it.endsWith(".txt") } - .sortedWith(compareByDescending { it }) - .firstOrNull() - - if (latestFile != null) { - context.assets.open("changelog/$latestFile").bufferedReader().use { it.readText() } - } else { - updateInfo.changelog + val filename = if (updateInfo.version.startsWith("v")) updateInfo.version else "v${updateInfo.version}" + try { + context.assets + .open("changelog/$filename.txt") + .bufferedReader() + .use { it.readText() } + } catch (e: Exception) { + // If specific version file not found, try to find the latest + val files = context.assets.list("changelog") ?: emptyArray() + val latestFile = + files + .filter { it.endsWith(".txt") } + .sortedWith(compareByDescending { it }) + .firstOrNull() + + if (latestFile != null) { + context.assets + .open("changelog/$latestFile") + .bufferedReader() + .use { it.readText() } + } else { + updateInfo.changelog + } } + } catch (e: Exception) { + updateInfo.changelog } - } catch (e: Exception) { + } else { updateInfo.changelog } - } else { - updateInfo.changelog } - } Dialog( onDismissRequest = onDismiss, - properties = androidx.compose.ui.window.DialogProperties( - usePlatformDefaultWidth = false, - decorFitsSystemWindows = false - ) + properties = + androidx.compose.ui.window.DialogProperties( + usePlatformDefaultWidth = false, + decorFitsSystemWindows = false, + ), ) { Box( - modifier = Modifier - .fillMaxSize() - .background(Color.Black.copy(alpha = 0.6f)) - .clickable(onClick = onDismiss), - contentAlignment = Alignment.BottomCenter + modifier = + Modifier + .fillMaxSize() + .background(Color.Black.copy(alpha = 0.6f)) + .clickable(onClick = onDismiss), + contentAlignment = Alignment.BottomCenter, ) { Surface( - modifier = Modifier - .fillMaxWidth() - .clickable(enabled = false) {}, + modifier = + Modifier + .fillMaxWidth() + .clickable(enabled = false) {}, shape = RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp), - color = Color(0xFF1E1E22) + color = Color(0xFF1E1E22), ) { Column( - modifier = Modifier - .fillMaxWidth() - .padding(top = 32.dp, bottom = 24.dp, start = 24.dp, end = 24.dp), - horizontalAlignment = Alignment.CenterHorizontally + modifier = + Modifier + .fillMaxWidth() + .padding(top = 32.dp, bottom = 24.dp, start = 24.dp, end = 24.dp), + horizontalAlignment = Alignment.CenterHorizontally, ) { Box( contentAlignment = Alignment.Center, - modifier = Modifier - .size(72.dp) - .clip(RoundedCornerShape(20.dp)) - .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.2f)) + modifier = + Modifier + .size(72.dp) + .clip(RoundedCornerShape(20.dp)) + .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.2f)), ) { Icon( painter = painterResource(id = R.drawable.ic_notification_logo), contentDescription = stringResource(R.string.update_flow), tint = MaterialTheme.colorScheme.primary, - modifier = Modifier.size(40.dp) + modifier = Modifier.size(40.dp), ) } Spacer(modifier = Modifier.height(24.dp)) Text( - text = stringResource(R.string.new_update_available), - style = MaterialTheme.typography.titleLarge.copy( - fontWeight = FontWeight.Bold, - fontSize = 22.sp - ), - color = Color.White + text = stringResource(R.string.new_update_available), + style = + MaterialTheme.typography.titleLarge.copy( + fontWeight = FontWeight.Bold, + fontSize = 22.sp, + ), + color = Color.White, ) Spacer(modifier = Modifier.height(8.dp)) Text( - text = "Version ${updateInfo.version}", + text = stringResource(R.string.ui_version, updateInfo.version), style = MaterialTheme.typography.bodyMedium, - color = Color.LightGray.copy(alpha = 0.7f) + color = Color.LightGray.copy(alpha = 0.7f), ) Spacer(modifier = Modifier.height(24.dp)) Column( - modifier = Modifier - .fillMaxWidth() - .weight(1f, fill = false) - .heightIn(max = 280.dp) - .verticalScroll(rememberScrollState()) + modifier = + Modifier + .fillMaxWidth() + .weight(1f, fill = false) + .heightIn(max = 280.dp) + .verticalScroll(rememberScrollState()), ) { Text( text = stringResource(R.string.release_notes).uppercase(), - style = MaterialTheme.typography.labelMedium.copy( - fontWeight = FontWeight.Bold, - letterSpacing = 1.2.sp - ), + style = + MaterialTheme.typography.labelMedium.copy( + fontWeight = FontWeight.Bold, + letterSpacing = 1.2.sp, + ), color = MaterialTheme.colorScheme.primary, - modifier = Modifier.padding(bottom = 12.dp) + modifier = Modifier.padding(bottom = 12.dp), ) MarkdownChangelogText( markdown = displayedChangelog, - textColor = Color.White.copy(alpha = 0.85f) + textColor = Color.White.copy(alpha = 0.85f), ) } @@ -157,51 +174,55 @@ fun UpdateDialog( Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(16.dp) + horizontalArrangement = Arrangement.spacedBy(16.dp), ) { Button( onClick = onDismiss, - modifier = Modifier - .weight(1f) - .height(52.dp), - colors = ButtonDefaults.buttonColors( - containerColor = Color.White.copy(alpha = 0.1f), - contentColor = Color.White - ), - shape = RoundedCornerShape(26.dp) + modifier = + Modifier + .weight(1f) + .height(52.dp), + colors = + ButtonDefaults.buttonColors( + containerColor = Color.White.copy(alpha = 0.1f), + contentColor = Color.White, + ), + shape = RoundedCornerShape(26.dp), ) { Text( text = stringResource(R.string.maybe_later), style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold + fontWeight = FontWeight.SemiBold, ) } Button( onClick = onUpdate, - modifier = Modifier - .weight(1f) - .height(52.dp), - colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary - ), - shape = RoundedCornerShape(26.dp) + modifier = + Modifier + .weight(1f) + .height(52.dp), + colors = + ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary, + ), + shape = RoundedCornerShape(26.dp), ) { Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center + horizontalArrangement = Arrangement.Center, ) { Icon( - Icons.Default.CloudDownload, - contentDescription = null, - modifier = Modifier.size(20.dp) + Icons.Default.CloudDownload, + contentDescription = null, + modifier = Modifier.size(20.dp), ) Spacer(Modifier.width(8.dp)) Text( text = stringResource(R.string.update_flow), style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold + fontWeight = FontWeight.SemiBold, ) } } @@ -217,56 +238,67 @@ fun UpdateDialog( * Handles Headers (#), Bullet points (- or *), and Bold (**text**). */ @Composable -fun MarkdownChangelogText(markdown: String, textColor: Color) { - val styledText = remember(markdown) { - buildAnnotatedString { - val lines = markdown.split("\n") - - lines.forEach { line -> - val trimmed = line.trim() - - when { - // 1. Headers (### or ## or #) - trimmed.startsWith("#") -> { - val text = trimmed.trimStart('#').trim() - withStyle(SpanStyle( - fontWeight = FontWeight.Bold, - fontSize = 14.sp, - color = textColor - )) { - append("• $text") // Treat headers as bullets in small view +fun MarkdownChangelogText( + markdown: String, + textColor: Color, +) { + val styledText = + remember(markdown) { + buildAnnotatedString { + val lines = markdown.split("\n") + + lines.forEach { line -> + val trimmed = line.trim() + + when { + // 1. Headers (### or ## or #) + trimmed.startsWith("#") -> { + val text = trimmed.trimStart('#').trim() + withStyle( + SpanStyle( + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + color = textColor, + ), + ) { + append("• $text") // Treat headers as bullets in small view + } + append("\n") } - append("\n") - } - // 2. Bullet Points (- or *) - trimmed.startsWith("-") || trimmed.startsWith("*") -> { - val text = trimmed.substring(1).trim() - append(" • ") // Simple bullet - parseBold(text, textColor) - append("\n") - } - // 3. Normal Text - else -> { - if (trimmed.isNotEmpty()) { - parseBold(trimmed, textColor) + + // 2. Bullet Points (- or *) + trimmed.startsWith("-") || trimmed.startsWith("*") -> { + val text = trimmed.substring(1).trim() + append(" • ") // Simple bullet + parseBold(text, textColor) append("\n") } + + // 3. Normal Text + else -> { + if (trimmed.isNotEmpty()) { + parseBold(trimmed, textColor) + append("\n") + } + } } } } } - } Text( text = styledText, style = MaterialTheme.typography.bodySmall, color = textColor.copy(alpha = 0.8f), - lineHeight = 18.sp + lineHeight = 18.sp, ) } // Helper to parse **bold** text inside a string -fun androidx.compose.ui.text.AnnotatedString.Builder.parseBold(text: String, baseColor: Color) { +fun androidx.compose.ui.text.AnnotatedString.Builder.parseBold( + text: String, + baseColor: Color, +) { val parts = text.split("**") parts.forEachIndexed { index, part -> // If index is odd, it was inside **, so make it bold @@ -280,4 +312,4 @@ fun androidx.compose.ui.text.AnnotatedString.Builder.parseBold(text: String, bas } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/VideoCard.kt b/app/src/main/java/io/github/aedev/flow/ui/components/VideoCard.kt index fc7dbcca5..3a25b3a5f 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/VideoCard.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/VideoCard.kt @@ -108,11 +108,12 @@ private fun VideoCollaborator.hasChannelCollaboratorSignal(): Boolean = internal fun List.displayCollaboratorChannelName( fallback: String, moreCollaboratorsText: String? = null, + conjunction: String, ): String { val names = map { it.name }.filter { it.isNotBlank() } return when { names.size > 2 && moreCollaboratorsText != null -> moreCollaboratorsText - names.size > 1 -> names.joinToString(" and ") + names.size > 1 -> names.joinToString(" $conjunction ") else -> fallback } } @@ -129,8 +130,9 @@ internal fun rememberCollaboratorChannelDisplayName( firstName, (collaborators.size - 1).coerceAtLeast(0), ) - return remember(fallback, collaborators, compactName) { - collaborators.displayCollaboratorChannelName(fallback, compactName) + val conjunction = stringResource(R.string.conjunction_and) + return remember(fallback, collaborators, compactName, conjunction) { + collaborators.displayCollaboratorChannelName(fallback, compactName, conjunction) } } @@ -333,7 +335,7 @@ fun VideoCardHorizontal( displayDate, ) } else { - "$displayChannelName · $displayDate" + stringResource(R.string.video_metadata_short_template, displayChannelName, displayDate) }, style = MaterialTheme.typography.bodySmall, color = @@ -576,7 +578,7 @@ fun VideoCardFullWidth( displayDate, ) } else { - "$displayChannelName · $displayDate" + stringResource(R.string.video_metadata_short_template, displayChannelName, displayDate) }, style = MaterialTheme.typography.bodySmall, color = diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/VideoPlayerComponents.kt b/app/src/main/java/io/github/aedev/flow/ui/components/VideoPlayerComponents.kt index 547879184..3727a7085 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/VideoPlayerComponents.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/VideoPlayerComponents.kt @@ -144,7 +144,9 @@ fun VideoInfoSection( onClick = {}, onLongClick = { val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - clipboard.setPrimaryClip(ClipData.newPlainText("Video Title", title)) + clipboard.setPrimaryClip( + ClipData.newPlainText(context.getString(R.string.title_label), title), + ) Toast.makeText(context, context.getString(R.string.title_copied), Toast.LENGTH_SHORT).show() }, ), @@ -171,12 +173,11 @@ fun VideoInfoSection( if (!isUpcoming && !uploadDate.isNullOrBlank()) { Text( - text = " • ", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - Text( - text = dateSettings.format(uploadDate, DateContext.WATCH, video.timestamp), + text = + stringResource( + R.string.duration_with_dot_template, + dateSettings.format(uploadDate, DateContext.WATCH, video.timestamp), + ), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) diff --git a/app/src/main/java/io/github/aedev/flow/ui/components/audio/EqualizerEditor.kt b/app/src/main/java/io/github/aedev/flow/ui/components/audio/EqualizerEditor.kt index 5bb40e199..f524b1c03 100644 --- a/app/src/main/java/io/github/aedev/flow/ui/components/audio/EqualizerEditor.kt +++ b/app/src/main/java/io/github/aedev/flow/ui/components/audio/EqualizerEditor.kt @@ -75,7 +75,10 @@ fun EqualizerEditor(modifier: Modifier = Modifier) { } // Any manual edit becomes the live "Custom" curve — applied to the players and persisted. - fun pushCustom(newBands: List = bands, newPreamp: Float = preamp) { + fun pushCustom( + newBands: List = bands, + newPreamp: Float = preamp, + ) { bands = newBands preamp = newPreamp AudioEffectsController.setCustomEq(ParametricEQ(newPreamp.toDouble(), newBands)) @@ -98,20 +101,27 @@ fun EqualizerEditor(modifier: Modifier = Modifier) { AudioEffectsController.availablePresetNames().forEach { presetName -> DropdownMenuItem( text = { Text(presetName) }, - trailingIcon = if (AudioEffectsController.isCustomPreset(presetName)) { - { - IconButton( - onClick = { AudioEffectsController.deleteCustomPreset(presetName) }, - modifier = Modifier.size(24.dp) - ) { - Icon(Icons.Default.Delete, stringResource(R.string.delete), modifier = Modifier.size(16.dp)) + trailingIcon = + if (AudioEffectsController.isCustomPreset(presetName)) { + { + IconButton( + onClick = { AudioEffectsController.deleteCustomPreset(presetName) }, + modifier = Modifier.size(24.dp), + ) { + Icon( + imageVector = Icons.Default.Delete, + contentDescription = stringResource(R.string.delete), + modifier = Modifier.size(16.dp), + ) + } } - } - } else null, + } else { + null + }, onClick = { AudioEffectsController.setEqProfile(presetName) expanded = false - } + }, ) } } @@ -124,7 +134,7 @@ fun EqualizerEditor(modifier: Modifier = Modifier) { value = bassBoost, onValueChange = { AudioEffectsController.setBassBoost(it) }, valueRange = 0f..15f, - steps = 15 + steps = 15, ) } } @@ -147,7 +157,7 @@ fun EqualizerEditor(modifier: Modifier = Modifier) { Slider( value = preamp, onValueChange = { pushCustom(newPreamp = it) }, - valueRange = -20f..20f + valueRange = -20f..20f, ) } @@ -159,7 +169,7 @@ fun EqualizerEditor(modifier: Modifier = Modifier) { }, onRemove = { pushCustom(newBands = bands.toMutableList().also { it.removeAt(index) }) - } + }, ) } } @@ -169,7 +179,7 @@ fun EqualizerEditor(modifier: Modifier = Modifier) { onSave = { name -> if (AudioEffectsController.saveCustomPreset(name)) showSaveDialog = false }, - onDismiss = { showSaveDialog = false } + onDismiss = { showSaveDialog = false }, ) } } @@ -177,7 +187,7 @@ fun EqualizerEditor(modifier: Modifier = Modifier) { @Composable private fun SavePresetDialog( onSave: (String) -> Unit, - onDismiss: () -> Unit + onDismiss: () -> Unit, ) { var name by remember { mutableStateOf("") } AlertDialog( @@ -188,7 +198,7 @@ private fun SavePresetDialog( value = name, onValueChange = { name = it }, label = { Text(stringResource(R.string.label_preset_name)) }, - singleLine = true + singleLine = true, ) }, confirmButton = { @@ -200,7 +210,7 @@ private fun SavePresetDialog( TextButton(onClick = onDismiss) { Text(stringResource(R.string.cancel)) } - } + }, ) } @@ -208,11 +218,11 @@ private fun SavePresetDialog( private fun BandControl( band: ParametricEQBand, onUpdate: (ParametricEQBand) -> Unit, - onRemove: () -> Unit + onRemove: () -> Unit, ) { Card( colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f)), - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) { Column(modifier = Modifier.padding(12.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { @@ -228,34 +238,53 @@ private fun BandControl( if (band.enabled) { Row(verticalAlignment = Alignment.CenterVertically) { - Text("F", fontWeight = FontWeight.Bold, modifier = Modifier.width(20.dp), fontSize = 12.sp) + Text( + text = stringResource(R.string.equalizer_frequency_label), + fontWeight = FontWeight.Bold, + modifier = Modifier.width(20.dp), + fontSize = 12.sp, + ) Slider( value = freqToLog(band.frequency), onValueChange = { onUpdate(band.copy(frequency = logToFreq(it))) }, valueRange = 0f..1f, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), + ) + Text( + stringResource(R.string.template_freq, band.frequency.roundToInt()), + modifier = Modifier.width(50.dp), + fontSize = 12.sp, ) - Text(stringResource(R.string.template_freq, band.frequency.roundToInt()), modifier = Modifier.width(50.dp), fontSize = 12.sp) } Row(verticalAlignment = Alignment.CenterVertically) { - Text("G", fontWeight = FontWeight.Bold, modifier = Modifier.width(20.dp), fontSize = 12.sp) + Text( + text = stringResource(R.string.equalizer_gain_label), + fontWeight = FontWeight.Bold, + modifier = Modifier.width(20.dp), + fontSize = 12.sp, + ) Slider( value = band.gain.toFloat(), onValueChange = { onUpdate(band.copy(gain = it.toDouble())) }, valueRange = -15f..15f, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) Text(stringResource(R.string.template_gain, band.gain), modifier = Modifier.width(50.dp), fontSize = 12.sp) } Row(verticalAlignment = Alignment.CenterVertically) { - Text("Q", fontWeight = FontWeight.Bold, modifier = Modifier.width(20.dp), fontSize = 12.sp) + Text( + text = stringResource(R.string.equalizer_q_label), + fontWeight = FontWeight.Bold, + modifier = Modifier.width(20.dp), + fontSize = 12.sp, + ) Slider( value = band.q.toFloat(), onValueChange = { onUpdate(band.copy(q = it.toDouble())) }, valueRange = 0.1f..10f, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) Text(stringResource(R.string.template_q, band.q), modifier = Modifier.width(50.dp), fontSize = 12.sp) } @@ -265,7 +294,10 @@ private fun BandControl( } @Composable -private fun FilterTypeButton(current: FilterType, onChange: (FilterType) -> Unit) { +private fun FilterTypeButton( + current: FilterType, + onChange: (FilterType) -> Unit, +) { var expanded by remember { mutableStateOf(false) } Box { TextButton(onClick = { expanded = true }, contentPadding = PaddingValues(0.dp)) { @@ -275,7 +307,10 @@ private fun FilterTypeButton(current: FilterType, onChange: (FilterType) -> Unit FilterType.values().forEach { type -> DropdownMenuItem( text = { Text(type.name) }, - onClick = { onChange(type); expanded = false } + onClick = { + onChange(type) + expanded = false + }, ) } } @@ -297,10 +332,11 @@ private fun logToFreq(norm: Float): Double { } // Editing scaffold shown when the active profile has no bands (e.g. Flat). -private fun defaultEditingBands(): List = listOf( - ParametricEQBand(60.0, 0.0, 1.41, FilterType.LSC), - ParametricEQBand(230.0, 0.0, 1.41, FilterType.PK), - ParametricEQBand(910.0, 0.0, 1.41, FilterType.PK), - ParametricEQBand(3600.0, 0.0, 1.41, FilterType.PK), - ParametricEQBand(14000.0, 0.0, 1.41, FilterType.HSC) -) +private fun defaultEditingBands(): List = + listOf( + ParametricEQBand(60.0, 0.0, 1.41, FilterType.LSC), + ParametricEQBand(230.0, 0.0, 1.41, FilterType.PK), + ParametricEQBand(910.0, 0.0, 1.41, FilterType.PK), + ParametricEQBand(3600.0, 0.0, 1.41, FilterType.PK), + ParametricEQBand(14000.0, 0.0, 1.41, FilterType.HSC), + ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f95597632..8c6c96d96 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,6 +39,7 @@ Subscribers Collaborators Collaborator + and %1$s and %2$d more Stats Library @@ -145,6 +146,7 @@ Workout Track Details Title + E Artist Album Video ID @@ -1579,6 +1581,11 @@ Playing Explicit • %1$s + %1$d / %2$d + %1$s: %2$s + F + G + Q Downloaded Create Playlist Playlist Name