Skip to content

Releases: QuantEcon/action-translation

v0.15.0 — Rebase Mode

14 Apr 06:18

Choose a tag to compare

Rebase Mode — Automatic conflict resolution for translation PRs

This release adds rebase mode, which eliminates merge conflicts when multiple upstream PRs modify the same translated file. Previously, 62% of translation-sync PRs conflicted because they replace entire files — merging one makes any sibling PR's "unchanged sections" stale.

How it works

When a translation-sync-* PR is merged in the target repo, rebase mode:

  1. Finds sibling translation-sync PRs with overlapping files
  2. Re-runs the translation pipeline against updated main
  3. Reuses cached translations for unchanged sections (zero Claude API calls in the common case)
  4. Force-pushes the rebased result

Setup

Add examples/rebase-translations.yml to your target repo's .github/workflows/ directory (see template).

What's new

  • Rebase mode (mode: rebase) — triggered by pull_request.closed on translation-sync- branches
  • Translation cache — section-level cache using targetBaseSha in PR metadata; unchanged sections skip Claude entirely
  • Structured PR metadata — machine-readable JSON in PR body for pipeline reconstruction
  • File type metadata — supports markdown, renamed, removed, and toc files during rebase
  • Rebase workflow templateexamples/rebase-translations.yml with concurrency group
  • 29 new tests (976 → 1005 total, 39 suites)

Fixes #63

v0.14.1

09 Apr 03:23

Choose a tag to compare

Fixed

  • Heading-map injection for new files: processFull() now builds and injects a translation: frontmatter block (heading-map + title) into newly translated files. Previously, only section-based updates via processSectionBased got heading-maps; new files were missing them.
  • MISSING_HEADINGMAP false positive for title-only files: translate status no longer flags files with no ## sections as missing a heading-map. These files have only a title — an empty heading-map is expected.

Refactored

  • Moved buildHeadingMap from CLI module (headingmap.ts) to shared module (heading-map.ts) to avoid coupling the Action bundle to CLI-only dependencies.
  • Added try/catch around heading-map injection in processFull so malformed translations fall back gracefully.

Documentation

  • Documented language-targeted \translate-resync syntax across README, quickstart, action-reference, and FAQ (e.g., \translate-resync fa to retrigger only Farsi).

Tests

976 pass (39 suites) — 4 new tests added.

v0.14.0

09 Apr 00:26

Choose a tag to compare

Fixed

  • Retry on Anthropic overloaded_error: The overloaded_error (APIError with status: undefined) is now retried with exponential backoff instead of failing immediately. Narrowed to match overloaded in the error message so unrelated status-less errors are not retried. Improved formatApiError to show a clear message when retries are exhausted. Fixes #57

Added

  • Language-targeted \translate-resync command: \translate-resync fa triggers only the Farsi workflow; \translate-resync zh-cn triggers only zh-cn. Bare \translate-resync (no argument) still triggers all languages for backward compatibility. Language argument is validated against supported languages; unsupported values are ignored with a warning and fall back to all-language resync. Fixes #58
  • Copilot PR review workflow in copilot-instructions.md: Documented the fetch, fix, reply, resolve process for addressing Copilot review comments
  • 5 tests: 2 for overloaded_error retry, 3 for language-targeted resync parsing (967 -> 972 total)

v0.13.1

26 Mar 01:33

Choose a tag to compare

Fixed

  • Headingmap CLI MyST role stripping: cleanHeading() in the headingmap CLI now strips MyST inline roles via MystParser.stripMystRoles(), matching the sync pipeline behavior from v0.12.5. Previously, roles like {index}`Mutable <single: Mutable>` appeared verbatim in heading-map keys/values when running npx translate headingmap.

Added

  • 1 test for MyST role stripping in buildHeadingMap (966 → 967 total)

v0.13.0 — Translation Frontmatter

25 Mar 23:06

Choose a tag to compare

What's Changed

Changed

  • Heading-map → translation frontmatter: Replaced flat heading-map: YAML block with structured translation: { title, headings } format. Title is now stored as an explicit field instead of a heading-map entry, resolving the inconsistency between the sync pipeline and the headingmap CLI.

Migration

Backward compatible — reads both old heading-map: and new translation: formats. Always writes new format. Existing documents migrate automatically on next sync or headingmap rebuild.

To proactively migrate a target repo:

npx translate headingmap -s <source-repo> -t <target-repo>

Details

  • heading-map.ts: extractHeadingMap reads translation.headings with heading-map fallback; new extractTranslationTitle(); serializeHeadingMap and injectHeadingMap write translation: format
  • file-processor.ts: Title tracked separately, passed to injectHeadingMap
  • headingmap CLI: Write gate checks (generatedMap || generatedTitle) for title-only files
  • init CLI: generateHeadingMap returns {map, title}, both injected
  • reviewer.ts: LLM prompts reference new format
  • 966 tests (39 suites)

Full Changelog: v0.12.5...v0.13.0

v0.12.5 — Heading-map MyST role fix

25 Mar 21:36

Choose a tag to compare

Bug Fix

  • Heading-map MyST role pollution: Headings with MyST inline roles like {index}`Pandas <single: Pandas>` were stored verbatim as heading-map keys/values instead of the clean display text (Pandas). Added MystParser.stripMystRoles() static method using global regex replacement to handle single roles, multiple roles, and mixed role+text headings. Applied across all heading-map paths: parser title extraction, file-processor heading-map updates, cleanHeading in updateHeadingMap, and lookupTargetHeading. Covers # titles and ##+ section/subsection headings. Affects 7 lectures in lecture-python-programming that use {index} roles in titles.

Tests

  • 19 tests for MyST role stripping — unit tests for stripMystRoles (including mixed role+text headings), title extraction integration, and heading-map operations with role syntax (935 → 954 total)

v0.12.4 — CJK–MyST spacing rule & target-label cleanup

25 Mar 02:57

Choose a tag to compare

Addresses feedback from lecture-python-programming.zh-cn PR #6.

Added

  • CJK–MyST spacing rule for zh-cn: New language-config rule instructs Claude to insert a space between Chinese characters and inline MyST directives ({doc}, {ref}, etc.) or Markdown links, preventing rendering failures (e.g. 请参阅 {doc} not 请参阅{doc})
  • MyST target-label blank-line cleanup: reconstructFromComponents now strips blank lines between MyST target labels ((label)=) and headings in post-processing, so targets always attach to their heading correctly
  • 1 test for target-label blank-line removal (934 → 935 total)

v0.12.3 — Scoped translation PRs

24 Mar 06:19

Choose a tag to compare

What's Changed

Fixes #45 — translation PRs are now scoped to the source PR's actual changes, preventing superset accumulation when earlier translation PRs are still open.

Fixed

  • Scope translation PRs to source PR's actual changes: Unchanged sections missing from target (pending an earlier unmerged translation PR) are now skipped instead of re-translated. Git's 3-way merge combines the PRs when merged independently. Recovery via /translate-resync if an earlier PR is abandoned.
  • Heading-map corruption when sections are skipped: includedSourceSections array keeps index-alignment with resultSections so updateHeadingMap() pairs sections correctly.
  • Markdown injection in PR body: Skipped section headings wrapped in backticks to neutralize Markdown syntax.

Added

  • Skipped sections notice: Translation PRs include a ⚠️ Sections Pending Earlier Translation PR notice listing which sections were skipped per file.
  • onSkippedSection callback and skippedSections in sync pipeline for tracking skipped sections.
  • 4 new tests (934 total).

Full Changelog: v0.12.2...v0.12.3

v0.12.2

24 Mar 04:24

Choose a tag to compare

What's Changed

Fixed

  • Position fallback guard for mismatched section counts: findTargetSectionByHeadingMap no longer uses position-based fallback when source and target have different section counts. Previously, when a new section was added to source but the translation PR hadn't been merged yet, the position fallback would grab the wrong target section, producing incorrect heading-map values. Now unmatched sections fall through to translateNewSection instead. (PR #43)

  • Resync uses PR merge commit SHA: \translate-resync now uses the PR's merge_commit_sha instead of github.context.sha (which points to HEAD of main for issue_comment events). Previously, oldContent and newContent could both reference the current main tip, causing the diff detector to miss the PR's actual changes. (PR #44)

Added

  • 3 new tests for position fallback guard (927 → 930 total)

Full Changelog: v0.12.1...v0.12.2

v0.12.1 — Sync evaluation bug fixes

24 Mar 01:50

Choose a tag to compare

Bug fix release addressing 5 issues identified in the real-world sync evaluation of lecture-python-programming.zh-cn / .fa.

Fixed

  • Duplicate preamble regression (Critical): Fixed intro extraction that duplicated pre-title content (anchors, raw blocks) in translated documents. Regression from v0.11.2.
  • Case-insensitive heading-map lookup (High): Heading case changes (e.g. "Iterables and Iterators" → "Iterables and iterators") no longer cause full section re-translations. Falls back to case-insensitive matching.
  • Position-based section fallback (High): Section matching now falls back to position when both heading-map and ID lookups fail, preventing unnecessary NEW section translations for translated headings.
  • Label retry on PR creation (Medium): Label application retries 3× with 2s delays, fixing GitHub API propagation failures that caused review workflows to skip.
  • Review response parsing with retry (Medium): Review evaluations now retry on parse failures with robust multi-strategy JSON extraction (direct parse, code block, greedy regex), preventing single malformed LLM responses from crashing the review workflow.

Added

  • E2E test fixture #25 (pre-title content) and #26 (heading case change)
  • 14 new parseJsonResponse tests (927 total, 39 suites)

Full Changelog: v0.12.0...v0.12.1