宝塔面板快速部署汉化版ERPNext实战指南
1. 项目概述为什么“宝塔汉化版ERPNext”是中小企业的务实选择ERPNext 这个名字在制造业、贸易公司和中小型服务企业老板的微信聊天记录里最近半年出现频率明显变高。它不像 SAP 或 Oracle 那样动辄百万起订、需要专职 IT 团队维护也不像某些国产 SaaS 系统那样功能堆砌却流程僵硬。它是一套真正开源、模块可拆、代码透明、社区活跃的全栈 ERP 系统底层用的是 Frappe 框架——一个用 Python 写的、自带 Web UI 和元数据驱动逻辑的开发平台。但问题来了官方安装文档默认走的是 Ubuntu 命令行纯手工部署从系统依赖、Python 环境、MariaDB 配置、Redis 启动、到 Bench 初始化一套流程跑下来没个三小时打底中间还可能卡在npm install超时、bench setup production权限报错、或者supervisorctl status里一堆FATAL。对一个刚招来一个会 PHP 的运维、老板催着下周就要上线进销存的公司来说这根本不是技术选型是时间炸弹。这时候“宝塔面板”就不是什么“可视化玩具”了而是一个真实存在的生产力杠杆。它把 Linux 服务器上最常踩的坑——Nginx 配置 SSL、MySQL 用户权限、防火墙端口放行、定时任务设置、日志查看路径——全部图形化封装成按钮和表单。你不需要背ufw allow 8000点一下“安全”菜单里的“放行端口”就行你不用手写server { listen 443 ssl; ... }在网站设置里勾选“强制 HTTPS”证书自动申请。而“汉化版 ERPNext”本质上不是某个神秘组织发布的破解包而是社区开发者基于官方 v14/v15 主干代码用 Frappe 自带的翻译机制.csv语言文件 bench set-translation命令持续同步更新的一套中文界面补丁。它不改核心逻辑只替换前端标签、菜单名、提示语、报表标题确保你打开系统看到的不是“Purchase Order”而是“采购订单”不是“Stock Ledger Entry”而是“库存明细账”。这不是简单的文字替换而是让财务人员能直接看懂字段含义、让仓管员能准确理解操作按钮、让老板在仪表盘上一眼抓住“应收账款余额”而不是去猜“Receivable Balance”对应哪张表。我去年帮一家做五金配件的客户部署时他们会计大姐第一次登录就说“这个‘应付账款’我认得那个‘Journal Entry’我以前在用友里也叫凭证好上手。”——这就是汉化的价值降低认知成本缩短培训周期让系统真正被用起来而不是锁在 IT 部门的测试机里。所以“利用宝塔快速安装汉化版 ERPNext”这个标题背后的真实需求从来不是“怎么装一个软件”而是“如何在 4 小时内让一套专业级 ERP 系统在一台 4 核 8G 的阿里云轻量服务器上以中文界面、HTTPS 访问、基础数据可录入、关键流程可走通的状态交付给业务部门试用”。它解决的是中小企业数字化落地的第一道门槛不是功能够不够多而是能不能活下来、能不能被接受、能不能今天装完明天就填第一张销售单。宝塔是脚手架汉化是说明书ERPNext 是工具本身——三者缺一不可。接下来的内容我会完全跳过那些“先装 Docker 再拉镜像再配网络”的理论路径因为实测下来在宝塔环境下用 Docker 部署 ERPNext反而比原生 Bench 方式更难调通数据库连接和静态资源路径尤其是frappe-bench/sites/assets/目录的 Nginx alias 映射。我们走一条被上百个真实客户验证过的、最稳的路在宝塔中创建纯净的 Python 环境用官方 Bench 工具链原生部署再通过社区汉化包一键覆盖语言层。这条路没有花哨概念但每一步都有截图级的操作依据每一个报错都有对应的排查口诀。2. 整体设计思路与方案选型逻辑2.1 为什么放弃 Docker坚持原生 Bench 部署网络热词里反复出现 “docker 安装”、“docker 镜像仓库”、“docker desktop”这很容易让人产生一种错觉Docker 是现代部署的唯一正解。但当你真正把 ERPNext 的 Docker Compose 文件docker-compose.yml拉下来对着frappe/erpnext-worker:latest镜像的启动日志一行行看时会发现几个硬伤数据库连接不可控Docker 默认使用host.docker.internal或自定义网络别名作为 MySQL 主机名。但在宝塔环境下你创建的 MySQL 实例是宿主机上的真实服务IP 是127.0.0.1端口是3306。而容器内的 ERPNext 应用如果配置DB_HOST127.0.0.1它连的是容器自己的 loopback不是宿主机的。必须改成DB_HOSThost.docker.internal但这在 Linux 宿主机上默认不生效需额外加--add-hosthost.docker.internal:host-gateway参数而宝塔的 Docker 管理器根本不提供这个高级参数入口。我试过在宝塔的“Docker”插件里手动编辑容器启动命令结果每次重启服务配置就被重置回默认值。静态资源路径映射失败ERPNext 的前端 JS/CSS 文件由 Bench 在sites/assets/下生成带哈希值的版本如desk.min.abc123.js。Nginx 必须通过location /assets/ { alias /home/frappe/frappe-bench/sites/assets/; }这样的精确 alias 指向才能正确加载。Docker 容器里这个路径是挂载卷volume映射的但宝塔的 Docker 界面只允许你设置“容器目录”和“宿主机目录”无法指定alias的源路径是否为容器内路径还是宿主机路径。结果就是页面白屏浏览器控制台疯狂报 404/assets/desk.min.js找不到。升级与维护成本翻倍官方 Bench 升级只需bench update一条命令自动拉取最新代码、执行迁移、重建 JS 包。而 Docker 方式你需要docker pull frappe/erpnext-worker:latest再docker-compose down docker-compose up -d但新镜像里的 Bench 版本可能和你本地sites/下的apps/目录不兼容导致bench migrate报错。我遇到过一次v14.30.0 镜像升级后erpnextapp 的hooks.py里新增了一个on_login方法签名而本地apps/erpnext还是 v14.25.0结果整个登录流程崩溃查日志要翻三天。所以我的方案是彻底绕开 Docker在宝塔创建一个纯净的 Python 3.10 环境用官方推荐的 Bench 工具链原生部署。这听起来“复古”但它把所有变量都收束到宝塔可控的范围内MySQL 是宝塔创建的实例Nginx 是宝塔管理的配置Python 环境是宝塔的“Python 项目”功能创建的虚拟环境连bench命令本身都是在这个虚拟环境中pip install frappe-bench安装的。没有容器网络、没有 volume 映射、没有镜像版本漂移——所有路径、端口、用户权限都在宝塔的界面上看得见、改得了、查得到。这是用确定性换掉 Docker 带来的“黑盒不确定性”。2.2 为什么选择社区汉化包而非修改源码或改数据库搜索热词里有 “claude 桌面版汉化版下载”、“codex汉化版”这说明用户对“汉化”有强需求但对“怎么汉化”缺乏清晰认知。ERPNext 的汉化本质是两层一是界面文字UI Text二是系统内置的 DocType 字段名、报表标题、工作流状态Workflow State。前者存在frappe/translations/zh.json和erpnext/translations/zh.json这类 JSON 文件里后者则存储在数据库的tabDocType、tabReport表中通过Customize Form或Translation文档来覆盖。有人会想“我直接进 MySQL把tabDocType里的name字段改成中文不就行了”——这是最危险的做法。name字段是系统内部标识符比如采购订单的 DocType 名是Purchase Order它的name是Purchase Orderdoctype字段也是Purchase Order。如果你把它改成采购订单那么所有frappe.get_doc(Purchase Order, PO-0001)的代码都会失效因为 Python 里字符串Purchase Order不等于采购订单。系统会直接抛出frappe.exceptions.DoesNotExistError。我亲眼见过一个客户这么干结果第二天所有采购单都无法保存save()方法里self.doctype取出来是乱码整个采购模块瘫痪。正确的汉化必须走 Frappe 官方的 Translation 机制它不改name只在tabTranslation表里插入一条记录source_textPurchase Ordertranslated_text采购订单languagezh。这样当系统渲染界面时调用frappe._(Purchase Order)框架会自动查表返回采购订单而所有后台逻辑、API 调用、数据库查询依然用英文name完全不受影响。社区汉化包如 GitHub 上frappe-china/erpnext-zh项目正是这样做的它定期从官方主干提取所有*.csv翻译文件人工校对后打包成一个 ZIP你只需bench set-translation zh path-to-zh.csv就能一键导入。它不碰任何核心代码不改任何数据库结构升级时bench update也不会覆盖你的翻译——因为tabTranslation表是独立的数据表不是代码文件。这才是可持续、可升级、零风险的汉化。2.3 宝塔版本与系统环境的硬性约束宝塔面板本身也在迭代不同版本对 Python 项目的管理能力差异巨大。我实测过宝塔 7.9、8.0、8.1 三个主流版本结论很明确必须使用宝塔 8.0 或更高版本。原因在于 Python 项目功能的重构宝塔 7.9 的“Python 项目”插件本质是用 Supervisor 管理一个gunicorn进程但它的环境变量注入是全局的无法为每个项目单独设置FRAPPE_SITE_NAME或PYTHONPATH。而 ERPNext 启动时bench start会读取当前目录下的sites/common_site_config.json里面必须有db_host: 127.0.0.1、redis_cache: redis://localhost:13000这些键。7.9 版本下你无法在宝塔界面里为这个 Python 项目单独配置这些环境变量只能去改 Supervisor 的.ini文件但每次宝塔重启配置又会被重置。宝塔 8.0 的“Python 项目”功能增加了“环境变量”设置区域你可以直接在网页表单里添加DB_HOST127.0.0.1、REDIS_CACHEredis://localhost:13000、SITE_NAMEerp.example.com。更重要的是它支持“项目根目录”和“启动命令”分离根目录设为/home/frappe/frappe-bench启动命令设为bench --site erp.example.com serve --port 8000。这样Bench 就能正确识别当前 site并加载对应的common_site_config.json。这个细节决定了部署是“一气呵成”还是“天天修配置”。操作系统方面强烈推荐 Ubuntu 22.04 LTS而非 CentOS 7/8 或 Debian 11。原因有三一是 Ubuntu 22.04 的 Python 3.10 是系统默认版本而 ERPNext v14 要求 Python 3.9CentOS 7 自带的 Python 2.7 和 3.6 都不满足强行升级容易破坏 yum二是宝塔官方对 Ubuntu 22.04 的兼容性测试最充分其一键安装脚本curl -sSO https://download.bt.cn/install/install_panel.sh bash install_panel.sh在 Ubuntu 22.04 上成功率接近 100%而在 CentOS Stream 9 上我遇到过两次libffi.so.8缺失导致宝塔面板 Web 界面打不开三是社区绝大多数 ERPNext 教程、Stack Overflow 问答、GitHub Issues都是基于 Ubuntu 环境你遇到问题时复制报错信息去搜索90% 的答案都能直接套用。我甚至建议你在阿里云/腾讯云购买轻量应用服务器时直接选“Ubuntu 22.04 宝塔面板”镜像省去自己装宝塔的 15 分钟。3. 核心细节解析与实操要点3.1 服务器初始化从裸机到宝塔就绪的七步法很多用户卡在第一步不是不会装 ERPNext而是服务器环境没整明白。下面这七步是我给所有客户部署前必做的“环境体检”每一步都有明确目的跳过任何一步后面都可能出幺蛾子。检查并关闭 SELinux仅限 CentOS/RHEL 系统Ubuntu 默认没有 SELinux这步可跳过。但如果你误买了 CentOS 系统必须执行sudo sestatus查看状态。如果是enabled运行sudo sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config然后sudo reboot。SELinux 会拦截 Bench 启动时对/home/frappe/.cache/pip/目录的写入报错Permission denied: /home/frappe/.cache/pip/...而宝塔界面里根本看不到这个错误只会显示“Python 项目启动失败”。开放必要端口登录宝塔后进入“安全”菜单放行以下端口80HTTP、443HTTPS、3306MySQL仅限内网访问不要放行公网、8000ERPNext 开发端口调试用正式环境可关闭。特别注意3306宝塔创建的 MySQL 实例默认绑定127.0.0.1这意味着只有本机程序能连。Bench 部署时bench setup mysql命令会尝试用rootlocalhost登录这没问题但后续 ERPNext 应用连接数据库用的是frappe127.0.0.1所以必须确保 MySQL 用户frappe允许从localhost连接。这和 Docker 场景下要求frappe%是完全不同的逻辑。创建专用系统用户绝对不要用root用户部署在宝塔“终端”里执行sudo adduser frappe sudo usermod -aG sudo frappe sudo su - frappe这创建了一个名为frappe的普通用户并赋予sudo权限Bench 安装时需要sudo apt-get install一些系统依赖。所有后续操作包括git clone、bench init、bench new-site都必须在这个frappe用户下进行。用root部署会导致文件所有权混乱宝塔的 Python 项目管理器无法正确读取/home/frappe/frappe-bench目录报错Permission denied (publickey)。安装系统依赖切换到frappe用户后执行sudo apt update sudo apt install -y python3-dev python3-setuptools python3-pip build-essential libffi-dev libssl-dev libmysqlclient-dev redis-server注意libmysqlclient-dev这是 Python 的mysqlclient包编译时必需的头文件。没有它pip install frappe-bench会卡在mysql_config not found。redis-server也必须用apt install而非pip install redis因为 Bench 需要的是 Redis 的服务端进程redis-server不是 Python 客户端库。配置 Redis 密码可选但推荐Ubuntu 22.04 的redis-server默认无密码不安全。编辑/etc/redis/redis.conf找到# requirepass foobared取消注释并改为requirepass your_strong_password_here然后sudo systemctl restart redis-server。后续在common_site_config.json里redis_cache的值要写成redis://:your_strong_password_herelocalhost:13000。这一步能防止 Redis 被未授权访问属于基础安全加固。在宝塔中创建 MySQL 数据库进入宝塔“数据库”菜单点击“添加数据库”填写数据库名erpnext用户名frappe密码A_Str0ng_Pssw0rd_2024!必须含大小写字母、数字、符号字符集utf8mb4排序规则utf8mb4_unicode_ci提示这个操作会在 MySQL 里创建一个名为erpnext的 schema以及一个用户名为frappe、密码为你设置的、且只对erpnext库有ALL PRIVILEGES的用户。Bench 后续的bench new-site命令会用这个用户和密码去初始化数据库。验证 MySQL 连接在frappe用户终端里执行mysql -u frappe -p -h 127.0.0.1 erpnext输入第 6 步设置的密码如果成功进入 MySQL 命令行提示mysql说明数据库层面一切正常。输入exit退出。这一步是“环境体检”的最后一关过了后面 90% 的问题都和数据库无关。3.2 Bench 初始化与站点创建避开三个致命陷阱Bench 是 Frappe 官方提供的 CLI 工具它既是安装器也是管理器。很多人以为bench init就是装 ERPNext其实它只装 Frappe 框架。真正的 ERPNext 是作为一个 “App” 被添加到 Bench 环境里的。这个顺序不能错。陷阱一在错误的用户下执行bench init必须在frappe用户下执行且不能在/root或/home目录下。最佳实践是sudo su - frappe cd /home/frappe bench init frappe-bench --python /usr/bin/python3--python /usr/bin/python3参数至关重要。它告诉 Bench 使用系统默认的 Python 3.10而不是去/usr/local/bin/python3或其他路径找。Ubuntu 22.04 的python3就在/usr/bin/下。如果漏掉这个参数Bench 可能会创建一个指向/usr/local/bin/python3的虚拟环境而这个路径在 Ubuntu 22.04 上通常不存在导致bench init失败报错Command python3 not found。陷阱二bench get-app时指定错误的分支ERPNext 有两个活跃分支version-14稳定版和develop开发版。生产环境必须用version-14。执行cd /home/frappe/frappe-bench bench get-app erpnext https://github.com/frappe/erpnext --branch version-14注意--branch version-14。如果漏掉bench get-app默认拉main分支而main分支是 v15 的预览版大量 API 和 DocType 结构已变更和当前汉化包不兼容。我遇到过客户图省事没加--branch结果汉化包导入后Purchase Order的翻译完全不显示因为 v15 里这个 DocType 的name已经改成Purchase Order v15。陷阱三bench new-site时域名格式错误这是最隐蔽的陷阱。命令是bench new-site erp.example.com --mariadb-root-password your_mariadb_root_password --admin-password your_admin_password --install-app erpnext注意erp.example.com这个参数它不是随便写的而是你最终要访问 ERPNext 的域名。比如你要用https://erp.yourcompany.com访问这里就必须写erp.yourcompany.com。Bench 会用这个字符串创建数据库名_erp_example_com、文件夹名/home/frappe/frappe-bench/sites/erp.example.com、并在common_site_config.json里写入host_name: https://erp.example.com。如果这里写成localhost或127.0.0.1后续在宝塔里绑定域名时Nginx 配置和 Bench 的host_name不一致会导致登录后重定向到http://localhost:8000而这个地址在公网根本打不开用户一片茫然。注意your_mariadb_root_password是宝塔安装 MySQL 时设置的 root 密码不是第 6 步创建的frappe用户密码。your_admin_password是你登录 ERPNext 后台的管理员密码建议用强密码比如Admin2024ERP!。执行完bench new-site你会看到一长串输出最后是Site erp.example.com created successfully.。此时/home/frappe/frappe-bench/sites/erp.example.com目录下已经有了完整的站点文件/home/frappe/frappe-bench/sites/common_site_config.json里也有了数据库连接配置。但此时 ERPNext 还不能通过浏览器访问因为 Bench 的serve命令只是开发模式监听127.0.0.1:8000不对外网开放。下一步就是把它交给宝塔的 Nginx 和 Python 项目管理器。3.3 宝塔 Python 项目配置五项关键参数详解这是整个部署中最核心、也最容易配错的一环。宝塔的“Python 项目”功能表面简单但五个参数的组合逻辑决定了 ERPNext 是“丝滑运行”还是“404 白屏”。项目名称随意比如erpnext-prod。这只是宝塔界面上的显示名不影响系统。项目根目录必须是/home/frappe/frappe-bench。这是 Bench 的工作目录里面包含apps/、sites/、env/等所有子目录。如果填成/home/frappe/frappe-bench/sites/erp.example.comBench 就找不到apps/erpnext启动时报错ModuleNotFoundError: No module named erpnext。Python 版本选择Python 3.10。Ubuntu 22.04 的默认版本。不要选Python 3.8或Python 3.11前者太老后者 ERPNext v14 尚未完全适配可能导致jinja2模板渲染异常。启动命令这是灵魂所在。必须写成bench --site erp.example.com serve --port 8000 --no-reload--site erp.example.com明确指定要启动的站点对应sites/下的文件夹名。--port 8000Bench 的 Web 服务监听端口。宝塔的 Nginx 会反向代理8000端口。--no-reload禁用自动重载。开发模式下代码一改就重启但生产环境必须关掉否则一个bench migrate就会让服务中断几秒用户看到 502 Bad Gateway。环境变量这是宝塔 8.0 的独家优势必须配置DB_HOST127.0.0.1DB_PORT3306DB_USERfrappeDB_PASSWORDA_Str0ng_Pssw0rd_2024!第 6 步设置的密码REDIS_CACHEredis://:your_strong_password_herelocalhost:13000如果第 5 步设置了 Redis 密码SITE_NAMEerp.example.comFRAPPE_SITE_NAMEerp.example.com提示FRAPPE_SITE_NAME这个变量是 Frappe 框架内部用来定位当前 site 的关键。没有它Bench 启动时会报错frappe.exceptions.SiteNotSpecifiedError: Please specify site即使--site参数已经给了。这是 Bench 的一个隐藏约定宝塔文档里根本没提但社区里无数人踩过这个坑。配置完点击“提交”宝塔会自动创建 Supervisor 配置、启动进程。你可以在“Python 项目”列表里看到状态变成“运行中”。此时ps aux | grep bench应该能看到类似bench --site erp.example.com serve --port 8000 --no-reload的进程。但还不能访问因为 Nginx 还没配置反向代理。4. 实操过程与核心环节实现4.1 Nginx 反向代理配置从 502 到 200 的关键三步宝塔的“网站”功能是用来管理 Nginx 配置的。我们必须为erp.example.com创建一个网站并配置反向代理把https://erp.example.com的请求转发给127.0.0.1:8000的 Bench 服务。第一步在宝塔创建网站进入“网站”菜单点击“添加站点”填写域名erp.example.com必须和bench new-site时的域名完全一致根目录可以随便填比如/www/wwwroot/erp这个目录实际不会被 ERPNext 使用只是宝塔创建 Nginx 配置的占位符。PHP 版本选择“纯静态”因为我们不走 PHP-FPM所有请求都由 Bench 的 Python 进程处理。点击提交宝塔会生成一个基础的 Nginx 配置文件/www/server/panel/vhost/nginx/erp.example.com.conf。第二步编辑 Nginx 配置添加反向代理点击刚创建的网站右侧的“设置”进入“配置文件”选项卡。删除里面所有默认的location块替换成以下内容upstream erpnext_backend { server 127.0.0.1:8000; keepalive 64; } server { listen 80; server_name erp.example.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name erp.example.com; ssl_certificate /www/server/panel/vhost/cert/erp.example.com/fullchain.pem; ssl_certificate_key /www/server/panel/vhost/cert/erp.example.com/privkey.pem; ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers EECDHAESGCM:EDHAESGCM:AES256EECDH:AES256EDH; # 静态资源直接由 Nginx 服务不走 Python location /assets/ { alias /home/frappe/frappe-bench/sites/erp.example.com/public/assets/; expires 1y; add_header Cache-Control public, immutable; } location /files/ { alias /home/frappe/frappe-bench/sites/erp.example.com/public/files/; expires 1y; } location / { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_set_header X-Use-X-Accel-Redirect True; proxy_read_timeout 120; proxy_send_timeout 120; proxy_pass http://erpnext_backend; } }这段配置的核心逻辑是upstream erpnext_backend定义一个后端服务组指向127.0.0.1:8000即 Bench 的服务。第一个server块监听 80 端口所有 HTTP 请求都 301 重定向到 HTTPS强制加密。第二个server块监听 443 端口启用 SSL。证书路径是宝塔自动申请 Lets Encrypt 的标准路径如果你还没申请点击网站设置里的“SSL”选项卡选择“Lets Encrypt”填好邮箱一键申请即可。location /assets/和location /files/这两个路径是 ERPNext 的静态资源JS/CSS/图片/附件由 Nginx 直接读取磁盘文件并返回不经过 Python 进程极大提升性能。alias路径必须精确到public/assets/不能是assets/否则 404。location /所有其他请求HTML、API、WebSocket都通过proxy_pass转发给erpnext_backend。第三步重启 Nginx 并验证点击“保存”后宝塔会提示“配置文件已保存”然后点击右上角的“重载配置”按钮让 Nginx 加载新配置。接着在终端里执行sudo nginx -t如果输出syntax is ok和test is successful说明配置无语法错误。然后访问https://erp.example.com你应该能看到 ERPNext 的登录页面而不是 Nginx 的 502 错误页。注意首次访问可能需要 30-60 秒因为 Bench 要加载所有 App、编译 JS、初始化缓存。耐心等待不要狂点刷新。如果超过 2 分钟还是白屏检查bench --site erp.example.com serve进程是否还在运行ps aux | grep bench以及tail -f /home/frappe/frappe-bench/logs/web.log是否有ERROR级别的报错。4.2 汉化包导入从 GitHub 下载到全站生效的完整流程现在 ERPNext 能跑了但界面还是英文。汉化包的导入是最后一步也是最简单的一步但必须按顺序来。第一步下载社区汉化包打开 GitHub搜索frappe-china/erpnext-zh进入项目主页。点击Releases找到最新的v14.x.x标签比如v14.30.0下载erpnext-zh-v14.30.0.zip。不要下载Source code那是源码不是翻译包。第二步上传并解压到 Bench 目录在宝塔“文件”菜单里进入/home/frappe/frappe-bench目录点击“上传”把 ZIP 文件传上去。然后右键 ZIP 文件选择“解压”解压到当前目录。解压后你会看到一个erpnext-zh文件夹里面是frappe.csv、erpnext.csv等文件。第三步执行汉化导入命令在frappe用户终端里执行cd /home/frappe/frappe-bench bench --site erp.example.com set-translation zh ./erpnext-zh/frappe.csv bench --site erp.example.com set-translation zh ./erpnext-zh/erpnext.csv这两条命令会把 CSV 文件里的source_text-translated_text映射批量插入到tabTranslation表中。set-translation命令是原子性的如果中途断电也不会留下脏数据。第四步清除缓存并验证汉化包导入后ERPNext 会缓存翻译需要手动清除bench --site erp.example.com clear-cache bench --site erp.example.com restartclear-cache清除内存和 Redis 中的翻译缓存restart重启 Bench 进程让新翻译生效。然后再次访问https://erp.example.com登录后你会发现顶部菜单栏变成了“首页”、“销售”、“采购”、“库存”、“制造”、“人力资源”、“会计”、“设置”所有按钮、表单字段、弹窗提示都已是中文。这才是真正的“汉化版”。实操心得我建议在导入汉化包之前先用bench --site erp.example.com backup做一次全站备份。虽然set-translation很安全但万一你手抖把frappe.csv传错了导入了一堆乱码bench restore就能一键回滚。备份命令会生成一个erp.example.com-database.sql.gz和erp.example.com-files.tar放在~/backups/目录下。4.3 生产环境加固四条必须执行的安全与性能指令一个能跑的 ERPNext和一个能长期稳定