Composer脚本不直接提取语言包,需封装php-xgettext、linguist等工具命令到scripts中,如"i18n:extract": "php bin/extract-lang.php",再通过composer run i18n:extract触发;提取失败多因自动加载未就绪,应手动引入autoload.php或启动Laravel应用实例。

Composer脚本如何触发语言包提取命令
Composer 本身不处理国际化(i18n)提取,它只负责执行你定义的脚本命令。真正干活的是 php-xgettext、symfony/translation 的 extract 命令,或 Laravel 的 lang:publish 等工具。你需要把提取逻辑封装成可调用的 PHP 脚本或 CLI 命令,再通过 Composer 的 scripts 注册。
常见做法是写一个独立的 PHP 文件(比如 bin/extract-lang.php),在其中加载框架上下文、扫描源码、调用翻译提取器生成 .pot 或 .json 文件。
- 确保该脚本有可执行权限(
chmod +x bin/extract-lang.php),或通过php bin/extract-lang.php显式调用 - 在
composer.json的scripts段里注册:"scripts": { "i18n:extract": "php bin/extract-lang.php" } - 运行时直接执行
composer run i18n:extract(Composer 2.5+)或composer i18n:extract(旧版)
为什么 extract 命令常报 “Class not found” 错误
这类错误几乎都源于自动加载未就绪——脚本在 Composer 自动加载器初始化前就执行了,或者用了错误的加载方式。典型表现是 new Translator() 或 app()->make(...) 报错。
- 不要在脚本开头直接 new 类;改用
require 'vendor/autoload.php'手动引入(确保路径正确) - 如果是 Laravel 项目,必须先启动应用实例:用
require __DIR__.'/../bootstrap/app.php'启动容器,再从$app获取服务 - 避免在脚本中依赖
$_SERVER或请求上下文(如request()),提取阶段无 HTTP 请求环境 - 检查脚本是否被当作 Web 入口执行(比如通过浏览器访问),应始终通过 CLI 运行
Laravel 中用 vendor/bin/linguist 提取时路径怎么配
linguist 是社区常用的小型提取工具,但默认不识别 Laravel 的 Blade 模板和 __('...') 语法,需手动指定解析规则和搜索路径。
- 基础命令示例:
vendor/bin/linguist --format=pot --output=resources/lang/en/messages.pot app/ resources/views/
- 必须加
--function=__('...')和--function=trans(...)才能捕获 Laravel 的翻译函数 - Blade 文件需显式加入搜索路径(
resources/views/),否则只扫 PHP 文件 - 若用
@lang或@trans指令,linguist默认不支持,得换php-xliff或自己写正则提取器
提取后怎么自动合并进现有语言文件而不覆盖
直接覆盖会丢掉已有的翻译和注释。安全做法是“提取 → 合并 → 人工校对”,而非全量替换。
- 用
msgmerge(GNU gettext 工具)合并:msgmerge --update resources/lang/zh_CN/messages.po resources/lang/en/messages.pot
- 若用 JSON 格式(如 Laravel 9+ 的
lang:publish输出),可用jq工具做键级合并:jq -s 'reduce .[] as $item ({}; . * $item)' en.json zh.json > merged.json - 注意:
msgmerge要求系统已安装gettext包(macOS 用brew install gettext,Ubuntu 用apt install gettext) - 合并不是万能的——新增键会加进去,但已删除的键不会自动清理,得靠 diff 工具辅助判断
实际落地时,最易被忽略的是提取范围和上下文一致性:比如漏扫 resources/js/ 里的 Vue 组件,或没处理 __($key, [], 'domain') 中的 domain 参数导致分域翻译错乱。











