diff --git a/.github/workflows/i18n.yml b/.github/workflows/i18n.yml new file mode 100644 index 0000000..c854947 --- /dev/null +++ b/.github/workflows/i18n.yml @@ -0,0 +1,97 @@ +name: Update Translations + +on: + push: + paths: + - 'install.sh' + - 'fail2ban_manager.sh' + - 'file_manager.sh' + - 'translate.py' + branches: + - main + +jobs: + update-translations: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Restore translation cache + id: cache-translations + uses: actions/cache@v3 + with: + path: po/cache_*.json + key: ${{ runner.os }}-translations-${{ hashFiles('po/*.po') }} + restore-keys: | + ${{ runner.os }}-translations- + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y gettext python3 python3-pip + pip3 install googletrans-py + + - name: Setup directories + run: | + mkdir -p po + mkdir -p languages/{en,fa,ru,zh_CN}/LC_MESSAGES + + - name: Extract strings from all scripts + run: | + touch po/POTFILES.in + for script in install.sh auto_update.sh fail2ban_manager.sh file_manager.sh; do + echo "$script" >> po/POTFILES.in + done + + xgettext \ + --files-from=po/POTFILES.in \ + --from-code=UTF-8 \ + --language=Shell \ + --keyword=gettext \ + --package-name=xray_install \ + --package-version=1.0 \ + --msgid-bugs-address=https://github.com/hello-yunshu/Xray_bash_onekey/issues \ + --copyright-holder="yunshu" \ + --output=po/xray_install.pot + + - name: Update/Create PO files + run: | + for lang in zh_CN en fa ru; do + if [ ! -f po/$lang.po ]; then + msginit --no-translator --locale=$lang --input=po/xray_install.pot --output=po/$lang.po + else + msgmerge --update --backup=none po/$lang.po po/xray_install.pot + fi + done + + - name: Auto translate + run: python3 translate.py + + - name: Save translation cache + if: always() + uses: actions/cache/save@v3 + with: + path: po/cache_*.json + key: ${{ runner.os }}-translations-${{ hashFiles('po/*.po') }} + + - name: Compile MO files + run: | + for lang in zh_CN en fa ru; do + msgfmt -o languages/${lang}/LC_MESSAGES/xray_install.mo po/${lang}.po + done + + - name: Create version file + run: | + TIMESTAMP=$(date +%s) + for lang in zh_CN en fa ru; do + echo "$TIMESTAMP" > languages/${lang}/LC_MESSAGES/version + done + + - name: Commit changes + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add po/ languages/ + git commit -m "Update translations for all languages [$(date +%Y-%m-%d)]" || echo "No changes to commit" + git push \ No newline at end of file diff --git a/README.md b/README.md index e6f6bec..5b9c452 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ - # Xray 支持 Reality / VLESS WebSocket/gRPC+TLS 协议 + Nginx 的一键安装脚本 +[简体中文](README.md) | [English](languages/en/README.md) + [![GitHub stars](https://img.shields.io/github/stars/hello-yunshu/Xray_bash_onekey?color=%230885ce)](https://github.com/hello-yunshu/Xray_bash_onekey/stargazers) [![GitHub forks](https://img.shields.io/github/forks/hello-yunshu/Xray_bash_onekey?color=%230885ce)](https://github.com/hello-yunshu/Xray_bash_onekey/network) [![GitHub issues](https://img.shields.io/github/issues/hello-yunshu/Xray_bash_onekey)](https://github.com/hello-yunshu/Xray_bash_onekey/issues) -> 感谢 JetBrains 提供的非商业开源软件开发授权 > Thanks for non-commercial open source development authorization by JetBrains ## 使用说明 diff --git a/auto_update.sh b/auto_update.sh index accbfd5..96cc05b 100644 --- a/auto_update.sh +++ b/auto_update.sh @@ -2,8 +2,11 @@ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH +VERSION="1.0.0" + idleleo_dir="/etc/idleleo" -nginx_dir="/etc/nginx" +local_bin="/usr/local" +nginx_dir="${local_bin}/nginx" xray_conf_dir="${idleleo_conf_dir}/xray" xray_conf="${xray_conf_dir}/config.json" log_dir="${idleleo_dir}/logs" @@ -15,18 +18,18 @@ info_extraction_all=$(jq -rc . ${xray_qr_config_file}) [[ ! -d "${log_dir}" ]] && mkdir -p ${log_dir} if [[ -f "${running_file}" ]]; then - echo "上个自动更新程序仍在运行! 检查于: $(date '+%Y-%m-%d %H:%M') 建议手动排错!" >>${log_file} + echo "Previous auto update process is still running! Checked at: $(date '+%Y-%m-%d %H:%M') Manual troubleshooting recommended!" >>${log_file} exit 1 else touch ${running_file} fi [[ -f "${log_file}" ]] && rm -rf ${log_file} -echo "更新时间: $(date '+%Y-%m-%d %H:%M')" >${log_file} +echo "Update time: $(date '+%Y-%m-%d %H:%M')" >${log_file} check_online_version() { echo ${get_versions_all} | jq -rc ".$1" - [[ 0 -ne $? ]] && echo "在线版本检测失败, 请稍后再试!" >>${log_file} && exit 1 + [[ 0 -ne $? ]] && echo "Online version check failed, please try again later!" >>${log_file} && exit 1 } info_extraction() { @@ -34,42 +37,68 @@ info_extraction() { } shell_online_version="$(check_online_version shell_online_version)" -xray_online_version="$(check_online_version xray_tested_version)" -nginx_online_version="$(check_online_version nginx_online_version)" -openssl_online_version="$(check_online_version openssl_online_version)" -jemalloc_online_version="$(check_online_version jemalloc_tested_version)" +xray_online_version="$(check_online_version xray_online_version)" +nginx_online_version="$(check_online_version nginx_build_version)" if [[ -f ${xray_qr_config_file} ]]; then if [[ $(info_extraction shell_version) == null ]] || [[ $(info_extraction shell_version) != ${shell_online_version} ]]; then bash idleleo -u auto_update - [[ 0 -ne $? ]] && echo "脚本 更新失败!" >>${log_file} && exit 1 - echo "脚本 更新成功!" >>${log_file} + [[ 0 -ne $? ]] && echo "Script update failed!" >>${log_file} && exit 1 + echo "Script updated successfully!" >>${log_file} add_shell_version=$(jq -r ". += {\"shell_version\": \"${shell_online_version}\"}" ${xray_qr_config_file}) echo "${add_shell_version}" | jq . >${xray_qr_config_file} else - echo "脚本 最新版!" >>${log_file} + echo "Script is up to date!" >>${log_file} fi - if [[ $(info_extraction nginx_version) == null ]] || [[ ! -f "${nginx_dir}/sbin/nginx" ]]; then - echo "Nginx 未安装!" - elif [[ ${nginx_online_version} != $(info_extraction nginx_version) ]] || [[ ${openssl_online_version} != $(info_extraction openssl_version) ]] || [[ ${jemalloc_online_version} != $(info_extraction jemalloc_version) ]]; then + if [[ $(info_extraction nginx_build_version) == null ]] || [[ ! -f "${nginx_dir}/sbin/nginx" ]]; then + echo "Nginx not installed!" + elif [[ ${nginx_online_version} != $(info_extraction nginx_build_version) ]]; then bash idleleo -n auto_update - [[ 0 -ne $? ]] && echo "Nginx 更新失败!" >>${log_file} && exit 1 - echo "Nginx 更新成功!" >>${log_file} + [[ 0 -ne $? ]] && echo "Nginx update failed!" >>${log_file} && exit 1 + echo "Nginx updated successfully!" >>${log_file} else - echo "Nginx 最新版!" >>${log_file} + echo "Nginx is up to date!" >>${log_file} fi if [[ -f ${xray_qr_config_file} ]] && [[ -f ${xray_conf} ]] && [[ -f /usr/local/bin/xray ]]; then if [[ $(info_extraction xray_version) == null ]]; then - echo "Xray 版本未知 无法自动更新" >>${log_file} + echo "Xray version unknown, cannot auto update" >>${log_file} elif [[ ${xray_online_version} != $(info_extraction xray_version) ]]; then bash idleleo -x auto_update - [[ 0 -ne $? ]] && echo "Xray 更新失败!" >>${log_file} && exit 1 - echo "Xray 更新成功!" >>${log_file} + [[ 0 -ne $? ]] && echo "Xray update failed!" >>${log_file} && exit 1 + echo "Xray updated successfully!" >>${log_file} elif [[ ${xray_online_version} == $(info_extraction xray_version) ]]; then - echo "Xray 最新版!" >>${log_file} + echo "Xray is up to date!" >>${log_file} fi else - echo "Xray 未安装!" >>${log_file} + echo "Xray not installed!" >>${log_file} fi fi rm -rf ${running_file} + +check_update() { + temp_file="/tmp/temp_script.sh" + if ! curl -s -o "$temp_file" "https://github.com/hello-yunshu/Xray_bash_onekey/raw/refs/heads/main/auto_update.sh"; then + echo "Failed to download remote script" >>${log_file} + return 1 + } + + remote_version=$(grep "^VERSION=" "$temp_file" | cut -d'"' -f2) + if [ -z "$remote_version" ]; then + echo "Unable to get remote version number" >>${log_file} + return 1 + } + + if [ "$VERSION" != "$remote_version" ]; then + echo "New version found: $remote_version" >>${log_file} + cp "$temp_file" "$0" + chmod +x "$0" + rm -f "$temp_file" + exec "$0" "$@" + fi + + rm -f "$temp_file" + return 0 +} + + +check_update \ No newline at end of file diff --git a/fail2ban_manager.sh b/fail2ban_manager.sh index 4c02244..45d12bc 100644 --- a/fail2ban_manager.sh +++ b/fail2ban_manager.sh @@ -1,19 +1,19 @@ #!/bin/bash # 定义当前版本号 -mf_SCRIPT_VERSION="1.0.8" +mf_SCRIPT_VERSION="1.0.9" mf_main_menu() { check_system echo -e "\n" - log_echo "${GreenBG} 设置 Fail2ban 用于防止暴力破解, 请选择: ${Font}" - log_echo "1. ${Green}安装 Fail2ban${Font}" - log_echo "2. ${Green}管理 Fail2ban${Font}" - log_echo "3. ${Green}卸载 Fail2ban${Font}" - log_echo "4. ${Green}查看 Fail2ban 状态${Font}" - log_echo "5. ${Green}退出${Font}" - read -rp "请输入: " fail2ban_fq + log_echo "${GreenBG} $(gettext "设置 Fail2ban 用于防止暴力破解, 请选择:") ${Font}" + log_echo "1. ${Green}$(gettext "安装") Fail2ban${Font}" + log_echo "2. ${Green}$(gettext "管理") Fail2ban${Font}" + log_echo "3. ${Green}$(gettext "卸载") Fail2ban${Font}" + log_echo "4. ${Green}$(gettext "查看") Fail2ban $(gettext "状态")${Font}" + log_echo "5. ${Green}$(gettext "退出")${Font}" + read -rp "$(gettext "请输入:")" fail2ban_fq [[ -z "${fail2ban_fq}" ]] && fail2ban_fq=1 case $fail2ban_fq in @@ -24,18 +24,18 @@ mf_main_menu() { 5) source "${idleleo}" ;; *) echo -e "\n" - log_echo "${Error} ${RedBG} 无效的选择 请重试 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "无效的选择 请重试") ${Font}" ;; esac } mf_install_fail2ban() { if command -v fail2ban-client &> /dev/null; then - log_echo "${OK} ${Green} Fail2ban 已经安装, 跳过安装步骤 ${Font}" + log_echo "${OK} ${Green} $(gettext "Fail2ban 已经安装, 跳过安装步骤") ${Font}" else pkg_install "fail2ban" mf_configure_fail2ban - judge "Fail2ban 安装" + judge "Fail2ban $(gettext "安装")" source "${idleleo}" fi } @@ -49,7 +49,7 @@ mf_configure_fail2ban() { # 检查 Nginx 是否安装 if [[ ${tls_mode} == "TLS" || ${reality_add_nginx} == "on" ]]; then if [[ ! -f "${nginx_dir}/sbin/nginx" ]]; then - log_echo "${Warning} ${YellowBG} Nginx 未安装, 请先安装 Nginx ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "Nginx 未安装, 请先安装 Nginx") ${Font}" return fi fi @@ -73,7 +73,7 @@ mf_configure_fail2ban() { fi systemctl daemon-reload systemctl restart fail2ban - judge "Fail2ban 配置" + judge "Fail2ban $(gettext "配置")" } mf_create_nginx_no_host_filter() { @@ -89,18 +89,18 @@ EOF mf_manage_fail2ban() { if ! command -v fail2ban-client &> /dev/null; then - log_echo "${Error} ${RedBG} Fail2ban 未安装, 请先安装 Fail2ban ${Font}" + log_echo "${Error} ${RedBG} $(gettext "Fail2ban 未安装, 请先安装 Fail2ban") ${Font}" return fi echo -e "\n" - log_echo "${Green} 请选择 Fail2ban 操作: ${Font}" - echo "1. 启动 Fail2ban" - echo "2. 重启 Fail2ban" - echo "3. 停止 Fail2ban" - echo "4. 添加自定义规则" - echo "5. 返回" - read_optimize "请输入: " mf_action 1 + log_echo "${Green} $(gettext "请选择 Fail2ban 操作:") ${Font}" + echo "1. $(gettext "启动") Fail2ban" + echo "2. $(gettext "重启") Fail2ban" + echo "3. $(gettext "停止") Fail2ban" + echo "4. $(gettext "添加自定义规则")" + echo "5. $(gettext "返回")" + read_optimize "$(gettext "请输入:")" mf_action 1 case $mf_action in 1) mf_start_enable_fail2ban @@ -119,7 +119,7 @@ mf_manage_fail2ban() { 5) mf_main_menu ;; *) echo -e "\n" - log_echo "${Error} ${RedBG} 无效的选择 请重试 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "无效的选择 请重试") ${Font}" mf_manage_fail2ban ;; esac @@ -132,31 +132,31 @@ mf_add_custom_rule() { local max_retry local ban_time - read_optimize "请输入新的 Jail 名称: " "jail_name" NULL - read_optimize "请输入 Filter 名称: " "filter_name" NULL - read_optimize "请输入日志路径: " "log_path" NULL - read_optimize "请输入最大重试次数 (默认 5): " "max_retry" 5 1 99 "最大重试次数必须在 1 到 99 之间" - read_optimize "请输入封禁时间 (秒, 默认 604800 秒): " "ban_time" 604800 1 8640000 "封禁时间必须在 1 到 8640000 秒之间" + read_optimize "$(gettext "请输入新的 Jail 名称:")" "jail_name" NULL + read_optimize "$(gettext "请输入 Filter 名称:")" "filter_name" NULL + read_optimize "$(gettext "请输入日志路径:")" "log_path" NULL + read_optimize "$(gettext "请输入最大重试次数 (默认 5):")" "max_retry" 5 1 99 "$(gettext "最大重试次数必须在 1 到 99 之间")" + read_optimize "$(gettext "请输入封禁时间 (秒, 默认 604800 秒):")" "ban_time" 604800 1 8640000 "$(gettext "封禁时间必须在 1 到 8640000 秒之间")" if grep -q "\[$jail_name\]" /etc/fail2ban/jail.local; then - log_echo "${Warning} ${YellowBG} Jail '$jail_name' 已存在 ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "Jail") '$jail_name' $(gettext "已存在") ${Font}" return fi echo -e "[$jail_name]\nenabled = true\nfilter = $filter_name\nlogpath = $log_path\nmaxretry = $max_retry\nbantime = $ban_time\n" >> /etc/fail2ban/jail.local - log_echo "${OK} ${GreenBG} 自定义规则添加成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "自定义规则添加成功") ${Font}" systemctl daemon-reload systemctl restart fail2ban - judge "Fail2ban 重启以应用新规则" + judge "Fail2ban $(gettext "重启以应用新规则")" } mf_start_enable_fail2ban() { systemctl daemon-reload systemctl start fail2ban systemctl enable fail2ban - judge "Fail2ban 启动" - timeout "清空屏幕!" + judge "Fail2ban $(gettext "启动")" + timeout "$(gettext "清空屏幕!")" clear } @@ -168,8 +168,8 @@ mf_uninstall_fail2ban() { if [[ -f "/etc/fail2ban/filter.d/nginx-no-host.conf" ]]; then rm -rf /etc/fail2ban/filter.d/nginx-no-host.conf fi - judge "Fail2ban 卸载" - timeout "清空屏幕!" + judge "Fail2ban $(gettext "卸载")" + timeout "$(gettext "清空屏幕!")" clear source "${idleleo}" } @@ -177,39 +177,39 @@ mf_uninstall_fail2ban() { mf_stop_disable_fail2ban() { systemctl stop fail2ban systemctl disable fail2ban - log_echo "${OK} ${GreenBG} Fail2ban 停止成功 ${Font}" - timeout "清空屏幕!" + log_echo "${OK} ${GreenBG} $(gettext "Fail2ban 停止成功") ${Font}" + timeout "$(gettext "清空屏幕!")" clear } mf_restart_fail2ban() { systemctl daemon-reload systemctl restart fail2ban - judge "Fail2ban 重启" - timeout "清空屏幕!" + judge "Fail2ban $(gettext "重启")" + timeout "$(gettext "清空屏幕!")" clear } mf_display_fail2ban_status() { if ! command -v fail2ban-client &> /dev/null; then - log_echo "${Error} ${RedBG} Fail2ban 未安装, 请先安装 Fail2ban ${Font}" + log_echo "${Error} ${RedBG} $(gettext "Fail2ban 未安装, 请先安装 Fail2ban") ${Font}" return fi - log_echo "${GreenBG} Fail2ban 总体状态: ${Font}" + log_echo "${GreenBG} $(gettext "Fail2ban 总体状态:") ${Font}" fail2ban-client status echo -e "\n" - log_echo "${Green} 默认启用的 Jail 状态: ${Font}" + log_echo "${Green} $(gettext "默认启用的 Jail 状态:") ${Font}" echo "----------------------------------------" - log_echo "${Green} SSH 封锁情况: ${Font}" + log_echo "${Green} $(gettext "SSH 封锁情况:") ${Font}" fail2ban-client status sshd if [[ ${tls_mode} == "TLS" || ${reality_add_nginx} == "on" ]]; then - log_echo "${Green} Fail2ban Nginx 封锁情况: ${Font}" + log_echo "${Green} $(gettext "Fail2ban Nginx 封锁情况:") ${Font}" fail2ban-client status nginx-badbots fail2ban-client status nginx-botsearch if [[ ${reality_add_nginx} == "on" ]]; then - log_echo "${Green} Fail2ban Nginx No Host 封锁情况: ${Font}" + log_echo "${Green} $(gettext "Fail2ban Nginx No Host 封锁情况:") ${Font}" fail2ban-client status nginx-no-host fi fi @@ -223,31 +223,31 @@ mf_check_for_updates() { # 直接使用 curl 下载远程版本信息 latest_version=$(curl -s "$mf_remote_url" | grep 'mf_SCRIPT_VERSION=' | head -n 1 | sed 's/mf_SCRIPT_VERSION="//; s/"//') if [ -n "$latest_version" ] && [ "$latest_version" != "$mf_SCRIPT_VERSION" ]; then - log_echo "${Warning} ${YellowBG} 新版本可用: $latest_version 当前版本: $mf_SCRIPT_VERSION ${Font}" - log_echo "${Warning} ${YellowBG} 请访问 https://github.com/hello-yunshu/Xray_bash_onekey 查看更新说明 ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "新版本可用:") $latest_version $(gettext "当前版本:") $mf_SCRIPT_VERSION ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请访问 https://github.com/hello-yunshu/Xray_bash_onekey 查看更新说明") ${Font}" - log_echo "${GreenBG} 是否要下载并安装新版本 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否要下载并安装新版本") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r update_choice case $update_choice in [yY][eE][sS] | [yY]) - log_echo "${Info} ${Green} 正在下载新版本... ${Font}" + log_echo "${Info} ${Green} $(gettext "正在下载新版本...") ${Font}" curl -sL "$mf_remote_url" -o "${idleleo_dir}/fail2ban_manager.sh" if [ $? -eq 0 ]; then chmod +x "${idleleo_dir}/fail2ban_manager.sh" - log_echo "${OK} ${Green} 下载完成,正在重新运行脚本... ${Font}" + log_echo "${OK} ${Green} $(gettext "下载完成,正在重新运行脚本...") ${Font}" bash "${idleleo}" --set-fail2ban else echo -e "\n" - log_echo "${Error} ${RedBG} 下载失败,请手动下载并安装新版本 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "下载失败,请手动下载并安装新版本") ${Font}" fi ;; *) - log_echo "${OK} ${Green} 跳过更新 ${Font}" + log_echo "${OK} ${Green} $(gettext "跳过更新") ${Font}" ;; esac else - log_echo "${OK} ${Green} 当前已经是最新版本: $mf_SCRIPT_VERSION ${Font}" + log_echo "${OK} ${Green} $(gettext "当前已经是最新版本:") $mf_SCRIPT_VERSION ${Font}" fi } diff --git a/file_manager.sh b/file_manager.sh index 8c52305..3eb4cdb 100644 --- a/file_manager.sh +++ b/file_manager.sh @@ -1,11 +1,11 @@ #!/bin/bash # 定义当前版本号 -fm_SCRIPT_VERSION="1.0.8" +fm_SCRIPT_VERSION="1.0.9" # 检查是否提供了扩展名参数 if [ -z "$1" ]; then - echo "用法: $0 <文件扩展名> [<目录路径>]" + echo "$(gettext "用法:")" $0 $(gettext "<文件扩展名> [<目录路径>]") exit 1 fi @@ -15,7 +15,7 @@ fm_WORKDIR="${2:-$(pwd)}" # 检查目录是否存在 if [ ! -d "$fm_WORKDIR" ]; then echo -e "\n" - log_echo "${Error} ${RedBG} 目录 $fm_WORKDIR 不存在 请检查路径 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "目录") $fm_WORKDIR $(gettext "不存在 请检查路径") ${Font}" exit 1 fi @@ -28,7 +28,7 @@ cd "$fm_WORKDIR" # 函数: 列出当前目录下所有指定扩展名的文件 fm_list_files() { local max_length - log_echo "${GreenBG} 列出所有 .$fm_EXTENSION 文件 ${Font}" + log_echo "${GreenBG} $(gettext "列出所有") .$fm_EXTENSION $(gettext "文件") ${Font}" # 设置 dotglob 选项,使通配符 * 包括以点开头的文件 shopt -s dotglob @@ -37,7 +37,7 @@ fm_list_files() { files=(*.$fm_EXTENSION) if [ ${#files[@]} -eq 0 ]; then - log_echo "${Warning} ${YellowBG} 没有找到 .$fm_EXTENSION 文件 ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "没有找到") .$fm_EXTENSION $(gettext "文件") ${Font}" return 1 else # 计算最大文件名长度 @@ -61,13 +61,13 @@ fm_list_files() { printf "%-${total_width}s\n" "$(printf '%*s' "$total_width" | tr ' ' '-')" # 居中文本 - local header_text="文件名" + local header_text="$(gettext "文件名")" local header_length=${#header_text} local padding=$(( (total_width - header_length - 4) / 2 )) local left_padding=$(( padding - 4 )) # 加上序号列的宽度 local right_padding=$(( padding - 4 )) - printf "| %-4s | %-${left_padding}s%-${header_length}s%-${right_padding}s |\n" "序号" "" "$header_text" "" + printf "| %-4s | %-${left_padding}s%-${header_length}s%-${right_padding}s |\n" "$(gettext "序号")" "" "$header_text" "" printf "%-${total_width}s\n" "$(printf '%*s' "$total_width" | tr ' ' '-')" @@ -90,16 +90,16 @@ fm_create_servername_file() { local url fm_list_files echo -e "\n" - log_echo "${Green} 请输入网址 (例如 hey.run)" - log_echo "${Green} 不要包含 http:// 或 https:// 开头 ${Font}" - read_optimize "请输入: " url + log_echo "${Green} $(gettext "请输入网址 (例如 hey.run)")" + log_echo "${Green} $(gettext "不要包含 http:// 或 https:// 开头") ${Font}" + read_optimize "$(gettext "请输入:")" url if [[ $url =~ ^(http|https):// ]]; then echo -e "\n" - log_echo "${Error} ${RedBG} 网址不能包含 http:// 或 https:// 开头 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "网址不能包含 http:// 或 https:// 开头") ${Font}" return fi echo "${url} reality;" > "${url}.serverNames" - log_echo "${OK} ${GreenBG} 文件 ${url}.serverNames 已创建 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "文件") ${url}.serverNames $(gettext "已创建") ${Font}" fm_restart_nginx_and_check_status fm_list_files } @@ -108,17 +108,17 @@ fm_create_servername_file() { fm_create_ws_or_grpc_server_file() { local host port weight content firewall_set_fq fm_list_files - read_optimize "请输入主机 (host): " host - read_optimize "请输入端口 (port): " port "" 1 65535 - read_optimize "请输入权重 (0~100 默认值 50): " weight "50" 0 100 + read_optimize "$(gettext "请输入主机 (host):")" host + read_optimize "$(gettext "请输入端口 (port):")" port "" 1 65535 + read_optimize "$(gettext "请输入权重 (0~100 默认值 50):")" weight "50" 0 100 content="server ${host}:${port} weight=${weight} max_fails=2 fail_timeout=10;" echo "$content" > "${host}.${fm_EXTENSION}" - log_echo "${OK} ${GreenBG} 文件 ${host}.${fm_EXTENSION} 已创建 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "文件") ${host}.${fm_EXTENSION} $(gettext "已创建") ${Font}" # 询问是否需要修改防火墙 echo -e "\n" - log_echo "${GreenBG} 是否需要设置防火墙 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要设置防火墙") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r firewall_set_fq case $firewall_set_fq in [yY][eE][sS] | [yY]) @@ -132,19 +132,19 @@ fm_create_ws_or_grpc_server_file() { iptables -I INPUT -p udp --dport ${port} -j ACCEPT iptables -I OUTPUT -p tcp --sport ${port} -j ACCEPT iptables -I OUTPUT -p udp --sport ${port} -j ACCEPT - log_echo "${OK} ${GreenBG} 防火墙 追加 完成 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "防火墙 追加 完成") ${Font}" if [[ "${ID}" == "centos" && ${VERSION_ID} -ge 7 ]]; then service iptables save service iptables restart - log_echo "${OK} ${GreenBG} 防火墙 重启 完成 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "防火墙 重启 完成") ${Font}" else netfilter-persistent save systemctl restart iptables - log_echo "${OK} ${GreenBG} 防火墙 重启 完成 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "防火墙 重启 完成") ${Font}" fi ;; *) - log_echo "${OK} ${GreenBG} 跳过防火墙设置 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "跳过防火墙设置") ${Font}" ;; esac fm_restart_nginx_and_check_status @@ -156,17 +156,17 @@ fm_edit_file() { fm_list_files local num_files=${#files[@]} local choice - read_optimize "请输入要编辑的文件编号 (1-$num_files): " choice "" 1 "$num_files" + read_optimize "$(gettext "请输入要编辑的文件编号") (1-$num_files): " choice "" 1 "$num_files" local filename="${files[$((choice - 1))]}" # 检查 vim 是否安装 if ! command -v vim &> /dev/null; then - log_echo "${Warning} ${YellowBG} vim 未安装 正在尝试安装 ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "vim 未安装 正在尝试安装") ${Font}" pkg_install vim fi vim "$filename" - log_echo "${OK} ${GreenBG} 文件 $filename 已编辑 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "文件") $filename $(gettext "已编辑") ${Font}" fm_restart_nginx_and_check_status } @@ -178,12 +178,12 @@ fm_delete_file() { local num_files=${#files[@]} local choice - read_optimize "请输入要删除的文件编号 (1-$num_files): " choice "" 1 "$num_files" + read_optimize "$(gettext "请输入要删除的文件编号") (1-$num_files): " choice "" 1 "$num_files" local filename="${files[$((choice - 1))]}" rm "$filename" - log_echo "${OK} ${GreenBG} 文件 $filename 已删除 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "文件") $filename $(gettext "已删除") ${Font}" fm_restart_nginx_and_check_status fm_list_files } @@ -199,7 +199,7 @@ fm_create_file() { ;; *) echo -e "\n" - log_echo "${Error} ${RedBG} 不支持的文件扩展名 $fm_EXTENSION ${Font}" + log_echo "${Error} ${RedBG} $(gettext "不支持的文件扩展名") $fm_EXTENSION ${Font}" ;; esac } @@ -209,14 +209,14 @@ fm_main_menu() { fm_list_files while true; do echo - log_echo "${GreenBG} 主菜单 ${Font}" - log_echo "1 ${Green}列出所有 $fm_EXTENSION 文件${Font}" - log_echo "2 ${Green}创建一个新的 $fm_EXTENSION 文件${Font}" - log_echo "3 ${Green}编辑一个已存在的 $fm_EXTENSION 文件${Font}" - log_echo "4 ${Green}删除一个已存在的 $fm_EXTENSION 文件${Font}" - log_echo "5 ${Green}退出${Font}" + log_echo "${GreenBG} $(gettext "主菜单") ${Font}" + log_echo "1 ${Green}$(gettext "列出所有") $fm_EXTENSION $(gettext "文件")${Font}" + log_echo "2 ${Green}$(gettext "创建一个新的") $fm_EXTENSION $(gettext "文件")${Font}" + log_echo "3 ${Green}$(gettext "编辑一个已存在的") $fm_EXTENSION $(gettext "文件")${Font}" + log_echo "4 ${Green}$(gettext "删除一个已存在的") $fm_EXTENSION $(gettext "文件")${Font}" + log_echo "5 ${Green}$(gettext "退出")${Font}" local choice - read_optimize "请选择一个选项: " choice "" 1 5 + read_optimize "$(gettext "请选择一个选项:")" choice "" 1 5 case $choice in 1) fm_list_files ;; @@ -226,7 +226,7 @@ fm_main_menu() { 5) source "$idleleo" ;; *) echo -e "\n" - log_echo "${Error} ${RedBG} 无效选项 请重试 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "无效选项 请重试") ${Font}" ;; esac done @@ -239,31 +239,31 @@ fm_check_for_updates() { # 直接使用 curl 下载远程版本信息 latest_version=$(curl -s "$fm_remote_url" | grep 'fm_SCRIPT_VERSION=' | head -n 1 | sed 's/fm_SCRIPT_VERSION="//; s/"//') if [ -n "$latest_version" ] && [ "$latest_version" != "$fm_SCRIPT_VERSION" ]; then - log_echo "${Warning} ${YellowBG} 新版本可用: $latest_version 当前版本: $fm_SCRIPT_VERSION ${Font}" - log_echo "${Warning} ${YellowBG} 请访问 https://github.com/hello-yunshu/Xray_bash_onekey 查看更新说明 ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "新版本可用:") $latest_version $(gettext "当前版本:") $fm_SCRIPT_VERSION ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请访问 https://github.com/hello-yunshu/Xray_bash_onekey 查看更新说明") ${Font}" - log_echo "${GreenBG} 是否要下载并安装新版本 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否要下载并安装新版本") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r update_choice case $update_choice in [yY][eE][sS] | [yY]) - log_echo "${Info} ${Green} 正在下载新版本... ${Font}" + log_echo "${Info} ${Green} $(gettext "正在下载新版本...") ${Font}" curl -sL "$fm_remote_url" -o "${idleleo_dir}/file_manager.sh" if [ $? -eq 0 ]; then chmod +x "${idleleo_dir}/file_manager.sh" - log_echo "${OK} ${Green} 下载完成,正在重新运行脚本... ${Font}" + log_echo "${OK} ${Green} $(gettext "下载完成,正在重新运行脚本...") ${Font}" bash "${idleleo}" --add-servernames else echo -e "\n" - log_echo "${Error} ${RedBG} 下载失败,请手动下载并安装新版本 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "下载失败,请手动下载并安装新版本") ${Font}" fi ;; *) - log_echo "${OK} ${Green} 跳过更新 ${Font}" + log_echo "${OK} ${Green} $(gettext "跳过更新") ${Font}" ;; esac else - log_echo "${OK} ${Green} 当前已经是最新版本: $fm_SCRIPT_VERSION ${Font}" + log_echo "${OK} ${Green} $(gettext "当前已经是最新版本:") $fm_SCRIPT_VERSION ${Font}" fi } @@ -272,10 +272,10 @@ fm_restart_nginx_and_check_status() { systemctl restart nginx if systemctl is-active --quiet nginx; then echo -e "\n" - log_echo "${OK} ${GreenBG} Nginx 重启成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "Nginx 重启成功") ${Font}" else echo -e "\n" - log_echo "${Error} ${RedBG} Nginx 重启失败 请检查配置文件是否有误 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "Nginx 重启失败 请检查配置文件是否有误") ${Font}" fm_edit_file fi fi diff --git a/install.sh b/install.sh index 345958b..333bbdc 100644 --- a/install.sh +++ b/install.sh @@ -32,13 +32,13 @@ YellowBG="\033[43;30m" Font="\033[0m" #notification information -Info="${Green}[提醒]${Font}" +Info="${Green}[$(gettext "提醒")]${Font}" OK="${Green}[OK]${Font}" -Error="${RedW}[错误]${Font}" -Warning="${RedW}[警告]${Font}" +Error="${RedW}[$(gettext "错误")]${Font}" +Warning="${RedW}[$(gettext "警告")]${Font}" shell_version="2.2.10" -shell_mode="未安装" +shell_mode="$(gettext "未安装")" tls_mode="None" ws_grpc_mode="None" local_bin="/usr/local" @@ -96,11 +96,19 @@ log_rotate() { local timestamp=$(date +%Y%m%d%H%M%S) local archived_log="${LOG_FILE}.${timestamp}.gz" - gzip -c "$LOG_FILE" > "$archived_log" + # 添加 gzip 错误处理 + if ! gzip -c "$LOG_FILE" > "$archived_log"; then + log_echo "${Error} ${RedBG} $(gettext "日志文件归档失败") ${Font}" + return 1 + fi - :> "$LOG_FILE" + # 添加清空日志文件的错误处理 + if ! :> "$LOG_FILE"; then + log_echo "${Error} ${RedBG} $(gettext "清空日志文件失败") ${Font}" + return 1 + fi - log "Log file rotated and archived as $archived_log" + log "$(gettext "日志文件已轮转并归档为") $archived_log" rotate_archives } @@ -116,7 +124,7 @@ rotate_archives() { log_echo() { local message=$(printf "%b" "$@") - echo "$message" + echo -e "$message" log "$message" } @@ -129,15 +137,15 @@ VERSION=$(echo "${VERSION}" | awk -F "[()]" '{print $2}') check_system() { if [[ "${ID}" == "centos" && ${VERSION_ID} -ge 7 ]]; then - log_echo "${OK} ${GreenBG} 当前系统为 Centos ${VERSION_ID} ${VERSION} ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "当前系统为") Centos ${VERSION_ID} ${VERSION} ${Font}" INS="yum" [[ ! -f "${xray_qr_config_file}" ]] && $INS update || true elif [[ "${ID}" == "debian" && ${VERSION_ID} -ge 8 ]]; then - log_echo "${OK} ${GreenBG} 当前系统为 Debian ${VERSION_ID} ${VERSION} ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "当前系统为") Debian ${VERSION_ID} ${VERSION} ${Font}" INS="apt" [[ ! -f "${xray_qr_config_file}" ]] && $INS update || true elif [[ "${ID}" == "ubuntu" && $(echo "${VERSION_ID}" | cut -d '.' -f1) -ge 16 ]]; then - log_echo "${OK} ${GreenBG} 当前系统为 Ubuntu ${VERSION_ID} ${UBUNTU_CODENAME} ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "当前系统为") Ubuntu ${VERSION_ID} ${UBUNTU_CODENAME} ${Font}" INS="apt" if [[ ! -f "${xray_qr_config_file}" ]]; then rm /var/lib/dpkg/lock || true @@ -147,16 +155,16 @@ check_system() { $INS update || true fi else - log_echo "${Error} ${RedBG} 当前系统为 ${ID} ${VERSION_ID} 不在支持的系统列表内, 安装中断! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "当前系统为") ${ID} ${VERSION_ID} $(gettext "不在支持的系统列表内, 安装中断!") ${Font}" exit 1 fi } is_root() { if [[ 0 == $UID ]]; then - log_echo "${OK} ${GreenBG} 当前用户是 root用户, 进入安装流程 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "当前用户是 root用户, 进入安装流程") ${Font}" else - log_echo "${Error} ${RedBG} 当前用户不是 root用户, 请切换到 root用户 后重新执行脚本! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "当前用户不是 root用户, 请切换到 root用户 后重新执行脚本!") ${Font}" exit 1 fi } @@ -171,19 +179,138 @@ check_and_create_user_group() { fi } +check_language_update() { + local lang_code="$1" + local local_file="${idleleo_dir}/languages/${lang_code}/LC_MESSAGES/xray_install.mo" + local github_url="https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/languages" + + # 如果本地文件不存在,直接返回需要更新 + [[ ! -f "${local_file}" ]] && return 0 + + # 获取远程文件的最后修改时间 + local remote_date + remote_date=$(curl -sI "${github_url}/${lang_code}/LC_MESSAGES/xray_install.mo" | grep -i "last-modified" | cut -d' ' -f2-) + + if [ -z "$remote_date" ]; then + log_echo "${Warning} ${YellowBG} $(gettext "无法获取远程语言文件信息") ${Font}" + return 1 + fi + + # 转换为时间戳进行比较 + local remote_timestamp=$(date -d "$remote_date" +%s) + local local_timestamp=$(stat -c %Y "$local_file") + + # 如果远程文件较新,返回需要更新 + [ "$remote_timestamp" -gt "$local_timestamp" ] +} + +update_language_file() { + local lang_code="$1" + local mo_file="${idleleo_dir}/languages/${lang_code}/LC_MESSAGES/xray_install.mo" + local github_url="https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/languages" + + mkdir -p "${idleleo_dir}/languages/${lang_code}/LC_MESSAGES" + + log_echo "${Info} ${Blue} $(gettext "正在更新语言文件...") ${Font}" + + if ! curl -s -o "${mo_file}" "${github_url}/${lang_code}/LC_MESSAGES/xray_install.mo"; then + log_echo "${Error} ${RedBG} $(gettext "语言文件更新失败") ${Font}" + return 1 + fi + + if [ ! -s "${mo_file}" ]; then + log_echo "${Error} ${RedBG} $(gettext "语言文件无效") ${Font}" + rm -f "${mo_file}" + return 1 + fi + + log_echo "${OK} ${Green} $(gettext "语言文件更新完成") ${Font}" +} + +init_language() { + if ! command -v gettext >/dev/null 2>&1; then + log_echo "${Warning} ${YellowBG} $(gettext "正在安装 gettext...") ${Font}" + ${INS} gettext + if [ $? -ne 0 ]; then + log_echo "${Error} ${RedBG} $(gettext "gettext 安装失败,将使用默认语言") ${Font}" + export LANG=zh_CN.UTF-8 + return 1 + fi + fi + + local gettext_paths=( + "/usr/share/gettext/gettext.sh" + "/usr/bin/gettext.sh" + "/usr/share/gettext-"*/gettext.sh + ) + + local gettext_sh="" + for path in "${gettext_paths[@]}"; do + if [ -f "$path" ]; then + gettext_sh="$path" + break + fi + done + + if [ -z "$gettext_sh" ]; then + log_echo "${Error} ${RedBG} $(gettext "未找到 gettext.sh,将使用默认语言") ${Font}" + export LANG=zh_CN.UTF-8 + return 1 + fi + + mkdir -p "${idleleo_dir}/languages" + export TEXTDOMAIN="xray_install" + export TEXTDOMAINDIR="${idleleo_dir}/languages" + . "$gettext_sh" + + if [ -f "${idleleo_dir}/language.conf" ]; then + source "${idleleo_dir}/language.conf" + + if [[ "${LANG%.*}" != "zh_CN" ]]; then + local lang_code + case "${LANG%.*}" in + "en_US") lang_code="en" ;; + "fa_IR") lang_code="fa" ;; + "ru_RU") lang_code="ru" ;; + *) + log_echo "${Warning} ${YellowBG} $(gettext "不支持的语言:")${LANG%.*}$(gettext ",将使用默认语言") ${Font}" + export LANG=zh_CN.UTF-8 + return 0 + ;; + esac + + local lang_file="${TEXTDOMAINDIR}/${lang_code}/LC_MESSAGES/${TEXTDOMAIN}.mo" + if [ ! -f "$lang_file" ]; then + if ! update_language_file "$lang_code"; then + log_echo "${Warning} ${YellowBG} $(gettext "语言文件更新失败,将使用默认语言") ${Font}" + export LANG=zh_CN.UTF-8 + return 0 + fi + elif check_language_update "$lang_code"; then + log_echo "${Info} ${Blue} $(gettext "发现语言文件更新") ${Font}" + if update_language_file "$lang_code"; then + . "$gettext_sh" + fi + fi + fi + else + export LANG=zh_CN.UTF-8 + fi +} + judge() { if [[ 0 -eq $? ]]; then - log_echo "${OK} ${GreenBG} $1 完成 ${Font}" + log_echo "${OK} ${GreenBG} $1 $(gettext "完成") ${Font}" sleep 0.5 else - log_echo "${Error} ${RedBG} $1 失败 ${Font}" + log_echo "${Error} ${RedBG} $1 $(gettext "失败") ${Font}" exit 1 fi } check_version() { echo ${get_versions_all} | jq -rc ".$1" - [[ 0 -ne $? ]] && log_echo "${Error} ${RedBG} 在线版本检测失败, 请稍后再试! ${Font}" && exit 1 + [[ 0 -ne $? ]] && log_echo "${Error} ${RedBG} $(gettext "在线版本检测失败, 请稍后再试!") ${Font}" && exit 1 } pkg_install_judge() { @@ -205,17 +332,17 @@ pkg_install() { fi done if [[ ${install_status} == 0 ]]; then - judge "安装 ${1//,/ }" + judge "$(gettext "安装") ${1//,/ }" else - log_echo "${OK} ${GreenBG} 已安装 ${1//,/ } ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已安装") ${1//,/ } ${Font}" sleep 0.5 fi else if [[ -z $(pkg_install_judge "$1") ]]; then ${INS} -y install $1 - judge "安装 $1" + judge "$(gettext "安装") $1" else - log_echo "${OK} ${GreenBG} 已安装 $1 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已安装") $1 ${Font}" sleep 0.5 fi fi @@ -232,11 +359,11 @@ dependency_install() { if [[ "${ID}" == "centos" ]]; then touch /var/spool/cron/root && chmod 600 /var/spool/cron/root systemctl start crond && systemctl enable crond >/dev/null 2>&1 - judge "crontab 自启动配置" + judge "crontab $(gettext "自启动配置")" else touch /var/spool/cron/crontabs/root && chmod 600 /var/spool/cron/crontabs/root systemctl start cron && systemctl enable cron >/dev/null 2>&1 - judge "crontab 自启动配置" + judge "crontab $(gettext "自启动配置")" fi fi if [[ ${tls_mode} != "None" ]]; then @@ -245,12 +372,12 @@ dependency_install() { else pkg_install "iputils-ping,libpcre3,libpcre3-dev,zlib1g-dev" fi - judge "Nginx 链接库安装" + judge "Nginx $(gettext "链接库安装")" fi } read_optimize() { - local prompt="$1" var_name="$2" default_value="${3:-NULL}" min_value="${4:-}" max_value="${5:-}" error_msg="${6:-值为空或超出范围, 请重新输入!}" + local prompt="$1" var_name="$2" default_value="${3:-NULL}" min_value="${4:-}" max_value="${5:-}" error_msg="${6:-$(gettext "值为空或超出范围, 请重新输入!")}" local user_input read -rp "$prompt" user_input @@ -259,7 +386,7 @@ read_optimize() { if [[ $default_value != "NULL" ]]; then user_input=$default_value else - log_echo "${Error} ${RedBG} 值为空, 请重新输入! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "值为空, 请重新输入!") ${Font}" read_optimize "$prompt" "$var_name" "$default_value" "$min_value" "$max_value" "$error_msg" return fi @@ -303,11 +430,11 @@ create_directory() { port_set() { if [[ "on" != ${old_config_status} ]]; then echo -e "\n" - log_echo "${GreenBG} 确定 连接端口 ${Font}" - read_optimize "请输入连接端口 (默认值:443):" "port" 443 0 65535 "请输入 0-65535 之间的值!" + log_echo "${GreenBG} $(gettext "确定 连接端口") ${Font}" + read_optimize "$(gettext "请输入连接端口") ($(gettext "默认值"):443):" "port" 443 0 65535 "$(gettext "请输入 0-65535 之间的值!")" if [[ ${port} -eq 9443 ]] && [[ ${tls_mode} == "Reality" ]]; then - echo -e "${Error} ${RedBG} 端口 9443 不允许使用, 请重新输入! ${Font}" - read_optimize "请输入连接端口 (默认值:443):" "port" 443 0 65535 "请输入 0-65535 之间的值!" + echo -e "${Error} ${RedBG} $(gettext "端口 9443 不允许使用, 请重新输入!") ${Font}" + read_optimize "$(gettext "请输入连接端口") ($(gettext "默认值"):443):" "port" 443 0 65535 "$(gettext "请输入 0-65535 之间的值!")" fi fi } @@ -315,12 +442,12 @@ port_set() { ws_grpc_choose() { if [[ "on" != ${old_config_status} ]]; then echo -e "\n" - log_echo "${GreenBG} 请选择 安装协议 ws/gRPC ${Font}" - echo -e "${Red}1${Font}: ws (默认)" + log_echo "${GreenBG} $(gettext "请选择 安装协议 ws/gRPC") ${Font}" + echo -e "${Red}1${Font}: ws ($(gettext "默认"))" echo "2: gRPC" echo "3: ws+gRPC" local choose_network - read_optimize "请输入: " "choose_network" 1 1 3 "请输入有效的数字" + read_optimize "$(gettext "请输入"): " "choose_network" 1 1 3 "$(gettext "请输入有效的数字")" if [[ $choose_network == 2 ]]; then [[ ${shell_mode} == "Nginx+ws+TLS" ]] && shell_mode="Nginx+gRPC+TLS" [[ ${shell_mode} == "Reality" ]] && shell_mode="Reality+gRPC" @@ -341,8 +468,8 @@ ws_grpc_choose() { xray_reality_add_more_choose() { if [[ "on" != ${old_config_status} ]]; then echo -e "\n" - log_echo "${GreenBG} 是否添加简单 ws/gRPC 协议 用于负载均衡 [Y/${Red}N${Font}${GreenBG}]? ${Font}" - echo -e "${Warning} ${YellowBG} 如不清楚具体用途, 请勿选择! ${Font}" + log_echo "${GreenBG} $(gettext "是否添加简单 ws/gRPC 协议 用于负载均衡") [Y/${Red}N${Font}${GreenBG}]? ${Font}" + echo -e "${Warning} ${YellowBG} $(gettext "如不清楚具体用途, 请勿选择!") ${Font}" read -r reality_add_more_fq case $reality_add_more_fq in [yY][eE][sS] | [yY]) @@ -361,7 +488,7 @@ xray_reality_add_more_choose() { grpc_inbound_port_set ws_path_set grpc_path_set - log_echo "${OK} ${GreenBG} 已跳过添加简单 ws/gRPC 协议 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已跳过添加简单 ws/gRPC 协议") ${Font}" ;; esac fi @@ -390,11 +517,11 @@ ws_inbound_port_set() { if [[ "on" != ${old_config_status} ]]; then if [[ ${ws_grpc_mode} == "onlyws" ]] || [[ ${ws_grpc_mode} == "all" ]]; then echo -e "\n" - log_echo "${GreenBG} 是否需要自定义 ws inbound_port [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要自定义 ws inbound_port") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r inbound_port_modify_fq case $inbound_port_modify_fq in [yY][eE][sS] | [yY]) - read_optimize "请输入自定义 ws inbound_port (请勿与其他端口相同! ):" "xport" "NULL" 0 65535 "请输入 0-65535 之间的值!" + read_optimize "$(gettext "请输入自定义 ws inbound_port") ($(gettext "请勿与其他端口相同!")): " "xport" "NULL" 0 65535 "$(gettext "请输入 0-65535 之间的值!")" log_echo "${Green} ws inbound_port: ${xport} ${Font}" ;; *) @@ -412,11 +539,11 @@ grpc_inbound_port_set() { if [[ "on" != ${old_config_status} ]]; then if [[ ${ws_grpc_mode} == "onlygRPC" ]] || [[ ${ws_grpc_mode} == "all" ]]; then echo -e "\n" - log_echo "${GreenBG} 是否需要自定义 gRPC inbound_port [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要自定义 gRPC inbound_port") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r inbound_port_modify_fq case $inbound_port_modify_fq in [yY][eE][sS] | [yY]) - read_optimize "请输入自定义 gRPC inbound_port (请勿与其他端口相同! ):" "gport" "NULL" 0 65535 "请输入 0-65535 之间的值!" + read_optimize "$(gettext "请输入自定义 gRPC inbound_port") ($(gettext "请勿与其他端口相同!")): " "gport" "NULL" 0 65535 "$(gettext "请输入 0-65535 之间的值!")" log_echo "${Green} gRPC inbound_port: ${gport} ${Font}" ;; *) @@ -433,7 +560,7 @@ grpc_inbound_port_set() { firewall_set() { echo -e "\n" - log_echo "${GreenBG} 是否需要设置防火墙 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要设置防火墙") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r firewall_set_fq case $firewall_set_fq in [yY][eE][sS] | [yY]) @@ -473,18 +600,18 @@ firewall_set() { if [[ "${ID}" == "centos" && ${VERSION_ID} -ge 7 ]]; then service iptables save service iptables restart - log_echo "${OK} ${GreenBG} 防火墙 重启 完成 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "防火墙 重启 完成") ${Font}" else netfilter-persistent save systemctl restart iptables - log_echo "${OK} ${GreenBG} 防火墙 重启 完成 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "防火墙 重启 完成") ${Font}" fi - log_echo "${OK} ${GreenBG} 开放防火墙相关端口 ${Font}" - log_echo "${GreenBG} 若修改配置, 请注意关闭防火墙相关端口 ${Font}" - log_echo "${OK} ${GreenBG} 配置 Xray FullCone ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "开放防火墙相关端口") ${Font}" + log_echo "${GreenBG} $(gettext "若修改配置, 请注意关闭防火墙相关端口") ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "配置 Xray FullCone") ${Font}" ;; *) - log_echo "${OK} ${GreenBG} 跳过防火墙设置 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "跳过防火墙设置") ${Font}" ;; esac } @@ -493,16 +620,16 @@ ws_path_set() { if [[ "on" != ${old_config_status} ]] || [[ ${change_ws_path} == "yes" ]]; then if [[ ${ws_grpc_mode} == "onlyws" ]] || [[ ${ws_grpc_mode} == "all" ]]; then echo -e "\n" - log_echo "${GreenBG} 是否需要自定义 ws 伪装路径 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要自定义 ws 伪装路径") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r path_modify_fq case $path_modify_fq in [yY][eE][sS] | [yY]) - read_optimize "请输入自定义 ws 伪装路径 (不需要“/”):" "path" "NULL" - log_echo "${Green} ws 伪装路径: ${path} ${Font}" + read_optimize "$(gettext "请输入自定义 ws 伪装路径") ($(gettext "不需要")"/"):" "path" "NULL" + log_echo "${Green} ws $(gettext "伪装路径"): ${path} ${Font}" ;; *) path="$(head -n 10 /dev/urandom | md5sum | head -c ${random_num})" - log_echo "${Green} ws 伪装路径: ${path} ${Font}" + log_echo "${Green} ws $(gettext "伪装路径"): ${path} ${Font}" ;; esac else @@ -510,7 +637,7 @@ ws_path_set() { fi elif [[ ${ws_grpc_mode} == "onlyws" ]] || [[ ${ws_grpc_mode} == "all" ]]; then echo -e "\n" - log_echo "${GreenBG} 是否需要修改 ws 伪装路径 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要修改 ws 伪装路径") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r change_ws_path_fq case $change_ws_path_fq in [yY][eE][sS] | [yY]) @@ -526,16 +653,16 @@ grpc_path_set() { if [[ "on" != ${old_config_status} ]] || [[ ${change_grpc_path} == "yes" ]]; then if [[ ${ws_grpc_mode} == "onlygRPC" ]] || [[ ${ws_grpc_mode} == "all" ]]; then echo -e "\n" - log_echo "${GreenBG} 是否需要自定义 gRPC 伪装路径 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要自定义 gRPC 伪装路径") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r path_modify_fq case $path_modify_fq in [yY][eE][sS] | [yY]) - read_optimize "请输入自定义 gRPC 伪装路径 (不需要“/”):" "serviceName" "NULL" - log_echo "${Green} gRPC 伪装路径: ${serviceName} ${Font}" + read_optimize "$(gettext "请输入自定义 gRPC 伪装路径") ($(gettext "不需要")"/"):" "serviceName" "NULL" + log_echo "${Green} gRPC $(gettext "伪装路径"): ${serviceName} ${Font}" ;; *) serviceName="$(head -n 10 /dev/urandom | md5sum | head -c ${random_num})" - log_echo "${Green} gRPC 伪装路径: ${serviceName} ${Font}" + log_echo "${Green} gRPC $(gettext "伪装路径"): ${serviceName} ${Font}" ;; esac else @@ -543,7 +670,7 @@ grpc_path_set() { fi elif [[ ${ws_grpc_mode} == "onlygRPC" ]] || [[ ${ws_grpc_mode} == "all" ]]; then echo -e "\n" - log_echo "${GreenBG} 是否需要修改 gRPC 伪装路径 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要修改 gRPC 伪装路径") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r change_grpc_path_fq case $change_grpc_path_fq in [yY][eE][sS] | [yY]) @@ -558,37 +685,37 @@ grpc_path_set() { email_set() { if [[ "on" != ${old_config_status} ]]; then echo -e "\n" - log_echo "${GreenBG} 是否需要自定义 Xray 用户名 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要自定义 Xray 用户名") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r custom_email_fq case $custom_email_fq in [yY][eE][sS] | [yY]) - read_optimize "请输入合法的email (e.g. me@idleleo.com): " "custom_email" "NULL" + read_optimize "$(gettext "请输入合法的email") (e.g. me@idleleo.com): " "custom_email" "NULL" ;; *) custom_email="$(head -n 10 /dev/urandom | md5sum | head -c ${random_num})@idleleo.com" ;; esac - log_echo "${Green} Xray 用户名 (email): ${custom_email} ${Font}" + log_echo "${Green} $(gettext "Xray 用户名") (email): ${custom_email} ${Font}" fi } UUID_set() { if [[ "on" != ${old_config_status} ]]; then echo -e "\n" - log_echo "${GreenBG} 是否需要自定义字符串映射为 UUIDv5 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要自定义字符串映射为 UUIDv5") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r need_UUID5 case $need_UUID5 in [yY][eE][sS] | [yY]) - read_optimize "请输入自定义字符串 (最多30字符):" "UUID5_char" "NULL" + read_optimize "$(gettext "请输入自定义字符串") ($(gettext "最多30字符")):" "UUID5_char" "NULL" UUID="$(UUIDv5_tranc ${UUID5_char})" - log_echo "${Green} 自定义字符串: ${UUID5_char} ${Font}" + log_echo "${Green} $(gettext "自定义字符串"): ${UUID5_char} ${Font}" log_echo "${Green} UUIDv5: ${UUID} ${Font}" echo -e "\n" ;; *) UUID5_char="$(head -n 10 /dev/urandom | md5sum | head -c ${random_num})" UUID="$(UUIDv5_tranc ${UUID5_char})" - log_echo "${Green} UUID 映射字符串: ${UUID5_char} ${Font}" + log_echo "${Green} $(gettext "UUID 映射字符串"): ${UUID5_char} ${Font}" log_echo "${Green} UUID: ${UUID} ${Font}" echo -e "\n" #[ -z "$UUID" ] && UUID=$(cat /proc/sys/kernel/random/uuid) @@ -600,7 +727,7 @@ UUID_set() { target_set() { if [[ "on" == ${old_config_status} ]] && [[ $(info_extraction target) != null ]]; then echo -e "\n" - log_echo "${GreenBG} 检测到 target 域名已配置, 是否保留 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${GreenBG} $(gettext "检测到 target 域名已配置, 是否保留") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r old_host_fq case $old_host_fq in [nN][oO] | [nN]) @@ -620,40 +747,40 @@ target_set() { while true; do echo -e "\n" - log_echo "${GreenBG} 请输入一个域名 (e.g. bing.com)${Font}" - log_echo "${Green}域名要求支持 TLSv1.3、X25519 与 H2 以及域名非跳转用${Font}" - read_optimize "确认域名符合要求后请输入: " "domain" "NULL" - log_echo "${Green}正在检测域名请等待…${Font}" + log_echo "${GreenBG} $(gettext "请输入一个域名") (e.g. bing.com)${Font}" + log_echo "${Green}$(gettext "域名要求支持 TLSv1.3、X25519 与 H2 以及域名非跳转用")${Font}" + read_optimize "$(gettext "确认域名符合要求后请输入"): " "domain" "NULL" + log_echo "${Green}$(gettext "正在检测域名请等待")…${Font}" output=$(nmap --script ssl-enum-ciphers -p 443 "${domain}") curl_output=$(curl -I -k -m 5 "https://${domain}" 2>&1) # 检测TLSv1.3支持 if ! echo "$output" | grep -q "TLSv1.3"; then - log_echo "${Warning} ${YellowBG} 该域名不支持 TLSv1.3 ${YellowBG}${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "该域名不支持 TLSv1.3") ${YellowBG}${Font}" fi # 检测X25519支持 if ! echo "$output" | grep -q "x25519"; then - log_echo "${Warning} ${YellowBG} 该域名不支持 X25519 ${YellowBG}${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "该域名不支持 X25519") ${YellowBG}${Font}" fi # 检测HTTP/2支持 if ! echo "$curl_output" | grep -q "HTTP/2"; then - log_echo "${Warning} ${YellowBG} 该域名不支持 HTTP/2 ${YellowBG}${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "该域名不支持 HTTP/2") ${YellowBG}${Font}" fi # 检测是否跳转 if echo "$curl_output" | grep -i -q 'location:'; then - log_echo "${Warning} ${YellowBG} 该域名发生了跳转 ${YellowBG}${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "该域名发生了跳转") ${YellowBG}${Font}" fi if ! echo "$output" | grep -q "TLSv1.3" || \ ! echo "$output" | grep -q "x25519" || \ ! echo "$curl_output" | grep -q "HTTP/2" || \ echo "$curl_output" | grep -i -q 'location:'; then - log_echo "${Warning} ${YellowBG} 该域名可能不满足所有要求 ${YellowBG}${Font}" - log_echo "${GreenBG} 是否仍要设置此域名 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "该域名可能不满足所有要求") ${YellowBG}${Font}" + log_echo "${GreenBG} $(gettext "是否仍要设置此域名") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r force_set_fq case $force_set_fq in [yY][eE][sS] | [yY]) @@ -665,12 +792,12 @@ target_set() { ;; esac else - log_echo "${OK} ${GreenBG} 域名 ${domain} 满足所有要求 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "域名") ${domain} $(gettext "满足所有要求") ${Font}" target=$domain break fi done - log_echo "${Green} target 域名: ${target} ${Font}" + log_echo "${Green} $(gettext "target 域名"): ${target} ${Font}" fi } @@ -678,13 +805,13 @@ serverNames_set() { if [[ ${target_reset} == 1 ]] || [[ "on" != ${old_config_status} ]]; then local custom_serverNames_fq echo -e "\n" - log_echo "${GreenBG} 是否需要修改 ${target} 域名的 serverNames 用户名 [Y/${Red}N${Font}${GreenBG}]? ${Font}" - echo -e "${Green} 默认为 ${target} 域名的本身${Font}" - echo -e "${Warning} ${YellowBG} 如不清楚具体用途, 请勿继续! ${Font}" + log_echo "${GreenBG} $(gettext "是否需要修改") ${target} $(gettext "域名的 serverNames 用户名") [Y/${Red}N${Font}${GreenBG}]? ${Font}" + echo -e "${Green} $(gettext "默认为") ${target} $(gettext "域名的本身")${Font}" + echo -e "${Warning} ${YellowBG} $(gettext "如不清楚具体用途, 请勿继续!") ${Font}" read -r custom_serverNames_fq case $custom_serverNames_fq in [yY][eE][sS] | [yY]) - read_optimize "请输入: " "serverNames" "NULL" + read_optimize "$(gettext "请输入"): " "serverNames" "NULL" ;; *) serverNames=$target @@ -717,25 +844,25 @@ shortIds_set() { nginx_upstream_server_set() { if [[ ${tls_mode} == "TLS" ]]; then echo -e "\n" - log_echo "${GreenBG} 是否变更 Nginx 负载均衡 [Y/${Red}N${Font}${GreenBG}]? ${Font}" - echo -e "${Warning} ${YellowBG} 如不清楚具体用途, 请勿继续! ${Font}" + log_echo "${GreenBG} $(gettext "是否变更 Nginx 负载均衡") [Y/${Red}N${Font}${GreenBG}]? ${Font}" + echo -e "${Warning} ${YellowBG} $(gettext "如不清楚具体用途, 请勿继续!") ${Font}" read -r nginx_upstream_server_fq case $nginx_upstream_server_fq in [yY][eE][sS] | [yY]) - echo -e "\n${GreenBG} 请选择协议为 ws 或 gRPC ${Font}" + echo -e "\n${GreenBG} $(gettext "请选择协议为 ws 或 gRPC") ${Font}" echo "1: ws" echo "2: gRPC" - echo "3: 返回" + echo "3: $(gettext "返回")" local upstream_choose - read_optimize "请输入: " "upstream_choose" "NULL" 1 3 "请重新输入正确的数字" + read_optimize "$(gettext "请输入"): " "upstream_choose" "NULL" 1 3 "$(gettext "请重新输入正确的数字")" fm_remote_url="https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/file_manager.sh" fm_file_path=${nginx_conf_dir} if [ ! -f "${idleleo_dir}/file_manager.sh" ]; then - log_echo "${Info} ${Green} 本地文件 file_manager.sh 不存在,正在下载... ${Font}" + log_echo "${Info} ${Green} $(gettext "本地文件 file_manager.sh 不存在,正在下载...") ${Font}" curl -sL "$fm_remote_url" -o "${idleleo_dir}/file_manager.sh" if [ $? -ne 0 ]; then - log_echo "${Error} ${RedBG} 下载失败,请手动下载并安装新版本 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "下载失败,请手动下载并安装新版本") ${Font}" return 1 fi chmod +x "${idleleo_dir}/file_manager.sh" @@ -745,7 +872,7 @@ nginx_upstream_server_set() { 2) source "${idleleo_dir}/file_manager.sh" grpcServers ${fm_file_path} ;; 3) ;; *) - log_echo "${Error} ${RedBG} 无效选项 请重试 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "无效选项 请重试") ${Font}" nginx_upstream_server_set ;; esac @@ -753,26 +880,26 @@ nginx_upstream_server_set() { *) ;; esac else - log_echo "${Error} ${RedBG} 当前模式不支持此操作! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "当前模式不支持此操作!") ${Font}" fi } nginx_servernames_server_set() { if [[ ${tls_mode} == "Reality" ]] && [[ ${reality_add_nginx} == "on" ]]; then echo -e "\n" - log_echo "${GreenBG} 是否变更 Nginx serverNames 配置 [Y/${Red}N${Font}${GreenBG}]? ${Font}" - echo -e "${Warning} ${YellowBG} 如不清楚具体用途, 请勿继续! ${Font}" - echo -e "${Info} ${GreenBG} 配置用途可以参考文章: (敬请期待) ${Font}" + log_echo "${GreenBG} $(gettext "是否变更 Nginx serverNames 配置") [Y/${Red}N${Font}${GreenBG}]? ${Font}" + echo -e "${Warning} ${YellowBG} $(gettext "如不清楚具体用途, 请勿继续!") ${Font}" + echo -e "${Info} ${GreenBG} $(gettext "配置用途可以参考文章"): ($(gettext "敬请期待")) ${Font}" read -r nginx_servernames_server_fq case $nginx_servernames_server_fq in [yY][eE][sS] | [yY]) fm_remote_url="https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/file_manager.sh" fm_file_path=${nginx_conf_dir} if [ ! -f "${idleleo_dir}/file_manager.sh" ]; then - log_echo "${Info} ${Green} 本地文件 file_manager.sh 不存在,正在下载... ${Font}" + log_echo "${Info} ${Green} $(gettext "本地文件 file_manager.sh 不存在,正在下载...") ${Font}" curl -sL "$fm_remote_url" -o "${idleleo_dir}/file_manager.sh" if [ $? -ne 0 ]; then - log_echo "${Error} ${RedBG} 下载失败,请手动下载并安装新版本 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "下载失败,请手动下载并安装新版本") ${Font}" return 1 fi chmod +x "${idleleo_dir}/file_manager.sh" @@ -782,7 +909,7 @@ nginx_servernames_server_set() { *) ;; esac else - log_echo "${Error} ${RedBG} 当前模式不支持此操作! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "当前模式不支持此操作!") ${Font}" fi } @@ -804,15 +931,15 @@ modify_listen_address() { if [[ ${ws_grpc_mode} == "onlyws" ]]; then jq --argjson modifynum "$modifynum" \ '.inbounds[$modifynum].listen = "0.0.0.0"' "${xray_conf}" > "${xray_conf}.tmp" - judge "Xray listen address 修改" + judge "$(gettext "Xray listen address 修改")" elif [[ ${ws_grpc_mode} == "onlygRPC" ]]; then jq --argjson modifynum2 "$modifynum2" \ '.inbounds[$modifynum2].listen = "0.0.0.0"' "${xray_conf}" > "${xray_conf}.tmp" - judge "Xray listen address 修改" + judge "$(gettext "Xray listen address 修改")" elif [[ ${ws_grpc_mode} == "all" ]]; then jq --argjson modifynum "$modifynum" --argjson modifynum2 "$modifynum2" \ '.inbounds[$modifynum].listen = "0.0.0.0" | .inbounds[$modifynum2].listen = "0.0.0.0"' "${xray_conf}" > "${xray_conf}.tmp" - judge "Xray listen address 修改" + judge "$(gettext "Xray listen address 修改")" fi mv "${xray_conf}.tmp" "${xray_conf}" } @@ -824,18 +951,18 @@ modify_inbound_port() { '.inbounds[0].port = $port | .inbounds[1].port = $xport | .inbounds[2].port = $gport' "${xray_conf}" > "${xray_conf}.tmp" - judge "Xray inbound port 修改" + judge "$(gettext "Xray inbound port 修改")" else jq --argjson xport "${xport}" --argjson gport "${gport}" \ '.inbounds[1].port = $xport | .inbounds[2].port = $gport' "${xray_conf}" > "${xray_conf}.tmp" - judge "Xray inbound port 修改" + judge "$(gettext "Xray inbound port 修改")" fi else jq --argjson xport "${xport}" --argjson gport "${gport}" \ '.inbounds[0].port = $xport | .inbounds[1].port = $gport' "${xray_conf}" > "${xray_conf}.tmp" - judge "Xray inbound port 修改" + judge "$(gettext "Xray inbound port 修改")" fi mv "${xray_conf}.tmp" "${xray_conf}" } @@ -855,15 +982,15 @@ modify_nginx_origin_conf() { modify_nginx_port() { if [[ ${tls_mode} == "Reality" ]] && [[ ${reality_add_nginx} == "on" ]]; then sed -i "s/^\( *\)listen.*/\1listen ${port} reuseport so_keepalive=on backlog=65535;/" ${nginx_conf} - judge "Nginx port 修改" + judge "$(gettext "Nginx port 修改")" elif [[ ${tls_mode} == "TLS" ]]; then sed -i "2s/^\( *\).*ssl reuseport;$/\1listen ${port} ssl reuseport;/" ${nginx_conf} sed -i "3s/^\( *\).*ssl reuseport;$/\1listen [::]:${port} ssl reuseport;/" ${nginx_conf} sed -i "4s/^\( *\).*quic reuseport;$/\1listen ${port} quic reuseport;/" ${nginx_conf} sed -i "5s/^\( *\).*quic reuseport;$/\1listen [::]:${port} quic reuseport;/" ${nginx_conf} - judge "Xray port 修改" + judge "$(gettext "Xray port 修改")" fi - log_echo "${Green} 端口号: ${port} ${Font}" + log_echo "${Green} $(gettext "端口号"): ${port} ${Font}" } modify_nginx_ssl_other() { @@ -911,29 +1038,29 @@ modify_path() { sed -i "s/^\( *\)\"path\".*/\1\"path\": \"\/${path}\"/" ${xray_conf} sed -i "s/^\( *\)\"serviceName\".*/\1\"serviceName\": \"${serviceName}\",/" ${xray_conf} if [[ ${tls_mode} != "Reality" ]] || [[ "$reality_add_more" == "off" ]]; then - judge "Xray 伪装路径 修改" + judge "$(gettext "Xray 伪装路径 修改")" else - log_echo "${Warning} ${YellowBG} Reality 不支持 path ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "Reality 不支持 path") ${Font}" fi } modify_email_address() { if [[ $(jq -r '.inbounds[0].settings.clients|length' ${xray_conf}) == 1 ]] && [[ $(jq -r '.inbounds[1].settings.clients|length' ${xray_conf}) == 1 ]]; then sed -i "s/^\( *\)\"email\".*/\1\"email\": \"${custom_email}\"/g" ${xray_conf} - judge "Xray 用户名 修改" + judge "$(gettext "Xray 用户名 修改")" else echo -e "\n" - log_echo "${Warning} ${YellowBG} 请先删除 多余的用户 ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请先删除 多余的用户") ${Font}" fi } modify_UUID() { if [[ $(jq -r '.inbounds[0].settings.clients|length' ${xray_conf}) == 1 ]] && [[ $(jq -r '.inbounds[1].settings.clients|length' ${xray_conf}) == 1 ]]; then sed -i "s/^\( *\)\"id\".*/\1\"id\": \"${UUID}\",/g" ${xray_conf} - judge "Xray UUID 修改" + judge "$(gettext "Xray UUID 修改")" else echo -e "\n" - log_echo "${Warning} ${YellowBG} 请先删除 多余的用户 ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请先删除 多余的用户") ${Font}" fi } @@ -941,7 +1068,7 @@ modify_target_serverNames() { jq --arg target "${target}:443" --arg serverNames "${serverNames}" ' .inbounds[0].streamSettings.realitySettings.target = $target | .inbounds[0].streamSettings.realitySettings.serverNames = [$serverNames]' "${xray_conf}" > "${xray_conf}.tmp" - judge "target serverNames 配置修改" + judge "$(gettext "target serverNames 配置修改")" mv "${xray_conf}.tmp" "${xray_conf}" } @@ -949,75 +1076,75 @@ modify_privateKey_shortIds() { jq --arg privateKey "${privateKey}" --arg shortIds "${shortIds}" ' .inbounds[0].streamSettings.realitySettings.privateKey = $privateKey | .inbounds[0].streamSettings.realitySettings.shortIds = [$shortIds]' "${xray_conf}" > "${xray_conf}.tmp" - judge "privateKey 和 shortIds 配置修改" + judge "$(gettext "privateKey 和 shortIds 配置修改")" mv "${xray_conf}.tmp" "${xray_conf}" } modify_reality_listen_address () { jq '.inbounds[0].listen = "127.0.0.1"' "${xray_conf}" > "${xray_conf}.tmp" mv "${xray_conf}.tmp" "${xray_conf}" - judge "Xray reality listen address 修改" + judge "$(gettext "Xray reality listen address 修改")" } xray_privilege_escalation() { if [[ -n "$(grep "User=nobody" ${xray_systemd_file})" ]]; then - log_echo "${OK} ${GreenBG} 检测到 Xray 的权限控制, 启动擦屁股程序 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "检测到 Xray 的权限控制, 启动擦屁股程序") ${Font}" chmod -fR a+rw /var/log/xray/ chown -fR nobody:nogroup /var/log/xray/ [[ -f "${ssl_chainpath}/xray.key" ]] && chown -fR nobody:nogroup ${ssl_chainpath}/* fi - log_echo "${OK} ${GreenBG} Xray 擦屁股 完成 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "Xray 擦屁股 完成") ${Font}" } xray_install() { if [[ $(xray version) == "" ]] || [[ ! -f "${xray_conf}" ]]; then bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install -f --version v${xray_version} - judge "安装 Xray" + judge "$(gettext "安装 Xray")" systemctl daemon-reload xray_privilege_escalation [[ -f "${xray_default_conf}" ]] && rm -rf ${xray_default_conf} ln -s ${xray_conf} ${xray_default_conf} else - log_echo "${OK} ${GreenBG} 已安装 Xray ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已安装 Xray") ${Font}" fi } xray_update() { - [[ ! -d "${local_bin}/etc/xray" ]] && log_echo "${GreenBG} 若更新无效, 建议直接卸载再安装! ${Font}" - log_echo "${Warning} ${GreenBG} 部分新功能需要重新安装才可生效 ${Font}" + [[ ! -d "${local_bin}/etc/xray" ]] && log_echo "${GreenBG} $(gettext "若更新无效, 建议直接卸载再安装!") ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "部分新功能需要重新安装才可生效") ${Font}" xray_online_version=$(check_version xray_online_version) ## xray_online_version=$(check_version xray_online_pre_version) ## if [[ $(info_extraction xray_version) != ${xray_online_version} ]] && [[ ${xray_version} != ${xray_online_version} ]]; then if [[ $(info_extraction xray_version) != ${xray_online_version} ]]; then if [[ ${auto_update} != "YES" ]]; then - log_echo "${Warning} ${GreenBG} 检测到存在最新版 ${Font}" - log_echo "${Warning} ${GreenBG} 脚本可能未兼容此版本 ${Font}" - log_echo "${Warning} ${GreenBG} 是否更新 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "检测到存在最新版") ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "脚本可能未兼容此版本") ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "是否更新") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r xray_test_fq else xray_test_fq=1 fi case $xray_test_fq in [yY][eE][sS] | [yY]) - log_echo "${OK} ${GreenBG} 即将升级 Xray ! ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "即将升级") Xray ! ${Font}" systemctl stop xray ## xray_version=${xray_online_version} bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install -f --version v${xray_version} - judge "Xray 升级" + judge "Xray $(gettext "升级")" ;; *) - log_echo "${OK} ${GreenBG} 即将升级/重装 Xray ! ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "即将升级/重装") Xray ! ${Font}" systemctl stop xray xray_version=$(info_extraction xray_version) bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install -f --version v${xray_version} - judge "Xray 升级" + judge "Xray $(gettext "升级")" ;; esac else - timeout "升级/重装 Xray !" + timeout "$(gettext "升级/重装") Xray !" systemctl stop xray bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install -f --version v${xray_version} - judge "Xray 升级" + judge "Xray $(gettext "升级")" fi xray_privilege_escalation [[ -f "${xray_default_conf}" ]] && rm -rf ${xray_default_conf} @@ -1030,13 +1157,13 @@ xray_update() { reality_nginx_add_fq() { echo -e "\n" - log_echo "${Warning} ${Green} Reality 协议有流量偷跑的风险 ${Font}" - log_echo "${Warning} ${Green} 该风险在 target 网址被 cdn 加速时存在 ${Font}" - log_echo "${GreenBG} 是否额外安装 nginx 前置保护(推荐) [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${Warning} ${Green} $(gettext "Reality 协议有流量偷跑的风险") ${Font}" + log_echo "${Warning} ${Green} $(gettext "该风险在 target 网址被 cdn 加速时存在") ${Font}" + log_echo "${GreenBG} $(gettext "是否额外安装 nginx 前置保护(推荐)") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r reality_nginx_add_fq case $reality_nginx_add_fq in [nN][oO] | [nN]) - log_echo "${OK} ${GreenBG} 已跳过安装 nginx ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已跳过安装") nginx ${Font}" ;; *) reality_add_nginx="on" @@ -1066,29 +1193,29 @@ nginx_exist_check() { sed -i "/^include.*\*\.conf;$/d" ${nginx_dir}/conf/nginx.conf fi modify_nginx_origin_conf - log_echo "${OK} ${GreenBG} Nginx 已存在, 跳过编译安装过程 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "Nginx 已存在, 跳过编译安装过程") ${Font}" #兼容代码,下个大版本删除 elif [[ -d "/etc/nginx" ]] && [[ "$(info_extraction nginx_version)" == "null" ]]; then - log_echo "${Error} ${GreenBG} 检测到旧版本安装的 nginx ! ${Font}" - log_echo "${Warning} ${GreenBG} 请先做好备份 ${Font}" - log_echo "${GreenBG} 是否需要删除 (请删除) [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${Error} ${GreenBG} $(gettext "检测到旧版本安装的") nginx ! ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "请先做好备份") ${Font}" + log_echo "${GreenBG} $(gettext "是否需要删除 (请删除)") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r remove_nginx_fq case $remove_nginx_fq in [nN][oO] | [nN]) - log_echo "${OK} ${GreenBG} 已跳过删除 nginx ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已跳过删除") nginx ${Font}" source "$idleleo" ;; *) rm -rf /etc/nginx/ [[ -f "${nginx_systemd_file}" ]] && rm -rf ${nginx_systemd_file} [[ -d "${nginx_conf_dir}" ]] && rm -rf ${nginx_conf_dir}/*.conf - log_echo "${Warning} ${GreenBG} 日志目录已更改, 日志清除需要重新设置 ! ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "日志目录已更改, 日志清除需要重新设置") ! ${Font}" nginx_install ;; esac #兼容代码结束 elif [[ -d "/etc/nginx" ]] && [[ "$(info_extraction nginx_version)" == "null" ]]; then - log_echo "${Error} ${RedBG} 检测到其他套件安装的 Nginx, 继续安装会造成冲突, 请处理后安装! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "检测到其他套件安装的 Nginx, 继续安装会造成冲突, 请处理后安装!") ${Font}" exit 1 else nginx_install @@ -1102,7 +1229,7 @@ nginx_install() { cd "$temp_dir" || exit - log_echo "${OK} ${GreenBG} 即将下载已编译的 Nginx ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "即将下载已编译的") Nginx ${Font}" local url="https://github.com/hello-yunshu/Xray_bash_onekey_Nginx/releases/download/v${latest_version}/xray-nginx-custom.tar.gz" wget -q --show-progress --progress=bar:force:noscroll "$url" -O xray-nginx-custom.tar.gz tar -xzvf xray-nginx-custom.tar.gz -C ./ @@ -1147,34 +1274,34 @@ nginx_update() { serviceName=$(info_extraction serviceName) fi if [[ 0 -eq ${read_config_status} ]]; then - [[ ${auto_update} == "YES" ]] && echo "Nginx 配置文件不完整, 退出升级!" && exit 1 - log_echo "${Error} ${RedBG} 配置文件不完整, 退出升级 ${Font}" + [[ ${auto_update} == "YES" ]] && echo "$(gettext "Nginx 配置文件不完整, 退出升级!")" && exit 1 + log_echo "${Error} ${RedBG} $(gettext "配置文件不完整, 退出升级") ${Font}" return 1 fi elif [[ ${tls_mode} == "Reality" ]] && [[ ${reality_add_nginx} == "on" ]]; then port=$(info_extraction port) serverNames=$(info_extraction serverNames) if [[ 0 -eq ${read_config_status} ]]; then - [[ ${auto_update} == "YES" ]] && echo "Nginx 配置文件不完整, 退出升级!" && exit 1 - log_echo "${Error} ${RedBG} 配置文件不完整, 退出升级 ${Font}" + [[ ${auto_update} == "YES" ]] && echo "$(gettext "Nginx 配置文件不完整, 退出升级!")" && exit 1 + log_echo "${Error} ${RedBG} $(gettext "配置文件不完整, 退出升级") ${Font}" return 1 fi elif [[ ${tls_mode} == "None" ]]; then - [[ ${auto_update} == "YES" ]] && echo "当前安装模式不需要 Nginx !" && exit 1 - log_echo "${Error} ${RedBG} 当前安装模式不需要 Nginx ! ${Font}" + [[ ${auto_update} == "YES" ]] && echo "$(gettext "当前安装模式不需要") Nginx !" && exit 1 + log_echo "${Error} ${RedBG} $(gettext "当前安装模式不需要") Nginx ! ${Font}" return 1 fi else - [[ ${auto_update} == "YES" ]] && echo "Nginx 配置文件不存在, 退出升级!" && exit 1 - log_echo "${Error} ${RedBG} 配置文件不存在, 退出升级 ${Font}" + [[ ${auto_update} == "YES" ]] && echo "$(gettext "Nginx 配置文件不存在, 退出升级!")" && exit 1 + log_echo "${Error} ${RedBG} $(gettext "配置文件不存在, 退出升级") ${Font}" return 1 fi service_stop - timeout "删除旧版 Nginx !" + timeout "$(gettext "删除旧版") Nginx !" rm -rf ${nginx_dir} if [[ ${auto_update} != "YES" ]]; then echo -e "\n" - log_echo "${GreenBG} 是否保留原 Nginx 配置文件 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${GreenBG} $(gettext "是否保留原 Nginx 配置文件") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r save_originconf_fq else save_originconf_fq=1 @@ -1182,11 +1309,11 @@ nginx_update() { case $save_originconf_fq in [nN][oO] | [nN]) rm -rf ${nginx_conf_dir}/*.conf - log_echo "${OK} ${GreenBG} 原配置文件已删除! ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "原配置文件已删除!") ${Font}" ;; *) save_originconf="Yes" - log_echo "${OK} ${GreenBG} 原配置文件已保留! ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "原配置文件已保留!") ${Font}" ;; esac nginx_install @@ -1200,12 +1327,12 @@ nginx_update() { service_start jq --arg nginx_build_version "${nginx_build_version}" '.nginx_build_version = $nginx_build_version' "${xray_qr_config_file}" > "${xray_qr_config_file}.tmp" mv "${xray_qr_config_file}.tmp" "${xray_qr_config_file}" - judge "Nginx 升级" + judge "Nginx $(gettext "升级")" else - log_echo "${OK} ${GreenBG} Nginx 已为最新版 ${Font}" + log_echo "${OK} ${GreenBG} Nginx $(gettext "已为最新版") ${Font}" fi else - log_echo "${Error} ${RedBG} Nginx 未安装 ${Font}" + log_echo "${Error} ${RedBG} Nginx $(gettext "未安装") ${Font}" fi } @@ -1217,27 +1344,27 @@ auto_update() { fi if [[ ! -f "${auto_update_file}" ]] || [[ $(crontab -l | grep -c "auto_update.sh") -lt 1 ]]; then echo -e "\n" - log_echo "${GreenBG} 设置后台定时自动更新程序 (包含: 脚本/Xray/Nginx) ${Font}" - log_echo "${GreenBG} 可能自动更新后有兼容问题, 谨慎开启 ${Font}" - log_echo "${GreenBG} 是否开启 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "设置后台定时自动更新程序 (包含: 脚本/Xray/Nginx)") ${Font}" + log_echo "${GreenBG} $(gettext "可能自动更新后有兼容问题, 谨慎开启") ${Font}" + log_echo "${GreenBG} $(gettext "是否开启") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r auto_update_fq case $auto_update_fq in [yY][eE][sS] | [yY]) wget -N -P ${idleleo_dir} --no-check-certificate https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/auto_update.sh && chmod +x ${auto_update_file} echo "0 1 15 * * bash ${auto_update_file}" >>${crontab_file} - judge "设置自动更新" + judge "$(gettext "设置自动更新")" ;; *) ;; esac else - log_echo "${OK} ${GreenBG} 已设置自动更新 ${Font}" - log_echo "${GreenBG} 是否关闭? [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已设置自动更新") ${Font}" + log_echo "${GreenBG} $(gettext "是否关闭") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r auto_update_close_fq case $auto_update_fq in [yY][eE][sS] | [yY]) sed -i "/auto_update.sh/d" ${crontab_file} rm -rf ${auto_update_file} - judge "删除自动更新" + judge "$(gettext "删除自动更新")" ;; *) ;; esac @@ -1246,15 +1373,15 @@ auto_update() { ssl_install() { pkg_install "socat" - judge "安装 SSL 证书生成脚本依赖" + judge "$(gettext "安装 SSL 证书生成脚本依赖")" curl https://get.acme.sh | sh -s email=${custom_email} - judge "安装 SSL 证书生成脚本" + judge "$(gettext "安装 SSL 证书生成脚本")" } domain_check() { if [[ "on" == ${old_config_status} ]] && [[ $(info_extraction host) != null ]] && [[ $(info_extraction ip_version) != null ]]; then echo -e "\n" - log_echo "${GreenBG} 检测到原域名配置存在, 是否跳过域名设置 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${GreenBG} $(gettext "检测到原域名配置存在, 是否跳过域名设置") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r old_host_fq case $old_host_fq in [nN][oO] | [nN]) ;; @@ -1268,21 +1395,21 @@ domain_check() { else local_ip=${ip_version} fi - log_echo "${OK} ${GreenBG} 已跳过域名设置 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已跳过域名设置") ${Font}" return 0 ;; esac fi echo -e "\n" - log_echo "${GreenBG} 确定 域名 信息 ${Font}" - read_optimize "请输入你的域名信息 (e.g. www.idleleo.com):" "domain" "NULL" - echo -e "\n${GreenBG} 请选择 公网IP(IPv4/IPv6) 或手动输入 域名 ${Font}" - echo -e "${Red}1${Font}: IPv4 (默认)" - echo "2: IPv6 (不推荐)" - echo "3: 域名" + log_echo "${GreenBG} $(gettext "确定域名信息") ${Font}" + read_optimize "$(gettext "请输入你的域名信息") (e.g. www.idleleo.com):" "domain" "NULL" + echo -e "\n${GreenBG} $(gettext "请选择公网IP(IPv4/IPv6)或手动输入域名") ${Font}" + echo -e "${Red}1${Font}: IPv4 ($(gettext "默认"))" + echo "2: IPv6 ($(gettext "不推荐"))" + echo "3: $(gettext "域名")" local ip_version_fq - read_optimize "请输入: " "ip_version_fq" 1 1 3 "请输入有效的数字" - log_echo "${OK} ${GreenBG} 正在获取 公网IP 信息, 请耐心等待 ${Font}" + read_optimize "$(gettext "请输入"): " "ip_version_fq" 1 1 3 "$(gettext "请输入有效的数字")" + log_echo "${OK} ${GreenBG} $(gettext "正在获取公网IP信息, 请耐心等待") ${Font}" if [[ ${ip_version_fq} == 1 ]]; then local_ip=$(curl -4 ip.sb) domain_ip=$(ping -4 "${domain}" -c 1 | sed '1{s/[^(]*(//;s/).*//;q}') @@ -1292,36 +1419,36 @@ domain_check() { domain_ip=$(ping -6 "${domain}" -c 1 | sed '2{s/[^(]*(//;s/).*//;q}' | tail -n +2) ip_version="IPv6" elif [[ ${ip_version_fq} == 3 ]]; then - log_echo "${Warning} ${GreenBG} 此选项用于服务器商仅提供域名访问服务器 ${Font}" - log_echo "${Warning} ${GreenBG} 注意服务器商域名添加 CNAME 记录 ${Font}" - read_optimize "请输入: " "local_ip" "NULL" + log_echo "${Warning} ${GreenBG} $(gettext "此选项用于服务器商仅提供域名访问服务器") ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "注意服务器商域名添加 CNAME 记录") ${Font}" + read_optimize "$(gettext "请输入"): " "local_ip" "NULL" ip_version=${local_ip} else local_ip=$(curl -4 ip.sb) domain_ip=$(ping -4 "${domain}" -c 1 | sed '1{s/[^(]*(//;s/).*//;q}') ip_version="IPv4" fi - log_echo "域名DNS 解析IP: ${domain_ip}" - log_echo "公网IP/域名: ${local_ip}" + log_echo "$(gettext "域名DNS解析IP"): ${domain_ip}" + log_echo "$(gettext "公网IP/域名"): ${local_ip}" if [[ ${ip_version_fq} != 3 ]] && [[ ${local_ip} == ${domain_ip} ]]; then - log_echo "${OK} ${GreenBG} 域名DNS 解析IP 与 公网IP 匹配 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "域名DNS解析IP与公网IP匹配") ${Font}" else - log_echo "${Warning} ${YellowBG} 请确保域名添加了正确的 A/AAAA 记录, 否则将无法正常使用 Xray ${Font}" - log_echo "${Error} ${RedBG} 域名DNS 解析IP 与 公网IP 不匹配, 请选择: ${Font}" - echo "1: 继续安装" - echo "2: 重新输入" - log_echo "${Red}3${Font}: 终止安装 (默认)" + log_echo "${Warning} ${YellowBG} $(gettext "请确保域名添加了正确的 A/AAAA 记录, 否则将无法正常使用 Xray") ${Font}" + log_echo "${Error} ${RedBG} $(gettext "域名DNS解析IP与公网IP不匹配, 请选择"): ${Font}" + echo "1: $(gettext "继续安装")" + echo "2: $(gettext "重新输入")" + log_echo "${Red}3${Font}: $(gettext "终止安装") ($(gettext "默认"))" local install - read_optimize "请输入: " "install" 3 1 3 "请输入有效的数字" + read_optimize "$(gettext "请输入"): " "install" 3 1 3 "$(gettext "请输入有效的数字")" case $install in 1) - log_echo "${OK} ${GreenBG} 继续安装 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "继续安装") ${Font}" ;; 2) domain_check ;; *) - log_echo "${Error} ${RedBG} 安装终止 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "安装终止") ${Font}" exit 2 ;; esac @@ -1332,7 +1459,7 @@ ip_check() { if [[ "on" == ${old_config_status} || ${auto_update} == "YES" ]] && [[ $(info_extraction host) != null ]] && [[ $(info_extraction ip_version) != null ]]; then if [[ ${auto_update} != "YES" ]]; then echo -e "\n" - log_echo "${GreenBG} 检测到原IP配置存在, 是否跳过IP设置 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${GreenBG} $(gettext "检测到原IP配置存在, 是否跳过IP设置") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r old_host_fq else old_host_fq=1 @@ -1349,26 +1476,21 @@ ip_check() { local_ip=${ip_version} fi echo -e "\n" - log_echo "${OK} ${GreenBG} 已跳过IP设置 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已跳过IP设置") ${Font}" return 0 ;; esac - # ##兼容代码,未来删除 - # elif [[ ${auto_update} == "YES" ]] && [[ $(info_extraction ip_version) == null ]]; then - # echo "无法测试 IP 版本, 跳过 Nginx 更新!" >>${log_file} - # echo "(原因来自于脚本版本低无法兼容, 重装可解决问题)" >>${log_file} - # exit 1 fi echo -e "\n" - log_echo "${GreenBG} 确定 公网IP 信息 ${Font}" - log_echo "${GreenBG} 请选择 公网IP 为 IPv4 或 IPv6 ${Font}" - echo -e "${Red}1${Font}: IPv4 (默认)" - echo "2: IPv6 (不推荐)" - echo "3: 手动输入" + log_echo "${GreenBG} $(gettext "确定公网IP信息") ${Font}" + log_echo "${GreenBG} $(gettext "请选择公网IP为IPv4或IPv6") ${Font}" + echo -e "${Red}1${Font}: IPv4 ($(gettext "默认"))" + echo "2: IPv6 ($(gettext "不推荐"))" + echo "3: $(gettext "手动输入")" local ip_version_fq - read_optimize "请输入: " "ip_version_fq" 1 1 3 "请输入有效的数字" + read_optimize "$(gettext "请输入"): " "ip_version_fq" 1 1 3 "$(gettext "请输入有效的数字")" [[ -z ${ip_version_fq} ]] && ip_version=1 - log_echo "${OK} ${GreenBG} 正在获取 公网IP 信息, 请耐心等待 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "正在获取公网IP信息, 请耐心等待") ${Font}" if [[ ${ip_version_fq} == 1 ]]; then local_ip=$(curl -4 ip.sb) ip_version="IPv4" @@ -1376,24 +1498,24 @@ ip_check() { local_ip=$(curl -6 ip.sb) ip_version="IPv6" elif [[ ${ip_version_fq} == 3 ]]; then - read_optimize "请输入: " "local_ip" "NULL" + read_optimize "$(gettext "请输入"): " "local_ip" "NULL" ip_version=${local_ip} else local_ip=$(curl -4 ip.sb) ip_version="IPv4" fi - log_echo "公网IP/域名: ${local_ip}" + log_echo "$(gettext "公网IP/域名"): ${local_ip}" } port_exist_check() { if [[ 0 -eq $(lsof -i:"$1" | grep -i -c "listen") ]]; then - log_echo "${OK} ${GreenBG} $1 端口未被占用 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "$1 端口未被占用") ${Font}" else - log_echo "${Error} ${RedBG} 检测到 $1 端口被占用, 以下为 $1 端口占用信息 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "检测到 $1 端口被占用, 以下为 $1 端口占用信息") ${Font}" lsof -i:"$1" - timeout "尝试自动 kill 占用进程!" + timeout "$(gettext "尝试自动 kill 占用进程")!" lsof -i:"$1" | awk '{print $2}' | grep -v "PID" | xargs kill -9 - log_echo "${OK} ${GreenBG} kill 完成 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "kill 完成") ${Font}" fi } @@ -1402,27 +1524,27 @@ acme() { #暂时解决ca问题 if "$HOME"/.acme.sh/acme.sh --issue -d ${domain} -w ${idleleo_conf_dir} --server letsencrypt --keylength ec-256 --force --test; then #if "$HOME"/.acme.sh/acme.sh --issue -d ${domain} -w ${idleleo_conf_dir} --keylength ec-256 --force --test; then - log_echo "${OK} ${GreenBG} SSL 证书测试签发成功, 开始正式签发 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "SSL 证书测试签发成功, 开始正式签发") ${Font}" rm -rf "$HOME/.acme.sh/${domain}_ecc" else - log_echo "${Error} ${RedBG} SSL 证书测试签发失败 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "SSL 证书测试签发失败") ${Font}" rm -rf "$HOME/.acme.sh/${domain}_ecc" exit 1 fi if "$HOME"/.acme.sh/acme.sh --issue -d ${domain} -w ${idleleo_conf_dir} --server letsencrypt --keylength ec-256 --force; then #if "$HOME"/.acme.sh/acme.sh --issue -d ${domain} -w ${idleleo_conf_dir} --keylength ec-256 --force; then - log_echo "${OK} ${GreenBG} SSL 证书生成成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "SSL 证书生成成功") ${Font}" mkdir -p ${ssl_chainpath} if "$HOME"/.acme.sh/acme.sh --installcert -d ${domain} --fullchainpath ${ssl_chainpath}/xray.crt --keypath ${ssl_chainpath}/xray.key --ecc --force; then chmod -f a+rw ${ssl_chainpath}/xray.crt chmod -f a+rw ${ssl_chainpath}/xray.key chown -fR nobody:nogroup ${ssl_chainpath}/* - log_echo "${OK} ${GreenBG} 证书配置成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "证书配置成功") ${Font}" systemctl stop nginx fi else - log_echo "${Error} ${RedBG} SSL 证书生成失败 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "SSL 证书生成失败") ${Font}" rm -rf "$HOME/.acme.sh/${domain}_ecc" exit 1 fi @@ -1450,13 +1572,13 @@ xray_conf_add() { modify_UUID else echo -e "\n" - log_echo "${Warning} ${GreenBG} 检测到 Xray 配置过多用户 ${Font}" - log_echo "${GreenBG} 是否保留原 Xray 配置文件 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "检测到 Xray 配置过多用户") ${Font}" + log_echo "${GreenBG} $(gettext "是否保留原 Xray 配置文件") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r save_originxray_fq case $save_originxray_fq in [nN][oO] | [nN]) rm -rf ${xray_conf} - log_echo "${OK} ${GreenBG} 原配置文件已删除! ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "原配置文件已删除!") ${Font}" xray_conf_add ;; *) ;; @@ -1469,7 +1591,7 @@ xray_reality_add_more() { modify_path modify_listen_address modify_inbound_port - judge "添加简单 ws/gRPC 协议" + judge "$(gettext "添加简单 ws/gRPC 协议")" else modify_path modify_inbound_port @@ -1484,33 +1606,33 @@ old_config_exist_check() { if [[ -f "${xray_qr_config_file}" ]]; then if [[ ${old_tls_mode} == ${tls_mode} ]]; then echo -e "\n" - log_echo "${GreenBG} 检测到配置文件, 是否读取配置文件 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${GreenBG} $(gettext "检测到配置文件, 是否读取配置文件") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r old_config_fq case $old_config_fq in [nN][oO] | [nN]) rm -rf ${xray_qr_config_file} - log_echo "${OK} ${GreenBG} 已删除配置文件 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已删除配置文件") ${Font}" ;; *) - log_echo "${OK} ${GreenBG} 已保留配置文件 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已保留配置文件") ${Font}" old_config_status="on" old_config_input ;; esac else echo -e "\n" - log_echo "${Warning} ${GreenBG} 检测到当前安装模式与配置文件的安装模式不一致 ${Font}" - log_echo "${GreenBG} 是否保留配置文件 (强烈不建议) [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "检测到当前安装模式与配置文件的安装模式不一致") ${Font}" + log_echo "${GreenBG} $(gettext "是否保留配置文件 (强烈不建议)") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r old_config_fq case $old_config_fq in [yY][eE][sS] | [yY]) - log_echo "${Warning} ${GreenBG} 请务必确保配置文件正确 ${Font}" - log_echo "${OK} ${GreenBG} 已保留配置文件 ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "请务必确保配置文件正确") ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已保留配置文件") ${Font}" menu ;; *) rm -rf ${xray_qr_config_file} - log_echo "${OK} ${GreenBG} 已删除配置文件 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已删除配置文件") ${Font}" ;; esac fi @@ -1596,17 +1718,17 @@ old_config_input() { fi if [[ 0 -eq ${read_config_status} ]]; then echo -e "\n" - log_echo "${GreenBG} 检测到配置文件不完整, 是否保留配置文件 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "检测到配置文件不完整, 是否保留配置文件") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r old_config_input_fq case $old_config_input_fq in [yY][eE][sS] | [yY]) old_config_status="off" - log_echo "${OK} ${GreenBG} 已保留配置文件 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已保留配置文件") ${Font}" ;; *) rm -rf ${xray_qr_config_file} old_config_status="off" - log_echo "${OK} ${GreenBG} 已删除配置文件 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已删除配置文件") ${Font}" ;; esac fi @@ -1635,7 +1757,7 @@ server { } EOF modify_nginx_ssl_other - judge "Nginx SSL 配置修改" + judge "$(gettext "Nginx SSL 配置修改")" } nginx_conf_add() { @@ -1705,7 +1827,7 @@ server { EOF modify_nginx_port modify_nginx_other - judge "Nginx 配置修改" + judge "$(gettext "Nginx 配置修改")" } nginx_reality_conf_add() { @@ -1735,7 +1857,7 @@ stream { EOF modify_nginx_port modify_nginx_other - judge "Nginx 配置修改" + judge "$(gettext "Nginx 配置修改")" } nginx_reality_serverNames_add () { @@ -1744,14 +1866,14 @@ nginx_reality_serverNames_add () { ${serverNames} reality; EOF # modify_nginx_reality_serverNames - judge "Nginx serverNames 配置修改" + judge "$(gettext "Nginx serverNames 配置修改")" } nginx_reality_serverNames_del () { [[ -f "${nginx_conf_dir}/${serverNames}.serverNames" ]] && rm -f "${nginx_conf_dir}/${serverNames}.serverNames" # modify_nginx_reality_serverNames - judge "Nginx serverNames 配置删除" + judge "$(gettext "Nginx serverNames 配置删除")" } @@ -1767,55 +1889,55 @@ upstream xray-grpc-server { } EOF nginx_servers_add - judge "Nginx servers 配置修改" + judge "$(gettext "Nginx servers 配置修改")" } enable_process_systemd() { if [[ ${tls_mode} == "TLS" ]] || [[ ${reality_add_nginx} == "on" ]]; then - [[ -f "${nginx_systemd_file}" ]] && systemctl enable nginx && judge "设置 Nginx 开机自启" + [[ -f "${nginx_systemd_file}" ]] && systemctl enable nginx && judge "$(gettext "设置 Nginx 开机自启")" fi systemctl enable xray - judge "设置 Xray 开机自启" + judge "$(gettext "设置 Xray 开机自启")" } disable_process_systemd() { if [[ ${tls_mode} == "TLS" ]] || [[ ${reality_add_nginx} == "on" ]]; then - [[ -f "${nginx_systemd_file}" ]] && systemctl stop nginx && systemctl disable nginx && judge "关闭 Nginx 开机自启" + [[ -f "${nginx_systemd_file}" ]] && systemctl stop nginx && systemctl disable nginx && judge "$(gettext "关闭 Nginx 开机自启")" fi systemctl disable xray - judge "关闭 Xray 开机自启" + judge "$(gettext "关闭 Xray 开机自启")" } stop_service_all() { [[ -f "${nginx_systemd_file}" ]] && systemctl stop nginx && systemctl disable nginx systemctl stop xray systemctl disable xray - log_echo "${OK} ${GreenBG} 停止已有服务 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "停止已有服务") ${Font}" } service_restart() { systemctl daemon-reload if [[ ${tls_mode} == "TLS" ]] || [[ ${reality_add_nginx} == "on" ]]; then - [[ -f "${nginx_systemd_file}" ]] && systemctl restart nginx && judge "Nginx 重启" + [[ -f "${nginx_systemd_file}" ]] && systemctl restart nginx && judge "$(gettext "Nginx 重启")" fi systemctl restart xray - judge "Xray 重启" + judge "$(gettext "Xray 重启")" } service_start() { if [[ ${tls_mode} == "TLS" ]] || [[ ${reality_add_nginx} == "on" ]]; then - [[ -f "${nginx_systemd_file}" ]] && systemctl start nginx && judge "Nginx 启动" + [[ -f "${nginx_systemd_file}" ]] && systemctl start nginx && judge "$(gettext "Nginx 启动")" fi systemctl start xray - judge "Xray 启动" + judge "$(gettext "Xray 启动")" } service_stop() { if [[ ${tls_mode} == "TLS" ]] || [[ ${reality_add_nginx} == "on" ]]; then - [[ -f "${nginx_systemd_file}" ]] && systemctl stop nginx && judge "Nginx 停止" + [[ -f "${nginx_systemd_file}" ]] && systemctl stop nginx && judge "$(gettext "Nginx 停止")" fi systemctl stop xray - judge "Xray 停止" + judge "$(gettext "Xray 停止")" } acme_cron_update() { @@ -1828,45 +1950,26 @@ acme_cron_update() { fi if [[ -f "${ssl_update_file}" ]] && [[ $(crontab -l | grep -c "ssl_update.sh") == "1" ]]; then echo -e "\n" - log_echo "${Warning} ${GreenBG} 新版本已自动设置证书自动更新 ${Font}" - log_echo "${Warning} ${GreenBG} 老版本请及时删除 废弃的 改版证书自动更新! ${Font}" - log_echo "${GreenBG} 已设置改版证书自动更新 ${Font}" - log_echo "${GreenBG} 是否需要删除改版证书自动更新 (请删除) [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "新版本已自动设置证书自动更新") ${Font}" + log_echo "${Warning} ${GreenBG} $(gettext "老版本请及时删除 废弃的 改版证书自动更新!") ${Font}" + log_echo "${GreenBG} $(gettext "已设置改版证书自动更新") ${Font}" + log_echo "${GreenBG} $(gettext "是否需要删除改版证书自动更新 (请删除)") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r remove_acme_cron_update_fq case $remove_acme_cron_update_fq in [nN][oO] | [nN]) ;; *) sed -i "/ssl_update.sh/d" ${crontab_file} rm -rf ${ssl_update_file} - judge "删除改版证书自动更新" + judge "$(gettext "删除改版证书自动更新")" ;; esac else echo -e "\n" - log_echo "${OK} ${GreenBG} 新版本已自动设置证书自动更新 ${Font}" - # log_echo "${GreenBG} 是否设置证书自动更新 (新版本无需设置) [Y/${Red}N${Font}${GreenBG}]? ${Font}" - # read -r acme_cron_update_fq - # case $acme_cron_update_fq in - # [yY][eE][sS] | [yY]) - # # if [[ "${ssl_self}" != "on" ]]; then - # # wget -N -P ${idleleo_dir} --no-check-certificate https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/ssl_update.sh && chmod +x ${ssl_update_file} - # # if [[ $(crontab -l | grep -c "acme.sh") -lt 1 ]]; then - # # echo "0 3 15 * * bash ${ssl_update_file}" >>${crontab_file} - # # else - # # sed -i "/acme.sh/c 0 3 15 * * bash ${ssl_update_file}" ${crontab_file} - # # fi - # # judge "设置证书自动更新" - # # else - # # log_echo "${Error} ${RedBG} 自定义证书不支持此操作! ${Font}" - # # fi - # log_echo "${Error} ${RedBG} 新版本请勿使用! ${Font}" - # ;; - # *) ;; - # esac + log_echo "${OK} ${GreenBG} $(gettext "新版本已自动设置证书自动更新") ${Font}" fi else - log_echo "${Error} ${RedBG} 当前模式不支持此操作! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "当前模式不支持此操作!") ${Font}" fi } @@ -1881,30 +1984,30 @@ check_cert_status() { ((days = stampDiff / 86400)) ((remainingDays = 90 - days)) tlsStatus=${remainingDays} - [[ ${remainingDays} -le 0 ]] && tlsStatus="${Red}已过期${Font}" + [[ ${remainingDays} -le 0 ]] && tlsStatus="${Red}$(gettext "已过期")${Font}" echo -e "\n" - log_echo "${Green}证书生成日期: $(date -d "@${modifyTime}" +"%F %H:%M:%S")${Font}" - log_echo "${Green}证书生成天数: ${days}${Font}" - log_echo "${Green}证书剩余天数: ${tlsStatus}${Font}" + log_echo "${Green}$(gettext "证书生成日期"): $(date -d "@${modifyTime}" +"%F %H:%M:%S")${Font}" + log_echo "${Green}$(gettext "证书生成天数"): ${days}${Font}" + log_echo "${Green}$(gettext "证书剩余天数"): ${tlsStatus}${Font}" echo -e "\n" if [[ ${remainingDays} -le 0 ]]; then echo -e "\n" - log_echo "${Warning} ${YellowBG} 是否立即更新证书 [Y/${Red}N${Font}${YellowBG}]? ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "是否立即更新证书") [Y/${Red}N${Font}${YellowBG}]? ${Font}" read -r cert_update_manuel_fq case $cert_update_manuel_fq in [yY][eE][sS] | [yY]) systemctl stop xray - judge "Xray 停止" + judge "$(gettext "Xray 停止")" cert_update_manuel ;; *) ;; esac fi else - log_echo "${Error} ${RedBG} 证书签发工具不存在, 请确认是否证书为脚本签发! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "证书签发工具不存在, 请确认是否证书为脚本签发!") ${Font}" fi else - log_echo "${Error} ${RedBG} 当前模式不支持此操作! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "当前模式不支持此操作!") ${Font}" fi } @@ -1913,24 +2016,24 @@ cert_update_manuel() { if [[ -f "${amce_sh_file}" ]]; then "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" else - log_echo "${Error} ${RedBG} 证书签发工具不存在, 请确认是否证书为脚本签发! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "证书签发工具不存在, 请确认是否证书为脚本签发!") ${Font}" fi host="$(info_extraction host)" "$HOME"/.acme.sh/acme.sh --installcert -d "${host}" --fullchainpath ${ssl_chainpath}/xray.crt --keypath ${ssl_chainpath}/xray.key --ecc - judge "证书更新" + judge "$(gettext "证书更新")" service_restart else - log_echo "${Error} ${RedBG} 当前模式不支持此操作! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "当前模式不支持此操作!") ${Font}" fi } set_fail2ban() { mf_remote_url="https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/fail2ban_manager.sh" if [ ! -f "${idleleo_dir}/fail2ban_manager.sh" ]; then - log_echo "${Info} ${Green} 本地文件 fail2ban_manager.sh 不存在,正在下载... ${Font}" + log_echo "${Info} ${Green} $(gettext "本地文件 fail2ban_manager.sh 不存在,正在下载...") ${Font}" curl -sL "$mf_remote_url" -o "${idleleo_dir}/fail2ban_manager.sh" if [ $? -ne 0 ]; then - log_echo "${Error} ${RedBG} 下载失败,请手动下载并安装新版本 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "下载失败,请手动下载并安装新版本") ${Font}" return 1 fi chmod +x "${idleleo_dir}/fail2ban_manager.sh" @@ -1941,11 +2044,11 @@ set_fail2ban() { clean_logs() { local cron_file logrotate_config echo -e "\n" - log_echo "${Green} 检测到日志文件大小如下: ${Font}" + log_echo "${Green} $(gettext "检测到日志文件大小如下:") ${Font}" log_echo "${Green}$(du -sh /var/log/xray ${nginx_dir}/logs)${Font}" - timeout "即将清除!" + timeout "$(gettext "即将清除!")" for i in $(find /var/log/xray/ ${nginx_dir}/logs -name "*.log"); do cat /dev/null >"$i"; done - judge "日志清理" + judge "$(gettext "日志清理")" #以下为兼容代码,1个大版本后删除 if [[ "${ID}" == "centos" ]]; then @@ -1955,46 +2058,46 @@ clean_logs() { fi if [[ $(grep -c "find /var/log/xray/ /etc/nginx/logs -name" "$cron_file") -ne '0' ]]; then - log_echo "${Warning} ${YellowBG} 已设置旧版自动清理日志任务 ${Font}" - log_echo "${GreenBG} 是否需要删除旧版自动清理日志任务 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "已设置旧版自动清理日志任务") ${Font}" + log_echo "${GreenBG} $(gettext "是否需要删除旧版自动清理日志任务") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r delete_task case $delete_task in [nN][oO] | [nN]) - log_echo "${OK} ${Green} 保留现有自动清理日志任务 ${Font}" + log_echo "${OK} ${Green} $(gettext "保留现有自动清理日志任务") ${Font}" return ;; *) sed -i "/find \/var\/log\/xray\/ \/etc\/nginx\/logs -name/d" "$cron_file" - judge "删除旧版自动清理日志任务" + judge "$(gettext "删除旧版自动清理日志任务")" ;; esac fi #兼容代码结束 echo -e "\n" - log_echo "${GreenBG} 是否需要设置自动清理日志 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${GreenBG} $(gettext "是否需要设置自动清理日志") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r auto_clean_logs_fq case $auto_clean_logs_fq in [nN][oO] | [nN]) - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear ;; *) - log_echo "${OK} ${Green} 将在 每周三 04:00 自动清空日志 ${Font}" + log_echo "${OK} ${Green} $(gettext "将在 每周三 04:00 自动清空日志") ${Font}" logrotate_config="/etc/logrotate.d/xray_log_cleanup" if [[ -f "$logrotate_config" ]]; then - log_echo "${Warning} ${YellowBG} 已设置自动清理日志任务 ${Font}" - log_echo "${GreenBG} 是否需要删除现有自动清理日志任务 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "已设置自动清理日志任务") ${Font}" + log_echo "${GreenBG} $(gettext "是否需要删除现有自动清理日志任务") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r delete_task case $delete_task in [yY][eE][sS] | [yY]) rm -f "$logrotate_config" - judge "删除自动清理日志任务" + judge "$(gettext "删除自动清理日志任务")" ;; *) - log_echo "${OK} ${Green} 保留现有自动清理日志任务 ${Font}" + log_echo "${OK} ${Green} $(gettext "保留现有自动清理日志任务") ${Font}" return ;; esac @@ -2009,7 +2112,7 @@ clean_logs() { echo " create 640 nobody nogroup" >> "$logrotate_config" echo "}" >> "$logrotate_config" - judge "设置自动清理日志" + judge "$(gettext "设置自动清理日志")" ;; esac } @@ -2115,49 +2218,49 @@ vless_qr_link_image() { elif [[ ${tls_mode} == "Reality" ]]; then vless_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction port)?security=reality&flow=xtls-rprx-vision&fp=chrome&pbk=$(info_extraction publicKey)&sni=$(info_extraction serverNames)&target=$(info_extraction target)&sid=$(info_extraction shortIds)#$(vless_urlquote $(info_extraction host))+Reality%E5%8D%8F%E8%AE%AE" if [[ ${ws_grpc_mode} == "onlyws" ]]; then - vless_ws_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction ws_port)?path=%2f$(vless_urlquote $(info_extraction path))%3Fed%3D2048&encryption=none&type=ws#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ACws%E5%8D%8F%E8%AE%AE" + vless_ws_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction ws_port)?path=%2f$(vless_urlquote $(info_extraction path))%3Fed%3D2048&encryption=none&type=ws#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ADws%E5%8D%8F%E8%AE%AE" elif [[ ${ws_grpc_mode} == "onlygRPC" ]]; then - vless_grpc_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction grpc_port)?serviceName=$(vless_urlquote $(info_extraction serviceName))&encryption=none&type=grpc#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ACgrpc%E5%8D%8F%E8%AE%AE" + vless_grpc_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction grpc_port)?serviceName=$(vless_urlquote $(info_extraction serviceName))&encryption=none&type=grpc#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ADgrpc%E5%8D%8F%E8%AE%AE" elif [[ ${ws_grpc_mode} == "all" ]]; then - vless_ws_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction ws_port)?path=%2f$(vless_urlquote $(info_extraction path))%3Fed%3D2048&encryption=none&type=ws#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ACws%E5%8D%8F%E8%AE%AE" - vless_grpc_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction grpc_port)?serviceName=$(vless_urlquote $(info_extraction serviceName))&encryption=none&type=grpc#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ACgrpc%E5%8D%8F%E8%AE%AE" + vless_ws_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction ws_port)?path=%2f$(vless_urlquote $(info_extraction path))%3Fed%3D2048&encryption=none&type=ws#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ADws%E5%8D%8F%E8%AE%AE" + vless_grpc_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction grpc_port)?serviceName=$(vless_urlquote $(info_extraction serviceName))&encryption=none&type=grpc#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ADgrpc%E5%8D%8F%E8%AE%AE" fi elif [[ ${tls_mode} == "None" ]]; then if [[ ${ws_grpc_mode} == "onlyws" ]]; then - vless_ws_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction ws_port)?path=%2f$(vless_urlquote $(info_extraction path))%3Fed%3D2048&encryption=none&type=ws#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ACws%E5%8D%8F%E8%AE%AE" + vless_ws_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction ws_port)?path=%2f$(vless_urlquote $(info_extraction path))%3Fed%3D2048&encryption=none&type=ws#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ADws%E5%8D%8F%E8%AE%AE" elif [[ ${ws_grpc_mode} == "onlygRPC" ]]; then - vless_grpc_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction grpc_port)?serviceName=$(vless_urlquote $(info_extraction serviceName))&encryption=none&type=grpc#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ACgrpc%E5%8D%8F%E8%AE%AE" + vless_grpc_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction grpc_port)?serviceName=$(vless_urlquote $(info_extraction serviceName))&encryption=none&type=grpc#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ADgrpc%E5%8D%8F%E8%AE%AE" elif [[ ${ws_grpc_mode} == "all" ]]; then - vless_ws_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction ws_port)?path=%2f$(vless_urlquote $(info_extraction path))%3Fed%3D2048&encryption=none&type=ws#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ACws%E5%8D%8F%E8%AE%AE" - vless_grpc_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction grpc_port)?serviceName=$(vless_urlquote $(info_extraction serviceName))&encryption=none&type=grpc#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ACgrpc%E5%8D%8F%E8%AE%AE" + vless_ws_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction ws_port)?path=%2f$(vless_urlquote $(info_extraction path))%3Fed%3D2048&encryption=none&type=ws#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ADws%E5%8D%8F%E8%AE%AE" + vless_grpc_link="vless://$(info_extraction id)@$(vless_urlquote $(info_extraction host)):$(info_extraction grpc_port)?serviceName=$(vless_urlquote $(info_extraction serviceName))&encryption=none&type=grpc#$(vless_urlquote $(info_extraction host))+%E5%8D%95%E7%8B%ADgrpc%E5%8D%8F%E8%AE%AE" fi fi { echo -e "\n" - log_echo "${Red} —————————————— Xray 配置分享 —————————————— ${Font}" + log_echo "${Red} —————————————— $(gettext "Xray 配置分享") —————————————— ${Font}" if [[ ${tls_mode} == "Reality" ]]; then - log_echo "${Red} URL 分享链接:${Font} ${vless_link}" - log_echo "$Red 二维码: $Font" + log_echo "${Red} $(gettext "URL 分享链接"):${Font} ${vless_link}" + log_echo "${Red} $(gettext "二维码"): ${Font}" echo -n "${vless_link}" | qrencode -o - -t utf8 echo -e "\n" fi if [[ ${ws_grpc_mode} == "onlyws" ]]; then - log_echo "${Red} ws URL 分享链接:${Font} ${vless_ws_link}" - log_echo "$Red 二维码: $Font" + log_echo "${Red} $(gettext "ws URL 分享链接"):${Font} ${vless_ws_link}" + log_echo "${Red} $(gettext "二维码"): ${Font}" echo -n "${vless_ws_link}" | qrencode -o - -t utf8 echo -e "\n" elif [[ ${ws_grpc_mode} == "onlygRPC" ]]; then - log_echo "${Red} gRPC URL 分享链接:${Font} ${vless_grpc_link}" - log_echo "$Red 二维码: $Font" + log_echo "${Red} $(gettext "gRPC URL 分享链接"):${Font} ${vless_grpc_link}" + log_echo "${Red} $(gettext "二维码"): ${Font}" echo -n "${vless_grpc_link}" | qrencode -o - -t utf8 echo -e "\n" elif [[ ${ws_grpc_mode} == "all" ]]; then - log_echo "${Red} ws URL 分享链接:${Font} ${vless_ws_link}" - log_echo "$Red 二维码: $Font" + log_echo "${Red} $(gettext "ws URL 分享链接"):${Font} ${vless_ws_link}" + log_echo "${Red} $(gettext "二维码"): ${Font}" echo -n "${vless_ws_link}" | qrencode -o - -t utf8 echo -e "\n" - log_echo "${Red} gRPC URL 分享链接:${Font} ${vless_grpc_link}" - log_echo "$Red 二维码: $Font" + log_echo "${Red} $(gettext "gRPC URL 分享链接"):${Font} ${vless_grpc_link}" + log_echo "${Red} $(gettext "二维码"): ${Font}" echo -n "${vless_grpc_link}" | qrencode -o - -t utf8 echo -e "\n" fi @@ -2166,7 +2269,7 @@ vless_qr_link_image() { vless_link_image_choice() { echo -e "\n" - log_echo "${GreenBG} 生成分享链接: ${Font}" + log_echo "${GreenBG} $(gettext "生成分享链接"): ${Font}" vless_qr_link_image } @@ -2180,80 +2283,80 @@ basic_information() { echo -e "\n" case ${shell_mode} in Nginx+ws+TLS) - log_echo "${OK} ${GreenBG} Xray+Nginx+ws+TLS 安装成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "Xray+Nginx+ws+TLS 安装成功") ${Font}" ;; Nginx+gRPC+TLS) - log_echo "${OK} ${GreenBG} Xray+Nginx+grpc+TLS 安装成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "Xray+Nginx+grpc+TLS 安装成功") ${Font}" ;; Nginx+ws+gRPC+TLS) - log_echo "${OK} ${GreenBG} Xray+Nginx+ws+gRPC+TLS 安装成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "Xray+Nginx+ws+gRPC+TLS 安装成功") ${Font}" ;; Reality) - log_echo "${OK} ${GreenBG} Xray+Reality 安装成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "Xray+Reality 安装成功") ${Font}" ;; Reality+ws) - log_echo "${OK} ${GreenBG} Xray+Reality+ws 安装成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "Xray+Reality+ws 安装成功") ${Font}" ;; Reality+gRPC) - log_echo "${OK} ${GreenBG} Xray+Reality+gRPC 安装成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "Xray+Reality+gRPC 安装成功") ${Font}" ;; Reality+ws+gRPC) - log_echo "${OK} ${GreenBG} Xray+Reality+ws+gRPC 安装成功 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "Xray+Reality+ws+gRPC 安装成功") ${Font}" ;; - ws?ONLY) - log_echo "${OK} ${GreenBG} ws ONLY 安装成功 ${Font}" + ws\ ONLY) + log_echo "${OK} ${GreenBG} $(gettext "ws ONLY 安装成功") ${Font}" ;; - gRPC?ONLY) - log_echo "${OK} ${GreenBG} gRPC ONLY 安装成功 ${Font}" + gRPC\ ONLY) + log_echo "${OK} ${GreenBG} $(gettext "gRPC ONLY 安装成功") ${Font}" ;; - ws+gRPC?ONLY) - log_echo "${OK} ${GreenBG} ws+gRPC ONLY 安装成功 ${Font}" + ws+gRPC\ ONLY) + log_echo "${OK} ${GreenBG} $(gettext "ws+gRPC ONLY 安装成功") ${Font}" ;; esac echo -e "\n" - log_echo "${Warning} ${YellowBG} VLESS 目前分享链接规范为实验阶段, 请自行判断是否适用 ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "VLESS 目前分享链接规范为实验阶段, 请自行判断是否适用") ${Font}" echo -e "\n" - log_echo "${Red} —————————————— Xray 配置信息 —————————————— ${Font}" - log_echo "${Red} 主机 (host):${Font} $(info_extraction host) " + log_echo "${Red} —————————————— $(gettext "Xray 配置信息") —————————————— ${Font}" + log_echo "${Red} $(gettext "主机") (host):${Font} $(info_extraction host) " if [[ ${tls_mode} == "None" ]]; then if [[ ${ws_grpc_mode} == "onlyws" ]]; then - log_echo "${Red} ws 端口 (port):${Font} $(info_extraction ws_port) " + log_echo "${Red} $(gettext "ws 端口") (port):${Font} $(info_extraction ws_port) " elif [[ ${ws_grpc_mode} == "onlygRPC" ]]; then - log_echo "${Red} gRPC 端口 (port):${Font} $(info_extraction grpc_port) " + log_echo "${Red} $(gettext "gRPC 端口") (port):${Font} $(info_extraction grpc_port) " elif [[ ${ws_grpc_mode} == "all" ]]; then - log_echo "${Red} ws 端口 (port):${Font} $(info_extraction ws_port) " - log_echo "${Red} gRPC 端口 (port):${Font} $(info_extraction grpc_port) " + log_echo "${Red} $(gettext "ws 端口") (port):${Font} $(info_extraction ws_port) " + log_echo "${Red} $(gettext "gRPC 端口") (port):${Font} $(info_extraction grpc_port) " fi else - log_echo "${Red} 端口 (port):${Font} $(info_extraction port) " + log_echo "${Red} $(gettext "端口") (port):${Font} $(info_extraction port) " fi if [[ ${tls_mode} == "TLS" ]]; then if [[ ${ws_grpc_mode} == "onlyws" ]]; then - log_echo "${Red} Xray ws 端口 (inbound_port):${Font} $(info_extraction ws_port) " + log_echo "${Red} $(gettext "Xray ws 端口") (inbound_port):${Font} $(info_extraction ws_port) " elif [[ ${ws_grpc_mode} == "onlygRPC" ]]; then - log_echo "${Red} Xray gRPC 端口 (inbound_port):${Font} $(info_extraction grpc_port) " + log_echo "${Red} $(gettext "Xray gRPC 端口") (inbound_port):${Font} $(info_extraction grpc_port) " elif [[ ${ws_grpc_mode} == "all" ]]; then - log_echo "${Red} Xray ws 端口 (inbound_port):${Font} $(info_extraction ws_port) " - log_echo "${Red} Xray gRPC 端口 (inbound_port):${Font} $(info_extraction grpc_port) " + log_echo "${Red} $(gettext "Xray ws 端口") (inbound_port):${Font} $(info_extraction ws_port) " + log_echo "${Red} $(gettext "Xray gRPC 端口") (inbound_port):${Font} $(info_extraction grpc_port) " fi fi - log_echo "${Red} UUIDv5 映射字符串:${Font} $(info_extraction idc)" - log_echo "${Red} 用户id (UUID):${Font} $(info_extraction id)" + log_echo "${Red} $(gettext "UUIDv5 映射字符串"):${Font} $(info_extraction idc)" + log_echo "${Red} $(gettext "用户id") (UUID):${Font} $(info_extraction id)" - log_echo "${Red} 加密 (encryption):${Font} None " - log_echo "${Red} 传输协议 (network):${Font} $(info_extraction net) " - log_echo "${Red} 底层传输安全 (tls):${Font} $(info_extraction tls) " + log_echo "${Red} $(gettext "加密") (encryption):${Font} None " + log_echo "${Red} $(gettext "传输协议") (network):${Font} $(info_extraction net) " + log_echo "${Red} $(gettext "底层传输安全") (tls):${Font} $(info_extraction tls) " if [[ ${tls_mode} != "Reality" ]]; then if [[ ${ws_grpc_mode} == "onlyws" ]]; then - log_echo "${Red} 路径 (path 不要落下/):${Font} /$(info_extraction path) " + log_echo "${Red} $(gettext "路径") (path $(gettext "不要落下/")):${Font} /$(info_extraction path) " elif [[ ${ws_grpc_mode} == "onlygRPC" ]]; then - log_echo "${Red} serviceName (不需要加/):${Font} $(info_extraction serviceName) " + log_echo "${Red} serviceName ($(gettext "不需要加/")):${Font} $(info_extraction serviceName) " elif [[ ${ws_grpc_mode} == "all" ]]; then - log_echo "${Red} 路径 (path 不要落下/):${Font} /$(info_extraction path) " - log_echo "${Red} serviceName (不需要加/):${Font} $(info_extraction serviceName) " + log_echo "${Red} $(gettext "路径") (path $(gettext "不要落下/")):${Font} /$(info_extraction path) " + log_echo "${Red} serviceName ($(gettext "不需要加/")):${Font} $(info_extraction serviceName) " fi else - log_echo "${Red} 流控 (flow):${Font} xtls-rprx-vision " + log_echo "${Red} $(gettext "流控") (flow):${Font} xtls-rprx-vision " log_echo "${Red} target:${Font} $(info_extraction target) " log_echo "${Red} serverNames:${Font} $(info_extraction serverNames) " log_echo "${Red} privateKey:${Font} $(info_extraction privateKey) " @@ -2261,16 +2364,16 @@ basic_information() { log_echo "${Red} shortIds:${Font} $(info_extraction shortIds) " if [[ "$reality_add_more" == "on" ]]; then if [[ ${ws_grpc_mode} == "onlyws" ]]; then - log_echo "${Red} ws 端口 (port):${Font} $(info_extraction ws_port) " - log_echo "${Red} ws 路径 (不要落下/):${Font} /$(info_extraction ws_path) " + log_echo "${Red} $(gettext "ws 端口") (port):${Font} $(info_extraction ws_port) " + log_echo "${Red} $(gettext "ws 路径") ($(gettext "不要落下/")):${Font} /$(info_extraction ws_path) " elif [[ ${ws_grpc_mode} == "onlygRPC" ]]; then - log_echo "${Red} gRPC 端口 (port):${Font} $(info_extraction grpc_port) " - log_echo "${Red} gRPC serviceName (不需要加/):${Font} $(info_extraction grpc_serviceName) " + log_echo "${Red} $(gettext "gRPC 端口") (port):${Font} $(info_extraction grpc_port) " + log_echo "${Red} gRPC serviceName ($(gettext "不需要加/")):${Font} $(info_extraction grpc_serviceName) " elif [[ ${ws_grpc_mode} == "all" ]]; then - log_echo "${Red} ws 端口 (port):${Font} $(info_extraction ws_port) " - log_echo "${Red} ws 路径 (不要落下/):${Font} /$(info_extraction ws_path) " - log_echo "${Red} gRPC 端口 (port):${Font} $(info_extraction grpc_port) " - log_echo "${Red} gRPC serviceName (不需要加/):${Font} $(info_extraction grpc_serviceName) " + log_echo "${Red} $(gettext "ws 端口") (port):${Font} $(info_extraction ws_port) " + log_echo "${Red} $(gettext "ws 路径") ($(gettext "不要落下/")):${Font} /$(info_extraction ws_path) " + log_echo "${Red} $(gettext "gRPC 端口") (port):${Font} $(info_extraction grpc_port) " + log_echo "${Red} gRPC serviceName ($(gettext "不需要加/")):${Font} $(info_extraction grpc_serviceName) " fi fi fi @@ -2284,12 +2387,12 @@ show_information() { ssl_judge_and_install() { cd $HOME echo -e "\n" - log_echo "${GreenBG} 即将申请证书, 支持使用自定义证书 ${Font}" - log_echo "${Green} 如需使用自定义证书, 请按如下步骤: ${Font}" - log_echo " 1. 将证书文件重命名: 私钥(xray.key)、证书(xray.crt)" - log_echo " 2. 将重命名后的证书文件放入 ${ssl_chainpath} 目录后再运行脚本" - log_echo " 3. 重新运行脚本" - log_echo "${GreenBG} 是否继续 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${GreenBG} $(gettext "即将申请证书, 支持使用自定义证书") ${Font}" + log_echo "${Green} $(gettext "如需使用自定义证书, 请按如下步骤:") ${Font}" + log_echo " $(gettext "1. 将证书文件重命名: 私钥(xray.key)、证书(xray.crt)")" + log_echo " $(gettext "2. 将重命名后的证书文件放入") ${ssl_chainpath} $(gettext "目录后再运行脚本")" + log_echo " $(gettext "3. 重新运行脚本")" + log_echo "${GreenBG} $(gettext "是否继续") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r ssl_continue case $ssl_continue in [nN][oO] | [nN]) @@ -2297,51 +2400,51 @@ ssl_judge_and_install() { ;; *) if [[ -f "${ssl_chainpath}/xray.key" && -f "${ssl_chainpath}/xray.crt" ]] && [[ -f "$HOME/.acme.sh/${domain}_ecc/${domain}.key" && -f "$HOME/.acme.sh/${domain}_ecc/${domain}.cer" ]]; then - log_echo "${GreenBG} 所有证书文件均已存在, 是否保留 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${GreenBG} $(gettext "所有证书文件均已存在, 是否保留") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r ssl_delete_1 case $ssl_delete_1 in [nN][oO] | [nN]) delete_tls_key_and_crt rm -rf ${ssl_chainpath}/* - log_echo "${OK} ${GreenBG} 已删除 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已删除") ${Font}" ssl_install acme ;; *) chown -fR nobody:nogroup ${ssl_chainpath}/* - judge "证书应用" + judge "$(gettext "证书应用")" ;; esac elif [[ -f "${ssl_chainpath}/xray.key" || -f "${ssl_chainpath}/xray.crt" ]] && [[ ! -f "$HOME/.acme.sh/${domain}_ecc/${domain}.key" && ! -f "$HOME/.acme.sh/${domain}_ecc/${domain}.cer" ]]; then - log_echo "${GreenBG} 证书文件已存在, 是否保留 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${GreenBG} $(gettext "证书文件已存在, 是否保留") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r ssl_delete_2 case $ssl_delete_2 in [nN][oO] | [nN]) rm -rf ${ssl_chainpath}/* - log_echo "${OK} ${GreenBG} 已删除 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已删除") ${Font}" ssl_install acme ;; *) chown -fR nobody:nogroup ${ssl_chainpath}/* - judge "证书应用" + judge "$(gettext "证书应用")" ssl_self="on" ;; esac elif [[ -f "$HOME/.acme.sh/${domain}_ecc/${domain}.key" && -f "$HOME/.acme.sh/${domain}_ecc/${domain}.cer" ]] && [[ ! -f "${ssl_chainpath}/xray.key" || ! -f "${ssl_chainpath}/xray.crt" ]]; then - log_echo "${GreenBG} 证书签发残留文件已存在, 是否保留 [${Red}Y${Font}${GreenBG}/N]? ${Font}" + log_echo "${GreenBG} $(gettext "证书签发残留文件已存在, 是否保留") [${Red}Y${Font}${GreenBG}/N]? ${Font}" read -r ssl_delete_3 case $ssl_delete_3 in [nN][oO] | [nN]) delete_tls_key_and_crt - log_echo "${OK} ${GreenBG} 已删除 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已删除") ${Font}" ssl_install acme ;; *) "$HOME"/.acme.sh/acme.sh --installcert -d "${domain}" --fullchainpath ${ssl_chainpath}/xray.crt --keypath ${ssl_chainpath}/xray.key --ecc chown -fR nobody:nogroup ${ssl_chainpath}/* - judge "证书应用" + judge "$(gettext "证书应用")" ;; esac else @@ -2371,47 +2474,31 @@ PrivateTmp=true WantedBy=multi-user.target EOF - judge "Nginx systemd ServerFile 添加" + judge "$(gettext "Nginx systemd ServerFile 添加")" systemctl daemon-reload } tls_type() { if [[ -f "${nginx_conf}" ]] && [[ ${tls_mode} == "TLS" ]]; then echo -e "\n" - log_echo "${GreenBG} 请选择支持的 TLS 版本 (default:2): ${Font}" - log_echo "${GreenBG} 建议选择 TLS1.3 only (安全模式) ${Font}" - echo -e "1: TLS1.2 and TLS1.3 (兼容模式)" - echo -e "${Red}2${Font}: TLS1.3 only (安全模式)" + log_echo "${GreenBG} $(gettext "请选择支持的 TLS 版本") (default:2): ${Font}" + log_echo "${GreenBG} $(gettext "建议选择 TLS1.3 only (安全模式)") ${Font}" + echo -e "1: TLS1.2 and TLS1.3 ($(gettext "兼容模式"))" + echo -e "${Red}2${Font}: TLS1.3 only ($(gettext "安全模式"))" local choose_tls - read_optimize "请输入: " "choose_tls" 2 1 2 "请输入有效的数字" + read_optimize "$(gettext "请输入"): " "choose_tls" 2 1 2 "$(gettext "请输入有效的数字")" if [[ ${choose_tls} == 1 ]]; then - # if [[ ${tls_mode} == "TLS" ]]; then - # sed -i "s/^\( *\)ssl_protocols\( *\).*/\1ssl_protocols\2TLSv1.2 TLSv1.3;/" $nginx_conf - # else - # log_echo "${Error} ${RedBG} Reality 用且仅用 TLS1.3, 请选择 TLS1.3 only (安全模式)! ${Font}" - # tls_type - # fi - # sed -i "s/^\( *\)ssl_protocols\( *\).*/\1ssl_protocols\2TLSv1.2 TLSv1.3;/" $nginx_conf - # log_echo "${OK} ${GreenBG} 已切换至 TLS1.2 and TLS1.3 ${Font}" - log_echo "${Error} ${RedBG} 从 2.2.1 版本起, 由于启用 h3 仅支持 TLS1.3, 请选择 TLS1.3 only (安全模式)! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "从 2.2.1 版本起, 由于启用 h3 仅支持 TLS1.3, 请选择 TLS1.3 only (安全模式)")! ${Font}" tls_type else - # if [[ ${tls_mode} == "TLS" ]]; then - # sed -i "s/^\( *\)ssl_protocols\( *\).*/\1ssl_protocols\2TLSv1.3;/" $nginx_conf - # ## else - # ##sed -i "s/^\( *\)\"minVersion\".*/\1\"minVersion\": \"1.3\",/" ${xray_conf} - # fi sed -i "s/^\( *\)ssl_protocols\( *\).*/\1ssl_protocols\2TLSv1.3;/" $nginx_conf - log_echo "${OK} ${GreenBG} 已切换至 TLS1.3 only ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已切换至 TLS1.3 only") ${Font}" fi - # if [[ ${tls_mode} == "TLS" ]]; then - [[ -f "${nginx_systemd_file}" ]] && systemctl restart nginx && judge "Nginx 重启" - # elif [[ ${tls_mode} == "Reality" ]]; then + [[ -f "${nginx_systemd_file}" ]] && systemctl restart nginx && judge "$(gettext "Nginx 重启")" systemctl restart xray - judge "Xray 重启" - # fi + judge "$(gettext "Xray 重启")" else - log_echo "${Error} ${RedBG} Nginx/配置文件不存在 或 当前模式不支持 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "Nginx/配置文件不存在 或 当前模式不支持") ${Font}" fi } @@ -2432,39 +2519,39 @@ reset_UUID() { service_restart reset_vless_qr_config else - log_echo "${Warning} ${YellowBG} 请先安装 Xray ! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请先安装 Xray") ! ${Font}" fi } reset_port() { if [[ -f "${xray_qr_config_file}" ]] && [[ -f "${xray_conf}" ]]; then if [[ ${tls_mode} == "TLS" ]]; then - read_optimize "请输入连接端口 (默认值:443):" "port" 443 0 65535 "请输入 0-65535 之间的值!" + read_optimize "$(gettext "请输入连接端口") ($(gettext "默认值"):443):" "port" 443 0 65535 "$(gettext "请输入 0-65535 之间的值")!" modify_nginx_port jq --argjson port "${port}" '.port = $port' "${xray_qr_config_file}" > "${xray_qr_config_file}.tmp" mv "${xray_qr_config_file}.tmp" "${xray_qr_config_file}" - log_echo "${Green} 连接端口号: ${port} ${Font}" + log_echo "${Green} $(gettext "连接端口号"): ${port} ${Font}" elif [[ ${tls_mode} == "Reality" ]]; then - read_optimize "请输入连接端口 (默认值:443):" "port" 443 0 65535 "请输入 0-65535 之间的值!" + read_optimize "$(gettext "请输入连接端口") ($(gettext "默认值"):443):" "port" 443 0 65535 "$(gettext "请输入 0-65535 之间的值")!" xport=$((RANDOM % 1000 + 20000)) gport=$((RANDOM % 1000 + 30000)) if [[ ${ws_grpc_mode} == "onlyws" ]]; then - read_optimize "请输入 ws inbound_port:" "xport" "NULL" 0 65535 "请输入 0-65535 之间的值!" + read_optimize "$(gettext "请输入 ws inbound_port"):" "xport" "NULL" 0 65535 "$(gettext "请输入 0-65535 之间的值")!" port_exist_check "${xport}" gport=$((RANDOM % 1000 + 30000)) - log_echo "${Green} ws inbound_port: ${xport} ${Font}" + log_echo "${Green} $(gettext "ws inbound_port"): ${xport} ${Font}" elif [[ ${ws_grpc_mode} == "onlygrpc" ]]; then - read_optimize "请输入 gRPC inbound_port:" "gport" "NULL" 0 65535 "请输入 0-65535 之间的值!" + read_optimize "$(gettext "请输入 gRPC inbound_port"):" "gport" "NULL" 0 65535 "$(gettext "请输入 0-65535 之间的值")!" port_exist_check "${gport}" xport=$((RANDOM % 1000 + 20000)) - log_echo "${Green} gRPC inbound_port: ${gport} ${Font}" + log_echo "${Green} $(gettext "gRPC inbound_port"): ${gport} ${Font}" elif [[ ${ws_grpc_mode} == "all" ]]; then - read_optimize "请输入 ws inbound_port:" "xport" "NULL" 0 65535 "请输入 0-65535 之间的值!" - read_optimize "请输入 gRPC inbound_port:" "gport" "NULL" 0 65535 "请输入 0-65535 之间的值!" + read_optimize "$(gettext "请输入 ws inbound_port"):" "xport" "NULL" 0 65535 "$(gettext "请输入 0-65535 之间的值")!" + read_optimize "$(gettext "请输入 gRPC inbound_port"):" "gport" "NULL" 0 65535 "$(gettext "请输入 0-65535 之间的值")!" port_exist_check "${xport}" port_exist_check "${gport}" - log_echo "${Green} ws inbound_port: ${xport} ${Font}" - log_echo "${Green} gRPC inbound_port: ${gport} ${Font}" + log_echo "${Green} $(gettext "ws inbound_port"): ${xport} ${Font}" + log_echo "${Green} $(gettext "gRPC inbound_port"): ${gport} ${Font}" fi jq --argjson port "$port" \ --argjson ws_port "$xport" \ @@ -2475,22 +2562,22 @@ reset_port() { [[ ${reality_add_nginx} == "on" ]] && modify_nginx_port elif [[ ${tls_mode} == "None" ]]; then if [[ ${ws_grpc_mode} == "onlyws" ]]; then - read_optimize "请输入 ws inbound_port:" "xport" "NULL" 0 65535 "请输入 0-65535 之间的值!" + read_optimize "$(gettext "请输入 ws inbound_port"):" "xport" "NULL" 0 65535 "$(gettext "请输入 0-65535 之间的值")!" port_exist_check "${xport}" gport=$((RANDOM % 1000 + 30000)) - log_echo "${Green} ws inbound_port: ${xport} ${Font}" + log_echo "${Green} $(gettext "ws inbound_port"): ${xport} ${Font}" elif [[ ${ws_grpc_mode} == "onlygrpc" ]]; then - read_optimize "请输入 gRPC inbound_port:" "gport" "NULL" 0 65535 "请输入 0-65535 之间的值!" + read_optimize "$(gettext "请输入 gRPC inbound_port"):" "gport" "NULL" 0 65535 "$(gettext "请输入 0-65535 之间的值")!" port_exist_check "${gport}" xport=$((RANDOM % 1000 + 20000)) - log_echo "${Green} gRPC inbound_port: ${gport} ${Font}" + log_echo "${Green} $(gettext "gRPC inbound_port"): ${gport} ${Font}" elif [[ ${ws_grpc_mode} == "all" ]]; then - read_optimize "请输入 ws inbound_port:" "xport" "NULL" 0 65535 "请输入 0-65535 之间的值!" - read_optimize "请输入 gRPC inbound_port:" "gport" "NULL" 0 65535 "请输入 0-65535 之间的值!" + read_optimize "$(gettext "请输入 ws inbound_port"):" "xport" "NULL" 0 65535 "$(gettext "请输入 0-65535 之间的值")!" + read_optimize "$(gettext "请输入 gRPC inbound_port"):" "gport" "NULL" 0 65535 "$(gettext "请输入 0-65535 之间的值")!" port_exist_check "${xport}" port_exist_check "${gport}" - log_echo "${Green} ws inbound_port: ${xport} ${Font}" - log_echo "${Green} gRPC inbound_port: ${gport} ${Font}" + log_echo "${Green} $(gettext "ws inbound_port"): ${xport} ${Font}" + log_echo "${Green} $(gettext "gRPC inbound_port"): ${gport} ${Font}" fi jq --argjson ws_port "$xport" \ --argjson grpc_port "$gport" \ @@ -2502,7 +2589,7 @@ reset_port() { service_restart reset_vless_qr_config else - log_echo "${Warning} ${YellowBG} 请先安装 Xray ! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请先安装 Xray") ! ${Font}" fi } @@ -2524,52 +2611,52 @@ reset_target() { service_restart reset_vless_qr_config elif [[ ${tls_mode} != "Reality" ]]; then - log_echo "${Warning} ${YellowBG} 此模式不支持修改 target ! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "此模式不支持修改 target") ! ${Font}" else - log_echo "${Warning} ${YellowBG} 请先安装 Xray ! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请先安装 Xray") ! ${Font}" fi } show_user() { if [[ -f "${xray_qr_config_file}" ]] && [[ -f "${xray_conf}" ]] && [[ ${tls_mode} != "None" ]]; then echo -e "\n" - log_echo "${GreenBG} 即将显示用户, 一次仅能显示一个 ${Font}" + log_echo "${GreenBG} $(gettext "即将显示用户, 一次仅能显示一个") ${Font}" if [[ ${tls_mode} == "TLS" ]]; then - log_echo "${GreenBG} 请选择 显示用户使用的协议 ws/gRPC ${Font}" - echo -e "${Red}1${Font}: ws (默认)" + log_echo "${GreenBG} $(gettext "请选择 显示用户使用的协议 ws/gRPC") ${Font}" + echo -e "${Red}1${Font}: ws ($(gettext "默认"))" echo "2: gRPC" local choose_user_prot - read_optimize "请输入: " "choose_user_prot" 1 1 2 "请输入有效的数字" + read_optimize "$(gettext "请输入"): " "choose_user_prot" 1 1 2 "$(gettext "请输入有效的数字")" choose_user_prot=$((choose_user_prot - 1)) elif [[ ${tls_mode} == "Reality" ]]; then choose_user_prot=0 fi echo -e "\n" - log_echo "${GreenBG} 请选择 要显示的用户编号: ${Font}" + log_echo "${GreenBG} $(gettext "请选择 要显示的用户编号"): ${Font}" jq -r -c .inbounds[${choose_user_prot}].settings.clients[].email ${xray_conf} | awk '{print NR""": "$0}' local show_user_index - read_optimize "请输入: " "show_user_index" "NULL" + read_optimize "$(gettext "请输入"): " "show_user_index" "NULL" if [[ $(jq -r '.inbounds['${choose_user_prot}'].settings.clients|length' ${xray_conf}) -lt ${show_user_index} ]] || [[ ${show_user_index} == 0 ]]; then - log_echo "${Error} ${RedBG} 选择错误! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "选择错误") ! ${Font}" show_user elif [[ ${show_user_index} == 1 ]]; then - log_echo "${Error} ${RedBG} 请直接在主菜单选择 [15] 显示主用户 ${Font}" - timeout "回到菜单!" + log_echo "${Error} ${RedBG} $(gettext "请直接在主菜单选择 [15] 显示主用户") ${Font}" + timeout "$(gettext "回到菜单") !" menu elif [[ ${show_user_index} -gt 1 ]]; then show_user_index=$((show_user_index - 1)) user_email=$(jq -r -c '.inbounds['${choose_user_prot}'].settings.clients['${show_user_index}'].email' ${xray_conf}) user_id=$(jq -r -c '.inbounds['${choose_user_prot}'].settings.clients['${show_user_index}'].id' ${xray_conf}) elif [[ ! -z $(echo ${show_user_index} | sed 's/[0-9]//g') ]] || [[ ${show_user_index} == '' ]]; then - log_echo "${Error} ${RedBG} 选择错误! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "选择错误") ! ${Font}" show_user else - log_echo "${Warning} ${YellowBG} 请先检测 Xray 是否正确安装! ${Font}" - timeout "回到菜单!" + log_echo "${Warning} ${YellowBG} $(gettext "请先检测 Xray 是否正确安装") ! ${Font}" + timeout "$(gettext "回到菜单") !" menu fi if [[ ! -z ${user_email} ]] && [[ ! -z ${user_id} ]]; then - log_echo "${Green} 用户名: ${user_email} ${Font}" + log_echo "${Green} $(gettext "用户名"): ${user_email} ${Font}" log_echo "${Green} UUID: ${user_id} ${Font}" if [[ ${tls_mode} == "TLS" ]]; then if [[ ${choose_user_prot} == 0 ]]; then @@ -2580,11 +2667,11 @@ show_user() { elif [[ ${tls_mode} == "Reality" ]]; then user_vless_link="vless://${user_id}@$(vless_urlquote $(info_extraction host)):$(info_extraction port)?security=tls&encryption=none&headerType=none&type=raw&flow=xtls-rprx-vision#$(vless_urlquote $(info_extraction host))+reality%E5%8D%8F%E8%AE%AE" fi - log_echo "${Red} URL 分享链接:${Font} ${user_vless_link}" + log_echo "${Red} $(gettext "URL 分享链接"):${Font} ${user_vless_link}" echo -n "${user_vless_link}" | qrencode -o - -t utf8 fi echo -e "\n" - log_echo "${GreenBG} 是否继续显示用户 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否继续显示用户") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r show_user_continue case $show_user_continue in [yY][eE][sS] | [yY]) @@ -2593,9 +2680,9 @@ show_user() { *) ;; esac elif [[ ${tls_mode} == "None" ]]; then - log_echo "${Warning} ${YellowBG} 此模式不支持删除用户! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "此模式不支持删除用户") ! ${Font}" else - log_echo "${Warning} ${YellowBG} 请先安装 Xray ! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请先安装 Xray") ! ${Font}" fi } @@ -2604,13 +2691,13 @@ add_user() { if [[ -f "${xray_qr_config_file}" ]] && [[ -f "${xray_conf}" ]] && [[ ${tls_mode} != "None" ]]; then service_stop echo -e "\n" - log_echo "${GreenBG} 即将添加用户, 一次仅能添加一个 ${Font}" + log_echo "${GreenBG} $(gettext "即将添加用户, 一次仅能添加一个") ${Font}" if [[ ${tls_mode} == "TLS" ]]; then - log_echo "${GreenBG} 请选择 添加用户使用的协议 ws/gRPC ${Font}" - echo -e "${Red}1${Font}: ws (默认)" + log_echo "${GreenBG} $(gettext "请选择 添加用户使用的协议 ws/gRPC") ${Font}" + echo -e "${Red}1${Font}: ws ($(gettext "默认"))" echo "2: gRPC" local choose_user_prot - read_optimize "请输入: " "choose_user_prot" 1 1 2 "请输入有效的数字" + read_optimize "$(gettext "请输入"): " "choose_user_prot" 1 1 2 "$(gettext "请输入有效的数字")" choose_user_prot=$((choose_user_prot - 1)) reality_user_more="" elif [[ ${tls_mode} == "Reality" ]]; then @@ -2628,12 +2715,12 @@ add_user() { if $reality_user_more != "" then ($reality_user_more | fromjson) else {} end + {"level": 0, "email": $custom_email} ]' "${xray_conf}" > "${xray_conf}.tmp" - judge "添加用户" + judge "$(gettext "添加用户")" mv "${xray_conf}.tmp" "${xray_conf}" jq ". += {\"multi_user\": \"yes\"}" ${xray_qr_config_file} > "${xray_qr_config_file}.tmp" mv "${xray_qr_config_file}.tmp" "${xray_qr_config_file}" echo -e "\n" - log_echo "${GreenBG} 是否继续添加用户 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否继续添加用户") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r add_user_continue case $add_user_continue in [yY][eE][sS] | [yY]) @@ -2643,9 +2730,9 @@ add_user() { esac service_start elif [[ ${tls_mode} == "None" ]]; then - log_echo "${Warning} ${YellowBG} 此模式不支持添加用户! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "此模式不支持添加用户") ! ${Font}" else - log_echo "${Warning} ${YellowBG} 请先安装 Xray ! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请先安装 Xray") ! ${Font}" fi } @@ -2653,38 +2740,38 @@ remove_user() { if [[ -f "${xray_qr_config_file}" ]] && [[ -f "${xray_conf}" ]] && [[ ${tls_mode} != "None" ]]; then service_stop echo -e "\n" - log_echo "${GreenBG} 即将删除用户, 一次仅能删除一个 ${Font}" + log_echo "${GreenBG} $(gettext "即将删除用户, 一次仅能删除一个") ${Font}" if [[ ${tls_mode} == "TLS" ]]; then - log_echo "${GreenBG} 请选择 删除用户使用的协议 ws/gRPC ${Font}" - echo -e "${Red}1${Font}: ws (默认)" + log_echo "${GreenBG} $(gettext "请选择 删除用户使用的协议 ws/gRPC") ${Font}" + echo -e "${Red}1${Font}: ws ($(gettext "默认"))" echo "2: gRPC" local choose_user_prot - read_optimize "请输入: " "choose_user_prot" 1 1 2 "请输入有效的数字" + read_optimize "$(gettext "请输入"): " "choose_user_prot" 1 1 2 "$(gettext "请输入有效的数字")" choose_user_prot=$((choose_user_prot - 1)) elif [[ ${tls_mode} == "Reality" ]]; then choose_user_prot=0 fi echo -e "\n" - log_echo "${GreenBG} 请选择 要删除的用户编号 ${Font}" + log_echo "${GreenBG} $(gettext "请选择 要删除的用户编号") ${Font}" jq -r -c .inbounds[${choose_user_prot}].settings.clients[].email ${xray_conf} | awk '{print NR""": "$0}' local del_user_index - read_optimize "请输入: " "del_user_index" "NULL" + read_optimize "$(gettext "请输入"): " "del_user_index" "NULL" if [[ $(jq -r '.inbounds['${choose_user_prot}'].settings.clients|length' ${xray_conf}) -lt ${del_user_index} ]] || [[ ${show_user_index} == 0 ]]; then - log_echo "${Error} ${RedBG} 选择错误! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "选择错误") ! ${Font}" remove_user elif [[ ${del_user_index} == 1 ]]; then echo -e "\n" - log_echo "${Error} ${RedBG} 请直接在主菜单修改主用户的 UUID/Email ! ${Font}" - timeout "回到菜单!" + log_echo "${Error} ${RedBG} $(gettext "请直接在主菜单修改主用户的 UUID/Email") ! ${Font}" + timeout "$(gettext "回到菜单") !" menu elif [[ ${del_user_index} -gt 1 ]]; then del_user_index=$((del_user_index - 1)) jq --argjson choose_user_prot "${choose_user_prot}" --argjson del_user_index "${del_user_index}" \ 'del(.inbounds[$choose_user_prot].settings.clients[$del_user_index])' ${xray_conf} > "${xray_conf}.tmp" - judge "删除用户" + judge "$(gettext "删除用户")" mv "${xray_conf}.tmp" "${xray_conf}" echo -e "\n" - log_echo "${GreenBG} 是否继续删除用户 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否继续删除用户") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r remove_user_continue case $remove_user_continue in [yY][eE][sS] | [yY]) @@ -2693,41 +2780,41 @@ remove_user() { *) ;; esac elif [[ ! -z $(echo ${del_user_index} | sed 's/[0-9]//g') ]] || [[ ${del_user_index} == '' ]]; then - log_echo "${Error} ${RedBG} 选择错误! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "选择错误") ! ${Font}" remove_user else - log_echo "${Warning} ${YellowBG} 请先检测 Xray 是否正确安装! ${Font}" - timeout "回到菜单!" + log_echo "${Warning} ${YellowBG} $(gettext "请先检测 Xray 是否正确安装") ! ${Font}" + timeout "$(gettext "回到菜单") !" menu fi service_start elif [[ ${tls_mode} == "None" ]]; then - log_echo "${Warning} ${YellowBG} 此模式不支持删除用户! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "此模式不支持删除用户") ! ${Font}" else - log_echo "${Warning} ${YellowBG} 请先安装 Xray ! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请先安装 Xray") ! ${Font}" fi } show_access_log() { - [[ -f "${xray_access_log}" ]] && tail -f ${xray_access_log} || log_echo "${Error} ${RedBG} log文件不存在! ${Font}" + [[ -f "${xray_access_log}" ]] && tail -f ${xray_access_log} || log_echo "${Error} ${RedBG} $(gettext "log文件不存在") ! ${Font}" } show_error_log() { - [[ -f "${xray_error_log}" ]] && tail -f ${xray_error_log} || log_echo "${Error} ${RedBG} log文件不存在! ${Font}" + [[ -f "${xray_error_log}" ]] && tail -f ${xray_error_log} || log_echo "${Error} ${RedBG} $(gettext "log文件不存在") ! ${Font}" } xray_status_add() { if [[ -f "${xray_conf}" ]]; then if [[ $(jq -r .stats ${xray_conf}) != null ]]; then echo -e "\n" - log_echo "${GreenBG} 已配置 Xray 流量统计 ${Font}" - log_echo "${GreenBG} 是否需要关闭此功能 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "已配置 Xray 流量统计") ${Font}" + log_echo "${GreenBG} $(gettext "是否需要关闭此功能") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r xray_status_add_fq case $xray_status_add_fq in [yY][eE][sS] | [yY]) service_stop jq "del(.api)|del(.stats)|del(.policy)" ${xray_conf} > "${xray_conf}.tmp" - judge "关闭 Xray 流量统计" + judge "$(gettext "关闭 Xray 流量统计")" mv "${xray_conf}.tmp" "${xray_conf}" service_start [[ -f "${xray_status_conf}" ]] && rm -rf ${xray_status_conf} @@ -2736,27 +2823,27 @@ xray_status_add() { esac else echo -e "\n" - log_echo "${GreenBG} Xray 流量统计需要使用 api ${Font}" - log_echo "${GreenBG} 可能会影响 Xray 性能 ${Font}" - log_echo "${GreenBG} 是否继续 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "Xray 流量统计需要使用 api") ${Font}" + log_echo "${GreenBG} $(gettext "可能会影响 Xray 性能") ${Font}" + log_echo "${GreenBG} $(gettext "是否继续") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r xray_status_add_fq case $xray_status_add_fq in [yY][eE][sS] | [yY]) - service_stop - wget -nc --no-check-certificate https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/status_config.json -O ${xray_status_conf} - local status_config - status_config=$(jq -c . "${xray_status_conf}") - jq --argjson status_config "${status_config}" \ - '. += $status_config' "${xray_conf}" > "${xray_conf}.tmp" - judge "设置 Xray 流量统计" - mv "${xray_conf}.tmp" "${xray_conf}" - service_start + service_stop + wget -nc --no-check-certificate "https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/status_config.json" -O ${xray_status_conf} + local status_config + status_config=$(jq -c . "${xray_status_conf}") + jq --argjson status_config "${status_config}" \ + '. += $status_config' "${xray_conf}" > "${xray_conf}.tmp" + judge "$(gettext "设置 Xray 流量统计")" + mv "${xray_conf}.tmp" "${xray_conf}" + service_start ;; *) ;; esac fi else - log_echo "${Warning} ${YellowBG} 请先安装 Xray ! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "请先安装 Xray") ! ${Font}" fi } @@ -2768,10 +2855,6 @@ bbr_boost_sh() { fi } -mtproxy_sh() { - wget -N --no-check-certificate "https://github.com/whunt1/onekeymakemtg/raw/master/mtproxy_go.sh" && chmod +x mtproxy_go.sh && bash mtproxy_go.sh -} - uninstall_all() { stop_service_all if [[ -f "${xray_bin_dir}/xray" ]]; then @@ -2782,10 +2865,10 @@ uninstall_all() { jq -r 'del(.xray_version)' ${xray_qr_config_file} > "${xray_qr_config_file}.tmp" mv "${xray_qr_config_file}.tmp" "${xray_qr_config_file}" fi - log_echo "${OK} ${GreenBG} 已卸载 Xray ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已卸载 Xray") ${Font}" fi if [[ -d "${nginx_dir}" ]]; then - log_echo "${GreenBG} 是否卸载 Nginx [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否卸载 Nginx") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r uninstall_nginx case $uninstall_nginx in [yY][eE][sS] | [yY]) @@ -2797,37 +2880,37 @@ uninstall_all() { jq 'del(.nginx_build_version)' ${xray_qr_config_file} > "${xray_qr_config_file}.tmp" mv "${xray_qr_config_file}.tmp" "${xray_qr_config_file}" fi - log_echo "${OK} ${GreenBG} 已卸载 Nginx ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已卸载 Nginx") ${Font}" ;; *) ;; esac fi - log_echo "${GreenBG} 是否删除所有脚本文件 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否删除所有脚本文件") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r remove_all_idleleo_file_fq case $remove_all_idleleo_file_fq in [yY][eE][sS] | [yY]) rm -rf ${idleleo_commend_file} rm -rf ${idleleo_dir} systemctl daemon-reload - log_echo "${OK} ${GreenBG} 已删除所有文件 ${Font}" - log_echo "${GreenBG} ヾ( ̄▽ ̄) 拜拜~ ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已删除所有文件") ${Font}" + log_echo "${GreenBG} $(gettext "ヾ( ̄▽ ̄) 拜拜~") ${Font}" exit 0 ;; *) systemctl daemon-reload - log_echo "${OK} ${GreenBG} 已保留脚本文件 (包含 SSL 证书等) ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已保留脚本文件 (包含 SSL 证书等)") ${Font}" ;; esac if [[ -f "${xray_qr_config_file}" ]]; then - log_echo "${GreenBG} 是否保留配置文件 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "是否保留配置文件") [Y/${Red}N${Font}${GreenBG}]? ${Font}" read -r remove_config_fq case $remove_config_fq in [yY][eE][sS] | [yY]) - log_echo "${OK} ${GreenBG} 已保留配置文件 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已保留配置文件") ${Font}" ;; *) rm -rf ${xray_qr_config_file} - log_echo "${OK} ${GreenBG} 已删除配置文件 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已删除配置文件") ${Font}" ;; esac fi @@ -2836,7 +2919,7 @@ uninstall_all() { delete_tls_key_and_crt() { [[ -f "$HOME/.acme.sh/acme.sh" ]] && /root/.acme.sh/acme.sh uninstall >/dev/null 2>&1 [[ -d "$HOME/.acme.sh" ]] && rm -rf "$HOME/.acme.sh" - log_echo "${OK} ${GreenBG} 已清空证书遗留文件 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "已清空证书遗留文件") ${Font}" } timeout() { @@ -2864,7 +2947,15 @@ timeout() { else timeout_index="0" fi - printf "${Warning} ${GreenBG} %d秒后将$1 ${Font} \033[${timeout_color};${timeout_bg}m%-s\033[0m \033[${timeout_color}m%d\033[0m \r" "$timeout_index" "$timeout_str" "$timeout_index" + printf "${Warning} ${GreenBG} %d%s%s ${Font} \033[%d;%dm%-s\033[0m \033[%dm%d\033[0m \r" \ + "$timeout_index" \ + "$(gettext "秒后将")" \ + "$1" \ + "$timeout_color" \ + "$timeout_bg" \ + "$timeout_str" \ + "$timeout_color" \ + "$timeout_index" sleep 0.1 timeout_str=${timeout_str%?} [[ ${timeout} -eq 0 ]] && printf "\n" @@ -3020,7 +3111,7 @@ install_xray_ws_only() { update_sh() { ol_version=${shell_online_version} echo "${ol_version}" >${shell_version_tmp} - [[ -z ${ol_version} ]] && log_echo "${Error} ${RedBG} 检测最新版本失败! ${Font}" && return 1 + [[ -z ${ol_version} ]] && log_echo "${Error} ${RedBG} $(gettext "检测最新版本失败!") ${Font}" && return 1 echo "${shell_version}" >>${shell_version_tmp} newest_version=$(sort -rV ${shell_version_tmp} | head -1) oldest_version=$(sort -V ${shell_version_tmp} | head -1) @@ -3029,15 +3120,15 @@ update_sh() { if [[ ${auto_update} != "YES" ]]; then if [[ ${version_difference} == 1 ]]; then echo -e "\n" - log_echo "${Warning} ${YellowBG} 存在新版本, 但版本跨度较大, 可能存在不兼容情况, 是否更新 [Y/${Red}N${Font}${YellowBG}]? ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "存在新版本, 但版本跨度较大, 可能存在不兼容情况, 是否更新") [Y/${Red}N${Font}${YellowBG}]? ${Font}" else echo -e "\n" - log_echo "${GreenBG} 存在新版本, 是否更新 [Y/${Red}N${Font}${GreenBG}]? ${Font}" + log_echo "${GreenBG} $(gettext "存在新版本, 是否更新") [Y/${Red}N${Font}${GreenBG}]? ${Font}" fi read -r update_confirm else - [[ -z ${ol_version} ]] && echo "检测 脚本 最新版本失败!" >>${log_file} && exit 1 - [[ ${version_difference} == 1 ]] && echo "脚本 版本差别过大, 跳过更新!" >>${log_file} && exit 1 + [[ -z ${ol_version} ]] && echo "$(gettext "检测 脚本 最新版本失败!")" >>${log_file} && exit 1 + [[ ${version_difference} == 1 ]] && echo "$(gettext "脚本 版本差别过大, 跳过更新!")" >>${log_file} && exit 1 update_confirm="YES" fi case $update_confirm in @@ -3047,14 +3138,14 @@ update_sh() { ln -s ${idleleo_dir}/install.sh ${idleleo_commend_file} [[ -f "${xray_qr_config_file}" ]] && jq --arg shell_version "${shell_version}" '.shell_version = $shell_version' "${xray_qr_config_file}" > "${xray_qr_config_file}.tmp" && mv "${xray_qr_config_file}.tmp" "${xray_qr_config_file}" clear - log_echo "${OK} ${GreenBG} 更新完成 ${Font}" - [[ ${version_difference} == 1 ]] && log_echo "${Warning} ${YellowBG} 脚本版本跨度较大, 若服务无法正常运行请卸载后重装! ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "更新完成") ${Font}" + [[ ${version_difference} == 1 ]] && log_echo "${Warning} ${YellowBG} $(gettext "脚本版本跨度较大, 若服务无法正常运行请卸载后重装!") ${Font}" ;; *) ;; esac else clear - log_echo "${OK} ${GreenBG} 当前版本为最新版本 ${Font}" + log_echo "${OK} ${GreenBG} $(gettext "当前版本为最新版本") ${Font}" fi } @@ -3066,7 +3157,7 @@ check_file_integrity() { [[ ! -d "${idleleo_dir}" ]] && mkdir -p ${idleleo_dir} [[ ! -d "${idleleo_dir}/tmp" ]] && mkdir -p ${idleleo_dir}/tmp wget -N --no-check-certificate -P ${idleleo_dir} https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/install.sh && chmod +x ${idleleo_dir}/install.sh - judge "下载最新脚本" + judge "$(gettext "下载最新脚本")" ln -s ${idleleo_dir}/install.sh ${idleleo_commend_file} clear source "$idleleo" @@ -3080,8 +3171,8 @@ read_version() { } maintain() { - log_echo "${Error} ${RedBG} 该选项暂时无法使用! ${Font}" - log_echo "${Error} ${RedBG} $1 ${Font}" + log_echo "${Error} ${RedBG} $(gettext "该选项暂时无法使用") ! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "$1") ${Font}" exit 0 } @@ -3099,7 +3190,7 @@ list() { ;; '-3' | '--install-none') echo -e "\n" - log_echo "${Warning} ${YellowBG} 此模式推荐用于负载均衡, 一般情况不推荐使用, 是否安装 [Y/${Red}N${Font}${YellowBG}]? ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "此模式推荐用于负载均衡, 一般情况不推荐使用, 是否安装") [Y/${Red}N${Font}${YellowBG}]? ${Font}" read -r wsonly_fq case $wsonly_fq in [yY][eE][sS] | [yY]) @@ -3188,33 +3279,33 @@ list() { } show_help() { - echo "usage: idleleo [OPTION]" + echo "$(gettext "usage: idleleo [OPTION]")" echo - echo 'OPTION:' - echo ' -1, --install-tls 安装 Xray (Nginx+ws/gRPC+TLS)' - echo ' -2, --install-reality 安装 Xray (Nginx+Reality+ws/gRPC)' - echo ' -3, --install-none 安装 Xray (ws/gRPC ONLY)' - echo ' -4, --add-upstream 变更 Nginx 负载均衡配置' - echo ' -5, --add-servernames 变更 Nginx serverNames 配置' - echo ' -au, --auto-update 设置自动更新' - echo ' -c, --clean-logs 清除日志文件' - echo ' -cs, --cert-status 查看证书状态' - echo ' -cu, --cert-update 更新证书有效期' - echo ' -cau, --cert-auto-update 设置证书自动更新' - echo ' -f, --set-fail2ban 设置 Fail2ban 防暴力破解' - echo ' -h, --help 显示帮助' - echo ' -n, --nginx-update 更新 Nginx' - echo ' -p, --port-reset 变更 port' - echo ' --purge, --uninstall 脚本卸载' - echo ' -s, --show 显示安装信息' - echo ' -t, --target-reset 变更 target' - echo ' -tcp, --tcp 配置 TCP 加速' - echo ' -tls, --tls 修改 TLS 配置' - echo ' -u, --update 升级脚本' - echo ' -uu, --uuid-reset 变更 UUIDv5/映射字符串' - echo ' -xa, --xray-access 显示 Xray 访问信息' - echo ' -xe, --xray-error 显示 Xray 错误信息' - echo ' -x, --xray-update 更新 Xray' + echo "$(gettext "OPTION:")" + echo "$(gettext " -1, --install-tls 安装 Xray (Nginx+ws/gRPC+TLS)")" + echo "$(gettext " -2, --install-reality 安装 Xray (Nginx+Reality+ws/gRPC)")" + echo "$(gettext " -3, --install-none 安装 Xray (ws/gRPC ONLY)")" + echo "$(gettext " -4, --add-upstream 变更 Nginx 负载均衡配置")" + echo "$(gettext " -5, --add-servernames 变更 Nginx serverNames 配置")" + echo "$(gettext " -au, --auto-update 设置自动更新")" + echo "$(gettext " -c, --clean-logs 清除日志文件")" + echo "$(gettext " -cs, --cert-status 查看证书状态")" + echo "$(gettext " -cu, --cert-update 更新证书有效期")" + echo "$(gettext " -cau, --cert-auto-update 设置证书自动更新")" + echo "$(gettext " -f, --set-fail2ban 设置 Fail2ban 防暴力破解")" + echo "$(gettext " -h, --help 显示帮助")" + echo "$(gettext " -n, --nginx-update 更新 Nginx")" + echo "$(gettext " -p, --port-reset 变更 port")" + echo "$(gettext " --purge, --uninstall 脚本卸载")" + echo "$(gettext " -s, --show 显示安装信息")" + echo "$(gettext " -t, --target-reset 变更 target")" + echo "$(gettext " -tcp, --tcp 配置 TCP 加速")" + echo "$(gettext " -tls, --tls 修改 TLS 配置")" + echo "$(gettext " -u, --update 升级脚本")" + echo "$(gettext " -uu, --uuid-reset 变更 UUIDv5/映射字符串")" + echo "$(gettext " -xa, --xray-access 显示 Xray 访问信息")" + echo "$(gettext " -xe, --xray-error 显示 Xray 错误信息")" + echo "$(gettext " -x, --xray-update 更新 Xray")" exit 0 } @@ -3229,22 +3320,20 @@ idleleo_commend() { version_difference=$(echo "(${shell_version:0:3}-${oldest_version:0:3})>0" | bc) if [[ -z ${old_version} ]]; then wget -N --no-check-certificate -P ${idleleo_dir} https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/install.sh && chmod +x ${idleleo_dir}/install.sh - judge "下载最新脚本" + judge "$(gettext "下载最新脚本")" clear source "$idleleo" elif [[ ${shell_version} != ${oldest_version} ]]; then if [[ ${version_difference} == 1 ]]; then - ## log_echo "${Warning} ${YellowBG} 脚本版本跨度较大, 可能存在不兼容情况, 是否继续使用 [Y/${Red}N${Font}${YellowBG}]? ${Font}" 紧急更新 - log_echo "${Warning} ${YellowBG} 此版本需要${Red}Xray版本在1.6.2及以上${Font}, 是否继续使用 [Y/${Red}N${Font}${YellowBG}]? ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "脚本版本跨度较大, 可能存在不兼容情况, 是否继续使用") [Y/${Red}N${Font}${YellowBG}]? ${Font}" read -r update_sh_fq case $update_sh_fq in [yY][eE][sS] | [yY]) rm -rf ${idleleo_dir}/install.sh wget -N --no-check-certificate -P ${idleleo_dir} https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/install.sh && chmod +x ${idleleo_dir}/install.sh - judge "下载最新脚本" + judge "$(gettext "下载最新脚本")" clear - ## log_echo "${Warning} ${YellowBG} 脚本版本跨度较大, 若服务无法正常运行请卸载后重装! ${Font}" 紧急更新 - log_echo "${Warning} ${YellowBG} 务必保证${Red}Xray版本在1.6.2及以上${Font}, 否则将无法正常使用! ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "脚本版本跨度较大, 若服务无法正常运行请卸载后重装") ! ${Font}" echo -e "\n" ;; *) @@ -3254,52 +3343,52 @@ idleleo_commend() { else rm -rf ${idleleo_dir}/install.sh wget -N --no-check-certificate -P ${idleleo_dir} https://raw.githubusercontent.com/hello-yunshu/Xray_bash_onekey/main/install.sh && chmod +x ${idleleo_dir}/install.sh - judge "下载最新脚本" + judge "$(gettext "下载最新脚本")" clear fi source "$idleleo" else ol_version=${shell_online_version} echo "${ol_version}" >${shell_version_tmp} - [[ -z ${ol_version} ]] && shell_need_update="${Red}[检测失败!]${Font}" + [[ -z ${ol_version} ]] && shell_need_update="${Red}[$(gettext "检测失败")]!${Font}" echo "${shell_version}" >>${shell_version_tmp} newest_version=$(sort -rV ${shell_version_tmp} | head -1) if [[ ${shell_version} != ${newest_version} ]]; then - shell_need_update="${Red}[有新版!]${Font}" + shell_need_update="${Red}[$(gettext "有新版")]!${Font}" shell_emoji="${Red}>_<${Font}" else - shell_need_update="${Green}[最新版]${Font}" + shell_need_update="${Green}[$(gettext "最新版")]${Font}" shell_emoji="${Green}^O^${Font}" fi if [[ -f "${xray_qr_config_file}" ]]; then if [[ "$(info_extraction nginx_build_version)" == "null" ]] || [[ ! -f "${nginx_dir}/sbin/nginx" ]]; then - nginx_need_update="${Green}[未安装]${Font}" + nginx_need_update="${Green}[$(gettext "未安装")]${Font}" elif [[ ${nginx_build_version} != $(info_extraction nginx_build_version) ]]; then - nginx_need_update="${Green}[有新版]${Font}" + nginx_need_update="${Green}[$(gettext "有新版")]${Font}" else - nginx_need_update="${Green}[最新版]${Font}" + nginx_need_update="${Green}[$(gettext "最新版")]${Font}" fi if [[ -f "${xray_qr_config_file}" ]] && [[ -f "${xray_conf}" ]] && [[ -f "${xray_bin_dir}/xray" ]]; then xray_online_version=$(check_version xray_online_version) ##xray_online_version=$(check_version xray_online_pre_version) if [[ "$(info_extraction xray_version)" == "null" ]]; then - xray_need_update="${Green}[已安装] (版本未知)${Font}" + xray_need_update="${Green}[$(gettext "已安装")] ($(gettext "版本未知"))${Font}" elif [[ ${xray_version} != $(info_extraction xray_version) ]] && [[ $(info_extraction xray_version) != ${xray_online_version} ]]; then - xray_need_update="${Red}[有新版!]${Font}" - ### xray_need_update="${Red}[请务必更新!]${Font}" + xray_need_update="${Red}[$(gettext "有新版")]!${Font}" + ### xray_need_update="${Red}[$(gettext "请务必更新")]!${Font}" elif [[ ${xray_version} == $(info_extraction xray_version) ]] || [[ $(info_extraction xray_version) == ${xray_online_version} ]]; then if [[ $(info_extraction xray_version) != ${xray_online_version} ]]; then - xray_need_update="${Green}[有测试版]${Font}" + xray_need_update="${Green}[$(gettext "有测试版")]${Font}" else - xray_need_update="${Green}[最新版]${Font}" + xray_need_update="${Green}[$(gettext "最新版")]${Font}" fi fi else - xray_need_update="${Red}[未安装]${Font}" + xray_need_update="${Red}[$(gettext "未安装")]${Font}" fi else - nginx_need_update="${Green}[未安装]${Font}" - xray_need_update="${Red}[未安装]${Font}" + nginx_need_update="${Green}[$(gettext "未安装")]${Font}" + xray_need_update="${Red}[$(gettext "未安装")]${Font}" fi fi fi @@ -3307,16 +3396,16 @@ idleleo_commend() { check_program() { if [[ -n $(pgrep nginx) ]]; then - nignx_status="${Green}运行中..${Font}" + nignx_status="${Green}$(gettext "运行中..")${Font}" elif [[ ${tls_mode} == "None" ]] || [[ ${reality_add_nginx} == "off" ]]; then - nignx_status="${Green}无需测试${Font}" + nignx_status="${Green}$(gettext "无需测试")${Font}" else - nignx_status="${Red}未运行${Font}" + nignx_status="${Red}$(gettext "未运行")${Font}" fi if [[ -n $(pgrep xray) ]]; then - xray_status="${Green}运行中..${Font}" + xray_status="${Green}$(gettext "运行中..")${Font}" else - xray_status="${Red}未运行${Font}" + xray_status="${Red}$(gettext "未运行")${Font}" fi } @@ -3326,19 +3415,18 @@ curl_local_connect() { check_xray_local_connect() { if [[ -f "${xray_qr_config_file}" ]]; then - xray_local_connect_status="${Red}无法连通${Font}" + xray_local_connect_status="${Red}$(gettext "无法连通")${Font}" if [[ ${tls_mode} == "TLS" ]]; then - [[ ${ws_grpc_mode} == "onlyws" ]] && [[ $(curl_local_connect $(info_extraction host) $(info_extraction path)) == "400" ]] && xray_local_connect_status="${Green}本地正常${Font}" - [[ ${ws_grpc_mode} == "onlygrpc" ]] && [[ $(curl_local_connect $(info_extraction host) $(info_extraction serviceName)) == "502" ]] && xray_local_connect_status="${Green}本地正常${Font}" - [[ ${ws_grpc_mode} == "all" ]] && [[ $(curl_local_connect $(info_extraction host) $(info_extraction serviceName)) == "502" && $(curl_local_connect $(info_extraction host) $(info_extraction path)) == "400" ]] && xray_local_connect_status="${Green}本地正常${Font}" + [[ ${ws_grpc_mode} == "onlyws" ]] && [[ $(curl_local_connect $(info_extraction host) $(info_extraction path)) == "400" ]] && xray_local_connect_status="${Green}$(gettext "本地正常")${Font}" + [[ ${ws_grpc_mode} == "onlygrpc" ]] && [[ $(curl_local_connect $(info_extraction host) $(info_extraction serviceName)) == "502" ]] && xray_local_connect_status="${Green}$(gettext "本地正常")${Font}" + [[ ${ws_grpc_mode} == "all" ]] && [[ $(curl_local_connect $(info_extraction host) $(info_extraction serviceName)) == "502" && $(curl_local_connect $(info_extraction host) $(info_extraction path)) == "400" ]] && xray_local_connect_status="${Green}$(gettext "本地正常")${Font}" elif [[ ${tls_mode} == "Reality" ]]; then - #[[ $(curl_local_connect $(info_extraction host)) == "302" ]] && xray_local_connect_status="${Green}本地正常${Font}" - xray_local_connect_status="${Green}无需测试${Font}" + xray_local_connect_status="${Green}$(gettext "无需测试")${Font}" elif [[ ${tls_mode} == "None" ]]; then - xray_local_connect_status="${Green}无需测试${Font}" + xray_local_connect_status="${Green}$(gettext "无需测试")${Font}" fi else - xray_local_connect_status="${Red}未安装${Font}" + xray_local_connect_status="${Red}$(gettext "未安装")${Font}" fi } @@ -3346,28 +3434,63 @@ check_online_version_connect() { xray_online_version_status=$(curl_local_connect "www.idleleo.com" "api/xray_shell_versions") if [[ ${xray_online_version_status} != "200" ]]; then if [[ ${xray_online_version_status} == "403" ]]; then - log_echo "${Error} ${RedBG} 脚本维护中.. 请稍后再试! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "脚本维护中.. 请稍后再试!") ${Font}" else - log_echo "${Error} ${RedBG} 无法检测所需依赖的在线版本, 请稍后再试! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "无法检测所需依赖的在线版本, 请稍后再试!") ${Font}" fi sleep 0.5 exit 0 fi } +set_language() { + echo -e "\n" + log_echo "${GreenBG} $(gettext "选择语言 / Select Language / انتخاب زبان / Выберите язык") ${Font}" + echo -e "${Green}1.${Font} 中文" + echo -e "${Green}2.${Font} English" + echo -e "${Green}3.${Font} فارسی" + echo -e "${Green}4.${Font} Русский" + + local lang_choice + read_optimize "$(gettext "请输入数字"): " "lang_choice" "NULL" 1 4 "$(gettext "请输入 1 到 4 之间的有效数字")" + + case $lang_choice in + 1) + export LANG=zh_CN.UTF-8 + ;; + 2) + export LANG=en_US.UTF-8 + ;; + 3) + export LANG=fa_IR.UTF-8 + ;; + 4) + export LANG=ru_RU.UTF-8 + ;; + *) + log_echo "${Error} ${RedBG} $(gettext "无效的选择") ${Font}" + return 1 + ;; + esac + + echo "LANG=$LANG" > "${idleleo_dir}/language.conf" + + source "$idleleo" +} + #以下为兼容代码,1个大版本后删除 fix_bugs() { local log_cleanup_file_path="/etc/logrotate.d/custom_log_cleanup" if [[ -f "${log_cleanup_file_path}" ]]; then echo -e "\n" - log_echo "${Warning} ${RedBG} 检测存在到 BUG ! ${Font}" - log_echo "${Warning} ${YellowBG} BUG 来源于自动清理日志错误的设置 ${Font}" - log_echo "${Warning} ${YellowBG} 开始修复.. ${Font}" + log_echo "${Warning} ${RedBG} $(gettext "检测存在到 BUG !") ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "BUG 来源于自动清理日志错误的设置") ${Font}" + log_echo "${Warning} ${YellowBG} $(gettext "开始修复..") ${Font}" [[ -f "${nginx_dir}/sbin/nginx" ]] && chown -fR nobody:nogroup "${nginx_dir}/logs" chown -fR nobody:nogroup /var/log/xray/ rm -f "${log_cleanup_file_path}" - judge "错误的配置文件删除" - log_echo "${Warning} ${YellowBG} 即将重新设置自动清理日志.. ${Font}" + judge "$(gettext "错误的配置文件删除")" + log_echo "${Warning} ${YellowBG} $(gettext "即将重新设置自动清理日志..") ${Font}" bash "${idleleo}" --clean-logs fi } @@ -3375,70 +3498,73 @@ fix_bugs() { menu() { echo -e "\n" - log_echo "Xray 安装管理脚本 ${Red}[${shell_version}]${Font} ${shell_emoji}" - log_echo "--- authored by hello-yunshu ---" - log_echo "--- changed by www.idleleo.com ---" + log_echo "Xray $(gettext "安装管理脚本") ${Red}[${shell_version}]${Font} ${shell_emoji}" + log_echo "--- $(gettext "作者"): hello-yunshu ---" + log_echo "--- $(gettext "修改"): www.idleleo.com ---" log_echo "--- https://github.com/hello-yunshu ---" echo -e "\n" - log_echo "当前模式: ${shell_mode}" + log_echo "$(gettext "当前模式"): ${shell_mode}" + log_echo "$(gettext "当前语言"): ${LANG%.*}" echo -e "\n" - - echo -e "可以使用${RedW} idleleo ${Font}命令管理脚本${Font}\n" - - log_echo "—————————————— ${GreenW}版本检测${Font} ——————————————" - log_echo "脚本: ${shell_need_update}" + + echo -e "$(gettext "可以使用")${RedW} idleleo ${Font}$(gettext "命令管理脚本")${Font}\n" + + log_echo "—————————————— ${GreenW}$(gettext "版本检测")${Font} ——————————————" + log_echo "$(gettext "脚本"): ${shell_need_update}" log_echo "Xray: ${xray_need_update}" log_echo "Nginx: ${nginx_need_update}" - log_echo "—————————————— ${GreenW}运行状态${Font} ——————————————" + log_echo "—————————————— ${GreenW}$(gettext "运行状态")${Font} ——————————————" log_echo "Xray: ${xray_status}" log_echo "Nginx: ${nignx_status}" - log_echo "连通性: ${xray_local_connect_status}" - echo -e "—————————————— ${GreenW}升级向导${Font} ——————————————" - echo -e "${Green}0.${Font} 升级 脚本" - echo -e "${Green}1.${Font} 升级 Xray" - echo -e "${Green}2.${Font} 升级 Nginx" - echo -e "—————————————— ${GreenW}安装向导${Font} ——————————————" - echo -e "${Green}3.${Font} 安装 Xray (Reality+ws/gRPC+Nginx)" - echo -e "${Green}4.${Font} 安装 Xray (Nginx+ws/gRPC+TLS)" - echo -e "${Green}5.${Font} 安装 Xray (ws/gRPC ONLY)" - echo -e "—————————————— ${GreenW}配置变更${Font} ——————————————" - echo -e "${Green}6.${Font} 变更 UUIDv5/映射字符串" - echo -e "${Green}7.${Font} 变更 port" - echo -e "${Green}8.${Font} 变更 target" - echo -e "${Green}9.${Font} 变更 TLS 版本" - echo -e "${Green}10.${Font} 变更 Nginx 负载均衡配置" - echo -e "${Green}11.${Font} 变更 Nginx serverNames 配置" - echo -e "—————————————— ${GreenW}用户管理${Font} ——————————————" - echo -e "${Green}12.${Font} 查看 Xray 用户" - echo -e "${Green}13.${Font} 添加 Xray 用户" - echo -e "${Green}14.${Font} 删除 Xray 用户" - echo -e "—————————————— ${GreenW}查看信息${Font} ——————————————" - echo -e "${Green}15.${Font} 查看 Xray 实时访问日志" - echo -e "${Green}16.${Font} 查看 Xray 实时错误日志" - echo -e "${Green}17.${Font} 查看 Xray 配置信息" - echo -e "—————————————— ${GreenW}服务相关${Font} ——————————————" - echo -e "${Green}18.${Font} 重启 所有服务" - echo -e "${Green}19.${Font} 启动 所有服务" - echo -e "${Green}20.${Font} 停止 所有服务" - echo -e "${Green}21.${Font} 查看 所有服务" - echo -e "—————————————— ${GreenW}证书相关${Font} ——————————————" - echo -e "${Green}22.${Font} 查看 证书状态" - echo -e "${Green}23.${Font} 更新 证书有效期" - echo -e "${Green}24.${Font} 设置 证书自动更新" - echo -e "—————————————— ${GreenW}其他选项${Font} ——————————————" - echo -e "${Green}25.${Font} 配置 自动更新" - echo -e "${Green}26.${Font} 设置 TCP 加速" - echo -e "${Green}27.${Font} 设置 Fail2ban 防暴力破解" - echo -e "${Green}28.${Font} 设置 Xray 流量统计" - echo -e "${Green}29.${Font} 清除 日志文件" - echo -e "${Green}30.${Font} 测试 服务器网速" - echo -e "—————————————— ${GreenW}卸载向导${Font} ——————————————" - echo -e "${Green}31.${Font} 卸载 脚本" - echo -e "${Green}32.${Font} 清空 证书文件" - echo -e "${Green}33.${Font} 退出 \n" - + log_echo "$(gettext "连通性"): ${xray_local_connect_status}" + echo -e "—————————————— ${GreenW}$(gettext "升级向导")${Font} ——————————————" + echo -e "${Green}0.${Font} $(gettext "升级") $(gettext "脚本")" + echo -e "${Green}1.${Font} $(gettext "升级") Xray" + echo -e "${Green}2.${Font} $(gettext "升级") Nginx" + echo -e "—————————————— ${GreenW}Language Settings${Font} ——————————————" + echo -e "${Green}34.${Font} English Version" + echo -e "—————————————— ${GreenW}$(gettext "安装向导")${Font} ——————————————" + echo -e "${Green}3.${Font} $(gettext "安装") Xray (Reality+ws/gRPC+Nginx)" + echo -e "${Green}4.${Font} $(gettext "安装") Xray (Nginx+ws/gRPC+TLS)" + echo -e "${Green}5.${Font} $(gettext "安装") Xray (ws/gRPC ONLY)" + echo -e "—————————————— ${GreenW}$(gettext "配置变更")${Font} ——————————————" + echo -e "${Green}6.${Font} $(gettext "变更") UUIDv5/$(gettext "映射字符串")" + echo -e "${Green}7.${Font} $(gettext "变更") port" + echo -e "${Green}8.${Font} $(gettext "变更") target" + echo -e "${Green}9.${Font} $(gettext "变更") TLS $(gettext "版本")" + echo -e "${Green}10.${Font} $(gettext "变更") Nginx $(gettext "负载均衡配置")" + echo -e "${Green}11.${Font} $(gettext "变更") Nginx serverNames $(gettext "配置")" + echo -e "—————————————— ${GreenW}$(gettext "用户管理")${Font} ——————————————" + echo -e "${Green}12.${Font} $(gettext "查看") Xray $(gettext "用户")" + echo -e "${Green}13.${Font} $(gettext "添加") Xray $(gettext "用户")" + echo -e "${Green}14.${Font} $(gettext "删除") Xray $(gettext "用户")" + echo -e "—————————————— ${GreenW}$(gettext "查看信息")${Font} ——————————————" + echo -e "${Green}15.${Font} $(gettext "查看") Xray $(gettext "实时访问日志")" + echo -e "${Green}16.${Font} $(gettext "查看") Xray $(gettext "实时错误日志")" + echo -e "${Green}17.${Font} $(gettext "查看") Xray $(gettext "配置信息")" + echo -e "—————————————— ${GreenW}$(gettext "服务相关")${Font} ——————————————" + echo -e "${Green}18.${Font} $(gettext "重启") $(gettext "所有服务")" + echo -e "${Green}19.${Font} $(gettext "启动") $(gettext "所有服务")" + echo -e "${Green}20.${Font} $(gettext "停止") $(gettext "所有服务")" + echo -e "${Green}21.${Font} $(gettext "查看") $(gettext "所有服务")" + echo -e "—————————————— ${GreenW}$(gettext "证书相关")${Font} ——————————————" + echo -e "${Green}22.${Font} $(gettext "查看") $(gettext "证书状态")" + echo -e "${Green}23.${Font} $(gettext "更新") $(gettext "证书有效期")" + echo -e "${Green}24.${Font} $(gettext "设置") $(gettext "证书自动更新")" + echo -e "—————————————— ${GreenW}$(gettext "其他选项")${Font} ——————————————" + echo -e "${Green}25.${Font} $(gettext "配置") $(gettext "自动更新")" + echo -e "${Green}26.${Font} $(gettext "设置") TCP $(gettext "加速")" + echo -e "${Green}27.${Font} $(gettext "设置") Fail2ban $(gettext "防暴力破解")" + echo -e "${Green}28.${Font} $(gettext "设置") Xray $(gettext "流量统计")" + echo -e "${Green}29.${Font} $(gettext "清除") $(gettext "日志文件")" + echo -e "${Green}30.${Font} $(gettext "测试") $(gettext "服务器网速")" + echo -e "—————————————— ${GreenW}$(gettext "卸载向导")${Font} ——————————————" + echo -e "${Green}31.${Font} $(gettext "卸载") $(gettext "脚本")" + echo -e "${Green}32.${Font} $(gettext "清空") $(gettext "证书文件")" + echo -e "${Green}33.${Font} $(gettext "退出") \n" + local menu_num - read_optimize "请输入选项: " "menu_num" "NULL" 0 33 "请输入 0 到 33 之间的有效数字" + read_optimize "$(gettext "请输入选项"): " "menu_num" "NULL" 0 34 "$(gettext "请输入 0 到 34 之间的有效数字")" case $menu_num in 0) update_sh @@ -3446,16 +3572,16 @@ menu() { ;; 1) xray_update - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear source "$idleleo" ;; 2) echo -e "\n" log_echo "${Red}[不建议]${Font} 频繁升级 Nginx, 请确认 Nginx 有升级的必要! " - timeout "开始升级!" + timeout "$(gettext "开始升级!")" nginx_update - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear source "$idleleo" ;; @@ -3487,49 +3613,49 @@ menu() { ;; 6) reset_UUID - judge "变更 UUIDv5/映射字符串" + judge "$(gettext "变更 UUIDv5/映射字符串")" menu ;; 7) reset_port - judge "变更 port" + judge "$(gettext "变更 port")" menu ;; 8) reset_target - judge "变更 target" + judge "$(gettext "变更 target")" menu ;; 9) tls_type - judge "变更 TLS 版本" + judge "$(gettext "变更 TLS 版本")" menu ;; 10) nginx_upstream_server_set - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear menu ;; 11) nginx_servernames_server_set - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear menu ;; 12) show_user - timeout "回到菜单!" + timeout "$(gettext "回到菜单!")" menu ;; 13) add_user - timeout "回到菜单!" + timeout "$(gettext "回到菜单!")" menu ;; 14) remove_user - timeout "回到菜单!" + timeout "$(gettext "回到菜单!")" menu ;; 15) @@ -3549,19 +3675,19 @@ menu() { ;; 18) service_restart - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear menu ;; 19) service_start - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear source "$idleleo" ;; 20) service_stop - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear source "$idleleo" ;; @@ -3574,23 +3700,23 @@ menu() { ;; 22) check_cert_status - timeout "回到菜单!" + timeout "$(gettext "回到菜单!")" menu ;; 23) cert_update_manuel - timeout "回到菜单!" + timeout "$(gettext "回到菜单!")" menu ;; 24) acme_cron_update - timeout "回到菜单!" + timeout "$(gettext "回到菜单!")" clear menu ;; 25) auto_update - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear menu ;; @@ -3604,7 +3730,7 @@ menu() { ;; 28) xray_status_add - timeout "回到菜单!" + timeout "$(gettext "回到菜单!")" menu ;; 29) @@ -3617,25 +3743,29 @@ menu() { ;; 31) uninstall_all - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear source "$idleleo" ;; 32) delete_tls_key_and_crt rm -rf ${ssl_chainpath}/* - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear menu ;; 33) - timeout "清空屏幕!" + timeout "$(gettext "清空屏幕!")" clear exit 0 ;; + 34) + set_language + bash idleleo + ;; *) clear - log_echo "${Error} ${RedBG} 请输入正确的数字! ${Font}" + log_echo "${Error} ${RedBG} $(gettext "请输入正确的数字!") ${Font}" menu ;; esac @@ -3643,6 +3773,7 @@ menu() { check_file_integrity check_online_version_connect +init_language read_version judge_mode idleleo_commend diff --git a/languages/en/README.md b/languages/en/README.md new file mode 100644 index 0000000..f47e91a --- /dev/null +++ b/languages/en/README.md @@ -0,0 +1,104 @@ +# One-click Installation Script for Xray with Reality / VLESS WebSocket/gRPC+TLS Protocol + Nginx + +[简体中文](README.md) | [English](languages/en/README.md) + +[![GitHub stars](https://img.shields.io/github/stars/hello-yunshu/Xray_bash_onekey?color=%230885ce)](https://github.com/hello-yunshu/Xray_bash_onekey/stargazers) [![GitHub forks](https://img.shields.io/github/forks/hello-yunshu/Xray_bash_onekey?color=%230885ce)](https://github.com/hello-yunshu/Xray_bash_onekey/network) [![GitHub issues](https://img.shields.io/github/issues/hello-yunshu/Xray_bash_onekey)](https://github.com/hello-yunshu/Xray_bash_onekey/issues) + +> Thanks for non-commercial open source development authorization by JetBrains + +## Instructions + +* You can directly enter the command: `idleleo` to manage the script. +* It is recommended to use Nginx frontend for Reality, which can be installed in the script. +* It is recommended to enable fail2ban, which can be installed in the script. +* Using the sharing link [proposal](https://github.com/XTLS/Xray-core/issues/91) (beta) from [@DuckSoft](https://github.com/DuckSoft), supporting Qv2ray, V2rayN, V2rayNG. +* Using the proposal from [XTLS](https://github.com/XTLS/Xray-core/issues/158) project, following the [UUIDv5](https://tools.ietf.org/html/rfc4122#section-4.3) standard, custom strings can be mapped to VLESS UUID. +* Reality installation instructions: [Setting up Xray Reality Protocol Server](https://hey.run/archives/da-jian-xray-reality-xie-yi-fu-wu-qi). +* Risks of Reality protocol: [Risks of Xray Reality Protocol](https://hey.run/archives/reality-xie-yi-de-feng-xian). +* Accelerating server using Reality protocol: [Accelerating Server Using Reality Protocol "Vulnerability"](https://hey.run/archives/li-yong-reality-xie-yi-lou-dong-jia-su-fu-wu-qi). +* Added load balancing configuration, tutorial: [XRay Advanced Usage – Setting up Backend Server Load Balancing](https://hey.run/archives/xrayjin-jie-wan-fa---da-jian-hou-duan-fu-wu-qi-fu-zai-jun-heng). +* Added gRPC protocol support, details can be found at: [Xray Advanced Usage – Using gRPC Protocol](https://hey.run/archives/xrayjin-jie-wan-fa---shi-yong-grpcxie-yi). + +## Telegram Group + +* Telegram chat group: + +## Preparation + +* Prepare a server running outside mainland China with a public IP. +* For Reality protocol installation, find a domain name that meets Xray requirements. +* For TLS version installation, prepare a domain name and add the A record. +* Read [Xray official documentation](https://xtls.github.io) to understand Reality TLS WebSocket gRPC and Xray related information, understand Reality target domain requirements. +* **Install curl**, Centos users run: `yum install -y curl`; Debian/Ubuntu users run: `apt install -y curl`. + +## Installation Method + +Copy and run: + +``` bash +bash <(curl -Ss https://www.idleleo.com/install.sh) +``` + +## Notes + +* If you don't understand the specific meaning of each setting in the script, except for required items, please use the default values provided by the script (press Enter all the way). +* Cloudflare users please enable CDN function after installation is complete. +* Using this script requires Linux basics and experience, understanding of computer network knowledge, and basic computer operations. +* Currently supports Debian 9+ / Ubuntu 18.04+ / Centos7+. Some Centos templates may have difficult compilation issues, it is recommended to switch to other system templates when encountering compilation problems. +* The author provides limited support, as they are too inexperienced. +* The sharing link is an experimental version, future changes are possible, please confirm client support yourself. +* Custom string mapping to UUIDv5 requires client support. + +## Acknowledgments + +* This script is derived from Thanks to wulabing +* TCP acceleration script project in this script references Thanks to ylx2016 + +## Certificate + +If you already have the certificate files for your domain name, you can name the crt and key files as xray.crt and xray.key and place them in the /etc/idleleo/cert directory (create the directory if it doesn't exist), please note the certificate file permissions and validity period, custom certificates need to be renewed manually after expiration. + +The script supports automatic generation of Let's Encrypted certificates, valid for 3 months, theoretically supporting automatic renewal. + +## View Client Configuration + +`cat /etc/idleleo/xray_info.txt` + +## Xray Introduction + +* Xray is an excellent open-source network proxy tool that can help you enjoy the internet smoothly, currently supporting Windows, Mac, Android, IOS, Linux and other operating systems. +* This script is a one-click complete configuration script. After all processes run normally, you can directly set up the client according to the output results. +* Please note: We still strongly recommend that you fully understand the entire program's workflow and principles. + +## Recommend Setting Up Single Proxy on Single Server + +* This script installs the latest version of Xray core by default. +* It is recommended to use the default port 443 as the connection port. +* The disguise content can be replaced as needed. + +## Other Notes + +* Recommended to use this script in a clean environment. If you are a beginner, please do not use Centos system. +* Please do not apply this program to production environment before confirming this script is actually usable. +* This program depends on Nginx to implement related functions. Users who have installed Nginx using [LNMP](https://lnmp.org) or other similar Nginx scripts should pay special attention, using this script may cause unpredictable errors. +* Centos system users please allow program-related ports (default: 80, 443) in the firewall in advance. + +## Start Method + +Start Xray: `systemctl start xray` + +Stop Xray: `systemctl stop xray` + +Start Nginx: `systemctl start nginx` + +Stop Nginx: `systemctl stop nginx` + +## Related Directories + +Xray server configuration: `/etc/idleleo/conf/xray/config.json` + +Nginx directory: `/usr/local/nginx` + +Certificate files: `/etc/idleleo/cert/xray.key` and `/etc/idleleo/cert/xray.crt` please note certificate permission settings + +Configuration information files etc: `/etc/idleleo` diff --git a/translate.py b/translate.py new file mode 100644 index 0000000..9bb1559 --- /dev/null +++ b/translate.py @@ -0,0 +1,74 @@ +import re +import time +import json +import os +from googletrans import Translator, LANGUAGES + +def load_translation_cache(cache_file): + if os.path.exists(cache_file): + with open(cache_file, 'r', encoding='utf-8') as f: + return json.load(f) + return {} + +def save_translation_cache(cache_file, translations): + with open(cache_file, 'w', encoding='utf-8') as f: + json.dump(translations, f, ensure_ascii=False, indent=2) + +def translate_po_file(input_file, output_file, target_lang): + cache_file = f'po/cache_{target_lang}.json' + translations = load_translation_cache(cache_file) + + # 使用最新的 Translator,并设置更可靠的服务 URL + translator = Translator(service_urls=['translate.google.com']) + + with open(input_file, 'r', encoding='utf-8') as f: + content = f.read() + + pattern = r'msgid "(.*?)"\nmsgstr ""' + matches = re.finditer(pattern, content) + + updated = False + for match in matches: + chinese_text = match.group(1) + if chinese_text and any('\u4e00' <= char <= '\u9fff' for char in chinese_text): + if chinese_text in translations: + translated_text = translations[chinese_text] + print(f"Using cached translation [{target_lang}]: {chinese_text} -> {translated_text}") + else: + try: + # 增加重试机制 + max_retries = 3 + for attempt in range(max_retries): + try: + time.sleep(2) # 增加延迟以避免请求过快 + translation = translator.translate(chinese_text, src='zh-cn', dest=target_lang) + translated_text = translation.text + translations[chinese_text] = translated_text + updated = True + print(f"New translation [{target_lang}]: {chinese_text} -> {translated_text}") + break + except Exception as e: + if attempt == max_retries - 1: + raise e + print(f"Retry {attempt + 1}/{max_retries} for: {chinese_text}") + time.sleep(5) # 重试前等待更长时间 + except Exception as e: + print(f"Translation failed for: {chinese_text}") + print(f"Error: {e}") + continue + + content = content.replace( + f'msgid "{chinese_text}"\nmsgstr ""', + f'msgid "{chinese_text}"\nmsgstr "{translated_text}"' + ) + + if updated: + save_translation_cache(cache_file, translations) + + with open(output_file, 'w', encoding='utf-8') as f: + f.write(content) + +if __name__ == '__main__': + for lang, code in [('en', 'en'), ('fa', 'fa'), ('ru', 'ru')]: + print(f"\nTranslating to {lang}...") + translate_po_file(f'po/{lang}.po', f'po/{lang}.po', code) \ No newline at end of file