没有不值得去解决的问题,也没有不值得去学习的技术!

Standardizing the Translation Workflow for WordPress Legacy Post Excerpts and English Overrides After Migrating From SyntaxHighlighter to Code Block Pro

图4:第一批 20 篇全部显示为 ready 的只读验收结果。

Yesterday, I completed a batch of Chinese excerpt generation and English override translations for legacy Gutenberg + Code Block Pro articles.

My original plan for today was simple:

  1. Find legacy articles using other code block formats with empty Chinese excerpts;
  2. Convert the old code blocks to Code Block Pro;
  3. Reuse the excerpt generation and override translation workflow validated yesterday;
  4. Process the remaining legacy articles in batches.

I started today by handling the SyntaxHighlighter Evolved code blocks in the Gutenberg editor.

In the end, this batch was completed successfully:

  • Fixed batch size: 20 articles
  • Chinese excerpts written successfully: 20 articles
  • English override translations successful: 20 articles
  • Final status completed: 20 articles
  • Unfinished: 0 articles

However, there was a noticeable period of over-engineering along the way. Fortunately, I caught the issue and rolled it back in time, ultimately returning to a simpler, more maintainable solution.

1. A stable downstream processing workflow was already in place yesterday

The core workflow established yesterday could already handle Gutenberg + Code Block Pro articles:

Plaintext
Fixed Chinese candidate articles
→ Production environment read-only pre-check
→ GLM generates Chinese excerpt
→ Write Chinese article excerpt
→ Trigger SlyTranslate
→ Override corresponding English article
→ Save completed status

The actual execution entry point is:

Plaintext
bin/execute-single-candidate.py

It is already responsible for:

  • Validating Chinese and English article IDs;
  • Validating Polylang associations;
  • Generating the Chinese excerpt;
  • Writing the Chinese excerpt;
  • Saving a backup before writing;
  • Triggering SlyTranslate;
  • Saving the execution status;
  • Resuming after partial translation stage failures.

Therefore, when facing SyntaxHighlighter today, what truly needed to be added was not another excerpt and translation pipeline.

Only the upstream needed to change:

Plaintext
Identify SyntaxHighlighter
→ Convert to Code Block Pro
→ Verify conversion result

After the conversion is complete, the process should continue using yesterday’s execution mechanism.

2. Identifying actual Gutenberg SyntaxHighlighter blocks

The structure primarily used in production articles is as follows:

HTML
<!-- wp:syntaxhighlighter/code {"language":"php"} -->
<pre class="wp-block-syntaxhighlighter-code">
...
</pre>
<!-- /wp:syntaxhighlighter/code -->

This differs from legacy articles that rely solely on shortcodes or HTML classes for detection.

To avoid misdetection, identification this time was based on complete Gutenberg block boundaries rather than simply searching for the syntaxhighlighter keyword.

Read-only statistics from the production environment revealed:

  • Articles containing complete SyntaxHighlighter Gutenberg blocks: 815
  • Total SyntaxHighlighter blocks: 4608
  • Some of these articles also mix other legacy formats
  • ready articles that can directly serve as candidates for the current stage: 98
Figure 1: Statistical results after read-only scanning of Gutenberg SyntaxHighlighter blocks in the production environment.
Figure 1: Statistical results after read-only scanning of Gutenberg SyntaxHighlighter blocks in the production environment.

This means SyntaxHighlighter is currently a high-volume code block format among legacy articles, warranting its own identification and conversion rules.

However, these “dedicated rules” should only cover identification and conversion, not extend to the excerpt generation and translation stages.

3. Starting with a single article as a pilot

Before establishing the official batch, I selected one article for a pilot run:

  • Chinese article ID: 17586
  • English article ID: 17641
  • SyntaxHighlighter blocks before conversion: 1
  • Code Block Pro blocks before conversion: 0

After manually opening the Gutenberg editor, I converted the original SyntaxHighlighter block to Code Block Pro and confirmed:

  • The SyntaxHighlighter count changed from 1 to 0;
  • The Code Block Pro count changed from 0 to 1;
  • The original code text remained unchanged;
  • The Chinese title was unchanged;
  • The Chinese excerpt was still empty;
  • The Gutenberg structure was intact;
  • The Polylang Chinese-English association was normal.

I then reused the existing single-article executor and successfully completed:

  • Chinese excerpt generation;
  • Chinese excerpt writing;
  • English article override translation;
  • Final status recorded as completed.
Figure 2: Editor interface after converting the pilot article from SyntaxHighlighter to Code Block Pro.
Figure 2: Editor interface after converting the pilot article from SyntaxHighlighter to Code Block Pro.

This step effectively proved:

After converting SyntaxHighlighter articles to Code Block Pro, they can directly enter yesterday’s processing workflow.

4. Establishing the first fixed batch of 20 articles

Following the successful pilot, I created the first fixed list from the ready candidates.

This batch contained 20 articles, including:

  • 18 articles each containing 1 SyntaxHighlighter block;
  • 2 articles each containing 2 SyntaxHighlighter blocks;
  • The pilot article 17586 was excluded from the official batch;
  • No overlap with the 42 articles processed yesterday;
  • All Chinese excerpts were empty;
  • Both Chinese and English articles were publish;
  • Polylang bidirectional relationships were normal.

Once the batch was generated, no articles were automatically added or replaced.

The reason for this is that manual conversion had become part of the batch. If candidates were reselected during execution, it could easily lead to inconsistencies between the list, the snapshot, and the objects of manual operation.

5. Special attention to code language during manual conversion

During the actual conversion, I found that upon opening the Gutenberg editor, some SyntaxHighlighter blocks were automatically converted to Code Block Pro by existing configurations, while others were not.

Therefore, each article was handled as follows:

  • Automatic conversion successful: check and save;
  • No automatic conversion: convert manually;
  • Check the Code Block Pro count before saving;
  • Check the language of each code block.

The language check is particularly important.

Code Block Pro sometimes inherits the language of the last edited code block instead of the language declared in the original SyntaxHighlighter block.

Therefore, the following rules were applied:

  • If the original block explicitly declared languages like php, bash, sql, or yaml, Code Block Pro was set to the corresponding language;
  • If the original block did not declare a language, it was set to Plaintext;
  • Mermaid code blocks continued to use mermaid;
  • HTML code blocks continued to use html.
Figure 3: Verifying the code language in Code Block Pro settings.
Figure 3: Verifying the code language in Code Block Pro settings.

It should be noted that Plaintext does not mean translation is absolutely prohibited.

If the content consists of commands, parameters, paths, configurations, or code, it should remain unchanged; if it contains natural language descriptions, they may be translated normally according to the translation prompt. A translation cannot be deemed abnormal solely because the hash of the Chinese and English Plaintext content differs.

6. All 20 converted articles pass read-only validation

After manual conversion was completed, I performed a read-only validation on the fixed 20 articles in the production environment.

The final results:

Plaintext
ready:20
pending:0
abnormal:0

All articles met the following criteria:

  • Chinese article remained publish;
  • Chinese language was zh;
  • Chinese title was unchanged;
  • Chinese excerpt was still empty;
  • Post-conversion body hash differed from the pre-conversion hash;
  • Gutenberg block structure was intact;
  • SyntaxHighlighter count was 0;
  • Code Block Pro count matched expectations;
  • Code Block Pro content was not empty;
  • No unknown code formats were mixed in;
  • English article remained publish;
  • Polylang bidirectional relationship was normal.
Figure 4: Read-only validation results showing all 20 articles in the first batch as ready.
Figure 4: Read-only validation results showing all 20 articles in the first batch as ready.

At this point, this batch was ready for excerpt generation and override translation.

7. A period of over-engineering occurred midway

At this stage, I should have directly reused the existing single-article executor.

However, midway through, I mistakenly treated the “new code block format” as a “new execution pipeline,” and successively designed or implemented:

  • A new batch executor;
  • A new execution list generator;
  • A new execution snapshot;
  • New batch-wide state control;
  • New automatic retry logic;
  • Stricter English body validation.

While these features are not entirely without value in isolation, they represent redundant design within the current project.

Because the downstream workflow already exists:

Plaintext
execute-single-candidate.py

The difference between SyntaxHighlighter and Code Block Pro disappears once the manual conversion is saved.

The correct architecture should be:

Plaintext
Different legacy code block formats

Each completes identification and conversion

Unified into Gutenberg + Code Block Pro

Reuse the same excerpt generation and override translation workflow

Therefore, the uncommitted new batch execution code was entirely reverted, and the repository was restored to the stable state of the remote main.

After the rollback:

Plaintext
Ran 238 tests
OK

The Git working tree was also clean again:

Plaintext
## main...origin/main

This rollback was crucial.

It prevented a situation where every time a legacy code block format was encountered, a new executor, state machine, and testing system would be added.

8. During official execution, 18 articles succeeded on the first try

After returning to the existing single-article executor, I executed the 20 articles in the fixed list order via a shell loop.

18 of the 20 articles completed smoothly, including:

  • Chinese excerpt generation;
  • Chinese excerpt writing;
  • SlyTranslate override translation;
  • Local status recorded as completed.
Figure 5: After batch execution, showing 18 successful and 2 pending recovery.
Figure 5: After batch execution, showing 18 successful and 2 pending recovery.

The execution log ultimately showed:

Plaintext
Total: 20
Successful: 18
Failed: 2

The two articles that did not complete immediately were:

  • Chinese article 16033
  • Chinese article 16967

These two failures were not due to structural article errors, but rather network timeouts at different stages.

The 18 successes and 2 failures during the batch process are recorded in the terminal log.

9. 16033: Network timeout before and after excerpt writing

During the first execution of article 16033:

  • GLM had already generated the excerpt;
  • A timeout occurred when calling the WordPress REST API to write the excerpt;
  • The local status remained at excerpt_generated;
  • The production environment excerpt was still empty;
  • The English article was unchanged.

Since the production excerpt was not actually written, it could be treated as a first-time execution again.

During the recovery process, I encountered:

  • WordPress REST connection being disconnected by the remote;
  • GLM request timeouts.

After the network finally recovered, the execution succeeded:

JSON
{
  "chinese_post_id": 16033,
  "english_post_id": 16055,
  "status": "completed"
}
Figure 6: Article 16033 ultimately re-executed successfully.
Figure 6: Article 16033 ultimately re-executed successfully.

This process demonstrates that a network timeout does not necessarily mean a write has occurred in the production environment.

You must determine this based on the following facts:

  • Which stage the local status is at;
  • Whether the production Chinese excerpt has changed;
  • Whether the English article has changed;
  • Whether there is a successful translation record.

10. 16967: POST succeeded, but verification GET disconnected

The situation with article 16967 was more complex.

During the initial execution, the GLM request had timed out. After re-executing, the excerpt POST was actually successful, but the program encountered the following during the post-write GET verification stage:

Plaintext
RemoteDisconnected

When executing from the beginning again, the program reported:

Plaintext
live validation failed: chinese_excerpt_not_empty

This indicates that the Chinese excerpt already exists, and it cannot be regenerated using the first-time execution workflow.

Read-only verification found:

  • Locally generated excerpt length: 140
  • Production Chinese excerpt length: 140
  • Local excerpt SHA-256:
Plaintext
6e276ea2813791292eed299f4ff75c76eed21cbe7f18fd6cb2376103d258b8fc
  • Production excerpt SHA-256 was exactly the same;
  • The two excerpts were identical character by character;
  • The English article title, excerpt, and body were still consistent with the pre-execution snapshot;
  • SlyTranslate had not yet been executed;
  • Polylang relationship was normal.

Therefore, it can be confirmed:

The WordPress excerpt POST was successful, but the verification request after the write did not receive a complete response.

I then updated the local status from:

Plaintext
excerpt_generated

Minimally advanced to:

Plaintext
chinese_excerpt_saved

Then executed:

Plaintext
--execute --resume

Ultimately completing the English override translation successfully:

JSON
{
  "chinese_post_id": 16967,
  "english_post_id": 17021,
  "status": "completed"
}
Figure 7: Article 16967 completing the override translation via --resume after fixing the local status.
Figure 7: Article 16967 completing the override translation via --resume after fixing the local status.

11. The decision to resume cannot be based solely on “whether a state file exists”

This also exposed a very important execution boundary.

The incorrect way to determine this is:

Plaintext
State file exists
→ Use --resume

In reality, the current execution states include:

Plaintext
prepared
excerpt_generated
chinese_excerpt_saved
translation_started
translation_failed
completed

The existing --resume only supports resuming from the following stages:

Plaintext
chinese_excerpt_saved
translation_started
translation_failed

Therefore, correct judgment must combine the state value:

Current StatusProcessing Method
No state fileFirst-time --execute
preparedConfirm production has not been written, then clean up or archive the failed state and re-execute
excerpt_generatedCheck if the production excerpt was actually written
chinese_excerpt_savedUse --resume
translation_startedUse --resume
translation_failedUse --resume
completedSkip

excerpt_generated in particular has two completely different outcomes:

  1. The POST failed, and the production excerpt is still empty;
  2. The POST succeeded, but the subsequent GET verification failed.

You cannot rely solely on local error messages; you must combine them with read-only checks in the production environment to make a judgment.

12. The first batch ultimately completes 20/20

After the two abnormal articles were recovered, the final results for the first batch were:

Plaintext
Chinese excerpt written: 20/20
English override translation: 20/20
completed: 20/20
Failed: 0
Figure 8: Article 16967 ultimately returns completed, completing all 20 articles in the first batch.
Figure 8: Article 16967 ultimately returns completed, completing all 20 articles in the first batch.

Completing this batch was not just about processing 20 legacy articles; more importantly, it clarified the unified processing method for subsequent legacy articles.

13. Standard processing workflow for all future legacy articles

Going forward, separate complete pipelines will no longer be built for different code block formats.

All legacy articles will be processed uniformly through the following stages.

Stage 1: Identify article format

For each legacy code block format, only the necessary identification rules will be added, for example:

  • SyntaxHighlighter;
  • Classic Editor <pre>;
  • WordPress Core Code;
  • Code blocks generated by old plugins;
  • Other unknown or mixed formats.

The filtering criteria include at least:

  • Chinese article;
  • Published;
  • Chinese excerpt is empty;
  • Corresponding English article exists;
  • Code block format can be reliably identified;
  • No overlap with previously processed batches.

Stage 2: Establish a fixed batch

Each time, select a manageable fixed batch size, such as 20 articles.

Once the batch is fixed:

  • No automatic additions;
  • No automatic replacement of failed articles;
  • Save Chinese and English IDs;
  • Save titles;
  • Save body hash;
  • Save code block counts;
  • Save Polylang relationships.

Stage 3: Manually convert code blocks

Unify all old code blocks into Gutenberg + Code Block Pro.

Before saving, check:

  • Old code blocks have disappeared;
  • Code Block Pro count is correct;
  • Code content has not been lost;
  • Code language is correct;
  • Gutenberg has no invalid blocks;
  • Title and other body content have not been accidentally modified.

Stage 4: Production environment read-only validation

Before officially generating excerpts, read-only confirm:

  • Chinese excerpt is still empty;
  • Chinese body hash matches the post-conversion baseline;
  • SyntaxHighlighter or other legacy format count is 0;
  • Code Block Pro count matches expectations;
  • English article exists and status is normal;
  • Polylang relationship is normal.

Stage 5: Reuse the existing single-article executor

No new excerpt or translation programs will be developed for each legacy format.

All will uniformly call:

Plaintext
execute-single-candidate.py

To complete:

  • GLM Chinese excerpt generation;
  • WordPress Chinese excerpt writing;
  • SlyTranslate English override translation;
  • Local backups;
  • Execution status recording.

Stage 6: Recover abnormal articles based on status

After a network exception, do not blindly re-execute.

First check:

  • Local status;
  • Production Chinese excerpt;
  • Whether the English article has changed;
  • Whether the local excerpt matches the production excerpt;
  • Whether the Polylang relationship is normal.

Then choose to:

  • Re-execute as a first-time run;
  • --resume after advancing the local status;
  • Recover only the translation stage;
  • Skip if already completed.

Stage 7: Use completed as the process completion flag

After the override translation is complete, overly strict automatic comparisons of the English body will no longer be performed.

Ultimately, it is only necessary to confirm:

  • The Chinese excerpt has been written;
  • The corresponding English article ID is correct;
  • The SlyTranslate request was successful;
  • There are no obvious write failures or rollbacks;
  • The local status is completed.

Code, commands, parameters, paths, and URLs continue to be handled by the translation protection mechanism.

An anomaly in the body will not be automatically determined just because natural language in the Plaintext has been translated.

14. The true value of standardizing this workflow

Today’s biggest takeaway is not how many scripts were added, but clarifying which code should be added and which should not.

What should be added:

  • Identifiers for different legacy formats;
  • Necessary batch generation rules;
  • Read-only validation after conversion.

What should not be redundantly added:

  • Excerpt generators;
  • WordPress writing logic;
  • SlyTranslate invocation logic;
  • Backup and recovery workflows;
  • Independent executors for each code block format.

Ultimately, a stable main pipeline should be formed:

Plaintext
Identify legacy format
→ Fixed candidate batch
→ Manually convert to Code Block Pro
→ Read-only validation
→ Reuse existing executor
→ Recover exceptions by status
→ completed

This workflow retains necessary safety boundaries while avoiding continuously adding code and maintenance costs for the sake of theoretical completeness.

Going forward, regardless of which legacy code block format is encountered, this standard can continue to be applied: only adjust the identification and conversion parts, while the downstream excerpt generation and English override translation remain unchanged.

系列导航

需要长期技术维护或远程问题排查?

我是拥有 15+ 年经验的 PHP / Go 后端工程师,长期关注已有系统维护、Bug 修复、性能优化、服务器排查、WordPress 网站维护和小功能迭代。

如果你的项目遇到以下情况,可以先从一次小问题排查开始合作:

  • ✅ PHP / Laravel / Yii2 老项目无人维护
  • ✅ Go / Gin 后端接口需要排查或优化
  • ✅ WordPress 网站访问慢、报错或插件冲突
  • ✅ Nginx / MySQL / Redis / Linux 服务器异常
  • ✅ CDN / Cloudflare / DNS / HTTPS 配置问题
  • ✅ 需要长期远程技术支持或兼职维护

更多介绍请查看:关于我 & 合作

微信:13980074657
邮箱:shuijingwanwq@gmail.com
Telegram:@shuijingwan
GitHub:https://github.com/shuijingwan

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理