diff --git a/app/src/main/java/com/m57/hermescontrol/ui/logs/LogsScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/logs/LogsScreen.kt index 0c7b37e7..51ea9a49 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/logs/LogsScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/logs/LogsScreen.kt @@ -18,11 +18,13 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel +import com.m57.hermescontrol.R import com.m57.hermescontrol.theme.LocalSpacing import com.m57.hermescontrol.ui.common.EmptyState import com.m57.hermescontrol.ui.common.ErrorState @@ -59,7 +61,7 @@ fun LogsScreen( } HermesScaffold( - title = { Text("Logs") }, + title = { Text(stringResource(R.string.screen_logs)) }, onOpenDrawer = onOpenDrawer, isRefreshing = state.isLoading, onRefresh = { viewModel.loadLogs() }, @@ -71,7 +73,7 @@ fun LogsScreen( state.errorMessage != null -> { ErrorState( - message = state.errorMessage ?: "Unknown error", + message = state.errorMessage ?: stringResource(R.string.error_unknown), onRetry = { viewModel.loadLogs() }, ) } @@ -80,8 +82,8 @@ fun LogsScreen( // B5 (Jun 18 2026, kanban t_2322818d): proper empty-state using // the shared EmptyState component instead of a bare Text. EmptyState( - title = "No logs available", - subtitle = "Log output from Hermes will appear here.", + title = stringResource(R.string.logs_empty_title), + subtitle = stringResource(R.string.logs_empty_desc), icon = Icons.Filled.HistoryEdu, ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/model/ModelScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/model/ModelScreen.kt index 8efb7d36..27036d4a 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/model/ModelScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/model/ModelScreen.kt @@ -35,10 +35,12 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel +import com.m57.hermescontrol.R import com.m57.hermescontrol.ui.common.EmptyState import com.m57.hermescontrol.ui.common.ErrorState import com.m57.hermescontrol.ui.common.HermesScaffold @@ -67,7 +69,7 @@ fun ModelScreen( } HermesScaffold( - title = { Text("Models") }, + title = { Text(stringResource(R.string.screen_models)) }, onOpenDrawer = onOpenDrawer, isRefreshing = state.isLoading, onRefresh = { viewModel.loadModelOptions() }, @@ -87,10 +89,10 @@ fun ModelScreen( state.providers.isEmpty() -> { EmptyState( - title = "No model providers reported", - subtitle = "Verify configuration or retry", + title = stringResource(R.string.model_empty_title), + subtitle = stringResource(R.string.model_empty_desc), onAction = { viewModel.loadModelOptions() }, - actionLabel = "Refresh", + actionLabel = stringResource(R.string.content_desc_refresh), modifier = Modifier.padding(paddingValues), ) } @@ -107,7 +109,10 @@ fun ModelScreen( Text(text = state.errorMessage ?: "", color = MaterialTheme.colorScheme.error) Spacer(modifier = Modifier.height(16.dp)) IconButton(onClick = { viewModel.loadModelOptions() }) { - Icon(imageVector = Icons.Filled.Refresh, contentDescription = "Retry") + Icon( + imageVector = Icons.Filled.Refresh, + contentDescription = stringResource(R.string.action_retry), + ) } } } else { @@ -153,7 +158,7 @@ fun ModelScreen( fontWeight = FontWeight.Bold, ) Text( - text = "Slug: ${provider.slug}", + text = stringResource(R.string.model_label_slug, provider.slug), style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) @@ -161,7 +166,7 @@ fun ModelScreen( if (isCurrent) { Text( - text = "CURRENT", + text = stringResource(R.string.model_status_current), style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.primary, fontWeight = FontWeight.Bold, @@ -183,7 +188,7 @@ fun ModelScreen( AnimatedVisibility(visible = isExpanded) { Column(modifier = Modifier.padding(top = 16.dp)) { Text( - text = "Available Models:", + text = stringResource(R.string.model_label_available), style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.SemiBold, modifier = Modifier.padding(bottom = 8.dp), @@ -192,7 +197,7 @@ fun ModelScreen( val models = provider.models.orEmpty() if (models.isEmpty()) { Text( - text = "No models reported or provider needs authentication.", + text = stringResource(R.string.model_no_models), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, ) @@ -262,7 +267,10 @@ fun ModelScreen( if (isActive) { Icon( imageVector = Icons.Filled.Check, - contentDescription = "Active Model", + contentDescription = + stringResource( + R.string.content_desc_active_model, + ), tint = MaterialTheme.colorScheme.primary, ) } diff --git a/app/src/main/java/com/m57/hermescontrol/ui/sessions/SessionsScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/sessions/SessionsScreen.kt index e5e6ad14..47662888 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/sessions/SessionsScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/sessions/SessionsScreen.kt @@ -21,11 +21,13 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import com.m57.hermescontrol.ChatScreen import com.m57.hermescontrol.NavigationController +import com.m57.hermescontrol.R import com.m57.hermescontrol.theme.LocalSpacing import com.m57.hermescontrol.ui.common.EmptyState import com.m57.hermescontrol.ui.common.ErrorState @@ -48,7 +50,7 @@ fun SessionsScreen( } HermesScaffold( - title = { Text("History") }, + title = { Text(stringResource(R.string.screen_history)) }, onOpenDrawer = onOpenDrawer, isRefreshing = state.isLoading, onRefresh = { viewModel.loadSessions() }, @@ -61,15 +63,15 @@ fun SessionsScreen( state.errorMessage != null -> { ErrorState( - message = state.errorMessage ?: "Unknown error", + message = state.errorMessage ?: stringResource(R.string.error_unknown), onRetry = { viewModel.loadSessions() }, ) } state.sessions.isEmpty() -> { EmptyState( - title = "No history", - subtitle = "Previous chat sessions from Hermes will appear here.", + title = stringResource(R.string.history_empty_title), + subtitle = stringResource(R.string.history_empty_desc), icon = Icons.Filled.History, ) } @@ -98,7 +100,7 @@ fun SessionsScreen( modifier = Modifier.padding(spacing.md), ) { Text( - text = session.title ?: "Untitled", + text = session.title ?: stringResource(R.string.history_untitled), style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold, ) @@ -107,7 +109,11 @@ fun SessionsScreen( verticalAlignment = Alignment.CenterVertically, ) { Text( - text = "${session.message_count ?: 0} messages", + text = + stringResource( + R.string.history_message_count, + session.message_count ?: 0, + ), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, ) diff --git a/app/src/main/java/com/m57/hermescontrol/ui/system/SystemScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/system/SystemScreen.kt index 2a307707..861c1bb5 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/system/SystemScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/system/SystemScreen.kt @@ -27,8 +27,10 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel +import com.m57.hermescontrol.R import com.m57.hermescontrol.theme.LocalHermesStatusColors import com.m57.hermescontrol.theme.LocalSpacing import com.m57.hermescontrol.ui.common.EmptyState @@ -65,7 +67,7 @@ fun SystemScreen( } HermesScaffold( - title = { Text("System") }, + title = { Text(stringResource(R.string.screen_system)) }, onOpenDrawer = onOpenDrawer, isRefreshing = state.isLoading, onRefresh = { viewModel.loadSystemData() }, @@ -77,15 +79,15 @@ fun SystemScreen( state.errorMessage != null -> { ErrorState( - message = state.errorMessage ?: "Unknown error", + message = state.errorMessage ?: stringResource(R.string.error_unknown), onRetry = { viewModel.loadSystemData() }, ) } state.stats == null && state.doctorReport == null -> { EmptyState( - title = "No system data", - subtitle = "Tap refresh to load system diagnostics.", + title = stringResource(R.string.system_empty_title), + subtitle = stringResource(R.string.system_empty_desc), ) } @@ -102,7 +104,7 @@ fun SystemScreen( // Stats row state.stats?.let { stats -> item { - SectionHeader(title = "Performance") + SectionHeader(title = stringResource(R.string.system_sec_performance)) } item { FlowRow( @@ -111,7 +113,7 @@ fun SystemScreen( ) { stats.cpuPercent?.let { cpu -> StatCard( - label = "CPU Usage", + label = stringResource(R.string.system_metric_cpu), value = "$cpu%", icon = Icons.Filled.Speed, modifier = Modifier.weight(1f), @@ -119,7 +121,7 @@ fun SystemScreen( } stats.memoryPercent?.let { mem -> StatCard( - label = "Memory", + label = stringResource(R.string.system_metric_memory), value = "$mem%", icon = Icons.Filled.Memory, modifier = Modifier.weight(1f), @@ -132,7 +134,7 @@ fun SystemScreen( // Doctor diagnostics state.doctorReport?.let { report -> item { - SectionHeader(title = "Doctor") + SectionHeader(title = stringResource(R.string.system_sec_doctor)) } item { Card( @@ -158,7 +160,12 @@ fun SystemScreen( }, ) StatusBadge( - text = if (report.ok) "Running" else "Failed", + text = + if (report.ok) { + stringResource(R.string.system_status_running) + } else { + stringResource(R.string.system_status_failed) + }, status = if (report.ok) { StatusBadgeType.SUCCESS @@ -169,10 +176,13 @@ fun SystemScreen( } Spacer(modifier = Modifier.height(spacing.sm)) report.pid?.let { pid -> - InfoRow(label = "Process PID", value = pid.toString()) + InfoRow( + label = stringResource(R.string.system_info_pid), + value = pid.toString(), + ) } report.name?.let { name -> - InfoRow(label = "Process Name", value = name) + InfoRow(label = stringResource(R.string.system_info_proc_name), value = name) } } } @@ -181,7 +191,7 @@ fun SystemScreen( // Admin actions item { - SectionHeader(title = "Administration") + SectionHeader(title = stringResource(R.string.system_sec_admin)) } item { Card( @@ -201,7 +211,7 @@ fun SystemScreen( contentDescription = null, modifier = Modifier.padding(end = spacing.xs), ) - Text("Trigger System Backup") + Text(stringResource(R.string.system_action_backup)) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index afa5e105..5c1f2527 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -195,4 +195,37 @@ Discard Edit Skill File Save Changes + + + No logs available + Log output from Hermes will appear here. + + + No system data + Tap refresh to load system diagnostics. + Performance + CPU Usage + Memory + Doctor + Running + Failed + Process PID + Process Name + Administration + Trigger System Backup + + + No model providers reported + Verify configuration or retry + Slug: %1$s + CURRENT + Available Models: + No models reported or provider needs authentication. + Active Model + + + No history + Previous chat sessions from Hermes will appear here. + Untitled + %1$d messages \ No newline at end of file