Merge branch 'main' into emilia-t

pull/14/head
minxiwan 1 week ago
commit 2f92f4f78b

@ -24,7 +24,8 @@ data class UserPreferences(
val shouldAutoReconnect: Boolean,
val themeId: String = "blue",
val useDynamicColor: Boolean = true,
val language: String = "zh" // 默认中文
val language: String = "zh", // 默认中文
val notificationSound: String = "default"
)
class UserPreferencesRepository(
@ -50,7 +51,8 @@ class UserPreferencesRepository(
shouldAutoReconnect = prefs[KEY_SHOULD_AUTO_RECONNECT] ?: false,
themeId = prefs[KEY_THEME_ID] ?: "blue",
useDynamicColor = prefs[KEY_USE_DYNAMIC_COLOR] ?: true,
language = prefs[KEY_LANGUAGE] ?: "zh"
language = prefs[KEY_LANGUAGE] ?: "zh",
notificationSound = prefs[KEY_NOTIFICATION_SOUND] ?: "default"
)
}
@ -66,6 +68,12 @@ class UserPreferencesRepository(
}
}
suspend fun setNotificationSound(sound: String) {
context.dataStore.edit { prefs ->
prefs[KEY_NOTIFICATION_SOUND] = sound
}
}
suspend fun setUseDynamicColor(enabled: Boolean) {
context.dataStore.edit { prefs ->
prefs[KEY_USE_DYNAMIC_COLOR] = enabled
@ -155,5 +163,6 @@ class UserPreferencesRepository(
val KEY_THEME_ID: Preferences.Key<String> = stringPreferencesKey("theme_id")
val KEY_USE_DYNAMIC_COLOR: Preferences.Key<Boolean> = booleanPreferencesKey("use_dynamic_color")
val KEY_LANGUAGE: Preferences.Key<String> = stringPreferencesKey("language")
val KEY_NOTIFICATION_SOUND: Preferences.Key<String> = stringPreferencesKey("notification_sound")
}
}

@ -31,6 +31,14 @@ enum class MessageChannel {
PRIVATE
}
/**
* 消息内容类型文本/音频
*/
enum class MessageContentType {
TEXT,
AUDIO
}
/**
* 单条消息的数据类
* @property id 唯一标识默认随机 UUID
@ -48,7 +56,10 @@ data class UiMessage(
val subtitle: String = "",
val content: String,
val channel: MessageChannel,
val timestampMillis: Long = System.currentTimeMillis()
val timestampMillis: Long = System.currentTimeMillis(),
val contentType: MessageContentType = MessageContentType.TEXT,
val audioBase64: String = "",
val audioDurationMillis: Long = 0L
)
/**
@ -86,7 +97,10 @@ data class ChatUiState(
val loadingPublicKey: Boolean = false,
val themeId: String = "blue",
val useDynamicColor: Boolean = true,
val language: String = "zh"
val language: String = "zh",
val notificationSound: String = "default",
val isSwitchingServer: Boolean = false,
val switchingServerLabel: String = ""
) {
/**
* 是否允许连接
@ -141,4 +155,4 @@ data class ChatUiState(
*/
sealed interface UiEvent {
data class ShowSnackbar(val message: String) : UiEvent
}
}

@ -19,6 +19,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
fun updateDisplayName(value: String) = ChatSessionManager.updateDisplayName(value)
fun updateServerUrl(value: String) = ChatSessionManager.updateServerUrl(value)
fun selectServerUrl(value: String) = ChatSessionManager.selectServerUrl(value)
fun updateTargetKey(value: String) = ChatSessionManager.updateTargetKey(value)
fun updateDraft(value: String) = ChatSessionManager.updateDraft(value)
fun toggleDirectMode(enabled: Boolean) = ChatSessionManager.toggleDirectMode(enabled)
@ -30,9 +31,12 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
fun connect() = ChatSessionManager.connect()
fun disconnect() = ChatSessionManager.disconnect()
fun sendMessage() = ChatSessionManager.sendMessage()
fun sendAudioMessage(audioBase64: String, durationMillis: Long) =
ChatSessionManager.sendAudioMessage(audioBase64, durationMillis)
fun onMessageCopied() = ChatSessionManager.onMessageCopied()
fun updateTheme(themeId: String) = ChatSessionManager.updateTheme(themeId)
fun updateUseDynamicColor(enabled: Boolean) = ChatSessionManager.updateUseDynamicColor(enabled)
fun updateLanguage(language: String) = ChatSessionManager.updateLanguage(language)
}
fun updateNotificationSound(sound: String) = ChatSessionManager.updateNotificationSound(sound)
}

@ -6,6 +6,82 @@ package com.onlinemsg.client.util
*/
object LanguageManager {
private val zhHantOverrides = mapOf(
"tab.settings" to "設定",
"settings.personal" to "個人設定",
"settings.display_name" to "顯示名稱",
"settings.server" to "伺服器",
"settings.server_url" to "伺服器位址",
"settings.save_server" to "儲存位址",
"settings.remove_current" to "刪除目前",
"settings.saved_servers" to "已儲存位址",
"settings.identity" to "身份與安全",
"settings.reveal_key" to "檢視/產生公鑰",
"settings.copy_key" to "複製公鑰",
"settings.my_key" to "我的公鑰",
"settings.theme" to "主題",
"settings.preset_themes" to "預設主題",
"settings.language" to "語言",
"settings.diagnostics" to "診斷",
"settings.status_hint" to "連線提示",
"settings.current_status" to "目前狀態",
"settings.cert_fingerprint" to "憑證指紋",
"settings.show_system" to "顯示系統訊息",
"settings.clear_msg" to "清空訊息",
"settings.chat_data" to "聊天資料",
"settings.dynamic_color" to "使用動態顏色",
"settings.notification_sound" to "通知音效",
"settings.notification_enabled" to "系統通知與音效已啟用",
"settings.notification_disabled" to "系統通知目前已關閉",
"settings.notification_sound_disabled" to "目前音效渠道已被靜音",
"settings.notification_system_settings" to "系統通知設定",
"settings.notification_channel_settings" to "當前音效設定",
"status.idle" to "未連線",
"status.connecting" to "連線中",
"status.ready" to "已連線",
"status.error" to "異常中斷",
"hint.tap_to_connect" to "點擊連線開始聊天",
"hint.connecting_server" to "正在連線伺服器...",
"hint.ready_chat" to "已連線,可以開始聊天",
"hint.closed" to "連線已關閉",
"hint.reconnecting" to "連線已中斷,正在重試",
"session.hint.switching_server" to "正在切換伺服器",
"hint.reconnect_invalid_server" to "重連失敗:伺服器位址無效",
"hint.fill_target_key" to "請先填寫目標公鑰,再傳送私訊",
"hint.server_rejected_prefix" to "伺服器拒絕連線:",
"hint.audio_send_failed_prefix" to "語音傳送失敗:",
"chat.private" to "私訊",
"chat.target_key" to "目標公鑰",
"chat.input_placeholder" to "輸入訊息",
"chat.send" to "傳送",
"chat.sending" to "傳送中",
"chat.empty_hint" to "連線後即可聊天。預設為廣播,切換到私訊後可填寫目標公鑰。",
"chat.mode_text" to "文字",
"chat.mode_audio" to "語音",
"chat.audio_hold_to_talk" to "按住說話",
"chat.audio_release_send" to "鬆開即可傳送",
"chat.audio_release_cancel" to "鬆開即可取消",
"chat.audio_slide_cancel" to "按住時上滑即可取消",
"chat.audio_canceled" to "已取消語音傳送",
"chat.audio_sent" to "語音訊息已傳送",
"chat.audio_too_short" to "錄音時間太短",
"chat.audio_too_long" to "錄音時間太長",
"chat.audio_record_failed" to "錄音失敗",
"chat.audio_permission_required" to "需要麥克風權限",
"chat.audio_recording" to "錄音中",
"chat.audio_play" to "播放語音",
"chat.audio_stop" to "停止播放",
"sound.default" to "預設",
"sound.ding" to "",
"sound.nameit5" to "音效 5",
"sound.wind_chime" to "風鈴",
"theme.blue" to "蔚藍",
"theme.gray" to "商務灰",
"theme.green" to "翠綠",
"theme.red" to "緋紅",
"theme.warm" to "溫暖"
)
private val translations = mapOf(
"zh" to mapOf(
"tab.chat" to "聊天",
@ -32,7 +108,103 @@ object LanguageManager {
"settings.connect" to "连接",
"settings.disconnect" to "断开",
"settings.clear_msg" to "清空消息",
"settings.chat_data" to "聊天数据",
"settings.dynamic_color" to "使用动态颜色",
"settings.notification_sound" to "通知音效",
"settings.notification_enabled" to "系统通知与音效已启用",
"settings.notification_disabled" to "系统通知当前已关闭",
"settings.notification_sound_disabled" to "当前音效渠道已被静音",
"settings.notification_system_settings" to "系统通知设置",
"settings.notification_channel_settings" to "当前音效设置",
"sound.default" to "默认",
"sound.ding" to "",
"sound.nameit5" to "音效 5",
"sound.wind_chime" to "风铃",
"status.idle" to "未连接",
"status.connecting" to "连接中",
"status.ready" to "已连接",
"status.error" to "异常断开",
"hint.tap_to_connect" to "点击连接开始聊天",
"hint.connecting_server" to "正在连接服务器...",
"hint.ready_chat" to "已连接,可以开始聊天",
"hint.closed" to "连接已关闭",
"hint.reconnecting" to "连接已中断,正在重试",
"session.hint.switching_server" to "正在切换服务器",
"hint.reconnect_invalid_server" to "重连失败:服务器地址无效",
"hint.fill_target_key" to "请先填写目标公钥,再发送私聊消息",
"hint.server_rejected_prefix" to "服务器拒绝连接:",
"hint.audio_send_failed_prefix" to "语音发送失败:",
"session.sender.system" to "系统",
"session.sender.me" to "",
"session.sender.anonymous" to "匿名用户",
"session.sender.private_message" to "私聊消息",
"session.reason.connection_error" to "连接异常",
"session.reason.connection_interrupted" to "连接已中断",
"session.text.policy_restriction" to "策略限制",
"session.text.connection_interrupted" to "连接中断",
"session.snackbar.invalid_server" to "请输入有效的服务器地址",
"session.snackbar.server_saved" to "服务器地址已保存",
"session.snackbar.server_list_updated" to "已更新服务器地址列表",
"session.snackbar.public_key_read_failed" to "公钥读取失败:%s",
"session.hint.connected_preparing" to "已连接,正在准备聊天...",
"session.hint.binary_handshake_parsing" to "收到二进制握手帧,正在尝试解析...",
"session.hint.connection_error_retrying" to "连接异常,正在重试",
"session.hint.server_saved" to "服务器地址已保存",
"session.hint.server_restored_default" to "已恢复默认服务器地址",
"session.hint.server_removed" to "已移除当前服务器地址",
"session.hint.fill_valid_server" to "请填写有效服务器地址",
"session.hint.connecting_server" to "正在连接服务器...",
"session.hint.connection_closed" to "连接已关闭",
"session.hint.audio_chunk_over_limit" to "语音过长,超过可发送分片上限",
"session.hint.audio_send_failed" to "语音发送失败:%s",
"session.hint.handshake_data_received" to "已收到握手数据,正在解析...",
"session.hint.handshake_incomplete_response" to "握手失败:服务端响应不完整",
"session.hint.handshake_unexpected_message" to "握手失败:收到非预期消息",
"session.hint.handshake_first_packet_parse_failed" to "握手失败:首包解析失败",
"session.hint.authenticating" to "正在完成身份验证...",
"session.hint.connection_timeout_retry" to "连接超时,请重试",
"session.hint.auth_failed" to "认证失败",
"session.hint.ready_to_chat" to "已连接,可以开始聊天",
"session.hint.server_rejected" to "服务器拒绝连接:%s",
"session.hint.auto_retry_connecting" to "正在自动重试连接...",
"session.hint.connection_interrupted_retry" to "连接已中断,正在重试",
"session.hint.fill_target_key_before_private" to "请先填写目标公钥,再发送私聊消息",
"session.hint.auto_reconnect_in" to "%ds 后自动重连(第 %d 次)",
"session.hint.reconnect_invalid_server" to "重连失败:服务器地址无效",
"session.hint.auto_reconnecting" to "正在自动重连...",
"session.hint.handshake_timeout" to "握手超时,请检查地址路径与反向代理",
"session.msg.connection_established" to "连接已建立",
"session.msg.text_frame_error" to "文本帧处理异常:%s",
"session.msg.binary_frame_error" to "二进制帧处理异常:%s",
"session.msg.handshake_binary_unreadable" to "握手二进制帧无法转为文本len=%d hex=%s",
"session.msg.connection_error" to "连接异常:%s",
"session.msg.auto_restore_connecting" to "已恢复上次会话,正在自动连接",
"session.msg.disconnected" to "已断开连接",
"session.msg.send_failed" to "发送失败:%s",
"session.msg.audio_chunk_canceled" to "语音过长,已取消发送",
"session.msg.audio_send_failed" to "语音发送失败:%s",
"session.msg.handshake_unexpected_type" to "握手阶段收到非预期消息类型:%s",
"session.msg.handshake_parse_failed" to "握手包解析失败:%s",
"session.msg.decryption_failed" to "收到无法解密的消息",
"session.msg.auth_timeout" to "认证超时,请检查网络后重试",
"session.msg.auth_request_sent" to "已发送认证请求",
"session.msg.auth_send_failed" to "认证发送失败:%s",
"session.msg.ready" to "连接准备完成",
"session.msg.unknown_message_type" to "收到未识别消息类型:%s",
"session.msg.server_rejected" to "连接被服务器拒绝(%d%s",
"session.msg.switching_connection_mode_retry" to "连接方式切换中,正在重试",
"session.msg.connection_closed_with_code" to "连接关闭 (%d)%s",
"session.msg.auto_reconnect_in" to "%s%ds 后自动重连(第 %d 次)",
"session.msg.handshake_timeout_with_url" to "握手超时:未收到服务端 publickey 首包(当前地址:%s",
"session.error.message_too_large" to "消息体过大(%dB请缩短消息内容后重试",
"session.error.connection_unavailable" to "连接不可用",
"session.notification.channel_name" to "OnlineMsg 消息提醒",
"session.notification.channel_desc" to "收到服务器新消息时提醒",
"session.notification.new_message" to "收到一条新消息",
"session.notification.new_voice_message" to "收到一条语音消息",
"session.message.voice" to "语音消息",
"session.subtitle.from_key" to "来自 %s",
"session.subtitle.private_to_key" to "私聊 %s",
"chat.broadcast" to "广播",
"chat.private" to "私聊",
"chat.target_key" to "目标公钥",
@ -40,8 +212,31 @@ object LanguageManager {
"chat.send" to "发送",
"chat.sending" to "发送中",
"chat.empty_hint" to "连接后即可聊天。默认广播,切换到私聊后可填写目标公钥。",
"chat.mode_text" to "文字",
"chat.mode_audio" to "语音",
"chat.audio_hold_to_talk" to "按住说话",
"chat.audio_release_send" to "松开发送",
"chat.audio_release_cancel" to "松开取消",
"chat.audio_slide_cancel" to "按住说话,上滑取消",
"chat.audio_canceled" to "已取消语音发送",
"chat.audio_sent" to "语音已发送",
"chat.audio_too_short" to "录音时间太短",
"chat.audio_too_long" to "录音时间过长",
"chat.audio_record_failed" to "录音失败,请重试",
"chat.audio_permission_required" to "请先授予麦克风权限",
"chat.audio_recording" to "录制中",
"chat.audio_play" to "播放语音",
"chat.audio_stop" to "停止播放",
"common.copied" to "已复制",
"common.unknown" to "未知",
"service.foreground.title.ready" to "OnlineMsg 已保持连接",
"service.foreground.title.connecting" to "OnlineMsg 正在连接",
"service.foreground.title.error" to "OnlineMsg 连接异常",
"service.foreground.title.idle" to "OnlineMsg 后台服务",
"service.foreground.hint.default" to "后台保持连接中",
"service.foreground.action.disconnect" to "断开",
"service.foreground.channel.name" to "OnlineMsg 后台连接",
"service.foreground.channel.desc" to "保持 WebSocket 后台长连接",
"theme.blue" to "蔚蓝",
"theme.gray" to "商务灰",
"theme.green" to "翠绿",
@ -73,7 +268,103 @@ object LanguageManager {
"settings.connect" to "Link",
"settings.disconnect" to "Dislink",
"settings.clear_msg" to "ClearMsg",
"settings.chat_data" to "Chat Data",
"settings.dynamic_color" to "Use dynamic color",
"settings.notification_sound" to "Notification Sound",
"settings.notification_enabled" to "Notifications and sound are enabled",
"settings.notification_disabled" to "Notifications are currently disabled",
"settings.notification_sound_disabled" to "The selected sound channel is muted",
"settings.notification_system_settings" to "System Notification Settings",
"settings.notification_channel_settings" to "Current Sound Channel",
"sound.default" to "Default",
"sound.ding" to "Ding",
"sound.nameit5" to "Sound 5",
"sound.wind_chime" to "Wind Chime",
"status.idle" to "Offline",
"status.connecting" to "Connecting",
"status.ready" to "Connected",
"status.error" to "Disconnected",
"hint.tap_to_connect" to "Tap connect to start chatting",
"hint.connecting_server" to "Connecting to server...",
"hint.ready_chat" to "Connected, ready to chat",
"hint.closed" to "Connection closed",
"hint.reconnecting" to "Connection interrupted, reconnecting",
"session.hint.switching_server" to "Switching server",
"hint.reconnect_invalid_server" to "Reconnect failed: invalid server address",
"hint.fill_target_key" to "Please fill target public key before private message",
"hint.server_rejected_prefix" to "Server rejected connection: ",
"hint.audio_send_failed_prefix" to "Voice send failed: ",
"session.sender.system" to "System",
"session.sender.me" to "Me",
"session.sender.anonymous" to "Anonymous",
"session.sender.private_message" to "Private Message",
"session.reason.connection_error" to "Connection error",
"session.reason.connection_interrupted" to "Connection interrupted",
"session.text.policy_restriction" to "policy restriction",
"session.text.connection_interrupted" to "connection interrupted",
"session.snackbar.invalid_server" to "Please enter a valid server address",
"session.snackbar.server_saved" to "Server address saved",
"session.snackbar.server_list_updated" to "Server address list updated",
"session.snackbar.public_key_read_failed" to "Public key read failed: %s",
"session.hint.connected_preparing" to "Connected, preparing chat...",
"session.hint.binary_handshake_parsing" to "Received binary handshake frame, parsing...",
"session.hint.connection_error_retrying" to "Connection error, retrying",
"session.hint.server_saved" to "Server address saved",
"session.hint.server_restored_default" to "Default server restored",
"session.hint.server_removed" to "Current server removed",
"session.hint.fill_valid_server" to "Please enter a valid server address",
"session.hint.connecting_server" to "Connecting to server...",
"session.hint.connection_closed" to "Connection closed",
"session.hint.audio_chunk_over_limit" to "Voice message too long, chunk limit exceeded",
"session.hint.audio_send_failed" to "Voice send failed: %s",
"session.hint.handshake_data_received" to "Handshake data received, parsing...",
"session.hint.handshake_incomplete_response" to "Handshake failed: incomplete server response",
"session.hint.handshake_unexpected_message" to "Handshake failed: unexpected message",
"session.hint.handshake_first_packet_parse_failed" to "Handshake failed: first packet parse failed",
"session.hint.authenticating" to "Authenticating...",
"session.hint.connection_timeout_retry" to "Connection timeout, please retry",
"session.hint.auth_failed" to "Authentication failed",
"session.hint.ready_to_chat" to "Connected, ready to chat",
"session.hint.server_rejected" to "Server rejected connection: %s",
"session.hint.auto_retry_connecting" to "Auto retry connecting...",
"session.hint.connection_interrupted_retry" to "Connection interrupted, retrying",
"session.hint.fill_target_key_before_private" to "Please enter target public key before private message",
"session.hint.auto_reconnect_in" to "Auto reconnect in %ds (attempt %d)",
"session.hint.reconnect_invalid_server" to "Reconnect failed: invalid server address",
"session.hint.auto_reconnecting" to "Auto reconnecting...",
"session.hint.handshake_timeout" to "Handshake timeout, check URL path or reverse proxy",
"session.msg.connection_established" to "Connection established",
"session.msg.text_frame_error" to "Text frame processing error: %s",
"session.msg.binary_frame_error" to "Binary frame processing error: %s",
"session.msg.handshake_binary_unreadable" to "Binary handshake frame unreadable, len=%d hex=%s",
"session.msg.connection_error" to "Connection error: %s",
"session.msg.auto_restore_connecting" to "Restored last session, auto connecting",
"session.msg.disconnected" to "Disconnected",
"session.msg.send_failed" to "Send failed: %s",
"session.msg.audio_chunk_canceled" to "Voice message too long, canceled",
"session.msg.audio_send_failed" to "Voice send failed: %s",
"session.msg.handshake_unexpected_type" to "Unexpected message type during handshake: %s",
"session.msg.handshake_parse_failed" to "Handshake packet parse failed: %s",
"session.msg.decryption_failed" to "Received undecryptable message",
"session.msg.auth_timeout" to "Authentication timeout, please check network and retry",
"session.msg.auth_request_sent" to "Authentication request sent",
"session.msg.auth_send_failed" to "Authentication send failed: %s",
"session.msg.ready" to "Connection ready",
"session.msg.unknown_message_type" to "Unknown message type received: %s",
"session.msg.server_rejected" to "Connection rejected by server (%d): %s",
"session.msg.switching_connection_mode_retry" to "Switching connection mode, retrying",
"session.msg.connection_closed_with_code" to "Connection closed (%d): %s",
"session.msg.auto_reconnect_in" to "%s, auto reconnect in %ds (attempt %d)",
"session.msg.handshake_timeout_with_url" to "Handshake timeout: no server publickey packet (url: %s)",
"session.error.message_too_large" to "Message too large (%dB), please shorten and retry",
"session.error.connection_unavailable" to "Connection unavailable",
"session.notification.channel_name" to "OnlineMsg Notifications",
"session.notification.channel_desc" to "Notify when new server messages arrive",
"session.notification.new_message" to "New message received",
"session.notification.new_voice_message" to "New voice message received",
"session.message.voice" to "Voice message",
"session.subtitle.from_key" to "From %s",
"session.subtitle.private_to_key" to "Private %s",
"chat.broadcast" to "Broadcast",
"chat.private" to "Private",
"chat.target_key" to "Target Public Key",
@ -81,8 +372,31 @@ object LanguageManager {
"chat.send" to "Send",
"chat.sending" to "Sending",
"chat.empty_hint" to "Connect to start chatting. Default is broadcast.",
"chat.mode_text" to "Text",
"chat.mode_audio" to "Voice",
"chat.audio_hold_to_talk" to "Hold to Talk",
"chat.audio_release_send" to "Release to Send",
"chat.audio_release_cancel" to "Release to Cancel",
"chat.audio_slide_cancel" to "Hold to talk, slide up to cancel",
"chat.audio_canceled" to "Voice message canceled",
"chat.audio_sent" to "Voice message sent",
"chat.audio_too_short" to "Recording is too short",
"chat.audio_too_long" to "Recording is too long",
"chat.audio_record_failed" to "Recording failed, try again",
"chat.audio_permission_required" to "Microphone permission is required",
"chat.audio_recording" to "Recording",
"chat.audio_play" to "Play voice",
"chat.audio_stop" to "Stop",
"common.copied" to "Copied",
"common.unknown" to "Unknown",
"service.foreground.title.ready" to "OnlineMsg Connected",
"service.foreground.title.connecting" to "OnlineMsg Connecting",
"service.foreground.title.error" to "OnlineMsg Connection Error",
"service.foreground.title.idle" to "OnlineMsg Background Service",
"service.foreground.hint.default" to "Keeping connection in background",
"service.foreground.action.disconnect" to "Disconnect",
"service.foreground.channel.name" to "OnlineMsg Background Connection",
"service.foreground.channel.desc" to "Keep WebSocket long connection in background",
"theme.blue" to "Blue",
"theme.gray" to "Business Gray",
"theme.green" to "Green",
@ -114,7 +428,103 @@ object LanguageManager {
"settings.connect" to "接続",
"settings.disconnect" to "切断",
"settings.clear_msg" to "履歴を消去",
"settings.chat_data" to "チャットデータ",
"settings.dynamic_color" to "動的カラーを使用",
"settings.notification_sound" to "通知音",
"settings.notification_enabled" to "通知と音が有効です",
"settings.notification_disabled" to "通知が現在オフです",
"settings.notification_sound_disabled" to "現在の音声チャンネルはミュートされています",
"settings.notification_system_settings" to "システム通知設定",
"settings.notification_channel_settings" to "現在の音設定",
"sound.default" to "デフォルト",
"sound.ding" to "ディン",
"sound.nameit5" to "効果音 5",
"sound.wind_chime" to "風鈴",
"status.idle" to "未接続",
"status.connecting" to "接続中",
"status.ready" to "接続済み",
"status.error" to "切断",
"hint.tap_to_connect" to "接続してチャットを開始",
"hint.connecting_server" to "サーバーへ接続中...",
"hint.ready_chat" to "接続完了、チャット可能",
"hint.closed" to "接続を閉じました",
"hint.reconnecting" to "接続が中断され、再接続中",
"session.hint.switching_server" to "サーバーを切り替え中",
"hint.reconnect_invalid_server" to "再接続失敗:サーバーアドレス無効",
"hint.fill_target_key" to "個人チャット前に相手の公開鍵を入力してください",
"hint.server_rejected_prefix" to "サーバーが接続を拒否しました:",
"hint.audio_send_failed_prefix" to "音声送信失敗:",
"session.sender.system" to "システム",
"session.sender.me" to "自分",
"session.sender.anonymous" to "匿名ユーザー",
"session.sender.private_message" to "個人メッセージ",
"session.reason.connection_error" to "接続エラー",
"session.reason.connection_interrupted" to "接続中断",
"session.text.policy_restriction" to "ポリシー制限",
"session.text.connection_interrupted" to "接続中断",
"session.snackbar.invalid_server" to "有効なサーバーアドレスを入力してください",
"session.snackbar.server_saved" to "サーバーアドレスを保存しました",
"session.snackbar.server_list_updated" to "サーバーアドレス一覧を更新しました",
"session.snackbar.public_key_read_failed" to "公開鍵の読み取りに失敗しました:%s",
"session.hint.connected_preparing" to "接続済み、チャット準備中...",
"session.hint.binary_handshake_parsing" to "バイナリ握手フレーム受信、解析中...",
"session.hint.connection_error_retrying" to "接続エラー、再試行中",
"session.hint.server_saved" to "サーバーアドレスを保存しました",
"session.hint.server_restored_default" to "デフォルトサーバーを復元しました",
"session.hint.server_removed" to "現在のサーバーを削除しました",
"session.hint.fill_valid_server" to "有効なサーバーアドレスを入力してください",
"session.hint.connecting_server" to "サーバーへ接続中...",
"session.hint.connection_closed" to "接続を閉じました",
"session.hint.audio_chunk_over_limit" to "音声が長すぎて分割上限を超えました",
"session.hint.audio_send_failed" to "音声送信失敗:%s",
"session.hint.handshake_data_received" to "握手データ受信、解析中...",
"session.hint.handshake_incomplete_response" to "握手失敗:サーバー応答が不完全です",
"session.hint.handshake_unexpected_message" to "握手失敗:予期しないメッセージ",
"session.hint.handshake_first_packet_parse_failed" to "握手失敗:初回パケット解析失敗",
"session.hint.authenticating" to "認証中...",
"session.hint.connection_timeout_retry" to "接続タイムアウト、再試行してください",
"session.hint.auth_failed" to "認証失敗",
"session.hint.ready_to_chat" to "接続済み、チャット可能",
"session.hint.server_rejected" to "サーバーが接続を拒否しました:%s",
"session.hint.auto_retry_connecting" to "自動再試行で接続中...",
"session.hint.connection_interrupted_retry" to "接続が中断され、再試行中",
"session.hint.fill_target_key_before_private" to "個人チャット前に相手の公開鍵を入力してください",
"session.hint.auto_reconnect_in" to "%d秒後に自動再接続%d回目",
"session.hint.reconnect_invalid_server" to "再接続失敗:サーバーアドレス無効",
"session.hint.auto_reconnecting" to "自動再接続中...",
"session.hint.handshake_timeout" to "握手タイムアウトURL パスまたはリバースプロキシを確認",
"session.msg.connection_established" to "接続が確立されました",
"session.msg.text_frame_error" to "テキストフレーム処理エラー:%s",
"session.msg.binary_frame_error" to "バイナリフレーム処理エラー:%s",
"session.msg.handshake_binary_unreadable" to "バイナリ握手フレームをテキスト化できません。len=%d hex=%s",
"session.msg.connection_error" to "接続エラー:%s",
"session.msg.auto_restore_connecting" to "前回セッションを復元し自動接続中",
"session.msg.disconnected" to "切断しました",
"session.msg.send_failed" to "送信失敗:%s",
"session.msg.audio_chunk_canceled" to "音声が長すぎるため送信を中止しました",
"session.msg.audio_send_failed" to "音声送信失敗:%s",
"session.msg.handshake_unexpected_type" to "握手中に予期しないメッセージ種別:%s",
"session.msg.handshake_parse_failed" to "握手パケット解析失敗:%s",
"session.msg.decryption_failed" to "復号できないメッセージを受信しました",
"session.msg.auth_timeout" to "認証タイムアウト:ネットワークを確認して再試行してください",
"session.msg.auth_request_sent" to "認証リクエストを送信しました",
"session.msg.auth_send_failed" to "認証送信失敗:%s",
"session.msg.ready" to "接続準備完了",
"session.msg.unknown_message_type" to "未識別メッセージ種別を受信:%s",
"session.msg.server_rejected" to "サーバーに接続拒否されました(%d%s",
"session.msg.switching_connection_mode_retry" to "接続方式を切り替えて再試行中",
"session.msg.connection_closed_with_code" to "接続が閉じられました(%d%s",
"session.msg.auto_reconnect_in" to "%s、%d秒後に自動再接続%d回目",
"session.msg.handshake_timeout_with_url" to "握手タイムアウトserver publickey 初回パケット未受信URL: %s",
"session.error.message_too_large" to "メッセージが大きすぎます(%dB。短くして再試行してください",
"session.error.connection_unavailable" to "接続不可",
"session.notification.channel_name" to "OnlineMsg 通知",
"session.notification.channel_desc" to "サーバー新着メッセージを通知",
"session.notification.new_message" to "新着メッセージ",
"session.notification.new_voice_message" to "新着音声メッセージ",
"session.message.voice" to "音声メッセージ",
"session.subtitle.from_key" to "%s から",
"session.subtitle.private_to_key" to "個人 %s",
"chat.broadcast" to "全体",
"chat.private" to "個人",
"chat.target_key" to "相手の公開鍵",
@ -122,8 +532,31 @@ object LanguageManager {
"chat.send" to "送信",
"chat.sending" to "送信中",
"chat.empty_hint" to "接続するとチャットを開始できます。",
"chat.mode_text" to "テキスト",
"chat.mode_audio" to "音声",
"chat.audio_hold_to_talk" to "長押しで録音",
"chat.audio_release_send" to "離して送信",
"chat.audio_release_cancel" to "離してキャンセル",
"chat.audio_slide_cancel" to "長押し中に上へスライドでキャンセル",
"chat.audio_canceled" to "音声送信をキャンセルしました",
"chat.audio_sent" to "音声を送信しました",
"chat.audio_too_short" to "録音時間が短すぎます",
"chat.audio_too_long" to "録音が長すぎます",
"chat.audio_record_failed" to "録音に失敗しました",
"chat.audio_permission_required" to "マイク権限が必要です",
"chat.audio_recording" to "録音中",
"chat.audio_play" to "再生",
"chat.audio_stop" to "停止",
"common.copied" to "コピーしました",
"common.unknown" to "不明",
"service.foreground.title.ready" to "OnlineMsg 接続維持中",
"service.foreground.title.connecting" to "OnlineMsg 接続中",
"service.foreground.title.error" to "OnlineMsg 接続エラー",
"service.foreground.title.idle" to "OnlineMsg バックグラウンドサービス",
"service.foreground.hint.default" to "バックグラウンドで接続を維持中",
"service.foreground.action.disconnect" to "切断",
"service.foreground.channel.name" to "OnlineMsg バックグラウンド接続",
"service.foreground.channel.desc" to "WebSocket のバックグラウンド長時間接続を維持",
"theme.blue" to "ブルー",
"theme.gray" to "ビジネスグレー",
"theme.green" to "グリーン",
@ -155,7 +588,103 @@ object LanguageManager {
"settings.connect" to "연결",
"settings.disconnect" to "연결 끊기",
"settings.clear_msg" to "정보 삭제",
"settings.chat_data" to "채팅 데이터",
"settings.dynamic_color" to "동적 색상 사용",
"settings.notification_sound" to "알림 효과음",
"settings.notification_enabled" to "시스템 알림과 효과음이 켜져 있습니다",
"settings.notification_disabled" to "시스템 알림이 현재 꺼져 있습니다",
"settings.notification_sound_disabled" to "현재 효과음 채널이 음소거되어 있습니다",
"settings.notification_system_settings" to "시스템 알림 설정",
"settings.notification_channel_settings" to "현재 효과음 설정",
"sound.default" to "기본값",
"sound.ding" to "",
"sound.nameit5" to "효과음 5",
"sound.wind_chime" to "풍경",
"status.idle" to "연결 안 됨",
"status.connecting" to "연결 중",
"status.ready" to "연결됨",
"status.error" to "연결 끊김",
"hint.tap_to_connect" to "연결을 눌러 채팅을 시작하세요",
"hint.connecting_server" to "서버에 연결 중...",
"hint.ready_chat" to "연결 완료, 채팅 가능",
"hint.closed" to "연결이 종료되었습니다",
"hint.reconnecting" to "연결이 끊겨 재연결 중입니다",
"session.hint.switching_server" to "서버 전환 중",
"hint.reconnect_invalid_server" to "재연결 실패: 서버 주소가 올바르지 않습니다",
"hint.fill_target_key" to "비공개 채팅 전 대상 공개키를 입력하세요",
"hint.server_rejected_prefix" to "서버가 연결을 거부했습니다: ",
"hint.audio_send_failed_prefix" to "음성 전송 실패: ",
"session.sender.system" to "시스템",
"session.sender.me" to "",
"session.sender.anonymous" to "익명 사용자",
"session.sender.private_message" to "비공개 메시지",
"session.reason.connection_error" to "연결 오류",
"session.reason.connection_interrupted" to "연결 중단",
"session.text.policy_restriction" to "정책 제한",
"session.text.connection_interrupted" to "연결 중단",
"session.snackbar.invalid_server" to "유효한 서버 주소를 입력하세요",
"session.snackbar.server_saved" to "서버 주소를 저장했습니다",
"session.snackbar.server_list_updated" to "서버 주소 목록을 업데이트했습니다",
"session.snackbar.public_key_read_failed" to "공개키 읽기 실패: %s",
"session.hint.connected_preparing" to "연결됨, 채팅 준비 중...",
"session.hint.binary_handshake_parsing" to "바이너리 핸드셰이크 프레임 수신, 파싱 중...",
"session.hint.connection_error_retrying" to "연결 오류, 재시도 중",
"session.hint.server_saved" to "서버 주소를 저장했습니다",
"session.hint.server_restored_default" to "기본 서버를 복원했습니다",
"session.hint.server_removed" to "현재 서버를 삭제했습니다",
"session.hint.fill_valid_server" to "유효한 서버 주소를 입력하세요",
"session.hint.connecting_server" to "서버에 연결 중...",
"session.hint.connection_closed" to "연결이 종료되었습니다",
"session.hint.audio_chunk_over_limit" to "음성이 너무 길어 분할 상한을 초과했습니다",
"session.hint.audio_send_failed" to "음성 전송 실패: %s",
"session.hint.handshake_data_received" to "핸드셰이크 데이터 수신, 파싱 중...",
"session.hint.handshake_incomplete_response" to "핸드셰이크 실패: 서버 응답이 불완전합니다",
"session.hint.handshake_unexpected_message" to "핸드셰이크 실패: 예상치 못한 메시지",
"session.hint.handshake_first_packet_parse_failed" to "핸드셰이크 실패: 첫 패킷 파싱 실패",
"session.hint.authenticating" to "인증 중...",
"session.hint.connection_timeout_retry" to "연결 시간 초과, 다시 시도하세요",
"session.hint.auth_failed" to "인증 실패",
"session.hint.ready_to_chat" to "연결 완료, 채팅 가능",
"session.hint.server_rejected" to "서버가 연결을 거부했습니다: %s",
"session.hint.auto_retry_connecting" to "자동 재시도 연결 중...",
"session.hint.connection_interrupted_retry" to "연결이 끊겨 재시도 중",
"session.hint.fill_target_key_before_private" to "비공개 채팅 전 대상 공개키를 입력하세요",
"session.hint.auto_reconnect_in" to "%d초 후 자동 재연결 (%d회차)",
"session.hint.reconnect_invalid_server" to "재연결 실패: 서버 주소가 올바르지 않습니다",
"session.hint.auto_reconnecting" to "자동 재연결 중...",
"session.hint.handshake_timeout" to "핸드셰이크 시간 초과: URL 경로 또는 리버스 프록시를 확인하세요",
"session.msg.connection_established" to "연결이 설정되었습니다",
"session.msg.text_frame_error" to "텍스트 프레임 처리 오류: %s",
"session.msg.binary_frame_error" to "바이너리 프레임 처리 오류: %s",
"session.msg.handshake_binary_unreadable" to "핸드셰이크 바이너리 프레임을 텍스트로 변환할 수 없습니다. len=%d hex=%s",
"session.msg.connection_error" to "연결 오류: %s",
"session.msg.auto_restore_connecting" to "이전 세션을 복원하여 자동 연결 중",
"session.msg.disconnected" to "연결 해제됨",
"session.msg.send_failed" to "전송 실패: %s",
"session.msg.audio_chunk_canceled" to "음성이 너무 길어 전송이 취소되었습니다",
"session.msg.audio_send_failed" to "음성 전송 실패: %s",
"session.msg.handshake_unexpected_type" to "핸드셰이크 중 예상치 못한 메시지 유형: %s",
"session.msg.handshake_parse_failed" to "핸드셰이크 패킷 파싱 실패: %s",
"session.msg.decryption_failed" to "복호화할 수 없는 메시지를 받았습니다",
"session.msg.auth_timeout" to "인증 시간 초과: 네트워크를 확인하고 다시 시도하세요",
"session.msg.auth_request_sent" to "인증 요청을 전송했습니다",
"session.msg.auth_send_failed" to "인증 전송 실패: %s",
"session.msg.ready" to "연결 준비 완료",
"session.msg.unknown_message_type" to "알 수 없는 메시지 유형 수신: %s",
"session.msg.server_rejected" to "서버가 연결을 거부했습니다 (%d): %s",
"session.msg.switching_connection_mode_retry" to "연결 방식을 전환하여 재시도 중",
"session.msg.connection_closed_with_code" to "연결 종료 (%d): %s",
"session.msg.auto_reconnect_in" to "%s, %d초 후 자동 재연결 (%d회차)",
"session.msg.handshake_timeout_with_url" to "핸드셰이크 시간 초과: 서버 publickey 첫 패킷 미수신 (URL: %s)",
"session.error.message_too_large" to "메시지가 너무 큽니다 (%dB). 줄여서 다시 시도하세요",
"session.error.connection_unavailable" to "연결 불가",
"session.notification.channel_name" to "OnlineMsg 알림",
"session.notification.channel_desc" to "서버 새 메시지 수신 시 알림",
"session.notification.new_message" to "새 메시지 수신",
"session.notification.new_voice_message" to "새 음성 메시지 수신",
"session.message.voice" to "음성 메시지",
"session.subtitle.from_key" to "%s 에서",
"session.subtitle.private_to_key" to "비공개 %s",
"chat.broadcast" to "브로드캐스트",
"chat.private" to "비공개 채팅",
"chat.target_key" to "대상 공개키",
@ -163,22 +692,54 @@ object LanguageManager {
"chat.send" to "전송",
"chat.sending" to "전송 중",
"chat.empty_hint" to "연결 후 채팅이 가능합니다. 기본은 브로드캐스트이며, 비공개 채팅으로 전환 후 대상 공개키를 입력할 수 있습니다.",
"chat.mode_text" to "텍스트",
"chat.mode_audio" to "음성",
"chat.audio_hold_to_talk" to "길게 눌러 말하기",
"chat.audio_release_send" to "손을 떼면 전송",
"chat.audio_release_cancel" to "손을 떼면 취소",
"chat.audio_slide_cancel" to "길게 누른 상태에서 위로 밀어 취소",
"chat.audio_canceled" to "음성 전송이 취소되었습니다",
"chat.audio_sent" to "음성 메시지를 보냈습니다",
"chat.audio_too_short" to "녹음 시간이 너무 짧습니다",
"chat.audio_too_long" to "녹음 시간이 너무 깁니다",
"chat.audio_record_failed" to "녹음에 실패했습니다",
"chat.audio_permission_required" to "마이크 권한이 필요합니다",
"chat.audio_recording" to "녹음 중",
"chat.audio_play" to "재생",
"chat.audio_stop" to "정지",
"common.copied" to "복사됨",
"common.unknown" to "알 수 없음",
"service.foreground.title.ready" to "OnlineMsg 연결 유지됨",
"service.foreground.title.connecting" to "OnlineMsg 연결 중",
"service.foreground.title.error" to "OnlineMsg 연결 오류",
"service.foreground.title.idle" to "OnlineMsg 백그라운드 서비스",
"service.foreground.hint.default" to "백그라운드에서 연결 유지 중",
"service.foreground.action.disconnect" to "연결 끊기",
"service.foreground.channel.name" to "OnlineMsg 백그라운드 연결",
"service.foreground.channel.desc" to "백그라운드에서 WebSocket 장기 연결 유지",
"theme.blue" to "파랑",
"theme.gray" to "비즈니스 그레이",
"theme.green" to "초록",
"theme.red" to "빨강",
"theme.warm" to "따뜻함"
)
),
"zh-Hant" to zhHantOverrides
)
fun getString(key: String, lang: String): String {
return translations[lang]?.get(key) ?: translations["en"]?.get(key) ?: key
return when (lang) {
"zh-Hant" -> translations["zh-Hant"]?.get(key)
?: translations["zh"]?.get(key)
?: translations["en"]?.get(key)
?: key
else -> translations[lang]?.get(key) ?: translations["en"]?.get(key) ?: key
}
}
val supportedLanguages = listOf(
LanguageOption("zh", "中文"),
LanguageOption("zh", "中文简体"),
LanguageOption("zh-Hant", "繁體中文"),
LanguageOption("en", "English"),
LanguageOption("ja", "日本语"),
LanguageOption("ko", "한국어")

Loading…
Cancel
Save