Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ fun LyricsMoreBottomSheet(
// Translate via AI
if (lyrics != null) {
ListItem(
headlineContent = { Text("Translate via AI") },
headlineContent = { Text(stringResource(R.string.ai_translate_via_ai)) },
leadingContent = {
Icon(
imageVector = Icons.Rounded.Translate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,19 +342,20 @@ class AiStateHolder @Inject constructor(

suspend fun translateLyrics(lyricsText: String): Result<String> {
return try {
val targetLanguage = context.resources.configuration.locales[0].displayLanguage
val prompt = """
Translate the provided song lyrics into Russian.
Translate the provided song lyrics into $targetLanguage.

Keep every timestamp exactly unchanged.

For each original line, output the original line first, then on the next line output the Russian translation with the same timestamp.
If the lyrics are ALREADY mostly in $targetLanguage, output ONLY the exact phrase "ALREADY_IN_TARGET_LANGUAGE" without any other text.

Do not add any extra text, explanations, numbering, labels, or formatting.
For each original line, output the original line first, then on the next line output the $targetLanguage translation with the same timestamp.

Do not add any extra text, explanations, numbering, labels, or formatting.
Do not remove, merge, split, or reorder lines.

Output only:

[timestamp] original text
[timestamp] translated text

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5106,31 +5106,49 @@ class PlayerViewModel @Inject constructor(
val currentSong = stablePlayerState.value.currentSong ?: return
val songId = currentSong.id.toLongOrNull() ?: return
val rawLyrics = currentSong.lyrics
val lyricsObj = stablePlayerState.value.lyrics

if (rawLyrics.isNullOrBlank()) {
sendToast("No lyrics to translate")
sendToast(context.getString(R.string.lyrics_not_found))
return
}

if (lyricsObj?.synced != null) {
val hasValidTranslation = lyricsObj.synced.any { !it.translation.isNullOrBlank() }
if (hasValidTranslation) {
sendToast(context.getString(R.string.ai_lyrics_already_translated))
return
}
}

viewModelScope.launch {
sendToast("Translating lyrics...")
sendToast(context.getString(R.string.ai_lyrics_translating))
val result = aiStateHolder.translateLyrics(rawLyrics)
result.onSuccess { translatedText ->
if (translatedText.trim() == "ALREADY_IN_TARGET_LANGUAGE") {
sendToast(context.getString(R.string.ai_lyrics_already_in_target_language))
return@onSuccess
}

if (translatedText.isNotBlank()) {
val validation = com.theveloper.pixelplay.utils.LyricsImportSecurity.validateImportedLrcContent(translatedText)
if (validation is com.theveloper.pixelplay.utils.LyricsImportValidationResult.Valid) {
lyricsStateHolder.importLyricsFromFile(songId, validation.value, currentSong)
sendToast("Lyrics translated successfully!")
sendToast(context.getString(R.string.ai_lyrics_translation_success))
} else {
val reason = (validation as com.theveloper.pixelplay.utils.LyricsImportValidationResult.Invalid).reason
val errorMsg = com.theveloper.pixelplay.utils.LyricsImportSecurity.messageFor(reason)
sendToast("AI format error: $errorMsg")
sendToast(context.getString(R.string.ai_error_generic, errorMsg))
}
} else {
sendToast("AI returned empty response")
sendToast(context.getString(R.string.ai_error_generic, "Empty response"))
}
}.onFailure {
sendToast("Translation failed: ${it.message}")
if (it.message?.contains("key", ignoreCase = true) == true || it.message?.contains("config", ignoreCase = true) == true) {
sendToast(context.getString(R.string.ai_error_api_key))
} else {
sendToast(context.getString(R.string.ai_error_generic, it.message))
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@
<string name="ai_daily_mix_updated">Daily Mix обновлен с помощью ИИ</string>
<string name="ai_no_songs_for_mix">ИИ не удалось найти песни для этого микса</string>

<string name="ai_translate_via_ai">Перевести с ИИ</string>
<string name="ai_lyrics_already_translated">У этого текста уже есть перевод</string>
<string name="ai_lyrics_already_in_target_language">Этот текст уже на этом языке</string>
<string name="ai_lyrics_api_not_configured">API не настроен</string>
<string name="ai_lyrics_translation_success">Текст успешно переведён!</string>
<string name="ai_lyrics_translating">Перевод текста...</string>

<string name="shortcut_shuffle_short">Перемешать</string>
<string name="shortcut_shuffle_long">Перемешать все песни</string>
<string name="shortcut_playlist_short">Плейлист</string>
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/res/values-ru/strings_presentation_batch_g.xml
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@
<string name="presentation_batch_g_presets_cd_pin">Закрепить</string>
<string name="presentation_batch_g_presets_cd_rename">Переименовать</string>
<string name="presentation_batch_g_presets_cd_delete">Удалить</string>
<string name="presentation_batch_g_beta_sheet_version">Бета 0.6.0</string>
<string name="presentation_batch_g_beta_sheet_welcome_title">Добро пожаловать в PixelPlayer 0.6.0-beta</string>
<string name="presentation_batch_g_beta_sheet_version">Бета 0.7.0</string>
<string name="presentation_batch_g_beta_sheet_welcome_title">Добро пожаловать в PixelPlayer 0.7.0-beta</string>
<string name="presentation_batch_g_beta_sheet_welcome_body">Эта бета сфокусирована на стабильности, скорости и кросс-девайс воспроизведении.</string>
<string name="presentation_batch_g_beta_sheet_expect_title">Что нового</string>
<string name="presentation_batch_g_beta_sheet_expect_1">Быстрая работа: плавный запуск, навигация и работа плеера.</string>
Expand Down Expand Up @@ -495,4 +495,4 @@
<string name="presentation_batch_g_beta_sheet_nightly_access">Доступны через артефакты GitHub Actions в репозитории, если опубликованы.</string>
<string name="presentation_batch_g_beta_sheet_nightly_report_title">Отчёт о проблемах в nightly</string>
<string name="presentation_batch_g_beta_sheet_nightly_report_body">При отчёте о проблеме из nightly всегда указывайте, что она в nightly, а не в официальном релизе. Укажите дату сборки, имя или номер запуска workflow или commit SHA — если возможно. Также проверьте, есть ли эта проблема в последнем официальном релизе.</string>
</resources>
</resources>
7 changes: 7 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@
<string name="ai_daily_mix_updated">Daily Mix updated with AI</string>
<string name="ai_no_songs_for_mix">AI couldn\'t find songs for this mix</string>

<string name="ai_translate_via_ai">Translate via AI</string>
<string name="ai_lyrics_already_translated">These lyrics already have a translation</string>
<string name="ai_lyrics_already_in_target_language">These lyrics are already in this language</string>
<string name="ai_lyrics_api_not_configured">API is not configured</string>
<string name="ai_lyrics_translation_success">Lyrics translated successfully!</string>
<string name="ai_lyrics_translating">Translating lyrics...</string>

<string name="shortcut_shuffle_short">Shuffle</string>
<string name="shortcut_shuffle_long">Shuffle all songs</string>
<string name="shortcut_playlist_short">Playlist</string>
Expand Down
Loading