diff --git a/bin/code-notify b/bin/code-notify index 187ea8c..06ff2f7 100755 --- a/bin/code-notify +++ b/bin/code-notify @@ -49,7 +49,7 @@ case "$COMMAND_NAME" in "version"|"-v"|"--version") show_version ;; - "on"|"off"|"status"|"test"|"setup"|"voice"|"sound"|"alerts"|"channels"|"usage"|"update") + "on"|"off"|"status"|"test"|"setup"|"voice"|"sound"|"alerts"|"channels"|"usage"|"update"|"lang") source "$LIB_DIR/commands/global.sh" handle_global_command "$@" ;; @@ -69,7 +69,7 @@ case "$COMMAND_NAME" in ;; esac ;; - + "cnp") # Called as 'cnp' - handle project commands directly source "$LIB_DIR/commands/project.sh" @@ -79,7 +79,7 @@ case "$COMMAND_NAME" in "code-notify"|*) # Called as 'code-notify' - full command parsing case "${1:-help}" in - "on"|"off"|"status"|"test"|"setup"|"voice"|"sound"|"alerts"|"channels"|"usage"|"update") + "on"|"off"|"status"|"test"|"setup"|"voice"|"sound"|"alerts"|"channels"|"usage"|"update"|"lang") source "$LIB_DIR/commands/global.sh" handle_global_command "$@" ;; diff --git a/lib/code-notify/commands/global.sh b/lib/code-notify/commands/global.sh index 0779e6c..287dd41 100755 --- a/lib/code-notify/commands/global.sh +++ b/lib/code-notify/commands/global.sh @@ -10,6 +10,7 @@ source "$GLOBAL_CMD_DIR/../utils/help.sh" source "$GLOBAL_CMD_DIR/../utils/click-through.sh" source "$GLOBAL_CMD_DIR/../utils/channels.sh" source "$GLOBAL_CMD_DIR/../utils/usage.sh" +source "$GLOBAL_CMD_DIR/../utils/lang.sh" CODE_NOTIFY_RELEASES_API="https://api.github.com/repos/mylee04/code-notify/releases/latest" @@ -55,6 +56,9 @@ handle_global_command() { "click-through") handle_click_through_command "$@" ;; + "lang") + handle_lang_command "$@" + ;; "help") show_help ;; @@ -594,6 +598,16 @@ show_status() { echo " ${DIM}- omp: not installed${RESET}" fi + # Language status + local lang_display + lang_display="$(get_lang)" + case "$lang_display" in + "zh") lang_display="中文" ;; + *) lang_display="English" ;; + esac + echo " ${GLOBE} Language: ${CYAN}$lang_display${RESET}" + echo "" + # Voice status echo "" if is_voice_enabled "global"; then @@ -1328,3 +1342,62 @@ show_sound_status() { echo " ${CYAN}cn sound test${RESET} Play current sound" echo " ${CYAN}cn sound list${RESET} Show available system sounds" } + +# ============================================ +# Language / i18n Management +# ============================================ + +# Handle lang commands +# Usage: cn lang, cn lang , cn lang status +handle_lang_command() { + local subcommand="${1:-status}" + + case "$subcommand" in + "zh"|"zh-CN"|"zh_CN"|"cn"|"chinese") + set_lang "zh" + success "语言已切换为中文" + info "通知文案将显示为中文。运行 ${CYAN}cn test${RESET} 测试效果。" + ;; + "en"|"english") + set_lang "en" + success "Language set to English" + info "Notifications will now display in English. Run ${CYAN}cn test${RESET} to verify." + ;; + "status"|"") + local current + current=$(get_lang) + case "$current" in + "zh") + echo "当前语言: 中文 (zh)" + echo "" + echo "切换为英文: ${CYAN}cn lang en${RESET}" + ;; + *) + echo "Current language: English (en)" + echo "" + echo "Switch to Chinese: ${CYAN}cn lang zh${RESET}" + ;; + esac + ;; + "help"|"-h"|"--help") + echo "" + echo "Usage: cn lang [locale|status]" + echo "" + echo "Locales:" + echo " ${CYAN}en${RESET} English (default)" + echo " ${CYAN}zh${RESET} 中文" + echo "" + echo "Examples:" + echo " cn lang zh # Switch to Chinese" + echo " cn lang en # Switch to English" + echo " cn lang status # Show current language" + ;; + *) + error "Unknown language: $subcommand" + echo "" + echo "Available: en, zh" + echo "Usage: cn lang " + return 1 + ;; + esac +} diff --git a/lib/code-notify/core/notifier.sh b/lib/code-notify/core/notifier.sh index 7eae839..84e68fe 100755 --- a/lib/code-notify/core/notifier.sh +++ b/lib/code-notify/core/notifier.sh @@ -20,6 +20,7 @@ source "$NOTIFIER_DIR/../utils/usage.sh" source "$NOTIFIER_DIR/../utils/click-through-store.sh" source "$NOTIFIER_DIR/../utils/click-through-runtime.sh" source "$NOTIFIER_DIR/../utils/click-through-resolver.sh" +source "$NOTIFIER_DIR/../utils/lang.sh" has_jq() { command -v jq >/dev/null 2>&1 @@ -417,79 +418,79 @@ fi case "$HOOK_TYPE" in "stop") TITLE="$TOOL_DISPLAY ✅" - SUBTITLE="Task Complete" - MESSAGE="$TOOL_DISPLAY completed the task" - VOICE_MESSAGE="$TOOL_DISPLAY completed the task" + SUBTITLE="$(t "task_complete")" + MESSAGE="$TOOL_DISPLAY $(t "completed_the_task")" + VOICE_MESSAGE="$TOOL_DISPLAY $(t "completed_the_task")" SOUND="Glass" ;; "notification") TITLE="$TOOL_DISPLAY 🔔" - SUBTITLE="Input Required" - MESSAGE="$TOOL_DISPLAY needs your input" - VOICE_MESSAGE="$TOOL_DISPLAY needs your input" + SUBTITLE="$(t "input_required")" + MESSAGE="$TOOL_DISPLAY $(t "needs_your_input")" + VOICE_MESSAGE="$TOOL_DISPLAY $(t "needs_your_input")" SOUND="Ping" ;; "SubagentStart") TITLE="$TOOL_DISPLAY 🤖" - SUBTITLE="Subagent Started" - MESSAGE="$TOOL_DISPLAY started a subagent" - VOICE_MESSAGE="$TOOL_DISPLAY started a subagent" + SUBTITLE="$(t "subagent_started")" + MESSAGE="$TOOL_DISPLAY $(t "started_a_subagent")" + VOICE_MESSAGE="$TOOL_DISPLAY $(t "started_a_subagent")" SOUND="Pop" ;; "SubagentStop") TITLE="$TOOL_DISPLAY ✅" - SUBTITLE="Subagent Complete" - MESSAGE="$TOOL_DISPLAY subagent completed" - VOICE_MESSAGE="$TOOL_DISPLAY subagent completed" + SUBTITLE="$(t "subagent_complete")" + MESSAGE="$TOOL_DISPLAY $(t "subagent_completed")" + VOICE_MESSAGE="$TOOL_DISPLAY $(t "subagent_completed")" SOUND="Glass" ;; "TeammateIdle") TITLE="$TOOL_DISPLAY 🔔" - SUBTITLE="Teammate Idle" - MESSAGE="$TOOL_DISPLAY teammate is waiting for input" - VOICE_MESSAGE="$TOOL_DISPLAY teammate is waiting for input" + SUBTITLE="$(t "waiting_for_input")" + MESSAGE="$TOOL_DISPLAY $(t "teammate_waiting")" + VOICE_MESSAGE="$TOOL_DISPLAY $(t "teammate_waiting")" SOUND="Ping" ;; "TaskCreated") TITLE="$TOOL_DISPLAY 📌" - SUBTITLE="Task Created" - MESSAGE="$TOOL_DISPLAY agent-team task was created" - VOICE_MESSAGE="$TOOL_DISPLAY task created" + SUBTITLE="$(t "task_created")" + MESSAGE="$TOOL_DISPLAY $(t "team_task_created")" + VOICE_MESSAGE="$TOOL_DISPLAY $(t "task_created")" SOUND="Pop" ;; "TaskCompleted") TITLE="$TOOL_DISPLAY ✅" - SUBTITLE="Task Complete" - MESSAGE="$TOOL_DISPLAY agent-team task completed" - VOICE_MESSAGE="$TOOL_DISPLAY task completed" + SUBTITLE="$(t "team_task_complete")" + MESSAGE="$TOOL_DISPLAY $(t "team_task_completed")" + VOICE_MESSAGE="$TOOL_DISPLAY $(t "task_complete")" SOUND="Glass" ;; "error"|"failed") TITLE="$TOOL_DISPLAY ❌" - SUBTITLE="Error" - MESSAGE="An error occurred in $TOOL_DISPLAY" - VOICE_MESSAGE="An error occurred in $TOOL_DISPLAY" + SUBTITLE="$(t "error")" + MESSAGE="$TOOL_DISPLAY $(t "error_occurred")" + VOICE_MESSAGE="$TOOL_DISPLAY $(t "error_occurred")" SOUND="Basso" ;; "test") TITLE="Code-Notify Test ✅" SUBTITLE="$PROJECT_NAME" - MESSAGE="Notifications are working!" - VOICE_MESSAGE="Notifications are working" + MESSAGE="$(t "notifications_working")" + VOICE_MESSAGE="$(t "notifications_working")" SOUND="Glass" ;; "usage") - TITLE="${CODE_NOTIFY_USAGE_TITLE:-$TOOL_DISPLAY usage alert}" - SUBTITLE="Usage Alert" - MESSAGE="${CODE_NOTIFY_USAGE_MESSAGE:-$TOOL_DISPLAY usage changed}" - VOICE_MESSAGE="${CODE_NOTIFY_USAGE_VOICE_MESSAGE:-$TOOL_DISPLAY usage alert}" + TITLE="${CODE_NOTIFY_USAGE_TITLE:-$TOOL_DISPLAY $(t "usage_alert")}" + SUBTITLE="$(t "usage_alert")" + MESSAGE="${CODE_NOTIFY_USAGE_MESSAGE:-$TOOL_DISPLAY $(t "usage_changed")}" + VOICE_MESSAGE="${CODE_NOTIFY_USAGE_VOICE_MESSAGE:-$TOOL_DISPLAY $(t "usage_alert")}" SOUND="Ping" ;; "usage_reset") - TITLE="${CODE_NOTIFY_USAGE_TITLE:-$TOOL_DISPLAY tokens reset}" - SUBTITLE="Tokens Reset" - MESSAGE="${CODE_NOTIFY_USAGE_MESSAGE:-$TOOL_DISPLAY tokens have reset. Usage is back to 100%.}" - VOICE_MESSAGE="${CODE_NOTIFY_USAGE_VOICE_MESSAGE:-$TOOL_DISPLAY tokens have reset}" + TITLE="${CODE_NOTIFY_USAGE_TITLE:-$TOOL_DISPLAY $(t "tokens_reset")}" + SUBTITLE="$(t "tokens_reset")" + MESSAGE="${CODE_NOTIFY_USAGE_MESSAGE:-$TOOL_DISPLAY $(t "tokens_have_reset")}" + VOICE_MESSAGE="${CODE_NOTIFY_USAGE_VOICE_MESSAGE:-$TOOL_DISPLAY $(t "tokens_reset")}" SOUND="Hero" ;; "PreToolUse") @@ -510,7 +511,7 @@ except Exception: fi TITLE="$TOOL_DISPLAY ❓" - SUBTITLE="Question" + SUBTITLE="$(t "question")" if [[ -n "$ASK_QUESTION_TEXT" ]]; then MESSAGE=$(printf '%s\n' "$ASK_QUESTION_TEXT" | head -c 150 | tr '\n' ' ') MESSAGE="${MESSAGE% }" @@ -518,16 +519,16 @@ except Exception: MESSAGE="${MESSAGE}..." fi else - MESSAGE="$TOOL_DISPLAY is asking a question" + MESSAGE="$TOOL_DISPLAY $(t "is_asking")" fi - VOICE_MESSAGE="$TOOL_DISPLAY is asking a question" + VOICE_MESSAGE="$TOOL_DISPLAY $(t "is_asking")" SOUND="Ping" ;; *) TITLE="$TOOL_DISPLAY 📢" - SUBTITLE="Status Update" + SUBTITLE="$(t "status_update")" MESSAGE="$TOOL_DISPLAY: $HOOK_TYPE" - VOICE_MESSAGE="$TOOL_DISPLAY status update" + VOICE_MESSAGE="$TOOL_DISPLAY $(t "status_update")" SOUND="Pop" ;; esac diff --git a/lib/code-notify/utils/help.sh b/lib/code-notify/utils/help.sh index c78dc77..e5d19bf 100644 --- a/lib/code-notify/utils/help.sh +++ b/lib/code-notify/utils/help.sh @@ -85,6 +85,7 @@ ${BOLD}SOUND COMMANDS:${RESET} ${GREEN}sound test${RESET} Play current sound ${GREEN}sound list${RESET} Show available system sounds ${GREEN}sound status${RESET} Show sound configuration + ${GREEN}lang${RESET} Set notification language (en/zh) ${BOLD}CHANNEL COMMANDS:${RESET} ${GREEN}channels status${RESET} Show Slack/Discord channel status @@ -149,6 +150,7 @@ ${BOLD}EXAMPLES:${RESET} cn usage check cn sound on # Enable notification sounds cn sound set ~/ding.wav # Use custom sound + cn lang zh # Switch notification text to Chinese EOF if is_macos_help_context; then diff --git a/lib/code-notify/utils/lang.sh b/lib/code-notify/utils/lang.sh new file mode 100644 index 0000000..105285a --- /dev/null +++ b/lib/code-notify/utils/lang.sh @@ -0,0 +1,142 @@ +#!/bin/bash + +# Language / i18n utilities for Code-Notify +# Usage: source this file, then use t() to translate notification strings + +LANG_DIR="$HOME/.claude/notifications" +LANG_FILE="$LANG_DIR/lang" + +# Get the current language setting +# Returns "en" (default) or "zh" +get_lang() { + if [[ -f "$LANG_FILE" ]]; then + local lang + lang=$(cat "$LANG_FILE" 2>/dev/null || echo "en") + case "$lang" in + "zh"|"zh-CN"|"zh_CN"|"cn") echo "zh" ;; + *) echo "en" ;; + esac + else + echo "en" + fi +} + +# Set the language +set_lang() { + local lang="${1:-en}" + case "$lang" in + "zh"|"zh-CN"|"zh_CN"|"cn") lang="zh" ;; + *) lang="en" ;; + esac + mkdir -p "$LANG_DIR" + echo "$lang" > "$LANG_FILE" +} + +# Translate a key to the current language +# Usage: t +t() { + local key="$1" + local lang + lang=$(get_lang) + + case "$lang" in + "zh") + case "$key" in + # Stop / task complete + "task_complete") echo "任务完成" ;; + "completed_the_task") echo "已完成任务" ;; + # Notification / input required + "input_required") echo "需要确认" ;; + "needs_your_input") echo "需要你的输入" ;; + # Subagent + "subagent_started") echo "子任务启动" ;; + "started_a_subagent") echo "启动了子任务" ;; + "subagent_complete") echo "子任务完成" ;; + "subagent_completed") echo "子任务已完成" ;; + # Teammate + "waiting_for_input") echo "等待输入" ;; + "teammate_waiting") echo "队友等待输入" ;; + # Team tasks + "task_created") echo "任务已创建" ;; + "team_task_created") echo "团队任务已创建" ;; + "team_task_complete") echo "团队任务完成" ;; + "team_task_completed") echo "团队任务已完成" ;; + # Error + "error") echo "出错了" ;; + "error_occurred") echo "发生了一个错误" ;; + # Test + "notifications_working") echo "通知功能正常工作!" ;; + # Usage + "usage_alert") echo "用量提醒" ;; + "usage_changed") echo "用量发生变化" ;; + "tokens_reset") echo "额度重置" ;; + "tokens_have_reset") echo "额度已重置,恢复到 100%。" ;; + # PreToolUse + "question") echo "有问题" ;; + "is_asking") echo "正在提问" ;; + # Default + "status_update") echo "状态更新" ;; + *) + # Fallback to English + case "$key" in + "task_complete") echo "Task Complete" ;; + "completed_the_task") echo "completed the task" ;; + "input_required") echo "Input Required" ;; + "needs_your_input") echo "needs your input" ;; + "subagent_started") echo "Subagent Started" ;; + "started_a_subagent") echo "started a subagent" ;; + "subagent_complete") echo "Subagent Complete" ;; + "subagent_completed") echo "subagent completed" ;; + "waiting_for_input") echo "Waiting for Input" ;; + "teammate_waiting") echo "teammate is waiting for input" ;; + "task_created") echo "Task Created" ;; + "team_task_created") echo "agent-team task was created" ;; + "team_task_complete") echo "Task Complete" ;; + "team_task_completed") echo "agent-team task completed" ;; + "error") echo "Error" ;; + "error_occurred") echo "An error occurred" ;; + "notifications_working") echo "Notifications are working!" ;; + "usage_alert") echo "Usage Alert" ;; + "usage_changed") echo "usage changed" ;; + "tokens_reset") echo "Tokens Reset" ;; + "tokens_have_reset") echo "tokens have reset. Usage is back to 100%." ;; + "question") echo "Question" ;; + "is_asking") echo "is asking a question" ;; + "status_update") echo "Status Update" ;; + *) echo "$key" ;; + esac + ;; + esac + ;; + *) + # English (default) + case "$key" in + "task_complete") echo "Task Complete" ;; + "completed_the_task") echo "completed the task" ;; + "input_required") echo "Input Required" ;; + "needs_your_input") echo "needs your input" ;; + "subagent_started") echo "Subagent Started" ;; + "started_a_subagent") echo "started a subagent" ;; + "subagent_complete") echo "Subagent Complete" ;; + "subagent_completed") echo "subagent completed" ;; + "waiting_for_input") echo "Waiting for Input" ;; + "teammate_waiting") echo "teammate is waiting for input" ;; + "task_created") echo "Task Created" ;; + "team_task_created") echo "agent-team task was created" ;; + "team_task_complete") echo "Task Complete" ;; + "team_task_completed") echo "agent-team task completed" ;; + "error") echo "Error" ;; + "error_occurred") echo "An error occurred" ;; + "notifications_working") echo "Notifications are working!" ;; + "usage_alert") echo "Usage Alert" ;; + "usage_changed") echo "usage changed" ;; + "tokens_reset") echo "Tokens Reset" ;; + "tokens_have_reset") echo "tokens have reset. Usage is back to 100%." ;; + "question") echo "Question" ;; + "is_asking") echo "is asking a question" ;; + "status_update") echo "Status Update" ;; + *) echo "$key" ;; + esac + ;; + esac +}