i18n: localization for notification title and text (#2143)

This commit is contained in:
Huang Xin
2025-09-30 16:03:33 +08:00
committed by GitHub
parent 1d4541e353
commit 0e6950a60f
28 changed files with 145 additions and 47 deletions
@@ -613,5 +613,7 @@
"Start Migration": "بدء الترحيل",
"Advanced Settings": "إعدادات متقدمة",
"File count: {{size}}": "عدد الملفات: {{size}}",
"Background Read Aloud": "قراءة بصوت عالٍ في الخلفية"
"Background Read Aloud": "قراءة بصوت عالٍ في الخلفية",
"Ready to read aloud": "جاهز للقراءة بصوت عالٍ",
"Read Aloud": "القراءة بصوت عالٍ"
}
@@ -597,5 +597,7 @@
"Start Migration": "মাইগ্রেশন শুরু করুন",
"Advanced Settings": "উন্নত সেটিংস",
"File count: {{size}}": "ফাইলের সংখ্যা: {{size}}",
"Background Read Aloud": "পটভূমিতে উচ্চস্বরে পড়ুন"
"Background Read Aloud": "পটভূমিতে উচ্চস্বরে পড়ুন",
"Ready to read aloud": "উচ্চস্বরে পড়ার জন্য প্রস্তুত",
"Read Aloud": "উচ্চস্বরে পড়ুন"
}
@@ -593,5 +593,7 @@
"Start Migration": "མཉམ་དུ་ཀློག་འཛུལ་བྱས་མ་ཐུབ།",
"Advanced Settings": "དབང་བསྐྱོད་སྒྲིག་སྟངས།",
"File count: {{size}}": "དེབ་གནས་བཅས་པའི་ཨང་། {{size}}",
"Background Read Aloud": "གནས་སྟངས་ཀྱིས་ཀློག་བྱེད།"
"Background Read Aloud": "གནས་སྟངས་ཀྱིས་ཀློག་བྱེད།",
"Ready to read aloud": "དེབ་ཀྱི་སྤྱོད་བྱས་མ་ཐུབ།",
"Read Aloud": "ཀློག་བྱེད།"
}
@@ -597,5 +597,7 @@
"Start Migration": "Migration starten",
"Advanced Settings": "Erweiterte Einstellungen",
"File count: {{size}}": "Dateianzahl: {{size}}",
"Background Read Aloud": "Hintergrund-Vorlesen"
"Background Read Aloud": "Hintergrund-Vorlesen",
"Ready to read aloud": "Bereit zum Vorlesen",
"Read Aloud": "Vorlesen"
}
@@ -597,5 +597,7 @@
"Start Migration": "Έναρξη μετανάστευσης",
"Advanced Settings": "Προηγμένες ρυθμίσεις",
"File count: {{size}}": "Αριθμός αρχείων: {{size}}",
"Background Read Aloud": "Ανάγνωση στο παρασκήνιο"
"Background Read Aloud": "Ανάγνωση στο παρασκήνιο",
"Ready to read aloud": "Έτοιμο για ανάγνωση",
"Read Aloud": "Ανάγνωση"
}
@@ -601,5 +601,7 @@
"Start Migration": "Iniciar Migración",
"Advanced Settings": "Configuraciones Avanzadas",
"File count: {{size}}": "Número de archivos: {{size}}",
"Background Read Aloud": "Lectura en segundo plano"
"Background Read Aloud": "Lectura en segundo plano",
"Ready to read aloud": "Listo para leer en voz alta",
"Read Aloud": "Leer en voz alta"
}
@@ -601,5 +601,7 @@
"Start Migration": "Démarrer la Migration",
"Advanced Settings": "Paramètres Avancés",
"File count: {{size}}": "Nombre de fichiers : {{size}}",
"Background Read Aloud": "Lecture Vocale en Arrière-Plan"
"Background Read Aloud": "Lecture Vocale en Arrière-Plan",
"Ready to read aloud": "Prêt à lire à haute voix",
"Read Aloud": "Lire à haute voix"
}
@@ -597,5 +597,7 @@
"Start Migration": "माइग्रेशन प्रारंभ करें",
"Advanced Settings": "उन्नत सेटिंग्स",
"File count: {{size}}": "फ़ाइलों की संख्या: {{size}}",
"Background Read Aloud": "पृष्ठभूमि में वाचन"
"Background Read Aloud": "पृष्ठभूमि में वाचन",
"Ready to read aloud": "उच्च स्वर में पढ़ने के लिए तैयार",
"Read Aloud": "उच्च स्वर में पढ़ें"
}
@@ -593,5 +593,7 @@
"Start Migration": "Mulai Migrasi",
"Advanced Settings": "Pengaturan Lanjutan",
"File count: {{size}}": "Jumlah file: {{size}}",
"Background Read Aloud": "Bacakan Latar Belakang"
"Background Read Aloud": "Bacakan Latar Belakang",
"Ready to read aloud": "Siap untuk dibacakan",
"Read Aloud": "Bacakan"
}
@@ -601,5 +601,7 @@
"Start Migration": "Inizia Migrazione",
"Advanced Settings": "Impostazioni Avanzate",
"File count: {{size}}": "Conteggio file: {{size}}",
"Background Read Aloud": "Background Read Aloud"
"Background Read Aloud": "Riproduzione in background",
"Ready to read aloud": "Pronto per la lettura ad alta voce",
"Read Aloud": "Leggi ad alta voce"
}
@@ -593,5 +593,7 @@
"Start Migration": "移行を開始",
"Advanced Settings": "詳細設定",
"File count: {{size}}": "ファイル数: {{size}}",
"Background Read Aloud": "バックグラウンド読み上げ"
"Background Read Aloud": "バックグラウンド読み上げ",
"Ready to read aloud": "読み上げの準備ができました",
"Read Aloud": "読み上げ"
}
@@ -593,5 +593,7 @@
"Start Migration": "마이그레이션 시작",
"Advanced Settings": "고급 설정",
"File count: {{size}}": "파일 수: {{size}}",
"Background Read Aloud": "백그라운드 음성 읽기"
"Background Read Aloud": "백그라운드 음성 읽기",
"Ready to read aloud": "읽기 준비 완료",
"Read Aloud": "음성 읽기"
}
@@ -597,5 +597,7 @@
"Start Migration": "Start Migratie",
"Advanced Settings": "Geavanceerde Instellingen",
"File count: {{size}}": "Bestandsaantal: {{size}}",
"Background Read Aloud": "Achtergrond Voorlezen"
"Background Read Aloud": "Achtergrond Voorlezen",
"Ready to read aloud": "Klaar om voor te lezen",
"Read Aloud": "Voorlezen"
}
@@ -605,5 +605,7 @@
"Start Migration": "Rozpocznij migrację",
"Advanced Settings": "Ustawienia zaawansowane",
"File count: {{size}}": "Liczba plików: {{size}}",
"Background Read Aloud": "Czytanie na głos w tle"
"Background Read Aloud": "Czytanie na głos w tle",
"Ready to read aloud": "Gotowy do przeczytania na głos",
"Read Aloud": "Czytaj na głos"
}
@@ -601,5 +601,7 @@
"Start Migration": "Iniciar Migração",
"Advanced Settings": "Configurações Avançadas",
"File count: {{size}}": "Contagem de arquivos: {{size}}",
"Background Read Aloud": "Leitura em Segundo Plano"
"Background Read Aloud": "Leitura em Segundo Plano",
"Ready to read aloud": "Pronto para leitura em voz alta",
"Read Aloud": "Ler em Voz Alta"
}
@@ -605,5 +605,7 @@
"Start Migration": "Начать миграцию",
"Advanced Settings": "Расширенные настройки",
"File count: {{size}}": "Количество файлов: {{size}}",
"Background Read Aloud": "Озвучивание в фоне"
"Background Read Aloud": "Озвучивание в фоне",
"Ready to read aloud": "Готов к чтению вслух",
"Read Aloud": "Читать вслух"
}
@@ -597,5 +597,7 @@
"Start Migration": "මැතිවරණය ආරම්භ කරන්න",
"Advanced Settings": "උසස් සැකසුම්",
"File count: {{size}}": "ගොනු ගණන: {{size}}",
"Background Read Aloud": "පසුබිම් පවසා කියවීම"
"Background Read Aloud": "පසුබිම් පවසා කියවීම",
"Ready to read aloud": "වාදනය කිරීමට සූදානම්",
"Read Aloud": "පවසා කියවීම"
}
@@ -597,5 +597,7 @@
"Start Migration": "மொத்தமாக்கலை தொடங்கவும்",
"Advanced Settings": "மேம்பட்ட அமைப்புகள்",
"File count: {{size}}": "கோப்பு எண்ணிக்கை: {{size}}",
"Background Read Aloud": "பின்னணி உரை வாசிப்பு"
"Background Read Aloud": "பின்னணி உரை வாசிப்பு",
"Ready to read aloud": "வாசிக்க தயாராக உள்ளது",
"Read Aloud": "உரை வாசிப்பு"
}
@@ -593,5 +593,7 @@
"Start Migration": "เริ่มการย้ายข้อมูล",
"Advanced Settings": "การตั้งค่าขั้นสูง",
"File count: {{size}}": "จำนวนไฟล์: {{size}}",
"Background Read Aloud": "อ่านออกเสียงเบื้องหลัง"
"Background Read Aloud": "อ่านออกเสียงเบื้องหลัง",
"Ready to read aloud": "พร้อมที่จะอ่านออกเสียง",
"Read Aloud": "อ่านออกเสียง"
}
@@ -597,5 +597,7 @@
"Start Migration": "Taşımayı Başlat",
"Advanced Settings": "Gelişmiş Ayarlar",
"File count: {{size}}": "Dosya sayısı: {{size}}",
"Background Read Aloud": "Arka Planda Sesli Okuma"
"Background Read Aloud": "Arka Planda Sesli Okuma",
"Ready to read aloud": "Sesli okumaya hazır",
"Read Aloud": "Sesli Oku"
}
@@ -605,5 +605,7 @@
"Start Migration": "Почати переміщення",
"Advanced Settings": "Розширені налаштування",
"File count: {{size}}": "Кількість файлів: {{size}}",
"Background Read Aloud": "Озвучування у фоновому режимі"
"Background Read Aloud": "Озвучування у фоновому режимі",
"Ready to read aloud": "Готовий до читання вголос",
"Read Aloud": "Читати вголос"
}
@@ -593,5 +593,7 @@
"Start Migration": "Bắt đầu di chuyển",
"Advanced Settings": "Cài đặt nâng cao",
"File count: {{size}}": "Số lượng tệp: {{size}}",
"Background Read Aloud": "Đọc To Nền"
"Background Read Aloud": "Đọc To Nền",
"Ready to read aloud": "Sẵn sàng để đọc to",
"Read Aloud": "Đọc To"
}
@@ -593,5 +593,7 @@
"Start Migration": "开始迁移",
"Advanced Settings": "高级设置",
"File count: {{size}}": "文件数量: {{size}}",
"Background Read Aloud": "后台语音朗读"
"Background Read Aloud": "后台语音朗读",
"Ready to read aloud": "语音朗读已就绪",
"Read Aloud": "语音朗读"
}
@@ -593,5 +593,7 @@
"Start Migration": "開始遷移",
"Advanced Settings": "高級設置",
"File count: {{size}}": "文件數量: {{size}}",
"Background Read Aloud": "背景朗讀"
"Background Read Aloud": "背景朗讀",
"Ready to read aloud": "朗讀準備就緒",
"Read Aloud": "朗讀"
}
@@ -99,6 +99,11 @@ class UpdateMediaSessionStateArgs {
@InvokeArg
class SetMediaSessionActiveArgs {
var active: Boolean? = null
var keepAppInForeground: Boolean? = null
var notificationTitle: String? = null
var notificationText: String? = null
var foregroundServiceTitle: String? = null
var foregroundServiceText: String? = null
}
class MediaForegroundService : Service() {
@@ -134,10 +139,10 @@ class MediaForegroundService : Service() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"TTS Media Playback",
NativeTTSPlugin.NOTIFICATION_TITLE,
NotificationManager.IMPORTANCE_MIN
).apply {
description = "Controls for TTS media playback"
description = NativeTTSPlugin.NOTIFICATION_TEXT
setShowBadge(false)
setSound(null, null)
}
@@ -148,8 +153,8 @@ class MediaForegroundService : Service() {
private fun startForegroundService() {
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("TTS Media Session")
.setContentText("Text-to-speech playback active")
.setContentTitle(NativeTTSPlugin.FOREGROUND_SERVICE_TITLE)
.setContentText(NativeTTSPlugin.FOREGROUND_SERVICE_TEXT)
.setSmallIcon(android.R.drawable.ic_media_play)
.setOngoing(true)
.setSilent(true)
@@ -183,6 +188,10 @@ class NativeTTSPlugin(private val activity: Activity) : Plugin(activity) {
companion object {
private const val TAG = "NativeTTSPlugin"
private const val CHANNEL_NAME = "tts_events"
var NOTIFICATION_TITLE = "Read Aloud"
var NOTIFICATION_TEXT = "Ready to read aloud"
var FOREGROUND_SERVICE_TITLE = "Read Aloud"
var FOREGROUND_SERVICE_TEXT = "Ready to read aloud"
}
private var textToSpeech: TextToSpeech? = null
@@ -198,6 +207,7 @@ class NativeTTSPlugin(private val activity: Activity) : Plugin(activity) {
private var player: Player? = null
private var mediaSession: MediaSession? = null
private var isMediaSessionActive = false
private var isForegroundServiceRunning = false
private val coroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
@@ -668,7 +678,6 @@ class NativeTTSPlugin(private val activity: Activity) : Plugin(activity) {
var args = invoke.parseArgs(UpdateMediaSessionStateArgs::class.java)
val isPlaying = args.playing ?: false
val position = args.position ?: 0.0
val duration = args.duration ?: 0.0
try {
player?.let { player ->
@@ -687,16 +696,28 @@ class NativeTTSPlugin(private val activity: Activity) : Plugin(activity) {
fun set_media_session_active(invoke: Invoke) {
var args = invoke.parseArgs(SetMediaSessionActiveArgs::class.java)
val active = args.active ?: true
val keepAppInForeground = args.keepAppInForeground ?: false
args.notificationTitle?.let { NOTIFICATION_TITLE = it }
args.notificationText?.let { NOTIFICATION_TEXT = it }
args.foregroundServiceTitle?.let { FOREGROUND_SERVICE_TITLE = it }
args.foregroundServiceText?.let { FOREGROUND_SERVICE_TEXT = it }
try {
if (active && !isMediaSessionActive) {
initializeMediaSession()
startForegroundService()
if (keepAppInForeground) {
startForegroundService()
isForegroundServiceRunning = true
}
isMediaSessionActive = true
Log.d(TAG, "Media session activated with foreground service")
} else if (!active && isMediaSessionActive) {
deinitializeMediaSession()
stopForegroundService()
if (isForegroundServiceRunning) {
stopForegroundService()
isForegroundServiceRunning = false
}
isMediaSessionActive = false
Log.d(TAG, "Media session deactivated and foreground service stopped")
}
@@ -710,7 +731,10 @@ class NativeTTSPlugin(private val activity: Activity) : Plugin(activity) {
fun destroy() {
try {
if (isMediaSessionActive) {
stopForegroundService()
if (isForegroundServiceRunning) {
stopForegroundService()
isForegroundServiceRunning = false
}
isMediaSessionActive = false
}
@@ -66,6 +66,11 @@ pub struct GetVoicesResponse {
#[serde(rename_all = "camelCase")]
pub struct SetMediaSessionActiveRequest {
pub active: bool,
pub keep_app_in_foreground: bool,
pub notification_title: Option<String>,
pub notification_text: Option<String>,
pub foreground_service_title: Option<String>,
pub foreground_service_text: Option<String>,
}
#[derive(Debug, Deserialize, Serialize)]
@@ -117,7 +117,14 @@ const TTSControl: React.FC<TTSControlProps> = ({ bookKey, gridInsets }) => {
artworkImage = await fetchImageAsBase64('/icon.png');
}
await mediaSession.setActive(true, settings.alwaysInForeground);
await mediaSession.setActive({
active: true,
keepAppInForeground: settings.alwaysInForeground,
notificationTitle: _('Read Aloud'),
notificationText: _('Ready to read aloud'),
foregroundServiceTitle: _('Read Aloud'),
foregroundServiceText: _('Ready to read aloud'),
});
mediaSession.updateMetadata({
title: title,
artist: sectionLabel || title,
@@ -129,7 +136,7 @@ const TTSControl: React.FC<TTSControlProps> = ({ bookKey, gridInsets }) => {
const deinitMediaSession = async () => {
if (mediaSessionRef.current && mediaSessionRef.current instanceof TauriMediaSession) {
await mediaSessionRef.current.setActive(false);
await mediaSessionRef.current.setActive({ active: false });
}
mediaSessionRef.current = null;
};
+26 -12
View File
@@ -16,6 +16,15 @@ export interface PlaybackState {
duration: number;
}
export interface MediaSessionState {
active: boolean;
keepAppInForeground?: boolean;
notificationTitle?: string;
notificationText?: string;
foregroundServiceTitle?: string;
foregroundServiceText?: string;
}
interface Permissions {
postNotification: PermissionState;
}
@@ -25,16 +34,16 @@ export class TauriMediaSession {
private eventListenerInited: boolean = false;
private eventListeners: PluginListener[] = [];
private async initializeListeners(keepAppInForeground: boolean) {
if (keepAppInForeground) {
const permission = await invoke<Permissions>('plugin:native-tts|checkPermissions');
if (permission.postNotification.startsWith('prompt')) {
await invoke<Permissions>('plugin:native-tts|requestPermissions', {
permissions: ['postNotification'],
});
}
private async requestPostNotificationPermission() {
const permission = await invoke<Permissions>('plugin:native-tts|checkPermissions');
if (permission.postNotification.startsWith('prompt')) {
await invoke<Permissions>('plugin:native-tts|requestPermissions', {
permissions: ['postNotification'],
});
}
}
private async initializeListeners() {
if (this.eventListenerInited) return;
this.eventListenerInited = true;
@@ -103,14 +112,19 @@ export class TauriMediaSession {
}
}
async setActive(active: boolean, keepAppInForeground: boolean = false) {
async setActive(sessionState: MediaSessionState) {
try {
if (active) {
await this.initializeListeners(keepAppInForeground);
if (sessionState.active) {
if (sessionState.keepAppInForeground) {
await this.requestPostNotificationPermission();
}
await this.initializeListeners();
} else {
await this.cleanupListeners();
}
await invoke('plugin:native-tts|set_media_session_active', { payload: { active } });
await invoke('plugin:native-tts|set_media_session_active', {
payload: sessionState,
});
} catch (error) {
console.error('Failed to set media session active state:', error);
}