ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Symfony Loco 翻译提供者桥接器(Loco Translation Provider Bridge)演进全解析

Symfony Loco 翻译提供者桥接器(Loco Translation Provider Bridge)演进全解析 后端Web框架【免费下载链接】symfonyThe Symfony PHP framework项目地址https://gitcode.com/GitHub_Trending/sy/symfony点击查看免费下载Symfony 官方仓库为 Loco 本地化平台localise.biz提供了开箱即用的翻译提供者桥接器位于 src/Symfony/Component/Translation/Bridge/Loco。它通过 DSN 连接 Loco 的翻译 API让 Symfony 应用能够把翻译键assets、翻译消息translations与标签tags直接同步到 Loco 项目管理。本文基于该桥接器的 CHANGELOG.md 完整梳理其从 5.3 到 8.2 的能力演进并结合源码逐条解读每次变更背后的实现原理帮助你理解如何配置 DSN、如何利用status、If-Modified-Since增量同步、域domain与标签过滤映射等能力把 Loco 桥接器正确接入自己的翻译工作流。一、桥接器概览5.3 诞生与 5.4 转正CHANGELOG 显示Loco 桥接器于5.3版本创建并在5.4版本起不再标记为实验性experimental意味着从 5.4 开始官方承诺其 API 稳定性可以放心在生产环境使用。该桥接器包含两个核心类均位于 src/Symfony/Component/Translation/Bridge/LocoLocoProvider.php实现ProviderInterface负责将翻译内容写入 Locowrite、从 Loco 读取read以及删除deleteLocoProviderFactory.php解析loco://DSN 并构建LocoProvider同时负责 HTTP 客户端的重试与认证配置。从 LocoProvider.php 的类注释可以理解 Loco 与 Symfony 的术语映射Loco 术语Symfony 术语Tags标签翻译域domainsAssets资产翻译键keysTranslations翻译翻译消息messages这一映射是理解后续所有配置域映射、标签过滤、键名编码的基础。1.1 DSN 配置示例桥接器自带的 README.md 给出了最小可用配置# .env file LOCO_DSNloco://API_KEYdefault?statustranslated,blank-translation其中API_KEY是你的 Loco 项目 API 密钥default表示使用 Loco 官方默认主机localise.biz源码中LocoProviderFactory::HOST常量见 LocoProviderFactory.php查询参数status用于限定读取的翻译状态。对应测试 LocoProviderFactoryTest.php 验证了 DSN 的两种合法形态loco://API_KEYdefault与loco://API_KEYdefault?statustranslated,provisional并验证loco://default缺少 API 密钥会被视为不完整 DSN。1.2 工厂的底层组装LocoProviderFactory::create()LocoProviderFactory.php做了三件事校验 DSN scheme 必须为loco否则抛出UnsupportedSchemeException将普通 HttpClient 包装成RetryableHttpClient重试策略为GenericRetryStrategy最多 3 次再通过ScopingHttpClient::forBaseUri固定请求基址https://host/api/并自动注入认证头Authorization: Loco API_KEY传入XliffFileLoader、XliffFileDumper与可选的TranslatorBagInterface最终构造LocoProvider。在框架层面translation_providers.php 注册了translation.provider_factory.loco服务它使用独立的 HTTP 客户端translation.provider_factory.loco.http_client最大主机连接数 10并注入translation.loader.xliff、translator作为 translatorBag与translation.dumper.xliff。二、6.1$translatorBag注入与If-Modified-Since增量同步2.1 新增$translatorBag构造参数6.1 为LocoProviderFactory和LocoProvider增加了TranslatorBagInterface类型的$translatorBag构造参数。它的核心作用在读取流程中体现read()时会通过$this-translatorBag?-getCatalogue($locale)获取上一次的目录catalogue以此作为增量同步的依据。从当前 LocoProvider.php 的构造函数可以看到$translatorBag已经是第 5 个参数框架配置中由service(translator)注入。2.2If-Modified-Since作为目录元数据6.1 的另一项变更把 HTTP 响应头If-Modified-Since作为 catalog metadata 保存用于判断翻译值是否真的发生了变化。实现位于 LocoProvider.php读取成功200后从响应头取出Last-Modified通过$catalogue-setCatalogueMetadata(last-modified, $lastModified, $domain)写入目录元数据下一次读取时LocoProvider.php若上一个目录实现了CatalogueMetadataAwareInterface则把getCatalogueMetadata(last-modified, $domain)作为请求头If-Modified-Since发送。当 Loco 返回304 Not ModifiedLocoProvider.php时桥接器不会重复解析 XLIFF而是直接复用上一个目录的既有消息与元数据并记录日志No modifications found in Loco for locale %s and domain %s.从而节省带宽与解析开销。测试 LocoProviderTest.php 的testReadWithLastModified完整覆盖了这一行为第一次读取携带Accept: */*第二次读取则额外携带If-Modified-Since: last-modified并断言 304 时返回的目录与期望目录完全一致。三、7.2status查询参数支持7.2 为读取流程加入了status查询参数支持用于限定导出哪些状态的翻译。这正是 DSN 中?statustranslated,blank-translation的来源。在 LocoProviderFactory.php 中status从 DSN 选项中取出并传给 Provider在 LocoProvider.php 的读取请求中作为查询参数发送query [ filter $filter, status $this-restrictToStatus ?? translated,blank-translation, ],两点实现细节值得注意默认值未配置status时默认导出translated,blank-translation两种状态的翻译LocoProvider.php__toString()回显LocoProvider::__toString()LocoProvider.php会把restrictToStatus拼回 DSN 字符串例如loco://localise.biz?statustranslated,provisional便于在调试面板等场景还原当前提供者的配置。测试testReadWithRestrictToStatusLocoProviderTest.php验证了当statustranslated,provisional时请求 URL 为https://localise.biz/api/export/locale/de.xlf?filtermessagesstatustranslated%2Cprovisional。四、8.2域配置语义与标签过滤映射的现代化8.2 是 CHANGELOG 中变化最密集的版本共四项变更全部围绕read()的域domain配置语义展开。4.1 不传 locale 时读取全部语言变更CallingLocoProvider::read()without locale now fetches them all不传 locale 时拉取全部语言。实现见 LocoProvider.php$locales $locales ?: $this-getLocales();。getLocales()LocoProvider.php会请求GET /api/locales获取 Loco 项目中全部语言并把连字符-规范化为下划线_例如fr-FR→fr_FR因为 Symfony 使用下划线风格的语言标识。测试testReadForNoLocalesLocoProviderTest.php验证不传 locales 时桥接器先请求/api/locales得到en、fr再分别导出两个语言目录。4.2 废弃$defaultLocale构造参数变更Deprecate passingLocoProviderandLocoProviderFactoryconstructor a$defaultLocaleargument: it has no effect and can be removed废弃向两个类构造函数传入$defaultLocale该参数无任何效果可删除。由于 4.1 支持了不传 locale 即读取全部原本用于兜底的默认语言参数失去了意义。当前源码保留了向后兼容的字符串参数占位逻辑当检测到传入字符串时会触发trigger_deprecation(symfony/loco-translation-provider, 8.2, ...)提示该参数无效果并将在 9.0 移除见 LocoProvider.php 与 LocoProviderFactory.php。仓库中的 LocoProviderWithDefaultLocaleTest.php 与 LocoProviderFactoryWithDefaultLocaleTest.php 专门覆盖了这一废弃兼容路径。4.3 废弃不传域或传*变更Deprecate passing no domains or*toLocoProvider::read()configure your loco provider domains as an associative array with an empty string key and*as value废弃不传域或传*应把域配置成以空字符串为键、*为值的关联数组。在 LocoProvider.php 中若$domains为空或等于[*]会触发废弃提示并把域内部规范化为[ *]。所谓关联数组语义是// 旧写法已废弃全部域 $provider-read([], [en]); // 或 [*] // 新写法以空字符串为键、* 为值 $provider-read([ *], [en]);测试testReadForAllDomainsLocoProviderTest.php验证了旧的空数组与[*]两种调用都会触发预期的废弃消息且请求的filter参数为空字符串。4.4 标签过滤到域的映射变更Allow to map a tag filter to a domain允许把标签过滤映射到域。这是 8.2 的核心能力read()的$domains参数现在支持以关联数组形式把 Loco 标签过滤tag filter映射到 Symfony 域。实现见 LocoProvider.php$filters []; foreach ($domains as $filter $domain) { $filters[\is_int($filter) ? $domain : $filter] $domain; } $domains $filters;含义是传[messages]整数键filter与域同名即用域名字符串本身作为 Loco 标签过滤传[foo bar]字符串键foo是 Loco 标签过滤bar是 Symfony 域请求使用filterfoo但导入结果归入域bar两种形式可以混用例如[messages, foo bar]此时发起两次请求filter分别为messages和foo。读取到数据后桥接器通过retrieveKeyFromId()LocoProvider.php剥掉键名前缀Loco 资产 ID 以域__键形式命名见下文写入流程导入时把foo__index.hello还原为index.hello放入目标域。两个测试直接佐证了该行为testReadWithDomainMappingLocoProviderTest.phpread([foo bar], [en])时请求filterfoo返回目录只有一个域bar键为index.hellotestReadWithDomainsAndFiltersMixedLocoProviderTest.phpread([messages, foo bar], [en])时filter依次为messages、foo。五、写入与删除域与键的编码约定虽然 CHANGELOG 的变更集中在读取侧但理解write/delete的编码约定有助于看懂 8.2 的域映射设计。见 LocoProvider.php写入对每个语言、每个域通过POST /api/import/xlf上传 XLIFF查询参数localelocale、tag-newdomain即把 Symfony 域作为 Loco 标签创建消息键被重编码为{$domain}__{$key}例如messages__a、validators__post.num_comments这样导入后 Loco 资产 ID 天然携带域信息自动补建语言write()首先调用createMissingLocales()LocoProvider.php对比本地目录语言与 Loco 现有语言缺失的通过POST /api/locales创建删除对每个域__键组合发起DELETE /api/assets/{id}.json并处理 403API 密钥权限不足与 500 级错误。testCompleteWriteProcessLocoProviderTest.php验证了完整写入链路先GET /api/locales发现缺少fr接着POST /api/locales创建再按en/fr × messages/validators四个组合依次导入 XLIFF且每个请求都携带Authorization: Loco API_KEY。六、常见问题与升级建议6.1 错误处理语义读取不存在的语言Loco 返回404桥接器记录 warningLocale %s does not exist in your Loco project.并取消该语言的全部并发请求返回空目录LocoProvider.php读取 200 之外的其他状态码抛出ProviderExceptionUnable to read the Loco response: ...写入/删除遇到 5xx抛出ProviderException删除遇到 403提示 API 密钥无权限并抛出异常。6.2 从旧版本升级的注意点如果你正在升级到 8.2需按 CHANGELOG 处理三处变更构造参数从LocoProvider/LocoProviderFactory的构造函数中移除$defaultLocale参数当前传入会触发废弃提示9.0 将移除读取全部域把read([], ...)或read([*], ...)改为read([ *], ...)域映射如果需要在不同 Loco 标签与 Symfony 域之间建立映射使用关联数组形式read([tag_filter domain], ...)。6.3 应用前提该桥接器依赖symfony/http-client与symfony/translation组件composer.jsoncomposer.json要求 PHP 8.4.1并依赖symfony/translation: ^7.4|^8.0在 FrameworkBundle 应用中启用后框架会通过translation.provider_collection与translation.provider_factory.loco服务见 translation_providers.php自动接入 DSN 配置仓库测试目录 Tests 提供了基于MockHttpClient的完整测试用例可作为理解桥接器请求行为的最佳参考。七、小结从 5.3 创建、5.4 转正到 6.1 引入$translatorBag与If-Modified-Since增量同步、7.2 支持status状态过滤再到 8.2 重构读取语义不传 locale 拉全部语言、废弃$defaultLocale与*域写法、支持标签过滤到域的映射Loco 桥接器的演进始终围绕更精确、更增量、更少配置三个目标。当前仓库中的 LocoProvider.php 与 LocoProviderFactory.php 是这些能力的完整实现配合 LocoProviderTest.php 等测试你可以清晰地把每一次 CHANGELOG 条目对应到具体代码行为从而安全地规划升级与配置迁移。赞分享后端Web框架【免费下载链接】symfonyThe Symfony PHP framework项目地址https://gitcode.com/GitHub_Trending/sy/symfony点击查看免费下载相关推荐革命性云端翻译集成Symfony Translation提供者系统深度解析革命性云端翻译集成Symfony Translation提供者系统深度解析 还在为多语言项目管理头痛Symfony Translation提供者系统为你带来国际化后端Symfony Postmark Mailer Bridge 演进全解从 4.3 桥接器引入到 8.2 远程模板与 Webhook 支持Symfony Postmark Mailer Bridge 演进全解从 4.3 桥接器引入到 8.2 远程模板与 Webhook 支持 导读 本文以 Pos后端Web框架ShowDoc 内置 Symfony Translation 组件演进全解从 CHANGELOG 读懂 2.1→5.4 的翻译能力图谱ShowDoc 内置 Symfony Translation 组件演进全解从 CHANGELOG 读懂 2.1→5.4 的翻译能力图谱 本文以 ShowDoc文档知识库后端前端上一篇TASK: 用户认证模块开发下一篇Gemma-4-26B-A4B-StyleTune快速上手指南从安装到生成高质量文本的完整教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进