---
title: Bricks + Polylang：WordPress 多语言建站方案与 ACF 实践
slug: bricks-polylang-acf-free-compatibility
date: 2026-10-28
author: Frankie 徐
category: wordpress
tags: ['wordpress', 'bricks', 'polylang', 'acf', 'multilingual']
description: 用 Bricks、Polylang 免费版和 ACF 免费版搭建多语言 WordPress，分享页面与模板关联、字段隔离、原生语言切换的实现方式，以及免费版的适用边界。
permalink: https://www.210k.cc/bricks-polylang-acf-free-compatibility
---

用 Bricks 做多语言 WordPress，页面、模板和自定义字段应该怎么配合？Polylang 免费版够不够用？如果网站还用了 ACF，修改英文内容时，会不会把中文或西班牙语一起改掉？

我用一个虚构的徒步旅行网站做了三语言实验，包含普通页面、文章、Trip 自定义内容类型和 Terrain 分类法。先把多语言流程跑通，再把样式、语言切换和分类导航整理到 Bricks 原生能力里。

在这次基础字段和简单内容模型的范围内，**Bricks + Polylang Free + ACF Free 可以完成三语言建站，各语言内容和字段也能独立维护。** 实际需要花心思的地方，是语言对象怎么关联、模板怎么选择，以及哪些字段应该独立翻译、哪些事实需要同步。

下面按建站思路介绍这套方案。

> 本文基于 2026 年 10 月 25 日的实验及后续原生化改造记录，测试域名与私有路径已省略。使用版本为 WordPress 7.1.3、Bricks 2.4.3、Bricks Abilities 2.0.0、Polylang Free 3.9.1、ACF Free 6.8.10。Bricks 本身需要许可证；这里的“免费版”指 Polylang 和 ACF。

## 先分清三个工具的职责

这套组合可以按内容、语言和展示来理解：

| 工具 | 负责什么 |
|---|---|
| Polylang | 给文章、页面、自定义内容和词条分配语言，关联同一内容的不同语言版本 |
| ACF | 定义自定义内容类型、分类法和字段，并保存各内容对象的字段值 |
| Bricks | 用页面、模板、动态数据和 Query Loop，把当前语言的内容渲染出来 |

例如，一条路线有英文、中文和西班牙语三个版本，它们分别是独立的 WordPress 内容对象，由 Polylang 建立翻译关联。Bricks 读取当前对象的标题、正文和 ACF 字段，生成对应语言的详情页。

这里有一个容易混淆的点：**Polylang 管的是语言内容的组织方式，译文质量仍取决于翻译和审核。** 换成 Polylang，并不会让原本不准确的机器翻译自动变好。如果需求只是修正现有译文，TranslatePress 也支持人工修订；如果需要各语言独立编辑长文、产品资料或结构化字段，Polylang 的模型更值得考虑。

## 页面、内容和模板都要有语言归属

演示站采用 EN、ZH、ES 三种语言，英文为默认语言，不显示 `/en/`；中文和西班牙语分别使用 `/zh/`、`/es/`。

内容模型包含四类普通页面、两篇文章、三条 Trip 路线和两个 Terrain 词条。每项都有三个语言版本，共 27 个页面、文章及 Trip 内容对象，以及 6 个 Terrain 词条。品牌、路线和价格都是虚构示例。

### 先关联内容，再检查模板

建站时，先在 Polylang 中把 Trip 和 Terrain 纳入可翻译范围，再为 post、term 分配语言并建立翻译关联。普通文章也要分配对应语言的博客分类，不能只把正文翻译了，却继续挂在另一种语言的分类下。

Bricks 模板同样需要处理语言。本例有七组模板：Header、Footer、Trip 详情、Trip 列表、Terrain 列表、普通文章详情和 404。每组维护三个关联版本，共 21 个模板。

它们使用正常的 Bricks 模板条件，再由 Polylang 的语言关联参与匹配。没有额外用 language taxonomy 条件强行选择某个语言模板。

这也带来明确的维护成本：同一版式有三份模板，修改共享结构后，要检查其他语言版本是否需要同步。不能假设建立翻译关联之后，Bricks 的全部结构和文案就会一直自动保持一致。

### URL 可以翻译到什么程度

独立内容可以使用各自的 slug。例如，同一条路线的路径可以是：

| 语言 | 路径示例 |
|---|---|
| English | `/trips/atlantic-field-notes/` |
| 简体中文 | `/zh/trips/daxiyang-haian-xingji/` |
| Español | `/es/trips/apuntes-del-atlantico/` |

这里的内容 slug 已经本地化，但 CPT base `/trips/` 和 taxonomy base `/terrain/` 在三种语言中共用。单篇内容的 slug，与 Polylang Pro 的 URL base 翻译、相同 slug 等能力，需要分开理解。

## ACF：共用字段定义，各语言保存自己的值

ACF 的字段定义不需要复制三套。这次共用一个 Trip 内容类型、一个 Terrain 分类法和一个五字段组：

| 字段 | 含义 | 本例的处理方式 |
|---|---|---|
| `trip_duration` | 行程天数 | 初始化时给各语言显式写入相同数值 |
| `trip_price` | 价格 | 初始化时给各语言显式写入相同数值 |
| `trip_meeting` | 集合地点说明 | 各语言独立文本 |
| `trip_highlight` | 路线亮点 | 各语言独立文本 |
| `trip_difficulty` | 难度描述 | 各语言独立文本 |

**字段定义共用，不等于字段值必须同步。** 各语言的 Trip 是独立 post，因此可以保存自己的 ACF 值。

为了保住译文，这次关闭了 Polylang 全局 custom-fields 同步。实际修改英文价格或描述时，中文和西班牙语的值没有跟着变化；从后台修改西班牙语字段，也没有改写其他语言，测试后再还原。

这样做解决了语言隔离，却留下另一项业务责任：价格、天数等共享事实更新时，需要有明确的定向同步规则。不能为了同步价格，就开启所有 custom fields 的全局同步，把已经翻译好的文本也覆盖掉。

Bricks 动态模板直接读取当前语言对象的字段。ACF 免费版可以满足本例的基础字段需求，但这次没有验证 Relationship、Post Object 的跨语言对象映射，也没有测试 Repeater、Flexible Content、Options Pages 等复杂场景，不能把五个基础字段的结果推广到所有 ACF 组合。

## 展示层优先使用 Bricks 原生能力

首版为了快速验证，写了一个辅助插件来提供共用 CSS、语言切换和分类导航。继续检查 Bricks 的能力后，这些功能大部分可以直接由原生系统承担，最终前台已经停用该插件。

### 样式放回设计系统

基础字体、颜色和表单默认值放到 Theme Style；品牌色、内容宽度放到 global variables；组件布局、响应式和子选择器放到 global classes。

本例最后使用了 1 个全站 Theme Style、7 个自定义变量和 37 个 global classes。迁移时保留原元素 ID，重新回读了内容、语言关联、字段值和模板条件，确认样式调整没有改写内容模型。

这样整理后，样式能在 Bricks 的原生编辑界面里继续维护。没有把整份外部 CSS 塞进某个 class 的自定义 CSS 输入框，再把它算作原生化。

### 语言切换要指向同一内容的译文

Bricks 2.4.3 已有原生 `polylang-language-switcher` 元素，可以用于 Header 和 Footer，本例共使用六处。无需再为相同功能维护一个 shortcode 封装。

检查切换器时，重点是目标关联：从西班牙语某条 Trip 切到中文，应该进入这条 Trip 的中文版本，而不是只跳到中文首页。链接显示 EN、ZH、ES，并不足以证明关联正确。

### 分类导航用原生 Query Loop

Terrain 导航改为 term Query Loop，用 `{term_name}` 和 `{term_url}` 输出词条名称和链接。详情页与列表页则读取当前语言的内容与查询结果。

这里踩过一个小坑：把循环直接放在 `text-link` 上，保存时被拒，因为该元素不注册 `hasLoop`。改成由 Block 承担循环项，再放原生链接与 Text 子节点即可。

另外，Bricks Heading 在本次实验中没有执行直接填入的 shortcode。分类标题与描述改用原生动态数据，并分别设置 CPT 和 Terrain archive 模板，比继续补渲染逻辑更清楚。

### 表单保持原生，但按实际链路验证

三种语言继续使用 Bricks Form，只保存演示咨询，不发送邮件。启用保存功能时，通过 `bricks/set-global-settings` 的真实状态转换，让 Bricks 自己初始化 submission table；单独写一个保存开关，不等于存储表已经准备好。

验证也需要走完整路径：空表单是否被拒绝、成功提示是否出现、记录是否真正落库、归属是否为对应语言的页面和表单。本例的三条测试提交在核对后按精确 ID 清理。

## 如果通过 AI 或脚本搭建，接口边界也要分清

这次布局自动化使用已注册的 `bricks/*` AI abilities，创建页面和模板、写入原生元素、设置条件并渲染回读，沿用 Bricks 保存管线，没有直接写元素 postmeta。

语言分配与翻译关联则调用 Polylang 的 PHP API，例如 `pll_set_post_language()`、`pll_save_post_translations()` 及对应 term API；ACF 定义和字段值使用其 import/update API。

这三类操作各有自己的接口，不能都归为“Bricks 原生多语言管理”。本次主要通过 SSH/WP-CLI 调用 WordPress Abilities API，后续也验证了 WordPress Abilities REST 的 class 读写，但没有验收 MCP Adapter 的客户端传输链路，也没有启用 `bricks/execute-php`。

ACF 的 REST 读取与 Polylang 的语言管理扩展也要区分：能通过 REST 读出 `acf` 数据，不代表免费版同时获得了 Polylang Pro 的 `lang`、`translations` REST 能力。

如果要重复执行初始化，还要留意 ACF import 的 key 不等于 upsert。本例重跑时保留既有 definition 和 field ID，避免后台出现重复定义。Polylang 设置写入后，也要用下一次独立请求回读，确认设置真正持久化。

## 怎么确认这套方案真的跑通

只看到三种语言的页面还不够。更有价值的检查是：语言切换是否到同一内容、模板是否选对、字段有没有串语、修改源文会不会覆盖译文，以及表单是否真的保存。

这次最终改造后的主要验证结果如下：

| 检查内容 | 实验结果 |
|---|---|
| 语言关系、字段值和修改隔离 | 175 项检查通过 |
| 原生化前后的内容保留 | 48 个内容/模板对象、6 个 Terrain 词条的事实保持一致；33 个 Bricks 文档完成原生化检查 |
| 匿名 HTTP | 702 项检查通过，覆盖 36 条正常路由、本地化 404、模板、字段、SEO 目标、REST 和资源 |
| 浏览器阅读与导航 | 7 个代表页面在 1440px、375px 下抽样检查，共 14 个视口；另验证四步真实导航 |
| 三语言表单 | 21 项浏览器、配置及持久化检查通过 |

这些数字对应原始实验记录，不是每次阅读本文时都在运行的检查。浏览器只抽样了代表页面，没有把全部路由逐一做双视口、跨浏览器测试；表单也没有覆盖邮件投递、付款或真实预订。

SEO 检查核对了 canonical 和 hreflang 的实际目标 URL。模板检查同时核对了请求实际使用的 Header、内容和 Footer 对象，避免把“页面出现了中文”当作模板正确的充分条件。

调样式时也遇到过几个具体问题：class 子选择器中的 `& a, & .brand` 展开异常，拆成独立 selector 后解决；表单的 `fieldMargin` 实际生成 `.form-group` padding，会被 class 中的 padding 归零抵消；Theme Style 和 classes 可以输出到 inline style，不能仅凭没有外链 CSS 文件判断保存失败。

还有一个未解决的版本问题：通过 WP-CLI 创建或更新 Theme Style 时，出现过 `borderStyle/styles/buttonSizes` 枚举警告。原生编辑 UI 和前台检查通过，但警告根因仍待确认，不能当作已经修复。

## 用到真实网站前，还要补哪些验证

这个实验能支持的结论是：在上述版本、基础字段和完整三语言内容的条件下，这条建站路线可行。要扩展到业务站点，还需要继续处理几件事。

首先是**缺译文和规模**。本例每条内容都有三语言版本，没有系统覆盖缺模板、下架、缺字段时的行为；三条 Trip 也不足以证明分页、搜索、复杂过滤和大数据量下的表现。媒体使用共用 attachment，没有验证独立媒体 metadata 翻译。

其次是**生产链路**。最终方案不再强制全站 no-cache，但生产缓存、登录态页面和性能仍需单独验证。SEO 插件 metadata、SMTP、支付、备份完整恢复以及完整无障碍检查，也没有被这次功能实验替代。

最后是**旧站迁移**。这次没有迁移原有 TranslatePress 站点。若要迁移，建议先在独立 staging 中选一个真实页面、一组 ACF/term 数据和原有 URL，确认译文、模板、菜单、字段与 SEO 信息能正确映射，再检查路径变化和必要的 301，并验证回滚。

对需要独立维护各语言内容的网站，Bricks 负责展示、Polylang 负责语言关联、ACF 负责结构化字段，是一条可以继续采用和验证的路线。实际维护的重点，会落在模板结构同步、共享事实更新和译文审核上。

## 参考资料

- [Bricks：How to use Polylang with Bricks](https://academy.bricksbuilder.io/integrations/polylang/)
- [Polylang：多语言 CPT 与 taxonomy](https://polylang.pro/documentation/support/guides/multilingual-custom-post-types-and-taxonomies/)
- [Polylang：PHP Function reference](https://polylang.pro/documentation/support/developers/function-reference/)
- [Polylang：metadata 同步](https://polylang.pro/documentation/support/guides/synchronize-metadatas-between-translations/)
- [Polylang：REST API](https://polylang.pro/documentation/support/developers/rest-api/)
- [Polylang：URL slug 翻译](https://polylang.pro/documentation/support/guides/translating-urls-slugs/)
- [ACF：WordPress REST API Integration](https://www.advancedcustomfields.com/resources/wp-rest-api-integration/)
- [TranslatePress：Translation Editor](https://translatepress.com/docs/translation-editor/)