From 302ef26f78cc1af1c5d45293197e8d604e7a0796 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Thu, 30 May 2024 17:04:36 -0400 Subject: [PATCH 01/54] Add UiState for voice to content --- .../voicetocontent/VoiceToContentUiState.kt | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt new file mode 100644 index 000000000000..ec5b18d4b37f --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt @@ -0,0 +1,39 @@ +package org.wordpress.android.ui.voicetocontent + +sealed class VoiceToContentUiState { + abstract val headerText: Int + abstract val onClose: () -> Unit + + data class Initializing( + override val headerText: Int, + val labelText: Int, + val onCloseAction: () -> Unit, + override val onClose: () -> Unit = onCloseAction + ) : VoiceToContentUiState() + + data class ReadyToRecord( + override val headerText: Int, + val labelText: Int, + val subLabelText: Int, + val onMicTap: () -> Unit, + val onCloseAction: () -> Unit, + val hasPermission: Boolean, + val onRequestPermission: () -> Unit, + override val onClose: () -> Unit = onCloseAction + ) : VoiceToContentUiState() + + data class Recording( + override val headerText: Int, + val elapsedTime: String, + val onStopTap: () -> Unit, + val onCloseAction: () -> Unit, + override val onClose: () -> Unit = onCloseAction + ) : VoiceToContentUiState() + + data class Processing( + override val headerText: Int, + val onCloseAction: () -> Unit, + override val onClose: () -> Unit = onCloseAction + ) : VoiceToContentUiState() +} + From 0540358da0065835bc534d06ecbb0820633b7c6e Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Thu, 30 May 2024 17:05:05 -0400 Subject: [PATCH 02/54] Move VoiceToContent screen into it's own class with initial UI pass --- .../ui/voicetocontent/VoiceToContentScreen.kt | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt new file mode 100644 index 000000000000..31de8959edd8 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -0,0 +1,174 @@ +package org.wordpress.android.ui.voicetocontent + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Call +import androidx.compose.material.icons.filled.Check +import androidx.compose.material.icons.filled.CheckCircle +import androidx.compose.material.icons.filled.Close +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import org.wordpress.android.R +import org.wordpress.android.ui.compose.theme.AppTheme + +@Composable +fun VoiceToContentScreen( + viewModel: VoiceToContentViewModel +) { + val state by viewModel.state.collectAsState() + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + when (val currentState = state) { + is VoiceToContentUiState.Initializing -> InitializingView(currentState) + is VoiceToContentUiState.ReadyToRecord -> ReadyToRecordView(currentState) + is VoiceToContentUiState.Recording -> RecordingView(currentState) + is VoiceToContentUiState.Processing -> ProcessingView(currentState) + } + } +} + +@Composable +fun InitializingView(state: VoiceToContentUiState.Initializing) { + Column { + Header(state.headerText, state.onClose) + Spacer(modifier = Modifier.height(16.dp)) + Text(stringResource(id = state.labelText)) + CircularProgressIndicator() + } +} + +@Composable +fun ReadyToRecordView( + state: VoiceToContentUiState.ReadyToRecord +) { + Column { + Header(state.headerText, state.onClose) + Spacer(modifier = Modifier.height(16.dp)) + Text(stringResource(id = state.labelText)) + Text(stringResource(id = state.subLabelText)) + Spacer(modifier = Modifier.height(16.dp)) + IconButton( + enabled = true, + onClick = if (state.hasPermission) { + state.onMicTap + } else { + state.onRequestPermission + } + ) { + Icon(imageVector = Icons.Default.CheckCircle, contentDescription = null) + } + } +} + +@Composable +fun RecordingView(state: VoiceToContentUiState.Recording) { + Column { + Header(state.headerText, state.onClose) + Spacer(modifier = Modifier.height(16.dp)) + Text(state.elapsedTime) + Spacer(modifier = Modifier.height(16.dp)) + Icon(imageVector = Icons.Default.Call, contentDescription = null) + Spacer(modifier = Modifier.height(16.dp)) + IconButton(onClick = state.onStopTap, enabled = true) { + Icon(imageVector = Icons.Default.Check, contentDescription = null) + } + } +} + +@Composable +fun ProcessingView(state: VoiceToContentUiState.Processing) { + Column { + Header(state.headerText, state.onClose) + Spacer(modifier = Modifier.height(16.dp)) + CircularProgressIndicator() + } +} + + +@Composable +fun Header(@StringRes headerText: Int, onClose: () -> Unit) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() + ) { + Text(text = stringResource(id = headerText), style = MaterialTheme.typography.h6) + IconButton(onClick = onClose) { + Icon(imageVector = Icons.Default.Close, contentDescription = null) + } + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewInitializingView() { + AppTheme { + InitializingView(VoiceToContentUiState.Initializing( + headerText = R.string.voice_to_content_initializing, + labelText = R.string.voice_to_content_preparing, + onCloseAction = {} + )) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewReadyToRecordView() { + AppTheme { + ReadyToRecordView(VoiceToContentUiState.ReadyToRecord( + headerText = R.string.voice_to_content_ready_to_record, + labelText = R.string.voice_to_content_ready_to_record_label, + subLabelText = R.string.voice_to_content_tap_to_start, + onMicTap = {}, + onCloseAction = {}, + hasPermission = true, + onRequestPermission = {} + )) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewRecordingView() { + AppTheme { + RecordingView(VoiceToContentUiState.Recording( + headerText = R.string.voice_to_content_recording, + elapsedTime = "0 sec", + onStopTap = {}, + onCloseAction = {} + )) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewProcessingView() { + AppTheme { + ProcessingView(VoiceToContentUiState.Processing( + headerText = R.string.voice_to_content_processing, + onCloseAction = {} + )) + } +} From 1fc33fafbe771e6da34c583dd01df568e56afd93 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Thu, 30 May 2024 17:06:56 -0400 Subject: [PATCH 03/54] Refactor: Move VoiceToContent screen into it's own class, move some permission checks to the viewmodel, observe viewmodel --- .../VoiceToContentDialogFragment.kt | 109 +++--------------- 1 file changed, 16 insertions(+), 93 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt index 25b39aefa519..6a751b11388e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt @@ -1,7 +1,6 @@ package org.wordpress.android.ui.voicetocontent import android.content.Intent -import android.content.pm.PackageManager import android.net.Uri import android.os.Bundle import android.view.LayoutInflater @@ -9,58 +8,51 @@ import android.view.View import android.view.ViewGroup import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog -import androidx.compose.foundation.clickable -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.platform.ComposeView import androidx.fragment.app.viewModels import com.google.android.material.bottomsheet.BottomSheetDialogFragment import dagger.hilt.android.AndroidEntryPoint import org.wordpress.android.ui.compose.theme.AppTheme -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material.Icon -import androidx.compose.material.Text -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.core.content.ContextCompat import org.wordpress.android.R import org.wordpress.android.util.audio.IAudioRecorder.Companion.REQUIRED_RECORDING_PERMISSIONS import android.provider.Settings +import androidx.compose.material.ExperimentalMaterialApi @AndroidEntryPoint class VoiceToContentDialogFragment : BottomSheetDialogFragment() { private val viewModel: VoiceToContentViewModel by viewModels() + @ExperimentalMaterialApi override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = ComposeView(requireContext()).apply { setContent { AppTheme { VoiceToContentScreen( - viewModel = viewModel, - onRequestPermission = { requestAllPermissionsForRecording() }, - hasPermission = { hasAllPermissionsForRecording() } + viewModel = viewModel ) } } } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + observeViewModel() + } + + private fun observeViewModel() { + viewModel.requestPermission.observe(viewLifecycleOwner) { + requestAllPermissionsForRecording() + } + } + private val requestMultiplePermissionsLauncher = registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions() ) { permissions -> val areAllPermissionsGranted = permissions.entries.all { it.value } if (areAllPermissionsGranted) { - viewModel.startRecording() + // todo: annmarie - this is something else we want to do + viewModel.showStartRecordingView() } else { // Check if any permissions were denied permanently if (permissions.entries.any { !it.value }) { @@ -69,15 +61,6 @@ class VoiceToContentDialogFragment : BottomSheetDialogFragment() { } } - private fun hasAllPermissionsForRecording(): Boolean { - return REQUIRED_RECORDING_PERMISSIONS.all { - ContextCompat.checkSelfPermission( - requireContext(), - it - ) == PackageManager.PERMISSION_GRANTED - } - } - private fun requestAllPermissionsForRecording() { requestMultiplePermissionsLauncher.launch(REQUIRED_RECORDING_PERMISSIONS) } @@ -104,63 +87,3 @@ class VoiceToContentDialogFragment : BottomSheetDialogFragment() { fun newInstance() = VoiceToContentDialogFragment() } } - -@Composable -fun VoiceToContentScreen( - viewModel: VoiceToContentViewModel, - onRequestPermission: () -> Unit, - hasPermission: () -> Boolean -) { - val result by viewModel.uiState.observeAsState() - val assistantFeature by viewModel.aiAssistantFeatureState.observeAsState() - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - ) { - when { - result?.isError == true -> { - Text(text = "Error happened", fontSize = 20.sp, fontWeight = FontWeight.Bold) - } - - result?.content != null -> { - Text(text = result?.content!!, fontSize = 20.sp, fontWeight = FontWeight.Bold) - } - - assistantFeature != null -> { - Text(text = "Assistant Feature Returned Successfully", fontSize = 20.sp, fontWeight = FontWeight.Bold) - Spacer(modifier = Modifier.height(16.dp)) - } - - else -> { - Text(text = "Ready to fake record - tap microphone", fontSize = 20.sp, fontWeight = FontWeight.Bold) - Spacer(modifier = Modifier.height(16.dp)) - Icon( - painterResource(id = R.drawable.ic_mic_white_24dp), - contentDescription = "Microphone", - modifier = Modifier - .size(64.dp) - .clickable { - if (hasPermission()) { - viewModel.startRecording() - } else { - onRequestPermission() - } - } - ) - - Spacer(modifier = Modifier.height(16.dp)) - Icon( - painterResource(id = com.google.android.exoplayer2.ui.R.drawable.exo_icon_stop), - contentDescription = "Stop", - modifier = Modifier - .size(64.dp) - .clickable { - viewModel.stopRecording() - } - ) - } - } - } -} From 426528b18ca98d2ee04d16c332b82ae7749ec6f2 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Thu, 30 May 2024 17:07:13 -0400 Subject: [PATCH 04/54] Add string placeholders for voiceToContent --- WordPress/src/main/res/values/strings.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 3ca5cf0a2a55..07c6f0106470 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -4902,5 +4902,14 @@ translators: %s: Select control option value e.g: "Auto, 25%". --> Audio Recording Permission Required To record audio, this app needs permission to access your microphone. You have previously denied this permission. Please enable the microphone permission in the app settings to use this feature. - + Initializing + Preparing + Ready to Record + Ready to Record + Tap to start + Recording + Elapsed Time + Tap to stop + Processing + Processing From 4ba9d753da149d4b984256aea6db4a97499bbf71 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Thu, 30 May 2024 17:09:06 -0400 Subject: [PATCH 05/54] Add placeholder methods for uiState. --- .../voicetocontent/VoiceToContentViewModel.kt | 85 ++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index 35aa99f89964..91ca4478a8c0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -1,19 +1,28 @@ package org.wordpress.android.ui.voicetocontent +import android.content.pm.PackageManager import android.util.Log +import androidx.core.content.ContextCompat import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch +import org.wordpress.android.R import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.model.jetpackai.JetpackAIAssistantFeature import org.wordpress.android.fluxc.network.rest.wpcom.jetpackai.JetpackAIAssistantFeatureResponse import org.wordpress.android.fluxc.store.jetpackai.JetpackAIStore import org.wordpress.android.modules.UI_THREAD import org.wordpress.android.ui.mysite.SelectedSiteRepository +import org.wordpress.android.util.audio.IAudioRecorder +import org.wordpress.android.viewmodel.ContextProvider import org.wordpress.android.viewmodel.ScopedViewModel import java.io.File import javax.inject.Inject @@ -26,7 +35,8 @@ class VoiceToContentViewModel @Inject constructor( private val voiceToContentUseCase: VoiceToContentUseCase, private val selectedSiteRepository: SelectedSiteRepository, private val jetpackAIStore: JetpackAIStore, - private val recordingUseCase: RecordingUseCase + private val recordingUseCase: RecordingUseCase, + private val contextProvider: ContextProvider ) : ScopedViewModel(mainDispatcher) { private val _uiState = MutableLiveData() val uiState = _uiState as LiveData @@ -34,10 +44,70 @@ class VoiceToContentViewModel @Inject constructor( private val _aiAssistantFeatureState = MutableLiveData() val aiAssistantFeatureState = _aiAssistantFeatureState as LiveData + private val _requestPermission = MutableLiveData() + val requestPermission = _requestPermission as LiveData + + private val _state = MutableStateFlow(VoiceToContentUiState.Initializing( + headerText = R.string.voice_to_content_initializing, + labelText = R.string.voice_to_content_preparing, + onCloseAction = ::onClose + )) + val state: StateFlow = _state.asStateFlow() + private fun isVoiceToContentEnabled() = voiceToContentFeatureUtils.isVoiceToContentEnabled() init { observeRecordingUpdates() + // Simulate initialization delay + viewModelScope.launch { + delay(2000) + _state.value = VoiceToContentUiState.ReadyToRecord( + headerText = R.string.voice_to_content_ready_to_record, + labelText = R.string.voice_to_content_ready_to_record_label, + subLabelText = R.string.voice_to_content_tap_to_start, + onMicTap = ::onMicTap, + onCloseAction = ::onClose, + onRequestPermission = ::onRequestPermission, + hasPermission = hasAllPermissionsForRecording() + ) + } + } + + private fun onClose() { + // Handle close + } + + private fun onRequestPermission() { + _requestPermission.postValue(Unit) + } + + private fun onMicTap() { + _state.value = VoiceToContentUiState.Recording( + headerText = R.string.voice_to_content_recording, + elapsedTime = "0 sec", + onStopTap = ::onStopTap, + onCloseAction = ::onClose + ) + // Simulate recording time + viewModelScope.launch { + for (i in 1..60) { + delay(1000) + _state.value = (state.value as? VoiceToContentUiState.Recording)?.copy( + elapsedTime = "$i sec" + ) ?: return@launch + } + _state.value = VoiceToContentUiState.Processing( + headerText = R.string.voice_to_content_processing, + onCloseAction = ::onClose + ) + // Simulate processing delay + delay(2000) + // Handle recording complete + } + } + + private fun onStopTap() { + // Handle stop recording } private fun observeRecordingUpdates() { @@ -53,6 +123,10 @@ class VoiceToContentViewModel @Inject constructor( } } + fun showStartRecordingView() { + onMicTap() + } + fun startRecording() { recordingUseCase.startRecording { recordingPath -> val file = getRecordingFile(recordingPath) @@ -107,5 +181,14 @@ class VoiceToContentViewModel @Inject constructor( } } } + + private fun hasAllPermissionsForRecording(): Boolean { + return IAudioRecorder.REQUIRED_RECORDING_PERMISSIONS.all { + ContextCompat.checkSelfPermission( + contextProvider.getContext(), + it + ) == PackageManager.PERMISSION_GRANTED + } + } } From 78b11f3a0ff76c1d30beb81021ccacdfc94659e8 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 31 May 2024 14:32:24 -0400 Subject: [PATCH 06/54] Move the call to jetpack ai assistant into its own use case --- .../PrepareVoiceToContentUseCase.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/PrepareVoiceToContentUseCase.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/PrepareVoiceToContentUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/PrepareVoiceToContentUseCase.kt new file mode 100644 index 000000000000..487eea60d28c --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/PrepareVoiceToContentUseCase.kt @@ -0,0 +1,30 @@ +package org.wordpress.android.ui.voicetocontent + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.wordpress.android.fluxc.model.SiteModel +import org.wordpress.android.fluxc.model.jetpackai.JetpackAIAssistantFeature +import org.wordpress.android.fluxc.network.rest.wpcom.jetpackai.JetpackAIAssistantFeatureResponse +import org.wordpress.android.fluxc.store.jetpackai.JetpackAIStore +import javax.inject.Inject + +class PrepareVoiceToContentUseCase @Inject constructor( + private val jetpackAIStore: JetpackAIStore +) { + suspend fun execute(site: SiteModel): PrepareVoiceToContentResult = + withContext(Dispatchers.IO) { + when (val response = jetpackAIStore.fetchJetpackAIAssistantFeature(site)) { + is JetpackAIAssistantFeatureResponse.Success -> { + PrepareVoiceToContentResult.Success(model = response.model) + } + is JetpackAIAssistantFeatureResponse.Error -> { + PrepareVoiceToContentResult.Error + } + } + } +} + +sealed class PrepareVoiceToContentResult { + data class Success(val model: JetpackAIAssistantFeature) : PrepareVoiceToContentResult() + data object Error : PrepareVoiceToContentResult() +} From 4ebfe6598c5bda3f0a13f9b095d1c1c7bd97765a Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 31 May 2024 14:32:38 -0400 Subject: [PATCH 07/54] Update string placeholders --- WordPress/src/main/res/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 07c6f0106470..4295974f3214 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -4911,5 +4911,7 @@ translators: %s: Select control option value e.g: "Auto, 25%". --> Elapsed Time Tap to stop Processing + Error Processing + Finished From 4f3032f8549f0969f4edb0057e0675cdfdd5a59e Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 31 May 2024 14:33:07 -0400 Subject: [PATCH 08/54] Add ErrorView, FinishedView, and update existing --- .../ui/voicetocontent/VoiceToContentUiState.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt index ec5b18d4b37f..4eb838d70741 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt @@ -15,6 +15,8 @@ sealed class VoiceToContentUiState { override val headerText: Int, val labelText: Int, val subLabelText: Int, + val requestsAvailable: Int, + val isEligibleForFeature: Boolean, val onMicTap: () -> Unit, val onCloseAction: () -> Unit, val hasPermission: Boolean, @@ -35,5 +37,19 @@ sealed class VoiceToContentUiState { val onCloseAction: () -> Unit, override val onClose: () -> Unit = onCloseAction ) : VoiceToContentUiState() + + data class Finished( + override val headerText: Int, + val content: String, // todo: this is wrong + val onCloseAction: () -> Unit, + override val onClose: () -> Unit = onCloseAction + ) : VoiceToContentUiState() + + data class Error( + override val headerText: Int, + val message: String, // todo: this is wrong + val onCloseAction: () -> Unit, + override val onClose: () -> Unit = onCloseAction + ) : VoiceToContentUiState() } From aebf427561e13b1201f7b4c8194fd621a7aa143f Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 31 May 2024 14:33:44 -0400 Subject: [PATCH 09/54] Add ErrorView and FinishedView to support the UI building --- .../ui/voicetocontent/VoiceToContentScreen.kt | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index 31de8959edd8..7df0306d2824 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -45,6 +45,8 @@ fun VoiceToContentScreen( is VoiceToContentUiState.ReadyToRecord -> ReadyToRecordView(currentState) is VoiceToContentUiState.Recording -> RecordingView(currentState) is VoiceToContentUiState.Processing -> ProcessingView(currentState) + is VoiceToContentUiState.Error -> ErrorView(currentState) + is VoiceToContentUiState.Finished -> FinishedView(currentState) } } } @@ -106,6 +108,23 @@ fun ProcessingView(state: VoiceToContentUiState.Processing) { } } +@Composable +fun ErrorView(state: VoiceToContentUiState.Error) { + Column { + Header(state.headerText, state.onClose) + Spacer(modifier = Modifier.height(16.dp)) + Text(state.message) + } +} + +@Composable +fun FinishedView(state: VoiceToContentUiState.Finished) { + Column { + Header(state.headerText, state.onClose) + Spacer(modifier = Modifier.height(16.dp)) + Text(state.content) + } +} @Composable fun Header(@StringRes headerText: Int, onClose: () -> Unit) { @@ -141,6 +160,8 @@ fun PreviewReadyToRecordView() { headerText = R.string.voice_to_content_ready_to_record, labelText = R.string.voice_to_content_ready_to_record_label, subLabelText = R.string.voice_to_content_tap_to_start, + requestsAvailable = 0, + isEligibleForFeature = true, onMicTap = {}, onCloseAction = {}, hasPermission = true, @@ -172,3 +193,27 @@ fun PreviewProcessingView() { )) } } + +@Preview(showBackground = true) +@Composable +fun PreviewErrorView() { + AppTheme { + ErrorView(VoiceToContentUiState.Error( + headerText = R.string.voice_to_content_error_label, + message = "Something bad happened and we can't continue", + onCloseAction = {} + )) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewFinishedView() { + AppTheme { + FinishedView(VoiceToContentUiState.Finished( + headerText = R.string.voice_to_content_finished_label, + content = "This is the transcribed text", + onCloseAction = {} + )) + } +} From 129a892a0f792e5dedd576f544240cc2a49d8cf9 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 31 May 2024 14:49:50 -0400 Subject: [PATCH 10/54] Observe dismiss action, refactor method names, and call vm.start --- .../ui/voicetocontent/VoiceToContentDialogFragment.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt index 6a751b11388e..b257f0ac7206 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt @@ -38,12 +38,17 @@ class VoiceToContentDialogFragment : BottomSheetDialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) observeViewModel() + viewModel.start() } private fun observeViewModel() { viewModel.requestPermission.observe(viewLifecycleOwner) { requestAllPermissionsForRecording() } + + viewModel.dismiss.observe(viewLifecycleOwner) { + dismiss() + } } private val requestMultiplePermissionsLauncher = registerForActivityResult( @@ -51,8 +56,7 @@ class VoiceToContentDialogFragment : BottomSheetDialogFragment() { ) { permissions -> val areAllPermissionsGranted = permissions.entries.all { it.value } if (areAllPermissionsGranted) { - // todo: annmarie - this is something else we want to do - viewModel.showStartRecordingView() + viewModel.onPermissionGranted() } else { // Check if any permissions were denied permanently if (permissions.entries.any { !it.value }) { From ff013f94f8c465a24e9e8387bfaf40a07fb61a8e Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 31 May 2024 14:51:32 -0400 Subject: [PATCH 11/54] Refactor: remove uiState and aiAssistantFeatureState. Add prepareVoiceToContentUseCase and transitionTo methods. Reorged methods --- .../voicetocontent/VoiceToContentViewModel.kt | 193 ++++++++++-------- 1 file changed, 104 insertions(+), 89 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index cd6b66defdf8..d028c8cd7f97 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -8,17 +8,12 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import org.wordpress.android.R -import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.model.jetpackai.JetpackAIAssistantFeature -import org.wordpress.android.fluxc.network.rest.wpcom.jetpackai.JetpackAIAssistantFeatureResponse -import org.wordpress.android.fluxc.store.jetpackai.JetpackAIStore import org.wordpress.android.modules.UI_THREAD import org.wordpress.android.ui.mysite.SelectedSiteRepository import org.wordpress.android.util.audio.IAudioRecorder @@ -36,19 +31,16 @@ class VoiceToContentViewModel @Inject constructor( private val voiceToContentFeatureUtils: VoiceToContentFeatureUtils, private val voiceToContentUseCase: VoiceToContentUseCase, private val selectedSiteRepository: SelectedSiteRepository, - private val jetpackAIStore: JetpackAIStore, private val recordingUseCase: RecordingUseCase, - private val contextProvider: ContextProvider + private val contextProvider: ContextProvider, + private val prepareVoiceToContentUseCase: PrepareVoiceToContentUseCase ) : ScopedViewModel(mainDispatcher) { - private val _uiState = MutableLiveData() - val uiState = _uiState as LiveData - - private val _aiAssistantFeatureState = MutableLiveData() - val aiAssistantFeatureState = _aiAssistantFeatureState as LiveData - private val _requestPermission = MutableLiveData() val requestPermission = _requestPermission as LiveData + private val _dismiss = MutableLiveData() + val dismiss = _dismiss as LiveData + private val _state = MutableStateFlow(VoiceToContentUiState.Initializing( headerText = R.string.voice_to_content_initializing, labelText = R.string.voice_to_content_preparing, @@ -60,58 +52,29 @@ class VoiceToContentViewModel @Inject constructor( init { observeRecordingUpdates() - // Simulate initialization delay - viewModelScope.launch { - delay(2000) - _state.value = VoiceToContentUiState.ReadyToRecord( - headerText = R.string.voice_to_content_ready_to_record, - labelText = R.string.voice_to_content_ready_to_record_label, - subLabelText = R.string.voice_to_content_tap_to_start, - onMicTap = ::onMicTap, - onCloseAction = ::onClose, - onRequestPermission = ::onRequestPermission, - hasPermission = hasAllPermissionsForRecording() - ) - } } - private fun onClose() { - // Handle close - } - - private fun onRequestPermission() { - _requestPermission.postValue(Unit) - } + fun start() { + val site = selectedSiteRepository.getSelectedSite() ?: run { + transitionToError() + return + } + if (isVoiceToContentEnabled()) { + viewModelScope.launch { + when (val result = prepareVoiceToContentUseCase.execute(site)) { + is PrepareVoiceToContentResult.Success -> { + transitionToReadyToRecord(result.model) + } - private fun onMicTap() { - _state.value = VoiceToContentUiState.Recording( - headerText = R.string.voice_to_content_recording, - elapsedTime = "0 sec", - onStopTap = ::onStopTap, - onCloseAction = ::onClose - ) - // Simulate recording time - viewModelScope.launch { - for (i in 1..60) { - delay(1000) - _state.value = (state.value as? VoiceToContentUiState.Recording)?.copy( - elapsedTime = "$i sec" - ) ?: return@launch + is PrepareVoiceToContentResult.Error -> { + transitionToError() + } + } } - _state.value = VoiceToContentUiState.Processing( - headerText = R.string.voice_to_content_processing, - onCloseAction = ::onClose - ) - // Simulate processing delay - delay(2000) - // Handle recording complete } } - private fun onStopTap() { - // Handle stop recording - } - + // Recording private fun observeRecordingUpdates() { viewModelScope.launch { recordingUseCase.recordingUpdates().collect { update -> @@ -125,11 +88,8 @@ class VoiceToContentViewModel @Inject constructor( } } - fun showStartRecordingView() { - onMicTap() - } - - fun startRecording() { + private fun startRecording() { + transitionToRecording() recordingUseCase.startRecording { audioRecorderResult -> when (audioRecorderResult) { is Success -> { @@ -137,11 +97,11 @@ class VoiceToContentViewModel @Inject constructor( file?.let { executeVoiceToContent(it) } ?: run { - _uiState.postValue(VoiceToContentResult(isError = true)) + transitionToError() } } is Error -> { - _uiState.postValue(VoiceToContentResult(isError = true)) + transitionToError() } } } @@ -156,39 +116,27 @@ class VoiceToContentViewModel @Inject constructor( return recordingFile } - fun stopRecording() { - recordingUseCase.stopRecording() + private fun stopRecording() { + transitionToProcessing() + recordingUseCase.stopRecording() } - fun executeVoiceToContent(file: File) { + // Workflow + private fun executeVoiceToContent(file: File) { val site = selectedSiteRepository.getSelectedSite() ?: run { - _uiState.postValue(VoiceToContentResult(isError = true)) + transitionToError() return } - if (isVoiceToContentEnabled()) { - viewModelScope.launch(Dispatchers.IO) { - val result = jetpackAIStore.fetchJetpackAIAssistantFeature(site) - when (result) { - is JetpackAIAssistantFeatureResponse.Success -> { - _aiAssistantFeatureState.postValue(result.model) - startVoiceToContentFlow(site, file) - } - is JetpackAIAssistantFeatureResponse.Error -> { - _uiState.postValue(VoiceToContentResult(isError = true)) - } - } - } + viewModelScope.launch { + val result = voiceToContentUseCase.execute(site, file) + transitionToFinished(result.content) } } - private fun startVoiceToContentFlow(site: SiteModel, file: File) { - if (isVoiceToContentEnabled()) { - viewModelScope.launch { - val result = voiceToContentUseCase.execute(site, file) - _uiState.postValue(result) - } - } + // Permissions + private fun onRequestPermission() { + _requestPermission.postValue(Unit) } private fun hasAllPermissionsForRecording(): Boolean { @@ -199,5 +147,72 @@ class VoiceToContentViewModel @Inject constructor( ) == PackageManager.PERMISSION_GRANTED } } + + fun onPermissionGranted() { + startRecording() + } + + // user actions + private fun onMicTap() { + startRecording() + } + + private fun onStopTap() { + stopRecording() + } + + private fun onClose() { + _dismiss.postValue(Unit) + } + + // transitions + private fun transitionToReadyToRecord(model: JetpackAIAssistantFeature) { + // todo: annmarie- put together the proper labels; especially the requests available count + _state.value = VoiceToContentUiState.ReadyToRecord( + headerText = R.string.voice_to_content_ready_to_record, + labelText = R.string.voice_to_content_ready_to_record_label, + subLabelText = R.string.voice_to_content_tap_to_start, + requestsAvailable = voiceToContentFeatureUtils.getRequestLimit(model), + isEligibleForFeature = voiceToContentFeatureUtils.isEligibleForVoiceToContent(model), + onMicTap = ::onMicTap, + onCloseAction = ::onClose, + onRequestPermission = ::onRequestPermission, + hasPermission = hasAllPermissionsForRecording() + ) + } + + private fun transitionToRecording() { + _state.value = VoiceToContentUiState.Recording( + headerText = R.string.voice_to_content_recording, + elapsedTime = "0 sec", + onStopTap = ::onStopTap, + onCloseAction = ::onClose + ) + } + + private fun transitionToProcessing() { + _state.value = VoiceToContentUiState.Processing( + headerText = R.string.voice_to_content_processing, + onCloseAction = ::onClose + ) + } + + // todo: annmarie - transition to error hasn't been fully fleshed out ... some errors will be shown on top of + // the existing screen + private fun transitionToError() { + _state.value = VoiceToContentUiState.Error( + headerText = R.string.voice_to_content_ready_to_record, + message = "Something bad happened and we can't continue", + onCloseAction = ::onClose + ) + } + // todo: annmarie - transition to finished MUST be removed, as we are pushing the user to editPostActivity + private fun transitionToFinished(content: String?) { + _state.value = VoiceToContentUiState.Finished( + headerText = R.string.voice_to_content_finished_label, + content = content ?: "", + onCloseAction = ::onClose + ) + } } From 78ad5500e959f55e41bd98d3e791459dd1e6d47e Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 3 Jun 2024 07:36:19 -0400 Subject: [PATCH 12/54] A bunch of POC commits that I will come back to later --- .idea/checkstyle-idea.xml | 28 +- .../ui/voicetocontent/MicToStopIcon.kt | 289 ++++++++++++++++++ .../ui/voicetocontent/VoiceToContentScreen.kt | 26 +- .../voicetocontent/VoiceToContentUiState.kt | 121 ++++++-- .../voicetocontent/VoiceToContentViewModel.kt | 12 +- .../main/res/drawable/v2c_green_circle.xml | 11 + WordPress/src/main/res/drawable/v2c_mic.xml | 12 + WordPress/src/main/res/drawable/v2c_stop.xml | 37 +++ .../VoiceToContentViewModelTest.kt | 140 ++++----- 9 files changed, 548 insertions(+), 128 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt create mode 100644 WordPress/src/main/res/drawable/v2c_green_circle.xml create mode 100644 WordPress/src/main/res/drawable/v2c_mic.xml create mode 100644 WordPress/src/main/res/drawable/v2c_stop.xml diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml index 7f921dc3495d..b05be3dcbb2d 100644 --- a/.idea/checkstyle-idea.xml +++ b/.idea/checkstyle-idea.xml @@ -1,18 +1,18 @@ - - + \ No newline at end of file diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt new file mode 100644 index 000000000000..f91d25e5d86d --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt @@ -0,0 +1,289 @@ +package org.wordpress.android.ui.voicetocontent + +import android.content.res.Configuration +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.with +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Devices +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import org.wordpress.android.R +import org.wordpress.android.ui.compose.theme.AppTheme + +@OptIn(ExperimentalAnimationApi::class) +@Suppress("DEPRECATION") +@Composable +fun MicToStopIcon(state: VoiceToContentUiState.ReadyToRecord) { + val isEnabled = state.isEligibleForFeature + var isTapped by remember { mutableStateOf(false) } + var isMic by remember { mutableStateOf(true) } + val isLight = !isSystemInDarkTheme() + + // For tries 1-3 +// val innerCircleColor by animateColorAsState( +// targetValue = if (isMic) MaterialTheme.colors.primary else if (isLight) Color.Black else Color.White +// ) + + // For try 4 + val circleColor by animateColorAsState( + targetValue = if (isMic) MaterialTheme.colors.primary else if (isLight) Color.Black else Color.White, label = "" + ) + + val iconColor by animateColorAsState( + targetValue = + if (isMic) Color.White else if (isLight) Color.White else Color.Black, label = "" + ) + + val micIcon: Painter = painterResource(id = R.drawable.v2c_mic) + val stopIcon: Painter = painterResource(id = R.drawable.v2c_stop) + + // Tries 1-5 + // val icon: Painter = if (isMic) painterResource(id = R.drawable.v2c_mic) else painterResource(id = R.drawable.v2c_stop) + + // First try with the box showing that is not transparent +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(100.dp) // Adjust the size as needed +// .background(MaterialTheme.colors.primary, shape = CircleShape) +// .clickable { isMic = !isMic } +// .animateContentSize() // Ensures smooth resizing if needed +// ) { +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(80.dp) // Adjust the size to make space for the inner circle +// .background(innerCircleColor, shape = CircleShape) +// ) { +// Image( +// painter = icon, +// contentDescription = null, +// modifier = Modifier.size(50.dp), // Adjust the size as needed +// colorFilter = androidx.compose.ui.graphics.ColorFilter.tint(iconColor) +// ) +// } +// } + + // Second attempt with the box being transparent +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(100.dp) // Adjust the size as needed +// .clickable { +// isMic = !isMic +// // todo myViewModel.onMicOrStopIconClicked(isMic) +// } +// .animateContentSize() // Ensures smooth resizing if needed +// ) { +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(80.dp) // Adjust the size to make space for the inner circle +// .background(MaterialTheme.colors.primary, shape = CircleShape) +// ) { +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(70.dp) // Adjust the size to make space for the inner circle +// .background(innerCircleColor, shape = CircleShape) +// ) { +// Image( +// painter = icon, +// contentDescription = null, +// modifier = Modifier.size(50.dp), // Adjust the size as needed +// colorFilter = ColorFilter.tint(iconColor) +// ) +// } +// } +// } + + // Third attempt with the box being transparent and the inner circle being animated +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(100.dp) // Adjust the size as needed +// .clickable { +// isMic = !isMic +// // myViewModel.onMicOrStopIconClicked(isMic) +// } +// ) { +// // Outer Circle +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(100.dp) +// .background(MaterialTheme.colors.primary, shape = CircleShape) +// ) { +// // Inner Circle +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(80.dp) +// .background(innerCircleColor, shape = CircleShape) +// ) { +// Image( +// painter = icon, +// contentDescription = null, +// modifier = Modifier.size(50.dp), // Adjust the size as needed +// colorFilter = ColorFilter.tint(iconColor) +// ) +// } +// } +// } + + // Four attempt +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(100.dp) // Adjust the size as needed +// .background(circleColor, shape = CircleShape) +// .clickable { +// isMic = !isMic +// // myViewModel.onMicOrStopIconClicked(isMic) +// } +// ) { +// Image( +// painter = icon, +// contentDescription = null, +// modifier = Modifier.size(50.dp), // Adjust the size as needed +// colorFilter = ColorFilter.tint(iconColor) +// ) +// } + + // Attempt five +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(100.dp) // Adjust the size as needed +// .clickable { +// isMic = !isMic +// // myViewModel.onMicOrStopIconClicked(isMic) +// } +// ) { +// Box( +// modifier = Modifier +// .size(100.dp) +// .background(circleColor, shape = CircleShape) +// .align(Alignment.Center) +// ) { +// Image( +// painter = icon, +// contentDescription = null, +// modifier = Modifier +// .size(50.dp) // Adjust the size as needed +// .align(Alignment.Center), +// colorFilter = ColorFilter.tint(iconColor) +// ) +// } +// } + +// // Attempt six +// Box( +// contentAlignment = Alignment.Center, +// modifier = Modifier +// .size(100.dp) // Adjust the size as needed +// .clickable { +// isMic = !isMic +// // myViewModel.onMicOrStopIconClicked(isMic) +// } +// ) { +// Box( +// modifier = Modifier +// .size(100.dp) +// .background(circleColor, shape = CircleShape) +// ) +// +// AnimatedContent( +// targetState = isMic, +// transitionSpec = { +// fadeIn(animationSpec = tween(300)) with fadeOut(animationSpec = tween(300)) +// }, label = "" +// ) { targetState -> +// val icon: Painter = if (targetState) painterResource(id = R.drawable.v2c_mic) else painterResource(id = R.drawable.v2c_stop) +// Image( +// painter = icon, +// contentDescription = null, +// modifier = Modifier.size(50.dp), // Adjust the size as needed +// colorFilter = ColorFilter.tint(iconColor) +// ) +// } +// } + // Attempt 7 + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .size(100.dp) + .clickable( + enabled = isEnabled && !isTapped, + onClick = { + if (isMic) { + isMic = false + isTapped = true + // todo: state.onMicTap() + } else { + // todo: nothing yet state.onMicTap + } + } + ) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(circleColor, shape = CircleShape) + ) + + AnimatedContent( + targetState = isMic, + transitionSpec = { + fadeIn(animationSpec = tween(300)) with fadeOut(animationSpec = tween(300)) + }, label = "" + ) { targetState -> + val icon: Painter = if (targetState) micIcon else stopIcon + val iconSize = if (targetState) 50.dp else 35.dp + Image( + painter = icon, + contentDescription = null, + modifier = Modifier.size(iconSize), + colorFilter = ColorFilter.tint(iconColor) + ) + } + } +} + +@Preview(showBackground = true) +@Preview(showBackground = true, device = Devices.PIXEL_4_XL) +@Preview(showBackground = true, device = Devices.PIXEL_4_XL, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +fun ExistingLayoutPreview() { + AppTheme { + MicToStopIcon(VoiceToContentUiState.ReadyToRecord( + header = R.string.voice_to_content_ready_to_record, + labelText = R.string.voice_to_content_ready_to_record_label, + subLabelText = R.string.voice_to_content_tap_to_start, + requestsAvailable = 0, + isEligibleForFeature = true, + onMicTap = {}, + onCloseAction = {}, + hasPermission = true, + onRequestPermission = {} + )) + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index 7df0306d2824..252e7b712675 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -54,7 +54,7 @@ fun VoiceToContentScreen( @Composable fun InitializingView(state: VoiceToContentUiState.Initializing) { Column { - Header(state.headerText, state.onClose) + Header(state.header, state.onClose) Spacer(modifier = Modifier.height(16.dp)) Text(stringResource(id = state.labelText)) CircularProgressIndicator() @@ -66,7 +66,7 @@ fun ReadyToRecordView( state: VoiceToContentUiState.ReadyToRecord ) { Column { - Header(state.headerText, state.onClose) + Header(state.header, state.onClose) Spacer(modifier = Modifier.height(16.dp)) Text(stringResource(id = state.labelText)) Text(stringResource(id = state.subLabelText)) @@ -81,13 +81,15 @@ fun ReadyToRecordView( ) { Icon(imageVector = Icons.Default.CheckCircle, contentDescription = null) } + Spacer(modifier = Modifier.height(16.dp)) + MicToStopIcon(state) } } @Composable fun RecordingView(state: VoiceToContentUiState.Recording) { Column { - Header(state.headerText, state.onClose) + Header(state.header, state.onClose) Spacer(modifier = Modifier.height(16.dp)) Text(state.elapsedTime) Spacer(modifier = Modifier.height(16.dp)) @@ -102,7 +104,7 @@ fun RecordingView(state: VoiceToContentUiState.Recording) { @Composable fun ProcessingView(state: VoiceToContentUiState.Processing) { Column { - Header(state.headerText, state.onClose) + Header(state.header, state.onClose) Spacer(modifier = Modifier.height(16.dp)) CircularProgressIndicator() } @@ -111,7 +113,7 @@ fun ProcessingView(state: VoiceToContentUiState.Processing) { @Composable fun ErrorView(state: VoiceToContentUiState.Error) { Column { - Header(state.headerText, state.onClose) + Header(state.header, state.onClose) Spacer(modifier = Modifier.height(16.dp)) Text(state.message) } @@ -120,7 +122,7 @@ fun ErrorView(state: VoiceToContentUiState.Error) { @Composable fun FinishedView(state: VoiceToContentUiState.Finished) { Column { - Header(state.headerText, state.onClose) + Header(state.header, state.onClose) Spacer(modifier = Modifier.height(16.dp)) Text(state.content) } @@ -145,7 +147,7 @@ fun Header(@StringRes headerText: Int, onClose: () -> Unit) { fun PreviewInitializingView() { AppTheme { InitializingView(VoiceToContentUiState.Initializing( - headerText = R.string.voice_to_content_initializing, + header = R.string.voice_to_content_initializing, labelText = R.string.voice_to_content_preparing, onCloseAction = {} )) @@ -157,7 +159,7 @@ fun PreviewInitializingView() { fun PreviewReadyToRecordView() { AppTheme { ReadyToRecordView(VoiceToContentUiState.ReadyToRecord( - headerText = R.string.voice_to_content_ready_to_record, + header = R.string.voice_to_content_ready_to_record, labelText = R.string.voice_to_content_ready_to_record_label, subLabelText = R.string.voice_to_content_tap_to_start, requestsAvailable = 0, @@ -175,7 +177,7 @@ fun PreviewReadyToRecordView() { fun PreviewRecordingView() { AppTheme { RecordingView(VoiceToContentUiState.Recording( - headerText = R.string.voice_to_content_recording, + header = R.string.voice_to_content_recording, elapsedTime = "0 sec", onStopTap = {}, onCloseAction = {} @@ -188,7 +190,7 @@ fun PreviewRecordingView() { fun PreviewProcessingView() { AppTheme { ProcessingView(VoiceToContentUiState.Processing( - headerText = R.string.voice_to_content_processing, + header = R.string.voice_to_content_processing, onCloseAction = {} )) } @@ -199,7 +201,7 @@ fun PreviewProcessingView() { fun PreviewErrorView() { AppTheme { ErrorView(VoiceToContentUiState.Error( - headerText = R.string.voice_to_content_error_label, + header = R.string.voice_to_content_error_label, message = "Something bad happened and we can't continue", onCloseAction = {} )) @@ -211,7 +213,7 @@ fun PreviewErrorView() { fun PreviewFinishedView() { AppTheme { FinishedView(VoiceToContentUiState.Finished( - headerText = R.string.voice_to_content_finished_label, + header = R.string.voice_to_content_finished_label, content = "This is the transcribed text", onCloseAction = {} )) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt index 4eb838d70741..639d893de0bd 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt @@ -1,55 +1,124 @@ package org.wordpress.android.ui.voicetocontent -sealed class VoiceToContentUiState { - abstract val headerText: Int - abstract val onClose: () -> Unit +import androidx.annotation.StringRes +sealed class VoiceToContentUiState( + @StringRes open val header: Int, + @StringRes open val subHeader: Int, + open val isSubHeaderVisible: Boolean, + open val isInitializingProgressIndicatorVisible: Boolean, + open val isRequestsAvailableVisible: Boolean, + open val requestsAvailable: Int, + open val isCountDownVisible: Boolean, + open val isMicButtonVisible: Boolean, + open val isMicButtonEnabled: Boolean, + open val isStopButtonVisible: Boolean, + open val isStopButtonEnabled: Boolean, + open val isWaveFormVisible: Boolean, + @StringRes open val status: Int, + open val isStatusVisible: Int, + + open val onClose: () -> Unit, + open val onCloseAction: () -> Unit, +) { data class Initializing( - override val headerText: Int, - val labelText: Int, - val onCloseAction: () -> Unit, + @StringRes override val header: Int, + @StringRes override val subHeader: Int, + override val onCloseAction: () -> Unit, override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState() + ) : VoiceToContentUiState(header, onCloseAction, onClose) data class ReadyToRecord( - override val headerText: Int, - val labelText: Int, - val subLabelText: Int, + @StringRes override val header: Int, + @StringRes val labelText: Int, + @StringRes val subLabelText: Int, val requestsAvailable: Int, val isEligibleForFeature: Boolean, val onMicTap: () -> Unit, - val onCloseAction: () -> Unit, + override val onCloseAction: () -> Unit, val hasPermission: Boolean, val onRequestPermission: () -> Unit, override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState() + ) : VoiceToContentUiState(header, onCloseAction, onClose) data class Recording( - override val headerText: Int, + @StringRes override val header: Int, val elapsedTime: String, val onStopTap: () -> Unit, - val onCloseAction: () -> Unit, + override val onCloseAction: () -> Unit, override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState() + ) : VoiceToContentUiState(header, onCloseAction, onClose) data class Processing( - override val headerText: Int, - val onCloseAction: () -> Unit, + @StringRes override val header: Int, + override val onCloseAction: () -> Unit, override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState() + ) : VoiceToContentUiState(header, onCloseAction, onClose) data class Finished( - override val headerText: Int, - val content: String, // todo: this is wrong - val onCloseAction: () -> Unit, + @StringRes override val header: Int, + val content: String, // Adjust as needed + override val onCloseAction: () -> Unit, override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState() + ) : VoiceToContentUiState(header, onCloseAction, onClose) data class Error( - override val headerText: Int, - val message: String, // todo: this is wrong - val onCloseAction: () -> Unit, + @StringRes override val header: Int, + val message: String, // Adjust as needed + override val onCloseAction: () -> Unit, override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState() + ) : VoiceToContentUiState(header, onCloseAction, onClose) } +//sealed class VoiceToContentUiState { +// abstract val headerText: Int +// abstract val onClose: () -> Unit +// +// data class Initializing( +// override val headerText: Int, +// val labelText: Int, +// val onCloseAction: () -> Unit, +// override val onClose: () -> Unit = onCloseAction +// ) : VoiceToContentUiState() +// +// data class ReadyToRecord( +// override val headerText: Int, +// val labelText: Int, +// val subLabelText: Int, +// val requestsAvailable: Int, +// val isEligibleForFeature: Boolean, +// val onMicTap: () -> Unit, +// val onCloseAction: () -> Unit, +// val hasPermission: Boolean, +// val onRequestPermission: () -> Unit, +// override val onClose: () -> Unit = onCloseAction +// ) : VoiceToContentUiState() +// +// data class Recording( +// override val headerText: Int, +// val elapsedTime: String, +// val onStopTap: () -> Unit, +// val onCloseAction: () -> Unit, +// override val onClose: () -> Unit = onCloseAction +// ) : VoiceToContentUiState() +// +// data class Processing( +// override val headerText: Int, +// val onCloseAction: () -> Unit, +// override val onClose: () -> Unit = onCloseAction +// ) : VoiceToContentUiState() +// +// data class Finished( +// override val headerText: Int, +// val content: String, // todo: this is wrong +// val onCloseAction: () -> Unit, +// override val onClose: () -> Unit = onCloseAction +// ) : VoiceToContentUiState() +// +// data class Error( +// override val headerText: Int, +// val message: String, // todo: this is wrong +// val onCloseAction: () -> Unit, +// override val onClose: () -> Unit = onCloseAction +// ) : VoiceToContentUiState() +//} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index d028c8cd7f97..9c54a6f0fb85 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -42,7 +42,7 @@ class VoiceToContentViewModel @Inject constructor( val dismiss = _dismiss as LiveData private val _state = MutableStateFlow(VoiceToContentUiState.Initializing( - headerText = R.string.voice_to_content_initializing, + header = R.string.voice_to_content_initializing, labelText = R.string.voice_to_content_preparing, onCloseAction = ::onClose )) @@ -169,7 +169,7 @@ class VoiceToContentViewModel @Inject constructor( private fun transitionToReadyToRecord(model: JetpackAIAssistantFeature) { // todo: annmarie- put together the proper labels; especially the requests available count _state.value = VoiceToContentUiState.ReadyToRecord( - headerText = R.string.voice_to_content_ready_to_record, + header = R.string.voice_to_content_ready_to_record, labelText = R.string.voice_to_content_ready_to_record_label, subLabelText = R.string.voice_to_content_tap_to_start, requestsAvailable = voiceToContentFeatureUtils.getRequestLimit(model), @@ -183,7 +183,7 @@ class VoiceToContentViewModel @Inject constructor( private fun transitionToRecording() { _state.value = VoiceToContentUiState.Recording( - headerText = R.string.voice_to_content_recording, + header = R.string.voice_to_content_recording, elapsedTime = "0 sec", onStopTap = ::onStopTap, onCloseAction = ::onClose @@ -192,7 +192,7 @@ class VoiceToContentViewModel @Inject constructor( private fun transitionToProcessing() { _state.value = VoiceToContentUiState.Processing( - headerText = R.string.voice_to_content_processing, + header = R.string.voice_to_content_processing, onCloseAction = ::onClose ) } @@ -201,7 +201,7 @@ class VoiceToContentViewModel @Inject constructor( // the existing screen private fun transitionToError() { _state.value = VoiceToContentUiState.Error( - headerText = R.string.voice_to_content_ready_to_record, + header = R.string.voice_to_content_ready_to_record, message = "Something bad happened and we can't continue", onCloseAction = ::onClose ) @@ -209,7 +209,7 @@ class VoiceToContentViewModel @Inject constructor( // todo: annmarie - transition to finished MUST be removed, as we are pushing the user to editPostActivity private fun transitionToFinished(content: String?) { _state.value = VoiceToContentUiState.Finished( - headerText = R.string.voice_to_content_finished_label, + header = R.string.voice_to_content_finished_label, content = content ?: "", onCloseAction = ::onClose ) diff --git a/WordPress/src/main/res/drawable/v2c_green_circle.xml b/WordPress/src/main/res/drawable/v2c_green_circle.xml new file mode 100644 index 000000000000..6385b8ca7ac7 --- /dev/null +++ b/WordPress/src/main/res/drawable/v2c_green_circle.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/WordPress/src/main/res/drawable/v2c_mic.xml b/WordPress/src/main/res/drawable/v2c_mic.xml new file mode 100644 index 000000000000..5613881bcbf2 --- /dev/null +++ b/WordPress/src/main/res/drawable/v2c_mic.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/WordPress/src/main/res/drawable/v2c_stop.xml b/WordPress/src/main/res/drawable/v2c_stop.xml new file mode 100644 index 000000000000..542532606ef9 --- /dev/null +++ b/WordPress/src/main/res/drawable/v2c_stop.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt index 6e56b26950dd..d4574af26ea1 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt @@ -57,76 +57,76 @@ class VoiceToContentViewModelTest : BaseUnitTest() { costs = null )*/ - @Before - fun setup() { - // Mock the recording updates to return a non-null flow before ViewModel instantiation - whenever(recordingUseCase.recordingUpdates()).thenReturn(createRecordingUpdateFlow()) - - viewModel = VoiceToContentViewModel( - testDispatcher(), - voiceToContentFeatureUtils, - voiceToContentUseCase, - selectedSiteRepository, - jetpackAIStore, - recordingUseCase - ) - - uiState = mutableListOf() - viewModel.uiState.observeForever { event -> - event?.let { result -> - uiState.add(result) - } - } - } - - // Helper function to create a consistent flow - private fun createRecordingUpdateFlow() = flow { - emit(RecordingUpdate(0, 0, false)) - } - - @Test - fun `when site is null, then execute posts error state `() = test { - whenever(selectedSiteRepository.getSelectedSite()).thenReturn(null) - val dummyFile = File("dummy_path") - viewModel.executeVoiceToContent(dummyFile) - - val expectedState = VoiceToContentResult(isError = true) - assertThat(uiState.first()).isEqualTo(expectedState) - } - - /* @Test - fun `when voice to content is enabled, then execute invokes use case `() = test { - val site = SiteModel().apply { id = 1 } - val dummyFile = File("dummy_path") - - whenever(selectedSiteRepository.getSelectedSite()).thenReturn(site) - whenever(voiceToContentFeatureUtils.isVoiceToContentEnabled()).thenReturn(true) - whenever(jetpackAIStore.fetchJetpackAIAssistantFeature(site)) - .thenReturn(JetpackAIAssistantFeatureResponse.Success(jetpackAIAssistantFeature)) - - viewModel.executeVoiceToContent(dummyFile) - - verify(voiceToContentUseCase).execute(site, dummyFile) - }*/ - - @Test - fun `when voice to content is disabled, then executeVoiceToContent does not invoke use case`() = runTest { - val site = SiteModel().apply { id = 1 } - whenever(selectedSiteRepository.getSelectedSite()).thenReturn(site) - whenever(voiceToContentFeatureUtils.isVoiceToContentEnabled()).thenReturn(false) - val dummyFile = File("dummy_path") - - viewModel.executeVoiceToContent(dummyFile) - - verifyNoInteractions(voiceToContentUseCase) - } - - @Test - fun `when startRecording is called, then recordingUseCase starts recording`() { - viewModel.startRecording() - - verify(recordingUseCase).startRecording(any()) - } +// @Before +// fun setup() { +// // Mock the recording updates to return a non-null flow before ViewModel instantiation +// whenever(recordingUseCase.recordingUpdates()).thenReturn(createRecordingUpdateFlow()) +// +// viewModel = VoiceToContentViewModel( +// testDispatcher(), +// voiceToContentFeatureUtils, +// voiceToContentUseCase, +// selectedSiteRepository, +// jetpackAIStore, +// recordingUseCase +// ) +// +// uiState = mutableListOf() +// viewModel.uiState.observeForever { event -> +// event?.let { result -> +// uiState.add(result) +// } +// } +// } +// +// // Helper function to create a consistent flow +// private fun createRecordingUpdateFlow() = flow { +// emit(RecordingUpdate(0, 0, false)) +// } +// +// @Test +// fun `when site is null, then execute posts error state `() = test { +// whenever(selectedSiteRepository.getSelectedSite()).thenReturn(null) +// val dummyFile = File("dummy_path") +// viewModel.executeVoiceToContent(dummyFile) +// +// val expectedState = VoiceToContentResult(isError = true) +// assertThat(uiState.first()).isEqualTo(expectedState) +// } +// +// /* @Test +// fun `when voice to content is enabled, then execute invokes use case `() = test { +// val site = SiteModel().apply { id = 1 } +// val dummyFile = File("dummy_path") +// +// whenever(selectedSiteRepository.getSelectedSite()).thenReturn(site) +// whenever(voiceToContentFeatureUtils.isVoiceToContentEnabled()).thenReturn(true) +// whenever(jetpackAIStore.fetchJetpackAIAssistantFeature(site)) +// .thenReturn(JetpackAIAssistantFeatureResponse.Success(jetpackAIAssistantFeature)) +// +// viewModel.executeVoiceToContent(dummyFile) +// +// verify(voiceToContentUseCase).execute(site, dummyFile) +// }*/ +// +//// @Test +//// fun `when voice to content is disabled, then executeVoiceToContent does not invoke use case`() = runTest { +//// val site = SiteModel().apply { id = 1 } +//// whenever(selectedSiteRepository.getSelectedSite()).thenReturn(site) +//// whenever(voiceToContentFeatureUtils.isVoiceToContentEnabled()).thenReturn(false) +//// val dummyFile = File("dummy_path") +//// +//// viewModel.executeVoiceToContent(dummyFile) +//// +//// verifyNoInteractions(voiceToContentUseCase) +//// } +// +// @Test +// fun `when startRecording is called, then recordingUseCase starts recording`() { +// viewModel.startRecording() +// +// verify(recordingUseCase).startRecording(any()) +// } } From 2780b8e14f38c27ec436e6116f98002ceb85c5e6 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 4 Jun 2024 18:41:07 +0300 Subject: [PATCH 13/54] Adds os_version parameter in feature flags and dynamic dashboard cards --- .../cards/dashboard/CardViewModelSlice.kt | 1 + .../android/util/BuildConfigWrapper.kt | 3 +++ .../android/util/config/FeatureFlagConfig.kt | 3 ++- .../dashboard/CardsViewModelSliceTest.kt | 19 +++++++++++++------ build.gradle | 2 +- .../mappings/wpcom/mobile/feature-flags.json | 3 +++ 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/CardViewModelSlice.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/CardViewModelSlice.kt index 37b39f4e2479..7e303986d344 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/CardViewModelSlice.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/CardViewModelSlice.kt @@ -153,6 +153,7 @@ class CardViewModelSlice @Inject constructor( identifier = buildConfigWrapper.getApplicationId(), marketingVersion = buildConfigWrapper.getAppVersionName(), platform = FEATURE_FLAG_PLATFORM_PARAMETER, + osVersion = buildConfigWrapper.androidVersion ) val result = cardsStore.fetchCards(payload) val error = result.error diff --git a/WordPress/src/main/java/org/wordpress/android/util/BuildConfigWrapper.kt b/WordPress/src/main/java/org/wordpress/android/util/BuildConfigWrapper.kt index b7bd6a2a1c9d..5911cf39ca0b 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/BuildConfigWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/BuildConfigWrapper.kt @@ -1,5 +1,6 @@ package org.wordpress.android.util +import android.os.Build import org.wordpress.android.BuildConfig import javax.inject.Inject @@ -33,4 +34,6 @@ class BuildConfigWrapper @Inject constructor() { val isFollowedSitesSettingsEnabled = BuildConfig.ENABLE_FOLLOWED_SITES_SETTINGS val isWhatsNewFeatureEnabled = BuildConfig.ENABLE_WHATS_NEW_FEATURE + + val androidVersion: String = Build.VERSION.RELEASE } diff --git a/WordPress/src/main/java/org/wordpress/android/util/config/FeatureFlagConfig.kt b/WordPress/src/main/java/org/wordpress/android/util/config/FeatureFlagConfig.kt index dbb843b6fb90..55992aad1cef 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/config/FeatureFlagConfig.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/config/FeatureFlagConfig.kt @@ -77,7 +77,8 @@ class FeatureFlagConfig ?: generateAndStoreUUID(), identifier = BuildConfig.APPLICATION_ID, marketingVersion = BuildConfig.VERSION_NAME, - platform = FEATURE_FLAG_PLATFORM_PARAMETER + platform = FEATURE_FLAG_PLATFORM_PARAMETER, + osVersion = android.os.Build.VERSION.RELEASE ) response.featureFlags?.let { configValues -> AppLog.e(UTILS, "Feature flag values synced") diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsViewModelSliceTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsViewModelSliceTest.kt index 90daaad5caaa..64f52cfbdea0 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsViewModelSliceTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsViewModelSliceTest.kt @@ -106,6 +106,7 @@ private const val DEVICE_ID_PARAM = "device_id_param" private const val IDENTIFIER_PARAM = "identifier_param" private const val MARKETING_VERSION_PARAM = "marketing_version_param" private const val PLATFORM_PARAM = "android" +private const val ANDROID_VERSION_PARAM = "14.0" /* MODEL */ @@ -296,7 +297,8 @@ class CardsViewModelSliceTest : BaseUnitTest() { DEVICE_ID_PARAM, IDENTIFIER_PARAM, MARKETING_VERSION_PARAM, - PLATFORM_PARAM + PLATFORM_PARAM, + ANDROID_VERSION_PARAM, ) viewModelSlice.initialize(testScope()) @@ -500,7 +502,8 @@ class CardsViewModelSliceTest : BaseUnitTest() { DEVICE_ID_PARAM, IDENTIFIER_PARAM, MARKETING_VERSION_PARAM, - PLATFORM_PARAM + PLATFORM_PARAM, + ANDROID_VERSION_PARAM, ) whenever(cardsStore.getCards(siteModel)).thenReturn(flowOf(CardsResult())) whenever(cardsStore.fetchCards(fetchCardsPayload)).thenReturn(apiError) @@ -522,7 +525,8 @@ class CardsViewModelSliceTest : BaseUnitTest() { DEVICE_ID_PARAM, IDENTIFIER_PARAM, MARKETING_VERSION_PARAM, - PLATFORM_PARAM + PLATFORM_PARAM, + ANDROID_VERSION_PARAM, ) whenever(cardsStore.getCards(siteModel)).thenReturn(flowOf(data)) whenever(cardsStore.fetchCards(fetchCardsPayload)).thenReturn(success) @@ -558,7 +562,8 @@ class CardsViewModelSliceTest : BaseUnitTest() { DEVICE_ID_PARAM, IDENTIFIER_PARAM, MARKETING_VERSION_PARAM, - PLATFORM_PARAM + PLATFORM_PARAM, + ANDROID_VERSION_PARAM, ) whenever(cardsStore.getCards(siteModel)).thenReturn(flowOf(data)) whenever(cardsStore.fetchCards(fetchCardsPayload)).thenReturn(success) @@ -581,7 +586,8 @@ class CardsViewModelSliceTest : BaseUnitTest() { DEVICE_ID_PARAM, IDENTIFIER_PARAM, MARKETING_VERSION_PARAM, - PLATFORM_PARAM + PLATFORM_PARAM, + ANDROID_VERSION_PARAM, ) whenever(cardsStore.getCards(siteModel)).thenReturn(flowOf(data)) whenever(cardsStore.fetchCards(fetchCardsPayload)).thenReturn(success) @@ -638,7 +644,8 @@ class CardsViewModelSliceTest : BaseUnitTest() { DEVICE_ID_PARAM, IDENTIFIER_PARAM, MARKETING_VERSION_PARAM, - PLATFORM_PARAM + PLATFORM_PARAM, + ANDROID_VERSION_PARAM, ) ) } diff --git a/build.gradle b/build.gradle index 07b9bdcd3e0d..d5e7a129508e 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ ext { automatticTracksVersion = '5.1.0' gutenbergMobileVersion = 'v1.120.0-alpha1' wordPressAztecVersion = 'v2.1.3' - wordPressFluxCVersion = 'trunk-8b7eeade00f33c5b4296722fb3854b3a32e06ad8' + wordPressFluxCVersion = '3028-22cf1a43db3d7070e871241bf6e7d3f944aba046' wordPressLoginVersion = '1.15.0' wordPressPersistentEditTextVersion = '1.0.2' wordPressUtilsVersion = '3.14.0' diff --git a/libs/mocks/src/main/assets/mocks/mappings/wpcom/mobile/feature-flags.json b/libs/mocks/src/main/assets/mocks/mappings/wpcom/mobile/feature-flags.json index fceb98ec7b9f..10183cd805b5 100644 --- a/libs/mocks/src/main/assets/mocks/mappings/wpcom/mobile/feature-flags.json +++ b/libs/mocks/src/main/assets/mocks/mappings/wpcom/mobile/feature-flags.json @@ -15,6 +15,9 @@ "marketing_version": { "matches": "(.*)" }, + "os_version": { + "matches": "(.*)" + }, "platform": { "matches": "android" }, From 05da5fb3d3fc72d0662535cf0636fe49b29bda12 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 6 Jun 2024 13:14:02 +0300 Subject: [PATCH 14/54] Fixes broken test --- .../android/ui/mysite/cards/dashboard/CardsViewModelSliceTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsViewModelSliceTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsViewModelSliceTest.kt index 64f52cfbdea0..a53d61c8df06 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsViewModelSliceTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsViewModelSliceTest.kt @@ -332,6 +332,7 @@ class CardsViewModelSliceTest : BaseUnitTest() { whenever(buildConfigWrapper.getAppVersionCode()).thenReturn(BUILD_NUMBER_PARAM.toInt()) whenever(buildConfigWrapper.getApplicationId()).thenReturn(IDENTIFIER_PARAM) whenever(buildConfigWrapper.getAppVersionName()).thenReturn(MARKETING_VERSION_PARAM) + whenever(buildConfigWrapper.androidVersion).thenReturn(ANDROID_VERSION_PARAM) whenever(preferenceUtilsWrapper.getFluxCPreferences()).thenReturn(sharedPreferences) whenever(sharedPreferences.getString(any(), anyOrNull())).thenReturn(DEVICE_ID_PARAM) } From d8450b699aaf40cad426f6829fe2df4d71f458f4 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 6 Jun 2024 13:14:34 +0300 Subject: [PATCH 15/54] Adds FeatureFlagsPayload parameter --- .../android/util/config/FeatureFlagConfig.kt | 17 ++++++++++------- build.gradle | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/util/config/FeatureFlagConfig.kt b/WordPress/src/main/java/org/wordpress/android/util/config/FeatureFlagConfig.kt index 55992aad1cef..0d0d08723354 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/config/FeatureFlagConfig.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/config/FeatureFlagConfig.kt @@ -6,6 +6,7 @@ import kotlinx.coroutines.launch import org.wordpress.android.BuildConfig import org.wordpress.android.analytics.AnalyticsTracker import org.wordpress.android.analytics.AnalyticsTracker.Stat +import org.wordpress.android.fluxc.network.rest.wpcom.mobile.FeatureFlagsRestClient import org.wordpress.android.fluxc.persistence.FeatureFlagConfigDao.FeatureFlag import org.wordpress.android.fluxc.store.NotificationStore.Companion.WPCOM_PUSH_DEVICE_UUID import org.wordpress.android.fluxc.store.mobile.FeatureFlagsStore @@ -72,13 +73,15 @@ class FeatureFlagConfig private suspend fun fetchRemoteFlags() { val response = featureFlagStore.fetchFeatureFlags( - buildNumber = BuildConfig.VERSION_CODE.toString(), - deviceId = preferences.getString(WPCOM_PUSH_DEVICE_UUID, null) - ?: generateAndStoreUUID(), - identifier = BuildConfig.APPLICATION_ID, - marketingVersion = BuildConfig.VERSION_NAME, - platform = FEATURE_FLAG_PLATFORM_PARAMETER, - osVersion = android.os.Build.VERSION.RELEASE + FeatureFlagsRestClient.FeatureFlagsPayload( + buildNumber = BuildConfig.VERSION_CODE.toString(), + deviceId = preferences.getString(WPCOM_PUSH_DEVICE_UUID, null) + ?: generateAndStoreUUID(), + identifier = BuildConfig.APPLICATION_ID, + marketingVersion = BuildConfig.VERSION_NAME, + platform = FEATURE_FLAG_PLATFORM_PARAMETER, + osVersion = android.os.Build.VERSION.RELEASE + ) ) response.featureFlags?.let { configValues -> AppLog.e(UTILS, "Feature flag values synced") diff --git a/build.gradle b/build.gradle index d5e7a129508e..0c4192b8252c 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ ext { automatticTracksVersion = '5.1.0' gutenbergMobileVersion = 'v1.120.0-alpha1' wordPressAztecVersion = 'v2.1.3' - wordPressFluxCVersion = '3028-22cf1a43db3d7070e871241bf6e7d3f944aba046' + wordPressFluxCVersion = '3028-eb0a976762876b228eed98b564ea77ab97659673' wordPressLoginVersion = '1.15.0' wordPressPersistentEditTextVersion = '1.0.2' wordPressUtilsVersion = '3.14.0' From 4384b1b1d95ff26b1031cba8ea296fdd82b99d7d Mon Sep 17 00:00:00 2001 From: Jarvis Lin Date: Thu, 6 Jun 2024 16:12:31 +0200 Subject: [PATCH 16/54] Fix a potential issue related to lifecycle, and rename a helper class to emphasize the implementation is related to I/O --- ...syncTaskHandler.kt => AsyncIoTaskExecutor.kt} | 16 +++++++++------- .../ui/reader/ReaderPostListFragment.java | 4 +++- .../ui/reader/adapters/ReaderPostAdapter.java | 11 ++++++++--- 3 files changed, 20 insertions(+), 11 deletions(-) rename WordPress/src/main/java/org/wordpress/android/datasets/{AsyncTaskHandler.kt => AsyncIoTaskExecutor.kt} (56%) diff --git a/WordPress/src/main/java/org/wordpress/android/datasets/AsyncTaskHandler.kt b/WordPress/src/main/java/org/wordpress/android/datasets/AsyncIoTaskExecutor.kt similarity index 56% rename from WordPress/src/main/java/org/wordpress/android/datasets/AsyncTaskHandler.kt rename to WordPress/src/main/java/org/wordpress/android/datasets/AsyncIoTaskExecutor.kt index b1bdfecde5a8..8b3bd9f15403 100644 --- a/WordPress/src/main/java/org/wordpress/android/datasets/AsyncTaskHandler.kt +++ b/WordPress/src/main/java/org/wordpress/android/datasets/AsyncIoTaskExecutor.kt @@ -6,18 +6,20 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext /** - * Helper class to handle async tasks by using coroutines + * Helper class to handle asynchronous I/O tasks using coroutines * @see Introduction */ -object AsyncTaskHandler { +object AsyncIoTaskExecutor { /** - * Load data in the background and handle the result on the main thread + * Execute a data loading task in the IO thread and handle the result on the main thread */ @JvmStatic - fun load(backgroundTask: () -> T, callback: AsyncTaskCallback) { - CoroutineScope(Dispatchers.IO).launch { + fun execute(scope: CoroutineScope, backgroundTask: () -> T, callback: IoTaskResultCallback) { + scope.launch { // handle the background task - val result = backgroundTask() + val result = withContext(Dispatchers.IO) { + backgroundTask() + } withContext(Dispatchers.Main) { // handle the result on the main thread @@ -26,7 +28,7 @@ object AsyncTaskHandler { } } - interface AsyncTaskCallback { + interface IoTaskResultCallback { fun onTaskFinished(result: T) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java index d62a859bfdeb..5702987f5286 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java @@ -153,6 +153,7 @@ import javax.inject.Inject; +import static androidx.lifecycle.LifecycleOwnerKt.getLifecycleScope; import static org.wordpress.android.fluxc.generated.AccountActionBuilder.newUpdateSubscriptionNotificationPostAction; import static org.wordpress.android.ui.reader.ReaderActivityLauncher.OpenUrlType.INTERNAL; @@ -1923,7 +1924,8 @@ private ReaderPostAdapter getPostAdapter() { mImageManager, mUiHelpers, mNetworkUtilsWrapper, - mIsTopLevel + mIsTopLevel, + getLifecycleScope(this) ); mPostAdapter.setOnFollowListener(this); mPostAdapter.setOnPostSelectedListener(this); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java index 54b22755cc1a..68975cec5bf2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java @@ -15,12 +15,13 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleCoroutineScope; import androidx.recyclerview.widget.RecyclerView; import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.analytics.AnalyticsTracker; -import org.wordpress.android.datasets.AsyncTaskHandler; +import org.wordpress.android.datasets.AsyncIoTaskExecutor; import org.wordpress.android.datasets.ReaderPostTable; import org.wordpress.android.datasets.ReaderTagTable; import org.wordpress.android.fluxc.store.AccountStore; @@ -87,6 +88,7 @@ public class ReaderPostAdapter extends RecyclerView.Adapter !ReaderTagTable.isFollowedTagName(currentTag.getTagSlug()), isAskingToFollow -> { final String slugForTracking = currentTag.getTagSlug(); @@ -688,7 +691,8 @@ public ReaderPostAdapter( ImageManager imageManager, UiHelpers uiHelpers, @NonNull final NetworkUtilsWrapper networkUtilsWrapper, - boolean isMainReader + boolean isMainReader, + LifecycleCoroutineScope scope ) { super(); ((WordPress) context.getApplicationContext()).component().inject(this); @@ -699,6 +703,7 @@ public ReaderPostAdapter( mNetworkUtilsWrapper = networkUtilsWrapper; mAvatarSzSmall = context.getResources().getDimensionPixelSize(R.dimen.avatar_sz_small); mIsMainReader = isMainReader; + mScope = scope; int displayWidth = DisplayUtils.getWindowPixelWidth(context); int cardMargin = context.getResources().getDimensionPixelSize(R.dimen.reader_card_margin); From 3c3ac5856d8e48fc01a268b004ed5e545a87d6f9 Mon Sep 17 00:00:00 2001 From: Aditi Bhatia Date: Fri, 7 Jun 2024 17:27:53 -0700 Subject: [PATCH 17/54] Add initialization check --- .../java/org/wordpress/android/ui/reader/ReaderFragment.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderFragment.kt index ec1427374780..ea9bf586f22a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderFragment.kt @@ -396,7 +396,9 @@ class ReaderFragment : Fragment(R.layout.reader_fragment_layout), ScrollableView } fun requestBookmarkTab() { - viewModel.bookmarkTabRequested() + if (::viewModel.isInitialized) { + viewModel.bookmarkTabRequested() + } } private fun showReaderInterests() { From c6b8452508fc3cf75c214ff85f0f5800ebfe92eb Mon Sep 17 00:00:00 2001 From: Aditi Bhatia Date: Fri, 7 Jun 2024 17:40:03 -0700 Subject: [PATCH 18/54] Initialize viewmodel if not --- .../java/org/wordpress/android/ui/reader/ReaderFragment.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderFragment.kt index ea9bf586f22a..033a3b56f768 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderFragment.kt @@ -396,9 +396,10 @@ class ReaderFragment : Fragment(R.layout.reader_fragment_layout), ScrollableView } fun requestBookmarkTab() { - if (::viewModel.isInitialized) { - viewModel.bookmarkTabRequested() + if (!::viewModel.isInitialized) { + viewModel = ViewModelProvider(this@ReaderFragment, viewModelFactory)[ReaderViewModel::class.java] } + viewModel.bookmarkTabRequested() } private fun showReaderInterests() { From 9b97d8b9dbded5a4fb1f7a2388430ac298faca46 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sun, 9 Jun 2024 17:22:56 -0400 Subject: [PATCH 19/54] Add amplitudes to RecordingUpdate to be passed back to caller --- .../java/org/wordpress/android/util/audio/AudioRecorder.kt | 2 ++ .../java/org/wordpress/android/util/audio/RecordingUpdate.kt | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/util/audio/AudioRecorder.kt b/WordPress/src/main/java/org/wordpress/android/util/audio/AudioRecorder.kt index 7b6f73ad6d90..283d18593793 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/audio/AudioRecorder.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/audio/AudioRecorder.kt @@ -150,10 +150,12 @@ class AudioRecorder( delay(RECORDING_UPDATE_INTERVAL) elapsedTimeInSeconds += (RECORDING_UPDATE_INTERVAL / 1000).toInt() val fileSize = File(filePath).length() + val amplitude = recorder?.maxAmplitude?.toFloat() ?: 0f _recordingUpdates.value = RecordingUpdate( elapsedTime = elapsedTimeInSeconds, fileSize = fileSize, fileSizeLimitExceeded = fileSize >= recordingStrategy.maxFileSize, + amplitudes = listOf(amplitude) ) if ( maxFileSizeExceeded(fileSize) || maxDurationExceeded(elapsedTimeInSeconds) ) { diff --git a/WordPress/src/main/java/org/wordpress/android/util/audio/RecordingUpdate.kt b/WordPress/src/main/java/org/wordpress/android/util/audio/RecordingUpdate.kt index fbd7ceabce38..f067d6cff8a4 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/audio/RecordingUpdate.kt +++ b/WordPress/src/main/java/org/wordpress/android/util/audio/RecordingUpdate.kt @@ -3,5 +3,6 @@ package org.wordpress.android.util.audio data class RecordingUpdate( val elapsedTime: Int = 0, // in seconds val fileSize: Long = 0L, // in bytes - val fileSizeLimitExceeded: Boolean = false + val fileSizeLimitExceeded: Boolean = false, + val amplitudes: List = emptyList() ) From fd307b7c757ac4d3d113d67e7119208e89df0119 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sun, 9 Jun 2024 17:23:16 -0400 Subject: [PATCH 20/54] Initial shot as waveform --- .../ui/voicetocontent/WaveformVisualizer.kt | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/WaveformVisualizer.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/WaveformVisualizer.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/WaveformVisualizer.kt new file mode 100644 index 000000000000..45ea2427a950 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/WaveformVisualizer.kt @@ -0,0 +1,149 @@ +package org.wordpress.android.ui.voicetocontent + +// import androidx.compose.animation.core.* +import androidx.compose.foundation.Canvas +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +// import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalDensity +// port androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.dp + +@Composable +fun WaveformVisualizer( + amplitudes: List, + modifier: Modifier = Modifier, + color: Color = MaterialTheme.colors.primary +) { + val spacingDp = 8.dp + val density = LocalDensity.current + val spacingPx = with(density) { spacingDp.toPx() } // 2dp spacing between bars + val strokeWidth = with(density) { 2.dp.toPx() } + + Canvas(modifier = modifier) { + val width = size.width + val height = size.height + val centerY = height / 2 + + // Calculate the number of lines that can fit within the width given the spacing + val numberOfLines = (width / spacingPx).toInt() + + // Adjust amplitudeStep to match the number of lines we can fit + val amplitudeStep = maxOf(1, amplitudes.size / numberOfLines) + + for (i in 0 until numberOfLines) { + val index = i * amplitudeStep + if (index >= amplitudes.size) break + + val x = i * spacingPx + val amplitude = amplitudes[index] + val y1 = centerY - (amplitude * height * 0.5f) + val y2 = centerY + (amplitude * height * 0.5f) + + drawLine( + color = color, + start = androidx.compose.ui.geometry.Offset(x, y1), + end = androidx.compose.ui.geometry.Offset(x, y2), + strokeWidth = strokeWidth + ) + } + } +} +// +//private fun Float.toPx(density: Density): Float { +// return with(density) { this@toPx.dp.toPx() } +//} + + + // Try three +// Canvas(modifier = modifier) { +// val width = size.width +// val height = size.height +// val centerY = height / 2 +// val stepWidth = width / (amplitudes.size.toFloat() - 1) +// +// for (i in amplitudes.indices) { +// val x = i * stepWidth +// val amplitude = amplitudes[i] +// val y1 = centerY - (amplitude * height * 0.5f) +// val y2 = centerY + (amplitude * height * 0.5f) +// +// drawLine( +// color = color, +// start = androidx.compose.ui.geometry.Offset(x, y1), +// end = androidx.compose.ui.geometry.Offset(x, y2), +// strokeWidth = 2.dp.toPx() +// ) +// } +// } + // Try two +// val infiniteTransition = rememberInfiniteTransition(label = "") +// val phase by infiniteTransition.animateFloat( +// initialValue = 0f, +// targetValue = 1f, +// animationSpec = infiniteRepeatable( +// animation = tween(durationMillis = 2000, easing = LinearEasing), +// repeatMode = RepeatMode.Restart +// ), label = "" +// ) +// +// Canvas(modifier = modifier) { +// val width = size.width +// val height = size.height +// val centerY = height / 2 +// +// // val amplitudeStep = maxOf(1, amplitudes.size / width.toInt()) +// val stepWidth = width / amplitudes.size.toFloat() +// +// for (i in amplitudes.indices) { +// // for (i in amplitudes.indices step amplitudeStep) { +// // Calculate the x-coordinate based on phase to create a scrolling effect +// val x = (i * stepWidth + phase * width) % width +// val amplitude = amplitudes[i] +// val y1 = centerY - (amplitude * height * 0.5f) +// val y2 = centerY + (amplitude * height * 0.5f) +// +// drawLine( +// color = color, +// start = androidx.compose.ui.geometry.Offset(x, y1), +// end = androidx.compose.ui.geometry.Offset(x, y2), +// strokeWidth = 2.dp.toPx() +// ) +// } + + + // Try One +// val infiniteTransition = rememberInfiniteTransition(label = "") +// val phase by infiniteTransition.animateFloat( +// initialValue = 0f, +// targetValue = 1f, +// animationSpec = infiniteRepeatable( +// animation = tween(durationMillis = 1000, easing = LinearEasing), +// repeatMode = RepeatMode.Restart +// ), label = "" +// ) +// +// Canvas(modifier = modifier) { +// val width = size.width +// val height = size.height +// val centerY = height / 2 +// val amplitudeStep = maxOf(1, amplitudes.size / width.toInt()) +// +// for (i in amplitudes.indices step amplitudeStep) { +// val x = ((i / amplitudeStep) + phase * width) % width +// val amplitude = amplitudes[i] +// val y1 = centerY - (amplitude * height * 0.5f) +// val y2 = centerY + (amplitude * height * 0.5f) +// +// drawLine( +// color = color, +// start = androidx.compose.ui.geometry.Offset(x, y1), +// end = androidx.compose.ui.geometry.Offset(x, y2), +// strokeWidth = 2.dp.toPx() +// ) +// } +// } +//} + From 79a46fbc7268deb29ca071f0b275f43f8a224928 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sun, 9 Jun 2024 17:23:42 -0400 Subject: [PATCH 21/54] Refactor: uiState, models, and views --- .../ui/voicetocontent/MicToStopIcon.kt | 264 +++------------ .../ui/voicetocontent/VoiceToContentScreen.kt | 312 +++++++++++------- .../voicetocontent/VoiceToContentUiState.kt | 162 +++------ .../voicetocontent/VoiceToContentViewModel.kt | 132 +++++--- WordPress/src/main/res/values/strings.xml | 8 + 5 files changed, 371 insertions(+), 507 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt index f91d25e5d86d..d02459df998d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt @@ -14,6 +14,7 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.ContentAlpha import androidx.compose.material.MaterialTheme import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -31,216 +32,47 @@ import org.wordpress.android.ui.compose.theme.AppTheme @OptIn(ExperimentalAnimationApi::class) @Suppress("DEPRECATION") @Composable -fun MicToStopIcon(state: VoiceToContentUiState.ReadyToRecord) { - val isEnabled = state.isEligibleForFeature - var isTapped by remember { mutableStateOf(false) } +fun MicToStopIcon(model: RecordingPanelUIModel) { + val isEnabled = model.isEnabled var isMic by remember { mutableStateOf(true) } val isLight = !isSystemInDarkTheme() - // For tries 1-3 -// val innerCircleColor by animateColorAsState( -// targetValue = if (isMic) MaterialTheme.colors.primary else if (isLight) Color.Black else Color.White -// ) - - // For try 4 val circleColor by animateColorAsState( - targetValue = if (isMic) MaterialTheme.colors.primary else if (isLight) Color.Black else Color.White, label = "" + targetValue = if (!isEnabled) MaterialTheme.colors.onSurface.copy(alpha = 0.3f) //ContentAlpha.disabled or 0.3f) + else if (isMic) MaterialTheme.colors.primary + else if (isLight) Color.Black + else Color.White, label = "" ) val iconColor by animateColorAsState( - targetValue = - if (isMic) Color.White else if (isLight) Color.White else Color.Black, label = "" + targetValue = if (!isEnabled) MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) + else if (isMic) Color.White + else if (isLight) Color.White + else Color.Black, label = "" ) val micIcon: Painter = painterResource(id = R.drawable.v2c_mic) val stopIcon: Painter = painterResource(id = R.drawable.v2c_stop) - // Tries 1-5 - // val icon: Painter = if (isMic) painterResource(id = R.drawable.v2c_mic) else painterResource(id = R.drawable.v2c_stop) - - // First try with the box showing that is not transparent -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(100.dp) // Adjust the size as needed -// .background(MaterialTheme.colors.primary, shape = CircleShape) -// .clickable { isMic = !isMic } -// .animateContentSize() // Ensures smooth resizing if needed -// ) { -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(80.dp) // Adjust the size to make space for the inner circle -// .background(innerCircleColor, shape = CircleShape) -// ) { -// Image( -// painter = icon, -// contentDescription = null, -// modifier = Modifier.size(50.dp), // Adjust the size as needed -// colorFilter = androidx.compose.ui.graphics.ColorFilter.tint(iconColor) -// ) -// } -// } - - // Second attempt with the box being transparent -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(100.dp) // Adjust the size as needed -// .clickable { -// isMic = !isMic -// // todo myViewModel.onMicOrStopIconClicked(isMic) -// } -// .animateContentSize() // Ensures smooth resizing if needed -// ) { -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(80.dp) // Adjust the size to make space for the inner circle -// .background(MaterialTheme.colors.primary, shape = CircleShape) -// ) { -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(70.dp) // Adjust the size to make space for the inner circle -// .background(innerCircleColor, shape = CircleShape) -// ) { -// Image( -// painter = icon, -// contentDescription = null, -// modifier = Modifier.size(50.dp), // Adjust the size as needed -// colorFilter = ColorFilter.tint(iconColor) -// ) -// } -// } -// } - - // Third attempt with the box being transparent and the inner circle being animated -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(100.dp) // Adjust the size as needed -// .clickable { -// isMic = !isMic -// // myViewModel.onMicOrStopIconClicked(isMic) -// } -// ) { -// // Outer Circle -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(100.dp) -// .background(MaterialTheme.colors.primary, shape = CircleShape) -// ) { -// // Inner Circle -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(80.dp) -// .background(innerCircleColor, shape = CircleShape) -// ) { -// Image( -// painter = icon, -// contentDescription = null, -// modifier = Modifier.size(50.dp), // Adjust the size as needed -// colorFilter = ColorFilter.tint(iconColor) -// ) -// } -// } -// } - - // Four attempt -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(100.dp) // Adjust the size as needed -// .background(circleColor, shape = CircleShape) -// .clickable { -// isMic = !isMic -// // myViewModel.onMicOrStopIconClicked(isMic) -// } -// ) { -// Image( -// painter = icon, -// contentDescription = null, -// modifier = Modifier.size(50.dp), // Adjust the size as needed -// colorFilter = ColorFilter.tint(iconColor) -// ) -// } - - // Attempt five -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(100.dp) // Adjust the size as needed -// .clickable { -// isMic = !isMic -// // myViewModel.onMicOrStopIconClicked(isMic) -// } -// ) { -// Box( -// modifier = Modifier -// .size(100.dp) -// .background(circleColor, shape = CircleShape) -// .align(Alignment.Center) -// ) { -// Image( -// painter = icon, -// contentDescription = null, -// modifier = Modifier -// .size(50.dp) // Adjust the size as needed -// .align(Alignment.Center), -// colorFilter = ColorFilter.tint(iconColor) -// ) -// } -// } - -// // Attempt six -// Box( -// contentAlignment = Alignment.Center, -// modifier = Modifier -// .size(100.dp) // Adjust the size as needed -// .clickable { -// isMic = !isMic -// // myViewModel.onMicOrStopIconClicked(isMic) -// } -// ) { -// Box( -// modifier = Modifier -// .size(100.dp) -// .background(circleColor, shape = CircleShape) -// ) -// -// AnimatedContent( -// targetState = isMic, -// transitionSpec = { -// fadeIn(animationSpec = tween(300)) with fadeOut(animationSpec = tween(300)) -// }, label = "" -// ) { targetState -> -// val icon: Painter = if (targetState) painterResource(id = R.drawable.v2c_mic) else painterResource(id = R.drawable.v2c_stop) -// Image( -// painter = icon, -// contentDescription = null, -// modifier = Modifier.size(50.dp), // Adjust the size as needed -// colorFilter = ColorFilter.tint(iconColor) -// ) -// } -// } - // Attempt 7 Box( contentAlignment = Alignment.Center, modifier = Modifier .size(100.dp) + .background(Color.Transparent) // Ensure transparent background .clickable( - enabled = isEnabled && !isTapped, + enabled = isEnabled, onClick = { - if (isMic) { - isMic = false - isTapped = true - // todo: state.onMicTap() + if (model.hasPermission) { + if (isMic) { + model.onMicTap?.invoke() + } else { + model.onStopTap?.invoke() + } + // isMic = !isMic } else { - // todo: nothing yet state.onMicTap + model.onRequestPermission?.invoke() } + isMic = !isMic } ) ) { @@ -249,19 +81,28 @@ fun MicToStopIcon(state: VoiceToContentUiState.ReadyToRecord) { .size(100.dp) .background(circleColor, shape = CircleShape) ) - - AnimatedContent( - targetState = isMic, - transitionSpec = { - fadeIn(animationSpec = tween(300)) with fadeOut(animationSpec = tween(300)) - }, label = "" - ) { targetState -> - val icon: Painter = if (targetState) micIcon else stopIcon - val iconSize = if (targetState) 50.dp else 35.dp + if (model.hasPermission) { + AnimatedContent( + targetState = isMic, + transitionSpec = { + fadeIn(animationSpec = tween(300)) with fadeOut(animationSpec = tween(300)) + }, label = "" + ) { targetState -> + val icon: Painter = if (targetState) micIcon else stopIcon + val iconSize = if (targetState) 50.dp else 35.dp + Image( + painter = icon, + contentDescription = null, + modifier = Modifier.size(iconSize), + colorFilter = ColorFilter.tint(iconColor) + ) + } + } else { + // Display mic icon statically if permission is not granted Image( - painter = icon, + painter = micIcon, contentDescription = null, - modifier = Modifier.size(iconSize), + modifier = Modifier.size(50.dp), colorFilter = ColorFilter.tint(iconColor) ) } @@ -274,16 +115,15 @@ fun MicToStopIcon(state: VoiceToContentUiState.ReadyToRecord) { @Composable fun ExistingLayoutPreview() { AppTheme { - MicToStopIcon(VoiceToContentUiState.ReadyToRecord( - header = R.string.voice_to_content_ready_to_record, - labelText = R.string.voice_to_content_ready_to_record_label, - subLabelText = R.string.voice_to_content_tap_to_start, - requestsAvailable = 0, - isEligibleForFeature = true, - onMicTap = {}, - onCloseAction = {}, - hasPermission = true, - onRequestPermission = {} - )) + MicToStopIcon( + RecordingPanelUIModel( + isEligibleForFeature = true, + onMicTap = {}, + onStopTap = {}, + hasPermission = true, + onRequestPermission = {}, + actionLabel = R.string.voice_to_content_ready_to_record_label, isEnabled = false + ) + ) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index 252e7b712675..2f1b60114b4d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -1,29 +1,37 @@ package org.wordpress.android.ui.voicetocontent -import androidx.annotation.StringRes +import android.content.res.Configuration +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Call -import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.Close +import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import org.wordpress.android.R @@ -34,188 +42,248 @@ fun VoiceToContentScreen( viewModel: VoiceToContentViewModel ) { val state by viewModel.state.collectAsState() - Column( - horizontalAlignment = Alignment.CenterHorizontally, + val amplitudes by viewModel.amplitudes.observeAsState(initial = listOf()) + val configuration = LocalConfiguration.current + val screenHeight = configuration.screenHeightDp.dp + val bottomSheetHeight = screenHeight * 0.6f // Set to 60% of screen height - but how can it be dynamic? + + Surface( modifier = Modifier .fillMaxWidth() - .padding(16.dp) + .height(bottomSheetHeight), + color = MaterialTheme.colors.surface ) { - when (val currentState = state) { - is VoiceToContentUiState.Initializing -> InitializingView(currentState) - is VoiceToContentUiState.ReadyToRecord -> ReadyToRecordView(currentState) - is VoiceToContentUiState.Recording -> RecordingView(currentState) - is VoiceToContentUiState.Processing -> ProcessingView(currentState) - is VoiceToContentUiState.Error -> ErrorView(currentState) - is VoiceToContentUiState.Finished -> FinishedView(currentState) - } + VoiceToContentView(state, amplitudes) } } @Composable -fun InitializingView(state: VoiceToContentUiState.Initializing) { - Column { - Header(state.header, state.onClose) - Spacer(modifier = Modifier.height(16.dp)) - Text(stringResource(id = state.labelText)) - CircularProgressIndicator() - } -} - -@Composable -fun ReadyToRecordView( - state: VoiceToContentUiState.ReadyToRecord -) { - Column { - Header(state.header, state.onClose) - Spacer(modifier = Modifier.height(16.dp)) - Text(stringResource(id = state.labelText)) - Text(stringResource(id = state.subLabelText)) - Spacer(modifier = Modifier.height(16.dp)) - IconButton( - enabled = true, - onClick = if (state.hasPermission) { - state.onMicTap - } else { - state.onRequestPermission +fun VoiceToContentView(state: VoiceToContentUiState, amplitudes: List) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + .background(MaterialTheme.colors.surface) // Use theme-aware background color + ) { + when (state.uiStateType) { + VoiceToContentUIStateType.PROCESSING -> ProcessingView(state) + VoiceToContentUIStateType.ERROR -> ErrorView(state) + else -> { + Header(state.header) + SecondaryHeader(state.secondaryHeader) + RecordingPanel(state.recordingPanel, amplitudes) } - ) { - Icon(imageVector = Icons.Default.CheckCircle, contentDescription = null) } - Spacer(modifier = Modifier.height(16.dp)) - MicToStopIcon(state) } } @Composable -fun RecordingView(state: VoiceToContentUiState.Recording) { - Column { - Header(state.header, state.onClose) - Spacer(modifier = Modifier.height(16.dp)) - Text(state.elapsedTime) - Spacer(modifier = Modifier.height(16.dp)) - Icon(imageVector = Icons.Default.Call, contentDescription = null) +fun ProcessingView(model: VoiceToContentUiState) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxWidth() + ) { + Header(model.header) Spacer(modifier = Modifier.height(16.dp)) - IconButton(onClick = state.onStopTap, enabled = true) { - Icon(imageVector = Icons.Default.Check, contentDescription = null) + Box( + modifier = Modifier.size(100.dp) // size the progress indicator + ) { + CircularProgressIndicator( + modifier = Modifier.fillMaxSize() + ) } } } @Composable -fun ProcessingView(state: VoiceToContentUiState.Processing) { - Column { - Header(state.header, state.onClose) - Spacer(modifier = Modifier.height(16.dp)) - CircularProgressIndicator() - } -} - -@Composable -fun ErrorView(state: VoiceToContentUiState.Error) { - Column { - Header(state.header, state.onClose) - Spacer(modifier = Modifier.height(16.dp)) - Text(state.message) - } -} - -@Composable -fun FinishedView(state: VoiceToContentUiState.Finished) { - Column { - Header(state.header, state.onClose) +fun ErrorView(model: VoiceToContentUiState) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxWidth() + ) { + Header(model.header) Spacer(modifier = Modifier.height(16.dp)) - Text(state.content) + Text("Unable to use Voice to Content at the moment, please try again later") } } @Composable -fun Header(@StringRes headerText: Int, onClose: () -> Unit) { +fun Header(model: HeaderUIModel) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth() ) { - Text(text = stringResource(id = headerText), style = MaterialTheme.typography.h6) - IconButton(onClick = onClose) { + Text(text = stringResource(id = model.label), style = MaterialTheme.typography.h6) + IconButton(onClick = model.onClose) { Icon(imageVector = Icons.Default.Close, contentDescription = null) } } } -@Preview(showBackground = true) @Composable -fun PreviewInitializingView() { - AppTheme { - InitializingView(VoiceToContentUiState.Initializing( - header = R.string.voice_to_content_initializing, - labelText = R.string.voice_to_content_preparing, - onCloseAction = {} - )) +fun SecondaryHeader(model: SecondaryHeaderUIModel?) { + model?.let { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Text(text = stringResource(id = model.label), style = MaterialTheme.typography.subtitle2) + Spacer(modifier = Modifier.width(8.dp)) // Add space between text and progress + if (model.isProgressIndicatorVisible) { + Box( + modifier = Modifier.size(20.dp) // size the progress indicator + ) { + CircularProgressIndicator( + modifier = Modifier.fillMaxSize() + ) + } + } else { + Text(text = model.requestsAvailable, style = MaterialTheme.typography.subtitle2) + } + Spacer(modifier = Modifier.height(16.dp)) + } + } +} + +@Composable +fun RecordingPanel(model: RecordingPanelUIModel?, amplitudes: List) { + model?.let { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxWidth() + .background(Color.Transparent) // todo: annmarie double check if this is needed + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier.padding(8.dp) // Adjust padding as needed + ) { + if (model.isEligibleForFeature) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .fillMaxWidth() + .height(IntrinsicSize.Max) + .padding(48.dp) + ) { + WaveformVisualizer( + amplitudes = amplitudes, + modifier = Modifier + .fillMaxWidth() + .height(40.dp) + .padding(16.dp), + color = MaterialTheme.colors.primary + ) + } + } else { + Text(text = stringResource(id = model.message)) + Text(text = model.urlLink) + } + MicToStopIcon(model) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = stringResource(id = model.actionLabel), + style = MaterialTheme.typography.h6, + ) + Spacer(modifier = Modifier.height(16.dp)) + } + } } } + @Preview(showBackground = true) +@Preview(showBackground = true, device = Devices.PIXEL_4_XL, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -fun PreviewReadyToRecordView() { +fun PreviewInitializingView() { AppTheme { - ReadyToRecordView(VoiceToContentUiState.ReadyToRecord( - header = R.string.voice_to_content_ready_to_record, - labelText = R.string.voice_to_content_ready_to_record_label, - subLabelText = R.string.voice_to_content_tap_to_start, - requestsAvailable = 0, - isEligibleForFeature = true, - onMicTap = {}, - onCloseAction = {}, - hasPermission = true, - onRequestPermission = {} - )) + val state = VoiceToContentUiState( + uiStateType = VoiceToContentUIStateType.INITIALIZING, + header = HeaderUIModel(label = R.string.voice_to_content_base_header_label, onClose = { }), + secondaryHeader = SecondaryHeaderUIModel(label = R.string.voice_to_content_secondary_header_label, isProgressIndicatorVisible = true), + recordingPanel = RecordingPanelUIModel(actionLabel = R.string.voice_to_content_begin_recording_label, isEnabled = false, hasPermission = false) + ) + VoiceToContentView(state = state, amplitudes = listOf()) } } @Preview(showBackground = true) +@Preview(showBackground = true, device = Devices.PIXEL_4_XL, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -fun PreviewRecordingView() { +fun PreviewReadyToRecordView() { AppTheme { - RecordingView(VoiceToContentUiState.Recording( - header = R.string.voice_to_content_recording, - elapsedTime = "0 sec", - onStopTap = {}, - onCloseAction = {} - )) + val state = VoiceToContentUiState( + uiStateType = VoiceToContentUIStateType.READY_TO_RECORD, + header = HeaderUIModel(label = R.string.voice_to_content_ready_to_record_label, onClose = { }), + secondaryHeader = SecondaryHeaderUIModel(label = R.string.voice_to_content_secondary_header_label), + recordingPanel = RecordingPanelUIModel( + actionLabel = R.string.voice_to_content_begin_recording_label, + isEnabled = true, + onMicTap = {}, + onStopTap = {}, + onRequestPermission = {}, + isEligibleForFeature = true) + ) + VoiceToContentView(state = state, amplitudes = listOf()) } } @Preview(showBackground = true) +@Preview(showBackground = true, device = Devices.PIXEL_4_XL, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -fun PreviewProcessingView() { +fun PreviewNotEligibleToRecordView() { AppTheme { - ProcessingView(VoiceToContentUiState.Processing( - header = R.string.voice_to_content_processing, - onCloseAction = {} - )) + val state = VoiceToContentUiState( + uiStateType = VoiceToContentUIStateType.INELIGIBLE_FOR_FEATURE, + header = HeaderUIModel(label = R.string.voice_to_content_ready_to_record_label, onClose = { }), + secondaryHeader = SecondaryHeaderUIModel(label = R.string.voice_to_content_secondary_header_label), + recordingPanel = RecordingPanelUIModel( + actionLabel = R.string.voice_to_content_begin_recording_label, + isEnabled = false, + isEligibleForFeature = false, + urlLink = "https://www.wordpress.com") + ) + VoiceToContentView(state = state, amplitudes = listOf()) } } @Preview(showBackground = true) +@Preview(showBackground = true, device = Devices.PIXEL_4_XL, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -fun PreviewErrorView() { +fun PreviewRecordingView() { AppTheme { - ErrorView(VoiceToContentUiState.Error( - header = R.string.voice_to_content_error_label, - message = "Something bad happened and we can't continue", - onCloseAction = {} - )) + val state = VoiceToContentUiState( + uiStateType = VoiceToContentUIStateType.RECORDING, + header = HeaderUIModel(label = R.string.voice_to_content_recording_label, onClose = { }), + secondaryHeader = SecondaryHeaderUIModel(label = R.string.voice_to_content_secondary_header_label), + recordingPanel = RecordingPanelUIModel( + actionLabel = R.string.voice_to_content_begin_recording_label, + isEnabled = true, + hasPermission = true, + onMicTap = {}, + onStopTap = {}, + onRequestPermission = {}, + isEligibleForFeature = true) + ) + VoiceToContentView(state = state, amplitudes = listOf(1.1f, 2.2f, 3.3f, 4.4f, 2.2f, 3.3f, 1.1f, 2.2f, 3.3f, 4.4f, 2.2f, 3.3f, 1.1f, 2.2f, 3.3f, 4.4f, 2.2f, 3.3f)) } } @Preview(showBackground = true) +@Preview(showBackground = true, device = Devices.PIXEL_4_XL, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -fun PreviewFinishedView() { +fun PreviewProcessingView() { AppTheme { - FinishedView(VoiceToContentUiState.Finished( - header = R.string.voice_to_content_finished_label, - content = "This is the transcribed text", - onCloseAction = {} - )) + val state = VoiceToContentUiState( + uiStateType = VoiceToContentUIStateType.PROCESSING, + header = HeaderUIModel(label = R.string.voice_to_content_processing_label, onClose = { }) + ) + VoiceToContentView(state = state, amplitudes = listOf()) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt index 639d893de0bd..2250cccf2508 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt @@ -1,124 +1,48 @@ package org.wordpress.android.ui.voicetocontent import androidx.annotation.StringRes - -sealed class VoiceToContentUiState( - @StringRes open val header: Int, - @StringRes open val subHeader: Int, - open val isSubHeaderVisible: Boolean, - open val isInitializingProgressIndicatorVisible: Boolean, - open val isRequestsAvailableVisible: Boolean, - open val requestsAvailable: Int, - open val isCountDownVisible: Boolean, - open val isMicButtonVisible: Boolean, - open val isMicButtonEnabled: Boolean, - open val isStopButtonVisible: Boolean, - open val isStopButtonEnabled: Boolean, - open val isWaveFormVisible: Boolean, - @StringRes open val status: Int, - open val isStatusVisible: Int, - - open val onClose: () -> Unit, - open val onCloseAction: () -> Unit, -) { - data class Initializing( - @StringRes override val header: Int, - @StringRes override val subHeader: Int, - override val onCloseAction: () -> Unit, - override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState(header, onCloseAction, onClose) - - data class ReadyToRecord( - @StringRes override val header: Int, - @StringRes val labelText: Int, - @StringRes val subLabelText: Int, - val requestsAvailable: Int, - val isEligibleForFeature: Boolean, - val onMicTap: () -> Unit, - override val onCloseAction: () -> Unit, - val hasPermission: Boolean, - val onRequestPermission: () -> Unit, - override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState(header, onCloseAction, onClose) - - data class Recording( - @StringRes override val header: Int, - val elapsedTime: String, - val onStopTap: () -> Unit, - override val onCloseAction: () -> Unit, - override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState(header, onCloseAction, onClose) - - data class Processing( - @StringRes override val header: Int, - override val onCloseAction: () -> Unit, - override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState(header, onCloseAction, onClose) - - data class Finished( - @StringRes override val header: Int, - val content: String, // Adjust as needed - override val onCloseAction: () -> Unit, - override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState(header, onCloseAction, onClose) - - data class Error( - @StringRes override val header: Int, - val message: String, // Adjust as needed - override val onCloseAction: () -> Unit, - override val onClose: () -> Unit = onCloseAction - ) : VoiceToContentUiState(header, onCloseAction, onClose) +import org.wordpress.android.R + +data class HeaderUIModel ( + @StringRes val label: Int, + val onClose: () -> Unit, +) + +data class SecondaryHeaderUIModel( + @StringRes val label: Int, + val isLabelVisible: Boolean = true, + val isProgressIndicatorVisible: Boolean = false, + val requestsAvailable: String = "0", + val timeElapsed: String = "00:00:00", + val isTimeElapsedVisible: Boolean = false +) + +data class RecordingPanelUIModel( + val onMicTap: (() -> Unit)? = null, + val onStopTap: (() -> Unit)? = null, + val isEligibleForFeature: Boolean = false, + val hasPermission: Boolean = false, + val onRequestPermission: (() -> Unit)? = null, + val isRecordEnabled: Boolean = false, + val isEnabled: Boolean = false, + @StringRes val message: Int = R.string.voice_to_content_not_eligible_for_feature, + val urlLink: String = "", + val onLinkTap: ((String) -> Unit)? = null, + @StringRes val actionLabel: Int +) + +enum class VoiceToContentUIStateType(val trackingName: String) { + INITIALIZING("initializing"), + READY_TO_RECORD("ready_to_record"), + INELIGIBLE_FOR_FEATURE("ineligible_for_feature"), + RECORDING("recording"), + PROCESSING("processing"), + ERROR("error") } -//sealed class VoiceToContentUiState { -// abstract val headerText: Int -// abstract val onClose: () -> Unit -// -// data class Initializing( -// override val headerText: Int, -// val labelText: Int, -// val onCloseAction: () -> Unit, -// override val onClose: () -> Unit = onCloseAction -// ) : VoiceToContentUiState() -// -// data class ReadyToRecord( -// override val headerText: Int, -// val labelText: Int, -// val subLabelText: Int, -// val requestsAvailable: Int, -// val isEligibleForFeature: Boolean, -// val onMicTap: () -> Unit, -// val onCloseAction: () -> Unit, -// val hasPermission: Boolean, -// val onRequestPermission: () -> Unit, -// override val onClose: () -> Unit = onCloseAction -// ) : VoiceToContentUiState() -// -// data class Recording( -// override val headerText: Int, -// val elapsedTime: String, -// val onStopTap: () -> Unit, -// val onCloseAction: () -> Unit, -// override val onClose: () -> Unit = onCloseAction -// ) : VoiceToContentUiState() -// -// data class Processing( -// override val headerText: Int, -// val onCloseAction: () -> Unit, -// override val onClose: () -> Unit = onCloseAction -// ) : VoiceToContentUiState() -// -// data class Finished( -// override val headerText: Int, -// val content: String, // todo: this is wrong -// val onCloseAction: () -> Unit, -// override val onClose: () -> Unit = onCloseAction -// ) : VoiceToContentUiState() -// -// data class Error( -// override val headerText: Int, -// val message: String, // todo: this is wrong -// val onCloseAction: () -> Unit, -// override val onClose: () -> Unit = onCloseAction -// ) : VoiceToContentUiState() -//} +data class VoiceToContentUiState( + val uiStateType: VoiceToContentUIStateType, + val header: HeaderUIModel, + val secondaryHeader: SecondaryHeaderUIModel? = null, + val recordingPanel: RecordingPanelUIModel? = null +) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index 9c54a6f0fb85..015c5913867d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -8,6 +8,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -41,10 +42,22 @@ class VoiceToContentViewModel @Inject constructor( private val _dismiss = MutableLiveData() val dismiss = _dismiss as LiveData - private val _state = MutableStateFlow(VoiceToContentUiState.Initializing( - header = R.string.voice_to_content_initializing, - labelText = R.string.voice_to_content_preparing, - onCloseAction = ::onClose + private val _amplitudes = MutableLiveData>() + val amplitudes: LiveData> get() = _amplitudes + + private val _state = MutableStateFlow(VoiceToContentUiState( + uiStateType = VoiceToContentUIStateType.INITIALIZING, + header = HeaderUIModel( + label = R.string.voice_to_content_base_header_label, + onClose = ::onClose), + secondaryHeader = SecondaryHeaderUIModel( + label = R.string.voice_to_content_secondary_header_label, + isLabelVisible = true, + isProgressIndicatorVisible = true, + isTimeElapsedVisible = false), + recordingPanel = RecordingPanelUIModel( + actionLabel = R.string.voice_to_content_begin_recording_label, + isEnabled = false) )) val state: StateFlow = _state.asStateFlow() @@ -55,32 +68,38 @@ class VoiceToContentViewModel @Inject constructor( } fun start() { - val site = selectedSiteRepository.getSelectedSite() ?: run { - transitionToError() - return - } - if (isVoiceToContentEnabled()) { - viewModelScope.launch { - when (val result = prepareVoiceToContentUseCase.execute(site)) { - is PrepareVoiceToContentResult.Success -> { - transitionToReadyToRecord(result.model) - } + val site = selectedSiteRepository.getSelectedSite() + if (site == null || !isVoiceToContentEnabled()) return - is PrepareVoiceToContentResult.Error -> { - transitionToError() - } + viewModelScope.launch { + when (val result = prepareVoiceToContentUseCase.execute(site)) { + is PrepareVoiceToContentResult.Success -> { + if (result.model.siteRequireUpgrade) + delay(1000) // todo: annmarie remove this for debug only + transitionToReadyToRecordOrIneligibleForFeature(result.model) + } + + is PrepareVoiceToContentResult.Error -> { + transitionToError() } } } } // Recording + // todo: This doesn't work as expected + private fun updateAmplitudes(newAmplitudes: List) { + _amplitudes.value = listOf(1.1f, 2.2f, 4.4f, 3.2f, 1.1f, 2.2f, 1.0f, 3.5f) + Log.d(javaClass.simpleName, "Update amplitudes: $newAmplitudes") + } + private fun observeRecordingUpdates() { viewModelScope.launch { recordingUseCase.recordingUpdates().collect { update -> if (update.fileSizeLimitExceeded) { stopRecording() } else { + updateAmplitudes(update.amplitudes) // todo: Handle other updates if needed when UI is ready, e.g., elapsed time and file size Log.d("AudioRecorder", "Recording update: $update") } @@ -97,11 +116,11 @@ class VoiceToContentViewModel @Inject constructor( file?.let { executeVoiceToContent(it) } ?: run { - transitionToError() + transitionToError() } } is Error -> { - transitionToError() + transitionToError() } } } @@ -130,7 +149,8 @@ class VoiceToContentViewModel @Inject constructor( viewModelScope.launch { val result = voiceToContentUseCase.execute(site, file) - transitionToFinished(result.content) + Log.i(javaClass.simpleName, "***=> result is ${result.content}") + _dismiss.postValue(Unit) } } @@ -166,52 +186,56 @@ class VoiceToContentViewModel @Inject constructor( } // transitions - private fun transitionToReadyToRecord(model: JetpackAIAssistantFeature) { - // todo: annmarie- put together the proper labels; especially the requests available count - _state.value = VoiceToContentUiState.ReadyToRecord( - header = R.string.voice_to_content_ready_to_record, - labelText = R.string.voice_to_content_ready_to_record_label, - subLabelText = R.string.voice_to_content_tap_to_start, - requestsAvailable = voiceToContentFeatureUtils.getRequestLimit(model), - isEligibleForFeature = voiceToContentFeatureUtils.isEligibleForVoiceToContent(model), - onMicTap = ::onMicTap, - onCloseAction = ::onClose, - onRequestPermission = ::onRequestPermission, - hasPermission = hasAllPermissionsForRecording() + private fun transitionToReadyToRecordOrIneligibleForFeature(model: JetpackAIAssistantFeature) { + val isEligibleForFeature = voiceToContentFeatureUtils.isEligibleForVoiceToContent(model) + val requestsAvailable = voiceToContentFeatureUtils.getRequestLimit(model) + val currentState = _state.value + _state.value = currentState.copy( + uiStateType = if (isEligibleForFeature) VoiceToContentUIStateType.READY_TO_RECORD else VoiceToContentUIStateType.INELIGIBLE_FOR_FEATURE, + secondaryHeader = currentState.secondaryHeader?.copy(requestsAvailable = requestsAvailable.toString(), isProgressIndicatorVisible = false), + recordingPanel = currentState.recordingPanel?.copy( + isEnabled = isEligibleForFeature, + isEligibleForFeature = isEligibleForFeature, + onMicTap = ::onMicTap, + onRequestPermission = ::onRequestPermission, + hasPermission = hasAllPermissionsForRecording()) ) } private fun transitionToRecording() { - _state.value = VoiceToContentUiState.Recording( - header = R.string.voice_to_content_recording, - elapsedTime = "0 sec", - onStopTap = ::onStopTap, - onCloseAction = ::onClose + val currentState = _state.value + _state.value = currentState.copy( + uiStateType = VoiceToContentUIStateType.RECORDING, + header = currentState.header.copy(label = R.string.voice_to_content_recording_label), + secondaryHeader = currentState.secondaryHeader?.copy( + timeElapsed = "00:00:00", + isTimeElapsedVisible = true + ), + recordingPanel = currentState.recordingPanel?.copy( + onStopTap = ::onStopTap, + hasPermission = true, + actionLabel = R.string.voice_to_content_done_label) ) } private fun transitionToProcessing() { - _state.value = VoiceToContentUiState.Processing( - header = R.string.voice_to_content_processing, - onCloseAction = ::onClose + val currentState = _state.value + _state.value = currentState.copy( + uiStateType = VoiceToContentUIStateType.PROCESSING, + header = currentState.header.copy(label = R.string.voice_to_content_processing), + secondaryHeader = null, + recordingPanel = null ) } - // todo: annmarie - transition to error hasn't been fully fleshed out ... some errors will be shown on top of - // the existing screen + // todo: annmarie - transition to error hasn't been fully fleshed out private fun transitionToError() { - _state.value = VoiceToContentUiState.Error( - header = R.string.voice_to_content_ready_to_record, - message = "Something bad happened and we can't continue", - onCloseAction = ::onClose - ) - } - // todo: annmarie - transition to finished MUST be removed, as we are pushing the user to editPostActivity - private fun transitionToFinished(content: String?) { - _state.value = VoiceToContentUiState.Finished( - header = R.string.voice_to_content_finished_label, - content = content ?: "", - onCloseAction = ::onClose + val currentState = _state.value + _state.value = currentState.copy( + uiStateType = VoiceToContentUIStateType.ERROR, + header = currentState.header.copy( label = R.string.voice_to_content_ready_to_record), + secondaryHeader = null, + recordingPanel = null ) } } diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 4295974f3214..743a1bed51e5 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -4914,4 +4914,12 @@ translators: %s: Select control option value e.g: "Auto, 25%". --> Error Processing Finished + + Post from Audio + Requests available: + Begin Recording + Recording + Out of requests or need requests message + Done + From a8b7aaf55912a70d77466a99fead5e099cb60f51 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sun, 9 Jun 2024 17:36:10 -0400 Subject: [PATCH 22/54] Address detekt issues --- .../ui/voicetocontent/MicToStopIcon.kt | 9 +++- .../ui/voicetocontent/VoiceToContentScreen.kt | 35 ++++++++++--- .../voicetocontent/VoiceToContentViewModel.kt | 29 ++++++++--- .../VoiceToContentViewModelTest.kt | 51 +++++++------------ 4 files changed, 74 insertions(+), 50 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt index d02459df998d..f15a233edefe 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt @@ -12,11 +12,16 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.ContentAlpha import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.* +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.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index 2f1b60114b4d..e8e28477cbb9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -206,10 +206,17 @@ fun PreviewInitializingView() { val state = VoiceToContentUiState( uiStateType = VoiceToContentUIStateType.INITIALIZING, header = HeaderUIModel(label = R.string.voice_to_content_base_header_label, onClose = { }), - secondaryHeader = SecondaryHeaderUIModel(label = R.string.voice_to_content_secondary_header_label, isProgressIndicatorVisible = true), - recordingPanel = RecordingPanelUIModel(actionLabel = R.string.voice_to_content_begin_recording_label, isEnabled = false, hasPermission = false) + secondaryHeader = SecondaryHeaderUIModel( + label = R.string.voice_to_content_secondary_header_label, + isProgressIndicatorVisible = true + ), + recordingPanel = RecordingPanelUIModel( + actionLabel = R.string.voice_to_content_begin_recording_label, + isEnabled = false, + hasPermission = false + ) ) - VoiceToContentView(state = state, amplitudes = listOf()) + VoiceToContentView(state = state, amplitudes = listOf()) } } @@ -228,7 +235,8 @@ fun PreviewReadyToRecordView() { onMicTap = {}, onStopTap = {}, onRequestPermission = {}, - isEligibleForFeature = true) + isEligibleForFeature = true + ) ) VoiceToContentView(state = state, amplitudes = listOf()) } @@ -247,7 +255,8 @@ fun PreviewNotEligibleToRecordView() { actionLabel = R.string.voice_to_content_begin_recording_label, isEnabled = false, isEligibleForFeature = false, - urlLink = "https://www.wordpress.com") + urlLink = "https://www.wordpress.com" + ) ) VoiceToContentView(state = state, amplitudes = listOf()) } @@ -269,9 +278,21 @@ fun PreviewRecordingView() { onMicTap = {}, onStopTap = {}, onRequestPermission = {}, - isEligibleForFeature = true) + isEligibleForFeature = true + ) + ) + VoiceToContentView( + state = state, + amplitudes = listOf( + 1.1f, + 2.2f, + 3.3f, + 4.4f, + 2.2f, + 3.3f, + 1.1f + ) ) - VoiceToContentView(state = state, amplitudes = listOf(1.1f, 2.2f, 3.3f, 4.4f, 2.2f, 3.3f, 1.1f, 2.2f, 3.3f, 4.4f, 2.2f, 3.3f, 1.1f, 2.2f, 3.3f, 4.4f, 2.2f, 3.3f)) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index 015c5913867d..18aeab9273b8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -20,6 +20,13 @@ import org.wordpress.android.ui.mysite.SelectedSiteRepository import org.wordpress.android.util.audio.IAudioRecorder import org.wordpress.android.viewmodel.ContextProvider import org.wordpress.android.viewmodel.ScopedViewModel +import org.wordpress.android.ui.voicetocontent.VoiceToContentUIStateType.INITIALIZING +import org.wordpress.android.ui.voicetocontent.VoiceToContentUIStateType.READY_TO_RECORD +import org.wordpress.android.ui.voicetocontent.VoiceToContentUIStateType.RECORDING +import org.wordpress.android.ui.voicetocontent.VoiceToContentUIStateType.ERROR +import org.wordpress.android.ui.voicetocontent.VoiceToContentUIStateType.INELIGIBLE_FOR_FEATURE +import org.wordpress.android.ui.voicetocontent.VoiceToContentUIStateType.PROCESSING + import java.io.File import javax.inject.Inject import javax.inject.Named @@ -46,7 +53,7 @@ class VoiceToContentViewModel @Inject constructor( val amplitudes: LiveData> get() = _amplitudes private val _state = MutableStateFlow(VoiceToContentUiState( - uiStateType = VoiceToContentUIStateType.INITIALIZING, + uiStateType = INITIALIZING, header = HeaderUIModel( label = R.string.voice_to_content_base_header_label, onClose = ::onClose), @@ -67,6 +74,7 @@ class VoiceToContentViewModel @Inject constructor( observeRecordingUpdates() } + @Suppress("MagicNumber") fun start() { val site = selectedSiteRepository.getSelectedSite() if (site == null || !isVoiceToContentEnabled()) return @@ -88,8 +96,9 @@ class VoiceToContentViewModel @Inject constructor( // Recording // todo: This doesn't work as expected + @Suppress("MagicNumber") private fun updateAmplitudes(newAmplitudes: List) { - _amplitudes.value = listOf(1.1f, 2.2f, 4.4f, 3.2f, 1.1f, 2.2f, 1.0f, 3.5f) + _amplitudes.value = listOf(1.1f, 2.2f, 4.4f, 3.2f, 1.1f, 2.2f, 1.0f, 3.5f) Log.d(javaClass.simpleName, "Update amplitudes: $newAmplitudes") } @@ -191,21 +200,25 @@ class VoiceToContentViewModel @Inject constructor( val requestsAvailable = voiceToContentFeatureUtils.getRequestLimit(model) val currentState = _state.value _state.value = currentState.copy( - uiStateType = if (isEligibleForFeature) VoiceToContentUIStateType.READY_TO_RECORD else VoiceToContentUIStateType.INELIGIBLE_FOR_FEATURE, - secondaryHeader = currentState.secondaryHeader?.copy(requestsAvailable = requestsAvailable.toString(), isProgressIndicatorVisible = false), + uiStateType = if (isEligibleForFeature) READY_TO_RECORD else INELIGIBLE_FOR_FEATURE, + secondaryHeader = currentState.secondaryHeader?.copy( + requestsAvailable = requestsAvailable.toString(), + isProgressIndicatorVisible = false + ), recordingPanel = currentState.recordingPanel?.copy( isEnabled = isEligibleForFeature, isEligibleForFeature = isEligibleForFeature, onMicTap = ::onMicTap, onRequestPermission = ::onRequestPermission, - hasPermission = hasAllPermissionsForRecording()) + hasPermission = hasAllPermissionsForRecording() + ) ) } private fun transitionToRecording() { val currentState = _state.value _state.value = currentState.copy( - uiStateType = VoiceToContentUIStateType.RECORDING, + uiStateType = RECORDING, header = currentState.header.copy(label = R.string.voice_to_content_recording_label), secondaryHeader = currentState.secondaryHeader?.copy( timeElapsed = "00:00:00", @@ -221,7 +234,7 @@ class VoiceToContentViewModel @Inject constructor( private fun transitionToProcessing() { val currentState = _state.value _state.value = currentState.copy( - uiStateType = VoiceToContentUIStateType.PROCESSING, + uiStateType = PROCESSING, header = currentState.header.copy(label = R.string.voice_to_content_processing), secondaryHeader = null, recordingPanel = null @@ -232,7 +245,7 @@ class VoiceToContentViewModel @Inject constructor( private fun transitionToError() { val currentState = _state.value _state.value = currentState.copy( - uiStateType = VoiceToContentUIStateType.ERROR, + uiStateType = ERROR, header = currentState.header.copy( label = R.string.voice_to_content_ready_to_record), secondaryHeader = null, recordingPanel = null diff --git a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt index d4574af26ea1..9b44f797b362 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt @@ -1,46 +1,31 @@ package org.wordpress.android.ui.voicetocontent import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.test.runTest -import org.assertj.core.api.Assertions.assertThat -import org.junit.Before -import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner -import org.mockito.kotlin.any -import org.mockito.kotlin.verify -import org.mockito.kotlin.verifyNoInteractions -import org.mockito.kotlin.whenever import org.wordpress.android.BaseUnitTest -import org.wordpress.android.fluxc.model.SiteModel -import org.wordpress.android.fluxc.store.jetpackai.JetpackAIStore -import org.wordpress.android.ui.mysite.SelectedSiteRepository -import org.wordpress.android.util.audio.RecordingUpdate -import java.io.File @ExperimentalCoroutinesApi @RunWith(MockitoJUnitRunner::class) class VoiceToContentViewModelTest : BaseUnitTest() { - @Mock - lateinit var voiceToContentFeatureUtils: VoiceToContentFeatureUtils - - @Mock - lateinit var voiceToContentUseCase: VoiceToContentUseCase - - @Mock - lateinit var recordingUseCase: RecordingUseCase - - @Mock - lateinit var selectedSiteRepository: SelectedSiteRepository - - @Mock - lateinit var jetpackAIStore: JetpackAIStore - - private lateinit var viewModel: VoiceToContentViewModel - - private lateinit var uiState: MutableList +// @Mock +// lateinit var voiceToContentFeatureUtils: VoiceToContentFeatureUtils +// +// @Mock +// lateinit var voiceToContentUseCase: VoiceToContentUseCase +// +// @Mock +// lateinit var recordingUseCase: RecordingUseCase +// +// @Mock +// lateinit var selectedSiteRepository: SelectedSiteRepository +// +// @Mock +// lateinit var jetpackAIStore: JetpackAIStore +// +// private lateinit var viewModel: VoiceToContentViewModel +// +// private lateinit var uiState: MutableList /* private val jetpackAIAssistantFeature = JetpackAIAssistantFeature( hasFeature = true, From 72665804648e4f09ec88a26be47e87b39a0a8e9f Mon Sep 17 00:00:00 2001 From: Ajesh R Pai Date: Mon, 10 Jun 2024 12:49:39 +0530 Subject: [PATCH 23/54] + Adds: text styles for all fonts --- .../ui/voicetocontent/VoiceToContentScreen.kt | 54 ++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index e8e28477cbb9..df7df96327cc 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.ContentAlpha import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme @@ -31,9 +32,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import org.wordpress.android.R import org.wordpress.android.ui.compose.theme.AppTheme @@ -117,7 +121,7 @@ fun Header(model: HeaderUIModel) { horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth() ) { - Text(text = stringResource(id = model.label), style = MaterialTheme.typography.h6) + Text(text = stringResource(id = model.label), style = headerStyle) IconButton(onClick = model.onClose) { Icon(imageVector = Icons.Default.Close, contentDescription = null) } @@ -131,7 +135,7 @@ fun SecondaryHeader(model: SecondaryHeaderUIModel?) { verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth() ) { - Text(text = stringResource(id = model.label), style = MaterialTheme.typography.subtitle2) + Text(text = stringResource(id = model.label), style = secondaryHeaderStyle) Spacer(modifier = Modifier.width(8.dp)) // Add space between text and progress if (model.isProgressIndicatorVisible) { Box( @@ -142,7 +146,7 @@ fun SecondaryHeader(model: SecondaryHeaderUIModel?) { ) } } else { - Text(text = model.requestsAvailable, style = MaterialTheme.typography.subtitle2) + Text(text = model.requestsAvailable, style = secondaryHeaderStyle) } Spacer(modifier = Modifier.height(16.dp)) } @@ -182,14 +186,14 @@ fun RecordingPanel(model: RecordingPanelUIModel?, amplitudes: List) { ) } } else { - Text(text = stringResource(id = model.message)) - Text(text = model.urlLink) + Text(text = stringResource(id = model.message), style = errorMessageStyle) + Text(text = model.urlLink, style = errorUrlLinkCTA) } MicToStopIcon(model) Spacer(modifier = Modifier.height(16.dp)) Text( text = stringResource(id = model.actionLabel), - style = MaterialTheme.typography.h6, + style = actionLabelStyle, ) Spacer(modifier = Modifier.height(16.dp)) } @@ -296,6 +300,44 @@ fun PreviewRecordingView() { } } +private val headerStyle: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.bodyLarge.copy( + fontWeight = FontWeight.SemiBold, + fontSize = 20.sp, + color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.high) + ) + +private val secondaryHeaderStyle: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.bodySmall.copy( + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium) + ) + +private val actionLabelStyle: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.high) + ) + +private val errorMessageStyle: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.titleMedium.copy( + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.high) + ) + +private val errorUrlLinkCTA: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.titleMedium.copy( + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + color = MaterialTheme.colors.primary + ) + @Preview(showBackground = true) @Preview(showBackground = true, device = Devices.PIXEL_4_XL, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable From ab59085dc3e38f1cbcb1b4f912af041199d7d90f Mon Sep 17 00:00:00 2001 From: Ajesh R Pai Date: Mon, 10 Jun 2024 12:50:50 +0530 Subject: [PATCH 24/54] =?UTF-8?q?=E2=86=92=20Moves:=20styles=20to=20top=20?= =?UTF-8?q?of=20the=20previews?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/voicetocontent/VoiceToContentScreen.kt | 75 +++++++++---------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index df7df96327cc..98c18cecb26e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -201,6 +201,43 @@ fun RecordingPanel(model: RecordingPanelUIModel?, amplitudes: List) { } } +private val headerStyle: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.bodyLarge.copy( + fontWeight = FontWeight.SemiBold, + fontSize = 20.sp, + color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.high) + ) + +private val secondaryHeaderStyle: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.bodySmall.copy( + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium) + ) + +private val actionLabelStyle: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.high) + ) + +private val errorMessageStyle: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.titleMedium.copy( + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.high) + ) + +private val errorUrlLinkCTA: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.titleMedium.copy( + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + color = MaterialTheme.colors.primary + ) @Preview(showBackground = true) @Preview(showBackground = true, device = Devices.PIXEL_4_XL, uiMode = Configuration.UI_MODE_NIGHT_YES) @@ -300,44 +337,6 @@ fun PreviewRecordingView() { } } -private val headerStyle: TextStyle - @Composable - get() = androidx.compose.material3.MaterialTheme.typography.bodyLarge.copy( - fontWeight = FontWeight.SemiBold, - fontSize = 20.sp, - color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.high) - ) - -private val secondaryHeaderStyle: TextStyle - @Composable - get() = androidx.compose.material3.MaterialTheme.typography.bodySmall.copy( - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium) - ) - -private val actionLabelStyle: TextStyle - @Composable - get() = androidx.compose.material3.MaterialTheme.typography.bodyMedium.copy( - color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.high) - ) - -private val errorMessageStyle: TextStyle - @Composable - get() = androidx.compose.material3.MaterialTheme.typography.titleMedium.copy( - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.high) - ) - -private val errorUrlLinkCTA: TextStyle - @Composable - get() = androidx.compose.material3.MaterialTheme.typography.titleMedium.copy( - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - color = MaterialTheme.colors.primary - ) - @Preview(showBackground = true) @Preview(showBackground = true, device = Devices.PIXEL_4_XL, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable From 313882ef6efc5cdc3e6b3da06e74d6140b29c30b Mon Sep 17 00:00:00 2001 From: Ajesh R Pai Date: Mon, 10 Jun 2024 14:21:03 +0530 Subject: [PATCH 25/54] =?UTF-8?q?=E2=86=91=20Updates:=20the=20logic=20of?= =?UTF-8?q?=20actionLabelStyle=20to=20enable=20or=20disable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/voicetocontent/VoiceToContentScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index 98c18cecb26e..3d56b8209ae1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -192,8 +192,8 @@ fun RecordingPanel(model: RecordingPanelUIModel?, amplitudes: List) { MicToStopIcon(model) Spacer(modifier = Modifier.height(16.dp)) Text( - text = stringResource(id = model.actionLabel), - style = actionLabelStyle, + text = stringResource(id = it.actionLabel), + style = if(it.isEnabled) actionLabelStyle else actionLabelStyleDisabled ) Spacer(modifier = Modifier.height(16.dp)) } From a660514f2b2483049ebb92e1f0ba46f80e52e54b Mon Sep 17 00:00:00 2001 From: Ajesh R Pai Date: Mon, 10 Jun 2024 14:45:58 +0530 Subject: [PATCH 26/54] + Adds: the missing style for disabled action label --- .../android/ui/voicetocontent/VoiceToContentScreen.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index 3d56b8209ae1..95f604accd7f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -223,6 +223,12 @@ private val actionLabelStyle: TextStyle color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.high) ) +private val actionLabelStyleDisabled: TextStyle + @Composable + get() = androidx.compose.material3.MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) + ) + private val errorMessageStyle: TextStyle @Composable get() = androidx.compose.material3.MaterialTheme.typography.titleMedium.copy( From a28c33df54910b9c1824918106c52c68dccb56da Mon Sep 17 00:00:00 2001 From: Ajesh R Pai Date: Mon, 10 Jun 2024 15:36:03 +0530 Subject: [PATCH 27/54] + Adds: url message to the state --- .../wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt index 2250cccf2508..197180475233 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt @@ -26,6 +26,7 @@ data class RecordingPanelUIModel( val isRecordEnabled: Boolean = false, val isEnabled: Boolean = false, @StringRes val message: Int = R.string.voice_to_content_not_eligible_for_feature, + val urlMessage: String = "", val urlLink: String = "", val onLinkTap: ((String) -> Unit)? = null, @StringRes val actionLabel: Int From 4d1ed6ab56d4b580581fbf60db7fa07225e3f55f Mon Sep 17 00:00:00 2001 From: Ajesh R Pai Date: Mon, 10 Jun 2024 15:36:44 +0530 Subject: [PATCH 28/54] + Adds: the logic for showing upgrade to use this feature link view --- .../ui/voicetocontent/VoiceToContentScreen.kt | 86 +++++++++++++++++-- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index 95f604accd7f..6bc3b11e5105 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -1,7 +1,9 @@ package org.wordpress.android.ui.voicetocontent import android.content.res.Configuration +import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -30,7 +32,9 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight @@ -38,7 +42,10 @@ import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.constraintlayout.compose.ConstraintLayout +import androidx.constraintlayout.compose.Dimension import org.wordpress.android.R +import org.wordpress.android.ui.compose.components.buttons.Drawable import org.wordpress.android.ui.compose.theme.AppTheme @Composable @@ -76,7 +83,7 @@ fun VoiceToContentView(state: VoiceToContentUiState, amplitudes: List) { else -> { Header(state.header) SecondaryHeader(state.secondaryHeader) - RecordingPanel(state.recordingPanel, amplitudes) + RecordingPanel(state, amplitudes) } } } @@ -154,8 +161,8 @@ fun SecondaryHeader(model: SecondaryHeaderUIModel?) { } @Composable -fun RecordingPanel(model: RecordingPanelUIModel?, amplitudes: List) { - model?.let { +fun RecordingPanel(model: VoiceToContentUiState, amplitudes: List) { + model.recordingPanel?.let { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, @@ -168,7 +175,7 @@ fun RecordingPanel(model: RecordingPanelUIModel?, amplitudes: List) { verticalArrangement = Arrangement.Center, modifier = Modifier.padding(8.dp) // Adjust padding as needed ) { - if (model.isEligibleForFeature) { + if (it.isEligibleForFeature) { Box( contentAlignment = Alignment.Center, modifier = Modifier @@ -185,15 +192,14 @@ fun RecordingPanel(model: RecordingPanelUIModel?, amplitudes: List) { color = MaterialTheme.colors.primary ) } - } else { - Text(text = stringResource(id = model.message), style = errorMessageStyle) - Text(text = model.urlLink, style = errorUrlLinkCTA) + } else if (model.uiStateType == VoiceToContentUIStateType.INELIGIBLE_FOR_FEATURE) { + InEligible(model = it) } - MicToStopIcon(model) + MicToStopIcon(it) Spacer(modifier = Modifier.height(16.dp)) Text( text = stringResource(id = it.actionLabel), - style = if(it.isEnabled) actionLabelStyle else actionLabelStyleDisabled + style = if (it.isEnabled) actionLabelStyle else actionLabelStyleDisabled ) Spacer(modifier = Modifier.height(16.dp)) } @@ -201,6 +207,67 @@ fun RecordingPanel(model: RecordingPanelUIModel?, amplitudes: List) { } } +@Composable +fun InEligible( + model: RecordingPanelUIModel, + modifier: Modifier = Modifier +) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = modifier + .fillMaxWidth() + ) { + Text(text = stringResource(id = model.message), style = errorMessageStyle) + if (model.urlLink.isBlank().not()) { + ClickableTextViewWithLinkImage( + text = model.urlMessage, + drawableRight = Drawable(R.drawable.ic_external_white_24dp), + onClick = { model.onLinkTap?.invoke(model.urlLink) } + ) + } + Spacer(modifier = Modifier.height(8.dp)) + } +} + +@Composable +fun ClickableTextViewWithLinkImage( + modifier: Modifier = Modifier, + drawableRight: Drawable? = null, + text: String, + onClick: () -> Unit +) { + ConstraintLayout(modifier = modifier + .clickable { onClick.invoke() }) { + val (buttonTextRef) = createRefs() + Box(modifier = Modifier + .constrainAs(buttonTextRef) { + end.linkTo(parent.end, drawableRight?.iconSize ?: 0.dp) + width = Dimension.wrapContent + } + ) { + Text( + text = text, + style = errorUrlLinkCTA + ) + } + + drawableRight?.let { drawable -> + val (imageRight) = createRefs() + Image( + modifier = Modifier.constrainAs(imageRight) { + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + start.linkTo(buttonTextRef.end, margin = 0.dp) + }.size(16.dp), + painter = painterResource(id = drawable.resId), + colorFilter = ColorFilter.tint(MaterialTheme.colors.primary), + contentDescription = null + ) + } + } +} + + private val headerStyle: TextStyle @Composable get() = androidx.compose.material3.MaterialTheme.typography.bodyLarge.copy( @@ -302,6 +369,7 @@ fun PreviewNotEligibleToRecordView() { actionLabel = R.string.voice_to_content_begin_recording_label, isEnabled = false, isEligibleForFeature = false, + urlMessage = "Upgrade to use this feature", urlLink = "https://www.wordpress.com" ) ) From 8c92669b58bde5c3df4fec024f96bf94eb7ccb7e Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 10 Jun 2024 13:32:37 -0400 Subject: [PATCH 29/54] Add support for upgradeURL --- .../android/ui/voicetocontent/VoiceToContentScreen.kt | 6 +++--- .../android/ui/voicetocontent/VoiceToContentUiState.kt | 2 +- .../android/ui/voicetocontent/VoiceToContentViewModel.kt | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index 6bc3b11e5105..adf6d71510de 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -218,11 +218,11 @@ fun InEligible( .fillMaxWidth() ) { Text(text = stringResource(id = model.message), style = errorMessageStyle) - if (model.urlLink.isBlank().not()) { + if (model.upgradeUrl?.isNotBlank() == true) { ClickableTextViewWithLinkImage( text = model.urlMessage, drawableRight = Drawable(R.drawable.ic_external_white_24dp), - onClick = { model.onLinkTap?.invoke(model.urlLink) } + onClick = { model.onLinkTap?.invoke(model.upgradeUrl) } ) } Spacer(modifier = Modifier.height(8.dp)) @@ -370,7 +370,7 @@ fun PreviewNotEligibleToRecordView() { isEnabled = false, isEligibleForFeature = false, urlMessage = "Upgrade to use this feature", - urlLink = "https://www.wordpress.com" + upgradeUrl = "https://www.wordpress.com" ) ) VoiceToContentView(state = state, amplitudes = listOf()) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt index 197180475233..69f32a35f8f0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt @@ -27,7 +27,7 @@ data class RecordingPanelUIModel( val isEnabled: Boolean = false, @StringRes val message: Int = R.string.voice_to_content_not_eligible_for_feature, val urlMessage: String = "", - val urlLink: String = "", + val upgradeUrl: String? = null, val onLinkTap: ((String) -> Unit)? = null, @StringRes val actionLabel: Int ) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index 18aeab9273b8..80d01e625b76 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -210,7 +210,8 @@ class VoiceToContentViewModel @Inject constructor( isEligibleForFeature = isEligibleForFeature, onMicTap = ::onMicTap, onRequestPermission = ::onRequestPermission, - hasPermission = hasAllPermissionsForRecording() + hasPermission = hasAllPermissionsForRecording(), + upgradeUrl = model.upgradeUrl ) ) } From ae00938c343859e718e42a2ec6d0e09ea19c57bd Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 10 Jun 2024 13:35:28 -0400 Subject: [PATCH 30/54] Fix checkstyle comment --- .../org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt | 2 +- .../wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt index f15a233edefe..8dc02b0c02d7 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt @@ -43,7 +43,7 @@ fun MicToStopIcon(model: RecordingPanelUIModel) { val isLight = !isSystemInDarkTheme() val circleColor by animateColorAsState( - targetValue = if (!isEnabled) MaterialTheme.colors.onSurface.copy(alpha = 0.3f) //ContentAlpha.disabled or 0.3f) + targetValue = if (!isEnabled) MaterialTheme.colors.onSurface.copy(alpha = 0.3f) else if (isMic) MaterialTheme.colors.primary else if (isLight) Color.Black else Color.White, label = "" diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index adf6d71510de..e352681038ea 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -168,7 +168,7 @@ fun RecordingPanel(model: VoiceToContentUiState, amplitudes: List) { horizontalArrangement = Arrangement.Center, modifier = Modifier .fillMaxWidth() - .background(Color.Transparent) // todo: annmarie double check if this is needed + .background(Color.Transparent) ) { Column( horizontalAlignment = Alignment.CenterHorizontally, From ee5cf02d5db53a335853379381d770b55875446a Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 10 Jun 2024 14:56:17 -0400 Subject: [PATCH 31/54] Rename properties for messages related to ineligibility and upgrade --- .../android/ui/voicetocontent/VoiceToContentUiState.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt index 69f32a35f8f0..d8d23fa27a7b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentUiState.kt @@ -25,8 +25,8 @@ data class RecordingPanelUIModel( val onRequestPermission: (() -> Unit)? = null, val isRecordEnabled: Boolean = false, val isEnabled: Boolean = false, - @StringRes val message: Int = R.string.voice_to_content_not_eligible_for_feature, - val urlMessage: String = "", + @StringRes val ineligibleMessage: Int = R.string.voice_to_content_ineligible, + @StringRes val upgradeMessage: Int = R.string.voice_to_content_upgrade, val upgradeUrl: String? = null, val onLinkTap: ((String) -> Unit)? = null, @StringRes val actionLabel: Int From eaccd7e4f383ee3f151bbf3bd7f28af3c3244d5d Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 10 Jun 2024 14:57:09 -0400 Subject: [PATCH 32/54] Support renamed properties for messages related to ineligibility and upgrade --- .../ui/voicetocontent/VoiceToContentScreen.kt | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index e352681038ea..16719dc1fa29 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -168,7 +168,7 @@ fun RecordingPanel(model: VoiceToContentUiState, amplitudes: List) { horizontalArrangement = Arrangement.Center, modifier = Modifier .fillMaxWidth() - .background(Color.Transparent) + .background(Color.Transparent) ) { Column( horizontalAlignment = Alignment.CenterHorizontally, @@ -217,10 +217,10 @@ fun InEligible( modifier = modifier .fillMaxWidth() ) { - Text(text = stringResource(id = model.message), style = errorMessageStyle) + Text(text = stringResource(id = model.ineligibleMessage), style = errorMessageStyle) if (model.upgradeUrl?.isNotBlank() == true) { ClickableTextViewWithLinkImage( - text = model.urlMessage, + text = stringResource(id = model.upgradeMessage), drawableRight = Drawable(R.drawable.ic_external_white_24dp), onClick = { model.onLinkTap?.invoke(model.upgradeUrl) } ) @@ -254,11 +254,13 @@ fun ClickableTextViewWithLinkImage( drawableRight?.let { drawable -> val (imageRight) = createRefs() Image( - modifier = Modifier.constrainAs(imageRight) { - top.linkTo(parent.top) - bottom.linkTo(parent.bottom) - start.linkTo(buttonTextRef.end, margin = 0.dp) - }.size(16.dp), + modifier = Modifier + .constrainAs(imageRight) { + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + start.linkTo(buttonTextRef.end, margin = 0.dp) + } + .size(16.dp), painter = painterResource(id = drawable.resId), colorFilter = ColorFilter.tint(MaterialTheme.colors.primary), contentDescription = null @@ -369,7 +371,7 @@ fun PreviewNotEligibleToRecordView() { actionLabel = R.string.voice_to_content_begin_recording_label, isEnabled = false, isEligibleForFeature = false, - urlMessage = "Upgrade to use this feature", + upgradeMessage = R.string.voice_to_content_upgrade, upgradeUrl = "https://www.wordpress.com" ) ) From 35a99949722739f4ac0ad8f8fefd9de3d53856fb Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 10 Jun 2024 14:57:32 -0400 Subject: [PATCH 33/54] Remove delay and incorrect check --- .../android/ui/voicetocontent/VoiceToContentViewModel.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index 80d01e625b76..547a918522f9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -8,7 +8,6 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -82,8 +81,6 @@ class VoiceToContentViewModel @Inject constructor( viewModelScope.launch { when (val result = prepareVoiceToContentUseCase.execute(site)) { is PrepareVoiceToContentResult.Success -> { - if (result.model.siteRequireUpgrade) - delay(1000) // todo: annmarie remove this for debug only transitionToReadyToRecordOrIneligibleForFeature(result.model) } From 57de5392448ddbf33d9199a4baa9c1ea541da38c Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 10 Jun 2024 15:01:39 -0400 Subject: [PATCH 34/54] Refactor: clean up unused strings --- WordPress/src/main/res/values/strings.xml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/WordPress/src/main/res/values/strings.xml b/WordPress/src/main/res/values/strings.xml index 743a1bed51e5..39410fb6200b 100644 --- a/WordPress/src/main/res/values/strings.xml +++ b/WordPress/src/main/res/values/strings.xml @@ -4902,24 +4902,15 @@ translators: %s: Select control option value e.g: "Auto, 25%". --> Audio Recording Permission Required To record audio, this app needs permission to access your microphone. You have previously denied this permission. Please enable the microphone permission in the app settings to use this feature. - Initializing - Preparing - Ready to Record - Ready to Record - Tap to start - Recording - Elapsed Time - Tap to stop Processing Error Processing - Finished - Post from Audio Requests available: Begin Recording Recording - Out of requests or need requests message + You don\'t have enough requests available to create a post from audio. + Upgrade for more requests Done From e98ada2f47113926b7f8ac5a84b75ba64004e3b4 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 10 Jun 2024 15:01:49 -0400 Subject: [PATCH 35/54] Apply correct strings --- .../android/ui/voicetocontent/VoiceToContentScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt index 16719dc1fa29..e2f3fe49a760 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentScreen.kt @@ -343,7 +343,7 @@ fun PreviewReadyToRecordView() { AppTheme { val state = VoiceToContentUiState( uiStateType = VoiceToContentUIStateType.READY_TO_RECORD, - header = HeaderUIModel(label = R.string.voice_to_content_ready_to_record_label, onClose = { }), + header = HeaderUIModel(label = R.string.voice_to_content_base_header_label, onClose = { }), secondaryHeader = SecondaryHeaderUIModel(label = R.string.voice_to_content_secondary_header_label), recordingPanel = RecordingPanelUIModel( actionLabel = R.string.voice_to_content_begin_recording_label, @@ -365,7 +365,7 @@ fun PreviewNotEligibleToRecordView() { AppTheme { val state = VoiceToContentUiState( uiStateType = VoiceToContentUIStateType.INELIGIBLE_FOR_FEATURE, - header = HeaderUIModel(label = R.string.voice_to_content_ready_to_record_label, onClose = { }), + header = HeaderUIModel(label = R.string.voice_to_content_base_header_label, onClose = { }), secondaryHeader = SecondaryHeaderUIModel(label = R.string.voice_to_content_secondary_header_label), recordingPanel = RecordingPanelUIModel( actionLabel = R.string.voice_to_content_begin_recording_label, From 50221d9be4d2ac69d71d2e8337b47e66b6f9ba8a Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 10 Jun 2024 15:28:00 -0400 Subject: [PATCH 36/54] Update FluxC hash --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 58a456beb870..b5ae76401ee5 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ ext { automatticTracksVersion = '5.1.0' gutenbergMobileVersion = 'v1.120.0' wordPressAztecVersion = 'v2.1.3' - wordPressFluxCVersion = '2.83.0' + wordPressFluxCVersion = '3031-d6bce60fed96824f0d92165583467c4d0532dc15' wordPressLoginVersion = '1.15.0' wordPressPersistentEditTextVersion = '1.0.2' wordPressUtilsVersion = '3.14.0' From e5866cb9eddb3127a6a182c0a03b22279e0c6460 Mon Sep 17 00:00:00 2001 From: Jarvis Lin Date: Mon, 10 Jun 2024 21:53:33 +0200 Subject: [PATCH 37/54] Make some refactors --- .../android/datasets/AsyncIoTaskExecutor.kt | 35 ------------- .../android/datasets/AsyncTaskExecutor.kt | 51 +++++++++++++++++++ .../ui/reader/adapters/ReaderPostAdapter.java | 7 +-- 3 files changed, 55 insertions(+), 38 deletions(-) delete mode 100644 WordPress/src/main/java/org/wordpress/android/datasets/AsyncIoTaskExecutor.kt create mode 100644 WordPress/src/main/java/org/wordpress/android/datasets/AsyncTaskExecutor.kt diff --git a/WordPress/src/main/java/org/wordpress/android/datasets/AsyncIoTaskExecutor.kt b/WordPress/src/main/java/org/wordpress/android/datasets/AsyncIoTaskExecutor.kt deleted file mode 100644 index 8b3bd9f15403..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/datasets/AsyncIoTaskExecutor.kt +++ /dev/null @@ -1,35 +0,0 @@ -package org.wordpress.android.datasets - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -/** - * Helper class to handle asynchronous I/O tasks using coroutines - * @see Introduction - */ -object AsyncIoTaskExecutor { - /** - * Execute a data loading task in the IO thread and handle the result on the main thread - */ - @JvmStatic - fun execute(scope: CoroutineScope, backgroundTask: () -> T, callback: IoTaskResultCallback) { - scope.launch { - // handle the background task - val result = withContext(Dispatchers.IO) { - backgroundTask() - } - - withContext(Dispatchers.Main) { - // handle the result on the main thread - callback.onTaskFinished(result) - } - } - } - - interface IoTaskResultCallback { - fun onTaskFinished(result: T) - } -} - diff --git a/WordPress/src/main/java/org/wordpress/android/datasets/AsyncTaskExecutor.kt b/WordPress/src/main/java/org/wordpress/android/datasets/AsyncTaskExecutor.kt new file mode 100644 index 000000000000..5b63e65e5b8e --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/datasets/AsyncTaskExecutor.kt @@ -0,0 +1,51 @@ +package org.wordpress.android.datasets + +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +/** + * Helper class to handle asynchronous I/O tasks using coroutines + * @see Introduction + */ +object AsyncTaskExecutor { + /** + * Execute a data loading task in the IO thread and handle the result on the main thread + */ + @JvmStatic + fun executeIo(scope: CoroutineScope, backgroundTask: () -> T, callback: AsyncTaskCallback) { + execute(scope, Dispatchers.IO, backgroundTask, callback) + } + + /** + * Execute a data loading task in the default thread and handle the result on the main thread + */ + @JvmStatic + fun executeDefault(scope: CoroutineScope, backgroundTask: () -> T, callback: AsyncTaskCallback) { + execute(scope, Dispatchers.Default, backgroundTask, callback) + } + + private fun execute( + scope: CoroutineScope, + dispatcher: CoroutineDispatcher, + backgroundTask: () -> T, + callback: AsyncTaskCallback + ) { + scope.launch(dispatcher) { + // handle the background task + val result = backgroundTask() + + withContext(Dispatchers.Main) { + // handle the result on the main thread + callback.onTaskFinished(result) + } + } + } + + interface AsyncTaskCallback { + fun onTaskFinished(result: T) + } +} + diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java index 68975cec5bf2..6dc4ad0d99d3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java @@ -21,7 +21,7 @@ import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.analytics.AnalyticsTracker; -import org.wordpress.android.datasets.AsyncIoTaskExecutor; +import org.wordpress.android.datasets.AsyncTaskExecutor; import org.wordpress.android.datasets.ReaderPostTable; import org.wordpress.android.datasets.ReaderTagTable; import org.wordpress.android.fluxc.store.AccountStore; @@ -83,12 +83,13 @@ import kotlin.jvm.functions.Function1; import kotlin.jvm.functions.Function2; import kotlin.jvm.functions.Function3; +import kotlinx.coroutines.CoroutineScope; public class ReaderPostAdapter extends RecyclerView.Adapter { private final ImageManager mImageManager; private final UiHelpers mUiHelpers; private final NetworkUtilsWrapper mNetworkUtilsWrapper; - private final LifecycleCoroutineScope mScope; + private final CoroutineScope mScope; private ReaderTag mCurrentTag; private long mCurrentBlogId; private long mCurrentFeedId; @@ -374,7 +375,7 @@ private void toggleFollowButton( return; } - AsyncIoTaskExecutor.execute( + AsyncTaskExecutor.executeIo( mScope, () -> !ReaderTagTable.isFollowedTagName(currentTag.getTagSlug()), isAskingToFollow -> { From fac2e05944ccccd2af91f24ab5e45e5b87930098 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Mon, 10 Jun 2024 16:15:47 -0400 Subject: [PATCH 38/54] Fix references to broken strings --- .../org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt | 2 +- .../android/ui/voicetocontent/VoiceToContentViewModel.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt index 8dc02b0c02d7..92bcf59e83f1 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt @@ -127,7 +127,7 @@ fun ExistingLayoutPreview() { onStopTap = {}, hasPermission = true, onRequestPermission = {}, - actionLabel = R.string.voice_to_content_ready_to_record_label, isEnabled = false + actionLabel = R.string.voice_to_content_base_header_label, isEnabled = false ) ) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index 547a918522f9..58c55824c4e9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -244,7 +244,7 @@ class VoiceToContentViewModel @Inject constructor( val currentState = _state.value _state.value = currentState.copy( uiStateType = ERROR, - header = currentState.header.copy( label = R.string.voice_to_content_ready_to_record), + header = currentState.header.copy( label = R.string.voice_to_content_error_label), secondaryHeader = null, recordingPanel = null ) From 5dfcf983187dd0c260d009cae68c7f3a6b2659e8 Mon Sep 17 00:00:00 2001 From: Andy Valdez Date: Mon, 10 Jun 2024 16:20:34 -0400 Subject: [PATCH 39/54] Revert "Merge pull request #20854 from wordpress-mobile/andy/target-sdk-34" This reverts commit 56f06862534d75f0374792115c51a10bbfbea8b8, reversing changes made to 0e05482e0a9bc246780ecf1bffe89678e82d8ed5. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2d22e9203b4d..7241fef5a8e5 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ plugins { ext { minSdkVersion = 24 compileSdkVersion = 34 - targetSdkVersion = 34 + targetSdkVersion = 33 } ext { From a0ce8e354241c121625859a1d7dd758cdf15b2df Mon Sep 17 00:00:00 2001 From: Automattic Release Bot Date: Mon, 10 Jun 2024 21:37:11 +0000 Subject: [PATCH 40/54] Update translations --- .../src/main/res/values-en-rGB/strings.xml | 6 +- .../src/main/res/values-es-rCL/strings.xml | 2742 ++++++++--------- WordPress/src/main/res/values-gl/strings.xml | 2728 ++++++++-------- 3 files changed, 2740 insertions(+), 2736 deletions(-) diff --git a/WordPress/src/main/res/values-en-rGB/strings.xml b/WordPress/src/main/res/values-en-rGB/strings.xml index 1effaf785c97..afa094cc8bc3 100644 --- a/WordPress/src/main/res/values-en-rGB/strings.xml +++ b/WordPress/src/main/res/values-en-rGB/strings.xml @@ -1,11 +1,15 @@ + Media location + Audio Recording Permission Required + To record audio, this app needs permission to access your microphone. You have previously denied this permission. Please enable the microphone permission in the app settings to use this feature. + Tap to edit Choose colours and fonts that suit you. When you’re reading a post, tap the AA icon at the top of the screen. Tags More from %s diff --git a/WordPress/src/main/res/values-es-rCL/strings.xml b/WordPress/src/main/res/values-es-rCL/strings.xml index e345139ffe57..b2b8b402e509 100644 --- a/WordPress/src/main/res/values-es-rCL/strings.xml +++ b/WordPress/src/main/res/values-es-rCL/strings.xml @@ -33,8 +33,6 @@ Language: es_CL Incremento de suscriptores Suscriptor Suscriptor por correo electrónico - Aún no hay suscriptores por correo electrónico - Aún no hay suscriptores Suscriptores por correo electrónico Suscriptores %s: Ya suscrito @@ -42,6 +40,8 @@ Language: es_CL No se pudo eliminar el suscriptor No se pudieron recuperar los suscriptores por correo electrónico del sitio No se pudieron recuperar los suscriptores del sitio + Aún no hay suscriptores por correo electrónico + Aún no hay suscriptores No se pudo agregar al calendario No se encontró ninguna aplicación para gestionar la solicitud de agregar al calendario Suscripciones al sitio @@ -67,609 +67,609 @@ Language: es_CL La semana pasada tuviste %1$s visitas y 1 comentario La semana pasada tuviste %1$s visitas y 1 Me gusta La semana pasada tuviste %1$s visitas, 1 Me gusta y 1 comentario. - La semana pasada tuviste %1$s visitas, %2$s Me gusta y 1 comentario. - La semana pasada tuviste %1$s visitas, 1 Me gusta y %2$s comentarios. - Sitios recientes - Todos los sitios - Sitios fijos - Editar pins - Hiciste cambios en esta página desde otro dispositivo y no los has guardado. Selecciona la versión de la página que quieres conservar. Hiciste cambios en esta entrada desde otro dispositivo y no los has guardado. Selecciona la versión de la entrada que quieres conservar. + Hiciste cambios en esta página desde otro dispositivo y no los has guardado. Selecciona la versión de la página que quieres conservar. Autoguardado disponible Otro dispositivo - Dispositivo actual - La página se ha modificado en otro dispositivo. Selecciona la versión de la página que quieres conservar. La entrada se ha modificado en otro dispositivo. Selecciona la versión de la entrada que quieres conservar. + La página se ha modificado en otro dispositivo. Selecciona la versión de la página que quieres conservar. + Dispositivo actual + Todos los sitios + Editar pins + Sitios fijos + Sitios recientes + La semana pasada tuviste %1$s visitas, 1 Me gusta y %2$s comentarios. + La semana pasada tuviste %1$s visitas, %2$s Me gusta y 1 comentario. Resolver conflicto + <Experimental> Extra grande + Extra pequeña Grande Normal Pequeña - Extra pequeña - Tamaño de fuente Fuente - Esquema de color + Tamaño de fuente envía tus comentarios - <Experimental> + Esquema de color Vaciar el color seleccionado No sigues etiquetas Ya estás siguiendo esta etiqueta Preferencias de lectura Etiquetas seguidas + Elige tus colores, fuentes y tamaños. Previsualiza aquí tu selección y lee entradas con tus estilos cuando hayas terminado. + Esta es una nueva característica aún en desarrollo. Para ayudarnos a mejorarla %s. + envía tus comentarios Caramelo + Noche h4x0r OLED - Noche Sepia Suave Por defecto - envía tus comentarios - Esta es una nueva característica aún en desarrollo. Para ayudarnos a mejorarla %s. - Elige tus colores, fuentes y tamaños. Previsualiza aquí tu selección y lee entradas con tus estilos cuando hayas terminado. Preferencias de lectura Sigue una etiqueta Leer - Puedes copiar el texto de tu entrada en caso de que tu contenido se vea afectado. Copia los detalles del error para depurarlo y compartirlo con el servicio de asistencia. - El editor ha encontrado un error inesperado. - Pulsa aquí para copiar el texto de la entrada. - Pulsa aquí para copiar los detalles del error. - Copiar texto de la entrada - Copiar detalles del error - Botón para copiar el texto de la entrada Botón para copiar los detalles del error + Botón para copiar el texto de la entrada + Copiar detalles del error + Copiar texto de la entrada + Pulsa aquí para copiar los detalles del error. + Pulsa aquí para copiar el texto de la entrada. + El editor ha encontrado un error inesperado. + Puedes copiar el texto de tu entrada en caso de que tu contenido se vea afectado. Copia los detalles del error para depurarlo y compartirlo con el servicio de asistencia. Error al actualizar el contenido - Leyenda del video. %s - Leyenda del video. Vacío - Editar el video La reproducción automática puede provocar problemas de usabilidad a algunos usuarios. + Editar el video + Leyenda del video. Vacío + Leyenda del video. %s Marcar todo como leído No leído - Sitio no encontrado. Comprueba que has iniciado sesión con la cuenta correcta. + Si actualizas aquí tu avatar, nombre e información sobre ti, también se actualizarán en todos los sitios que utilicen perfiles Gravatar. + ¿Qué es Gravatar? Hecho Las actualizaciones pueden tardar algún tiempo en sincronizarse con tu perfil de Gravatar. - ¿Qué es Gravatar? - Si actualizas aquí tu avatar, nombre e información sobre ti, también se actualizarán en todos los sitios que utilicen perfiles Gravatar. Tu perfil de WordPress.com funciona con Gravatar + Sitio no encontrado. Comprueba que has iniciado sesión con la cuenta correcta. No se pueden cargar los medios para compartir. Comprueba los permisos de la aplicación\n o utiliza la biblioteca de medios. No podemos abrir las estadísticas en este momento. Por favor, inténtalo de nuevo más tarde - Registros del servidor webs - Registros de PHP - Métricas - Supervisión del sitio Utiliza <b>Descubrir</b> para encontrar sitios y etiquetas. Prueba a seleccionar <b>Suscripciones</b> para ver el contenido suscrito y gestionar tus suscripciones. Ir a suscripciones Los blogs a los que estás suscrito no han publicado nada recientemente Suscríbete a blogs en Descubrir o busca un blog que ya te guste. - No hay blogs recomendados + Supervisión del sitio + Métricas + Registros de PHP + Registros del servidor webs No hay entradas con esta etiqueta - No ha sido posible bloquear este blog - Las entradas de este blog ya no se mostrarán - No se pudo cancelar la suscripción al blog + No hay blogs recomendados No tienes autorización para acceder a este blog + No ha sido posible bloquear este blog No es posible suscribirse a este blog - Ya estás suscrito a este blog. - No se puede mostrar este blog + No se pudo cancelar la suscripción al blog + Las entradas de este blog ya no se mostrarán Elige tus intereses 1 suscriptor - %s suscriptores - %,d suscriptores - Blog suscrito - Buscar blogs suscritos - Suscrito + Ya estás suscrito a este blog. + No se puede mostrar este blog + Blog del lector + Gestionar etiquetas y blogs + Etiqueta Suscribirse + Suscrito + Buscar blogs suscritos + Blog suscrito + %,d suscriptores + %s suscriptores Bloquear este blog Editar etiquetas y blogs Blogs suscritos - Seguir etiquetas - Gestionar etiquetas y blogs - Etiqueta - Blog del lector Suscrito - %d etiquetas - 1 etiqueta - 0 etiquetas - %d blogs - 1 blog - 0 blogs - Listas + Seguir etiquetas + Seguir etiquetas + Blogs a los que suscribirse Automattic + Descubrir Me gustó + Listas Guardado Suscripciones - Descubrir - Buscar - Seguir etiquetas - Blogs a los que suscribirse - Etiquetas recomendadas + 1 blog + %d blogs + 0 blogs + 1 etiqueta + %d etiquetas + 0 etiquetas Buscar un blog + Etiquetas recomendadas Sigue una etiqueta y podrás ve las mejores publicaciones asociadas a ella. - Sin etiquetas + Buscar Suscríbete a blogs en Descubrir y verás sus últimas publicaciones aquí. O busca un blog que ya te guste. - No hay suscripciones al blog + Sin etiquetas + Filtrar por blog + Filtrar por etiqueta Suscríbete a un blog Ver las últimas entradas de los blogs a los que estás suscrito - Filtrar por etiqueta - Filtrar por blog + No hay suscripciones al blog Esperando conexión Tráfico - Trabajo sin conexión - Conexión de red restablecida - Conexión de red perdida, trabajando sin conexión - Tamaño de fuente, %1$s Tipo de archivo no admitido como archivo de medios. - No podemos abrir las páginas en este momento. Por favor, inténtalo de nuevo más tarde - Simplemente busca un dominio - Mejora a un plan - Registra o transfiere un dominio gratis durante un año con cualquier plan de pago anual. - Nunca caduca + Tamaño de fuente, %1$s + Conexión de red perdida, trabajando sin conexión + Conexión de red restablecida + Trabajo sin conexión Tu dominio gratuito de WordPress.com - Otros dominios para %s + Simplemente busca un dominio Dominio principal %s + Nunca caduca + Otros dominios para %s + Mejora a un plan + Registra o transfiere un dominio gratis durante un año con cualquier plan de pago anual. + No podemos abrir las páginas en este momento. Por favor, inténtalo de nuevo más tarde ¡Bloganuary ya está aquí! ¡Vamos! Activa las sugerencias de publicación - Bloganuary utilizará las sugerencias de publicación diarias para enviarte temas durante el mes de enero. Bloganuary usará las sugerencias diarias de publicación para enviarte temas para el mes de enero. Actualmente tienes desactivadas las sugerencias de publicación. + Bloganuary utilizará las sugerencias de publicación diarias para enviarte temas durante el mes de enero. Lee las respuestas de otros blogueros para conseguir inspiración y hacer nuevas conexiones. - Publica tu respuesta. + Bloganuary Recibe una sugerencia nueva para inspirarte cada día. + Publica tu respuesta. Únete a nuestro reto de escritura de un mes - Bloganuary Durante el mes de enero, las sugerencias para escribir en el blog provendrán de Bloganuary, nuestro reto comunitario para crear un hábito de blogueo para el nuevo año. ¡Bloganuary está a la vuelta de la esquina! - Por esta razón, te recomendamos que edites el bloque utilizando tu navegador web. - Por este motivo, te recomendamos que edites el bloque utilizando el editor web. - También puedes aplanar el contenido desagrupando el bloque. - Ir a los ajustes Cancelar - Conceder + Ir a los ajustes Has denegado de forma permanente el permiso de la cámara. Es necesario para escanear el código de barras. Actívalo en los ajustes de la aplicación + Conceder + También puedes aplanar el contenido desagrupando el bloque. + Por este motivo, te recomendamos que edites el bloque utilizando el editor web. + Por esta razón, te recomendamos que edites el bloque utilizando tu navegador web. Se necesita el permiso de la cámara para escanear el código de barras Conceder permiso de la cámara Se necesita el permiso de la cámara para escanear el código de barras. Escanear código de barras Es posible que los bloques anidados a más de %d niveles no se muestren correctamente en el editor móvil. - Vamos - Es hora de continuar tu viaje por WordPress en la aplicación Jetpack. Vaciar la búsqueda + Es hora de continuar tu viaje por WordPress en la aplicación Jetpack. + Vamos Muy alta - Introduce tu clave de seguridad para continuar. Hubo algunos problemas con el inicio de sesión de la clave de seguridad Usa una clave de seguridad + Introduce tu clave de seguridad para continuar. + No se pudieron recuperar tus dominios + Todos + De <b>Bloganuary</b> No se pudieron recuperar los dominios - %s durante el primer año + Teclea para obtener más sugerencias %s / año + %s durante el primer año + Buscar un dominio Transferir dominio ¿Quieres transferir un dominio que ya tienes? - Teclea para obtener más sugerencias - Buscar un dominio OK Algo ha ido mal al agregar el dominio al carrito. Asegúrate de que estás conectado y vuelve a intentarlo. Error - Todos - No se pudieron recuperar tus dominios Dominio del sitio - De <b>Bloganuary</b> - Editado Filtrar por autor - Bloque \'%s\' convertido a bloques + Editado Alternativamente, puedes convertir el contenido en bloques. + Bloque \'%s\' convertido a bloques + Tarjetas Agregar o eliminar atajos - Desactivar atajos - Activar atajos Atajos - Tarjetas + Activar atajos + Desactivar atajos * Dominio gratuito durante el primer año incluido en todos los planes de pago anuales. Elige el sitio Utilízalo con un sitio que ya hayas iniciado. - Sitio de WordPress.com existente - Obtener dominio - Agrega un sitio más tarde. - Solo tienes que comprar un dominio - No te preocupes, puedes agregar un sitio más adelante. - Elige cómo\nutilizar tu dominio - Elige cómo quieres utilizar tu dominio - Comprar dominio Buscar un dominio Pulsa abajo para encontrar tu dominio perfecto. No tienes dominios Comprueba que estás conectado y tira para actualizar. + Caduca el %1$s + Todos los dominios Abrir detalles del dominio - Busca en tus dominios Comprar un dominio - Todos los dominios - Caduca el %1$s + Busca en tus dominios + No te preocupes, puedes agregar un sitio más adelante. + Sitio de WordPress.com existente + Elige cómo\nutilizar tu dominio + Elige cómo quieres utilizar tu dominio + Obtener dominio + Agrega un sitio más tarde. + Solo tienes que comprar un dominio + Comprar dominio Cuenta y ajustes - Elige un plan Gratis durante el primer año con los planes de pago anuales - Guardado - Guardar + Elige un plan Puede que te guste - Desagrupar bloque - Toca aquí para mostrar más detalles. - Patrones sincronizados - Bloque profundamente anidado + Guardar + Guardado Los bloques anidados a más profundidad de %d niveles puede que no se procesen correctamente en el editor móvil. Por este motivo, recomendamos allanar el contenido desagrupando el bloque o editando el bloque usando el editor web. + Bloque profundamente anidado + Patrones sincronizados + Toca aquí para mostrar más detalles. + Desagrupar bloque El bloque no se puede procesar debido a que está profundamente anidado. Toca aquí para más detalles. Uy, vaya, algo salió mal. Por favor, inténtalo de nuevo más tarde. Ir a la web Pulsa el botón de personalización para mostrar más tarjetas. Todas las tarjetas están ocultas - Descubre cómo sacarle el máximo partido a tu sitio con la aplicación. Acciones recientes realizadas en tu sitio. - Vista general de las páginas de tu sitio. + Promociona una entrada y mira las campañas actuales. Ideas diarias para las entradas de tu blog. Sugerencias para bloguear - Promociona una entrada y mira las campañas actuales. - Tus próximas entradas programadas. - Entradas programadas Tus últimos borradores de entradas. Borradores de entradas + Descubre cómo sacarle el máximo partido a tu sitio con la aplicación. + Vista general de las páginas de tu sitio. + Tus próximas entradas programadas. + Entradas programadas Vistas, visitantes y me gusta El contenido de las tarjetas puede variar en función de lo que esté pasando con tu sitio + Cambiar ajustes + Seleccionar más + Solo estarán disponibles las fotos y videos seleccionados a los que hayas dado acceso. Agregar u ocultar tarjetas Personalizar la pestaña de inicio Pulsa para personalizar la pestaña Inicio Personaliza la pestaña Inicio - Cambiar ajustes - Seleccionar más - Solo estarán disponibles las fotos y videos seleccionados a los que hayas dado acceso. Ver todas las campañas Toda la actividad Todas las páginas - Elegir un archivo Agregar una imagen o video - Ver todas las entradas programadas + Elegir un archivo Ver todos los borradores - Ver estadísticas - Ocultar esto - Si no puedo responder a tu pregunta, te ayudaré a abrir una petición de asistencia con nuestro equipo. + Ver todas las entradas programadas Hola, soy Jetpack AI Assistant. + Si no puedo responder a tu pregunta, te ayudaré a abrir una petición de asistencia con nuestro equipo. + Ocultar esto + Ver estadísticas Accede a este bloque de Paywall en tu navegador web para realizar ajustes avanzados. Respuesta: Pregunta: Transcripción del bot móvil de Jetpack: Error al enviar la petición de asistencia - Petición creada Creando petición de asistencia… - ¿Cómo puedo utilizar mi dominio personalizado en la aplicación? + Petición creada + ¿En qué podemos ayudarte? + Contactar con el soporte técnico + Enviar un mensaje… No me acuerdo de mis datos de acceso ¿Por qué no puedo acceder? + ¿Cuál es la dirección de mi sitio? + ¿Cómo puedo utilizar mi dominio personalizado en la aplicación? No puedo subir fotos/videos Ayuda, mi sitio no funciona. - ¿Cuál es la dirección de mi sitio? ¿No estás seguro/a de qué preguntar? - Contactar con el soporte técnico - ¿En qué podemos ayudarte? - Enviar un mensaje… Borrar %1$d compartidas en redes sociales restantes + Algo salió mal + Algo salió mal, no se pudieron recoger las campañas + Algo salió mal CERRAR A la app de WordPress le faltan componentes obligatorios y debe ser reinstalada de la Google Play Store. Instalación fallida - Algo salió mal - Algo salió mal - Algo salió mal, no se pudieron recoger las campañas + Compartir social Conectar cuentas Compartir social - Compartir social Social Se compartirá en %1$d cuentas + No se compartirá en ninguna red social Se compartirá en %1$d de %2$d cuentas Se compartirá en %1$s - No se compartirá en ninguna red social - Personaliza el mensaje que quieres compartir. Si no agregas tu propio texto aquí, usaremos el título de la entrada como mensaje. - Personalizar el mensaje Ahora no Conectar cuentas - Insertar bloque de video - Insertar bloque de imagen - Insertar bloque de galería + Personaliza el mensaje que quieres compartir. Si no agregas tu propio texto aquí, usaremos el título de la entrada como mensaje. + Personalizar el mensaje Insertar bloque de audio - Crear - No has creado ninguna campaña todavía. Haz clic en Crear para empezar. - No tienes campañas + Insertar bloque de galería + Insertar bloque de imagen + Insertar bloque de video Detalles de la campaña + Crear campaña + Campaña de Blaze Campañas de Blaze Presupuesto - Clics - Impresiones - PROGRAMADA - EN MODERACIÓN + Crear + No has creado ninguna campaña todavía. Haz clic en Crear para empezar. + No tienes campañas + ACTIVA CANCELADA - RECHAZADA COMPLETADA - ACTIVA - Crear campaña - Campaña de Blaze - No se pudo cargar el flujo de promoción de Blaze - Aumenta el tráfico compartiendo automáticamente las entradas con tus amigos a través de las redes sociales. + EN MODERACIÓN + RECHAZADA + PROGRAMADA + Clics + Impresiones + 1 entrada compartidas en redes sociales restante Cerrar editor Rehacer el último cambio Deshacer el último cambio - 1 entrada compartidas en redes sociales restante Suscríbete ahora para compartir más + Aumenta el tráfico compartiendo automáticamente las entradas con tus amigos a través de las redes sociales. + No se pudo cargar el flujo de promoción de Blaze Aumenta el tráfico compartiendo automáticamente las entradas con tus amigos a través de las redes sociales. Compartir en redes sociales - %s separado - La edición de patrones sincronizados todavía no está incluida en %s para iOS La edición de patrones sincronizados todavía no está incluida en %s para Android + La edición de patrones sincronizados todavía no está incluida en %s para iOS + %s separado Reutilizable Se ha producido un error al guardar tus opciones de privacidad. + Analítica + Nos permiten optimizar el rendimiento mediante la recopilación de información sobre la forma en que los usuarios interactúan con nuestras aplicaciones para móviles. + Tu privacidad es extremamente importante para nosotros y siempre lo ha sido. Utilizamos, almacenamos y procesamos tus datos personales para optimizar nuestra aplicación (y tu experiencia) de diversas maneras. Algunos usos de tus datos son absolutamente necesarios para que las cosas funcionen, y otros puedes personalizarlos en los Ajustes. Guardar Ajustes - Nos permiten optimizar el rendimiento mediante la recopilación de información sobre la forma en que los usuarios interactúan con nuestras aplicaciones para móviles. - Analítica Gestión de la privacidad - Tu privacidad es extremamente importante para nosotros y siempre lo ha sido. Utilizamos, almacenamos y procesamos tus datos personales para optimizar nuestra aplicación (y tu experiencia) de diversas maneras. Algunos usos de tus datos son absolutamente necesarios para que las cosas funcionen, y otros puedes personalizarlos en los Ajustes. Yo. Gestionar los detalles de tu perfil. Mensaje - Bloque desagrupado - Bloque agrupado + No es posible cerrar la cuenta de este usuario porque tiene compras activas. + No es posible cerrar la cuenta de este usuario porque tiene suscripciones activas. + Ocurrió un error al cerrar la cuenta. + Se ha cerrado la cuenta. El dominio puede tardar hasta 30 minutos en empezar a funcionar correctamente. Tu nuevo dominio <b>%s</b> se está configurando. ¡Todo listo! Obtén un dominio gratuito durante el primer año, elimina los anuncios de tu sitio y aumenta tu espacio de almacenamiento. Consigue un dominio gratis con un plan anual + Bloque agrupado + Bloque desagrupado Obtén más información sobre las plantillas Tu página de inicio usa una plantilla de tema, por lo que se abrirá en el editor web. Página de inicio - Se ha cerrado la cuenta. - Ocurrió un error al cerrar la cuenta. - No es posible cerrar la cuenta de este usuario porque tiene compras activas. - No es posible cerrar la cuenta de este usuario porque tiene suscripciones activas. - No es posible cerrar la cuenta de este usuario si tiene cargos rechazados sin resolver. No es posible cerrar la cuenta de este usuario de inmediato porque tiene compras activas. Contacta con nuestros Happiness Engineers para eliminar la cuenta definitivamente. - No tienes autorización para cerrar la cuenta. + No es posible cerrar la cuenta de este usuario si tiene cargos rechazados sin resolver. No se pudo cerrar la cuenta automáticamente. + No tienes autorización para cerrar la cuenta. Confirmar el cierre de la cuenta… Para confirmar, vuelve a introducir tu nombre de usuario antes de cerrarla. Cerrar cuenta - Saber más La opción de compartir automáticamente en Twitter ya no está disponible debido a las modificaciones que ha sufrido esta red social en lo que respecta a términos y precios. + Saber más La opción de compartir automáticamente en Twitter ya no está disponible %s para iOS aún no es compatible con editar bloques reutilizables %s para Android aún no es compatible con editar bloques reutilizables Activa las notificaciones para estar al tanto de lo que sucede en tu sitio La aplicación de Jetpack tiene todas las funciones de la aplicación de WordPress, y ahora ofrece acceso exclusivo a Estadísticas, Lector, Notificaciones y mucho más. - Usa WordPress con %s en la\u00A0aplicación de Jetpack. Usa WordPress con %s en la\u00A0aplicación de Jetpack. - Color sin etiquetar. %s + Usa WordPress con %s en la\u00A0aplicación de Jetpack. Actividad reciente + Color sin etiquetar. %s Como en el ejemplo superior, un dominio le permite a la gente encontrar y visitar tu sitio desde su navegador. Elnombredetuweb.com - Buscar con palabras clave - Busca una dominio corto y memorable para ayudar a la gente a encontrar y visitar tu sitio. - el primer año - Tu web ha sido creada con éxito, pero hemos encontrado un problema al preparar tu dominio personalizado al finalizar la compra. Por favor, inténtalo otra vez o contacta con nuestro soporte para obtener ayuda. Puede tardar hasta 30 minutos en que tu dominio personalizado empiece a funcionar. Te hemos mandado tu recibo por correo electrónico. %s + el primer año + Busca una dominio corto y memorable para ayudar a la gente a encontrar y visitar tu sitio. + Buscar con palabras clave + Tu web ha sido creada con éxito, pero hemos encontrado un problema al preparar tu dominio personalizado al finalizar la compra. Por favor, inténtalo otra vez o contacta con nuestro soporte para obtener ayuda. Las notificaciones de la App han sido desactivadas. Pulsa aquí para activarlas. Recomendamos <b>desinstalar la aplicación WordPress</b> en tu dispositivo para evitar conflictos de datos. Parece que todavía tienes la aplicación WordPress instalada. Ya no necesitas la aplicación WordPress en tu dispositivo Recomendamos <b>desinstalar la aplicación WordPress</b> en tu dispositivo para evitar conflictos de datos. Bienvenido a la aplicación Jetpack. Puedes desinstalar la aplicación WordPress. - Eliminar bloques Privacidad y valoraciones - Ajustes de reproducción - Color de la barra de reproducción - Manual - Dinámica - Describe el propósito de la imagen. Déjalo vacío si la imagen es decorativa. - Comience con diseños personalizados y preparados para dispositivos móviles + Eliminar bloques + Para usar recordatorios para publicar tienes que activar los avisos instantáneos. Crear otra página + Comience con diseños personalizados y preparados para dispositivos móviles Agregar páginas a tu sitio - Para usar recordatorios para publicar tienes que activar los avisos instantáneos. + Describe el propósito de la imagen. Déjalo vacío si la imagen es decorativa. + Dinámica + Manual + Color de la barra de reproducción + Ajustes de reproducción Activar los avisos instantáneos - Continuar con subdominio - Comprar dominio - Fotos y videos, Música y audio + Activar los avisoa Música y audio Fotos y videos + Fotos y videos, Música y audio %s necesita permisos para acceder a tus audios - %s necesita permisos para acceder a tus videos %s necesita permisos para acceder a tus fotos - %s necesita permisos para acceder a tus fotos y videos %s necesita permisos para acceder a tu música, audios, fotos y videos - Activar los avisoa + %s necesita permisos para acceder a tus fotos y videos + %s necesita permisos para acceder a tus videos + Continuar con subdominio + Comprar dominio Ve a Ajustes &rarr; Notificaciones &rarr; Ajustes de la app, y activa %1$s para recibir notificaciones inmediatamente. Tendrás que abrir la aplicación para ver las notificaciones. Las notificaciones push están desactivadas - Las notificaciones push están desactivadas. Descarta el aviso del permiso de notificaciones. Corrección + Las notificaciones push están desactivadas. <b>%1$s</b> está usando %2$s plugins individuales de Jetpack - <b>%1$s</b> está usando el plugin <b>%2$s</b> La aplicación de WordPress no es compatible con los los plugins individuales de Jetpack. + <b>%1$s</b> está usando el plugin <b>%2$s</b> <b>%1$s</b> está usando plugins individuales de Jetpack que no son compatibles con la aplicación de WordPress. <b>%1$s</b> está usando el plugin <b>%2$s</b> que no es compatible con la aplicación de WordPress. + Por favor, pásate a la aplicación Jetpack donde te guiaremos para que conectes el plugin Jetpack para usar este sitio con la aplicación. No se pudo acceder a algunos de tus sitios No se pudo acceder a uno de tus sitios - Por favor, pásate a la aplicación Jetpack donde te guiaremos para que conectes el plugin Jetpack para usar este sitio con la aplicación. Cambia a la aplicación Jetpack %1$s usa %2$s, que todavía no es compatible con todas las funciones de la aplicación.\n\nInstala el %3$s para usar la aplicación con este sitio. - Este sitio %1$s usa %2$s, que todavía no es compatible con todas las funciones de la aplicación. Instala el %3$s. + Este sitio %1$s usa %2$s, que todavía no es compatible con todas las funciones de la aplicación. Instala el %3$s. El cambio es gratuito y solo te llevará un minuto. - Encontrarás más información en Jetpack.com - Cambiar a la aplicación de Jetpack + Hecho + Configurar + Ahora que Jetpack está instalado, solo tenemos que configurarlo. Solo te llevará un minuto. WP Admin + Contenido Gestionar Tráfico - Contenido - Configurar - Hecho - Ahora que Jetpack está instalado, solo tenemos que configurarlo. Solo te llevará un minuto. - Promocionar una entrada con Blaze ahora + Cambiar a la aplicación de Jetpack + Encontrarás más información en Jetpack.com Promocionar esta página con Blaze Promocionar esta entrada con Blaze + Promocionar una entrada con Blaze ahora Inicia y detén la actividad promocional con Blaze y haz un seguimiento del rendimiento siempre que quieras. - Tu contenido aparecerá en millones de sitios web de WordPress y Tumblr. + Blaze Comienza a promocionar cualquier entrada o página en cuestión de minutos y a un precio muy asequible. + Tu contenido aparecerá en millones de sitios web de WordPress y Tumblr. Genera más tráfico hacia tu sitio con Blaze - Blaze - Este dominio ya está registrado - Oferta - Recomendado - Mejor alternativa - al año + Gratis + Ayuda + Registros Ayuda + al año + Mejor alternativa + Recomendado + Oferta + Este dominio ya está registrado Con nuestras preguntas frecuentes podrás resolver algunas de tus dudas. ¡Gracias por cambiar a la aplicación Jetpack! - Registros Entradas - Gratis - Ayuda Menú de bloques - Muestra tu trabajo en millones de sitios. - Promociona tu contenido con Blaze - Cerrar Contactar con el soporte técnico + Cerrar Instalar el plugin completo Términos y condiciones Al configurar Jetpack, aceptas nuestros + Muestra tu trabajo en millones de sitios. + Promociona tu contenido con Blaze plugin completo de Jetpack + %1$s usa %2$s, que todavía no es compatible con todas las funciones de la aplicación.\n\nInstala el %3$s para usar la aplicación con este sitio. plugins individuales de Jetpack el plugin %1$s - %1$s usa %2$s, que todavía no es compatible con todas las funciones de la aplicación.\n\nInstala el %3$s para usar la aplicación con este sitio. Instala el plugin completo de Jetpack - Solo hay un sitio disponible, por lo que no puedes cambiar tu sitio principal. Contactar con soporte Reintentar En estos momentos, no se puede instalar Jetpack. - Se ha producido un problema Ícono de error - Todo listo para usar este sitio con la aplicación. + Se ha producido un problema + Solo hay un sitio disponible, por lo que no puedes cambiar tu sitio principal. + Promocionar con Blaze Jetpack instalado - Instala Jetpack en tu sitio. Esto puede llevar unos minutos completarse. - Instalando Jetpack + Todo listo para usar este sitio con la aplicación. Continuar Las credenciales de tu web no se almacenarán y solo se usarán para instalar Jetpack. Instalar Jetpack + Instala Jetpack en tu sitio. Esto puede llevar unos minutos completarse. + Instalando Jetpack Ícono de Jetpack - Promocionar con Blaze Libera todo el potencial de tu sitio. Obtén estadísticas, notificaciones y más con Jetpack. - Tu sitio tiene el plugin de Jetpack - La aplicación móvil Jetpack está diseñada para funcionar junto con el plugin de Jetpack. Haz el cambio ahora y obtén acceso a estadísticas, notificaciones o el lector, entre otras funciones. Recibe notificaciones por nuevos comentarios, Me gusta, visualizaciones, etc. Comparte tu contenido y busca tus comunidades y sitios favoritos para seguirlos. Consulta el crecimiento del tráfico a tu sitio con información útil y estadísticas completas. - Estadísticas y datos clave - Con Jetpack sacarás más partido de tu sitio de WordPress. El cambio es gratuito y solo te llevará un minuto. - Dale un impulso a WordPress con Jetpack + La aplicación móvil Jetpack está diseñada para funcionar junto con el plugin de Jetpack. Haz el cambio ahora y obtén acceso a estadísticas, notificaciones o el lector, entre otras funciones. + Tu sitio tiene el plugin de Jetpack Puedes gestionar los recordatorios y estímulos para bloguear en cualquier momento desde Mi sitio > Ajustes > Bloguear Cada notificación incluirá una palabra o una breve frase inspiradora Ve a <b>Ajustes del sitio</b> para reactivarlos. Se han ocultado los estímulos para bloguear. + Con Jetpack sacarás más partido de tu sitio de WordPress. El cambio es gratuito y solo te llevará un minuto. + Estadísticas y datos clave + Dale un impulso a WordPress con Jetpack Desactivar estímulos + Bloguear + Mostrar estímulos + Recordatorios de blogueo Recibe ayuda de nuestro grupo de voluntarios. Foros de la comunidad - Recordatorios de blogueo - Mostrar estímulos - Bloguear Por favor, instala la Google Play Store para obener al app Jetpack - Hacerlo más tarde - Cambiar a Jetpack Algunas características de Jetpack como Estadísticas, Lector o Notificaciones, entre otras, han sido eliminadas de la app de WordPress. Las características de Jetpack se han trasladado. + Hacerlo más tarde + Cambiar a Jetpack %1$s se trasladarán a %2$s - %1$s se trasladará a %2$s %1$s se trasladarán pronto + %1$s se trasladará a %2$s %1$s se trasladará pronto - Obtén la aplicación de Jetpack Ver todas las respuestas %1$s es menor que la semana anterior %1$s es mayor que la semana anterior - Tus visitantes en los últimos siete días son %1$s menos que en los siete días anteriores. - Tus visitantes en los últimos siete días son %1$s más que en los siete días anteriores. Tus visitas en los últimos siete días son %1$s menos que en los siete días anteriores. Tus visitas en los últimos siete días son %1$s más que en los siete días anteriores. - Siete días anteriores + Tus visitantes en los últimos siete días son %1$s menos que en los siete días anteriores. + Tus visitantes en los últimos siete días son %1$s más que en los siete días anteriores. Últimos siete días - %d semanas + Siete días anteriores 1 semana + %d semanas + Obtén la aplicación de Jetpack Desde <b>Day One</b> - Recuérdamelo más tarde Algunas funciones, como estadísticas, lector o avisos, se trasladarán pronto a la aplicación móvil de Jetpack. - Cambiar a la aplicación de Jetpack + Recuérdamelo más tarde Más información en jetpack.com El cambio es gratuito y solo lleva un minuto. - Pronto se van a retirar de la aplicación de WordPress las estadísticas, lectura, avisos y otras funcionalidades de Jetpack. Se van a retirar de la aplicación de WordPress las estadísticas, lectura, avisos y otras funcionalidades de Jetpack el %s. - Las funciones de Jetpack se trasladarán pronto. - Los avisos se están trasladando a la aplicación de Jetpack - El lector se está trasladando a la aplicación de Jetpack - La estadísticas se están trasladado a la aplicación de Jetpack - Cambiar a la nueva aplicación de Jetpack + Pronto se van a retirar de la aplicación de WordPress las estadísticas, lectura, avisos y otras funcionalidades de Jetpack. + Cambiar a la aplicación de Jetpack Se ha producido un error al cargar las indicaciones. ¡Oh! Todavía no hay sugerencias - %d respuestas 1 respuesta + %d respuestas 0 respuestas + Las funciones de Jetpack se trasladarán pronto. + Los avisos se están trasladando a la aplicación de Jetpack + El lector se está trasladando a la aplicación de Jetpack + La estadísticas se están trasladado a la aplicación de Jetpack + Cambiar a la nueva aplicación de Jetpack ✓ Respondido Peticiones cerrar Alternativamente, puedes separar y editar este bloque por separado tocando en \"Separar\". - ¿Borrar permanentemente la categoría \'%s\'? - Categoría borrada correctamente Borrando la categoría que ha fallado + Categoría borrada correctamente + ¿Borrar permanentemente la categoría \'%s\'? Borrando la categoría - Actualizando la categoría Actualizar categoría - Las entradas de este usuario no volverán a mostrarse + Actualizando la categoría Bloquear usuario Denunciar a este usuario + Las entradas de este usuario no volverán a mostrarse + enlaces URI + enlaces web + Continuar sin Jetpack Abrir enlaces en WordPress Parece que tienes instalada la aplicación de Jetpack.\n\n¿Quieres abrir enlaces en la aplicación de Jetpack en el futuro?\n\nPuedes cambiar esta opción en cualquier momento desde Ajustes de la aplicación > Abrir enlaces en Jetpack. ¿Quieres abrir enlaces en Jetpack? - Continuar sin Jetpack - Jetpack proporciona estadísticas, notificaciones y mucho más para ayudarte a crear y ampliar el sitio de WordPress de tus sueños.\n\nLa aplicación de WordPress ya no admite la creación de sitios nuevos. + Cambia a la aplicación de Jetpack para seguir recibiendo notificaciones en tiempo real en tu dispositivo. Jetpack proporciona estadísticas, notificaciones y mucho más para ayudarte a crear y ampliar el sitio de WordPress de tus sueños. + Jetpack proporciona estadísticas, notificaciones y mucho más para ayudarte a crear y ampliar el sitio de WordPress de tus sueños.\n\nLa aplicación de WordPress ya no admite la creación de sitios nuevos. Crear un sitio de WordPress nuevo con la aplicación de Jetpack - enlaces web - enlaces URI - Cambia a la aplicación de Jetpack para seguir recibiendo notificaciones en tiempo real en tu dispositivo. Cambia a la aplicación de Jetpack para buscar tus entradas y sitios favoritos, seguirlos e indicar que te gustan con el Lector. Cambia a la aplicación de Jetpack para ver cómo crece el tráfico de tu sitio con estadísticas y detalles. + De acuerdo + ¿Necesitas ayuda? + Abrir enlaces en Jetpack + No se puede desactivar Abrir enlaces en Jetpack + No se puede activar Abrir enlaces en Jetpack Recibe tus notificaciones con la aplicación de Jetpack Sigue cualquier sitio con la aplicación de Jetpack Obtén tus estadísticas con la nueva aplicación de Jetpack - No se puede desactivar Abrir enlaces en Jetpack - No se puede activar Abrir enlaces en Jetpack - Abrir enlaces en Jetpack - ¿Necesitas ayuda? - De acuerdo + Contacta con el equipo de soporte o inténtalo de nuevo más tarde. + Algo no ha ido como estaba previsto. Tus datos están protegidos, pero no podemos transferirlos en este momento. No podemos transferir tus datos y ajustes sin una conexión de red. Comprueba tu conexión de red para asegurarte de que funcione y vuelve a intentarlo. No se pudo conectar a Internet. - Contacta con el equipo de soporte o inténtalo de nuevo más tarde. - Algo no ha ido como estaba previsto. Tus datos están protegidos, pero no podemos transferirlos en este momento. - Vaya, se ha producido un error. - Volver a intentarlo Terminar + Vaya, se ha producido un error. Ícono Quitar aplicación de WordPress + Volver a intentarlo Hemos transferido todos tus datos y ajustes. Todo está tal y como lo dejaste. ¡Gracias por cambiar a Jetpack! Desactivaremos las notificaciones de la aplicación de WordPress. Recibirás las mismas notificaciones, pero a partir de ahora desde la aplicación de Jetpack. - Centro de Ayuda de WordPress - Soporte Permite que la aplicación desactive las notificaciones de WordPress. desactivar notificaciones de WordPress - ¿Necesitas ayuda? + Soporte + Centro de Ayuda de WordPress + Tu foto de perfil Continuar + ¿Necesitas ayuda? Hemos encontrado tu sitio. Continúa para transferir todos tus datos y acceder a Jetpack automáticamente. Hemos encontrado tus sitios. Continúa para transferir todos tus datos y acceder a Jetpack automáticamente. - Tu foto de perfil Parece que estas realizando el cambio desde la aplicación de WordPress. ¡Te damos la bienvenida a Jetpack! ícono - Página superior Atributos de la página + Página superior Contribuir Noticias 1 respuesta @@ -680,40 +680,43 @@ Language: es_CL ¿Estás disfrutando de %s? Comparte una entrada en %s Conexiones de Jetpack Social - Por favor, accede a la aplicación Jetpack para agregar un widget. Conexiones de Jetpack Social + Por favor, accede a la aplicación Jetpack para agregar un widget. Acabamos de enviar un enlace mágico a ¡Revisa tu correo electrónico en este dispositivo! Usar una contraseña para acceder - Mantente informado con actualizaciones en tiempo real para nuevos comentarios, tráfico del sitio, informes de seguridad y más. Los avisos funcionan con Jetpack - Observa cómo crece tu tráfico y obtén información sobre tu audiencia con estadísticas e información rediseñadas, ahora disponibles en la nueva aplicación Jetpack. - Las estadísticas funcionan con Jetpack - Encuentra, sigue y dale \"Me gusta\" a todos tus sitios y publicaciones favoritos con Reader, ahora disponible en la nueva aplicación Jetpack. + Mantente informado con actualizaciones en tiempo real para nuevos comentarios, tráfico del sitio, informes de seguridad y más. Reader funciona con Jetpack - La nueva app de Jetpack tiene estadísticas, lector, avisos, y más para mejorar tu WordPress. + Encuentra, sigue y dale \"Me gusta\" a todos tus sitios y publicaciones favoritos con Reader, ahora disponible en la nueva aplicación Jetpack. + Las estadísticas funcionan con Jetpack + Observa cómo crece tu tráfico y obtén información sobre tu audiencia con estadísticas e información rediseñadas, ahora disponibles en la nueva aplicación Jetpack. WordPress es mejor con Jetpack - Actualiza tu plan para usar fondos de video - Actualiza tu plan para subir audio - Funciona gracias a Jetpack - URL no válida. + La nueva app de Jetpack tiene estadísticas, lector, avisos, y más para mejorar tu WordPress. Degradado + URL no válida. + Funciona gracias a Jetpack + Actualiza tu plan para subir audio + Actualiza tu plan para usar fondos de video Continuar a los avisos - Continuar a las estadísticas Continuar al lector + Continuar a las estadísticas Prueba la nueva aplicación Jetpack Problema al mostrar el bloque. \nToca para intentar la recuperación del bloque. + ⭐️ Tu última entrada %1$s ha recibido %2$s Me gusta. + La semana pasada tuviste %1$s visitas, %2$s Me gusta y %3$s comentarios. La semana pasada tuviste %1$s visitas y %2$s comentarios La semana pasada tuviste %1$s visitas y %2$s Me gusta La semana pasada tuviste %1$s visitas. - La semana pasada tuviste %1$s visitas, %2$s Me gusta y %3$s comentarios. - ⭐️ Tu última entrada %1$s ha recibido %2$s Me gusta. Funciona gracias a Jetpack Imagen que señala que el escaneo de código de acceso está en proceso - Imagen que señala un error ¿Seguro que quieres continuar? Salir del flujo de escaneo de código de acceso No se pudo acceder con este código de acceso. Toca el botón Analizar de nuevo para volver a escanear el código. + Imagen que señala un error + Descartar + Toca Descartar y vuelve a tu navegador web para continuar. + ¡Has accedido! Ha fallado la autentificación Este código de acceso ha caducado. Toca el botón Analizar de nuevo para volver a escanear el código. El código de acceso ha caducado @@ -722,488 +725,485 @@ Language: es_CL Se requiere una conexión activa a Internet para escanear códigos de acceso No hay conexión Analizar de nuevo - Descartar - Toca Descartar y vuelve a tu navegador web para continuar. - ¡Has accedido! + ¿Estás intentando acceder a tu navegador web cerca de %1$s? Sí, quiero acceder Escanea solo los códigos QR que has cogido directamente del navegador web. No escanees nunca un código que te haya enviado alguien. - ¿Estás intentando acceder a tu navegador web cerca de %1$s? ¿Estás intentando acceder a %1$s cerca de %2$s? 💡Comentar en otros blogs es una buena forma de aumentar la atención y seguidores a tu nuevo sitio. 💡Toca \"VER MÁS\" para ver los principales comentaristas. + ✍️ Programa tus borradores para publicar en el mejor momento y llegar a tu público. ¡Vuelve a comprobarlo cuando hayas publicado tu primera entrada! Comprueba nuestros consejos destacados para aumentar tus visitas y tu tráfico %1$s - ✍️ Programa tus borradores para publicar en el mejor momento y llegar a tu público. 💡Publicar con constancia es una buena forma de crear tu público. Agrega un recordatorio para mantenerte al día. 💡Bloguea más rápidamente con nuestro curso <i>Introducción a los blogs</i> ofrecido por expertos. Se están cargando los estímulos para bloguear. Espera un momento e inténtalo de nuevo. ¿No puedes decidirte? Puedes cambiar el tema en cualquier momento. + Vista previa del tema %s Bloguear Elegido para ti Ideal para %s - Vista previa del tema %s Elige un tema - Me he saltado el estímulo para bloguear de hoy Más información + Me he saltado el estímulo para bloguear de hoy + Programar Totales Otros Buscar - WordPress Vistas - Programar - Programa tu entrada + WordPress Configurar recordatorios + Programa tu entrada Configura tus recordatorios de blogueo Consulta el curso Haz crecer tu audiencia - También puedes reorganizar los bloques tocando un bloque y luego tocando las flechas arriba y abajo que aparecen en la parte inferior izquierda del bloque para moverlo encima o debajo de otros bloques. - Archivo de imagen no encontrado. - Arrastrar y soltar hace que reordenar bloques sea algo trivial. Presiona y sujeta un bloque, luego arrástralo a su nueva ubicación y suéltalo. - Arrastrar y soltar - Botones de flechas %1$s. Seleccionado actualmente: %2$s - Todas las tareas están completas - Tarea completada + Botones de flechas + Arrastrar y soltar + Arrastrar y soltar hace que reordenar bloques sea algo trivial. Presiona y sujeta un bloque, luego arrástralo a su nueva ubicación y suéltalo. + Archivo de imagen no encontrado. + También puedes reorganizar los bloques tocando un bloque y luego tocando las flechas arriba y abajo que aparecen en la parte inferior izquierda del bloque para moverlo encima o debajo de otros bloques. Explorar código de acceso + Tarea completada + Todas las tareas están completas ⭐️ Tu última entrada %1$s ha recibido %2$s me gusta. No hay suficiente actividad. ¡Vuelve a comprobarlo más tarde, cuando tu sitio haya tenido más visitas! - %1$s, %2$s%% del total de suscriptores %1$s (%2$s%%) + %1$s, %2$s%% del total de suscriptores Copiar enlace ¡Enhorabuena! Ya sabes manejarte<br/> - Conoce la aplicación Sube los medios directamente a tu sitio desde tu dispositivo o cámara Sube fotos o videos - Obtén actualizaciones en tiempo real desde tu bolsillo - Selecciona %1$s Medios %2$s para ver tu biblioteca actual. + Conoce la aplicación + Miniatura de video Obtén actualizaciones en tiempo real desde tu bolsillo. - Comprueba tus avisos Selecciona la %1$s Pestaña de avisos %2$s para recibir actualizaciones sobre la marcha. - Selecciona %1$s Más %2$s para subir medios. Puedes agregarlos a tus entradas o páginas desde cualquier dispositivo. + Comprueba tus avisos Utiliza <b> Descubrir </b> para encontrar sitios y etiquetas. - Miniatura de video + Selecciona %1$s Medios %2$s para ver tu biblioteca actual. + Selecciona %1$s Más %2$s para subir medios. Puedes agregarlos a tus entradas o páginas desde cualquier dispositivo. + Obtén actualizaciones en tiempo real desde tu bolsillo Principales comentaristas - Publicada hace %1$d años - Publicada hace un año - Publicada hace %1$d meses + Publicada hace un día + Publicada hace un minuto Publicada hace un mes + Publicada hace un año + Publicada hace una hora Publicada hace %1$d días - Publicada hace un día Publicada hace %1$d horas - Publicada hace una hora Publicada hace %1$d minutos - Publicada hace un minuto + Publicada hace %1$d meses Publicada hace unos segundos + Publicada hace %1$d años Total de comentarios Total de \"Me gusta\" - Descartar Responder Estímulo diario + Descartar Entendido Toca <b>%1$s</b> para ver tu sitio Selecciona el %1$s Lector %2$s para descubrir otros sitios. Aprende más sobre los estímulos - Video no seleccionado - Video seleccionado Miniatura del medio + Video seleccionado + Video no seleccionado 🔥 La hora más popular %1$s %2$s Visitar el escritorio Tu sitio ya está protegido con VaultPress. Más abajo, puedes encontrar un enlace a tu escritorio de VaultPress. - Tu sitio tiene VaultPress Idioma actual: + Tu sitio tiene VaultPress Crear sitio - Agregar bloques - Pantalla inicial Más información Conviértete en un mejor escritor creando un hábito de escritura. Toca para más información. + Agregar bloques + Pantalla inicial Nuevo en la aplicación móvil de WordPress: Mensajes + ¿Te interesa crear tu audiencia? Echa un vistazo a nuestros <a href=\"%1$s\">mejores consejos</a>. Un buen nombre es corto y fácil de recordar.\nPuedes cambiarlo más adelante. Dale un nombre a tu web %s Nombre del sitio - ¿Te interesa crear tu audiencia? Echa un vistazo a nuestros <a href=\"%1$s\">mejores consejos</a>. Vistas y visitantes - Eliminada como imagen destacada Establecer como imagen destacada + Eliminada como imagen destacada + Pronto eliminaremos el editor clásico para las nuevas entradas, pero esto no afectará a la edición de ninguna de tus entradas o páginas existentes. Adelántate ahora activando el editor de bloques en los ajustes del sitio. + Descartar Mantener actual Reemplazar la imagen destacada Ya tienes establecida una imagen destacada. ¿Quieres reemplazarla con la nueva imagen? ¿Reemplazamos la imagen destacada actual? - Descartar - Pronto eliminaremos el editor clásico para las nuevas entradas, pero esto no afectará a la edición de ninguna de tus entradas o páginas existentes. Adelántate ahora activando el editor de bloques en los ajustes del sitio. + Cancelar + Aceptar + http(s):// Prueba el nuevo editor de bloques - Editar el bloque %s Guardando - Reintentar todo + Editar el bloque %s Eliminar la subida - Reintentar + Reintentar todo No se pudo subir el archivo + Reintentar No - Cancelar - Aceptar - http(s):// - Insertar enlace - Beta - El editor está todavía cargando - Fallo al obtener la estructura del contenido Bloques: %1$d\nPalabras: %2$d\nCaracteres: %3$d Estructura del contenido - Elige un medio de la biblioteca de medios de WordPress - Elige un medio de la galería + Insertar enlace + Beta Haz una foto o video con la cámara + Elige un medio de la galería + Elige un medio de la biblioteca de medios de WordPress %dpx - Aceptar Por favor, espera hasta que se hayan guardado todos los archivos - Archivos guardándose - Contenido + Aceptar + El editor está todavía cargando + Fallo al obtener la estructura del contenido Haz la película de tu vida. + ¡Te mostraremos un nuevo estímulo cada día en tu escritorio para ayudarte a que fluyan esos fluidos creativos! + Nota: Recordármelo Pruébalo ahora - Nota: - ¡Te mostraremos un nuevo estímulo cada día en tu escritorio para ayudarte a que fluyan esos fluidos creativos! + Contenido + Archivos guardándose El mejor modo de convertirte en un mejor escritor es crear un hábito de escritura y compartir con otros - ¡aquí es donde entran los estímulos! - Presentando\nEstímulos para bloguear Configurar recordatorios + Presentando\nEstímulos para bloguear Incluir el estímulo para bloquear Publicar con regularidad atrae nuevos lectores. ¡Cuéntanos cuándo quieres escribir y te enviaremos un recordatorio! Conviértete en un mejor escritor creando un hábito - Escritura y poesía - Viajes - Tecnología - Deportes Inmobiliaria - Política - Fotografía - Personal - Gente - Paternidad - Noticias - Música - Servicios locales - Estilo de vida - Diseño de interiores - Salud - Juegos - Comida - Forma física y ejercicio + Deportes + Tecnología + Viajes + Escritura y poesía + Comunitario y ONG + Educación + Moda Películas y televisión Finanzas - Moda + Forma física y ejercicio + Comida + Juegos + Salud + Diseño de interiores + Estilo de vida + Servicios locales + Música + Noticias + Paternidad + Gente + Personal + Fotografía + Política DIY - Educación - Comunitario y ONG - Negocios - Libros - Belleza - Automoción - Arte + Omitir por hoy + Ver más estímulos Ej.: Moda, poesía, política Temática del sitio Toca <b>%1$s</b> para continuar. - Omitir por hoy - Ver más estímulos + Arte + Automoción + Belleza + Libros + Negocios + ✓ Respondido %d respuestas Comparte el estímulo de bloguear - ✓ Respondido + Todos Responder estímulo Estímulos - Todos Esta combinación de color puede ser difícil de leer para la gente. Intenta usar un color de fondo más claro y/o un color de texto más oscuro. - Esta combinación de color puede ser difícil de leer para la gente. Intenta usar un color de fondo más oscuro y/o un color de texto más claro. Fallo al insertar los medios.\nToca para más información. + Esta combinación de color puede ser difícil de leer para la gente. Intenta usar un color de fondo más oscuro y/o un color de texto más claro. Elige una temática de las listadas a continuación o escribe la tuya propia. ¿De qué trata tu web? - Resumen semanal - Inicio Agregar categorías - ¿Qué aplicación de correo electrónico usas? + Inicio + Resumen semanal Ha habido un problema al comunicar con el sitio. Se ha devuelto un código de error HTTP 401. - Las llamadas XML-RPC parecen bloqueadas en este sitio (código de error 401). Si el intento de acceso falla, toca en el ícono de ayuda para ver las FAQ. + ¿Qué aplicación de correo electrónico usas? No se pudo leer el sitio WordPress en esa URL. Toca en el ícono de ayuda para ver las FAQ. + Las llamadas XML-RPC parecen bloqueadas en este sitio (código de error 401). Si el intento de acceso falla, toca en el ícono de ayuda para ver las FAQ. Los servicios XML-RPC están desactivados en este sitio. Menú Tu búsqueda incluye caracteres no compatibles en los dominios de WordPress.com. Se permiten los siguientes caracteres: A–Z, a–z, 0–9. + Ocurrió un error al actualizar el contenido del aviso Comprueba tu conexión a Internet y actualiza la página. Estadísticas de hoy - Ocurrió un error al actualizar el contenido del aviso Editar Fallo al moderar los comentarios - Mover a la papelera Marcar como spam + Mover a la papelera Rechazar - Ajustes de la galería de mosaico Navega a la pantalla de selección del diseño + Ajustes de la galería de mosaico Estilo de la galería Puedes conectar tu cuenta de %s en el sitio web WordPress.com. Cuando hayas terminado, vuelve a la aplicación para cambiar tus ajustes sociales. Ícono de la aplicación Ícono de volver Logotipo de Automattic WordPress - WooCommerce - Tumblr - Simplenote - Pocket Casts - Jetpack Day One - Código fuente + Jetpack + Pocket Casts Política de privacidad + Simplenote + Código fuente Términos del servicio + Tumblr + WooCommerce Trabaja desde cualquier lugar - Trabaja con nosotros Familia Automattic - Legal y otros - Twitter Instagram + Legal y otros Valóranos Compartir con amigos + Twitter + Trabaja con nosotros Puedes editar este bloque usando la versión web del editor. - Abrir los ajustes de seguridad de Jetpack Nota: Debes permitir el acceso desde WordPress.com para editar este bloque en el editor móvil. - Nota: El diseño puede variar entre temas y tamaños de pantalla - Ajustes de la dirección + Abrir los ajustes de seguridad de Jetpack AGREGAR MEDIOS + Ajustes de la dirección + Nota: El diseño puede variar entre temas y tamaños de pantalla Estamos teniendo problemas en este momento para cargar los datos de tu sitio. - Algunos datos no se han cargado + ¡Video no subido! Para subir videos de más de 5 minutos es necesario un plan de pago. El escritorio no está actualizado. Por favor, comprueba tu conexión y luego pulsa para refrescar. No se pudo actualizar el escritorio. - ¡Video no subido! Para subir videos de más de 5 minutos es necesario un plan de pago. + Algunos datos no se han cargado Agradecimientos Aviso de privacidad de California - Versión %1$s Agradecimientos Legal y otros Sobre %1$s + Versión %1$s Blog - Lo básico - Seleccionado: Por defecto - Más opciones de soporte - Obtener soporte - Tamaño de la fuente Toca dos veces para seleccionar un tamaño de fuente - Toca dos veces para seleccionar el tamaño de fuente por defecto - Contactar con el soporte + Tamaño de la fuente + Obtener soporte + Más opciones de soporte + Seleccionado: Por defecto + Lo básico %1$s (%2$s) - Seguir la conversación + Contactar con el soporte + Toca dos veces para seleccionar el tamaño de fuente por defecto Sé el primero en comentar - Ver todos los comentarios + Seguir la conversación Ha habido un error al obtener los datos de la entrada - Ha habido un error al obtener los comentarios + Ver todos los comentarios Ajustes para seguir la conversación - Desde el portapapeles - Imagen destacada + Ha habido un error al obtener los comentarios Copiar la URL desde el portapapeles, %s + Imagen destacada + Desde el portapapeles Acerca de WordPress - Crear una entrada + Copiar el enlace + Autor + Cambiado a modo HTML + Cambiado a modo visual ¡Publicar regularmente ayuda a crear tu audiencia! Crear tu próxima entrada - Cambiado a modo visual - Cambiado a modo HTML + Crear una entrada Enlace copiado al portapapeles - Autor - Copiar el enlace Agregar un dominio personalizado hace que sea más fácil para tus visitantes encontrar tu sitio Agrega tu dominio Las entradas aparecen en la página de tu blog en orden cronológicamente inverso. ¡Es el momento de compartir tus ideas con el mundo! Crear tu primera entrada - Sin título Siguientes entradas programadas + Sin título Trabaja en el borrador de una entrada <span style=\"color:#008000;\">Gratis el primer año </span><span style=\"color:#50575e;\"><s>%s /año</s></span> Crear un enlace Seleccionar el dominio Dominios - Fija - Fijar la entrada en la portada Marcar como fija - Dejar de seguir la conversación + Fijar la entrada en la portada + Fija Activar los avisos de la aplicación Estás siguiendo esta conversación. Recibirás avisos por correo electrónico cuando se publiquen nuevos comentarios. + Dejar de seguir la conversación Gestionar las opciones para seguir la conversación, ventana emergente - No se pudieron desactivar los avisos de la aplicación No se pudieron activar los avisos de la aplicación - Desactivados los avisos de la aplicación + No se pudieron desactivar los avisos de la aplicación + Siguiendo esta conversación\n¿Activar los avisos de la aplicación? Activados los avisos de la aplicación Cancelada la suscripción a esta conversación - Siguiendo esta conversación\n¿Activar los avisos de la aplicación? - Buscar un dominio + Desactivados los avisos de la aplicación Los dominios comprados en este sitio redirigirán a los visitantes a <b>%s</b> Con tu plan, tienes incluido el registro de dominio gratis durante un año - Reclama tu dominio gratuito + Buscar un dominio Agregar un dominio + Reclama tu dominio gratuito <span style=\"color:#d63638;\">Caduca el %s</span> Caduca el %s - <span style=\"color:#B26200;\">%1$s el primer año </span><span style=\"color:#50575e;\"><s>%2$s /año</s></span> %s<span style=\"color:#50575e;\"> /año</span> + <span style=\"color:#B26200;\">%1$s el primer año </span><span style=\"color:#50575e;\"><s>%2$s /año</s></span> ¿Quieres descartarlos? Hay cambios sin guardar + Comentario El comentario no puede estar vacío + Dirección de correo electrónico + Hecho Correo electrónico del usuario no válido - Dirección web no válida + Nombre El nombre de usuario no puede estar vacío - Dirección de correo electrónico Dirección web - Comentario - Nombre - Hecho + Dirección web no válida Pronto llegarán las vistas previas de los bloques incrustados Resumen semanal - Opciones de incrustación Doble toque para ver las opciones de incrustación. + Opciones de incrustación ¡Sitio creado! Completa otra tarea. - Altura de la línea Obtén tu dominio + Altura de la línea Error desconocido al recuperar la plantilla recomendada de la aplicación + Comparte WordPress con un amigo + Dominios + Enlaces rápidos Respuesta recibida no válida No se ha recibido ninguna respuesta Aplicaciones Automattic - Aplicaciones para cualquier pantalla - Comparte WordPress con un amigo - Enlaces rápidos - Dominios - Repaso semanal: %s - Hora del aviso Recibirás recordatorios para bloquear <b>todos los días</b> a las <b>%s</b>. + Hora del aviso + Repaso semanal: %s %1$s a la semana a las %2$s Los controles de formato de texto están dentro de la barra de herramientas situada encima del teclado mientras editas un bloque de texto - Selecionado: %s - Selecciona un color de arriba - Navega para seleccionar %s - Mover bloques - Cómo editar tu entrada Cómo editar tu página - Personalizar bloques + Cómo editar tu entrada + Mover bloques + Navega para seleccionar %s + Selecciona un color de arriba + Selecionado: %s Los cambios en la imagen destacada no se verán afectados por los botones de deshacer/rehacer. + Personalizar bloques Aplica el ajuste Puedes reorganizar los bloques tocando un bloque y luego tocando las flechas arriba y abajo que aparecen en la parte inferior izquierda del bloque para moverlo encima o debajo de otros bloques. - Bienvenido al mundo de los bloques Para eliminar un bloque, selecciona el bloque y haz clic en los tres puntos de la parte inferior derecha del bloque para ver los ajustes. A partir de ahí, elige la opción para eliminar el bloque. - Algunos bloques tienen ajustes adicionales. Toca el ícono de los ajustes en la parte inferior derecha del bloque para ver más opciones. + Bienvenido al mundo de los bloques Bloque %s, disponible nuevamente - Edición de texto enriquecido + Algunos bloques tienen ajustes adicionales. Toca el ícono de los ajustes en la parte inferior derecha del bloque para ver más opciones. Una vez que te hayas familiarizado con los nombres de los diferentes bloques, puedes agregar un bloque escribiendo una barra inclinada seguida del nombre del bloque, por ejemplo, \"/imagen\" o \"/encabezado\". + Edición de texto enriquecido Haz que tu contenido destaque agregando imágenes, gifs, videos y medios incrustados a tus páginas. - ¡Pruébalo agregando unos cuantos bloques a tu entrada o página! - Medio incrustado Cada bloque tiene sus propios ajustes. Para encontrarlos, toca en un bloque. Sus ajustes aparecerán en la barra de herramientas de la parte inferior de la pantalla. - Crear diseños + Medio incrustado + ¡Pruébalo agregando unos cuantos bloques a tu entrada o página! Los bloques son piezas de contenido que puedes insertar, reorganizar y dar estilo sin necesidad de saber programar. Los bloques son una forma fácil y moderna para que crees bonitos diseños. + Crear diseños Los bloques te permiten centrarte en la escritura de tu contenido, sabiendo que todas las herramientas de formato que necesitas están ahí para ayudarte a transmitir tu mensaje. Organiza tu contenido en columnas, agrega botones de llamada a la acción y superpón imágenes con texto. Agrega un nuevo bloque en cualquier momento tocando el ícono \"+\" en la barra de herramientas en la parte inferior izquierda. %1$s de %2$s completado - Aprende lo básico con un rápido recorrido. Ha fallado la moderación de uno o más comentarios + Aprende lo básico con un rápido recorrido. Crear un sitio Ten tu sitio activo y funcionando en solo unos rápidos pasos Crea tu web WordPress - No se pudieron activar las estadísticas del sitio Activar las estadísticas del sitio + No se pudieron activar las estadísticas del sitio Activa las estadísticas del sitio para ver información detallada sobre el tráfico, los \"Me gusta\", los comentarios y los suscriptores. - ¿Buscas las estadísticas? - ¿Qué es un bloque? Estamos trabajando duro para agregar compatibilidad para vistas previas %s. Mientras tanto, puedes previsualizar el contenido incrustado en la entrada. + ¿Qué es un bloque? + ¿Buscas las estadísticas? Estamos trabajando duro para agregar compatibilidad para vistas previas %s. Mientras tanto, puedes previsualizar el contenido incrustado en la página. - No se pudo incrustar el medio - Prueba otro término de búsqueda No se han encontrado bloques - Todavía no están disponibles las vistas previas de %s Pronto llegarán las vistas previas del bloque incrustado %s - Toca dos veces para previsualizar la entrada. + Todavía no están disponibles las vistas previas de %s + Prueba otro término de búsqueda + No se pudo incrustar el medio Toca dos veces para previsualizar la página. + Toca dos veces para previsualizar la entrada. Mostrado en la pestaña del navegador de tu visitante y en otros sitios online. Muéstrame el camino - ¿Quieres una pequeña ayuda para gestionar este sitio con la aplicación? Crear un nuevo sitio - Puedes cambiar los sitios en cualquier momento. Elige un sitio para abrir + Puedes cambiar los sitios en cualquier momento. + ¿Quieres una pequeña ayuda para gestionar este sitio con la aplicación? Lo sentimos, en este momento Jetpack Scan no es compatible con las instalaciones multisitio de WordPress. Los multisitios de WordPress no son compatibles URL no válida. Por favor, introduce una URL válida. - Leyenda incrustada. %s - Leyenda incrustada. Vacía - visita nuestra página de documentación Jetpack Backup para instalaciones multisitio proporciona copias de seguridad descargables, no restauraciones con un solo clic. Para más información, %1$s. - Publicar regularmente puede ayudar a que tus lectores permanezcan implicados, y a atraer nuevos visitantes a tu sitio. - Consejo - Puedes actualizar esto en cualquier momento - Selecciona los días en los que quieres bloguear + visita nuestra página de documentación + Leyenda incrustada. Vacía + Leyenda incrustada. %s Puedes actualizar esto en cualquier momento desde Mi sitio > Ajustes > Recordatorios de blogueo. - No tienes configurado ningún recordatorio. + Selecciona los días en los que quieres bloguear + Puedes actualizar esto en cualquier momento + Consejo + Publicar regularmente puede ayudar a que tus lectores permanezcan implicados, y a atraer nuevos visitantes a tu sitio. Recibirás recordatorios para bloguear %1$s a la semana el %2$s a las %3$s. + No tienes configurado ningún recordatorio. ¡Recordatorios eliminados! ¡Todo configurado! - Actualizar - Nada configurado %s a la semana - Configurar recordatorios - Configura recordatorios de blogueo los días que quieras publicar. + Nada configurado + Actualizar Tu entrada se está publicando … mientras tanto puedes configurar recordatorios de blogueo los días que quiera publicar. - Configura tus recordatorios de blogueo + Configura recordatorios de blogueo los días que quieras publicar. + Configurar recordatorios Este es tu recordatorio para crear algo hoy Es hora de bloguear en %s WordPress para iOS aún no es compatible con editar bloques reutilizables + Configura tus recordatorios de blogueo WordPress para Android aún no es compatible con editar bloques reutilizables Alternativamente, puedes separar y editar estos bloques por separado tocando en \"Separar patrones\". Hecho Avísame <a href=\"%1$s\">Introduce las credenciales de tu servidor</a> para activar las restauraciones del sitio con un clic de las copias de seguridad. - Establecer como imagen destacada - Eliminar como imagen destacada Crear una categoría + Eliminar como imagen destacada + Establecer como imagen destacada Soporte de WordPress para Android Gestiona las categorías de tu sitio - Categorías - Recordatorios El contenido de la página de tus últimas entradas se genera automáticamente y no se puede editar. + Recordatorios + Categorías Ajustes del borde No mostrar de nuevo - Ver el almacenamiento Tenemos que guardar tu contenido en tu dispositivo antes de que pueda ser publicado. Revisa tus ajustes de almacenamiento y elimina archivos para ganar espacio. - Insuficiente almacenamiento en el dispositivo + Ver el almacenamiento Posición del eje Y + Insuficiente almacenamiento en el dispositivo Posición del eje X - Teclea una URL - Resultados del insertador de corte - %s tiene una URL configurada %s no tiene una URL configurada - %s convertido a bloques normales + %s tiene una URL configurada + Resultados del insertador de corte + Teclea una URL Bloque %s - Opacidad - Opciones de medios + %s convertido a bloques normales URL no válida. Archivo de audio no encontrado. - Insertar entrada cruzada - Arrastra para ajustar el punto focal - Toca dos veces para abrir la hoja inferior para agregar imagen o video + Opciones de medios + Opacidad Toca dos veces para abrir la hoja de acción para agregar imagen o video - La unidad actual es %s + Toca dos veces para abrir la hoja inferior para agregar imagen o video + Arrastra para ajustar el punto focal + Insertar entrada cruzada + Ajustes de columnas Entrada cruzada + La unidad actual es %s %s convertido a bloque normal - Ajustes de columnas - Agregar enlace a %s Agregar texto del enlace + Agregar enlace a %s Agregar una imagen o video - La ruta especificada es un directorio y no un archivo de medios No se pudo encontrar el archivo de medios en la ruta - Ruta de archivo de medios vacía inesperada + La ruta especificada es un directorio y no un archivo de medios El tipo de archivo no está permitido + Ruta de archivo de medios vacía inesperada El medio estaba vacío <a href=\"%1$s\">Introduce las credenciales de tu servidor</a> para corregir las amenazas. <a href=\"%1$s\">Introduce las credenciales de tu servidor</a> para corregir la amenaza. Toca dos veces para agregar un enlace. - Probar con otra cuenta Ver las instrucciones + Probar con otra cuenta Si ya tienes un sitio, tendrás que instalar el plugin gratuito de Jetpack y conectarlo a tu cuenta de WordPress. Tu foto de perfil Si quieres usar esta aplicación para %1$s, deberás tener el plugin de Jetpack configurado y conectado a una cuenta de WordPress.com. - Mover la imagen hacia delante - Mover la imagen hacia atrás - Ajustes de anchura - \"rel\" del enlace Ajustes de columna + \"rel\" del enlace + Mover la imagen hacia atrás + Mover la imagen hacia delante Sin descripción - (Sin título) - Sitio + Ajustes de anchura Información de hoja inferior del perfil de usuario + Sitio + (Sin título) Lista de Me gusta %s Dos Tres @@ -1211,62 +1211,62 @@ Language: es_CL Ícono social %s Mención NUEVO - Previsualizar la entrada Previsualizar la página - Reintentar + Previsualizar la entrada GIF + Reintentar Uno Agregar título Vista previa no disponible Cargando - Etiqueta del enlace - Color del texto Enlace %s + Color del texto + Etiqueta del enlace Relleno - Cuatro Destacado + Cuatro Agregar imagen - URL personalizada Crear una incrustación + URL personalizada Columna %d Más Describe brevemente el enlace para ayudar a los usuarios de lectores de pantalla Agregar bloques No se han encontrado sitios de Jetpack - ¿Qué es el texto alt? - Transformar %s a Transformar bloque… + Transformar %s a + ¿Qué es el texto alt? Fallo al insertar los medios. - Fallo al insertar el archivo de audio. - Describe el propósito de la imagen. Déjalo vacío si la imagen es puramente decorativa. %1$s transformado a %2$s + Describe el propósito de la imagen. Déjalo vacío si la imagen es puramente decorativa. + Fallo al insertar el archivo de audio. Error al cargar los datos de me gusta. %s. %d me gusta 1 me gusta Sugerencia: - Usar botón de ícono - Campo de introducción de búsqueda. - Botón de búsqueda. El texto actual del botón es - Bloques de búsqueda Etiqueta del bloque de búsqueda. El texto actual es - Exterior - No se ha establecido ningún marcador de posición personalizado - Dentro - Ocultar el encabezado de búsqueda - Doble toque para editar el texto del marcador de posición - Doble toque para editar el texto de la etiqueta - Doble toque para editar el texto del botón + Bloques de búsqueda + Botón de búsqueda. El texto actual del botón es + Campo de introducción de búsqueda. + Usar botón de ícono doble toque para cambiar la unidad - El texto de marcador de posición actual es - Vaciar la búsqueda - Cancelar la búsqueda - Posición del botón - %1$s. %2$s is %3$s %4$s. + Doble toque para editar el texto del botón + Doble toque para editar el texto de la etiqueta + Doble toque para editar el texto del marcador de posición + Ocultar el encabezado de búsqueda + Dentro + No se ha establecido ningún marcador de posición personalizado + Exterior + Sin responder + No hay ningún comentario sin responder Ocurrió un error al obtener los datos de los me gusta - Ocurrió un error al obtener los me gusta. No hay ninguna red disponible. - No hay ningún comentario sin responder - Sin responder + Ocurrió un error al obtener los me gusta. + %1$s. %2$s is %3$s %4$s. + Posición del botón + Cancelar la búsqueda + Vaciar la búsqueda + El texto de marcador de posición actual es AGREGAR ENLACE Ajustes de búsqueda Direcciones IP permitidas siempre @@ -1274,341 +1274,341 @@ Language: es_CL Agregar el texto del botón Descartar Descargar - Amenazas corregidas correctamente. - Por favor, confirma que quieres corregir todas las %s amenazas activas. La exploración ha encontrado %1$s amenazas potenciales con %2$s. Por favor, revísalas a continuación y lleva a cabo alguna acción o toca el botón de corregir todo. Estamos %3$s si nos necesitas. + Por favor, confirma que quieres corregir todas las %s amenazas activas. + Amenazas corregidas correctamente. Trabajamos duro para corregir estas amenazas en segundo plano. Mientras tanto puedes seguir usando tu sitio como siempre, puedes volver a comprobar el progreso en cualquier momento. Editar el punto focal - Toque doble para abrir la hoja del fondo para editar, reemplazar o vaciar la imagen Toque doble para abrir la hoja de acción para editar, reemplazar o vaciar la imagen + Toque doble para abrir la hoja del fondo para editar, reemplazar o vaciar la imagen example.com Teclea un nombre para tu sitio <b>Se han completado todas las tareas</b><br/>Has llegado a más gente. ¡Buen trabajo! <b>Se han completado todas las tareas</b><br/>Has personalizado tu sitio. ¡Bien hecho! - ¿No querías crear una nueva cuenta? Vuelve atrás y vuelve a introducir tu dirección de correo electrónico. Una vez desactivado el enlace de invitación, nadie podrá usarlo para unirse a tu equipo. ¿Seguro que deseas continuar? - Desactivar enlace de invitación + ¿No querías crear una nueva cuenta? Vuelve atrás y vuelve a introducir tu dirección de correo electrónico. Respuesta recibida no válida - No se ha recibido ninguna respuesta Ocurrió un error al recuperar datos para el perfil %1$s Ha habido un error al obtener los perfiles + Desactivar enlace de invitación Error desconocido al obtener los datos de los enlaces de invitación Utiliza este enlace para embarcar a los miembros de tu equipo sin tener que invitarlos uno a uno. Cualquiera que visite estas URL podrá registrarse en tu organización, aunque haya recibido el enlace de otra persona, así que asegúrate de que lo compartes con gente de confianza. - Caduca %1$s + No se ha recibido ninguna respuesta Desactivar enlace de invitación - Compartir enlace de invitación + Caduca %1$s Generar nuevo enlace de invitación Refrescar el estado del enlace Enlace de invitación - Se ha encontrado una amenaza - Se han encontrado amenazas + Compartir enlace de invitación + <b>Exploración finalizada</b><br>No se han encontrado amenazas potenciales <b>Exploración finalizada</b><br>%s amenazas potenciales encontradas <b>Exploración finalizada</b><br>Una amenaza potencial encontrada - <b>Exploración finalizada</b><br>No se han encontrado amenazas potenciales - Corrigiendo la amenaza + Se han encontrado amenazas + Se ha encontrado una amenaza Desactivar + Corrigiendo la amenaza Revisa tus páginas y haz cambios, o agrega o elimina páginas. - Ve tu sitio - Descubre y sigue sitios que te inspiren. - Compartir socialmente Comparte automáticamente las nuevas entradas en tus medios sociales. + Compartir socialmente + Descubre y sigue sitios que te inspiren. Dale un nombre a tu sitio que refleje su personalidad y temática. + Ve tu sitio Revisa las estadísticas de tu sitio - Trataremos de crear un archivo de copia de seguridad descargable. No pudimos encontrar el estado para decir cuánto tardará tu copia de seguridad descargable. + Trataremos de crear un archivo de copia de seguridad descargable. Vaya, no hemos podido encontrar el estado de tu copia de seguridad descargable Ícono de marca de comprobación Ícono de reloj Te avisaremos cuando hayamos terminado. - Volveremos a intentar restaurar tu sitio. + No pudimos restaurar tu sitio No pudimos encontrar el estado para decir cuánto tardará tu restauración. + Volveremos a intentar restaurar tu sitio. Vaya, no hemos podido encontrar el estado de tu restauración - No pudimos restaurar tu sitio - Confirmar - ¿Estás seguro de querer revertir tu sitio al %1$s a las %2$s?\n Todo lo que hayas cambiado desde entonces se perderá. No pudimos crear tu copia de seguridad - (SQL) (excluye temas, plugins y subidas) + (SQL) + Confirmar + ¿Estás seguro de querer revertir tu sitio al %1$s a las %2$s?\n Todo lo que hayas cambiado desde entonces se perderá. + Elementos incluidos en esta descarga Directorio wp-content Raíz de WordPress - Elementos incluidos en esta descarga Subiendo… - Reemplazar archivo - Reemplazar audio - Problema al abrir el audio - ABRIR - Ninguna aplicación puede gestionar esta solicitud. - Ícono de candado - Fallo al insertar el archivo de audio. Por favor, toca para ver las opciones. Toca dos veces para seleccionar un archivo de audio - Toca dos veces para escuchar el archivo de audio - Elegir audio - Reproductor de audio - archivo de audio - Leyenda del audio. %s - Leyenda del audio. Vacía - Agregar audio + Fallo al insertar el archivo de audio. Por favor, toca para ver las opciones. + Ícono de candado + Ninguna aplicación puede gestionar esta solicitud. + ABRIR + Problema al abrir el audio + Reemplazar audio + Reemplazar archivo Accede o regístrate con WordPress.com - Usasr este audio - Elige un audio del dispositivo + Agregar audio + Leyenda del audio. Vacía + Leyenda del audio. %s + archivo de audio + Reproductor de audio + Elegir audio + Toca dos veces para escuchar el archivo de audio Opcional: Introduce un mensaje personalizado que enviar con tu invitación. + Elige un audio del dispositivo + Usasr este audio Aprende más sobre los perfiles - Corregido - Encontrado aquí para ayudar La exploración ha encontrado una amenaza potencial con %1$s. Por favor, revísalas a continuación y lleva a cabo alguna acción o toca el botón de corregir todo. Estamos %2$s si nos necesitas. + Encontrado + Corregido Para revisar tu sitio de nuevo ejecuta una exploración manual, o espera a que Jetpack explore tu sitio más tarde hoy mismo. ¡Bienvenido a la exploración de Jetpack! Le estamos echando un vistazo a tu web para dejarlo todo a punto para el primer análisis completo. Te informaremos si encontramos algún problema que le pueda afectar y después comenzará tu primer análisis. - Bienvenido a la herramienta de exploración de Jetpack, estamos echándole un primer vistazo a tu web en estos momentos, te mostraremos los resultados enseguida. Trabajamos duro para corregir estas amenazas en segundo plano. Mientras tanto puedes seguir usando tu sitio como siempre, puedes volver a comprobar el progreso en cualquier momento. Te enviaremos un aviso si se encuentra una amenaza. Mientras tanto, no dudes en seguir usando tu sitio con normalidad, puedes comprobar el progreso en cualquier momento. + Bienvenido a la herramienta de exploración de Jetpack, estamos echándole un primer vistazo a tu web en estos momentos, te mostraremos los resultados enseguida. Corrigiendo amenazas Jetpack Scan no ha podido realizar un análisis de tu sitio. Comprueba si tu sitio está caído. Si no, vuelve a intentarlo. Si tu sitio está caído o si Jetpack Scan sigue teniendo problemas, ponte en contacto con nuestro equipo de soporte. - Algo salió mal - Haciendo copia de seguridad del sitio + La copia de seguridad de tu sitio se ha realizado correctamente Haciendo copia de seguridad del sitio desde %1$s %2$s + Haciendo copia de seguridad del sitio Creando una copia de seguridad descargable - La copia de seguridad de tu sitio se ha realizado correctamente + Algo salió mal La copia de seguridad de tu sitio se ha realizado correctamente\nHecha copia de seguridad desde %1$s %2$s La copia de seguridad de tu sitio se está realizando\nHaciendo copia de seguridad desde %1$s %2$s Elegir audio Hay otra restauración en curso. - Ícono de error Botón Listo - No se pudo restaurar - Botón Visitar sitio + Ícono de error + Todos los elementos seleccionados se han restaurado a la versión del %1$s %2$s. Botón Listo + No se pudo restaurar + Tu sitio se ha restaurado Ícono de restaurar Visitar el sitio - Todos los elementos seleccionados se han restaurado a la versión del %1$s %2$s. - Tu sitio se ha restaurado + Botón Visitar sitio No hace falta que esperes. Te enviaremos un aviso cuando la restauración se haya completado. - Ícono de restaurar sitio Estamos restaurando la versión de tu sitio del %1$s %2$s. Estamos restaurando el sitio + Ícono de restaurar sitio Botón Confirmar restauración del sitio - Imagen de un círculo rojo con un signo de exclamación - Advertencia Botón Restaurar sitio - Ícono de restaurar + Advertencia + Imagen de un círculo rojo con un signo de exclamación + Listo + Botón Listo + Nube con ícono de X + Restaurar Restaurar sitio + Elige los elementos que quieres restaurar: %1$s %2$s es el punto seleccionado para la restauración. Restaurar sitio - Elige los elementos que quieres restaurar: - Restaurar - Nube con ícono de X - Botón Listo - Listo + Ícono de restaurar La descarga ha fallado - Tableta - Dispositivos móviles - Selecciona %1$s Páginas %2$s para ver tu lista de páginas. + Selecciona %1$s Página de inicio %2$s para editar tu página de inicio. Cambia, agrega o elimina páginas en tu sitio. + Selecciona %1$s Páginas %2$s para ver tu lista de páginas. Revisar las páginas del sitio - Selecciona %1$s Página de inicio %2$s para editar tu página de inicio. - Marcar como no leída - Marcar como leída - No se pudieron subir los elementos multimedia.\n%1$s + Dispositivos móviles + Tableta Espacio de almacenamiento del sitio insuficiente + No se pudieron subir los elementos multimedia.\n%1$s No se puede activar o desactivar el estado Es visible de esta entrada - Marcar entrada como no leída Marcar entrada como leída + Marcar entrada como no leída + Marcar como leída + Marcar como no leída + Por favor, confirma que quieres corregir una amenaza activa. + Se ha producido un error al corregir las amenazas. Ponte en contacto con el servicio de soporte. Se ha producido un error al comprobar el estado de la reparación. Ponte en contacto con el servicio de soporte. La amenaza se ha corregido correctamente. - Se ha producido un error al corregir las amenazas. Ponte en contacto con el servicio de soporte. - Por favor, confirma que quieres corregir una amenaza activa. Corregir todas las amenazas No se pudo ignorar la amenaza. Ponte en contacto con el servicio de soporte. Se ha ignorado la amenaza. No deberías ignorar un problema de seguridad a menos que estés absolutamente seguro de que no es dañino. Si eliges ignorar esta amenaza, seguirá en tu sitio <b>%s</b>. No se pudo corregir la amenaza. Ponte en contacto con el servicio de soporte. - Amenaza ignorada - Amenaza corregida el %s - Corrigiendo la amenaza - Se ha ignorado - No se encontró ningún elemento - Fijo - Todos - Analizando archivos - Preparando escaneado - Historia - Historial de exploraciones Prueba a ajustar el rango de fechas No se han encontrado copias de seguridad coincidentes Tu primera copia de seguridad estará disponible aquí en 24 horas y recibirás una notificación una vez que se haya completado + Historial de exploraciones + Todos + Fijo + Se ha ignorado + Historia + No se encontró ningún elemento + Preparando escaneado + Analizando archivos + Corrigiendo la amenaza + Amenaza corregida el %s + Amenaza ignorada Tu primera copia de seguridad estará lista pronto Ocurrió un problema al gestionar la petición. Por favor, inténtalo de nuevo más tarde. - Mover al final Cambiar la posición del bloque - Ícono - También hemos enviado un enlace a tu archivo. + Mover al final Botón de compartir enlace + También hemos enviado un enlace a tu archivo. + Ícono + Hemos creado una copia de seguridad de tu sitio desde %1$s %2$s. + Descargar Botón de descarga - Ícono de copia de seguridad descargable lista Compartir enlace - Descargar - Hemos creado una copia de seguridad de tu sitio desde %1$s %2$s. Tu copia de seguridad ya está disponible para descargarla + Ícono de copia de seguridad descargable lista Tu copia de seguridad - No hace falta que esperes. Te avisaremos cuando la copia de seguridad esté lista - Ícono de copia de seguridad descargable en curso Estamos creando una copia de seguridad descargable de tu sitio desde %1$s %2$s. + No hace falta que esperes. Te avisaremos cuando la copia de seguridad esté lista Se está creando una copia de seguridad descargable de tu sitio - Descargar copia de seguridad + Ícono de copia de seguridad descargable en curso Hay otra descarga en curso. - Ocurrió un problema al gestionar la petición. Por favor, inténtalo de nuevo más tarde. Botón Crear copia de seguridad descargable %1$s %2$s es el punto seleccionado para crear una copia de seguridad descargable. + Ocurrió un problema al gestionar la petición. Por favor, inténtalo de nuevo más tarde. + Descargar copia de seguridad %1$s · %2$s · %1$s · %2$s %1$s · - entrada cruzada - usuario No coincide con %s. - Ocurrió un problema al cargar las sugerencias. No hay sugerencias %s disponibles. + Ocurrió un problema al cargar las sugerencias. Escribe algo para filtrar la lista de sugerencias. - Consigue un presupuesto gratuito - Ignorar amenaza + usuario + entrada cruzada Corregir amenaza Jetpack Scan solucionará la amenaza. + Jetpack Scan borrará el archivo o el directorio afectados. Jetpack Scan editará el archivo o el directorio afectados. Jetpack Scan se actualizará a una versión más reciente (%s). - Jetpack Scan borrará el archivo o el directorio afectados. + Consigue un presupuesto gratuito + Ignorar amenaza Jetpack Scan reemplazará el archivo o el directorio afectados. Jetpack Scan no puede solucionar automáticamente esta amenaza.\n Te sugerimos que soluciones esta amenaza manualmente: asegúrate de que WordPress, tu tema y todos los plugins están actualizados y elimina el código, tema o plugin que esté causando problemas en tu sitio web. \n \n\n Si necesitas más ayuda para resolver esta amenaza, te recomendamos <b>Codeable</b>, una plataforma de profesionales de confianza, altamente cualificados, expertos en WordPress.\n Han hecho una selección de expertos en seguridad para ayudarnos con estos proyectos. Los precios oscilan entre 70–120 USD/hora y puedes obtener un presupuesto gratuito sin compromiso.\n + Amenaza detectada en el archivo: Solucionando la amenaza - ¿Cómo lo solucionó Jetpack? ¿Cómo vamos a repararlo? - Amenaza detectada en el archivo: - Información técnica + ¿Cómo lo solucionó Jetpack? ¿Cuál fue el problema? + Información técnica Detalles de la amenaza - Se ha encontrado una vulnerabilidad en un tema - Se ha encontrado una vulnerabilidad en un plugin - Amenaza encontrada %s + Amenazas de base de datos %s + %s: patrón de código malicioso + Plugin vulnerable: %1$s (versión %2$s) + Tema vulnerable: %1$s (versión %2$s) Se ha encontrado una vulnerabilidad en WordPress + Amenaza encontrada %s Varias vulnerabilidades - Tema vulnerable: %1$s (versión %2$s) - Plugin vulnerable: %1$s (versión %2$s) - %s: patrón de código malicioso - Amenazas de base de datos %s - %s: archivo principal infectado - Se ha encontrado una amenaza - Corregir todo + Se ha encontrado una vulnerabilidad en un plugin + Se ha encontrado una vulnerabilidad en un tema + La última exploración de Jetpack se ejecutó %1$s y no encontró ningún riesgo. %2$s en unos segundos - hace %s minuto(s) hace %s hora(s) + hace %s minuto(s) este sitio - La última exploración de Jetpack se ejecutó %1$s y no encontró ningún riesgo. %2$s - Puede que tu sitio web esté desprotegido - No te preocupes + %s: archivo principal infectado + Se ha encontrado una amenaza + Corregir todo + Filtro de tipo de actividad (%s tipos seleccionados) + Copias de seguridad Analizar de nuevo + No te preocupes + Puede que tu sitio web esté desprotegido Analizar ahora Ícono de estado del análisis - Copias de seguridad - Filtro de tipo de actividad (%s tipos seleccionados) - %1$s (mostrando %2$s elementos) - Filtro de tipo de actividad No se han registrado actividades en el rango de fechas seleccionado. No hay actividades disponibles Revisa tu conexión a Internet e inténtalo de nuevo. + Filtro de tipo de actividad + %1$s (mostrando %2$s elementos) Sin conexión Tipo de actividad (%s) Filtro de rango de fechas Intenta ajustar los filtros de rango de fecha o de tipo de actividad No se han encontrado eventos coincidentes - Base de datos del sitio - (incluye wp-config.php y cualquier archivo que no sea de WordPress) + Crea un ícono de copia de seguridad descargable Subidas de medios Plugins de WordPress + (incluye wp-config.php y cualquier archivo que no sea de WordPress) + Base de datos del sitio Temas de WordPress - Crea un ícono de copia de seguridad descargable + Tipo de actividad + Rango de fechas + Descargar copia de seguridad + Restaurar hasta este punto + Descarga de la copia de seguridad Crear un archivo descargable Crear una copia de seguridad descargable Descargar copia de seguridad - Descarga de la copia de seguridad - Error Elegir archivo - Descargar copia de seguridad - Restaurar hasta este punto - Tipo de actividad - Rango de fechas + Error Filtrar por tipo de actividad + Duplicar Copiar la versión de esta aplicación Editar la entrada primero La entrada que estás tratando de copiar tiene dos versiones que están en conflicto o has hecho cambios recientemente, pero no los has guardado.\nEdita la entrada primero para resolver cualquier conflicto o procede a copiar la versión de esta aplicación. Conflicto de sincronización de la entrada - Duplicar - Nombre del archivo - Ajustes del archivo del bloque - Fallo al subir los archivos.\nPor favor, toca para ver las opciones. - Fallo al guardar los medios.\nPor favor, toca para ver las opciones. Editar el archivo + Fallo al guardar los medios.\nPor favor, toca para ver las opciones. + Fallo al subir los archivos.\nPor favor, toca para ver las opciones. + Ajustes del archivo del bloque + Nombre del archivo Copiar la URL del archivo - Elige un dominio Jetpack - Siguiendo la conversación por correo electrónico + Elige un dominio Seguir la conversación por correo electrónico - No se pudo anular la suscripción a los comentarios de esta entrada + Siguiendo la conversación por correo electrónico No se pudo crear la suscripción a los comentarios de esta entrada + No se pudo anular la suscripción a los comentarios de esta entrada Error al recuperar el estado de suscripción para la entrada + Aplicar + Vaciar Respuesta recibida no válida No se ha recibido ninguna respuesta - Vaciar - Aplicar Los medios han sido eliminados. Intenta volver a crear tu historia. - Hecho Se ha producido un error al elegir el tema. - Por favor, revisa tu conexión a Internet e inténtalo de nuevo. Toca en reintentar cuando vuelvas a estar conectado. Los diseños no están disponibles sin conexión + Por favor, revisa tu conexión a Internet e inténtalo de nuevo. + Hecho Continuar con las credenciales de la tienda Encuentra tu correo electrónico conectado + ¡Bienvenido! Prueba a seguir más etiquetas para ampliar la búsqueda No hay entradas recientes - ¡Bienvenido! Explorar + A <b>Madison Ruíz</b> le ha gustado tu entrada <b>Juan Gómez</b> ha respondido en tu entrada Hoy has recibido <b>50 me gusta</b> en tu sitio - A <b>Madison Ruíz</b> le ha gustado tu entrada - Se ha abierto el menú de bloques desplazable. Selecciona un bloque. Se ha cerrado el menú de bloques desplazable. + Se ha abierto el menú de bloques desplazable. Selecciona un bloque. Elegir - Toca \"Reintentar\" cuando vuelvas a estar en línea o crea una página en blanco usando el botón a continuación. - Los diseños no están disponibles sin conexión Toca \"Reintentar\" o crea una página en blanco usando el botón a continuación. Los diseños no están disponibles debido a un error + Toca \"Reintentar\" cuando vuelvas a estar en línea o crea una página en blanco usando el botón a continuación. + Los diseños no están disponibles sin conexión Agregar una categoría + Categorías + No establecido Agregar una nueva categoría Categorías - No establecido - Categorías + Mis diez mejores cafés Museos en Londres Los mejores fanáticos del mundo - Mis diez mejores cafés - Política + Pamela Nguyen + Rock n\' roll semanal + Noticias web Música Jardinería + Arte + Política Fútbol Cocina - Arte - Rock n\' roll semanal - Noticias web - Pamela Nguyen Estoy muy inspirado por el trabajo del fotógrafo Cameron Karsten. Probaré estas técnicas en mi próximo Inspírate Sigue tus sitios favoritos y descubre nuevos blogs. + Bienvenido al maquetador web más popular del mundo. Observa cómo crece tu audiencia con analíticas avanzadas. - Mira los comentarios y avisos en tiempo real. Con el potente editor puedes publicar sobre la marcha. - Bienvenido al maquetador web más popular del mundo. + Mira los comentarios y avisos en tiempo real. La carga del medio ha fallado - Estamos trabajando duro para agregar más bloques con cada versión. \"%s\" no es totalmente compatible - Botón de ayuda - Editar usando el editor web + Estamos trabajando duro para agregar más bloques con cada versión. Elegir las imágenes + Editar usando el editor web + Botón de ayuda Página en blanco creada Página creada Inserción del medio fallida. @@ -1618,626 +1618,626 @@ Language: es_CL Primeros pasos Sigue etiquetas para descubrir nuevos blogs Por - Este referido no puede ser marcado como spam - Desmarcar como spam - Marcar como spam - Abrir la web + Subiendo medios Subiendo medios GIF Subiendo medios de inventarios - Subiendo medios + Marcar como spam + Abrir la web + Desmarcar como spam + Este referido no puede ser marcado como spam Busca o escribe la URL Agregar este enlace de teléfono - Agregar este enlace Agregar este enlace de correo electrónico + Agregar este enlace No hay conexión a Internet.\nNo están disponibles las sugerencias. %s %s seleccionado - Obtener un enlace de acceso por correo electrónico - Vaya, no encontramos una cuenta de WordPress.com conectada a esta dirección de correo electrónico. - Micrófono No se puede mostrar este comentario + Vaya, no encontramos una cuenta de WordPress.com conectada a esta dirección de correo electrónico. + Obtener un enlace de acceso por correo electrónico Navegar por elementos + Micrófono Informar de esta entrada - Bienvenido al Lector. Descubre millones de blogs a tu alcance. Ocurrió un error interno del servidor Tu acción no está permitida + Bienvenido al Lector. Descubre millones de blogs a tu alcance. %1$s elementos más - Seleccionar un diseño Nota: el diseño de la columna puede variar entre temas y tamaños de pantalla - Crear una entrada o historia + Seleccionar un diseño Crear una página Crear una entrada + Crear una entrada o historia Puede que te guste Ocultar - Leyenda del video. Vacía - Actualiza el título. - Pegar el bloque después - Título de la página. %s + Este dispositivo no es compatible con la API de Camera2 Título de la página. Vacío + Título de la página. %s + Pegar el bloque después + Actualiza el título. + Leyenda del video. Vacía Ocurrió un error al reproducir tu video - Este dispositivo no es compatible con la API de Camera2 Cerrar - Vista previa - Crear una página - Crear una página en blanco Empieza eligiendo entre una amplia variedad de diseños de página prefabricados. O simplemente empieza con una página en blanco. Elegir un diseño + Crear una página en blanco + Crear una página + Vista previa Pon un título a tu historia Toca crear %1$s. %2$s Después selecciona <b>Entrada del blog</b> - Elegir el dispositivo + Cuota de almacenamiento superada + No se puede subir el archivo.\nSe ha superado la cuota de almacenamiento. Entrada de la historia Para la edición de los íconos del sitio en sitios WordPress autoalojados se necesita el plugin Jetpack. + Elegir el dispositivo No se pudo encontrar el salto de página enlazado - No se puede subir el archivo.\nSe ha superado la cuota de almacenamiento. - Cuota de almacenamiento superada Agregar un archivo - Reemplazar el video Reemplazar la imagen o video - Convertir en enlace - Elegir un video - Elegir una imagen o video - Elegir una imagen - Bloque eliminado + Reemplazar el video + Si continúas con Google y aún no tienes una cuenta de WordPress.com, crearás una cuenta y aceptas nuestros %1$stérminos del servicio%2$s. Introduce la dirección de tu sitio existente + Bloque eliminado + Elegir una imagen + Elegir una imagen o video + Elegir un video + Convertir en enlace Confirmación del registro - Si continúas con Google y aún no tienes una cuenta de WordPress.com, crearás una cuenta y aceptas nuestros %1$stérminos del servicio%2$s. Si continúas, aceptas nuestros %1$stérminos del servicio%2$s. Usaremos esta dirección de correo electrónico para crear tu nueva cuenta de WordPress.com. Te hemos enviado por correo electrónico un enlace de registro para crear tu nueva cuenta de WordPress.com. Comprueba tu correo electrónico en este dispositivo y toca el enlace en el correo electrónico que has recibido de WordPress.com. Introduce la información de tu cuenta para %1$s. - o Continuar con Google - Encuentra la dirección de tu sitio Hecho - ¿No ves el correo electrónico? Comprueba tu carpeta de spam o correo no deseado. - Comprueba tu correo electrónico en este dispositivo y toca el enlace en el correo electrónico que has recibido de WordPress.com. + Encuentra la dirección de tu sitio Te enviaremos por correo electrónico un enlace que te hará acceder automáticamente, sin necesidad de contraseña. + Comprueba tu correo electrónico en este dispositivo y toca el enlace en el correo electrónico que has recibido de WordPress.com. + o + ¿No ves el correo electrónico? Comprueba tu carpeta de spam o correo no deseado. Comprobar el correo electrónico - Primeros pasos + Crear una cuenta Introduce tu dirección de correo electrónico para acceder o crear una cuenta de WordPress.com. + Primeros pasos O escribe tu contraseña - Crear una cuenta - Enviar el enlace por correo electrónico Restablecer tu contraseña + Enviar el enlace por correo electrónico Ha habido un problema al gestionar la solicitud. Por favor, inténtalo de nuevo más tarde. - Comprueba el título de tu sitio Toca <b>%1$s</b> para configurar un nuevo título + Comprueba el título de tu sitio Al enviar esta entrada a la papelera también se descartarán los cambios locales, ¿estás seguro de que quieres continuar? Opciones del bloque %s - Eliminar el bloque - Duplicar bloque - Copiar bloque - Bloque copiado - Bloque pegado - Bloque duplicado - Bloque cortado Bloque copiado + Bloque cortado + Bloque duplicado + Bloque pegado + Bloque copiado + Copiar bloque + Duplicar bloque + Eliminar el bloque El título del sitio solo puede ser cambiado por un usuario con el perfil de administrador. - El título del sitio se muestra en la barra de título de un navegador web y en la cabecera de la mayoría de los temas. - No se pudo actualizar el título del sitio. Comprueba tu conexión de red e inténtalo nuevamente. Cambios sin guardar - Abrir el enlace en un navegador + No se pudo actualizar el título del sitio. Comprueba tu conexión de red e inténtalo nuevamente. + El título del sitio se muestra en la barra de título de un navegador web y en la cabecera de la mayoría de los temas. Navega a la hoja de contenido anterior - Navega para personalizar el degradado - Navega al selector de color personalizado - Tipo de degradado - Volver - Toca dos veces para seleccionar la opción + Abrir el enlace en un navegador Personalizar el degradado - Autor de la página + Toca dos veces para seleccionar la opción + Volver + Tipo de degradado + Navega al selector de color personalizado + Navega para personalizar el degradado La miniatura del medio no se ha podido cargar - Estructura del contenido Todos Yo + Estructura del contenido + Autor de la página Descartar No establecido - Las etiquetas ayudan a los lectores diciéndoles de qué se trata la entrada. - Fecha de publicación - Agregar etiquetas + Las entradas en la papelera no se pueden editar. ¿Deseas cambiar el estado de esta entrada a \"borrador\" para poder trabajar en ella? + Cancelar + Mover a borrador Volver + Publicando en Guardar ahora - Enviar ahora Programar ahora - Publicando en - Etiquetas + Enviar ahora Fecha de publicación - Cancelar - Mover a borrador - Las entradas en la papelera no se pueden editar. ¿Deseas cambiar el estado de esta entrada a \"borrador\" para poder trabajar en ella? + Etiquetas + Fecha de publicación + Agregar etiquetas + Las etiquetas ayudan a los lectores diciéndoles de qué se trata la entrada. + La Ley de Privacidad del Consumidor de California (\"CCPA\") nos obliga a que proporcionemos información adicional a los residentes de California sobre las categorías de información personal que recopilamos y compartimos, dónde obtenemos esa información personal y cómo y por qué la usamos. + Lee el aviso de privacidad de CCPA ¿Mover entrada a borradores? - Elige tus etiquetas - Hecho - Selecciona algunos para continuar Publicado - En la papelera Programada + En la papelera Fecha de publicación - Lee el aviso de privacidad de CCPA - La Ley de Privacidad del Consumidor de California (\"CCPA\") nos obliga a que proporcionemos información adicional a los residentes de California sobre las categorías de información personal que recopilamos y compartimos, dónde obtenemos esa información personal y cómo y por qué la usamos. + Hecho + Selecciona algunos para continuar + Elige tus etiquetas Aviso de privacidad para usuarios de California Estado y visibilidad Actualizar ahora %1$s · - Abrir el menú de acciones de bloques Mover arriba - Insertar una mención - Toca dos veces para abrir la hoja inferior con las opciones disponibles + Abrir el menú de acciones de bloques Toca dos veces pata abrir la hoja de acción con las opciones disponibles + Toca dos veces para abrir la hoja inferior con las opciones disponibles + Insertar una mención No podemos abrir las páginas en este momento. Por favor, inténtalo de nuevo más tarde - Establecer como página de entradas Establecer como página de inicio - %1$s no es una %2$s válida - Seleccionar la página - Página de entradas - Página de inicio estática + Establecer como página de entradas Blog clásico La página de inicio seleccionada y la página de entradas no pueden ser la misma. - Ha fallado la actualización de la página de inicio, comprueba tu conexión a internet - No se pueden guardar los ajustes de la página de inicio antes de que las páginas estén cargadas - No se pueden guardar los ajustes de la página de inicio + Página de entradas + Seleccionar la página + Página de inicio estática + %1$s no es una %2$s válida Aceptar + No se pueden guardar los ajustes de la página de inicio antes de que las páginas estén cargadas Ha fallado la carga de las páginas - Elige entre una página de inicio que muestre tus últimas publicaciones (blog clásico) o una página fija/estática. + No se pueden guardar los ajustes de la página de inicio + Ha fallado la actualización de la página de inicio, comprueba tu conexión a internet Ajustes de la página de inicio - Página de inicio - Ha fallado la actualización de la página de entradas - Página de entradas actualizada correctamente - Ha fallado la actualización de la página de inicio - Página de inicio actualizada correctamente - Para establecer la página de entradas, activa \"Página de inicio estática\" en los ajustes del sitio + Elige entre una página de inicio que muestre tus últimas publicaciones (blog clásico) o una página fija/estática. Para establecer la página de inicio, activa \"Página de inicio estática\" en los ajustes del sitio + Para establecer la página de entradas, activa \"Página de inicio estática\" en los ajustes del sitio + Página de inicio actualizada correctamente + Ha fallado la actualización de la página de inicio + Página de entradas actualizada correctamente + Ha fallado la actualización de la página de entradas + Página de inicio Seleccionar un color Toca dos veces para ir a los ajustes del color - Saber más - Qué hay de nuevo en %s - Insertar %d recortar Fallo al cargar en el archivo, por favor, inténtalo de nuevo. - Vista previa de la miniatura de la imagen + Qué hay de nuevo en %s + Saber más + Insertar %d + Elegir el medio Usar este medio Usar este video - Elegir el medio Elegir el video + Vista previa de la miniatura de la imagen No se pudo seleccionar el sitio. Por favor, inténtalo de nuevo. - Continuar - Ha fallado reblog - Gestionar blogs - Una vez que crees un sitio en WordPress.com, puedes volver a publicar el contenido que te gusta en tu propio sitio. - No hay blogs de WordPress.com disponibles - Qué hay de nuevo + Insertar Copiada la dirección del enlace - Copiar la dirección del enlace Compartir en No se pudo compartir - Insertar Continuar + Copiar la dirección del enlace Copiar + Gestionar blogs + Una vez que crees un sitio en WordPress.com, puedes volver a publicar el contenido que te gusta en tu propio sitio. + No hay blogs de WordPress.com disponibles + Ha fallado reblog + Continuar + Qué hay de nuevo Número de columnas - Mover el bloque a la derecha desde la posición %1$s a la posición %2$s - Mover el bloque a la derecha - Mover el bloque a la izquierda desde la posición %1$s a la posición %2$s - Mover bloque a la izquierda - Toca dos veces para mover el bloque hacia la derecha Toca dos veces para mover el bloque hacia la izquierda + Toca dos veces para mover el bloque hacia la derecha + Mover bloque a la izquierda + Mover el bloque a la izquierda desde la posición %1$s a la posición %2$s + Mover el bloque a la derecha + Mover el bloque a la derecha desde la posición %1$s a la posición %2$s Ajustes del bloque - Creando el escritorio - Configurar el tema - Agregando las características del sitio Obteniendo la URL del sitio + Agregando las características del sitio + Configurar el tema + Creando el escritorio Tu sitio estará listo en breve ¡Hurra!\nCasi está hecho - Cancelar la subida Ha habido un problema al gestionar la petición + Cancelar la subida Funciona con Tenor Elegir desde Tenor - Sábado Viernes - Jueves - Miércoles - Martes Lunes + Sábado Domingo + Jueves + Martes + Miércoles Ha fallado el acceso al contenido de un sitio privado. Algunos medios pueden no estar disponibles Accediendo al contenido de un sitio privado Fallo al recortar y guardar la imagen, por favor, inténtalo de nuevo. + No pudimos completar esta acción y no se publicó esta página privada. + No pudimos completar esta acción y no se ha programado esta página. + No pudimos completar esta acción y no se envió esta página a revisión. + Formato de página desconocido Fallo al cargar la imagen.\nPor favor, toca para volver a intentarlo. Previsualizar la imagen - Formato de página desconocido - No pudimos completar esta acción y no se envió esta página a revisión. - No pudimos completar esta acción y no se ha programado esta página. - No pudimos completar esta acción y no se publicó esta página privada. + No pudimos subir este medio y no se envió esta página a revisión. No pudimos completar esta acción y no se publicó esta página. - No pudimos enviar esta página a revisión, pero lo intentaremos de nuevo más tarde. - No pudimos programar esta página, pero lo intentaremos de nuevo más tarde. - No pudimos publicar esta página privada, pero lo intentaremos de nuevo más tarde. No pudimos publicar esta página, pero lo intentaremos de nuevo más tarde. - No pudimos subir este medio y no se envió esta página a revisión. - No pudimos subir este medio y no se ha programado esta página. - No pudimos subir este medio y no se publicó esta página privada. + No pudimos publicar esta página privada, pero lo intentaremos de nuevo más tarde. + No pudimos programar esta página, pero lo intentaremos de nuevo más tarde. + No pudimos enviar esta página a revisión, pero lo intentaremos de nuevo más tarde. No pudimos subir este medio y no se publicó la página. + No pudimos subir este medio y no se publicó esta página privada. + No pudimos subir este medio y no se ha programado esta página. Guardaremos tu borrador cuando tu dispositivo vuelva a estar online Publicaremos tu página privada cuando tu dispositivo vuelva a estar online. - Programaremos tu página cuando tu dispositivo vuelva a estar online. - Enviaremos tu página para revisión cuando tu dispositivo vuelva a estar online. - Publicaremos la página cuando tu dispositivo vuelva a estar online. - Página en espera - Subiendo la página El dispositivo está desconectado. La página se ha guardado localmente. Hiciste cambios no guardados en esta página - Tu página se está subiendo - La página ha fallado al subir los medios y ha sido guardada localmente - Página guardada en el dispositivo - La página se ha guardado online - Selecciona un blog para el atajo a QuickPress - Establecido por el ahorrador de batería + Página en espera + Subiendo la página + Enviaremos tu página para revisión cuando tu dispositivo vuelva a estar online. + Publicaremos la página cuando tu dispositivo vuelva a estar online. + Programaremos tu página cuando tu dispositivo vuelva a estar online. + Apariencia Oscuro + Establecido por el ahorrador de batería Claro - Apariencia Recientemente has hecho cambios en esta página, pero no los has guardado. Elige una versión para cargar:\n\n + Página guardada en el dispositivo + La página ha fallado al subir los medios y ha sido guardada localmente + La página se ha guardado online + Tu página se está subiendo + Selecciona un blog para el atajo a QuickPress Mensaje de advertencia Mostrar el contenido de la entrada - Mostrar solo el extracto - Enlazar a Ajustes de enlace - Longitud del extracto (palabras) + Enlazar a + Mostrar solo el extracto Editar el medio de la portada - PERSONALIZAR + Longitud del extracto (palabras) URL del enlace del botón - Radio del borde + PERSONALIZAR Agregar un bloque de párrafo + Radio del borde Crear una entrada - En la papelera - Programada + No conectado Publicada + Programada + En la papelera La conexión con Facebook no puede encontrar ninguna página. Jetpack Social no puede conectar con perfiles de Facebook, solo con páginas publicadas. - No conectado - Me gusta - Comentarios - No leído No enviar a la papelera Papelera + Comentarios + Me gusta + No leído Actividad - Entradas y páginas General - Agregar una nueva tarjeta + Entradas y páginas Agregar una nueva tarjeta de estadísticas - Usa el botón de filtro para encontrar entradas sobre temas específicos + Agregar una nueva tarjeta Selecciona una etiqueta o blog, ventana emergente Quitar el filtro actual Acceder a WordPress.com - Accede a WordPress.com para ver las últimas entradas de las etiquetas que sigues + Usa el botón de filtro para encontrar entradas sobre temas específicos Accede a WordPress.com para ver las últimas entradas de los blogs que sigues - Reemplazar el bloque actual - Agregar al final - Agregar al principio - Agregar el bloque antes + Accede a WordPress.com para ver las últimas entradas de las etiquetas que sigues Agregar el bloque después + Agregar el bloque antes + Agregar al principio + Agregar al final + Reemplazar el bloque actual Agregar una etiqueta Filtrar - Leyenda del video. %s - Editar el video - Editar los medios Agregar un shortcode… - Autor de la entrada + Editar los medios + Editar el video + Leyenda del video. %s Crear una entrada - Has escuchado todas las estadísticas de este período.\n Si vuelves a tocar, se reiniciará desde el principio. - No hay estadísticas en este período. - Actividad de publicación para %1$s - Los días con visitas %1$s para %2$s son: %2$s %3$s. Toca para más. - explora todas las estadísticas para este período - muy altas + Autor de la entrada +   y %1$d %2$s altas - medias bajas -   y %1$d %2$s + medias + muy altas + explora todas las estadísticas para este período + Los días con visitas %1$s para %2$s son: %2$s %3$s. Toca para más. + No hay estadísticas en este período. + Has escuchado todas las estadísticas de este período.\n Si vuelves a tocar, se reiniciará desde el principio. + Actividad de publicación para %1$s %1$s, %2$d %3$s - Leyenda de la galería. %s Crear una entrada o página + Leyenda de la galería. %s Creador de la web Ahora no Cualquier cosa que quieras crear o compartir, te ayudaremos a hacerlo aquí mismo. + Imagen no seleccionada Bienvenido a WordPress Biblioteca de fotos - Imagen no seleccionada - , seleccionada - Imagen seleccionada - Miniatura de la imagen Entrada del blog Agregar nueva + , seleccionada + Miniatura de la imagen + Imagen seleccionada Publicar - Sincronizar ahora Esta entrada se sincronizará inmediatamente. ¿Preparado para sincronizar? - Este dominio no está disponible + Sincronizar ahora -%s + Este dominio no está disponible No pudimos acceder a tu sitio. Tendrás que contactar con tu alojamiento para solucionarlo. - No pudimos acceder a tu sitio debido a un problema con el <b>certificado SSL</b>. Tendrás que contactar con tu alojamiento para solucionarlo. No pudimos acceder a tu sitio porque necesita <b>identificación HTTP</b>. Tendrás que contactar con tu alojamiento para solucionarlo. + No pudimos acceder a tu sitio debido a un problema con el <b>certificado SSL</b>. Tendrás que contactar con tu alojamiento para solucionarlo. + Accede con las credenciales de tu sitio %1$s No pudimos acceder en tu sitio al <b>archivo XMLRCP</b>. Tendrás que contactar con tu alojamiento para solucionarlo. ¡Ya casi estamos! Solo necesitamos verificar tu dirección de correo electrónico conectada a Jetpack <b>%1$s</b> - Accede con las credenciales de tu sitio %1$s Página del sitio - Me gusta + No podemos abrir las entradas en este momento. Por favor, inténtalo de nuevo más tarde Descubrir + Me gusta Guardado - %sE - %sP - %sT - %sG - %sM - %sK - No podemos abrir las entradas en este momento. Por favor, inténtalo de nuevo más tarde No podemos cargar los datos para tu sitio en este momento. Por favor, inténtalo de nuevo más tarde + %sK + %sM + %sG + %sT + %sP + %sE Biblioteca de medios de WordPress - No compatible - Desagrupar - Toca para ocultar el teclado - Toca aquí para mostrar la ayuda - Haz un video - Haz una foto o un video - Haz una foto Empieza a escribir… - Bloque %s. Este bloque tiene contenido no válido - Bloque %s. Vacío + Haz una foto + Haz una foto o un video + Haz un video + Toca aquí para mostrar la ayuda + Toca para ocultar el teclado + Desagrupar + No compatible Cortar bloque - Problema al abrir el video - Problema al mostrar el bloque - Título de la entrada. %s - Título de la entrada. Vacío - Pegar la URL - Bloque de salto de página. %s - Abrir los ajustes + Bloque %s. Vacío + Bloque %s. Este bloque tiene contenido no válido Ninguna aplicación puede manejar esta petición. Por favor, instala un navegador web. - Navegar arriba - Mover el bloque hacia arriba, de la fila %1$s a la fila %2$s - Mover el bloque arriba + Abrir los ajustes + Bloque de salto de página. %s + Pegar la URL + Título de la entrada. Vacío + Título de la entrada. %s + Problema al mostrar el bloque + Problema al abrir el video Mover el bloque hacia abajo, de la fila %1$s a la fila %2$s - Mover el bloque abajo - Texto del enlace - Enlace insertado - Leyenda de la imagen. %s - Ocultar el teclado - Ícono de ayuda + Mover el bloque arriba + Mover el bloque hacia arriba, de la fila %1$s a la fila %2$s + Navegar arriba Toca dos veces para deshacer el último cambio - Toca dos veces para alternar los ajustes - Toca dos veces para seleccionar una imagen - Toca dos veces para seleccionar un video - Toca dos veces para seleccionar + Ícono de ayuda + Ocultar el teclado + Leyenda de la imagen. %s + Enlace insertado + Texto del enlace + Mover el bloque abajo Toca dos veces para rehacer el último cambio - Toca dos veces para mover el bloque hacia arriba - Toca dos veces para mover el bloque hacia abajo - Toca dos veces para editar este valor - Toca dos veces para agregar un bloque + Toca dos veces para seleccionar + Toca dos veces para seleccionar un video + Toca dos veces para seleccionar una imagen + Toca dos veces para alternar los ajustes Toca dos veces y mantén para editar - El valor actual es %s + Toca dos veces para agregar un bloque + Toca dos veces para editar este valor + Toca dos veces para mover el bloque hacia abajo + Toca dos veces para mover el bloque hacia arriba Elegir desde el dispositivo - Ocurrió un error desconocido. Por favor, inténtalo de nuevo. - Texto alternativo - Agregar video - Agregar la URL + El valor actual es %s Agregar el texto alternativo AGREGAR EL BLOQUE AQUÍ Agregar descripción - Toca el botón \"Agregar a las entradas guardadas\" para guardar una entrada en tu lista. + Agregar la URL + Agregar video + Texto alternativo + Ocurrió un error desconocido. Por favor, inténtalo de nuevo. La lista se ha cargado con %1$d elementos. - Avisos + Toca el botón \"Agregar a las entradas guardadas\" para guardar una entrada en tu lista. Desactivado Activado Al desactivar los avisos para este sitio, se desactivarán los avisos mostrados en la pestaña de avisos de este sitio. Puedes ajustar qué tipo de aviso ves después de activar los avisos para este sitio. - Para ver los avisos en la pestaña de avisos de este sitio, activa los avisos para este sitio. + Avisos Activar los avisos mostrados en la pestaña de avisos de este sitio Desactivar los avisos mostrados en la pestaña de avisos de este sitio + Para ver los avisos en la pestaña de avisos de este sitio, activa los avisos para este sitio. Avisos para este sitio Avisos para este sitio Agregar una imagen o video - No pudimos enviar esta entrada para revisión, pero lo intentaremos de nuevo más tarde. - No pudimos programar esta entrada, pero lo intentaremos de nuevo más tarde. No pudimos publicar esta entrada privada, pero lo intentaremos de nuevo más tarde. + No pudimos programar esta entrada, pero lo intentaremos de nuevo más tarde. + No pudimos enviar esta entrada para revisión, pero lo intentaremos de nuevo más tarde. + No pudimos completar esta acción y no se publicó esta entrada. + No pudimos completar esta acción y no se envió esta entrada privada. No pudimos publicar esta entrada, pero lo intentaremos de nuevo más tarde. - No pudimos completar esta acción y no se envió esta entrada para revisión. No pudimos completar esta acción y no se ha programado esta entrada. - No pudimos completar esta acción y no se envió esta entrada privada. - No pudimos completar esta acción y no se publicó esta entrada. - No pudimos subir este medio y no se envió esta entrada para revisión. - No pudimos subir este medio y no se ha programado esta entrada. - No pudimos subir este medio y no se publicó esta entrada privada. - No pudimos subir este medio y no se publicó la entrada. + No pudimos completar esta acción y no se envió esta entrada para revisión. No pudimos subir este medio. - No pudimos completar esta acción, pero lo intentaremos de nuevo más tarde. + No pudimos subir este medio y no se publicó la entrada. + No pudimos subir este medio y no se publicó esta entrada privada. + No pudimos subir este medio y no se ha programado esta entrada. + No pudimos subir este medio y no se envió esta entrada para revisión. No pudimos completar esta acción. + No pudimos completar esta acción, pero lo intentaremos de nuevo más tarde. No se puede previsualizar un borrador vacío No se puede previsualizar una página vacía No se puede previsualizar una entrada vacía + Generando la vista previa… Vista previa no disponible Error al intentar guardar la entrada antes de previsualizarla - Generando la vista previa… - Guardando… Hiciste cambios no guardados en esta entrada + Guardando… + Borrar permanentemente + Recientemente has hecho cambios en esta entrada, pero no los has guardado. Elige una versión para cargar:\n\n + Desde esta aplicación\nGuardado en %1$s\n\nDesde otro dispositivo\nGuardado en %2$s\n La versión desde esta aplicación La versión desde otro dispositivo - Desde esta aplicación\nGuardado en %1$s\n\nDesde otro dispositivo\nGuardado en %2$s\n - Recientemente has hecho cambios en esta entrada, pero no los has guardado. Elige una versión para cargar:\n\n ¿Qué versión te gustaría editar? - Borrar permanentemente No guardaremos los últimos cambios en tu borrador. - No programaremos estos cambios. - No enviaremos estos cambios para revisión. - No publicaremos estos cambios. Guardaremos tu borrador cuando tu dispositivo vuelva a estar online + No enviaremos estos cambios para revisión. Publicaremos tu entrada privada cuando tu dispositivo vuelva a estar online. - Programaremos tu entrada cuando tu dispositivo vuelva a estar online. + No publicaremos estos cambios. + No programaremos estos cambios. Enviaremos tu entrada para revisión cuando tu dispositivo vuelva a estar online. Publicaremos la entrada cuando tu dispositivo vuelva a estar online. + Programaremos tu entrada cuando tu dispositivo vuelva a estar online. + Guardando el nombre de usuario… Esta acción no puede cancelarse. Es posible que el nombre de usuario ya haya sido actualizado. Tu nuevo nombre de usuario es %1$s - Guardando el nombre de usuario… - Cambiar el nombre de usuario Estás cambiando tu nombre de usuario a %1$s%2$s%3$s. Cambiar tu nombre de usuario también afectará a tu perfil de Gravatar y a las direcciones de perfil de Intense Debate. Para continuar, confirma tu nuevo nombre de usuario. + Cambiar el nombre de usuario ¡Cuidado! Estás a punto de cambiar tu nombre de usuario, que actualmente es %1$s%2$s%3$s. No podrás volver a recuperar tu nombre de usuario. Ver y cambiar los ajustes de rendimiento de Jetpack Rendimiento y velocidad - Más - Reemplaza la búsqueda integrada en WordPress con una experiencia mejorada de búsqueda + Alojamiento de video sin anuncios + Imágenes más rápidas + Archivos estáticos más rápidos Búsqueda mejorada + Reemplaza la búsqueda integrada en WordPress con una experiencia mejorada de búsqueda Búsqueda de Jetpack - Alojamiento de video sin anuncios Medios - Carga las páginas más rápido al permitir a Jetpack optimizar tus imágenes y archivos estáticos (como CSS y JavaScript). - Archivos estáticos más rápidos - Imágenes más rápidas + Más Desactivado - Activado - Acelerador de sitios + Carga las páginas más rápido al permitir a Jetpack optimizar tus imágenes y archivos estáticos (como CSS y JavaScript). Mejora la velocidad de tu sitio al cargar solo las imágenes visibles en la pantalla. Rendimiento + Acelerador de sitios + Activado Descargas - Archivo - Descargas de archivos Las estadísticas de descarga de archivos no se registraron antes del 28 de Junio de 2019. + Descargas de archivos + Archivo Zona horaria del sitio (UTC -%s) - Zona horaria del sitio (UTC +%s) Zona horaria del sitio (UTC) - Escritorio - Por defecto + Zona horaria del sitio (UTC +%s) + \"%1$s\" programado para publicar el \"%2$s\" en tu aplicación de %3$s\n%4$s + Entrada programada de WordPress: \"%s\" Cerrar el diálogo - Seleccionar el tipo de vista previa - Compartir Volver Avanzar - \"%1$s\" programado para publicar el \"%2$s\" en tu aplicación de %3$s\n%4$s - Entrada programada de WordPress: \"%s\" \"%s\" se publicará en 10 minutos - \"%s\" se publicará en 1 hora + Seleccionar el tipo de vista previa + Compartir + Por defecto + Escritorio \"%s\" ha sido publicado - Entrada programada: recordatorio de 10 minutos - Entrada programada: recordatorio de 1 hora + \"%s\" se publicará en 1 hora Entrada programada + Entrada programada: recordatorio de 1 hora + Entrada programada: recordatorio de 10 minutos El aviso no puede crearse cuando la fecha de publicación ha pasado. Cuando se publique - 10 minutos antes - 1 hora antes Desactivado + 1 hora antes + 10 minutos antes Agregar al calendario Aviso Fecha y hora Por favor, introduce una dirección completa de una web, como example.com. Accede con WordPress.com para conectar con %1$s - Visitas - Entrada - %1$s: %2$s, %3$s: %4$s - Elemento contraído - Elemento expandido + Editor Contraer Ampliar Gráfico actualizado. - %1$s %2$s del período: %3$s, cambio desde el período anterior - %4$s + Elemento contraído + Elemento expandido + %1$s: %2$s, %3$s: %4$s Cargando los datos de la tarjeta seleccionada - Editor - Ampliar + %1$s %2$s del período: %3$s, cambio desde el período anterior - %4$s + Entrada + Visitas Cerrar - Verifica tu dirección de correo electrónico - las instrucciones se enviaron a tu correo electrónico + Ampliar Verifica tu dirección de correo electrónico - las instrucciones se enviaron a %s + Verifica tu dirección de correo electrónico - las instrucciones se enviaron a tu correo electrónico Cancelar Aceptar - http(s):// Quitar enlace + http(s):// Insertar enlace - Reintentar la subida Subiendo medios.\nPor favor, toca para ver las opciones. + Reintentar la subida Abrir enlace en una nueva ventana/pestaña Para ver tus estadísticas accede a la cuenta de WordPress.com. - Ninguna entrada coincide con tu búsqueda - Buscar entradas Aquí es donde la gente te encuentra en Internet. Elige un nombre de dominio premium Todos los planes de WordPress.com incluyen un nombre de dominio personalizado. Registra ahora tu dominio premium gratuito. + Ninguna entrada coincide con tu búsqueda + Buscar entradas + Histórico De un vistazo Hoy - Histórico - Visitas esta semana - Por favor, accede a la aplicación WordPress para agregar un widget. - No hay ninguna red disponible + Agregar widget + Histórico + Color + Oscuro + Claro No se pudieron cargar los datos - Tipo + No hay ninguna red disponible + Por favor, accede a la aplicación WordPress para agregar un widget. Color + Tipo Selecciona tu sitio - Oscuro - Claro - Color - Selecciona tu sitio Sitio - Histórico + Selecciona tu sitio Visitas esta semana - Agregar widget + Visitas esta semana Está tardando más tiempo del normal recargar los detalles del plugin. Por favor, compruébalo de nuevo más tarde. Si acabas de registrar un nombre de dominio, por favor, espera hasta que terminemos de configurarlo e inténtalo de nuevo.\n\nEn caso contrario, parece que algo fue mal y la característica del plugin podría no estar disponible para este sitio. Estado (no disponible) Al registrar este dominio aceptas nuestros %1$stérminos y condiciones%2$s - Comprueba tu conexión a la red e inténtalo de nuevo. No se pudo cargar esta página en este momento. No se pudieron recuperar los ajustes. Algunas APIs no están disponibles para la cuenta e ID de esta aplicación OAuth. + Comprueba tu conexión a la red e inténtalo de nuevo. Al configurar Jetpack aceptas nuestros %1$stérminos y condiciones%2$s No hay ninguna conexión. La edición está desactivada. - Para volver a conectar la aplicación con tu sitio alojado, introduce aquí la nueva contraseña del sitio. - Contraseña actualizada Actualizar contraseña + Contraseña actualizada + Para volver a conectar la aplicación con tu sitio alojado, introduce aquí la nueva contraseña del sitio. Registrando el nombre de dominio… - Selecciona la provincia Selecciona el país - Registrar un dominio - Código postal - Provincia - Ciudad - Dirección 2 + Selecciona la provincia Dirección - País + Dirección 2 + Ciudad Código del país + País Teléfono - Organización (opcional) + Código postal + Registrar un dominio + Provincia Para tu comodidad, hemos precompletado tu información de contacto\n de WordPress.com. Por favor, comprueba que es la información correcta que quieres usar para este dominio. + Organización (opcional) Información de contacto del dominio Registrar públicamente Registrar privadamente con protección de privacidad Los propietarios de dominios tienen que compartir información en una base de datos pública de todos los dominios.\n Con la protección de privacidad publicamos nuestra propia información en vez de la tuya, y te redirigiremos de forma privada cualquier comunicación dirigida a ti. - Protección de privacidad Por favor, introduce un %s válido - Nuevo + Protección de privacidad + Gestiona tus estadísticas Descartar - Pruébalo ahora + Nuevo Elige qué estadísticas ver, y céntrate en los datos que más te preocupen. Toca en %1$s al fondo de las estadísticas para personalizarlas. - Gestiona tus estadísticas + Pruébalo ahora Recuperando revisiones… Fallo al insertar los medios.\nPor favor, toca para ver las opciones. Fallo al insertar los medios.\nPor favor, toca para volver a intentarlo. Tu borrador se está subiendo Subiendo borrador - Borradores Ocurrió un error mientras se restauraba la entrada + Borradores Retroceder a: %s - Solo ves las estadísticas más relevantes. Agrega y organiza tus detalles abajo. - Estadísticas anuales del sitio No se pudieron cargar las sugerencias de dominios Teclea una palabra clave para más ideas No se han encontrado sugerencias Registrar dominio - Quitar de los detalles - Mover abajo - Mover arriba - Ajustes de los parámetros de las estadísticas + Estadísticas anuales del sitio + Solo ves las estadísticas más relevantes. Agrega y organiza tus detalles abajo. + Cambios locales + Al enviar esta entrada a la papelera también se descartarán los cambios sin guardar, ¿estás seguro de querer continuar? La entrada se está moviendo a borradores - La entrada se está restaurando Entrada restaurada + La entrada se está restaurando La entrada se está enviando a la papelera - Al enviar esta entrada a la papelera también se descartarán los cambios sin guardar, ¿estás seguro de querer continuar? - Cambios locales + Ajustes de los parámetros de las estadísticas + Mover abajo + Mover arriba + Quitar de los detalles Mover a borradores - Cambiar a la vista de lista Cambiar a la vista de tarjetas - No tienes ninguna entrada en la papelera + Cambiar a la vista de lista No tienes ninguna entrada en borrador - No tienes ninguna entrada programada Aún no has publicado ninguna entrada + No tienes ninguna entrada programada + No tienes ninguna entrada en la papelera Por favor, inicia sesión con tu nombre de usuario y contraseña. Por favor, inicia sesión con tu nombre de usuario WordPress.com, en lugar de tu dirección de correo electrónico. Promedio palabras/entrada @@ -2255,7 +2255,6 @@ Language: es_CL Registro de dominio Para instalar plugins, debes tener un dominio personalizado asociado con su sitio. Instalar plugin - Podrás personalizar la apariencia de tu sitio más tarde Publicar en: %s Programado para: %s Publicado en: %s @@ -2266,6 +2265,7 @@ Language: es_CL Periodo Meses y Años Cargar Más + Podrás personalizar la apariencia de tu sitio más tarde Hoy Mejor Hora Mejor Día @@ -2286,19 +2286,19 @@ Language: es_CL No podemos cargar planes en este momento. Por favor inténtalo de nuevo más tarde. No se pueden cargar planes Sin conexión - Cambiar al editor de bloques Se ha producido un problema al cargar los datos, actualiza la página para volver a intentarlo. Datos no cargados Edita nuevas publicaciones y páginas con el editor de bloques Utiliza el Editor de Bloques + Cambiar al editor de bloques salir Haz crecer tu audiencia - Personaliza tu sitio Siguientes pasos - Elige un ícono del sitio único Tus visitantes verán tu ícono en su navegador. Agrega un ícono personalizado para un look pulido y profesional. - Selecciona las %1$s estadísticas %2$s para ver cómo está rindiendo tu sitio. + Personaliza tu sitio + Elige un ícono del sitio único Puntea %1$sEl Icono de tu Sitio%2$s para cargar uno nuevo + Selecciona las %1$s estadísticas %2$s para ver cómo está rindiendo tu sitio. Guarda en borrador y publica una entrada. Habilita el compartir publicaciones Comparte automáticamente nuevas publicaciones en tus cuentas de redes sociales. @@ -2308,45 +2308,44 @@ Language: es_CL Recordatorio Seleccione el siguiente período Seleccione el período anterior - %1$s de visitas Tiempo Más Popular + %1$s de visitas %1$s (%2$s) +%1$s (%2$s) - Mostrando vista previa del sitio Limpiar + Hubo un problema + Mostrando vista previa del sitio Parece como si estuvieras en una conexión lenta. Si no ves el nuevo sitio en la lista, prueba a actualizar. Cancelar Asistente de Creación de Sitios Estamos creando tu nuevo sitio - Hubo un problema Crear sitio Crear sitio Aquí es donde la gente te encontrará en Internet. + Hubo un problema No hay direcciones disponibles que coincidan con tu búsqueda Error al comunicarse con el servidor, inténtalo de nuevo - Hubo un problema Hubo un problema - ¡Tu sitio ha sido creado! %1$d de %2$d + ¡Tu sitio ha sido creado! Crear sitio Sugerencias actualizadas No se pudo seleccionar el sitio autohospedado recién agregado. Conflicto de versión + Deshacer Permite que los informes automáticos de caídas nos ayuden a mejorar el rendimiento de la aplicación. Informe de caída - Deshacer Versión web descartada Versión local descartada Actualizando entrada Descartar Web - Descartar local - Local\nGuardado el %1$s\n\nWeb\nGuardado el %2$s\n Este post tiene dos versiones que están en conflicto. Selecciona la versión que quieras descartar.\n\n + Descartar local Resolver conflicto de sincronización + Local\nGuardado el %1$s\n\nWeb\nGuardado el %2$s\n No hay datos para este período Quita la ubicación de los medios No podemos abrir las estadísticas en este momento. Por favor inténtalo de nuevo más tarde No hay medios que coincidan con tu búsqueda - ¡Busca para encontrar GIF para agregar a tu biblioteca de medios! Vistas Autor Autores @@ -2376,8 +2375,9 @@ Language: es_CL Compartir entrada Crear entrada Ha pasado %1$s desde que %2$s fue publicado. Así es la performance de la entrada hasta ahora: - Ha pasado %1$s desde que %2$s fue publicado. Haz rodar la pelota e incrementa las vistas de tu entrada al compartirlo: + ¡Busca para encontrar GIF para agregar a tu biblioteca de medios! Etiquetas y Categorías + Ha pasado %1$s desde que %2$s fue publicado. Haz rodar la pelota e incrementa las vistas de tu entrada al compartirlo: Todo-el-tiempo %1$s - %2$s Servicio @@ -2425,8 +2425,8 @@ Language: es_CL Mediano Imagen en miniatura Historial - La página seleccionada no está disponible Revisión pendiente + La página seleccionada no está disponible No tienes ninguna página en la papelera No tiene ninguna página programada No tienes ninguna página en borrador @@ -2445,8 +2445,8 @@ Language: es_CL Hemos intentado demasiadas veces enviarte un código de verificación de SMS: Tómate un descanso y solicita uno nuevo en un minuto. No hay ninguna cuenta WordPress.com que coincida con esta cuenta de Google. No hay sitios que coincidan con tu búsqueda - Ningún blog coincide con tu búsqueda Se ha cambiado la página padre + Ningún blog coincide con tu búsqueda La página se ha eliminado permanentemente La página se ha programado La página ha sido publicada @@ -2461,23 +2461,23 @@ Language: es_CL Descartar pulsa aquí Crea tu sitio - Obtén tu sitio y hazlo funcionar. ¿No se siente bien tachar las cosas de una lista? + Obtén tu sitio y hazlo funcionar. Ve tu sitio - Previsualiza tu sitio para ver lo que verán tus visitantes. Comparte tu sitio - Toca en %1$s Social %2$s para continuar - Pulsa en %1$s Conexiones %2$s para agregar tus cuentas de medios sociales Conéctate a tus cuentas de medios sociales – tu sitio compartirá automáticamente nuevos mensajes. + Pulsa en %1$s Conexiones %2$s para agregar tus cuentas de medios sociales + Previsualiza tu sitio para ver lo que verán tus visitantes. + Toca en %1$s Social %2$s para continuar Publicar una entrada Tap %1$s Crear Entrada %2$s para crear una nueva entrada - No, gracias Conecta con otros sitios + No, gracias Ir Cancelar No ahora - Más No tienes ningún sitio + Más Agrega aquí etiquetas para descubrir entradas sobre tus temas favoritos Inicia sesión en la cuenta WordPress.com que usaste para conectar jetpack. Jetpack @@ -2489,278 +2489,278 @@ Language: es_CL No tienes ninguna etiqueta Añade aquí tus etiquetas de uso frecuente para que las puedas seleccionar rápidamente al etiquetar tus entradas Crear una etiqueta - No hay medios que coincidan con tu búsqueda ¿Cerrar sesión de WordPress? + No hay medios que coincidan con tu búsqueda Tienes cambios pendientes de subir en las entradas de tu sitio. Al desconectarse se eliminarán los cambios del dispositivo. ¿Deseas cerrar sesión de todos modos? Aún sin vistas Aún sin usuarios Los posts que te gusten aparecerán aquí Aún no te gusta algo Descubre blogs - Aún no hay “me gusta” Ya que estás en un plan gratuito, verás eventos limitados en tu actividad. - Cuando realices cambios en tu sitio, podrás ver tu historial de actividades aquí + Aún no hay “me gusta” Aún sin actividad - Crear una entrada - Crear una página - Cargar media + Cuando realices cambios en tu sitio, podrás ver tu historial de actividades aquí No tienes ningún medio + Cargar media + Crear una página + Crear una entrada + imagen del tema galería de imágenes ícono del sitio - imagen del tema imagen destacada Descartar imagen de perfil - Pasajero Correo + WordPress + Email de contacto + No establecido Por favor ingresa tu dirección de correo electrónico Para continuar, por favor ingresa tu dirección de correo electrónico y tu nombre Nuevo mensaje desede ‘Ayuda y Soporte’ - WordPress - No establecido - Email de contacto - Restauración en progreso + Pasajero Restaurando a %1$s %2$s + Restauración en progreso + Botón de acción del Registro de Actividad Actualmente restaurando tu sitio - Tu sitio ha sido restaurado satisfactoriamente Tu sitio ha sido restaurado correctamente\nRestaurado a %1$s %2$s + Tu sitio ha sido restaurado satisfactoriamente Tu sitio está siendo restaurado\nRestaurando a %1$s %2$s - Botón de acción del Registro de Actividad Auto-administrado Guarda esta entrada y vuelve cuando quieras para leerla. Solo estará disponible en este dispositivo — las entradas guardadas no se sincronizan con otros dispositivos. - Guardar Entrada para Más tarde - No se pudo realizar la búsqueda No se encontraron resultados - Leer la entrada de origen + No se pudo realizar la búsqueda + Guardar Entrada para Más tarde Sitios + Leer la entrada de origen Enlace mágico enviado - Verificación de código - Credenciales de login - Enlace mágico enviado + Dirección de correo electrónico Inicio de sesión con Enlace Mágico + Enlace mágico enviado + Credenciales de login Dirección del sitio a acceder - Dirección de correo electrónico - Pulse %s para guardar un mensaje en la lista. - No hay mensajes guardados — todavía! + Verificación de código Se guardó la entrada Ver todas - Eliminar de las entradas guardadas + Eliminado Agregar a entradas guardadas + Pulse %s para guardar un mensaje en la lista. + No hay mensajes guardados — todavía! + Eliminar de las entradas guardadas Entradas guardadas - Eliminado - Cambiar el icono del sitio Cancelar Eliminar Cambiar - No tienes permiso para editar el icono del sitio. - No tienes permiso para agregar un icono de sitio. - ¿Cómo te gustaría editar el icono? - ¿Deseas agregar un icono de sitio? Ícono del sitio este sitio Habilitar - ¿Habilitar notificaciones para %1$s%2$s%3$s? - Activar los avisos del blog - Desactivar los avisos del blog + Cambiar el icono del sitio + ¿Deseas agregar un icono de sitio? + No tienes permiso para agregar un icono de sitio. + ¿Cómo te gustaría editar el icono? + No tienes permiso para editar el icono del sitio. Icono de jetpack + Política de Privacidad + Política de Cookies + Registro de actividades Evento Icono de actividad - Registro de actividades + Comparte información con nuestra herramienta de análisis sobre el uso de los servicios mientras estás conectado a tu cuenta de WordPress.com. + Recopilar información + Opciones de privacidad + Esta información nos ayuda a mejorar nuestros productos, hacer marketing más relevante para ti, personalizar tu experiencia en WordPress.com, y más, como se detalla en nuestra política de privacidad. Leer la política de privacidad + ¿Habilitar notificaciones para %1$s%2$s%3$s? Usamos otras herramientas de rastreo, incluyendo algunas de terceras partes. Lee acerca de estos y cómo controlarlos. Política de Terceras Partes - Esta información nos ayuda a mejorar nuestros productos, hacer marketing más relevante para ti, personalizar tu experiencia en WordPress.com, y más, como se detalla en nuestra política de privacidad. - Política de Privacidad - Comparte información con nuestra herramienta de análisis sobre el uso de los servicios mientras estás conectado a tu cuenta de WordPress.com. - Política de Cookies - Opciones de privacidad - Recopilar información + Desactivar los avisos del blog + Activar los avisos del blog Entrada enviada - La característica del plugin requiere que el sitio esté en buena forma. La característica del plugin requiere que la suscripción de dominio principal se asocie con este usuario. - La característica del plugin requiere privilegios de administrador. - El plugin no puede ser instalado en sitios VIP. - El plugin no se puede instalar debido a limitaciones de espacio en disco. + La característica del plugin requiere que el sitio esté en buena forma. La característica del plugin requiere una dirección de correo electrónico verificada. - La característica del plugin requiere que el sitio sea público. + El plugin no se puede instalar debido a limitaciones de espacio en disco. La característica del plugin requiere un plan de negocios. + El plugin no puede ser instalado en sitios VIP. + La característica del plugin requiere privilegios de administrador. La característica del plugin requiere un dominio personalizado. + La característica del plugin requiere que el sitio sea público. Estamos haciendo la configuración final — casi está listo… Instalando plugin… Instalar La instalación del primer plugin en tu sitio puede tardar hasta 1 minuto. Durante este tiempo no podrás realizar cambios en tu sitio. - Instalar plugin - Notificaciones - Enviarme nuevos comentarios Semanalmente - Al instante Diariamente Nuevas entradas - Recibir notificaciones de nuevos entradas de este sitio + Enviarme nuevos comentarios + Al instante Enviarme email en nuevas entradas - Todos Mis Sitios Seguidos - Sitios Seguidos - Persona que lee el dispositivo con notificaciones + Recibir notificaciones de nuevos entradas de este sitio + Notificaciones + Instalar plugin Gente que mira los gráficos + Persona que lee el dispositivo con notificaciones + Sitios Seguidos + Todos Mis Sitios Seguidos %1$s en %2$s ¿Seguro que quieres eliminar definitivamente esta publicación? Importante General Utiliza esta foto %1$d de %2$d + Agregar %d + No se puede guardar un borrador vacío + Elige entre la Biblioteca de Fotos Gratis + Previsualizar %d + %1$s de ilimitado Fotos proporcionadas por %s Busca fotos gratuitas para agregar a tu Biblioteca Multimedia Buscar en la biblioteca de fotos gratis - Elige entre la Biblioteca de Fotos Gratis - No se puede guardar un borrador vacío - %1$s de ilimitado - Previsualizar %d - Agregar %d Crear Etiqueta - navegar hacia arriba - Notificaciones - Abrir enlace externo ver más foto eliminar - Reproducir vídeo - reproducir vídeo destacado - plugin logo banner de plugin - selección de medios de WordPress - cámara abierta - selecciona desde el dispositivo - información de rol reproducir - vista previa de la imagen vista previa audio - reproducir vídeo papelera reintentar - previsualización de medios, nombre de archivo %s eliminar %s + previsualización de medios, nombre de archivo %s + reproducir vídeo + vista previa de la imagen + navegar hacia arriba + Notificaciones + información de rol + cámara abierta + selecciona desde el dispositivo + Reproducir vídeo + selección de medios de WordPress + plugin logo imagen del perfil de %s - marca el check + reproducir vídeo destacado Registrarse con Google… + marca el check + Abrir enlace externo Error en la conexión a Jetpack: %s Ya estás conectado a Jetpack - Modo Visual - Modo HTML Vista previa - Guardar como Borrador %s TB + Modo HTML + Guardar como Borrador + Modo Visual %s GB - %s MB - %s kB - %s B %1$s de %2$s - Si necesitas más espacio considera actualizar tu plan de WordPress. - Espacio Utilizado Multimedia Comentario marcado como no spam Comentario marcado como spam + Cuenta nueva + Comentario aprobado Comentario eliminado - Comentario restaurado - Comentario enviado a la papelera - Ya no me gusta el comentario Me gusta el comentario + Comentario enviado a la papelera Comentario no aprobado - Comentario aprobado - Detalle de notificación %s + Ya no me gusta el comentario + Comentario restaurado Editar Foto + %s B + %s kB + %s MB + Detalle de notificación %s Elegir sitio - Cuenta nueva + Si necesitas más espacio considera actualizar tu plan de WordPress. + Espacio Utilizado Has ingresado como - Detalle de la persona + Yo Detalles del archivo - Botones de compartir + Configuración de notificaciones Notificaciones + Detalle de la persona + Botones de compartir Lector - Yo Mi sitio - Configuración de notificaciones Tu avatar ha sido subido y estará disponible en breve. - Parece que ha desactivado los permisos requeridos para esta función. <br/><br/>Para cambiar esto, edita tus permisos y asegúrate de que <strong>%s</strong> está habilitado. Permisos Destacado - No puedes acceder a tus ajustes para compartir porque tu módulo Social de Jetpack está desactivado. - Módulo Social desactivado Versión %s + Parece que ha desactivado los permisos requeridos para esta función. <br/><br/>Para cambiar esto, edita tus permisos y asegúrate de que <strong>%s</strong> está habilitado. + Módulo Social desactivado + No puedes acceder a tus ajustes para compartir porque tu módulo Social de Jetpack está desactivado. El sonido elegido tiene una ruta de acceso no válida. Por favor, elija otro. QP %s - %1$d páginas/entradas restantes + %1$d páginas/entradas, y 1 archivo restante + %1$d páginas, y 1 archivo restante + %1$d entradas, y 1 archivo restante 1 página restante %1$d páginas restantes + %1$d páginas/entradas restantes %1$d entradas restantes - %1$d páginas/entradas, y 1 archivo restante - %1$d entradas, y 1 archivo restante - %1$d páginas, y 1 archivo restante - 1 entrada, y 1 archivo restante 1 página y 1 archivo restante + 1 página, y %1$d de %2$d archivos restantes %1$d páginas/entradas, y %2$d de %3$d archivos restantes - %1$d entradas, y %2$d de %3$d archivos restantes %1$d páginas, y %2$d de %3$d archivos restantes + 1 entrada, y 1 archivo restante + %1$d entradas, y %2$d de %3$d archivos restantes 1 entrada, y %1$d de %2$d archivos restantes - 1 página, y %1$d de %2$d archivos restantes %1$d entradas/páginas no cargadas %1$d páginas no cargadas + 1 página con %1$d archivos no subidos 1 página no cargada - %1$d entradas no subidas - 1 entrada no subida %1$d entradas/páginas con %2$d archivos no subidos %1$d páginas con %2$d archivos no cargados - 1 página con %1$d archivos no subidos - %1$d entradas con %2$d archivos no cargados 1 entrada con %1$d archivos no subidos + 1 entrada no subida + %1$d entradas con %2$d archivos no cargados + %1$d entradas no subidas + (Sin título) + \@%s + 1 página con 1 archivo no subido %1$d entradas/páginas con 1 archivo no subido %1$d páginas con 1 archivo no subido - 1 página con 1 archivo no subido - %1$d entradas con 1 archivo no subido 1 entrada con 1 archivo no subido - (Sin título) - \@%s + %1$d entradas con 1 archivo no subido Crear sitio - Toca para continuar. ¡Sitio creado! - Google tardó mucho en responder. Es posible que tengas que esperar por una mejor conexión. Cambia tu nombre de usuario - Escribe para obtener más sugerencias - Tu nombre de usuario actual es %1$s %2$s %3$s. Con pocas excepciones, otros sólo verán el nombre mostrado, %4$s %5$s %6$s. - No se sugieren nombres de usuario de %1$s %2$s %3$s. Por favor ingresa más letras o números para obtener sugerencias. - Se ha producido un error al recuperar sugerencias de nombre de usuario. - ¿Descartar cambiar nombre de usuario? - Descartar Guardar Añadir Avatar + Google tardó mucho en responder. Es posible que tengas que esperar por una mejor conexión. + Toca para continuar. El correo electrónico ya existe en WordPress.com.\nProcedemos a Ingresar. - Actualizando cuenta… + Descartar + ¿Descartar cambiar nombre de usuario? + Se ha producido un error al recuperar sugerencias de nombre de usuario. + No se sugieren nombres de usuario de %1$s %2$s %3$s. Por favor ingresa más letras o números para obtener sugerencias. + Tu nombre de usuario actual es %1$s %2$s %3$s. Con pocas excepciones, otros sólo verán el nombre mostrado, %4$s %5$s %6$s. + Escribe para obtener más sugerencias Enviando correo electrónico + Actualizando cuenta… Reintentar Cerrar - Hubo algunos problemas para enviar el correo electrónico. Puedes reintentar ahora o cerrar y volver a intentarlo más tarde. Nombre de usuario - Siempre puedes acceder con un enlace como el que acabas de usar, pero también puedes configurar una contraseña si lo prefieres. - Contraseña (opcional) - Nombre para Mostrar Reintentar + Hubo algún problema al subir tu avatar. Revertir Hubo algunos problemas al actualizar tu cuenta. Puedes reintentar o revertir los cambios para continuar. - Hubo algún problema al subir tu avatar. - Necesita actualización - Buscar Plugins + Nombre para Mostrar + Contraseña (opcional) + Hubo algunos problemas para enviar el correo electrónico. Puedes reintentar ahora o cerrar y volver a intentarlo más tarde. + Siempre puedes acceder con un enlace como el que acabas de usar, pero también puedes configurar una contraseña si lo prefieres. Nuevo Popular - Sin coincidencias - Ver Todos - Administrar - No se puede buscar plugins - Error al instalar %s - Instalado correctamente %s Instalar Me gusta Añadir nuevo sitio Crea un nuevo sitio para tu negocio, revista o blog personal; o conecta una instalación existente de WordPress. + Buscar Plugins + Error al instalar %s + Instalado correctamente %s + Administrar + Necesita actualización + No se puede buscar plugins + Ver Todos + Sin coincidencias Para obtener notificaciones útiles en tu dispositivo desde tu sitio de WordPress, tendrás que instalar el plugin Jetpack. ¿Deseas configurar Jetpack? Carga diferida de imágenes Instalar Jetpack @@ -2771,17 +2771,17 @@ Language: es_CL Versión 5 estrellas 4 estrellas + 1 estrella 3 estrellas 2 estrellas - 1 estrella + Preguntas Más Frecuentes Ninguno proporcionado %s descargas %s calificaciones Leer Reseñas - Preguntas Más Frecuentes - Qué hay de nuevo Instalación Descripción + Qué hay de nuevo Opciones Instalado Versión %s instalada @@ -2789,21 +2789,21 @@ Language: es_CL por %s Cambiar foto No se pueden cargar plugins - Páginas - Administra las etiquetas de tu sitio Guardando Eliminando ¿Eliminar permanentemente la etiqueta \'%s\'? + Administra las etiquetas de tu sitio + Páginas Ya existe una etiqueta con este nombre Agregar nueva etiqueta Descripción Etiqueta Tu sitio WordPress.com soporta el uso de páginas móviles aceleradas, una iniciativa liderada por Google que acelera drásticamente los tiempos de carga en dispositivos móviles Páginas Móviles Aceleradas (AMP) - No se pudieron cargar las zonas horarias Aprende sobre el formato de fecha y hora - Formato personalizado + No se pudieron cargar las zonas horarias Personalizado + Formato personalizado Entradas por página Elige una ciudad en tu zona horaria Zona horaria @@ -2849,15 +2849,15 @@ Language: es_CL Envíame un mensaje con otro código en su lugar Enviaremos un mensaje de texto al número de teléfono que termina en %s. Por favor ingresa el código de verificación indicado en el SMS. Tamaño - 1 archivo restante Faltan %1$d de %2$d archivos + 1 archivo restante 1 entrada restante Subiendo… Escribir Entrada %d archivos cargados correctamente ,%d cargado exitosamente - 1 archivo cargado 1 archivo no subido + 1 archivo cargado %d archivos cargados %d archivos no cargados Quitar de la entrada @@ -2887,22 +2887,22 @@ Language: es_CL Protección contra ataques de fuerza bruta Enviar notificaciones push Enviar notificaciones por correo electrónico - Supervisar el tiempo de funcionamiento del sitio Seguridad - Configuración de Jetpack + Supervisar el tiempo de funcionamiento del sitio + Agregar a librería de medios Agregar a Elegir sitio - Agregar a librería de medios + Configuración de Jetpack Agregar a nueva entrada IP o rango no válido Eliminando ¿Eliminar este vídeo? ¿Eliminar esta imagen? - Detalles del documento Detalles del audio + Detalles del documento Detalles del video - Detalles de la imagen Vista previa + Detalles de la imagen Fecha de Subida Duración Dimensiones de Vídeo @@ -2911,8 +2911,8 @@ Language: es_CL Nombre de Archivo URL Texto alternativo - Conectar un sitio Parpadeo de luz + Conectar un sitio Vibrar dispositivo Seleccionar sonido Visuales y de Sonidos @@ -2927,8 +2927,8 @@ Language: es_CL Activar los avisos Desactivar los avisos Desactivado - Activado Tamaño Máximo del Vídeo + Activado Tamaño Máximo de la Imagen Hubo un error al subir los medios en esta entrada: %s. Hubo un error al subir esta entrada: %s. @@ -2940,8 +2940,8 @@ Language: es_CL Se ha eliminado el medio. ¿Eliminarlo de esta entrada? Error al abrir el explorador Web predeterminado. Por favor, elige otra aplicación: No se puede abrir el vínculo - No pude encontrar la entrada en el servidor Esta entrada ya no existe + No pude encontrar la entrada en el servidor Se canceló la carga de medios Hubo un error al cargar el medio en esta página: %s. Hubo un error al cargar esta página: %s. @@ -2951,45 +2951,45 @@ Language: es_CL Entrada programada Reintentar Entrada en cola - Cargando \"%s\" Se perdió la conexión al servidor - Mis sitios + Cargando \"%s\" Mi sitio + Mis sitios No pude detectar tu aplicación de cliente de correo Introduce un código de verificación Por favor escribe el nombre de usuario Inicia sesión en WordPress.com para acceder a la entrada. Error al agregar el sitio. Código de error: %s Comprobando la dirección del sitio - ¿Necesita más ayuda? Tu dirección de sitio aparece en la barra en la parte superior de la pantalla cuando visitas tu sitio en Chrome. + ¿Necesita más ayuda? ¿Cuál es la dirección de mi sitio? Dirección del sitio Introduce la dirección del sitio WordPress con el que te gustaría conectar. Ya has iniciado sesión en WordPress.com Continuar - Conectar otro sitio Ingresa tu contraseña de WordPress.com. + Conectar otro sitio Solicitando correo de acceso Parece que esta contraseña es incorrecta. Por favor revisa tu información y vuelva a intentarlo. Solicitando un código de verificación vía SMS. Envíame un mensaje con un código en su lugar ¡Casi lo tenemos! Por favor, introduce el código de verificación de tu aplicación Authenticator. - Abrir correo electrónico Siguiente Inicia sesión en WordPress.com usando una dirección de correo electrónico para administrar todos tus sitios de WordPress. - Foto de Perfil + Abrir correo electrónico Respuesta inesperada del servidor + Foto de Perfil No se puede detener la carga porque ya está terminado Título Rehacer Deshacer ¡Disculpas! Esta característica no está implementada todavía :( - Los medios son demasiado pequeños para mostrar ADVERTENCIA: ¡no todos los artículos soltados son soportados! + Los medios son demasiado pequeños para mostrar No se permite colocar imágenes en el Título - Se ha producido un error al soltar texto No se permite el soltado de imágenes en modo html + Se ha producido un error al soltar texto Comparte tu historia aquí… Privado Borrador @@ -3003,12 +3003,12 @@ Language: es_CL Etiquetas Slug Extracto - Sin Asignar Más opciones Categorías y Etiquetas + Sin Asignar Todo - Nivel superior Categoría de padre (opcional): + Nivel superior No tienes audio No tienes ningún documento No tienes videos @@ -3018,16 +3018,16 @@ Language: es_CL El archivo excede el tamaño máximo de carga de este sitio Video demasiado grande para subir Imagen demasiado grande para subirla. Intente cambiar la configuración de Optimizar Imágenes en la aplicación - Audio Vídeos Documentos Imágenes Todo + Audio %1$s denegó el acceso a tus archivos de medios. Para solucionar esto modifica tus permisos y activa %2$s. Ver comentarios Calidad de los vídeos. Los valores más altos significan una mejor calidad de video. - Redimensiona vídeos en entradas a este tamaño Habilitar para cambiar el tamaño y comprimir vídeos + Redimensiona vídeos en entradas a este tamaño Optimizar Vídeos Borrador cargado Calidad de Vídeo @@ -3040,41 +3040,41 @@ Language: es_CL Cambia el texto de la etiqueta de los botones compartir. Este texto no aparecerá hasta que se añada al menos un botón para compartir. Conectando cuenta No se pudo realizar la conexión %s porque no se seleccionó ninguna cuenta. - Conectado Twitter Likes + Conectado Permitir que usted y sus lectores puedan colocar “me gusta” a los comentarios Botones Editar “Más” Botones Un botón “Más” contiene un menú desplegable que muestra los botones de uso compartido Seleccione los botones que se muestran bajo sus mensajes - Nombre de usuario Twitter Me Gusta en Comentarios - Estilo del Botón + Nombre de usuario Twitter Etiqueta + Estilo del Botón Botones compartir Mostrar Botón “Me Gusta” Mostrar Botón Teblog Reblog & Me Gusta Botones Oficiales Sólo Texto - Sólo Ícono - Icono y Texto Selecciona la cuenta que deseas autorizar. Ten en cuenta que las entradas se compartirán automáticamente en la cuenta seleccionada. + Icono y Texto + Sólo Ícono Conectando %s ¿Desconectar de %s? Conectar otra cuenta - Reconectar Desconectar - Conectar Conéctate para compartir automáticamente tus entradas del blog a %s. + Conectar + Reconectar Cuentas conectadas Conecta tus servicios de medios sociales favoritos y comparte automáticamente las entradas nuevas con tus amigos. Notificaciones. Administra tus notificaciones. Lector. Sigue el contenido de otros sitios. Mi sitio. Ve tu sitio y adminístralo, incluyendo estadísticas. - Social No ahora + Social Error de carga. Intenta cambiar la configuración de optimizar imágenes Guardando media a este dispositivo No se puede guardar media @@ -3085,12 +3085,12 @@ Language: es_CL Pulsa y manten pulsado para seleccionar varios comentarios Elige vídeo desde el dispositivo Elige la foto desde el dispositivo - Medios de WordPress Añadir como Galería Agregar individualmente - Agregar varias fotos + Medios de WordPress %d columnas 1 columna + Agregar varias fotos Reenviar email Enviamos un correo electrónico a %s cuando te inscribiste por primera vez. Por favor, abre el mensaje y haga clic en el botón azul para activar la publicación. Te enviamos un email cuando te inscribiste por primera vez. Por favor, abre el mensaje y haz clic en el botón azul para activar la publicación. @@ -3098,8 +3098,8 @@ Language: es_CL Error al enviar correo electrónico de verificación. ¿Ya estás verificado? Email de verificación enviado, revisa tu buzón de entrada Guardar entrada como borrador - Grabar video Tomar foto + Grabar video ¡Ten cuidado! Una vez que eliminas un sitio, no se puede recuperar. Por favor, asegúrate antes de proceder. Todas tus entradas, imágenes y datos serán borrados. Y la dirección de este sitio (%s) se perderá. ¿Eliminar sitio? @@ -3114,11 +3114,11 @@ Language: es_CL Entrada guardada en línea Calidad de las imágenes. Valores más altos significan imágenes de mejor calidad. Habilitar para cambiar el tamaño y comprimir imágenes - Máxima + Subido Alta - Media Baja - Subido + Máxima + Media Falló la Carga Eliminado Eliminando @@ -3129,14 +3129,14 @@ Language: es_CL Formato desconocida de entrada Enviar Suscriptor - Se ha detectado un sitio duplicado. Este sitio ya existe en la aplicación, no se puede agregar. + Se ha detectado un sitio duplicado. Ya estás registrado en una cuenta WordPress.com, no puedes agregar un sitio WordPress.com enlazado a otra cuenta. No se puede cargar el medio Se requiere conexión para actualizar la biblioteca No tienes permiso para ver o editar medios - No se han encontrado medios Se denegó el permiso de lectura a los medios del dispositivo + No se han encontrado medios Optimizar Imágenes Sucedió un error en media Error al cargar medios @@ -3169,8 +3169,8 @@ Language: es_CL Gustando… Procesando… ¡Listo! - Me gusta el comentario Cerrar Sesión + Me gusta el comentario Inicia sesión en WordPress.com Más en WordPress.com Más de %s @@ -3198,21 +3198,21 @@ Language: es_CL Desde %1$s No se pudo quitar al espectador Algunas cargas de archivos fallaron. Puedes cambiar a modo HTML en este estado. ¿Eliminar los archivos que fallaron y continuar? - Miniatura de imagen Editor Visual - Ancho - Enlace a - Texto alternativo - Leyenda + Miniatura de imagen Cambios guardados + Leyenda + Texto alternativo + Enlace a + Ancho ¿Descartar los cambios no guardados? ¿Detener la cargar? Se produjo un error al cargar los archivos Actualmente estás subiendo archivos. Por favor, espera hasta que termine. No se puede insertar medios directamente en modo HTML. Por favor, cambia al modo visual. Cargando Galería… - ¡Toca para volver a intentarlo! Invitación enviada exitosamente + ¡Toca para volver a intentarlo! %1$s: %2$s ¡Invitación enviada pero sucedió un error! ¡Se produjo un error al intentar enviar la invitación! @@ -3222,8 +3222,8 @@ Language: es_CL Mensaje personalizado Invitar Nombres de usuarios o correos electrónicos - Invitar Personas Externos + Invitar Personas Borrar historial de búsqueda ¿Borrar historial de búsqueda? No se encontraron resultados para %s para tu idioma @@ -3249,8 +3249,8 @@ Language: es_CL Ingresando Se muestra públicamente cuando comentas. Capturar o seleccionar foto - Planes Plan + Planes Tus mensajes, páginas y ajustes se te enviarán por correo electrónico a %s. Exporta tu contenido ¡Correo electrónico de exportación enviado! @@ -3291,14 +3291,14 @@ Language: es_CL Imagen Galería Chat - Audio Aside + Audio Información sobre cursos y eventos WordPress.com (online y presencial). Oportunidades para participar en Investigación y encuestas WordPress.com. Consejos para sacar el máximo provecho de WordPress.com. Comunidad - Investigación Sugerencias + Investigación Respuestas a mis comentarios Menciones de usuario Logros del sitio @@ -3336,8 +3336,8 @@ Language: es_CL No hay comentarios en spam Todo No se pudo cargar la página - Desactivado Idioma de la interfaz + Desactivado Acerca de la aplicación No pude guardar la configuración de la cuenta No se pudo recuperar la configuración de tu cuenta @@ -3437,11 +3437,11 @@ Language: es_CL General El más reciente primero Los mas viejos primero - Cerrar después Comentarios Publicaciones relacionadas Privacidad Discusión + Cerrar después No tienes permiso para cargar medios en este sitio Desconocida Nunca @@ -3455,11 +3455,11 @@ Language: es_CL Algo salió mal. No se pudo activar el tema por %1$s Gracias por elegir %1$s - ADMINISTRAR SITIO - LISTO Soporte Detalles Ver + ADMINISTRAR SITIO + LISTO Prueba y Personaliza Activar Activo @@ -3501,18 +3501,18 @@ Language: es_CL No se han podido cargar los ajustes de avisos Me gusta al comentario Avisos de la aplicación - Correo electrónico Pestaña de avisos + Correo electrónico Siempre enviaremos correos electrónicos importantes con respecto a su cuenta, pero también puedes conseguir algunos extras útiles. Sumario de la Última Entrada Sin conexión Entrada enviada a la papelera - Papelera Estadísticas + Papelera Vista previa Ver - Publicar Editar + Publicar No se pudo encontrar este blog Deshacer La solicitud ha expirado. Inicia sesión en WordPress.com para intentarlo de nuevo. @@ -3522,236 +3522,236 @@ Language: es_CL Entradas, vistas y visitantes de todos los tiempos Detalles Cerrar sesión de WordPress.com - Iniciar sesión en WordPress.com Iniciar/Cerrar sesión - Preferencias de la Cuenta + Iniciar sesión en WordPress.com \"%s\" no se ocultó porque es el sitio actual + Preferencias de la Cuenta Crear sitio WordPress.com Añadir sitio autoalojado - Agrega un sitio Mostrar/Ocultar sitios - Elegir sitio + Agrega un sitio Ver sitio - Ver Administrador + Elegir sitio Cambiar sitio - Ajustes del sitio - Entradas - Publicar + Ver Administrador Aspecto + Publicar + Entradas + Ajustes del sitio Configuración Toca para mostrarlos Anular todas las selecciones - Seleccionar todo - Ocultar Mostrar - Inicie sesión de nuevo para continuar. - Código de verificación no válido - Código de verificación + Ocultar + Seleccionar todo Idioma + Código de verificación + Código de verificación no válido + Inicie sesión de nuevo para continuar. No fue posible cargar las entradas No se pudo abrir la notificación - Términos de Búsqueda Desconocidos - Términos de búsqueda Autores + Términos de búsqueda Recuperando páginas… Recuperando entradas… Recuperando medios… + Términos de Búsqueda Desconocidos Los informes de la aplicación se han copiado al portapapeles - Este blog está vacío Nuevas entradas Ocurrió un error al copiar el texto en el portapapeles Subiendo entrada - %1$d años - Un año + Este blog está vacío + Obteniendo temas… %1$d meses + Un año + %1$d años Un mes - %1$d días - Un día - %1$d horas - hace una hora %1$d minutos + hace una hora + %1$d horas + Un día + %1$d días hace un minuto hace unos segundos Vídeos - Entradas y Páginas Países Me gusta - Visitantes - Vistas Años - Obteniendo temas… + Vistas + Visitantes + Entradas y Páginas Detalles %d seleccionados - Revisa nuestras Preguntas Más Frecuentes Aún no hay comentarios - Me gusta Ver artículo original + Me gusta Los comentarios están cerrados %1$d de %2$d - No se puede publicar una entrada vacía - No tienes permiso para ver o editar entradas - No tienes permiso para ver o editar páginas - Más Hace más de 1 mes - Hace más de 1 semana Hace más de 2 días - Ayuda y soporte + Hace más de 1 semana Me gustó Comentario - Comentario eliminado - Responder a %s Aún no se han publicado entradas. ¿Por qué no crear una? + Responder a %s Cerrar sesión… + Comentario eliminado + Más + No tienes permiso para ver o editar páginas + No tienes permiso para ver o editar entradas + No se puede publicar una entrada vacía + Revisa nuestras Preguntas Más Frecuentes + Ayuda y soporte No es posible realizar esta acción - Programación Actualizar + Programación Introduce una URL o etiqueta para seguir - SI normalmente se conecta sin problemas a este sitio sin problemas, este error puede significar que alguien están intentando suplantar el sitio, por lo que no deberías continuar. ¿Quieres, de todas formas, confiar en el certificado? - Certificado SSL no válido Ayuda - El usuario o contraseña que ingresaste no son correctos - Ingresa una dirección de correo electrónico válida - Tu dirección de correo electrónico no es válida - Error al descargar la imagen - No se pudo cargar el comentario - Ocurrió un error al editar el comentario - Ocurrió un error al moderar el comentario - Ocurrió un error + Certificado SSL no válido + SI normalmente se conecta sin problemas a este sitio sin problemas, este error puede significar que alguien están intentando suplantar el sitio, por lo que no deberías continuar. ¿Quieres, de todas formas, confiar en el certificado? + El elemento multimedia no ha podido ser recuperado + Ha ocurrido un error mientras se accedía a este blog + No es spam + No se pudo añadir la categoría + El campo nombre de categoría es necesario + Se necesita una tarjeta SD montada para subir medios + Sin notificaciones + Las entradas no pueden ser actualizadas en este momento No se pudieron actualizar los comentarios + Ocurrió un error + Ocurrió un error al moderar el comentario + Ocurrió un error al editar el comentario + No se pudo cargar el comentario + Error al descargar la imagen + Tu dirección de correo electrónico no es válida + Ingresa una dirección de correo electrónico válida + No hay conexiones de red disponible + El usuario o contraseña que ingresaste no son correctos Las páginas no pueden ser actualizadas en este momento - Las entradas no pueden ser actualizadas en este momento - Se ha producido un error al eliminar la entrada - Sin notificaciones - Se necesita una tarjeta SD montada para subir medios - El campo nombre de categoría es necesario Categoría agregada correctamente - No se pudo añadir la categoría - No es spam Ocurrió un error al obtener los temas - Ha ocurrido un error mientras se accedía a este blog - El elemento multimedia no ha podido ser recuperado - No hay conexiones de red disponible - No se pudo eliminar esta etiqueta - No se pudo agregar esta etiqueta + Se ha producido un error al eliminar la entrada + Seleccionar categorías + Error de conexión + Ocurrió un error al cargar la entrada. Actualiza tus entradas e intenta nuevamente. + Aprender más + Malla (red) de miniaturas + No tienes permiso para ver la librería multimedia + Texto del enlace (opcional) + Crear un enlace + Ajustes de página + Borrador local + Alineación horizontal + Ajustes de entrada + Aprobado + Pendiente + Spam + En la papelera + Editar comentario + Aprobar + Rechazar + Spam + Enviar a la papelera + ¿Enviar a la papelera? + Papelera + Guardando cambios + Eliminar sitio + Ver en el navegador + Añadir nueva categoría + Nombre de la categoría + No se pudo crear un archivo temporal para subir el archivo multimedia. Asegúrate que haya suficiente espacio libre en tu dispositivo. + Se necesita autorización + Nueva entrada + Nuevo elemento multimedia + Cambios locales + Ajustes de imagen + Blog de WordPress + Este blog está oculto y no se puede cargar. Actívalo de nuevo en ajustes y prueba de nuevo. Registro de la aplicación Hubo un error al crear la base de datos de la app. Por favor, intenta reinstalar la app. - Este blog está oculto y no se puede cargar. Actívalo de nuevo en ajustes y prueba de nuevo. + Algunos elementos multimedia no pudieron ser borrados. Prueba más tarde. No se puede actualizar Media en este momento - Blog de WordPress - Ajustes de imagen - Cambios locales - Nuevo elemento multimedia - Nueva entrada Sin notificaciones… aún. - Se necesita autorización Comprueba que la URL del sitio ingresada es válida - No se pudo crear un archivo temporal para subir el archivo multimedia. Asegúrate que haya suficiente espacio libre en tu dispositivo. - Nombre de la categoría - Añadir nueva categoría - Ver en el navegador - Eliminar sitio - Guardando cambios - Papelera - ¿Enviar a la papelera? - Enviar a la papelera - Spam - Rechazar - Aprobar - Editar comentario - En la papelera - Spam - Pendiente - Aprobado ¿Eliminar página? ¿Eliminar entrada? - Ajustes de entrada No se pudo encontrar el archivo para cargar. ¿Lo eliminaste o moviste? - Alineación horizontal - Borrador local - Ajustes de página - Crear un enlace - Texto del enlace (opcional) - Algunos elementos multimedia no pudieron ser borrados. Prueba más tarde. - No tienes permiso para ver la librería multimedia - Malla (red) de miniaturas - Aprender más - Ocurrió un error al cargar la entrada. Actualiza tus entradas e intenta nuevamente. Se ha producido un error al acceder a este plugin - Error de conexión - Seleccionar categorías + No se pudo agregar esta etiqueta + No se pudo eliminar esta etiqueta Compartir enlace Recuperando entradas… A ti, y a %,d personas más les gusta esto A %,d personas les gusta esto - No puedes compartir en WordPress sin un blog visible Comentado marcado como spam + No puedes compartir en WordPress sin un blog visible Comentario no aprobado + Elige una foto + Elige un vídeo No fue posible cargar esta entrada A ti y a otra persona les gusta esto - Elige un vídeo - Elige una foto - Registro - No se pudo abrir %s - No se pudo ver la imágen - No se pudo compartir - Esa no es un etiqueta válida - No se pudo publicar tu comentario - Te gusta esto - A una persona le gusta esto + Esta lista esta vacía + Compartir + Seguir Eliminado %s + A una persona le gusta esto + Te gusta esto Agregado %s + No se pudo compartir + No se pudo ver la imágen + No se pudo abrir %s + No se pudo publicar tu comentario Contestar el comentario… - Seguir - Compartir - Reblog (Sin título) Aún no hay comentarios - Esta lista esta vacía - Meses - Semanas - Días - Ayer - Hoy - Referentes - Etiquetas y categorías - Clics - Estadísticas - Compartir - Activar - No se pudo actualizar - Descripción - Leyenda + Esa no es un etiqueta válida + Reblog + Registro + Temas + Cuadrados + Mosaico + Círculos Título + Leyenda + Descripción + No se pudo actualizar + Activar + Compartir + Estadísticas + Clics + Etiquetas y categorías + Referentes + Hoy + Ayer + Días + Semanas + Meses Pase de diapositivas - Círculos - Mosaico - Cuadrados - Temas Descartar Administrar - y %d más. - %d nuevas notificaciones Respuesta publicada + %d nuevas notificaciones + y %d más. Iniciar Sesión Cargando… - Contraseña HTTP Usuario HTTP + Contraseña HTTP Se ha producido un error al cargar los archivos Nombre de usuario o contraseña incorrecta. - Iniciar sesión - Nombre de usuario Contraseña + Nombre de usuario + Iniciar sesión Lector - Incluír imagen en el contenido del mensaje Usar como imagen destacada - Ancho - Leyenda (opcional) + Incluír imagen en el contenido del mensaje + No hay red disponible Páginas + Leyenda (opcional) + Ancho Entradas Anónimo - No hay red disponible - hecho OK + hecho URL Subiendo… Alineamiento @@ -3764,27 +3764,27 @@ Language: es_CL El nombre del acceso directo no puede ser vacío Privado Título - Separa las etiquetas con comas Categorías + Separa las etiquetas con comas Requiere tarjeta SD Multimedia Categoría actualizada correctamente - Aprobar Eliminar - Actualizando la categoría que falló + Aprobar Ninguno - Publicar ahora - Responder - en - Vista previa - Error de actualización de categorías + Actualizando la categoría que falló Error - No - - Ajustes de avisos - Añadir - Guardar Cancelar + Guardar + Añadir + Error de actualización de categorías + Vista previa + en + Responder + Ajustes de avisos + + No + Publicar ahora Una vez Dos veces diff --git a/WordPress/src/main/res/values-gl/strings.xml b/WordPress/src/main/res/values-gl/strings.xml index 70efa8546730..42259fc46fb2 100644 --- a/WordPress/src/main/res/values-gl/strings.xml +++ b/WordPress/src/main/res/values-gl/strings.xml @@ -7,225 +7,225 @@ Language: gl_ES --> Subscritor + Subscritores Subscritor por correo electrónico - Aínda non hai subscritores por correo electrónico - Aínda non hai subscritores Subscritores por correo electrónico - Subscritores + Aínda non hai subscritores %s: Xa suscrito + Aínda non hai subscritores por correo electrónico Non hai aplicación de cámara dispoñible. Non se puido eliminar o subscritor - Non se puideron recuperar os subscritores por correo electrónico do sitio Non se puideron recuperar os subscritores do sitio - Non se puido engadir ao calendario - Non se encontrou ningunha aplicación para xestionar a solicitude de engadir ao calendario - Subscricións ao sitio + Non se puideron recuperar os subscritores por correo electrónico do sitio Subscritores Subscritores + Subscricións ao sitio Aínda non hai subscritores + Non se puido engadir ao calendario + Non se encontrou ningunha aplicación para xestionar a solicitude de engadir ao calendario Correos electrónicos + Clics Subscritores Subscritores totais Totais de subscritores %1$s: %2$s, %3$s: %4$s, %5$s: %6$s - Clics + Nome Aperturas + Subscritor + Subscritores Últimos correos electrónicos Subscritor desde - Nome - Subscritores - Subscritor Total de subscritores de %1$s: %2$s Hai unha revisión máis recente desta páxina Actualizando o contido Subscritores - A semana pasada tiveches %1$s visitas e 1 comentario A semana pasada tiveches %1$s visitas e 1 Gústame + A semana pasada tiveches %1$s visitas e 1 comentario A semana pasada tiveches %1$s visitas, 1 Gústame e 1 comentario. - A semana pasada tiveches %1$s visitas, %2$s Gústame e 1 comentario. - A semana pasada tiveches %1$s visitas, 1 Gústame e %2$s comentarios. - Sitios recentes Todos os sitios - Sitios fixos Editar pins - Fixeches cambios nesta páxina desde outro dispositivo e non os gardaches. Selecciona a versión da páxina que queres conservar. - Fixeches cambios nesta entrada desde outro dispositivo e non os gardaches. Selecciona a versión da entrada que queres conservar. - Autogardado dispoñible + Sitios recentes + Sitios fixos Outro dispositivo Dispositivo actual + Autogardado dispoñible + A semana pasada tiveches %1$s visitas, %2$s Gústame e 1 comentario. + A semana pasada tiveches %1$s visitas, 1 Gústame e %2$s comentarios. A páxina modificouse noutro dispositivo. Selecciona a versión da páxina que queres conservar. A entrada modificouse noutro dispositivo. Selecciona a versión da entrada que queres conservar. + Fixeches cambios nesta páxina desde outro dispositivo e non os gardaches. Selecciona a versión da páxina que queres conservar. + Fixeches cambios nesta entrada desde outro dispositivo e non os gardaches. Selecciona a versión da entrada que queres conservar. Resolver conflito - Extra grande + Fonte Grande - Normal Pequena - Extra pequena + Normal Tamaño de fonte - Fonte + Extra grande + Extra pequena Esquema de cor - envía os teus comentarios <Experimental> - Baleirar a cor seleccionada + envía os teus comentarios Non segues etiquetas + Baleirar a cor seleccionada Xa estás seguindo esta etiqueta - Preferencias de lectura - Etiquetas seguidas + OLED + Suave Caramelo h4x0r - OLED - Noite Sepia - Suave + Noite Por defecto + Etiquetas seguidas envía os teus comentarios + Preferencias de lectura Esta é unha nova característica aínda en desenvolvemento. Para axudarnos a mellorala %s. Elixe as túas cores, fontes e tamaños. Previsualiza aquí a túa selección e le entradas cos teus estilos cando remates. Preferencias de lectura Segue unha etiqueta Ler - Podes copiar o texto da túa entrada en caso de que o teu contido se vexa afectado. Copia os detalles do erro para depuralo e compartilo co servizo de asistencia. - O editor atopou un erro inesperado. - Pulsa aquí para copiar o texto da entrada. - Pulsa aquí para copiar os detalles do erro. Copiar texto da entrada Copiar detalles do erro Botón para copiar o texto da entrada + Pulsa aquí para copiar o texto da entrada. Botón para copiar os detalles do erro + Pulsa aquí para copiar os detalles do erro. + O editor atopou un erro inesperado. + Podes copiar o texto da túa entrada en caso de que o teu contido se vexa afectado. Copia os detalles do erro para depuralo e compartilo co servizo de asistencia. Erro ao actualizar o contido + Non lido + Editar o vídeo + Marcar todo como lido Lenda do vídeo. %s Lenda do vídeo. Baleiro - Editar o vídeo A reprodución automática pode provocar problemas de usabilidade a algúns usuarios. - Marcar todo como lido - Non lido - Sitio non encontrado. Comproba que iniciaches sesión coa conta correcta. Feito - As actualizacións poden tardar algún tempo en sincronizarse co teu perfil de Gravatar. Que é Gravatar? - Se actualizas aquí o teu avatar, nome e información sobre ti, tamén se actualizarán en todos os sitios que utilicen perfís Gravatar. O teu perfil de WordPress.com funciona con Gravatar + As actualizacións poden tardar algún tempo en sincronizarse co teu perfil de Gravatar. + Sitio non encontrado. Comproba que iniciaches sesión coa conta correcta. + Se actualizas aquí o teu avatar, nome e información sobre ti, tamén se actualizarán en todos os sitios que utilicen perfís Gravatar. No se poden cargar os medios para compartir. Comproba os permisos da aplicación\n ou utiliza a biblioteca de medios. Non podemos abrir a monitorización do sitio neste momento. Por favor, inténtao de novo máis tarde - Rexistros do servidor web - Rexistros de PHP Métricas + Rexistros de PHP + Rexistros do servidor web Supervisión do sitio - Utiliza <b>Descubrir</b> para encontrar sitios e etiquetas. Proba a seleccionar <b>Subscricións</b> para ver o contido subscrito e xestionar as túas subscricións. Ir a subscricións Os blogs aos que estás subscrito non publicaron nada recientemente Subscríbete a blogs en Descubrir ou busca un blog que xa che guste. + Utiliza <b>Descubrir</b> para encontrar sitios e etiquetas. Proba a seleccionar <b>Subscricións</b> para ver o contido subscrito e xestionar as túas subscricións. Non hai blogs recomendados Non hai entradas con esta etiqueta Non se puido bloquear este blog - As entradas deste blog xa non se mostrarán Non se puido cancelar a subscrición ao blog - Non tes autorización para acceder a este blog Non é posible subscribirse a este blog - Xa estás subscrito a este blog. - Non se pode amosar este blog - Elixe os teus intereses + Non tes autorización para acceder a este blog + As entradas deste blog xa non se mostrarán 1 subscritor + Elixe os teus intereses + Non se pode amosar este blog + Xa estás subscrito a este blog. + Etiqueta + Subscribirse + Subscrito + Subscrito + Seguir etiquetas + Blog do lector %s subscritores %,d subscritores Blog subscrito - Buscar blogs subscritos - Subscrito - Subscribirse Bloquear este blog - Editar etiquetas e blogs Blogs subscritos - Seguir etiquetas + Editar etiquetas e blogs Xestionar etiquetas e blogs - Etiqueta - Blog do lector - Subscrito - %d etiquetas + Buscar blogs subscritos 1 etiqueta + Listas + Gustoume + Gardado 0 etiquetas - %d blogs 1 blog + Buscar + %d etiquetas 0 blogs - Listas + %d blogs + Descubrir Automattic - Gustoume - Gardado Subscricións - Descubrir - Buscar - Seguir etiquetas - Blogs aos que subscribirse Etiquetas recomendadas Buscar un blog + Blogs aos que subscribirse + Seguir etiquetas Sigue unha etiqueta e poderás ve as mellores publicacións asociadas a ela. Sen etiquetas Subscríbete a blogs en Descubrir e verás as súas últimas publicacións aquí. Ou busca un blog que xa che guste. - Non hai subscricións ao blog - Subscríbete a un blog - Ver as últimas entradas dos blogs aos que estás subscrito Filtrar por etiqueta Filtrar por blog - Esperando conexión + Subscríbete a un blog + Non hai subscricións ao blog + Ver as últimas entradas dos blogs aos que estás subscrito Tráfico + Esperando conexión Traballo sen conexión + Tamaño da fonte, %1$s Conexión de rede restablecida Conexión de rede perdida, traballando sen conexión - Tamaño da fonte, %1$s Tipo de arquivo non admitido como arquivo de medios. - Non podemos abrir as páxinas neste momento. Por favor, inténtao de novo máis tarde - Simplemente busca un dominio - Mellora a un plan - Rexistra ou transfire un dominio gratis durante un ano con calquera plan de pago anual. + %s Nunca caduca - O teu dominio gratuíto de WordPress.com - Outros dominios para %s Dominio principal - %s + Mellora a un plan + Outros dominios para %s + Simplemente busca un dominio + O teu dominio gratuíto de WordPress.com + Non podemos abrir as páxinas neste momento. Por favor, inténtao de novo máis tarde + Rexistra ou transfire un dominio gratis durante un ano con calquera plan de pago anual. Bloganuary xa está aquí! Imos aló! - Activa as suxestións de publicación Bloganuary utilizará as suxerencias de publicación diarias para enviarche temas durante o mes de xaneiro. Bloganuary usará as suxerencias diarias de publicación para enviarche temas para o mes de xaneiro. Actualmente tes desactivadas as suxerencias de publicación. + Activa as suxestións de publicación Le as respostas doutros blogueiros para conseguir inspiración e facer novas conexións. + Bloganuary + Bloganuary está á volta da esquina! Publica a tú resposta. - Recibe unha suxerencia nova para inspirarte cada día. Únete ao noso reto de escritura dun mes - Bloganuary + Recibe unha suxerencia nova para inspirarte cada día. Durante o mes de xaneiro, as suxerencias para escribir no blog provirán de Bloganuary, o noso reto comunitario para crear un hábito de blogueo para o novo ano. - Bloganuary está á volta da esquina! - Por esta razón, recomendámosche que edites o bloque utilizando o teu navegador web. - Por este motivo, recomendámosche que edites o bloque utilizando o editor web. - Tamén podes aplanar o contido desagrupando o bloque. - Ir aos axustes - Cancelar Conceder + Cancelar + Ir aos axustes + Tamén podes aplanar o contido desagrupando o bloque. + Por este motivo, recomendámosche que edites o bloque utilizando o editor web. + Por esta razón, recomendámosche que edites o bloque utilizando o teu navegador web. Denegaches de forma permanente o permiso da cámara. É necesario para escanear o código de barras. Actívao nos axustes da aplicación - Necesítase o permiso da cámara para escanear o código de barras + Escanear o código de barras Conceder permiso á cámara Necesítase o permiso da cámara para escanear o código de barras. - Escanear o código de barras + Necesítase o permiso da cámara para escanear o código de barras É posible que os bloques aniñados a máis de %d niveis non se mostren correctamente no editor móbil. Imos - É hora de continuar a túa xornada de WordPress na aplicación Jetpack. Baleirar a busca + É hora de continuar a túa xornada de WordPress na aplicación Jetpack. Moi alta + Usa unha clave de seguridade Introduce a túa clave de seguridade para continuar. Houbo algúns problemas coa clave de seguridade de inicio de sesión - Usa unha clave de seguridade - Non se puideron recuperar os dominios - %s durante o primeiro ano - %s / ano - Transferir dominio - Queres transferir un dominio que xa tes? - Teclea para obter máis suxerencias - Buscar un dominio OK - Algo saíu mal ao engadir o dominio ao carriño. Asegúrate de que estás conectado e volve a intentalo. - Erro Todos - Non se puideron recuperar os teus dominios + Erro + %s / ano Dominio do sitio + Transferir dominio + Buscar un dominio + %s durante o primeiro ano De <b>Bloganuary</b> + Non se puideron recuperar os dominios + Teclea para obter máis suxerencias + Non se puideron recuperar os teus dominios + Queres transferir un dominio que xa tes? + Algo saíu mal ao engadir o dominio ao carriño. Asegúrate de que estás conectado e volve a intentalo. Editado Filtrar por autor Bloque \'%s\' convertido a bloques @@ -249,12 +249,12 @@ Language: gl_ES Busca un dominio Toca a continuación para atopar o teu dominio perfecto. Non tes ningún dominio - Comproba que estás en liña e tira para actualizar. Abre os detalles do dominio Busca nos teus dominios Comprar un dominio - Todos os dominios Caduca o %1$s + Comproba que estás en liña e tira para actualizar. + Todos os dominios Conta e axustes Selecciona un plan Gratis durante o primeiro ano cos plans de pago anuais @@ -283,13 +283,13 @@ Language: gl_ES Borradores de publicacións Vistas, visitantes e gústame As tarxetas poden amosar contido diferente dependendo do que este a suceder co teu sitio - Engadir ou ocultar tarxetas - Personaliza a pestana de inicio Toca para personalizar a túa pestana de inicio Personaliza a túa pestana de inicio Cambiar os axustes Selecciona Máis Só están dispoñibles as fotos e os vídeos seleccionados aos que deches acceso. + Engadir ou ocultar tarxetas + Personaliza a pestana de inicio Ver todas as campañas Toda a actividade Todas as páxinas @@ -304,69 +304,69 @@ Language: gl_ES Accede a este bloque de Paywall no teu navegador web para axustes avanzados. Resposta: Pregunta: - Transcrición do bot móbil de Jetpack: - Erro ao enviar a petición de asistencia Petición creada Creando petición de asistencia… - Como poido utilizar o meu dominio personalizado na aplicación? - Non me acordo dos meus datos de acceso + Transcrición do bot móbil de Jetpack: + Erro ao enviar a petición de asistencia + Contactar co soporte técnico + Enviar unha mensaxe… Por que non poido acceder? - Non poido subir fotos/vídeos + Non estás seguro/a de que preguntar? Axuda, o meu sitio non funciona. Cal é o enderezo do meu sitio? - Non estás seguro/a de que preguntar? - Contactar co soporte técnico + Non poido subir fotos/vídeos + Non me acordo dos meus datos de acceso + Como poido utilizar o meu dominio personalizado na aplicación? En que che podo axudar? - Enviar unha mensaxe… Borrar %1$d compartidas en redes sociais restantes PECHAR - Á app de WordPress fáltanlle compoñentes obrigatorios e debe ser reinstalada da Google Play Store. - Instalación fallida - Algo saíu mal - Algo saíu mal - Algo saíu mal, non se puideron obter as campañas Contas conectadas Compartir en redes sociais Compartir en redes sociais Redes sociais - Compartindo en %1$d contas - Compartindo en %1$d de %2$d contas - Compartindo en %1$s - Non se compartirá en ningunha rede social - Personaliza a mensaxe que queres compartir. Se non engades o teu propio texto aquí, usaremos o título da entrada como mensaxe. + Instalación fallida + Algo saíu mal + Algo saíu mal + Algo saíu mal, non se puideron obter as campañas + Á app de WordPress fáltanlle compoñentes obrigatorios e debe ser reinstalada da Google Play Store. Personalizar a mensaxe Agora non Contas conectadas + Compartindo en %1$s + Non se compartirá en ningunha rede social + Compartindo en %1$d contas + Compartindo en %1$d de %2$d contas + Personaliza a mensaxe que queres compartir. Se non engades o teu propio texto aquí, usaremos o título da entrada como mensaxe. Insertar bloque de vídeo Insertar bloque de imaxe - Insertar bloque de galería Insertar bloque de audio + Insertar bloque de galería Crear - Aínda non creaches ningunha campaña. Fai clic en Crear para empezar. - Non tes campañas - Detalles da campaña - Campañas de Blaze - Orzamento Clics Impresións - PROGRAMADA - EN MODERACIÓN + Pechar o editor + Orzamento + ACTIVA CANCELADA REXEITADA + PROGRAMADA COMPLETADA - ACTIVA - Crear campaña + EN MODERACIÓN Campaña de Blaze - Non se puido cargar o fluxo de promoción de Blaze - Aumenta o tráfico compartindo automaticamente as entradas cos teus amigos a través das redes sociais. - Pechar o editor + Campañas de Blaze + Crear campaña + Detalles da campaña Refacer o último cambio Desfacer o último cambio - 1 entrada compartida en redes sociais restante + Non tes campañas Subscríbete agora para compartir máis - Aumenta o tráfico compartindo automaticamente as entradas cos teus amigos a través das redes sociais. + 1 entrada compartida en redes sociais restante + Non se puido cargar o fluxo de promoción de Blaze + Aínda non creaches ningunha campaña. Fai clic en Crear para empezar. + Aumenta o tráfico compartindo automaticamente as entradas cos teus amigos a través das redes sociais. Compartir en redes sociais + Aumenta o tráfico compartindo automaticamente as entradas cos teus amigos a través das redes sociais. %s separado A edición de padróns sincronizados aínda non está incluída en %s para iOS A edición de padróns sincronizados aínda non está incluída en %s para Android @@ -374,94 +374,94 @@ Language: gl_ES Produciuse un erro ao gardar as túas opcións de privacidade. Gardar Axustes - Permítenos optimizar o rendemento mediante a recompilación de información sobre a forma na que os usuarios interactúan coas nosas aplicacións para móbiles. Analítica Xestión da privacidade - A túa privacidade é extremamente importante para nós e sempre o foi. Utilizamos, almacenamos e procesamos os teus datos persoais para optimizar a nosa aplicación (e a túa experiencia) de diversas maneiras. Algúns usos dos teus datos son absolutamente necesarios para que as cousas funcionen, e outros podes personalizalos nos Axustes. Eu. Xestionar os detalles do teu perfil. + Permítenos optimizar o rendemento mediante a recompilación de información sobre a forma na que os usuarios interactúan coas nosas aplicacións para móbiles. + A túa privacidade é extremamente importante para nós e sempre o foi. Utilizamos, almacenamos e procesamos os teus datos persoais para optimizar a nosa aplicación (e a túa experiencia) de diversas maneiras. Algúns usos dos teus datos son absolutamente necesarios para que as cousas funcionen, e outros podes personalizalos nos Axustes. Mensaxe - Bloque desagrupado + Aprende máis sobre os modelos + Páxina de inicio Bloque agrupado - O dominio pode tardar ata 30 minutos en empezar a funcionar correctamente. - O teu novo dominio <b>%s</b> estase configurando. + Bloque desagrupado + Pechouse a conta. Todo listo! - Obtén un dominio gratuíto durante o primeiro ano, elimina os anuncios do teu sitio e aumenta o teu espazo de almacenamento. Consigue un dominio gratis cun plan anual - Aprende máis sobre os modelos + O teu novo dominio <b>%s</b> estase configurando. + O dominio pode tardar ata 30 minutos en empezar a funcionar correctamente. A túa páxina de inicio usa un modelo de tema, polo que se abrirá no editor web. - Páxina de inicio - Pechouse a conta. + Obtén un dominio gratuíto durante o primeiro ano, elimina os anuncios do teu sitio e aumenta o teu espazo de almacenamento. Ocorreu un erro ao pechar a conta. Non é posible pechar a conta deste usuario porque ten compras activas. Non é posible pechar a conta deste usuario porque ten subscricións activas. + Confirmar o peche da conta… Non é posible pechar a conta deste usuario se ten cargos rexeitados sen resolver. Non é posible pechar a conta deste usuario de inmediato porque ten compras activas. Contacta co noso equipo de soporte para eliminar a conta definitivamente. Non tes autorización para pechar a conta. Non se puido pechar a conta automaticamente! - Confirmar o peche da conta… Para confirmar, volve a introducir o teu nome de usuario antes de cerrala. Pechar conta Saber máis - O uso compartido automático de Twitter xa non está disponible debido aos cambios de Twitter nos termos e prezos. A opción de compartir automaticamente en Twitter xa non está dispoñible + O uso compartido automático de Twitter xa non está disponible debido aos cambios de Twitter nos termos e prezos. A edición de bloques reutilizables aínda non é compatible con %s para iOS. A edición de bloques reutilizables aínda non é compatible con %s para Android. Permitir avisos para estar ao día co teu sitio A aplicación JetPack ten todas as funcionalidades da aplicación WordPress, e agora acceso exclusivo a Estatísticas, Lector, Avisos e máis. Usar WordPress con %s na aplicación\u00A0JetPack. Usar WordPress con %s na aplicación\u00A0JetPack. - Cor sen etiquetar. %s Actividade recente - Como no exemplo superior, un dominio permítelle á xente encontrar e visitar o teu sitio desde o seu navegador. ONomeDaTuaWeb.com + Cor sen etiquetar. %s + Como no exemplo superior, un dominio permítelle á xente encontrar e visitar o teu sitio desde o seu navegador. + o primeiro ano Buscar con palabras clave + Enviámosche o teu recibo por correo electrónico. %s + Pode tardar ata 30 minutos en que o teu dominio personalizado empece a funcionar. Busca unha dominio curto e memorable para axudar á xente a encontrar e visitar o teu sitio. - o primeiro ano A túa web creouse correctamente, pero encontramos un problema ao preparar o teu dominio personalizado ao finalizar a compra. Por favor, inténtao de novo ou contacta co noso soporte para obter axuda. - Pode tardar ata 30 minutos en que o teu dominio personalizado empece a funcionar. - Enviámosche o teu recibo por correo electrónico. %s As notificacións da app desactiváronse. Pulsa aquí para activalas. - Recomendamos <b>desinstalar a aplicación WordPress</b> no teu dispositivo para evitar conflitos de datos. - Parece que aínda tes a aplicación WordPress instalada. Xa non necesitas a aplicación WordPress no teu dispositivo - Recomendamos <b>desinstalar a aplicación WordPress</b> no teu dispositivo para evitar conflitos de datos. + Parece que aínda tes a aplicación WordPress instalada. Benvido á aplicación Jetpack. Podes desinstalar a aplicación WordPress. + Recomendamos <b>desinstalar a aplicación WordPress</b> no teu dispositivo para evitar conflitos de datos. + Recomendamos <b>desinstalar a aplicación WordPress</b> no teu dispositivo para evitar conflitos de datos. Eliminar bloques Privacidade e valoracións - Axustes de reprodución - Cor da barra de reprodución Manual Dinámica - Describe o propósito da imaxe. Déixao baleiro se a imaxe é decorativa. - Comeza con deseños personalizados e preparados para dispositivos móbiles + Axustes de reprodución + Cor da barra de reprodución Crear outra páxina Engadir páxinas ao teu sitio + Comeza con deseños personalizados e preparados para dispositivos móbiles + Describe o propósito da imaxe. Déixao baleiro se a imaxe é decorativa. Para usar recordatorios para publicar, tes que activar os avisos instantáneos. - Activar os avisos instantáneos - Continuar con subdominio Comprar dominio - Fotos e vídeos, música e audio Música e audio Fotos e vídeos + Activar os avisos + Continuar con subdominio + Activar os avisos instantáneos + Fotos e vídeos, música e audio %s necesita permisos para acceder aos teus audios %s necesita permisos para acceder aos teus vídeos %s necesita permisos para acceder ás túas fotos %s necesita permisos para acceder ás túas fotos e vídeos %s necesita permisos para acceder á túa música, audios, fotos e vídeos - Activar os avisos Vai a Axustes &rarr; Notificacións &rarr; Axustes da app, e activa %1$s para recibir notificacións inmediatamente. - Terás que abrir a aplicación para ver as notificacións. + Corrección As notificacións push están desactivadas As notificacións push están desactivadas. Descarta o aviso do permiso de notificacións. - Corrección + Terás que abrir a aplicación para ver as notificacións. <b>%1$s</b> está usando %2$s plugins individuais de Jetpack <b>%1$s</b> está usando o plugin <b>%2$s</b> A aplicación de WordPress non é compatible cos plugins individuais de Jetpack. <b>%1$s</b> está usando plugins individuais de Jetpack que non son compatibles coa aplicación de WordPress. <b>%1$s</b> está usando o plugin <b>%2$s</b>, que non é compatible coa aplicación de WordPress. - Non se puido acceder a algúns dos teus sitios Non se puido acceder a un dos teus sitios + Non se puido acceder a algúns dos teus sitios Por favor, pásate á aplicación Jetpack, onde te guiaremos para que conectes o plugin Jetpack para usar este sitio coa aplicación. Cambia á aplicación de Jetpack %1$s usa %2$s, que aínda non é compatible con todas as funcións da aplicación.\n\nInstala o %3$s para usar a aplicación con este sitio. @@ -469,132 +469,132 @@ Language: gl_ES %1$s usa %2$s, que aínda non é compatible con todas as funcións da aplicación. Instala o %3$s. %1$s usa %2$s, que aínda non é compatible con todas as funcións da aplicación. Instala o %3$s. O cambio é gratuíto e só che levará un minuto. - Encontrarás máis información en Jetpack.com - Cambia á aplicación de Jetpack - WP Admin + Feito Xestionar + Configurar Tráfico Contido - Configurar - Feito + WP Admin + Encontrarás máis información en Jetpack.com + Cambia á aplicación de Jetpack Agora que Jetpack está instalado, só tenemos que configuralo. Só che levará un minuto. + Fai un seguimento do rendemento, inicia e para a actividade promocional de Blaze en calquera momento. Promover unha entrada con Blaze agora Promover esta páxina con Blaze Promover esta entrada con Blaze - Fai un seguimento do rendemento, inicia e para a actividade promocional de Blaze en calquera momento. - O teu contido aparecerá en millóns de sitios de WordPress e Tumblr. - Promove calquera entrada ou páxina en cuestión de minutos por só uns euros ao día. - Xera máis tráfico cara o teu sitio con Blaze - Blaze - Este dominio xa está rexistrado Oferta Recomendado Mellor alternativa - ao ano Axuda + O teu contido aparecerá en millóns de sitios de WordPress e Tumblr. + Blaze + Este dominio xa está rexistrado + Xera máis tráfico cara o teu sitio con Blaze Consulta o noso FAQ para obter respostas a preguntas habituais que poderías ter. - Grazas por cambiar á aplicación de Jetpack! Rexistros Entradas Gratis Axuda + Grazas por cambiar á aplicación de Jetpack! + Promove calquera entrada ou páxina en cuestión de minutos por só uns euros ao día. + ao ano Menú de bloques - Amosa o teu traballo en millóns de sitios. - Promove o teu contido con Blaze Pechar Contactar con soporte - Instalar o plugin completo Termos e condicións + Instalar o plugin completo Ao configurar Jetpack, aceptas os nosos + Amosa o teu traballo en millóns de sitios. + Promove o teu contido con Blaze plugin completo de Jetpack plugins individuais de Jetpack o plugin %1$s %1$s usa %2$s, que aínda non é compatible con todas as funcións da aplicación.\n\nInstala o %3$s para usar a aplicación con este sitio. - Por favor, instala o plugin completo de Jetpack - Só hai un sitio dispoñible, polo que non podes cambiar o teu sitio principal. Contactar con soporte Reintentar + Icona de erro + Por favor, instala o plugin completo de Jetpack + Só hai un sitio dispoñible, polo que non podes cambiar o teu sitio principal. Jetpack non se puido instalar agora. Produciuse un problema - Icona de erro - Todo listo para usar este sitio coa aplicación. + Promocionar con Blaze Jetpack instalado Instalando Jetpack no teu sitio. Isto pode levar uns minutos completarse. Instalando Jetpack Continuar As credenciais da túa web non se almacenarán, e só se utilizan para instalar Jetpack. - Instalar Jetpack Icona de Jetpack - Promocionar con Blaze + Todo listo para usar este sitio coa aplicación. + Instalar Jetpack Libera todo o potencial do teu sitio. Obtén estatísticas, notificacións e máis con Jetpack. O teu sitio ten o plugin de Jetpack - A aplicación móbil Jetpack está deseñada para funcionar xunto co plugin de Jetpack. Fai o cambio agora e obtén acceso a estatísticas, notificacións e ao lector, entre outras funcións. Recibe notificacións por novos comentarios, Gústame, visualizacións, etc. - Comparte o teu contido e busca as túas comunidades e sitios favoritos para seguilos. Consulta o crecemento do tráfico ao teu sitio con información útil e estatísticas completas. + Comparte o teu contido e busca as túas comunidades e sitios favoritos para seguilos. + A aplicación móbil Jetpack está deseñada para funcionar xunto co plugin de Jetpack. Fai o cambio agora e obtén acceso a estatísticas, notificacións e ao lector, entre outras funcións. Estatísticas e datos clave - Con Jetpack sacarás máis partido do teu sitio de WordPress. O cambio é gratuíto e só che levará un minuto. + Ocultáronse os estímulos para bloguear. Dálle un impulso a WordPress con Jetpack - Podes xestionar os recordatorios e estímulos para bloguear en calquera momento desde O meu sitio > Axustes > Bloguear. - Cada notificación incluirá unha palabra ou unha breve frase inspiradora. Vai a <b>Axustes do sitio</b> para reactivalos. - Ocultáronse os estímulos para bloguear. + Cada notificación incluirá unha palabra ou unha breve frase inspiradora. + Podes xestionar os recordatorios e estímulos para bloguear en calquera momento desde O meu sitio > Axustes > Bloguear. + Con Jetpack sacarás máis partido do teu sitio de WordPress. O cambio é gratuíto e só che levará un minuto. + Bloguear + Amosar estímulos Desactivar estímulos - Recibe axuda do noso grupo de voluntarios. Foros da comunidade Recordatorios de blogueo - Amosar estímulos - Bloguear - Por favor, instala a Google Play Store para obter a app de Jetpack + Recibe axuda do noso grupo de voluntarios. Facelo máis tarde Cambiar a Jetpack - Algunhas características de Jetpack como Estatísticas, Lector ou Notificacións, entre outras, elimináronse da app de WordPress. - As características de Jetpack trasladáronse. - %1$s trasladaranse a %2$s - %1$s trasladarase a %2$s - %1$s trasladaranse pronto %1$s trasladarase pronto - Obtén a aplicación de Jetpack + %1$s trasladaranse pronto + %1$s trasladarase a %2$s + %1$s trasladaranse a %2$s + As características de Jetpack trasladáronse. + Por favor, instala a Google Play Store para obter a app de Jetpack + Algunhas características de Jetpack como Estatísticas, Lector ou Notificacións, entre outras, elimináronse da app de WordPress. + 1 semana + %d semanas + Últimos sete días + Sete días anteriores Ver todas as respostas + Obtén a aplicación de Jetpack %1$s é menor que a semana anterior %1$s é maior que a semana anterior - Os teus visitantes nos últimos sete días son %1$s menos que nos sete días anteriores. - Os teus visitantes nos últimos sete días son %1$s máis que nos sete días anteriores. As túas visitas nos últimos sete días son %1$s menos que nos sete días anteriores. As túas visitas nos últimos sete días son %1$s máis que nos sete días anteriores. - Sete días anteriores - Últimos sete días - %d semanas - 1 semana + Os teus visitantes nos últimos sete días son %1$s menos que nos sete días anteriores. + Os teus visitantes nos últimos sete días son %1$s máis que nos sete días anteriores. Desde <b>Day One</b> Recórdamo máis tarde - As estatísticas, o lector, as notificacións e outras características trasladaranse pronto á aplicación móbil de Jetpack. Cambiar á aplicación de Jetpack Máis información en jetpack.com O cambio é gratuíto e só leva un minuto. Vanse a retirar pronto da aplicación de WordPress as estatísticas, lectura, avisos e outras funcionalidades de Jetpack. Vanse a retirar da aplicación de WordPress as estatísticas, lectura, avisos e outras funcionalidades de Jetpack o %s. + As estatísticas, o lector, as notificacións e outras características trasladaranse pronto á aplicación móbil de Jetpack. + Vaia! + 1 resposta + 0 respostas + %d respostas + Aínda non hai suxerencias + Cambiar á nova aplicación de Jetpack As funcións de Jetpack trasladaranse pronto. Os avisos estanse trasladando á aplicación de Jetpack O lector estase trasladando á aplicación de Jetpack - A estatísticas estanse trasladado á aplicación de Jetpack - Cambiar á nova aplicación de Jetpack Produciuse un erro ao cargar as indicacións. - Vaia! - Aínda non hai suxerencias - %d respostas - 1 resposta - 0 respostas - ✓ Respondido + A estatísticas estanse trasladado á aplicación de Jetpack Peticións + ✓ Respondido pechar Alternativamente, podes separar e editar este bloque por separado tocando en «Separar padrón». - Borrar permanentemente a categoría «%s»? - Categoría borrada correctamente Borrando a categoría que fallou + Categoría borrada correctamente + Borrar permanentemente a categoría «%s»? + Actualizar categoría Borrando a categoría Actualizando a categoría - Actualizar categoría As entradas deste usuario non se volverán a mostrar Bloquear usuario Informar deste usuario @@ -602,45 +602,45 @@ Language: gl_ES Parece que tes a aplicación de Jetpack instalada.\n\nQuixeras abrir as ligazóns na aplicación Jetpack a partir de agora?\n\nSempre podes modificar este comportamento en Configuración > Abrir ligazóns en Jetpack Abrir ligazóns en Jetpack? Continuar sen Jetpack - O Jetpack fornece estatísticas, notificacións e moito máis para axudarche a crear e desenvolver o sitio WordPress dos teus soños.\n\nA aplicación WordPress xa non é compatíbel coa creación de sitios novos. Jetpack fornece estatísticas, notificacións e moito máis para axudarche a crear e desenvolver o sitio WordPress dos teus soños. + O Jetpack fornece estatísticas, notificacións e moito máis para axudarche a crear e desenvolver o sitio WordPress dos teus soños.\n\nA aplicación WordPress xa non é compatíbel coa creación de sitios novos. Crear un novo sitio WordPress coa aplicación Jetpack - weblinks urilinks + weblinks Muda para a aplicación Jetpack para continuar a recibir notificacións en tempo real no seu dispositivo. Muda para a aplicación Jetpack para encontrar, seguir e gustar todas as túas publicacións e sitios favoritos co Lector. Muda para a aplicación Jetpack para observar o crecemento do tráfico do teu sitio con estatísticas e outros detalles. - Recibe as túas notificacións coa aplicación de Jetpack + De acordo + Necesitas axuda? + Abrir ligazóns en Jetpack Segue calquera sitio coa aplicación de Jetpack - Obtén as túas estatísticas coa nova aplicación de Jetpack - Non se pode desactivar abrir as ligazóns en Jetpack Non se pode activar abrir as ligazóns en Jetpack - Abrir ligazóns en Jetpack - Necesitas axuda? - De acordo - Non podemos transferir os teus datos e axustes sen unha conexión de rede. - Comproba a túa conexión de rede para asegurarte de que funcione e volve a intentalo. + Non se pode desactivar abrir as ligazóns en Jetpack + Obtén as túas estatísticas coa nova aplicación de Jetpack + Recibe as túas notificacións coa aplicación de Jetpack Non se puido conectar a Internet. Contacta co equipo de soporte ou inténtao de novo máis tarde. + Comproba a túa conexión de rede para asegurarte de que funcione e volve a intentalo. + Non podemos transferir os teus datos e axustes sen unha conexión de rede. Algo non foi como estaba previsto. Os teus datos están protexidos, pero non podemos transferilos neste momento. - Vaia, produciuse un erro. - Volver a intentalo Terminar + Volver a intentalo Icona para quitar a aplicación de WordPress + Vaia, produciuse un erro. Transferimos todos os teus datos e axustes. Todo está tal e como o deixaches. Grazas por cambiar a Jetpack! Desactivaremos as notificacións da aplicación de WordPress. Recibirás as mesmas notificacións, pero a partir de agora desde a aplicación de Jetpack. - Centro de axuda de WordPress Soporte - Permite que a aplicación desactive as notificacións de WordPress. + Centro de axuda de WordPress desactivar notificacións de WordPress - Necesitas axuda? + Permite que a aplicación desactive as notificacións de WordPress. Continuar - Encontramos o teu sitio. Continúa para transferir todos os teus datos e acceder a Jetpack automaticamente. - Encontramos os teus sitios. Continúa para transferir todos os teus datos e acceder a Jetpack automaticamente. + Necesitas axuda? A túa foto de perfil Parece que estas realizando o cambio desde a aplicación de WordPress. + Encontramos o teu sitio. Continúa para transferir todos os teus datos e acceder a Jetpack automaticamente. + Encontramos os teus sitios. Continúa para transferir todos os teus datos e acceder a Jetpack automaticamente. Dámosche a benvida a Jetpack! icona Páxina pai @@ -655,54 +655,54 @@ Language: gl_ES Estás gozando de %s? Comparte unha entrada en %s Conexións de Jetpack Social - Por favor, accede á aplicación Jetpack para engadir un widget. Conexións de Jetpack Social + Por favor, accede á aplicación Jetpack para engadir un widget. Acabamos de enviar unha ligazón máxica a Revisa o teu correo electrónico neste dispositivo! Usar un contrasinal para acceder - Mantente informado con actualizacións en tempo real para novos comentarios, tráfico do sitio, informes de seguridade e máis. - Os avisos funcionan con Jetpack - Observa como crece o teu tráfico e obtén información sobre a túa audiencia con estatísticas e información redeseñadas, agora dispoñibles na nova aplicación Jetpack. As estatísticas funcionan con Jetpack - Encontra, segue e dálle «Gústame» a todos os teus sitios e publicacións favoritos con Reader, agora dispoñible na nova aplicación Jetpack. Reader funciona con Jetpack - A nova aplicación Jetpack ten estatísticas, lector, notificacións e máis que melloran o teu WordPress. + Os avisos funcionan con Jetpack + Mantente informado con actualizacións en tempo real para novos comentarios, tráfico do sitio, informes de seguridade e máis. + Encontra, segue e dálle «Gústame» a todos os teus sitios e publicacións favoritos con Reader, agora dispoñible na nova aplicación Jetpack. + Observa como crece o teu tráfico e obtén información sobre a túa audiencia con estatísticas e información redeseñadas, agora dispoñibles na nova aplicación Jetpack. WordPress é mellor con Jetpack - Actualiza o teu plan para usar fondos de vídeo - Actualiza o teu plan para subir audio - Funciona grazas a Jetpack - URL non válida. + A nova aplicación Jetpack ten estatísticas, lector, notificacións e máis que melloran o teu WordPress. Degradado - Continuar aos avisos + URL non válida. + Funciona grazas a Jetpack Continuar ás estatísticas Continuar ao lector + Continuar aos avisos + Actualiza o teu plan para subir audio + Actualiza o teu plan para usar fondos de vídeo Proba a nova aplicación de Jetpack - Problema ao mostrar o bloque. \nToca para intentar a recuperación do bloque. - A semana pasada tiveches %1$s visitas e %2$s comentarios - A semana pasada tiveches %1$s visitas e %2$s Gústame A semana pasada tiveches %1$s visitas. - A semana pasada tiveches %1$s visitas, %2$s Gústame e %3$s comentarios. + A semana pasada tiveches %1$s visitas e %2$s Gústame + A semana pasada tiveches %1$s visitas e %2$s comentarios ⭐️ A túa última entrada %1$s recibiu %2$s Gústame. + A semana pasada tiveches %1$s visitas, %2$s Gústame e %3$s comentarios. + Problema ao mostrar o bloque. \nToca para intentar a recuperación do bloque. Funciona grazas a Jetpack - Imaxe que sinala que o escaneo do código de acceso está en proceso Imaxe que sinala un erro - Seguro que queres continuar? Saír do fluxo de escaneo de código de acceso + Seguro que queres continuar? + Imaxe que sinala que o escaneo do código de acceso está en proceso Non se puido acceder con este código de acceso. Toca o botón Analizar de novo para volver a escanear o código. - Fallou a autentificación - Este código de acceso caducou. Toca o botón Analizar de novo para volver a escanear o código. + Descartar + Analizar de novo + Non hai conexión + Si, quero acceder + Accediches! O código de acceso caducou - Non se puido validar o código de acceso escaneado. Toca o botón Analizar de novo para volver a escanear o código. + Fallou a autentificación Non se puido validar o código de acceso - Requírese unha conexión activa a Internet para escanear códigos de acceso - Non hai conexión - Analizar de novo - Descartar + Estás intentando acceder ao teu navegador web cerca de %1$s? Toca descartar e volve ao teu navegador web para continuar. - Accediches! - Si, quero acceder + Requírese unha conexión activa a Internet para escanear códigos de acceso + Este código de acceso caducou. Toca o botón Analizar de novo para volver a escanear o código. Escanea só os códigos QR que colliches directamente do navegador web. Non escanees nunca un código que che enviara alguén. - Estás intentando acceder ao teu navegador web cerca de %1$s? + Non se puido validar o código de acceso escaneado. Toca o botón Analizar de novo para volver a escanear o código. Estás intentando acceder a %1$s cerca de %2$s? 💡Comentar noutros blogs é unha boa forma de chamar a atención e ter máis subscritores no teu novo sitio. 💡Toca «VER MÁIS» para ver os principais comentaristas. @@ -711,82 +711,82 @@ Language: gl_ES ✍️ Programa os teus borradores para publicar no mellor momento e chegar ao teu público. 💡Publicar con constancia é unha boa forma de crear o teu público. Engade un recordatorio para manterte ao día. 💡Bloguea máis rapidamente co noso curso <i>Introdución aos blogs</i> ofrecido por expertos. - Estanse cargando os estímulos para bloguear. Espera un momento e inténtao de novo. Non podes decidirte? Podes cambiar o tema en calquera momento. - Bloguear - Elixido para ti - Ideal para %s - Vista previa do tema %s - Elixe un tema - Salteime o estímulo para bloguear de hoxe - Máis información + Estanse cargando os estímulos para bloguear. Espera un momento e inténtao de novo. + Vistas Totais Outros Buscar - WordPress - Vistas + Bloguear Programar - Programa a túa entrada + WordPress + Máis información + Ideal para %s + Elixido para ti + Elixe un tema + Vista previa do tema %s + Salteime o estímulo para bloguear de hoxe Configurar recordatorios - Configura os teus recordatorios de blogueo + Programa a túa entrada Consulta o curso + Configura os teus recordatorios de blogueo Fai crecer a túa audiencia - Tamén podes reorganizar os bloques tocando un bloque e logo tocando as frechas arriba e abaixo que aparecen na parte inferior esquerda do bloque para movelo encima ou debaixo doutros bloques. - Arquivo de imaxe non encontrado. - Arrastrar e soltar fai que reordear bloques sexa algo trivial. Presiona e suxeita un bloque, logo arrástrao á súa nova ubicación e sóltao. Arrastrar e soltar Botóns de frechas - %1$s. Seleccionado actualmente: %2$s - Todas as tarefas están completas Tarefa completada Explorar código de acceso + Todas as tarefas están completas + Arquivo de imaxe non encontrado. + %1$s. Seleccionado actualmente: %2$s + Arrastrar e soltar fai que reordear bloques sexa algo trivial. Presiona e suxeita un bloque, logo arrástrao á súa nova ubicación e sóltao. + Tamén podes reorganizar os bloques tocando un bloque e logo tocando as frechas arriba e abaixo que aparecen na parte inferior esquerda do bloque para movelo encima ou debaixo doutros bloques. ⭐️ A túa última entrada %1$s recibiu %2$s gústame. Non hai suficiente actividade. Volve a comprobalo máis tarde, cando o teu sitio teña máis visitas! - %1$s, %2$s%% do total de subscritores %1$s (%2$s%%) + %1$s, %2$s%% do total de subscritores Copiar ligazón - Noraboa! Xa sabes manexarte<br/> Coñece a aplicación - Sube os medios directamente ao teu sitio desde o teu dispositivo ou cámara Sube fotos ou vídeos + Noraboa! Xa sabes manexarte<br/> + Sube os medios directamente ao teu sitio desde o teu dispositivo ou cámara + Miniatura de vídeo + Principais comentaristas + Comproba os teus avisos Obtén actualizacións en tempo real desde o teu peto - Selecciona %1$s Medios %2$s para ver a túa biblioteca actual. Obtén actualizacións en tempo real desde o teu peto. - Comproba os teus avisos + Utiliza <b> Descubrir </b> para encontrar sitios e etiquetas. + Selecciona %1$s Medios %2$s para ver a túa biblioteca actual. Selecciona a %1$s Pestana de avisos %2$s para recibir actualizacións sobre a marcha. Selecciona %1$s Máis %2$s para subir medios. Podes engadilos ás túas entradas ou páxinas desde calquera dispositivo. - Utiliza <b> Descubrir </b> para encontrar sitios e etiquetas. - Miniatura de vídeo - Principais comentaristas - Publicada fai %1$d anos + Total de «Gústame» + Total de comentarios + Publicada fai un día Publicada fai un ano - Publicada fai %1$d meses Publicada fai un mes + Publicada fai unha hora + Publicada fai uns segundos + Publicada fai un minuto Publicada fai %1$d días - Publicada fai un día + Publicada fai %1$d anos Publicada fai %1$d horas - Publicada fai unha hora + Publicada fai %1$d meses Publicada fai %1$d minutos - Publicada fai un minuto - Publicada fai uns segundos - Total de comentarios - Total de «Gústame» Descartar Resposta Estímulo diario Entendido Toca <b>%1$s</b> para ver o teu sitio Selecciona o %1$s Lector %2$s para descubrir outros sitios. - Aprende máis sobre os estímulos - Vídeo non seleccionado Vídeo seleccionado Miniatura do medio + Vídeo non seleccionado 🔥 A hora máis popular + Aprende máis sobre os estímulos %1$s %2$s Visitar o escritorio O teu sitio xa está protexido con VaultPress. Máis abaixo, podes encontrar unha ligazón ao teu escritorio de VaultPress. - O teu sitio ten VaultPress Idioma actual: + O teu sitio ten VaultPress Crear sitio Engadir bloques Pantalla inicial @@ -802,110 +802,110 @@ Language: gl_ES Establecer como imaxe destacada Manter actual Reemplazar a imaxe destacada - Xa tes establecida unha imaxe destacada. Queres remprazala coa nova imaxe? - Remprazamos a imaxe destacada actual? Descartar + Remprazamos a imaxe destacada actual? + Xa tes establecida unha imaxe destacada. Queres remprazala coa nova imaxe? Pronto eliminaremos o editor clásico para as novas entradas, pero isto non afectará á edición de ningunha das túas entradas ou páxinas existentes. Adiántate agora activando o editor de bloques nos axustes do sitio. - Proba o novo editor de bloques - Editar o bloque %s Gardando - Reintentar todo - Eliminar a subida - Reintentar - Non se puido subir o arquivo - Non Si Cancelar Aceptar + Non + Reintentar + Reintentar todo http(s):// + Editar o bloque %s + Eliminar a subida + Non se puido subir o arquivo + Proba o novo editor de bloques Inserir unha ligazón Beta - O editor aínda está cargando - Fallo ao obter a estrutura do contido - Bloques: %1$d\nPalabras: %2$d\nCaracteres: %3$d + Aceptar + %dpx Estrutura do contido - Elixe un medio da biblioteca de medios de WordPress + O editor aínda está cargando Elixe un medio da galería + Fallo ao obter a estrutura do contido Fai unha foto ou un vídeo coa cámara - %dpx - Aceptar + Elixe un medio da biblioteca de medios de WordPress Por favor, espera ata que se teñan gardado todos os arquivos - Arquivos gardándose + Bloques: %1$d\nPalabras: %2$d\nCaracteres: %3$d + Nota: Contido - Fai a película da túa vida. Recordarmo Próbao agora - Nota: + Arquivos gardándose + Fai a película da túa vida. Mostrarémosche un novo estímulo cada día no teu escritorio para axudarche a que flúan eses fluídos creativos! O mellor modo de converterte nun mellor escritor é crear un hábito de escritura e compartir con outros - aquí é onde entran os estímulos! - Presentando\nIndicacións para bloguear Configurar recordatorios - Incluír as indicacións para bloguear Publicar con regularidade atrae novos lectores. Cóntanos cando queres escribir e enviarémosche un recordatorio! - Convértete nun mellor escritor creando un hábito - Escritura e poesía + Presentando\nIndicacións para bloguear + Incluír as indicacións para bloguear Viaxes - Tecnoloxía Deportes + Tecnoloxía Inmobiliaria - Política - Fotografía - Persoal - Xente - Paternidade + Escritura e poesía + Convértete nun mellor escritor creando un hábito + Bricolaxe Noticias + Comida Música - Servizos locais - Estilo de vida - Deseño de interiores + Xente Saúde Xogos - Comida - Forma física e exercicio - Películas e televisión Finanzas Moda - Bricolaxe + Política + Persoal + Paternidade + Estilo de vida Educación + Fotografía + Servizos locais + Deseño de interiores + Películas e televisión + Forma física e exercicio Comunitario e ONG - Negocios + Arte Libros Beleza + Negocios Automoción - Arte - P.ex.: Moda, poesía, política Temática do sitio + Ver máis estímulos Toca <b>%1$s</b> para continuar. + P.ex.: Moda, poesía, política Omitir hoxe - Ver máis estímulos %d respostas - Comparte o estímulo de bloguear ✓ Respondido - Responder estímulo - Estímulos + Comparte o estímulo de bloguear Todos + Estímulos + Responder estímulo Esta combinación de cor pode ser difícil de ler para a xente. Intenta usar unha cor de fondo máis clara e/ou unha cor de texto máis escura. Esta combinación de cor pode ser difícil de ler para a xente. Intenta usar unha cor de fondo máis escura e/ou unha cor de texto máis clara. Fallo ao inserir os medios.\nToca para máis información. - Elixe unha temática das listadas a continuación ou escribe a túa propia. De que trata a túa web? - Resumo semanal + Elixe unha temática das listadas a continuación ou escribe a túa propia. Inicio + Resumo semanal Engadir categorías Que aplicación de correo electrónico usas? Houbo un problema ao comunicar co sitio. Devolveuse un código de erro HTTP 401. - As chamadas XML-RPC parecen bloqueadas neste sitio (código de erro 401). Se o intento de acceso falla, toca na icona de axuda para ver as FAQ. Non se puido ler o sitio WordPress nesa URL. Toca na icona de axuda para ver as FAQ. + As chamadas XML-RPC parecen bloqueadas neste sitio (código de erro 401). Se o intento de acceso falla, toca na icona de axuda para ver as FAQ. Os servizos XML-RPC están desactivados neste sitio. Menú A túa busca inclúe caracteres non compatibles nos dominios de WordPress.com. Permítense os seguintes caracteres: A–Z, a–z, 0–9. - Comproba a túa conexión a Internet e actualiza a páxina. Estatísticas de hoxe + Comproba a túa conexión a Internet e actualiza a páxina. Ocorreu un erro ao actualizar o contido do aviso Editar - Fallo ao moderar os comentarios - Mover á papeleira Marcar como spam + Mover á papeleira + Fallo ao moderar os comentarios Rexeitar Axustes da galería de mosaico Navega á pantalla de selección do deseño @@ -913,58 +913,58 @@ Language: gl_ES Podes conectar a túa conta de %s na web de WordPress.com. Cando o teñas feito, volve á aplicación para cambiar os teus axustes sociais. Icona da aplicación Icona de volver - Logotipo de Automattic WordPress - WooCommerce + Logotipo de Automattic Tumblr - Simplenote - Pocket Casts Jetpack Day One + Simplenote + WooCommerce Código fonte + Pocket Casts Política de privacidade Termos do servizo Traballa desde calquera lugar - Traballa con nós - Familia Automattic - Legal e outros + Valóranos Twitter Instagram - Valóranos + Traballa con nós + Legal e outros + Familia Automattic Compartir con amigos Podes editar este bloque usando a versión web do editor. Abrir os axustes de seguridade de Jetpack Nota: Debes permitir o acceso desde WordPress.com para editar este bloque no editor móbil. - Nota: O deseño pode variar entre temas e tamaños de pantalla - Axustes do enderezo ENGADIR MEDIOS + Axustes do enderezo + Nota: O deseño pode variar entre temas e tamaños de pantalla Estamos tendo problemas neste momento para cargar os datos do teu sitio. Algúns datos non se cargaron - O escritorio non está actualizado. Por favor, comproba a túa conexión e logo pulsa para refrescar. Non se puido actualizar o escritorio. Vídeo non subido! Para subir vídeos de máis de 5 minutos é necesario un plan de pago. + O escritorio non está actualizado. Por favor, comproba a túa conexión e logo pulsa para refrescar. Agradecementos Aviso de privacidade de California - Versión %1$s - Agradecementos - Legal e outros - Sobre %1$s Blog + Tamaño da fonte + Sobre %1$s O básico + Obter soporte + Versión %1$s + Legal e outros + Agradecementos Seleccionado: Por defecto Máis opcións de soporte - Obter soporte - Tamaño da fonte Toca dúas veces para seleccionar un tamaño de fonte - Toca dúas veces para seleccionar o tamaño de fonte por defecto - Contactar co soporte %1$s (%2$s) + Contactar co soporte + Ver todos os comentarios Seguir a conversa Sé o primeiro en comentar - Ver todos os comentarios Houbo un erro ao obter os datos da entrada - Houbo un erro ao obter os comentarios + Toca dúas veces para seleccionar o tamaño de fonte por defecto Axustes para seguir a conversa + Houbo un erro ao obter os comentarios Desde o portapapeis Imaxe destacada Copiar a URL desde o portapapeis, %s @@ -978,49 +978,49 @@ Language: gl_ES Autor Copiar ligazón Engadir un dominio personalizado fai que sexa máis fácil para os teus visitantes encontrar o teu sitio + Sen título Engade o teu dominio - As entradas aparecen na páxina do teu blog en orde cronoloxicamente inverso. É o momento de compartir as túas ideas co mundo! Crear a túa primeira entrada - Sen título Seguintes entradas programadas + As entradas aparecen na páxina do teu blog en orde cronoloxicamente inverso. É o momento de compartir as túas ideas co mundo! Traballa no borrador dunha entrada <span style=\"color:#008000;\">Gratis o primeiro ano </span><span style=\"color:#50575e;\"><s>%s /ano</s></span> Crear unha ligazón Seleccionar o dominio Dominios Fixa - Fixar a entrada na portada Marcar como fixa Deixar de seguir a conversación Activar os avisos da aplicación + Fixar a entrada na portada Estás seguindo esta conversa. Recibirás avisos por correo electrónico cando se publiquen novos comentarios. - Xestionar as opcións para seguir a conversa, ventá emerxente - Non se puideron desactivar os avisos da aplicación Non se puideron activar os avisos da aplicación - Desactivados os avisos da aplicación + Non se puideron desactivar os avisos da aplicación + Xestionar as opcións para seguir a conversa, ventá emerxente Activados os avisos da aplicación + Desactivados os avisos da aplicación Cancelada a subscrición a esta conversación Seguindo esta conversa\nActivar os avisos da aplicación? Buscar un dominio - Os dominios comprados neste sitio redirixirán aos visitantes a <b>%s</b> Co teu plan, tes incluído o rexistro de dominio gratis durante un ano - Reclama o teu dominio gratuíto + Os dominios comprados neste sitio redirixirán aos visitantes a <b>%s</b> Engadir un dominio + Reclama o teu dominio gratuíto <span style=\"color:#d63638;\">Caduca o %s</span> Caduca o %s - <span style=\"color:#B26200;\">%1$s o primeiro ano </span><span style=\"color:#50575e;\"><s>%2$s /ano</s></span> %s<span style=\"color:#50575e;\"> /ano</span> - Queres descartalos? - Hai cambios sen gardar - O comentario non pode estar baleiro - Correo electrónico do usuario non válido - Enderezo web non válido - O nome de usuario non pode estar baleiro - Enderezo de correo electrónico - Enderezo web - Comentario + <span style=\"color:#B26200;\">%1$s o primeiro ano </span><span style=\"color:#50575e;\"><s>%2$s /ano</s></span> Nome Feito + Comentario + Enderezo web + Enderezo de correo electrónico + Correo electrónico do usuario non válido + Enderezo web non válido + O comentario non pode estar baleiro + Hai cambios sen gardar + O nome de usuario non pode estar baleiro + Queres descartalos? Pronto chegarán as vistas previas dos bloques incrustados Resumo semanal Opcións de incrustación @@ -1029,68 +1029,68 @@ Language: gl_ES Altura da liña Obtén o teu dominio Erro descoñecido ao recuperar o modelo recomendado da aplicación - Resposta recibida non válida + Dominios + Enlaces rápidos Non se recibiu ningunha resposta - Aplicacións Automattic - Aplicacións para calquera pantalla + Resposta recibida non válida Comparte WordPress cun amigo - Enlaces rápidos - Dominios - Repaso semanal: %s + Aplicacións Automattic - Aplicacións para calquera pantalla Hora do aviso + Repaso semanal: %s Recibirás recordatorios para bloguear <b>todos os días</b> ás <b>%s</b>. %1$s á semana ás %2$s Os controis de formato de texto están dentro da barra de ferramentas situada enriba do teclado mentres editas un bloque de texto + Mover bloques Selecionado: %s Selecciona unha cor de arriba - Navega para seleccionar %s - Mover bloques Como editar a túa entrada Como editar a túa páxina + Navega para seleccionar %s Personalizar bloques Os cambios na imaxe destacada non se verán afectados polos botóns de desfacer/refacer. Aplica o axuste Podes reorganizar os bloques tocando un bloque e logo tocando as frechas arriba e abaixo que aparecen na parte inferior esquerda do bloque para movelo encima ou debaixo doutros bloques. Benvido ao mundo dos bloques Para eliminar un bloque, selecciona o bloque e fai clic nos tres puntos da parte inferior dereita do bloque para ver os axustes. A partir de aí, elixe a opción para eliminar o bloque. - Algúns bloques teñen axustes adicionais. Toca a icona dos axustes na parte inferior dereita do bloque para ver máis opcións. Bloque %s, dispoñible novamente + Algúns bloques teñen axustes adicionais. Toca a icona dos axustes na parte inferior dereita do bloque para ver máis opcións. Edición de texto enriquecido Unha vez que te familiarices cos nomes dos diferentes bloques, podes engadir un bloque escribindo unha barra inclinada seguida do nome do bloque, por exemplo, «/imaxe» ou «/cabeceira. Fai que o teu contido destaque engadindo imaxes, gifs, vídeos e medios incrustados ás túas páxinas. - Próbao engadindo uns cantos bloques á túa entrada ou páxina! Medio incrustado + Próbao engadindo uns cantos bloques á túa entrada ou páxina! Cada bloque ten os seus propios axustes. Para encontralos, toca nun bloque. Os seusS axustes aparecerán na barra de ferramentas da parte inferior da pantalla. Crear deseños Os bloques son pezas de contido que podes insertar, reorganizar e dar estilo sen necesidade de saber programar. Os bloques son unha forma fácil e moderna para que crees bonitos deseños. Os bloques permítenche centrarte na escritura do teu contido, sabendo que todas as ferramentas de formato que necesitas están aí para axudarche a transmitir a túa mensaxe. Organiza o teu contido en columnas, engade botóns de chamada á acción e superpón imaxes con texto. - Engade un novo bloque en calquera momento tocando a icona «+» na barra de ferramentas na parte inferior esquerda. %1$s de %2$s completado - Aprende o básico cun recorrido rápido. + Engade un novo bloque en calquera momento tocando a icona «+» na barra de ferramentas na parte inferior esquerda. Fallou a moderación dun o máis comentarios + Aprende o básico cun recorrido rápido. Crear un sitio - Ten o teu sitio activo e funcionando en só uns rápidos pasos + Activar as estatísticas do sitio Crea a túa web WordPress Non se puideron activar as estatísticas do sitio - Activar as estatísticas do sitio + Ten o teu sitio activo e funcionando en só uns rápidos pasos Activa as estatísticas do sitio para ver información detallada sobre o tráfico, os «Gústame», os comentarios e os subscritores. - Buscas as estatísticas? Que é un bloque? + Buscas as estatísticas? Estamos traballando duro para engadir compatibilidade para vistas previas %s. Mentres tanto, podes previsualizar o contido incrustado na entrada. Estamos traballando duro para engadir compatibilidade para vistas previas %s. Mentres tanto, podes previsualizar o contido incrustado na páxina. + Non se encontraron bloques Non se puido incrustar o medio Proba outro termo de busca - Non se encontraron bloques Aínda non están dispoñibles as vistas previas de %s Pronto chegarán as vistas previas do bloque incrustado %s Toca dúas veces para previsualizar a entrada. Toca dúas veces para previsualizar a páxina. Mostrado na pestana do navegador do teu visitante e noutros sitios en liña. Móstrame o camiño - Queres unha pequena axuda para xestionar este sitio coa aplicación? Crear un novo sitio - Podes cambiar os sitios en calquera momento. Elixe un sitio para abrir + Podes cambiar os sitios en calquera momento. + Queres unha pequena axuda para xestionar este sitio coa aplicación? Sentímolo, neste momento Jetpack Scan non é compatible coas instalacións multisitio de WordPress. Os multisitios de WordPress non son compatibles URL non válida. Por favor, introduce unha URL válida. @@ -1098,86 +1098,86 @@ Language: gl_ES Lenda incrustada. Baleira visita a nosa páxina de documentación Jetpack Backup para instalacións multisitio proporciona copias de seguridade descargables, non restauracións cun só clic. Para máis información, %1$s. - Publicar regularmente pode axudar a que os teus lectores permanezan implicados, e a atraer novos visitantes ao teu sitio. Consello Podes actualizar isto en calquera momento Selecciona os días nos que queres bloguear Podes actualizar isto en calquera momento desde O meu sitio > Axustes > Recordatorios de blogueo. + Publicar regularmente pode axudar a que os teus lectores permanezan implicados, e a atraer novos visitantes ao teu sitio. + Todo configurado! + Recordatorios eliminados! Non tes configurado ningún recordatorio. Recibirás recordatorios para bloguear %1$s á semana o %2$s ás %3$s. - Recordatorios eliminados! - Todo configurado! Actualizar Nada configurado %s á semana Configurar recordatorios Configura recordatorios de blogueo os días que queiras publicar. A túa entrada estase publicando… mentres tanto podes configurar recordatorios de blogueo os días que quieras publicar. + É hora de bloguear en %s Configura os teus recordatorios de blogueo Este é o teu recordatorio para crear algo hoxe - É hora de bloguear en %s WordPress para iOS aínda non é compatible con editar bloques reutilizables WordPress para Android aínda non é compatible con editar bloques reutilizables Alternativamente, podes separar e editar estes bloques por separado tocando en «Separar padróns». Feito Avísame <a href=\"%1$s\">Introduce as credenciais do teu servidor</a> para activar as restauracións do sitio cun clic das copias de seguridade. + Crear unha categoría Establecer como imaxe destacada Eliminar como imaxe destacada - Crear unha categoría Soporte de WordPress para Android Xestiona as categorías do teu sitio Categorías - Recordatorios O contido da páxina das túas últimas entradas xérase automaticamente e non se pode editar. + Recordatorios Axustes do borde - Non amosar de novo Ver o almacenamento + Non amosar de novo Tenemos que gardar o teu contido no teu dispositivo antes de que poida ser publicado. Revisa os teus axustes de almacenamento e elimina arquivos para gañar espazo. Insuficiente almacenamento no dispositivo Posición do eixo Y Posición do eixo X Teclea unha URL - Resultados do insertador de corte %s ten unha URL configurada %s non ten unha URL configurada - %s convertido a bloques normais + Resultados do insertador de corte Bloque %s - Opacidade + %s convertido a bloques normais Opcións de medios URL non válida. Arquivo de audio non encontrado. + Opacidade Insertar entrada cruzada Arrastra para axustar o punto focal - Toca dúas veces para abrir a folla inferior para engadir imaxe ou vídeo Toca dúas veces para abrir a folla de acción para engadir imaxe ou vídeo - A unidade actual é %s + Toca dúas veces para abrir a folla inferior para engadir imaxe ou vídeo Entrada cruzada - %s convertido a bloque normal Axustes de columnas - Engadir enlace a %s + A unidade actual é %s + %s convertido a bloque normal Engadir texto do enlace + Engadir enlace a %s Engadir unha imaxe ou vídeo - A ruta especificada é un directorio e non un arquivo de medios Non se puido encontrar o arquivo de medios na ruta - Ruta de arquivo de medios baleira inesperada - O tipo de arquivo non está permitido + A ruta especificada é un directorio e non un arquivo de medios O medio estaba baleiro - <a href=\"%1$s\">Introduce as credenciais do teu servidor</a> para corrixir as ameazas. + O tipo de arquivo non está permitido + Ruta de arquivo de medios baleira inesperada <a href=\"%1$s\">Introduce as credenciais do teu servidor</a> para corrixir a ameaza. - Toca dúas veces para engadir un enlace. - Probar con outra conta + <a href=\"%1$s\">Introduce as credenciais do teu servidor</a> para corrixir as ameazas. Ver as instrucións + Probar con outra conta + Toca dúas veces para engadir un enlace. Se xa tes un sitio, terás que instalar o plugin gratuíto de Jetpack e conectalo á túa conta de WordPress. A túa foto de perfil Se queres usar esta aplicación para %1$s, deberás ter o plugin de Jetpack configurado e conectado a unha conta de WordPress.com. + Axustes de anchura Mover a imaxe cara diante Mover a imaxe cara atrás - Axustes de anchura - «rel» da ligazón Axustes de columna + «rel» da ligazón Sen descrición - (Sen título) Sitio + (Sen título) Información de folla inferior do perfil de usuario Lista de Gústame %s Dous @@ -1191,18 +1191,18 @@ Language: gl_ES Reintentar GIF Un - Engade o título Vista previa non dispoñible + Engade o título Cargando Etiqueta do enlace - Cor do texto ligazón %s + Cor do texto Recheo - Catro Destacado + Catro Engadir imaxe - URL personalizada Crear uhna incrustación + URL personalizada Columna %d Máis Describe brevemente o enlace para axudar aos usuarios de lectores de pantalla @@ -1212,40 +1212,40 @@ Language: gl_ES Transformar %s a Transformar bloque… Fallo ao insertar os medios. + %d gústame Fallo ao insertar o arquivo de audio. - Describe o propósito da imaxe. Déixao baleiro se a imaxe é puramente decorativa. - %1$s transformado a %2$s Erro ao cargar os datos de gústame. %s - %d gústame + %1$s transformado a %2$s + Describe o propósito da imaxe. Déixao baleiro se a imaxe é puramente decorativa. 1 gústame Suxerencia: + Bloques de busca Usar botón de icona Campo de introdución de busca. - Botón de busca. O texto actual do botón é - Bloques de busca Etiqueta do bloque de busca. O texto actual é - Exterior - Non se estableceu ningún marcador de posición personalizado + Botón de busca. O texto actual do botón é Dentro Ocultar o encabezado de busca - Dobre toque para editar o texto do marcador de posición + Exterior + Non se estableceu ningún marcador de posición personalizado Dobre toque para editar o texto da etiqueta Dobre toque para editar o texto do botón + Dobre toque para editar o texto do marcador de posición dobre toque para cambiar a unidade - O texto de marcador de posición actual é + Sen responder Baleirar a busca Cancelar a busca - Posición do botón + Non hai ningunha rede dispoñible. + Non hai ningún comentario sen responder %1$s. %2$s é %3$s %4$s. Ocorreu un erro ao obter os datos dos gústame Ocorreu un erro ao obter os gústame. - Non hai ningunha rede dispoñible. - Non hai ningún comentario sen responder - Sen responder - ENGALIR LIGAZÓN + Posición do botón + O texto de marcador de posición actual é Axustes de busca - Direccións IP permitidas sempre + ENGALIR LIGAZÓN Comentarios non permitidos + Direccións IP permitidas sempre Engadir o texto do botón Descartar Descargar @@ -1254,352 +1254,352 @@ Language: gl_ES A exploración encontrou %1$s ameazas potenciais con %2$s. Por favor, revísaas a continuación e leva a cabo algunha acción ou toca o botón de corrixir todo. Estamos %3$s se nos necesitas. Traballamos duro para corrixir estas ameazas en segundo plano. Mentres tanto podes seguir usando o teu sitio como sempre, podes volver a comprobar o progreso en calquera momento. Editar o punto focal - Toque dobre para abrir a folla do fondo para editar, substituír ou baleirar a imaxe - Toque dobre para abrir a folla de acción para editar, substituír ou baleirar a imaxe example.com Escribe un nome para o teu sitio + Toque dobre para abrir a folla do fondo para editar, substituír ou baleirar a imaxe + Toque dobre para abrir a folla de acción para editar, substituír ou baleirar a imaxe <b>Completáronse todas as tarefas</b><br/>Chegaches a máis xente. Bo traballo! <b>Completáronse todas as tarefas</b><br/>Personalizaches o teu sitio. Ben feito! Non querías crear unha nova conta? Volve atrás e volve a introducir o teu enderezo de correo electrónico. Unha vez desactivado o enlace de invitación, ninguén poderá usalo para unirse ao teu equipo. Seguro que desexas continuar? Desactivar enlace de invitación - Resposta recibida non válida Non se recibiu ningunha resposta - Ocorreu un erro ao recuperar datos para o perfil %1$s + Resposta recibida non válida Houbo un erro ao obter os perfís Erro descoñecido ao obter os datos dos enlaces de invitación + Ocorreu un erro ao recuperar datos para o perfil %1$s Utiliza este enlace para embarcar aos membros do teu equipo sen ter que invitalos un a un. Calquera que visite estas URL poderá rexistrarse na túa organización, anque recibira o enlace doutra persoa, así que asegúrate de que o compartes con xente de confianza. + Enlace de invitación Caduca %1$s - Desactivar enlace de invitación Compartir enlace de invitación Xerar novo enlace de invitación + Desactivar enlace de invitación Refrescar o estado do enlace - Enlace de invitación Encontrouse unha ameaza Encontráronse ameazas + <b>Exploración finalizada</b><br>Non se encontraron ameazas potenciais <b>Exploración finalizada</b><br>Encontradas %s ameazas potenciais <b>Exploración finalizada</b><br>Encontrada unha ameaza potencial - <b>Exploración finalizada</b><br>Non se encontraron ameazas potenciais - Corrixindo a ameaza Desactivar + Corrixindo a ameaza Revisa as túas páxinas e fai cambios, ou engade ou elimina páxinas. Visita o teu sitio Descobre e segue sitios que te inspiren. - Compartir socialmente Comparte automaticamente as novas entradas nos teus medios sociais. Dálle un nome ao teu sitio que reflexe a súa personalidade e temática. + Compartir socialmente Revisa as túas estatísticas Trataremos de crear un arquivo de copia de seguridade descargable. Non puidemos encontrar o estado para dicir canto tardará a túa copia de seguridade descargable. - Vaia, non puidemos encontrar o estado da túa copia de seguridade descargable - Icona de marca de comprobación Icona de reloxo + Icona de marca de comprobación Avisámoste cando teñamos rematado. + Vaia, non puidemos encontrar o estado da túa copia de seguridade descargable + Non puidemos restaurar o teu sitio Volveremos a intentar restaurar o teu sitio. - Non puidemos encontrar o estado para decir canto tardará a túa restauración. Vaia, non puidemos encontrar o estado da túa restauración - Non puidemos restaurar o teu sitio + Non puidemos encontrar o estado para decir canto tardará a túa restauración. + (SQL) Confirmar - Estás seguro de querer reverter o teu sitio ao %1$s ás %2$s?\n Todo o que cambiaras desde entón perderase. Non puidemos crear a túa copia de seguridade - (SQL) (exclúe temas, plugins e subidas) - Directorio wp-content + Estás seguro de querer reverter o teu sitio ao %1$s ás %2$s?\n Todo o que cambiaras desde entón perderase. + Subindo… Raíz de WordPress + Directorio wp-content Elementos incluídos nesta descarga - Subindo… + ABERTO + Icona de cadeado Substituír arquivo Substituír audio Problema ao abrir o audio - ABERTO + Toca dúas veces para seleccionar un arquivo de audio Ningunha aplicación pode xestionar esta solicitude. - Icona de cadeado Fallo ao insertar o arquivo de audio. Por favor, toca para ver as opcións. - Toca dúas veces para seleccionar un arquivo de audio - Toca dúas veces para escoitar o arquivo de audio Elixir audio Reprodutor de audio - arquivo de audio + Usar este audio Lenda do audio. %s Lenda do audio. Baleira - Engadir audio - Accede ou rexístrate con WordPress.com - Usar este audio Elixe un audio do dispositivo + Toca dúas veces para escoitar o arquivo de audio + Accede ou rexístrate con WordPress.com Opcional: introduce unha mensaxe personalizada para enviar coa túa invitación. - Aprende máis sobre os perfís + arquivo de audio + Engadir audio Corrixido Encontrado aquí para axudar + Aprende máis sobre os perfís A exploración encontrou unha ameaza potencial con %1$s. Por favor, revísaas a continuación e leva a cabo algunha acción ou toca o botón de corrixir todo. Estamos %2$s se nos necesitas. Para revisar o teu sitio de novo, executa unha exploración manual ou espera a que Jetpack explore o teu sitio máis tarde hoxe mesmo. Benvido á exploración de Jetpack! Estamos botándolle un vistazo á túa web para deixalo todo a punto para a primeira análise completa. Informarémoste se encontramos algún problema que lle poida afectar e despois comezará a túa primeira análise. Benvido á ferramenta de exploración de Jetpack, estamos botándolle un primeiro vistazo á túa web nestes momentos, mostrarémosche os resultados enseguida. - Traballamos duro para corrixir estas ameazas en segundo plano. Mentres tanto podes seguir usando o teu sitio coma sempre, podes volver a comprobar o progreso en calquera momento. Enviarémosche un aviso se se encontra unha ameaza. Mentres tanto, non dubides en seguir usando o teu sitio con normalidade, podes comprobar o progreso en calquera momento. + Traballamos duro para corrixir estas ameazas en segundo plano. Mentres tanto podes seguir usando o teu sitio coma sempre, podes volver a comprobar o progreso en calquera momento. Corrixindo ameazas Jetpack Scan non puido realizar unha análise do teu sitio. Comproba se o teu sitio está caído. Se non, volve a intentalo. Se o teu sitio está caído ou se Jetpack Scan segue tendo problemas, ponte en contacto co noso equipo de soporte. - Algo saíu mal Facendo copia de seguridade do sitio - Facendo copia de seguridade do sitio desde %1$s %2$s + Algo saíu mal Creando unha copia de seguridade descargable + Facendo copia de seguridade do sitio desde %1$s %2$s A copia de seguridade do teu sitio realizouse correctamente + Elixir audio A copia de seguridade do teu sitio realizouse correctamente\nFeita a copia de seguridade desde %1$s %2$s A copia de seguridade do teu sitio estase realizando\nFacendo a copia de seguridade desde %1$s %2$s - Elixir audio - Hai outra restauración en curso. Icona de erro Botón Listo - Non se puido restaurar - Botón Visitar sitio + Hai outra restauración en curso. + Visitar o sitio Botón Listo Icona de restaurar - Visitar o sitio - Todos os elementos seleccionados restauráronse á versión do %1$s %2$s. + Non se puido restaurar + Botón Visitar sitio Restaurouse o teu sitio + Todos os elementos seleccionados restauráronse á versión do %1$s %2$s. Non fai falta que esperes. Enviarémosche un aviso cando se complete a restauración. Icona de restaurar sitio - Estamos restaurando a versión do teu sitio do %1$s %2$s. Estamos restaurando o sitio Botón de Confirmar a restauración do sitio - Imaxe dun círculo vermello cun signo de exclamación + Estamos restaurando a versión do teu sitio do %1$s %2$s. Advertencia Botón Restaurar sitio + Imaxe dun círculo vermello cun signo de exclamación + Listo + Restaurar + Botón Listo Icona de restaurar Restaurar sitio - %1$s %2$s é o punto seleccionado para a restauración. Restaurar sitio - Elixe os elementos que queres restaurar: - Restaurar Nube con icona X - Botón Listo - Listo - A descarga fallou + Elixe os elementos que queres restaurar: + %1$s %2$s é o punto seleccionado para a restauración. Tableta Dispositivos móbiles - Selecciona %1$s Páxinas %2$s para ver a túa lista de páxinas. - Cambia, engade ou elimina páxinas no teu sitio. + A descarga fallou Revisar as páxinas do sitio + Cambia, engade ou elimina páxinas no teu sitio. + Selecciona %1$s Páxinas %2$s para ver a túa lista de páxinas. Selecciona %1$s Páxina de inicio %2$s para editar a túa páxina de inicio. - Marcar como non lida Marcar como lida - Non se puideron subir los elementos multimedia.\n%1$s + Marcar como non lida + Marcar entrada como lida + Marcar entrada como non lida Espazo de almacenamento do sitio insuficiente Non se pode alternar o estado visto desta entrada - Marcar entrada como non lida - Marcar entrada como lida - Produciuse un erro ao comprobar o estado da reparación. Ponte en contacto co servizo de soporte. + Non se puideron subir los elementos multimedia.\n%1$s A ameaza correxiuse correctamente. Produciuse un erro ao corrixir as ameazas. Ponte en contacto co servizo de soporte. Por favor, confirma que queres corrixir unha ameaza activa. + Produciuse un erro ao comprobar o estado da reparación. Ponte en contacto co servizo de soporte. Corrixir todas as ameazas - Non se puido ignorar a ameaza. Ponte en contacto co servizo de soporte. Ignorouse a ameaza. + Non se puido ignorar a ameaza. Ponte en contacto co servizo de soporte. No deberías ignorar un problema de seguridade a menos que esteas absolutamente seguro de que non é dañino. Se elixes ignorar esta ameaza, seguirá no teu sitio <b>%s</b>. Non se puido corrixir a ameaza. Ponte en contacto co servizo de soporte. - Ameaza ignorada - Ameaza corrixida en %s - Corrixindo a ameaza + Todos + Corrixido Ignorouse + Historia + Historial de exploracións + Corrixindo a ameaza + Ameaza ignorada Non se encontrou ningún elemento - Corrixido - Todos Analizando arquivos Preparando escaneado - Historia - Historial de exploracións - Proba a axustar o rango de datas + Ameaza corrixida en %s Non se encontraron copias de seguridade coincidentes + Proba a axustar o rango de datas A túa primeira copia de seguridade estará dispoñible aquí en 24 horas e recibirás unha notificación unha vez que se complete A túa primeira copia de seguridade pronto estará lista Ocorreu un problema ao xestionar a petición. Por favor, inténtao de novo máis tarde. Mover ao final Cambiar a posición do bloque icona - Tamén che enviamos un enlace ao teu arquivo. Botón de compartir enlace + Tamén che enviamos un enlace ao teu arquivo. + Descargar + Compartir enlace Botón de descarga Icona de copia de seguridade descargable lista - Compartir enlace - Descargar - Creamos unha copia de seguridade do teu sitio desde %1$s %2$s. A túa copia de seguridade xa está dispoñible para descargala + Creamos unha copia de seguridade do teu sitio desde %1$s %2$s. A túa copia de seguridade - Non fai falta que esperes. Avisarémoste cando estea lista a copia de seguridade Icona de copia de seguridade descargable en curso - Estamos creando unha copia de seguridade descargable do teu sitio desde %1$s %2$s. Estase creando unha copia de seguridade descargable do teu sitio + Estamos creando unha copia de seguridade descargable do teu sitio desde %1$s %2$s. + Non fai falta que esperes. Avisarémoste cando estea lista a copia de seguridade Descargar copia de seguridade - Hai outra descarga en curso. - Ocorreu un problema ao xestionar a petición. Por favor, inténtao de novo máis tarde. Botón Crear copia de seguridade descargable + Hai outra descarga en curso. %1$s %2$s é o punto seleccionado para crear unha copia de seguridade descargable. + Ocorreu un problema ao xestionar a petición. Por favor, inténtao de novo máis tarde. %1$s · %2$s · - %1$s · %2$s %1$s · - entrada cruzada + %1$s · %2$s usuario + entrada cruzada + Corrixir ameaza + Ignorar ameaza Non coincide con %s. - Ocorreu un problema ao cargar as suxerencias. - Non hai suxerencias %s dispoñibles. - Escribe algo para filtrar a lista de suxerencias. Consegue un orzamento gratuíto - Ignorar ameaza - Corrixir ameaza + Non hai suxerencias %s dispoñibles. Jetpack Scan solucionará a ameaza. - Jetpack Scan editará o arquivo ou o directorio afectados. + Ocorreu un problema ao cargar as suxerencias. + Escribe algo para filtrar a lista de suxerencias. Jetpack Scan actualizarase a unha versión máis recente (%s). + Jetpack Scan editará o arquivo ou o directorio afectados. Jetpack Scan borrará o arquivo ou o directorio afectados. Jetpack Scan reemplazará o arquivo ou o directorio afectados. Jetpack Scan non pode solucionar automaticamente esta ameaza.\n Suxerímosche que soluciones esta ameaza manualmente: asegúrate de que WordPress, o teu tema e todos os plugins están actualizados e elimina o código, tema ou plugin que estea causando problemas no teu sitio web. \n \n\n Se necesitas máis axuda para resolver esta ameaza, recomendámosche <b>Codeable</b>, unha plataforma de profesionais de confianza, altamente cualificados, expertos en WordPress.\n Fixeron unha selección de expertos en seguridade para axudarnos con estes proxectos. Os prezos oscilan entre 70–120 USD/hora e podes obter un presuposto gratuíto sen compromiso. - Solucionando a ameaza - Como o solucionou Jetpack? Como imos a reparalo? + Solucionando a ameaza Ameaza detectada no arquivo: Información técnica Cal foi o problema? + Como o solucionou Jetpack? Detalles da ameaza + Ameaza encontrada %s + Ameazas de base de datos %s + %s: patrón de código malicioso + Varias vulnerabilidades Encontrouse unha vulnerabilidade nun tema Encontrouse unha vulnerabilidade nun plugin - Ameaza encontrada %s Encontrouse unha vulnerabilidade en WordPress - Varias vulnerabilidades Tema vulnerable: %1$s (versión %2$s) Plugin vulnerable: %1$s (versión %2$s) - %s: patrón de código malicioso - Ameazas de base de datos %s - %s: arquivo principal infectado - Encontrouse unha ameaza Corrixir todo - hai uns segundos - fai %s minuto(s) - fai %s hora(s) este sitio + Encontrouse unha ameaza + fai %s hora(s) + fai %s minuto(s) + hai uns segundos + %s: arquivo principal infectado Executouse a última exploración de Jetpack %1$s e non se encontrou ningún risco. %2$s - Pode que o teu sitio web estea desprotexido - Non te preocupes - Analizar de novo + Copias de seguridade Analizar agora + Analizar de novo Icona de estado da análise - Copias de seguridade + Pode que o teu sitio web estea desprotexido + Non te preocupes Filtro de tipo de actividade (%s tipos seleccionados) - %1$s (mostrando %2$s elementos) Filtro de tipo de actividade - Non se rexistraron actividades no rango de datas seleccionado. Non hai actividades dispoñibles Revisa a túa conexión a Internet e inténtao de novo. + Non se rexistraron actividades no rango de datas seleccionado. + %1$s (mostrando %2$s elementos) Sen conexión - Tipo de actividade (%s) Filtro de rango de datas - Intenta axustar os filtros de rango de data ou de tipo de actividade + Tipo de actividade (%s) Non se encontraron eventos coincidentes - Base de datos do sitio - (inclúe wp-config.php e calquera arquivo que non sexa de WordPress) + Intenta axustar os filtros de rango de data ou de tipo de actividade Subidas de medios - Plugins de WordPress Temas de WordPress + Plugins de WordPress Crea unha icona de copia de seguridade descargable - Crear un arquivo descargable - Crear unha copia de seguridade descargable - Descargar copia de seguridade - Descarga da copia de seguridade - Erro - Elixir arquivo + Base de datos do sitio + (inclúe wp-config.php e calquera arquivo que non sexa de WordPress) Descargar copia de seguridade Restaurar até este punto Tipo de actividade + Erro + Elixir arquivo + Descargar copia de seguridade + Descarga da copia de seguridade + Crear un arquivo descargable + Crear unha copia de seguridade descargable Rango de datas Filtrar por tipo de actividade - Copiar a versión desta aplicación + Duplicar + Conflicto de sincronización da entrada Editar a entrada primeiro + Copiar a versión desta aplicación A entrada que estás tratando de copiar ten dúas versións que están en conflito ou fixeches cambios recentemente, pero non os gardaches.\nEdita a entrada primeiro para resolver calquera conflito ou procede a copiar a versión desta aplicación. - Conflicto de sincronización da entrada - Duplicar Nome do arquivo + Editar o arquivo + Copiar a URL do arquivo Axustes do arquivo do bloque Erro ao subir os arquivos.\nPor favor, toca para ver as opcións. Erro ao gardar os medios.\nPor favor, toca para ver as opcións. - Editar o arquivo - Copiar a URL do arquivo - Elixe un dominio Jetpack - Seguindo a conversa por correo electrónico + Elixe un dominio + Erro ao recuperar o estado da subscrición para a entrada + Non se puido crear a subscrición aos comentarios desta entrada Seguir a conversa por correo electrónico + Seguindo a conversa por correo electrónico Non se puido anular a subscrición aos comentarios desta entrada - Non se puido crear a subscrición aos comentarios desta entrada - Erro ao recuperar o estado da subscrición para a entrada - Resposta recibida non válida - Non se recibiu ningunha resposta Baleirar Aplicar + Non se recibiu ningunha resposta + Resposta recibida non válida Elimináronse os medios. Intenta volver a crear a túa historia. Feito - Ocorreu un erro ao seleccionar o tema. - Por favor, revisa a túa conexión a Internet e inténtao de novo. Toca en reintentar cando volvas a estar conectado. Os deseños non están dispoñibles sen conexión - Continuar coas credenciais da tenda + Por favor, revisa a túa conexión a Internet e inténtao de novo. + Ocorreu un erro ao seleccionar o tema. + Explorar + Benvido! + Non hai entradas recentes Encontra o teu correo electrónico conectado + Continuar coas credenciais da tenda Proba a seguir máis etiquetas para ampliar a busca - Non hai entradas recentes - Benvido! - Explorar + A <b>Madison Ruíz</b> gustoullea túa entrada <b>Xan Vilaboi</b> respondeu na túa entrada Hoxe recibiches <b>50 gústame</b> no teu sitio - A <b>Madison Ruíz</b> gustoullea túa entrada - Abriuse o menú de bloques desprazable. Selecciona un bloque. - Pechouse o menú de bloques desprazable. Elixir - Toca «Reintentar» cando volvas a estar en liña ou crea unha páxina en branco usando o seguinte botón. - Os deseños non están dispoñibles sen conexión - Toca «Reintentar» ou crea unha páxina en branco usando o seguinte botón. - Os deseños non están dispoñibles debido a un erro - Engadir unha categoría - Engadir unha nova categoría - Categorías + Pechouse o menú de bloques desprazable. + Abriuse o menú de bloques desprazable. Selecciona un bloque. Non establecido + Categorías Categorías - Museos en Londres - Os mellores fanáticos do mundo - Os meus dez mellores cafés - Política + Engadir unha categoría + Engadir unha nova categoría + Os deseños non están dispoñibles sen conexión + Os deseños non están dispoñibles debido a un erro + Toca «Reintentar» ou crea unha páxina en branco usando o seguinte botón. + Toca «Reintentar» cando volvas a estar en liña ou crea unha páxina en branco usando o seguinte botón. + Arte Música - Xardinería - Fútbol Cociña - Arte - Rock n\' roll semanal + Política + Fútbol Noticias web + Xardinería Pamela Nguyen + Os meus dez mellores cafés + Museos en Londres + Rock n\' roll semanal + Os mellores fanáticos do mundo Estou moi inspirado polo traballo do fotógrafo Cameron Karsten. Probarei estas técnicas no meu próximo Inspírate - Segue o teus sitios favoritos e descobre novos blogs. - Observa como crece a túa audiencia con analíticas avanzadas. Mira os comentarios e avisos en tempo real. Co potente editor podes publicar sobre a marcha. + Observa como crece a túa audiencia con analíticas avanzadas. + Segue o teus sitios favoritos e descobre novos blogs. Benvido ao maquetador web máis popular do mundo. A carga do medio fallou Estamos traballando duro para engadir máis bloques con cada versión. «%s» non é totalmente compatible Botón de axuda - Editar usando o editor web Elixir as imaxes - Páxina en branco creada + Editar usando o editor web Páxina creada + Páxina en branco creada Inserción do medio fallida. Fallou a inserción do medio: %s Elixe desde a biblioteca de medios de WordPress Volver + por Primeiros pasos Segue etiquetas para descubrir novos blogs - por - Este referido non pode ser marcado como spam - Desmarcar como spam Marcar como spam Abrir a web + Desmarcar como spam + Subindo medios Subindo medios GIF Subindo medios de inventarios - Subindo medios + Este referido non pode ser marcado como spam Busca ou escribe a URL Engadir este enlace de teléfono Engadir este enlace @@ -1607,79 +1607,78 @@ Language: gl_ES Non hai conexión a Internet.\nNon están dispoñibles as suxestións. %s %s seleccionado - Obter un enlace de acceso por correo electrónico - Vaia, non encontramos unha conta de WordPress.com conectada a este enderezo de correo electrónico. Micrófono - Non se pode amosar este comentario Navegar por elementos + Obter un enlace de acceso por correo electrónico + Non se pode amosar este comentario + Vaia, non encontramos unha conta de WordPress.com conectada a este enderezo de correo electrónico. Informar desta entrada - Benvido ao lector. Descobre millóns de blogs ao teu alcance. - Ocorreu un erro interno no servidor - A túa acción non está permitida %1$s elementos máis + A túa acción non está permitida + Ocorreu un erro interno no servidor + Benvido ao lector. Descobre millóns de blogs ao teu alcance. Seleccionar un deseño Nota: o deseño da columna pode variar entre temas e tamaños de pantalla - Crear unha entrada ou historia + Ocultar Crear unha páxina Crear unha entrada Pode que che guste - Ocultar - Lenda do vídeo. Baleira - Actualiza o título. - Pegar o bloque despois + Crear unha entrada ou historia Título da páxina. %s Título da páxina. Baleiro - Ocorreu un erro ao reproducir o teu vídeo + Pegar o bloque despois + Actualiza o título. + Lenda do vídeo. Baleira Este dispositivo non é compatible coa API de Camera2 - Pechar + Ocorreu un erro ao reproducir o teu vídeo Vista previa Crear unha páxina - Crear unha páxina en branco - Empeza elixindo entre unha ampla variedade de deseños de páxina prefabricados. Ou simplemente empeza cunha páxina en branco. Elixir un deseño + Crear unha páxina en branco Pon un título á túa historia Toca %1$s Crear. %2$s Despois selecciona <b>Entrada do blog</b> - Elixir o dispositivo - Entrada da historia + Empeza elixindo entre unha ampla variedade de deseños de páxina prefabricados. Ou simplemente empeza cunha páxina en branco. + Pechar Para editares as iconas nos sitios auto-aloxados precisas o plugin Jetpack. + Entrada da historia + Elixir o dispositivo + Cota de almacenamento superada Non se puido encontrar o salto de páxina enlazado Non se pode subir o arquivo.\nSuperouse a cota de almacenamento. - Cota de almacenamento superada Engadir un arquivo Substituír o vídeo Substituír a imaxe ou vídeo - Converter en ligazón Elixir un vídeo - Elixir unha imaxe ou vídeo Elixir unha imaxe Bloque eliminado - Introduce o enderezo do teu sitio existente Confirmación do rexistro + Elixir unha imaxe ou vídeo + Introduce o enderezo do teu sitio existente Se continúas con Google e aínda non tes unha conta de WordPress.com, crearás unha conta e aceptas os nosos %1$stermos do servizo%2$s. + Converter en ligazón Se continúas, aceptas os nosos %1$stermos do servizo%2$s. Usaremos este enderezo de correo electrónico para crear a túa nova conta de WordPress.com. Enviámosche por correo electrónico un enlace de rexistro para crear a túa nova conta de WordPress.com. Comproba o teu correo electrónico neste dispositivo e toca o enlace no correo electrónico que recibiches de WordPress.com. Introduce a información da túa conta para %1$s. ou + Feito Continuar con Google Encontra o enderezo do teu sitio - Feito No ves o correo electrónico? Comproba a túa carpeta de spam ou correo non desexado. - Comproba o teu correo electrónico neste dispositivo e toca o enlace no correo electrónico que recibiches de WordPress.com. Enviarémosche por correo electrónico un enlace que che fará acceder automaticamente, sen necesidade de contrasinal. - Comprobar o correo electrónico + Comproba o teu correo electrónico neste dispositivo e toca o enlace no correo electrónico que recibiches de WordPress.com. Primeiros pasos - Introduce o teu enderezo de correo electrónico para acceder ou crear unha conta de WordPress.com. - Ou escribe a túa contrasinal + Comprobar o correo electrónico Crear unha conta Enviar o enlace por correo electrónico Restablecer o teu contrasinal + Ou escribe a túa contrasinal + Introduce o teu enderezo de correo electrónico para acceder ou crear unha conta de WordPress.com. Ocorreu un problema ao xestionar a petición. Por favor, inténtao de novo máis tarde. - Comproba o título do teu sitio Toca <b>%1$s</b> para configurar un novo título + Comproba o título do teu sitio Ao enviar esta entrada á papeleira tamén se descartarán os cambios locais. Estás seguro de que queres seguir? Opciones do bloque %s - Eliminar o bloque Duplicar bloque Copiar bloque Bloque copiado @@ -1688,26 +1687,26 @@ Language: gl_ES Bloque cortado Bloque copiado O título do sitio só pode ser cambiado por un usuario co perfil de administrador. - O título do sitio móstrase na barra de título dun navegador web e na cabeceira da maioría dos temas. - Non se puido actualizar o título do sitio. Comproba a túa conexión de rede e inténtao de novo. + Eliminar o bloque Cambios sen gardar + Non se puido actualizar o título do sitio. Comproba a túa conexión de rede e inténtao de novo. + O título do sitio móstrase na barra de título dun navegador web e na cabeceira da maioría dos temas. Abrir o enlace nun navegador Navega á folla de contido anterior - Navega para personalizar o degradado - Navega ao selector de cor personalizado + Personalizar gradiente Tipo de degradado - Volver Toca dúas veces para seleccionar a opción - Personalizar gradiente + Navega ao selector de cor personalizado + Navega para personalizar o degradado + Volver + Eu + Todos Autor da páxina - A miniatura do medio non se puido cargar Estrutura do contido - Todos - Eu + A miniatura do medio non se puido cargar Rexeitar Non establecido As etiquetas axudan aos lectores dicíndolles de que se trata a entrada. - Data de publicación Engadir etiquetas Volver Gardar agora @@ -1718,461 +1717,462 @@ Language: gl_ES Data de publicación Cancelar Mover a borrador + Data de publicación As entradas na papeleira non se poden editar. Desexas cambiar o estado desta entrada a «borrador» para poder traballar nela? - Mover entrada a borrador? - Elixe as túas etiquetas - Feito - Selecciona algúns para continuar - Publicado - Na papeleira - Programado Data de publicación + Programado + Na papeleira + Publicado + Feito + Mover entrada a borrador? Le o aviso de privacidade de CCPA + Selecciona algúns para continuar A Ley de Privacidade do Consumidor de California («CCPA») obríganos a que proporcionemos información adicional aos residentes de California sobre as categorías de información personal que recompilamos e compartimos, onde obtemos esa información personal e como e por que a usamos. - Aviso de privacidade para usuarios de California - Estado e visibilidade + Elixe as túas etiquetas Actualizar agora + Estado e visibilidade + Aviso de privacidade para usuarios de California %1$s · Abrir o menú de accións de bloques Mover arriba Insertar unha mención - Toca dúas veces para abrir a folla inferior coas opcións dispoñibles Toca dúas veces pata abrir a folla de acción coas opcións dispoñibles - No podemos abrir as páxinas neste momento. Por favor, inténtao de novo máis tarde - Establecer como páxina de entradas - Establecer como páxina de inicio - %1$s non é unha %2$s válida - Seleccionar a páxina + Toca dúas veces para abrir a folla inferior coas opcións dispoñibles Páxina de entradas - Páxina de inicio estática + Seleccionar a páxina Blog clásico + Páxina de inicio estática + Establecer como páxina de inicio + Establecer como páxina de entradas A páxina de inicio seleccionada e a páxina de entradas non poden ser a mesma. - Fallou a actualización da páxina de inicio, comproba a túa conexión a internet - Non se poden gardar os axustes da páxina de inicio antes de que as páxinas estean cargadas - Non se poden gardar os axustes da páxina de inicio + No podemos abrir as páxinas neste momento. Por favor, inténtao de novo máis tarde + %1$s non é unha %2$s válida Aceptar + Axustes da páxina de inicio Fallou a carga das páxinas + Non se poden gardar os axustes da páxina de inicio + Non se poden gardar os axustes da páxina de inicio antes de que as páxinas estean cargadas + Fallou a actualización da páxina de inicio, comproba a túa conexión a internet Elixe entre unha páxina de inicio que mostre as túas últimas publicacións (blog clásico) ou unha páxina fixa/estática. - Axustes da páxina de inicio Páxina de inicio - Fallou a actualización da páxina de entradas - Páxina de entradas actualizada correctamente Fallou a actualización da páxina de inicio + Fallou a actualización da páxina de entradas Páxina de inicio actualizada correctamente - Para establecer a páxina de entradas, activa «Páxina de inicio estática» nos axustes do sitio + Páxina de entradas actualizada correctamente Para establecer a páxina de inicio, activa «Páxina de inicio estática» nos axustes do sitio + Para establecer a páxina de entradas, activa «Páxina de inicio estática» nos axustes do sitio Seleccionar unha cor Toca dúas veces para ir aos axustes da cor - Saber máis - Que hai de novo en %s - Insertar %d recortar - Erro ao cargar no arquivo, por favor, inténtao de novo. - Vista previa da miniatura da imaxe - Usar este medio - Usar este vídeo - Elixir o medio + Insertar %d Elixir o vídeo + Elixir o medio + Saber máis + Usar este vídeo + Usar este medio + Vista previa da miniatura da imaxe Non se puido seleccionar o sitio. Por favor, inténtao de novo. + Erro ao cargar no arquivo, por favor, inténtao de novo. + Que hai de novo en %s + Copiar + Insertar + Continuar Continuar + Compartir en + Que hai de novo Fallou o reblog + Non se puido compartir + Copiar o enderezo do enlace + Copiada o enderezo do enlace Administrar blogues - Unha vez que crees un blog en WordPress.com, podes volver a publicar o contido que che gusta no teu propio sitio. Non hai blogs de WordPress.com dispoñibles - Que hai de novo - Copiada o enderezo do enlace - Copiar o enderezo do enlace - Compartir en - Non se puido compartir - Insertar - Continuar - Copiar + Unha vez que crees un blog en WordPress.com, podes volver a publicar o contido que che gusta no teu propio sitio. Número de columnas - Mover o bloque á dereita desde a posición %1$s á posición %2$s - Mover o bloque á dereita + Toca dúas veces para mover o bloque cara a esquerda + Toca dúas veces para mover o bloque cara a dereita Mover o bloque á esquerda desde a posición %1$s á posición %2$s + Mover o bloque á dereita desde a posición %1$s á posición %2$s Mover bloque á esquerda - Toca dúas veces para mover o bloque cara a dereita - Toca dúas veces para mover o bloque cara a esquerda - Axustes do bloque - Creando o escritorio + Mover o bloque á dereita Configurar o tema - Engadindo as características do sitio Obtendo a URL do sitio + Creando o escritorio + Engadindo as características do sitio O teu sitio estará listo en breve Hurra!\nCase está feito + Axustes do bloque Cancelar a subida Houbo un problema ao xestionar a petición - Funciona con Tenor - Elixir desde Tenor - Sábado + Domingo + Luns Venres + Martes + Sábado Xoves Mércores - Martes - Luns - Domingo - Fallou o acceso ao contido dun sitio privado. Algúns medios poden non estar dispoñibles + Funciona con Tenor + Elixir desde Tenor Accedendo ao contido dun sitio privado + Fallou o acceso ao contido dun sitio privado. Algúns medios poden non estar dispoñibles Erro ao recortar e gardar a imaxe, por favor, inténtao de novo. - Erro ao cargar a imaxe.\nPor favor, toca para volver a intentalo. Previsualizar a imaxe Formato de páxina descoñecido - Non puidemos completar esta acción e non se enviou esta páxina a revisión. Non puidemos completar esta acción e non se programou esta páxina. Non puidemos completar esta acción e non se publicou esta páxina privada. - Non puidemos completar esta acción e non se publicou esta páxina. - Non puidemos enviar esta páxina a revisión, pero intentarémolo de novo máis tarde. + Non puidemos completar esta acción e non se enviou esta páxina a revisión. + Erro ao cargar a imaxe.\nPor favor, toca para volver a intentalo. + Non puidemos publicar esta páxina, pero intentarémolo de novo máis tarde. Non puidemos programar esta páxina, pero intentarémolo de novo máis tarde. + Non puidemos completar esta acción e non se publicou esta páxina. Non puidemos publicar esta páxina privada, pero intentarémolo de novo máis tarde. - Non puidemos publicar esta páxina, pero intentarémolo de novo máis tarde. + Non puidemos enviar esta páxina a revisión, pero intentarémolo de novo máis tarde. Non puidemos subir este medio e non se enviou esta páxina a revisión. - Non puidemos subir este medio e non se programou esta páxina. - Non puidemos subir este medio e non se publicou esta páxina privada. - Non puidemos subir este medio e non se publicou a páxina. Gardaremos o teu borrador cando o teu dispositivo volva a estar en liña + Non puidemos subir este medio e non se publicou a páxina. + Non puidemos subir este medio e non se programou esta páxina. Publicaremos a túa páxina privada cando o teu dispositivo volva a estar en liña. - Programaremos a túa páxina cando o teu dispositivo volva a estar en liña. - Enviaremos a túa páxina para revisión cando o teu dispositivo volva a estar en liña. - Publicaremos a páxina cando o teu dispositivo volva a estar en liña. + Non puidemos subir este medio e non se publicou esta páxina privada. Páxina en espera Subindo a páxina O dispositivo está desconectado. A páxina gardouse localmente. Fixeches cambios non gardados nesta páxina - A túa páxina estase subindo - A páxina fallou ao subir os medios e gardouse localmente - Páxina gardada no dispositivo - A páxina gardouse en liña - Selecciona un blog para o atallo a QuickPress - Establecido polo aforrador de batería + Publicaremos a páxina cando o teu dispositivo volva a estar en liña. + Programaremos a túa páxina cando o teu dispositivo volva a estar en liña. + Enviaremos a túa páxina para revisión cando o teu dispositivo volva a estar en liña. Escuro Claro - Aparencia + A páxina gardouse en liña + Establecido polo aforrador de batería + Páxina gardada no dispositivo + A túa páxina estase subindo + Selecciona un blog para o atallo a QuickPress + A páxina fallou ao subir os medios e gardouse localmente Recentemente fixeches cambios nesta páxina, pero non os gardaches. Elixe unha versión para cargar:\n\n + Aparencia Mensaxe de advertencia Amosar o contido da entrada - Amosar só o extracto Enlazar a + Amosar só o extracto Axustes da ligazón Lonxitude do extracto (palabras) Editar o medio da portada PERSONALIZAR URL do enlace do botón - Radio do borde Engadir un bloque de parágrafo - Crear unha entrada + Radio do borde Na papeleira Programada Publicada - A conexión con Facebook non pode encontrar ningunha páxina. Jetpack Social non pode conectar con perfís de Facebook, só con páxinas publicadas. Non conectado + Crear unha entrada + A conexión con Facebook non pode encontrar ningunha páxina. Jetpack Social non pode conectar con perfís de Facebook, só con páxinas publicadas. Gústame - Comentarios + Papeleira Non lido + Comentarios Non enviar á papeleira - Papeleira - Actividade - Entradas e páxinas Xeral + Actividade Engadir unha nova tarxeta + Entradas e páxinas Engadir unha nova tarxeta de estatísticas + Acceder a WordPress.com + Quitar o filtro actual Usa o botón de filtro para encontrar entradas sobre temas específicos Selecciona unha etiqueta ou un blog, ventá emerxente - Quitar o filtro actual - Acceder a WordPress.com - Inicia sesión en WordPress.com para ver as últimas entradas das etiquetas que sigues Inicia sesión en WordPress.com para ver as últimas entradas dos sitios que sigues - Substituír o bloque actual + Inicia sesión en WordPress.com para ver as últimas entradas das etiquetas que sigues Engadir ao final - Engadir ao principio - Engadir o bloque antes Engadir o bloque despois + Engadir o bloque antes + Engadir ao principio + Substituír o bloque actual Engadir unha etiqueta Filtrar - Lenda do vídeo. %s Editar o vídeo Editar os medios + Lenda do vídeo. %s Engadir un shortcode… + baixas + altas + medias + moi altas Autor da entrada Crear unha entrada - Escoitaches todas as estatísticas deste período.\n Se volves a tocar, reiniciarase desde o principio. - Non hai estatísticas neste período. +   e %1$d %2$s Actividade de publicación para %1$s - Os días con visitas %1$s para %2$s son: %2$s %3$s. Toca para máis. explora todas as estatísticas para este período - moi altas - altas - medias - baixas -   e %1$d %2$s + Non hai estatísticas neste período. + Os días con visitas %1$s para %2$s son: %2$s %3$s. Toca para máis. + Escoitaches todas as estatísticas deste período.\n Se volves a tocar, reiniciarase desde o principio. %1$s, %2$d %3$s Lenda da galería. %s Crear unha entrada ou páxina - Creador da web Agora non + Creador da web Calquera cousa que queiras crear ou compartir, axudarémosche a facelo aquí mesmo. - Benvido a WordPress Biblioteca de fotos Imaxe non seleccionada + Benvido a WordPress + Engadir nova + Entrada do blog , seleccionada Imaxe seleccionada Miniatura da imaxe - Entrada do blog - Engadir nova Publicar Sincronizar agora - Esta entrada sincronizarase inmediatamente. Preparado para sincronizar? - Este dominio non está dispoñible + Esta entrada sincronizarase inmediatamente. -%s + Este dominio non está dispoñible Non puidemos acceder ao teu sitio. Terás que contactar co teu aloxamento para solucionalo. - Non puidemos acceder ao teu sitio debido a un problema co <b>certificado SSL</b>. Terás que contactar co teu aloxamento para solucionalo. Non puidemos acceder ao teu sitio porque necesita <b>identificación HTTP</b>. Terás que contactar co teu aloxamento para solucionalo. - Non puidemos acceder no teu sitio ao <b>arquivo XMLRCP</b>. Terás que contactar co teu aloxamento para solucionalo. - Xa case estamos! Só necesitamos verificar o teu enderezo de correo electrónico conectado a Jetpack <b>%1$s</b> - Accede coas credenciais do teu sitio %1$s + Non puidemos acceder ao teu sitio debido a un problema co <b>certificado SSL</b>. Terás que contactar co teu aloxamento para solucionalo. Páxina do sitio + Accede coas credenciais do teu sitio %1$s + Xa case estamos! Só necesitamos verificar o teu enderezo de correo electrónico conectado a Jetpack <b>%1$s</b> + Non puidemos acceder no teu sitio ao <b>arquivo XMLRCP</b>. Terás que contactar co teu aloxamento para solucionalo. + Gardados Gústame Descubre - Gardados - %sE - %sP - %sT %sG %sM - %sK + %sT + %sP + %sE Non podemos abrir as entradas neste momento. Por favor, inténtao de novo máis tarde Non puidemos cargar os datos para o teu sitio neste momento. Por favor, inténtao de novo máis tarde + %sK Biblioteca de medios de WordPress - Non compatible Desagrupar - Toca para ocultar o teclado - Toca aquí para amosar a axuda Fai un vídeo - Fai unha foto ou un vídeo Fai unha foto Empeza a escribir… - Bloque %s. Este bloque ten contido non válido + Toca aquí para amosar a axuda + Fai unha foto ou un vídeo + Toca para ocultar o teclado + Non compatible Bloque %s. Baleiro + Bloque %s. Este bloque ten contido non válido Cortar bloque - Problema ao abrir o vídeo - Problema ao amosar o bloque + Pegar a URL + Abrir os axustes Título da entrada. %s Título da entrada. Baleiro - Pegar a URL Bloque de salto de páxina. %s - Abrir os axustes + Problema ao amosar o bloque + Problema ao abrir o vídeo Ningunha aplicación pode manexar esta petición. Por favor, instala un navegador web. Navegar arriba Mover o bloque cara arriba, da fila %1$s á fila %2$s - Mover o bloque arriba Mover o bloque cara abaixo, da fila %1$s á fila %2$s - Mover o bloque abaixo - Texto do enlace + Mover o bloque arriba + Icona de axuda Enlace insertado - Lenda da imaxe. %s Ocultar o teclado - Icona de axuda + Lenda da imaxe. %s Toca dúas veces para desfacer o último cambio + Mover o bloque abaixo + Texto do enlace + Toca dúas veces para seleccionar Toca dúas veces para alternar os axustes - Toca dúas veces para seleccionar unha imaxe Toca dúas veces para seleccionar un vídeo - Toca dúas veces para seleccionar + Toca dúas veces para seleccionar unha imaxe Toca dúas veces para refacer o último cambio - Toca dúas veces para mover o bloque cara arriba - Toca dúas veces para mover o bloque cara abaixo - Toca dúas veces para editar este valor Toca dúas veces para engadir un bloque Toca dúas veces e mantén para editar - O valor actual é %s + Toca dúas veces para editar este valor + Toca dúas veces para mover o bloque cara arriba + Toca dúas veces para mover o bloque cara abaixo Elixir desde o dispositivo - Ocorreu un erro descoñecido. Por favor, inténtao de novo. - Texto alternativo - Engadir vídeo + O valor actual é %s Engadir a URL - Engadir o texto alternativo + Texto alternativo ENGADIR O BLOQUE AQUÍ + Ocorreu un erro descoñecido. Por favor, inténtao de novo. + Engadir o texto alternativo Engadir descrición - Toca o botón «Engadir ás entradas gardadas» para gardar unha entrada na túa lista. + Engadir vídeo A lista cargouse con %1$d elementos. + Toca o botón «Engadir ás entradas gardadas» para gardar unha entrada na túa lista. Notificacións - Desactivado Activado + Desactivado Ao desactivar os avisos para este sitio, desactivaranse os avisos mostrados na pestana de avisos deste sitio. Podes axustar que tipo de aviso ves despois de activar os avisos para este sitio. - Para ver os avisos na pestana de avisos deste sitio, activa os avisos para este sitio. - Activar os avisos mostrados na pestana de avisos deste sitio - Desactivar os avisos mostrados na pestana de avisos deste sitio Avisos para este sitio Avisos para este sitio + Activar os avisos mostrados na pestana de avisos deste sitio + Desactivar os avisos mostrados na pestana de avisos deste sitio + Para ver os avisos na pestana de avisos deste sitio, activa os avisos para este sitio. Engadir unha imaxe ou un vídeo - Non puidemos enviar esta entrada para revisión, pero intentarémolo de novo máis tarde. Non puidemos programar esta entrada, pero intentarémolo de novo máis tarde. Non puidemos publicar esta entrada privada, pero intentarémolo de novo máis tarde. + Non puidemos enviar esta entrada para revisión, pero intentarémolo de novo máis tarde. Non puidemos publicar esta entrada, pero intentarémolo de novo máis tarde. - Non puidemos completar esta acción e non se enviou esta entrada para revisión. + Non puidemos completar esta acción e non se publicou esta entrada. Non puidemos completar esta acción e non se programou esta entrada. Non puidemos completar esta acción e non se enviou esta entrada privada. - Non puidemos completar esta acción e non se publicou esta entrada. - Non puidemos subir este medio e non se enviou esta entrada para revisión. + Non puidemos completar esta acción e non se enviou esta entrada para revisión. + Non puidemos subir este medio. + Non puidemos subir este medio e non se publicou a entrada. Non puidemos subir este medio e non se programou esta entrada. Non puidemos subir este medio e non se publicou esta entrada privada. - Non puidemos subir este medio e non se publicou a entrada. - Non puidemos subir este medio. - Non puidemos completar esta acción, pero intentarémolo de novo máis tarde. - Non puidemos completar esta acción. - Non se pode previsualizar un borrador baleiro - Non se pode previsualizar unha páxina baleira - Non se pode previsualizar unha entrada baleira + Non puidemos subir este medio e non se enviou esta entrada para revisión. Vista previa non dispoñible - Erro ao intentar gardar a entrada antes de previsualizala Xerando a vista previa… + Non se pode previsualizar unha entrada baleira + Non se pode previsualizar unha páxina baleira + Non se pode previsualizar un borrador baleiro + Non puidemos completar esta acción. + Erro ao intentar gardar a entrada antes de previsualizala + Non puidemos completar esta acción, pero intentarémolo de novo máis tarde. Gardando… Fixeches cambios non gardados nesta entrada + Borrar permanentemente A versión desde esta aplicación A versión desde outro dispositivo - Desde esta aplicación\nGardado en %1$s\n\nDesde outro dispositivo\nGardado en %2$s\n - Recentemente fixeches cambios nesta entrada, pero non os gardaches. Elixe unha versión para cargar:\n\n Que versión che gustaría editar? - Borrar permanentemente Non gardaremos os últimos cambios no teu borrador. + Recentemente fixeches cambios nesta entrada, pero non os gardaches. Elixe unha versión para cargar:\n\n + Desde esta aplicación\nGardado en %1$s\n\nDesde outro dispositivo\nGardado en %2$s\n + Non publicaremos estes cambios. Non programaremos estes cambios. Non enviaremos estes cambios para revisión. - Non publicaremos estes cambios. Gardaremos o teu borrador cando o teu dispositivo volva a estar en liña Publicaremos a túa entrada privada cando o teu dispositivo volva a estar en liña. + Publicaremos a entrada cando o teu dispositivo volva a estar en liña. Programaremos a túa entrada cando o teu dispositivo volva a estar en liña. Enviaremos a túa entrada para revisión cando o teu dispositivo volva a estar en liña. - Publicaremos a entrada cando o teu dispositivo volva a estar en liña. - Esta acción non pode cancelarse. É posible que o nome de usuario xa se actualizara. - O teu novo nome de usuario é %1$s Gardando o nome de usuario… - Cambiar o nome do usuario - Estás cambiando o teu nome de usuario a %1$s%2$s%3$s. Cambiar o teu nome de usuario tamén afectará ao teu perfil de Gravatar e ás direccións de perfil de Intense Debate. Para continuar, confirma o teu novo nome de usuario. + O teu novo nome de usuario é %1$s + Esta acción non pode cancelarse. É posible que o nome de usuario xa se actualizara. Coidado! - Estás a punto de cambiar o teu nome de usuario, que actualmente é %1$s%2$s%3$s. Non poderás volver a recuperar o teu nome de usuario. - Ver e cambiar os axustes de rendemento de Jetpack + Cambiar o nome do usuario Rendemento e velocidade + Ver e cambiar os axustes de rendemento de Jetpack + Estás a punto de cambiar o teu nome de usuario, que actualmente é %1$s%2$s%3$s. Non poderás volver a recuperar o teu nome de usuario. + Estás cambiando o teu nome de usuario a %1$s%2$s%3$s. Cambiar o teu nome de usuario tamén afectará ao teu perfil de Gravatar e ás direccións de perfil de Intense Debate. Para continuar, confirma o teu novo nome de usuario. + Desactivados Máis - Substitúe a busca integrada en WordPress cunha experiencia mellorada de busca - Busca mellorada + Medios + Imaxes máis rápidas Busca de Jetpack + Busca mellorada + Arquivos estáticos máis rápidos Aloxamento de vídeo sen anuncios - Medios + Substitúe a busca integrada en WordPress cunha experiencia mellorada de busca Carga as páxinas máis rápido ao permitir a Jetpack optimizar as túas imaxes e arquivos estáticos (como CSS e JavaScript). - Arquivos estáticos máis rápidos - Imaxes máis rápidas - Desactivados Activados + Rendemento Acelerador de sitios Mellora a velocidade do teu sitio ao cargar só as imaxes visibles na pantalla. - Rendemento Descargas Arquivo Descargas de arquivos - As estatísticas de descarga de arquivos non se rexistraron antes do 28 de xuño de 2019. - Zona horaria do sitio (UTC -%s) - Zona horaria do sitio (UTC +%s) Zona horaria do sitio (UTC) - Escritorio - Por defecto - Pechar o diálogo - Seleccionar o tipo de vista previa + Zona horaria do sitio (UTC +%s) + Zona horaria do sitio (UTC -%s) + As estatísticas de descarga de arquivos non se rexistraron antes do 28 de xuño de 2019. Compartir + Por defecto Volver + Escritorio Avanzar - «%1$s» programado para publicar o «%2$s» na túa aplicación de %3$s\n%4$s + Seleccionar o tipo de vista previa Entrada programada de WordPress: «%s» «%s» publicarase en 10 minutos - «%s» publicarase en 1 hora + «%1$s» programado para publicar o «%2$s» na túa aplicación de %3$s\n%4$s + Pechar o diálogo + Cando se publique + Entrada programada Publicouse «%s» - Entrada programada: recordatorio de 10 minutos Entrada programada: recordatorio de 1 hora - Entrada programada + Entrada programada: recordatorio de 10 minutos + «%s» publicarase en 1 hora O aviso non pode crearse cando a data de publicación xa pasou. - Cando se publique - 10 minutos antes - 1 hora antes Desactivados - Engadir ao calendario Aviso + 1 hora antes + Engadir ao calendario + 10 minutos antes Data e hora Por favor, introduce un enderezo completo dunha web, como exemplo.gal. - Accede con WordPress.com para conectar con %1$s - Visitas Entrada - %1$s: %2$s, %3$s: %4$s - Elemento contraído - Elemento expandido - Contraer + Visitas + Editor Ampliar + Contraer + Elemento expandido + Elemento contraído Gráfico actualizado. - %1$s %2$s do período: %3$s, cambio desde o período anterior - %4$s + %1$s: %2$s, %3$s: %4$s Cargando os datos da tarxeta seleccionada - Editor + Accede con WordPress.com para conectar con %1$s + %1$s %2$s do período: %3$s, cambio desde o período anterior - %4$s Ampliar Contraer - Verifica o teu enderezo de correo electrónico - as instrucións enviáronse ao teu correo electrónico Verifica o teu enderezo de correo electrónico - as instrucións enviáronse a %s - Cancelar - Aceptar + Verifica o teu enderezo de correo electrónico - as instrucións enviáronse ao teu correo electrónico http(s):// - Quitar enlace + Aceptar + Cancelar Insertar enlace + Quitar enlace Reintentar a subida Subindo medios.\nPor favor, toca para ver as opcións. Abrir enlace nunha nova ventá/pestana Para ver as túas estatísticas accede á conta de WordPress.com. - Ningunha entrada coincide coa túa busca + Hoxe + Histórico + Dun vistazo Buscar entradas + Ningunha entrada coincide coa túa busca Aquí é onde a xente te encontra en Internet. Elixe un nome de dominio personalizado Todos os plans anuais de WordPress.com inclúen un nome de dominio personalizado. Rexistra agora o teu dominio gratuíto. - Dun vistazo - Hoxe - Histórico - Visitas esta semana - Por favor, accede á aplicación WordPress para engadir un widget. - Non hai ningunha rede dispoñible - Non se pudieron cargar os datos + Escuro + Sitio Tipo Cor - Selecciona o teu sitio - Escuro Claro Cor - Selecciona o teu sitio - Sitio Histórico - Visitas esta semana Engadir widget + Visitas esta semana + Visitas esta semana + Selecciona o teu sitio + Selecciona o teu sitio + Non se pudieron cargar os datos + Non hai ningunha rede dispoñible + Por favor, accede á aplicación WordPress para engadir un widget. Está levando máis tempo do normal recargar os detalles do plugin. Por favor, compróbao de novo máis tarde. Se acabas de rexistrar un nome de dominio, por favor, espera ata que terminemos de configuralo e inténtao de novo.\n\nEn caso contrario, parece que algo saíu mal e a característica do plugin podería non estar dispoñible para este sitio. Estado (non dispoñible) - Ao rexistrar este dominio aceptas os nosos %1$stermos e condicións%2$s - Comproba a túa conexión á rede e inténtao de novo. Non se puido cargar esta páxina neste momento. - Non se puideron recuperar os axustes. Algunhas APIs non están dispoñibles para a conta e ID desta aplicación OAuth. + Comproba a túa conexión á rede e inténtao de novo. Ao configurar Jetpack aceptas os nosos %1$stermos e condicións%2$s + Ao rexistrar este dominio aceptas os nosos %1$stermos e condicións%2$s + Non se puideron recuperar os axustes. Algunhas APIs non están dispoñibles para a conta e ID desta aplicación OAuth. + Actualizar contrasinal + Contrasinal actualizado Non hai ningunha conexión. A edición está desactivada. Para volver a conectar a aplicación co teu sitio aloxado, introduce aquí o novo contrasinal do sitio. - Contrasinal actualizado - Actualizar contrasinal Rexistrando o nome de dominio… Selecciona a provincia Selecciona o país - Rexistrar un dominio Código Postal - Provincia Cidade Enderezo 2 + Provincia + Teléfono Enderezo País Código do país - Teléfono + Rexistrar un dominio Organización (opcional) Para a túa comodidade, completamos a túa información de contacto\n de WordPress.com. Por favor, comproba que é a información correcta que queres usar para este dominio. - Información de contacto do dominio Rexistrar publicamente + Información de contacto do dominio Rexistrar privadamente con protección de privacidade Os propietarios de dominios teñen que compartir información nunha base de datos pública de todos os dominios.\n Coa protección de privacidade publicamos a nosa propia información en vez da túa, e redirixirémosche de forma privada calquera comunicación dirixida a ti. Protección da privacidade @@ -2180,8 +2180,8 @@ Language: gl_ES Novo Descartar Próbao agora - Elixe que estatísticas ver, e céntrate nos datos que máis te preocupen. Toca en %1$s ao fondo das estatísticas para personalizalas. Xestiona as túas estatísticas + Elixe que estatísticas ver, e céntrate nos datos que máis te preocupen. Toca en %1$s ao fondo das estatísticas para personalizalas. Recuperando revisións… Fallo ao insertar os medios.\nPor favor, toca para ver as opcións. Fallo ao insertar os medios.\nPor favor, toca para volver a intentalo. @@ -2230,7 +2230,6 @@ Language: gl_ES Rexistrar dominio Para instalar plugins necesitas ter un dominio personalizado asociado ao teu sitio. Instalar plugin - Poderás personalizar a aparencia do teu sitio máis adiante Publicar o: %s Programada para o: %s Publicado o: %s @@ -2241,6 +2240,7 @@ Language: gl_ES Período Meses e anos Cargar máis + Poderás personalizar a aparencia do teu sitio máis adiante Hoxe Mellor hora Mellor día @@ -2254,531 +2254,531 @@ Language: gl_ES O sitio aínda non se cargou Máis entradas Menos entradas - Podes perder o que levas feito. Estás seguro de que queres saír? Ver os plans - Requírese unha conexión a Internet para ver os plans, así que os detalles poderían estar desactualizados. Requírese unha conexión a Internet para ver os plans. + Podes perder o que levas feito. Estás seguro de que queres saír? Non podemos cargar os plans neste momento. Por favor, inténtao de novo. - Non se poden cargar os plans + Requírese unha conexión a Internet para ver os plans, así que os detalles poderían estar desactualizados. Non hai conexión - Cambiar ao editor de bloques - Houbo un problema ao cargar os teus datos, recarga a páxina e inténtao de novo. Datos non cargados - Edita as novas entradas e páxinas co editor de bloques Usar editor de bloques + Non se poden cargar os plans + Cambiar ao editor de bloques + Edita as novas entradas e páxinas co editor de bloques + Houbo un problema ao cargar os teus datos, recarga a páxina e inténtao de novo. saír + Seguintes pasos + Os teus visitantes verán a túa icona no seu navegador. Engade unha icona personalizada para conseguir un aspecto profesional e refinado. Fai crecer a túa audiencia Personaliza o teu sitio - Seguintes pasos Elixe unha icona do sitio único - Os teus visitantes verán a túa icona no seu navegador. Engade unha icona personalizada para conseguir un aspecto profesional e refinado. - Toca en %1$s Estatísticas %2$s para ver como está rendendo o teu sitio. Toca en %1$s Icona do teu sitio %2$s para subir un novo + Toca en %1$s Estatísticas %2$s para ver como está rendendo o teu sitio. Garda en borrador e publica unha entrada. Activar compartir entradas Comparte automaticamente as novas entradas nas túas contas de medios sociais. Revisa as estatísticas do teu sitio Mantente ao día sobre o rendemento do teu sitio. - Saltar tarefa Recordatorio + Saltar tarefa + Hora máis popular Elixe o seguinte período Elixe o período anterior - %1$s de vistas - Hora máis popular %1$s (%2$s) +%1$s (%2$s) - Mostrando a vista previa + %1$s de vistas Baleirar - Parece que tes unha conexión lenta. Se non ves o teu novo sitio na lista, inténtao actualizando. + Crear sitio + Crear sitio + Houbo un problema + Mostrando a vista previa Cancelar o asistente de creación de sitios Estamos creando o teu novo sitio - Houbo un problema - Crear sitio - Crear sitio Aquí é onde a xente te encontra en Internet. + Parece que tes unha conexión lenta. Se non ves o teu novo sitio na lista, inténtao actualizando. + Houbo un problema Non hai direccións dispoñibles que coincidan coa túa busca Erro durante a comunicación co servidor. Inténtao de novo - Houbo un problema Houbo un problema - Creouse o teu sitio! - %1$d de %2$d Crear sitio + %1$d de %2$d + Conflicto de versións Suxerencias actualizadas + Creouse o teu sitio! Non se puido seleccionar o sitio auto-hospedado que acabas de engadir - Conflicto de versións - Activa os informes de erros automáticos para axudarnos a mellorar o rendemento da app. - Informes de erros Desfacer + Descartar web + Informes de erros + Actualizando contido Versión web descartada Versión local descartada - Actualizando contido - Descartar web + Activa os informes de erros automáticos para axudarnos a mellorar o rendemento da app. Descartar local - Local\nGardado o %1$s\n\nWeb\nGardado o %2$s\n - Este contido ten dúas versións en conflito. Selecciona que versión queres descartar.\n Resolver conflicto de sincronización + Este contido ten dúas versións en conflito. Selecciona que versión queres descartar.\n + Local\nGardado o %1$s\n\nWeb\nGardado o %2$s\n Non hai datos neste período Eliminar a ubicación dos medios Non podemos abrir as estatísticas neste momento. Por favor, inténtao de novo máis tarde - Ningún medio coincide coa túa busca - Busca para encontrar GIF para engadir á túa biblioteca de medios! - Visitas Autor Autores + Tumblr + Twitter + Facebook + Path + LinkedIn + Google+ + Visitas + Visitas + Título Visitas - Buscar termo - Buscar termos Visitas - Título + Visitas Vídeos - Visitas - País - Países - Clics - Ligazón Clics - Visitas + Clics + País Referente + Ver máis Referentes + Países + Compartir entrada + Buscar termo + Crear entrada + Buscar termos Entradas e páxinas - Path - LinkedIn - Google+ - Tumblr - Twitter - Facebook - Ver máis - Compartir entrada - Crear entrada + Ningún medio coincide coa túa busca + Busca para encontrar GIF para engadir á túa biblioteca de medios! Pasaron %1$s desde que se publicou %2$s. Así é como funcionou a entrada ata agora: - Pasaron %1$s desde que se publicou %2$s. Pon a bola a rodar e aumenta as vistas das entradas compartindo a túa entrada: - Etiquetas e categorías + Ligazón Histórico - %1$s - %2$s - Servizo - %1$s | %2$s - Visitas - Título - Visitas - Título - Comentarios - Título + Etiquetas e categorías + Pasaron %1$s desde que se publicou %2$s. Pon a bola a rodar e aumenta as vistas das entradas compartindo a túa entrada: Autor - Entradas e páxinas Autores + WordPress.com + Título + Título + Visitas + Título Desde Correo electrónico - WordPress.com + Visitas + Servizo + Comentarios + %1$s | %2$s + %1$s - %2$s Xestionar datos - Aínda non se engadiron impresións + Entradas e páxinas Aínda non hai datos + Aínda non se engadiron impresións Menú de depuración Cambiando contrasinal… - O teu contrasinal debe ter polo menos seis caracteres de lonxitude. Para facelo máis forte, usa letras maiúsculas e minúsculas, números e símbolos coma ! \" ? $ % ^ & ). - Contrasinal cambiado con éxito Cambiar contrasinal + Contrasinal cambiado con éxito + O teu contrasinal debe ter polo menos seis caracteres de lonxitude. Para facelo máis forte, usa letras maiúsculas e minúsculas, números e símbolos coma ! \" ? $ % ^ & ). Nome (sen titulo) Vista previa HTML Vista previa visual Revision - Anterior Seguinte + Anterior %1$s utilizado - Por favor, introduce un sitio WordPress WordPress.com ou autoaloxado conectado a Jetpack - Cargando revisión - Revisión cargada Cargar + Aínda non hai histórico + Revisión cargada + Cargando revisión Entrada creada o %1$s ás %2$s Páxina creada o %1$s ás %2$s - Aínda non hai histórico Cando fas cambios á túa entrada poderás ver aquí o histórico Cando fas cambios á túa páxina poderás ver aquí o histórico + Por favor, introduce un sitio WordPress WordPress.com ou autoaloxado conectado a Jetpack Avatar do usuario - Tamaño completo Grande Mediano - Miniatura Historia - A páxina seleccionada non está dispoñible + Tamaño completo + Miniatura Pendente de revisión + A páxina seleccionada non está dispoñible + Buscar páxinas + Mover a borradores + Borrar permanentemente + Ningunha páxina coincide coa túa busca + Non tes ningunha páxina en borrador Non tes ningunha páxina na papeleira Non tes ningunha páxina programada - Non tes ningunha páxina en borrador Todavía non publicaches ningunha páxina - Buscar páxinas - Ningunha páxina coincide coa túa busca - Borrar permanentemente Mover á papeleira - Mover a borradores - Facer superior Ver - No lixo - Programadas - Borradores Publicadas + Borradores + Programadas + No lixo + Facer superior Fixemos demasiados intentos para enviar un código de verificación por SMS - tómate un descanso e solicita un novo dentro dun minuto. - Non hai ningunha conta de WordPress.com que coincida con esta conta de Google. + A páxina superior cambiou Ningún sitio coincide coa túa busca + Non hai ningunha conta de WordPress.com que coincida con esta conta de Google. Ningún blog coincide coa túa busca - A páxina superior cambiou - A páxina borrouse permanentemente - A páxina foi programada - A páxina foi publicada + Nivel superior + Facer superior A páxina enviouse á papeleira A páxina moveuse a borradores - Nivel superior + A páxina borrouse permanentemente + Houbo un problema ao borrar a páxina Estás seguro de querer borrar a páxina %s? Houbo un problema ao cambiar a páxina superior Houbo un problema ao cambiar o estado da páxina - Houbo un problema ao borrar a páxina - Facer superior Descartar + A páxina foi programada + A páxina foi publicada toca aquí Crea o teu sitio Pon o teu sitio en marcha. A que se sinte un ben terminando unha lista? Ver o teu sitio - Previsualiza o teu sitio para ver o que verán os teus visitantes. Comparte o teu sitio - Toca en %1$s Social %2$s para continuar Toca en %1$s Conexións %2$s para engadir as túas contas de medios sociais Conecta coas túas contas de medios sociais - o teu sitio compartirá automaticamente as novas entradas. + Previsualiza o teu sitio para ver o que verán os teus visitantes. + Toca en %1$s Social %2$s para continuar Publica unha entrada Toca en %1$s Crear entrada %2$s para crear unha nova entrada - Non, grazas Segue outros sitios + Non, grazas Ir + Máis Cancelar Agora non - Máis Non tes sitios Engade aquí etiquetas para descubrir entradas sobre as túas temáticas favoritas - Accede á conta de WordPress.com que usaches para conectar con Jetpack. Jetpack FAQ de Jetpack + Accede á conta de WordPress.com que usaches para conectar con Jetpack. Para usar as estatísticas no teu sitio WordPress necesitas instalar o plugin Jetpack. - Non hai temas que coincidan coa túa busca + Crea unha etiqueta + Saír de WordPress? + No tes ningunha etiqueta Que che gustaría encontrar? Non hai etiquetas que coincidan coa túa busca - No tes ningunha etiqueta - Engade aquí as etiquetas que uses frecuentemente para poder seleccionalas rapidamente ao etiquetar as túas entradas - Crea unha etiqueta Ningún medio coincide coa túa busca - Saír de WordPress? + Non hai temas que coincidan coa túa busca + Engade aquí as etiquetas que uses frecuentemente para poder seleccionalas rapidamente ao etiquetar as túas entradas Tes cambios en entradas que non se subiron ao teu sitio. Saír agora borrará eses cambios do teu dispositivo. Queres saír de todos modos? - Aínda non hai lectores Aínda non hai usuarios + Aínda non hai lectores As entradas que che gusten aparecerán aquí Aínda non che gustou nada Descubre blogs Aínda non hai gústame Como estás nun plan gratuíto verás eventos limitados na túa actividade. - Cando fagas cambios no teu sitio poderás ver o historial da túa actividade aquí Aínda non hai actividade + Cando fagas cambios no teu sitio poderás ver o historial da túa actividade aquí + Sube medios Crear unha entrada Crea unha páxina - Sube medios Non tes ningún medio - galería de imaxes icona do sitio imaxe do tema + galería de imaxes imaxe destacada Descartar foto de perfil - Dato transitorio Email - Por favor, introduce o teu enderezo de correo electrónico - Para continuar, por favor, introduce o teu enderezo de correo electrónico e o nome - Novo mensaxe de «Axuda e soporte» WordPress Non establecido + Dato transitorio Correo electrónico de contacto + Por favor, introduce o teu enderezo de correo electrónico + Novo mensaxe de «Axuda e soporte» + Para continuar, por favor, introduce o teu enderezo de correo electrónico e o nome Restauración en progreso Restaurando a %1$s %2$s + Botón de acción do rexistro de actividade Actualmente restaurando o teu sitio O teu sitio restaurouse satisfactoriamente O teu sitio restaurouse con éxito\nRebobinado a %1$s %2$s O teu sitio está a ser restaurado\nRebobinando a %1$s %2$s - Botón de acción do rexistro de actividade Xestionado automaticamente Garda esta entrada e volve cando queiras para lela. Só estará dispoñible neste dispositivo — as entradas gardadas non se sincronizan con outros dispositivos. + Non se encontraron resultados Gardar entradas para máis tarde Non se puido realizar a busca - Non se encontraron resultados - Le a entrada de orixe Sitios + Le a entrada de orixe Enviado enlace máxico - Verificación do código - Credenciais de acceso Enviado enlace máxico Acceso por enlace máxico + Verificación do código + Credenciais de acceso Acceso mediante o enderezo do sitio Acceso mediante enderezo de correo electrónico - Toca %s para gardar unha entrada na túa lista. - Aínda non hai entradas gardadas! - Entrada gardada + Borrado Ver todas - Borrada das entradas gardadas - Engadir ás entradas gardadas + Entrada gardada Entradas gardadas - Borrado - Cambiar icona do sitio - Cancelar + Engadir ás entradas gardadas + Aínda non hai entradas gardadas! + Borrada das entradas gardadas + Toca %s para gardar unha entrada na túa lista. Eliminar + Cancelar + Activar Cambiar - Non tes permiso para editar a icona do sitio. - Non tes permiso para engadir unha icona ao sitio. - Como che gustaría editar a icona? - Gustaríache engadir unha icona do sitio? - Icona do sitio este sitio - Activar - Activar avisos para %1$s%2$s%3$s? - Activar avisos do blog - Desactivar os avisos do blog - Icona de Jetpack + Icona do sitio + Cambiar icona do sitio + Gustaríache engadir unha icona do sitio? + Como che gustaría editar a icona? + Non tes permiso para engadir unha icona ao sitio. + Non tes permiso para editar a icona do sitio. Evento - Icona de actividade + Icona de Jetpack Rexistro de actividade - Le a política de privacidade - Usamos outras ferramentas de seguimento, incluídas algunhas de terceiros. Le acerca destas e como controlalas. - Política de terceiros - Esta información axúdanos a mellorar os nosos produtos, facer que o marketing sexa máis relevante, personalizar a túa experiencia en WordPress.com e máis, tal como se detalla na nosa política de privacidade. - Política de privacidade - Comparte información coa nosa ferramenta de análise acerca do uso que fas dos servizos mentres estás conectado á túa conta de WordPress.com. + Icona de actividade Política de cookies + Política de privacidade Axustes de privacidade + Política de terceiros Recompilar información + Le a política de privacidade + Activar avisos para %1$s%2$s%3$s? + Usamos outras ferramentas de seguimento, incluídas algunhas de terceiros. Le acerca destas e como controlalas. + Comparte información coa nosa ferramenta de análise acerca do uso que fas dos servizos mentres estás conectado á túa conta de WordPress.com. + Esta información axúdanos a mellorar os nosos produtos, facer que o marketing sexa máis relevante, personalizar a túa experiencia en WordPress.com e máis, tal como se detalla na nosa política de privacidade. + Activar avisos do blog + Desactivar os avisos do blog Entrada enviada Unha característica do plugin require que o sitio estea en bo estado. Unha característica do plugin necesita que a subscrición do dominio principal estea asociada con este usuario. - Unha característica do plugin necesita privilexios de administrador. O plugin non pode instalarse en sitios VIP. - O plugin non se pode instalar debido ás limitacións de espazo do disco. - Unha característica do plugin require un enderezo de correo electrónico verificado. - Unha característica do plugin require que o sitio sexa público. - Unha característica do plugin require un plan business. Unha característica do plugin require un dominio personalizado. + Unha característica do plugin require un plan business. + Unha característica do plugin necesita privilexios de administrador. + Unha característica do plugin require que o sitio sexa público. + Unha característica do plugin require un enderezo de correo electrónico verificado. + O plugin non se pode instalar debido ás limitacións de espazo do disco. Estamos facendo a configuración final, está case listo… Instalando plugin… Instalar Instalar o primeiro plugin no teu sitio pode levar ata 1 minuto. Durante este tempo non poderás realizar cambios no teu sitio. - Instalar plugin Notificacións - Enviarme novos comentarios por correo electrónico + Diariamente Semanalmente Instantaneamente - Diariamente Novas entradas - Recibe avisos das novas entradas deste sitio + Instalar plugin Enviarme novas entradas por correo electrónico - Todos os meus sitios seguidos + Enviarme novos comentarios por correo electrónico + Recibe avisos das novas entradas deste sitio Sitios seguidos - Dispositivo de lectura personal con avisos + Todos os meus sitios seguidos Xente mirando gráficos e táboas - %1$s en %2$s + Dispositivo de lectura personal con avisos Seguro que queres eliminar definitivamente esta publicación? - Importante + %1$s en %2$s Xeral + Importante Utilizar esta foto %1$d de %2$d + Engadir %d + Vista previa %d + %1$s de ilimitado Fotografías facilitadas por %s - Busca para encontrar fotografías gratuítas para engadir á túa biblioteca de medios Busca na biblioteca de fotos gratuítas - Selecciona da biblioteca gratuíta de fotos Non se pode gardar un borrador baleiro - %1$s de ilimitado - Vista previa %d - Engadir %d + Selecciona da biblioteca gratuíta de fotos + Busca para encontrar fotografías gratuítas para engadir á túa biblioteca de medios Crear etiqueta - navegar cara arriba Notificacións - Abrir enlace externo - amosar máis + reproduce + reintentar + papeleira + audio foto borrar + vista previa + eliminar %s + información do perfil + amosar máis Reproducir vídeo - reproducir vídeo destacado + reproducir vídeo + marca de verificación + abrir cámara logo do plugin + navegar cara arriba banner do plugin - elixe desde medios de WordPress - abrir cámara - elixe desde o dispositivo - información do perfil - reproduce previsualizar imaxe - vista previa - audio - reproducir vídeo - papeleira - reintentar - vista previa de medios, nome do arquivo %s - eliminar %s + elixe desde o dispositivo + Abrir enlace externo + reproducir vídeo destacado Imaxe de perfil de %s - marca de verificación Rexístrarte con Google… + elixe desde medios de WordPress + vista previa de medios, nome do arquivo %s Fallou a conexión a Jetpack: %s Xa estás conectado a Jetpack - Modo visual - Modo HTML + %s TB Vista previa + Modo HTML + Modo visual Gardar coma borrador - %s TB %s GB %s MB %s kB - %s B %1$s de %2$s - Se necesitas máis espazo, considera actualizar o teu plan de WordPress. - Espazo utilizado + %s B Medios - Comentario marcado como non spam - Comentario marcado como spam + Elixe o sitio + Espazo utilizado + Editar foto + Nova conta + O comentario gustou + O comentario non gustou Comentario borrado Comentario restaurado - Comentario enviado á papeleira - O comentario non gustou - O comentario gustou - Comentario sen aprobar Comentario aprobado + Comentario sen aprobar + Comentario enviado á papeleira + Comentario marcado como spam Detalle de notificación %s - Editar foto - Elixe o sitio - Nova conta + Comentario marcado como non spam + Se necesitas máis espazo, considera actualizar o teu plan de WordPress. + Lector + Notificacións + Eu + Detalles do arquivo Conectado como Detalle da persoa - Detalles do arquivo Botóns de compartir - Notificacións - Lector - Eu - O meu sitio Axustes de avisos + O meu sitio O teu avatar subiuse e estará dispoñible en breve. - Parece que desactivaches os permisos necesarios para esta característica.<br/><br/>Para cambialo, edita os teus permisos e asegúrate de que <strong>%s</strong> estea activado. - Permisos + Version %s Destacados - Non podes acceder aos teus axustes para compartir en redes sociais porque o teu módulo Jetpack Social está desactivado. + Permisos + Parece que desactivaches os permisos necesarios para esta característica.<br/><br/>Para cambialo, edita os teus permisos e asegúrate de que <strong>%s</strong> estea activado. Módulo Social desactivado. - Version %s + Non podes acceder aos teus axustes para compartir en redes sociais porque o teu módulo Jetpack Social está desactivado. O son escollido ten unha ruta incorrecta. Por favor, elixe un distinto. QP %s - quedan %1$d páxinas / entradas Queda 1 páxina quedan %1$d páxinas quedan %1$d entradas - %1$d páxinas / entradas e 1 arquivo restantes + quedan %1$d páxinas / entradas %1$d entradas e 1 arquivo restantes %1$d páxinas e 1 arquivo restantes - 1 entrada e 1 arquivo restantes + %1$d páxinas / entradas e 1 arquivo restantes 1 páxina e 1 arquivo restantes - %1$d páxinas / entradas e %2$d de %3$d arquivos restantes + 1 entrada e 1 arquivo restantes + queda 1 páxina e %1$d de %2$d arquivos + queda 1 entrada e %1$d de %2$d arquivos %1$d entradas e %2$d de %3$d arquivos restantes quedan %1$d páxinas e %2$d de %3$d arquivos - queda 1 entrada e %1$d de %2$d arquivos - queda 1 páxina e %1$d de %2$d arquivos - %1$d entradas / páxinas sen subir + %1$d páxinas / entradas e %2$d de %3$d arquivos restantes %1$d páxinas sen subir + %1$d entradas / páxinas sen subir 1 páxina sen subir - %1$d entradas sen subir 1 entrada sen subir - %1$d entradas / páxinas con %2$d arquivos sen subir - %1$d páxinas %2$d arquivos sen subir + %1$d entradas sen subir 1 páxina con %1$d arquivos sen subir - %1$d entradas con %2$d arquivos sen subir 1 entrada con %1$d arquivos sen subir - %1$d entradas / páxinas con 1 arquivo sen subir - %1$d páxinas con 1 arquivo sen subir + %1$d entradas con %2$d arquivos sen subir + %1$d páxinas %2$d arquivos sen subir + %1$d entradas / páxinas con %2$d arquivos sen subir + \@%s + (sen título) + 1 entrada con 1 arquivo sen subir 1 páxina con 1 arquivo sen subir + %1$d páxinas con 1 arquivo sen subir %1$d entradas con 1 arquivo sen subir - 1 entrada con 1 arquivo sen subir - (sen título) - \@%s + %1$d entradas / páxinas con 1 arquivo sen subir Crear sitio - Toca para continuar. + Gardar + Descartar + Engadir avatar Sitio creado! - A Google levoulle demasiado tempo responder. Pode que teñas que esperar ata que teñas unha conexión a internet máis rápida. Cambiar o nome do usuario + Toca para continuar. + Descartas cambiar de nome de usuario? Teclea para obter máis suxerencias - O teu nome de usuario actual é %1$s%2$s%3$s. Con poucas excepcións, outros só verán o teu nome a amosar, %4$s%5$s%6$s. - Non se suxeriu ningún nome de usuario desde %1$s%2$s%3$s. Por favor, introduce máis letras ou números para obter suxerencias. Ocorreu un erro ao recuperar suxerencias de nomes de usuario. - Descartas cambiar de nome de usuario? - Descartar - Gardar - Engadir avatar + A Google levoulle demasiado tempo responder. Pode que teñas que esperar ata que teñas unha conexión a internet máis rápida. + Non se suxeriu ningún nome de usuario desde %1$s%2$s%3$s. Por favor, introduce máis letras ou números para obter suxerencias. + O teu nome de usuario actual é %1$s%2$s%3$s. Con poucas excepcións, outros só verán o teu nome a amosar, %4$s%5$s%6$s. O correo electrónico xa existe en WordPress.com.\nAcceder. - Actualizando conta… Enviando correo + Actualizando conta… + Reintentar Reintentar - Pechar - Houbo algún problema ao enviar o correo electrónico. Podes reintentalo agora ou pechar e intentalo máis tarde. + Reverter Nome do usuario - Sempre podes acceder cunha ligazón máxica coma a que acabas de usar, pero tamén podes configurar un contrasinal se o prefires. - Contrasinal (opcional) Nome a amosar - Reintentar - Reverter - Houbo algún problema ao actualizar a túa conta. Podes reintentalo ou reverter os teus cambios para continuar. + Contrasinal (opcional) Houbo algún problema ao subir o teu avatar. - Necesita actualizarse - Buscar plugins + Houbo algún problema ao enviar o correo electrónico. Podes reintentalo agora ou pechar e intentalo máis tarde. + Houbo algún problema ao actualizar a túa conta. Podes reintentalo ou reverter os teus cambios para continuar. + Sempre podes acceder cunha ligazón máxica coma a que acabas de usar, pero tamén podes configurar un contrasinal se o prefires. + Pechar Novo + Gústame + Xestionar + Instalar Populares - Ningunha coincidencia Ver todos - Xestionar - Non se puideron buscar plugins + Ningunha coincidencia + Necesita actualizarse + Engadir sitio novo + Buscar plugins Erro ao instalar %s + Non se puideron buscar plugins %s instalado correctamente - Instalar - Gústame - Engadir sitio novo Crea un novo sitio para o teu negocio, revista ou blog personal; ou conecta cunha instalación de WordPress existente. - Para obter avisos útiles no teu dispositivo desde o teu sitio WordPress terás que instalar o plugin Jetpack. Gustaríache configurar Jetpack? Carga diferida de imaxes + Para obter avisos útiles no teu dispositivo desde o teu sitio WordPress terás que instalar o plugin Jetpack. Gustaríache configurar Jetpack? Instala Jetpack Alternar texto A túa versión de WordPress Require a versión de WordPress Actualizado por última vez + 3 estrelas Versión - 5 estrelas 4 estrelas - 3 estrelas 2 estrelas 1 estrela - Ningún - %s descargas + 5 estrelas %s valoracións + %s descargas Ler valoracións + Ningún Preguntas frecuentes Que hai de novo - Instalación Descrición + Instalación Axustes Instalado Versión %s instalada - Versión %s por %s + Versión %s Cambiar foto Non é posible cargar plugins - Páxinas - Xestiona as etiquetas do teu sitio Gardando Borrando + Xestiona as etiquetas do teu sitio Borrar permanentemente a etiqueta \'%s\'? + Páxinas Xa existe unha etiqueta con este nome - Engadir nova etiqueta - Descrición Etiqueta + Descrición + Engadir nova etiqueta O teu sitio WordPress.com é compatible co uso de páxinas aceleradas para móbiles, unha iniciativa de Google que acelera enormemente a carga das páxinas en dispositivos móbiles Páxinas móbiles aceleradas (AMP) Non se puideron cargar as zonas horarias Aprende máis sobre formatos de data e hora - Formato personalizado Personalizador + Formato personalizado Entradas por páxina Elixe unha cidade na túa zona horaria Zona horaria @@ -2805,18 +2805,18 @@ Language: gl_ES A versión %s está dispoñible. Actualizacións automáticas Activo - Inactivo Activo Plugins Plugins + Inactivo Abrir enlace nunha nova ventá/pestana Enlace a Ocorreu un erro. Por favor, facilita un código de identificación para continuar. Por favor, volve a teclear o teu contrasinal para continuar. Acceso detido - Por favor, espera mentres se accede. Acceso en progreso… + Por favor, espera mentres se accede. Toca para continuar. Conectado! Non se puido iniciar o acceso desde Google. @@ -2832,15 +2832,15 @@ Language: gl_ES %d arquivos subidos con éxito , %d subido correctamente 1 arquivo subido - 1 arquivo non subido %d arquivos subidos + 1 arquivo non subido %d arquivos non subidos Quitar da entrada Quitar esta imaxe da entrada? Personalizar Detalles do arquivo - \nQuizais probando con outra conta? Houbo algún problema ao conectar coa conta de Google. + \nQuizais probando con outra conta? Pechar Para seguir con esta conta de Google, por favor, facilita o contrasinal correspondente de WordPress.com. Só se che pedirá unha vez. Ocorreu un erro na rede. Por favor, revisa a túa conexión e inténtao de novo. @@ -2848,46 +2848,46 @@ Language: gl_ES Elixir imaxe destacada Accede a WordPress.com para compartir o contido. Introduce o enderezo do teu sitio WordPress no que queiras compartir o contido. - Erro ao desconectar o sitio Sitio desconectado + Erro ao desconectar o sitio Desconectar Estás seguro de querer desconectar Jetpack do sitio? «Desconecta de WordPress.com» Podes marcar un enderezo IP (ou series de enderezos) coma «Sempre permitida», evitando que sexa bloqueada por Jetpack. Acéptanse IPv4 e IPv6. Para especificar un rango, introduce un valor inferior e un valor superior separados por un guión. Exemplo: 12.12.12.1–12.12.12.100 Requiere a identificación en dous pasos - Relacionar contas usando o correo electrónico Permitir o acceso con WordPress.com + Relacionar contas usando o correo electrónico Acceso con WordPress.com Bloquea intentos de acceso maliciosos Protección contra ataques de forza bruta Enviar avisos instantáneos Enviar avisos por correo electrónico - Supervisar o tempo de actividade do teu sitio Seguridade - Axustes de Jetpack + Supervisar o tempo de actividade do teu sitio Engadindo a Elixe o sitio + Axustes de Jetpack Engadir á biblioteca de medios Engadir a unha nova entrada IP ou rango de IP non válido Borrando Borrar este vídeo? Eliminar esta imaxe? - Detalles do documento Detalles do audio + Detalles do documento Detalles do vídeo: - Detalles da imaxe Vista previa - Data de actualización + Detalles da imaxe Duración + Data de actualización Dimensións do vídeo Sen imaxe - Tipo de arquivo - Nome do arquivo URL + Nome do arquivo + Tipo de arquivo Texto alternativo - Conectar un sitio Luz parpadeante + Conectar un sitio Vibración do dispositivo Elixe son Vistas e sons @@ -2902,8 +2902,8 @@ Language: gl_ES Activar os avisos Desactivar os avisos Desactivado - Activado Tamaño máximo de vídeo + Activado Tamaño máximo de imaxe Houbo un erro ao subir os medios a esta entrada: %s. Houbo un erro ao subir esta entrada: %s. @@ -2915,23 +2915,23 @@ Language: gl_ES Os medios borráronse. Borrámolos desta entrada? Erro ao abrir o navegador web por defecto. Por favor, elixe outra aplicación: Non se puido abrir o enlace - Non se puido encontrar a entrada no servidor Esta entrada xa non existe + Non se puido encontrar a entrada no servidor Cancelouse a subida de medios Houbo un erro ao subir os medios a esta páxina: %s. Houbo un erro ao subir esta páxina: %s. A túa entrada estase subindo Subindo medios… - Páxina programada Entrada programada + Páxina programada Reintentar Entrada á espera Subindo «%s» Perdeuse a conexión co servidor - Os meus sitios O meu sitio - Non se puido detectar un cliente de correo electrónico + Os meus sitios Por favor, introduce un código de verificación + Non se puido detectar un cliente de correo electrónico Por favor, introduce un nome de usuario Accede a WordPress.com para acceder á entrada. Erro ao engadir o sitio. Código de erro: %s @@ -2950,15 +2950,15 @@ Language: gl_ES Solicitando un código de verificación por SMS. Envíame un código en texto no seu lugar Case o temos! Por favor, introduce o código de verificación para WordPress.com desde a túa aplicación Authenticator. - Abrir correo electrónico Seguinte + Abrir correo electrónico Accede a WordPress.com usando un enderezo de correo electrónico para xestionar todos os teus sitios WordPress. Foto de perfil Resposta inesperada do servidor Non se pode detener a subida porque xa finalizou - Título Refacer Desfacer + Título Desculpas! Esta característica aínda non está implementada :( Medios demasiado pequenos para amosar Advertencia: non todos os elementos arrastrados son compatibles! @@ -2966,18 +2966,18 @@ Language: gl_ES Ocorreu un erro ao arrastrar texto Non está permitido arrastrar imaxes no modo HTML Comparte a túa historia aquí… - Privada Borrador + Privada Pendente de revisión Publicar Agora Só os que teñan este contrasinal poden ver esta entrada Os extractos son resumos opcionais do contido feitos a man. O slug é a versión amigable da URL do título da entrada. - Formato de entrada - Etiquetas Slug + Etiquetas Extracto + Formato de entrada Non definido Máis opcións Categorías e etiquetas @@ -2985,27 +2985,27 @@ Language: gl_ES Nivel superior Categoría superior (opcional): Non tes ningún audio - Non tes ningún documento No tes ningún vídeo + Non tes ningún documento No tes ningunha imaxe O servidor tarda demasiado en responder Arquivo demasiado grande para subir a este sitio O arquivo supera o tamaño máximo de subida deste sitio Vídeo demasiado grande para subir A imaxe é demasiado grande para subila. Trata de cambiar a optimización de imaxes nos axustes da aplicación + Todos Audio Vídeos - Documentos Imaxes - Todos + Documentos %1$s denegou o acceso aos teus arquivos de medios. Para solucionar, isto modifica os teus permisos e activa %2$s. Ver comentarios Calidade dos vídeos. Valores máis altos implican vídeos de mellor calidade. - Redimensiona os vídeos nas entradas a este tamaño Activa o redimensionado e a compresión de vídeos + Redimensiona os vídeos nas entradas a este tamaño Optimizar vídeos - Borrador subido Calidade do vídeo + Borrador subido Cámara Almacenamento Editar permisos @@ -3015,41 +3015,41 @@ Language: gl_ES Cambia o texto da etiqueta dos botóns de compartir. Este texto non aparecerá ata que engadas polo menos un botón de compartir. Conectando conta A conexión con %s non se puido establecer debido a que non se seleccionou ningunha conta. - Conectado - Twitter Gústame + Twitter + Conectado Permite que ti e os teus lectores lle dean gústame a todos os comentarios Botóns Editar os botóns «Máis» Un botón «Máis» contén un despregable que mostra botóns de compartir Elixe que botóns se mostrarán debaixo das túas entradas - Usuario de Twitter Gústame ao comentario - Estilo do botón + Usuario de Twitter Etiqueta + Estilo do botón Botóns de compartir Amosar botón de gústame - Amosar botón de reblog Reblog e gústame - Botóns oficiais + Amosar botón de reblog Só texto + Botóns oficiais Só icona Icona e texto Elixe a conta á que queres autorizar. Dáte conta de que as túas entradas compartiranse automaticamente na conta seleccionada. Conectando %s Desconectar de %s? Conectar con outra conta + Conectar Reconectar Desconectar - Conectar Conéctate para compartir automaticamente as entradas do teu blog en %s Contas conectadas Conecta cos teus servizos de medios sociais favoritos para compartir automaticamente as novas entradas cos teus amigos. Avisos. Xestiona os teus avisos. Lector. Segue contido doutros sitios. O meu sitio. Ve o teu sitio e xestiónao, estatísticas incluídas. - Social Agora non + Social Erro na subida. Trata de cambiar a optimización de imaxes nos axustes da túa aplicación Gardando medios neste dispositivo Non foi posible gardar os medios @@ -3060,12 +3060,12 @@ Language: gl_ES Toca e mantén para elixir varios comentarios Elixe un vídeo do dispositivo Elixe unha foto do dispositivo - Medios de WordPress Engadir como galería + Medios de WordPress Engadir individualmente - Engadir varias fotos - %d columnas 1 columna + %d columnas + Engadir varias fotos Volver a enviar correo electrónico Enviamos un correo electrónico a %s cando te rexistraches. Por favor, abre a mensaxe e fai clic no botón azul para activar a publicación. Enviámosche un correo electrónico cando te rexistraches. Por favor, abre a mensaxe e fai clic no botón azul para activar a publicación. @@ -3073,8 +3073,8 @@ Language: gl_ES Erro ao enviar o correo electrónico de verificación. Xa o verificaches? Enviado o correo electrónico de verificación, revisa a túa bandexa de entrada Gardando a entrada coma borrador - Tomar vídeo Tomar foto + Tomar vídeo Ten coidado! Unha vez se borre un sitio non se pode recuperar. Por favor, pénsao ben antes de proceder. Todas as túas entradas, imaxes e datos borraranse. E o enderezo deste sitio (%s) perderase. Borrar sitio? @@ -3159,9 +3159,9 @@ Language: gl_ES agora Lector Sen conexión, non se pode gardar o perfil. - Dereita - Esquerda Ningún + Esquerda + Dereita Seleccionado %1$d Non foi posible obter os usuarios do sitio Á procura dos usuarios… @@ -3173,23 +3173,23 @@ Language: gl_ES Desde %1$s Non foi posible eliminar o lector Fallou a carga dalgúns ficheiros. Nesta situación non podes cambiar a modo HTML\nQueres borrar todas as cargas que fallaron e continuar? - Miniatura Editor visual - Largo - Ligar a - Texto alternativo - Lenda + Miniatura Cambios gardados + Lenda + Texto alternativo + Ligar a + Largo Descartar os cambios sen gardar? Suspender a carga? Houbo un erro na inserción do ficheiro Estanse a cargar os ficheiros. Por favor, espera a que o proceso termine. Non se poden inserir ficheiros directamente no modo HTML. Hai que volver ao modo visual. Cargando a galería… - Pulsa para tentalo outra vez! + Enviouse a invitación, pero houbo algún erro. Invitación enviada con éxito %1$s: %2$s - Enviouse a invitación, pero houbo algún erro. + Pulsa para tentalo outra vez! Houbo un erro mentres se enviaba a invitación. Non se pode enviar: Hai nomes de usuario ou enderezos de correo non válidos. Fallou o envío: un nome de usuario ou un enderezo non é válido. @@ -3197,8 +3197,8 @@ Language: gl_ES Mensaxe personalizada Invitar Nomes de usuario ou enderezos de correo electrónico - Invitar xente Externo + Invitar xente Limpar o historial de busca Limpar o historial de busca? Non se atoparon artigos para %s na túa lingua @@ -3206,33 +3206,33 @@ Language: gl_ES Artigos relacionados Os enlaces están inhabilitados na vista previa Enviar - %1$s foi eliminado Se eliminas a %1$s, o usuario non poderá acceder máis a este sitio, aínda que todos os contidos creados por %1$s permanecerán nel.\n\nQueres aínda así eliminar a este usuario? + %1$s foi eliminado Eliminar a %1$s - Rol Xente + Rol Os blogs nesta lista non publicaron nada recentemente Non foi posible eliminar o usuario - Non foi posible actualizar o rol do usuario Non foi posible obter os lectores do sitio + Non foi posible actualizar o rol do usuario Houbo un erro ao actualizar o teu Gravatar - Erro ao recargar o teu Gravatar Erro na localización da imaxe recortada + Erro ao recargar o teu Gravatar Erro no recorte da imaxe Verificando o enderezo de correo electrónico Non dispoñible neste momento. Introduce o teu contrasinal.. Conectando Móstrase publicamente no teus comentarios. Fai ou escolle unha foto - Plans - Plan Os teus artigos, páxinas e configuración enviaránseche a %s. + Plan + Plans Exportar os contidos - Mensaxe de exportación enviada Exportando os contidos… - Comprobando as compras - Mostrar compras + Mensaxe de exportación enviada Tes melloras Premium no teu sitio. Cancela as melloras antes de eliminalo. + Mostrar compras + Comprobando as compras Melloras Premium Algo foi mal. Non foi posible solicitar as compras. Eliminando o sitio… @@ -3241,15 +3241,15 @@ Language: gl_ES Dominio principal Houbo un erro ao eliminar o sitio. Por favor, contacta co soporte para obter asistencia. Erro na eliminación do sitio - Exportar os contidos Escribe %1$s na caixa de embaixo para confirmar. Nese momento o teu sitio desaparecerá para sempre. + Exportar os contidos Confirmar a eliminación do sitio Contactar co soporte Se queres un sitio pero non queres preservar os contidos que tes agora, o noso soporte pode eliminar artigos, páxinas, ficheiros e comentarios por ti.\n \nIsto manterá activo o teu sitio e a súa URL, e darache a oportunidade de comezar a crear contidos desde cero. Contacta connosco para solicitar unha limpeza total do teu sitio. - Imos che axudar Borrar todo e comezar desde cero - Comezar desde cero + Imos che axudar Configuración da aplicación + Comezar desde cero Eliminar os contidos que non foi posible cargar Avanzado Non hai comentarios no lixo @@ -3257,33 +3257,33 @@ Language: gl_ES Non hai comentarios aprobados Omitir Non foi posible conectar. Os métodos XML-RPC requiridos non están no servidor. - Centro - Vídeo Estado - Estándar - Cita - Ligazón - Imaxe + Vídeo + Centro Galería + Imaxe + Cita + Estándar Chat - Audio + Ligazón Aparte Información sobre os cursos e eventos de WordPress.com (en liña ou presenciais) + Audio Oportunidades para participar nas investigacións e enquisas de WordPress.com. Trucos para sacar o mellor partido de WordPress.com Comunidade - Investigación - Propostas Respostas aos meus comentarios - Mencións do usuario + Propostas + Investigación Logros do sitio + Mencións do usuario Gústame nos meus artigos Gústame nos meus comentarios Comentarios no meu sitio %d elementos 1 elemento - Todos os usuarios Comentarios de usuarios coñecidos + Todos os usuarios Ningún comentario %d comentarios por páxina 1 comentario por páxina @@ -3293,11 +3293,11 @@ Language: gl_ES Aprobar automaticamente os comentarios de quen sexa. Aprobar automaticamente se o usuario ten un comentario aprobado previamente Solicitar aprobación manual para calquera comentario. - %d días 1 día - Enderezo web + %d días Sitio principal Preme no enlace de verificación na mensaxe enviada a %1$s para confirmar o teu novo enderezo + Enderezo web Estanse a cargar os ficheiros. Por favor, espera a que o proceso termine. Non foi posible actualizar os comentarios neste momento - mostrando comentarios antigos Poñer como imaxe destacada @@ -3306,13 +3306,13 @@ Language: gl_ES Eliminar definitivamente estes comentarios? Eliminar definitivamente este comentario? Eliminar - Recuperar Comentario eliminado + Recuperar Non hai comentarios spam - Todo Non foi posible cargar a páxina - Off + Todo Idioma da interface + Off Acerca da aplicación Non foi posible gardar a configuración da conta Non foi posible acceder á configuración da conta @@ -3320,9 +3320,9 @@ Language: gl_ES Código de idioma no aceptado Permitir a xerarquización dos comentarios en fíos Fíos até - Desactivado - Busca Borrar + Busca + Desactivado Tamaño orixinal O sitio só é visible para ti e para os usuarios autorizados O sitio é visible para calquera, pero pídese aos motores de busca que non o indexen. @@ -3331,9 +3331,9 @@ Language: gl_ES Acerca de mi Se non se define, o nome mostrado por defecto será o nome de usuario, Nome público - Apelido - Nome O meu perfil + Nome + Apelido Imaxe de vista previa do artigo relacionado Non foi posible gardar a información do sitio Non foi posible acceder á información do sitio @@ -3388,8 +3388,8 @@ Language: gl_ES %d niveis Privado Oculto - Público Eliminar o sitio + Público Pendentes de moderación Enlaces nos comentarios Aprobar automaticamente @@ -3404,22 +3404,22 @@ Language: gl_ES Formato predeterminado Categoría predeterminada Enderezo - Subtítulo Título do sitio + Subtítulo Prederterminado para os artigos novos - Escrita Conta - Xeral + Escrita Os máis recentes primeiro + Xeral + Conversa + Privacidade + Artigos relacionados + Comentarios Os máis antigos primeiro Pecar despois de - Comentarios - Artigos relacionados - Privacidade - Conversa Non tes permiso para cargar ficheiros neste sitio - Descoñecido Nunca + Descoñecido O artigo xa non existe Non tes permiso para ver este artigo Non foi posible acceder a este artigo @@ -3430,22 +3430,22 @@ Language: gl_ES Algo foi mal. Non foi posible activar o tema. por %1$s Grazas por escoller %1$s - XESTIONAR O SITIO - FEITO - Soporte - Detalles Ver + Detalles + Soporte + FEITO + XESTIONAR O SITIO Probar e personalizar Activar - Activo - Soporte - Detalles - Personalizar Tema actual - Páxina actualizada - Artigo actualizado - Páxina publicada + Personalizar + Detalles + Soporte + Activo Artigo publicado + Páxina publicada + Artigo actualizado + Páxina actualizada Sentímolo, non se atoparon temas. Cargar máis artigos Non hai sitios que coincidan con \'%s\' @@ -3465,8 +3465,8 @@ Language: gl_ES Publicado orixinalmente por %s Publicado orixinalmente por %1$s en %2$s %s gústame - 1 gústame Gústame + 1 gústame Artigo da Guía de Lectura Configuración de notificacións que aparece no teu dispositivo Configuración de notificacións enviada ao correo electrónico asociado á túa conta. @@ -3476,18 +3476,18 @@ Language: gl_ES Non foi posible cargar a configuración das notificacións Gústame ao comentario Notificacións da aplicación - Correo electrónico Lapela de notificacións + Correo electrónico Enviaremos sempre mensaxes importantes relativos á túa conta, e terás tamén algúns extras de utilidade. Resumo do último artigo Sen conexión Artigo botado ao lixo - Lixo Estatísticas Vista previa Ver - Publicar Editar + Publicar + Lixo Non se puido atopar este blog Desfacer A solicitude expirou. Inicia sesión en WordPress.com para tentalo de novo. @@ -3497,236 +3497,236 @@ Language: gl_ES Entradas, visitas e lectores desde o comezo. Información Desconectarse de WordPress.com - Conectarse a WordPress.com Entrar/Saír + Conectarse a WordPress.com Configuración da conta \"%s\" non foi ocultado porque é o sitio actual Crear un sitio en WordPress.com + Mostrar/ocultar sitios Engadir un sitio autoaloxado Engadir un sitio - Mostrar/ocultar sitios - Escoller sitio Ver o sitio - Ir ao Panel + Escoller sitio Cambiar de sitio - Axustes do sitio - Entradas + Ir ao Panel Publicar Aparencia - Configuración + Axustes do sitio + Entradas Pulsa para velos - Desmarcar todo - Seleccionar todo - Ocultar + Configuración Mostrar - Inicia sesión de novo para continuar - Código de verificación non válido - Código de verificación + Ocultar + Seleccionar todo + Desmarcar todo Idioma - Fallou a procura de artigos - Non foi posible abrir a notificación + Código de verificación + Código de verificación non válido + Inicia sesión de novo para continuar Termos de busca descoñecidos - Termos de busca Autores + Termos de busca Á procura das páxinas… Á procura dos artigos… Á procura dos ficheiros… - Os rexistros da aplicación foron copiados no portapapeis - Este blog está baleiro + Non foi posible abrir a notificación + Fallou a procura de artigos + Cargando Artigos novos Houbo un erro ao copiar o texto no portapapeis - Cargando - %1$d anos - Un ano - %1$d meses - Un mes - %1$d días - Un día - %1$d horas + Os rexistros da aplicación foron copiados no portapapeis + Este blog está baleiro hai unha hora - %1$d minutos hai un minuto hai uns segundos - Vídeos Artigos e páxinas + Vídeos Países - Gústame - Lectores - Visitas Anos + Visitas + Lectores Á procura dos temas… + %1$d meses + Un ano + %1$d anos + Un mes + %1$d minutos + %1$d horas + Un día + %1$d días + Gústame Detalles %d seleccionados - Ves as FAQ Sen comentarios aínda - Gústame Ver o artigo orixinal Os comentarios están pechados %1$d de %2$d Non se pode publicar un artigo baleiro - Non tes permiso para ver ou editar artigos Non tes permiso para ver ou editar páxinas - Máis + Non tes permiso para ver ou editar artigos Con máis dun mes de antigüidade - Con máis dunha semana de antigüidade + Máis Con máis de dous días de antigüidade - Axuda e soporte - Gustou + Con máis dunha semana de antigüidade Comentario Comentario no lixo - Resposta a %s Aínda sen artigos. Por que non crear un? + Resposta a %s + Gústame + Gustou + Ves as FAQ Saíndo… + Axuda e soporte Non foi posible realizar esta acción - Programar Actualizar + Programar Introduce unha URL ou etiqueta para seguir - Se habitualmente conectas a este sitio sen problema, este erro pode significar que alguén esta¡á tentando suplantarche no sitio, así que que non deberías continuar. Queres confiar no certificado aínda así? - Certificado SSL non válido Axuda - O nome de usuario ou o contrasinal introducido é incorrecto + Certificado SSL non válido + Se habitualmente conectas a este sitio sen problema, este erro pode significar que alguén esta¡á tentando suplantarche no sitio, así que que non deberías continuar. Queres confiar no certificado aínda así? + Non hai rede dispoñible + Houbo un erro mentres se accedía a este blogue + Non é spam + Categoría engadida con éxito + O campo de nome de categoría é obrigatorio + Sen notificacións + Houbo un erro Introduce un enderezo de correo electrónico válido - O enderezo de correo non é válido - Erro na descarga da imaxe + O nome de usuario ou o contrasinal introducido é incorrecto + Non foi posible obter o elemento multimedia + Non foi posible actualizar os artigos neste momento + Non foi posible actualizar as páxinas neste momento Non foi posible cargar o comentario - Houbo un erro durante a edición do comentario - Houbo un erro durante a moderación - Houbo un erro Non foi posible actualizar os comentarios neste momento - Non foi posible actualizar as páxinas neste momento - Non foi posible actualizar os artigos neste momento - Houbo un erro mentres se eliminaba a entrada - Sen notificacións - Para cargar ficheiros fai é necesario ter unha tarxeta SD montada - O campo de nome de categoría é obrigatorio - Categoría engadida con éxito - Fallou a adición da categoría - Non é spam + O enderezo de correo non é válido + Houbo un erro durante a moderación + Houbo un erro durante a edición do comentario + Erro na descarga da imaxe Fallou a procura de temas - Houbo un erro mentres se accedía a este blogue - Non foi posible obter o elemento multimedia - Non hai rede dispoñible - Non se puido eliminar esta etiqueta - Non se puido engadir esta etiqueta - Rexistro da aplicación - Houbo un erro mentres se creaba a base de datos da aplicación. Proba a reinstalar a aplicación. - Este blogue non se pode cargar porque está oculto. Habilítao de novo na configuración e proba outra vez. - Non se poden actualizar os medios neste momento - Blogue feito con WordPress - Configuración da imaxe - Cambios locais - Ficheiro novo - Artigo novo + Fallou a adición da categoría + Para cargar ficheiros fai é necesario ter unha tarxeta SD montada + Houbo un erro mentres se eliminaba a entrada Sen notificacións … de momento. - Necesítase autorización - Comproba se a URL introducida é válida - Non foi posible crear o ficheiro temporal para a carga. Asegúrate de que haxa espazo libre suficiente no dispositivo. - Nome da categoría + Artigo novo + Ficheiro novo + Cambios locais + Configuración da imaxe + Blogue feito con WordPress Engadir categoría nova - Ver no navegador - Borrar o sitio + Nome da categoría + Non foi posible crear o ficheiro temporal para a carga. Asegúrate de que haxa espazo libre suficiente no dispositivo. + Comproba se a URL introducida é válida + Necesítase autorización Gardando os cambios - Lixo - Botar ao lixo? - Botar ao lixo - Spam - Rexeitar - Aprobar - Editar o comentario - No lixo - Spam - Pendente - Aprobado - Eliminar a páxina - Eliminar o artigo - Configuración do artigo - Non foi posible atopar o ficheiro para cargar. Terá sido eliminado ou movido? - Aliñamento horizontal - Borrador local - Configuración da páxina - Crear un enlace - Texto do enlace (opcional) - Non se poden eliminar algún ficheiros neste momento. Téntao de novo máis tarde. - Non tes permiso para ver a Biblioteca Multimedia + Borrar o sitio + Ver no navegador + Seleccionar categorías + Erro de conexión Grella de miniaturas - Saber máis + Non tes permiso para ver a Biblioteca Multimedia + Non se poden eliminar algún ficheiros neste momento. Téntao de novo máis tarde. + Texto do enlace (opcional) + Crear un enlace + Configuración da páxina + Borrador local + Aliñamento horizontal + Configuración do artigo + Eliminar o artigo + Eliminar a páxina + Aprobado + Pendente + Spam + No lixo + Editar o comentario + Aprobar + Rexeitar + Spam + Botar ao lixo + Botar ao lixo? + Lixo + Rexistro da aplicación + Este blogue non se pode cargar porque está oculto. Habilítao de novo na configuración e proba outra vez. + Houbo un erro mentres se creaba a base de datos da aplicación. Proba a reinstalar a aplicación. Houbo un erro mentres se cargaba o artigo. Actualiza os artigos e téntao de novo. + Saber máis + Non foi posible atopar o ficheiro para cargar. Terá sido eliminado ou movido? + Non se poden actualizar os medios neste momento Ocorreu un erro ao acceder a este plugin - Erro de conexión - Seleccionar categorías + Non se puido engadir esta etiqueta + Non se puido eliminar esta etiqueta Enlace para compartir Á procura de artigos… + Comentario sinalado como spam + Non podes compartir en WordPress se non tes algún blogue visible A ti e a outros %,d gustoulles isto A %,d persoas gustoulles isto - Non podes compartir en WordPress se non tes algún blogue visible - Comentario sinalado como spam Comentario sen aprobar - Non foi posible acceder a este artigo - A ti e a un máis gustoulles isto - Escoller vídeo Escoller foto - Rexistro - No foi posible abrir %s - Non foi posible mostrar a imaxe - Non foi posible compartir - Esa non é unha etiqueta válida + Escoller vídeo + A ti e a un máis gustoulles isto + Non foi posible acceder a este artigo + (Sen título) + Compartir + Seguir + Responder ao comentario + %s engadido + %s eliminado Non foi posible enviar o comentario - Gústache isto + Esta lista está baleira A unha persoa gustoulle isto - %s eliminado - %s engadido - Responder ao comentario - Seguir - Compartir - Reblog - (Sen título) + Gústache isto + Non foi posible compartir + Non foi posible mostrar a imaxe + No foi posible abrir %s Sen comentarios aínda - Esta lista está baleira - Meses - Semanas - Días - Onte - Hoxe - Referencias + Reblog + Rexistro + Esa non é unha etiqueta válida Etiquetas e categorías - Clics - Estatísticas - Compartir + Referencias + Hoxe + Onte + Días + Semanas + Meses Activar - Fallou a actualización - Descrición - Lenda - Título - Pase de diapositivas - Círculos - Mosaico + Compartir + Estatísticas Cadrados + Mosaico + Círculos + Pase de diapositivas + Título + Lenda + Descrición Temas + Clics + Fallou a actualización Descartar Xestionar - e %d máis. %d notificacións novas + e %d máis. Resposta publicada Entrar Cargando… - contrasinal HTTP usuario HTTP + contrasinal HTTP Houbo un erro mentres se cargaba o ficheiro Nome de usuario ou contrasinal incorrecto - Iniciar sesión - Nome de usuario Contrasinal + Nome de usuario + Iniciar sesión Guía de Lectura - Incluír una imaxe no contido do artigo - Usar como imaxe destacada - Largo - Lenda (opcional) Páxinas + Lenda (opcional) + Largo Artigos Anónimo + Usar como imaxe destacada + Incluír una imaxe no contido do artigo Non hai rede dispoñible - feito Vale + feito URL Cargando… Aliñación @@ -3744,22 +3744,22 @@ Language: gl_ES Tarxeta SD requirida Multimedia Categoría actualizada correctamente. - Aprobar Borrar - Actualizando a categoría que fallou + Aprobar Ningún - Publicar agora + Actualizando a categoría que fallou + Si + Non + Opcións de notificación Responder - en Vista previa - Erro na actualización da categoría Erro - Non - Si - Opcións de notificación - Engadir - Gardar Cancelar + Gardar + Engadir + en + Erro na actualización da categoría + Publicar agora Unha vez Dúas veces From c2a61cc6a62c3bcc2948beacd144699d86f53bd0 Mon Sep 17 00:00:00 2001 From: Automattic Release Bot Date: Mon, 10 Jun 2024 21:37:18 +0000 Subject: [PATCH 41/54] Bump version number --- version.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.properties b/version.properties index 3f2a5f2d327a..eed4110780a6 100644 --- a/version.properties +++ b/version.properties @@ -1,2 +1,2 @@ -versionName=25.1-rc-1 -versionCode=1436 \ No newline at end of file +versionName=25.1-rc-2 +versionCode=1437 \ No newline at end of file From 8521e728623f573da544841dd046aedca70bc266 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 11 Jun 2024 11:32:00 +0300 Subject: [PATCH 42/54] Updates FluxC reference to point to trunk --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 74da1fecf5d3..ebbc2036d83a 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ ext { automatticTracksVersion = '5.1.0' gutenbergMobileVersion = 'v1.120.0' wordPressAztecVersion = 'v2.1.3' - wordPressFluxCVersion = '3028-eb0a976762876b228eed98b564ea77ab97659673' + wordPressFluxCVersion = 'trunk-b5d95fda4257bd1b3c94b33088f5e2a3f48ff1c2' wordPressLoginVersion = '1.15.0' wordPressPersistentEditTextVersion = '1.0.2' wordPressUtilsVersion = '3.14.0' From c415bc5f49d03d301bbf858fecef850aa2432970 Mon Sep 17 00:00:00 2001 From: Pantelis Stampoulis Date: Tue, 11 Jun 2024 12:56:43 +0300 Subject: [PATCH 43/54] Updates FluxC hash --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7241fef5a8e5..531047d75949 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ ext { automatticTracksVersion = '5.1.0' gutenbergMobileVersion = 'v1.120.0' wordPressAztecVersion = 'v2.1.3' - wordPressFluxCVersion = '2.84.0' + wordPressFluxCVersion = 'trunk-0fe67fa241426afeaaa66bc3970ba46634efa5c8' wordPressLoginVersion = '1.15.0' wordPressPersistentEditTextVersion = '1.0.2' wordPressUtilsVersion = '3.14.0' From 784aa420f0f85c1035111a0ea1f630dbe88f0288 Mon Sep 17 00:00:00 2001 From: Pantelis Stampoulis Date: Tue, 11 Jun 2024 13:41:16 +0300 Subject: [PATCH 44/54] Fix unit tests --- .../ui/voicetocontent/VoiceToContentFeatureUtilsTest.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentFeatureUtilsTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentFeatureUtilsTest.kt index b9b4fb433897..166cdfb33892 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentFeatureUtilsTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentFeatureUtilsTest.kt @@ -80,6 +80,7 @@ class VoiceToContentFeatureUtilsTest { requestsLimit = 0, usagePeriod = null, siteRequireUpgrade = true, + upgradeUrl = null, upgradeType = "", currentTier = null, nextTier = null, @@ -100,6 +101,7 @@ class VoiceToContentFeatureUtilsTest { usagePeriod = null, siteRequireUpgrade = false, upgradeType = "", + upgradeUrl = null, currentTier = null, nextTier = null, tierPlans = emptyList(), @@ -119,6 +121,7 @@ class VoiceToContentFeatureUtilsTest { usagePeriod = null, siteRequireUpgrade = false, upgradeType = "", + upgradeUrl = null, currentTier = Tier(JETPACK_AI_FREE, 0, 0, null), nextTier = null, tierPlans = emptyList(), @@ -141,6 +144,7 @@ class VoiceToContentFeatureUtilsTest { usagePeriod = null, siteRequireUpgrade = false, upgradeType = "", + upgradeUrl = null, currentTier = Tier("", 0, 1, null), nextTier = null, tierPlans = emptyList(), @@ -160,6 +164,7 @@ class VoiceToContentFeatureUtilsTest { usagePeriod = UsagePeriod("2024-01-01", "2024-02-01", 100), siteRequireUpgrade = false, upgradeType = "", + upgradeUrl = null, currentTier = Tier("", 200, 0, null), nextTier = null, tierPlans = emptyList(), From c435cbe4005186bf49ff6679b1b857b96dc84fbd Mon Sep 17 00:00:00 2001 From: Pantelis Stampoulis Date: Tue, 11 Jun 2024 14:06:04 +0300 Subject: [PATCH 45/54] Fix unit tests --- .../ui/voicetocontent/VoiceToContentViewModelTest.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt index 9b44f797b362..2556e99e7e84 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt @@ -5,9 +5,9 @@ import org.junit.runner.RunWith import org.mockito.junit.MockitoJUnitRunner import org.wordpress.android.BaseUnitTest -@ExperimentalCoroutinesApi -@RunWith(MockitoJUnitRunner::class) -class VoiceToContentViewModelTest : BaseUnitTest() { +//@ExperimentalCoroutinesApi +//@RunWith(MockitoJUnitRunner::class) +//class VoiceToContentViewModelTest : BaseUnitTest() { // @Mock // lateinit var voiceToContentFeatureUtils: VoiceToContentFeatureUtils // @@ -112,6 +112,6 @@ class VoiceToContentViewModelTest : BaseUnitTest() { // // verify(recordingUseCase).startRecording(any()) // } -} +//} From 27f8afd3277da3cb3327a92a406c17fffe2dff4a Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 11 Jun 2024 08:36:17 -0400 Subject: [PATCH 46/54] Add microphone vector asset --- WordPress/src/main/res/drawable/ic_mic_none_24.xml | 11 +++++++++++ WordPress/src/main/res/drawable/v2c_mic.xml | 12 ------------ 2 files changed, 11 insertions(+), 12 deletions(-) create mode 100644 WordPress/src/main/res/drawable/ic_mic_none_24.xml delete mode 100644 WordPress/src/main/res/drawable/v2c_mic.xml diff --git a/WordPress/src/main/res/drawable/ic_mic_none_24.xml b/WordPress/src/main/res/drawable/ic_mic_none_24.xml new file mode 100644 index 000000000000..6c4b34e4b2e1 --- /dev/null +++ b/WordPress/src/main/res/drawable/ic_mic_none_24.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/WordPress/src/main/res/drawable/v2c_mic.xml b/WordPress/src/main/res/drawable/v2c_mic.xml deleted file mode 100644 index 5613881bcbf2..000000000000 --- a/WordPress/src/main/res/drawable/v2c_mic.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - From c3157552f538b65c9052f6b0665ffec82977e723 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 11 Jun 2024 08:37:25 -0400 Subject: [PATCH 47/54] Update to use ic mic --- .../ui/voicetocontent/MicToStopIcon.kt | 2 +- WordPress/src/main/res/drawable/v2c_stop.xml | 25 ------------------- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt index 92bcf59e83f1..a85466a27b44 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/MicToStopIcon.kt @@ -56,7 +56,7 @@ fun MicToStopIcon(model: RecordingPanelUIModel) { else Color.Black, label = "" ) - val micIcon: Painter = painterResource(id = R.drawable.v2c_mic) + val micIcon: Painter = painterResource(id = R.drawable.ic_mic_none_24) val stopIcon: Painter = painterResource(id = R.drawable.v2c_stop) Box( diff --git a/WordPress/src/main/res/drawable/v2c_stop.xml b/WordPress/src/main/res/drawable/v2c_stop.xml index 542532606ef9..c06853463df7 100644 --- a/WordPress/src/main/res/drawable/v2c_stop.xml +++ b/WordPress/src/main/res/drawable/v2c_stop.xml @@ -10,28 +10,3 @@ android:pathData="M1.474,0L30.526,0A1.474,1.474 0,0 1,32 1.474L32,30.526A1.474,1.474 0,0 1,30.526 32L1.474,32A1.474,1.474 0,0 1,0 30.526L0,1.474A1.474,1.474 0,0 1,1.474 0z"/> - - - - - - - - - - - - - - - - - - - - - - - - - From 8c76a462439312f9ff84153fe25ab531c1fbee5b Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 11 Jun 2024 08:55:01 -0400 Subject: [PATCH 48/54] Revert back to normal after accidently commit --- .idea/checkstyle-idea.xml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml index b05be3dcbb2d..b084c99aaa78 100644 --- a/.idea/checkstyle-idea.xml +++ b/.idea/checkstyle-idea.xml @@ -1,18 +1,18 @@ - - 9.0.1 - AllSourcesWithTests - - - - \ No newline at end of file + + + + From 5af902df3195d754eade231bb3eddda071b65980 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 11 Jun 2024 09:18:26 -0400 Subject: [PATCH 49/54] Add start test for the view model --- .../VoiceToContentViewModelTest.kt | 138 +++++++----------- 1 file changed, 56 insertions(+), 82 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt index 2556e99e7e84..8eb598e70603 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt @@ -1,33 +1,43 @@ package org.wordpress.android.ui.voicetocontent import kotlinx.coroutines.ExperimentalCoroutinesApi +import org.junit.Before import org.junit.runner.RunWith +import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner +import org.mockito.kotlin.verifyNoInteractions +import org.mockito.kotlin.whenever import org.wordpress.android.BaseUnitTest +import org.wordpress.android.ui.mysite.SelectedSiteRepository +import org.wordpress.android.viewmodel.ContextProvider +import kotlin.test.Test -//@ExperimentalCoroutinesApi -//@RunWith(MockitoJUnitRunner::class) -//class VoiceToContentViewModelTest : BaseUnitTest() { -// @Mock -// lateinit var voiceToContentFeatureUtils: VoiceToContentFeatureUtils -// -// @Mock -// lateinit var voiceToContentUseCase: VoiceToContentUseCase -// -// @Mock -// lateinit var recordingUseCase: RecordingUseCase -// -// @Mock -// lateinit var selectedSiteRepository: SelectedSiteRepository -// -// @Mock -// lateinit var jetpackAIStore: JetpackAIStore -// -// private lateinit var viewModel: VoiceToContentViewModel -// -// private lateinit var uiState: MutableList +@ExperimentalCoroutinesApi +@RunWith(MockitoJUnitRunner::class) +class VoiceToContentViewModelTest : BaseUnitTest() { + @Mock + lateinit var voiceToContentFeatureUtils: VoiceToContentFeatureUtils + + @Mock + lateinit var voiceToContentUseCase: VoiceToContentUseCase + + @Mock + lateinit var recordingUseCase: RecordingUseCase - /* private val jetpackAIAssistantFeature = JetpackAIAssistantFeature( + @Mock + lateinit var selectedSiteRepository: SelectedSiteRepository + + @Mock + lateinit var prepareVoiceToContentUseCase: PrepareVoiceToContentUseCase + + @Mock + lateinit var contextProvider: ContextProvider + + private lateinit var viewModel: VoiceToContentViewModel + + // private lateinit var uiState: MutableList + + /* private val jetpackAIAssistantFeature = JetpackAIAssistantFeature( hasFeature = true, isOverLimit = false, requestsCount = 0, @@ -42,76 +52,40 @@ import org.wordpress.android.BaseUnitTest costs = null )*/ -// @Before -// fun setup() { -// // Mock the recording updates to return a non-null flow before ViewModel instantiation -// whenever(recordingUseCase.recordingUpdates()).thenReturn(createRecordingUpdateFlow()) -// -// viewModel = VoiceToContentViewModel( -// testDispatcher(), -// voiceToContentFeatureUtils, -// voiceToContentUseCase, -// selectedSiteRepository, -// jetpackAIStore, -// recordingUseCase -// ) -// + @Before + fun setup() { + // Mock the recording updates to return a non-null flow before ViewModel instantiation + //whenever(recordingUseCase.recordingUpdates()).thenReturn(createRecordingUpdateFlow()) + + viewModel = VoiceToContentViewModel( + testDispatcher(), + voiceToContentFeatureUtils, + voiceToContentUseCase, + selectedSiteRepository, + recordingUseCase, + contextProvider, + prepareVoiceToContentUseCase + ) // uiState = mutableListOf() // viewModel.uiState.observeForever { event -> // event?.let { result -> // uiState.add(result) // } // } -// } -// + } + + // // // Helper function to create a consistent flow // private fun createRecordingUpdateFlow() = flow { // emit(RecordingUpdate(0, 0, false)) // } // -// @Test -// fun `when site is null, then execute posts error state `() = test { -// whenever(selectedSiteRepository.getSelectedSite()).thenReturn(null) -// val dummyFile = File("dummy_path") -// viewModel.executeVoiceToContent(dummyFile) -// -// val expectedState = VoiceToContentResult(isError = true) -// assertThat(uiState.first()).isEqualTo(expectedState) -// } -// -// /* @Test -// fun `when voice to content is enabled, then execute invokes use case `() = test { -// val site = SiteModel().apply { id = 1 } -// val dummyFile = File("dummy_path") -// -// whenever(selectedSiteRepository.getSelectedSite()).thenReturn(site) -// whenever(voiceToContentFeatureUtils.isVoiceToContentEnabled()).thenReturn(true) -// whenever(jetpackAIStore.fetchJetpackAIAssistantFeature(site)) -// .thenReturn(JetpackAIAssistantFeatureResponse.Success(jetpackAIAssistantFeature)) -// -// viewModel.executeVoiceToContent(dummyFile) -// -// verify(voiceToContentUseCase).execute(site, dummyFile) -// }*/ -// -//// @Test -//// fun `when voice to content is disabled, then executeVoiceToContent does not invoke use case`() = runTest { -//// val site = SiteModel().apply { id = 1 } -//// whenever(selectedSiteRepository.getSelectedSite()).thenReturn(site) -//// whenever(voiceToContentFeatureUtils.isVoiceToContentEnabled()).thenReturn(false) -//// val dummyFile = File("dummy_path") -//// -//// viewModel.executeVoiceToContent(dummyFile) -//// -//// verifyNoInteractions(voiceToContentUseCase) -//// } -// -// @Test -// fun `when startRecording is called, then recordingUseCase starts recording`() { -// viewModel.startRecording() -// -// verify(recordingUseCase).startRecording(any()) -// } -//} + @Test + fun `when site is null, then execute posts error state `() = test { + whenever(selectedSiteRepository.getSelectedSite()).thenReturn(null) + viewModel.start() + verifyNoInteractions(prepareVoiceToContentUseCase) + } +} From bf16b778a0ec4126da55eb511b4959515db7b457 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 11 Jun 2024 10:04:40 -0400 Subject: [PATCH 50/54] Fix checkstyle --- .../android/ui/voicetocontent/VoiceToContentViewModelTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt index 8eb598e70603..24e429460212 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt @@ -55,7 +55,7 @@ class VoiceToContentViewModelTest : BaseUnitTest() { @Before fun setup() { // Mock the recording updates to return a non-null flow before ViewModel instantiation - //whenever(recordingUseCase.recordingUpdates()).thenReturn(createRecordingUpdateFlow()) + // whenever(recordingUseCase.recordingUpdates()).thenReturn(createRecordingUpdateFlow()) viewModel = VoiceToContentViewModel( testDispatcher(), From 7859334d960f345d43c9cafcfd561f6d9999ef50 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 11 Jun 2024 10:44:03 -0400 Subject: [PATCH 51/54] Remove unused resource --- WordPress/src/main/res/drawable/v2c_green_circle.xml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 WordPress/src/main/res/drawable/v2c_green_circle.xml diff --git a/WordPress/src/main/res/drawable/v2c_green_circle.xml b/WordPress/src/main/res/drawable/v2c_green_circle.xml deleted file mode 100644 index 6385b8ca7ac7..000000000000 --- a/WordPress/src/main/res/drawable/v2c_green_circle.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - From fbc20403c0cd92bf2f5586d8ef684ffa06657fb1 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 11 Jun 2024 12:10:22 -0400 Subject: [PATCH 52/54] Address failing test --- .../VoiceToContentViewModelTest.kt | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt index 24e429460212..98939094fa6d 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt @@ -1,19 +1,21 @@ package org.wordpress.android.ui.voicetocontent +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.launch import org.junit.Before -import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.junit.MockitoJUnitRunner import org.mockito.kotlin.verifyNoInteractions import org.mockito.kotlin.whenever import org.wordpress.android.BaseUnitTest import org.wordpress.android.ui.mysite.SelectedSiteRepository +import org.wordpress.android.util.audio.RecordingUpdate import org.wordpress.android.viewmodel.ContextProvider import kotlin.test.Test @ExperimentalCoroutinesApi -@RunWith(MockitoJUnitRunner::class) class VoiceToContentViewModelTest : BaseUnitTest() { @Mock lateinit var voiceToContentFeatureUtils: VoiceToContentFeatureUtils @@ -35,8 +37,22 @@ class VoiceToContentViewModelTest : BaseUnitTest() { private lateinit var viewModel: VoiceToContentViewModel - // private lateinit var uiState: MutableList + private var uiStateChanges = mutableListOf() + private val uiState + get() = viewModel.state.value + private fun testUiStateChanges( + block: suspend CoroutineScope.() -> T + ) { + test { + uiStateChanges.clear() + val job = launch(testDispatcher()) { + viewModel.state.toList(uiStateChanges) + } + this.block() + job.cancel() + } + } /* private val jetpackAIAssistantFeature = JetpackAIAssistantFeature( hasFeature = true, isOverLimit = false, @@ -55,7 +71,7 @@ class VoiceToContentViewModelTest : BaseUnitTest() { @Before fun setup() { // Mock the recording updates to return a non-null flow before ViewModel instantiation - // whenever(recordingUseCase.recordingUpdates()).thenReturn(createRecordingUpdateFlow()) + whenever(recordingUseCase.recordingUpdates()).thenReturn(createRecordingUpdateFlow()) viewModel = VoiceToContentViewModel( testDispatcher(), @@ -66,20 +82,13 @@ class VoiceToContentViewModelTest : BaseUnitTest() { contextProvider, prepareVoiceToContentUseCase ) -// uiState = mutableListOf() -// viewModel.uiState.observeForever { event -> -// event?.let { result -> -// uiState.add(result) -// } -// } } - // -// // Helper function to create a consistent flow -// private fun createRecordingUpdateFlow() = flow { -// emit(RecordingUpdate(0, 0, false)) -// } -// + // Helper function to create a consistent flow + private fun createRecordingUpdateFlow() = flow { + emit(RecordingUpdate(0, 0, false)) + } + @Test fun `when site is null, then execute posts error state `() = test { whenever(selectedSiteRepository.getSelectedSite()).thenReturn(null) From 82bf5ed98b7d0dccd38ea661794a5b68474e0b21 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 11 Jun 2024 13:03:44 -0400 Subject: [PATCH 53/54] Address detekt issues --- .../VoiceToContentViewModelTest.kt | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt index 98939094fa6d..c437637ce5ac 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModelTest.kt @@ -1,10 +1,7 @@ package org.wordpress.android.ui.voicetocontent -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.launch import org.junit.Before import org.mockito.Mock import org.mockito.kotlin.verifyNoInteractions @@ -37,22 +34,22 @@ class VoiceToContentViewModelTest : BaseUnitTest() { private lateinit var viewModel: VoiceToContentViewModel - private var uiStateChanges = mutableListOf() - private val uiState - get() = viewModel.state.value - - private fun testUiStateChanges( - block: suspend CoroutineScope.() -> T - ) { - test { - uiStateChanges.clear() - val job = launch(testDispatcher()) { - viewModel.state.toList(uiStateChanges) - } - this.block() - job.cancel() - } - } +// private var uiStateChanges = mutableListOf() +// private val uiState +// get() = viewModel.state.value + +// private fun testUiStateChanges( +// block: suspend CoroutineScope.() -> T +// ) { +// test { +// uiStateChanges.clear() +// val job = launch(testDispatcher()) { +// viewModel.state.toList(uiStateChanges) +// } +// this.block() +// job.cancel() +// } +// } /* private val jetpackAIAssistantFeature = JetpackAIAssistantFeature( hasFeature = true, isOverLimit = false, From 98b27b1db9e8ea4d2f5c2e5a4f83ed3af23b26c4 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 11 Jun 2024 16:13:26 -0400 Subject: [PATCH 54/54] Fix opening quickpress shortcut --- .../java/org/wordpress/android/ui/posts/EditPostActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt index 2239cc19d4ad..16db759bfb31 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt @@ -638,7 +638,7 @@ class EditPostActivity : LocaleAwareActivity(), EditorFragmentActivity, EditorIm val hasQuickPressBlogId = extras.containsKey(EditPostActivityConstants.EXTRA_QUICKPRESS_BLOG_ID) // QuickPress might want to use a different blog than the current blog - return if (!isActionSendOrNewMedia && !hasQuickPressFlag && hasQuickPressBlogId) { + return if ((isActionSendOrNewMedia || hasQuickPressFlag) && hasQuickPressBlogId) { val localSiteId = intent.getIntExtra(EditPostActivityConstants.EXTRA_QUICKPRESS_BLOG_ID, -1) siteStore.getSiteByLocalId(localSiteId) } else {