Migrate legacy localized strings and remove runtime hardcoded UI text.

This copies old locale resources into the 2026 app, reuses legacy string keys where possible, and moves user-facing runtime text to string resources with missing entries added for all supported locales.

Made-with: Cursor
This commit is contained in:
2026-03-01 15:07:26 +01:00
parent 1823d0bf1b
commit a2cbb181d5
30 changed files with 1088 additions and 144 deletions

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.city
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun CityScreen(onBackToDashboard: () -> Unit) {
MockScreenScaffold(
title = "City",
subtitle = "Mock city management screen.",
actions = listOf(ScreenAction("Back to Dashboard", onBackToDashboard))
title = stringResource(id = R.string.title_city),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(stringResource(id = R.string.back_to_dashboard), onBackToDashboard))
)
}

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.constructor
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun ChartConstructorScreen(onBackToWidgetConstructor: () -> Unit) {
MockScreenScaffold(
title = "Chart Constructor",
subtitle = "Mock chart widget constructor variant.",
actions = listOf(ScreenAction("Back to Widget Constructor", onBackToWidgetConstructor))
title = stringResource(id = R.string.widget_chart_constructor_title),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(stringResource(id = R.string.back_to_widget_constructor), onBackToWidgetConstructor))
)
}

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.constructor
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun MapConstructorScreen(onBackToWidgetConstructor: () -> Unit) {
MockScreenScaffold(
title = "Map Constructor",
subtitle = "Mock map widget constructor variant.",
actions = listOf(ScreenAction("Back to Widget Constructor", onBackToWidgetConstructor))
title = stringResource(id = R.string.widget_map_constructor_title),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(stringResource(id = R.string.back_to_widget_constructor), onBackToWidgetConstructor))
)
}

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.constructor
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun NewsConstructorScreen(onBackToWidgetConstructor: () -> Unit) {
MockScreenScaffold(
title = "News Constructor",
subtitle = "Mock news widget constructor variant.",
actions = listOf(ScreenAction("Back to Widget Constructor", onBackToWidgetConstructor))
title = stringResource(id = R.string.widget_news_constructor_title),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(stringResource(id = R.string.back_to_widget_constructor), onBackToWidgetConstructor))
)
}

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.constructor
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun SelectMapWidgetLocationScreen(onDone: () -> Unit) {
MockScreenScaffold(
title = "Select Map Widget Location",
subtitle = "Mock map location picker for widget.",
actions = listOf(ScreenAction("Done", onDone))
title = stringResource(id = R.string.widget_select_map_location),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(stringResource(id = R.string.toast_done), onDone))
)
}

View File

@@ -1,6 +1,8 @@
package org.db3.airmq.features.constructor
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@@ -13,14 +15,14 @@ fun WidgetConstructorScreen(
onBackToManage: () -> Unit
) {
MockScreenScaffold(
title = "Widget Constructor",
subtitle = "Select constructor variant.",
title = stringResource(id = R.string.title_widget_constructor),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(
ScreenAction("Select Map Widget Location", onOpenSelectMapWidgetLocation),
ScreenAction("Open Map Constructor", onOpenMapConstructor),
ScreenAction("Open Chart Constructor", onOpenChartConstructor),
ScreenAction("Open News Constructor", onOpenNewsConstructor),
ScreenAction("Back to Manage", onBackToManage)
ScreenAction(stringResource(id = R.string.widget_select_map_location), onOpenSelectMapWidgetLocation),
ScreenAction(stringResource(id = R.string.widget_open_map_constructor), onOpenMapConstructor),
ScreenAction(stringResource(id = R.string.widget_open_chart_constructor), onOpenChartConstructor),
ScreenAction(stringResource(id = R.string.widget_open_news_constructor), onOpenNewsConstructor),
ScreenAction(stringResource(id = R.string.back_to_manage), onBackToManage)
)
)
}

View File

@@ -1,6 +1,8 @@
package org.db3.airmq.features.dashboard
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@@ -14,15 +16,15 @@ fun DashboardScreen(
onOpenWidgetConstructor: () -> Unit
) {
MockScreenScaffold(
title = "Dashboard",
subtitle = "Bottom-tab equivalent: dashboard",
title = stringResource(id = R.string.title_dashboard),
subtitle = stringResource(id = R.string.dashboard_subtitle),
actions = listOf(
ScreenAction("Open Map", onOpenMap),
ScreenAction("Open Manage", onOpenManage),
ScreenAction("Open City", onOpenCity),
ScreenAction("Open Device", onOpenDevice),
ScreenAction("Open News", onOpenNews),
ScreenAction("Open Widget Constructor", onOpenWidgetConstructor)
ScreenAction(stringResource(id = R.string.dashboard_open_map), onOpenMap),
ScreenAction(stringResource(id = R.string.dashboard_open_manage), onOpenManage),
ScreenAction(stringResource(id = R.string.dashboard_open_city), onOpenCity),
ScreenAction(stringResource(id = R.string.dashboard_open_device), onOpenDevice),
ScreenAction(stringResource(id = R.string.dashboard_open_news), onOpenNews),
ScreenAction(stringResource(id = R.string.manage_open_widget_constructor), onOpenWidgetConstructor)
)
)
}

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.debug
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun DebugScreen(onBackToSettings: () -> Unit) {
MockScreenScaffold(
title = "Debug",
subtitle = "Debug-only tools placeholder.",
actions = listOf(ScreenAction("Back to Settings", onBackToSettings))
title = stringResource(id = R.string.title_debug),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(stringResource(id = R.string.back_to_settings), onBackToSettings))
)
}

View File

@@ -1,6 +1,8 @@
package org.db3.airmq.features.device
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@@ -11,11 +13,11 @@ fun DeviceScreen(
onShowOnMap: () -> Unit
) {
MockScreenScaffold(
title = "Device",
subtitle = "Mock deviceId: $deviceId",
title = stringResource(id = R.string.title_device),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(
ScreenAction("Select Location", onOpenLocation),
ScreenAction("Show on Map", onShowOnMap)
ScreenAction(stringResource(id = R.string.title_location), onOpenLocation),
ScreenAction(stringResource(id = R.string.button_view_on_map), onShowOnMap)
)
)
}

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.entry
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun SplashScreen(onContinue: () -> Unit) {
MockScreenScaffold(
title = "Splash",
subtitle = "Entry flow starting point.",
actions = listOf(ScreenAction(label = "Continue to Wizard", onClick = onContinue))
title = stringResource(id = R.string.screen_splash_title),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(label = stringResource(id = R.string.screen_continue_to_wizard), onClick = onContinue))
)
}

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.entry
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun WizardScreen(onFinish: () -> Unit) {
MockScreenScaffold(
title = "Wizard",
subtitle = "Mock onboarding/wizard flow.",
actions = listOf(ScreenAction(label = "Finish Wizard", onClick = onFinish))
title = stringResource(id = R.string.screen_wizard_title),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(label = stringResource(id = R.string.screen_finish_wizard), onClick = onFinish))
)
}

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.location
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun LocationScreen(onBackToManage: () -> Unit) {
MockScreenScaffold(
title = "Location",
subtitle = "Mock location picker/editor screen.",
actions = listOf(ScreenAction("Back to Manage", onBackToManage))
title = stringResource(id = R.string.title_location),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(stringResource(id = R.string.back_to_manage), onBackToManage))
)
}

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.login
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun LoginScreen(onLogInToManage: () -> Unit) {
MockScreenScaffold(
title = "Login",
subtitle = "Mock account sign-in screen.",
actions = listOf(ScreenAction("Log In to Manage", onLogInToManage))
title = stringResource(id = R.string.button_sign_in),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(stringResource(id = R.string.screen_log_in_to_manage), onLogInToManage))
)
}

View File

@@ -27,11 +27,13 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import kotlinx.coroutines.flow.collectLatest
import org.db3.airmq.R
import org.db3.airmq.features.common.AirMqButton
import org.db3.airmq.features.common.AirMqButtonStyle
import org.db3.airmq.features.manage.ManageScreenContract.Action
@@ -107,14 +109,14 @@ private fun ManageScreenContent(
}
Spacer(modifier = Modifier.height(8.dp))
AirMqButton(
text = "Open Widget Constructor",
text = stringResource(id = R.string.manage_open_widget_constructor),
onClick = onOpenWidgetConstructor,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
)
AirMqButton(
text = "Back to Dashboard",
text = stringResource(id = R.string.back_to_dashboard),
onClick = onBackToDashboard,
style = AirMqButtonStyle.Outlined,
modifier = Modifier
@@ -147,12 +149,12 @@ private fun ProfileHeader(
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "Manage",
text = stringResource(id = R.string.title_manage),
style = MaterialTheme.typography.headlineSmall,
color = Color.White
)
AirMqButton(
text = "Settings",
text = stringResource(id = R.string.title_settings),
onClick = onSettingsClick,
style = AirMqButtonStyle.Text
)
@@ -205,7 +207,7 @@ private fun AnonymousContent(
)
Spacer(modifier = Modifier.height(16.dp))
AirMqButton(
text = "Sign in",
text = stringResource(id = R.string.button_sign_in),
onClick = onSignIn,
style = AirMqButtonStyle.Gradient,
modifier = Modifier.fillMaxWidth()
@@ -229,7 +231,7 @@ private fun AuthorizedContent(
Text(text = devicesLabel, style = MaterialTheme.typography.titleMedium)
Spacer(modifier = Modifier.height(12.dp))
AirMqButton(
text = "Setup",
text = stringResource(id = R.string.button_setup),
onClick = onOpenSetup,
style = AirMqButtonStyle.Gradient,
modifier = Modifier.fillMaxWidth()
@@ -272,13 +274,17 @@ private fun DeviceRow(
Spacer(modifier = Modifier.height(8.dp))
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
AirMqButton(
text = "Open",
text = stringResource(id = R.string.button_open),
onClick = onOpenDevice,
style = AirMqButtonStyle.Contained,
modifier = Modifier.weight(1f)
)
AirMqButton(
text = if (item.hasLocation) "Show on map" else "Set location",
text = if (item.hasLocation) {
stringResource(id = R.string.button_view_on_map)
} else {
stringResource(id = R.string.manage_set_location)
},
onClick = onOpenLocation,
style = AirMqButtonStyle.Outlined,
modifier = Modifier.weight(1f)

View File

@@ -16,9 +16,9 @@ object ManageScreenContract {
data class State(
val userMode: UserMode = UserMode.ANONYMOUS,
val userName: String = "Anonymous",
val userEmail: String = "Please sign in to access your devices.",
val devicesLabel: String = "Sign in to see your devices",
val userName: String = "",
val userEmail: String = "",
val devicesLabel: String = "",
val devices: List<DeviceItem> = emptyList()
)

View File

@@ -1,7 +1,9 @@
package org.db3.airmq.features.manage
import android.content.Context
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -9,6 +11,7 @@ import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import org.db3.airmq.R
import org.db3.airmq.features.manage.ManageScreenContract.Action
import org.db3.airmq.features.manage.ManageScreenContract.DeviceItem
import org.db3.airmq.features.manage.ManageScreenContract.Event
@@ -16,7 +19,9 @@ import org.db3.airmq.features.manage.ManageScreenContract.State
import org.db3.airmq.features.manage.ManageScreenContract.UserMode
@HiltViewModel
class ManageViewModel @Inject constructor() : ViewModel() {
class ManageViewModel @Inject constructor(
@ApplicationContext private val appContext: Context
) : ViewModel() {
// Temporary migration stub: keep screen in anonymous mode.
private val forceAnonymous = true
@@ -45,24 +50,27 @@ class ManageViewModel @Inject constructor() : ViewModel() {
}
return when (mode) {
UserMode.ANONYMOUS -> State(
userMode = UserMode.ANONYMOUS
userMode = UserMode.ANONYMOUS,
userName = appContext.getString(R.string.text_anonymous_user),
userEmail = appContext.getString(R.string.text_please_sign_in),
devicesLabel = appContext.getString(R.string.text_sign_in_small)
)
UserMode.AUTHORIZED -> State(
userMode = UserMode.AUTHORIZED,
userName = "Anton Betsun",
userEmail = "messbees@gmail.com",
devicesLabel = "My devices",
userName = appContext.getString(R.string.mock_user_name),
userEmail = appContext.getString(R.string.mock_user_email),
devicesLabel = appContext.getString(R.string.text_your_devices),
devices = listOf(
DeviceItem(
id = "device-1",
name = "AirMQ #42",
status = "Online",
name = appContext.getString(R.string.mock_device_name_42),
status = appContext.getString(R.string.map_status_online),
hasLocation = true
),
DeviceItem(
id = "device-2",
name = "AirMQ #17",
status = "Offline",
name = appContext.getString(R.string.mock_device_name_17),
status = appContext.getString(R.string.map_status_offline),
hasLocation = false
)
)

View File

@@ -67,7 +67,7 @@ fun MapScreen(
// Stub for future navigation integration.
Toast.makeText(
context,
"Open device ${action.deviceId} is not wired yet",
context.getString(R.string.map_open_device_not_wired, action.deviceId),
Toast.LENGTH_SHORT
).show()
}
@@ -110,7 +110,7 @@ private fun MapScreenContent(
onHelpClick = {
Toast.makeText(
context,
context.getString(R.string.map_sensor_help_title),
context.getString(R.string.text_what_does_it_mean_title),
Toast.LENGTH_SHORT
).show()
},
@@ -209,7 +209,11 @@ private fun AirMQMap(
val marker = Marker(map).apply {
position = GeoPoint(item.latitude, item.longitude)
title = listOfNotNull(item.title, item.city).joinToString(" - ")
subDescription = if (item.isOnline) "Online" else "Offline"
subDescription = if (item.isOnline) {
context.getString(R.string.map_status_online)
} else {
context.getString(R.string.map_status_offline)
}
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
icon = createMarkerIcon(map, item)
setOnMarkerClickListener { _, _ ->

View File

@@ -31,7 +31,7 @@ object MapScreenContract {
val name: String,
val status: String,
val selectedRange: TimeRange = TimeRange.DAY,
val displayedDateRange: String = "Today",
val displayedDateRange: String = "",
val selectedSensor: DeviceSensorType = DeviceSensorType.TEMPERATURE
)

View File

@@ -61,8 +61,8 @@ fun MapTopControls(
var isExpanded by remember(initiallyExpanded) { mutableStateOf(initiallyExpanded) }
val arrowRotation = if (isExpanded) 180f else 0f
val selectedLabel = when (selectedSensor) {
SensorType.DUST -> stringResource(id = R.string.map_sensor_air_quality)
SensorType.RADIOACTIVITY -> stringResource(id = R.string.map_sensor_radioactivity)
SensorType.DUST -> stringResource(id = R.string.text_air_quality)
SensorType.RADIOACTIVITY -> stringResource(id = R.string.sensor_radioactivity)
}
Box(
@@ -117,7 +117,7 @@ fun MapTopControls(
Column(modifier = Modifier.padding(top = 8.dp, bottom = 10.dp)) {
SensorTypeItem(
iconRes = R.drawable.ic_dust,
titleRes = R.string.map_sensor_air_quality,
titleRes = R.string.text_air_quality,
selected = selectedSensor == SensorType.DUST,
onClick = {
onSensorSelected(SensorType.DUST)
@@ -127,7 +127,7 @@ fun MapTopControls(
HorizontalDivider(color = Color(0x1F000000))
SensorTypeItem(
iconRes = R.drawable.ic_radiation,
titleRes = R.string.map_sensor_radioactivity,
titleRes = R.string.sensor_radioactivity,
selected = selectedSensor == SensorType.RADIOACTIVITY,
onClick = {
onSensorSelected(SensorType.RADIOACTIVITY)
@@ -135,7 +135,7 @@ fun MapTopControls(
}
)
Text(
text = stringResource(id = R.string.map_sensor_help_link),
text = stringResource(id = R.string.text_what_does_it_mean),
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(top = 12.dp)
@@ -223,12 +223,12 @@ fun MapFloatingActions(
) {
RoundIconButton(
iconRes = R.drawable.ic_map_search,
contentDescription = stringResource(id = R.string.map_search_action_content_desc),
contentDescription = stringResource(id = R.string.content_search),
onClick = onSearchClick
)
RoundIconButton(
iconRes = R.drawable.ic_map_my_location,
contentDescription = stringResource(id = R.string.map_my_location_content_desc),
contentDescription = stringResource(id = R.string.content_my_location),
onClick = onMyLocationClick
)
}
@@ -280,7 +280,7 @@ fun MapSearchOverlay(
verticalAlignment = Alignment.CenterVertically
) {
AirMqButton(
text = stringResource(id = R.string.map_back),
text = stringResource(id = R.string.content_back),
onClick = onClose,
style = AirMqButtonStyle.Outlined
)
@@ -357,7 +357,7 @@ fun MapDevicePanel(
verticalAlignment = Alignment.CenterVertically
) {
AirMqButton(
text = stringResource(id = R.string.map_close),
text = stringResource(id = R.string.button_close),
onClick = onClose,
style = AirMqButtonStyle.Text
)
@@ -373,7 +373,7 @@ fun MapDevicePanel(
)
}
AirMqButton(
text = stringResource(id = R.string.map_open_device),
text = stringResource(id = R.string.button_open),
onClick = onOpenDevice,
style = AirMqButtonStyle.Outlined
)
@@ -436,22 +436,22 @@ private fun TimeRangeRow(
FilterChip(
selected = selected == TimeRange.HOUR,
onClick = { onSelected(TimeRange.HOUR) },
label = { Text(stringResource(id = R.string.map_filter_hour)) }
label = { Text(stringResource(id = R.string.filter_hour)) }
)
FilterChip(
selected = selected == TimeRange.DAY,
onClick = { onSelected(TimeRange.DAY) },
label = { Text(stringResource(id = R.string.map_filter_day)) }
label = { Text(stringResource(id = R.string.filter_day)) }
)
FilterChip(
selected = selected == TimeRange.WEEK,
onClick = { onSelected(TimeRange.WEEK) },
label = { Text(stringResource(id = R.string.map_filter_week)) }
label = { Text(stringResource(id = R.string.filter_week)) }
)
FilterChip(
selected = selected == TimeRange.MONTH,
onClick = { onSelected(TimeRange.MONTH) },
label = { Text(stringResource(id = R.string.map_filter_month)) }
label = { Text(stringResource(id = R.string.filter_month)) }
)
}
}
@@ -468,17 +468,17 @@ private fun DeviceSensorRow(
FilterChip(
selected = selectedSensor == DeviceSensorType.TEMPERATURE,
onClick = { onSelected(DeviceSensorType.TEMPERATURE) },
label = { Text(stringResource(id = R.string.map_device_sensor_temperature)) }
label = { Text(stringResource(id = R.string.sensor_temperature)) }
)
FilterChip(
selected = selectedSensor == DeviceSensorType.DUST,
onClick = { onSelected(DeviceSensorType.DUST) },
label = { Text(stringResource(id = R.string.map_device_sensor_dust)) }
label = { Text(stringResource(id = R.string.sensor_dust)) }
)
FilterChip(
selected = selectedSensor == DeviceSensorType.RADIOACTIVITY,
onClick = { onSelected(DeviceSensorType.RADIOACTIVITY) },
label = { Text(stringResource(id = R.string.map_device_sensor_radioactivity)) }
label = { Text(stringResource(id = R.string.sensor_radioactivity)) }
)
}
}

View File

@@ -1,8 +1,10 @@
package org.db3.airmq.features.map
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -12,6 +14,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.db3.airmq.R
import org.db3.airmq.features.map.MapScreenContract.Action
import org.db3.airmq.features.map.MapScreenContract.DevicePanelState
import org.db3.airmq.features.map.MapScreenContract.DeviceSensorType
@@ -27,6 +30,7 @@ import org.db3.airmq.sdk.settings.SettingsService
@HiltViewModel
class MapViewModel @Inject constructor(
@ApplicationContext private val appContext: Context,
private val mapService: MapService,
private val settingsService: SettingsService
) : ViewModel() {
@@ -81,7 +85,7 @@ class MapViewModel @Inject constructor(
}
is Event.MyLocationClicked -> {
_actions.tryEmit(Action.ShowToast("My location logic will be added later"))
_actions.tryEmit(Action.ShowToast(appContext.getString(R.string.map_my_location_coming_soon)))
}
is Event.TopSensorSelected -> {
@@ -121,14 +125,24 @@ class MapViewModel @Inject constructor(
is Event.DateBackClicked -> {
val panelData = _uiState.value.devicePanelState ?: return
_uiState.value = _uiState.value.copy(
devicePanelState = panelData.copy(displayedDateRange = "Previous ${rangeLabel(panelData.selectedRange)}")
devicePanelState = panelData.copy(
displayedDateRange = appContext.getString(
R.string.map_previous_period,
rangeLabel(panelData.selectedRange)
)
)
)
}
Event.DateForwardClicked -> {
val panelData = _uiState.value.devicePanelState ?: return
_uiState.value = _uiState.value.copy(
devicePanelState = panelData.copy(displayedDateRange = "Next ${rangeLabel(panelData.selectedRange)}")
devicePanelState = panelData.copy(
displayedDateRange = appContext.getString(
R.string.map_next_period,
rangeLabel(panelData.selectedRange)
)
)
)
}
is Event.DeviceSensorSelected -> {
@@ -162,7 +176,11 @@ class MapViewModel @Inject constructor(
},
onFailure = { throwable ->
domainItems = emptyList()
_actions.tryEmit(Action.ShowToast(throwable.message ?: "Failed to load map items"))
_actions.tryEmit(
Action.ShowToast(
throwable.message ?: appContext.getString(R.string.map_failed_to_load_items)
)
)
val searchPanelState = _uiState.value.searchPanelState
_uiState.value.copy(
isLoading = false,
@@ -186,16 +204,16 @@ class MapViewModel @Inject constructor(
SearchResult(
id = item.id,
title = item.title,
subtitle = item.city ?: "No city"
subtitle = item.city ?: appContext.getString(R.string.map_no_city)
)
}
}
private fun rangeLabel(range: TimeRange): String = when (range) {
TimeRange.HOUR -> "Last hour"
TimeRange.DAY -> "Today"
TimeRange.WEEK -> "This week"
TimeRange.MONTH -> "This month"
TimeRange.HOUR -> appContext.getString(R.string.map_time_last_hour)
TimeRange.DAY -> appContext.getString(R.string.map_time_today)
TimeRange.WEEK -> appContext.getString(R.string.map_time_this_week)
TimeRange.MONTH -> appContext.getString(R.string.map_time_this_month)
}
private fun remapMarkers() {
@@ -231,7 +249,11 @@ class MapViewModel @Inject constructor(
return DevicePanelState(
id = id,
name = title,
status = if (isOnline) "online" else "offline",
status = if (isOnline) {
appContext.getString(R.string.map_status_online)
} else {
appContext.getString(R.string.map_status_offline)
},
selectedRange = TimeRange.DAY,
displayedDateRange = rangeLabel(TimeRange.DAY),
selectedSensor = defaultSensor

View File

@@ -15,6 +15,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavType
import androidx.navigation.NavGraph.Companion.findStartDestination
@@ -52,9 +53,9 @@ import org.db3.airmq.ui.theme.LegacyNavUnselected
fun AirMQNavGraph(modifier: Modifier = Modifier) {
val navController = rememberNavController()
val tabItems = listOf(
BottomTabItem(route = AirMqRoutes.MAP, label = "Map", iconRes = R.drawable.ic_map),
BottomTabItem(route = AirMqRoutes.DASHBOARD, label = "Dashboard", iconRes = R.drawable.ic_dashboard),
BottomTabItem(route = AirMqRoutes.MANAGE, label = "Manage", iconRes = R.drawable.ic_manage_active)
BottomTabItem(route = AirMqRoutes.MAP, label = stringResource(id = R.string.title_map), iconRes = R.drawable.ic_map),
BottomTabItem(route = AirMqRoutes.DASHBOARD, label = stringResource(id = R.string.title_dashboard), iconRes = R.drawable.ic_dashboard),
BottomTabItem(route = AirMqRoutes.MANAGE, label = stringResource(id = R.string.title_manage), iconRes = R.drawable.ic_manage_active)
)
val tabRoutes = tabItems.map { it.route }.toSet()
val navBackStackEntry by navController.currentBackStackEntryAsState()

View File

@@ -1,14 +1,16 @@
package org.db3.airmq.features.news
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@Composable
fun NewsDetailScreen(newsId: String, onBackToNews: () -> Unit) {
MockScreenScaffold(
title = "News Detail",
subtitle = "Mock newsId: $newsId",
actions = listOf(ScreenAction("Back to News", onBackToNews))
title = stringResource(id = R.string.news_detail_title),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(ScreenAction(stringResource(id = R.string.back_to_news), onBackToNews))
)
}

View File

@@ -1,6 +1,8 @@
package org.db3.airmq.features.news
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@@ -10,11 +12,11 @@ fun NewsScreen(
onBackToDashboard: () -> Unit
) {
MockScreenScaffold(
title = "News",
subtitle = "Mock news list screen.",
title = stringResource(id = R.string.text_widget_news),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(
ScreenAction("Open News Detail", onOpenNewsDetail),
ScreenAction("Back to Dashboard", onBackToDashboard)
ScreenAction(stringResource(id = R.string.news_open_detail), onOpenNewsDetail),
ScreenAction(stringResource(id = R.string.back_to_dashboard), onBackToDashboard)
)
)
}

View File

@@ -31,10 +31,12 @@ import androidx.compose.ui.Modifier
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.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import kotlinx.coroutines.flow.collectLatest
import org.db3.airmq.R
import org.db3.airmq.features.settings.SettingsScreenContract.Action
import org.db3.airmq.features.settings.SettingsScreenContract.Event
import org.db3.airmq.features.settings.SettingsScreenContract.State
@@ -99,7 +101,7 @@ private fun SettingsScreenContent(
verticalArrangement = Arrangement.spacedBy(2.dp)
) {
Text(
text = "Application",
text = stringResource(id = R.string.pref_application_header),
style = MaterialTheme.typography.labelLarge,
color = Color(0xFF607D8B),
modifier = Modifier.padding(start = headerTextStart, top = 4.dp, bottom = 4.dp)
@@ -107,7 +109,7 @@ private fun SettingsScreenContent(
PreferenceRow(
iconName = "ic_pref_city",
iconFallbackRes = android.R.drawable.ic_menu_myplaces,
title = "City in dashboard",
title = stringResource(id = R.string.pref_city_title),
summary = uiState.city,
iconSize = iconSize,
iconTextGap = iconTextGap,
@@ -116,7 +118,7 @@ private fun SettingsScreenContent(
PreferenceCheckRow(
iconName = "ic_pref_notifications",
iconFallbackRes = android.R.drawable.ic_dialog_info,
title = "Notify when device becomes offline",
title = stringResource(id = R.string.pref_notifications_title),
checked = uiState.deviceStatusNotificationsEnabled,
iconSize = iconSize,
iconTextGap = iconTextGap,
@@ -125,7 +127,7 @@ private fun SettingsScreenContent(
PreferenceCheckRow(
iconName = "ic_pref_offline_devices",
iconFallbackRes = android.R.drawable.ic_menu_mylocation,
title = "Show offline devices",
title = stringResource(id = R.string.pref_offline_devices_title),
checked = uiState.offlineDevicesVisible,
iconSize = iconSize,
iconTextGap = iconTextGap,
@@ -134,7 +136,7 @@ private fun SettingsScreenContent(
PreferenceRow(
iconName = "ic_pref_info",
iconFallbackRes = android.R.drawable.ic_dialog_info,
title = "About",
title = stringResource(id = R.string.pref_about),
iconSize = iconSize,
iconTextGap = iconTextGap,
onClick = { onEvent(Event.AboutClicked) }
@@ -143,7 +145,7 @@ private fun SettingsScreenContent(
PreferenceRow(
iconName = "ic_pref_debug",
iconFallbackRes = android.R.drawable.ic_lock_power_off,
title = "Log out",
title = stringResource(id = R.string.pref_logout_title),
iconSize = iconSize,
iconTextGap = iconTextGap,
onClick = { onEvent(Event.LogOutClicked) }

View File

@@ -9,7 +9,7 @@ object SettingsScreenContract {
data class State(
val userMode: UserMode = UserMode.ANONYMOUS,
val city: String = "Minsk",
val city: String = "",
val deviceStatusNotificationsEnabled: Boolean = true,
val offlineDevicesVisible: Boolean = false,
val advancedEnabled: Boolean = false,

View File

@@ -1,8 +1,10 @@
package org.db3.airmq.features.settings
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -12,6 +14,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.db3.airmq.R
import org.db3.airmq.features.settings.SettingsScreenContract.Action
import org.db3.airmq.features.settings.SettingsScreenContract.Event
import org.db3.airmq.features.settings.SettingsScreenContract.State
@@ -20,6 +23,7 @@ import org.db3.airmq.sdk.settings.SettingsService
@HiltViewModel
class SettingsViewModel @Inject constructor(
@ApplicationContext private val appContext: Context,
private val settingsService: SettingsService
) : ViewModel() {
@@ -38,8 +42,8 @@ class SettingsViewModel @Inject constructor(
fun onEvent(event: Event) {
when (event) {
Event.CityClicked -> _actions.tryEmit(Action.ShowMessage("Coming Soon"))
Event.AboutClicked -> _actions.tryEmit(Action.ShowMessage("Coming Soon"))
Event.CityClicked -> _actions.tryEmit(Action.ShowMessage(appContext.getString(R.string.coming_soon)))
Event.AboutClicked -> _actions.tryEmit(Action.ShowMessage(appContext.getString(R.string.coming_soon)))
Event.DebugClicked -> _actions.tryEmit(Action.OpenDebug)
Event.LogOutClicked -> _actions.tryEmit(Action.LogOutToManage)
is Event.DeviceStatusNotificationsChanged -> {
@@ -65,7 +69,7 @@ class SettingsViewModel @Inject constructor(
private fun loadSettings() {
viewModelScope.launch(Dispatchers.IO) {
val city = settingsService.getCity() ?: "Minsk"
val city = settingsService.getCity() ?: appContext.getString(R.string.city_minsk)
val deviceStatus = settingsService.getDeviceStatusNotificationsEnabled()
val offlineVisible = settingsService.getOfflineDevicesVisible()
val advanced = settingsService.getAdvancedEnabled()
@@ -91,7 +95,10 @@ class SettingsViewModel @Inject constructor(
if (result.isFailure) {
_uiState.value = previous
_actions.tryEmit(
Action.ShowMessage(result.exceptionOrNull()?.message ?: "Failed to save settings")
Action.ShowMessage(
result.exceptionOrNull()?.message
?: appContext.getString(R.string.settings_save_failed)
)
)
}
}

View File

@@ -1,6 +1,8 @@
package org.db3.airmq.features.setup
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.db3.airmq.R
import org.db3.airmq.features.common.MockScreenScaffold
import org.db3.airmq.features.common.ScreenAction
@@ -10,11 +12,11 @@ fun SetupScreen(
onCancelSetup: () -> Unit
) {
MockScreenScaffold(
title = "Setup",
subtitle = "Mock setup flow for device onboarding.",
title = stringResource(id = R.string.button_setup),
subtitle = stringResource(id = R.string.coming_soon),
actions = listOf(
ScreenAction("Finish Setup", onFinishSetup),
ScreenAction("Cancel Setup", onCancelSetup)
ScreenAction(stringResource(id = R.string.button_finish), onFinishSetup),
ScreenAction(stringResource(id = R.string.button_cancel), onCancelSetup)
)
)
}

View File

@@ -0,0 +1,277 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title_map">Карта</string>
<string name="title_dashboard">Дашборд</string>
<string name="title_manage">Кіраванне</string>
<string name="title_settings">Налады</string>
<string name="title_device">Прылада</string>
<string name="title_location">Месцазнаходжанне</string>
<string name="dialog_internet">Падлучыцеся да Інтэрнэту</string>
<string name="dialog_are_you_sure">Вы ўпэўненыя?</string>
<string name="dialog_select_device_title">Выбраць прыладу</string>
<string name="dialog_anonym_title">Працягнуць ананімна?</string>
<string name="text_setup_error_title">Памылка</string>
<string name="text_setup_finish">Новая прылада паспяхова дададзена!</string>
<string name="text_your_devices">Вашы прылады</string>
<string name="text_anonymous_user">Ананімны карыстальнік</string>
<string name="err_short_password">Пароль Wifi мусіць змяшчаць мінімум 8 сімвалаў</string>
<string name="err_no_name">Вы не пазначылі імя</string>
<string name="err_no_model">Вы не выбралі мадэль</string>
<string name="button_ok">ОК</string>
<string name="button_continue">Працягнуць</string>
<string name="button_select">Выбраць</string>
<string name="button_cancel">Адмяніць</string>
<string name="text_privacy_policy"><b><u>Палітыка канфідэнцыйнасці</u></b></string>
<string name="button_sign_in_google">Увайсці з дапамогай Google</string>
<string name="button_sign_in_facebook">Увайсці з дапамогай Facebook</string>
<string name="button_look_for_device">Пошук прылады</string>
<string name="button_finish">Завяршыць</string>
<string name="button_continue_anonym">Працягнуць ананімна</string>
<string name="button_exit_setup">Выйсці з усталявання</string>
<string name="button_abort">Перарваць</string>
<string name="button_wait">Чаканне…</string>
<string name="button_setup">Дадаць прыладу</string>
<string name="button_connecting">Падлучэнне…</string>
<string name="hint_password">Пароль</string>
<string name="hint_device_name">Імя прылады</string>
<string name="hint_setup_name">Імя</string>
<string name="hint_setup_model">Мадэль</string>
<string name="content_settings">Налады</string>
<string name="sensor_temperature">Тэмпература</string>
<string name="sensor_pressure">Ціск</string>
<string name="sensor_dust">Цвёрдыя часціцы</string>
<string name="sensor_radioactivity">Радыеактыўнасць</string>
<string name="pref_account_header">Акаўнт</string>
<string name="pref_device_header">Прылада</string>
<string name="toast_copied">Скапіявана</string>
<string name="dialog_enable_wifi_title">Уключыце Wi-Fi</string>
<string name="dialog_select_wifi_title">Выбраць сетку Wi-Fi</string>
<string name="dialog_exit_setup_text">Вы ўпэўненыя, што хочаце перарваць усталяванне? Верагодна, наступным разам перад усталяваннем прыйдзецца скінуць прыладу AirMQ</string>
<string name="dialog_exit_setup_title">Перарваць усталяванне</string>
<string name="title_device_config">Кіраванне</string>
<string name="dialog_about_title">Аб праграме</string>
<string name="dialog_anonym_mesage">Вы не зможаце захоўваць налады і дадаваць новыя прылады AirMQ</string>
<string name="text_sign_in">Увайсці ў AirMQ</string>
<string name="text_setup_error">Памылка падчас усталявання:</string>
<string name="text_whats_new">Што новага</string>
<string name="text_fixes">Выпраўленні</string>
<string name="text_setup_1">Уключыце ці перазагрузіце прыладу AirMQ, пасля чаго яна стане бачнай на працягу 90 секунд. Потым націсніце кнопку \"Выбраць прыладу\". На некаторых прыладах для карэктнага злучэння з прыладай AirMQ патрэбны ўключаны GPS.</string>
<string name="text_setup_2">Увядзіце імя прылады і выберыце яго мадэль</string>
<string name="text_setup_3">Выберыце сетку Wi-Fi, да якой хочаце падлучыць вашу прыладу</string>
<string name="text_setup_steps">Шаг %d из 3</string>
<string name="text_setup_label">Усталяванне новай прылады</string>
<string name="text_terms_conditions"><b><u>Умовамі і палажэннямі</u></b></string>
<string name="text_please_sign_in">Налады не сінхранізуюцца, калі ласка, увайдзіце ў сістэму</string>
<string name="text_sign_in_small">Увайдзіце ў сістэму для дадавання прылад</string>
<string name="err_no_device_ap">Вы не выбралі сетку Wi-Fi</string>
<string name="button_sign_in">Увайсці</string>
<string name="button_register">Зарэгістраваць</string>
<string name="button_copy_log">Капіяваць лог</string>
<string name="hint_setup_wifi">Сетка Wi-Fi</string>
<string name="content_desc_user_pic">Выява карыстальніка</string>
<string name="content_device_icon">Іконка прылады</string>
<string name="content_network_icon">Іконка сеткі</string>
<string name="content_airmq_logo">Лагатып AirMQ</string>
<string name="sensor_humidity">Вільготнасць</string>
<string name="pref_logout_title">Выйсці</string>
<string name="pref_prefix_title">Прэфікс кропкі доступу AirMQ</string>
<string name="pref_wpakey_title">Пароль па змаўчанні</string>
<string name="pref_versions">Версіі файлаў канфігурацыі</string>
<string name="pref_about">Аб праграме</string>
<string name="pref_notifications_title">Паведамляць, калі прылада становіцца неактыўнай</string>
<string name="notification_device_status_title">Ваша прылада адключылася ад сеткі!</string>
<string name="notification_device_status_text">%s цяпер неактыўны. Націсніце на гэта апавяшчэнне, каб адчыніць канфігурацыю прылады</string>
<string name="toast_oauth_failed">Памылка аўтарызацыі Google</string>
<string name="snackbar_not_registered">Патрабуецца рэгістрацыя</string>
<string name="text_policy_label">Уваходзячы ў сістэму, вы згаджаецеся з нашымі %1$s и %2$s</string>
<string name="text_what_does_it_mean"><u>Што гэта значыць?</u></string>
<string name="text_air_quality">Якасць паветра</string>
<string name="filter_hour">Гадзіна</string>
<string name="filter_day">Дзень</string>
<string name="filter_week">Тыдзень</string>
<string name="filter_month">Месяц</string>
<string name="pref_fullscreen">Бязрамачны інтэрфэйс</string>
<string name="text_error">Памылка</string>
<string name="text_error_connecting">Прылада не адказвае. Паспрабуйце выключыць мабільны інтэрнэт і паўтарыць.</string>
<string name="button_setup_in_progress">Устаноўка…</string>
<string name="button_start_setup">Пачаць устаноўку</string>
<string name="text_device_name">Імя</string>
<string name="text_device_id">ID прылады</string>
<string name="text_device_ip">IP-Адрас</string>
<string name="text_device_firmware">Версія прашыўкі</string>
<string name="text_device_location">Месцазнаходжанне</string>
<string name="text_device_location_unset">Прылада не зарэгістравана</string>
<string name="text_device_visibility">Бачнасць</string>
<string name="text_device_visibility_visible">Апублікавана</string>
<string name="text_device_visibility_private">Схавана</string>
<string name="text_device_visibility_not_registered">Зарэгіструйце прыладу, каб мяняць бачнасць</string>
<string name="button_rename">Перайменаваць</string>
<string name="button_update">Абнавіць</string>
<string name="button_unregister">Скінуць</string>
<string name="button_hide">Схаваць</string>
<string name="button_publish">Апублікаваць</string>
<string name="button_reboot">Перазагрузіць</string>
<string name="button_reset">Скінуць</string>
<string name="button_view_on_map">Адчыніць на карце</string>
<string name="hint_new_name">Новае імя</string>
<string name="dialog_rename_title">Перайменаваць</string>
<string name="err_short_name">Імя занадта кароткае!</string>
<string name="toast_error">Памылка</string>
<string name="toast_rebooting">Перазагрузка…</string>
<string name="toast_resetting">Скід…</string>
<string name="pref_offline_devices_title">Паказваць недаступныя прылады</string>
<string name="button_open">Адчыніць</string>
<string name="pref_advanced">Уключыць пашыраныя налады</string>
<string name="pref_advanced_header">Пашыраныя налады</string>
<string name="pref_application_header">Праграма</string>
<string name="pref_advanced_config">Уключыць пашыраную канфігурацыю прылады</string>
<string name="text_device_config_version">Версія канфігурацыі</string>
<string name="text_device_uptime">Аптайм</string>
<string name="content_sensor_icon">Іконка датчыка</string>
<string name="text_no_data">Няма дадзеных</string>
<string name="dialog_widget_delete_title">Выдаліць віджэты</string>
<string name="dialog_widget_delete_text">Вы ўпэўненыя, што хочаце выдаліць гэты віджэт?</string>
<string name="button_add_widget">Дадаць віджэт</string>
<string name="city_minsk">Мінск</string>
<string name="city_barauliany">Бараўляны</string>
<string name="city_navapolack">Наваполацк</string>
<string name="city_mahiliou">Магілёў</string>
<string name="city_hrodna">Гродна</string>
<string name="city_homiel">Гомель</string>
<string name="city_polack">Полацк</string>
<string name="city_barysau">Барысаў</string>
<string name="city_narac">Нарач</string>
<string name="city_salihorsk">Салігорск</string>
<string name="city_brest">Брэст</string>
<string name="city_babrujsk">Бабруйск</string>
<string name="pref_city_title">Горад у дашбордзе</string>
<string name="dialog_select_city_title">Выберыце горад</string>
<string name="toast_widget_login">Увайдзіце ў сістэму, каб дадаваць віджэты</string>
<string name="text_yesterday">Учора</string>
<string name="text_now">Зараз</string>
<string name="text_no_device">Гэта прылада была выдалена</string>
<string name="text_hour_ago">Гадзіну таму</string>
<string name="text_week_ago">Тыдзень таму</string>
<string name="text_month_ago">Месяц таму</string>
<string name="dialog_widget_add_title">Дадаць віджэт</string>
<string name="text_device_wifi">Сетка WiFi</string>
<string name="text_device_wifi_secondary">Запасная сетка WiFi</string>
<string name="text_days">д</string>
<string name="text_hours">г</string>
<string name="text_minutes">х</string>
<string name="text_move_up">Перамясціць уверх</string>
<string name="teext_move_down">Перамясціць уніз</string>
<string name="text_configure">Наладзіць</string>
<string name="text_add_to_home_screen">Дадаць на працоўны стол</string>
<string name="text_remove">Прыбраць</string>
<string name="snackbar_widget_removed">Віджэт выдалены</string>
<string name="button_undo">Адмяніць</string>
<string name="text_loading">Загрузка…</string>
<string name="content_back">Назад</string>
<string name="title_widget_constructor">Дадаванне віджэта</string>
<string name="text_choose_widget_layout">Выберыце від/выгляд віджэта</string>
<string name="text_no_location">Месцазнаходжанне не выбрана</string>
<string name="text_display_heatmap">Паказваць хітмэп</string>
<string name="text_display_sensors">Паказваць прылады</string>
<string name="text_display_both">Паказваць усё</string>
<string name="text_widget_map">Карта</string>
<string name="text_device">Прылада</string>
<string name="text_widget_chart">Графік</string>
<string name="text_choose_sensor">Выберыце датчык</string>
<string name="text_choose_timeframe">Выберыце прамежак часу</string>
<string name="text_no_devices">У вас няма дададзеных прылад</string>
<string name="text_latest_news">Апошнія навіны</string>
<string name="text_widget_news">Навіны</string>
<string name="button_change">Змяніць</string>
<string name="text_nothing_to_show">Няма прылад</string>
<string name="title_city">Горад</string>
<string name="text_detect_automatically">Вызначаць аўтаматычна</string>
<string name="text_no_city_hint"><u>Няма вашага горада?</u></string>
<string name="text_wrong_city_hint"><u>Няправільны горад?</u></string>
<string name="text_city_warning">Гэтая опцыя вызначае, якія дадзеныя будуць адлюстроўвацца ў дашбордзе. Калі горад не выбраны, будзе ўсталяваны стандартны варыянт.</string>
<string name="text_no_city">"Калі вы не бачыце ваш горад, значыць, у ім няма прылад "</string>
<string name="button_enter_manual">Увесці ўручную</string>
<string name="text_welcome">Вітаем вас у AirMQ</string>
<string name="text_welcome_second">Даведайся чым дыхае твой горад</string>
<string name="text_permission">Неабходны дазвол:</string>
<string name="text_permission_second">• Месцазнаходжанне</string>
<string name="text_permission_third">Месцазнаходжанне неабходна для прадастаўлення дакладных дадзеных пра паветра ў вашым рэгіёне</string>
<string name="button_allow">Дазволіць</string>
<string name="button_not_now">Не зараз</string>
<string name="button_skip">Прапусціць</string>
<string name="button_next">Далей</string>
<string name="text_link"><u>Спасылка</u></string>
<string name="dialog_secondary_wifi">Запасная сетка WiFi</string>
<string name="toast_done">Гатова</string>
<string name="toast_disconnected">Прылада адключылася</string>
<string name="text_device_narodmon">Дасылаць дадзеныя ў сэрвіс <u>narodmon.ru</u></string>
<string name="text_device_narodmon_title">Narodmon.ru</string>
<string name="text_device_luftdata">Дасылаць дадзеныя ў сэрвіс <u>sensor.community</u></string>
<string name="text_device_luftdata_title">Sensor.community</string>
<string name="text_aqi_title">Якасць атмасфернага паветра</string>
<string name="text_rad_title">Узровень радыеактыўнасці</string>
<string name="text_rad">"Датчыкі радыеактыўнасці зроблены на базе лічыльніка Гейгера-Мюлера і вымяраюць фонавае гама-радыеактыўнае выпрамяненне ў месцы ўстаноўкі. Значэнні на індыкатарах і графіках адпавядаюць магутнасці эквівалентнай дозы радыеактыўнага выпрамянення, якая характарызуе ступень уздзеяння гама-выпрамянення на арганізм. Магутнасць эквівалентнай дозы вымяраецца ў зівертах у гадзіну (Зв/г), для зручнасці ўведзена адзінка мілізіверт у гадзіну (мЗв/г) "</string>
<string name="text_aqi">"Датчыкі, якія прымяняюцца ў нашым праекце, збіраюць інфармацыю пра становішча вонкавага навакольнага паветра, надвор’я, а таксама фонавага радыеактыўнага выпрамянення. Адным з важных паказчыкаў якасці паветра, якія непасрэдна ўплываюць на здароўе чалавека, з’яўляецца наяўнасць цвёрдых узважаных часціц і аэразоляў (Particulate Matter, PM), якія мы прызвычаіліся называць пылам. Часціцы могуць з’яўляцца ў паветры як у рэзультаце прыродных і стыхійных з’яў (пылавыя буры, пажары, марскі саляны пыл), так і ў вынікудзейнасці чалавека - прамысловасці, транспарта, хатняга ацяплення, спальвання смецця. Вымярэнне колькасці цвёрдых часціц адбываецца па трох катэгорыях: памерах да 1, 2.5 і 10 мкм. Часцей за ўсё выкарыстоўваюць паказчык канцэнтрацыі цвёрдых часціц памерам да 2.5 мкм, РМ2.5, які паказвае масу частак пылу на адзінку аб’ёма паветра і вымяраецца ў мкГ/м3. Для зручнасці індыкацыі ступені ўздзеяння цвёрдых часціц у атмасферы на арганізм чалавека прымяняецца наступная колеравая шкала. Для ацэнкі ўзяты сярэднія значэнні канцэнтрацыі часціц PM2.5 за апошнія 24 гадзіны. "</string>
<string name="text_what_does_it_mean_title">Што вымяраюць датчыкі AirMQ?</string>
<string name="notification_device_config_title">Даступна аднаўленне</string>
<string name="notification_device_config_text">Ваша прылада \"%s\" гатова к аднаўленню</string>
<string name="dialog_upload_title">Загрузка…</string>
<string name="toast_not_on_network">Вы павінны быць у адной сеткі WiFi з вашай прыладай.</string>
<string name="button_select_device">Выбраць прыладу</string>
<string name="content_search">Пошук</string>
<string name="content_my_location">Маё месцазнаходжанне</string>
<string name="button_close">Закрыць</string>
<string name="map_search_hint">Імя прылады ці горад</string>
<string name="map_search_empty">Пакуль няма вынікаў</string>
<string name="map_arrow_left">&lt;</string>
<string name="map_arrow_right">&gt;</string>
<string name="map_chart_placeholder">Заглушка графіка</string>
<string name="map_open_device_not_wired">Адкрыццё прылады %1$s пакуль не падключана</string>
<string name="map_status_online">Анлайн</string>
<string name="map_status_offline">Афлайн</string>
<string name="map_my_location_coming_soon">Логіка майго месцазнаходжання будзе дададзена пазней</string>
<string name="map_previous_period">Папярэдні %1$s</string>
<string name="map_next_period">Наступны %1$s</string>
<string name="map_failed_to_load_items">Не ўдалося загрузіць элементы карты</string>
<string name="map_no_city">Няма горада</string>
<string name="map_time_last_hour">Апошняя гадзіна</string>
<string name="map_time_today">Сёння</string>
<string name="map_time_this_week">Гэты тыдзень</string>
<string name="map_time_this_month">Гэты месяц</string>
<string name="settings_save_failed">Не ўдалося захаваць налады</string>
<string name="title_debug">Адладка</string>
<string name="manage_open_widget_constructor">Адкрыць канструктар віджэтаў</string>
<string name="back_to_dashboard">Назад да дашборда</string>
<string name="manage_set_location">Задаць месцазнаходжанне</string>
<string name="dashboard_subtitle">Эквівалент ніжняй укладкі: дашборд</string>
<string name="dashboard_open_map">Адкрыць карту</string>
<string name="dashboard_open_manage">Адкрыць кіраванне</string>
<string name="dashboard_open_city">Адкрыць горад</string>
<string name="dashboard_open_device">Адкрыць прыладу</string>
<string name="dashboard_open_news">Адкрыць навіны</string>
<string name="screen_splash_title">Застаўка</string>
<string name="screen_continue_to_wizard">Працягнуць у майстар</string>
<string name="screen_wizard_title">Майстар</string>
<string name="screen_finish_wizard">Завяршыць майстар</string>
<string name="screen_mock_device_id">Тэставы deviceId: %1$s</string>
<string name="back_to_settings">Назад да налад</string>
<string name="back_to_manage">Назад да кіравання</string>
<string name="screen_log_in_to_manage">Увайсці ў кіраванне</string>
<string name="news_open_detail">Адкрыць дэталі навіны</string>
<string name="news_detail_title">Дэталі навіны</string>
<string name="screen_mock_news_id">Тэставы newsId: %1$s</string>
<string name="widget_select_map_location">Выбраць лакацыю віджэта карты</string>
<string name="widget_open_map_constructor">Адкрыць канструктар карты</string>
<string name="widget_open_chart_constructor">Адкрыць канструктар графіка</string>
<string name="widget_open_news_constructor">Адкрыць канструктар навін</string>
<string name="back_to_widget_constructor">Назад да канструктара віджэтаў</string>
<string name="widget_map_constructor_title">Канструктар карты</string>
<string name="widget_chart_constructor_title">Канструктар графіка</string>
<string name="widget_news_constructor_title">Канструктар навін</string>
<string name="back_to_news">Назад да навін</string>
<string name="mock_user_name">Anton Betsun</string>
<string name="mock_user_email">messbees@gmail.com</string>
<string name="mock_device_name_42">AirMQ #42</string>
<string name="mock_device_name_17">AirMQ #17</string>
</resources>

View File

@@ -0,0 +1,277 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="title_map">Карта</string>
<string name="title_dashboard">Дашборд</string>
<string name="title_manage">Управление</string>
<string name="title_settings">Настройки</string>
<string name="title_device">Устройство</string>
<string name="title_location">Местоположение</string>
<string name="dialog_internet">Подключитесть к Интернету</string>
<string name="dialog_are_you_sure">Вы уверены?</string>
<string name="dialog_select_device_title">Выбрать устройство</string>
<string name="dialog_anonym_title">Продолжить анонимно?</string>
<string name="text_setup_error_title">Ошибка</string>
<string name="text_setup_finish">Новое устройство успешно добавлено!</string>
<string name="text_your_devices">Ваши устройства</string>
<string name="text_anonymous_user">Анонимный пользователь</string>
<string name="err_short_password">Пароль Wifi должен содержать минимум 8 символов</string>
<string name="err_no_name">Вы не указали имя</string>
<string name="err_no_model">Вы не выбрали модель</string>
<string name="button_ok">ОК</string>
<string name="button_continue">Продолжить</string>
<string name="button_select">Выбрать</string>
<string name="button_cancel">Отменить</string>
<string name="text_privacy_policy"><b><u>Политикой конфиденциальности</u></b></string>
<string name="button_sign_in_google">Войти с помощью Google</string>
<string name="button_sign_in_facebook">Войти с помощью Facebook</string>
<string name="button_look_for_device">Поиск устройства</string>
<string name="button_finish">Завершить</string>
<string name="button_continue_anonym">Продолжить анонимно</string>
<string name="button_exit_setup">Выйти из установки</string>
<string name="button_abort">Прервать</string>
<string name="button_wait">Ожидание…</string>
<string name="button_setup">Добавить устройство</string>
<string name="button_connecting">Подключение…</string>
<string name="hint_password">Пароль</string>
<string name="hint_device_name">Имя устройства</string>
<string name="hint_setup_name">Имя</string>
<string name="hint_setup_model">Модель</string>
<string name="content_settings">Настройки</string>
<string name="sensor_temperature">Температура</string>
<string name="sensor_pressure">Давление</string>
<string name="sensor_dust">Твердые частицы</string>
<string name="sensor_radioactivity">Радиоактивность</string>
<string name="pref_account_header">Аккаунт</string>
<string name="pref_device_header">Устройство</string>
<string name="toast_copied">Скопировано</string>
<string name="dialog_enable_wifi_title">Включите Wi-Fi</string>
<string name="dialog_select_wifi_title">Выбрать сеть Wi-Fi</string>
<string name="dialog_exit_setup_text">Вы уверены, что хотите прервать установку? Вероятно, в следующий раз перед установкой придется сбросить устройство AirMQ</string>
<string name="dialog_exit_setup_title">Прервать установку</string>
<string name="title_device_config">Управление</string>
<string name="dialog_about_title">О приложении</string>
<string name="dialog_anonym_mesage">Вы не сможете сохранять настройки и добавлять новые устройства AirMQ</string>
<string name="text_sign_in">Войти в AirMQ</string>
<string name="text_setup_error">Ошибка во время установки:</string>
<string name="text_whats_new">Что нового</string>
<string name="text_fixes">Исправления</string>
<string name="text_setup_1">Включите или перезагрузите устройство AirMQ, после чего оно станет обнаруживаемым в течение 90 секунд. Затем нажмите кнопку \"Выбрать устройство\". На некоторых устройствах для корректного соединения с устройством необходим включенный GPS.</string>
<string name="text_setup_2">Введите имя устройства и выберите его модель</string>
<string name="text_setup_3">Выберите сеть Wi-Fi, к которой хотите подключить ваше устройство</string>
<string name="text_setup_steps">Шаг %d из 3</string>
<string name="text_setup_label">Установка нового устройства</string>
<string name="text_terms_conditions"><b><u>Условиями и положениями</u></b></string>
<string name="text_please_sign_in">Настройки не синхронизируются, пожалуйста, войдите в систему</string>
<string name="text_sign_in_small">Войдите в систему для добавления устройств</string>
<string name="err_no_device_ap">Вы не выбрали сеть Wi-Fi</string>
<string name="button_sign_in">Войти</string>
<string name="button_register">Зарегистрировать</string>
<string name="button_copy_log">Скопировать лог</string>
<string name="hint_setup_wifi">Сеть Wi-Fi</string>
<string name="content_desc_user_pic">Картинка пользователя</string>
<string name="content_device_icon">Иконка устройства</string>
<string name="content_network_icon">Иконка сети</string>
<string name="content_airmq_logo">Логотип AirMQ</string>
<string name="sensor_humidity">Влажность</string>
<string name="pref_logout_title">Выйти</string>
<string name="pref_prefix_title">Префикс точки доступа AirMQ</string>
<string name="pref_wpakey_title">Пароль по умолчанию</string>
<string name="pref_versions">Версии файлов конфигурации</string>
<string name="pref_about">О приложении</string>
<string name="pref_notifications_title">Уведомлять, когда устройство становится неактивно</string>
<string name="notification_device_status_title">Ваше устройство отключилось от сети!</string>
<string name="notification_device_status_text">%s теперь неактивен. Нажмите на это уведомление, чтобы открыть конфигурацию устройства</string>
<string name="toast_oauth_failed">Ошибка авторизации Google</string>
<string name="snackbar_not_registered">Требуется регистрация</string>
<string name="text_policy_label">Входя в систему, вы соглашаетесь с нашими %1$s и %2$s</string>
<string name="text_what_does_it_mean"><u>Что это значит?</u></string>
<string name="text_air_quality">Качество воздуха</string>
<string name="filter_hour">Час</string>
<string name="filter_day">День</string>
<string name="filter_week">Неделя</string>
<string name="filter_month">Месяц</string>
<string name="pref_fullscreen">Безрамочный интерфейс</string>
<string name="text_error">Ошибка</string>
<string name="text_error_connecting">Устройство не отвечает. Попробуйте выключить мобильный интернет и повторить.</string>
<string name="button_setup_in_progress">Установка…</string>
<string name="button_start_setup">Начать установку</string>
<string name="text_device_name">Имя</string>
<string name="text_device_id">ID устройства</string>
<string name="text_device_ip">IP-Адрес</string>
<string name="text_device_firmware">Версия прошивки</string>
<string name="text_device_location">Местоположение</string>
<string name="text_device_location_unset">Устройство не зарегистрировано</string>
<string name="text_device_visibility">Видимость</string>
<string name="text_device_visibility_visible">Опубликовано</string>
<string name="text_device_visibility_private">Скрыто</string>
<string name="text_device_visibility_not_registered">Зарегистрируйте устройство, чтобы менять видимость</string>
<string name="button_rename">Переименовать</string>
<string name="button_update">Обновить</string>
<string name="button_unregister">Сбросить</string>
<string name="button_hide">Скрыть</string>
<string name="button_publish">Опубликовать</string>
<string name="button_reboot">Перезагрузить</string>
<string name="button_reset">Сбросить</string>
<string name="button_view_on_map">Открыть на карте</string>
<string name="hint_new_name">Новое имя</string>
<string name="dialog_rename_title">Переименовать</string>
<string name="err_short_name">Имя слишком короткое!</string>
<string name="toast_error">Ошибка</string>
<string name="toast_rebooting">Перезагрузка…</string>
<string name="toast_resetting">Сброс…</string>
<string name="pref_offline_devices_title">Показывать недоступные устройства</string>
<string name="button_open">Открыть</string>
<string name="pref_advanced">Включить продвинутые настройки</string>
<string name="pref_advanced_header">Продвинутые настройки</string>
<string name="pref_application_header">Приложение</string>
<string name="pref_advanced_config">Включить расширенную конфигурацию устройства</string>
<string name="text_device_config_version">Версия конфигурации</string>
<string name="text_device_uptime">Аптайм</string>
<string name="content_sensor_icon">Иконка датчика</string>
<string name="text_no_data">Нет данных</string>
<string name="dialog_widget_delete_title">Удалить виджет</string>
<string name="dialog_widget_delete_text">Вы уверены, что хотите удалить этот виджет?</string>
<string name="button_add_widget">Добавить виджет</string>
<string name="city_minsk">Минск</string>
<string name="city_barauliany">Боровляны</string>
<string name="city_navapolack">Новополоцк</string>
<string name="city_mahiliou">Могилев</string>
<string name="city_hrodna">Гродно</string>
<string name="city_homiel">Гомель</string>
<string name="city_polack">Полоцк</string>
<string name="city_barysau">Борисов</string>
<string name="city_narac">Нарочь</string>
<string name="city_salihorsk">Солигорск</string>
<string name="city_brest">Брест</string>
<string name="city_babrujsk">Бобруйск</string>
<string name="pref_city_title">Город в дашборде</string>
<string name="dialog_select_city_title">Выберите город</string>
<string name="toast_widget_login">Войдите в систему, чтобы добавлять виджеты</string>
<string name="text_yesterday">Вчера</string>
<string name="text_now">Сейчас</string>
<string name="text_no_device">Это устройство было удалено</string>
<string name="text_hour_ago">Час назад</string>
<string name="text_week_ago">Неделю назад</string>
<string name="text_month_ago">Месяц назад</string>
<string name="dialog_widget_add_title">Добавить виджет</string>
<string name="text_device_wifi">Сеть WiFi</string>
<string name="text_device_wifi_secondary">Запасная сеть WiFi</string>
<string name="text_days">д</string>
<string name="text_hours">ч</string>
<string name="text_minutes">м</string>
<string name="text_move_up">Переместить вверх</string>
<string name="teext_move_down">Переместить вниз</string>
<string name="text_configure">Настроить</string>
<string name="text_add_to_home_screen">Добавить на рабочий стол</string>
<string name="text_remove">Убрать</string>
<string name="snackbar_widget_removed">Виджет удален</string>
<string name="button_undo">Отменить</string>
<string name="text_loading">Загрузка…</string>
<string name="content_back">Назад</string>
<string name="title_widget_constructor">Добавление виджета</string>
<string name="text_choose_widget_layout">Выберите вид виджета</string>
<string name="text_no_location">Местоположение не выбрано</string>
<string name="text_display_heatmap">Показывать хитмэп</string>
<string name="text_display_sensors">Показывать устройства</string>
<string name="text_display_both">Показывать все</string>
<string name="text_widget_map">Карта</string>
<string name="text_device">Устройство</string>
<string name="text_widget_chart">График</string>
<string name="text_choose_sensor">Выберите датчик</string>
<string name="text_choose_timeframe">Выберите временной промежуток</string>
<string name="text_no_devices">У вас нет добавленных устройств</string>
<string name="text_latest_news">Последние новости</string>
<string name="text_widget_news">Новости</string>
<string name="button_change">Изменить</string>
<string name="text_nothing_to_show">Нет устройств</string>
<string name="title_city">Город</string>
<string name="text_detect_automatically">Определять автоматически</string>
<string name="text_no_city_hint"><u>Нет вашего города?</u></string>
<string name="text_wrong_city_hint"><u>Неправильный город?</u></string>
<string name="text_city_warning">Эта опция определяет, какие данные будут отображаться в дашборде. Если город не выбран, установится стандартный вариант.</string>
<string name="text_no_city">"Если вы не видете ваш город, значит в нем нет устройств "</string>
<string name="button_enter_manual">Ввести вручную</string>
<string name="text_welcome">Добро пожаловать в AirMQ</string>
<string name="text_welcome_second">Узнай чем дышит твой город</string>
<string name="text_permission">Необходимо разрешение:</string>
<string name="text_permission_second">• Местоположение</string>
<string name="text_permission_third">Местоположение необходимо для предоставления точных данных о воздухе в вашем регионе</string>
<string name="button_allow">Разрешить</string>
<string name="button_not_now">Не сейчас</string>
<string name="button_skip">Пропустить</string>
<string name="button_next">Далее</string>
<string name="text_link"><u>Ссылка</u></string>
<string name="dialog_secondary_wifi">Запасная сеть WiFi</string>
<string name="toast_done">Готово</string>
<string name="toast_disconnected">Устройство отключилось</string>
<string name="text_device_narodmon">Отправлять данные в сервис <u>narodmon.ru</u></string>
<string name="text_device_narodmon_title">Narodmon.ru</string>
<string name="text_device_luftdata">Отправлять данные в сервис <u>sensor.community</u></string>
<string name="text_device_luftdata_title">Sensor.community</string>
<string name="text_aqi_title">Качество атмосферного воздуха</string>
<string name="text_rad_title">Уровень радиоактивности</string>
<string name="text_rad">"Датчики радиоактивности сделаны на базе счетчика Гейгера-Мюллера и измеряют фоновое гамма-радиоактивное излучение в месте установки. Значения на индикаторах и графиках соответствуют мощности эквивалентной дозы радиоактивного излучения, которая характеризует степень воздействия гамма-излучения на организм. Мощность эквивалентной дозы измеряется в зивертах/час (Зв/ч), для удобства отображения принята единица миллизиверт/час (мЗв/ч) "</string>
<string name="text_aqi">"Датчики, применяемые в нашем проекте, собирают информацию о состоянии наружного окружающего воздуха, погоды, а также фонового радиоактивного излучения. Одним из важных показателей качества воздуха, непосредственно влияющих на здоровье человека, является содержание твердых взвешенных частиц и аэрозолей (Particulate Matter, PM), которые мы привыкли называть пылью. Частицы могут появляться в воздухе как в результате природных и стихийных явлений (пылевые бури, пожары, морская соляная пыль), так и в результате деятельности человека - промышленности, транспорта, домашнего отопления, сжигания мусора. Измерение количества твердых частиц производится по трем категориям: размером до 1, 2.5 и 10 мкм. Наиболее часто используемым показателем является массовая концентрация твердых частиц размером до 2.5 мкм, PM2.5, которая указывает на массу пылевых частиц в единице объема воздуха и измеряется в мкГ/м3. Для удобства индикации степени воздействия твердых частиц в атмосфере на организм человека применяется следующая цветовая шкала. Для оценки взяты средние значения концентрации частиц PM2.5 за последние 24 часа. "</string>
<string name="text_what_does_it_mean_title">Что измеряют датчики AirMQ?</string>
<string name="notification_device_config_title">Доступно обновление</string>
<string name="notification_device_config_text">Ваше устройство \"%s\" готово к обновлению</string>
<string name="dialog_upload_title">Загрузка…</string>
<string name="toast_not_on_network">Вы должны быть в одной сети WiFi с вашим устройством.</string>
<string name="button_select_device">Выбрать устройство</string>
<string name="content_search">Поиск</string>
<string name="content_my_location">Мое местоположение</string>
<string name="button_close">Закрыть</string>
<string name="map_search_hint">Имя устройства или город</string>
<string name="map_search_empty">Результатов пока нет</string>
<string name="map_arrow_left">&lt;</string>
<string name="map_arrow_right">&gt;</string>
<string name="map_chart_placeholder">Заглушка графика</string>
<string name="map_open_device_not_wired">Открытие устройства %1$s пока не подключено</string>
<string name="map_status_online">Онлайн</string>
<string name="map_status_offline">Офлайн</string>
<string name="map_my_location_coming_soon">Логика моего местоположения будет добавлена позже</string>
<string name="map_previous_period">Предыдущий %1$s</string>
<string name="map_next_period">Следующий %1$s</string>
<string name="map_failed_to_load_items">Не удалось загрузить элементы карты</string>
<string name="map_no_city">Нет города</string>
<string name="map_time_last_hour">Последний час</string>
<string name="map_time_today">Сегодня</string>
<string name="map_time_this_week">Эта неделя</string>
<string name="map_time_this_month">Этот месяц</string>
<string name="settings_save_failed">Не удалось сохранить настройки</string>
<string name="title_debug">Отладка</string>
<string name="manage_open_widget_constructor">Открыть конструктор виджетов</string>
<string name="back_to_dashboard">Назад к дашборду</string>
<string name="manage_set_location">Задать местоположение</string>
<string name="dashboard_subtitle">Эквивалент нижней вкладки: дашборд</string>
<string name="dashboard_open_map">Открыть карту</string>
<string name="dashboard_open_manage">Открыть управление</string>
<string name="dashboard_open_city">Открыть город</string>
<string name="dashboard_open_device">Открыть устройство</string>
<string name="dashboard_open_news">Открыть новости</string>
<string name="screen_splash_title">Заставка</string>
<string name="screen_continue_to_wizard">Продолжить в мастер</string>
<string name="screen_wizard_title">Мастер</string>
<string name="screen_finish_wizard">Завершить мастер</string>
<string name="screen_mock_device_id">Тестовый deviceId: %1$s</string>
<string name="back_to_settings">Назад к настройкам</string>
<string name="back_to_manage">Назад к управлению</string>
<string name="screen_log_in_to_manage">Войти в управление</string>
<string name="news_open_detail">Открыть детали новости</string>
<string name="news_detail_title">Детали новости</string>
<string name="screen_mock_news_id">Тестовый newsId: %1$s</string>
<string name="widget_select_map_location">Выбрать локацию виджета карты</string>
<string name="widget_open_map_constructor">Открыть конструктор карты</string>
<string name="widget_open_chart_constructor">Открыть конструктор графика</string>
<string name="widget_open_news_constructor">Открыть конструктор новостей</string>
<string name="back_to_widget_constructor">Назад к конструктору виджетов</string>
<string name="widget_map_constructor_title">Конструктор карты</string>
<string name="widget_chart_constructor_title">Конструктор графика</string>
<string name="widget_news_constructor_title">Конструктор новостей</string>
<string name="back_to_news">Назад к новостям</string>
<string name="mock_user_name">Anton Betsun</string>
<string name="mock_user_email">messbees@gmail.com</string>
<string name="mock_device_name_42">AirMQ #42</string>
<string name="mock_device_name_17">AirMQ #17</string>
</resources>

View File

@@ -1,25 +1,333 @@
<resources>
<string name="app_name">AirMQ</string>
<string name="map_sensor_dust">Dust</string>
<string name="map_sensor_air_quality">Air quality</string>
<string name="map_sensor_radioactivity">Radioactivity</string>
<string name="map_sensor_help_link">What does this mean?</string>
<string name="map_sensor_help_title">What do AirMQ sensors measure?</string>
<string name="map_search_action_content_desc">Search</string>
<string name="map_my_location_content_desc">My location</string>
<string name="map_back">Back</string>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name" translatable="false">AirMQ</string>
<string name="title_map">Map</string>
<string name="title_dashboard">Dashboard</string>
<string name="title_manage">Manage</string>
<string name="title_settings">Settings</string>
<string name="title_device_config">Config</string>
<string name="title_device">Device</string>
<string name="title_location">Select location</string>
<!-- Actions -->
<!-- Dialog -->
<string name="dialog_internet">Connect to Internet</string>
<string name="dialog_exit_setup_title">Exit config</string>
<string name="dialog_exit_setup_text">Are you sure you want to exit setup? You may have to reset your AirMQ device after that.</string>
<string name="dialog_select_wifi_title">Choose Wi-Fi network</string>
<string name="dialog_enable_wifi_title">Enable WiFi</string>
<string name="dialog_are_you_sure">Are you sure?</string>
<string name="dialog_about_title">About</string>
<string name="dialog_about_text" translatable="false">App by Anton Betsun \nDesign by Alexander Prokhorov</string>
<string name="dialog_anonym_title">Continue anonymously?</string>
<string name="dialog_anonym_mesage">You will not be able to back up your preferences and add new AirMQ devices</string>
<string name="dialog_select_device_title">Select device</string>
<!-- Text -->
<string name="coming_soon" translatable="false">Coming soon</string>
<string name="text_sign_in">Sign in to AirMQ</string>
<string name="text_air_mq" translatable="false">AirMQ</string>
<string name="text_model_basic" translatable="false">Basic</string>
<string name="text_setup_error">"Error during setup: "</string>
<string name="text_setup_error_title">Error</string>
<string name="text_whats_new">What\'s new</string>
<string name="text_nothing_to_show">Nothing to show</string>
<string name="text_fixes">Fixes</string>
<string name="text_setup_uploading_config" translatable="false">Uploading config…</string>
<string name="text_setup_config_uploaded" translatable="false">Config uploaded.</string>
<string name="text_setup_uploading_rules" translatable="false">Uploading rules…</string>
<string name="text_setup_rules_uploaded" translatable="false">Rules uploaded.</string>
<string name="text_setup_setting_name" translatable="false">Setting name…</string>
<string name="text_setup_name_set" translatable="false">Name set.</string>
<string name="text_setup_setting_password" translatable="false">Setting password…</string>
<string name="text_setup_password_set" translatable="false">Password set.</string>
<string name="text_setup_setting_ssid" translatable="false">Setting SSID…</string>
<string name="text_setup_ssid_set" translatable="false">SSID set.</string>
<string name="text_setup_saving_wifi" translatable="false">Saving WiFi configuration…</string>
<string name="text_setup_wifi_saved" translatable="false">Saved.</string>
<string name="text_setup_checking_connection" translatable="false">Checking connection… </string>
<string name="text_setup_device_connected" translatable="false">Device connected to %1$s at %2$s.</string>
<string name="text_setup_waiting_internet" translatable="false">Waiting for Internet…</string>
<string name="text_setup_connected_internet" translatable="false">Connected to Internet, finishing…</string>
<string name="text_setup_disconnected" translatable="false">Disconnected!</string>
<string name="text_setup_1">Turn on or reboot your device, after that it will be discoverable for 90 seconds. When you are ready, press \'LOOK FOR A DEVICE\' button. On some Android devices enabled GPS service may be requied to continue.</string>
<string name="text_setup_2">Choose a name for your device and specify its model before connecting it to WiFi</string>
<string name="text_setup_3">Select the WiFi network to which you want to connect your device</string>
<string name="text_setup_steps">Step %d of 3</string>
<string name="text_setup_finish">Successfully added a new device!</string>
<string name="text_setup_label">Setting up a new device</string>
<string name="text_model_mobile" translatable="false">Mobile</string>
<string name="text_model_solar" translatable="false">Solar</string>
<string name="text_model_geiger" translatable="false">Geiger</string>
<string name="text_policy_label">By signing in you confirm that you agree with our %1$s and %2$s</string>
<string name="text_privacy_policy"><b><u>Privacy Policy</u></b></string>
<string name="text_terms_conditions"><b><u>Terms &amp; conditions</u></b></string>
<string name="text_your_devices">Your devices</string>
<string name="text_anonymous_user">Anonymous user</string>
<string name="text_please_sign_in">Your preferences are not being synced, please sign in</string>
<string name="text_sign_in_small">Sign in to add devices</string>
<string name="text_what_does_it_mean"><u>What does this mean?</u></string>
<!-- Errors -->
<string name="err_short_password">Wifi password must be at least 8 characters long</string>
<string name="err_no_name">You didn\'t select name</string>
<string name="err_no_model">You didn\'t select model</string>
<string name="err_no_device_ap">You didn\'t select wifi network</string>
<!-- Buttons -->
<string name="button_sign_in">Sign in</string>
<string name="button_ok">OK</string>
<string name="button_continue">Continue</string>
<string name="button_select">Select</string>
<string name="button_cancel">Cancel</string>
<string name="button_register">Register</string>
<string name="button_sign_in_google">Sign in with Google</string>
<string name="button_sign_in_facebook">Sign in with Facebook</string>
<string name="button_copy_log">Copy log</string>
<string name="button_look_for_device">Look for a device</string>
<string name="button_finish">Finish</string>
<string name="button_continue_anonym">Continue anonymously</string>
<string name="button_exit_setup">Exit setup</string>
<string name="button_abort">Abort</string>
<string name="button_wait">Wait</string>
<string name="button_setup">Add new device</string>
<string name="button_connecting">Connecting…</string>
<!-- Hints -->
<string name="hint_password">Password</string>
<string name="hint_device_name">Device name</string>
<string name="hint_setup_name">Name</string>
<string name="hint_setup_model">Model</string>
<string name="hint_setup_wifi">WiFi network</string>
<!-- Content descriptors -->
<string name="content_desc_user_pic">User Picture</string>
<string name="content_device_icon">Device icon</string>
<string name="content_network_icon">Network icon</string>
<string name="content_airmq_logo">AirMQ logo</string>
<string name="content_settings">Settings</string>
<!-- Sensor types -->
<string name="sensor_temperature">Temperature</string>
<string name="sensor_humidity">Humidity</string>
<string name="sensor_pressure">Pressure</string>
<string name="sensor_dust">Particulate matter</string>
<string name="sensor_co2" translatable="false" tools:ignore="UnusedResources">CO2</string>
<string name="sensor_voc" translatable="false" tools:ignore="UnusedResources">VOC</string>
<string name="sensor_radioactivity">Radioactivity</string>
<!-- Time filters -->
<string name="filter_hour">Hour</string>
<string name="filter_day">Day</string>
<string name="filter_week">Week</string>
<string name="filter_month">Month</string>
<!-- Preferences -->
<string name="pref_account_header">Account</string>
<string name="pref_logout_title">Log out</string>
<string name="pref_device_header">Device</string>
<string name="pref_prefix_title">AirMQ Hotspot Prefix</string>
<string name="pref_wpakey_title">Default WPA key</string>
<string name="pref_versions">Config versions</string>
<string name="pref_about">About</string>
<string name="pref_notifications_title">Notify when device becomes offline</string>
<!-- Notifications -->
<string name="notification_device_status_title">Your device became offline!</string>
<string name="notification_device_status_text">%s is now offline. Click this to open device config page</string>
<!-- Privacy Policy -->
<!-- Snackbars and toasts -->
<string name="toast_oauth_failed" tools:ignore="UnusedResources">Google authorisation failed</string>
<string name="toast_copied">Copied</string>
<string name="snackbar_not_registered">Device requires registration</string>
<string name="oauth_token" translatable="false" tools:ignore="Typos">21688843933-n04t4s1h7rjad12tdj1pc9j6kajgh2ka.apps.googleusercontent.com</string>
<string name="facebook_app_id" translatable="false">356744979027664</string>
<string name="fb_login_protocol_scheme" translatable="false">fb356744979027664</string>
<string name="text_air_quality">Air quality</string>
<string name="pref_fullscreen">Borderless layout</string>
<string name="text_error">Error</string>
<string name="text_error_connecting">Can\'t get response from device. Try to disable mobile data.</string>
<string name="button_setup_in_progress">Setup…</string>
<string name="button_start_setup">Start setup</string>
<string name="text_device_name">Name</string>
<string name="text_device_id">Device ID</string>
<string name="text_device_ip">IP Address</string>
<string name="text_device_firmware">Firmware version</string>
<string name="text_device_location">Location</string>
<string name="text_device_location_unset">Device is not registered</string>
<string name="text_device_location_set" translatable="false">%s, %s</string>
<string name="text_device_visibility">Visibility</string>
<string name="text_device_visibility_visible">Public</string>
<string name="text_device_visibility_private">Private</string>
<string name="text_device_visibility_not_registered">Register device to change visibility</string>
<string name="button_rename">Rename</string>
<string name="button_update">Update</string>
<string name="button_unregister">Unregister</string>
<string name="button_hide">Hide</string>
<string name="button_publish">Publish</string>
<string name="button_reboot">Reboot</string>
<string name="button_reset">Reset</string>
<string name="button_view_on_map">View on map</string>
<string name="hint_new_name">New name</string>
<string name="dialog_rename_title">Rename</string>
<string name="err_short_name">Name is too short!</string>
<string name="toast_error">Error</string>
<string name="toast_rebooting">Rebooting…</string>
<string name="toast_resetting">Resetting…</string>
<string name="pref_offline_devices_title">Show offline devices</string>
<string name="button_open">Open</string>
<string name="pref_advanced">Enable advanced options</string>
<string name="pref_advanced_header">Advanced</string>
<string name="pref_application_header">Application</string>
<string name="pref_advanced_config">Enable extended device config</string>
<string name="text_device_config_version">Config version </string>
<string name="text_device_uptime">Uptime</string>
<string name="content_sensor_icon">Sensor icon</string>
<string name="text_no_data">No data</string>
<string name="dialog_widget_delete_title">Delete widget</string>
<string name="dialog_widget_delete_text">Are you sure you want to delete this widget?</string>
<string name="button_add_widget">Add widget</string>
<string name="city_minsk">Minsk</string>
<string name="city_barauliany">Barauliany</string>
<string name="city_navapolack">Navapolack</string>
<string name="city_mahiliou">Mahilioŭ</string>
<string name="city_hrodna">Hrodna</string>
<string name="city_homiel">Homieĺ</string>
<string name="city_polack">Polack</string>
<string name="city_barysau">Barysaŭ</string>
<string name="city_narac">Narač</string>
<string name="city_salihorsk">Salihorsk</string>
<string name="city_brest">Brest</string>
<string name="city_babrujsk">Babrujsk</string>
<string name="pref_city_title">City in dashboard</string>
<string name="dialog_select_city_title">Select city</string>
<string name="toast_widget_login">Log in to add widgets</string>
<string name="text_yesterday">Yesterday</string>
<string name="text_now">Now</string>
<string name="text_no_device">This device was deleted</string>
<string name="text_hour_ago">Hour ago</string>
<string name="text_week_ago">Week ago</string>
<string name="text_month_ago">Month ago</string>
<string name="dialog_widget_add_title">Add widget</string>
<string name="text_device_wifi">WiFi network</string>
<string name="text_device_wifi_secondary">Secondary WiFi network</string>
<string name="text_days">d</string>
<string name="text_hours">h</string>
<string name="text_minutes">m</string>
<string name="text_move_up">Move up</string>
<string name="teext_move_down">Move down</string>
<string name="text_configure">Configure</string>
<string name="text_add_to_home_screen">Add to Home screen</string>
<string name="text_remove">Remove</string>
<string name="snackbar_widget_removed">Widget removed</string>
<string name="button_undo">Undo</string>
<string name="text_loading">Loading…</string>
<string name="content_back">Back</string>
<string name="title_widget_constructor">New widget</string>
<string name="text_choose_widget_layout">Choose widget layout</string>
<string name="text_no_location">Location is not specified</string>
<string name="text_display_heatmap">Display heatmap</string>
<string name="text_display_sensors">Display sensors</string>
<string name="text_display_both">Display both</string>
<string name="text_widget_map">Map</string>
<string name="text_device">Device</string>
<string name="text_widget_chart">Chart</string>
<string name="text_choose_sensor">Choose sensor</string>
<string name="text_choose_timeframe">Choose timeframe</string>
<string name="text_no_devices">You do not have configured devices</string>
<string name="text_latest_news">Latest news</string>
<string name="text_widget_news">News</string>
<string name="button_change">Change</string>
<string name="title_city">City</string>
<string name="text_detect_automatically">Detect automatically</string>
<string name="text_no_city_hint"><u>Don\'t see your city?</u></string>
<string name="text_wrong_city_hint"><u>Wrong city?</u></string>
<string name="text_no_city">If you dont see your city, there are not enough sensors there to provide reliable data just yet. Instead, data from the closest available city will be displayed when automatic detection is enabled</string>
<string name="text_city_warning">This setting affects what data is displayed in the dashboard. If no city is selected, default value will be set.</string>
<string name="button_enter_manual">Enter manually</string>
<string name="text_welcome">Welcome to AirMQ</string>
<string name="text_welcome_second">Learn what your city breathes</string>
<string name="text_permission">Permission requied:</string>
<string name="text_permission_second">• Location</string>
<string name="text_permission_third">Location permission is needed to provide accurate data about air quality in your area</string>
<string name="button_allow">Allow</string>
<string name="button_not_now">Not now</string>
<string name="button_skip">Skip</string>
<string name="button_next">Next</string>
<string name="text_link"><u>Link</u></string>
<string name="dialog_secondary_wifi">Secondary WiFi</string>
<string name="toast_done">Done</string>
<string name="toast_disconnected">Device disconnected</string>
<string name="toast_not_on_network">You need to be in the same WiFi network with your device.</string>
<string name="text_device_narodmon">Send data to <u>narodmon.ru</u></string>
<string name="text_device_narodmon_title">Narodmon.ru</string>
<string name="text_device_luftdata">Send data to <u>sensor.community</u></string>
<string name="text_device_luftdata_title">Sensor.community</string>
<string name="text_aqi_title">Качество атмосферного воздуха</string>
<string name="text_rad_title">Уровень радиоактивности</string>
<string name="text_rad">"Датчики радиоактивности сделаны на базе счетчика Гейгера-Мюллера и измеряют фоновое гамма-радиоактивное излучение в месте установки. Значения на индикаторах и графиках соответствуют мощности эквивалентной дозы радиоактивного излучения, которая характеризует степень воздействия гамма-излучения на организм. Мощность эквивалентной дозы измеряется в зивертах/час (Зв/ч), для удобства отображения принята единица миллизиверт/час (мЗв/ч) "</string>
<string name="text_aqi">"Датчики, применяемые в нашем проекте, собирают информацию о состоянии наружного окружающего воздуха, погоды, а также фонового радиоактивного излучения. Одним из важных показателей качества воздуха, непосредственно влияющих на здоровье человека, является содержание твердых взвешенных частиц и аэрозолей (Particulate Matter, PM), которые мы привыкли называть пылью. Частицы могут появляться в воздухе как в результате природных и стихийных явлений (пылевые бури, пожары, морская соляная пыль), так и в результате деятельности человека - промышленности, транспорта, домашнего отопления, сжигания мусора. Измерение количества твердых частиц производится по трем категориям: размером до 1, 2.5 и 10 мкм. Наиболее часто используемым показателем является массовая концентрация твердых частиц размером до 2.5 мкм, PM2.5, которая указывает на массу пылевых частиц в единице объема воздуха и измеряется в мкГ/м3. Для удобства индикации степени воздействия твердых частиц в атмосфере на организм человека применяется следующая цветовая шкала. Для оценки взяты средние значения концентрации частиц PM2.5 за последние 24 часа. "</string>
<string name="text_what_does_it_mean_title">Что измеряют датчики AirMQ?</string>
<string name="notification_device_config_title">Update is available</string>
<string name="notification_device_config_text">Your device \"%s\" is ready to update</string>
<string name="dialog_upload_title">Uploading…</string>
<string name="button_select_device">Select device</string>
<string name="content_search">Search</string>
<string name="content_my_location">My location</string>
<string name="button_close">Close</string>
<string name="map_search_hint">Device name or city</string>
<string name="map_search_empty">No results yet</string>
<string name="map_close">Close</string>
<string name="map_open_device">Open</string>
<string name="map_arrow_left">&lt;</string>
<string name="map_arrow_right">&gt;</string>
<string name="map_chart_placeholder">Chart placeholder</string>
<string name="map_filter_hour">Hour</string>
<string name="map_filter_day">Day</string>
<string name="map_filter_week">Week</string>
<string name="map_filter_month">Month</string>
<string name="map_device_sensor_temperature">Temperature</string>
<string name="map_device_sensor_dust">Dust</string>
<string name="map_device_sensor_radioactivity">Radioactivity</string>
<string name="map_open_device_not_wired">Open device %1$s is not wired yet</string>
<string name="map_status_online">Online</string>
<string name="map_status_offline">Offline</string>
<string name="map_my_location_coming_soon">My location logic will be added later</string>
<string name="map_previous_period">Previous %1$s</string>
<string name="map_next_period">Next %1$s</string>
<string name="map_failed_to_load_items">Failed to load map items</string>
<string name="map_no_city">No city</string>
<string name="map_time_last_hour">Last hour</string>
<string name="map_time_today">Today</string>
<string name="map_time_this_week">This week</string>
<string name="map_time_this_month">This month</string>
<string name="settings_save_failed">Failed to save settings</string>
<string name="title_debug">Debug</string>
<string name="manage_open_widget_constructor">Open Widget Constructor</string>
<string name="back_to_dashboard">Back to Dashboard</string>
<string name="manage_set_location">Set location</string>
<string name="dashboard_subtitle">Bottom-tab equivalent: dashboard</string>
<string name="dashboard_open_map">Open Map</string>
<string name="dashboard_open_manage">Open Manage</string>
<string name="dashboard_open_city">Open City</string>
<string name="dashboard_open_device">Open Device</string>
<string name="dashboard_open_news">Open News</string>
<string name="screen_splash_title">Splash</string>
<string name="screen_continue_to_wizard">Continue to Wizard</string>
<string name="screen_wizard_title">Wizard</string>
<string name="screen_finish_wizard">Finish Wizard</string>
<string name="screen_mock_device_id">Mock deviceId: %1$s</string>
<string name="back_to_settings">Back to Settings</string>
<string name="back_to_manage">Back to Manage</string>
<string name="screen_log_in_to_manage">Log In to Manage</string>
<string name="news_open_detail">Open News Detail</string>
<string name="news_detail_title">News Detail</string>
<string name="screen_mock_news_id">Mock newsId: %1$s</string>
<string name="widget_select_map_location">Select Map Widget Location</string>
<string name="widget_open_map_constructor">Open Map Constructor</string>
<string name="widget_open_chart_constructor">Open Chart Constructor</string>
<string name="widget_open_news_constructor">Open News Constructor</string>
<string name="back_to_widget_constructor">Back to Widget Constructor</string>
<string name="widget_map_constructor_title">Map Constructor</string>
<string name="widget_chart_constructor_title">Chart Constructor</string>
<string name="widget_news_constructor_title">News Constructor</string>
<string name="back_to_news">Back to News</string>
<string name="mock_user_name">Anton Betsun</string>
<string name="mock_user_email">messbees@gmail.com</string>
<string name="mock_device_name_42">AirMQ #42</string>
<string name="mock_device_name_17">AirMQ #17</string>
</resources>