Skip to content

feat: add Phrase In-Context Editor to staging builds#113

Merged
deividasma merged 2 commits into
masterfrom
feat/phrase-ice
Jul 16, 2026
Merged

feat: add Phrase In-Context Editor to staging builds#113
deividasma merged 2 commits into
masterfrom
feat/phrase-ice

Conversation

@deividasma

@deividasma deividasma commented Jul 15, 2026

Copy link
Copy Markdown

Embeds the Phrase In-Context Editor (ICE) so translators can edit strings in place on the staging deployment.

The frontend compiles into a single binary, so ICE is included or excluded at build time:

Command ICE
make build eliminated from the bundle entirely
make build-staging (new) compiled in

Even in the staging build, ICE stays dormant until opted in per browser via ?phraseapp=enabled (week-long cookie; ?phraseapp=disabled clears it). Translation keys are decorated via a vue-i18n postTranslation hook only after the ICE script has initialised (markers rendered earlier never get edit bubbles), and a synthetic scroll is dispatched on DOM changes so ICE repositions its edit overlays.

Verified: the production bundle contains zero references to Phrase; the staging bundle includes the integration; unit tests cover the module.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a staging build option for the frontend and full application.
    • Introduced staging-only Phrase In-Context Editor support for translation review.
    • Added an opt-in/out flow via URL parameter, with the choice persisted in a cookie for one week.
  • Tests

    • Added automated coverage for staging activation, opt-in/out behavior, editor script loading, and translation decoration behavior.

@deividasma deividasma mentioned this pull request Jul 15, 2026
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4b61826a-76e6-4287-bf8f-04dc4b466783

📥 Commits

Reviewing files that changed from the base of the PR and between 9713844 and 521b495.

📒 Files selected for processing (2)
  • frontend/src/i18n/__tests__/phrase.test.ts
  • frontend/src/i18n/phrase.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/i18n/tests/phrase.test.ts
  • frontend/src/i18n/phrase.ts

📝 Walkthrough

Walkthrough

Changes

The project adds staging-specific build commands and a Vite staging script. The frontend loads Phrase ICE only for staging builds with cookie or URL opt-in, integrates post-translation decoration and DOM rescanning, and adds tests for initialization and translation behavior.

Staging Phrase ICE integration

Layer / File(s) Summary
Staging build commands
Makefile, frontend/package.json
Adds staging build targets and runs the frontend typecheck followed by vite build --mode staging.
Phrase ICE loading and rescanning
frontend/src/i18n/phrase.ts
Adds staging-only opt-in handling, Phrase script injection, readiness-gated translation decoration, and DOM/layout rescan triggers.
i18n wiring and validation
frontend/src/i18n/index.ts, frontend/src/i18n/__tests__/phrase.test.ts
Loads Phrase ICE before i18n creation, conditionally registers postTranslation, and tests mode, opt-in, script, readiness, and output behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Frontend
  participant loadPhraseIce
  participant PhraseScript
  participant VueI18n
  Frontend->>loadPhraseIce: Read staging mode and phraseapp opt-in
  loadPhraseIce->>PhraseScript: Inject ICE script
  PhraseScript-->>loadPhraseIce: Trigger script onload
  loadPhraseIce->>VueI18n: Decorate translated strings
  loadPhraseIce->>Frontend: Dispatch DOM rescan events
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding Phrase In-Context Editor support to staging builds.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/phrase-ice

Comment @coderabbitai help to get the list of available commands.

@hex-botas

hex-botas Bot commented Jul 15, 2026

Copy link
Copy Markdown

🔍 Hex review — Phrase ICE requirements check

Looks good — all four requirements met; no blocking issues. One thing worth confirming (Phrase datacenter).

Req Status Evidence
1. Embedded per official Phrase ICE guide src/i18n/phrase.ts: PHRASEAPP_CONFIG global + cdn.phrase.com/strings/plugins/editor/latest/ice/index.js (async type="module") + [[__ __]] decorators via a vue-i18n postTranslation hook. Matches the Strings ICE guide + the hpanel/hcart convention.
2. Account ID 3b42d924…d6b9 phraseAccountId constant is exact; also present in the staging bundle.
3. Project ID f2d90a99…94e3 phraseProjectId constant is exact; also present in the staging bundle.
4. Staging-only, never in production Verified by building both. Production dist/: grep finds zero phrase/PHRASEAPP/id/cdn.phrase.com (statically eliminated via the inlined import.meta.env.MODE==="staging" check). Staging dist/: PHRASEAPP_CONFIG + both ids + CDN URL present in i18n-*.js.

Notes (non-blocking):

  • PHRASEAPP_CONFIG sets no datacenter. If Hostinger's Phrase account is EU-hosted, the Strings ICE may need datacenter: "eu" to connect — worth confirming against the Phrase account (can't be verified from the diff). The extra phraseEnabled/fullReparse keys are legacy-editor fields and are harmless.
  • CSP is fine: the index page is served via http.go r.NotFoundHandler, which gorilla/mux does not wrap with the r.Use default-src 'self' middleware, so the external Phrase script is not blocked. Author's analysis confirmed.
  • Deploy follow-up (already flagged in the PR): the staging pipeline must switch to make build-staging, otherwise ICE ships nowhere.

Last reviewed: 2026-07-15 11:29 UTC


Generated by hex
Triggered by deividas.maciulskis@hostinger.com

@deividasma deividasma marked this pull request as ready for review July 15, 2026 11:36

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/i18n/phrase.ts`:
- Around line 120-134: Update the MutationObserver callback in phrase.ts to
trigger for every childList mutation, including removals, while retaining the
existing characterData behavior. Remove the addedNodes-only condition so DOM
removals also invoke trigger() and rescan stale edit-bubble coordinates.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 91299c9a-0b88-4894-b455-d930542b92c8

📥 Commits

Reviewing files that changed from the base of the PR and between 8767a83 and d1c24fb.

📒 Files selected for processing (6)
  • Makefile
  • frontend/PHRASE.md
  • frontend/package.json
  • frontend/src/i18n/__tests__/phrase.test.ts
  • frontend/src/i18n/index.ts
  • frontend/src/i18n/phrase.ts

Comment thread frontend/src/i18n/phrase.ts
Embed the Phrase In-Context Editor so translators can edit strings
directly on the staging deployment. Since the frontend is compiled into
a single binary, ICE is included at build time: make build-staging
(vite build --mode staging) compiles it in, while production builds
eliminate it entirely. Even on staging, ICE stays dormant until a
translator opts in via ?phraseapp=enabled (week-long cookie).

Translation keys are decorated ([[__ __]] markers via a vue-i18n
postTranslation hook) only after the CDN script has initialised, since
markers rendered earlier never get edit bubbles, and a synthetic scroll
is dispatched on DOM changes because ICE only re-scans the page on
scroll.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
frontend/src/i18n/__tests__/phrase.test.ts (1)

67-121: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for ?phraseapp=disabled.

The suite covers cookie absence and ?phraseapp=enabled, but not the required disable override. Start with an enabled cookie, load a URL containing ?phraseapp=disabled, and assert that no ICE configuration or script is installed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/i18n/__tests__/phrase.test.ts` around lines 67 - 121, Add a test
in the loadPhraseIce suite that starts with documentStub.cookie set to
phraseapp=enabled, sets locationStub.href with ?phraseapp=disabled, and invokes
loadPhraseIce. Assert that window.PHRASEAPP_CONFIG remains undefined and
appendedScripts remains empty, covering the disable override behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/i18n/__tests__/phrase.test.ts`:
- Around line 142-147: Update the non-string test around phrasePostTranslation
to initialize the ICE state by enabling ICE and advancing readiness before
invoking the handler. Ensure the test exercises the typeof translated guard
while retaining the assertion that the original non-string message is returned
unchanged.

---

Nitpick comments:
In `@frontend/src/i18n/__tests__/phrase.test.ts`:
- Around line 67-121: Add a test in the loadPhraseIce suite that starts with
documentStub.cookie set to phraseapp=enabled, sets locationStub.href with
?phraseapp=disabled, and invokes loadPhraseIce. Assert that
window.PHRASEAPP_CONFIG remains undefined and appendedScripts remains empty,
covering the disable override behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7a43420e-4786-4e51-ae50-aa13170f168e

📥 Commits

Reviewing files that changed from the base of the PR and between d1c24fb and 9713844.

📒 Files selected for processing (5)
  • Makefile
  • frontend/package.json
  • frontend/src/i18n/__tests__/phrase.test.ts
  • frontend/src/i18n/index.ts
  • frontend/src/i18n/phrase.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • frontend/package.json
  • Makefile
  • frontend/src/i18n/phrase.ts

Comment thread frontend/src/i18n/__tests__/phrase.test.ts Outdated
Removals shift layout just like additions, but ICE only cleans up the
removed node's own overlay — the remaining edit bubbles kept stale
coordinates until the next scroll. Also strengthen the tests: exercise
the non-string pass-through with ICE ready (previously it short-
circuited on the readiness flag) and cover ?phraseapp=disabled.
@deividasma deividasma merged commit 4f2a713 into master Jul 16, 2026
5 checks passed
@deividasma deividasma deleted the feat/phrase-ice branch July 16, 2026 06:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants