mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 23:05:26 +02:00
Merge branch 'master' into l10n_weblate
This commit is contained in:
commit
daa5e6d1f0
@ -5,8 +5,8 @@ import android.os.Build
|
||||
import android.util.Log
|
||||
import com.arthenica.ffmpegkit.FFmpegKit
|
||||
import com.arthenica.ffmpegkit.ReturnCode
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter.ISO_DATE_TIME
|
||||
@ -40,8 +40,46 @@ data class AppSettings(
|
||||
DARK,
|
||||
}
|
||||
|
||||
fun toJSONObject(): JSONObject {
|
||||
return JSONObject(
|
||||
mapOf(
|
||||
"audioRecorderSettings" to audioRecorderSettings.toJSONObject(),
|
||||
"hasSeenOnboarding" to hasSeenOnboarding,
|
||||
"showAdvancedSettings" to showAdvancedSettings,
|
||||
"theme" to theme.name,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun exportToString(): String {
|
||||
return JSONObject(
|
||||
mapOf(
|
||||
"_meta" to mapOf(
|
||||
"version" to 1,
|
||||
"date" to LocalDateTime.now().format(ISO_DATE_TIME),
|
||||
"app" to "app.myzel394.alibi",
|
||||
),
|
||||
"data" to toJSONObject(),
|
||||
)
|
||||
).toString(0)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getDefaultInstance(): AppSettings = AppSettings()
|
||||
|
||||
fun fromJSONObject(data: JSONObject): AppSettings {
|
||||
return AppSettings(
|
||||
audioRecorderSettings = AudioRecorderSettings.fromJSONObject(data.getJSONObject("audioRecorderSettings")),
|
||||
hasSeenOnboarding = data.getBoolean("hasSeenOnboarding"),
|
||||
showAdvancedSettings = data.getBoolean("showAdvancedSettings"),
|
||||
theme = Theme.valueOf(data.getString("theme")),
|
||||
)
|
||||
}
|
||||
|
||||
fun fromExportedString(data: String): AppSettings {
|
||||
val json = JSONObject(data)
|
||||
return fromJSONObject(json.getJSONObject("data"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,6 +330,20 @@ data class AudioRecorderSettings(
|
||||
return supportedFormats.contains(outputFormat)
|
||||
}
|
||||
|
||||
fun toJSONObject(): JSONObject {
|
||||
return JSONObject(
|
||||
mapOf(
|
||||
"maxDuration" to maxDuration,
|
||||
"intervalDuration" to intervalDuration,
|
||||
"forceExactMaxDuration" to forceExactMaxDuration,
|
||||
"bitRate" to bitRate,
|
||||
"samplingRate" to samplingRate,
|
||||
"outputFormat" to outputFormat,
|
||||
"encoder" to encoder,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getDefaultInstance(): AudioRecorderSettings = AudioRecorderSettings()
|
||||
val EXAMPLE_MAX_DURATIONS = listOf(
|
||||
@ -398,5 +450,23 @@ data class AudioRecorderSettings(
|
||||
}
|
||||
}
|
||||
}).toMap()
|
||||
|
||||
fun fromJSONObject(data: JSONObject): AudioRecorderSettings {
|
||||
return AudioRecorderSettings(
|
||||
maxDuration = data.getLong("maxDuration"),
|
||||
intervalDuration = data.getLong("intervalDuration"),
|
||||
forceExactMaxDuration = data.getBoolean("forceExactMaxDuration"),
|
||||
bitRate = data.getInt("bitRate"),
|
||||
samplingRate = data.optInt("samplingRate", -1).let {
|
||||
if (it == -1) null else it
|
||||
},
|
||||
outputFormat = data.optInt("outputFormat", -1).let {
|
||||
if (it == -1) null else it
|
||||
},
|
||||
encoder = data.optInt("encoder", -1).let {
|
||||
if (it == -1) null else it
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,165 @@
|
||||
package app.myzel394.alibi.ui.components.SettingsScreen.atoms
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.material.icons.filled.Upload
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.SnackbarDuration
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.SnackbarVisuals
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.myzel394.alibi.R
|
||||
import app.myzel394.alibi.dataStore
|
||||
import app.myzel394.alibi.db.AppSettings
|
||||
import app.myzel394.alibi.ui.utils.rememberFileSaverDialog
|
||||
import app.myzel394.alibi.ui.utils.rememberFileSelectorDialog
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
|
||||
@Composable
|
||||
fun ImportExport(
|
||||
snackbarHostState: SnackbarHostState,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
val dataStore = LocalContext.current.dataStore
|
||||
val settings = dataStore
|
||||
.data
|
||||
.collectAsState(initial = AppSettings.getDefaultInstance())
|
||||
.value
|
||||
|
||||
var settingsToBeImported by remember { mutableStateOf<AppSettings?>(null) }
|
||||
|
||||
val saveFile = rememberFileSaverDialog("application/json")
|
||||
val openFile = rememberFileSelectorDialog { uri ->
|
||||
val file = File.createTempFile("alibi_settings", ".json")
|
||||
|
||||
context.contentResolver.openInputStream(uri)!!.use {
|
||||
it.copyTo(file.outputStream())
|
||||
}
|
||||
val rawContent = file.readText()
|
||||
|
||||
settingsToBeImported = AppSettings.fromExportedString(rawContent)
|
||||
}
|
||||
|
||||
if (settingsToBeImported != null) {
|
||||
val successMessage = stringResource(R.string.ui_settings_option_import_success)
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = {
|
||||
settingsToBeImported = null
|
||||
},
|
||||
title = {
|
||||
Text(stringResource(R.string.ui_settings_option_import_label))
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.ui_settings_option_import_dialog_text))
|
||||
},
|
||||
icon = {
|
||||
Icon(
|
||||
Icons.Default.Download,
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
confirmButton = {
|
||||
Button(
|
||||
onClick = {
|
||||
scope.launch {
|
||||
dataStore.updateData {
|
||||
settingsToBeImported!!
|
||||
}
|
||||
settingsToBeImported = null
|
||||
|
||||
snackbarHostState.showSnackbar(
|
||||
message = successMessage,
|
||||
withDismissAction = true,
|
||||
duration = SnackbarDuration.Short,
|
||||
)
|
||||
}
|
||||
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.CheckCircle,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(ButtonDefaults.IconSize),
|
||||
)
|
||||
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
|
||||
Text(stringResource(R.string.ui_settings_option_import_dialog_confirm))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
Button(
|
||||
onClick = {
|
||||
settingsToBeImported = null
|
||||
},
|
||||
colors = ButtonDefaults.textButtonColors(),
|
||||
) {
|
||||
Text(stringResource(R.string.dialog_close_cancel_label))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
Button(
|
||||
onClick = {
|
||||
openFile("application/json")
|
||||
},
|
||||
colors = ButtonDefaults.filledTonalButtonColors(),
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Download,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(ButtonDefaults.IconSize),
|
||||
)
|
||||
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
|
||||
Text(stringResource(R.string.ui_settings_option_import_label))
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
val rawContent = settings.exportToString()
|
||||
|
||||
val tempFile = File.createTempFile("alibi_settings", ".json")
|
||||
tempFile.writeText(rawContent)
|
||||
|
||||
saveFile(tempFile, "alibi_settings.json")
|
||||
},
|
||||
colors = ButtonDefaults.filledTonalButtonColors(),
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Upload,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(ButtonDefaults.IconSize),
|
||||
)
|
||||
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
|
||||
Text(stringResource(R.string.ui_settings_option_export_label))
|
||||
}
|
||||
}
|
||||
}
|
@ -64,7 +64,7 @@ fun AudioRecorder(
|
||||
try {
|
||||
val file = audioRecorder.lastRecording!!.concatenateFiles()
|
||||
|
||||
saveFile(file)
|
||||
saveFile(file, file.name)
|
||||
} catch (error: Exception) {
|
||||
Log.getStackTraceString(error)
|
||||
} finally {
|
||||
@ -165,7 +165,7 @@ fun AudioRecorder(
|
||||
}
|
||||
)
|
||||
},
|
||||
) {padding ->
|
||||
) { padding ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
|
@ -1,6 +1,7 @@
|
||||
package app.myzel394.alibi.ui.screens
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
@ -15,7 +16,9 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LargeTopAppBar
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Snackbar
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
@ -39,6 +42,7 @@ import app.myzel394.alibi.ui.SUPPORTS_DARK_MODE_NATIVELY
|
||||
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.BitrateTile
|
||||
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.EncoderTile
|
||||
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.ForceExactMaxDurationTile
|
||||
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.ImportExport
|
||||
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.InAppLanguagePicker
|
||||
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.IntervalDurationTile
|
||||
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.MaxDurationTile
|
||||
@ -63,7 +67,21 @@ fun SettingsScreen(
|
||||
)
|
||||
|
||||
Scaffold(
|
||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
||||
snackbarHost = {
|
||||
SnackbarHost(
|
||||
hostState = snackbarHostState,
|
||||
snackbar = {
|
||||
Snackbar(
|
||||
snackbarData = it,
|
||||
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
actionColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
actionContentColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
dismissActionContentColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
topBar = {
|
||||
LargeTopAppBar(
|
||||
title = {
|
||||
@ -128,16 +146,26 @@ fun SettingsScreen(
|
||||
ForceExactMaxDurationTile()
|
||||
InAppLanguagePicker()
|
||||
AnimatedVisibility(visible = settings.showAdvancedSettings) {
|
||||
Column {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(32.dp),
|
||||
) {
|
||||
Column {
|
||||
Divider(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 32.dp)
|
||||
)
|
||||
BitrateTile()
|
||||
SamplingRateTile()
|
||||
EncoderTile(snackbarHostState = snackbarHostState)
|
||||
OutputFormatTile()
|
||||
}
|
||||
Divider(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 32.dp)
|
||||
.fillMaxWidth(0.5f)
|
||||
)
|
||||
BitrateTile()
|
||||
SamplingRateTile()
|
||||
EncoderTile(snackbarHostState = snackbarHostState)
|
||||
OutputFormatTile()
|
||||
ImportExport(snackbarHostState = snackbarHostState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +1,53 @@
|
||||
package app.myzel394.alibi.ui.utils
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import java.io.File
|
||||
|
||||
@Composable
|
||||
fun rememberFileSaverDialog(mimeType: String): ((File) -> Unit) {
|
||||
fun rememberFileSaverDialog(mimeType: String): ((File, String) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
|
||||
var file = remember { mutableStateOf<File?>(null) }
|
||||
|
||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument(mimeType)) {
|
||||
it?.let {
|
||||
context.contentResolver.openOutputStream(it)?.use { outputStream ->
|
||||
file.value!!.inputStream().use { inputStream ->
|
||||
inputStream.copyTo(outputStream)
|
||||
val launcher =
|
||||
rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument(mimeType)) {
|
||||
it?.let {
|
||||
context.contentResolver.openOutputStream(it)?.use { outputStream ->
|
||||
file.value!!.inputStream().use { inputStream ->
|
||||
inputStream.copyTo(outputStream)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.value = null
|
||||
}
|
||||
|
||||
return { it, name ->
|
||||
file.value = it
|
||||
launcher.launch(name ?: it.name)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberFileSelectorDialog(
|
||||
callback: (Uri) -> Unit
|
||||
): ((String) -> Unit) {
|
||||
val launcher =
|
||||
rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) {
|
||||
if (it != null) {
|
||||
callback(it)
|
||||
}
|
||||
}
|
||||
|
||||
file.value = null
|
||||
}
|
||||
|
||||
return {
|
||||
file.value = it
|
||||
launcher.launch(it.name)
|
||||
return { mimeType ->
|
||||
launcher.launch(arrayOf(mimeType))
|
||||
}
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="app_name">Alibi</string>
|
||||
|
||||
<string name="dialog_close_cancel_label">Abbrechen</string>
|
||||
<string name="dialog_close_neutral_label">OK</string>
|
||||
<string name="continue_label">Fortsetzten</string>
|
||||
|
||||
<string name="format_kbps"><xliff:g name="value">%s</xliff:g> KB/s</string>
|
||||
<string name="form_error_type_notNumber">Bitte eine gültige Nummer eingeben</string>
|
||||
<string name="form_error_value_notInRange">Bitte gib eine Nummer zwischen<xliff:g name="min">%s</xliff:g> und <xliff:g name="max">%s</xliff:g>ein</string>
|
||||
<string name="form_error_value_mustBeGreaterThan">Bitte gib eine größere Zahl als <xliff:g name="min">%s </xliff:g>ein</string>
|
||||
|
||||
<string name="notificationChannels_recorder_name">Recorder</string>
|
||||
<string name="notificationChannels_recorder_description">Zeigt den aktuellen Status der Aufnahme an</string>
|
||||
|
||||
<string name="ui_permissions_request_title">Berechtigung verweigert</string>
|
||||
<string name="ui_permissions_request">Bitte erteile die Berechtigung, um fortzufahren</string>
|
||||
<string name="ui_permissions_permanentlyDenied_message">Du wirst zu den Einstellungen weitergeleitet, um dort die Berechtigung zu erteilen.</string>
|
||||
|
||||
<string name="ui_audioRecorder_action_start_label">Aufnahme starten</string>
|
||||
<string name="ui_audioRecorder_action_saveOldRecording_label">Aufnahme vom <xliff:g name="date">%s</xliff:g> speichern</string>
|
||||
<string name="ui_audioRecorder_action_delete_label">Löschen</string>
|
||||
<string name="ui_audioRecorder_action_delete_confirm_title">Aufnahme Löschen?</string>
|
||||
<string name="ui_audioRecorder_action_delete_confirm_message">Bist du sicher, dass du diese Aufnahme löschen möchtest?</string>
|
||||
<string name="ui_audioRecorder_action_pause_label">Aufnahme pausieren</string>
|
||||
<string name="ui_audioRecorder_action_resume_label">Aufnahme fortsetzten</string>
|
||||
<string name="ui_audioRecorder_action_save_label">Aufnahme speichern</string>
|
||||
<string name="ui_audioRecorder_action_start_description">Alibi wird im Hintergrund weiterhin aufnehmen und die letzten <xliff:g name="durationInMinutes">%s</xliff:g> Minuten auf Wunsch speichern</string>
|
||||
<string name="ui_audioRecorder_action_save_processing_dialog_title">Bearbeiten</string>
|
||||
<string name="ui_audioRecorder_action_save_processing_dialog_description">Audio wird bearbeitet, Alibi nicht schließen! Du wirst automatisch aufgefordert, die Datei zu speichern, wenn diese fertig bearbeitet ist</string>
|
||||
<string name="ui_audioRecorder_state_recording_title">Aufnahme läuft</string>
|
||||
<string name="ui_audioRecorder_state_recording_description">Alibi nimmt im Hintergrund weiter auf</string>
|
||||
|
||||
<string name="ui_welcome_explanation_title">Wilkommen zu Alibi!</string>
|
||||
<string name="ui_welcome_explanation_message">Alibi funktioniert wird eine Dashcam für dein Handy. Es ermöglicht dir, Ton im Hintergrund kontinuierlich aufzunehmen und die letzten 30 Minuten auf Wunsch zu speichern.</string>
|
||||
<string name="ui_welcome_responsibility_title">Du bist für die Nutzung dieser App verantwortlich!</string>
|
||||
<string name="ui_welcome_responsibility_message">Alibi übernimmt keine Verantwortung für die Nutzung dieser App. Du trägst die alleinige Verantwortung. Die Nutzung erfolgt auf eigene Gefahr.</string>
|
||||
<string name="ui_welcome_start_label">Alibi Starten</string>
|
||||
|
||||
<string name="ui_settings_title">Einstellungen</string>
|
||||
<string name="ui_settings_advancedSettings_label">Erweiterte Einstellungen</string>
|
||||
<string name="ui_settings_hint_recordingActive_title">Aufnahme läuft</string>
|
||||
<string name="ui_settings_hint_recordingActive_message">Änderungen an den Einstellungen werden erst nach dem Neustart der Aufnahme wirksam</string>
|
||||
<string name="ui_settings_option_maxDuration_title">Maximale Aufnahmezeit</string>
|
||||
<string name="ui_settings_option_maxDuration_description">Setze die maximale Aufnahmezeit fest</string>
|
||||
<string name="ui_settings_option_intervalDuration_title">Intervall-Länge</string>
|
||||
<string name="ui_settings_option_intervalDuration_description">Dauer eines einzelnen Intervalls. Alibi nimmt in Intervallen auf und speichert diese einzeln ab. Die Intervalle werden automatisch zusammengefügt, wenn du eine Aufnahme speicherst. Die ältesten Intervalle werden automatisch gelöscht, wenn die maximale Aufnahmezeit erreicht ist.</string>
|
||||
<string name="ui_settings_option_forceExactDuration_title">Erzwinge exakte Länge</string>
|
||||
<string name="ui_settings_option_forceExactDuration_description">Erzwingt, dass die Ausgabedatei genau für die angegebene Dauer zugeschnitten wird. Wenn dies deaktiviert ist, kann die Ausgabedatei etwas länger sein, da mehrere Intervalle zusammengefasst werden.</string>
|
||||
<string name="ui_settings_option_bitrate_title">Bitrate</string>
|
||||
<string name="ui_settings_option_bitrate_description">Eine höhere Bitrate bedeutet bessere Qualität, aber auch eine größere Dateigröße</string>
|
||||
<string name="ui_settings_option_bitrate_explanation">Leg die Bitrate fest</string>
|
||||
<string name="ui_settings_option_outputFormat_title">Ausgabeformat</string>
|
||||
<string name="ui_settings_option_samplingRate_title">Abtastrate</string>
|
||||
<string name="ui_settings_option_samplingRate_description">Leg fest, wie oft pro Sekunde der Ton abgetastet werden soll. Eine höhere Abtastrate bedeutet bessere Qualität, aber auch eine größere Dateigröße</string>
|
||||
<string name="ui_settings_option_samplingRate_explanation">Leg die Abtastrate fest</string>
|
||||
<string name="ui_settings_option_encoder_title">Encoder</string>
|
||||
<string name="ui_settings_option_encoder_extra_outputFormatChanged">Das Ausgabeformat wurde geändert, da das aktuelle mit diesem Encoder inkompatibel war</string>
|
||||
<string name="ui_settings_value_auto_label">Auto</string>
|
||||
<string name="ui_audioRecorder_state_paused_title">Aufnahme pausiert</string>
|
||||
<string name="ui_audioRecorder_state_paused_description">Audio-Aufnahme wurde pausiert</string>
|
||||
<string name="ui_audioRecorder_error_recording_title">Es ist ein Fehler aufgetreten</string>
|
||||
<string name="ui_audioRecorder_error_recording_description">Alibi stieß bei der Aufnahme auf einen Fehler. Soll die Aufnahme gespeichert werden? </string>
|
||||
<string name="ui_settings_language_title">Sprache</string>
|
||||
<string name="ui_settings_language_update_label">Ändern</string>
|
||||
</resources>
|
@ -1,149 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8' ?>
|
||||
<resources>
|
||||
<string name="app_name">Alibi</string>
|
||||
<string name="bottom_sheet_collapse_description">收起底部动作条</string>
|
||||
<string name="bottom_sheet_dismiss_description">关闭底部动作条</string>
|
||||
<string name="bottom_sheet_drag_handle_description">拖动手柄</string>
|
||||
<string name="bottom_sheet_expand_description">展开底部动作条</string>
|
||||
<string name="call_notification_answer_action">接听</string>
|
||||
<string name="call_notification_answer_video_action">视频通话</string>
|
||||
<string name="call_notification_decline_action">拒接</string>
|
||||
<string name="call_notification_hang_up_action">挂断</string>
|
||||
<string name="call_notification_incoming_text">来电</string>
|
||||
<string name="call_notification_ongoing_text">正在通话</string>
|
||||
<string name="call_notification_screening_text">正在过滤来电</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="close_drawer">关闭导航菜单</string>
|
||||
<string name="close_sheet">关闭工作表</string>
|
||||
<string name="collapsed">已收起</string>
|
||||
<string name="continue_label">继续</string>
|
||||
<string name="date_input_headline">输入日期</string>
|
||||
<string name="date_input_headline_description">输入日期:%1$s</string>
|
||||
<string name="date_input_invalid_for_pattern">日期不符合预期格式:%1$s</string>
|
||||
<string name="date_input_invalid_not_allowed">不允许的日期:%1$s</string>
|
||||
<string name="date_input_invalid_year_range">日期超出预期年份范围 %1$s - %2$s</string>
|
||||
<string name="date_input_label">日期</string>
|
||||
<string name="date_input_no_input_description">无</string>
|
||||
<string name="date_input_title">选择日期</string>
|
||||
<string name="date_picker_headline">选定的日期</string>
|
||||
<string name="date_picker_headline_description">当前的选择:%1$s</string>
|
||||
<string name="date_picker_navigate_to_year_description">切换到年份:%1$s</string>
|
||||
<string name="date_picker_no_selection_description">无</string>
|
||||
<string name="date_picker_scroll_to_earlier_years">滚动显示之前的年份</string>
|
||||
<string name="date_picker_scroll_to_later_years">滚动显示之后的年份</string>
|
||||
<string name="date_picker_switch_to_calendar_mode">切换到日历输入模式</string>
|
||||
<string name="date_picker_switch_to_day_selection">滑动可选择年份,点按可切换回选择日期</string>
|
||||
<string name="date_picker_switch_to_input_mode">切换到文本字段输入模式</string>
|
||||
<string name="date_picker_switch_to_next_month">转到下个月</string>
|
||||
<string name="date_picker_switch_to_previous_month">转到上个月</string>
|
||||
<string name="date_picker_switch_to_year_selection">切换以选择年份</string>
|
||||
<string name="date_picker_title">选择日期</string>
|
||||
<string name="date_picker_today_description">今天</string>
|
||||
<string name="date_picker_year_picker_pane_title">年份选择器可见</string>
|
||||
<string name="date_range_input_invalid_range_input">输入的日期范围无效</string>
|
||||
<string name="date_range_input_title">输入日期</string>
|
||||
<string name="date_range_picker_day_in_range">在范围内</string>
|
||||
<string name="date_range_picker_end_headline">结束日期</string>
|
||||
<string name="date_range_picker_scroll_to_next_month">滚动显示下个月</string>
|
||||
<string name="date_range_picker_scroll_to_previous_month">滚动显示上个月</string>
|
||||
<string name="date_range_picker_start_headline">开始日期</string>
|
||||
<string name="date_range_picker_title">选择日期</string>
|
||||
<string name="default_error_message">输入无效</string>
|
||||
<string name="default_popup_window_title">弹出式窗口</string>
|
||||
<string name="dialog">对话框</string>
|
||||
<string name="dialog_close_cancel_label">取消</string>
|
||||
<string name="dialog_close_neutral_label">OK</string>
|
||||
<string name="dropdown_menu">下拉菜单</string>
|
||||
<string name="expanded">已展开</string>
|
||||
<string name="form_error_type_notNumber">请输入有效数字</string>
|
||||
<string name="form_error_value_mustBeGreaterThan">请输入一个大于 %s 的数字</string>
|
||||
<string name="form_error_value_notInRange">请输入一个在 %s 和 %s 之间的数字</string>
|
||||
<string name="format_kbps">%s KB/s</string>
|
||||
<string name="in_progress">进行中</string>
|
||||
<string name="indeterminate">部分选中</string>
|
||||
<string name="navigation_menu">导航菜单</string>
|
||||
<string name="not_selected">未选择</string>
|
||||
<string name="notificationChannels_recorder_description">显示当前录制状态</string>
|
||||
<string name="notificationChannels_recorder_name">录音机</string>
|
||||
<string name="off">已关闭</string>
|
||||
<string name="ok">Ok</string>
|
||||
<string name="on">已开启</string>
|
||||
<string name="range_end">范围终点</string>
|
||||
<string name="range_start">范围起点</string>
|
||||
<string name="scd_duration_dialog_at_least_placeholder">最小值</string>
|
||||
<string name="scd_duration_dialog_at_most_placeholder">最大值</string>
|
||||
<string name="scd_duration_dialog_clear_input">清除输入</string>
|
||||
<string name="scd_duration_dialog_delete_last_input">删除最后一条输入</string>
|
||||
<string name="scd_duration_dialog_hour_code">h</string>
|
||||
<string name="scd_duration_dialog_hours">小时</string>
|
||||
<string name="scd_duration_dialog_minute_code">m</string>
|
||||
<string name="scd_duration_dialog_minutes">分钟</string>
|
||||
<string name="scd_duration_dialog_second_code">s</string>
|
||||
<string name="scd_duration_dialog_seconds">秒</string>
|
||||
<string name="scd_list_dialog_max_choices">最多选择 %1$d 个选项</string>
|
||||
<string name="scd_list_dialog_min_choices">至少选择 %1$d 个选项</string>
|
||||
<string name="search_bar_search">搜索</string>
|
||||
<string name="selected">已选择</string>
|
||||
<string name="snackbar_dismiss">关闭</string>
|
||||
<string name="status_bar_notification_info_overflow">999+</string>
|
||||
<string name="suggestions_available">以下是搜索建议</string>
|
||||
<string name="switch_role">开关</string>
|
||||
<string name="tab">标签页</string>
|
||||
<string name="template_percent">百分之 %1$d。</string>
|
||||
<string name="time_picker_am">上午</string>
|
||||
<string name="time_picker_hour">时</string>
|
||||
<string name="time_picker_hour_24h_suffix">%1$d 小时</string>
|
||||
<string name="time_picker_hour_selection">选择小时</string>
|
||||
<string name="time_picker_hour_suffix">%1$d 点</string>
|
||||
<string name="time_picker_hour_text_field">表示小时</string>
|
||||
<string name="time_picker_minute">分</string>
|
||||
<string name="time_picker_minute_selection">选择分钟</string>
|
||||
<string name="time_picker_minute_suffix">%1$d 分钟</string>
|
||||
<string name="time_picker_minute_text_field">表示分钟</string>
|
||||
<string name="time_picker_period_toggle_description">选择上午或下午</string>
|
||||
<string name="time_picker_pm">下午</string>
|
||||
<string name="tooltip_long_press_label">显示提示</string>
|
||||
<string name="tooltip_pane_description">提示</string>
|
||||
<string name="ui_audioRecorder_action_delete_confirm_message">您确定要删除此录音吗?</string>
|
||||
<string name="ui_audioRecorder_action_delete_confirm_title">确定删除记录?</string>
|
||||
<string name="ui_audioRecorder_action_delete_label">删除</string>
|
||||
<string name="ui_audioRecorder_action_pause_label">暂停录制</string>
|
||||
<string name="ui_audioRecorder_action_resume_label">恢复录制</string>
|
||||
<string name="ui_audioRecorder_action_saveOldRecording_label">保存自 %s 起的录音</string>
|
||||
<string name="ui_audioRecorder_action_save_label">保存录音</string>
|
||||
<string name="ui_audioRecorder_action_save_processing_dialog_description">正在处理音频,请勿关闭Alibi! 一旦文件准备好,您将自动收到保存文件的提示</string>
|
||||
<string name="ui_audioRecorder_action_save_processing_dialog_title">处理中</string>
|
||||
<string name="ui_audioRecorder_action_start_description">根据您的要求,Alibi 将继续在后台录制并存储最近 %s 分钟的录音</string>
|
||||
<string name="ui_audioRecorder_action_start_label">开始录音</string>
|
||||
<string name="ui_audioRecorder_state_paused_description">音频录制已暂停</string>
|
||||
<string name="ui_audioRecorder_state_paused_title">录制暂停</string>
|
||||
<string name="ui_audioRecorder_state_recording_description">Alibi会在后台持续记录</string>
|
||||
<string name="ui_audioRecorder_state_recording_title">录制中</string>
|
||||
<string name="ui_permissions_permanentlyDenied_message">您将被重定向到应用程序设置页面,在那里可以授予相关权限</string>
|
||||
<string name="ui_permissions_request">请授予权限以继续</string>
|
||||
<string name="ui_permissions_request_title">无法获取权限</string>
|
||||
<string name="ui_settings_advancedSettings_label">高级设置</string>
|
||||
<string name="ui_settings_hint_recordingActive_message">您的更改将在下次开始录音时应用</string>
|
||||
<string name="ui_settings_hint_recordingActive_title">您正在录音...</string>
|
||||
<string name="ui_settings_option_bitrate_description">更高的比特率意味着更好的音频质量以及更大的储存空间占用</string>
|
||||
<string name="ui_settings_option_bitrate_explanation">为音频录制设置比特率</string>
|
||||
<string name="ui_settings_option_bitrate_title">比特率</string>
|
||||
<string name="ui_settings_option_encoder_title">编码器</string>
|
||||
<string name="ui_settings_option_forceExactDuration_description">强制将输出文件拆分为指定的时长。如果禁用此选项,由于批量音频样本被一同编码,输出文件可能会略长一些。</string>
|
||||
<string name="ui_settings_option_forceExactDuration_title">强制指定时长</string>
|
||||
<string name="ui_settings_option_intervalDuration_description">按照指定的时长录制一个单独的批次。Alibi会记录多个批次并删除最旧的批次。在导出音频时,所有批次将被合并到一起。</string>
|
||||
<string name="ui_settings_option_intervalDuration_title">批处理时间</string>
|
||||
<string name="ui_settings_option_maxDuration_description">设置录音的最大时长</string>
|
||||
<string name="ui_settings_option_maxDuration_title">最大持续时间</string>
|
||||
<string name="ui_settings_option_outputFormat_title">输出格式</string>
|
||||
<string name="ui_settings_option_samplingRate_description">定义每秒从音频信号中提取的采样数</string>
|
||||
<string name="ui_settings_option_samplingRate_explanation">设置采样率</string>
|
||||
<string name="ui_settings_option_samplingRate_title">采样率</string>
|
||||
<string name="ui_settings_title">设置</string>
|
||||
<string name="ui_settings_value_auto_label">自动</string>
|
||||
<string name="ui_welcome_explanation_message">Alibi就像你手机上的行车记录仪一样。它会不断地录制音频,并在您需要时保存最近的30分钟录音。</string>
|
||||
<string name="ui_welcome_explanation_title">欢迎使用Alibi!</string>
|
||||
<string name="ui_welcome_responsibility_message">Alibi不对该应用程序的使用负任何责任。您在使用时需自行承担使用风险。</string>
|
||||
<string name="ui_welcome_responsibility_title">您需要自行承担使用该应用程序所带来的风险和后果。</string>
|
||||
<string name="ui_welcome_start_label">开始使用Alibi</string>
|
||||
</resources>
|
@ -1,18 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="app_name">Alibi</string>
|
||||
|
||||
<string name="dialog_close_cancel_label">Abbrechen</string>
|
||||
<string name="dialog_close_neutral_label">OK</string>
|
||||
<string name="continue_label">Fortsetzten</string>
|
||||
|
||||
<string name="format_kbps"><xliff:g name="value">%s</xliff:g> KB/s</string>
|
||||
<string name="form_error_type_notNumber">Bitte eine gültige Nummer eingeben</string>
|
||||
<string name="form_error_value_notInRange">Bitte gib eine Nummer zwischen<xliff:g name="min">%s</xliff:g> und <xliff:g name="max">%s</xliff:g>ein</string>
|
||||
<string name="form_error_value_mustBeGreaterThan">Please enter a number greater than <xliff:g name="min">%s</xliff:g></string>
|
||||
<string name="form_error_value_mustBeGreaterThan">Bitte gib eine größere Zahl als <xliff:g name="min">%s </xliff:g>ein</string>
|
||||
|
||||
<string name="notificationChannels_recorder_name">Recorder</string>
|
||||
<string name="notificationChannels_recorder_description">Zeigt den aktuellen Status der Aufnahme an</string>
|
||||
|
||||
<string name="ui_permissions_request_title">Berechtigung verweigert</string>
|
||||
<string name="ui_permissions_request">Bitte erteile die Berechtigung, um fortzufahren</string>
|
||||
<string name="ui_permissions_permanentlyDenied_message">Du wirst zu den Einstellungen weitergeleitet, um dort die Berechtigung zu erteilen.</string>
|
||||
|
||||
<string name="ui_audioRecorder_action_start_label">Aufnahme starten</string>
|
||||
<string name="ui_audioRecorder_action_saveOldRecording_label">Aufnahme vom <xliff:g name="date">%s</xliff:g> speichern</string>
|
||||
<string name="ui_audioRecorder_action_delete_label">Löschen</string>
|
||||
@ -26,11 +31,13 @@
|
||||
<string name="ui_audioRecorder_action_save_processing_dialog_description">Audio wird bearbeitet, Alibi nicht schließen! Du wirst automatisch aufgefordert, die Datei zu speichern, wenn diese fertig bearbeitet ist</string>
|
||||
<string name="ui_audioRecorder_state_recording_title">Aufnahme läuft</string>
|
||||
<string name="ui_audioRecorder_state_recording_description">Alibi nimmt im Hintergrund weiter auf</string>
|
||||
|
||||
<string name="ui_welcome_explanation_title">Wilkommen zu Alibi!</string>
|
||||
<string name="ui_welcome_explanation_message">Alibi funktioniert wird eine Dashcam für dein Handy. Es ermöglicht dir, Ton im Hintergrund kontinuierlich aufzunehmen und die letzten 30 Minuten auf Wunsch zu speichern.</string>
|
||||
<string name="ui_welcome_responsibility_title">Du bist für die Nutzung dieser App verantwortlich!</string>
|
||||
<string name="ui_welcome_responsibility_message">Alibi übernimmt keine Verantwortung für die Nutzung dieser App. Du trägst die alleinige Verantwortung. Die Nutzung erfolgt auf eigene Gefahr.</string>
|
||||
<string name="ui_welcome_start_label">Alibi Starten</string>
|
||||
|
||||
<string name="ui_settings_title">Einstellungen</string>
|
||||
<string name="ui_settings_advancedSettings_label">Erweiterte Einstellungen</string>
|
||||
<string name="ui_settings_hint_recordingActive_title">Aufnahme läuft</string>
|
||||
@ -57,9 +64,4 @@
|
||||
<string name="ui_audioRecorder_error_recording_description">Alibi stieß bei der Aufnahme auf einen Fehler. Soll die Aufnahme gespeichert werden? </string>
|
||||
<string name="ui_settings_language_title">Sprache</string>
|
||||
<string name="ui_settings_language_update_label">Ändern</string>
|
||||
<string name="ui_settings_option_import_label">Import Settings</string>
|
||||
<string name="ui_settings_option_export_label">Export Settings</string>
|
||||
<string name="ui_settings_option_import_dialog_text">Are you sure you want to import these settings? Your current settings will be overwritten!</string>
|
||||
<string name="ui_settings_option_import_dialog_confirm">Import settings</string>
|
||||
<string name="ui_settings_option_import_success">Settings have been imported successfully!</string>
|
||||
</resources>
|
||||
|
@ -1,65 +1,149 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<?xml version='1.0' encoding='utf-8' ?>
|
||||
<resources>
|
||||
<string name="app_name">Alibi</string>
|
||||
<string name="bottom_sheet_collapse_description">收起底部动作条</string>
|
||||
<string name="bottom_sheet_dismiss_description">关闭底部动作条</string>
|
||||
<string name="bottom_sheet_drag_handle_description">拖动手柄</string>
|
||||
<string name="bottom_sheet_expand_description">展开底部动作条</string>
|
||||
<string name="call_notification_answer_action">接听</string>
|
||||
<string name="call_notification_answer_video_action">视频通话</string>
|
||||
<string name="call_notification_decline_action">拒接</string>
|
||||
<string name="call_notification_hang_up_action">挂断</string>
|
||||
<string name="call_notification_incoming_text">来电</string>
|
||||
<string name="call_notification_ongoing_text">正在通话</string>
|
||||
<string name="call_notification_screening_text">正在过滤来电</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="close_drawer">关闭导航菜单</string>
|
||||
<string name="close_sheet">关闭工作表</string>
|
||||
<string name="collapsed">已收起</string>
|
||||
<string name="continue_label">继续</string>
|
||||
<string name="date_input_headline">输入日期</string>
|
||||
<string name="date_input_headline_description">输入日期:%1$s</string>
|
||||
<string name="date_input_invalid_for_pattern">日期不符合预期格式:%1$s</string>
|
||||
<string name="date_input_invalid_not_allowed">不允许的日期:%1$s</string>
|
||||
<string name="date_input_invalid_year_range">日期超出预期年份范围 %1$s - %2$s</string>
|
||||
<string name="date_input_label">日期</string>
|
||||
<string name="date_input_no_input_description">无</string>
|
||||
<string name="date_input_title">选择日期</string>
|
||||
<string name="date_picker_headline">选定的日期</string>
|
||||
<string name="date_picker_headline_description">当前的选择:%1$s</string>
|
||||
<string name="date_picker_navigate_to_year_description">切换到年份:%1$s</string>
|
||||
<string name="date_picker_no_selection_description">无</string>
|
||||
<string name="date_picker_scroll_to_earlier_years">滚动显示之前的年份</string>
|
||||
<string name="date_picker_scroll_to_later_years">滚动显示之后的年份</string>
|
||||
<string name="date_picker_switch_to_calendar_mode">切换到日历输入模式</string>
|
||||
<string name="date_picker_switch_to_day_selection">滑动可选择年份,点按可切换回选择日期</string>
|
||||
<string name="date_picker_switch_to_input_mode">切换到文本字段输入模式</string>
|
||||
<string name="date_picker_switch_to_next_month">转到下个月</string>
|
||||
<string name="date_picker_switch_to_previous_month">转到上个月</string>
|
||||
<string name="date_picker_switch_to_year_selection">切换以选择年份</string>
|
||||
<string name="date_picker_title">选择日期</string>
|
||||
<string name="date_picker_today_description">今天</string>
|
||||
<string name="date_picker_year_picker_pane_title">年份选择器可见</string>
|
||||
<string name="date_range_input_invalid_range_input">输入的日期范围无效</string>
|
||||
<string name="date_range_input_title">输入日期</string>
|
||||
<string name="date_range_picker_day_in_range">在范围内</string>
|
||||
<string name="date_range_picker_end_headline">结束日期</string>
|
||||
<string name="date_range_picker_scroll_to_next_month">滚动显示下个月</string>
|
||||
<string name="date_range_picker_scroll_to_previous_month">滚动显示上个月</string>
|
||||
<string name="date_range_picker_start_headline">开始日期</string>
|
||||
<string name="date_range_picker_title">选择日期</string>
|
||||
<string name="default_error_message">输入无效</string>
|
||||
<string name="default_popup_window_title">弹出式窗口</string>
|
||||
<string name="dialog">对话框</string>
|
||||
<string name="dialog_close_cancel_label">取消</string>
|
||||
<string name="dialog_close_neutral_label">OK</string>
|
||||
<string name="continue_label">继续</string>
|
||||
<string name="format_kbps"><xliff:g name="value">%s</xliff:g> KB/s</string>
|
||||
<string name="dropdown_menu">下拉菜单</string>
|
||||
<string name="expanded">已展开</string>
|
||||
<string name="form_error_type_notNumber">请输入有效数字</string>
|
||||
<string name="form_error_value_notInRange">Please enter a number between <xliff:g name="min">%s</xliff:g> and <xliff:g name="max">%s</xliff:g></string>
|
||||
<string name="form_error_value_mustBeGreaterThan">Please enter a number greater than <xliff:g name="min">%s</xliff:g></string>
|
||||
<string name="notificationChannels_recorder_name">录音机</string>
|
||||
<string name="form_error_value_mustBeGreaterThan">请输入一个大于 %s 的数字</string>
|
||||
<string name="form_error_value_notInRange">请输入一个在 %s 和 %s 之间的数字</string>
|
||||
<string name="format_kbps">%s KB/s</string>
|
||||
<string name="in_progress">进行中</string>
|
||||
<string name="indeterminate">部分选中</string>
|
||||
<string name="navigation_menu">导航菜单</string>
|
||||
<string name="not_selected">未选择</string>
|
||||
<string name="notificationChannels_recorder_description">显示当前录制状态</string>
|
||||
<string name="ui_permissions_request_title">无法获取权限</string>
|
||||
<string name="ui_permissions_request">请授予权限以继续</string>
|
||||
<string name="ui_permissions_permanentlyDenied_message">您将被重定向到应用程序设置页面,在那里可以授予相关权限</string>
|
||||
<string name="ui_audioRecorder_action_start_label">开始录音</string>
|
||||
<string name="ui_audioRecorder_action_saveOldRecording_label">Save Recording from <xliff:g name="date">%s</xliff:g></string>
|
||||
<string name="ui_audioRecorder_action_delete_label">删除</string>
|
||||
<string name="ui_audioRecorder_action_delete_confirm_title">确定删除记录?</string>
|
||||
<string name="notificationChannels_recorder_name">录音机</string>
|
||||
<string name="off">已关闭</string>
|
||||
<string name="ok">Ok</string>
|
||||
<string name="on">已开启</string>
|
||||
<string name="range_end">范围终点</string>
|
||||
<string name="range_start">范围起点</string>
|
||||
<string name="scd_duration_dialog_at_least_placeholder">最小值</string>
|
||||
<string name="scd_duration_dialog_at_most_placeholder">最大值</string>
|
||||
<string name="scd_duration_dialog_clear_input">清除输入</string>
|
||||
<string name="scd_duration_dialog_delete_last_input">删除最后一条输入</string>
|
||||
<string name="scd_duration_dialog_hour_code">h</string>
|
||||
<string name="scd_duration_dialog_hours">小时</string>
|
||||
<string name="scd_duration_dialog_minute_code">m</string>
|
||||
<string name="scd_duration_dialog_minutes">分钟</string>
|
||||
<string name="scd_duration_dialog_second_code">s</string>
|
||||
<string name="scd_duration_dialog_seconds">秒</string>
|
||||
<string name="scd_list_dialog_max_choices">最多选择 %1$d 个选项</string>
|
||||
<string name="scd_list_dialog_min_choices">至少选择 %1$d 个选项</string>
|
||||
<string name="search_bar_search">搜索</string>
|
||||
<string name="selected">已选择</string>
|
||||
<string name="snackbar_dismiss">关闭</string>
|
||||
<string name="status_bar_notification_info_overflow">999+</string>
|
||||
<string name="suggestions_available">以下是搜索建议</string>
|
||||
<string name="switch_role">开关</string>
|
||||
<string name="tab">标签页</string>
|
||||
<string name="template_percent">百分之 %1$d。</string>
|
||||
<string name="time_picker_am">上午</string>
|
||||
<string name="time_picker_hour">时</string>
|
||||
<string name="time_picker_hour_24h_suffix">%1$d 小时</string>
|
||||
<string name="time_picker_hour_selection">选择小时</string>
|
||||
<string name="time_picker_hour_suffix">%1$d 点</string>
|
||||
<string name="time_picker_hour_text_field">表示小时</string>
|
||||
<string name="time_picker_minute">分</string>
|
||||
<string name="time_picker_minute_selection">选择分钟</string>
|
||||
<string name="time_picker_minute_suffix">%1$d 分钟</string>
|
||||
<string name="time_picker_minute_text_field">表示分钟</string>
|
||||
<string name="time_picker_period_toggle_description">选择上午或下午</string>
|
||||
<string name="time_picker_pm">下午</string>
|
||||
<string name="tooltip_long_press_label">显示提示</string>
|
||||
<string name="tooltip_pane_description">提示</string>
|
||||
<string name="ui_audioRecorder_action_delete_confirm_message">您确定要删除此录音吗?</string>
|
||||
<string name="ui_audioRecorder_action_delete_confirm_title">确定删除记录?</string>
|
||||
<string name="ui_audioRecorder_action_delete_label">删除</string>
|
||||
<string name="ui_audioRecorder_action_pause_label">暂停录制</string>
|
||||
<string name="ui_audioRecorder_action_resume_label">恢复录制</string>
|
||||
<string name="ui_audioRecorder_action_saveOldRecording_label">保存自 %s 起的录音</string>
|
||||
<string name="ui_audioRecorder_action_save_label">保存录音</string>
|
||||
<string name="ui_audioRecorder_action_start_description">Alibi will continue recording in the background and store the last <xliff:g name="durationInMinutes">%s</xliff:g> minutes at your request</string>
|
||||
<string name="ui_audioRecorder_action_save_processing_dialog_title">处理中</string>
|
||||
<string name="ui_audioRecorder_action_save_processing_dialog_description">正在处理音频,请勿关闭Alibi! 一旦文件准备好,您将自动收到保存文件的提示</string>
|
||||
<string name="ui_audioRecorder_state_recording_title">录制中</string>
|
||||
<string name="ui_audioRecorder_action_save_processing_dialog_title">处理中</string>
|
||||
<string name="ui_audioRecorder_action_start_description">根据您的要求,Alibi 将继续在后台录制并存储最近 %s 分钟的录音</string>
|
||||
<string name="ui_audioRecorder_action_start_label">开始录音</string>
|
||||
<string name="ui_audioRecorder_state_paused_description">音频录制已暂停</string>
|
||||
<string name="ui_audioRecorder_state_paused_title">录制暂停</string>
|
||||
<string name="ui_audioRecorder_state_recording_description">Alibi会在后台持续记录</string>
|
||||
<string name="ui_welcome_explanation_title">欢迎使用Alibi!</string>
|
||||
<string name="ui_welcome_explanation_message">Alibi就像你手机上的行车记录仪一样。它会不断地录制音频,并在您需要时保存最近的30分钟录音。</string>
|
||||
<string name="ui_welcome_responsibility_title">您需要自行承担使用该应用程序所带来的风险和后果。</string>
|
||||
<string name="ui_welcome_responsibility_message">Alibi不对该应用程序的使用负任何责任。您在使用时需自行承担使用风险。</string>
|
||||
<string name="ui_welcome_start_label">开始使用Alibi</string>
|
||||
<string name="ui_settings_title">设置</string>
|
||||
<string name="ui_audioRecorder_state_recording_title">录制中</string>
|
||||
<string name="ui_permissions_permanentlyDenied_message">您将被重定向到应用程序设置页面,在那里可以授予相关权限</string>
|
||||
<string name="ui_permissions_request">请授予权限以继续</string>
|
||||
<string name="ui_permissions_request_title">无法获取权限</string>
|
||||
<string name="ui_settings_advancedSettings_label">高级设置</string>
|
||||
<string name="ui_settings_hint_recordingActive_title">您正在录音...</string>
|
||||
<string name="ui_settings_hint_recordingActive_message">您的更改将在下次开始录音时应用</string>
|
||||
<string name="ui_settings_option_maxDuration_title">最大持续时间</string>
|
||||
<string name="ui_settings_option_maxDuration_description">设置录音的最大时长</string>
|
||||
<string name="ui_settings_option_intervalDuration_title">批处理时间</string>
|
||||
<string name="ui_settings_option_intervalDuration_description">按照指定的时长录制一个单独的批次。Alibi会记录多个批次并删除最旧的批次。在导出音频时,所有批次将被合并到一起。</string>
|
||||
<string name="ui_settings_option_forceExactDuration_title">强制指定时长</string>
|
||||
<string name="ui_settings_option_forceExactDuration_description">强制将输出文件拆分为指定的时长。如果禁用此选项,由于批量音频样本被一同编码,输出文件可能会略长一些。</string>
|
||||
<string name="ui_settings_option_bitrate_title">比特率</string>
|
||||
<string name="ui_settings_hint_recordingActive_title">您正在录音...</string>
|
||||
<string name="ui_settings_option_bitrate_description">更高的比特率意味着更好的音频质量以及更大的储存空间占用</string>
|
||||
<string name="ui_settings_option_bitrate_explanation">为音频录制设置比特率</string>
|
||||
<string name="ui_settings_option_bitrate_title">比特率</string>
|
||||
<string name="ui_settings_option_encoder_title">编码器</string>
|
||||
<string name="ui_settings_option_forceExactDuration_description">强制将输出文件拆分为指定的时长。如果禁用此选项,由于批量音频样本被一同编码,输出文件可能会略长一些。</string>
|
||||
<string name="ui_settings_option_forceExactDuration_title">强制指定时长</string>
|
||||
<string name="ui_settings_option_intervalDuration_description">按照指定的时长录制一个单独的批次。Alibi会记录多个批次并删除最旧的批次。在导出音频时,所有批次将被合并到一起。</string>
|
||||
<string name="ui_settings_option_intervalDuration_title">批处理时间</string>
|
||||
<string name="ui_settings_option_maxDuration_description">设置录音的最大时长</string>
|
||||
<string name="ui_settings_option_maxDuration_title">最大持续时间</string>
|
||||
<string name="ui_settings_option_outputFormat_title">输出格式</string>
|
||||
<string name="ui_settings_option_samplingRate_title">采样率</string>
|
||||
<string name="ui_settings_option_samplingRate_description">定义每秒从音频信号中提取的采样数</string>
|
||||
<string name="ui_settings_option_samplingRate_explanation">设置采样率</string>
|
||||
<string name="ui_settings_option_encoder_title">编码器</string>
|
||||
<string name="ui_settings_option_encoder_extra_outputFormatChanged">Output Format has been changed because the current one was incompatible with this encoder</string>
|
||||
<string name="ui_settings_option_samplingRate_title">采样率</string>
|
||||
<string name="ui_settings_title">设置</string>
|
||||
<string name="ui_settings_value_auto_label">自动</string>
|
||||
<string name="ui_audioRecorder_state_paused_title">录制暂停</string>
|
||||
<string name="ui_audioRecorder_state_paused_description">音频录制已暂停</string>
|
||||
<string name="ui_audioRecorder_error_recording_title">An error occured</string>
|
||||
<string name="ui_audioRecorder_error_recording_description">Alibi encountered an error during recording. Would you like to try saving the recording?</string>
|
||||
<string name="ui_settings_language_title">Language</string>
|
||||
<string name="ui_settings_language_update_label">Change</string>
|
||||
<string name="ui_settings_option_import_label">Import Settings</string>
|
||||
<string name="ui_settings_option_export_label">Export Settings</string>
|
||||
<string name="ui_settings_option_import_dialog_text">Are you sure you want to import these settings? Your current settings will be overwritten!</string>
|
||||
<string name="ui_settings_option_import_dialog_confirm">Import settings</string>
|
||||
<string name="ui_settings_option_import_success">Settings have been imported successfully!</string>
|
||||
<string name="ui_welcome_explanation_message">Alibi就像你手机上的行车记录仪一样。它会不断地录制音频,并在您需要时保存最近的30分钟录音。</string>
|
||||
<string name="ui_welcome_explanation_title">欢迎使用Alibi!</string>
|
||||
<string name="ui_welcome_responsibility_message">Alibi不对该应用程序的使用负任何责任。您在使用时需自行承担使用风险。</string>
|
||||
<string name="ui_welcome_responsibility_title">您需要自行承担使用该应用程序所带来的风险和后果。</string>
|
||||
<string name="ui_welcome_start_label">开始使用Alibi</string>
|
||||
</resources>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="app_name">Alibi</string>
|
||||
|
||||
<string name="dialog_close_cancel_label">Cancel</string>
|
||||
@ -64,4 +63,9 @@
|
||||
<string name="ui_audioRecorder_error_recording_description">Alibi encountered an error during recording. Would you like to try saving the recording?</string>
|
||||
<string name="ui_settings_language_title">Language</string>
|
||||
<string name="ui_settings_language_update_label">Change</string>
|
||||
<string name="ui_settings_option_import_label">Import Settings</string>
|
||||
<string name="ui_settings_option_export_label">Export Settings</string>
|
||||
<string name="ui_settings_option_import_dialog_text">Are you sure you want to import these settings? Your current settings will be overwritten!</string>
|
||||
<string name="ui_settings_option_import_dialog_confirm">Import settings</string>
|
||||
<string name="ui_settings_option_import_success">Settings have been imported successfully!</string>
|
||||
</resources>
|
13
crowdin.yml
Normal file
13
crowdin.yml
Normal file
@ -0,0 +1,13 @@
|
||||
files:
|
||||
- source: /app/src/main/res/values/strings.xml
|
||||
translation: /app/src/main/res/values-%android_code%/strings.xml
|
||||
translate_attributes: 0
|
||||
content_segmentation: 0
|
||||
type: xml
|
||||
languages_mapping:
|
||||
android_code:
|
||||
de-rDE: de
|
||||
tr-rTR: tr
|
||||
zh-rCN: zh
|
||||
- source: /fastlane/metadata/android/en-US/*.txt
|
||||
translation: /fastlane/metadata/android/%locale%/%original_file_name%
|
Loading…
x
Reference in New Issue
Block a user