diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a0c814..2b575ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to Tolk are documented in this file. - **Settings** in the **Tools › Translations** menu, below **Audit**, for users who may edit Tolk's settings. - **Translated slugs**, a setting that lists the collections whose new localizations get a slug made from their translated title, the way Statamic makes slugs in the target site's language. It is empty by default, so new localizations keep their origin's slug as before, and an existing slug is never changed. +- **Automatic updates**, off by default (the settings' new Automation tab): saving a published entry in its origin updates its localizations in the background, as **Update translations** does, and with **Create missing localizations** also translates it into the sites that have none. They can be limited to some collections, and in collections with revisions published at once. Each update is a run, listed as an automatic update, followed in the origin's banner after the save, and counted under **Automatic updates** in the Overview's usage; the localization's banner says when an automatic update last saved it. With a queue worker the update runs on the queue; without one, in the process that saved the entry, after its response. - **Reset** on the Overview's usage card, which deletes the month's usage, and on the runs list, which deletes the finished runs; both ask first and are offered to users who may edit Tolk's settings. ### Changed diff --git a/README.md b/README.md index 845e082..e26341a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Tolk translates multi-site Statamic content from an origin site into its localiz - **One field at a time**: "Translate from origin" in a field's actions. - **In bulk**: a listing action, an Overview of every collection, taxonomy, global set and navigation by language, and runs with an estimate before they start, progress, cancel and resume. No queue or database needed. - **From the command line**: translate collections, or the whole website into a new language in one command, plus the app's `lang/` files and the texts of forms. -- **Updates, not retranslations**: when the origin changes, only the changed paragraphs are sent again. Text a human edited is never overwritten unless you ask. +- **Updates, not retranslations**: when the origin changes, only the changed paragraphs are sent again. Text a human edited is never overwritten unless you ask. Optionally, saving an entry updates its translations by itself. - **Quality**: a site profile, instructions, per-language formality and a glossary go with every request; an optional second model reviews each translation and its corrections are applied and listed with reasons. - **Your own API keys**, from `.env`. Cost estimates before every bulk run, and usage per run and per month. diff --git a/TASKS.md b/TASKS.md index beab986..c06fa52 100644 --- a/TASKS.md +++ b/TASKS.md @@ -58,7 +58,7 @@ Status: **Brief** = stated by the owner in the original request. **Confirmed** = | D3 | Direction | The source is always the target's origin as Statamic defines it. Two entry points: pull (inside a localization) and push (from the origin). No any-to-any. | Confirmed 2026-10-02 | | D4 | Editor behaviour | Translations are filled into the open publish form unsaved; the editor reviews and saves. Bulk action, overview and CLI save server-side. | Confirmed 2026-10-02 | | D5 | Overwrite policy | Per field: untranslated, machine (current or outdated), manual. A field is manual as soon as a human changed its text. Manual fields are never overwritten unless the operation explicitly sets "overwrite manual edits". | Confirmed 2026-10-02 | -| D6 | Origin changes | Outdated translations are flagged and updated on request. Only changed fields are re-sent, and unchanged paragraphs inside a changed field are reused. Automatic update on origin save is an optional extra (T11.1). | Confirmed 2026-10-02 | +| D6 | Origin changes | Outdated translations are flagged and updated on request. Only changed fields are re-sent, and unchanged paragraphs inside a changed field are reused. Automatic update on origin save is an optional extra (T11.1), built 2026-10-09 off by default. | Confirmed 2026-10-02; T11.1 built 2026-10-09 at the owner's request | | D7 | Context | Whole-entry context (document summary and neighbouring paragraphs), AI-generated editable site profile, global instructions text, per-language instructions, glossary, per-field "translate" toggle and hint. No retrieval-based consistency memory in v1. | Brief (context, default text) + Confirmed 2026-10-02 (details; the owner chose the model-generated site profile) | | D8 | Review | Reviewer-as-editor: a second model receives source and translation and returns corrected text only for segments it would change, each with a reason; corrections are applied automatically. Off by default; a setting turns it on and picks the reviewer; every operation can override; "Review again" is a manual action that accepts any configured model, including the same one. One automatic round. | Brief (multi-model review, follow-up review) + Confirmed 2026-10-02 (mechanics). The owner asked for corrections to be applied automatically and for the most cost-efficient method. This design is that method: only corrected segments come back, reused paragraphs are not reviewed again, and instructions are cached where the provider allows it. | | D9 | Model defaults | Quality tier per provider by default, fast tier selectable. Explicit model ids are stored; SDK defaults are never relied on. | Confirmed 2026-10-02 | @@ -81,7 +81,7 @@ Status: **Brief** = stated by the owner in the original request. **Confirmed** = | D26 | Revisions | On collections with revisions enabled, updates to a published localization go to its working copy, as the CP does. "Publish changes" publishes them only when the working copy held nothing else. | Confirmed 2026-10-02 | | D27 | Machine versus manual | Decided by text alone: a field counts as machine-translated while its translatable text is exactly what the addon produced. Differences that are not text (a swapped image, a toggled option, ids, normalisation by the CP) are not tracked, and Update rebuilds the field's structure from the origin. An editor can protect a field explicitly ("mark as manual"). | Confirmed 2026-10-02 (the alternative, comparing whole values, misreads CP normalisation as manual edits and silently stops updates) + planner's details (T2.4: defaults that Statamic fills into set fields are not target text, §A3 "Target-side walks") | | D28 | Untranslatable parts | When one part of a field cannot be translated after the retries (invalid output, refusal), the field is still delivered with that part left in the source language, flagged, and retried on the next Update. A `strict_fields` setting fails the field instead. | Confirmed 2026-10-02 | -| D29 | Optional extras | Automatic update on origin save, database drivers, Eloquent test group, dashboard widget and command palette entries are built only if the owner asks for them (Phase 11). The owner asked for none of them for v1 (T0.1), so the Phase 11 tasks are marked deferred (`- [-]`). | Confirmed 2026-10-02 | +| D29 | Optional extras | Automatic update on origin save, database drivers, Eloquent test group, dashboard widget and command palette entries are built only if the owner asks for them (Phase 11). The owner asked for none of them for v1 (T0.1), so the Phase 11 tasks are marked deferred (`- [-]`). On 2026-10-09 the owner asked for T11.1, off by default, as a run rather than a job of its own, and with a second setting that also creates missing localizations. | Confirmed 2026-10-02; T11.1 2026-10-09 | ## Vocabulary @@ -186,12 +186,12 @@ src/Http/Controllers/Cp/ src/Http/Requests/ src/Http/EditorStatus.php the editor banner's status payload (T5.3) src/Http/EditorTranslation.php the payloads of editor/plan, editor/review and editor/unit (T5.4, T7.5) -src/Http/EditorPush.php the editor's push: the user's running push from an item, and what the banner needs to follow it (T8.13) +src/Http/EditorPush.php the editor's push: the user's running push or automatic update from an item, and what the banner needs to follow it (T8.13, T11.1) src/Http/RunState.php the state payload of a run: run, counts, counts by type and site, a page of items, stalled (T8.7, T8.9) src/Http/Rules/ ModelReference (provider:model format), CatalogModel (§A14 catalog check) -src/Jobs/ -src/Listeners/ -src/Runs/ Run, RunItem, Claim, FileRunRepository, RunRequest, RunPlanner, PlannedRun, EstimateProgress, RunProcessor, WorkReport, ApplyReport, RunDispatcher, Estimate, Estimator, UsageLog, UsageRecorder +src/Jobs/ WorkRun (a queue lane), UpdateTranslations (an automatic update, T11.1) +src/Listeners/ BumpOverviewVersion, ForgetStateOfDeletedContent, QueueTranslationUpdates (T11.1) +src/Runs/ Run, RunItem, Claim, FileRunRepository, RunRequest, RunPlanner, PlannedRun, EstimateProgress, RunProcessor, WorkReport, ApplyReport, RunDispatcher, Estimate, Estimator, UsageLog, UsageRecorder, AutoUpdater (T11.1) src/State/ FieldState, PendingState, ItemState, Concerns/ReadsStoredValues, FileStateRepository, StatusResolver, TargetStatus, FieldStatusInfo, StateWriter, ConfirmReport, StatusScanner, ScanResult, OverviewCache, OverviewScanner src/Support/ Settings, Language, Languages, ContentWriter, GitListeners, Audit, SiteSetup, Pruner, PruneReport, Sanitizer, LangFiles, Concerns/StoresFiles (JSON read, atomic write) src/Targets/ TargetRef, TargetFactory, ApplyOptions, ApplyResult, EntryFamilies, EntryTarget, TermTarget, GlobalsTarget, NavTarget, LangTarget, FormsTarget, Concerns/AppliesFields (the apply steps of §A11 that the targets share), Concerns/WritesLangFile (what LangTarget and FormsTarget share: the file through LangFiles, its apply, no CP surface) @@ -496,6 +496,7 @@ A **run** is a bulk job: `{ id (ULID), status, driver, created_by, created_at, s - **Drivers** (D23). All of them call the same processor. - `browser`: the run page keeps `concurrency.browser` lanes calling `POST runs/{id}/tick` (translate, deadline `runs.tick_seconds`, at most one unit, so the request makes at most one provider call, D24; T12.2) and one loop calling `POST runs/{id}/apply`. The worker id is built on the server from the user id, a nonce the page generated and the lane number. - `queue`: `concurrency.queue` lane jobs; each translates for a while, applies what is ready, and re-dispatches itself while work remains. Job timeout and lane deadline are derived from the connection's `retry_after`. Lane jobs carry the run's `generation`: starting the run again, or taking it over in the browser, makes a new one, and the lanes of an older generation end at their next step (T8.6). + - Automatic updates (T11.1) have no page: their run uses `queue` when Tolk's runs go on a queue with a worker (`AutoUpdater::queued()`), and otherwise `cli`, driven by the process that saved the entry after its response (`AutoUpdater::drive()`, worker `auto`). Their `scope.automatic` is true and `scope.reference` the saved entry; their usage counts under the source `auto`. - `cli`: the command starts `concurrency.cli` worker processes (`tolk:work`, workers `cli-1` and up) that translate, and applies in its own process (`cli-apply`), one item at a time; while no worker runs it translates itself (`cli-0`), one item before each apply. A long-lived process may apply, because `ContentWriter` refreshes Stache's memory inside the lock (§A11, T2.3). The command starts its runs with `RunProcessor::start()`; `RunDispatcher::start()`, which the CP calls, hands a `cli` run whose command has ended to the CP's driver (T8.10). - **Waiting.** `ProviderPaused` / `ProviderUnavailable` release the item with `available_at` in the future and count a wait. After 10 waits in a row the item fails with "provider unavailable"; three such items in a row abort the run. When nothing can be claimed right now, the processor reports how long to wait and drivers honour it instead of spinning. - **Usage** is recorded at every provider call, per model, on the run and in the monthly usage log. Nothing is added at the end. @@ -576,7 +577,7 @@ Global sets and the nav page editor do not render pushed components (R3 §2.4), | `excluded_fields` | list of handles | empty | | `translated_slugs` | collections | empty (D16) | | `providers` | provider status fieldtype (display only, stores nothing) | | -| `auto_update`, `auto_update_collections`, `auto_update_publish` | toggle, collections, toggle | `false`, empty, `false`; only if T11.1 is built | +| `auto_update`, `auto_update_create`, `auto_update_collections`, `auto_update_publish` | toggle, toggle, collections, toggle (Automation tab; the last three shown only while `auto_update` is on, kept while hidden) | `false`, `false`, empty, `false` (T11.1) | `Support\Settings` is the only reader of user settings. It merges the defaults above with `Addon::get('reachweb/statamic-tolk')->settings()->raw()` on each access (memoized per request, with `fresh()` for long-running workers). Use `raw()`: `all()` and `get()` cast every value to a string (R4 §12.1). Unlike Resrv it does not merge settings into config at boot, so queue workers and CLI workers never run on stale settings. @@ -2101,14 +2102,16 @@ Read R3 §6 (addon pages, UI components, toasts) and R1 §3–§4 (Resrv's CP co In T0.1 (2026-10-02) the owner asked for none of these for v1 (D29). Each task is marked `- [-]` (deferred), and the loop skips it. To build one later, the owner changes it back to `- [ ]`. Each one is independent. -- [-] **T11.1 Automatic update when the origin changes** - - Settings: add `auto_update`, `auto_update_collections` and `auto_update_publish` to the blueprint (a new Automation tab) and to `Settings`. The tab explains that this spends API credit on every published save of an origin and that manual edits are never overwritten. - - `src/Listeners/QueueTranslationUpdates.php`, on `EntrySaved`. Act only when all hold: `autoUpdate()` is on; `$event->isInitial()` (a real save, not the cascade re-save of a localization, R4 §10.1); the entry is published; its collection is in `autoUpdateCollections()` or that list is empty; the entry has direct localizations. - - `src/Jobs/UpdateTranslations.php` (`$entryId`, `$actor` captured at dispatch). On the `sync` connection use `dispatchAfterResponse()` so the editor's save does not wait for the model, and take a per-entry cache lock inside the job so two quick saves do not overlap. Otherwise dispatch to the queue with a 10-second delay and `ShouldBeUniqueUntilProcessing` per entry: a save that arrives while a job is already running must queue a new job, not be dropped. - - The job: for each direct localization, `TargetTranslator::translate()` with mode `Update`, review as configured, profile `background`; then one `GitListeners::commit()`. On revision-enabled collections the update lands in the working copy unless `auto_update_publish` is on (and then only under the rule of §A11). Log failures with `report()`; never throw into the editor's request. - - With revisions enabled, `EntrySaved` fires for a published origin only when it is published (R4 §11), which is the right moment. Chains update naturally: saving the `de` localization fires its own initial `EntrySaved`. - - The localization's banner shows "updated automatically from {source} on {date}", and "not published yet" when the update is in a working copy. - - **Self-check:** `tests/Feature/AutoUpdateTest.php` with faked agents: off by default (no job); on: editing one field of the origin updates that field in each machine-translated localization and nothing else; a manual field is untouched; a draft origin triggers nothing; the collections filter is respected; the cascade re-save does not trigger a second job; a second save during a running job queues another job; a provider failure leaves the localization outdated and the origin save succeeds; one commit is dispatched per job. +- [x] **T11.1 Automatic update when the origin changes** + - Settings: `auto_update`, `auto_update_create` (owner, 2026-10-09: also create the missing localizations, as Translate into… does; off by default), `auto_update_collections` and `auto_update_publish` in the blueprint (a new Automation tab after Content) and in `Settings`. The instructions say that every published save that changes text spends API credit and that manual edits are never overwritten. + - Built as a run, at the owner's choice (2026-10-09): a job translating each localization with `TargetTranslator` could outlast a queue connection's `retry_after` on a long entry and be handed out twice, and its updates would leave no trace but the log. A run of the entry is the origin's **Update translations**: Runs page, usage, revisions, one commit, stalled-run recovery. + - `src/Listeners/QueueTranslationUpdates.php`, on `EntrySaved`. Acts only when `$event->isInitial()` (a real save, not the cascade re-save of a localization, R4 §10.1) and `AutoUpdater::applies()`: `auto_update` is on; the collection has more than one site, is not excluded, and is in `auto_update_collections` or that list is empty; the entry is published; and `AutoUpdater::sites()` is not empty: `EntryFamilies::originSites()`, the sites of its direct localizations and, with `auto_update_create` and for the root of the family, the sites it has none in (the rule `EditorStatus` uses for the origin block). Catches and reports everything, so the save never fails. + - `src/Jobs/UpdateTranslations.php` (`$entryId`, `$userId` of `$event->authenticatedUser`, null from code), `ShouldBeUniqueUntilProcessing` per entry on Tolk's cache store and its runs' queue connection and name. When `AutoUpdater::queued()` (Tolk's runs use the queue and its connection has a worker) it waits `DELAY_SECONDS` (10) on the queue, so saves within that time make one job, and a save while it runs queues another; otherwise it is dispatched after the response. The job reads the settings fresh, re-checks `applies()`, and under a 60-second cache lock per entry starts the run unless `AutoUpdater::busy()`: an unfinished run from the entry (`scope.reference`, a push included) that moved within `runs.claim_ttl`. A busy job on the queue is released for `RETRY_SECONDS` (15) until `retryUntil()` (15 minutes); after a response it polls every 2 seconds for up to 15 minutes. It never throws (`report()`); a user who was deleted meanwhile updates nothing. + - `src/Runs/AutoUpdater.php`: `start()` builds the run with `RunPlanner` (mode `update`, `publish_changes` from `auto_update_publish`, `new_status` from the settings, the user, `reference` and `automatic: true`, `sourceSite` the entry's site, `entryIds` the entry), estimates it item by item without a model call, deletes it when nothing is pending, and otherwise starts it: `RunDispatcher::start()` with the `queue` driver, or `RunProcessor::start()` with the `cli` driver for the job to `drive()` in its process (translate for 30 seconds, apply for `WorkRun::APPLY_SECONDS`, sleep `WorkRun::waitSeconds()`, until the run no longer runs), without PHP's time limit. Review follows the settings; one commit per run comes from `RunProcessor::finalize()`. + - With revisions enabled, `EntrySaved` fires for a published origin only when it is published (R4 §11), which is the right moment. Chains update naturally: saving the `el` localization fires its own initial `EntrySaved`, and its own localizations are its direct descendants. + - Banner (`EditorStatus`): the origin block's `auto_update` is `save` (published, no revisions), `publish` (a draft, or revisions) or null, and the banner says "Translations are updated automatically each time this entry is saved." or "…when this entry is published."; `auto_update_sites` lists the sites an update covers (`AutoUpdater::sites()`). `active_run` (EditorPush) carries `automatic`. After a save with `auto_update: save` and a covered site that is missing, untranslated or outdated, the push block enters the phase `expecting` ("Updating the translations automatically into …", the buttons hidden) and reads `editor/status` again, waiting 1, 2, 4, 8 and 15 seconds before each look: it follows the run once it shows; says "The translations into … were updated automatically." (phase `updated`, with Close) when no covered site awaits an update before the run was seen; and stops waiting after the last look or a failed read. The localization block's `auto_updated` (`at`, `unpublished`: a published localization with revisions and a working copy) comes from the latest automatic run among the 50 most recent whose item for its site is done, looked up only while the settings cover the origin's collection: "Updated automatically from {source} on {date}." and ", not published yet". + - Runs list and page: "Automatic update" and "Started automatically on {date}, when {name} saved the entry."; a stalled `cli` run that is automatic names the process, not the command. Usage source `auto` ("Automatic updates" on the Overview). `tolk:doctor` and the Audit page say how automatic updates run while they are on. + - **Self-check:** `tests/Feature/AutoUpdateTest.php` with faked agents: off by default (no job); on: editing one field of the origin updates that field in each machine-translated localization and nothing else; a manual field is untouched; a draft origin, a collection outside the list or excluded, and an entry without localizations trigger nothing; the cascade re-save does not trigger a second job (a chain whose middle localization is published); two saves within the delay make one queued job, and a save once it runs queues another; a provider failure leaves the localization outdated and the origin save succeeds; one commit is dispatched per run; missing localizations are created only with `auto_update_create`; the saver's site rights apply; a save that changes no text keeps no run; a job waits for, or is released while, an earlier run from the entry moves. Also `SettingsTest`, `EditorStatusTest`, `EditorPushTest`, `AuditTest`, and Vitest for the banner, the push follower, the save hook and the run pages. - [-] **T11.2 Database drivers for state and runs** - `database/migrations/create_tolk_tables.php.stub`, published with the tag `tolk-migrations` and not auto-loaded: `tolk_states` (`id`, `reference` unique, `source_site`, `fields` json, timestamps), `tolk_runs` (`id` string primary, `status`, `driver`, `payload` json, timestamps), `tolk_run_items` (`id`, `run_id` indexed, `index`, `status` indexed, `stage`, `claimed_by`, `claim_token`, `claim_expires_at`, `available_at`, `payload` json; unique on `run_id` + `index`). Standard Schema builder only, so it runs on SQLite, MySQL/MariaDB and PostgreSQL. @@ -2246,7 +2249,7 @@ In T0.1 (2026-10-02) the owner asked for none of these for v1 (D29). Each task i - The same flows work with a real queue worker. - After parallel runs with the Stache watcher off, every localization exists once and is found by queries (T12.1). - Formatting, links, sets, ids and non-text values of translated content are identical to the origin's (golden tests), and content is never round-tripped through HTML. -- No web request makes more than one provider call. +- No web request makes more than one provider call. (An automatic update on a site without a queue worker runs in the process that saved the entry once its response has been sent, T11.1.) - No API key appears in any file, log line, queue payload or response. ## Out of scope for v1 (do not implement without asking the owner) @@ -2263,7 +2266,7 @@ In T0.1 (2026-10-02) the owner asked for none of these for v1 (D29). Each task i - A translation-status column or filter in core's entry listings. - In-form UI for global sets, the nav page editor and stacked inline editors. - Field actions on nested fields. -- Automatic update for terms, global sets and navs (entries only, and only if T11.1 is built). +- Automatic update for terms, global sets and navs (T11.1 updates entries only). - Bundled handlers for third-party fieldtypes such as SEO addons (D17). - Creating sites, and translating Antlers templates. - Human approval workflows beyond drafts. @@ -2407,3 +2410,4 @@ T13.1 done 2026-10-08: `README.md` (features, requirements, installation, a five T13.2 done 2026-10-08: `resources/boost/guidelines/core.blade.php`, one file of 119 lines in the form of Statamic's: what Tolk does, requirements and keys, where settings, config, state, runs and usage live with "do not edit the files under `content/tolk/` by hand", which fields are translated and the per-field options, the permissions, every command in a line each (with the advice to prefer `--dry-run` and not to run `tolk:translate` or `tolk:site` unasked), registering a fieldtype handler with the guide's `SeoMetaHandler` as a snippet, the events with their properties, and what is public. The two snippets (an Antlers form template, the PHP handler) are `` blocks inside `@verbatim`. `tests/Feature/BoostGuidelineTest.php` renders the file as Boost 2.10 does (backticks and `` lost 2 and `` 1 of 160 placeholder segments, so §A3 keeps `<1>`; 6,000 characters into Greek took Sonnet 5.5 42.8 s against `http.timeout.web` 45, so `batch.max_chars.web` is 4,000 (was 6,000). Found and fixed: the output cap left no room for each segment's JSON, so 80 short strings stopped with `Length` at 2,048 on all four models (they need up to 2,618); `TranslationEngine` adds 32 tokens per segment (`TranslationEngineTest` +1, the cap datasets of both engine tests updated). Estimates were about half the real cost: output is now characters × 1.5 ÷ `tokens.chars_per_token` + 20 tokens per segment and review output characters × 1.0 ÷ it, and two whole-site runs now estimate $0.23 and $0.28 for $0.21 and $0.28 spent ($0.13 and $0.17 before; `EstimatorTest` updated). The owner read Greek and German output (Sonnet 5.5; Gemini 3.8 Flash reviewed by Sonnet 5.5) and accepted it; at the owner's choice the translation prompt gained rule 9 (one form of address, as the language instructions say or else the one usual for this kind of website), because Sonnet mixed "man" and "Sie" in three German articles with formality default (prompt snapshots, `docs/context-and-glossary.md`). Acceptance criteria, all 2026-10-08 in the sandbox: (1) ✓ the offer filled six fields of a new Greek article localization, Bard and Replicator included, stored nothing before Save and the origin's structure after (Sonnet 5.5); (2) ✓ a field action translated only the German title (Sonnet 5.5); (3) ✓ the listing action's run of four articles into Greek and German showed its estimate and progress, was cancelled after one item and resumed to 8 done (Sonnet 5.5); (4) ✓ `tolk:site de` after its preflight and estimate: 26 targets, entries with translated titles and kept slugs, five terms, the global set and the navigation, in 38 s (Sonnet 5.5), and `tolk:translate --all --site=el` (Gemini 3.8 Flash reviewed by Sonnet 5.5); (5) ✓ an origin edit read outdated, Update sent the one changed paragraph and kept a hand-edited excerpt, `--force` replaced it, and opening and saving in the CP changed no status (Sonnet 5.5); (6) ✓ site profile, instructions, German informal formality and a glossary row were in the captured prompt and turned the German from Sie, Schlucht and a dash into du, Klamm and none (Sonnet 5.5); (7) ✓ Sonnet 5.5's review of Gemini 3.5 Flash-Lite's Greek applied three corrections listed with reasons, and Review again with Gemini 3.8 Flash three more; (8) ✓ both keys come from `.env` and pass Test connection (Haiku 5.5 3.2 s, Gemini 3.5 Flash-Lite 1.4 s); OpenAI deferred by the owner; (9) ✓ `tolk:lang` and `tolk:forms` into German (Sonnet 5.5) and Greek (Gemini 3.8 Flash) kept every `:parameter` and plural variant, a second run sent nothing and a hand edit was kept. A real queue worker ✓ (a database queue on a temporary SQLite file: the listing's run of 13 articles into Greek on the worker, Sonnet 5.5, while a four-worker CLI run re-translated the German site, Gemini 3.8 Flash, and a `--queue` run of the pages); parallel runs with the Stache watcher off ✓ (every page and article once per site, queries matching the files before and after `stache:clear`); golden structure and one provider call per web request ✓ (the suite); no key in any file, log, cache, queue payload or report ✓. Deferred T12.2 timings (`07-spike-findings.md`): the longest demo article (1,079 characters) is one editor unit at any concurrency, 9.4 s on Sonnet 5.5, 6.3 s on Haiku 5.5, 10.0 s on Gemini 3.8 Flash and 4.7 s on Flash-Lite; `http.timeout.web` and `concurrency.*` unchanged. Browser suite: with the owner's keys in the sandbox four scenarios assumed none (the automatic reviewer, "No API key"), now read from the sandbox or anchored; and focus after Undo fell to the page since the watcher change in `dbf198f`, now kept with `holds()` and `restore()`. Pest 3,215 passed (parallel), Vitest 565, Playwright 65 passed with the keys in the sandbox (4 skipped: the screenshots), Pint clean, `resources/dist/build` rebuilt. `CLAUDE.md`: where the keys are and how the live tests get them. TASKS.md: version pins, §A15, T4.12's cap, T8.2's heuristic, the risks rows. CI's first run on this work failed two SDK contract tests in every cell: `composer update` installed `laravel/ai` 1.2.0 (2026-10-07), which keeps the structured output format when options set `output_config` or `text` (laravel/ai#1105); `RequestShapeTest` now expects either behaviour by version, the suite passes on 1.0.1 and 1.2.0, the probe's tiny calls answered on 1.2.0, and the lock stays on 1.0.1. CI then passed on the full matrix (PHP 8.3–8.5 × Laravel 12 and 13, and the CP assets), GitHub Actions run 37835273934. +T11.1 done 2026-10-09: built at the owner's request, off by default, with the owner's two choices: a run of the entry instead of a job translating each localization with `TargetTranslator` (that job could outlast a queue connection's `retry_after` and be handed out twice, and its updates would show nowhere), and `auto_update_create`, which also creates the missing localizations. `QueueTranslationUpdates` on the initial `EntrySaved` of a published origin dispatches `UpdateTranslations` (10 seconds on the queue with a worker, unique until processing; otherwise after the response), which under a lock per entry and once no earlier run from the entry is moving makes the run with `AutoUpdater` (an update as the saver, estimated first and not kept when nothing is pending) and starts it with queue lanes or drives it in its own process as `cli`. Runs carry `scope.automatic`; usage counts under the new source `auto`; `EntryFamilies::originSites()` is now the one rule for the sites an entry is the origin of. Banner: the origin says when saving updates it and, after a save, looks for the run and follows it; the localization says when an automatic update last saved it and whether that waits in a working copy. Runs list and page, `tolk:doctor` and the Audit page name automatic updates. Docs (`configuration.md` Automation, `editor.md` and `bulk-and-runs.md` "Automatic updates", `troubleshooting.md`, `extending.md`, README, CHANGELOG) and the Boost guideline. `tests/Feature/AutoUpdateTest.php` (18 tests; dropping the `isInitial()` check fails the chain case), Pest 3,363 passed (parallel), Vitest 622, Pint clean, `resources/dist/build` rebuilt. Sandbox, through artisan with the fake engine and `auto_update` forced on in that process only (the owner's `.env` has the fake engine off, and the sandbox holds the owner's uncommitted content and untracked settings, which `reset()` would remove): a throwaway article translated into Greek, its excerpt edited and saved; the Greek excerpt was unchanged until the process ended and then updated, title kept, by one completed `cli` run with one save, in about a second; the entry, its state, the run and the three zero-token usage entries it recorded were removed again. The browser check followed (the owner asked for it): with the sandbox's content, settings and runs backed up, the fake engine on for its duration, and everything restored and compared by checksum afterwards. It found that a run finished before the banner's first look left the save without a word, and that a missing site the settings do not create kept the banner looking for 30 seconds: the origin block now lists `auto_update_sites`, and the banner shows the phases `expecting` and `updated`. Through PHP-FPM, the save's `editor/confirm` already named the running run, so the banner went from nothing to running to the completed result; the Greek banner read "Updated automatically from English on Oct 9, 2026, 9:50 PM." in light and dark mode. `tests/Browser/editor-auto-update.spec.js` (3 scenarios); Playwright 69 passed, 4 skipped (the screenshots). diff --git a/docs/bulk-and-runs.md b/docs/bulk-and-runs.md index a448dad..2299fc8 100644 --- a/docs/bulk-and-runs.md +++ b/docs/bulk-and-runs.md @@ -7,6 +7,7 @@ Runs are started from: - the **Translate…** action in entry and term listings and in a structured collection's tree view; - the [Overview](#the-overview), which also translates global sets and navigation; - an origin entry's **Translate into…** and **Update translations** ([The editor](editor.md#in-the-origin)), a run of that one entry; +- saving a published origin entry, when automatic updates are on ([Automatic updates](#automatic-updates)); - the command line, `tolk:translate` and `tolk:site` ([The command line](cli.md)). In the CP they need the `run bulk translations` permission, except the origin entry's buttons, which need `translate content`. The commands need no permission. @@ -63,6 +64,8 @@ A run started in the CP is driven in one of two ways, decided by `runs.execution Runs from the command line are driven by the command, with worker processes (see [The command line](cli.md#how-the-command-runs)). Their page shows their progress like any other. +Automatic updates have no page to drive them, so they run on the queue or in the process that saved the entry ([Automatic updates](#automatic-updates)). + ### "Keep this tab open" With the browser driver, the run moves only while its page is open: "Keep this tab open while the run is in progress. Closing it pauses the run until you open it again." The page warns before you leave it while it drives the run. Nothing is lost when it closes: the next time anyone who may see the run opens its page, the run continues. An item the closed page was working on is picked up again after about 80 seconds. A scheduled `tolk:prune` stops a run that made no progress for five minutes, a browser-driven one whose page stayed closed included; its page then offers **Resume** ([Stalled runs](#stalled-runs)). @@ -94,9 +97,20 @@ With a `retry_after` of 120, each lane job starts requests for up to 30 seconds A lane that is killed is started again, up to five times in a row. If no worker works on a queue run for a while, its page shows "This run is not moving" with **Resume** and **Run in this browser instead**, which hands the run to the page (the browser driver) for a site whose queue has no worker after all. +### Automatic updates + +With `auto_update` on ([Configuration](configuration.md#automation)), saving a published origin entry starts a run of that entry, as its **Update translations** button does ([The editor](editor.md#automatic-updates)). A run with nothing to translate is not kept. No page drives it: + +- **With a queue worker** (`runs.execution` is `auto` or `queue`, and the connection has a worker), a job waits 10 seconds on the queue, so quick saves of the entry make one update, then starts the run with queue lanes, as above. +- **Without one**, or with `runs.execution` set to `browser`, the PHP process that saved the entry runs it after it has sent its response, so the editor does not wait. That process stays busy until the run ends, without PHP's time limit, sleeping through the waits a provider asks for. A web server that stops a request after a fixed time (PHP-FPM's `request_terminate_timeout`) stops the run with it; the run then stalls, and **Resume** on its page finishes it in the browser. Run a queue worker on a site whose entries are long or have many sites. + +A save while an earlier run of the entry is still moving waits for that run (up to 15 minutes), so the same fields are not translated twice. A run started from the entry's banner counts too. + +On the runs list an automatic run says **Automatic update**, and its page "Started automatically on …, when … saved the entry." It translates as the user who saved the entry: the sites they may not edit are left out. A save without a signed-in user, from code or a command, may update every site. + ### Stalled runs -A run whose driver has gone (a closed command, a dead worker) is shown as not moving on its page. `tolk:prune` stops runs that made no progress for `runs.claim_ttl` seconds (5 minutes by default): it marks them aborted and commits what they saved, so their page offers **Resume**, which translates and saves the rest. See [The command line](cli.md#tolkprune). +A run whose driver has gone (a closed command, a dead worker, the process of an automatic update) is shown as not moving on its page. `tolk:prune` stops runs that made no progress for `runs.claim_ttl` seconds (5 minutes by default): it marks them aborted and commits what they saved, so their page offers **Resume**, which translates and saves the rest. See [The command line](cli.md#tolkprune). ## Why one writer @@ -143,6 +157,7 @@ With Statamic's git integration, a run makes one commit ("Content translated") w - **Editor**: the entry and term editor, and **Generate** and **Test connection** in the settings. - **Runs**: the runs started in the CP (the **Translate…** action, the Overview, **Translate into…** and **Update translations**) or with `--queue`. - **Command line**: `tolk:translate` and `tolk:site` without `--queue`, `tolk:lang`, `tolk:forms` and `tolk:profile`. A command-line run resumed on its run page counts under Runs from then on. + - **Automatic updates**: the runs started by saving an origin entry ([Automatic updates](#automatic-updates)). - Users who may edit Tolk's settings can **Reset** the month's usage on the Overview, after a confirmation: the month's file is deleted and counting starts again from zero. A run's page keeps showing the run's own usage. - Costs are computed from the prices in the model catalog (`models.*.price`). The monthly usage keeps the price of the day of each call; a run's page computes its cost from its tokens at the current prices. A model without a price makes the cost "unknown". - Tolk sets no budget caps. Set spending limits with the provider; when one is reached, the provider rejects the requests and the run is aborted with that message. diff --git a/docs/configuration.md b/docs/configuration.md index 8e6752d..728cdd4 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -52,6 +52,17 @@ See [Context and glossary](context-and-glossary.md#the-glossary). | `excluded_fields` | Excluded fields | none | Field handles that are never translated, in every blueprint of entries, terms and global sets. This applies to top-level fields; for a field inside a Replicator, Grid or Bard set, switch off its **Translate automatically** option instead (below). | | `translated_slugs` | Translated slugs | none | New localizations of these collections get a slug made from their translated title, the way Statamic makes slugs in the target site's language ("Hallo Welt" becomes `hallo-welt`). In every other collection a new localization keeps its origin's slug. An existing slug is never changed. See [Entries](content-types.md#entries). | +### Automation + +| Key | Field | Default | Meaning | +| --- | --- | --- | --- | +| `auto_update` | Update translations automatically | off | Each time an entry is saved published in its origin, its localizations are updated in the background: the fields whose origin changed and the fields not translated yet, as **Update translations** does. Fields edited by hand are never overwritten. Every save that changes text spends API credit. See [Automatic updates](editor.md#automatic-updates). | +| `auto_update_create` | Create missing localizations | off | Also translates the entry into the sites of its collection that have no localization of it yet, as **Translate into…** does. New localizations follow `new_localization_status`. Shown only while `auto_update` is on, like the two below; their values are kept while they are hidden. | +| `auto_update_collections` | Collections | none | Only the entries of these collections are updated automatically. Empty: every collection that is not excluded. | +| `auto_update_publish` | Publish updates | off | In collections with revisions, an update of a published localization goes into its working copy and waits until someone publishes it. On: it is published at once, unless the localization already had unpublished changes. | + +Entries only: terms, global sets and the navigation are not updated automatically. + ### Providers `providers` (Providers) shows, for Anthropic, OpenAI and Gemini, whether a key is set, whether it is Tolk's own, from the addon's config (`TOLK_*_API_KEY` by default), or comes from `config/ai.php`, which Tolk shares with the rest of the site, and, without a key, which variables to set, with **Test connection**: one small request to the provider's fast model, with a 20-second timeout, answered with the time it took or a readable error. The field stores nothing. diff --git a/docs/editor.md b/docs/editor.md index fc9fb20..4429e80 100644 --- a/docs/editor.md +++ b/docs/editor.md @@ -103,6 +103,20 @@ When it has finished, the banner shows a line per site with a link to the locali You need only `translate content` for this: you follow and cancel the run you started from the entry, and it continues when you open the entry again, without seeing the Runs pages. A cancelled or aborted run is resumed on the Runs pages, which need `run bulk translations`; otherwise start the translation again from the entry. +### Automatic updates + +With **Update translations automatically** on in the settings (the Automation tab, see [Configuration](configuration.md#automation)), you do not need the button: each time you save a published entry in its origin, Tolk starts the same run as **Update translations**, into every localization of the entry. It translates the fields whose origin changed and the fields not translated yet, and keeps the fields edited by hand. With **Create missing localizations** on, it also translates the entry into the sites of its collection that have none, as **Translate into…** does. + +- The origin's banner says when it happens: "Translations are updated automatically each time this entry is saved", or "…when this entry is published" for a draft, and in a collection with revisions, where Save goes to the working copy and only Publish saves the entry. +- After a save, the banner says "Updating the translations automatically into Greek…" and then shows the run's progress and its result, as for **Update translations**. When the update is done before the banner sees its run, it says "The translations into Greek were updated automatically." With a queue worker the run starts about 10 seconds after the save; when it has not started within half a minute, the banner stops waiting for it, and shows it the next time you open the entry. You can leave the page: the run does not need it. +- A save that changes no text starts nothing. A save while an earlier run of the entry is still going waits for it, so the same fields are not paid for twice. +- The run translates as you: the sites you may not edit are left out. It is listed on the Runs page as an automatic update, and its cost counts under **Automatic updates** on the Overview. +- The localization's banner says when an automatic update last saved it, "Updated automatically from English on 9 Oct 2026, 10:42.", with "not published yet" while the update waits in the working copy of a published localization in a collection with revisions (unless **Publish updates** is on). +- Saves from code (an import, a form handler) count too, when the entry is published. +- Entries only: terms, global sets and the navigation are updated with **Update translations**, bulk runs or the command line. + +How the run is driven, with and without a queue worker, is in [Bulk translations and runs](bulk-and-runs.md#automatic-updates). + ## Collections with revisions In the editor, Tolk only fills the form, and Statamic saves it as it always does: on a collection with revisions, your Save goes to the working copy, and publishing stays a separate step. What happens when Tolk saves server-side (Translate into…, bulk runs, the command line) is in [Bulk translations and runs](bulk-and-runs.md#revisions). diff --git a/docs/extending.md b/docs/extending.md index 3975286..7ad96fe 100644 --- a/docs/extending.md +++ b/docs/extending.md @@ -178,7 +178,7 @@ Tolk dispatches three events, all in `Reach\StatamicTolk\Events`: | Event | When | Properties | | --- | --- | --- | | `TargetTranslated` | Translations were saved into a target server-side: by a run, Translate into…, or the command line. | `ref` (a `TargetRef`: `type`, `id`, `site`; as a string `entry::{id}`, `term::{taxonomy}::{slug}::{site}`, `globals::{handle}::{site}`, `nav::{handle}::{site}`, `lang::{group}::{lang}` or `forms::{lang}`), `handles` (the fields saved), `models` (the models called, as `provider:model`), `usage` | -| `RunStarted` | A run moved from pending to running. | `runId`, `driver` (`RunDriver`: `browser`, `queue` or `cli`), `createdBy` (`['id' => …, 'name' => …]`, or `null` from the command line), `counts` (items per status) | +| `RunStarted` | A run moved from pending to running. | `runId`, `driver` (`RunDriver`: `browser`, `queue` or `cli`; `cli` also for an automatic update driven by the process that saved the entry), `createdBy` (`['id' => …, 'name' => …]`, or `null` from the command line and for an automatic update of an entry saved without a signed-in user), `counts` (items per status) | | `RunFinished` | A run ended: completed, completed with errors, cancelled or aborted. A run that is resumed and ends again fires it again. | `runId`, `status` (`RunStatus`), `counts` (items per status), `usage` | `usage` is a `UsageMap`; `$event->usage->toArray()` gives, per model, the `input`, `output`, `cache_read`, `cache_write` and `reasoning` tokens and the number of `calls`. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index f0d0b2f..2c26461 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -56,8 +56,13 @@ To force one way, set `runs.execution` to `queue` or `browser`. `tolk:doctor` re - **A queue run**: no worker has worked on it for a while. Start one (`php artisan queue:work`, or check your process manager), then press **Resume**; or press **Run in this browser instead** to let the page drive it. - **A command-line run**: the command that ran it stopped (closed terminal, Ctrl-C, a crash). Press **Resume** on its run page to continue it in the CP (on the queue when it has a worker, otherwise driven by the page), or start the command again. +- **An automatic update**: the PHP process that saved the entry stopped before the run ended, usually because the web server stops requests after a fixed time. Press **Resume** on its run page, or save the entry again. A queue worker avoids it ([Automatic updates](bulk-and-runs.md#automatic-updates)). - `tolk:prune` stops runs that made no progress for `runs.claim_ttl` seconds (5 minutes): it marks them aborted and commits what they saved, so **Resume** continues them. Schedule it daily ([`tolk:prune`](cli.md#tolkprune)). +### Saving an entry does not update its translations + +Automatic updates need **Update translations automatically** on (the settings' Automation tab), and only these saves count: of an entry in a collection with more than one site, not excluded, and among **Collections** when that list is not empty; in the entry's origin, not in a localization without localizations of its own; while the entry is published (with revisions, when it is published). A save that changes no text starts nothing, and the user who saved must be allowed to edit the localizations. With a queue worker the update starts about 10 seconds after the save. Each update is listed on the Runs page. See [Automatic updates](editor.md#automatic-updates). + ### Items fail with "No worker finished this item in 3 attempts." The process translating the item died three times (a PHP time or memory limit, a killed worker). Check the PHP error log, raise `memory_limit` or `max_execution_time` for the queue worker, or lower the batch sizes; then **Retry failed**. diff --git a/resources/blueprints/settings.yaml b/resources/blueprints/settings.yaml index 275cf3c..fb733f4 100644 --- a/resources/blueprints/settings.yaml +++ b/resources/blueprints/settings.yaml @@ -203,6 +203,49 @@ tabs: instructions: 'New localizations of these collections get a slug made from their translated title, as Statamic makes slugs. In other collections they keep the slug of their origin. A slug that already exists is never changed.' mode: select default: [] + automation: + display: Automation + sections: + - + fields: + - + handle: auto_update + field: + type: toggle + display: 'Update translations automatically' + instructions: 'Each time an entry is saved published in the site its localizations are translated from, they are updated in the background: the fields whose origin changed and the fields not translated yet. Fields edited by hand are never overwritten. Every such save that changes text spends API credit. Each update is a run on the Translations › Runs page.' + default: false + - + handle: auto_update_create + field: + type: toggle + display: 'Create missing localizations' + instructions: 'Also translate the entry into the sites of its collection that have no localization of it yet. New localizations are drafts, or published when their origin is, as the New localizations setting on the General tab says.' + default: false + always_save: true + if: + auto_update: 'equals true' + - + handle: auto_update_collections + field: + type: collections + display: Collections + instructions: 'Only the entries of these collections are updated automatically. Leave empty for every collection that is not excluded.' + mode: select + default: [] + always_save: true + if: + auto_update: 'equals true' + - + handle: auto_update_publish + field: + type: toggle + display: 'Publish updates' + instructions: 'In collections with revisions, an update of a published localization is saved as a working copy and waits until someone publishes it. Turn this on to publish it at once, unless the localization already had unpublished changes.' + default: false + always_save: true + if: + auto_update: 'equals true' providers: display: Providers sections: diff --git a/resources/boost/guidelines/core.blade.php b/resources/boost/guidelines/core.blade.php index 7c6e47c..901b651 100644 --- a/resources/boost/guidelines/core.blade.php +++ b/resources/boost/guidelines/core.blade.php @@ -61,6 +61,8 @@ A command that translates calls a paid provider and saves content. Prefer `--dry-run` while exploring, and do not run `tolk:translate` or `tolk:site` unless asked to. +With the `auto_update` setting on (**Update translations automatically**, off by default), every save of a published entry in its origin, from code, an import or a seeder too, starts a run that updates its localizations, and with `auto_update_create` creates the missing ones, calling a paid provider. Check `resources/addons/statamic-tolk.yaml` before saving entries in bulk from code, and ask before an import that would trigger it. + ### Translating another fieldtype - A fieldtype of this application or of another addon is translated once a **handler** is registered for it: a class implementing `Reach\StatamicTolk\Contracts\FieldHandler` with one method, `map(Field $field, mixed $value, Closure $translate, WalkContext $context): mixed`, which returns the value with every piece of text replaced by `$translate($leaf)` and nothing else changed. The rule: when `$translate` returns each leaf's own text, `map()` returns a value identical (`===`) to the one it was given. @@ -109,7 +111,7 @@ public function map(Field $field, mixed $value, Closure $translate, WalkContext Three events in `Reach\StatamicTolk\Events`, fired by server-side saves only (runs, Translate into…, the commands). The editor saves nothing itself: when an editor saves a translated localization, Statamic fires its own `EntrySaved` or `TermSaved`. - `TargetTranslated`: translations were saved into one target. `ref` (a `TargetRef` with `type`, `id` and `site`), `handles` (the fields saved), `models` (as `provider:model`) and `usage`. -- `RunStarted`: a run moved from pending to running. `runId`, `driver` (`RunDriver`: `browser`, `queue` or `cli`), `createdBy` (`['id' => …, 'name' => …]`, or `null` from the command line) and `counts` (items per status). +- `RunStarted`: a run moved from pending to running. `runId`, `driver` (`RunDriver`: `browser`, `queue` or `cli`), `createdBy` (`['id' => …, 'name' => …]`, or `null` from the command line and for an automatic update of an entry saved without a signed-in user) and `counts` (items per status). - `RunFinished`: a run ended, completed, completed with errors, cancelled or aborted; a resumed run fires it again when it ends. `runId`, `status` (`RunStatus`), `counts` and `usage`. - `usage` is a `UsageMap`; `$event->usage->toArray()` gives, per model, the input, output, cache read, cache write and reasoning tokens and the number of calls. diff --git a/resources/dist/build/assets/cp-ByCdgQdW.js b/resources/dist/build/assets/cp-ByCdgQdW.js deleted file mode 100644 index 8ad9582..0000000 --- a/resources/dist/build/assets/cp-ByCdgQdW.js +++ /dev/null @@ -1 +0,0 @@ -var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r},{AfterSaveHooks:n,BeforeSaveHooks:r,Pipeline:i,PipelineStopped:a,Request:o}=__STATAMIC__.savePipeline,{BaseTransition:s,BaseTransitionPropsValidators:c,Comment:l,DeprecationTypes:u,EffectScope:d,ErrorCodes:f,ErrorTypeStrings:p,Fragment:m,KeepAlive:h,ReactiveEffect:g,Static:_,Suspense:v,Teleport:y,Text:b,TrackOpTypes:x,Transition:S,TransitionGroup:C,TriggerOpTypes:w,VueElement:T,__esModule:E,assertNumber:D,callWithAsyncErrorHandling:ee,callWithErrorHandling:te,camelize:ne,capitalize:re,cloneVNode:ie,compatUtils:ae,compile:oe,computed:O,createApp:se,createBlock:k,createCommentVNode:A,createElementBlock:j,createElementVNode:M,createHydrationRenderer:ce,createPropsRestProxy:le,createRenderer:ue,createSSRApp:de,createSlots:fe,createStaticVNode:pe,createTextVNode:N,createVNode:P,customRef:me,defineAsyncComponent:he,defineComponent:ge,defineCustomElement:_e,defineEmits:ve,defineExpose:ye,defineModel:be,defineOptions:xe,defineProps:Se,defineSSRCustomElement:Ce,defineSlots:we,devtools:Te,effect:Ee,effectScope:De,getCurrentInstance:Oe,getCurrentScope:ke,getCurrentWatcher:Ae,getTransitionRawChildren:je,guardReactiveProps:Me,h:Ne,handleError:Pe,hasInjectionContext:Fe,hydrate:Ie,hydrateOnIdle:Le,hydrateOnInteraction:Re,hydrateOnMediaQuery:ze,hydrateOnVisible:Be,initCustomFormatter:Ve,initDirectivesForSSR:He,inject:Ue,isMemoSame:We,isProxy:Ge,isReactive:Ke,isReadonly:qe,isRef:Je,isRuntimeOnly:Ye,isShallow:Xe,isVNode:Ze,markRaw:Qe,mergeDefaults:$e,mergeModels:et,mergeProps:tt,nextTick:nt,nodeOps:rt,normalizeClass:it,normalizeProps:at,normalizeStyle:ot,onActivated:st,onBeforeMount:ct,onBeforeUnmount:lt,onBeforeUpdate:ut,onDeactivated:dt,onErrorCaptured:ft,onMounted:pt,onRenderTracked:mt,onRenderTriggered:ht,onScopeDispose:gt,onServerPrefetch:_t,onUnmounted:vt,onUpdated:yt,onWatcherCleanup:bt,openBlock:F,patchProp:xt,popScopeId:St,provide:Ct,proxyRefs:wt,pushScopeId:Tt,queuePostFlushCb:Et,reactive:Dt,readonly:Ot,ref:I,registerRuntimeCompiler:kt,render:At,renderList:L,renderSlot:jt,resolveComponent:Mt,resolveDirective:Nt,resolveDynamicComponent:Pt,resolveFilter:Ft,resolveTransitionHooks:It,setBlockTracking:Lt,setDevtoolsHook:Rt,setTransitionHooks:zt,shallowReactive:Bt,shallowReadonly:Vt,shallowRef:Ht,ssrContextKey:Ut,ssrUtils:Wt,stop:Gt,toDisplayString:R,toHandlerKey:Kt,toHandlers:qt,toRaw:Jt,toRef:Yt,toRefs:Xt,toValue:Zt,transformVNodeArgs:Qt,triggerRef:$t,unref:z,useAttrs:en,useCssModule:tn,useCssVars:nn,useHost:rn,useId:an,useModel:on,useSSRContext:sn,useShadowRoot:cn,useSlots:ln,useTemplateRef:un,useTransitionState:dn,vModelCheckbox:fn,vModelDynamic:pn,vModelRadio:mn,vModelSelect:hn,vModelText:gn,vShow:_n,version:vn,warn:yn,watch:bn,watchEffect:xn,watchPostEffect:Sn,watchSyncEffect:Cn,withAsyncContext:wn,withCtx:B,withDefaults:Tn,withDirectives:En,withKeys:Dn,withMemo:On,withModifiers:kn,withScopeId:An}=window.Vue,{Alert:jn,AuthCard:Mn,Avatar:Nn,Badge:Pn,Button:V,ButtonGroup:Fn,Calendar:In,Card:H,CardList:Ln,CardListItem:Rn,CardPanel:zn,CharacterCounter:Bn,Checkbox:Vn,CheckboxGroup:Hn,CodeEditor:Un,Combobox:Wn,CommandPaletteItem:Gn,ConfirmationModal:Kn,ContentDirection:qn,useContentDirection:Jn,useUiDirection:Yn,Context:Xn,ContextFooter:Zn,ContextHeader:Qn,ContextItem:$n,ContextLabel:er,ContextMenu:tr,ContextSeparator:nr,CreateForm:rr,DatePicker:ir,DateRangePicker:ar,Description:U,DocsCallout:or,DragHandle:sr,Dropdown:cr,DropdownItem:lr,DropdownLabel:ur,DropdownMenu:dr,DropdownSeparator:fr,DropdownFooter:pr,DropdownHeader:mr,Editable:hr,ErrorMessage:gr,EmptyStateItem:_r,EmptyStateMenu:vr,Field:yr,Header:br,Heading:W,HoverCard:xr,Icon:G,Input:Sr,InputGroup:Cr,InputGroupAppend:wr,InputGroupPrepend:Tr,Label:Er,Listing:Dr,ListingCustomizeColumns:Or,ListingFilters:kr,ListingHeaderCell:Ar,ListingPagination:jr,ListingPresets:Mr,ListingPresetTrigger:Nr,ListingRowActions:Pr,ListingSearch:Fr,ListingTable:Ir,ListingTableBody:Lr,ListingTableHead:Rr,ListingToggleAll:zr,LivePreview:Br,LivePreviewPopout:Vr,MiddleEllipsis:Hr,Modal:Ur,ModalClose:Wr,ModalTitle:Gr,Pagination:Kr,Panel:qr,PanelFooter:Jr,PanelHeader:Yr,Popover:Xr,PublishComponents:Zr,PublishContainer:Qr,publishContextKey:$r,injectPublishContext:ei,PublishField:ti,PublishFields:ni,PublishFieldsProvider:ri,PublishForm:ii,PublishLocalizations:ai,PublishSections:oi,PublishTabs:si,Radio:ci,RadioGroup:li,Select:ui,Separator:di,Slider:fi,Skeleton:pi,SplitterGroup:mi,SplitterPanel:hi,SplitterResizeHandle:gi,StatusIndicator:_i,Subheading:vi,Switch:yi,TabContent:bi,Stack:xi,StackClose:Si,StackHeader:Ci,StackFooter:wi,StackContent:Ti,Table:Ei,TableCell:K,TableColumn:q,TableColumns:Di,TableRow:Oi,TableRows:ki,TabList:Ai,TabProvider:ji,Tabs:Mi,TabTrigger:Ni,Text:J,Textarea:Pi,TimePicker:Fi,TimezoneHoverCard:Ii,Timezones:Li,ToggleGroup:Ri,ToggleItem:zi,Widget:Bi,registerIconSet:Vi,registerIconSetFromStrings:Hi}=__STATAMIC__.ui,Ui=/(<\/?\d+>|||\s+)/,Wi=/^(?:<\/?\d+>||)$/,Gi=/^\s+$/;function Ki(e){return String(e??``).split(Ui).filter(e=>e!==``).map(e=>({text:e,kind:Gi.test(e)?`space`:Wi.test(e)?`placeholder`:`word`}))}function qi(e,t){let n=new Set,r=new Set;if(e.length*t.length>25e4)return[n,r];let i=t.length+1,a=new Uint32Array((e.length+1)*i);for(let n=e.length-1;n>=0;n--)for(let r=t.length-1;r>=0;r--)a[n*i+r]=e[n]===t[r]?a[(n+1)*i+r+1]+1:Math.max(a[(n+1)*i+r],a[n*i+r+1]);for(let o=0,s=0;o=a[o*i+s+1]?o++:s++;return[n,r]}function Ji(e,t){let n=0,r=e.map(e=>({...e,changed:e.kind!==`space`&&!t.has(n++)}));return r.forEach((e,t)=>{e.kind===`space`&&(e.changed=!!(r[t-1]?.changed&&r[t+1]?.changed))}),r}function Yi(e,t){let n=Ki(e),r=Ki(t),i=e=>e.filter(e=>e.kind!==`space`).map(e=>e.text),[a,o]=qi(i(n),i(r));return{before:Ji(n,a),after:Ji(r,o)}}var Y=t({ApiError:()=>Xi,asMap:()=>X,get:()=>Zi,normalizeError:()=>ta,post:()=>Qi}),Xi=class extends Error{constructor({status:e,code:t,message:n,data:r}){super(n),this.name=`ApiError`,this.status=e,this.code=t,this.data=r}};function X(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}function Zi(e,t={}){return ea(`get`,e,{params:t})}function Qi(e,t={}){return ea(`post`,e,t)}function $i(){return Statamic.$app.config.globalProperties.$axios}async function ea(e,t,n){let r=$i(),i=/^https?:\/\//i.test(t)?t:cp_url(`tolk/${t.replace(/^\/+/,``)}`);try{return(await r[e](i,n)).data}catch(e){throw ta(e)}}function ta(e){let t=e?.response,n=t?.data!==null&&typeof t?.data==`object`?t.data:null,r=t?.status??0;return new Xi({status:r,code:typeof n?.code==`string`?n.code:null,message:typeof n?.message==`string`&&n.message!==``?n.message:na(r),data:n})}function na(e){return e===0?__(`The server could not be reached.`):__(`The request failed with status :status.`,{status:e})}var ra={untranslated:{text:e=>__n(`:count field untranslated|:count fields untranslated`,e),description:()=>__(`Not translated yet. Translate fills them in.`)},outdated:{text:e=>__n(`:count field outdated|:count fields outdated`,e),description:()=>__(`The source changed since they were translated, or part of their text is still untranslated. Update translates them again.`)},manual:{text:e=>__n(`:count field edited by hand|:count fields edited by hand`,e),description:()=>__(`Edited by hand. Translate and Update leave them alone.`)},attention:{text:e=>__n(`:count needs attention|:count need attention`,e),description:()=>__(`Edited by hand, and the source changed since. Check them against the source.`)},untracked:{text:e=>__n(`:count untracked|:count untracked`,e),description:()=>__(`Edited by hand before their translation was tracked, so a change to the source cannot be detected. Mark them as up to date to track them.`)},current:{text:e=>__n(`:count field up to date|:count fields up to date`,e),description:()=>__(`Translated and up to date with the source.`)}},ia={missing:`red`,untranslated:`orange`,outdated:`amber`,attention:`purple`,manual:`sky`,untracked:`default`,current:`green`};function aa(e){return ia[e]??`default`}function oa(e){return{missing:__(`Missing`),untranslated:__(`Untranslated`),outdated:__(`Outdated`),attention:__(`Needs attention`),current:__(`Up to date`)}[e]??e}function sa(e={}){return Object.entries(ra).filter(([t])=>(e[t]??0)>0).map(([t,n])=>({key:t,count:e[t],text:n.text(e[t]),description:n.description()}))}function ca(e){let t=e?.defaults??{};return!(t.providers_configured||t.fake_engine)||!t.translator}function la(e){if(e?.translatable!==!0)return{visible:!1,reason:e?.reason??null,setup:!1,translator:null,localization:null,origin:null};let t=ca(e);return{visible:!0,reason:null,setup:t,translator:e.defaults?.translator??null,localization:e.localization?ua(e.localization,t):null,origin:e.origin?ha(e.origin,t):null}}function ua(e,t){let n=e.counts??{},r=sa(n),i=Object.entries(e.fields??{}).filter(([,e])=>e.incomplete).map(([e,t])=>({handle:e,label:t.label})),a=(e.out_of_scope??[]).filter(e=>e.reason===`not_localizable`).map(({handle:e,label:t})=>({handle:e,label:t})),o=da(e,r);return{source:e.source,target:e.target,status:e.status,label:oa(e.status),parts:r,summary:o,lead:r.length>0?__(`From :source:`,{source:e.source?.name??``}):o,incomplete:i,incompleteNote:i.length?fa(i):null,notLocalizable:a,hint:a.length?pa(ma(a),a.length):null,translate:!t&&(n.untranslated??0)>0,update:!t&&(n.outdated??0)>0}}function da(e,t){let n=e.source?.name??``;return t.length===0?__(`Nothing to translate from :source.`,{source:n}):t.every(e=>e.key===`current`)?__(`Up to date with :source.`,{source:n}):__(`From :source: :parts.`,{source:n,parts:t.map(e=>e.text).join(`, `)})}function fa(e){return __n(`:fields is partly untranslated. Update translates the rest.|:fields are partly untranslated. Update translates the rest.`,e.length,{fields:ma(e)})}function pa(e,t){return __n(`:fields is not translated because it is not localizable.|:fields are not translated because they are not localizable.`,t,{fields:e})}function ma(e){return e.map(e=>e.label).join(`, `)}function ha(e,t){let n=(e.localizations??[]).map(e=>{let t=!e.exists,n=e.counts??{},r=t?[]:sa(n);return{site:e.site,name:e.name,exists:e.exists,status:e.status,label:oa(e.status),color:aa(e.status),parts:r,summary:ga(e,r),editUrl:e.edit_url??null,translate:t||(n.untranslated??0)>0,update:!t&&(n.outdated??0)>0}});return{localizations:n,upToDate:n.length>0&&n.every(e=>e.status===`current`),translateInto:!t&&n.some(e=>e.translate),update:!t&&n.some(e=>e.update)}}function ga(e,t){return e.exists?t.length===0?__(`Nothing to translate.`):t.every(e=>e.key===`current`)?null:t.map(e=>e.text).join(`, `):__(`Not created yet.`)}function _a(e,t=globalThis.Statamic?.$config?.get(`tolk.models`)){if(typeof t?.[e]==`string`)return t[e];let n=e.indexOf(`:`);return n===-1?e:e.slice(n+1)}function va(e,t){let n=X(t?.localization?.fields);return e.map(e=>n[e]?.label??e).join(`, `)}function ya(e,t=null){if(!e)return null;let n=e.kind===`review`,r=e.delivered.length,i=e.corrections?.length??0,a=Object.keys(e.skipped).filter(t=>e.skipped[t]===`edited`),o=Object.keys(e.planSkipped??{}).filter(t=>e.planSkipped[t]===`manual`),s=Object.keys(e.failed);return{translated:n?null:xa(r,ba(e)),reviewed:Sa(e,i),corrections:i,reviewSkipped:e.reviewSkipped?.length?__(`Part of the text could not be reviewed and was kept as it was.`):null,incomplete:e.incomplete.length?__n(`:fields is partly untranslated. Update translates the rest after you save.|:fields are partly untranslated. Update translates the rest after you save.`,e.incomplete.length,{fields:va(e.incomplete,t)}):null,edited:a.length?__n(`:fields was skipped because you edited it.|:fields were skipped because you edited them.`,a.length,{fields:va(a,t)}):null,manual:o.length?Ca(o,n,t):null,failed:s.length?n?__n(`:fields could not be reviewed.|:fields could not be reviewed.`,s.length,{fields:va(s,t)}):__n(`:fields could not be translated.|:fields could not be translated.`,s.length,{fields:va(s,t)}):null,cancelled:e.cancelled?n?__(`The review was cancelled before it finished.`):__(`The translation was cancelled before it finished.`):null,unsaved:r>0?__(`Not saved yet. Check the fields, then save.`):null}}function ba(e){let t=e.models.filter(t=>t!==e.reviewer);return(t.length?t:e.models).map(e=>_a(e)).join(`, `)}function xa(e,t){return e===0?__(`No fields were translated.`):t?__n(`:count field translated with :model.|:count fields translated with :model.`,e,{model:t}):__n(`:count field translated.|:count fields translated.`,e)}function Sa(e,t){if(e.kind===`review`&&(e.planned??[]).length===0)return __(`There was nothing to review: no field holds a translation that is up to date.`);if(!e.reviewer||!e.reviewedUnits?.length)return null;let n=_a(e.reviewer);return t>0?__n(`Reviewed with :model: :count correction.|Reviewed with :model: :count corrections.`,t,{model:n}):__(`Reviewed with :model: nothing to correct.`,{model:n})}function Ca(e,t,n){let r=va(e,n);return t?__n(`:fields was not reviewed because it was edited by hand. Overwrite manual edits in the options reviews it too.|:fields were not reviewed because they were edited by hand. Overwrite manual edits in the options reviews them too.`,e.length,{fields:r}):__n(`:fields was skipped because it was edited by hand. Overwrite manual edits in the options replaces it.|:fields were skipped because they were edited by hand. Overwrite manual edits in the options replaces them.`,e.length,{fields:r})}var wa={class:`space-y-6`},Ta={class:`space-y-2 text-sm`},Ea={class:`text-xs font-medium text-gray-500 dark:text-gray-400`},Da={class:`whitespace-pre-wrap`,"data-tolk-change-before":``},Oa={class:`text-xs font-medium text-gray-500 dark:text-gray-400`},ka={class:`whitespace-pre-wrap`,"data-tolk-change-after":``},Aa={class:`text-xs font-medium text-gray-500 dark:text-gray-400`},ja={class:`whitespace-pre-wrap`,"data-tolk-change-reason":``},Ma={class:`flex items-center justify-end gap-3 pt-3 pb-1`},Na={__name:`ChangesModal`,props:{modal:{type:Object,required:!0},corrections:{type:Array,default:()=>[]},reviewer:{type:String,default:null}},setup(e){let t=e,n=O(()=>t.corrections.map(e=>({...e,key:`${e.handle}:${e.id}`,diff:Yi(e.before,e.after)})));function r(e,t){return e.kind===`placeholder`?[`font-mono text-xs text-gray-500 dark:text-gray-400`,e.changed&&`rounded-sm bg-amber-100 dark:bg-amber-900/40!`]:e.changed?t===`before`?`rounded-sm bg-red-100 text-red-900 line-through dark:bg-red-900/40! dark:text-red-100`:`rounded-sm bg-green-100 text-green-900 underline decoration-green-700/60 dark:bg-green-900/40! dark:text-green-100 dark:decoration-green-300/60`:null}return(t,i)=>(F(),k(z(Ur),{open:``,title:t.__(`Changes by the reviewer`),icon:`dictionary-language-book`,"data-tolk-changes":``,onDismissed:i[1]||=t=>e.modal.dismissed(),"onUpdate:open":i[2]||=t=>e.modal.closed(t)},{footer:B(()=>[M(`div`,Ma,[P(z(V),{variant:`primary`,text:t.__(`Close`),"data-tolk-changes-action":`close`,onClick:i[0]||=t=>e.modal.hide()},null,8,[`text`])])]),default:B(()=>[M(`div`,wa,[e.reviewer?(F(),k(z(U),{key:0},{default:B(()=>[N(R(t.__(`Corrected by :model. The corrections are in the form; nothing is saved until you press Save.`,{model:z(_a)(e.reviewer)})),1)]),_:1})):A(``,!0),(F(!0),j(m,null,L(n.value,e=>(F(),j(`div`,{key:e.key,class:`space-y-2`,"data-tolk-change":``},[P(z(W),{"data-tolk-change-label":``},{default:B(()=>[N(R(e.label),1)]),_:2},1024),M(`dl`,Ta,[M(`div`,null,[M(`dt`,Ea,R(t.__(`Before`)),1),M(`dd`,Da,[(F(!0),j(m,null,L(e.diff.before,(e,t)=>(F(),k(Pt(e.changed?`del`:`span`),{key:t,class:it(r(e,`before`)),"data-tolk-removed":e.changed&&e.kind!==`space`?``:null},{default:B(()=>[N(R(e.text),1)]),_:2},1032,[`class`,`data-tolk-removed`]))),128))])]),M(`div`,null,[M(`dt`,Oa,R(t.__(`After`)),1),M(`dd`,ka,[(F(!0),j(m,null,L(e.diff.after,(e,t)=>(F(),k(Pt(e.changed?`ins`:`span`),{key:t,class:it(r(e,`after`)),"data-tolk-added":e.changed&&e.kind!==`space`?``:null},{default:B(()=>[N(R(e.text),1)]),_:2},1032,[`class`,`data-tolk-added`]))),128))])]),M(`div`,null,[M(`dt`,Aa,R(t.__(`Reason`)),1),M(`dd`,ja,R(e.reason),1)])])]))),128))])]),_:1},8,[`title`]))}},Pa=[`aria-label`,`aria-valuemax`,`aria-valuenow`],Fa={__name:`ProgressBar`,props:{value:{type:Number,default:0},max:{type:Number,default:0},label:{type:String,required:!0}},setup(e){let t=e,n=O(()=>t.max>0?Math.min(100,Math.round(t.value/t.max*100)):0);return(t,r)=>(F(),j(`div`,{role:`progressbar`,"aria-label":e.label,"aria-valuemin":`0`,"aria-valuemax":e.max,"aria-valuenow":e.value,class:`h-1.5 w-full overflow-hidden rounded-full bg-gray-200 dark:bg-gray-700`,"data-tolk-progress":``},[M(`div`,{class:`h-full rounded-full bg-blue-600 transition-[width] duration-300 dark:bg-blue-400!`,style:ot({width:`${n.value}%`})},null,4)],8,Pa))}},Ia=`base`;function La(){let e=Bt(new Map),t=!1;function n(e=Statamic.$events){t||(t=!0,e.$on(`publish-container-created`,r),e.$on(`publish-container-destroyed`,i))}function r(t){let n=(e.get(t.name)?.mounted??0)+1;e.set(t.name,{payload:t,context:null,clean:null,mounted:n})}function i({name:t}){let n=e.get(t);n&&(n.mounted>1?e.set(t,{...n,mounted:n.mounted-1}):e.delete(t))}function a(t,n){let r=e.get(t)??{payload:null,context:null,clean:null,mounted:0};e.set(t,{...r,...n})}function o(t,n){a(t,{context:n,clean:e.get(t)?.clean??Z(n.values.value)})}function s(e){let t=c(e);t!==null&&a(e,{clean:Z(t)})}function c(t){let n=e.get(t);return(n?.context??n?.payload)?.values?.value??null}function l(t){let n=e.get(t)?.clean,r=c(t);return!n||r===null?[]:[...new Set([...Object.keys(r),...Object.keys(n)])].filter(e=>!Va(r[e],n[e]))}return{listen:n,attachContext:o,refreshClean:s,dirtyHandles:l,context:t=>e.get(t)?.context??null,payload:t=>e.get(t)?.payload??null,base:()=>e.get(`base`)?.context??null,others:()=>[...e.keys()].filter(e=>e!==Ia)}}var Ra=La();function Z(e){return Array.isArray(e)?e.map(Z):typeof e!=`object`||!e?e:Object.fromEntries(Object.keys(e).map(t=>[t,Z(e[t])]))}var za=new Set([`type`,`id`,`_id`,`marks`]);function Ba(e){return typeof e==`string`?e:Array.isArray(e)?e.map(Ba).join(``):typeof e!=`object`||!e?``:Object.keys(e).filter(e=>!za.has(e)).sort().map(t=>Ba(e[t])).join(``)}function Va(e,t){return Ba(e)===Ba(t)}var Ha=2e3,Ua=1e3,Wa=100,Ga=50,Ka=e=>new Promise(t=>setTimeout(t,e)),qa=e=>typeof e==`function`?e:()=>e,Ja=(e,t,n)=>()=>e.reference.value===t&&n();async function Ya(e,t,n){let r=()=>600-(t()-e());for(let e=r();e>0;e=r())await n(e)}function Xa(e,t,n){return Object.hasOwn(t,n)?!Va(e.values.value[n],t[n]):e.values.value[n]!==void 0}function Za(e,t,n){return n===null&&typeof e.values.value[t]==`string`?``:Z(n)}function Qa(e,t){return!!t&&!t.pending&&t.plan!==e.delivered?.plan}function $a(e,t,n={}){let r=e.localizedFields.value;return{reference:e.reference.value,dirty:Statamic.$dirty.has(e.name.value),fields:Object.fromEntries(t.map(t=>[t,{value:Z(e.values.value[t]),meta:Z(e.meta.value[t]),localized:r.includes(t),delivered:n[t]?Z(n[t]):null}]))}}async function eo(e,t,{reference:n,plan:r,lastChangeAt:i=0,planValues:a={},delivered:o,now:s=Date.now,sleep:c=Ka,active:l=()=>!0}){let u=Object.keys(t??{}),d={stale:!1,applied:[],skipped:{},repeated:[]},f=()=>(d.stale=!0,d.applied=[],d.skipped=Object.fromEntries(u.map(e=>[e,`stale`])),d),p=Ja(e,n,l);if(!p()||(await Ya(qa(i),s,c),!p()))return f();let m=[];for(let n of u){let i=t[n];if(o[n]?.plan===r){d.repeated.push(n);continue}if(Xa(e,a,n)){d.skipped[n]=`edited`;continue}o[n]={plan:r,value:void 0,pending:!0,incomplete:!!i.incomplete,sync:!!i.sync},i.meta!==void 0&&e.setFieldMeta(n,Z(i.meta)),e.setFieldValue(n,Za(e,n,i.value)),i.sync?(so(e,n,!1),Statamic.$dirty.add(e.name.value),m.push(n)):(e.desyncField(n),e.localizedFields.value.includes(n)||(so(e,n,!0),Statamic.$dirty.add(e.name.value))),d.applied.push(n)}if(!d.applied.length)return d;if(await c(300),!p())return d.applied.forEach(e=>delete o[e]),f();m.forEach(t=>so(e,t,!1));for(let t of d.applied)o[t]={...o[t],value:Z(e.values.value[t]),pending:!1};return d}async function to(e,t,n,{registry:r=Ra,sleep:i=Ka}={}){let a={restored:[],kept:[]};if(!t||e.reference.value!==t.reference)return a;for(let[r,i]of Object.entries(t.fields)){let t=n[r];if(Qa(i,t)){if(!Va(e.values.value[r],t.value)){a.kept.push(r);continue}a.restored.push(r)}}if(!a.restored.length)return a;e.withoutDirtying(()=>{for(let r of a.restored){let i=t.fields[r];e.setFieldMeta(r,Z(i.meta)),e.setFieldValue(r,Za(e,r,i.value)),so(e,r,i.localized),i.delivered?n[r]=Z(i.delivered):delete n[r]}});let o=()=>{e.reference.value===t.reference&&(a.restored.forEach(n=>so(e,n,t.fields[n].localized)),!t.dirty&&r.dirtyHandles(e.name.value).length===0&&Statamic.$dirty.remove(e.name.value))};return o(),await i(300),o(),a}async function no(e,t,{reference:n,lastChangeAt:r=0,now:i=Date.now,sleep:a=Ka,active:o=()=>!0}={}){let s=qa(r),c=Ja(e,n,o),l=()=>s()+Ha-i();if(!c())return{stale:!0,kept:!1,reset:!1};if(!io(e,t))return{stale:!1,kept:!1,reset:!1};for(await Ya(s,i,a);c()&&!ao(e)&&l()>0;)await a(Math.min(Wa,l()));let u=ao(e);return!c()||!await oo(e,t,{sleep:a,current:c})?{stale:!0,kept:!1,reset:u}:{stale:!1,kept:!0,reset:u}}async function ro(e,t,{reference:n,sleep:r=Ka,active:i=()=>!0}={}){let a=Ja(e,n,i);return!io(e,t)||(await r(Ua),!a()||e.values.value.slug===t&&!ao(e))?!1:oo(e,t,{sleep:r,current:a})}function io(e,t){return typeof t==`string`&&t!==``&&Object.hasOwn(e.values.value??{},`slug`)}function ao(e){return e.meta.value?.slug?.auto===!0}async function oo(e,t,{sleep:n,current:r}){return ao(e)&&e.values.value.slug===t&&(e.setFieldValue(`slug`,``),await n(Ga),!r())?!1:(e.values.value.slug!==t&&e.setFieldValue(`slug`,t),!0)}function so(e,t,n){let r=e.localizedFields.value,i=r.indexOf(t);n&&i===-1?r.push(t):!n&&i!==-1&&r.splice(i,1)}var co=2e3,lo=5;function uo(e,t){return new Promise(n=>{if(t?.aborted)return n();let r=()=>{clearTimeout(i),t?.removeEventListener(`abort`,r),n()},i=setTimeout(r,e);t?.addEventListener(`abort`,r,{once:!0})})}function fo(e){let t=e?.status??0;return t===429||t===503?`wait`:t===409&&e.code===`busy`?`busy`:t===409&&e.code===`source_changed`||t===410||t===502?`stop`:`fail`}function po(e,t=``){return{status:e?.status??0,code:e?.code??null,message:e?.message||t}}var mo=e=>Object.entries(X(e)),ho=({id:e,fields:t})=>({id:e,fields:t});async function go({api:e=Y,plan:t,concurrency:n=1,onFields:r=()=>{},onProgress:i=()=>{},signal:a=null,finishing:o=()=>!0,sleep:s=uo,maxWaits:c=5,busyMs:l=co,maxBusyWaits:u=60}){let d=Math.max(1,Math.floor(Number(n))||1),f=[...t.units??[]],p=new Set(f.map(e=>e.id)),m={total:f.length,done:0,waiting:0},h=new Map,g=[],_=[],v=[],y={},b=new Set,x=new Set,S=new Set,C=new Set,w={},T=null,E=()=>T!==null||!!a?.aborted,D=()=>i({...m});function ee(){if(!E())return f.shift();let e=T===null&&o()?f.findIndex(e=>!p.has(e.id)):-1;return e===-1?null:f.splice(e,1)[0]}function te(e){let t=mo(e).map(([e,t])=>(h.set(e,t),e));t.length&&g.push(Promise.resolve().then(()=>r(e)).then(e=>({handles:t,result:e}),e=>({handles:t,error:e})))}function ne(e,t){te(t?.fields);for(let[e,n]of mo(t?.failed))y[e]=n;(Array.isArray(t?.warnings)?t.warnings:[]).forEach(e=>b.add(e)),(Array.isArray(t?.unchanged)?t.unchanged:[]).forEach(e=>x.add(e)),t?.reviewed===!0&&S.add(e.id),t?.review_skipped===!0&&C.add(e.id);for(let[e,n]of mo(t?.usage))w[e]=vo(w[e]??{},n);let n=Array.isArray(t?.spawned)?t.spawned:[];f.push(...n),m.total+=n.length}async function re(n){let r=0,i=0;for(;;)try{return ne(n,await e.post(`editor/unit`,{plan:t.plan,unit:n.id}))}catch(e){let t=fo(e),o=t===`wait`&&r0?Number(e.data.retry_after):lo;if(m.waiting++,D(),await s(t===`wait`?d*1e3:l,a),m.waiting--,D(),E()){v.push(ho(n));return}}}return te(t.ready),D(),await new Promise(e=>{let t=0,n=()=>{let r;for(;t{t--,m.done++,D(),n()});t===0&&e()};n()}),v.push(...f.map(ho)),_o(await Promise.all(g),{received:h,failed:y,failedUnits:_,cancelledUnits:v,warnings:[...b],unchanged:x,reviewedUnits:[...S],reviewSkipped:[...C],usage:w,stopped:T,aborted:!!a?.aborted,progress:m})}function _o(e,{received:t,failed:n,failedUnits:r,cancelledUnits:i,warnings:a,unchanged:o,reviewedUnits:s,reviewSkipped:c,usage:l,stopped:u,aborted:d,progress:f}){let p=[],m={},h=!1;for(let{handles:t,result:r,error:i}of e){if(i){t.forEach(e=>n[e]??=`not_filled`);continue}h||=r?.stale===!0;for(let e of r?.applied??(r?[]:t))p.includes(e)||p.push(e);Object.assign(m,r?.skipped??{})}for(let e of r)for(let t of e.fields??[])!p.includes(t)&&!(t in m)&&(n[t]??=e.error?.code??`failed`);return p.forEach(e=>delete n[e]),{delivered:p,incomplete:p.filter(e=>t.get(e)?.incomplete===!0),skipped:m,failed:n,failedUnits:r,cancelledUnits:i,warnings:a,corrections:p.flatMap(e=>{let n=t.get(e)?.corrections;return Array.isArray(n)?n.map(t=>({handle:e,...t})):[]}),unchanged:[...o].filter(e=>!p.includes(e)),reviewedUnits:s,reviewSkipped:c,usage:l,models:Object.keys(l),stopped:u,aborted:d,stale:h,units:{total:f.total,done:f.done}}}function vo(e,t){let n={...e};for(let[e,r]of mo(t))typeof r==`number`&&(n[e]=(n[e]??0)+r);return n}var yo=t({BACKOFF_MS:()=>xo,FINAL_STATUSES:()=>bo,IDLE_MS:()=>Co,MAX_BACKOFF_MS:()=>So,MAX_RETRIES:()=>5,POLL_MS:()=>wo,backoff:()=>Mo,estimateLoop:()=>zo,isFinal:()=>Do,latest:()=>Oo,nonce:()=>Eo,pollState:()=>Ro,retryable:()=>jo,startApplyLoop:()=>Io,startLanes:()=>Fo}),bo=[`completed`,`completed_with_errors`,`cancelled`,`aborted`],xo=1e3,So=3e4,Co=1e3,wo=2e3,To=null;function Eo(){return To??=Array.from(crypto.getRandomValues(new Uint8Array(12)),e=>e.toString(16).padStart(2,`0`)).join(``),To}function Do(e){return bo.includes(e?.run?.status)}function Oo(e){let t=null;return n=>{t!==null&&ko(n,t)||(t=n,e(n))}}function ko(e,t){let n=Ao(e),r=Ao(t);return n=500}function Mo(e,t=xo){return Math.min(t*2**Math.max(0,e-1),So)}function No(e,t){return e==null?t:Math.max(0,Number(e)||0)*1e3}async function Po(e,{retries:t,backoffMs:n,sleep:r,signal:i}){for(let a=1;;a++)try{return{response:await e()}}catch(e){if(i?.aborted)return{};if(a>t||!jo(e))return{error:po(e)};if(await r(Mo(a,n),i),i?.aborted)return{}}}function Fo({api:e=Y,urls:t,lanes:n=1,nonce:r=Eo(),onState:i=()=>{},onFailure:a=()=>{},signal:o=null,query:s=()=>({}),sleep:c=uo,retries:l=5,backoffMs:u=xo,idleMs:d=Co}){let f=Math.max(1,Math.floor(Number(n))||1),p=new Map,m=new Set,h=[],g=[],_=()=>!!o?.aborted,v=e=>m.forEach(t=>t(e)),y=()=>[...p.values()].filter(e=>e===`running`).length;function b(e,t){let n={lane:e,error:t};return g.push(n),a(n),`failed`}let x=n=>e.post(t.tick,{...s(),nonce:r,lane:n});async function S(e){for(;!_();){let{response:t,error:n}=await Po(()=>x(e),{retries:l,backoffMs:u,sleep:c,signal:o});if(_())break;if(n)return b(e,n);if(i(t),v({lane:e,state:t}),Do(t)||t?.report?.remains!==!0)return`finished`;await c(No(t.report.wait,d),o)}return`aborted`}function C(e,t){p.set(e,t),v({lane:e,ended:t}),y()===0&&h.splice(0).forEach(e=>e())}function w(e){p.set(e,`running`),S(e).catch(t=>b(e,po(t))).then(t=>C(e,t))}for(let e=1;e<=f;e++)w(e);return{get active(){return y()},failed:g,restart(){if(_())return 0;let e=[...p].filter(([,e])=>e===`finished`).map(([e])=>e);return e.forEach(w),e.length},idle(){return y()===0?Promise.resolve():new Promise(e=>h.push(e))},subscribe(e){return m.add(e),()=>m.delete(e)}}}async function Io({api:e=Y,urls:t,lanes:n=null,onState:r=()=>{},onFailure:i=()=>{},signal:a=null,query:o=()=>({}),sleep:s=uo,retries:c=5,backoffMs:l=xo,idleMs:u=Co}){let d=()=>!!a?.aborted,f=null,p=!1,m=null,h=n?.subscribe(e=>{(e.ended||Number(X(e.state?.counts).translated)>0)&&(p=!0,m?.())})??(()=>{}),g=()=>new Promise(e=>{let t=()=>{m=null,a?.removeEventListener(`abort`,t),e()};m=t,a?.addEventListener(`abort`,t,{once:!0})});try{for(;!d();){p=!1;let{response:m,error:h}=await Po(()=>e.post(t.apply,o()),{retries:c,backoffMs:l,sleep:s,signal:a});if(d())break;if(h)return i({error:h}),{state:f,error:h};if(f=m,r(m),Do(m))break;if(n&&Lo(m)&&n.restart(),m?.report?.remains===!0)await s(No(m.report.wait,u),a);else if(n?.active)p||await g();else break}}finally{h()}return{state:f,error:null}}function Lo(e){let t=e?.run;return t?.status===`running`&&t?.driver===`browser`&&Number(X(e.counts).pending)>0}async function Ro({api:e=Y,url:t,interval:n=wo,onState:r=()=>{},onFailure:i=()=>{},signal:a=null,query:o=()=>({}),sleep:s=uo,retries:c=5,backoffMs:l=xo}){let u=null;for(;!a?.aborted;){let{response:d,error:f}=await Po(()=>e.get(t,o()),{retries:c,backoffMs:l,sleep:s,signal:a});if(a?.aborted)break;if(f)return i({error:f}),{state:u,error:f};if(u=d,r(d),Do(d))break;await s(n,a)}return{state:u,error:null}}async function zo({api:e=Y,url:t,estimate:n=null,onEstimate:r=()=>{},onFailure:i=()=>{},signal:a=null,sleep:o=uo,retries:s=5,backoffMs:c=xo}){let l=n,u=n===null?0:n.next===null?null:Math.max(0,Math.floor(Number(n.next))||0);for(;u!==null&&!a?.aborted;){let{response:n,error:d}=await Po(()=>e.post(t,{from:u}),{retries:s,backoffMs:c,sleep:o,signal:a});if(a?.aborted)break;if(d)return i({error:d}),{estimate:l,error:d};l=n,r(n),u=Number.isInteger(n?.next)?n.next:null}return{estimate:l,error:null}}var Bo=[`pending`,`translating`,`translated`,`applying`,`done`,`skipped`,`failed`],Vo=[`pending`,`translating`,`translated`,`applying`],Ho={pending:`default`,running:`blue`,completed:`green`,completed_with_errors:`orange`,cancelled:`amber`,aborted:`red`},Uo={pending:`default`,translating:`blue`,translated:`sky`,applying:`blue`,done:`green`,skipped:`default`,failed:`red`};function Wo(e){return{pending:__(`Not started`),running:__(`Running`),completed:__(`Completed`),completed_with_errors:__(`Completed with errors`),cancelled:__(`Cancelled`),aborted:__(`Aborted`)}[e]??e}function Go(e){return Ho[e]??`default`}function Ko(e){return{pending:__(`Waiting`),translating:__(`Translating`),translated:__(`Translated, not saved yet`),applying:__(`Saving`),done:__(`Done`),skipped:__(`Skipped`),failed:__(`Failed`)}[e]??e}function qo(e){return Uo[e]??`default`}function Jo(e){return{entry:__(`Entries`),term:__(`Terms`),globals:__(`Global sets`),nav:__(`Navigation`)}[e]??e}function Yo(e=[]){let t=Object.fromEntries((Array.isArray(e)?e:[]).map(e=>[e.handle,e.name]));return e=>t[e]??e}function Q(e,t=void 0){return new Intl.NumberFormat(t).format(Number(e)||0)}function Xo(e,t=void 0){let n=Number(e)||0,r=n>0&&n<.01?{maximumSignificantDigits:2}:{minimumFractionDigits:2,maximumFractionDigits:2};return new Intl.NumberFormat(t,{style:`currency`,currency:`USD`,...r}).format(n)}function Zo(e,t=void 0){let n=Date.parse(e??``);return Number.isNaN(n)?``:new Intl.DateTimeFormat(t,{dateStyle:`medium`,timeStyle:`short`}).format(n)}function Qo(e){let t={...Object.fromEntries(Bo.map(e=>[e,0])),...X(e?.counts)},n=Bo.reduce((e,n)=>e+(Number(t[n])||0),0),r=Vo.reduce((e,n)=>e+(Number(t[n])||0),0);return{counts:t,total:n,finished:n-r,unfinished:r}}function $o(e){let t=e?.run??{},{counts:n,unfinished:r}=Qo(e),i=Do(e),a=t.status===`running`&&!!e?.stalled;return{start:t.status===`pending`,cancel:t.status===`running`,resume:a||[`cancelled`,`aborted`].includes(t.status)&&r>0,retry:i&&n.failed>0,takeOver:a&&t.driver===`queue`}}function es(e,t){let n=[t];return e.skipped>0&&n.push(__n(`:count skipped|:count skipped`,e.skipped)),e.failed>0&&n.push(__n(`:count failed|:count failed`,e.failed)),n.join(`, `)}function ts(e){let t=e?.run??{};if(!Do(e))return null;let{counts:n}=Qo(e),r=es(n,__n(`:count done|:count done`,n.done));return{status:t.status,variant:{completed:`success`,completed_with_errors:`warning`,cancelled:`warning`,aborted:`error`}[t.status],text:{completed:__(`The run is complete: :items.`,{items:r}),completed_with_errors:__(`The run is complete, with errors: :items.`,{items:r}),cancelled:__(`The run was cancelled: :items.`,{items:r}),aborted:__(`The run was stopped: :items.`,{items:r})}[t.status],error:t.error??null}}function ns(e,t=e=>e){return(Array.isArray(e)?e:[]).map(({type:e,site:n,counts:r})=>{let i=Qo({counts:r});return{key:`${e}|${n}`,type:Jo(e),site:t(n),total:i.total,skipped:i.counts.skipped,done:i.counts.done,failed:i.counts.failed}})}function rs(e){let t={excluded_collection:e=>__n(`:count target is in a collection excluded in the settings.|:count targets are in collections excluded in the settings.`,e),site_not_in_collection:e=>__n(`:count target is in a site its collection does not have.|:count targets are in sites their collection does not have.`,e),unauthorized:e=>__n(`:count target is one you may not edit.|:count targets are ones you may not edit.`,e),from_site:e=>__n(`:count target is a navigation in the site it is translated from.|:count targets are navigations in the site they are translated from.`,e)};return Object.entries(X(e?.skipped)).filter(([,e])=>Number(e)>0).map(([e,n])=>({reason:e,text:t[e]?.(Number(n))??__(`:count targets left out: :reason.`,{count:n,reason:e.replaceAll(`_`,` `)})}))}function is(e){let t=(Array.isArray(e?.out_of_scope)?e.out_of_scope:[]).filter(e=>e.reason===`not_localizable`);if(t.length===0)return null;let n=new Set(t.map(e=>e.container));return pa(t.map(e=>n.size>1?`${e.label||e.handle} (${e.container})`:e.label||e.handle).join(`, `),t.length)}function as(e,t=e=>e){let n=t=>Array.isArray(e?.[t])?e[t]:[],r=n(`collections`),i=n(`taxonomies`),a=n(`globals`),o=n(`navs`),s=n(`entry_ids`).length,c=n(`term_ids`).length,l=[],u=(e,t)=>{e.includes(`*`)?l.push(t):e.length>0&&l.push(e.join(`, `))};return u(r,__(`All collections`)),s>0&&l.push(__n(`:count selected entry|:count selected entries`,s)),u(i,__(`All taxonomies`)),c>0&&l.push(__n(`:count selected term|:count selected terms`,c)),u(a,__(`All global sets`)),u(o,__(`All navigation`)),{what:l.join(`, `)||__(`Nothing selected`),sites:n(`sites`).map(t).join(`, `)}}function os(e,t={}){let n=e=>e?X(t)[e]??e:null,r=[{key:`mode`,label:__(`Translate`),value:{missing:__(`Only what is not translated yet`),update:__(`Also update outdated translations`),all:__(`Retranslate everything`),review:__(`Review existing translations`)}[e?.mode]??e?.mode??``},{key:`translator`,label:__(`Model`),value:n(e?.translator)??__(`Default`)},{key:`review`,label:__(`Review`),value:e?.review?n(e?.reviewer)??__(`On`):__(`Off`)},{key:`overwrite_manual`,label:__(`Manual edits`),value:e?.overwrite_manual?__(`Overwritten`):__(`Kept`)},{key:`new_status`,label:__(`New localizations`),value:e?.new_status===`mirror`?__(`Same as origin`):__(`Drafts`)}];return e?.publish_changes&&r.push({key:`publish_changes`,label:__(`Revisions`),value:__(`Changes are published`)}),r}function ss(e,t=0){if(!e)return null;let n=Number.isInteger(e.next)?e.next:null;return{finished:n===null,progress:n===null?null:__(`:done of :total items`,{done:Math.min(n,t),total:t}),segments:Number(e.segments)||0,chars:Number(e.chars)||0,inputTokens:Number(e.input_tokens)||0,outputTokens:Number(e.output_tokens)||0,cost:e.cost===null||e.cost===void 0?null:Number(e.cost)}}function cs(e,t={}){let n=Object.entries(X(e?.usage)).map(([e,n])=>({model:X(t)[e]??e,input:Number(n?.input)||0,output:Number(n?.output)||0,calls:Number(n?.calls)||0}));return{rows:n,input:n.reduce((e,t)=>e+t.input,0),output:n.reduce((e,t)=>e+t.output,0),calls:n.reduce((e,t)=>e+t.calls,0),cost:e?.cost===null||e?.cost===void 0?null:Number(e.cost)}}var ls={current:()=>__(`up to date`),outdated:()=>__(`outdated, not updated in this mode`),untranslated:()=>__(`not translated yet`),manual:()=>__(`edited by hand, kept`),target_changed:()=>__(`edited meanwhile, kept`),not_applicable:()=>__(`empty in the source`),not_requested:()=>__(`not requested`),origin_untranslated:()=>__(`not translated in its source yet`),structure_differs:()=>__(`its structure differs from the source`),no_corrections:()=>__(`reviewed, nothing to correct`)},us={nothing_to_do:()=>__(`Nothing to do.`),dependency_failed:()=>__(`An item it depends on failed.`),unauthorized:()=>__(`You may not edit it.`),target_changed:()=>__(`Edited by someone while it was being translated.`),no_corrections:()=>__(`Reviewed, nothing to correct.`),source_changed:()=>__(`Its source changed, so it is translated again.`)};function ds(e,t=e=>e){let n=Object.entries(X(e?.fields)),r=e=>n.filter(([,t])=>t===e).map(([e])=>e),i=n.filter(([,e])=>e===`applied`||e===`incomplete`).length,a=n.filter(([,e])=>![`applied`,`incomplete`].includes(e)).map(([e,t])=>({handle:e,reason:ls[t]?.()??String(t).replaceAll(`_`,` `)})),o=e?.reason?us[e.reason]?.()??null:null,s=Object.entries(X(e?.corrections)).flatMap(([e,t])=>(Array.isArray(t)?t:[]).map(t=>({...t,handle:e,label:e})));return{index:e?.index,title:e?.title||e?.source_id||``,site:t(e?.target_site),status:e?.status,statusLabel:Ko(e?.status),statusColor:qo(e?.status),editUrl:e?.edit_url??null,applied:i>0?__n(`:count field saved|:count fields saved`,i):null,incomplete:r(`incomplete`),kept:a,reason:o,error:e?.error??null,rootPage:e?.root_page?.edit_url?{title:e.root_page.title||``,url:e.root_page.edit_url}:null,warnings:Array.isArray(e?.warnings)?e.warnings:[],corrected:s.length>0?__n(`:count correction|:count corrections`,s.length):null,corrections:s}}function fs({urls:e,lanes:t=1,onState:n=()=>{},onEstimate:r=()=>{},onFailures:i=()=>{},query:a=()=>({}),api:o=Y,ticker:s=yo}){let c=null,l=()=>{},u=null,d=null,f=[];function p(e){f=[...f,e],i(f)}function m(){c?.abort(),c=null,u=null,d=null}function h(r){m();let h=new AbortController;c=h,l=s.latest(n),f=[],i(f),l(r);let _=r?.run??{},v={onState:l,onFailure:p,signal:h.signal,query:a};if(_.status===`pending`)g(_.estimate??null,h.signal);else if(_.status===`running`&&_.driver===`browser`){u=s.startLanes({api:o,urls:e,lanes:t,...v});let n=s.startApplyLoop({api:o,urls:e,lanes:u,...v}).catch(e=>p({error:po(e)})).finally(()=>{d===n&&(d=null)});d=n}else _.status===`running`&&s.pollState({api:o,url:e.state,...v}).catch(e=>p({error:po(e)}))}async function g(t,n){try{let{error:i}=await s.estimateLoop({api:o,url:e.estimate,estimate:t,onEstimate:r,onFailure:p,signal:n});!i&&!n.aborted&&await _()}catch(e){n.aborted||p({error:po(e)})}}async function _(){let t=c?.signal,n=await o.get(e.state,a());return t&&!t.aborted&&l(n),n}async function v(e,t=!0){let n=await o.post(e,a());return t?h(n):l(n),n}return{follow:h,refresh:_,stop:m,start:()=>v(e.start),cancel:()=>v(e.cancel,!1),resume:()=>v(e.resume),retry:()=>v(e.retry),takeOver:()=>v(e.take_over),get active(){return!!(u&&u.active>0||d)},get failures(){return f}}}var ps=[`idle`,`offer`,`planning`,`working`,`done`,`error`];function ms(){return{reference:null,status:null,phase:`idle`,progress:{total:0,done:0,waiting:0,cancelling:!1},summary:null,snapshot:null,delivered:{},lastChangeAt:0,planReference:null,error:null,request:null,notSaved:[],created:!1,slugKept:!1,push:null}}var hs=null;function gs(){return hs??=Statamic.$pinia.defineStore(`tolk-editor`,{state:()=>({containers:{}}),getters:{phaseOf:e=>t=>e.containers[t]?.phase??`idle`},actions:{container(e){return this.containers[e]??=ms(),this.containers[e]},switched(e,t,n=Date.now()){this.containers[e]={...ms(),reference:t,lastChangeAt:n}},saved(e,t=Date.now()){let n=this.container(e),r=Object.keys(n.delivered);return n.lastChangeAt=Math.max(n.lastChangeAt,t),n.delivered={},r},setPhase(e,t,n=null){if(!ps.includes(t))throw Error(`Unknown editor phase [${t}].`);let r=this.container(e);r.phase=t,r.error=t===`error`?n:null},clearResult(e){Object.assign(this.container(e),{summary:null,snapshot:null,request:null}),this.setPhase(e,`idle`)},forget(e){delete this.containers[e]}}}),hs()}var _s=[`starting`,`running`];function vs(e){return(e?.localizations??[]).filter(e=>e.translate).map(({site:e,name:t,exists:n,summary:r})=>({site:e,name:t,missing:!n,summary:r}))}function ys(e){return(e?.localizations??[]).filter(e=>e.update).map(e=>e.site)}function bs(e){return(e?.origin?.localizations??[]).filter(e=>!e.exists).map(e=>e.site)}function xs(e,t){if(!e)return null;let n=new Map((t?.origin?.localizations??[]).map(e=>[e.site,e])),r=e=>n.get(e)?.name??e,i=e.state,a=(e.sites?.length?e.sites:i?.run?.scope?.sites??[]).map(r),o=Qo(i),s=i?Do(i):!1,c=s?ts(i):null,l=s?(e.missing??[]).filter(e=>n.get(e)?.exists):[];return{sites:a.join(`, `),progress:o,keepOpen:e.phase===`running`&&e.driver===`browser`,failure:e.failures?.length?e.failures.at(-1).error?.message??null:null,error:e.phase===`error`?e.error?.message??null:null,result:c&&{...c,text:Ss(c.status,o.counts),items:(i.items??[]).map(e=>{let t=ds(e,r);return{...t,handle:e.target_site,editUrl:n.get(e.target_site)?.edit_url??t.editUrl}})},reload:l.length>0}}function Ss(e,t){let n=es(t,__n(`:count saved|:count saved`,t.done));return{completed:__(`The translations are done: :items.`,{items:n}),completed_with_errors:__(`The translations are done, with errors: :items.`,{items:n}),cancelled:__(`The translations were cancelled: :items.`,{items:n}),aborted:__(`The translations were stopped: :items.`,{items:n})}[e]}function Cs({store:e=gs,api:t=Y,createFollower:n=fs}={}){let r=new Map;function i(t){return Object.values(e().containers).filter(e=>e.push?.run===t)}function a(e,t){for(let n of i(e))n.push.state=t,Do(t)&&n.push.phase===`running`&&(n.push.phase=`finished`,n.push.cancelling=!1,s(n.reference));Do(t)&&r.delete(e)}function o(e,t){for(let n of i(e))n.push.failures=t}async function s(n){try{let r=await t.get(`editor/status`,{reference:n});for(let t of Object.values(e().containers))t.reference===n&&(t.status=r)}catch(e){e?.status!==403&&Statamic.$toast.error(__(`The translation status could not be updated: :message`,{message:e?.message??``}))}}function c(e,{run:t=null,driver:n=null,sites:r=null,missing:i=[]}){return{phase:e,run:t,driver:n,sites:r,state:null,failures:[],missing:i,cancelling:!1,error:null}}function l(t,n,r,i=null){e().container(t).push=c(`running`,{run:n.run,driver:n.driver,sites:i,missing:r})}function u(e){return e?.push?.run?r.get(e.push.run)??null:null}function d(e,t){let i=r.get(e.run);i||(i=n({urls:e.urls,lanes:e.lanes,onState:t=>a(e.run,t),onFailures:t=>o(e.run,t)}),r.set(e.run,i)),i.follow(t)}async function f(n,{reference:r,sites:i,mode:a,overwriteManual:o=!1,review:s=null,newStatus:u=null}){let f=e().container(n);if(_s.includes(f.push?.phase)||f.reference!==r)return null;let m=bs(f.status).filter(e=>i.includes(e));f.push=c(`starting`,{sites:i,missing:m});try{let c=await t.post(`editor/push`,{reference:r,sites:i,mode:a,overwrite_manual:o,review:s,new_status:u});return e().containers[n]?.reference===r&&l(n,c,m,i),d(c,c.state),c}catch(t){let i=e().containers[n];return i?.reference===r?t?.code===`run_active`&&t.data?.active_run?(i.push=null,await p(n,{active_run:t.data.active_run,origin:i.status?.origin}),null):(i.push={...i.push,phase:`error`,error:po(t)},null):null}}async function p(n,r){let i=r?.active_run,a=e().containers[n];if(!i||!a||a.push?.run===i.run)return;let o=a.reference;l(n,i,bs(r));try{d(i,await t.get(i.urls.state))}catch(t){let r=e().containers[n];r?.reference===o&&r.push?.run===i.run&&(r.push.failures=[{error:po(t)}])}}async function m(t){let n=e().containers[t],r=u(n);if(r){n.push.failures=[];try{r.follow(await r.refresh())}catch(e){n.push.failures=[{error:po(e)}]}}}async function h(t){let n=e().containers[t],r=u(n);if(r){n.push.cancelling=!0;try{await r.cancel()}catch(e){n.push.cancelling=!1,Statamic.$toast.error(e.message)}}}function g(t){let n=e().containers[t];n&&!_s.includes(n.push?.phase)&&(n.push=null)}return{start:f,adopt:p,resume:m,cancel:h,dismiss:g,following:e=>r.has(e)}}var ws=Cs(),Ts=[`planning`,`working`],Es=[`source_changed`,`plan_expired`,`target_missing`],Ds=`edited_in_form`;function Os(e,t,n){return!!t&&!t.pending&&Va(e.values.value[n],t.value)}function ks(e,t,{name:n,registry:r,delivered:i={}}){let a=X(t?.localization?.fields),o=e.originValues?.value??{},s=new Set(r.dirtyHandles(n));for(let[t,n]of Object.entries(a))n?.status===`untranslated`&&Object.hasOwn(o,t)&&!Va(e.values.value[t],o[t])&&s.add(t);return[...s].filter(t=>Object.hasOwn(a,t)&&!Os(e,i[t],t))}function As(e,t){let n=X(t?.localization?.fields);return e.localizedFields.value.filter(e=>Object.hasOwn(n,e))}function js(e,{overwriteManual:t=!1}={}){let n=Object.values(e?.delivered??{}).some(e=>!e.pending&&!e.sync),r=e?.status?.localization?.counts??{};return n||(r.current??0)>0||t&&(r.manual??0)>0}function Ms(e){let t=new Set([...e?.delivered??[],...Object.keys(e?.skipped??{}),...e?.unchanged??[]]);return(e?.planned??[]).filter(e=>!t.has(e))}function Ns(e){let t=e?.status?.localization;return e?.created&&!e.slugKept&&!t?.translate_slug?t?.origin_slug??null:null}function Ps(e){let t=e?.snapshot?.fields;return t?Object.entries(t).some(([t,n])=>Qa(n,e.delivered?.[t])):!1}function Fs(e,t){return __n(`:fields was changed after the translation and was kept.|:fields were changed after the translation and were kept.`,e.length,{fields:va(e,t)})}function Is(e){return Object.entries(X(e))}function Ls(e){return Object.fromEntries(Is(e).filter(([,e])=>e===Ds).map(([e])=>[e,`edited`]))}function Rs(e){return Object.fromEntries(Is(e).filter(([,e])=>e!==Ds))}function zs(e,t){return e.replace===!0&&(e.fields??[]).includes(t)}function Bs(e,{reference:t,skip:n}){return{reference:t,mode:e.mode,overwrite_manual:e.overwriteManual,fields:e.fields,skip:n,translator:e.translator,review:e.review,reviewer:e.reviewer}}function Vs(e,{reference:t,handles:n,values:r}){return{reference:t,values:Object.fromEntries(n.map(e=>[e,r[e]])),overwrite_manual:e.overwriteManual,reviewer:e.reviewer}}function Hs(e,t){let n=t.snapshot,r=!1;if(!n||n.reference!==e.reference)return e;for(let[i,a]of Object.entries(n.fields))Qa(a,t.delivered[i])&&(e.fields[i]=a,r=!0);return r&&(e.dirty=n.dirty),e}function Us({store:e=gs,registry:t=Ra,api:n=Y,concurrency:r=()=>Statamic.$config.get(`tolk.concurrency`),run:i=go,fill:a=eo,undoFill:o=to,keepSlug:s=no,recheckSlug:c=ro}={}){let l=new Map,u=new Set;function d(e){let t=l.get(e);t&&(l.delete(e),t.controller.abort())}function f(t){let n=l.get(t),r=e().containers[t];n&&!n.controller.signal.aborted&&r?.phase===`working`&&(n.controller.abort(),r.progress={...r.progress,cancelling:!0})}async function p(o,u,{continuing:d=!1}={}){let f=e(),p=t.context(o),m=f.container(o);if(!p||Ts.includes(m.phase)||l.has(o)||!p.reference.value)return null;let h=p.reference.value,g={},_=new AbortController,v=()=>l.get(o)?.token===g,y=()=>v()&&f.containers[o]===m&&p.reference.value===h,b=()=>f.containers[o]?.lastChangeAt??0,x=Ns(m),S=u.kind===`review`,C=S?u.fields??As(p,m.status):u.fields,w=$a(p,C??Object.keys(p.values.value),m.delivered),T=Z(p.values.value),E=S?[]:ks(p,m.status,{name:o,registry:t,delivered:m.delivered}).filter(e=>!zs(u,e)),[D,ee]=S?[`editor/review`,Vs(u,{reference:h,handles:C,values:T})]:[`editor/plan`,Bs(u,{reference:h,skip:E})];d&&Hs(w,m),l.set(o,{token:g,controller:_}),Object.assign(m,{request:u,snapshot:w,summary:null,notSaved:[],planReference:h,progress:ms().progress}),f.setPhase(o,`planning`);let te=x?s(p,x,{reference:h,lastChangeAt:b,active:v}):null;te?.catch(()=>{});try{let e=await n.post(D,ee);if(!y())return null;if(te){if(await te,!y())return null;m.slugKept=!0}f.setPhase(o,`working`),m.progress={...ms().progress,total:e.units?.length??0};let t={reference:h,plan:e.plan,lastChangeAt:b,planValues:T,delivered:m.delivered,active:v},s=await i({api:n,plan:e,concurrency:r(),signal:_.signal,finishing:v,onFields:e=>a(p,e,t),onProgress:e=>{y()&&(m.progress={...e,cancelling:_.signal.aborted})}});if(te&&s.delivered.length&&y()&&await c(p,x,{reference:h,active:v}),!y())return null;let l={...s,kind:u.kind,reviewer:e.reviewer??null,plan:e.plan,planned:Array.isArray(e.fields)?e.fields:[],skipped:{...Ls(e.skipped),...s.skipped},planSkipped:Rs(e.skipped),warnings:[...new Set([...Array.isArray(e.warnings)?e.warnings:[],...s.warnings??[]])],cancelled:_.signal.aborted};return m.summary=l,f.setPhase(o,s.stopped?`error`:`done`,s.stopped),l}catch(e){return y()&&f.setPhase(o,`error`,po(e,__(`Something went wrong.`))),null}finally{v()&&l.delete(o)}}function m(e,{mode:t=`missing`,fields:n=null,overwriteManual:r=!1,translator:i=null,review:a=null,reviewer:o=null,replace:s=!1}={}){return p(e,{kind:`translate`,mode:t,fields:n,overwriteManual:r,translator:i,review:a,reviewer:o,replace:s})}function h(e,{fields:t=null,overwriteManual:n=!1,reviewer:r=null}={}){return p(e,{kind:`review`,fields:t,overwriteManual:n,reviewer:r})}function g(t){let n=e().containers[t];if(!n?.request||Ts.includes(n.phase))return null;let r=n.summary?Ms(n.summary):n.request.fields;return r!==null&&r.length===0?(e().setPhase(t,`done`),null):p(t,{...n.request,fields:r},{continuing:!0})}async function _(n){let r=e(),i=r.containers[n],a=t.context(n);if(!a||!i?.snapshot||Ts.includes(i.phase)||u.has(n))return null;u.add(n);try{let e=await o(a,i.snapshot,i.delivered,{registry:t});return r.containers[n]===i&&r.clearResult(n),e}finally{u.delete(n)}}return{translate:m,review:h,retry:g,cancel:f,abort:d,undo:_,running:e=>l.has(e)}}var Ws=Us(),Gs=`tolk-banner`;function Ks(e){return typeof e==`string`&&e.startsWith(`term::`)}function qs(e,t){return[`idle`,`done`,`error`].includes(e)&&!!t?.localization&&!t?.setup}function Js(e){let t=e?.reference?.value;return e?.name===`base`&&typeof t==`string`&&(t.startsWith(`entry::`)||Ks(t))&&Statamic.$config.get(`tolk.multisite`)===!0&&Statamic.$permissions.has(`translate content`)}function Ys({store:e=gs,abort:t=e=>Ws.abort(e)}={}){let n=new Map,r=!1;function i(e=Statamic.$events){r||(r=!0,e.$on(`publish-container-created`,a),e.$on(`publish-container-destroyed`,o))}function a(r){let i=null;t(r.name),Js(r)&&(e().forget(r.name),i=r.pushComponent(Gs,{props:{containerName:r.name}})),n.set(r.name,[...n.get(r.name)??[],i])}function o({name:e}){let[t,...r]=n.get(e)??[];t?.destroy(),r.length?n.set(e,r):n.delete(e)}return{listen:i,pushed:e=>(n.get(e)??[]).filter(Boolean).length}}var Xs=Ys();function Zs({name:e,ctx:t,store:n=gs(),registry:r=Ra,loadStatus:i=e=>Zi(`editor/status`,{reference:e}),now:a=Date.now,settleMs:o=600,onSwitch:s=e=>Ws.abort(e),onStatus:c=(e,t)=>ws.adopt(e,t)}){let l=I(null),u=!!t.reference.value&&n.container(e).reference===t.reference.value;r.attachContext(e,t);let d=r=>t.reference.value===r&&n.containers[e]?.reference===r;async function f(r){if(l.value=null,!t.readOnly?.value)try{let t=await i(r);d(r)&&(n.container(e).status=t,c(e,t))}catch(e){d(r)&&e?.status!==403&&(l.value=e)}}function p(t){let i=a();s(e),n.switched(e,t,i),r.refreshClean(e),setTimeout(()=>{n.containers[e]?.lastChangeAt===i&&d(t)&&r.refreshClean(e)},o),f(t)}return{failure:l,stop:bn(()=>[t.reference.value,t.site.value],([t],r)=>{if(t){if(r===void 0&&u){n.container(e).status===null&&f(t);return}p(t)}},{immediate:!0,flush:`post`})}}function Qs(){let e=!1,t=!1,n=Dt({open:!1,show(){e?t=!0:n.open=!0},hide(){t=!1,e||(n.open=!1)},dismissed(){e=!0},closed(r){r||(e=!1,n.open=!1,t&&(t=!1,nt(()=>n.open=!0)))}});return n}var $s={class:`space-y-2 ps-6`,"data-tolk-push":``},ec={class:`sr-only`,"aria-live":`polite`,"data-tolk-push-announcement":``},tc={key:0,class:`flex flex-wrap items-center gap-2 pt-1`,"data-tolk-push-actions":``},nc={key:2,class:`space-y-2`,"data-tolk-push-phase":`running`},rc={class:`flex flex-wrap items-center justify-between gap-2`},ic={key:1,class:`flex flex-wrap items-center gap-2`,"data-tolk-push-failure":``},ac=[`data-tolk-push-status`],oc={class:`space-y-1`},sc=[`data-tolk-push-item`,`data-tolk-push-item-status`],cc=[`href`],lc=[`href`],uc={class:`flex flex-wrap gap-2`},dc={key:4,class:`flex flex-wrap items-center gap-2`,"data-tolk-push-phase":`error`},fc={class:`space-y-6`},pc={class:`space-y-3`},mc=[`data-tolk-push-site`],hc={class:`flex items-center justify-end gap-3 pt-3 pb-1`},gc={__name:`OriginPush`,props:{containerName:{type:String,required:!0},reference:{type:String,required:!0},origin:{type:Object,required:!0},status:{type:Object,default:null},dirty:{type:Boolean,default:!1}},setup(e){let t=e,n=gs(),r=O(()=>n.containers[t.containerName]?.push??null),i=O(()=>xs(r.value,t.status)),a=O(()=>_s.includes(r.value?.phase)),o=O(()=>!a.value&&(t.origin.translateInto||t.origin.update)),s=O(()=>vs(t.origin)),c=Qs(),l=I([]),u=I(`draft`),d=I(!1),f=O(()=>s.value.some(e=>e.missing&&l.value.includes(e.site))),p=O(()=>Ks(t.reference));function h(){l.value=s.value.map(e=>e.site),u.value=t.status?.defaults?.new_status===`mirror`?`mirror`:`draft`,d.value=t.status?.defaults?.review===!0,c.show()}function g(e,t){l.value=t?[...new Set([...l.value,e])]:l.value.filter(t=>t!==e)}function _(){c.hide(),ws.start(t.containerName,{reference:t.reference,sites:s.value.map(e=>e.site).filter(e=>l.value.includes(e)),mode:`missing`,review:d.value,newStatus:f.value?u.value:null})}function v(){ws.start(t.containerName,{reference:t.reference,sites:ys(t.origin),mode:`update`})}let y=O(()=>{switch(r.value?.phase){case`starting`:return __(`Starting the translation…`);case`running`:return i.value.failure?__(`The translations stopped: :message`,{message:i.value.failure}):__(`Translating into :sites…`,{sites:i.value.sites});case`error`:return i.value?.error??``;default:return i.value?.result?.text??``}});function b(){window.location.reload()}return(t,n)=>(F(),j(`div`,$s,[M(`p`,ec,R(y.value),1),o.value?(F(),j(`div`,tc,[e.origin.translateInto?(F(),k(z(V),{key:0,variant:`primary`,size:`sm`,disabled:e.dirty,"data-tolk-action":`translate-into`,onClick:h},{default:B(()=>[N(R(t.__(`Translate into…`)),1)]),_:1},8,[`disabled`])):A(``,!0),e.origin.update?(F(),k(z(V),{key:1,size:`sm`,disabled:e.dirty,"data-tolk-action":`update-translations`,onClick:v},{default:B(()=>[N(R(t.__(`Update translations`)),1)]),_:1},8,[`disabled`])):A(``,!0),e.dirty?(F(),k(z(U),{key:2,"data-tolk-save-first":``},{default:B(()=>[N(R(p.value?t.__(`Save first: the translations are made from the saved term.`):t.__(`Save first: the translations are made from the saved entry.`)),1)]),_:1})):A(``,!0)])):A(``,!0),r.value?.phase===`starting`?(F(),k(z(J),{key:1,as:`p`,"data-tolk-push-phase":`starting`},{default:B(()=>[N(R(t.__(`Starting the translation…`)),1)]),_:1})):A(``,!0),r.value?.phase===`running`?(F(),j(`div`,nc,[M(`div`,rc,[r.value.cancelling?(F(),k(z(J),{key:0},{default:B(()=>[N(R(t.__(`Cancelling. Translations already being saved are still saved.`)),1)]),_:1})):(F(),k(z(J),{key:1},{default:B(()=>[N(R(t.__(`Translating into :sites…`,{sites:i.value.sites})),1)]),_:1})),P(z(V),{size:`sm`,variant:`ghost`,disabled:r.value.cancelling,"data-tolk-action":`push-cancel`,onClick:n[0]||=t=>z(ws).cancel(e.containerName)},{default:B(()=>[N(R(t.__(`Cancel`)),1)]),_:1},8,[`disabled`])]),P(Fa,{value:i.value.progress.finished,max:i.value.progress.total,label:t.__(`Translation progress`)},null,8,[`value`,`max`,`label`]),P(z(U),{"data-tolk-push-progress":``},{default:B(()=>[N(R(t.__(`:finished of :total translations finished.`,{finished:i.value.progress.finished,total:i.value.progress.total})),1)]),_:1}),i.value.keepOpen?(F(),k(z(U),{key:0},{default:B(()=>[N(R(p.value?t.__(`Keep this page open until the translations are saved. If you leave, they continue when you open this term again.`):t.__(`Keep this page open until the translations are saved. If you leave, they continue when you open this entry again.`)),1)]),_:1})):A(``,!0),i.value.failure?(F(),j(`div`,ic,[P(z(G),{name:`warning-diamond`,class:`size-4 shrink-0 text-red-600`,"aria-hidden":`true`}),P(z(J),{variant:`danger`},{default:B(()=>[N(R(t.__(`The translations stopped: :message`,{message:i.value.failure})),1)]),_:1}),P(z(V),{size:`sm`,"data-tolk-action":`push-resume`,onClick:n[1]||=t=>z(ws).resume(e.containerName)},{default:B(()=>[N(R(t.__(`Try again`)),1)]),_:1})])):A(``,!0)])):A(``,!0),i.value?.result?(F(),j(`div`,{key:3,class:`space-y-2`,"data-tolk-push-result":``,"data-tolk-push-status":i.value.result.status},[P(z(J),{as:`p`},{default:B(()=>[N(R(i.value.result.text),1)]),_:1}),i.value.result.error?(F(),k(z(J),{key:0,as:`p`,variant:`danger`},{default:B(()=>[N(R(i.value.result.error),1)]),_:1})):A(``,!0),M(`ul`,oc,[(F(!0),j(m,null,L(i.value.result.items,e=>(F(),j(`li`,{key:e.index,class:`flex flex-wrap items-center gap-2`,"data-tolk-push-item":e.handle,"data-tolk-push-item-status":e.status},[e.editUrl?(F(),j(`a`,{key:0,href:e.editUrl,class:`text-sm font-medium underline`},R(e.site),9,cc)):(F(),k(z(J),{key:1,variant:`strong`},{default:B(()=>[N(R(e.site),1)]),_:2},1024)),P(z(Pn),{text:e.statusLabel,color:e.statusColor},null,8,[`text`,`color`]),e.error||e.reason?(F(),k(z(U),{key:2},{default:B(()=>[N(R(e.error??e.reason)+` `,1),e.rootPage?(F(),j(`a`,{key:0,href:e.rootPage.url,class:`font-medium underline`,"data-tolk-root-page":``},R(t.__(`Open :title`,{title:e.rootPage.title})),9,lc)):A(``,!0)]),_:2},1024)):A(``,!0)],8,sc))),128))]),i.value.reload?(F(),k(z(U),{key:1},{default:B(()=>[N(R(t.__(`Reload the page to see the new localizations in the Sites panel.`)),1)]),_:1})):A(``,!0),M(`div`,uc,[i.value.reload?(F(),k(z(V),{key:0,size:`sm`,variant:`primary`,"data-tolk-action":`reload`,onClick:b},{default:B(()=>[N(R(t.__(`Reload`)),1)]),_:1})):A(``,!0),P(z(V),{size:`sm`,variant:`ghost`,"data-tolk-action":`push-close`,onClick:n[2]||=t=>z(ws).dismiss(e.containerName)},{default:B(()=>[N(R(t.__(`Close`)),1)]),_:1})])],8,ac)):A(``,!0),r.value?.phase===`error`?(F(),j(`div`,dc,[P(z(G),{name:`warning-diamond`,class:`size-4 shrink-0 text-red-600`,"aria-hidden":`true`}),P(z(J),{variant:`danger`,"data-tolk-push-error":``},{default:B(()=>[N(R(i.value.error),1)]),_:1}),P(z(V),{size:`sm`,variant:`ghost`,"data-tolk-action":`push-close`,onClick:n[3]||=t=>z(ws).dismiss(e.containerName)},{default:B(()=>[N(R(t.__(`Close`)),1)]),_:1})])):A(``,!0),z(c).open?(F(),k(z(Ur),{key:5,open:``,title:t.__(`Translate into other languages`),icon:`dictionary-language-book`,"data-tolk-push-modal":``,onDismissed:n[7]||=e=>z(c).dismissed(),"onUpdate:open":n[8]||=e=>z(c).closed(e)},{footer:B(()=>[M(`div`,hc,[P(z(V),{variant:`ghost`,text:t.__(`Cancel`),"data-tolk-push-action":`close`,onClick:n[6]||=e=>z(c).hide()},null,8,[`text`]),P(z(V),{variant:`primary`,text:t.__(`Translate`),disabled:l.value.length===0,"data-tolk-push-action":`translate`,onClick:_},null,8,[`text`,`disabled`])])]),default:B(()=>[M(`div`,fc,[P(z(J),{as:`p`},{default:B(()=>[N(R(p.value?t.__(`The saved term is translated and saved in each language you choose. This form stays as it is.`):t.__(`The saved entry is translated and saved in each language you choose. This form stays as it is.`)),1)]),_:1}),M(`div`,pc,[(F(!0),j(m,null,L(s.value,e=>(F(),j(`div`,{key:e.site,"data-tolk-push-site":e.site},[P(z(Vn),{"model-value":l.value.includes(e.site),label:e.name,description:e.summary,"onUpdate:modelValue":t=>g(e.site,t)},null,8,[`model-value`,`label`,`description`,`onUpdate:modelValue`])],8,mc))),128))]),f.value?(F(),k(z(yr),{key:0,id:`tolk-push-status`,label:t.__(`New localizations`)},{default:B(()=>[P(z(li),{modelValue:u.value,"onUpdate:modelValue":n[4]||=e=>u.value=e,appearance:`inline`,"data-tolk-push-new-status":``},{default:B(()=>[P(z(ci),{value:`draft`,label:t.__(`Drafts`)},null,8,[`label`]),P(z(ci),{value:`mirror`,label:t.__(`Same as origin`)},null,8,[`label`])]),_:1},8,[`modelValue`])]),_:1},8,[`label`])):A(``,!0),P(z(Vn),{modelValue:d.value,"onUpdate:modelValue":n[5]||=e=>d.value=e,label:t.__(`Review after translating`),description:t.__(`A second model checks each translation and corrects it before it is saved.`)},null,8,[`modelValue`,`label`,`description`])])]),_:1},8,[`title`])):A(``,!0)]))}},_c=`tolk.offer`,vc=null;function yc(e,t,{preferences:n=()=>Statamic.$preferences,toast:r=()=>Statamic.$toast}={}){let i=()=>new Promise(r=>r(n().set(e,t))).then(()=>!0,()=>(r().error(__(`Your choice could not be saved.`)),!1)),a=vc?vc.then(i):i();return vc=a,a.then(()=>{vc===a&&(vc=null)}),a}function bc(e=Statamic.$preferences){return e.get(_c,!0)!==!1}function xc(e,t=Statamic.$preferences){return e?.offer===!0&&bc(t)&&la(e).localization?.translate===!0}function Sc(e){let t=la(e);return{count:e?.localization?.counts?.untranslated??0,source:t.localization?.source?.name??``,target:t.localization?.target?.name??``,translator:t.translator}}var Cc=350;function wc({store:e=gs,registry:t=Ra,translations:n=Ws,preferences:r=()=>Statamic.$preferences,toast:i=()=>Statamic.$toast,openAfterMs:a=Cc,clock:o=()=>Date.now(),wait:s=(e,t)=>setTimeout(e,t)}={}){let c=null,l=!1;function u(e=Statamic.$events){l||(l=!0,e.$on(`localization.created`,d))}function d(n){let r=n?.container?.name,i=t.context(r)?.reference?.value;if(r!==`base`||!i)return;m();let s=e(),l=o()+a;if(f(s,r,i,l))return;let u=bn(()=>{let e=s.containers[r];return[e?.reference,e?.status]},()=>{f(s,r,i,l)&&(u(),c===u&&(c=null))});c=u}function f(e,n,r,i){let a=e.containers[n];return a?.reference===r?(a.created=!0,a.status!==null&&(p(e,n,r,i),!0)):t.context(n)?.reference?.value!==r}function p(e,t,n,i){let a=i-o();if(a>0){s(()=>p(e,t,n,i),a);return}let c=e.containers[t];c?.reference===n&&c.phase===`idle`&&xc(c.status,r())&&e.setPhase(t,`offer`)}function m(){c?.(),c=null}function h(t,n){let a=e();return a.phaseOf(t)===`offer`&&(n&&yc(_c,!1,{preferences:r,toast:i}),a.setPhase(t,`idle`),!0)}function g(e,{dontOfferAgain:t=!1}={}){return h(e,t)?n.translate(e,{mode:`missing`}):null}function _(e,{dontOfferAgain:t=!1}={}){h(e,t)}return{listen:u,created:d,accept:g,decline:_,waiting:e=>e===`base`&&c!==null}}var Tc=wc(),Ec={class:`space-y-1`},Dc={class:`flex items-center justify-end gap-3 pt-3 pb-1`},Oc={__name:`TranslateOffer`,props:{containerName:{type:String,required:!0},status:{type:Object,default:null},open:{type:Boolean,default:!1}},setup(e){let t=e,n=I(!1),r=O(()=>Sc(t.status));bn(()=>t.open,e=>{e&&(n.value=!1)});function i(){Tc.accept(t.containerName,{dontOfferAgain:n.value})}function a(){Tc.decline(t.containerName,{dontOfferAgain:n.value})}return(t,o)=>(F(),k(z(Ur),{open:e.open,title:t.__(`Translate this entry?`),icon:`dictionary-language-book`,"data-tolk-offer":``,onDismissed:a},{footer:B(()=>[M(`div`,Dc,[P(z(V),{variant:`ghost`,text:t.__(`Not now`),"data-tolk-offer-action":`decline`,onClick:a},null,8,[`text`]),P(z(V),{variant:`primary`,text:t.__(`Translate`),"data-tolk-offer-action":`translate`,onClick:i},null,8,[`text`])])]),default:B(()=>[M(`div`,Ec,[P(z(J),{as:`p`,"data-tolk-offer-text":``},{default:B(()=>[N(R(t.__n(`Translate :count field from :source into :target. Nothing is saved until you press Save.|Translate :count fields from :source into :target. Nothing is saved until you press Save.`,r.value.count,{source:r.value.source,target:r.value.target})),1)]),_:1}),r.value.translator?(F(),k(z(U),{key:0,"data-tolk-offer-model":``},{default:B(()=>[N(R(t.__(`Model: :model`,{model:z(_a)(r.value.translator)})),1)]),_:1})):A(``,!0)]),P(z(Vn),{modelValue:n.value,"onUpdate:modelValue":o[0]||=e=>n.value=e,label:t.__(`Don't offer again`)},null,8,[`modelValue`,`label`])]),_:1},8,[`open`,`title`]))}},kc=`tolk.editor.translator`,Ac=`tolk.editor.reviewer`;function jc(e=Statamic.$preferences,t=kc){let n=e.get(t,null);return typeof n==`string`&&n!==``?n:null}function Mc(e,{fakeEngine:t=!1,defaultModel:n=null,extra:r=[]}={}){let i=[];for(let r of Object.values(X(e)).flat())(r.configured||t)&&i.push({value:r.value,label:r.value===n?__(`:model (default)`,{model:r.label}):r.label});for(let e of r)e&&!i.some(t=>t.value===e)&&i.push({value:e,label:e===n?__(`:model (default)`,{model:e}):e});return i}function Nc(e,{remembered:t=null,defaultModel:n=null}={}){let r=t=>t!==null&&e.some(e=>e.value===t);return r(t)?t:r(n)?n:e[0]?.value??null}function Pc(e,t){return e&&e!==t?e:null}function Fc(e,t,n){return n?e||null:Pc(e,t)}function Ic({model:e=null,defaultModel:t=null,retranslate:n=!1,overwriteManual:r=!1,review:i=null,reviewer:a=null,defaultReviewer:o=null}={}){let s=Pc(e,t);return{mode:n?`all`:`update`,overwriteManual:r,translator:s,review:i,reviewer:i===!0?Fc(a,o,s):null}}function Lc({reviewer:e=null,defaultReviewer:t=null,overwriteManual:n=!1}={}){return{overwriteManual:n,reviewer:Pc(e,t)}}function Rc(e){let t=e?.localization?.counts??{};return{markCurrent:(t.attention??0)+(t.untracked??0)>0,protect:(t.current??0)+(t.outdated??0)>0}}function zc(e,t){return e===0?__(`No field needed changing.`):t?__n(`:count field is now protected from updates.|:count fields are now protected from updates.`,e):__n(`:count field marked as up to date.|:count fields marked as up to date.`,e)}function Bc({store:e=gs,registry:t=Ra,api:n=Y,translations:r=Ws,preferences:i=()=>Statamic.$preferences,toast:a=()=>Statamic.$toast}={}){let o=null;function s(){return o??=n.get(`models`).catch(e=>{throw o=null,e}),o}function c(e,t){t!==jc(i(),e)&&yc(e,t,{preferences:i,toast:a})}function l(t,n={}){let i=Ic(n);return Ts.includes(e().phaseOf(t))?null:(c(kc,i.translator),i.review===!0&&c(Ac,Pc(n.reviewer,n.defaultReviewer)),r.translate(t,i))}function u(t,n={}){let i=Lc(n);return Ts.includes(e().phaseOf(t))?null:(c(Ac,i.reviewer),r.review(t,i))}async function d(r,{protect:i=!1}={}){let o=e().containers[r],s=t.context(r)?.reference?.value??null;if(!o||!s||o.reference!==s||Ts.includes(o.phase))return null;try{let{baselined:e=0,...t}=await n.post(`editor/baseline`,{reference:s,protect:i});return o.status=t,a().success(zc(e,i)),e}catch(e){return a().error(e?.message||__(`Something went wrong.`)),null}}function f(e){return yc(_c,e,{preferences:i,toast:a})}return{loadModels:s,translate:l,review:u,baseline:d,setOffers:f}}var Vc=Bc(),Hc={class:`space-y-4`},Uc={class:`space-y-3`},Wc={class:`grid gap-4 sm:grid-cols-2`},Gc={class:`space-y-3`},Kc={key:0,class:`space-y-3 border-t border-gray-200 pt-4 dark:border-gray-700`,"aria-labelledby":`tolk-options-state-heading`,"data-tolk-options-state":``},qc={key:0,class:`flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4`},Jc={key:1,class:`flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4`},Yc={key:1,class:`flex items-start justify-between gap-4 border-t border-gray-200 pt-4 dark:border-gray-700`,"data-tolk-options-offer":``},Xc={class:`space-y-0.5`},Zc={class:`flex items-center justify-end gap-3 pt-3 pb-1`},Qc={__name:`TranslateOptions`,props:{containerName:{type:String,required:!0},status:{type:Object,default:null}},setup(e){let t=e,n=gs(),r=O(()=>Ks(n.containers[t.containerName]?.reference)),i=Qs(),a=I(!1),o=I(null),s=I(null),c=I(null),l=I(null),u=I(!1),d=I(!1),f=I(!1),p=I(!0),h=I(!1),g=!!Statamic.$config.get(`tolk.settingsUrl`),_=O(()=>s.value?.defaults?.translator??t.status?.defaults?.translator??null),v=O(()=>s.value?.defaults?.reviewer??null),y=O(()=>jc()),b=O(()=>jc(Statamic.$preferences,Ac));function x(e,n,r){return Mc(s.value?.catalog,{fakeEngine:t.status?.defaults?.fake_engine===!0,defaultModel:e,extra:g?[e,n,r]:[e]})}let S=O(()=>x(_.value,y.value,c.value)),C=O(()=>x(v.value,b.value,l.value)),w=O(()=>js(n.containers[t.containerName],{overwriteManual:f.value})),T=O(()=>u.value||w.value),E=O(()=>Rc(t.status)),D=O(()=>t.status?.offer===!0);async function ee(){d.value=!1,f.value=!1,u.value=t.status?.defaults?.review===!0,o.value=null,p.value=bc(),i.show(),a.value=!0;try{s.value=await Vc.loadModels()}catch(e){o.value=e.message}finally{a.value=!1}c.value=Nc(S.value,{remembered:y.value,defaultModel:_.value}),l.value=Nc(C.value,{remembered:b.value,defaultModel:v.value})}function te(){i.hide(),Vc.translate(t.containerName,{model:c.value,defaultModel:_.value,retranslate:d.value,overwriteManual:f.value,review:u.value,reviewer:l.value,defaultReviewer:v.value})}function ne(){i.hide(),Vc.review(t.containerName,{reviewer:l.value,defaultReviewer:v.value,overwriteManual:f.value})}async function re(e){h.value=!0;try{await Vc.baseline(t.containerName,{protect:e})!==null&&i.hide()}finally{h.value=!1}}async function ie(e){p.value=e,await Vc.setOffers(e)||(p.value=!e)}return(e,t)=>(F(),j(m,null,[P(z(V),{size:`sm`,variant:`ghost`,icon:`sliders-horizontal`,text:e.__(`Options`),"data-tolk-action":`options`,onClick:ee},null,8,[`text`]),z(i).open?(F(),k(z(Ur),{key:0,open:``,title:e.__(`Translation options`),icon:`sliders-horizontal`,"data-tolk-options":``,onDismissed:t[8]||=e=>z(i).dismissed(),"onUpdate:open":t[9]||=e=>z(i).closed(e)},{footer:B(()=>[M(`div`,Zc,[P(z(V),{variant:`ghost`,text:e.__(`Close`),"data-tolk-options-action":`close`,onClick:t[7]||=e=>z(i).hide()},null,8,[`text`]),w.value?(F(),k(z(V),{key:0,text:e.__(`Review`),disabled:a.value||!l.value,"data-tolk-options-action":`review`,onClick:ne},null,8,[`text`,`disabled`])):A(``,!0),P(z(V),{variant:`primary`,text:e.__(`Translate`),disabled:a.value||!c.value,"data-tolk-options-action":`translate`,onClick:te},null,8,[`text`,`disabled`])])]),default:B(()=>[M(`div`,Hc,[M(`div`,Uc,[M(`div`,Wc,[P(z(yr),{id:`tolk-options-model`,label:e.__(`Model`)},{default:B(()=>[P(z(Wn),{id:`tolk-options-model`,modelValue:c.value,"onUpdate:modelValue":t[0]||=e=>c.value=e,options:S.value,taggable:z(g),disabled:a.value,placeholder:a.value?e.__(`Loading…`):e.__(`Choose a model`),"data-tolk-options-model":``},null,8,[`modelValue`,`options`,`taggable`,`disabled`,`placeholder`])]),_:1},8,[`label`]),P(z(yr),{id:`tolk-options-reviewer`,label:e.__(`Reviewer`),"data-tolk-options-review":``},{default:B(()=>[P(z(Wn),{id:`tolk-options-reviewer`,modelValue:l.value,"onUpdate:modelValue":t[1]||=e=>l.value=e,options:C.value,taggable:z(g),disabled:a.value||!T.value,placeholder:a.value?e.__(`Loading…`):e.__(`Choose a model`),"data-tolk-options-reviewer":``},null,8,[`modelValue`,`options`,`taggable`,`disabled`,`placeholder`])]),_:1},8,[`label`])]),z(g)?(F(),k(z(U),{key:0},{default:B(()=>[N(R(e.__(`You may also type a model outside the list, as provider:model.`)),1)]),_:1})):A(``,!0),o.value?(F(),k(z(J),{key:1,as:`p`,variant:`danger`,"data-tolk-options-failure":``},{default:B(()=>[N(R(e.__(`The models could not be loaded: :message`,{message:o.value})),1)]),_:1})):A(``,!0)]),M(`div`,Gc,[P(z(Vn),{modelValue:d.value,"onUpdate:modelValue":t[2]||=e=>d.value=e,label:e.__(`Retranslate everything`),description:e.__(`Also translates the fields that are up to date again.`)},null,8,[`modelValue`,`label`,`description`]),P(z(Vn),{modelValue:f.value,"onUpdate:modelValue":t[3]||=e=>f.value=e,label:e.__(`Overwrite manual edits`),description:e.__(`Also replaces the text of fields edited by hand.`)},null,8,[`modelValue`,`label`,`description`]),P(z(Vn),{modelValue:u.value,"onUpdate:modelValue":t[4]||=e=>u.value=e,label:e.__(`Review after translating`),description:e.__(`The reviewer checks the new translation and corrects it.`)},null,8,[`modelValue`,`label`,`description`])]),E.value.markCurrent||E.value.protect?(F(),j(`section`,Kc,[P(z(W),{id:`tolk-options-state-heading`,level:2,text:e.__(`Translation status`)},null,8,[`text`]),E.value.markCurrent?(F(),j(`div`,qc,[P(z(U),null,{default:B(()=>[N(R(e.__(`Records that the fields edited by hand match the current source, so a later change to the source is flagged.`)),1)]),_:1}),P(z(V),{size:`sm`,class:`shrink-0 self-start sm:self-auto`,text:e.__(`Mark manual fields as up to date`),disabled:h.value,"data-tolk-action":`mark-current`,onClick:t[5]||=e=>re(!1)},null,8,[`text`,`disabled`])])):A(``,!0),E.value.protect?(F(),j(`div`,Jc,[P(z(U),null,{default:B(()=>[N(R(e.__(`Treats the translated fields as edited by hand, so Translate and Update leave them alone.`)),1)]),_:1}),P(z(V),{size:`sm`,class:`shrink-0 self-start sm:self-auto`,text:r.value?e.__(`Protect this term from updates`):e.__(`Protect this entry from updates`),disabled:h.value,"data-tolk-action":`protect`,onClick:t[6]||=e=>re(!0)},null,8,[`text`,`disabled`])])):A(``,!0)])):A(``,!0),D.value&&!r.value?(F(),j(`div`,Yc,[M(`div`,Xc,[P(z(Er),{for:`tolk-options-offer`,text:e.__(`Offer to translate new localizations`)},null,8,[`text`]),P(z(U),{id:`tolk-options-offer-description`},{default:B(()=>[N(R(e.__(`Asks whether to translate each localization you create. Only for your account.`)),1)]),_:1})]),P(z(yi),{id:`tolk-options-offer`,"model-value":p.value,"aria-describedby":`tolk-options-offer-description`,"onUpdate:modelValue":ie},null,8,[`model-value`])])):A(``,!0)])]),_:1},8,[`title`])):A(``,!0)],64))}},$c=`localizable`,el={ok:{color:`green`,icon:`checkmark`,class:`text-green-600`},warning:{color:`amber`,icon:`alert-warning-exclamation-mark`,class:`text-amber-600`},error:{color:`red`,icon:`warning-diamond`,class:`text-red-600`}};function tl(e){return`tolk-audit-${e}`}function nl(e){return e?`${e}#${tl($c)}`:null}function rl(e){return{ok:__(`OK`),warning:__(`Warning`),error:__(`Error`)}[e]??e}function $(e){return{label:rl(e),...el[e]??el.warning}}function il(e){let t=(Array.isArray(e)?e:[]).flatMap(e=>e.items??[]),n=t.filter(e=>e.level===`error`).length,r=t.filter(e=>e.level===`warning`).length;if(n===0&&r===0)return{level:`ok`,text:__(`Everything is set up. Tolk found nothing to change.`)};let i=[n>0?__n(`:count error|:count errors`,n):null,r>0?__n(`:count warning|:count warnings`,r):null].filter(Boolean);return{level:n>0?`error`:`warning`,text:__(`The audit found :problems. Errors keep Tolk from translating; warnings leave something untranslated or slower than it could be.`,{problems:i.join(`, `)})}}function al(e,t){return e?.id===`localizable`?t?__(`A text field that is not localizable is shared by every site, so Tolk does not translate it. Choose the fields that hold text in each language and make them localizable.`):__(`A text field that is not localizable is shared by every site, so Tolk does not translate it. Someone who may edit the Tolk settings and blueprints can make them localizable here, or with php please tolk:doctor --fix-localizable.`):e?.detail??``}function ol(e){return typeof e?.namespace==`string`&&typeof e?.blueprint==`string`&&Array.isArray(e?.fields)}function sl(e){return`${e.namespace}|${e.blueprint}`}function cl(e){let t=Array.isArray(e?.fields)?e.fields:[];return{editable:t.filter(e=>!e.fieldset),imported:t.filter(e=>!!e.fieldset)}}function ll(e){return e.label&&e.label!==e.handle?`${e.label} (${e.handle})`:e.handle}function ul(e){return __(`From the fieldset :fieldset: make it localizable in the fieldset, which changes every blueprint that imports it.`,{fieldset:e.fieldset})}function dl(e,t){let n=new Set(Array.isArray(t)?t:[]);return cl(e).editable.map(e=>e.handle).filter(e=>n.has(e))}function fl(e,t){let n=cl(e).editable.filter(e=>t.includes(e.handle)).map(ll).join(`, `);return __n(`This changes the blueprint file of :blueprint: :fields becomes localizable, so each site keeps its own value and Tolk translates it. Existing localizations keep the value they inherit until they are translated or edited.|This changes the blueprint file of :blueprint: :fields become localizable, so each site keeps its own value and Tolk translates them. Existing localizations keep the values they inherit until they are translated or edited.`,t.length,{blueprint:e.name,fields:n})}function pl(e){return e>0?__n(`:count field is now localizable.|:count fields are now localizable.`,e):__(`Nothing changed: the fields were already localizable.`)}function ml(e,t){return __n(`:fields was not saved because it was hidden when you saved. Show it and save again.|:fields were not saved because they were hidden when you saved. Show them and save again.`,e.length,{fields:va(e,t)})}function hl({PipelineStopped:e,store:t=gs,registry:n=Ra,api:r=Y,now:i=Date.now,settleMs:a=600}){let o=!1;function s(e=Statamic.$hooks){if(!o){o=!0;for(let t of[`entry`,`term`])e.on(`${t}.saving`,c),e.on(`${t}.saved`,l)}}function c(n,r){if(Ts.includes(t().phaseOf(`base`))){Statamic.$toast.error(__(`A translation is in progress. Wait for it to finish, or cancel it.`)),r(new e);return}n()}async function l(e,t,n){try{await u(n)}catch(e){console.error(e)}finally{e()}}async function u(e){let o=t(),s=o.containers[Ia],c=gl(e,s);if(!s?.reference||c!==s.reference)return;let l=i(),u=o.saved(Ia,l);n.refreshClean(Ia),setTimeout(()=>{let e=o.containers[Ia];e?.lastChangeAt===l&&e.reference===c&&n.refreshClean(Ia)},a),(s.phase===`done`||s.phase===`error`)&&o.clearResult(Ia);try{let{not_saved:e=[],...t}=await r.post(`editor/confirm`,{reference:c,delivered:u}),n=o.containers[Ia];n?.reference===c&&(n.status=t,n.notSaved=e),e.length&&Statamic.$toast.error(ml(e,t),{duration:1e4})}catch(e){e?.status!==403&&Statamic.$toast.error(__(`The translation status could not be updated: :message`,{message:e?.message??``}))}}return{listen:s,saving:c,saved:l}}function gl(e,t){let n=e?.response?.data?.data;return typeof n?.reference==`string`?n.reference:typeof n?.id==`string`&&t?.reference?.startsWith(`term::${n.id}::`)?t.reference:e?.reference??null}var _l=`[data-tolk-offer], [data-tolk-options], [data-tolk-changes], [data-tolk-push-modal]`,vl=`[data-tolk-action]:not([disabled])`,yl=`[data-tolk-focus]`,bl=`button:not([disabled]), [href], [tabindex="0"]`;function xl(e,{modals:t=null,doc:n=globalThis.document,wait:r=setTimeout,delays:i=[0,400]}={}){let a=null;function o(){let r=n?.activeElement,i=e();return!!(r&&i&&(i.contains(r)||t&&r.closest?.(t)))}function s(){return!n.activeElement||n.activeElement===n.body||n.activeElement===a}function c(){let t=e();if(!t?.isConnected||!s())return;let n=t.querySelector(vl),r=n??t.querySelector(yl)??t.querySelector(bl);r?.focus(),a=n?null:r}return{holds:o,restore:c,changing(){o()&&i.forEach(e=>r(c,e))}}}var Sl={class:`sr-only`,"aria-live":`polite`,"data-tolk-announcement":``},Cl={key:0,class:`flex items-center gap-2`},wl={key:0,class:`space-y-2`,"data-tolk-localization":``},Tl={class:`flex flex-wrap items-center justify-between gap-x-6 gap-y-3`},El={class:`flex flex-wrap items-center gap-2`},Dl={key:0,class:`flex flex-wrap items-center gap-2`,"data-tolk-actions":``},Ol=[`href`],kl={key:1,class:`flex items-center gap-2`,tabindex:`-1`,"data-tolk-focus":``,"data-tolk-phase":`planning`},Al={key:2,class:`space-y-2`,"data-tolk-phase":`working`},jl={class:`flex flex-wrap items-center justify-between gap-2`},Ml={key:3,class:`space-y-1`,"data-tolk-phase":`error`},Nl={class:`flex items-center gap-2`},Pl={key:4,class:`space-y-1`,"data-tolk-summary":``},Fl={key:1,class:`flex flex-wrap items-center gap-2`},Il={key:5,class:`flex flex-wrap gap-2`},Ll={key:6,class:`flex items-center gap-2`,"data-tolk-not-saved":``},Rl={key:7,class:`space-y-2`,"data-tolk-origin":``},zl={class:`flex items-center gap-2`},Bl={class:`grid grid-cols-[auto_auto_minmax(0,1fr)] items-center gap-x-3 gap-y-1.5 ps-6`},Vl=[`data-tolk-site`],Hl=[`href`],Ul=[`href`],Wl={__name:`EditorBanner`,props:{containerName:{type:String,required:!0}},setup(e){let t=e,n=ei(),r=gs(),i=t.containerName,{failure:a,stop:o}=Zs({name:i,ctx:n,store:r});lt(o);let s=O(()=>r.containers[i]??null),c=O(()=>s.value?.phase??`idle`),l=nl(Statamic.$config.get(`tolk.auditUrl`)),u=O(()=>la(s.value?.status??null)),d=O(()=>ya(s.value?.summary??null,s.value?.status??null)),f=O(()=>Ps(s.value)),p=O(()=>Es.includes(s.value?.error?.code)),h=O(()=>s.value?.notSaved?.length?ml(s.value.notSaved,s.value.status):null),g=O(()=>qs(c.value,u.value)),_=O(()=>js(s.value)),v=O(()=>{let e=s.value?.request;return e?.kind===`translate`&&e.fields?.length===1?va(e.fields,s.value.status):null}),y=O(()=>{let e=u.value.localization?.target?.name??``;return s.value?.progress?.cancelling?__(`Cancelling. Fields already on their way are still filled in.`):s.value?.request?.kind===`review`?__(`Reviewing the translation…`):v.value?__(`Translating :field into :site…`,{field:v.value,site:e}):__(`Translating into :site…`,{site:e})}),b=O(()=>{switch(c.value){case`planning`:return __(`Preparing the translation…`);case`working`:return y.value;case`error`:return s.value?.error?.message??``;case`done`:return[d.value?.translated,d.value?.reviewed].filter(Boolean).join(` `);default:return``}}),x=Qs();bn(()=>s.value?.summary,()=>x.hide());let S=O(()=>!!u.value.origin?.upToDate&&!u.value.localization&&!s.value?.push),C=O(()=>!n.readOnly.value&&(a.value!==null||u.value.visible&&!S.value)),w=O(()=>Ra.dirtyHandles(i).length>0),T=Statamic.$config.get(`tolk.settingsUrl`),E=O(()=>Ks(s.value?.reference)),D=I(null),ee=xl(()=>D.value?.$el??null,{modals:_l});bn([c,()=>s.value?.push?.phase],()=>ee.changing()),bn(C,e=>{!e&&ee.holds()&&nt(()=>document.getElementById(`content-card`)?.focus())});function te(e){Ws.translate(i,{mode:e})}async function ne(){let e=ee.holds(),t=await Ws.undo(i);e&&(await nt(),ee.restore()),t?.kept.length&&Statamic.$toast.info(Fs(t.kept,s.value?.status))}return(e,t)=>{let n=Nt(`tooltip`);return C.value?(F(),k(z(H),{key:0,ref_key:`card`,ref:D,class:`mb-6 space-y-3`,"data-tolk-banner":``},{default:B(()=>[M(`p`,Sl,R(b.value),1),z(a)?(F(),j(`div`,Cl,[P(z(G),{name:`warning-diamond`,class:`size-4 shrink-0 text-red-600`,"aria-hidden":`true`}),P(z(J),{variant:`danger`},{default:B(()=>[N(R(e.__(`The translation status could not be loaded: :message`,{message:z(a).message})),1)]),_:1})])):(F(),j(m,{key:1},[u.value.localization?(F(),j(`div`,wl,[M(`div`,Tl,[M(`div`,El,[P(z(G),{name:`dictionary-language-book`,class:`size-4 shrink-0 text-gray-500`,"aria-hidden":`true`}),P(z(J),null,{default:B(()=>[N(R(u.value.localization.lead),1)]),_:1}),(F(!0),j(m,null,L(u.value.localization.parts,e=>En((F(),k(z(Pn),{key:e.key,text:e.text,color:z(aa)(e.key),tabindex:`0`,"data-tolk-part":e.key},null,8,[`text`,`color`,`data-tolk-part`])),[[n,e.description]])),128))]),g.value?(F(),j(`div`,Dl,[c.value===`idle`?(F(),j(m,{key:0},[u.value.localization.translate?(F(),k(z(V),{key:0,variant:`primary`,size:`sm`,"data-tolk-action":`translate`,onClick:t[0]||=e=>te(`missing`)},{default:B(()=>[N(R(e.__(`Translate`)),1)]),_:1})):A(``,!0),u.value.localization.update?(F(),k(z(V),{key:1,size:`sm`,"data-tolk-action":`update`,onClick:t[1]||=e=>te(`update`)},{default:B(()=>[N(R(e.__(`Update`)),1)]),_:1})):A(``,!0)],64)):A(``,!0),_.value?(F(),k(z(V),{key:1,size:`sm`,"data-tolk-action":`review`,onClick:t[2]||=e=>z(Ws).review(z(i))},{default:B(()=>[N(R(e.__(`Review`)),1)]),_:1})):A(``,!0),P(Qc,{"container-name":z(i),status:s.value.status},null,8,[`container-name`,`status`])])):A(``,!0)]),u.value.localization.incompleteNote?(F(),k(z(U),{key:0},{default:B(()=>[N(R(u.value.localization.incompleteNote),1)]),_:1})):A(``,!0),u.value.localization.hint?(F(),k(z(U),{key:1,"data-tolk-not-localizable":``},{default:B(()=>[N(R(u.value.localization.hint)+` `,1),z(l)?(F(),j(`a`,{key:0,href:z(l),"data-tolk-audit-link":``},R(e.__(`Open the setup audit`)),9,Ol)):(F(),j(m,{key:1},[N(R(e.__(`Run php please tolk:doctor for details.`)),1)],64))]),_:1})):A(``,!0)])):A(``,!0),c.value===`planning`?(F(),j(`div`,kl,[P(z(J),null,{default:B(()=>[N(R(e.__(`Preparing the translation…`)),1)]),_:1})])):A(``,!0),c.value===`working`?(F(),j(`div`,Al,[M(`div`,jl,[P(z(J),{"data-tolk-working-field":v.value?``:null},{default:B(()=>[N(R(y.value),1)]),_:1},8,[`data-tolk-working-field`]),P(z(V),{size:`sm`,variant:`ghost`,disabled:s.value.progress.cancelling,"data-tolk-action":`cancel`,onClick:t[3]||=e=>z(Ws).cancel(z(i))},{default:B(()=>[N(R(e.__(`Cancel`)),1)]),_:1},8,[`disabled`])]),P(Fa,{value:s.value.progress.done,max:s.value.progress.total,label:s.value.request?.kind===`review`?e.__(`Review progress`):e.__(`Translation progress`)},null,8,[`value`,`max`,`label`]),s.value.progress.waiting?(F(),k(z(U),{key:0},{default:B(()=>[N(R(e.__(`The provider asked to wait. Trying again shortly.`)),1)]),_:1})):A(``,!0)])):A(``,!0),c.value===`error`?(F(),j(`div`,Ml,[M(`div`,Nl,[P(z(G),{name:`warning-diamond`,class:`size-4 shrink-0 text-red-600`,"aria-hidden":`true`}),P(z(J),{variant:`danger`,"data-tolk-error":``},{default:B(()=>[N(R(s.value.error?.message),1)]),_:1})])])):A(``,!0),d.value&&(c.value===`done`||c.value===`error`)?(F(),j(`div`,Pl,[d.value.translated?(F(),k(z(J),{key:0,as:`p`,"data-tolk-summary-translated":``},{default:B(()=>[N(R(d.value.translated),1)]),_:1})):A(``,!0),d.value.reviewed?(F(),j(`div`,Fl,[P(z(J),{"data-tolk-summary-reviewed":``},{default:B(()=>[N(R(d.value.reviewed),1)]),_:1}),d.value.corrections?(F(),k(z(V),{key:0,size:`sm`,variant:`ghost`,"data-tolk-action":`view-changes`,onClick:t[4]||=e=>z(x).show()},{default:B(()=>[N(R(e.__(`View changes`)),1)]),_:1})):A(``,!0)])):A(``,!0),d.value.reviewSkipped?(F(),k(z(U),{key:2,"data-tolk-summary-review-skipped":``},{default:B(()=>[N(R(d.value.reviewSkipped),1)]),_:1})):A(``,!0),d.value.cancelled?(F(),k(z(U),{key:3},{default:B(()=>[N(R(d.value.cancelled),1)]),_:1})):A(``,!0),d.value.incomplete?(F(),k(z(U),{key:4,"data-tolk-summary-incomplete":``},{default:B(()=>[N(R(d.value.incomplete),1)]),_:1})):A(``,!0),d.value.edited?(F(),k(z(U),{key:5,"data-tolk-summary-edited":``},{default:B(()=>[N(R(d.value.edited),1)]),_:1})):A(``,!0),d.value.manual?(F(),k(z(U),{key:6,"data-tolk-summary-manual":``},{default:B(()=>[N(R(d.value.manual),1)]),_:1})):A(``,!0),d.value.failed?(F(),k(z(U),{key:7,"data-tolk-summary-failed":``},{default:B(()=>[N(R(d.value.failed),1)]),_:1})):A(``,!0),d.value.unsaved?(F(),k(z(U),{key:8,"data-tolk-summary-unsaved":``},{default:B(()=>[N(R(d.value.unsaved),1)]),_:1})):A(``,!0)])):A(``,!0),c.value===`error`||c.value===`done`&&f.value?(F(),j(`div`,Il,[c.value===`error`?(F(),k(z(V),{key:0,size:`sm`,variant:`primary`,"data-tolk-action":`retry`,onClick:t[5]||=e=>z(Ws).retry(z(i))},{default:B(()=>[N(R(p.value?e.__(`Start again`):e.__(`Retry`)),1)]),_:1})):A(``,!0),f.value?(F(),k(z(V),{key:1,size:`sm`,"data-tolk-action":`undo`,onClick:ne},{default:B(()=>[N(R(e.__(`Undo`)),1)]),_:1})):A(``,!0)])):A(``,!0),h.value?(F(),j(`div`,Ll,[P(z(G),{name:`warning-diamond`,class:`size-4 shrink-0 text-amber-600`,"aria-hidden":`true`}),P(z(J),null,{default:B(()=>[N(R(h.value),1)]),_:1})])):A(``,!0),u.value.origin?(F(),j(`div`,Rl,[M(`div`,zl,[P(z(G),{name:`dictionary-language-book`,class:`size-4 shrink-0 text-gray-500`,"aria-hidden":`true`}),P(z(J),null,{default:B(()=>[N(R(E.value?e.__(`Translations of this term:`):e.__(`Translations of this entry:`)),1)]),_:1})]),M(`ul`,Bl,[(F(!0),j(m,null,L(u.value.origin.localizations,e=>(F(),j(`li`,{key:e.site,class:`col-span-3 grid grid-cols-subgrid items-center`,"data-tolk-site":e.site},[e.editUrl?(F(),j(`a`,{key:0,href:e.editUrl,class:`text-sm font-medium underline`},R(e.name),9,Hl)):(F(),k(z(J),{key:1,variant:`strong`},{default:B(()=>[N(R(e.name),1)]),_:2},1024)),P(z(Pn),{text:e.label,color:e.color,class:`justify-self-start`},null,8,[`text`,`color`]),e.exists&&e.summary?(F(),k(z(U),{key:2},{default:B(()=>[N(R(e.summary),1)]),_:2},1024)):A(``,!0)],8,Vl))),128))]),P(gc,{"container-name":z(i),reference:s.value.reference,origin:u.value.origin,status:s.value.status,dirty:w.value},null,8,[`container-name`,`reference`,`origin`,`status`,`dirty`])])):A(``,!0),u.value.localization?(F(),k(Oc,{key:8,"container-name":z(i),status:s.value.status,open:c.value===`offer`},null,8,[`container-name`,`status`,`open`])):A(``,!0),z(x).open?(F(),k(Na,{key:9,modal:z(x),corrections:s.value.summary?.corrections??[],reviewer:s.value.summary?.reviewer??null},null,8,[`modal`,`corrections`,`reviewer`])):A(``,!0),u.value.setup?(F(),k(z(U),{key:10,"data-tolk-setup":``},{default:B(()=>[N(R(e.__(`Translation is not set up yet.`))+` `,1),z(T)?(F(),j(`a`,{key:0,href:z(T)},R(e.__(`Open the Tolk settings`)),9,Ul)):(F(),j(m,{key:1},[N(R(e.__(`Ask an administrator to configure a provider in the Tolk settings.`)),1)],64))]),_:1})):A(``,!0)],64))]),_:1},512)):A(``,!0)}}},Gl={class:`flex items-center justify-end gap-3 pt-3 pb-1`},Kl={__name:`TranslateFieldConfirm`,emits:[`confirm`,`cancel`],setup(e,{emit:t}){let n=t,r=Qs(),i=!1;pt(()=>r.show());function a(e){i||(i=!0,n(e))}function o(e){r.hide(),a(e)}function s(e){r.closed(e),e||a(`cancel`)}return(e,t)=>z(r).open?(F(),k(z(Ur),{key:0,open:``,title:e.__(`Translate from origin`),"data-tolk-field-confirm":``,onDismissed:t[2]||=e=>z(r).dismissed(),"onUpdate:open":s},{footer:B(()=>[M(`div`,Gl,[P(z(V),{variant:`ghost`,text:e.__(`Cancel`),"data-tolk-field-confirm-action":`cancel`,onClick:t[0]||=e=>o(`cancel`)},null,8,[`text`]),P(z(V),{variant:`primary`,text:e.__(`Translate`),"data-tolk-field-confirm-action":`translate`,onClick:t[1]||=e=>o(`confirm`)},null,8,[`text`])])]),default:B(()=>[P(z(J),{as:`p`},{default:B(()=>[N(R(e.__(`The current content of this field will be replaced.`)),1)]),_:1})]),_:1},8,[`title`])):A(``,!0)}},ql=`tolk-translate-field-confirm`;function Jl(e,t){if(e===t)return!0;if(Array.isArray(e)||Array.isArray(t))return Array.isArray(e)&&Array.isArray(t)&&e.length===t.length&&e.every((e,n)=>Jl(e,t[n]));if(e===null||t===null||typeof e!=`object`||typeof t!=`object`)return!1;let n=Object.keys(e);return n.length===Object.keys(t).length&&n.every(n=>Object.hasOwn(t,n)&&Jl(e[n],t[n]))}function Yl({registry:e=Ra,store:t=gs,translations:n=Ws,fieldActions:r=()=>Statamic.$fieldActions,config:i=()=>Statamic.$config,permissions:a=()=>Statamic.$permissions,toast:o=()=>Statamic.$toast,components:s=()=>Statamic.$components,doc:c=()=>globalThis.document,wait:l=setTimeout}={}){let u=!1;function d({vm:n,fieldPathPrefix:r,handle:i,config:o,isReadOnly:s}){if(r||s||!o?.localizable||!a().has(`translate content`)||n&&n.publishContainer?.name!==`base`||e.others().length>0)return!1;let c=e.base(),l=t().containers[Ia],u=l?.status;if(!c||c.readOnly?.value||!u?.localization||l.reference!==c.reference.value)return!1;let d=X(u.localization.fields)[i];return!ca(u)&&!Ts.includes(l.phase)&&Object.hasOwn(c.originValues?.value??{},i)&&!!d&&d.status!==`not_applicable`}async function f({handle:r,value:i}){let a=e.base(),s=t();if(!a||!Jl(i,a.values.value[r])){o().error(Ks(s.containers.base?.reference)?__(`This field is not part of the term being translated.`):__(`This field is not part of the entry being translated.`));return}if(Ts.includes(s.phaseOf(`base`))||n.running(`base`)){o().error(__(`A translation is already running. Try again when it has finished.`));return}let c=s.containers[Ia],l=await n.translate(Ia,{mode:`all`,fields:[r],overwriteManual:!0,replace:!0});if(s.containers.base===c){if(c.phase===`error`){o().error(c.error?.message||__(`Something went wrong.`));return}if(l&&!l.cancelled&&!l.delivered.includes(r)){let e=ya(l,c.status);o().error(e.failed??e.edited??e.translated)}}}function p(e){return[...c()?.querySelectorAll(`label[for]`)??[]].find(t=>t.getAttribute(`for`)===`field_${e}`)?.closest(`[data-ui-input-group]`)?.querySelector(`[data-ui-field-header] [data-ui-dropdown-trigger]`)??null}function m(){let e=c()?.querySelector(`[data-tolk-banner]`);return e?.querySelector(`[data-tolk-action="cancel"]`)??e?.querySelector(`[data-tolk-focus]`)??null}function h(e){for(let t of[0,400])l(()=>{let t=c()?.activeElement;(!t||t===c().body)&&e()?.focus()},t)}function g(e){let t=s().append(ql,{props:{}});t.on(`confirm`,()=>{t.destroy(),f(e).catch(()=>o().error(__(`Something went wrong.`))),h(()=>m()??p(e.handle))}),t.on(`cancel`,()=>{t.destroy(),h(()=>p(e.handle))})}let _={get title(){return __(`Translate from origin`)},visible:d,run:g};function v(){if(!u){u=!0;for(let e of i().get(`tolk.fieldtypes`)??[])r().add(`${e}-fieldtype`,_)}}return{register:v,action:_,visible:d,run:g}}var Xl=Yl(),{Fieldtype:Zl,IndexFieldtype:Ql,FieldtypeMixin:$l,HasActionsMixin:eu,HasInputOptionsMixin:tu,HasPreferencesMixin:nu,IndexFieldtypeMixin:ru,InlineEditForm:iu,DateFormatter:au,NumberFormatter:ou,ItemActions:su,RelatedItem:cu,RestoreRevision:lu,RevisionHistory:uu,RevisionPreview:du,SaveButtonOptions:fu,SortableList:pu,requireElevatedSession:mu,requireElevatedSessionIf:hu,clone:gu,debounce:_u,deepClone:vu,resetValuesFromResponse:yu}=__STATAMIC__.core,bu=`automatic`;function xu(e){return typeof e==`string`&&e.trim()!==``?e.trim():null}function Su(e){return/^[^\s:]+:\S+$/.test(e)}function Cu(e){return{quality:__(`Quality`),fast:__(`Fast`)}[e]??null}function wu(e,t){return{value:e,label:e,note:X(t)[e.split(`:`)[0]]?.[0]?.configured===!1?__(`No API key`):__(`Custom model`),disabled:!1}}function Tu(e,t){let n=[{value:bu,label:e?.automatic||__(`Automatic`),note:null,disabled:!1}],r=e?.fake_engine===!0;for(let t of Object.values(X(e?.catalog)).flat())n.push({value:t.value,label:t.label,note:t.configured?Cu(t.tier):__(`No API key`),disabled:!t.configured&&!r});let i=xu(t);return i&&!n.some(e=>e.value===i)&&n.push(wu(i,e?.catalog)),n}function Eu(e,t){if(e===null||e===`automatic`)return null;let n=t.find(t=>t.value===e);if(n)return n.disabled?void 0:n.value;let r=typeof e==`string`?e.trim():``;return Su(r)?r:void 0}var Du=[`data-tolk-model-note`],Ou={__name:`ModelSelect`,props:Zl.props,emits:Zl.emits,setup(e,{expose:t,emit:n}){let r=n,i=e,{expose:a,isReadOnly:o,update:s}=Zl.use(r,i),c=O(()=>Tu(i.meta,i.value)),l=O(()=>xu(i.value)??`automatic`);function u(e){let t=Eu(e,c.value);t!==void 0&&t!==xu(i.value)&&s(t)}return t(a),(e,t)=>(F(),k(z(Wn),{id:e.id,"model-value":l.value,options:c.value,"read-only":z(o),placeholder:e.__(`Choose a model`),taggable:``,"data-tolk-model-select":``,"onUpdate:modelValue":u},{option:B(e=>[M(`span`,{class:it([`truncate`,{"opacity-50":e.disabled}])},R(e.label),3),e.note?(F(),j(`span`,{key:0,class:it([`ms-auto shrink-0 text-xs text-gray-500 dark:text-gray-400`,{"opacity-50":e.disabled}]),"data-tolk-model-note":e.value},R(e.note),11,Du)):A(``,!0)]),_:1},8,[`id`,`model-value`,`options`,`read-only`,`placeholder`]))}};function ku(e){let t=e?.fake_engine===!0;return(Array.isArray(e?.providers)?e.providers:[]).map(e=>{let n=e.configured===!0;return{provider:e.provider,label:e.label,badge:Au(n),source:ju(e.source),hint:n?null:Mu(e.env),testable:n||t}})}function Au(e){return e?{text:__(`Configured`),color:`green`}:{text:__(`No API key`),color:`default`}}function ju(e){return{ai:__(`The key comes from config/ai.php, which Tolk shares with the rest of the site.`),addon:__(`The key is Tolk's own, from the addon's config.`)}[e]??null}function Mu(e){return e?.ai?__(`Add :variable to the .env file, or :override to give Tolk a key of its own.`,{variable:e.ai,override:e.addon}):null}function Nu(e){if(e?.ok!==!0)return{ok:!1,text:e?.error||__(`The test failed.`)};let t={model:e.label||e.model,ms:e.latency_ms};return{ok:!0,text:e.fake?__(`The fake engine answered for :model in :ms ms, without calling the provider.`,t):__(`:model answered in :ms ms.`,t)}}async function Pu(e,t=Y){try{return await t.post(`providers/test`,{provider:e})}catch(e){return{ok:!1,error:e.message}}}var Fu={class:`divide-y divide-gray-200 dark:divide-gray-700`,"data-tolk-providers":``},Iu=[`data-tolk-provider`],Lu={class:`flex flex-wrap items-center gap-2`},Ru={__name:`ProvidersStatus`,props:Zl.props,emits:Zl.emits,setup(e,{expose:t,emit:n}){let r=n,i=e,{expose:a}=Zl.use(r,i),o=O(()=>ku(i.meta)),s=Dt({}),c=Dt({});async function l(e){s[e]=!0,c[e]=null;try{c[e]=Nu(await Pu(e))}finally{s[e]=!1}}return t(a),(e,t)=>(F(),j(`div`,Fu,[(F(!0),j(m,null,L(o.value,t=>(F(),j(`div`,{key:t.provider,class:`space-y-1 py-3 first:pt-0 last:pb-0`,"data-tolk-provider":t.provider},[M(`div`,Lu,[P(z(J),{variant:`strong`},{default:B(()=>[N(R(t.label),1)]),_:2},1024),P(z(Pn),{text:t.badge.text,color:t.badge.color,"data-tolk-provider-status":``},null,8,[`text`,`color`]),t.testable?(F(),k(z(V),{key:0,class:`ms-auto`,size:`sm`,text:e.__(`Test connection`),loading:!!s[t.provider],disabled:!!s[t.provider],"data-tolk-provider-test":``,onClick:e=>l(t.provider)},null,8,[`text`,`loading`,`disabled`,`onClick`])):A(``,!0)]),t.source?(F(),k(z(U),{key:0},{default:B(()=>[N(R(t.source),1)]),_:2},1024)):A(``,!0),t.hint?(F(),k(z(U),{key:1},{default:B(()=>[N(R(t.hint),1)]),_:2},1024)):A(``,!0),c[t.provider]?(F(),k(z(J),{key:2,variant:c[t.provider].ok?`success`:`danger`,"data-tolk-provider-result":c[t.provider].ok?`ok`:`failed`},{default:B(()=>[N(R(c[t.provider].text),1)]),_:2},1032,[`variant`,`data-tolk-provider-result`])):A(``,!0)],8,Iu))),128))]))}},{asMap:zu}=Y,Bu=`glossary`;function Vu(e,t=Y){let n=zu(e),r=Object.hasOwn(n,`translator_model`)?{model:n.translator_model||null}:{};return t.post(`site-profile/generate`,r)}function Hu(e){return typeof e==`string`&&e.trim()!==``}function Uu(e){return String(e??``).normalize(`NFKD`).toLowerCase().replace(/\p{Mn}+/gu,``).replace(/[\s\p{Z}]+/gu,` `).trim()}function Wu(e){let t=e?.site;return Array.isArray(t)?t.length===0:!t}function Gu(e){return new Set((Array.isArray(e)?e:[]).filter(Wu).map(e=>Uu(e?.term)).filter(e=>e!==``))}function Ku(e,t,n={}){let r=Gu(t);return(Array.isArray(e)?e:[]).map(e=>{let t=r.has(Uu(e));return{term:e,inGlossary:t,chosen:!t&&n[e]!==!0}})}function qu(){return Array.from(crypto.getRandomValues(new Uint8Array(12)),e=>`abcdefghijklmnopqrstuvwxyz0123456789`[e%36]).join(``)}function Ju(e){return JSON.parse(JSON.stringify(e??{}))}function Yu(e,t,n,r=qu){let i=Array.isArray(t)?t:[],a=zu(n),o=Gu(i),s={...zu(a.existing)},c=[];for(let t of e){let e=Uu(t);if(e===``||o.has(e))continue;let n=r();o.add(e),s[n]=Ju(zu(a.new)),c.push({...Ju(zu(a.defaults)),term:t.trim(),do_not_translate:!0,_id:n})}return{rows:[...i,...c],meta:{...a,existing:s},added:c.map(e=>e.term)}}var Xu={class:`space-y-3`,"data-tolk-site-profile":``},Zu={key:0,class:`flex flex-wrap items-center gap-3`},Qu={key:3,class:`space-y-2`,"data-tolk-site-profile-terms":``},$u={class:`space-y-1`},ed=[`data-tolk-site-profile-term`],td={class:`flex flex-wrap items-center gap-3`},nd={class:`list-disc ps-5 text-sm`},rd=[`data-tolk-site-profile-term`],id={__name:`SiteProfile`,props:Zl.props,emits:Zl.emits,setup(e,{expose:t,emit:n}){let r=n,i=e,{expose:a,isReadOnly:o,update:s}=Zl.use(r,i),c=ei(),l=I(!1),u=I(!1),d=I(null),f=I(null),p=I(null),h=Dt({}),g=O(()=>X(c?.values.value)),_=O(()=>!o.value&&Object.hasOwn(g.value,`glossary`)&&Object.hasOwn(X(c?.meta.value),`glossary`)),v=O(()=>Ku(f.value?.terms,g.value[Bu],h)),y=O(()=>v.value.filter(e=>e.chosen).map(e=>e.term));function b(){Hu(i.value)?u.value=!0:x()}async function x(){u.value=!1,l.value=!0,d.value=null;try{let e=await Vu(g.value);s(e.profile),f.value={label:e.label||e.model,terms:Array.isArray(e.terms)?e.terms:[]},p.value=null,Object.keys(h).forEach(e=>delete h[e])}catch(e){d.value=e.message}finally{l.value=!1}}function S(e,t){h[e]=!t}function C(){let e=Yu(y.value,g.value[Bu],c.meta.value[Bu]);c.setFieldMeta(Bu,e.meta),c.setFieldValue(Bu,e.rows),p.value=e.added.length}return t(a),(e,t)=>(F(),j(`div`,Xu,[P(z(Pi),{id:e.id,name:e.handle,"model-value":e.value,"read-only":z(o),rows:8,"onUpdate:modelValue":z(s)},null,8,[`id`,`name`,`model-value`,`read-only`,`onUpdate:modelValue`]),z(o)?A(``,!0):(F(),j(`div`,Zu,[P(z(V),{size:`sm`,icon:`ai-sparks`,text:e.__(`Generate`),loading:l.value,disabled:l.value,"data-tolk-site-profile-generate":``,onClick:b},null,8,[`text`,`loading`,`disabled`]),P(z(U),null,{default:B(()=>[N(R(e.__(`Has the translator write a profile from the content of the default site. Check it before you save.`)),1)]),_:1})])),d.value?(F(),k(z(J),{key:1,variant:`danger`,"data-tolk-site-profile-error":``},{default:B(()=>[N(R(d.value),1)]),_:1})):A(``,!0),f.value?(F(),k(z(U),{key:2,"data-tolk-site-profile-written":``},{default:B(()=>[N(R(e.__(`Written by :model. It is not saved until you save the settings.`,{model:f.value.label})),1)]),_:1})):A(``,!0),v.value.length?(F(),j(`div`,Qu,[P(z(J),{variant:`strong`},{default:B(()=>[N(R(e.__(`Names to keep untranslated`)),1)]),_:1}),_.value?(F(),j(m,{key:0},[M(`div`,$u,[(F(!0),j(m,null,L(v.value,t=>(F(),j(`div`,{key:t.term,"data-tolk-site-profile-term":t.term},[P(z(Vn),{"model-value":t.chosen,label:t.term,description:t.inGlossary?e.__(`Already in the glossary`):null,disabled:t.inGlossary,"onUpdate:modelValue":e=>S(t.term,e)},null,8,[`model-value`,`label`,`description`,`disabled`,`onUpdate:modelValue`])],8,ed))),128))]),M(`div`,td,[P(z(V),{size:`sm`,text:e.__(`Add to glossary`),disabled:y.value.length===0,"data-tolk-site-profile-add":``,onClick:C},null,8,[`text`,`disabled`]),p.value===null?A(``,!0):(F(),k(z(U),{key:0,"data-tolk-site-profile-added":``},{default:B(()=>[N(R(e.__n(`Added :count name to the glossary with Do not translate on. Save the settings to keep it.|Added :count names to the glossary with Do not translate on. Save the settings to keep them.`,p.value)),1)]),_:1}))])],64)):(F(),j(m,{key:1},[M(`ul`,nd,[(F(!0),j(m,null,L(v.value,e=>(F(),j(`li`,{key:e.term,"data-tolk-site-profile-term":e.term},R(e.term),9,rd))),128))]),P(z(U),null,{default:B(()=>[N(R(e.__(`Add them to the glossary with Do not translate on, so that every translation keeps them.`)),1)]),_:1})],64))])):A(``,!0),u.value?(F(),k(z(Kn),{key:4,open:``,"onUpdate:open":t[0]||=e=>u.value=e,title:e.__(`Replace the site profile?`),"body-text":e.__(`A new profile replaces the text in this field. Nothing is saved until you save the settings.`),"button-text":e.__(`Generate`),onConfirm:x},null,8,[`title`,`body-text`,`button-text`])):A(``,!0)]))}},{Form:ad,Head:od,Link:sd,router:cd,toggleArchitecturalBackground:ld,useArchitecturalBackground:ud,useForm:dd,usePage:fd,usePoll:pd}=__STATAMIC__.inertia,md={class:`mx-auto max-w-page space-y-6`,"data-tolk-audit":``},hd={class:`flex flex-wrap items-center gap-2`},gd={key:1,class:`space-y-3`},_d=[`data-tolk-item-level`],vd=[`data-tolk-blueprint`],yd={class:`flex flex-wrap items-center justify-between gap-2`},bd={class:`flex items-center gap-2`},xd=[`href`],Sd={class:`space-y-2`},Cd=[`data-tolk-field`],wd=[`data-tolk-field-imported`],Td=[`href`],Ed={key:1,class:`space-y-1 ps-6`},Dd=[`data-tolk-field`],Od={class:`text-xs text-gray-600 dark:text-gray-400`},kd={key:1,class:`flex items-start gap-2`},Ad={__name:`Audit`,props:{checks:{type:Array,default:()=>[]},canMakeLocalizable:{type:Boolean,default:!1},urls:{type:Object,required:!0}},setup(e){let t=e,n=I(t.checks),r=Dt({}),i=I(null),a=I(null),o=O(()=>il(n.value));bn(()=>t.checks,e=>n.value=e);function s(e,t){return(r[sl(e)]??[]).includes(t)}function c(e,t,n){let i=sl(e),a=(r[i]??[]).filter(e=>e!==t);r[i]=n?[...a,t]:a}function l(e){let t=dl(e,r[sl(e)]);t.length>0&&(i.value={item:e,fields:t,text:fl(e,t)})}async function u(){let{item:e,fields:o}=i.value,s=sl(e);i.value=null,a.value=s;try{let i=await Qi(t.urls.localizable,{namespace:e.namespace,blueprint:e.blueprint,fields:o});n.value=i.checks,delete r[s],Statamic.$toast.success(pl(i.changed))}catch(e){Statamic.$toast.error(e.message)}finally{a.value=null}}return(t,d)=>(F(),j(`div`,md,[P(z(od),{title:t.__(`Audit`)},null,8,[`title`]),P(z(br),{title:t.__(`Setup audit`),icon:`clipboard-check`},{default:B(()=>[P(z(sd),{href:e.urls.overview,class:`text-sm text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-200`},{default:B(()=>[N(R(t.__(`Overview`)),1)]),_:1},8,[`href`]),P(z(V),{text:t.__(`Check again`),icon:`sync`,"data-tolk-audit-reload":``,onClick:d[0]||=e=>z(cd).reload()},null,8,[`text`])]),_:1},8,[`title`]),P(z(H),{class:`flex items-start gap-3`,"data-tolk-audit-summary":``,"data-tolk-audit-level":o.value.level},{default:B(()=>[P(z(G),{name:z($)(o.value.level).icon,class:it([`mt-0.5 size-5 shrink-0`,z($)(o.value.level).class]),"aria-hidden":`true`},null,8,[`name`,`class`]),P(z(J),null,{default:B(()=>[N(R(o.value.text),1)]),_:1})]),_:1},8,[`data-tolk-audit-level`]),(F(!0),j(m,null,L(n.value,n=>(F(),k(z(H),{id:z(tl)(n.id),key:n.id,class:`space-y-3`,"data-tolk-check":n.id,"data-tolk-check-level":n.level},{default:B(()=>[M(`div`,hd,[P(z(G),{name:z($)(n.level).icon,class:it([`size-4 shrink-0`,z($)(n.level).class]),"aria-hidden":`true`},null,8,[`name`,`class`]),P(z(W),{size:`lg`,level:2},{default:B(()=>[N(R(n.title),1)]),_:2},1024),P(z(Pn),{text:z($)(n.level).label,color:z($)(n.level).color},null,8,[`text`,`color`])]),P(z(U),null,{default:B(()=>[N(R(z(al)(n,e.canMakeLocalizable)),1)]),_:2},1024),n.items.length===0?(F(),k(z(J),{key:0,"data-tolk-audit-nothing":``},{default:B(()=>[N(R(n.id===z(`localizable`)?t.__(`Every text field Tolk could translate is localizable.`):t.__(`Nothing to report.`)),1)]),_:2},1024)):(F(),j(`ul`,gd,[(F(!0),j(m,null,L(n.items,(i,o)=>(F(),j(`li`,{key:o,"data-tolk-item":``,"data-tolk-item-level":i.level},[z(ol)(i)?(F(),j(`div`,{key:0,class:`space-y-2 rounded-lg border border-gray-200 p-3 dark:border-gray-700`,"data-tolk-blueprint":z(sl)(i)},[M(`div`,yd,[M(`div`,bd,[P(z(G),{name:z($)(i.level).icon,class:it([`size-4 shrink-0`,z($)(i.level).class]),role:`img`,"aria-label":z($)(i.level).label},null,8,[`name`,`class`,`aria-label`]),P(z(J),{class:`font-medium`},{default:B(()=>[N(R(i.name),1)]),_:2},1024)]),i.edit_url?(F(),j(`a`,{key:0,href:i.edit_url,class:`text-sm text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-blueprint-link":``},R(t.__(`Edit blueprint`)),9,xd)):A(``,!0)]),n.id===z(`localizable`)?(F(),j(m,{key:0},[M(`div`,Sd,[(F(!0),j(m,null,L(z(cl)(i).editable,t=>(F(),j(`div`,{key:t.handle,"data-tolk-field":t.handle},[e.canMakeLocalizable?(F(),k(z(Vn),{key:0,"model-value":s(i,t.handle),label:z(ll)(t),disabled:a.value!==null,"onUpdate:modelValue":e=>c(i,t.handle,e)},null,8,[`model-value`,`label`,`disabled`,`onUpdate:modelValue`])):(F(),k(z(J),{key:1},{default:B(()=>[N(R(z(ll)(t)),1)]),_:2},1024))],8,Cd))),128)),(F(!0),j(m,null,L(z(cl)(i).imported,n=>(F(),j(`div`,{key:n.handle,"data-tolk-field-imported":n.handle},[e.canMakeLocalizable?(F(),k(z(Vn),{key:0,"model-value":!1,label:z(ll)(n),description:z(ul)(n),disabled:``},null,8,[`label`,`description`])):(F(),j(m,{key:1},[P(z(J),null,{default:B(()=>[N(R(z(ll)(n)),1)]),_:2},1024),P(z(U),null,{default:B(()=>[N(R(z(ul)(n)),1)]),_:2},1024)],64)),n.fieldset_url?(F(),j(`a`,{key:2,href:n.fieldset_url,class:`ms-6 text-sm text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-fieldset-link":``},R(t.__(`Edit fieldset`)),9,Td)):A(``,!0)],8,wd))),128))]),e.canMakeLocalizable&&z(cl)(i).editable.length>0?(F(),k(z(V),{key:0,size:`sm`,variant:`primary`,text:t.__(`Make localizable`),loading:a.value===z(sl)(i),disabled:a.value!==null||z(dl)(i,r[z(sl)(i)]).length===0,"data-tolk-make-localizable":``,onClick:e=>l(i)},null,8,[`text`,`loading`,`disabled`,`onClick`])):A(``,!0)],64)):(F(),j(`ul`,Ed,[(F(!0),j(m,null,L(i.fields,e=>(F(),j(`li`,{key:e.path??e.handle,"data-tolk-field":e.path??e.handle},[P(z(J),null,{default:B(()=>[N(R(e.label)+` `,1),M(`code`,Od,R(e.path??e.handle),1)]),_:2},1024)],8,Dd))),128))]))],8,vd)):(F(),j(`div`,kd,[P(z(G),{name:z($)(i.level).icon,class:it([`mt-0.5 size-4 shrink-0`,z($)(i.level).class]),role:`img`,"aria-label":z($)(i.level).label},null,8,[`name`,`class`,`aria-label`]),P(z(J),null,{default:B(()=>[N(R(i.text),1)]),_:2},1024)]))],8,_d))),128))]))]),_:2},1032,[`id`,`data-tolk-check`,`data-tolk-check-level`]))),128)),i.value?(F(),k(z(Kn),{key:0,open:``,title:t.__(`Make these fields localizable?`),"button-text":t.__(`Make localizable`),"data-tolk-localizable-confirm":``,"onUpdate:open":d[1]||=e=>i.value=e?i.value:null,onConfirm:u},{default:B(()=>[P(z(J),null,{default:B(()=>[N(R(i.value.text),1)]),_:1})]),_:1},8,[`title`,`button-text`])):A(``,!0)]))}},jd={class:`overflow-x-auto`},Md={__name:`RunsTable`,props:{runs:{type:Array,default:()=>[]}},setup(e){let t=e,n=Yo(Statamic.$config.get(`sites`)),r=O(()=>t.runs.map(e=>{let t=Qo({counts:e.counts}),r=cs(e),i=as(e.scope,n);return{id:e.id,url:e.url,status:e.status,what:i.what,sites:i.sites,progress:__(`:finished of :total`,{finished:Q(t.finished),total:Q(t.total)}),failed:t.counts.failed,tokens:r.input+r.output,cost:r.cost,date:Zo(e.created_at),by:e.created_by?.name??__(`Command line`)}}));return(e,t)=>(F(),j(`div`,jd,[P(z(Ei),null,{default:B(()=>[P(z(Di),null,{default:B(()=>[P(z(q),null,{default:B(()=>[N(R(e.__(`Status`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(e.__(`Content`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(e.__(`Sites`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(e.__(`Items finished`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(e.__(`Usage`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(e.__(`Created`)),1)]),_:1})]),_:1}),P(z(ki),null,{default:B(()=>[(F(!0),j(m,null,L(r.value,t=>(F(),k(z(Oi),{key:t.id,"data-tolk-run-row":``,"data-tolk-run-id":t.id},{default:B(()=>[P(z(K),null,{default:B(()=>[P(z(sd),{href:t.url,class:`inline-flex`},{default:B(()=>[P(z(Pn),{text:z(Wo)(t.status),color:z(Go)(t.status)},null,8,[`text`,`color`])]),_:2},1032,[`href`])]),_:2},1024),P(z(K),null,{default:B(()=>[P(z(sd),{href:t.url,class:`text-blue-600 hover:underline dark:text-blue-400`},{default:B(()=>[N(R(t.what),1)]),_:2},1032,[`href`])]),_:2},1024),P(z(K),null,{default:B(()=>[N(R(t.sites),1)]),_:2},1024),P(z(K),null,{default:B(()=>[N(R(t.progress)+` `,1),t.failed>0?(F(),k(z(U),{key:0},{default:B(()=>[N(R(e.__n(`:count failed|:count failed`,t.failed)),1)]),_:2},1024)):A(``,!0)]),_:2},1024),P(z(K),null,{default:B(()=>[N(R(e.__(`:tokens tokens`,{tokens:z(Q)(t.tokens)}))+` `,1),P(z(U),null,{default:B(()=>[N(R(t.cost===null?e.__(`Cost unknown`):z(Xo)(t.cost)),1)]),_:2},1024)]),_:2},1024),P(z(K),null,{default:B(()=>[N(R(t.date)+` `,1),P(z(U),null,{default:B(()=>[N(R(t.by),1)]),_:2},1024)]),_:2},1024)]),_:2},1032,[`data-tolk-run-id`]))),128))]),_:1})]),_:1})]))}};function Nd({scan:e,onChange:t=()=>{},concurrency:n=3}){let r=[],i=0,a=0;function o(e){return e.generation===a}function s(){for(;i0;)c(r.shift())}async function c(n){i++,t(n.cell.key,{status:`loading`});try{let r=null;do{let i=await e({...n.cell,cursor:r,fresh:n.fresh});if(!o(n))return;r=i.cursor??null,t(n.cell.key,{...i,status:r===null?`done`:`loading`})}while(r!==null)}catch(e){o(n)&&t(n.cell.key,{status:`failed`,error:e?.message??String(e)})}finally{i--,s()}}function l(){a++,r=[]}function u(e,n){for(let i of e)r.push({cell:i,fresh:n,generation:a}),t(i.key,{status:`waiting`});s()}return{load(e,{fresh:t=!1}={}){l(),u(e,t)},retry(e){u([e],!1)},stop:l,get active(){return i}}}var Pd=[`entry`,`term`,`globals`,`nav`],Fd=[`missing`,`untranslated`,`outdated`,`attention`,`current`],Id={entry:`collections`,term:`taxonomies`,globals:`globals`,nav:`navs`};function Ld(e){return e===`current`?__(`Current`):oa(e)}function Rd(e){return{entry:__(`Collections`),term:__(`Taxonomies`),globals:__(`Global sets`),nav:__(`Navigation`)}[e]??e}function zd(e,t,n){return`${e}|${t}|${n}`}function Bd(e,t){let n=new Set((Array.isArray(e)?e:[]).flatMap(e=>e.sites??[]));return(Array.isArray(t)?t:[]).filter(e=>n.has(e.handle))}function Vd(e){let t=Array.isArray(e)?e:[];return Pd.map(e=>({type:e,label:Rd(e),rows:t.filter(t=>t.type===e)})).filter(e=>e.rows.length>0)}function Hd(e,t){return{key:zd(e.type,e.handle,t),type:e.type,container:e.handle,site:t}}function Ud(e){return(Array.isArray(e)?e:[]).flatMap(e=>(e.sites??[]).map(t=>Hd(e,t)))}function Wd(e){let t=X(e?.counts),n=e=>Number(t[e])||0;return{counts:Object.fromEntries(Fd.map(e=>[e,n(e)])),untracked:Number(e?.untracked)||0,scanned:Number(e?.scanned)||0,missing:n(`missing`)+n(`untranslated`),outdated:n(`outdated`)}}function Gd(e){let t=Wd(e);return{...t,badges:Fd.filter(e=>t.counts[e]>0).map(e=>({status:e,text:`${Ld(e)} ${t.counts[e]}`,color:aa(e)})),finished:e?.status===`done`,loading:e?.status===`waiting`||e?.status===`loading`,failed:e?.status===`failed`,error:e?.error??null}}function Kd(e,t,n,r){return{sites:[n],[Id[e]]:[t],options:{mode:r}}}function qd(e,t,n){let r={};for(let i of Array.isArray(e)?e:[]){if(!(i.sites??[]).includes(n))continue;let e=X(t)[zd(i.type,i.handle,n)];(e?.status!==`done`||Wd(e).missing!==0)&&(r[Id[i.type]]??=[]).push(i.handle)}return Object.keys(r).length>0?{sites:[n],...r,options:{mode:`missing`}}:null}function Jd({multisite:e,providers:t,fakeEngine:n}){return e?(Array.isArray(t)?t:[]).some(e=>e.configured)||n?null:`no_provider`:`single_site`}function Yd(e){let t=X(e?.labels),n=Object.entries(X(e?.models)).map(([e,n])=>({reference:e,model:t[e]??e,calls:Number(n?.calls)||0,input:Number(n?.input)||0,output:Number(n?.output)||0,cost:n?.cost===null||n?.cost===void 0?null:Number(n.cost),sources:Object.keys(X(n?.sources))}));return{month:e?.month??``,rows:n,calls:n.reduce((e,t)=>e+t.calls,0),cost:n.some(e=>e.cost===null)?null:n.reduce((e,t)=>e+t.cost,0)}}function Xd(e){return{editor:__(`Editor`),run:__(`Runs`),cli:__(`Command line`)}[e]??e}function Zd(e,t=void 0){let n=/^(\d{4})-(\d{2})$/.exec(e??``);return n?new Intl.DateTimeFormat(t,{month:`long`,year:`numeric`}).format(Date.UTC(n[1],n[2]-1,15)):``}var Qd={class:`mx-auto max-w-page space-y-6`,"data-tolk-overview":``},$d={class:`flex flex-wrap gap-4 text-sm`},ef=[`href`],tf={class:`overflow-x-auto`},nf={class:`flex flex-col items-start gap-1`},rf={key:1,class:`space-y-1.5`},af={key:0,class:`flex flex-wrap gap-1`},of={key:4,class:`space-y-1`},sf={key:5,class:`flex flex-wrap gap-1`},cf={class:`grid gap-6 lg:grid-cols-2`},lf={class:`flex flex-wrap items-center justify-between gap-2`},uf={class:`overflow-x-auto`},df={class:`space-y-2`},ff=[`data-tolk-provider`],pf=[`href`],mf={class:`flex flex-wrap items-baseline justify-between gap-2`},hf={__name:`Overview`,props:{multisite:{type:Boolean,default:!1},sites:{type:Array,default:()=>[]},rows:{type:Array,default:()=>[]},providers:{type:Array,default:()=>[]},fakeEngine:{type:Boolean,default:!1},usage:{type:Object,default:()=>({})},canResetUsage:{type:Boolean,default:!1},runs:{type:Array,default:()=>[]},urls:{type:Object,required:!0}},setup(e){let t=e,n=Dt({}),r=I(null),i=I(t.usage),a=I(!1),o=I(!1),s=Statamic.$config.get(`tolk`)?.settingsUrl??null,c=O(()=>Jd(t)),l=O(()=>Bd(t.rows,t.sites)),u=O(()=>Vd(t.rows).map(e=>({...e,rows:e.rows.map(e=>({...e,cells:l.value.map(t=>{let r=Hd(e,t.handle),i=e.sites.includes(t.handle),a=n[r.key];return{site:t,cell:r,status:i?a?.status??`waiting`:`none`,view:i?Gd(a):null}})}))}))),d=O(()=>Ud(t.rows)),f=O(()=>Yd(i.value)),p=O(()=>Object.values(n).some(e=>Number(e?.untracked)>0)),h=O(()=>Object.fromEntries(l.value.map(e=>[e.handle,qd(t.rows,n,e.handle)]))),g=Nd({scan:({key:e,...n})=>Qi(t.urls.scan,n),onChange:(e,t)=>n[e]=t});pt(()=>{c.value===null&&g.load(d.value)}),lt(()=>g.stop());function _(){g.load(d.value,{fresh:!0})}async function v(e,n){r.value=e;try{let{url:e}=await Qi(t.urls.store,n);g.stop(),cd.visit(e)}catch(e){Statamic.$toast.error(e.message),r.value=null}}async function y(){let e=Zd(f.value.month);a.value=!1,o.value=!0;try{i.value=(await Qi(t.urls.resetUsage,{month:f.value.month})).usage,Statamic.$toast.success(__(`The usage of :month was reset.`,{month:e}))}catch(e){Statamic.$toast.error(e.message)}finally{o.value=!1}}return(t,n)=>(F(),j(`div`,Qd,[P(z(od),{title:t.__(`Translations`)},null,8,[`title`]),P(z(br),{title:t.__(`Translations`),icon:`dictionary-language-book`},{default:B(()=>[P(z(sd),{href:e.urls.runs,class:`text-sm text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-200`,"data-tolk-runs-link":``},{default:B(()=>[N(R(t.__(`All runs`)),1)]),_:1},8,[`href`]),c.value===null&&d.value.length>0?(F(),k(z(V),{key:0,text:t.__(`Count again`),icon:`sync`,"data-tolk-count-again":``,onClick:_},null,8,[`text`])):A(``,!0)]),_:1},8,[`title`]),c.value===`single_site`?(F(),k(z(H),{key:0,class:`space-y-3`,"data-tolk-overview-empty":`single_site`},{default:B(()=>[P(z(W),{size:`lg`,text:t.__(`This site has one language`)},null,8,[`text`]),P(z(J),null,{default:B(()=>[N(R(t.__(`Tolk translates the content of one site into the languages of the others. Add a site for each language in Statamic first; the overview then shows what is translated into each.`)),1)]),_:1}),P(z(sd),{href:e.urls.audit,class:`text-sm text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-audit-link":``},{default:B(()=>[N(R(t.__(`Check the setup`)),1)]),_:1},8,[`href`])]),_:1})):c.value===`no_provider`?(F(),k(z(H),{key:1,class:`space-y-3`,"data-tolk-overview-empty":`no_provider`},{default:B(()=>[P(z(W),{size:`lg`,text:t.__(`No AI provider is set up`)},null,8,[`text`]),P(z(J),null,{default:B(()=>[N(R(t.__(`Tolk needs an API key of Anthropic, OpenAI or Google Gemini in the .env file before it can translate. The settings list the variables to set.`)),1)]),_:1}),M(`div`,$d,[z(s)?(F(),j(`a`,{key:0,href:z(s),class:`text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-settings-link":``},R(t.__(`Open the settings`)),9,ef)):A(``,!0),P(z(sd),{href:e.urls.audit,class:`text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-audit-link":``},{default:B(()=>[N(R(t.__(`Check the setup`)),1)]),_:1},8,[`href`])])]),_:1})):e.rows.length===0?(F(),k(z(H),{key:2,"data-tolk-overview-nothing":``},{default:B(()=>[P(z(J),null,{default:B(()=>[N(R(t.__(`No collection, taxonomy, global set or navigation has more than one site yet, so there is nothing to translate.`)),1)]),_:1})]),_:1})):(F(),k(z(H),{key:3,class:`space-y-3`,"data-tolk-matrix":``},{default:B(()=>[M(`div`,tf,[P(z(Ei),null,{default:B(()=>[P(z(Di),null,{default:B(()=>[P(z(q),null,{default:B(()=>[N(R(t.__(`Content`)),1)]),_:1}),(F(!0),j(m,null,L(l.value,e=>(F(),k(z(q),{key:e.handle,"data-tolk-column":e.handle},{default:B(()=>[M(`div`,nf,[M(`span`,null,R(e.name),1),h.value[e.handle]?(F(),k(z(V),{key:0,size:`xs`,text:t.__(`Translate everything missing`),"aria-label":t.__(`Translate everything missing into :site`,{site:e.name}),loading:r.value===`site|${e.handle}`,disabled:r.value!==null,"data-tolk-site-action":e.handle,onClick:t=>v(`site|${e.handle}`,h.value[e.handle])},null,8,[`text`,`aria-label`,`loading`,`disabled`,`data-tolk-site-action`,`onClick`])):A(``,!0)])]),_:2},1032,[`data-tolk-column`]))),128))]),_:1}),P(z(ki),null,{default:B(()=>[(F(!0),j(m,null,L(u.value,e=>(F(),j(m,{key:e.type},[P(z(Oi),{"data-tolk-group":e.type},{default:B(()=>[P(z(K),{colspan:l.value.length+1,class:`bg-gray-50 dark:bg-gray-900`},{default:B(()=>[P(z(W),{text:e.label},null,8,[`text`])]),_:2},1032,[`colspan`])]),_:2},1032,[`data-tolk-group`]),(F(!0),j(m,null,L(e.rows,e=>(F(),k(z(Oi),{key:`${e.type}|${e.handle}`,"data-tolk-row":`${e.type}|${e.handle}`},{default:B(()=>[P(z(K),null,{default:B(()=>[P(z(J),null,{default:B(()=>[N(R(e.title),1)]),_:2},1024),P(z(U),null,{default:B(()=>[N(R(e.handle),1)]),_:2},1024)]),_:2},1024),(F(!0),j(m,null,L(e.cells,({site:i,cell:a,status:o,view:s})=>(F(),k(z(K),{key:i.handle,class:`align-top`,"data-tolk-cell":a.key,"data-tolk-cell-status":o},{default:B(()=>[s?(F(),j(`div`,rf,[s.badges.length?(F(),j(`div`,af,[(F(!0),j(m,null,L(s.badges,e=>(F(),k(z(Pn),{key:e.status,text:e.text,color:e.color,"data-tolk-count":e.status},null,8,[`text`,`color`,`data-tolk-count`]))),128))])):A(``,!0),s.loading?(F(),k(z(U),{key:1},{default:B(()=>[N(R(t.__(`Counting…`)),1)]),_:1})):s.finished&&s.scanned===0?(F(),k(z(U),{key:2},{default:B(()=>[N(R(t.__(`Nothing to translate`)),1)]),_:1})):A(``,!0),s.untracked>0?(F(),k(z(U),{key:3,"data-tolk-untracked":``},{default:B(()=>[N(R(t.__n(`:count untracked field|:count untracked fields`,s.untracked)),1)]),_:2},1024)):A(``,!0),s.failed?(F(),j(`div`,of,[P(z(J),{size:`sm`,variant:`danger`,"data-tolk-cell-error":``},{default:B(()=>[N(R(s.error),1)]),_:2},1024),P(z(V),{size:`xs`,text:t.__(`Try again`),"data-tolk-cell-retry":``,onClick:e=>z(g).retry(a)},null,8,[`text`,`onClick`])])):A(``,!0),s.missing>0||s.outdated>0?(F(),j(`div`,sf,[s.missing>0?(F(),k(z(V),{key:0,size:`xs`,text:t.__(`Translate missing`),"aria-label":t.__(`Translate missing :content into :site`,{content:e.title,site:i.name}),loading:r.value===`${a.key}|missing`,disabled:r.value!==null,"data-tolk-cell-action":`missing`,onClick:t=>v(`${a.key}|missing`,z(Kd)(e.type,e.handle,i.handle,`missing`))},null,8,[`text`,`aria-label`,`loading`,`disabled`,`onClick`])):A(``,!0),s.outdated>0?(F(),k(z(V),{key:1,size:`xs`,text:t.__(`Update outdated`),"aria-label":t.__(`Update outdated :content in :site`,{content:e.title,site:i.name}),loading:r.value===`${a.key}|update`,disabled:r.value!==null,"data-tolk-cell-action":`update`,onClick:t=>v(`${a.key}|update`,z(Kd)(e.type,e.handle,i.handle,`update`))},null,8,[`text`,`aria-label`,`loading`,`disabled`,`onClick`])):A(``,!0)])):A(``,!0)])):(F(),k(z(U),{key:0},{default:B(()=>[...n[2]||=[N(`—`,-1)]]),_:1}))]),_:2},1032,[`data-tolk-cell`,`data-tolk-cell-status`]))),128))]),_:2},1032,[`data-tolk-row`]))),128))],64))),128))]),_:1})]),_:1})]),p.value?(F(),k(z(U),{key:0,"data-tolk-baseline-hint":``},{default:B(()=>[N(R(t.__(`Untracked fields were translated by hand without a record of their origin, so a change to the origin goes unnoticed. Run php please tolk:baseline to record the origin of each.`)),1)]),_:1})):A(``,!0)]),_:1})),M(`div`,cf,[P(z(H),{class:`space-y-3`,"data-tolk-usage":``},{default:B(()=>[M(`div`,lf,[P(z(W),{size:`lg`,text:t.__(`Usage in :month`,{month:z(Zd)(f.value.month)})},null,8,[`text`]),e.canResetUsage&&f.value.rows.length>0?(F(),k(z(V),{key:0,size:`sm`,text:t.__(`Reset`),"aria-label":t.__(`Reset the usage of :month`,{month:z(Zd)(f.value.month)}),loading:o.value,"data-tolk-usage-reset":``,onClick:n[0]||=e=>a.value=!0},null,8,[`text`,`aria-label`,`loading`])):A(``,!0)]),f.value.rows.length===0?(F(),k(z(J),{key:0},{default:B(()=>[N(R(t.__(`No model was called this month.`)),1)]),_:1})):(F(),j(m,{key:1},[M(`div`,uf,[P(z(Ei),null,{default:B(()=>[P(z(Di),null,{default:B(()=>[P(z(q),null,{default:B(()=>[N(R(t.__(`Model`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(t.__(`Calls`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(t.__(`Tokens`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(t.__(`Cost`)),1)]),_:1})]),_:1}),P(z(ki),null,{default:B(()=>[(F(!0),j(m,null,L(f.value.rows,e=>(F(),k(z(Oi),{key:e.reference,"data-tolk-usage-model":e.reference},{default:B(()=>[P(z(K),null,{default:B(()=>[N(R(e.model)+` `,1),P(z(U),null,{default:B(()=>[N(R(e.sources.map(z(Xd)).join(`, `)),1)]),_:2},1024)]),_:2},1024),P(z(K),null,{default:B(()=>[N(R(z(Q)(e.calls)),1)]),_:2},1024),P(z(K),null,{default:B(()=>[N(R(t.__(`:input in, :output out`,{input:z(Q)(e.input),output:z(Q)(e.output)})),1)]),_:2},1024),P(z(K),null,{default:B(()=>[N(R(e.cost===null?t.__(`Unknown`):z(Xo)(e.cost)),1)]),_:2},1024)]),_:2},1032,[`data-tolk-usage-model`]))),128))]),_:1})]),_:1})]),P(z(U),{"data-tolk-usage-total":``},{default:B(()=>[N(R(f.value.cost===null?t.__n(`:calls call this month. The cost is unknown: a model without a price was called.|:calls calls this month. The cost is unknown: a model without a price was called.`,f.value.calls,{calls:z(Q)(f.value.calls)}):t.__n(`:calls call this month, an estimated :cost.|:calls calls this month, an estimated :cost.`,f.value.calls,{calls:z(Q)(f.value.calls),cost:z(Xo)(f.value.cost)})),1)]),_:1})],64))]),_:1}),P(z(H),{class:`space-y-3`,"data-tolk-providers":``},{default:B(()=>[P(z(W),{size:`lg`,text:t.__(`Providers`)},null,8,[`text`]),M(`ul`,df,[(F(!0),j(m,null,L(e.providers,e=>(F(),j(`li`,{key:e.provider,class:`flex items-center justify-between gap-2`,"data-tolk-provider":e.provider},[P(z(J),null,{default:B(()=>[N(R(e.label),1)]),_:2},1024),P(z(Pn),tt({ref_for:!0},z(Au)(e.configured)),null,16)],8,ff))),128))]),e.fakeEngine?(F(),k(z(U),{key:0,"data-tolk-fake-engine":``},{default:B(()=>[N(R(t.__(`The fake engine is on: translations are made up without calling a provider.`)),1)]),_:1})):A(``,!0),z(s)?(F(),j(`a`,{key:1,href:z(s),class:`text-sm text-blue-600 hover:underline dark:text-blue-400`},R(t.__(`Settings`)),9,pf)):A(``,!0)]),_:1})]),P(z(H),{class:`space-y-3`,"data-tolk-latest-runs":``},{default:B(()=>[M(`div`,mf,[P(z(W),{size:`lg`,text:t.__(`Latest runs`)},null,8,[`text`]),e.runs.length>0?(F(),k(z(sd),{key:0,href:e.urls.runs,class:`text-sm text-blue-600 hover:underline dark:text-blue-400`},{default:B(()=>[N(R(t.__(`All runs`)),1)]),_:1},8,[`href`])):A(``,!0)]),e.runs.length===0?(F(),k(z(J),{key:0},{default:B(()=>[N(R(t.__(`No translation runs yet.`)),1)]),_:1})):(F(),k(Md,{key:1,runs:e.runs},null,8,[`runs`]))]),_:1}),a.value?(F(),k(z(Kn),{key:4,open:``,danger:``,title:t.__(`Reset the usage of :month?`,{month:z(Zd)(f.value.month)}),"body-text":t.__(`The calls, tokens and costs counted this month are deleted, and counting starts again from zero. The runs keep their own usage.`),"button-text":t.__(`Reset`),"data-tolk-usage-reset-confirm":``,"onUpdate:open":n[1]||=e=>a.value=e,onConfirm:y},null,8,[`title`,`body-text`,`button-text`])):A(``,!0)]))}},gf={class:`mx-auto max-w-page space-y-6`,"data-tolk-runs":``},_f={__name:`Index`,props:{runs:{type:Array,default:()=>[]},canReset:{type:Boolean,default:!1},urls:{type:Object,default:()=>({})}},setup(e){let t=e,n=I(!1),r=I(!1),i=O(()=>t.runs.some(e=>bo.includes(e.status)));async function a(){n.value=!1,r.value=!0;try{let{deleted:e}=await Qi(t.urls.reset);Statamic.$toast.success(__n(`:count run was deleted.|:count runs were deleted.`,e)),cd.reload({only:[`runs`]})}catch(e){Statamic.$toast.error(e.message)}finally{r.value=!1}}return(t,o)=>(F(),j(`div`,gf,[P(z(od),{title:t.__(`Translation runs`)},null,8,[`title`]),P(z(br),{title:t.__(`Translation runs`),icon:`dictionary-language-book`},{default:B(()=>[e.canReset&&i.value?(F(),k(z(V),{key:0,text:t.__(`Reset`),loading:r.value,"data-tolk-runs-reset":``,onClick:o[0]||=e=>n.value=!0},null,8,[`text`,`loading`])):A(``,!0)]),_:1},8,[`title`]),e.runs.length===0?(F(),k(z(H),{key:0,"data-tolk-runs-empty":``},{default:B(()=>[P(z(J),null,{default:B(()=>[N(R(t.__(`No translation runs yet. Runs started from a listing, the overview or the command line appear here.`)),1)]),_:1})]),_:1})):(F(),k(z(H),{key:1},{default:B(()=>[P(Md,{runs:e.runs},null,8,[`runs`])]),_:1})),n.value?(F(),k(z(Kn),{key:2,open:``,danger:``,title:t.__(`Delete the finished runs?`),"body-text":t.__(`Every completed, cancelled and aborted run is deleted with its results, and can no longer be resumed or retried. Pending and running runs stay. The translations they saved stay too.`),"button-text":t.__(`Delete`),"data-tolk-runs-reset-confirm":``,"onUpdate:open":o[1]||=e=>n.value=e,onConfirm:a},null,8,[`title`,`body-text`,`button-text`])):A(``,!0)]))}},vf=[`data-tolk-run-status`],yf={class:`flex flex-wrap items-center gap-2`},bf={class:`flex flex-wrap items-center gap-x-4 gap-y-1`,"data-tolk-run-counts":``},xf={class:`space-y-3`},Sf={class:`flex flex-wrap gap-2`},Cf={class:`flex flex-wrap items-center justify-between gap-2`},wf={class:`space-y-3`},Tf={key:1,class:`flex flex-wrap gap-2`},Ef={class:`grid gap-6 lg:grid-cols-2`},Df={class:`overflow-x-auto`},Of={class:`grid grid-cols-[auto_1fr] gap-x-4 gap-y-1 text-sm`},kf={class:`text-gray-600 dark:text-gray-400`},Af=[`data-tolk-option`],jf={class:`flex flex-wrap items-baseline justify-between gap-2`},Mf={key:0,class:`flex flex-wrap gap-x-10 gap-y-2 text-sm`},Nf={class:`text-gray-600 dark:text-gray-400`},Pf={"data-tolk-estimate-segments":``},Ff={class:`text-gray-600 dark:text-gray-400`},If={"data-tolk-estimate-chars":``},Lf={class:`text-gray-600 dark:text-gray-400`},Rf={"data-tolk-estimate-input":``},zf={class:`text-gray-600 dark:text-gray-400`},Bf={"data-tolk-estimate-output":``},Vf={class:`text-gray-600 dark:text-gray-400`},Hf={"data-tolk-estimate-cost":``},Uf={class:`flex flex-wrap items-center justify-between gap-2`},Wf={class:`w-56`},Gf={class:`overflow-x-auto`},Kf=[`href`],qf={key:1},Jf={key:1,class:`flex flex-wrap items-center gap-2`},Yf=[`href`],Xf={key:1,class:`flex items-center justify-end gap-2`,"data-tolk-items-pages":``},Zf={__name:`Show`,props:{state:{type:Object,required:!0},urls:{type:Object,required:!0},models:{type:Object,default:()=>({})},lanes:{type:Number,default:1}},setup(e){let t=e,n=I(t.state),r=I(t.state.run?.estimate??null),i=I([]),a=I(null),o=I(t.state.pagination?.page??1),s=t.state.pagination?.per_page??50,c=I(`all`),l=Yo(Statamic.$config.get(`sites`)),u=fs({urls:t.urls,lanes:t.lanes,onState:e=>{n.value=e,r.value=e.run?.estimate??r.value},onEstimate:e=>r.value=e,onFailures:e=>i.value=e,query:()=>({page:o.value,per_page:s,...c.value===`all`?{}:{status:c.value}})});function d(e){u.active&&(e.preventDefault(),e.returnValue=``)}pt(()=>{u.follow(t.state),window.addEventListener(`beforeunload`,d)}),lt(()=>{u.stop(),window.removeEventListener(`beforeunload`,d)});let f=O(()=>n.value.run??{}),p=O(()=>f.value.status),h=O(()=>Qo(n.value)),g=O(()=>$o(n.value)),_=O(()=>ts(n.value)),v=O(()=>as(f.value.scope,l)),y=O(()=>ns(n.value.breakdown,l)),b=O(()=>rs(f.value.scope)),x=nl(Statamic.$config.get(`tolk.auditUrl`)),S=O(()=>is(f.value.scope)),C=O(()=>os(f.value.options,t.models)),w=O(()=>ss(r.value,h.value.total)),T=O(()=>cs(f.value,t.models)),E=O(()=>(n.value.items??[]).map(e=>ds(e,l))),D=O(()=>n.value.pagination??{page:1,last_page:1,total:0}),ee=O(()=>p.value===`running`&&f.value.driver===`browser`),te=O(()=>p.value===`running`&&!!n.value.stalled),ne=O(()=>Bo.filter(e=>h.value.counts[e]>0).map(e=>({key:e,text:`${Q(h.value.counts[e])} ${Ko(e).toLowerCase()}`}))),re=O(()=>[{label:__(`All items`),value:`all`},...Bo.map(e=>({label:Ko(e),value:e}))]),ie=I(null),ae=xl(()=>ie.value),oe=Qs(),se=I([]);function ce(e){se.value=e.corrections,oe.show()}bn(p,()=>ae.changing());let le=O(()=>{let e=f.value.created_by?.name,t=Zo(f.value.created_at);return e?__(`Created by :name on :date`,{name:e,date:t}):__(`Created on :date from the command line`,{date:t})});async function ue(e,t){let n=ae.holds();a.value=e;try{let n=await t();e===`retry`&&n?.retried===0&&Statamic.$toast.info(__(`No item failed, so nothing was retried.`))}catch(e){Statamic.$toast.error(e.message)}finally{a.value=null,n&&nt(ae.restore)}}async function de(e){o.value=Math.max(1,e);try{await u.refresh()}catch(e){Statamic.$toast.error(e.message)}}function fe(e){c.value=e??`all`,de(1)}return(t,r)=>(F(),j(`div`,{ref_key:`root`,ref:ie,class:`mx-auto max-w-page space-y-6`,"data-tolk-run":``,"data-tolk-run-status":p.value},[P(z(od),{title:t.__(`Translation run`)},null,8,[`title`]),P(z(br),{title:t.__(`Translation run`),icon:`dictionary-language-book`},{default:B(()=>[P(z(sd),{href:e.urls.index,class:`text-sm text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-200`,"data-tolk-runs-link":``},{default:B(()=>[N(R(t.__(`All runs`)),1)]),_:1},8,[`href`]),g.value.cancel?(F(),k(z(V),{key:0,text:t.__(`Cancel`),loading:a.value===`cancel`,disabled:a.value!==null,"data-tolk-action":`cancel`,onClick:r[0]||=e=>ue(`cancel`,z(u).cancel)},null,8,[`text`,`loading`,`disabled`])):A(``,!0),g.value.start?(F(),k(z(V),{key:1,variant:`primary`,text:t.__(`Start`),loading:a.value===`start`,disabled:a.value!==null,"data-tolk-action":`start`,onClick:r[1]||=e=>ue(`start`,z(u).start)},null,8,[`text`,`loading`,`disabled`])):A(``,!0)]),_:1},8,[`title`]),P(z(H),{class:`space-y-3`,"data-tolk-run-summary":``},{default:B(()=>[M(`div`,yf,[P(z(Pn),{text:z(Wo)(p.value),color:z(Go)(p.value),"data-tolk-run-status-badge":``},null,8,[`text`,`color`]),P(z(J),null,{default:B(()=>[N(R(v.value.sites?t.__(`:what into :sites`,{what:v.value.what,sites:v.value.sites}):v.value.what),1)]),_:1})]),P(z(U),null,{default:B(()=>[N(R(le.value),1)]),_:1}),p.value===`pending`?A(``,!0):(F(),j(m,{key:0},[P(Fa,{value:h.value.finished,max:h.value.total,label:t.__(`Run progress`)},null,8,[`value`,`max`,`label`]),M(`div`,bf,[P(z(J),null,{default:B(()=>[N(R(t.__(`:finished of :total items finished`,{finished:z(Q)(h.value.finished),total:z(Q)(h.value.total)})),1)]),_:1}),(F(!0),j(m,null,L(ne.value,e=>(F(),k(z(U),{key:e.key,"data-tolk-count":e.key},{default:B(()=>[N(R(e.text),1)]),_:2},1032,[`data-tolk-count`]))),128))]),P(z(U),{"data-tolk-run-usage":``},{default:B(()=>[N(R(t.__n(`:input input and :output output tokens in :calls call.|:input input and :output output tokens in :calls calls.`,T.value.calls,{input:z(Q)(T.value.input),output:z(Q)(T.value.output),calls:z(Q)(T.value.calls)}))+` `+R(T.value.cost===null?t.__(`The cost is unknown: a model without a price was called.`):t.__(`Estimated cost so far: :cost.`,{cost:z(Xo)(T.value.cost)})),1)]),_:1})],64))]),_:1}),ee.value?(F(),k(z(jn),{key:0,variant:`default`,icon:`info`,"data-tolk-keep-open":``},{default:B(()=>[N(R(t.__(`Keep this tab open while the run is in progress. Closing it pauses the run until you open it again.`)),1)]),_:1})):A(``,!0),te.value?(F(),k(z(jn),{key:1,variant:`warning`,heading:t.__(`This run is not moving`),"data-tolk-stalled":``},{default:B(()=>[M(`div`,xf,[f.value.driver===`cli`?(F(),k(z(J),{key:0},{default:B(()=>[N(R(t.__(`The command running this run has not worked on it for a while and may have stopped. Resume continues the run from here.`)),1)]),_:1})):(F(),k(z(J),{key:1},{default:B(()=>[N(R(t.__(`No queue worker has worked on this run for a while. Start a worker for the queue, or run it in this browser instead.`)),1)]),_:1})),M(`div`,Sf,[P(z(V),{size:`sm`,text:t.__(`Resume`),loading:a.value===`resume`,disabled:a.value!==null,"data-tolk-action":`resume`,onClick:r[2]||=e=>ue(`resume`,z(u).resume)},null,8,[`text`,`loading`,`disabled`]),g.value.takeOver?(F(),k(z(V),{key:0,size:`sm`,variant:`primary`,text:t.__(`Run in this browser instead`),loading:a.value===`take-over`,disabled:a.value!==null,"data-tolk-action":`take-over`,onClick:r[3]||=e=>ue(`take-over`,z(u).takeOver)},null,8,[`text`,`loading`,`disabled`])):A(``,!0)])])]),_:1},8,[`heading`])):A(``,!0),(F(!0),j(m,null,L(i.value,(e,i)=>(F(),k(z(jn),{key:i,variant:`error`,"data-tolk-run-failure":``},{default:B(()=>[M(`div`,Cf,[P(z(J),null,{default:B(()=>[N(R(t.__(`Following the run stopped: :message`,{message:e.error?.message??``})),1)]),_:2},1024),i===0?(F(),k(z(V),{key:0,size:`sm`,text:t.__(`Try again`),"data-tolk-action":`follow-again`,onClick:r[4]||=e=>z(u).follow(n.value)},null,8,[`text`])):A(``,!0)])]),_:2},1024))),128)),_.value?(F(),k(z(jn),{key:2,variant:_.value.variant,"data-tolk-run-result":``},{default:B(()=>[M(`div`,wf,[P(z(J),{as:`p`},{default:B(()=>[N(R(_.value.text),1)]),_:1}),_.value.error?(F(),k(z(J),{key:0,as:`p`,variant:`danger`},{default:B(()=>[N(R(_.value.error),1)]),_:1})):A(``,!0),g.value.retry||g.value.resume?(F(),j(`div`,Tf,[g.value.retry?(F(),k(z(V),{key:0,size:`sm`,text:t.__(`Retry failed`),loading:a.value===`retry`,disabled:a.value!==null,"data-tolk-action":`retry`,onClick:r[5]||=e=>ue(`retry`,z(u).retry)},null,8,[`text`,`loading`,`disabled`])):A(``,!0),g.value.resume?(F(),k(z(V),{key:1,size:`sm`,text:t.__(`Resume`),loading:a.value===`resume`,disabled:a.value!==null,"data-tolk-action":`resume`,onClick:r[6]||=e=>ue(`resume`,z(u).resume)},null,8,[`text`,`loading`,`disabled`])):A(``,!0)])):A(``,!0)])]),_:1},8,[`variant`])):A(``,!0),M(`div`,Ef,[P(z(H),{class:`space-y-3`,"data-tolk-breakdown":``},{default:B(()=>[P(z(W),{size:`lg`,text:t.__(`What it translates`)},null,8,[`text`]),M(`div`,Df,[P(z(Ei),null,{default:B(()=>[P(z(Di),null,{default:B(()=>[P(z(q),null,{default:B(()=>[N(R(t.__(`Content`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(t.__(`Site`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(t.__(`Items`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(t.__(`Skipped`)),1)]),_:1})]),_:1}),P(z(ki),null,{default:B(()=>[(F(!0),j(m,null,L(y.value,e=>(F(),k(z(Oi),{key:e.key,"data-tolk-breakdown-row":e.key},{default:B(()=>[P(z(K),null,{default:B(()=>[N(R(e.type),1)]),_:2},1024),P(z(K),null,{default:B(()=>[N(R(e.site),1)]),_:2},1024),P(z(K),{"data-tolk-breakdown-total":``},{default:B(()=>[N(R(z(Q)(e.total)),1)]),_:2},1024),P(z(K),{"data-tolk-breakdown-skipped":``},{default:B(()=>[N(R(z(Q)(e.skipped)),1)]),_:2},1024)]),_:2},1032,[`data-tolk-breakdown-row`]))),128))]),_:1})]),_:1})]),y.value.length===0?(F(),k(z(U),{key:0},{default:B(()=>[N(R(t.__(`This run has nothing to translate.`)),1)]),_:1})):A(``,!0),(F(!0),j(m,null,L(b.value,e=>(F(),k(z(U),{key:e.reason,"data-tolk-left-out":e.reason},{default:B(()=>[N(R(e.text),1)]),_:2},1032,[`data-tolk-left-out`]))),128)),S.value?(F(),k(z(U),{key:1,"data-tolk-not-localizable":``},{default:B(()=>[N(R(S.value)+` `,1),z(x)?(F(),k(z(sd),{key:0,href:z(x),class:`text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-audit-link":``},{default:B(()=>[N(R(t.__(`Open the setup audit`)),1)]),_:1},8,[`href`])):(F(),j(m,{key:1},[N(R(t.__(`Run php please tolk:doctor for details.`)),1)],64))]),_:1})):A(``,!0)]),_:1}),P(z(H),{class:`space-y-3`,"data-tolk-settings":``},{default:B(()=>[P(z(W),{size:`lg`,text:t.__(`Settings`)},null,8,[`text`]),M(`dl`,Of,[(F(!0),j(m,null,L(C.value,e=>(F(),j(m,{key:e.key},[M(`dt`,kf,R(e.label),1),M(`dd`,{"data-tolk-option":e.key},R(e.value),9,Af)],64))),128))])]),_:1})]),p.value===`pending`||w.value?(F(),k(z(H),{key:3,class:`space-y-3`,"data-tolk-estimate":``,"data-tolk-estimate-finished":w.value?.finished?`true`:`false`},{default:B(()=>[M(`div`,jf,[P(z(W),{size:`lg`,text:t.__(`Estimate`)},null,8,[`text`]),w.value?w.value.finished?A(``,!0):(F(),k(z(U),{key:1},{default:B(()=>[N(R(t.__(`Estimating… :progress`,{progress:w.value.progress})),1)]),_:1})):(F(),k(z(U),{key:0},{default:B(()=>[N(R(t.__(`Estimating…`)),1)]),_:1}))]),w.value?(F(),j(`dl`,Mf,[M(`div`,null,[M(`dt`,Nf,R(t.__(`Segments`)),1),M(`dd`,Pf,R(z(Q)(w.value.segments)),1)]),M(`div`,null,[M(`dt`,Ff,R(t.__(`Characters`)),1),M(`dd`,If,R(z(Q)(w.value.chars)),1)]),M(`div`,null,[M(`dt`,Lf,R(t.__(`Input tokens`)),1),M(`dd`,Rf,R(z(Q)(w.value.inputTokens)),1)]),M(`div`,null,[M(`dt`,zf,R(t.__(`Output tokens`)),1),M(`dd`,Bf,R(z(Q)(w.value.outputTokens)),1)]),M(`div`,null,[M(`dt`,Vf,R(t.__(`Cost`)),1),M(`dd`,Hf,R(w.value.cost===null?t.__(`Unknown`):z(Xo)(w.value.cost)),1)])])):A(``,!0),P(z(U),null,{default:B(()=>[N(R(t.__(`An estimate: the tokens a language takes vary, and so does what a model writes.`))+` `,1),w.value&&w.value.cost===null?(F(),j(m,{key:0},[N(R(t.__(`The cost is unknown because a model has no price.`)),1)],64)):A(``,!0)]),_:1})]),_:1},8,[`data-tolk-estimate-finished`])):A(``,!0),P(z(H),{class:`space-y-3`,"data-tolk-items":``},{default:B(()=>[M(`div`,Uf,[P(z(W),{size:`lg`,text:t.__(`Items`)},null,8,[`text`]),M(`div`,Wf,[P(z(ui),{"model-value":c.value,options:re.value,size:`sm`,"data-tolk-items-filter":``,"onUpdate:modelValue":fe},null,8,[`model-value`,`options`])])]),M(`div`,Gf,[P(z(Ei),null,{default:B(()=>[P(z(Di),null,{default:B(()=>[P(z(q),null,{default:B(()=>[N(R(t.__(`Title`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(t.__(`Site`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(t.__(`Status`)),1)]),_:1}),P(z(q),null,{default:B(()=>[N(R(t.__(`Result`)),1)]),_:1})]),_:1}),P(z(ki),null,{default:B(()=>[(F(!0),j(m,null,L(E.value,e=>(F(),k(z(Oi),{key:e.index,"data-tolk-item":``,"data-tolk-item-status":e.status},{default:B(()=>[P(z(K),null,{default:B(()=>[e.editUrl?(F(),j(`a`,{key:0,href:e.editUrl,class:`text-blue-600 hover:underline dark:text-blue-400`},R(e.title),9,Kf)):(F(),j(`span`,qf,R(e.title),1))]),_:2},1024),P(z(K),null,{default:B(()=>[N(R(e.site),1)]),_:2},1024),P(z(K),null,{default:B(()=>[P(z(Pn),{text:e.statusLabel,color:e.statusColor},null,8,[`text`,`color`])]),_:2},1024),P(z(K),{class:`space-y-1`},{default:B(()=>[e.applied?(F(),k(z(J),{key:0,size:`sm`},{default:B(()=>[N(R(e.applied),1)]),_:2},1024)):A(``,!0),e.corrections.length?(F(),j(`div`,Jf,[P(z(J),{size:`sm`},{default:B(()=>[N(R(e.corrected),1)]),_:2},1024),P(z(V),{size:`sm`,variant:`ghost`,text:t.__(`View changes`),"aria-label":t.__(`View changes to :title in :site`,{title:e.title,site:e.site}),"data-tolk-item-changes":``,onClick:t=>ce(e)},null,8,[`text`,`aria-label`,`onClick`])])):A(``,!0),e.incomplete.length?(F(),k(z(U),{key:2},{default:B(()=>[N(R(t.__(`Left incomplete: :fields`,{fields:e.incomplete.join(`, `)})),1)]),_:2},1024)):A(``,!0),e.kept.length?(F(),k(z(U),{key:3},{default:B(()=>[N(R(t.__(`Not changed: :fields`,{fields:e.kept.map(e=>`${e.handle} (${e.reason})`).join(`, `)})),1)]),_:2},1024)):A(``,!0),e.reason?(F(),k(z(U),{key:4},{default:B(()=>[N(R(e.reason),1)]),_:2},1024)):A(``,!0),e.error?(F(),k(z(J),{key:5,size:`sm`,variant:`danger`,"data-tolk-item-error":``},{default:B(()=>[N(R(e.error)+` `,1),e.rootPage?(F(),j(`a`,{key:0,href:e.rootPage.url,class:`text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-root-page":``},R(t.__(`Open :title`,{title:e.rootPage.title})),9,Yf)):A(``,!0)]),_:2},1024)):A(``,!0),(F(!0),j(m,null,L(e.warnings,(e,t)=>(F(),k(z(U),{key:t},{default:B(()=>[N(R(e),1)]),_:2},1024))),128))]),_:2},1024)]),_:2},1032,[`data-tolk-item-status`]))),128))]),_:1})]),_:1})]),E.value.length===0?(F(),k(z(U),{key:0},{default:B(()=>[N(R(t.__(`No items.`)),1)]),_:1})):A(``,!0),D.value.last_page>1?(F(),j(`div`,Xf,[P(z(U),null,{default:B(()=>[N(R(t.__(`Page :page of :pages`,{page:D.value.page,pages:D.value.last_page})),1)]),_:1}),P(z(V),{size:`sm`,icon:`chevron-left`,"aria-label":t.__(`Previous page`),disabled:D.value.page<=1,onClick:r[7]||=e=>de(D.value.page-1)},null,8,[`aria-label`,`disabled`]),P(z(V),{size:`sm`,icon:`chevron-right`,"aria-label":t.__(`Next page`),disabled:D.value.page>=D.value.last_page,onClick:r[8]||=e=>de(D.value.page+1)},null,8,[`aria-label`,`disabled`])])):A(``,!0),z(oe).open?(F(),k(Na,{key:2,modal:z(oe),corrections:se.value},null,8,[`modal`,`corrections`])):A(``,!0)]),_:1})],8,vf))}};Statamic.booting(()=>{Statamic.$components.register(Gs,Wl),Statamic.$components.register(ql,Kl),Statamic.$components.register(`tolk_model-fieldtype`,Ou),Statamic.$components.register(`tolk_providers-fieldtype`,Ru),Statamic.$components.register(`tolk_site_profile-fieldtype`,id),Statamic.$inertia.register(`tolk::Audit`,Ad),Statamic.$inertia.register(`tolk::Overview`,hf),Statamic.$inertia.register(`tolk::Runs/Index`,_f),Statamic.$inertia.register(`tolk::Runs/Show`,Zf),Ra.listen(),Xs.listen(),Tc.listen(),hl({PipelineStopped:a}).listen(),Xl.register()}); \ No newline at end of file diff --git a/resources/dist/build/assets/cp-CJQDbIPa.js b/resources/dist/build/assets/cp-CJQDbIPa.js new file mode 100644 index 0000000..1df064c --- /dev/null +++ b/resources/dist/build/assets/cp-CJQDbIPa.js @@ -0,0 +1 @@ +var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r},{AfterSaveHooks:n,BeforeSaveHooks:r,Pipeline:i,PipelineStopped:a,Request:o}=__STATAMIC__.savePipeline,{BaseTransition:s,BaseTransitionPropsValidators:c,Comment:l,DeprecationTypes:u,EffectScope:d,ErrorCodes:f,ErrorTypeStrings:p,Fragment:m,KeepAlive:h,ReactiveEffect:g,Static:_,Suspense:v,Teleport:y,Text:b,TrackOpTypes:x,Transition:S,TransitionGroup:ee,TriggerOpTypes:C,VueElement:w,__esModule:T,assertNumber:E,callWithAsyncErrorHandling:te,callWithErrorHandling:ne,camelize:re,capitalize:ie,cloneVNode:ae,compatUtils:oe,compile:se,computed:D,createApp:ce,createBlock:O,createCommentVNode:k,createElementBlock:A,createElementVNode:j,createHydrationRenderer:le,createPropsRestProxy:ue,createRenderer:de,createSSRApp:fe,createSlots:pe,createStaticVNode:me,createTextVNode:M,createVNode:N,customRef:he,defineAsyncComponent:ge,defineComponent:_e,defineCustomElement:ve,defineEmits:ye,defineExpose:be,defineModel:xe,defineOptions:Se,defineProps:Ce,defineSSRCustomElement:we,defineSlots:Te,devtools:Ee,effect:De,effectScope:Oe,getCurrentInstance:ke,getCurrentScope:Ae,getCurrentWatcher:je,getTransitionRawChildren:Me,guardReactiveProps:Ne,h:Pe,handleError:Fe,hasInjectionContext:Ie,hydrate:Le,hydrateOnIdle:Re,hydrateOnInteraction:ze,hydrateOnMediaQuery:Be,hydrateOnVisible:Ve,initCustomFormatter:He,initDirectivesForSSR:Ue,inject:We,isMemoSame:Ge,isProxy:Ke,isReactive:qe,isReadonly:Je,isRef:Ye,isRuntimeOnly:Xe,isShallow:Ze,isVNode:Qe,markRaw:$e,mergeDefaults:et,mergeModels:tt,mergeProps:nt,nextTick:rt,nodeOps:it,normalizeClass:at,normalizeProps:ot,normalizeStyle:st,onActivated:ct,onBeforeMount:lt,onBeforeUnmount:ut,onBeforeUpdate:dt,onDeactivated:ft,onErrorCaptured:pt,onMounted:mt,onRenderTracked:ht,onRenderTriggered:gt,onScopeDispose:_t,onServerPrefetch:vt,onUnmounted:yt,onUpdated:bt,onWatcherCleanup:xt,openBlock:P,patchProp:St,popScopeId:Ct,provide:wt,proxyRefs:Tt,pushScopeId:Et,queuePostFlushCb:Dt,reactive:Ot,readonly:kt,ref:F,registerRuntimeCompiler:At,render:jt,renderList:I,renderSlot:Mt,resolveComponent:Nt,resolveDirective:Pt,resolveDynamicComponent:Ft,resolveFilter:It,resolveTransitionHooks:Lt,setBlockTracking:Rt,setDevtoolsHook:zt,setTransitionHooks:Bt,shallowReactive:Vt,shallowReadonly:Ht,shallowRef:Ut,ssrContextKey:Wt,ssrUtils:Gt,stop:Kt,toDisplayString:L,toHandlerKey:qt,toHandlers:Jt,toRaw:Yt,toRef:Xt,toRefs:Zt,toValue:Qt,transformVNodeArgs:$t,triggerRef:en,unref:R,useAttrs:tn,useCssModule:nn,useCssVars:rn,useHost:an,useId:on,useModel:sn,useSSRContext:cn,useShadowRoot:ln,useSlots:un,useTemplateRef:dn,useTransitionState:fn,vModelCheckbox:pn,vModelDynamic:mn,vModelRadio:hn,vModelSelect:gn,vModelText:_n,vShow:vn,version:yn,warn:bn,watch:xn,watchEffect:Sn,watchPostEffect:Cn,watchSyncEffect:wn,withAsyncContext:Tn,withCtx:z,withDefaults:En,withDirectives:Dn,withKeys:On,withMemo:kn,withModifiers:An,withScopeId:jn}=window.Vue,{Alert:Mn,AuthCard:Nn,Avatar:Pn,Badge:Fn,Button:B,ButtonGroup:In,Calendar:Ln,Card:V,CardList:Rn,CardListItem:zn,CardPanel:Bn,CharacterCounter:Vn,Checkbox:Hn,CheckboxGroup:Un,CodeEditor:Wn,Combobox:Gn,CommandPaletteItem:Kn,ConfirmationModal:qn,ContentDirection:Jn,useContentDirection:Yn,useUiDirection:Xn,Context:Zn,ContextFooter:Qn,ContextHeader:$n,ContextItem:er,ContextLabel:tr,ContextMenu:nr,ContextSeparator:rr,CreateForm:ir,DatePicker:ar,DateRangePicker:or,Description:H,DocsCallout:sr,DragHandle:cr,Dropdown:lr,DropdownItem:ur,DropdownLabel:dr,DropdownMenu:fr,DropdownSeparator:pr,DropdownFooter:mr,DropdownHeader:hr,Editable:gr,ErrorMessage:_r,EmptyStateItem:vr,EmptyStateMenu:yr,Field:br,Header:xr,Heading:U,HoverCard:Sr,Icon:W,Input:Cr,InputGroup:wr,InputGroupAppend:Tr,InputGroupPrepend:Er,Label:Dr,Listing:Or,ListingCustomizeColumns:kr,ListingFilters:Ar,ListingHeaderCell:jr,ListingPagination:Mr,ListingPresets:Nr,ListingPresetTrigger:Pr,ListingRowActions:Fr,ListingSearch:Ir,ListingTable:Lr,ListingTableBody:Rr,ListingTableHead:zr,ListingToggleAll:Br,LivePreview:Vr,LivePreviewPopout:Hr,MiddleEllipsis:Ur,Modal:Wr,ModalClose:Gr,ModalTitle:Kr,Pagination:qr,Panel:Jr,PanelFooter:Yr,PanelHeader:Xr,Popover:Zr,PublishComponents:Qr,PublishContainer:$r,publishContextKey:ei,injectPublishContext:ti,PublishField:ni,PublishFields:ri,PublishFieldsProvider:ii,PublishForm:ai,PublishLocalizations:oi,PublishSections:si,PublishTabs:ci,Radio:li,RadioGroup:ui,Select:di,Separator:fi,Slider:pi,Skeleton:mi,SplitterGroup:hi,SplitterPanel:gi,SplitterResizeHandle:_i,StatusIndicator:vi,Subheading:yi,Switch:bi,TabContent:xi,Stack:Si,StackClose:Ci,StackHeader:wi,StackFooter:Ti,StackContent:Ei,Table:Di,TableCell:G,TableColumn:K,TableColumns:Oi,TableRow:ki,TableRows:Ai,TabList:ji,TabProvider:Mi,Tabs:Ni,TabTrigger:Pi,Text:q,Textarea:Fi,TimePicker:Ii,TimezoneHoverCard:Li,Timezones:Ri,ToggleGroup:zi,ToggleItem:Bi,Widget:Vi,registerIconSet:Hi,registerIconSetFromStrings:Ui}=__STATAMIC__.ui,Wi=/(<\/?\d+>|||\s+)/,Gi=/^(?:<\/?\d+>||)$/,Ki=/^\s+$/;function qi(e){return String(e??``).split(Wi).filter(e=>e!==``).map(e=>({text:e,kind:Ki.test(e)?`space`:Gi.test(e)?`placeholder`:`word`}))}function Ji(e,t){let n=new Set,r=new Set;if(e.length*t.length>25e4)return[n,r];let i=t.length+1,a=new Uint32Array((e.length+1)*i);for(let n=e.length-1;n>=0;n--)for(let r=t.length-1;r>=0;r--)a[n*i+r]=e[n]===t[r]?a[(n+1)*i+r+1]+1:Math.max(a[(n+1)*i+r],a[n*i+r+1]);for(let o=0,s=0;o=a[o*i+s+1]?o++:s++;return[n,r]}function Yi(e,t){let n=0,r=e.map(e=>({...e,changed:e.kind!==`space`&&!t.has(n++)}));return r.forEach((e,t)=>{e.kind===`space`&&(e.changed=!!(r[t-1]?.changed&&r[t+1]?.changed))}),r}function Xi(e,t){let n=qi(e),r=qi(t),i=e=>e.filter(e=>e.kind!==`space`).map(e=>e.text),[a,o]=Ji(i(n),i(r));return{before:Yi(n,a),after:Yi(r,o)}}var J=t({ApiError:()=>Zi,asMap:()=>Y,get:()=>Qi,normalizeError:()=>na,post:()=>$i}),Zi=class extends Error{constructor({status:e,code:t,message:n,data:r}){super(n),this.name=`ApiError`,this.status=e,this.code=t,this.data=r}};function Y(e){return e&&typeof e==`object`&&!Array.isArray(e)?e:{}}function Qi(e,t={}){return ta(`get`,e,{params:t})}function $i(e,t={}){return ta(`post`,e,t)}function ea(){return Statamic.$app.config.globalProperties.$axios}async function ta(e,t,n){let r=ea(),i=/^https?:\/\//i.test(t)?t:cp_url(`tolk/${t.replace(/^\/+/,``)}`);try{return(await r[e](i,n)).data}catch(e){throw na(e)}}function na(e){let t=e?.response,n=t?.data!==null&&typeof t?.data==`object`?t.data:null,r=t?.status??0;return new Zi({status:r,code:typeof n?.code==`string`?n.code:null,message:typeof n?.message==`string`&&n.message!==``?n.message:ra(r),data:n})}function ra(e){return e===0?__(`The server could not be reached.`):__(`The request failed with status :status.`,{status:e})}var ia={untranslated:{text:e=>__n(`:count field untranslated|:count fields untranslated`,e),description:()=>__(`Not translated yet. Translate fills them in.`)},outdated:{text:e=>__n(`:count field outdated|:count fields outdated`,e),description:()=>__(`The source changed since they were translated, or part of their text is still untranslated. Update translates them again.`)},manual:{text:e=>__n(`:count field edited by hand|:count fields edited by hand`,e),description:()=>__(`Edited by hand. Translate and Update leave them alone.`)},attention:{text:e=>__n(`:count needs attention|:count need attention`,e),description:()=>__(`Edited by hand, and the source changed since. Check them against the source.`)},untracked:{text:e=>__n(`:count untracked|:count untracked`,e),description:()=>__(`Edited by hand before their translation was tracked, so a change to the source cannot be detected. Mark them as up to date to track them.`)},current:{text:e=>__n(`:count field up to date|:count fields up to date`,e),description:()=>__(`Translated and up to date with the source.`)}},aa={missing:`red`,untranslated:`orange`,outdated:`amber`,attention:`purple`,manual:`sky`,untracked:`default`,current:`green`};function oa(e){return aa[e]??`default`}function sa(e){return{missing:__(`Missing`),untranslated:__(`Untranslated`),outdated:__(`Outdated`),attention:__(`Needs attention`),current:__(`Up to date`)}[e]??e}function ca(e={}){return Object.entries(ia).filter(([t])=>(e[t]??0)>0).map(([t,n])=>({key:t,count:e[t],text:n.text(e[t]),description:n.description()}))}function la(e){let t=e?.defaults??{};return!(t.providers_configured||t.fake_engine)||!t.translator}function ua(e){if(e?.translatable!==!0)return{visible:!1,reason:e?.reason??null,setup:!1,translator:null,localization:null,origin:null};let t=la(e);return{visible:!0,reason:null,setup:t,translator:e.defaults?.translator??null,localization:e.localization?da(e.localization,t):null,origin:e.origin?_a(e.origin,t):null}}function da(e,t){let n=e.counts??{},r=ca(n),i=Object.entries(e.fields??{}).filter(([,e])=>e.incomplete).map(([e,t])=>({handle:e,label:t.label})),a=(e.out_of_scope??[]).filter(e=>e.reason===`not_localizable`).map(({handle:e,label:t})=>({handle:e,label:t})),o=pa(e,r);return{source:e.source,target:e.target,status:e.status,label:sa(e.status),parts:r,summary:o,lead:r.length>0?__(`From :source:`,{source:e.source?.name??``}):o,incomplete:i,incompleteNote:i.length?ma(i):null,notLocalizable:a,hint:a.length?ha(ga(a),a.length):null,translate:!t&&(n.untranslated??0)>0,update:!t&&(n.outdated??0)>0,autoUpdated:fa(e.auto_updated,e.source)}}function fa(e,t){let n=Date.parse(e?.at??``);if(Number.isNaN(n))return null;let r={source:t?.name??``,date:new Intl.DateTimeFormat(void 0,{dateStyle:`medium`,timeStyle:`short`}).format(n)};return e.unpublished?__(`Updated automatically from :source on :date, not published yet.`,r):__(`Updated automatically from :source on :date.`,r)}function pa(e,t){let n=e.source?.name??``;return t.length===0?__(`Nothing to translate from :source.`,{source:n}):t.every(e=>e.key===`current`)?__(`Up to date with :source.`,{source:n}):__(`From :source: :parts.`,{source:n,parts:t.map(e=>e.text).join(`, `)})}function ma(e){return __n(`:fields is partly untranslated. Update translates the rest.|:fields are partly untranslated. Update translates the rest.`,e.length,{fields:ga(e)})}function ha(e,t){return __n(`:fields is not translated because it is not localizable.|:fields are not translated because they are not localizable.`,t,{fields:e})}function ga(e){return e.map(e=>e.label).join(`, `)}function _a(e,t){let n=(e.localizations??[]).map(e=>{let t=!e.exists,n=e.counts??{},r=t?[]:ca(n);return{site:e.site,name:e.name,exists:e.exists,status:e.status,label:sa(e.status),color:oa(e.status),parts:r,summary:va(e,r),editUrl:e.edit_url??null,translate:t||(n.untranslated??0)>0,update:!t&&(n.outdated??0)>0}});return{localizations:n,upToDate:n.length>0&&n.every(e=>e.status===`current`),translateInto:!t&&n.some(e=>e.translate),update:!t&&n.some(e=>e.update),autoUpdate:{save:__(`Translations are updated automatically each time this entry is saved.`),publish:__(`Translations are updated automatically when this entry is published.`)}[e.auto_update]??null}}function va(e,t){return e.exists?t.length===0?__(`Nothing to translate.`):t.every(e=>e.key===`current`)?null:t.map(e=>e.text).join(`, `):__(`Not created yet.`)}function ya(e,t=globalThis.Statamic?.$config?.get(`tolk.models`)){if(typeof t?.[e]==`string`)return t[e];let n=e.indexOf(`:`);return n===-1?e:e.slice(n+1)}function ba(e,t){let n=Y(t?.localization?.fields);return e.map(e=>n[e]?.label??e).join(`, `)}function xa(e,t=null){if(!e)return null;let n=e.kind===`review`,r=e.delivered.length,i=e.corrections?.length??0,a=Object.keys(e.skipped).filter(t=>e.skipped[t]===`edited`),o=Object.keys(e.planSkipped??{}).filter(t=>e.planSkipped[t]===`manual`),s=Object.keys(e.failed);return{translated:n?null:Ca(r,Sa(e)),reviewed:wa(e,i),corrections:i,reviewSkipped:e.reviewSkipped?.length?__(`Part of the text could not be reviewed and was kept as it was.`):null,incomplete:e.incomplete.length?__n(`:fields is partly untranslated. Update translates the rest after you save.|:fields are partly untranslated. Update translates the rest after you save.`,e.incomplete.length,{fields:ba(e.incomplete,t)}):null,edited:a.length?__n(`:fields was skipped because you edited it.|:fields were skipped because you edited them.`,a.length,{fields:ba(a,t)}):null,manual:o.length?Ta(o,n,t):null,failed:s.length?n?__n(`:fields could not be reviewed.|:fields could not be reviewed.`,s.length,{fields:ba(s,t)}):__n(`:fields could not be translated.|:fields could not be translated.`,s.length,{fields:ba(s,t)}):null,cancelled:e.cancelled?n?__(`The review was cancelled before it finished.`):__(`The translation was cancelled before it finished.`):null,unsaved:r>0?__(`Not saved yet. Check the fields, then save.`):null}}function Sa(e){let t=e.models.filter(t=>t!==e.reviewer);return(t.length?t:e.models).map(e=>ya(e)).join(`, `)}function Ca(e,t){return e===0?__(`No fields were translated.`):t?__n(`:count field translated with :model.|:count fields translated with :model.`,e,{model:t}):__n(`:count field translated.|:count fields translated.`,e)}function wa(e,t){if(e.kind===`review`&&(e.planned??[]).length===0)return __(`There was nothing to review: no field holds a translation that is up to date.`);if(!e.reviewer||!e.reviewedUnits?.length)return null;let n=ya(e.reviewer);return t>0?__n(`Reviewed with :model: :count correction.|Reviewed with :model: :count corrections.`,t,{model:n}):__(`Reviewed with :model: nothing to correct.`,{model:n})}function Ta(e,t,n){let r=ba(e,n);return t?__n(`:fields was not reviewed because it was edited by hand. Overwrite manual edits in the options reviews it too.|:fields were not reviewed because they were edited by hand. Overwrite manual edits in the options reviews them too.`,e.length,{fields:r}):__n(`:fields was skipped because it was edited by hand. Overwrite manual edits in the options replaces it.|:fields were skipped because they were edited by hand. Overwrite manual edits in the options replaces them.`,e.length,{fields:r})}var Ea={class:`space-y-6`},Da={class:`space-y-2 text-sm`},Oa={class:`text-xs font-medium text-gray-500 dark:text-gray-400`},ka={class:`whitespace-pre-wrap`,"data-tolk-change-before":``},Aa={class:`text-xs font-medium text-gray-500 dark:text-gray-400`},ja={class:`whitespace-pre-wrap`,"data-tolk-change-after":``},Ma={class:`text-xs font-medium text-gray-500 dark:text-gray-400`},Na={class:`whitespace-pre-wrap`,"data-tolk-change-reason":``},Pa={class:`flex items-center justify-end gap-3 pt-3 pb-1`},Fa={__name:`ChangesModal`,props:{modal:{type:Object,required:!0},corrections:{type:Array,default:()=>[]},reviewer:{type:String,default:null}},setup(e){let t=e,n=D(()=>t.corrections.map(e=>({...e,key:`${e.handle}:${e.id}`,diff:Xi(e.before,e.after)})));function r(e,t){return e.kind===`placeholder`?[`font-mono text-xs text-gray-500 dark:text-gray-400`,e.changed&&`rounded-sm bg-amber-100 dark:bg-amber-900/40!`]:e.changed?t===`before`?`rounded-sm bg-red-100 text-red-900 line-through dark:bg-red-900/40! dark:text-red-100`:`rounded-sm bg-green-100 text-green-900 underline decoration-green-700/60 dark:bg-green-900/40! dark:text-green-100 dark:decoration-green-300/60`:null}return(t,i)=>(P(),O(R(Wr),{open:``,title:t.__(`Changes by the reviewer`),icon:`dictionary-language-book`,"data-tolk-changes":``,onDismissed:i[1]||=t=>e.modal.dismissed(),"onUpdate:open":i[2]||=t=>e.modal.closed(t)},{footer:z(()=>[j(`div`,Pa,[N(R(B),{variant:`primary`,text:t.__(`Close`),"data-tolk-changes-action":`close`,onClick:i[0]||=t=>e.modal.hide()},null,8,[`text`])])]),default:z(()=>[j(`div`,Ea,[e.reviewer?(P(),O(R(H),{key:0},{default:z(()=>[M(L(t.__(`Corrected by :model. The corrections are in the form; nothing is saved until you press Save.`,{model:R(ya)(e.reviewer)})),1)]),_:1})):k(``,!0),(P(!0),A(m,null,I(n.value,e=>(P(),A(`div`,{key:e.key,class:`space-y-2`,"data-tolk-change":``},[N(R(U),{"data-tolk-change-label":``},{default:z(()=>[M(L(e.label),1)]),_:2},1024),j(`dl`,Da,[j(`div`,null,[j(`dt`,Oa,L(t.__(`Before`)),1),j(`dd`,ka,[(P(!0),A(m,null,I(e.diff.before,(e,t)=>(P(),O(Ft(e.changed?`del`:`span`),{key:t,class:at(r(e,`before`)),"data-tolk-removed":e.changed&&e.kind!==`space`?``:null},{default:z(()=>[M(L(e.text),1)]),_:2},1032,[`class`,`data-tolk-removed`]))),128))])]),j(`div`,null,[j(`dt`,Aa,L(t.__(`After`)),1),j(`dd`,ja,[(P(!0),A(m,null,I(e.diff.after,(e,t)=>(P(),O(Ft(e.changed?`ins`:`span`),{key:t,class:at(r(e,`after`)),"data-tolk-added":e.changed&&e.kind!==`space`?``:null},{default:z(()=>[M(L(e.text),1)]),_:2},1032,[`class`,`data-tolk-added`]))),128))])]),j(`div`,null,[j(`dt`,Ma,L(t.__(`Reason`)),1),j(`dd`,Na,L(e.reason),1)])])]))),128))])]),_:1},8,[`title`]))}},Ia=[`aria-label`,`aria-valuemax`,`aria-valuenow`],La={__name:`ProgressBar`,props:{value:{type:Number,default:0},max:{type:Number,default:0},label:{type:String,required:!0}},setup(e){let t=e,n=D(()=>t.max>0?Math.min(100,Math.round(t.value/t.max*100)):0);return(t,r)=>(P(),A(`div`,{role:`progressbar`,"aria-label":e.label,"aria-valuemin":`0`,"aria-valuemax":e.max,"aria-valuenow":e.value,class:`h-1.5 w-full overflow-hidden rounded-full bg-gray-200 dark:bg-gray-700`,"data-tolk-progress":``},[j(`div`,{class:`h-full rounded-full bg-blue-600 transition-[width] duration-300 dark:bg-blue-400!`,style:st({width:`${n.value}%`})},null,4)],8,Ia))}},X=`base`;function Ra(){let e=Vt(new Map),t=!1;function n(e=Statamic.$events){t||(t=!0,e.$on(`publish-container-created`,r),e.$on(`publish-container-destroyed`,i))}function r(t){let n=(e.get(t.name)?.mounted??0)+1;e.set(t.name,{payload:t,context:null,clean:null,mounted:n})}function i({name:t}){let n=e.get(t);n&&(n.mounted>1?e.set(t,{...n,mounted:n.mounted-1}):e.delete(t))}function a(t,n){let r=e.get(t)??{payload:null,context:null,clean:null,mounted:0};e.set(t,{...r,...n})}function o(t,n){a(t,{context:n,clean:e.get(t)?.clean??Z(n.values.value)})}function s(e){let t=c(e);t!==null&&a(e,{clean:Z(t)})}function c(t){let n=e.get(t);return(n?.context??n?.payload)?.values?.value??null}function l(t){let n=e.get(t)?.clean,r=c(t);return!n||r===null?[]:[...new Set([...Object.keys(r),...Object.keys(n)])].filter(e=>!Ha(r[e],n[e]))}return{listen:n,attachContext:o,refreshClean:s,dirtyHandles:l,context:t=>e.get(t)?.context??null,payload:t=>e.get(t)?.payload??null,base:()=>e.get(`base`)?.context??null,others:()=>[...e.keys()].filter(e=>e!==X)}}var za=Ra();function Z(e){return Array.isArray(e)?e.map(Z):typeof e!=`object`||!e?e:Object.fromEntries(Object.keys(e).map(t=>[t,Z(e[t])]))}var Ba=new Set([`type`,`id`,`_id`,`marks`]);function Va(e){return typeof e==`string`?e:Array.isArray(e)?e.map(Va).join(``):typeof e!=`object`||!e?``:Object.keys(e).filter(e=>!Ba.has(e)).sort().map(t=>Va(e[t])).join(``)}function Ha(e,t){return Va(e)===Va(t)}var Ua=2e3,Wa=1e3,Ga=100,Ka=50,qa=e=>new Promise(t=>setTimeout(t,e)),Ja=e=>typeof e==`function`?e:()=>e,Ya=(e,t,n)=>()=>e.reference.value===t&&n();async function Xa(e,t,n){let r=()=>600-(t()-e());for(let e=r();e>0;e=r())await n(e)}function Za(e,t,n){return Object.hasOwn(t,n)?!Ha(e.values.value[n],t[n]):e.values.value[n]!==void 0}function Qa(e,t,n){return n===null&&typeof e.values.value[t]==`string`?``:Z(n)}function $a(e,t){return!!t&&!t.pending&&t.plan!==e.delivered?.plan}function eo(e,t,n={}){let r=e.localizedFields.value;return{reference:e.reference.value,dirty:Statamic.$dirty.has(e.name.value),fields:Object.fromEntries(t.map(t=>[t,{value:Z(e.values.value[t]),meta:Z(e.meta.value[t]),localized:r.includes(t),delivered:n[t]?Z(n[t]):null}]))}}async function to(e,t,{reference:n,plan:r,lastChangeAt:i=0,planValues:a={},delivered:o,now:s=Date.now,sleep:c=qa,active:l=()=>!0}){let u=Object.keys(t??{}),d={stale:!1,applied:[],skipped:{},repeated:[]},f=()=>(d.stale=!0,d.applied=[],d.skipped=Object.fromEntries(u.map(e=>[e,`stale`])),d),p=Ya(e,n,l);if(!p()||(await Xa(Ja(i),s,c),!p()))return f();let m=[];for(let n of u){let i=t[n];if(o[n]?.plan===r){d.repeated.push(n);continue}if(Za(e,a,n)){d.skipped[n]=`edited`;continue}o[n]={plan:r,value:void 0,pending:!0,incomplete:!!i.incomplete,sync:!!i.sync},i.meta!==void 0&&e.setFieldMeta(n,Z(i.meta)),e.setFieldValue(n,Qa(e,n,i.value)),i.sync?(co(e,n,!1),Statamic.$dirty.add(e.name.value),m.push(n)):(e.desyncField(n),e.localizedFields.value.includes(n)||(co(e,n,!0),Statamic.$dirty.add(e.name.value))),d.applied.push(n)}if(!d.applied.length)return d;if(await c(300),!p())return d.applied.forEach(e=>delete o[e]),f();m.forEach(t=>co(e,t,!1));for(let t of d.applied)o[t]={...o[t],value:Z(e.values.value[t]),pending:!1};return d}async function no(e,t,n,{registry:r=za,sleep:i=qa}={}){let a={restored:[],kept:[]};if(!t||e.reference.value!==t.reference)return a;for(let[r,i]of Object.entries(t.fields)){let t=n[r];if($a(i,t)){if(!Ha(e.values.value[r],t.value)){a.kept.push(r);continue}a.restored.push(r)}}if(!a.restored.length)return a;e.withoutDirtying(()=>{for(let r of a.restored){let i=t.fields[r];e.setFieldMeta(r,Z(i.meta)),e.setFieldValue(r,Qa(e,r,i.value)),co(e,r,i.localized),i.delivered?n[r]=Z(i.delivered):delete n[r]}});let o=()=>{e.reference.value===t.reference&&(a.restored.forEach(n=>co(e,n,t.fields[n].localized)),!t.dirty&&r.dirtyHandles(e.name.value).length===0&&Statamic.$dirty.remove(e.name.value))};return o(),await i(300),o(),a}async function ro(e,t,{reference:n,lastChangeAt:r=0,now:i=Date.now,sleep:a=qa,active:o=()=>!0}={}){let s=Ja(r),c=Ya(e,n,o),l=()=>s()+Ua-i();if(!c())return{stale:!0,kept:!1,reset:!1};if(!ao(e,t))return{stale:!1,kept:!1,reset:!1};for(await Xa(s,i,a);c()&&!oo(e)&&l()>0;)await a(Math.min(Ga,l()));let u=oo(e);return!c()||!await so(e,t,{sleep:a,current:c})?{stale:!0,kept:!1,reset:u}:{stale:!1,kept:!0,reset:u}}async function io(e,t,{reference:n,sleep:r=qa,active:i=()=>!0}={}){let a=Ya(e,n,i);return!ao(e,t)||(await r(Wa),!a()||e.values.value.slug===t&&!oo(e))?!1:so(e,t,{sleep:r,current:a})}function ao(e,t){return typeof t==`string`&&t!==``&&Object.hasOwn(e.values.value??{},`slug`)}function oo(e){return e.meta.value?.slug?.auto===!0}async function so(e,t,{sleep:n,current:r}){return oo(e)&&e.values.value.slug===t&&(e.setFieldValue(`slug`,``),await n(Ka),!r())?!1:(e.values.value.slug!==t&&e.setFieldValue(`slug`,t),!0)}function co(e,t,n){let r=e.localizedFields.value,i=r.indexOf(t);n&&i===-1?r.push(t):!n&&i!==-1&&r.splice(i,1)}var lo=2e3,uo=5;function fo(e,t){return new Promise(n=>{if(t?.aborted)return n();let r=()=>{clearTimeout(i),t?.removeEventListener(`abort`,r),n()},i=setTimeout(r,e);t?.addEventListener(`abort`,r,{once:!0})})}function po(e){let t=e?.status??0;return t===429||t===503?`wait`:t===409&&e.code===`busy`?`busy`:t===409&&e.code===`source_changed`||t===410||t===502?`stop`:`fail`}function mo(e,t=``){return{status:e?.status??0,code:e?.code??null,message:e?.message||t}}var ho=e=>Object.entries(Y(e)),go=({id:e,fields:t})=>({id:e,fields:t});async function _o({api:e=J,plan:t,concurrency:n=1,onFields:r=()=>{},onProgress:i=()=>{},signal:a=null,finishing:o=()=>!0,sleep:s=fo,maxWaits:c=5,busyMs:l=lo,maxBusyWaits:u=60}){let d=Math.max(1,Math.floor(Number(n))||1),f=[...t.units??[]],p=new Set(f.map(e=>e.id)),m={total:f.length,done:0,waiting:0},h=new Map,g=[],_=[],v=[],y={},b=new Set,x=new Set,S=new Set,ee=new Set,C={},w=null,T=()=>w!==null||!!a?.aborted,E=()=>i({...m});function te(){if(!T())return f.shift();let e=w===null&&o()?f.findIndex(e=>!p.has(e.id)):-1;return e===-1?null:f.splice(e,1)[0]}function ne(e){let t=ho(e).map(([e,t])=>(h.set(e,t),e));t.length&&g.push(Promise.resolve().then(()=>r(e)).then(e=>({handles:t,result:e}),e=>({handles:t,error:e})))}function re(e,t){ne(t?.fields);for(let[e,n]of ho(t?.failed))y[e]=n;(Array.isArray(t?.warnings)?t.warnings:[]).forEach(e=>b.add(e)),(Array.isArray(t?.unchanged)?t.unchanged:[]).forEach(e=>x.add(e)),t?.reviewed===!0&&S.add(e.id),t?.review_skipped===!0&&ee.add(e.id);for(let[e,n]of ho(t?.usage))C[e]=yo(C[e]??{},n);let n=Array.isArray(t?.spawned)?t.spawned:[];f.push(...n),m.total+=n.length}async function ie(n){let r=0,i=0;for(;;)try{return re(n,await e.post(`editor/unit`,{plan:t.plan,unit:n.id}))}catch(e){let t=po(e),o=t===`wait`&&r0?Number(e.data.retry_after):uo;if(m.waiting++,E(),await s(t===`wait`?d*1e3:l,a),m.waiting--,E(),T()){v.push(go(n));return}}}return ne(t.ready),E(),await new Promise(e=>{let t=0,n=()=>{let r;for(;t{t--,m.done++,E(),n()});t===0&&e()};n()}),v.push(...f.map(go)),vo(await Promise.all(g),{received:h,failed:y,failedUnits:_,cancelledUnits:v,warnings:[...b],unchanged:x,reviewedUnits:[...S],reviewSkipped:[...ee],usage:C,stopped:w,aborted:!!a?.aborted,progress:m})}function vo(e,{received:t,failed:n,failedUnits:r,cancelledUnits:i,warnings:a,unchanged:o,reviewedUnits:s,reviewSkipped:c,usage:l,stopped:u,aborted:d,progress:f}){let p=[],m={},h=!1;for(let{handles:t,result:r,error:i}of e){if(i){t.forEach(e=>n[e]??=`not_filled`);continue}h||=r?.stale===!0;for(let e of r?.applied??(r?[]:t))p.includes(e)||p.push(e);Object.assign(m,r?.skipped??{})}for(let e of r)for(let t of e.fields??[])!p.includes(t)&&!(t in m)&&(n[t]??=e.error?.code??`failed`);return p.forEach(e=>delete n[e]),{delivered:p,incomplete:p.filter(e=>t.get(e)?.incomplete===!0),skipped:m,failed:n,failedUnits:r,cancelledUnits:i,warnings:a,corrections:p.flatMap(e=>{let n=t.get(e)?.corrections;return Array.isArray(n)?n.map(t=>({handle:e,...t})):[]}),unchanged:[...o].filter(e=>!p.includes(e)),reviewedUnits:s,reviewSkipped:c,usage:l,models:Object.keys(l),stopped:u,aborted:d,stale:h,units:{total:f.total,done:f.done}}}function yo(e,t){let n={...e};for(let[e,r]of ho(t))typeof r==`number`&&(n[e]=(n[e]??0)+r);return n}var bo=t({BACKOFF_MS:()=>So,FINAL_STATUSES:()=>xo,IDLE_MS:()=>wo,MAX_BACKOFF_MS:()=>Co,MAX_RETRIES:()=>5,POLL_MS:()=>To,backoff:()=>No,estimateLoop:()=>Bo,isFinal:()=>Oo,latest:()=>ko,nonce:()=>Do,pollState:()=>zo,retryable:()=>Mo,startApplyLoop:()=>Lo,startLanes:()=>Io}),xo=[`completed`,`completed_with_errors`,`cancelled`,`aborted`],So=1e3,Co=3e4,wo=1e3,To=2e3,Eo=null;function Do(){return Eo??=Array.from(crypto.getRandomValues(new Uint8Array(12)),e=>e.toString(16).padStart(2,`0`)).join(``),Eo}function Oo(e){return xo.includes(e?.run?.status)}function ko(e){let t=null;return n=>{t!==null&&Ao(n,t)||(t=n,e(n))}}function Ao(e,t){let n=jo(e),r=jo(t);return n=500}function No(e,t=So){return Math.min(t*2**Math.max(0,e-1),Co)}function Po(e,t){return e==null?t:Math.max(0,Number(e)||0)*1e3}async function Fo(e,{retries:t,backoffMs:n,sleep:r,signal:i}){for(let a=1;;a++)try{return{response:await e()}}catch(e){if(i?.aborted)return{};if(a>t||!Mo(e))return{error:mo(e)};if(await r(No(a,n),i),i?.aborted)return{}}}function Io({api:e=J,urls:t,lanes:n=1,nonce:r=Do(),onState:i=()=>{},onFailure:a=()=>{},signal:o=null,query:s=()=>({}),sleep:c=fo,retries:l=5,backoffMs:u=So,idleMs:d=wo}){let f=Math.max(1,Math.floor(Number(n))||1),p=new Map,m=new Set,h=[],g=[],_=()=>!!o?.aborted,v=e=>m.forEach(t=>t(e)),y=()=>[...p.values()].filter(e=>e===`running`).length;function b(e,t){let n={lane:e,error:t};return g.push(n),a(n),`failed`}let x=n=>e.post(t.tick,{...s(),nonce:r,lane:n});async function S(e){for(;!_();){let{response:t,error:n}=await Fo(()=>x(e),{retries:l,backoffMs:u,sleep:c,signal:o});if(_())break;if(n)return b(e,n);if(i(t),v({lane:e,state:t}),Oo(t)||t?.report?.remains!==!0)return`finished`;await c(Po(t.report.wait,d),o)}return`aborted`}function ee(e,t){p.set(e,t),v({lane:e,ended:t}),y()===0&&h.splice(0).forEach(e=>e())}function C(e){p.set(e,`running`),S(e).catch(t=>b(e,mo(t))).then(t=>ee(e,t))}for(let e=1;e<=f;e++)C(e);return{get active(){return y()},failed:g,restart(){if(_())return 0;let e=[...p].filter(([,e])=>e===`finished`).map(([e])=>e);return e.forEach(C),e.length},idle(){return y()===0?Promise.resolve():new Promise(e=>h.push(e))},subscribe(e){return m.add(e),()=>m.delete(e)}}}async function Lo({api:e=J,urls:t,lanes:n=null,onState:r=()=>{},onFailure:i=()=>{},signal:a=null,query:o=()=>({}),sleep:s=fo,retries:c=5,backoffMs:l=So,idleMs:u=wo}){let d=()=>!!a?.aborted,f=null,p=!1,m=null,h=n?.subscribe(e=>{(e.ended||Number(Y(e.state?.counts).translated)>0)&&(p=!0,m?.())})??(()=>{}),g=()=>new Promise(e=>{let t=()=>{m=null,a?.removeEventListener(`abort`,t),e()};m=t,a?.addEventListener(`abort`,t,{once:!0})});try{for(;!d();){p=!1;let{response:m,error:h}=await Fo(()=>e.post(t.apply,o()),{retries:c,backoffMs:l,sleep:s,signal:a});if(d())break;if(h)return i({error:h}),{state:f,error:h};if(f=m,r(m),Oo(m))break;if(n&&Ro(m)&&n.restart(),m?.report?.remains===!0)await s(Po(m.report.wait,u),a);else if(n?.active)p||await g();else break}}finally{h()}return{state:f,error:null}}function Ro(e){let t=e?.run;return t?.status===`running`&&t?.driver===`browser`&&Number(Y(e.counts).pending)>0}async function zo({api:e=J,url:t,interval:n=To,onState:r=()=>{},onFailure:i=()=>{},signal:a=null,query:o=()=>({}),sleep:s=fo,retries:c=5,backoffMs:l=So}){let u=null;for(;!a?.aborted;){let{response:d,error:f}=await Fo(()=>e.get(t,o()),{retries:c,backoffMs:l,sleep:s,signal:a});if(a?.aborted)break;if(f)return i({error:f}),{state:u,error:f};if(u=d,r(d),Oo(d))break;await s(n,a)}return{state:u,error:null}}async function Bo({api:e=J,url:t,estimate:n=null,onEstimate:r=()=>{},onFailure:i=()=>{},signal:a=null,sleep:o=fo,retries:s=5,backoffMs:c=So}){let l=n,u=n===null?0:n.next===null?null:Math.max(0,Math.floor(Number(n.next))||0);for(;u!==null&&!a?.aborted;){let{response:n,error:d}=await Fo(()=>e.post(t,{from:u}),{retries:s,backoffMs:c,sleep:o,signal:a});if(a?.aborted)break;if(d)return i({error:d}),{estimate:l,error:d};l=n,r(n),u=Number.isInteger(n?.next)?n.next:null}return{estimate:l,error:null}}var Vo=[`pending`,`translating`,`translated`,`applying`,`done`,`skipped`,`failed`],Ho=[`pending`,`translating`,`translated`,`applying`],Uo={pending:`default`,running:`blue`,completed:`green`,completed_with_errors:`orange`,cancelled:`amber`,aborted:`red`},Wo={pending:`default`,translating:`blue`,translated:`sky`,applying:`blue`,done:`green`,skipped:`default`,failed:`red`};function Go(e){return{pending:__(`Not started`),running:__(`Running`),completed:__(`Completed`),completed_with_errors:__(`Completed with errors`),cancelled:__(`Cancelled`),aborted:__(`Aborted`)}[e]??e}function Ko(e){return Uo[e]??`default`}function qo(e){return{pending:__(`Waiting`),translating:__(`Translating`),translated:__(`Translated, not saved yet`),applying:__(`Saving`),done:__(`Done`),skipped:__(`Skipped`),failed:__(`Failed`)}[e]??e}function Jo(e){return Wo[e]??`default`}function Yo(e){return{entry:__(`Entries`),term:__(`Terms`),globals:__(`Global sets`),nav:__(`Navigation`)}[e]??e}function Xo(e=[]){let t=Object.fromEntries((Array.isArray(e)?e:[]).map(e=>[e.handle,e.name]));return e=>t[e]??e}function Q(e,t=void 0){return new Intl.NumberFormat(t).format(Number(e)||0)}function Zo(e,t=void 0){let n=Number(e)||0,r=n>0&&n<.01?{maximumSignificantDigits:2}:{minimumFractionDigits:2,maximumFractionDigits:2};return new Intl.NumberFormat(t,{style:`currency`,currency:`USD`,...r}).format(n)}function Qo(e,t=void 0){let n=Date.parse(e??``);return Number.isNaN(n)?``:new Intl.DateTimeFormat(t,{dateStyle:`medium`,timeStyle:`short`}).format(n)}function $o(e){let t={...Object.fromEntries(Vo.map(e=>[e,0])),...Y(e?.counts)},n=Vo.reduce((e,n)=>e+(Number(t[n])||0),0),r=Ho.reduce((e,n)=>e+(Number(t[n])||0),0);return{counts:t,total:n,finished:n-r,unfinished:r}}function es(e){let t=e?.run??{},{counts:n,unfinished:r}=$o(e),i=Oo(e),a=t.status===`running`&&!!e?.stalled;return{start:t.status===`pending`,cancel:t.status===`running`,resume:a||[`cancelled`,`aborted`].includes(t.status)&&r>0,retry:i&&n.failed>0,takeOver:a&&t.driver===`queue`}}function ts(e,t){let n=[t];return e.skipped>0&&n.push(__n(`:count skipped|:count skipped`,e.skipped)),e.failed>0&&n.push(__n(`:count failed|:count failed`,e.failed)),n.join(`, `)}function ns(e){let t=e?.run??{};if(!Oo(e))return null;let{counts:n}=$o(e),r=ts(n,__n(`:count done|:count done`,n.done));return{status:t.status,variant:{completed:`success`,completed_with_errors:`warning`,cancelled:`warning`,aborted:`error`}[t.status],text:{completed:__(`The run is complete: :items.`,{items:r}),completed_with_errors:__(`The run is complete, with errors: :items.`,{items:r}),cancelled:__(`The run was cancelled: :items.`,{items:r}),aborted:__(`The run was stopped: :items.`,{items:r})}[t.status],error:t.error??null}}function rs(e,t=e=>e){return(Array.isArray(e)?e:[]).map(({type:e,site:n,counts:r})=>{let i=$o({counts:r});return{key:`${e}|${n}`,type:Yo(e),site:t(n),total:i.total,skipped:i.counts.skipped,done:i.counts.done,failed:i.counts.failed}})}function is(e){let t={excluded_collection:e=>__n(`:count target is in a collection excluded in the settings.|:count targets are in collections excluded in the settings.`,e),site_not_in_collection:e=>__n(`:count target is in a site its collection does not have.|:count targets are in sites their collection does not have.`,e),unauthorized:e=>__n(`:count target is one you may not edit.|:count targets are ones you may not edit.`,e),from_site:e=>__n(`:count target is a navigation in the site it is translated from.|:count targets are navigations in the site they are translated from.`,e)};return Object.entries(Y(e?.skipped)).filter(([,e])=>Number(e)>0).map(([e,n])=>({reason:e,text:t[e]?.(Number(n))??__(`:count targets left out: :reason.`,{count:n,reason:e.replaceAll(`_`,` `)})}))}function as(e){let t=(Array.isArray(e?.out_of_scope)?e.out_of_scope:[]).filter(e=>e.reason===`not_localizable`);if(t.length===0)return null;let n=new Set(t.map(e=>e.container));return ha(t.map(e=>n.size>1?`${e.label||e.handle} (${e.container})`:e.label||e.handle).join(`, `),t.length)}function os(e,t=e=>e){let n=t=>Array.isArray(e?.[t])?e[t]:[],r=n(`collections`),i=n(`taxonomies`),a=n(`globals`),o=n(`navs`),s=n(`entry_ids`).length,c=n(`term_ids`).length,l=[],u=(e,t)=>{e.includes(`*`)?l.push(t):e.length>0&&l.push(e.join(`, `))};return u(r,__(`All collections`)),s>0&&l.push(__n(`:count selected entry|:count selected entries`,s)),u(i,__(`All taxonomies`)),c>0&&l.push(__n(`:count selected term|:count selected terms`,c)),u(a,__(`All global sets`)),u(o,__(`All navigation`)),{what:l.join(`, `)||__(`Nothing selected`),sites:n(`sites`).map(t).join(`, `),automatic:e?.automatic===!0}}function ss(e,t={}){let n=e=>e?Y(t)[e]??e:null,r=[{key:`mode`,label:__(`Translate`),value:{missing:__(`Only what is not translated yet`),update:__(`Also update outdated translations`),all:__(`Retranslate everything`),review:__(`Review existing translations`)}[e?.mode]??e?.mode??``},{key:`translator`,label:__(`Model`),value:n(e?.translator)??__(`Default`)},{key:`review`,label:__(`Review`),value:e?.review?n(e?.reviewer)??__(`On`):__(`Off`)},{key:`overwrite_manual`,label:__(`Manual edits`),value:e?.overwrite_manual?__(`Overwritten`):__(`Kept`)},{key:`new_status`,label:__(`New localizations`),value:e?.new_status===`mirror`?__(`Same as origin`):__(`Drafts`)}];return e?.publish_changes&&r.push({key:`publish_changes`,label:__(`Revisions`),value:__(`Changes are published`)}),r}function cs(e,t=0){if(!e)return null;let n=Number.isInteger(e.next)?e.next:null;return{finished:n===null,progress:n===null?null:__(`:done of :total items`,{done:Math.min(n,t),total:t}),segments:Number(e.segments)||0,chars:Number(e.chars)||0,inputTokens:Number(e.input_tokens)||0,outputTokens:Number(e.output_tokens)||0,cost:e.cost===null||e.cost===void 0?null:Number(e.cost)}}function ls(e,t={}){let n=Object.entries(Y(e?.usage)).map(([e,n])=>({model:Y(t)[e]??e,input:Number(n?.input)||0,output:Number(n?.output)||0,calls:Number(n?.calls)||0}));return{rows:n,input:n.reduce((e,t)=>e+t.input,0),output:n.reduce((e,t)=>e+t.output,0),calls:n.reduce((e,t)=>e+t.calls,0),cost:e?.cost===null||e?.cost===void 0?null:Number(e.cost)}}var us={current:()=>__(`up to date`),outdated:()=>__(`outdated, not updated in this mode`),untranslated:()=>__(`not translated yet`),manual:()=>__(`edited by hand, kept`),target_changed:()=>__(`edited meanwhile, kept`),not_applicable:()=>__(`empty in the source`),not_requested:()=>__(`not requested`),origin_untranslated:()=>__(`not translated in its source yet`),structure_differs:()=>__(`its structure differs from the source`),no_corrections:()=>__(`reviewed, nothing to correct`)},ds={nothing_to_do:()=>__(`Nothing to do.`),dependency_failed:()=>__(`An item it depends on failed.`),unauthorized:()=>__(`You may not edit it.`),target_changed:()=>__(`Edited by someone while it was being translated.`),no_corrections:()=>__(`Reviewed, nothing to correct.`),source_changed:()=>__(`Its source changed, so it is translated again.`)};function fs(e,t=e=>e){let n=Object.entries(Y(e?.fields)),r=e=>n.filter(([,t])=>t===e).map(([e])=>e),i=n.filter(([,e])=>e===`applied`||e===`incomplete`).length,a=n.filter(([,e])=>![`applied`,`incomplete`].includes(e)).map(([e,t])=>({handle:e,reason:us[t]?.()??String(t).replaceAll(`_`,` `)})),o=e?.reason?ds[e.reason]?.()??null:null,s=Object.entries(Y(e?.corrections)).flatMap(([e,t])=>(Array.isArray(t)?t:[]).map(t=>({...t,handle:e,label:e})));return{index:e?.index,title:e?.title||e?.source_id||``,site:t(e?.target_site),status:e?.status,statusLabel:qo(e?.status),statusColor:Jo(e?.status),editUrl:e?.edit_url??null,applied:i>0?__n(`:count field saved|:count fields saved`,i):null,incomplete:r(`incomplete`),kept:a,reason:o,error:e?.error??null,rootPage:e?.root_page?.edit_url?{title:e.root_page.title||``,url:e.root_page.edit_url}:null,warnings:Array.isArray(e?.warnings)?e.warnings:[],corrected:s.length>0?__n(`:count correction|:count corrections`,s.length):null,corrections:s}}function ps({urls:e,lanes:t=1,onState:n=()=>{},onEstimate:r=()=>{},onFailures:i=()=>{},query:a=()=>({}),api:o=J,ticker:s=bo}){let c=null,l=()=>{},u=null,d=null,f=[];function p(e){f=[...f,e],i(f)}function m(){c?.abort(),c=null,u=null,d=null}function h(r){m();let h=new AbortController;c=h,l=s.latest(n),f=[],i(f),l(r);let _=r?.run??{},v={onState:l,onFailure:p,signal:h.signal,query:a};if(_.status===`pending`)g(_.estimate??null,h.signal);else if(_.status===`running`&&_.driver===`browser`){u=s.startLanes({api:o,urls:e,lanes:t,...v});let n=s.startApplyLoop({api:o,urls:e,lanes:u,...v}).catch(e=>p({error:mo(e)})).finally(()=>{d===n&&(d=null)});d=n}else _.status===`running`&&s.pollState({api:o,url:e.state,...v}).catch(e=>p({error:mo(e)}))}async function g(t,n){try{let{error:i}=await s.estimateLoop({api:o,url:e.estimate,estimate:t,onEstimate:r,onFailure:p,signal:n});!i&&!n.aborted&&await _()}catch(e){n.aborted||p({error:mo(e)})}}async function _(){let t=c?.signal,n=await o.get(e.state,a());return t&&!t.aborted&&l(n),n}async function v(e,t=!0){let n=await o.post(e,a());return t?h(n):l(n),n}return{follow:h,refresh:_,stop:m,start:()=>v(e.start),cancel:()=>v(e.cancel,!1),resume:()=>v(e.resume),retry:()=>v(e.retry),takeOver:()=>v(e.take_over),get active(){return!!(u&&u.active>0||d)},get failures(){return f}}}var ms=[`idle`,`offer`,`planning`,`working`,`done`,`error`];function hs(){return{reference:null,status:null,phase:`idle`,progress:{total:0,done:0,waiting:0,cancelling:!1},summary:null,snapshot:null,delivered:{},lastChangeAt:0,planReference:null,error:null,request:null,notSaved:[],created:!1,slugKept:!1,push:null}}var gs=null;function _s(){return gs??=Statamic.$pinia.defineStore(`tolk-editor`,{state:()=>({containers:{}}),getters:{phaseOf:e=>t=>e.containers[t]?.phase??`idle`},actions:{container(e){return this.containers[e]??=hs(),this.containers[e]},switched(e,t,n=Date.now()){this.containers[e]={...hs(),reference:t,lastChangeAt:n}},saved(e,t=Date.now()){let n=this.container(e),r=Object.keys(n.delivered);return n.lastChangeAt=Math.max(n.lastChangeAt,t),n.delivered={},r},setPhase(e,t,n=null){if(!ms.includes(t))throw Error(`Unknown editor phase [${t}].`);let r=this.container(e);r.phase=t,r.error=t===`error`?n:null},clearResult(e){Object.assign(this.container(e),{summary:null,snapshot:null,request:null}),this.setPhase(e,`idle`)},forget(e){delete this.containers[e]}}}),gs()}var vs=[`starting`,`running`,`expecting`],ys=[1e3,2e3,4e3,8e3,15e3];function bs(e){let t=e?.origin?.auto_update_sites??[];return(e?.origin?.localizations??[]).filter(e=>t.includes(e.site)).filter(e=>!e.exists||[`untranslated`,`outdated`].includes(e.status)).map(e=>e.site)}function xs(e){return(e?.localizations??[]).filter(e=>e.translate).map(({site:e,name:t,exists:n,summary:r})=>({site:e,name:t,missing:!n,summary:r}))}function Ss(e){return(e?.localizations??[]).filter(e=>e.update).map(e=>e.site)}function Cs(e){return(e?.origin?.localizations??[]).filter(e=>!e.exists).map(e=>e.site)}function ws(e,t){if(!e)return null;let n=new Map((t?.origin?.localizations??[]).map(e=>[e.site,e])),r=e=>n.get(e)?.name??e,i=e.state,a=(e.sites?.length?e.sites:i?.run?.scope?.sites??[]).map(r),o=$o(i),s=i?Oo(i):!1,c=s?ns(i):null,l=s?(e.missing??[]).filter(e=>n.get(e)?.exists):[];return{sites:a.join(`, `),automatic:!!e.automatic,progress:o,keepOpen:e.phase===`running`&&e.driver===`browser`,failure:e.failures?.length?e.failures.at(-1).error?.message??null:null,error:e.phase===`error`?e.error?.message??null:null,result:c&&{...c,text:Ts(c.status,o.counts),items:(i.items??[]).map(e=>{let t=fs(e,r);return{...t,handle:e.target_site,editUrl:n.get(e.target_site)?.edit_url??t.editUrl}})},reload:l.length>0}}function Ts(e,t){let n=ts(t,__n(`:count saved|:count saved`,t.done));return{completed:__(`The translations are done: :items.`,{items:n}),completed_with_errors:__(`The translations are done, with errors: :items.`,{items:n}),cancelled:__(`The translations were cancelled: :items.`,{items:n}),aborted:__(`The translations were stopped: :items.`,{items:n})}[e]}function Es({store:e=_s,api:t=J,createFollower:n=ps,wait:r=e=>new Promise(t=>setTimeout(t,e)),delays:i=ys}={}){let a=new Map,o=0;function s(t){return Object.values(e().containers).filter(e=>e.push?.run===t)}function c(e,t){for(let n of s(e))n.push.state=t,Oo(t)&&n.push.phase===`running`&&(n.push.phase=`finished`,n.push.cancelling=!1,u(n.reference));Oo(t)&&a.delete(e)}function l(e,t){for(let n of s(e))n.push.failures=t}async function u(n){try{let r=await t.get(`editor/status`,{reference:n});for(let t of Object.values(e().containers))t.reference===n&&(t.status=r)}catch(e){e?.status!==403&&Statamic.$toast.error(__(`The translation status could not be updated: :message`,{message:e?.message??``}))}}function d(e,{run:t=null,driver:n=null,automatic:r=!1,sites:i=null,missing:a=[]}){return{phase:e,run:t,driver:n,automatic:r,sites:i,state:null,failures:[],missing:a,cancelling:!1,error:null}}function f(t,n,r,i=null){e().container(t).push=d(`running`,{run:n.run,driver:n.driver,automatic:n.automatic===!0,sites:i,missing:r})}function p(e){return e?.push?.run?a.get(e.push.run)??null:null}function m(e,t){let r=a.get(e.run);r||(r=n({urls:e.urls,lanes:e.lanes,onState:t=>c(e.run,t),onFailures:t=>l(e.run,t)}),a.set(e.run,r)),r.follow(t)}async function h(n,{reference:r,sites:i,mode:a,overwriteManual:o=!1,review:s=null,newStatus:c=null}){let l=e().container(n);if(vs.includes(l.push?.phase)||l.reference!==r)return null;let u=Cs(l.status).filter(e=>i.includes(e));l.push=d(`starting`,{sites:i,missing:u});try{let l=await t.post(`editor/push`,{reference:r,sites:i,mode:a,overwrite_manual:o,review:s,new_status:c});return e().containers[n]?.reference===r&&f(n,l,u,i),m(l,l.state),l}catch(t){let i=e().containers[n];return i?.reference===r?t?.code===`run_active`&&t.data?.active_run?(i.push=null,await g(n,{active_run:t.data.active_run,origin:i.status?.origin}),null):(i.push={...i.push,phase:`error`,error:mo(t)},null):null}}async function g(n,r){let i=r?.active_run,a=e().containers[n];if(!i||!a||a.push?.run===i.run)return;let o=a.reference;f(n,i,Cs(r));try{m(i,await t.get(i.urls.state))}catch(t){let r=e().containers[n];r?.reference===o&&r.push?.run===i.run&&(r.push.failures=[{error:mo(t)}])}}async function _(n,a){let s=e().containers[n],c=s?.reference;if(a?.active_run){await g(n,a);return}let l=bs(a);if(!s||a?.origin?.auto_update!==`save`||l.length===0||vs.includes(s.push?.phase))return;let u=++o;s.push={...d(`expecting`,{automatic:!0,sites:l}),expecting:u};let f=()=>{let t=e().containers[n];return t?.reference===c&&t.push?.phase===`expecting`&&t.push.expecting===u?t:null};for(let e of i){if(await r(e),!f())return;let i=null;try{i=await t.get(`editor/status`,{reference:c})}catch{}let a=f();if(!a||i===null){a&&(a.push=null);return}if(a.status=i,i.active_run){a.push=null,await g(n,i);return}if(bs(i).length===0){a.push=d(`updated`,{automatic:!0,sites:l});return}}let p=f();p&&(p.push=null)}async function v(t){let n=e().containers[t],r=p(n);if(r){n.push.failures=[];try{r.follow(await r.refresh())}catch(e){n.push.failures=[{error:mo(e)}]}}}async function y(t){let n=e().containers[t],r=p(n);if(r){n.push.cancelling=!0;try{await r.cancel()}catch(e){n.push.cancelling=!1,Statamic.$toast.error(e.message)}}}function b(t){let n=e().containers[t];n&&!vs.includes(n.push?.phase)&&(n.push=null)}return{start:h,adopt:g,afterSave:_,resume:v,cancel:y,dismiss:b,following:e=>a.has(e)}}var Ds=Es(),Os=[`planning`,`working`],ks=[`source_changed`,`plan_expired`,`target_missing`],As=`edited_in_form`;function js(e,t,n){return!!t&&!t.pending&&Ha(e.values.value[n],t.value)}function Ms(e,t,{name:n,registry:r,delivered:i={}}){let a=Y(t?.localization?.fields),o=e.originValues?.value??{},s=new Set(r.dirtyHandles(n));for(let[t,n]of Object.entries(a))n?.status===`untranslated`&&Object.hasOwn(o,t)&&!Ha(e.values.value[t],o[t])&&s.add(t);return[...s].filter(t=>Object.hasOwn(a,t)&&!js(e,i[t],t))}function Ns(e,t){let n=Y(t?.localization?.fields);return e.localizedFields.value.filter(e=>Object.hasOwn(n,e))}function Ps(e,{overwriteManual:t=!1}={}){let n=Object.values(e?.delivered??{}).some(e=>!e.pending&&!e.sync),r=e?.status?.localization?.counts??{};return n||(r.current??0)>0||t&&(r.manual??0)>0}function Fs(e){let t=new Set([...e?.delivered??[],...Object.keys(e?.skipped??{}),...e?.unchanged??[]]);return(e?.planned??[]).filter(e=>!t.has(e))}function Is(e){let t=e?.status?.localization;return e?.created&&!e.slugKept&&!t?.translate_slug?t?.origin_slug??null:null}function Ls(e){let t=e?.snapshot?.fields;return t?Object.entries(t).some(([t,n])=>$a(n,e.delivered?.[t])):!1}function Rs(e,t){return __n(`:fields was changed after the translation and was kept.|:fields were changed after the translation and were kept.`,e.length,{fields:ba(e,t)})}function zs(e){return Object.entries(Y(e))}function Bs(e){return Object.fromEntries(zs(e).filter(([,e])=>e===As).map(([e])=>[e,`edited`]))}function Vs(e){return Object.fromEntries(zs(e).filter(([,e])=>e!==As))}function Hs(e,t){return e.replace===!0&&(e.fields??[]).includes(t)}function Us(e,{reference:t,skip:n}){return{reference:t,mode:e.mode,overwrite_manual:e.overwriteManual,fields:e.fields,skip:n,translator:e.translator,review:e.review,reviewer:e.reviewer}}function Ws(e,{reference:t,handles:n,values:r}){return{reference:t,values:Object.fromEntries(n.map(e=>[e,r[e]])),overwrite_manual:e.overwriteManual,reviewer:e.reviewer}}function Gs(e,t){let n=t.snapshot,r=!1;if(!n||n.reference!==e.reference)return e;for(let[i,a]of Object.entries(n.fields))$a(a,t.delivered[i])&&(e.fields[i]=a,r=!0);return r&&(e.dirty=n.dirty),e}function Ks({store:e=_s,registry:t=za,api:n=J,concurrency:r=()=>Statamic.$config.get(`tolk.concurrency`),run:i=_o,fill:a=to,undoFill:o=no,keepSlug:s=ro,recheckSlug:c=io}={}){let l=new Map,u=new Set;function d(e){let t=l.get(e);t&&(l.delete(e),t.controller.abort())}function f(t){let n=l.get(t),r=e().containers[t];n&&!n.controller.signal.aborted&&r?.phase===`working`&&(n.controller.abort(),r.progress={...r.progress,cancelling:!0})}async function p(o,u,{continuing:d=!1}={}){let f=e(),p=t.context(o),m=f.container(o);if(!p||Os.includes(m.phase)||l.has(o)||!p.reference.value)return null;let h=p.reference.value,g={},_=new AbortController,v=()=>l.get(o)?.token===g,y=()=>v()&&f.containers[o]===m&&p.reference.value===h,b=()=>f.containers[o]?.lastChangeAt??0,x=Is(m),S=u.kind===`review`,ee=S?u.fields??Ns(p,m.status):u.fields,C=eo(p,ee??Object.keys(p.values.value),m.delivered),w=Z(p.values.value),T=S?[]:Ms(p,m.status,{name:o,registry:t,delivered:m.delivered}).filter(e=>!Hs(u,e)),[E,te]=S?[`editor/review`,Ws(u,{reference:h,handles:ee,values:w})]:[`editor/plan`,Us(u,{reference:h,skip:T})];d&&Gs(C,m),l.set(o,{token:g,controller:_}),Object.assign(m,{request:u,snapshot:C,summary:null,notSaved:[],planReference:h,progress:hs().progress}),f.setPhase(o,`planning`);let ne=x?s(p,x,{reference:h,lastChangeAt:b,active:v}):null;ne?.catch(()=>{});try{let e=await n.post(E,te);if(!y())return null;if(ne){if(await ne,!y())return null;m.slugKept=!0}f.setPhase(o,`working`),m.progress={...hs().progress,total:e.units?.length??0};let t={reference:h,plan:e.plan,lastChangeAt:b,planValues:w,delivered:m.delivered,active:v},s=await i({api:n,plan:e,concurrency:r(),signal:_.signal,finishing:v,onFields:e=>a(p,e,t),onProgress:e=>{y()&&(m.progress={...e,cancelling:_.signal.aborted})}});if(ne&&s.delivered.length&&y()&&await c(p,x,{reference:h,active:v}),!y())return null;let l={...s,kind:u.kind,reviewer:e.reviewer??null,plan:e.plan,planned:Array.isArray(e.fields)?e.fields:[],skipped:{...Bs(e.skipped),...s.skipped},planSkipped:Vs(e.skipped),warnings:[...new Set([...Array.isArray(e.warnings)?e.warnings:[],...s.warnings??[]])],cancelled:_.signal.aborted};return m.summary=l,f.setPhase(o,s.stopped?`error`:`done`,s.stopped),l}catch(e){return y()&&f.setPhase(o,`error`,mo(e,__(`Something went wrong.`))),null}finally{v()&&l.delete(o)}}function m(e,{mode:t=`missing`,fields:n=null,overwriteManual:r=!1,translator:i=null,review:a=null,reviewer:o=null,replace:s=!1}={}){return p(e,{kind:`translate`,mode:t,fields:n,overwriteManual:r,translator:i,review:a,reviewer:o,replace:s})}function h(e,{fields:t=null,overwriteManual:n=!1,reviewer:r=null}={}){return p(e,{kind:`review`,fields:t,overwriteManual:n,reviewer:r})}function g(t){let n=e().containers[t];if(!n?.request||Os.includes(n.phase))return null;let r=n.summary?Fs(n.summary):n.request.fields;return r!==null&&r.length===0?(e().setPhase(t,`done`),null):p(t,{...n.request,fields:r},{continuing:!0})}async function _(n){let r=e(),i=r.containers[n],a=t.context(n);if(!a||!i?.snapshot||Os.includes(i.phase)||u.has(n))return null;u.add(n);try{let e=await o(a,i.snapshot,i.delivered,{registry:t});return r.containers[n]===i&&r.clearResult(n),e}finally{u.delete(n)}}return{translate:m,review:h,retry:g,cancel:f,abort:d,undo:_,running:e=>l.has(e)}}var qs=Ks(),Js=`tolk-banner`;function Ys(e){return typeof e==`string`&&e.startsWith(`term::`)}function Xs(e,t){return[`idle`,`done`,`error`].includes(e)&&!!t?.localization&&!t?.setup}function Zs(e){let t=e?.reference?.value;return e?.name===`base`&&typeof t==`string`&&(t.startsWith(`entry::`)||Ys(t))&&Statamic.$config.get(`tolk.multisite`)===!0&&Statamic.$permissions.has(`translate content`)}function Qs({store:e=_s,abort:t=e=>qs.abort(e)}={}){let n=new Map,r=!1;function i(e=Statamic.$events){r||(r=!0,e.$on(`publish-container-created`,a),e.$on(`publish-container-destroyed`,o))}function a(r){let i=null;t(r.name),Zs(r)&&(e().forget(r.name),i=r.pushComponent(Js,{props:{containerName:r.name}})),n.set(r.name,[...n.get(r.name)??[],i])}function o({name:e}){let[t,...r]=n.get(e)??[];t?.destroy(),r.length?n.set(e,r):n.delete(e)}return{listen:i,pushed:e=>(n.get(e)??[]).filter(Boolean).length}}var $s=Qs();function ec({name:e,ctx:t,store:n=_s(),registry:r=za,loadStatus:i=e=>Qi(`editor/status`,{reference:e}),now:a=Date.now,settleMs:o=600,onSwitch:s=e=>qs.abort(e),onStatus:c=(e,t)=>Ds.adopt(e,t)}){let l=F(null),u=!!t.reference.value&&n.container(e).reference===t.reference.value;r.attachContext(e,t);let d=r=>t.reference.value===r&&n.containers[e]?.reference===r;async function f(r){if(l.value=null,!t.readOnly?.value)try{let t=await i(r);d(r)&&(n.container(e).status=t,c(e,t))}catch(e){d(r)&&e?.status!==403&&(l.value=e)}}function p(t){let i=a();s(e),n.switched(e,t,i),r.refreshClean(e),setTimeout(()=>{n.containers[e]?.lastChangeAt===i&&d(t)&&r.refreshClean(e)},o),f(t)}return{failure:l,stop:xn(()=>[t.reference.value,t.site.value],([t],r)=>{if(t){if(r===void 0&&u){n.container(e).status===null&&f(t);return}p(t)}},{immediate:!0,flush:`post`})}}function tc(){let e=!1,t=!1,n=Ot({open:!1,show(){e?t=!0:n.open=!0},hide(){t=!1,e||(n.open=!1)},dismissed(){e=!0},closed(r){r||(e=!1,n.open=!1,t&&(t=!1,rt(()=>n.open=!0)))}});return n}var nc={class:`space-y-2 ps-6`,"data-tolk-push":``},rc={class:`sr-only`,"aria-live":`polite`,"data-tolk-push-announcement":``},ic={key:0,class:`flex flex-wrap items-center gap-2 pt-1`,"data-tolk-push-actions":``},ac={key:3,class:`flex flex-wrap items-center gap-2`,"data-tolk-push-phase":`updated`},oc={key:4,class:`space-y-2`,"data-tolk-push-phase":`running`},sc={class:`flex flex-wrap items-center justify-between gap-2`},cc={key:1,class:`flex flex-wrap items-center gap-2`,"data-tolk-push-failure":``},lc=[`data-tolk-push-status`],uc={class:`space-y-1`},dc=[`data-tolk-push-item`,`data-tolk-push-item-status`],fc=[`href`],pc=[`href`],mc={class:`flex flex-wrap gap-2`},hc={key:6,class:`flex flex-wrap items-center gap-2`,"data-tolk-push-phase":`error`},gc={class:`space-y-6`},_c={class:`space-y-3`},vc=[`data-tolk-push-site`],yc={class:`flex items-center justify-end gap-3 pt-3 pb-1`},bc={__name:`OriginPush`,props:{containerName:{type:String,required:!0},reference:{type:String,required:!0},origin:{type:Object,required:!0},status:{type:Object,default:null},dirty:{type:Boolean,default:!1}},setup(e){let t=e,n=_s(),r=D(()=>n.containers[t.containerName]?.push??null),i=D(()=>ws(r.value,t.status)),a=D(()=>vs.includes(r.value?.phase)),o=D(()=>!a.value&&(t.origin.translateInto||t.origin.update)),s=D(()=>xs(t.origin)),c=tc(),l=F([]),u=F(`draft`),d=F(!1),f=D(()=>s.value.some(e=>e.missing&&l.value.includes(e.site))),p=D(()=>Ys(t.reference));function h(){l.value=s.value.map(e=>e.site),u.value=t.status?.defaults?.new_status===`mirror`?`mirror`:`draft`,d.value=t.status?.defaults?.review===!0,c.show()}function g(e,t){l.value=t?[...new Set([...l.value,e])]:l.value.filter(t=>t!==e)}function _(){c.hide(),Ds.start(t.containerName,{reference:t.reference,sites:s.value.map(e=>e.site).filter(e=>l.value.includes(e)),mode:`missing`,review:d.value,newStatus:f.value?u.value:null})}function v(){Ds.start(t.containerName,{reference:t.reference,sites:Ss(t.origin),mode:`update`})}let y=D(()=>i.value?.automatic?__(`Updating the translations automatically into :sites…`,{sites:i.value.sites}):__(`Translating into :sites…`,{sites:i.value.sites})),b=D(()=>__(`The translations into :sites were updated automatically.`,{sites:i.value?.sites??``})),x=D(()=>{switch(r.value?.phase){case`starting`:return __(`Starting the translation…`);case`expecting`:return y.value;case`updated`:return b.value;case`running`:return i.value.failure?__(`The translations stopped: :message`,{message:i.value.failure}):y.value;case`error`:return i.value?.error??``;default:return i.value?.result?.text??``}});function S(){window.location.reload()}return(t,n)=>(P(),A(`div`,nc,[j(`p`,rc,L(x.value),1),o.value?(P(),A(`div`,ic,[e.origin.translateInto?(P(),O(R(B),{key:0,variant:`primary`,size:`sm`,disabled:e.dirty,"data-tolk-action":`translate-into`,onClick:h},{default:z(()=>[M(L(t.__(`Translate into…`)),1)]),_:1},8,[`disabled`])):k(``,!0),e.origin.update?(P(),O(R(B),{key:1,size:`sm`,disabled:e.dirty,"data-tolk-action":`update-translations`,onClick:v},{default:z(()=>[M(L(t.__(`Update translations`)),1)]),_:1},8,[`disabled`])):k(``,!0),e.dirty?(P(),O(R(H),{key:2,"data-tolk-save-first":``},{default:z(()=>[M(L(p.value?t.__(`Save first: the translations are made from the saved term.`):t.__(`Save first: the translations are made from the saved entry.`)),1)]),_:1})):k(``,!0)])):k(``,!0),r.value?.phase===`starting`?(P(),O(R(q),{key:1,as:`p`,"data-tolk-push-phase":`starting`},{default:z(()=>[M(L(t.__(`Starting the translation…`)),1)]),_:1})):k(``,!0),r.value?.phase===`expecting`?(P(),O(R(q),{key:2,as:`p`,"data-tolk-push-phase":`expecting`},{default:z(()=>[M(L(y.value),1)]),_:1})):k(``,!0),r.value?.phase===`updated`?(P(),A(`div`,ac,[N(R(q),null,{default:z(()=>[M(L(b.value),1)]),_:1}),N(R(B),{size:`sm`,variant:`ghost`,"data-tolk-action":`push-close`,onClick:n[0]||=t=>R(Ds).dismiss(e.containerName)},{default:z(()=>[M(L(t.__(`Close`)),1)]),_:1})])):k(``,!0),r.value?.phase===`running`?(P(),A(`div`,oc,[j(`div`,sc,[r.value.cancelling?(P(),O(R(q),{key:0},{default:z(()=>[M(L(t.__(`Cancelling. Translations already being saved are still saved.`)),1)]),_:1})):(P(),O(R(q),{key:1,"data-tolk-push-working":``},{default:z(()=>[M(L(y.value),1)]),_:1})),N(R(B),{size:`sm`,variant:`ghost`,disabled:r.value.cancelling,"data-tolk-action":`push-cancel`,onClick:n[1]||=t=>R(Ds).cancel(e.containerName)},{default:z(()=>[M(L(t.__(`Cancel`)),1)]),_:1},8,[`disabled`])]),N(La,{value:i.value.progress.finished,max:i.value.progress.total,label:t.__(`Translation progress`)},null,8,[`value`,`max`,`label`]),N(R(H),{"data-tolk-push-progress":``},{default:z(()=>[M(L(t.__(`:finished of :total translations finished.`,{finished:i.value.progress.finished,total:i.value.progress.total})),1)]),_:1}),i.value.keepOpen?(P(),O(R(H),{key:0},{default:z(()=>[M(L(p.value?t.__(`Keep this page open until the translations are saved. If you leave, they continue when you open this term again.`):t.__(`Keep this page open until the translations are saved. If you leave, they continue when you open this entry again.`)),1)]),_:1})):k(``,!0),i.value.failure?(P(),A(`div`,cc,[N(R(W),{name:`warning-diamond`,class:`size-4 shrink-0 text-red-600`,"aria-hidden":`true`}),N(R(q),{variant:`danger`},{default:z(()=>[M(L(t.__(`The translations stopped: :message`,{message:i.value.failure})),1)]),_:1}),N(R(B),{size:`sm`,"data-tolk-action":`push-resume`,onClick:n[2]||=t=>R(Ds).resume(e.containerName)},{default:z(()=>[M(L(t.__(`Try again`)),1)]),_:1})])):k(``,!0)])):k(``,!0),i.value?.result?(P(),A(`div`,{key:5,class:`space-y-2`,"data-tolk-push-result":``,"data-tolk-push-status":i.value.result.status},[N(R(q),{as:`p`},{default:z(()=>[M(L(i.value.result.text),1)]),_:1}),i.value.result.error?(P(),O(R(q),{key:0,as:`p`,variant:`danger`},{default:z(()=>[M(L(i.value.result.error),1)]),_:1})):k(``,!0),j(`ul`,uc,[(P(!0),A(m,null,I(i.value.result.items,e=>(P(),A(`li`,{key:e.index,class:`flex flex-wrap items-center gap-2`,"data-tolk-push-item":e.handle,"data-tolk-push-item-status":e.status},[e.editUrl?(P(),A(`a`,{key:0,href:e.editUrl,class:`text-sm font-medium underline`},L(e.site),9,fc)):(P(),O(R(q),{key:1,variant:`strong`},{default:z(()=>[M(L(e.site),1)]),_:2},1024)),N(R(Fn),{text:e.statusLabel,color:e.statusColor},null,8,[`text`,`color`]),e.error||e.reason?(P(),O(R(H),{key:2},{default:z(()=>[M(L(e.error??e.reason)+` `,1),e.rootPage?(P(),A(`a`,{key:0,href:e.rootPage.url,class:`font-medium underline`,"data-tolk-root-page":``},L(t.__(`Open :title`,{title:e.rootPage.title})),9,pc)):k(``,!0)]),_:2},1024)):k(``,!0)],8,dc))),128))]),i.value.reload?(P(),O(R(H),{key:1},{default:z(()=>[M(L(t.__(`Reload the page to see the new localizations in the Sites panel.`)),1)]),_:1})):k(``,!0),j(`div`,mc,[i.value.reload?(P(),O(R(B),{key:0,size:`sm`,variant:`primary`,"data-tolk-action":`reload`,onClick:S},{default:z(()=>[M(L(t.__(`Reload`)),1)]),_:1})):k(``,!0),N(R(B),{size:`sm`,variant:`ghost`,"data-tolk-action":`push-close`,onClick:n[3]||=t=>R(Ds).dismiss(e.containerName)},{default:z(()=>[M(L(t.__(`Close`)),1)]),_:1})])],8,lc)):k(``,!0),r.value?.phase===`error`?(P(),A(`div`,hc,[N(R(W),{name:`warning-diamond`,class:`size-4 shrink-0 text-red-600`,"aria-hidden":`true`}),N(R(q),{variant:`danger`,"data-tolk-push-error":``},{default:z(()=>[M(L(i.value.error),1)]),_:1}),N(R(B),{size:`sm`,variant:`ghost`,"data-tolk-action":`push-close`,onClick:n[4]||=t=>R(Ds).dismiss(e.containerName)},{default:z(()=>[M(L(t.__(`Close`)),1)]),_:1})])):k(``,!0),R(c).open?(P(),O(R(Wr),{key:7,open:``,title:t.__(`Translate into other languages`),icon:`dictionary-language-book`,"data-tolk-push-modal":``,onDismissed:n[8]||=e=>R(c).dismissed(),"onUpdate:open":n[9]||=e=>R(c).closed(e)},{footer:z(()=>[j(`div`,yc,[N(R(B),{variant:`ghost`,text:t.__(`Cancel`),"data-tolk-push-action":`close`,onClick:n[7]||=e=>R(c).hide()},null,8,[`text`]),N(R(B),{variant:`primary`,text:t.__(`Translate`),disabled:l.value.length===0,"data-tolk-push-action":`translate`,onClick:_},null,8,[`text`,`disabled`])])]),default:z(()=>[j(`div`,gc,[N(R(q),{as:`p`},{default:z(()=>[M(L(p.value?t.__(`The saved term is translated and saved in each language you choose. This form stays as it is.`):t.__(`The saved entry is translated and saved in each language you choose. This form stays as it is.`)),1)]),_:1}),j(`div`,_c,[(P(!0),A(m,null,I(s.value,e=>(P(),A(`div`,{key:e.site,"data-tolk-push-site":e.site},[N(R(Hn),{"model-value":l.value.includes(e.site),label:e.name,description:e.summary,"onUpdate:modelValue":t=>g(e.site,t)},null,8,[`model-value`,`label`,`description`,`onUpdate:modelValue`])],8,vc))),128))]),f.value?(P(),O(R(br),{key:0,id:`tolk-push-status`,label:t.__(`New localizations`)},{default:z(()=>[N(R(ui),{modelValue:u.value,"onUpdate:modelValue":n[5]||=e=>u.value=e,appearance:`inline`,"data-tolk-push-new-status":``},{default:z(()=>[N(R(li),{value:`draft`,label:t.__(`Drafts`)},null,8,[`label`]),N(R(li),{value:`mirror`,label:t.__(`Same as origin`)},null,8,[`label`])]),_:1},8,[`modelValue`])]),_:1},8,[`label`])):k(``,!0),N(R(Hn),{modelValue:d.value,"onUpdate:modelValue":n[6]||=e=>d.value=e,label:t.__(`Review after translating`),description:t.__(`A second model checks each translation and corrects it before it is saved.`)},null,8,[`modelValue`,`label`,`description`])])]),_:1},8,[`title`])):k(``,!0)]))}},xc=`tolk.offer`,Sc=null;function Cc(e,t,{preferences:n=()=>Statamic.$preferences,toast:r=()=>Statamic.$toast}={}){let i=()=>new Promise(r=>r(n().set(e,t))).then(()=>!0,()=>(r().error(__(`Your choice could not be saved.`)),!1)),a=Sc?Sc.then(i):i();return Sc=a,a.then(()=>{Sc===a&&(Sc=null)}),a}function wc(e=Statamic.$preferences){return e.get(xc,!0)!==!1}function Tc(e,t=Statamic.$preferences){return e?.offer===!0&&wc(t)&&ua(e).localization?.translate===!0}function Ec(e){let t=ua(e);return{count:e?.localization?.counts?.untranslated??0,source:t.localization?.source?.name??``,target:t.localization?.target?.name??``,translator:t.translator}}var Dc=350;function Oc({store:e=_s,registry:t=za,translations:n=qs,preferences:r=()=>Statamic.$preferences,toast:i=()=>Statamic.$toast,openAfterMs:a=Dc,clock:o=()=>Date.now(),wait:s=(e,t)=>setTimeout(e,t)}={}){let c=null,l=!1;function u(e=Statamic.$events){l||(l=!0,e.$on(`localization.created`,d))}function d(n){let r=n?.container?.name,i=t.context(r)?.reference?.value;if(r!==`base`||!i)return;m();let s=e(),l=o()+a;if(f(s,r,i,l))return;let u=xn(()=>{let e=s.containers[r];return[e?.reference,e?.status]},()=>{f(s,r,i,l)&&(u(),c===u&&(c=null))});c=u}function f(e,n,r,i){let a=e.containers[n];return a?.reference===r?(a.created=!0,a.status!==null&&(p(e,n,r,i),!0)):t.context(n)?.reference?.value!==r}function p(e,t,n,i){let a=i-o();if(a>0){s(()=>p(e,t,n,i),a);return}let c=e.containers[t];c?.reference===n&&c.phase===`idle`&&Tc(c.status,r())&&e.setPhase(t,`offer`)}function m(){c?.(),c=null}function h(t,n){let a=e();return a.phaseOf(t)===`offer`&&(n&&Cc(xc,!1,{preferences:r,toast:i}),a.setPhase(t,`idle`),!0)}function g(e,{dontOfferAgain:t=!1}={}){return h(e,t)?n.translate(e,{mode:`missing`}):null}function _(e,{dontOfferAgain:t=!1}={}){h(e,t)}return{listen:u,created:d,accept:g,decline:_,waiting:e=>e===`base`&&c!==null}}var kc=Oc(),Ac={class:`space-y-1`},jc={class:`flex items-center justify-end gap-3 pt-3 pb-1`},Mc={__name:`TranslateOffer`,props:{containerName:{type:String,required:!0},status:{type:Object,default:null},open:{type:Boolean,default:!1}},setup(e){let t=e,n=F(!1),r=D(()=>Ec(t.status));xn(()=>t.open,e=>{e&&(n.value=!1)});function i(){kc.accept(t.containerName,{dontOfferAgain:n.value})}function a(){kc.decline(t.containerName,{dontOfferAgain:n.value})}return(t,o)=>(P(),O(R(Wr),{open:e.open,title:t.__(`Translate this entry?`),icon:`dictionary-language-book`,"data-tolk-offer":``,onDismissed:a},{footer:z(()=>[j(`div`,jc,[N(R(B),{variant:`ghost`,text:t.__(`Not now`),"data-tolk-offer-action":`decline`,onClick:a},null,8,[`text`]),N(R(B),{variant:`primary`,text:t.__(`Translate`),"data-tolk-offer-action":`translate`,onClick:i},null,8,[`text`])])]),default:z(()=>[j(`div`,Ac,[N(R(q),{as:`p`,"data-tolk-offer-text":``},{default:z(()=>[M(L(t.__n(`Translate :count field from :source into :target. Nothing is saved until you press Save.|Translate :count fields from :source into :target. Nothing is saved until you press Save.`,r.value.count,{source:r.value.source,target:r.value.target})),1)]),_:1}),r.value.translator?(P(),O(R(H),{key:0,"data-tolk-offer-model":``},{default:z(()=>[M(L(t.__(`Model: :model`,{model:R(ya)(r.value.translator)})),1)]),_:1})):k(``,!0)]),N(R(Hn),{modelValue:n.value,"onUpdate:modelValue":o[0]||=e=>n.value=e,label:t.__(`Don't offer again`)},null,8,[`modelValue`,`label`])]),_:1},8,[`open`,`title`]))}},Nc=`tolk.editor.translator`,Pc=`tolk.editor.reviewer`;function Fc(e=Statamic.$preferences,t=Nc){let n=e.get(t,null);return typeof n==`string`&&n!==``?n:null}function Ic(e,{fakeEngine:t=!1,defaultModel:n=null,extra:r=[]}={}){let i=[];for(let r of Object.values(Y(e)).flat())(r.configured||t)&&i.push({value:r.value,label:r.value===n?__(`:model (default)`,{model:r.label}):r.label});for(let e of r)e&&!i.some(t=>t.value===e)&&i.push({value:e,label:e===n?__(`:model (default)`,{model:e}):e});return i}function Lc(e,{remembered:t=null,defaultModel:n=null}={}){let r=t=>t!==null&&e.some(e=>e.value===t);return r(t)?t:r(n)?n:e[0]?.value??null}function Rc(e,t){return e&&e!==t?e:null}function zc(e,t,n){return n?e||null:Rc(e,t)}function Bc({model:e=null,defaultModel:t=null,retranslate:n=!1,overwriteManual:r=!1,review:i=null,reviewer:a=null,defaultReviewer:o=null}={}){let s=Rc(e,t);return{mode:n?`all`:`update`,overwriteManual:r,translator:s,review:i,reviewer:i===!0?zc(a,o,s):null}}function Vc({reviewer:e=null,defaultReviewer:t=null,overwriteManual:n=!1}={}){return{overwriteManual:n,reviewer:Rc(e,t)}}function Hc(e){let t=e?.localization?.counts??{};return{markCurrent:(t.attention??0)+(t.untracked??0)>0,protect:(t.current??0)+(t.outdated??0)>0}}function Uc(e,t){return e===0?__(`No field needed changing.`):t?__n(`:count field is now protected from updates.|:count fields are now protected from updates.`,e):__n(`:count field marked as up to date.|:count fields marked as up to date.`,e)}function Wc({store:e=_s,registry:t=za,api:n=J,translations:r=qs,preferences:i=()=>Statamic.$preferences,toast:a=()=>Statamic.$toast}={}){let o=null;function s(){return o??=n.get(`models`).catch(e=>{throw o=null,e}),o}function c(e,t){t!==Fc(i(),e)&&Cc(e,t,{preferences:i,toast:a})}function l(t,n={}){let i=Bc(n);return Os.includes(e().phaseOf(t))?null:(c(Nc,i.translator),i.review===!0&&c(Pc,Rc(n.reviewer,n.defaultReviewer)),r.translate(t,i))}function u(t,n={}){let i=Vc(n);return Os.includes(e().phaseOf(t))?null:(c(Pc,i.reviewer),r.review(t,i))}async function d(r,{protect:i=!1}={}){let o=e().containers[r],s=t.context(r)?.reference?.value??null;if(!o||!s||o.reference!==s||Os.includes(o.phase))return null;try{let{baselined:e=0,...t}=await n.post(`editor/baseline`,{reference:s,protect:i});return o.status=t,a().success(Uc(e,i)),e}catch(e){return a().error(e?.message||__(`Something went wrong.`)),null}}function f(e){return Cc(xc,e,{preferences:i,toast:a})}return{loadModels:s,translate:l,review:u,baseline:d,setOffers:f}}var Gc=Wc(),Kc={class:`space-y-4`},qc={class:`space-y-3`},Jc={class:`grid gap-4 sm:grid-cols-2`},Yc={class:`space-y-3`},Xc={key:0,class:`space-y-3 border-t border-gray-200 pt-4 dark:border-gray-700`,"aria-labelledby":`tolk-options-state-heading`,"data-tolk-options-state":``},Zc={key:0,class:`flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4`},Qc={key:1,class:`flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4`},$c={key:1,class:`flex items-start justify-between gap-4 border-t border-gray-200 pt-4 dark:border-gray-700`,"data-tolk-options-offer":``},el={class:`space-y-0.5`},tl={class:`flex items-center justify-end gap-3 pt-3 pb-1`},nl={__name:`TranslateOptions`,props:{containerName:{type:String,required:!0},status:{type:Object,default:null}},setup(e){let t=e,n=_s(),r=D(()=>Ys(n.containers[t.containerName]?.reference)),i=tc(),a=F(!1),o=F(null),s=F(null),c=F(null),l=F(null),u=F(!1),d=F(!1),f=F(!1),p=F(!0),h=F(!1),g=!!Statamic.$config.get(`tolk.settingsUrl`),_=D(()=>s.value?.defaults?.translator??t.status?.defaults?.translator??null),v=D(()=>s.value?.defaults?.reviewer??null),y=D(()=>Fc()),b=D(()=>Fc(Statamic.$preferences,Pc));function x(e,n,r){return Ic(s.value?.catalog,{fakeEngine:t.status?.defaults?.fake_engine===!0,defaultModel:e,extra:g?[e,n,r]:[e]})}let S=D(()=>x(_.value,y.value,c.value)),ee=D(()=>x(v.value,b.value,l.value)),C=D(()=>Ps(n.containers[t.containerName],{overwriteManual:f.value})),w=D(()=>u.value||C.value),T=D(()=>Hc(t.status)),E=D(()=>t.status?.offer===!0);async function te(){d.value=!1,f.value=!1,u.value=t.status?.defaults?.review===!0,o.value=null,p.value=wc(),i.show(),a.value=!0;try{s.value=await Gc.loadModels()}catch(e){o.value=e.message}finally{a.value=!1}c.value=Lc(S.value,{remembered:y.value,defaultModel:_.value}),l.value=Lc(ee.value,{remembered:b.value,defaultModel:v.value})}function ne(){i.hide(),Gc.translate(t.containerName,{model:c.value,defaultModel:_.value,retranslate:d.value,overwriteManual:f.value,review:u.value,reviewer:l.value,defaultReviewer:v.value})}function re(){i.hide(),Gc.review(t.containerName,{reviewer:l.value,defaultReviewer:v.value,overwriteManual:f.value})}async function ie(e){h.value=!0;try{await Gc.baseline(t.containerName,{protect:e})!==null&&i.hide()}finally{h.value=!1}}async function ae(e){p.value=e,await Gc.setOffers(e)||(p.value=!e)}return(e,t)=>(P(),A(m,null,[N(R(B),{size:`sm`,variant:`ghost`,icon:`sliders-horizontal`,text:e.__(`Options`),"data-tolk-action":`options`,onClick:te},null,8,[`text`]),R(i).open?(P(),O(R(Wr),{key:0,open:``,title:e.__(`Translation options`),icon:`sliders-horizontal`,"data-tolk-options":``,onDismissed:t[8]||=e=>R(i).dismissed(),"onUpdate:open":t[9]||=e=>R(i).closed(e)},{footer:z(()=>[j(`div`,tl,[N(R(B),{variant:`ghost`,text:e.__(`Close`),"data-tolk-options-action":`close`,onClick:t[7]||=e=>R(i).hide()},null,8,[`text`]),C.value?(P(),O(R(B),{key:0,text:e.__(`Review`),disabled:a.value||!l.value,"data-tolk-options-action":`review`,onClick:re},null,8,[`text`,`disabled`])):k(``,!0),N(R(B),{variant:`primary`,text:e.__(`Translate`),disabled:a.value||!c.value,"data-tolk-options-action":`translate`,onClick:ne},null,8,[`text`,`disabled`])])]),default:z(()=>[j(`div`,Kc,[j(`div`,qc,[j(`div`,Jc,[N(R(br),{id:`tolk-options-model`,label:e.__(`Model`)},{default:z(()=>[N(R(Gn),{id:`tolk-options-model`,modelValue:c.value,"onUpdate:modelValue":t[0]||=e=>c.value=e,options:S.value,taggable:R(g),disabled:a.value,placeholder:a.value?e.__(`Loading…`):e.__(`Choose a model`),"data-tolk-options-model":``},null,8,[`modelValue`,`options`,`taggable`,`disabled`,`placeholder`])]),_:1},8,[`label`]),N(R(br),{id:`tolk-options-reviewer`,label:e.__(`Reviewer`),"data-tolk-options-review":``},{default:z(()=>[N(R(Gn),{id:`tolk-options-reviewer`,modelValue:l.value,"onUpdate:modelValue":t[1]||=e=>l.value=e,options:ee.value,taggable:R(g),disabled:a.value||!w.value,placeholder:a.value?e.__(`Loading…`):e.__(`Choose a model`),"data-tolk-options-reviewer":``},null,8,[`modelValue`,`options`,`taggable`,`disabled`,`placeholder`])]),_:1},8,[`label`])]),R(g)?(P(),O(R(H),{key:0},{default:z(()=>[M(L(e.__(`You may also type a model outside the list, as provider:model.`)),1)]),_:1})):k(``,!0),o.value?(P(),O(R(q),{key:1,as:`p`,variant:`danger`,"data-tolk-options-failure":``},{default:z(()=>[M(L(e.__(`The models could not be loaded: :message`,{message:o.value})),1)]),_:1})):k(``,!0)]),j(`div`,Yc,[N(R(Hn),{modelValue:d.value,"onUpdate:modelValue":t[2]||=e=>d.value=e,label:e.__(`Retranslate everything`),description:e.__(`Also translates the fields that are up to date again.`)},null,8,[`modelValue`,`label`,`description`]),N(R(Hn),{modelValue:f.value,"onUpdate:modelValue":t[3]||=e=>f.value=e,label:e.__(`Overwrite manual edits`),description:e.__(`Also replaces the text of fields edited by hand.`)},null,8,[`modelValue`,`label`,`description`]),N(R(Hn),{modelValue:u.value,"onUpdate:modelValue":t[4]||=e=>u.value=e,label:e.__(`Review after translating`),description:e.__(`The reviewer checks the new translation and corrects it.`)},null,8,[`modelValue`,`label`,`description`])]),T.value.markCurrent||T.value.protect?(P(),A(`section`,Xc,[N(R(U),{id:`tolk-options-state-heading`,level:2,text:e.__(`Translation status`)},null,8,[`text`]),T.value.markCurrent?(P(),A(`div`,Zc,[N(R(H),null,{default:z(()=>[M(L(e.__(`Records that the fields edited by hand match the current source, so a later change to the source is flagged.`)),1)]),_:1}),N(R(B),{size:`sm`,class:`shrink-0 self-start sm:self-auto`,text:e.__(`Mark manual fields as up to date`),disabled:h.value,"data-tolk-action":`mark-current`,onClick:t[5]||=e=>ie(!1)},null,8,[`text`,`disabled`])])):k(``,!0),T.value.protect?(P(),A(`div`,Qc,[N(R(H),null,{default:z(()=>[M(L(e.__(`Treats the translated fields as edited by hand, so Translate and Update leave them alone.`)),1)]),_:1}),N(R(B),{size:`sm`,class:`shrink-0 self-start sm:self-auto`,text:r.value?e.__(`Protect this term from updates`):e.__(`Protect this entry from updates`),disabled:h.value,"data-tolk-action":`protect`,onClick:t[6]||=e=>ie(!0)},null,8,[`text`,`disabled`])])):k(``,!0)])):k(``,!0),E.value&&!r.value?(P(),A(`div`,$c,[j(`div`,el,[N(R(Dr),{for:`tolk-options-offer`,text:e.__(`Offer to translate new localizations`)},null,8,[`text`]),N(R(H),{id:`tolk-options-offer-description`},{default:z(()=>[M(L(e.__(`Asks whether to translate each localization you create. Only for your account.`)),1)]),_:1})]),N(R(bi),{id:`tolk-options-offer`,"model-value":p.value,"aria-describedby":`tolk-options-offer-description`,"onUpdate:modelValue":ae},null,8,[`model-value`])])):k(``,!0)])]),_:1},8,[`title`])):k(``,!0)],64))}},rl=`localizable`,il={ok:{color:`green`,icon:`checkmark`,class:`text-green-600`},warning:{color:`amber`,icon:`alert-warning-exclamation-mark`,class:`text-amber-600`},error:{color:`red`,icon:`warning-diamond`,class:`text-red-600`}};function al(e){return`tolk-audit-${e}`}function ol(e){return e?`${e}#${al(rl)}`:null}function sl(e){return{ok:__(`OK`),warning:__(`Warning`),error:__(`Error`)}[e]??e}function $(e){return{label:sl(e),...il[e]??il.warning}}function cl(e){let t=(Array.isArray(e)?e:[]).flatMap(e=>e.items??[]),n=t.filter(e=>e.level===`error`).length,r=t.filter(e=>e.level===`warning`).length;if(n===0&&r===0)return{level:`ok`,text:__(`Everything is set up. Tolk found nothing to change.`)};let i=[n>0?__n(`:count error|:count errors`,n):null,r>0?__n(`:count warning|:count warnings`,r):null].filter(Boolean);return{level:n>0?`error`:`warning`,text:__(`The audit found :problems. Errors keep Tolk from translating; warnings leave something untranslated or slower than it could be.`,{problems:i.join(`, `)})}}function ll(e,t){return e?.id===`localizable`?t?__(`A text field that is not localizable is shared by every site, so Tolk does not translate it. Choose the fields that hold text in each language and make them localizable.`):__(`A text field that is not localizable is shared by every site, so Tolk does not translate it. Someone who may edit the Tolk settings and blueprints can make them localizable here, or with php please tolk:doctor --fix-localizable.`):e?.detail??``}function ul(e){return typeof e?.namespace==`string`&&typeof e?.blueprint==`string`&&Array.isArray(e?.fields)}function dl(e){return`${e.namespace}|${e.blueprint}`}function fl(e){let t=Array.isArray(e?.fields)?e.fields:[];return{editable:t.filter(e=>!e.fieldset),imported:t.filter(e=>!!e.fieldset)}}function pl(e){return e.label&&e.label!==e.handle?`${e.label} (${e.handle})`:e.handle}function ml(e){return __(`From the fieldset :fieldset: make it localizable in the fieldset, which changes every blueprint that imports it.`,{fieldset:e.fieldset})}function hl(e,t){let n=new Set(Array.isArray(t)?t:[]);return fl(e).editable.map(e=>e.handle).filter(e=>n.has(e))}function gl(e,t){let n=fl(e).editable.filter(e=>t.includes(e.handle)).map(pl).join(`, `);return __n(`This changes the blueprint file of :blueprint: :fields becomes localizable, so each site keeps its own value and Tolk translates it. Existing localizations keep the value they inherit until they are translated or edited.|This changes the blueprint file of :blueprint: :fields become localizable, so each site keeps its own value and Tolk translates them. Existing localizations keep the values they inherit until they are translated or edited.`,t.length,{blueprint:e.name,fields:n})}function _l(e){return e>0?__n(`:count field is now localizable.|:count fields are now localizable.`,e):__(`Nothing changed: the fields were already localizable.`)}function vl(e,t){return __n(`:fields was not saved because it was hidden when you saved. Show it and save again.|:fields were not saved because they were hidden when you saved. Show them and save again.`,e.length,{fields:ba(e,t)})}function yl({PipelineStopped:e,store:t=_s,registry:n=za,api:r=J,now:i=Date.now,settleMs:a=600,onConfirmed:o=(e,t)=>Ds.afterSave(e,t)}){let s=!1;function c(e=Statamic.$hooks){if(!s){s=!0;for(let t of[`entry`,`term`])e.on(`${t}.saving`,l),e.on(`${t}.saved`,u)}}function l(n,r){if(Os.includes(t().phaseOf(`base`))){Statamic.$toast.error(__(`A translation is in progress. Wait for it to finish, or cancel it.`)),r(new e);return}n()}async function u(e,t,n){try{await d(n)}catch(e){console.error(e)}finally{e()}}async function d(e){let s=t(),c=s.containers[X],l=bl(e,c);if(!c?.reference||l!==c.reference)return;let u=i(),d=s.saved(X,u);n.refreshClean(X),setTimeout(()=>{let e=s.containers[X];e?.lastChangeAt===u&&e.reference===l&&n.refreshClean(X)},a),(c.phase===`done`||c.phase===`error`)&&s.clearResult(X);try{let{not_saved:e=[],...t}=await r.post(`editor/confirm`,{reference:l,delivered:d}),n=s.containers[X];n?.reference===l&&(n.status=t,n.notSaved=e,o(X,t)),e.length&&Statamic.$toast.error(vl(e,t),{duration:1e4})}catch(e){e?.status!==403&&Statamic.$toast.error(__(`The translation status could not be updated: :message`,{message:e?.message??``}))}}return{listen:c,saving:l,saved:u}}function bl(e,t){let n=e?.response?.data?.data;return typeof n?.reference==`string`?n.reference:typeof n?.id==`string`&&t?.reference?.startsWith(`term::${n.id}::`)?t.reference:e?.reference??null}var xl=`[data-tolk-offer], [data-tolk-options], [data-tolk-changes], [data-tolk-push-modal]`,Sl=`[data-tolk-action]:not([disabled])`,Cl=`[data-tolk-focus]`,wl=`button:not([disabled]), [href], [tabindex="0"]`;function Tl(e,{modals:t=null,doc:n=globalThis.document,wait:r=setTimeout,delays:i=[0,400]}={}){let a=null;function o(){let r=n?.activeElement,i=e();return!!(r&&i&&(i.contains(r)||t&&r.closest?.(t)))}function s(){return!n.activeElement||n.activeElement===n.body||n.activeElement===a}function c(){let t=e();if(!t?.isConnected||!s())return;let n=t.querySelector(Sl),r=n??t.querySelector(Cl)??t.querySelector(wl);r?.focus(),a=n?null:r}return{holds:o,restore:c,changing(){o()&&i.forEach(e=>r(c,e))}}}var El={class:`sr-only`,"aria-live":`polite`,"data-tolk-announcement":``},Dl={key:0,class:`flex items-center gap-2`},Ol={key:0,class:`space-y-2`,"data-tolk-localization":``},kl={class:`flex flex-wrap items-center justify-between gap-x-6 gap-y-3`},Al={class:`flex flex-wrap items-center gap-2`},jl={key:0,class:`flex flex-wrap items-center gap-2`,"data-tolk-actions":``},Ml=[`href`],Nl={key:1,class:`flex items-center gap-2`,tabindex:`-1`,"data-tolk-focus":``,"data-tolk-phase":`planning`},Pl={key:2,class:`space-y-2`,"data-tolk-phase":`working`},Fl={class:`flex flex-wrap items-center justify-between gap-2`},Il={key:3,class:`space-y-1`,"data-tolk-phase":`error`},Ll={class:`flex items-center gap-2`},Rl={key:4,class:`space-y-1`,"data-tolk-summary":``},zl={key:1,class:`flex flex-wrap items-center gap-2`},Bl={key:5,class:`flex flex-wrap gap-2`},Vl={key:6,class:`flex items-center gap-2`,"data-tolk-not-saved":``},Hl={key:7,class:`space-y-2`,"data-tolk-origin":``},Ul={class:`flex items-center gap-2`},Wl={class:`grid grid-cols-[auto_auto_minmax(0,1fr)] items-center gap-x-3 gap-y-1.5 ps-6`},Gl=[`data-tolk-site`],Kl=[`href`],ql=[`href`],Jl={__name:`EditorBanner`,props:{containerName:{type:String,required:!0}},setup(e){let t=e,n=ti(),r=_s(),i=t.containerName,{failure:a,stop:o}=ec({name:i,ctx:n,store:r});ut(o);let s=D(()=>r.containers[i]??null),c=D(()=>s.value?.phase??`idle`),l=ol(Statamic.$config.get(`tolk.auditUrl`)),u=D(()=>ua(s.value?.status??null)),d=D(()=>xa(s.value?.summary??null,s.value?.status??null)),f=D(()=>Ls(s.value)),p=D(()=>ks.includes(s.value?.error?.code)),h=D(()=>s.value?.notSaved?.length?vl(s.value.notSaved,s.value.status):null),g=D(()=>Xs(c.value,u.value)),_=D(()=>Ps(s.value)),v=D(()=>{let e=s.value?.request;return e?.kind===`translate`&&e.fields?.length===1?ba(e.fields,s.value.status):null}),y=D(()=>{let e=u.value.localization?.target?.name??``;return s.value?.progress?.cancelling?__(`Cancelling. Fields already on their way are still filled in.`):s.value?.request?.kind===`review`?__(`Reviewing the translation…`):v.value?__(`Translating :field into :site…`,{field:v.value,site:e}):__(`Translating into :site…`,{site:e})}),b=D(()=>{switch(c.value){case`planning`:return __(`Preparing the translation…`);case`working`:return y.value;case`error`:return s.value?.error?.message??``;case`done`:return[d.value?.translated,d.value?.reviewed].filter(Boolean).join(` `);default:return``}}),x=tc();xn(()=>s.value?.summary,()=>x.hide());let S=D(()=>!!u.value.origin?.upToDate&&!u.value.localization&&!s.value?.push),ee=D(()=>!n.readOnly.value&&(a.value!==null||u.value.visible&&!S.value)),C=D(()=>za.dirtyHandles(i).length>0),w=Statamic.$config.get(`tolk.settingsUrl`),T=D(()=>Ys(s.value?.reference)),E=F(null),te=Tl(()=>E.value?.$el??null,{modals:xl});xn([c,()=>s.value?.push?.phase],()=>te.changing()),xn(ee,e=>{!e&&te.holds()&&rt(()=>document.getElementById(`content-card`)?.focus())});function ne(e){qs.translate(i,{mode:e})}async function re(){let e=te.holds(),t=await qs.undo(i);e&&(await rt(),te.restore()),t?.kept.length&&Statamic.$toast.info(Rs(t.kept,s.value?.status))}return(e,t)=>{let n=Pt(`tooltip`);return ee.value?(P(),O(R(V),{key:0,ref_key:`card`,ref:E,class:`mb-6 space-y-3`,"data-tolk-banner":``},{default:z(()=>[j(`p`,El,L(b.value),1),R(a)?(P(),A(`div`,Dl,[N(R(W),{name:`warning-diamond`,class:`size-4 shrink-0 text-red-600`,"aria-hidden":`true`}),N(R(q),{variant:`danger`},{default:z(()=>[M(L(e.__(`The translation status could not be loaded: :message`,{message:R(a).message})),1)]),_:1})])):(P(),A(m,{key:1},[u.value.localization?(P(),A(`div`,Ol,[j(`div`,kl,[j(`div`,Al,[N(R(W),{name:`dictionary-language-book`,class:`size-4 shrink-0 text-gray-500`,"aria-hidden":`true`}),N(R(q),null,{default:z(()=>[M(L(u.value.localization.lead),1)]),_:1}),(P(!0),A(m,null,I(u.value.localization.parts,e=>Dn((P(),O(R(Fn),{key:e.key,text:e.text,color:R(oa)(e.key),tabindex:`0`,"data-tolk-part":e.key},null,8,[`text`,`color`,`data-tolk-part`])),[[n,e.description]])),128))]),g.value?(P(),A(`div`,jl,[c.value===`idle`?(P(),A(m,{key:0},[u.value.localization.translate?(P(),O(R(B),{key:0,variant:`primary`,size:`sm`,"data-tolk-action":`translate`,onClick:t[0]||=e=>ne(`missing`)},{default:z(()=>[M(L(e.__(`Translate`)),1)]),_:1})):k(``,!0),u.value.localization.update?(P(),O(R(B),{key:1,size:`sm`,"data-tolk-action":`update`,onClick:t[1]||=e=>ne(`update`)},{default:z(()=>[M(L(e.__(`Update`)),1)]),_:1})):k(``,!0)],64)):k(``,!0),_.value?(P(),O(R(B),{key:1,size:`sm`,"data-tolk-action":`review`,onClick:t[2]||=e=>R(qs).review(R(i))},{default:z(()=>[M(L(e.__(`Review`)),1)]),_:1})):k(``,!0),N(nl,{"container-name":R(i),status:s.value.status},null,8,[`container-name`,`status`])])):k(``,!0)]),u.value.localization.autoUpdated?(P(),O(R(H),{key:0,"data-tolk-auto-updated":``},{default:z(()=>[M(L(u.value.localization.autoUpdated),1)]),_:1})):k(``,!0),u.value.localization.incompleteNote?(P(),O(R(H),{key:1},{default:z(()=>[M(L(u.value.localization.incompleteNote),1)]),_:1})):k(``,!0),u.value.localization.hint?(P(),O(R(H),{key:2,"data-tolk-not-localizable":``},{default:z(()=>[M(L(u.value.localization.hint)+` `,1),R(l)?(P(),A(`a`,{key:0,href:R(l),"data-tolk-audit-link":``},L(e.__(`Open the setup audit`)),9,Ml)):(P(),A(m,{key:1},[M(L(e.__(`Run php please tolk:doctor for details.`)),1)],64))]),_:1})):k(``,!0)])):k(``,!0),c.value===`planning`?(P(),A(`div`,Nl,[N(R(q),null,{default:z(()=>[M(L(e.__(`Preparing the translation…`)),1)]),_:1})])):k(``,!0),c.value===`working`?(P(),A(`div`,Pl,[j(`div`,Fl,[N(R(q),{"data-tolk-working-field":v.value?``:null},{default:z(()=>[M(L(y.value),1)]),_:1},8,[`data-tolk-working-field`]),N(R(B),{size:`sm`,variant:`ghost`,disabled:s.value.progress.cancelling,"data-tolk-action":`cancel`,onClick:t[3]||=e=>R(qs).cancel(R(i))},{default:z(()=>[M(L(e.__(`Cancel`)),1)]),_:1},8,[`disabled`])]),N(La,{value:s.value.progress.done,max:s.value.progress.total,label:s.value.request?.kind===`review`?e.__(`Review progress`):e.__(`Translation progress`)},null,8,[`value`,`max`,`label`]),s.value.progress.waiting?(P(),O(R(H),{key:0},{default:z(()=>[M(L(e.__(`The provider asked to wait. Trying again shortly.`)),1)]),_:1})):k(``,!0)])):k(``,!0),c.value===`error`?(P(),A(`div`,Il,[j(`div`,Ll,[N(R(W),{name:`warning-diamond`,class:`size-4 shrink-0 text-red-600`,"aria-hidden":`true`}),N(R(q),{variant:`danger`,"data-tolk-error":``},{default:z(()=>[M(L(s.value.error?.message),1)]),_:1})])])):k(``,!0),d.value&&(c.value===`done`||c.value===`error`)?(P(),A(`div`,Rl,[d.value.translated?(P(),O(R(q),{key:0,as:`p`,"data-tolk-summary-translated":``},{default:z(()=>[M(L(d.value.translated),1)]),_:1})):k(``,!0),d.value.reviewed?(P(),A(`div`,zl,[N(R(q),{"data-tolk-summary-reviewed":``},{default:z(()=>[M(L(d.value.reviewed),1)]),_:1}),d.value.corrections?(P(),O(R(B),{key:0,size:`sm`,variant:`ghost`,"data-tolk-action":`view-changes`,onClick:t[4]||=e=>R(x).show()},{default:z(()=>[M(L(e.__(`View changes`)),1)]),_:1})):k(``,!0)])):k(``,!0),d.value.reviewSkipped?(P(),O(R(H),{key:2,"data-tolk-summary-review-skipped":``},{default:z(()=>[M(L(d.value.reviewSkipped),1)]),_:1})):k(``,!0),d.value.cancelled?(P(),O(R(H),{key:3},{default:z(()=>[M(L(d.value.cancelled),1)]),_:1})):k(``,!0),d.value.incomplete?(P(),O(R(H),{key:4,"data-tolk-summary-incomplete":``},{default:z(()=>[M(L(d.value.incomplete),1)]),_:1})):k(``,!0),d.value.edited?(P(),O(R(H),{key:5,"data-tolk-summary-edited":``},{default:z(()=>[M(L(d.value.edited),1)]),_:1})):k(``,!0),d.value.manual?(P(),O(R(H),{key:6,"data-tolk-summary-manual":``},{default:z(()=>[M(L(d.value.manual),1)]),_:1})):k(``,!0),d.value.failed?(P(),O(R(H),{key:7,"data-tolk-summary-failed":``},{default:z(()=>[M(L(d.value.failed),1)]),_:1})):k(``,!0),d.value.unsaved?(P(),O(R(H),{key:8,"data-tolk-summary-unsaved":``},{default:z(()=>[M(L(d.value.unsaved),1)]),_:1})):k(``,!0)])):k(``,!0),c.value===`error`||c.value===`done`&&f.value?(P(),A(`div`,Bl,[c.value===`error`?(P(),O(R(B),{key:0,size:`sm`,variant:`primary`,"data-tolk-action":`retry`,onClick:t[5]||=e=>R(qs).retry(R(i))},{default:z(()=>[M(L(p.value?e.__(`Start again`):e.__(`Retry`)),1)]),_:1})):k(``,!0),f.value?(P(),O(R(B),{key:1,size:`sm`,"data-tolk-action":`undo`,onClick:re},{default:z(()=>[M(L(e.__(`Undo`)),1)]),_:1})):k(``,!0)])):k(``,!0),h.value?(P(),A(`div`,Vl,[N(R(W),{name:`warning-diamond`,class:`size-4 shrink-0 text-amber-600`,"aria-hidden":`true`}),N(R(q),null,{default:z(()=>[M(L(h.value),1)]),_:1})])):k(``,!0),u.value.origin?(P(),A(`div`,Hl,[j(`div`,Ul,[N(R(W),{name:`dictionary-language-book`,class:`size-4 shrink-0 text-gray-500`,"aria-hidden":`true`}),N(R(q),null,{default:z(()=>[M(L(T.value?e.__(`Translations of this term:`):e.__(`Translations of this entry:`)),1)]),_:1})]),j(`ul`,Wl,[(P(!0),A(m,null,I(u.value.origin.localizations,e=>(P(),A(`li`,{key:e.site,class:`col-span-3 grid grid-cols-subgrid items-center`,"data-tolk-site":e.site},[e.editUrl?(P(),A(`a`,{key:0,href:e.editUrl,class:`text-sm font-medium underline`},L(e.name),9,Kl)):(P(),O(R(q),{key:1,variant:`strong`},{default:z(()=>[M(L(e.name),1)]),_:2},1024)),N(R(Fn),{text:e.label,color:e.color,class:`justify-self-start`},null,8,[`text`,`color`]),e.exists&&e.summary?(P(),O(R(H),{key:2},{default:z(()=>[M(L(e.summary),1)]),_:2},1024)):k(``,!0)],8,Gl))),128))]),u.value.origin.autoUpdate?(P(),O(R(H),{key:0,class:`ps-6`,"data-tolk-auto-update":``},{default:z(()=>[M(L(u.value.origin.autoUpdate),1)]),_:1})):k(``,!0),N(bc,{"container-name":R(i),reference:s.value.reference,origin:u.value.origin,status:s.value.status,dirty:C.value},null,8,[`container-name`,`reference`,`origin`,`status`,`dirty`])])):k(``,!0),u.value.localization?(P(),O(Mc,{key:8,"container-name":R(i),status:s.value.status,open:c.value===`offer`},null,8,[`container-name`,`status`,`open`])):k(``,!0),R(x).open?(P(),O(Fa,{key:9,modal:R(x),corrections:s.value.summary?.corrections??[],reviewer:s.value.summary?.reviewer??null},null,8,[`modal`,`corrections`,`reviewer`])):k(``,!0),u.value.setup?(P(),O(R(H),{key:10,"data-tolk-setup":``},{default:z(()=>[M(L(e.__(`Translation is not set up yet.`))+` `,1),R(w)?(P(),A(`a`,{key:0,href:R(w)},L(e.__(`Open the Tolk settings`)),9,ql)):(P(),A(m,{key:1},[M(L(e.__(`Ask an administrator to configure a provider in the Tolk settings.`)),1)],64))]),_:1})):k(``,!0)],64))]),_:1},512)):k(``,!0)}}},Yl={class:`flex items-center justify-end gap-3 pt-3 pb-1`},Xl={__name:`TranslateFieldConfirm`,emits:[`confirm`,`cancel`],setup(e,{emit:t}){let n=t,r=tc(),i=!1;mt(()=>r.show());function a(e){i||(i=!0,n(e))}function o(e){r.hide(),a(e)}function s(e){r.closed(e),e||a(`cancel`)}return(e,t)=>R(r).open?(P(),O(R(Wr),{key:0,open:``,title:e.__(`Translate from origin`),"data-tolk-field-confirm":``,onDismissed:t[2]||=e=>R(r).dismissed(),"onUpdate:open":s},{footer:z(()=>[j(`div`,Yl,[N(R(B),{variant:`ghost`,text:e.__(`Cancel`),"data-tolk-field-confirm-action":`cancel`,onClick:t[0]||=e=>o(`cancel`)},null,8,[`text`]),N(R(B),{variant:`primary`,text:e.__(`Translate`),"data-tolk-field-confirm-action":`translate`,onClick:t[1]||=e=>o(`confirm`)},null,8,[`text`])])]),default:z(()=>[N(R(q),{as:`p`},{default:z(()=>[M(L(e.__(`The current content of this field will be replaced.`)),1)]),_:1})]),_:1},8,[`title`])):k(``,!0)}},Zl=`tolk-translate-field-confirm`;function Ql(e,t){if(e===t)return!0;if(Array.isArray(e)||Array.isArray(t))return Array.isArray(e)&&Array.isArray(t)&&e.length===t.length&&e.every((e,n)=>Ql(e,t[n]));if(e===null||t===null||typeof e!=`object`||typeof t!=`object`)return!1;let n=Object.keys(e);return n.length===Object.keys(t).length&&n.every(n=>Object.hasOwn(t,n)&&Ql(e[n],t[n]))}function $l({registry:e=za,store:t=_s,translations:n=qs,fieldActions:r=()=>Statamic.$fieldActions,config:i=()=>Statamic.$config,permissions:a=()=>Statamic.$permissions,toast:o=()=>Statamic.$toast,components:s=()=>Statamic.$components,doc:c=()=>globalThis.document,wait:l=setTimeout}={}){let u=!1;function d({vm:n,fieldPathPrefix:r,handle:i,config:o,isReadOnly:s}){if(r||s||!o?.localizable||!a().has(`translate content`)||n&&n.publishContainer?.name!==`base`||e.others().length>0)return!1;let c=e.base(),l=t().containers[X],u=l?.status;if(!c||c.readOnly?.value||!u?.localization||l.reference!==c.reference.value)return!1;let d=Y(u.localization.fields)[i];return!la(u)&&!Os.includes(l.phase)&&Object.hasOwn(c.originValues?.value??{},i)&&!!d&&d.status!==`not_applicable`}async function f({handle:r,value:i}){let a=e.base(),s=t();if(!a||!Ql(i,a.values.value[r])){o().error(Ys(s.containers.base?.reference)?__(`This field is not part of the term being translated.`):__(`This field is not part of the entry being translated.`));return}if(Os.includes(s.phaseOf(`base`))||n.running(`base`)){o().error(__(`A translation is already running. Try again when it has finished.`));return}let c=s.containers[X],l=await n.translate(X,{mode:`all`,fields:[r],overwriteManual:!0,replace:!0});if(s.containers.base===c){if(c.phase===`error`){o().error(c.error?.message||__(`Something went wrong.`));return}if(l&&!l.cancelled&&!l.delivered.includes(r)){let e=xa(l,c.status);o().error(e.failed??e.edited??e.translated)}}}function p(e){return[...c()?.querySelectorAll(`label[for]`)??[]].find(t=>t.getAttribute(`for`)===`field_${e}`)?.closest(`[data-ui-input-group]`)?.querySelector(`[data-ui-field-header] [data-ui-dropdown-trigger]`)??null}function m(){let e=c()?.querySelector(`[data-tolk-banner]`);return e?.querySelector(`[data-tolk-action="cancel"]`)??e?.querySelector(`[data-tolk-focus]`)??null}function h(e){for(let t of[0,400])l(()=>{let t=c()?.activeElement;(!t||t===c().body)&&e()?.focus()},t)}function g(e){let t=s().append(Zl,{props:{}});t.on(`confirm`,()=>{t.destroy(),f(e).catch(()=>o().error(__(`Something went wrong.`))),h(()=>m()??p(e.handle))}),t.on(`cancel`,()=>{t.destroy(),h(()=>p(e.handle))})}let _={get title(){return __(`Translate from origin`)},visible:d,run:g};function v(){if(!u){u=!0;for(let e of i().get(`tolk.fieldtypes`)??[])r().add(`${e}-fieldtype`,_)}}return{register:v,action:_,visible:d,run:g}}var eu=$l(),{Fieldtype:tu,IndexFieldtype:nu,FieldtypeMixin:ru,HasActionsMixin:iu,HasInputOptionsMixin:au,HasPreferencesMixin:ou,IndexFieldtypeMixin:su,InlineEditForm:cu,DateFormatter:lu,NumberFormatter:uu,ItemActions:du,RelatedItem:fu,RestoreRevision:pu,RevisionHistory:mu,RevisionPreview:hu,SaveButtonOptions:gu,SortableList:_u,requireElevatedSession:vu,requireElevatedSessionIf:yu,clone:bu,debounce:xu,deepClone:Su,resetValuesFromResponse:Cu}=__STATAMIC__.core,wu=`automatic`;function Tu(e){return typeof e==`string`&&e.trim()!==``?e.trim():null}function Eu(e){return/^[^\s:]+:\S+$/.test(e)}function Du(e){return{quality:__(`Quality`),fast:__(`Fast`)}[e]??null}function Ou(e,t){return{value:e,label:e,note:Y(t)[e.split(`:`)[0]]?.[0]?.configured===!1?__(`No API key`):__(`Custom model`),disabled:!1}}function ku(e,t){let n=[{value:wu,label:e?.automatic||__(`Automatic`),note:null,disabled:!1}],r=e?.fake_engine===!0;for(let t of Object.values(Y(e?.catalog)).flat())n.push({value:t.value,label:t.label,note:t.configured?Du(t.tier):__(`No API key`),disabled:!t.configured&&!r});let i=Tu(t);return i&&!n.some(e=>e.value===i)&&n.push(Ou(i,e?.catalog)),n}function Au(e,t){if(e===null||e===`automatic`)return null;let n=t.find(t=>t.value===e);if(n)return n.disabled?void 0:n.value;let r=typeof e==`string`?e.trim():``;return Eu(r)?r:void 0}var ju=[`data-tolk-model-note`],Mu={__name:`ModelSelect`,props:tu.props,emits:tu.emits,setup(e,{expose:t,emit:n}){let r=n,i=e,{expose:a,isReadOnly:o,update:s}=tu.use(r,i),c=D(()=>ku(i.meta,i.value)),l=D(()=>Tu(i.value)??`automatic`);function u(e){let t=Au(e,c.value);t!==void 0&&t!==Tu(i.value)&&s(t)}return t(a),(e,t)=>(P(),O(R(Gn),{id:e.id,"model-value":l.value,options:c.value,"read-only":R(o),placeholder:e.__(`Choose a model`),taggable:``,"data-tolk-model-select":``,"onUpdate:modelValue":u},{option:z(e=>[j(`span`,{class:at([`truncate`,{"opacity-50":e.disabled}])},L(e.label),3),e.note?(P(),A(`span`,{key:0,class:at([`ms-auto shrink-0 text-xs text-gray-500 dark:text-gray-400`,{"opacity-50":e.disabled}]),"data-tolk-model-note":e.value},L(e.note),11,ju)):k(``,!0)]),_:1},8,[`id`,`model-value`,`options`,`read-only`,`placeholder`]))}};function Nu(e){let t=e?.fake_engine===!0;return(Array.isArray(e?.providers)?e.providers:[]).map(e=>{let n=e.configured===!0;return{provider:e.provider,label:e.label,badge:Pu(n),source:Fu(e.source),hint:n?null:Iu(e.env),testable:n||t}})}function Pu(e){return e?{text:__(`Configured`),color:`green`}:{text:__(`No API key`),color:`default`}}function Fu(e){return{ai:__(`The key comes from config/ai.php, which Tolk shares with the rest of the site.`),addon:__(`The key is Tolk's own, from the addon's config.`)}[e]??null}function Iu(e){return e?.ai?__(`Add :variable to the .env file, or :override to give Tolk a key of its own.`,{variable:e.ai,override:e.addon}):null}function Lu(e){if(e?.ok!==!0)return{ok:!1,text:e?.error||__(`The test failed.`)};let t={model:e.label||e.model,ms:e.latency_ms};return{ok:!0,text:e.fake?__(`The fake engine answered for :model in :ms ms, without calling the provider.`,t):__(`:model answered in :ms ms.`,t)}}async function Ru(e,t=J){try{return await t.post(`providers/test`,{provider:e})}catch(e){return{ok:!1,error:e.message}}}var zu={class:`divide-y divide-gray-200 dark:divide-gray-700`,"data-tolk-providers":``},Bu=[`data-tolk-provider`],Vu={class:`flex flex-wrap items-center gap-2`},Hu={__name:`ProvidersStatus`,props:tu.props,emits:tu.emits,setup(e,{expose:t,emit:n}){let r=n,i=e,{expose:a}=tu.use(r,i),o=D(()=>Nu(i.meta)),s=Ot({}),c=Ot({});async function l(e){s[e]=!0,c[e]=null;try{c[e]=Lu(await Ru(e))}finally{s[e]=!1}}return t(a),(e,t)=>(P(),A(`div`,zu,[(P(!0),A(m,null,I(o.value,t=>(P(),A(`div`,{key:t.provider,class:`space-y-1 py-3 first:pt-0 last:pb-0`,"data-tolk-provider":t.provider},[j(`div`,Vu,[N(R(q),{variant:`strong`},{default:z(()=>[M(L(t.label),1)]),_:2},1024),N(R(Fn),{text:t.badge.text,color:t.badge.color,"data-tolk-provider-status":``},null,8,[`text`,`color`]),t.testable?(P(),O(R(B),{key:0,class:`ms-auto`,size:`sm`,text:e.__(`Test connection`),loading:!!s[t.provider],disabled:!!s[t.provider],"data-tolk-provider-test":``,onClick:e=>l(t.provider)},null,8,[`text`,`loading`,`disabled`,`onClick`])):k(``,!0)]),t.source?(P(),O(R(H),{key:0},{default:z(()=>[M(L(t.source),1)]),_:2},1024)):k(``,!0),t.hint?(P(),O(R(H),{key:1},{default:z(()=>[M(L(t.hint),1)]),_:2},1024)):k(``,!0),c[t.provider]?(P(),O(R(q),{key:2,variant:c[t.provider].ok?`success`:`danger`,"data-tolk-provider-result":c[t.provider].ok?`ok`:`failed`},{default:z(()=>[M(L(c[t.provider].text),1)]),_:2},1032,[`variant`,`data-tolk-provider-result`])):k(``,!0)],8,Bu))),128))]))}},{asMap:Uu}=J,Wu=`glossary`;function Gu(e,t=J){let n=Uu(e),r=Object.hasOwn(n,`translator_model`)?{model:n.translator_model||null}:{};return t.post(`site-profile/generate`,r)}function Ku(e){return typeof e==`string`&&e.trim()!==``}function qu(e){return String(e??``).normalize(`NFKD`).toLowerCase().replace(/\p{Mn}+/gu,``).replace(/[\s\p{Z}]+/gu,` `).trim()}function Ju(e){let t=e?.site;return Array.isArray(t)?t.length===0:!t}function Yu(e){return new Set((Array.isArray(e)?e:[]).filter(Ju).map(e=>qu(e?.term)).filter(e=>e!==``))}function Xu(e,t,n={}){let r=Yu(t);return(Array.isArray(e)?e:[]).map(e=>{let t=r.has(qu(e));return{term:e,inGlossary:t,chosen:!t&&n[e]!==!0}})}function Zu(){return Array.from(crypto.getRandomValues(new Uint8Array(12)),e=>`abcdefghijklmnopqrstuvwxyz0123456789`[e%36]).join(``)}function Qu(e){return JSON.parse(JSON.stringify(e??{}))}function $u(e,t,n,r=Zu){let i=Array.isArray(t)?t:[],a=Uu(n),o=Yu(i),s={...Uu(a.existing)},c=[];for(let t of e){let e=qu(t);if(e===``||o.has(e))continue;let n=r();o.add(e),s[n]=Qu(Uu(a.new)),c.push({...Qu(Uu(a.defaults)),term:t.trim(),do_not_translate:!0,_id:n})}return{rows:[...i,...c],meta:{...a,existing:s},added:c.map(e=>e.term)}}var ed={class:`space-y-3`,"data-tolk-site-profile":``},td={key:0,class:`flex flex-wrap items-center gap-3`},nd={key:3,class:`space-y-2`,"data-tolk-site-profile-terms":``},rd={class:`space-y-1`},id=[`data-tolk-site-profile-term`],ad={class:`flex flex-wrap items-center gap-3`},od={class:`list-disc ps-5 text-sm`},sd=[`data-tolk-site-profile-term`],cd={__name:`SiteProfile`,props:tu.props,emits:tu.emits,setup(e,{expose:t,emit:n}){let r=n,i=e,{expose:a,isReadOnly:o,update:s}=tu.use(r,i),c=ti(),l=F(!1),u=F(!1),d=F(null),f=F(null),p=F(null),h=Ot({}),g=D(()=>Y(c?.values.value)),_=D(()=>!o.value&&Object.hasOwn(g.value,`glossary`)&&Object.hasOwn(Y(c?.meta.value),`glossary`)),v=D(()=>Xu(f.value?.terms,g.value[Wu],h)),y=D(()=>v.value.filter(e=>e.chosen).map(e=>e.term));function b(){Ku(i.value)?u.value=!0:x()}async function x(){u.value=!1,l.value=!0,d.value=null;try{let e=await Gu(g.value);s(e.profile),f.value={label:e.label||e.model,terms:Array.isArray(e.terms)?e.terms:[]},p.value=null,Object.keys(h).forEach(e=>delete h[e])}catch(e){d.value=e.message}finally{l.value=!1}}function S(e,t){h[e]=!t}function ee(){let e=$u(y.value,g.value[Wu],c.meta.value[Wu]);c.setFieldMeta(Wu,e.meta),c.setFieldValue(Wu,e.rows),p.value=e.added.length}return t(a),(e,t)=>(P(),A(`div`,ed,[N(R(Fi),{id:e.id,name:e.handle,"model-value":e.value,"read-only":R(o),rows:8,"onUpdate:modelValue":R(s)},null,8,[`id`,`name`,`model-value`,`read-only`,`onUpdate:modelValue`]),R(o)?k(``,!0):(P(),A(`div`,td,[N(R(B),{size:`sm`,icon:`ai-sparks`,text:e.__(`Generate`),loading:l.value,disabled:l.value,"data-tolk-site-profile-generate":``,onClick:b},null,8,[`text`,`loading`,`disabled`]),N(R(H),null,{default:z(()=>[M(L(e.__(`Has the translator write a profile from the content of the default site. Check it before you save.`)),1)]),_:1})])),d.value?(P(),O(R(q),{key:1,variant:`danger`,"data-tolk-site-profile-error":``},{default:z(()=>[M(L(d.value),1)]),_:1})):k(``,!0),f.value?(P(),O(R(H),{key:2,"data-tolk-site-profile-written":``},{default:z(()=>[M(L(e.__(`Written by :model. It is not saved until you save the settings.`,{model:f.value.label})),1)]),_:1})):k(``,!0),v.value.length?(P(),A(`div`,nd,[N(R(q),{variant:`strong`},{default:z(()=>[M(L(e.__(`Names to keep untranslated`)),1)]),_:1}),_.value?(P(),A(m,{key:0},[j(`div`,rd,[(P(!0),A(m,null,I(v.value,t=>(P(),A(`div`,{key:t.term,"data-tolk-site-profile-term":t.term},[N(R(Hn),{"model-value":t.chosen,label:t.term,description:t.inGlossary?e.__(`Already in the glossary`):null,disabled:t.inGlossary,"onUpdate:modelValue":e=>S(t.term,e)},null,8,[`model-value`,`label`,`description`,`disabled`,`onUpdate:modelValue`])],8,id))),128))]),j(`div`,ad,[N(R(B),{size:`sm`,text:e.__(`Add to glossary`),disabled:y.value.length===0,"data-tolk-site-profile-add":``,onClick:ee},null,8,[`text`,`disabled`]),p.value===null?k(``,!0):(P(),O(R(H),{key:0,"data-tolk-site-profile-added":``},{default:z(()=>[M(L(e.__n(`Added :count name to the glossary with Do not translate on. Save the settings to keep it.|Added :count names to the glossary with Do not translate on. Save the settings to keep them.`,p.value)),1)]),_:1}))])],64)):(P(),A(m,{key:1},[j(`ul`,od,[(P(!0),A(m,null,I(v.value,e=>(P(),A(`li`,{key:e.term,"data-tolk-site-profile-term":e.term},L(e.term),9,sd))),128))]),N(R(H),null,{default:z(()=>[M(L(e.__(`Add them to the glossary with Do not translate on, so that every translation keeps them.`)),1)]),_:1})],64))])):k(``,!0),u.value?(P(),O(R(qn),{key:4,open:``,"onUpdate:open":t[0]||=e=>u.value=e,title:e.__(`Replace the site profile?`),"body-text":e.__(`A new profile replaces the text in this field. Nothing is saved until you save the settings.`),"button-text":e.__(`Generate`),onConfirm:x},null,8,[`title`,`body-text`,`button-text`])):k(``,!0)]))}},{Form:ld,Head:ud,Link:dd,router:fd,toggleArchitecturalBackground:pd,useArchitecturalBackground:md,useForm:hd,usePage:gd,usePoll:_d}=__STATAMIC__.inertia,vd={class:`mx-auto max-w-page space-y-6`,"data-tolk-audit":``},yd={class:`flex flex-wrap items-center gap-2`},bd={key:1,class:`space-y-3`},xd=[`data-tolk-item-level`],Sd=[`data-tolk-blueprint`],Cd={class:`flex flex-wrap items-center justify-between gap-2`},wd={class:`flex items-center gap-2`},Td=[`href`],Ed={class:`space-y-2`},Dd=[`data-tolk-field`],Od=[`data-tolk-field-imported`],kd=[`href`],Ad={key:1,class:`space-y-1 ps-6`},jd=[`data-tolk-field`],Md={class:`text-xs text-gray-600 dark:text-gray-400`},Nd={key:1,class:`flex items-start gap-2`},Pd={__name:`Audit`,props:{checks:{type:Array,default:()=>[]},canMakeLocalizable:{type:Boolean,default:!1},urls:{type:Object,required:!0}},setup(e){let t=e,n=F(t.checks),r=Ot({}),i=F(null),a=F(null),o=D(()=>cl(n.value));xn(()=>t.checks,e=>n.value=e);function s(e,t){return(r[dl(e)]??[]).includes(t)}function c(e,t,n){let i=dl(e),a=(r[i]??[]).filter(e=>e!==t);r[i]=n?[...a,t]:a}function l(e){let t=hl(e,r[dl(e)]);t.length>0&&(i.value={item:e,fields:t,text:gl(e,t)})}async function u(){let{item:e,fields:o}=i.value,s=dl(e);i.value=null,a.value=s;try{let i=await $i(t.urls.localizable,{namespace:e.namespace,blueprint:e.blueprint,fields:o});n.value=i.checks,delete r[s],Statamic.$toast.success(_l(i.changed))}catch(e){Statamic.$toast.error(e.message)}finally{a.value=null}}return(t,d)=>(P(),A(`div`,vd,[N(R(ud),{title:t.__(`Audit`)},null,8,[`title`]),N(R(xr),{title:t.__(`Setup audit`),icon:`clipboard-check`},{default:z(()=>[N(R(dd),{href:e.urls.overview,class:`text-sm text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-200`},{default:z(()=>[M(L(t.__(`Overview`)),1)]),_:1},8,[`href`]),N(R(B),{text:t.__(`Check again`),icon:`sync`,"data-tolk-audit-reload":``,onClick:d[0]||=e=>R(fd).reload()},null,8,[`text`])]),_:1},8,[`title`]),N(R(V),{class:`flex items-start gap-3`,"data-tolk-audit-summary":``,"data-tolk-audit-level":o.value.level},{default:z(()=>[N(R(W),{name:R($)(o.value.level).icon,class:at([`mt-0.5 size-5 shrink-0`,R($)(o.value.level).class]),"aria-hidden":`true`},null,8,[`name`,`class`]),N(R(q),null,{default:z(()=>[M(L(o.value.text),1)]),_:1})]),_:1},8,[`data-tolk-audit-level`]),(P(!0),A(m,null,I(n.value,n=>(P(),O(R(V),{id:R(al)(n.id),key:n.id,class:`space-y-3`,"data-tolk-check":n.id,"data-tolk-check-level":n.level},{default:z(()=>[j(`div`,yd,[N(R(W),{name:R($)(n.level).icon,class:at([`size-4 shrink-0`,R($)(n.level).class]),"aria-hidden":`true`},null,8,[`name`,`class`]),N(R(U),{size:`lg`,level:2},{default:z(()=>[M(L(n.title),1)]),_:2},1024),N(R(Fn),{text:R($)(n.level).label,color:R($)(n.level).color},null,8,[`text`,`color`])]),N(R(H),null,{default:z(()=>[M(L(R(ll)(n,e.canMakeLocalizable)),1)]),_:2},1024),n.items.length===0?(P(),O(R(q),{key:0,"data-tolk-audit-nothing":``},{default:z(()=>[M(L(n.id===R(`localizable`)?t.__(`Every text field Tolk could translate is localizable.`):t.__(`Nothing to report.`)),1)]),_:2},1024)):(P(),A(`ul`,bd,[(P(!0),A(m,null,I(n.items,(i,o)=>(P(),A(`li`,{key:o,"data-tolk-item":``,"data-tolk-item-level":i.level},[R(ul)(i)?(P(),A(`div`,{key:0,class:`space-y-2 rounded-lg border border-gray-200 p-3 dark:border-gray-700`,"data-tolk-blueprint":R(dl)(i)},[j(`div`,Cd,[j(`div`,wd,[N(R(W),{name:R($)(i.level).icon,class:at([`size-4 shrink-0`,R($)(i.level).class]),role:`img`,"aria-label":R($)(i.level).label},null,8,[`name`,`class`,`aria-label`]),N(R(q),{class:`font-medium`},{default:z(()=>[M(L(i.name),1)]),_:2},1024)]),i.edit_url?(P(),A(`a`,{key:0,href:i.edit_url,class:`text-sm text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-blueprint-link":``},L(t.__(`Edit blueprint`)),9,Td)):k(``,!0)]),n.id===R(`localizable`)?(P(),A(m,{key:0},[j(`div`,Ed,[(P(!0),A(m,null,I(R(fl)(i).editable,t=>(P(),A(`div`,{key:t.handle,"data-tolk-field":t.handle},[e.canMakeLocalizable?(P(),O(R(Hn),{key:0,"model-value":s(i,t.handle),label:R(pl)(t),disabled:a.value!==null,"onUpdate:modelValue":e=>c(i,t.handle,e)},null,8,[`model-value`,`label`,`disabled`,`onUpdate:modelValue`])):(P(),O(R(q),{key:1},{default:z(()=>[M(L(R(pl)(t)),1)]),_:2},1024))],8,Dd))),128)),(P(!0),A(m,null,I(R(fl)(i).imported,n=>(P(),A(`div`,{key:n.handle,"data-tolk-field-imported":n.handle},[e.canMakeLocalizable?(P(),O(R(Hn),{key:0,"model-value":!1,label:R(pl)(n),description:R(ml)(n),disabled:``},null,8,[`label`,`description`])):(P(),A(m,{key:1},[N(R(q),null,{default:z(()=>[M(L(R(pl)(n)),1)]),_:2},1024),N(R(H),null,{default:z(()=>[M(L(R(ml)(n)),1)]),_:2},1024)],64)),n.fieldset_url?(P(),A(`a`,{key:2,href:n.fieldset_url,class:`ms-6 text-sm text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-fieldset-link":``},L(t.__(`Edit fieldset`)),9,kd)):k(``,!0)],8,Od))),128))]),e.canMakeLocalizable&&R(fl)(i).editable.length>0?(P(),O(R(B),{key:0,size:`sm`,variant:`primary`,text:t.__(`Make localizable`),loading:a.value===R(dl)(i),disabled:a.value!==null||R(hl)(i,r[R(dl)(i)]).length===0,"data-tolk-make-localizable":``,onClick:e=>l(i)},null,8,[`text`,`loading`,`disabled`,`onClick`])):k(``,!0)],64)):(P(),A(`ul`,Ad,[(P(!0),A(m,null,I(i.fields,e=>(P(),A(`li`,{key:e.path??e.handle,"data-tolk-field":e.path??e.handle},[N(R(q),null,{default:z(()=>[M(L(e.label)+` `,1),j(`code`,Md,L(e.path??e.handle),1)]),_:2},1024)],8,jd))),128))]))],8,Sd)):(P(),A(`div`,Nd,[N(R(W),{name:R($)(i.level).icon,class:at([`mt-0.5 size-4 shrink-0`,R($)(i.level).class]),role:`img`,"aria-label":R($)(i.level).label},null,8,[`name`,`class`,`aria-label`]),N(R(q),null,{default:z(()=>[M(L(i.text),1)]),_:2},1024)]))],8,xd))),128))]))]),_:2},1032,[`id`,`data-tolk-check`,`data-tolk-check-level`]))),128)),i.value?(P(),O(R(qn),{key:0,open:``,title:t.__(`Make these fields localizable?`),"button-text":t.__(`Make localizable`),"data-tolk-localizable-confirm":``,"onUpdate:open":d[1]||=e=>i.value=e?i.value:null,onConfirm:u},{default:z(()=>[N(R(q),null,{default:z(()=>[M(L(i.value.text),1)]),_:1})]),_:1},8,[`title`,`button-text`])):k(``,!0)]))}},Fd={class:`overflow-x-auto`},Id={__name:`RunsTable`,props:{runs:{type:Array,default:()=>[]}},setup(e){let t=e,n=Xo(Statamic.$config.get(`sites`)),r=D(()=>t.runs.map(e=>{let t=$o({counts:e.counts}),r=ls(e),i=os(e.scope,n);return{id:e.id,url:e.url,status:e.status,what:i.what,automatic:i.automatic,sites:i.sites,progress:__(`:finished of :total`,{finished:Q(t.finished),total:Q(t.total)}),failed:t.counts.failed,tokens:r.input+r.output,cost:r.cost,date:Qo(e.created_at),by:e.created_by?.name??(i.automatic?__(`Automatic update`):__(`Command line`))}}));return(e,t)=>(P(),A(`div`,Fd,[N(R(Di),null,{default:z(()=>[N(R(Oi),null,{default:z(()=>[N(R(K),null,{default:z(()=>[M(L(e.__(`Status`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(e.__(`Content`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(e.__(`Sites`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(e.__(`Items finished`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(e.__(`Usage`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(e.__(`Created`)),1)]),_:1})]),_:1}),N(R(Ai),null,{default:z(()=>[(P(!0),A(m,null,I(r.value,t=>(P(),O(R(ki),{key:t.id,"data-tolk-run-row":``,"data-tolk-run-id":t.id},{default:z(()=>[N(R(G),null,{default:z(()=>[N(R(dd),{href:t.url,class:`inline-flex`},{default:z(()=>[N(R(Fn),{text:R(Go)(t.status),color:R(Ko)(t.status)},null,8,[`text`,`color`])]),_:2},1032,[`href`])]),_:2},1024),N(R(G),null,{default:z(()=>[N(R(dd),{href:t.url,class:`text-blue-600 hover:underline dark:text-blue-400`},{default:z(()=>[M(L(t.what),1)]),_:2},1032,[`href`]),t.automatic?(P(),O(R(H),{key:0,"data-tolk-run-automatic":``},{default:z(()=>[M(L(e.__(`Automatic update`)),1)]),_:1})):k(``,!0)]),_:2},1024),N(R(G),null,{default:z(()=>[M(L(t.sites),1)]),_:2},1024),N(R(G),null,{default:z(()=>[M(L(t.progress)+` `,1),t.failed>0?(P(),O(R(H),{key:0},{default:z(()=>[M(L(e.__n(`:count failed|:count failed`,t.failed)),1)]),_:2},1024)):k(``,!0)]),_:2},1024),N(R(G),null,{default:z(()=>[M(L(e.__(`:tokens tokens`,{tokens:R(Q)(t.tokens)}))+` `,1),N(R(H),null,{default:z(()=>[M(L(t.cost===null?e.__(`Cost unknown`):R(Zo)(t.cost)),1)]),_:2},1024)]),_:2},1024),N(R(G),null,{default:z(()=>[M(L(t.date)+` `,1),N(R(H),null,{default:z(()=>[M(L(t.by),1)]),_:2},1024)]),_:2},1024)]),_:2},1032,[`data-tolk-run-id`]))),128))]),_:1})]),_:1})]))}};function Ld({scan:e,onChange:t=()=>{},concurrency:n=3}){let r=[],i=0,a=0;function o(e){return e.generation===a}function s(){for(;i0;)c(r.shift())}async function c(n){i++,t(n.cell.key,{status:`loading`});try{let r=null;do{let i=await e({...n.cell,cursor:r,fresh:n.fresh});if(!o(n))return;r=i.cursor??null,t(n.cell.key,{...i,status:r===null?`done`:`loading`})}while(r!==null)}catch(e){o(n)&&t(n.cell.key,{status:`failed`,error:e?.message??String(e)})}finally{i--,s()}}function l(){a++,r=[]}function u(e,n){for(let i of e)r.push({cell:i,fresh:n,generation:a}),t(i.key,{status:`waiting`});s()}return{load(e,{fresh:t=!1}={}){l(),u(e,t)},retry(e){u([e],!1)},stop:l,get active(){return i}}}var Rd=[`entry`,`term`,`globals`,`nav`],zd=[`missing`,`untranslated`,`outdated`,`attention`,`current`],Bd={entry:`collections`,term:`taxonomies`,globals:`globals`,nav:`navs`};function Vd(e){return e===`current`?__(`Current`):sa(e)}function Hd(e){return{entry:__(`Collections`),term:__(`Taxonomies`),globals:__(`Global sets`),nav:__(`Navigation`)}[e]??e}function Ud(e,t,n){return`${e}|${t}|${n}`}function Wd(e,t){let n=new Set((Array.isArray(e)?e:[]).flatMap(e=>e.sites??[]));return(Array.isArray(t)?t:[]).filter(e=>n.has(e.handle))}function Gd(e){let t=Array.isArray(e)?e:[];return Rd.map(e=>({type:e,label:Hd(e),rows:t.filter(t=>t.type===e)})).filter(e=>e.rows.length>0)}function Kd(e,t){return{key:Ud(e.type,e.handle,t),type:e.type,container:e.handle,site:t}}function qd(e){return(Array.isArray(e)?e:[]).flatMap(e=>(e.sites??[]).map(t=>Kd(e,t)))}function Jd(e){let t=Y(e?.counts),n=e=>Number(t[e])||0;return{counts:Object.fromEntries(zd.map(e=>[e,n(e)])),untracked:Number(e?.untracked)||0,scanned:Number(e?.scanned)||0,missing:n(`missing`)+n(`untranslated`),outdated:n(`outdated`)}}function Yd(e){let t=Jd(e);return{...t,badges:zd.filter(e=>t.counts[e]>0).map(e=>({status:e,text:`${Vd(e)} ${t.counts[e]}`,color:oa(e)})),finished:e?.status===`done`,loading:e?.status===`waiting`||e?.status===`loading`,failed:e?.status===`failed`,error:e?.error??null}}function Xd(e,t,n,r){return{sites:[n],[Bd[e]]:[t],options:{mode:r}}}function Zd(e,t,n){let r={};for(let i of Array.isArray(e)?e:[]){if(!(i.sites??[]).includes(n))continue;let e=Y(t)[Ud(i.type,i.handle,n)];(e?.status!==`done`||Jd(e).missing!==0)&&(r[Bd[i.type]]??=[]).push(i.handle)}return Object.keys(r).length>0?{sites:[n],...r,options:{mode:`missing`}}:null}function Qd({multisite:e,providers:t,fakeEngine:n}){return e?(Array.isArray(t)?t:[]).some(e=>e.configured)||n?null:`no_provider`:`single_site`}function $d(e){let t=Y(e?.labels),n=Object.entries(Y(e?.models)).map(([e,n])=>({reference:e,model:t[e]??e,calls:Number(n?.calls)||0,input:Number(n?.input)||0,output:Number(n?.output)||0,cost:n?.cost===null||n?.cost===void 0?null:Number(n.cost),sources:Object.keys(Y(n?.sources))}));return{month:e?.month??``,rows:n,calls:n.reduce((e,t)=>e+t.calls,0),cost:n.some(e=>e.cost===null)?null:n.reduce((e,t)=>e+t.cost,0)}}function ef(e){return{editor:__(`Editor`),run:__(`Runs`),cli:__(`Command line`),auto:__(`Automatic updates`)}[e]??e}function tf(e,t=void 0){let n=/^(\d{4})-(\d{2})$/.exec(e??``);return n?new Intl.DateTimeFormat(t,{month:`long`,year:`numeric`}).format(Date.UTC(n[1],n[2]-1,15)):``}var nf={class:`mx-auto max-w-page space-y-6`,"data-tolk-overview":``},rf={class:`flex flex-wrap gap-4 text-sm`},af=[`href`],of={class:`overflow-x-auto`},sf={class:`flex flex-col items-start gap-1`},cf={key:1,class:`space-y-1.5`},lf={key:0,class:`flex flex-wrap gap-1`},uf={key:4,class:`space-y-1`},df={key:5,class:`flex flex-wrap gap-1`},ff={class:`grid gap-6 lg:grid-cols-2`},pf={class:`flex flex-wrap items-center justify-between gap-2`},mf={class:`overflow-x-auto`},hf={class:`space-y-2`},gf=[`data-tolk-provider`],_f=[`href`],vf={class:`flex flex-wrap items-baseline justify-between gap-2`},yf={__name:`Overview`,props:{multisite:{type:Boolean,default:!1},sites:{type:Array,default:()=>[]},rows:{type:Array,default:()=>[]},providers:{type:Array,default:()=>[]},fakeEngine:{type:Boolean,default:!1},usage:{type:Object,default:()=>({})},canResetUsage:{type:Boolean,default:!1},runs:{type:Array,default:()=>[]},urls:{type:Object,required:!0}},setup(e){let t=e,n=Ot({}),r=F(null),i=F(t.usage),a=F(!1),o=F(!1),s=Statamic.$config.get(`tolk`)?.settingsUrl??null,c=D(()=>Qd(t)),l=D(()=>Wd(t.rows,t.sites)),u=D(()=>Gd(t.rows).map(e=>({...e,rows:e.rows.map(e=>({...e,cells:l.value.map(t=>{let r=Kd(e,t.handle),i=e.sites.includes(t.handle),a=n[r.key];return{site:t,cell:r,status:i?a?.status??`waiting`:`none`,view:i?Yd(a):null}})}))}))),d=D(()=>qd(t.rows)),f=D(()=>$d(i.value)),p=D(()=>Object.values(n).some(e=>Number(e?.untracked)>0)),h=D(()=>Object.fromEntries(l.value.map(e=>[e.handle,Zd(t.rows,n,e.handle)]))),g=Ld({scan:({key:e,...n})=>$i(t.urls.scan,n),onChange:(e,t)=>n[e]=t});mt(()=>{c.value===null&&g.load(d.value)}),ut(()=>g.stop());function _(){g.load(d.value,{fresh:!0})}async function v(e,n){r.value=e;try{let{url:e}=await $i(t.urls.store,n);g.stop(),fd.visit(e)}catch(e){Statamic.$toast.error(e.message),r.value=null}}async function y(){let e=tf(f.value.month);a.value=!1,o.value=!0;try{i.value=(await $i(t.urls.resetUsage,{month:f.value.month})).usage,Statamic.$toast.success(__(`The usage of :month was reset.`,{month:e}))}catch(e){Statamic.$toast.error(e.message)}finally{o.value=!1}}return(t,n)=>(P(),A(`div`,nf,[N(R(ud),{title:t.__(`Translations`)},null,8,[`title`]),N(R(xr),{title:t.__(`Translations`),icon:`dictionary-language-book`},{default:z(()=>[N(R(dd),{href:e.urls.runs,class:`text-sm text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-200`,"data-tolk-runs-link":``},{default:z(()=>[M(L(t.__(`All runs`)),1)]),_:1},8,[`href`]),c.value===null&&d.value.length>0?(P(),O(R(B),{key:0,text:t.__(`Count again`),icon:`sync`,"data-tolk-count-again":``,onClick:_},null,8,[`text`])):k(``,!0)]),_:1},8,[`title`]),c.value===`single_site`?(P(),O(R(V),{key:0,class:`space-y-3`,"data-tolk-overview-empty":`single_site`},{default:z(()=>[N(R(U),{size:`lg`,text:t.__(`This site has one language`)},null,8,[`text`]),N(R(q),null,{default:z(()=>[M(L(t.__(`Tolk translates the content of one site into the languages of the others. Add a site for each language in Statamic first; the overview then shows what is translated into each.`)),1)]),_:1}),N(R(dd),{href:e.urls.audit,class:`text-sm text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-audit-link":``},{default:z(()=>[M(L(t.__(`Check the setup`)),1)]),_:1},8,[`href`])]),_:1})):c.value===`no_provider`?(P(),O(R(V),{key:1,class:`space-y-3`,"data-tolk-overview-empty":`no_provider`},{default:z(()=>[N(R(U),{size:`lg`,text:t.__(`No AI provider is set up`)},null,8,[`text`]),N(R(q),null,{default:z(()=>[M(L(t.__(`Tolk needs an API key of Anthropic, OpenAI or Google Gemini in the .env file before it can translate. The settings list the variables to set.`)),1)]),_:1}),j(`div`,rf,[R(s)?(P(),A(`a`,{key:0,href:R(s),class:`text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-settings-link":``},L(t.__(`Open the settings`)),9,af)):k(``,!0),N(R(dd),{href:e.urls.audit,class:`text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-audit-link":``},{default:z(()=>[M(L(t.__(`Check the setup`)),1)]),_:1},8,[`href`])])]),_:1})):e.rows.length===0?(P(),O(R(V),{key:2,"data-tolk-overview-nothing":``},{default:z(()=>[N(R(q),null,{default:z(()=>[M(L(t.__(`No collection, taxonomy, global set or navigation has more than one site yet, so there is nothing to translate.`)),1)]),_:1})]),_:1})):(P(),O(R(V),{key:3,class:`space-y-3`,"data-tolk-matrix":``},{default:z(()=>[j(`div`,of,[N(R(Di),null,{default:z(()=>[N(R(Oi),null,{default:z(()=>[N(R(K),null,{default:z(()=>[M(L(t.__(`Content`)),1)]),_:1}),(P(!0),A(m,null,I(l.value,e=>(P(),O(R(K),{key:e.handle,"data-tolk-column":e.handle},{default:z(()=>[j(`div`,sf,[j(`span`,null,L(e.name),1),h.value[e.handle]?(P(),O(R(B),{key:0,size:`xs`,text:t.__(`Translate everything missing`),"aria-label":t.__(`Translate everything missing into :site`,{site:e.name}),loading:r.value===`site|${e.handle}`,disabled:r.value!==null,"data-tolk-site-action":e.handle,onClick:t=>v(`site|${e.handle}`,h.value[e.handle])},null,8,[`text`,`aria-label`,`loading`,`disabled`,`data-tolk-site-action`,`onClick`])):k(``,!0)])]),_:2},1032,[`data-tolk-column`]))),128))]),_:1}),N(R(Ai),null,{default:z(()=>[(P(!0),A(m,null,I(u.value,e=>(P(),A(m,{key:e.type},[N(R(ki),{"data-tolk-group":e.type},{default:z(()=>[N(R(G),{colspan:l.value.length+1,class:`bg-gray-50 dark:bg-gray-900`},{default:z(()=>[N(R(U),{text:e.label},null,8,[`text`])]),_:2},1032,[`colspan`])]),_:2},1032,[`data-tolk-group`]),(P(!0),A(m,null,I(e.rows,e=>(P(),O(R(ki),{key:`${e.type}|${e.handle}`,"data-tolk-row":`${e.type}|${e.handle}`},{default:z(()=>[N(R(G),null,{default:z(()=>[N(R(q),null,{default:z(()=>[M(L(e.title),1)]),_:2},1024),N(R(H),null,{default:z(()=>[M(L(e.handle),1)]),_:2},1024)]),_:2},1024),(P(!0),A(m,null,I(e.cells,({site:i,cell:a,status:o,view:s})=>(P(),O(R(G),{key:i.handle,class:`align-top`,"data-tolk-cell":a.key,"data-tolk-cell-status":o},{default:z(()=>[s?(P(),A(`div`,cf,[s.badges.length?(P(),A(`div`,lf,[(P(!0),A(m,null,I(s.badges,e=>(P(),O(R(Fn),{key:e.status,text:e.text,color:e.color,"data-tolk-count":e.status},null,8,[`text`,`color`,`data-tolk-count`]))),128))])):k(``,!0),s.loading?(P(),O(R(H),{key:1},{default:z(()=>[M(L(t.__(`Counting…`)),1)]),_:1})):s.finished&&s.scanned===0?(P(),O(R(H),{key:2},{default:z(()=>[M(L(t.__(`Nothing to translate`)),1)]),_:1})):k(``,!0),s.untracked>0?(P(),O(R(H),{key:3,"data-tolk-untracked":``},{default:z(()=>[M(L(t.__n(`:count untracked field|:count untracked fields`,s.untracked)),1)]),_:2},1024)):k(``,!0),s.failed?(P(),A(`div`,uf,[N(R(q),{size:`sm`,variant:`danger`,"data-tolk-cell-error":``},{default:z(()=>[M(L(s.error),1)]),_:2},1024),N(R(B),{size:`xs`,text:t.__(`Try again`),"data-tolk-cell-retry":``,onClick:e=>R(g).retry(a)},null,8,[`text`,`onClick`])])):k(``,!0),s.missing>0||s.outdated>0?(P(),A(`div`,df,[s.missing>0?(P(),O(R(B),{key:0,size:`xs`,text:t.__(`Translate missing`),"aria-label":t.__(`Translate missing :content into :site`,{content:e.title,site:i.name}),loading:r.value===`${a.key}|missing`,disabled:r.value!==null,"data-tolk-cell-action":`missing`,onClick:t=>v(`${a.key}|missing`,R(Xd)(e.type,e.handle,i.handle,`missing`))},null,8,[`text`,`aria-label`,`loading`,`disabled`,`onClick`])):k(``,!0),s.outdated>0?(P(),O(R(B),{key:1,size:`xs`,text:t.__(`Update outdated`),"aria-label":t.__(`Update outdated :content in :site`,{content:e.title,site:i.name}),loading:r.value===`${a.key}|update`,disabled:r.value!==null,"data-tolk-cell-action":`update`,onClick:t=>v(`${a.key}|update`,R(Xd)(e.type,e.handle,i.handle,`update`))},null,8,[`text`,`aria-label`,`loading`,`disabled`,`onClick`])):k(``,!0)])):k(``,!0)])):(P(),O(R(H),{key:0},{default:z(()=>[...n[2]||=[M(`—`,-1)]]),_:1}))]),_:2},1032,[`data-tolk-cell`,`data-tolk-cell-status`]))),128))]),_:2},1032,[`data-tolk-row`]))),128))],64))),128))]),_:1})]),_:1})]),p.value?(P(),O(R(H),{key:0,"data-tolk-baseline-hint":``},{default:z(()=>[M(L(t.__(`Untracked fields were translated by hand without a record of their origin, so a change to the origin goes unnoticed. Run php please tolk:baseline to record the origin of each.`)),1)]),_:1})):k(``,!0)]),_:1})),j(`div`,ff,[N(R(V),{class:`space-y-3`,"data-tolk-usage":``},{default:z(()=>[j(`div`,pf,[N(R(U),{size:`lg`,text:t.__(`Usage in :month`,{month:R(tf)(f.value.month)})},null,8,[`text`]),e.canResetUsage&&f.value.rows.length>0?(P(),O(R(B),{key:0,size:`sm`,text:t.__(`Reset`),"aria-label":t.__(`Reset the usage of :month`,{month:R(tf)(f.value.month)}),loading:o.value,"data-tolk-usage-reset":``,onClick:n[0]||=e=>a.value=!0},null,8,[`text`,`aria-label`,`loading`])):k(``,!0)]),f.value.rows.length===0?(P(),O(R(q),{key:0},{default:z(()=>[M(L(t.__(`No model was called this month.`)),1)]),_:1})):(P(),A(m,{key:1},[j(`div`,mf,[N(R(Di),null,{default:z(()=>[N(R(Oi),null,{default:z(()=>[N(R(K),null,{default:z(()=>[M(L(t.__(`Model`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(t.__(`Calls`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(t.__(`Tokens`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(t.__(`Cost`)),1)]),_:1})]),_:1}),N(R(Ai),null,{default:z(()=>[(P(!0),A(m,null,I(f.value.rows,e=>(P(),O(R(ki),{key:e.reference,"data-tolk-usage-model":e.reference},{default:z(()=>[N(R(G),null,{default:z(()=>[M(L(e.model)+` `,1),N(R(H),null,{default:z(()=>[M(L(e.sources.map(R(ef)).join(`, `)),1)]),_:2},1024)]),_:2},1024),N(R(G),null,{default:z(()=>[M(L(R(Q)(e.calls)),1)]),_:2},1024),N(R(G),null,{default:z(()=>[M(L(t.__(`:input in, :output out`,{input:R(Q)(e.input),output:R(Q)(e.output)})),1)]),_:2},1024),N(R(G),null,{default:z(()=>[M(L(e.cost===null?t.__(`Unknown`):R(Zo)(e.cost)),1)]),_:2},1024)]),_:2},1032,[`data-tolk-usage-model`]))),128))]),_:1})]),_:1})]),N(R(H),{"data-tolk-usage-total":``},{default:z(()=>[M(L(f.value.cost===null?t.__n(`:calls call this month. The cost is unknown: a model without a price was called.|:calls calls this month. The cost is unknown: a model without a price was called.`,f.value.calls,{calls:R(Q)(f.value.calls)}):t.__n(`:calls call this month, an estimated :cost.|:calls calls this month, an estimated :cost.`,f.value.calls,{calls:R(Q)(f.value.calls),cost:R(Zo)(f.value.cost)})),1)]),_:1})],64))]),_:1}),N(R(V),{class:`space-y-3`,"data-tolk-providers":``},{default:z(()=>[N(R(U),{size:`lg`,text:t.__(`Providers`)},null,8,[`text`]),j(`ul`,hf,[(P(!0),A(m,null,I(e.providers,e=>(P(),A(`li`,{key:e.provider,class:`flex items-center justify-between gap-2`,"data-tolk-provider":e.provider},[N(R(q),null,{default:z(()=>[M(L(e.label),1)]),_:2},1024),N(R(Fn),nt({ref_for:!0},R(Pu)(e.configured)),null,16)],8,gf))),128))]),e.fakeEngine?(P(),O(R(H),{key:0,"data-tolk-fake-engine":``},{default:z(()=>[M(L(t.__(`The fake engine is on: translations are made up without calling a provider.`)),1)]),_:1})):k(``,!0),R(s)?(P(),A(`a`,{key:1,href:R(s),class:`text-sm text-blue-600 hover:underline dark:text-blue-400`},L(t.__(`Settings`)),9,_f)):k(``,!0)]),_:1})]),N(R(V),{class:`space-y-3`,"data-tolk-latest-runs":``},{default:z(()=>[j(`div`,vf,[N(R(U),{size:`lg`,text:t.__(`Latest runs`)},null,8,[`text`]),e.runs.length>0?(P(),O(R(dd),{key:0,href:e.urls.runs,class:`text-sm text-blue-600 hover:underline dark:text-blue-400`},{default:z(()=>[M(L(t.__(`All runs`)),1)]),_:1},8,[`href`])):k(``,!0)]),e.runs.length===0?(P(),O(R(q),{key:0},{default:z(()=>[M(L(t.__(`No translation runs yet.`)),1)]),_:1})):(P(),O(Id,{key:1,runs:e.runs},null,8,[`runs`]))]),_:1}),a.value?(P(),O(R(qn),{key:4,open:``,danger:``,title:t.__(`Reset the usage of :month?`,{month:R(tf)(f.value.month)}),"body-text":t.__(`The calls, tokens and costs counted this month are deleted, and counting starts again from zero. The runs keep their own usage.`),"button-text":t.__(`Reset`),"data-tolk-usage-reset-confirm":``,"onUpdate:open":n[1]||=e=>a.value=e,onConfirm:y},null,8,[`title`,`body-text`,`button-text`])):k(``,!0)]))}},bf={class:`mx-auto max-w-page space-y-6`,"data-tolk-runs":``},xf={__name:`Index`,props:{runs:{type:Array,default:()=>[]},canReset:{type:Boolean,default:!1},urls:{type:Object,default:()=>({})}},setup(e){let t=e,n=F(!1),r=F(!1),i=D(()=>t.runs.some(e=>xo.includes(e.status)));async function a(){n.value=!1,r.value=!0;try{let{deleted:e}=await $i(t.urls.reset);Statamic.$toast.success(__n(`:count run was deleted.|:count runs were deleted.`,e)),fd.reload({only:[`runs`]})}catch(e){Statamic.$toast.error(e.message)}finally{r.value=!1}}return(t,o)=>(P(),A(`div`,bf,[N(R(ud),{title:t.__(`Translation runs`)},null,8,[`title`]),N(R(xr),{title:t.__(`Translation runs`),icon:`dictionary-language-book`},{default:z(()=>[e.canReset&&i.value?(P(),O(R(B),{key:0,text:t.__(`Reset`),loading:r.value,"data-tolk-runs-reset":``,onClick:o[0]||=e=>n.value=!0},null,8,[`text`,`loading`])):k(``,!0)]),_:1},8,[`title`]),e.runs.length===0?(P(),O(R(V),{key:0,"data-tolk-runs-empty":``},{default:z(()=>[N(R(q),null,{default:z(()=>[M(L(t.__(`No translation runs yet. Runs started from a listing, the overview or the command line appear here.`)),1)]),_:1})]),_:1})):(P(),O(R(V),{key:1},{default:z(()=>[N(Id,{runs:e.runs},null,8,[`runs`])]),_:1})),n.value?(P(),O(R(qn),{key:2,open:``,danger:``,title:t.__(`Delete the finished runs?`),"body-text":t.__(`Every completed, cancelled and aborted run is deleted with its results, and can no longer be resumed or retried. Pending and running runs stay. The translations they saved stay too.`),"button-text":t.__(`Delete`),"data-tolk-runs-reset-confirm":``,"onUpdate:open":o[1]||=e=>n.value=e,onConfirm:a},null,8,[`title`,`body-text`,`button-text`])):k(``,!0)]))}},Sf=[`data-tolk-run-status`],Cf={class:`flex flex-wrap items-center gap-2`},wf={class:`flex flex-wrap items-center gap-x-4 gap-y-1`,"data-tolk-run-counts":``},Tf={class:`space-y-3`},Ef={class:`flex flex-wrap gap-2`},Df={class:`flex flex-wrap items-center justify-between gap-2`},Of={class:`space-y-3`},kf={key:1,class:`flex flex-wrap gap-2`},Af={class:`grid gap-6 lg:grid-cols-2`},jf={class:`overflow-x-auto`},Mf={class:`grid grid-cols-[auto_1fr] gap-x-4 gap-y-1 text-sm`},Nf={class:`text-gray-600 dark:text-gray-400`},Pf=[`data-tolk-option`],Ff={class:`flex flex-wrap items-baseline justify-between gap-2`},If={key:0,class:`flex flex-wrap gap-x-10 gap-y-2 text-sm`},Lf={class:`text-gray-600 dark:text-gray-400`},Rf={"data-tolk-estimate-segments":``},zf={class:`text-gray-600 dark:text-gray-400`},Bf={"data-tolk-estimate-chars":``},Vf={class:`text-gray-600 dark:text-gray-400`},Hf={"data-tolk-estimate-input":``},Uf={class:`text-gray-600 dark:text-gray-400`},Wf={"data-tolk-estimate-output":``},Gf={class:`text-gray-600 dark:text-gray-400`},Kf={"data-tolk-estimate-cost":``},qf={class:`flex flex-wrap items-center justify-between gap-2`},Jf={class:`w-56`},Yf={class:`overflow-x-auto`},Xf=[`href`],Zf={key:1},Qf={key:1,class:`flex flex-wrap items-center gap-2`},$f=[`href`],ep={key:1,class:`flex items-center justify-end gap-2`,"data-tolk-items-pages":``},tp={__name:`Show`,props:{state:{type:Object,required:!0},urls:{type:Object,required:!0},models:{type:Object,default:()=>({})},lanes:{type:Number,default:1}},setup(e){let t=e,n=F(t.state),r=F(t.state.run?.estimate??null),i=F([]),a=F(null),o=F(t.state.pagination?.page??1),s=t.state.pagination?.per_page??50,c=F(`all`),l=Xo(Statamic.$config.get(`sites`)),u=ps({urls:t.urls,lanes:t.lanes,onState:e=>{n.value=e,r.value=e.run?.estimate??r.value},onEstimate:e=>r.value=e,onFailures:e=>i.value=e,query:()=>({page:o.value,per_page:s,...c.value===`all`?{}:{status:c.value}})});function d(e){u.active&&(e.preventDefault(),e.returnValue=``)}mt(()=>{u.follow(t.state),window.addEventListener(`beforeunload`,d)}),ut(()=>{u.stop(),window.removeEventListener(`beforeunload`,d)});let f=D(()=>n.value.run??{}),p=D(()=>f.value.status),h=D(()=>$o(n.value)),g=D(()=>es(n.value)),_=D(()=>ns(n.value)),v=D(()=>os(f.value.scope,l)),y=D(()=>rs(n.value.breakdown,l)),b=D(()=>is(f.value.scope)),x=ol(Statamic.$config.get(`tolk.auditUrl`)),S=D(()=>as(f.value.scope)),ee=D(()=>ss(f.value.options,t.models)),C=D(()=>cs(r.value,h.value.total)),w=D(()=>ls(f.value,t.models)),T=D(()=>(n.value.items??[]).map(e=>fs(e,l))),E=D(()=>n.value.pagination??{page:1,last_page:1,total:0}),te=D(()=>p.value===`running`&&f.value.driver===`browser`),ne=D(()=>p.value===`running`&&!!n.value.stalled),re=D(()=>Vo.filter(e=>h.value.counts[e]>0).map(e=>({key:e,text:`${Q(h.value.counts[e])} ${qo(e).toLowerCase()}`}))),ie=D(()=>[{label:__(`All items`),value:`all`},...Vo.map(e=>({label:qo(e),value:e}))]),ae=F(null),oe=Tl(()=>ae.value),se=tc(),ce=F([]);function le(e){ce.value=e.corrections,se.show()}xn(p,()=>oe.changing());let ue=D(()=>{let e=f.value.created_by?.name,t=Qo(f.value.created_at);return v.value.automatic?e?__(`Started automatically on :date, when :name saved the entry.`,{name:e,date:t}):__(`Started automatically on :date, when the entry was saved.`,{date:t}):e?__(`Created by :name on :date`,{name:e,date:t}):__(`Created on :date from the command line`,{date:t})});async function de(e,t){let n=oe.holds();a.value=e;try{let n=await t();e===`retry`&&n?.retried===0&&Statamic.$toast.info(__(`No item failed, so nothing was retried.`))}catch(e){Statamic.$toast.error(e.message)}finally{a.value=null,n&&rt(oe.restore)}}async function fe(e){o.value=Math.max(1,e);try{await u.refresh()}catch(e){Statamic.$toast.error(e.message)}}function pe(e){c.value=e??`all`,fe(1)}return(t,r)=>(P(),A(`div`,{ref_key:`root`,ref:ae,class:`mx-auto max-w-page space-y-6`,"data-tolk-run":``,"data-tolk-run-status":p.value},[N(R(ud),{title:t.__(`Translation run`)},null,8,[`title`]),N(R(xr),{title:t.__(`Translation run`),icon:`dictionary-language-book`},{default:z(()=>[N(R(dd),{href:e.urls.index,class:`text-sm text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-200`,"data-tolk-runs-link":``},{default:z(()=>[M(L(t.__(`All runs`)),1)]),_:1},8,[`href`]),g.value.cancel?(P(),O(R(B),{key:0,text:t.__(`Cancel`),loading:a.value===`cancel`,disabled:a.value!==null,"data-tolk-action":`cancel`,onClick:r[0]||=e=>de(`cancel`,R(u).cancel)},null,8,[`text`,`loading`,`disabled`])):k(``,!0),g.value.start?(P(),O(R(B),{key:1,variant:`primary`,text:t.__(`Start`),loading:a.value===`start`,disabled:a.value!==null,"data-tolk-action":`start`,onClick:r[1]||=e=>de(`start`,R(u).start)},null,8,[`text`,`loading`,`disabled`])):k(``,!0)]),_:1},8,[`title`]),N(R(V),{class:`space-y-3`,"data-tolk-run-summary":``},{default:z(()=>[j(`div`,Cf,[N(R(Fn),{text:R(Go)(p.value),color:R(Ko)(p.value),"data-tolk-run-status-badge":``},null,8,[`text`,`color`]),N(R(q),null,{default:z(()=>[M(L(v.value.sites?t.__(`:what into :sites`,{what:v.value.what,sites:v.value.sites}):v.value.what),1)]),_:1})]),N(R(H),null,{default:z(()=>[M(L(ue.value),1)]),_:1}),p.value===`pending`?k(``,!0):(P(),A(m,{key:0},[N(La,{value:h.value.finished,max:h.value.total,label:t.__(`Run progress`)},null,8,[`value`,`max`,`label`]),j(`div`,wf,[N(R(q),null,{default:z(()=>[M(L(t.__(`:finished of :total items finished`,{finished:R(Q)(h.value.finished),total:R(Q)(h.value.total)})),1)]),_:1}),(P(!0),A(m,null,I(re.value,e=>(P(),O(R(H),{key:e.key,"data-tolk-count":e.key},{default:z(()=>[M(L(e.text),1)]),_:2},1032,[`data-tolk-count`]))),128))]),N(R(H),{"data-tolk-run-usage":``},{default:z(()=>[M(L(t.__n(`:input input and :output output tokens in :calls call.|:input input and :output output tokens in :calls calls.`,w.value.calls,{input:R(Q)(w.value.input),output:R(Q)(w.value.output),calls:R(Q)(w.value.calls)}))+` `+L(w.value.cost===null?t.__(`The cost is unknown: a model without a price was called.`):t.__(`Estimated cost so far: :cost.`,{cost:R(Zo)(w.value.cost)})),1)]),_:1})],64))]),_:1}),te.value?(P(),O(R(Mn),{key:0,variant:`default`,icon:`info`,"data-tolk-keep-open":``},{default:z(()=>[M(L(t.__(`Keep this tab open while the run is in progress. Closing it pauses the run until you open it again.`)),1)]),_:1})):k(``,!0),ne.value?(P(),O(R(Mn),{key:1,variant:`warning`,heading:t.__(`This run is not moving`),"data-tolk-stalled":``},{default:z(()=>[j(`div`,Tf,[f.value.driver===`cli`&&v.value.automatic?(P(),O(R(q),{key:0},{default:z(()=>[M(L(t.__(`The process that updates these translations has not worked on them for a while and may have stopped. Resume continues the run from here.`)),1)]),_:1})):f.value.driver===`cli`?(P(),O(R(q),{key:1},{default:z(()=>[M(L(t.__(`The command running this run has not worked on it for a while and may have stopped. Resume continues the run from here.`)),1)]),_:1})):(P(),O(R(q),{key:2},{default:z(()=>[M(L(t.__(`No queue worker has worked on this run for a while. Start a worker for the queue, or run it in this browser instead.`)),1)]),_:1})),j(`div`,Ef,[N(R(B),{size:`sm`,text:t.__(`Resume`),loading:a.value===`resume`,disabled:a.value!==null,"data-tolk-action":`resume`,onClick:r[2]||=e=>de(`resume`,R(u).resume)},null,8,[`text`,`loading`,`disabled`]),g.value.takeOver?(P(),O(R(B),{key:0,size:`sm`,variant:`primary`,text:t.__(`Run in this browser instead`),loading:a.value===`take-over`,disabled:a.value!==null,"data-tolk-action":`take-over`,onClick:r[3]||=e=>de(`take-over`,R(u).takeOver)},null,8,[`text`,`loading`,`disabled`])):k(``,!0)])])]),_:1},8,[`heading`])):k(``,!0),(P(!0),A(m,null,I(i.value,(e,i)=>(P(),O(R(Mn),{key:i,variant:`error`,"data-tolk-run-failure":``},{default:z(()=>[j(`div`,Df,[N(R(q),null,{default:z(()=>[M(L(t.__(`Following the run stopped: :message`,{message:e.error?.message??``})),1)]),_:2},1024),i===0?(P(),O(R(B),{key:0,size:`sm`,text:t.__(`Try again`),"data-tolk-action":`follow-again`,onClick:r[4]||=e=>R(u).follow(n.value)},null,8,[`text`])):k(``,!0)])]),_:2},1024))),128)),_.value?(P(),O(R(Mn),{key:2,variant:_.value.variant,"data-tolk-run-result":``},{default:z(()=>[j(`div`,Of,[N(R(q),{as:`p`},{default:z(()=>[M(L(_.value.text),1)]),_:1}),_.value.error?(P(),O(R(q),{key:0,as:`p`,variant:`danger`},{default:z(()=>[M(L(_.value.error),1)]),_:1})):k(``,!0),g.value.retry||g.value.resume?(P(),A(`div`,kf,[g.value.retry?(P(),O(R(B),{key:0,size:`sm`,text:t.__(`Retry failed`),loading:a.value===`retry`,disabled:a.value!==null,"data-tolk-action":`retry`,onClick:r[5]||=e=>de(`retry`,R(u).retry)},null,8,[`text`,`loading`,`disabled`])):k(``,!0),g.value.resume?(P(),O(R(B),{key:1,size:`sm`,text:t.__(`Resume`),loading:a.value===`resume`,disabled:a.value!==null,"data-tolk-action":`resume`,onClick:r[6]||=e=>de(`resume`,R(u).resume)},null,8,[`text`,`loading`,`disabled`])):k(``,!0)])):k(``,!0)])]),_:1},8,[`variant`])):k(``,!0),j(`div`,Af,[N(R(V),{class:`space-y-3`,"data-tolk-breakdown":``},{default:z(()=>[N(R(U),{size:`lg`,text:t.__(`What it translates`)},null,8,[`text`]),j(`div`,jf,[N(R(Di),null,{default:z(()=>[N(R(Oi),null,{default:z(()=>[N(R(K),null,{default:z(()=>[M(L(t.__(`Content`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(t.__(`Site`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(t.__(`Items`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(t.__(`Skipped`)),1)]),_:1})]),_:1}),N(R(Ai),null,{default:z(()=>[(P(!0),A(m,null,I(y.value,e=>(P(),O(R(ki),{key:e.key,"data-tolk-breakdown-row":e.key},{default:z(()=>[N(R(G),null,{default:z(()=>[M(L(e.type),1)]),_:2},1024),N(R(G),null,{default:z(()=>[M(L(e.site),1)]),_:2},1024),N(R(G),{"data-tolk-breakdown-total":``},{default:z(()=>[M(L(R(Q)(e.total)),1)]),_:2},1024),N(R(G),{"data-tolk-breakdown-skipped":``},{default:z(()=>[M(L(R(Q)(e.skipped)),1)]),_:2},1024)]),_:2},1032,[`data-tolk-breakdown-row`]))),128))]),_:1})]),_:1})]),y.value.length===0?(P(),O(R(H),{key:0},{default:z(()=>[M(L(t.__(`This run has nothing to translate.`)),1)]),_:1})):k(``,!0),(P(!0),A(m,null,I(b.value,e=>(P(),O(R(H),{key:e.reason,"data-tolk-left-out":e.reason},{default:z(()=>[M(L(e.text),1)]),_:2},1032,[`data-tolk-left-out`]))),128)),S.value?(P(),O(R(H),{key:1,"data-tolk-not-localizable":``},{default:z(()=>[M(L(S.value)+` `,1),R(x)?(P(),O(R(dd),{key:0,href:R(x),class:`text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-audit-link":``},{default:z(()=>[M(L(t.__(`Open the setup audit`)),1)]),_:1},8,[`href`])):(P(),A(m,{key:1},[M(L(t.__(`Run php please tolk:doctor for details.`)),1)],64))]),_:1})):k(``,!0)]),_:1}),N(R(V),{class:`space-y-3`,"data-tolk-settings":``},{default:z(()=>[N(R(U),{size:`lg`,text:t.__(`Settings`)},null,8,[`text`]),j(`dl`,Mf,[(P(!0),A(m,null,I(ee.value,e=>(P(),A(m,{key:e.key},[j(`dt`,Nf,L(e.label),1),j(`dd`,{"data-tolk-option":e.key},L(e.value),9,Pf)],64))),128))])]),_:1})]),p.value===`pending`||C.value?(P(),O(R(V),{key:3,class:`space-y-3`,"data-tolk-estimate":``,"data-tolk-estimate-finished":C.value?.finished?`true`:`false`},{default:z(()=>[j(`div`,Ff,[N(R(U),{size:`lg`,text:t.__(`Estimate`)},null,8,[`text`]),C.value?C.value.finished?k(``,!0):(P(),O(R(H),{key:1},{default:z(()=>[M(L(t.__(`Estimating… :progress`,{progress:C.value.progress})),1)]),_:1})):(P(),O(R(H),{key:0},{default:z(()=>[M(L(t.__(`Estimating…`)),1)]),_:1}))]),C.value?(P(),A(`dl`,If,[j(`div`,null,[j(`dt`,Lf,L(t.__(`Segments`)),1),j(`dd`,Rf,L(R(Q)(C.value.segments)),1)]),j(`div`,null,[j(`dt`,zf,L(t.__(`Characters`)),1),j(`dd`,Bf,L(R(Q)(C.value.chars)),1)]),j(`div`,null,[j(`dt`,Vf,L(t.__(`Input tokens`)),1),j(`dd`,Hf,L(R(Q)(C.value.inputTokens)),1)]),j(`div`,null,[j(`dt`,Uf,L(t.__(`Output tokens`)),1),j(`dd`,Wf,L(R(Q)(C.value.outputTokens)),1)]),j(`div`,null,[j(`dt`,Gf,L(t.__(`Cost`)),1),j(`dd`,Kf,L(C.value.cost===null?t.__(`Unknown`):R(Zo)(C.value.cost)),1)])])):k(``,!0),N(R(H),null,{default:z(()=>[M(L(t.__(`An estimate: the tokens a language takes vary, and so does what a model writes.`))+` `,1),C.value&&C.value.cost===null?(P(),A(m,{key:0},[M(L(t.__(`The cost is unknown because a model has no price.`)),1)],64)):k(``,!0)]),_:1})]),_:1},8,[`data-tolk-estimate-finished`])):k(``,!0),N(R(V),{class:`space-y-3`,"data-tolk-items":``},{default:z(()=>[j(`div`,qf,[N(R(U),{size:`lg`,text:t.__(`Items`)},null,8,[`text`]),j(`div`,Jf,[N(R(di),{"model-value":c.value,options:ie.value,size:`sm`,"data-tolk-items-filter":``,"onUpdate:modelValue":pe},null,8,[`model-value`,`options`])])]),j(`div`,Yf,[N(R(Di),null,{default:z(()=>[N(R(Oi),null,{default:z(()=>[N(R(K),null,{default:z(()=>[M(L(t.__(`Title`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(t.__(`Site`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(t.__(`Status`)),1)]),_:1}),N(R(K),null,{default:z(()=>[M(L(t.__(`Result`)),1)]),_:1})]),_:1}),N(R(Ai),null,{default:z(()=>[(P(!0),A(m,null,I(T.value,e=>(P(),O(R(ki),{key:e.index,"data-tolk-item":``,"data-tolk-item-status":e.status},{default:z(()=>[N(R(G),null,{default:z(()=>[e.editUrl?(P(),A(`a`,{key:0,href:e.editUrl,class:`text-blue-600 hover:underline dark:text-blue-400`},L(e.title),9,Xf)):(P(),A(`span`,Zf,L(e.title),1))]),_:2},1024),N(R(G),null,{default:z(()=>[M(L(e.site),1)]),_:2},1024),N(R(G),null,{default:z(()=>[N(R(Fn),{text:e.statusLabel,color:e.statusColor},null,8,[`text`,`color`])]),_:2},1024),N(R(G),{class:`space-y-1`},{default:z(()=>[e.applied?(P(),O(R(q),{key:0,size:`sm`},{default:z(()=>[M(L(e.applied),1)]),_:2},1024)):k(``,!0),e.corrections.length?(P(),A(`div`,Qf,[N(R(q),{size:`sm`},{default:z(()=>[M(L(e.corrected),1)]),_:2},1024),N(R(B),{size:`sm`,variant:`ghost`,text:t.__(`View changes`),"aria-label":t.__(`View changes to :title in :site`,{title:e.title,site:e.site}),"data-tolk-item-changes":``,onClick:t=>le(e)},null,8,[`text`,`aria-label`,`onClick`])])):k(``,!0),e.incomplete.length?(P(),O(R(H),{key:2},{default:z(()=>[M(L(t.__(`Left incomplete: :fields`,{fields:e.incomplete.join(`, `)})),1)]),_:2},1024)):k(``,!0),e.kept.length?(P(),O(R(H),{key:3},{default:z(()=>[M(L(t.__(`Not changed: :fields`,{fields:e.kept.map(e=>`${e.handle} (${e.reason})`).join(`, `)})),1)]),_:2},1024)):k(``,!0),e.reason?(P(),O(R(H),{key:4},{default:z(()=>[M(L(e.reason),1)]),_:2},1024)):k(``,!0),e.error?(P(),O(R(q),{key:5,size:`sm`,variant:`danger`,"data-tolk-item-error":``},{default:z(()=>[M(L(e.error)+` `,1),e.rootPage?(P(),A(`a`,{key:0,href:e.rootPage.url,class:`text-blue-600 hover:underline dark:text-blue-400`,"data-tolk-root-page":``},L(t.__(`Open :title`,{title:e.rootPage.title})),9,$f)):k(``,!0)]),_:2},1024)):k(``,!0),(P(!0),A(m,null,I(e.warnings,(e,t)=>(P(),O(R(H),{key:t},{default:z(()=>[M(L(e),1)]),_:2},1024))),128))]),_:2},1024)]),_:2},1032,[`data-tolk-item-status`]))),128))]),_:1})]),_:1})]),T.value.length===0?(P(),O(R(H),{key:0},{default:z(()=>[M(L(t.__(`No items.`)),1)]),_:1})):k(``,!0),E.value.last_page>1?(P(),A(`div`,ep,[N(R(H),null,{default:z(()=>[M(L(t.__(`Page :page of :pages`,{page:E.value.page,pages:E.value.last_page})),1)]),_:1}),N(R(B),{size:`sm`,icon:`chevron-left`,"aria-label":t.__(`Previous page`),disabled:E.value.page<=1,onClick:r[7]||=e=>fe(E.value.page-1)},null,8,[`aria-label`,`disabled`]),N(R(B),{size:`sm`,icon:`chevron-right`,"aria-label":t.__(`Next page`),disabled:E.value.page>=E.value.last_page,onClick:r[8]||=e=>fe(E.value.page+1)},null,8,[`aria-label`,`disabled`])])):k(``,!0),R(se).open?(P(),O(Fa,{key:2,modal:R(se),corrections:ce.value},null,8,[`modal`,`corrections`])):k(``,!0)]),_:1})],8,Sf))}};Statamic.booting(()=>{Statamic.$components.register(Js,Jl),Statamic.$components.register(Zl,Xl),Statamic.$components.register(`tolk_model-fieldtype`,Mu),Statamic.$components.register(`tolk_providers-fieldtype`,Hu),Statamic.$components.register(`tolk_site_profile-fieldtype`,cd),Statamic.$inertia.register(`tolk::Audit`,Pd),Statamic.$inertia.register(`tolk::Overview`,yf),Statamic.$inertia.register(`tolk::Runs/Index`,xf),Statamic.$inertia.register(`tolk::Runs/Show`,tp),za.listen(),$s.listen(),kc.listen(),yl({PipelineStopped:a}).listen(),eu.register()}); \ No newline at end of file diff --git a/resources/dist/build/manifest.json b/resources/dist/build/manifest.json index 3558693..8666f13 100644 --- a/resources/dist/build/manifest.json +++ b/resources/dist/build/manifest.json @@ -9,7 +9,7 @@ "isEntry": true }, "resources/js/cp.js": { - "file": "assets/cp-ByCdgQdW.js", + "file": "assets/cp-CJQDbIPa.js", "name": "cp", "src": "resources/js/cp.js", "isEntry": true diff --git a/resources/js/components/EditorBanner.vue b/resources/js/components/EditorBanner.vue index b177d70..34b3cb8 100644 --- a/resources/js/components/EditorBanner.vue +++ b/resources/js/components/EditorBanner.vue @@ -163,6 +163,7 @@ async function undo() { + {{ banner.localization.autoUpdated }} {{ banner.localization.incompleteNote }} {{ banner.localization.hint }} @@ -247,6 +248,7 @@ async function undo() { {{ localization.summary }} + {{ banner.origin.autoUpdate }} + shown.value?.automatic + ? __('Updating the translations automatically into :sites…', { sites: shown.value.sites }) + : __('Translating into :sites…', { sites: shown.value.sites }), +); + +const updated = computed(() => __('The translations into :sites were updated automatically.', { sites: shown.value?.sites ?? '' })); + // What a screen reader announces as the run moves on. const announcement = computed(() => { switch (push.value?.phase) { case 'starting': return __('Starting the translation…'); + case 'expecting': + return working.value; + case 'updated': + return updated.value; case 'running': - return shown.value.failure ? __('The translations stopped: :message', { message: shown.value.failure }) : __('Translating into :sites…', { sites: shown.value.sites }); + return shown.value.failure ? __('The translations stopped: :message', { message: shown.value.failure }) : working.value; case 'error': return shown.value?.error ?? ''; default: @@ -93,10 +105,17 @@ function reload() { {{ __('Starting the translation…') }} + {{ working }} + +
+ {{ updated }} + +
+
{{ __('Cancelling. Translations already being saved are still saved.') }} - {{ __('Translating into :sites…', { sites: shown.sites }) }} + {{ working }} diff --git a/resources/js/components/RunsTable.vue b/resources/js/components/RunsTable.vue index fcbc2fa..f94c37a 100644 --- a/resources/js/components/RunsTable.vue +++ b/resources/js/components/RunsTable.vue @@ -21,13 +21,14 @@ const rows = computed(() => url: run.url, status: run.status, what: scope.what, + automatic: scope.automatic, sites: scope.sites, progress: __(':finished of :total', { finished: formatNumber(progress.finished), total: formatNumber(progress.total) }), failed: progress.counts.failed, tokens: usage.input + usage.output, cost: usage.cost, date: formatDate(run.created_at), - by: run.created_by?.name ?? __('Command line'), + by: run.created_by?.name ?? (scope.automatic ? __('Automatic update') : __('Command line')), }; }), ); @@ -51,6 +52,7 @@ const rows = computed(() => {{ row.what }} + {{ __('Automatic update') }} {{ row.sites }} diff --git a/resources/js/editor/push.js b/resources/js/editor/push.js index 487cda0..1037509 100644 --- a/resources/js/editor/push.js +++ b/resources/js/editor/push.js @@ -5,8 +5,22 @@ import { isFinal } from '../runs/ticker.js'; import { useEditorStore } from './store.js'; import { describeError } from './unitRunner.js'; -// While a push is starting or running, the origin's buttons make way for its progress. -export const PUSHING = ['starting', 'running']; +// While a push is starting or running, or a save's automatic update is expected, the origin's buttons make way for it. +export const PUSHING = ['starting', 'running', 'expecting']; + +// Milliseconds between the looks for the run a save starts with automatic updates on (T11.1): the process that saved +// starts it after its response, a queue worker after UpdateTranslations::DELAY_SECONDS. +export const EXPECT_DELAYS = [1000, 2000, 4000, 8000, 15000]; + +// The sites an automatic update would translate into now (`auto_update_sites`): missing, untranslated or outdated. +export function awaitingSites(status) { + const covered = status?.origin?.auto_update_sites ?? []; + + return (status?.origin?.localizations ?? []) + .filter((localization) => covered.includes(localization.site)) + .filter((localization) => !localization.exists || ['untranslated', 'outdated'].includes(localization.status)) + .map((localization) => localization.site); +} // The sites Translate into… offers: missing, or with untranslated fields (`describe(status).origin`). export function pushChoices(origin) { @@ -43,6 +57,7 @@ export function describePush(push, status) { return { sites: sites.join(', '), + automatic: Boolean(push.automatic), progress, keepOpen: push.phase === 'running' && push.driver === 'browser', failure: push.failures?.length ? push.failures.at(-1).error?.message ?? null : null, @@ -76,9 +91,17 @@ function pushResultText(status, counts) { // otherwise. The open form is not touched; the run saves server-side (D4). A follower belongs to its run, not to the // form: it keeps driving when the editor switches site or leaves for another page, and a banner that shows the item // again (a switch back, a reload) picks the run up from `editor/status`'s `active_run`. -export function createPushes({ store = useEditorStore, api = defaultApi, createFollower = defaultCreateFollower } = {}) { +export function createPushes({ + store = useEditorStore, + api = defaultApi, + createFollower = defaultCreateFollower, + wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), + delays = EXPECT_DELAYS, +} = {}) { // Run id → follower. const followers = new Map(); + // Counts the saves whose automatic update the banner waits for, so a look ends once the banner shows something else. + let expectations = 0; // Every container that shows the run. function showing(runId) { @@ -125,12 +148,12 @@ export function createPushes({ store = useEditorStore, api = defaultApi, createF } // The store's `push` of a container (`initialState()` in store.js). - function pushState(phase, { run = null, driver = null, sites = null, missing = [] }) { - return { phase, run, driver, sites, state: null, failures: [], missing, cancelling: false, error: null }; + function pushState(phase, { run = null, driver = null, automatic = false, sites = null, missing = [] }) { + return { phase, run, driver, automatic, sites, state: null, failures: [], missing, cancelling: false, error: null }; } function show(name, run, missing, sites = null) { - store().container(name).push = pushState('running', { run: run.run, driver: run.driver, sites, missing }); + store().container(name).push = pushState('running', { run: run.run, driver: run.driver, automatic: run.automatic === true, sites, missing }); } function followerOf(container) { @@ -231,6 +254,85 @@ export function createPushes({ store = useEditorStore, api = defaultApi, createF } } + // After a save, `editor/confirm`'s status: a run the save started is followed. With automatic updates on each save + // (T11.1), the run may start a little later, so while a localization still needs it, the status is read again a few + // times until the run shows. Looking stops when the form shows another item or follows a run. + async function afterSave(name, status) { + const container = store().containers[name]; + const reference = container?.reference; + + if (status?.active_run) { + await adopt(name, status); + + return; + } + + const sites = awaitingSites(status); + + if (!container || status?.origin?.auto_update !== 'save' || sites.length === 0 || PUSHING.includes(container.push?.phase)) { + return; + } + + const id = ++expectations; + container.push = { ...pushState('expecting', { automatic: true, sites }), expecting: id }; + + // The container while it still shows this item and waits for this update. + const expecting = () => { + const current = store().containers[name]; + + return current?.reference === reference && current.push?.phase === 'expecting' && current.push.expecting === id ? current : null; + }; + + for (const delay of delays) { + await wait(delay); + + if (!expecting()) { + return; + } + + let next = null; + + try { + next = await api.get('editor/status', { reference }); + } catch { + // Looked for again on the next load of the banner. + } + + const current = expecting(); + + if (!current || next === null) { + if (current) { + current.push = null; + } + + return; + } + + current.status = next; + + if (next.active_run) { + current.push = null; + await adopt(name, next); + + return; + } + + // Saved before its run could be seen: the update is done. + if (awaitingSites(next).length === 0) { + current.push = pushState('updated', { automatic: true, sites }); + + return; + } + } + + // Not started yet, as when a queue worker is busy: the update still comes, and the banner shows it on its next load. + const current = expecting(); + + if (current) { + current.push = null; + } + } + // Starts the loops again after they gave up, from a fresh state. async function resume(name) { const container = store().containers[name]; @@ -279,6 +381,7 @@ export function createPushes({ store = useEditorStore, api = defaultApi, createF return { start, adopt, + afterSave, resume, cancel, dismiss, diff --git a/resources/js/editor/push.test.js b/resources/js/editor/push.test.js index ae03465..ddc3ae5 100644 --- a/resources/js/editor/push.test.js +++ b/resources/js/editor/push.test.js @@ -1,7 +1,7 @@ import { createPinia, defineStore, setActivePinia } from 'pinia'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { ApiError } from '../api.js'; -import { createPushes, describePush, missingSites, pushChoices, updateSites } from './push.js'; +import { awaitingSites, createPushes, describePush, EXPECT_DELAYS, missingSites, pushChoices, updateSites } from './push.js'; import { useEditorStore } from './store.js'; function translate(key, replacements = {}) { @@ -115,11 +115,11 @@ function fakeApi({ post, get } = {}) { }; } -function setup({ api = fakeApi({ post: pushAnswer(), get: status() }), followers = fakeFollowers() } = {}) { +function setup({ api = fakeApi({ post: pushAnswer(), get: status() }), followers = fakeFollowers(), wait = async () => {} } = {}) { store.switched('base', REFERENCE); store.container('base').status = status(); - return { api, followers, pushes: createPushes({ store: () => store, api, createFollower: followers.create }) }; + return { api, followers, pushes: createPushes({ store: () => store, api, createFollower: followers.create, wait }) }; } describe('choices', () => { @@ -497,3 +497,133 @@ describe('adopt', () => { expect(describePush(store.container('base').push, status()).failure).toBe('Down'); }); }); + +describe('after a save', () => { + const origin = (localizations, extra = {}) => ({ localizations, auto_update: 'save', auto_update_sites: ['el'], ...extra }); + const outdated = (extra = {}) => status([], { origin: origin([localization('el', 'Greek', true, { status: 'outdated' }), localization('de', 'German', false)], extra) }); + const current = () => status([], { origin: origin([localization('el', 'Greek', true), localization('de', 'German', false)]) }); + const running = () => ({ ...current(), active_run: { ...pushAnswer({ driver: 'cli' }), automatic: true } }); + const statusLooks = (api) => api.requests.filter((request) => request.url === 'editor/status'); + + it('knows which sites an automatic update would translate into', () => { + expect(awaitingSites(outdated())).toEqual(['el']); + expect(awaitingSites(outdated({ auto_update_sites: ['el', 'de'] }))).toEqual(['el', 'de']); + expect(awaitingSites(status([], { origin: origin([localization('el', 'Greek', true, { status: 'untranslated' })]) }))).toEqual(['el']); + expect(awaitingSites(current())).toEqual([]); + expect(awaitingSites(outdated({ auto_update_sites: [] }))).toEqual([]); + expect(awaitingSites(null)).toEqual([]); + }); + + it('follows the run the save started', async () => { + const { api, followers, pushes } = setup({ api: fakeApi({ get: () => runState({ driver: 'cli' }) }) }); + + await pushes.afterSave('base', running()); + + expect(store.container('base').push).toMatchObject({ phase: 'running', run: '01RUN', driver: 'cli', automatic: true }); + expect(followers.made).toHaveLength(1); + expect(api.requests.map((request) => request.url)).toEqual(['https://cp.test/cp/tolk/runs/01RUN/state']); + }); + + it('shows that it expects the update, looks for its run until it shows, and follows it', async () => { + const answers = [outdated(), running()]; + const waits = []; + const phases = []; + const { api, followers, pushes } = setup({ + api: fakeApi({ get: (url) => (url === 'editor/status' ? answers.shift() : runState({ driver: 'cli' })) }), + wait: async (ms) => { + waits.push(ms); + phases.push(store.container('base').push?.phase); + }, + }); + + await pushes.afterSave('base', outdated()); + + expect(phases).toEqual(['expecting', 'expecting']); + expect(waits).toEqual(EXPECT_DELAYS.slice(0, 2)); + expect(statusLooks(api)).toEqual([ + { method: 'get', url: 'editor/status', data: { reference: REFERENCE } }, + { method: 'get', url: 'editor/status', data: { reference: REFERENCE } }, + ]); + expect(store.container('base').push).toMatchObject({ phase: 'running', automatic: true }); + expect(followers.made).toHaveLength(1); + }); + + it('says the translations were updated when they are current before their run was seen', async () => { + const { api, pushes } = setup({ api: fakeApi({ get: current() }) }); + + await pushes.afterSave('base', outdated()); + + expect(statusLooks(api)).toHaveLength(1); + expect(store.container('base').status).toEqual(current()); + expect(store.container('base').push).toMatchObject({ phase: 'updated', automatic: true, sites: ['el'] }); + expect(describePush(store.container('base').push, current())).toMatchObject({ sites: 'Greek', automatic: true, result: null }); + + pushes.dismiss('base'); + + expect(store.container('base').push).toBeNull(); + }); + + it('stops expecting after the last look, or when a status cannot be read', async () => { + const slow = setup({ api: fakeApi({ get: outdated() }) }); + + await slow.pushes.afterSave('base', outdated()); + + expect(statusLooks(slow.api)).toHaveLength(EXPECT_DELAYS.length); + expect(store.container('base').push).toBeNull(); + + const failing = setup({ api: fakeApi({ get: () => Promise.reject(new ApiError('Server Error', 500)) }) }); + + await failing.pushes.afterSave('base', outdated()); + + expect(statusLooks(failing.api)).toHaveLength(1); + expect(store.container('base').push).toBeNull(); + expect(toasts).toEqual([]); + }); + + it('expects nothing without automatic updates on save, when no covered site awaits one, or while a push runs', async () => { + const { api, pushes } = setup(); + + await pushes.afterSave('base', outdated({ auto_update: 'publish' })); + await pushes.afterSave('base', outdated({ auto_update_sites: [] })); + await pushes.afterSave('base', current()); + await pushes.afterSave('base', null); + + store.container('base').push = { phase: 'running', run: '01OTHER' }; + await pushes.afterSave('base', outdated()); + + expect(api.get).not.toHaveBeenCalled(); + expect(store.container('base').push).toMatchObject({ phase: 'running', run: '01OTHER' }); + }); + + it('stops when the form shows another item, and leaves a later save to the expectation already running', async () => { + const switching = setup({ wait: async () => store.switched('base', 'entry::other') }); + + await switching.pushes.afterSave('base', outdated()); + + expect(switching.api.get).not.toHaveBeenCalled(); + + let saves = 0; + const resaved = setup({ + api: fakeApi({ get: current() }), + wait: async () => { + if (saves++ === 0) { + await resaved.pushes.afterSave('base', outdated()); + } + }, + }); + + await resaved.pushes.afterSave('base', outdated()); + + expect(statusLooks(resaved.api)).toHaveLength(1); + expect(store.container('base').push.phase).toBe('updated'); + }); +}); + +describe('describePush of an automatic update', () => { + it('says that it is automatic', () => { + const push = { phase: 'running', run: '01RUN', driver: 'cli', automatic: true, sites: null, state: runState({ driver: 'cli' }), failures: [], missing: [] }; + + expect(describePush(push, status())).toMatchObject({ automatic: true, keepOpen: false }); + expect(describePush({ ...push, automatic: false }, status()).automatic).toBe(false); + }); +}); diff --git a/resources/js/editor/saveHooks.js b/resources/js/editor/saveHooks.js index 29321d3..4814ddc 100644 --- a/resources/js/editor/saveHooks.js +++ b/resources/js/editor/saveHooks.js @@ -1,5 +1,6 @@ import * as defaultApi from '../api.js'; import { SETTLE_MS } from './fill.js'; +import { pushes } from './push.js'; import { BASE, registry as sharedRegistry } from './registry.js'; import { fieldLabels } from './statuses.js'; import { useEditorStore } from './store.js'; @@ -25,6 +26,7 @@ export function createSaveHooks({ api = defaultApi, now = Date.now, settleMs = SETTLE_MS, + onConfirmed = (name, status) => pushes.afterSave(name, status), }) { let listening = false; @@ -102,6 +104,8 @@ export function createSaveHooks({ if (latest?.reference === reference) { latest.status = status; latest.notSaved = notSaved; + // Not awaited: the save hooks would wait for an automatic update to start. + onConfirmed(BASE, status); } if (notSaved.length) { diff --git a/resources/js/editor/saveHooks.test.js b/resources/js/editor/saveHooks.test.js index bcb504f..85d9154 100644 --- a/resources/js/editor/saveHooks.test.js +++ b/resources/js/editor/saveHooks.test.js @@ -127,6 +127,16 @@ describe('entry.saved', () => { expect(toasts).toEqual([]); }); + it('hands the fresh status on, so a run the save started is followed', async () => { + mount(); + const onConfirmed = vi.fn(); + const api = { post: vi.fn(async () => ({ ...freshStatus(), not_saved: [] })) }; + + await run(hooks({ api, onConfirmed }).saved, savedPayload()); + + expect(onConfirmed).toHaveBeenCalledExactlyOnceWith('base', freshStatus()); + }); + it('resolves only once the confirm request has returned', async () => { mount(); let answer; diff --git a/resources/js/editor/statuses.js b/resources/js/editor/statuses.js index 05559fa..5e7c192 100644 --- a/resources/js/editor/statuses.js +++ b/resources/js/editor/statuses.js @@ -119,9 +119,25 @@ function describeLocalization(block, setup) { hint: notLocalizable.length ? notLocalizableText(labels(notLocalizable), notLocalizable.length) : null, translate: !setup && (counts.untranslated ?? 0) > 0, update: !setup && (counts.outdated ?? 0) > 0, + autoUpdated: autoUpdatedNote(block.auto_updated, block.source), }; } +// When an automatic update from the origin last saved the localization (T11.1). +function autoUpdatedNote(update, source) { + const time = Date.parse(update?.at ?? ''); + + if (Number.isNaN(time)) { + return null; + } + + const replacements = { source: source?.name ?? '', date: new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(time) }; + + return update.unpublished + ? __('Updated automatically from :source on :date, not published yet.', replacements) + : __('Updated automatically from :source on :date.', replacements); +} + function localizationSummary(block, parts) { const source = block.source?.name ?? ''; @@ -183,6 +199,11 @@ function describeOrigin(block, setup) { upToDate: localizations.length > 0 && localizations.every((localization) => localization.status === 'current'), translateInto: !setup && localizations.some((localization) => localization.translate), update: !setup && localizations.some((localization) => localization.update), + autoUpdate: + { + save: __('Translations are updated automatically each time this entry is saved.'), + publish: __('Translations are updated automatically when this entry is published.'), + }[block.auto_update] ?? null, }; } diff --git a/resources/js/editor/statuses.test.js b/resources/js/editor/statuses.test.js index 5b8ca08..3a937a6 100644 --- a/resources/js/editor/statuses.test.js +++ b/resources/js/editor/statuses.test.js @@ -342,6 +342,32 @@ describe('an origin whose translations', () => { }); }); +describe('automatic updates', () => { + const origin = (autoUpdate) => + describeStatus( + payload({ + origin: { localizations: [{ site: 'el', name: 'Greek', exists: true, status: 'outdated', counts: { ...zero, outdated: 1 } }], auto_update: autoUpdate }, + }), + ).origin; + + it('says when saving or publishing the origin updates its translations', () => { + expect(origin('save').autoUpdate).toBe('Translations are updated automatically each time this entry is saved.'); + expect(origin('publish').autoUpdate).toBe('Translations are updated automatically when this entry is published.'); + expect(origin(null).autoUpdate).toBeNull(); + expect(origin(undefined).autoUpdate).toBeNull(); + }); + + it('tells a localization when an automatic update last saved it, and that it waits to be published', () => { + const note = (autoUpdated) => describeStatus(payload({ localization: localization({}, {}, { auto_updated: autoUpdated }) })).localization.autoUpdated; + const date = new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(Date.parse('2026-10-09T08:30:00Z')); + + expect(note({ at: '2026-10-09T08:30:00Z', unpublished: false })).toBe(`Updated automatically from English on ${date}.`); + expect(note({ at: '2026-10-09T08:30:00Z', unpublished: true })).toBe(`Updated automatically from English on ${date}, not published yet.`); + expect(note(null)).toBeNull(); + expect(note({ at: 'nonsense', unpublished: false })).toBeNull(); + }); +}); + it('describes both blocks for an entry in the middle of a chain', () => { const banner = describeStatus( payload({ diff --git a/resources/js/overview/matrix.js b/resources/js/overview/matrix.js index 6ad4a12..baa030f 100644 --- a/resources/js/overview/matrix.js +++ b/resources/js/overview/matrix.js @@ -156,7 +156,7 @@ export function describeMonth(usage) { } export function sourceLabel(source) { - return { editor: __('Editor'), run: __('Runs'), cli: __('Command line') }[source] ?? source; + return { editor: __('Editor'), run: __('Runs'), cli: __('Command line'), auto: __('Automatic updates') }[source] ?? source; } // `YYYY-MM` as the month's name. diff --git a/resources/js/overview/matrix.test.js b/resources/js/overview/matrix.test.js index a46fd72..1af68bf 100644 --- a/resources/js/overview/matrix.test.js +++ b/resources/js/overview/matrix.test.js @@ -11,6 +11,7 @@ import { matrixCells, matrixColumns, siteRun, + sourceLabel, statusColor, statusLabel, } from './matrix.js'; @@ -190,6 +191,10 @@ describe('the page', () => { expect(describeMonth({ month: '2026-10', models: [], labels: [] })).toMatchObject({ rows: [], calls: 0, cost: 0 }); }); + it('names where the usage came from', () => { + expect(['editor', 'run', 'cli', 'auto', 'other'].map(sourceLabel)).toEqual(['Editor', 'Runs', 'Command line', 'Automatic updates', 'other']); + }); + it('names the month', () => { expect(formatMonth('2026-10', 'en-US')).toBe('October 2026'); expect(formatMonth('2027-01', 'en-US')).toBe('January 2027'); diff --git a/resources/js/pages/Runs/Show.test.js b/resources/js/pages/Runs/Show.test.js index e4ff6ed..07d4f60 100644 --- a/resources/js/pages/Runs/Show.test.js +++ b/resources/js/pages/Runs/Show.test.js @@ -145,3 +145,14 @@ describe('the result of a run', () => { expect(lines(html)).toEqual(['The run was stopped: 0 done.', 'The AI provider rejected the request: the API key is not valid.']); }); }); + +describe('a run that stopped moving', () => { + const stalled = (driver, automatic) => + render('data-tolk-stalled', { stalled: true, run: { driver }, scope: { automatic }, actions: { takeOver: false }, busy: null, follower: {}, act: () => {} }); + + it('blames the process of an automatic update, the command, or the queue', async () => { + expect(text(await stalled('cli', true))).toContain('The process that updates these translations has not worked on them for a while'); + expect(text(await stalled('cli', false))).toContain('The command running this run has not worked on it for a while'); + expect(text(await stalled('queue', true))).toContain('No queue worker has worked on this run for a while'); + }); +}); diff --git a/resources/js/pages/Runs/Show.vue b/resources/js/pages/Runs/Show.vue index a8e1a3f..1a58383 100644 --- a/resources/js/pages/Runs/Show.vue +++ b/resources/js/pages/Runs/Show.vue @@ -129,6 +129,12 @@ const created = computed(() => { const by = run.value.created_by?.name; const at = formatDate(run.value.created_at); + if (scope.value.automatic) { + return by + ? __('Started automatically on :date, when :name saved the entry.', { name: by, date: at }) + : __('Started automatically on :date, when the entry was saved.', { date: at }); + } + return by ? __('Created by :name on :date', { name: by, date: at }) : __('Created on :date from the command line', { date: at }); }); @@ -228,7 +234,10 @@ function filterBy(value) {
- {{ __('The command running this run has not worked on it for a while and may have stopped. Resume continues the run from here.') }} + {{ + __('The process that updates these translations has not worked on them for a while and may have stopped. Resume continues the run from here.') + }} + {{ __('The command running this run has not worked on it for a while and may have stopped. Resume continues the run from here.') }} {{ __('No queue worker has worked on this run for a while. Start a worker for the queue, or run it in this browser instead.') }}