Compare commits

..
39 Commits
Author SHA1 Message Date
Amruth Pillai 409d09809a chore: release v5.2.6 2026-08-14 05:24:08 +02:00
ignaciocarreandAmruth Pillai 6d9ebccc63 feat(mcp): add cover-letter PDF downloads (#3304)
* feat(mcp): add cover-letter PDF downloads

* fix(mcp): bind signed PDF targets

* test(mcp): cover unavailable cover letters

* fix(api): accept legacy PDF download targets

* fix(server): limit legacy PDF tokens to resumes

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 23:09:56 +02:00
Syed Ali Abbas ZaidiandAmruth Pillai 45303fb465 feat(resume): add a deterministic ATS parseability check (#3314)
* feat(resume): add a deterministic ATS parseability check

Adds an offline ATS linter that reports whether a parser can read a
resume, surfaced as an always-on panel in the builder.

The existing Resume Analysis panel needs a configured AI provider, so
users who never set one up get no feedback at all. These 22 rules run
as a pure function over ResumeData with no provider, no network and no
rendered PDF, so they work for everyone on every edit.

Rules cover contact details, date parseability, sections that hold
content but never render, column and sidebar placement, and typography
thresholds. The catalog mirrors the Semantic CSS diagnostic catalog:
stable codes carrying a severity, meaning and action, with no i18n
dependency so the web layer translates by code. Each finding carries a
JSON Pointer, which is what makes jump-to-field work.

Deliberately no second score. Resume Analysis owns overallScore, so
this reports "N of M checks passed" and counts by severity instead.

* fix(resume): accept localized ongoing periods and reject bare ones

Two period-parsing bugs found in review.

The ongoing-token set was English-only, so a German resume reading
"2020 - heute" was reported as unparseable and the panel told the user
to rewrite a perfectly valid range. Rather than guess translations for
55 locales, a range ending that carries no digits and is not a month
name in the resume's locale is now read as ongoing. That keeps a
genuinely incomplete ending such as "Jan 2020 - Feb" reported, since
"Feb" resolves as a month.

A bare "Present" also parsed as a valid period, so an experience entry
with no start date passed the check. A standalone ongoing token is now
rejected; ongoing tokens remain valid as the end of a range.

* feat(web): scroll ATS findings to the item they belong to

Findings for different items in one section all landed on the section
header, so a date problem on the third role gave no more help than
naming the section.

getAtsFindingTarget now resolves the offending item from the finding's
JSON Pointer against the resume, and SectionItem carries a matching DOM
id. The panel scrolls to that item and falls back to the section header
when the item is not mounted, which is what happens while its section
is collapsed.

* fix(resume): recognize ongoing periods by token, not by shape

The previous heuristic read any short, digit-free range ending as an
ongoing marker, so "2020 - unknown", "2020 - later" and "2020 - tbd"
parsed cleanly and suppressed the finding they should have raised.

Replaced with an explicit table of ongoing words keyed by language,
covering the locales the app ships. Matching is exact, so unrecognized
endings are reported again. A locale missing from the table falls back
to the earlier behaviour of reporting its ongoing periods, which is a
visible gap someone can close by adding a word rather than a silent
hole in detection.

Tests assert every listed token parses and that the table stays
lowercase, since lookups normalize that way.

* fix(ats): parse punctuated ongoing tokens

* fix(ats): parse Unicode punctuated ongoing tokens

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 23:07:55 +02:00
Santhi PrakashandAmruth Pillai f64d02df7f fix(pdf): ignore phantom gengar skill text nodes (#3289)
* docs(agents): align Redis compose commands with development guide

- Problem: AGENTS.md omitted Redis from dev infrastructure compose commands
  while docs/contributing/development.mdx starts redis for local dev.
- Fix: document full postgres/redis/seaweedfs compose command and note that
  REDIS_URL and ENCRYPTION_SECRET are required for AI agent features.
- Verification: preflight upstream fetch; manual diff against development.mdx
  and compose.dev.yml redis service; duplicate PR gate passed.

* fix(pdf): ignore phantom gengar skill text nodes

- Problem: gengar template resumes with skills keywords fail semantic CSS activation because the legacy renderer emits a harmless empty text node that parity treats as a mismatch.

- Fix: treat the specific empty text artifact as presentation-neutral in the legacy parity comparator and add a regression test for the phantom fontSize 9 node.

- Verification: pnpm test src/semantic/legacy-parity.test.ts in packages/pdf passed (31 tests).

* docs: clarify host and container Redis URLs

- Problem: the development guide only showed the Docker Redis hostname, which fails for host-run development.\n- Fix: document localhost for host execution and redis for Docker execution.\n- Verification: pnpm test src/semantic/legacy-parity.test.ts (31 passed).

* fix(pdf): omit empty skill proficiency text

* test(pdf): cover blank skill proficiency

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 23:07:49 +02:00
bad431b2fc fix(import): auto-detect JSON format and show readable errors (#1) (#3296)
* fix(import): auto-detect JSON format and show readable errors (#1)

Readable import errors, a fail-soft v4 parser, and auto-detect of the JSON format so uploads just work. The format dropdown becomes an optional override. PDF and DOCX (AI) paths are untouched.

* fix(import): address review feedback on the v4 guard and error message

- reactive-resume-v4-json.tsx: reject arrays in isRecord so array-valued
  basics, sections, or metadata no longer pass the v4 shape guard.
- reactive-resume-v4-json.tsx: reuse the guard's error instance in the
  catch arm instead of allocating a duplicate NOT_V4_MESSAGE.
- error.ts: use a singular "Problem" label for root-level Zod issues so
  the message stays grammatical.
- add a regression test for array-valued v4 branches.

* fix(import): preserve selected JSON format

* test(import): cover selected JSON parser

---------

Co-authored-by: MrTig-afk <MrTig-afk@users.noreply.github.com>
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 23:01:06 +02:00
Syed Ali Abbas ZaidiandAmruth Pillai 9f13638eab fix(web): drop focus when panning the builder canvas (#3303)
react-zoom-pan-pinch calls preventDefault() on its window-level mousedown
listener so that dragging the canvas does not select text. That also cancels the
browser's native focus shift, so focus stays wherever it was before the pan --
typically the sidebar button that opened the last dialog, since closing a dialog
restores focus to its trigger. A focused button activates on Space keyup, so
holding space to pan and then releasing it reopened the most recent dialog.

Blur the focused element from onPanningStart, which reinstates exactly the focus
change the browser would have made on its own. onPanningStart only fires when the
mousedown target is inside the transform wrapper, so sidebar and dialog clicks are
unaffected, and keyboard-only users never trigger a pointer pan.

Closes #3300

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 22:54:23 +02:00
13e584d522 fix(icon-picker): allow selecting the empty/no-icon option (#3298)
The icon picker grid starts with an empty string entry that renders the
"no icon" (prohibit) symbol, but the onClick guard "if (icon)" treated
the empty string as falsy and ignored the click. Change the guard to
check for a defined string value so the empty/no-icon option can be
selected.

Closes #3252
Closes #3261

Co-authored-by: Devin <devin@example.com>
Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 22:54:16 +02:00
Santhi PrakashandAmruth Pillai 6035402832 docs(agents): align Redis compose commands with development guide (#3288)
* docs(agents): align Redis compose commands with development guide

- Problem: AGENTS.md omitted Redis from dev infrastructure compose commands
  while docs/contributing/development.mdx starts redis for local dev.
- Fix: document full postgres/redis/seaweedfs compose command and note that
  REDIS_URL and ENCRYPTION_SECRET are required for AI agent features.
- Verification: preflight upstream fetch; manual diff against development.mdx
  and compose.dev.yml redis service; duplicate PR gate passed.

* docs(agents): clarify Redis development URLs

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 22:54:10 +02:00
Shehraan HafizandAmruth Pillai 69961210bd fix(pdf): missing spaces around bold rich text in PDFs (#3273)
* fix(pdf): missing spaces around bold rich text in PDFs

* fix(pdf): make bold tag matching quote-aware

* fix(pdf): preserve quoted bold tag attributes

* fix(pdf): handle encoded non-breaking spaces in bold boundaries

* fix(pdf): preserve top-level bold boundary spaces

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 22:54:05 +02:00
Santhi PrakashandAmruth Pillai 7eb6d3bdbf fix(auth): use loopback URL for MCP OAuth JWKS verification (#3297)
* fix(auth): use loopback URL for MCP OAuth JWKS verification

Fetch the JWKS endpoint over the internal loopback address instead of the public APP_URL, so token verification works under Docker port-mapping, reverse proxies, and other deployments where the public URL does not loop back to the Node process.

Also log the specific MCP OAuth verification error instead of swallowing it with a bare catch.

Fixes #3077

* fix(auth): normalize internal JWKS URL and throttle MCP OAuth warnings

 - Problem: default loopback JWKS URL used PORT in dev where the server
   listens on SERVER_PORT (3001), and trailing-slash overrides produced
   //api/auth/jwks; unthrottled warn logs could flood on bad bearer tokens.
 - Fix: resolveInternalBaseUrl trims/normalizes BETTER_AUTH_INTERNAL_URL,
   mirrors apps/server listen-port selection, and MCP OAuth warnings are
   throttled to once per minute.
 - Verification: pnpm exec biome check on changed files; pnpm typecheck.

* fix(auth): declare BETTER_AUTH_INTERNAL_URL in turbo globalEnv

- Problem: Turborepo strict env mode strips undeclared BETTER_AUTH_INTERNAL_URL under pnpm dev, so the JWKS override silently falls back to loopback.
- Fix: add BETTER_AUTH_INTERNAL_URL to turbo.json globalEnv (required for any new env var per CLAUDE.md).
- Verification: python3 JSON parse of turbo.json; confirmed var was absent from globalEnv before this change.

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 22:51:02 +02:00
Santhi PrakashandAmruth Pillai 5fc9c3ee04 fix(pdf): register Noto punctuation fallback for missing glyphs (#3294)
* fix(pdf): register Noto punctuation fallback for missing glyphs

- Problem: U+2022 bullet characters render as garbled glyphs when the body
  font (e.g. IBM Plex Serif) lacks the glyph and no PDF fallback is registered.
- Fix: append Noto Serif/Sans to the PDF fallback stack as a general-purpose
  punctuation source covering General Punctuation (U+2000–U+206F).
- Verification: pnpm --filter @reactive-resume/fonts test;
  pnpm --filter @reactive-resume/pdf test src/hooks/use-register-fonts.test.ts

* test(fonts): clarify zh-CN fallback test description

- Problem: getPdfFallbackFontFamilies("Times-Roman", { locale: "zh-CN" }) now
  returns ["Noto Serif SC", "Noto Serif"] (the general-purpose punctuation
  fallback is appended), so the test description "returns only the Simplified
  Chinese font for zh-CN (unchanged behavior)" is no longer accurate.
- Fix: rename the test to describe that it uses the Simplified Chinese font
  plus the punctuation fallback. The assertion is unchanged.
- Verification: pnpm --filter @reactive-resume/fonts test -> 45/45 passing.

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 22:50:58 +02:00
Santhi PrakashandAmruth Pillai a8d1f5a685 docs(contributing): align app names in guide frontmatter (#3287)
- Problem: development.mdx and architecture.mdx frontmatter still referenced
  removed client/worker/artboard apps even though the monorepo only ships
  apps/web and apps/server.
- Fix: update both descriptions to say web and server apps.
- Verification: docs-only; grep confirms only apps/web and apps/server exist.

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 22:50:53 +02:00
Santhi PrakashandAmruth Pillai dd9843172b docs(contributing): align development guide with dotenvx workflow (#3286)
* docs(contributing): align development guide with dotenvx workflow

- Problem: development.mdx told contributors to use a root `.env` file and
  export DATABASE_URL manually, while AGENTS.md and compose.dev.yml use
  `.env.local` loaded through dotenvx for dev and migration commands.
- Fix: update the setup, migration, dev-server, and database sections to
  match the dotenvx commands documented in AGENTS.md.
- Verification: preflight_ship.py (upstream bug marker present); duplicate
  PR check clean; docs-only change.

* docs(contributing): add cp command to env setup step

- Problem: setup step said to copy .env.example but the bash block only listed variable assignments.
- Fix: add explicit cp .env.example .env.local command and label the following block as edits.
- Verification: manual review of development.mdx; addresses CodeRabbit review on #3286.

* docs(contributing): align AGENTS.md env copy target with dotenvx

- Problem: AGENTS.md told contributors to copy .env.example to .env while all dev commands use .env.local.
- Fix: update the copy instruction to .env.local for consistency with the dotenvx workflow.
- Verification: manual review; folded into #3286 dotenvx alignment PR.

* docs(contributing): dotenvx-wrap remaining dev script references

- Problem: scripts table and troubleshooting still showed bare pnpm dev/db commands after the dotenvx workflow update.
- Fix: prefix dev, db, and port-override examples with dotenvx run -f .env.local --.
- Verification: manual review of development.mdx; folded into #3286.

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-08-13 22:50:48 +02:00
Amruth Pillai 28d698635f build: use official pnpm image 2026-08-13 22:43:53 +02:00
Amruth Pillai 3635b3d578 fix(stylesheet): skip parity on explicit activation (#3316) 2026-08-13 15:53:28 +02:00
Amruth Pillai 5a75eda893 ci: remove semantic CSS acceptance test 2026-08-13 09:40:54 +02:00
github-actions[bot]andCrowdin Bot e4b28e9825 Sync Translations from Crowdin (#3315)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2026-08-13 09:36:15 +02:00
Amruth Pillai 2d6ea9ce8d fix(auth): allow implicit social signup 2026-08-13 09:23:04 +02:00
Amruth Pillai 0e463883af docs: design implicit social signup 2026-08-13 09:16:18 +02:00
Syed Ali Abbas Zaidi 3a5b12e2a4 fix(web): confirm before the import dialog's provider link navigates away (#3308) 2026-08-11 10:26:04 +02:00
Amruth Pillai 035d94183b fix(web): show static template previews in gallery (#3302) 2026-08-10 12:18:47 +02:00
Amruth Pillai efd950bd93 fix(server): log unhandled rejections instead of crashing the process
Node 24 terminates the whole process on an unhandled promise rejection, so a
single request's stray rejection could take the server down for every user
(as the USER_STOPPED agent-abort bug did). Add a process-level unhandledRejection
handler that logs and keeps serving. Uncaught exceptions are intentionally left
on Node's default crash-and-restart, since process state is unsafe afterward.

Claude-Session: https://claude.ai/code/session_01ULhhLQ24DvnYwzP4afDuye
2026-08-09 16:01:23 +02:00
Amruth Pillai 04100aa9ef fix(agent): abort stopped runs with an AbortError, not a bare string
Stopping (or archiving) an agent run called controller.abort("USER_STOPPED")
with a plain string reason. The AI SDK only recognizes a cancellation when the
reason is an AbortError (err.name === "AbortError" / isAbortError); a bare
string is treated as a real stream error, and its rejection escaped the
background resumable-stream pump and crashed the whole server process with
ERR_UNHANDLED_REJECTION on every user Stop. Abort with a DOMException named
AbortError (label preserved as the message) so the SDK cancels the run
gracefully. Same fix for the USER_ARCHIVED path.

Claude-Session: https://claude.ai/code/session_01ULhhLQ24DvnYwzP4afDuye
2026-08-09 15:46:31 +02:00
Amruth Pillai c292968314 chore: update translations 2026-08-09 15:10:09 +02:00
Amruth Pillai ba1f469950 fix(a11y): label 2FA copy button, restore template focus ring, guard API-key double-submit
- Add an sr-only "Copy secret" label to the icon-only copy button in the 2FA
  enable dialog; it was previously announced as an unlabeled button.
- Add a focus-visible ring to template gallery cards. The only ring was gated
  on the selected state, so keyboard focus was invisible while tabbing.
- Disable the API-key create submit button while the request is in flight to
  prevent duplicate keys from a double-click.

Surfaced by a shadscan UI audit. The remaining ~95 findings were false
positives from the auditor not understanding the pnpm monorepo and the
TanStack Start root-route shell, and were waived.

Claude-Session: https://claude.ai/code/session_01JYTniVDeA56o1kGhdoCUoD
2026-08-09 14:48:46 +02:00
Amruth Pillai b4f245a38e fix(deps): restore @react-pdf/textkit patch dropped by the 4.6.0 bump
The dependency-update commit bumped @react-pdf/renderer 4.5.1->4.6.0 (textkit
6.3.0->6.4.0) and silently dropped the pnpm patch that overrides font vertical
metrics to prefer OS/2 sTypo* over inflated hhea values, matching browser line
boxes. 6.4.0 did not upstream it, so the semantic-CSS template visual snapshots
(baselined with the patch, maxDiffPixelRatio 0) no longer matched and the E2E
job failed. Re-create the patch for textkit@6.4.0 and re-register it in
patchedDependencies; remove the orphaned 6.3.0 patch.

Claude-Session: https://claude.ai/code/session_01ULhhLQ24DvnYwzP4afDuye
2026-08-09 14:41:01 +02:00
Amruth Pillai e6a31aab97 fix(stylesheet): warm and reuse the server PDF preflight worker
The server PDF preflight spawned a fresh worker per semantic-CSS edit, each
racing a 15s startup deadline to cold-load the ~721kB+5MB PDF runtime. That
load is super-linear in CPU (~3s at 1 vCPU, >15s on a throttled/shared vCPU),
so on a constrained box every edit hit the startup-timeout path and returned
STYLESHEET_PREFLIGHT_WORKER_FAILED. Since the service only advances the applied
stylesheet when preflight passes, custom styles never applied and the editor
stuck on Checking.

Warm one worker at boot and reuse it (message-based input, respawn on
crash/timeout), so the cold load is paid once instead of per edit. Raise the
render deadline 5s->30s (a rich resume renders ~5-18s on a slow box) and the
readiness ceiling to 120s so the one-time warm completes even when throttled.
Surface worker load failures instead of an unhandled-rejection crash, and log
runner-side failure paths so the previously opaque failure is diagnosable.
Verified in node:24-slim under --cpus=0.25/0.35/0.5: all reused requests pass.

Claude-Session: https://claude.ai/code/session_01ULhhLQ24DvnYwzP4afDuye
2026-08-09 14:30:55 +02:00
Amruth Pillai 88a19619da chore: update dependencies 2026-08-09 12:17:09 +02:00
autofix-ci[bot] 36232b631d [autofix.ci] apply automated fixes 2026-07-31 15:25:43 +00:00
Amruth Pillai 9eec1520a1 Merge branch 'main' of github.com:amruthpillai/reactive-resume 2026-07-31 17:24:40 +02:00
Amruth Pillai 131c1492cd chore: update dependencies 2026-07-31 17:24:32 +02:00
Amruth PillaiandCursor Agent ba8e1be2ab fix(stylesheet): harden PDF preflight and surface worker failures (#3284)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-07-31 07:57:54 +02:00
Amruth PillaiandCursor Agent 4a8f87ab8f fix(web): stop custom styles from sticking on Checking (#3283)
Concurrent compile requests from editor intelligence were rejecting
in-flight edit compiles as stale, and the store swallowed that rejection
without leaving compiling. Resolve all compile results and surface
compile failures as an error status so styles can apply again.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-07-31 01:00:45 +02:00
github-actions[bot]andCrowdin Bot 186c400ab7 Sync Translations from Crowdin (#3281)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2026-07-30 18:59:23 +02:00
Amruth Pillai d314361ad6 fix(ci): run current semantic CSS tests 2026-07-30 18:48:56 +02:00
Amruth Pillai b071a118a3 test: remove slow OpenAPI spec synchronization test 2026-07-30 16:37:03 +02:00
Amruth Pillai 3589b534f5 feat: enable semantic CSS by default 2026-07-30 16:28:44 +02:00
github-actions[bot]andCrowdin Bot 1ee24e5a9f Sync Translations from Crowdin (#3280)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2026-07-30 13:01:23 +02:00
Amruth Pillai 93bf1e882d docs: update spec.json 2026-07-30 13:00:30 +02:00
180 changed files with 7287 additions and 6686 deletions
-30
View File
@@ -77,38 +77,8 @@ jobs:
run: pnpm build
- name: Run Baseline E2E Tests
env:
FLAG_SEMANTIC_CSS_AUTHORING: "false"
FLAG_SEMANTIC_CSS_DEFAULT: "false"
run: pnpm exec playwright test --grep-invert "@semantic-css"
- name: Run Semantic CSS Opt-In Acceptance
env:
FLAG_SEMANTIC_CSS_AUTHORING: "true"
FLAG_SEMANTIC_CSS_DEFAULT: "false"
run: |
pnpm exec playwright test \
tests/e2e/specs/semantic-css/legacy-conversion.spec.ts \
tests/e2e/specs/semantic-css/invalid-last-valid.spec.ts \
tests/e2e/specs/semantic-css/portable-stylesheet.spec.ts \
tests/e2e/specs/semantic-css/revision-conflict.spec.ts \
tests/e2e/specs/semantic-css/template-visual.spec.ts
- name: Run Semantic CSS Default-On Acceptance
env:
FLAG_SEMANTIC_CSS_AUTHORING: "true"
FLAG_SEMANTIC_CSS_DEFAULT: "true"
run: pnpm exec playwright test tests/e2e/specs/semantic-css/default-mode.spec.ts
- name: Run Semantic CSS Dormant Acceptance
env:
FLAG_SEMANTIC_CSS_AUTHORING: "false"
FLAG_SEMANTIC_CSS_DEFAULT: "false"
run: |
pnpm exec playwright test \
tests/e2e/specs/semantic-css/dormant-mode.spec.ts \
tests/e2e/specs/semantic-css/flag-off-semantic.spec.ts
- name: Upload Playwright Report
if: always()
uses: actions/upload-artifact@v7
+5 -2
View File
@@ -12,7 +12,7 @@ Internal packages are source-consumed through `package.json` export maps that po
- **Node.js 24** (matches Dockerfile `ARG NODE_VERSION=24`). Use `nvm install 24 && nvm use 24` if needed.
- **Docker** is required to run PostgreSQL. Start it with `sudo dockerd &` if the daemon isn't running.
- **pnpm 11.17.0** is managed via corepack (`corepack enable`).
- **pnpm 11.21.0**. Install pnpm directly using the [official installation guide](https://pnpm.io/installation).
### Codebase map
@@ -107,7 +107,7 @@ The production server runs migrations during startup before serving traffic. Man
### Environment
Copy `.env.example` to `.env`. The three required variables are:
Copy `.env.example` to `.env.local`. The three required variables are:
- `APP_URL` (default `http://localhost:3000`)
- `DATABASE_URL` (default `postgresql://postgres:postgres@localhost:5432/postgres`)
@@ -115,6 +115,8 @@ Copy `.env.example` to `.env`. The three required variables are:
S3/SeaweedFS is optional. If `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, and `S3_BUCKET` are all set, the app uses S3-compatible storage. The checked-in `.env.example` sets SeaweedFS defaults, so either start the `seaweedfs` compose service too or comment out those S3 vars to use local filesystem storage under `<workspace>/data`. `LOCAL_STORAGE_PATH` must be absolute when set.
`REDIS_URL` and `ENCRYPTION_SECRET` are optional for core resume flows, but both are required for saved AI providers and the authenticated `/agent` workspace. Start the `redis` compose service and set both vars in `.env.local` when working on those features. For host-run development, use `REDIS_URL=redis://localhost:6379`; the container-run app uses `REDIS_URL=redis://redis:6379`.
When running dev servers or migration commands, prefix the command with `dotenvx run -f .env.local --`. For example: `dotenvx run -f .env.local -- pnpm dev`. Tests, typechecks, linters, boundary checks, and `pnpm build` do not need this prefix by default. If one of those commands fails because a specific environment variable is required, rerun it with the `dotenvx run -f .env.local --` prefix.
### Common commands
@@ -124,6 +126,7 @@ When running dev servers or migration commands, prefix the command with `dotenvx
| Install deps | `pnpm install` |
| Start Postgres only | `sudo docker compose -f compose.dev.yml up -d postgres` |
| Start Postgres + SeaweedFS | `sudo docker compose -f compose.dev.yml up -d postgres seaweedfs seaweedfs_create_bucket` |
| Start full dev infrastructure | `sudo docker compose -f compose.dev.yml up -d postgres redis seaweedfs seaweedfs_create_bucket` |
| Generate migrations | `dotenvx run -f .env.local -- pnpm db:generate` |
| Run migrations | `dotenvx run -f .env.local -- pnpm db:migrate` |
| Dev server | `dotenvx run -f .env.local -- pnpm dev` (starts on port 3000) |
+7 -7
View File
@@ -1,17 +1,17 @@
# syntax=docker/dockerfile:1.7
ARG PNPM_VERSION=11.21.0
ARG NODE_VERSION=24
FROM node:${NODE_VERSION}-slim AS base
FROM ghcr.io/pnpm/pnpm:${PNPM_VERSION} AS base
ARG NODE_VERSION
RUN pnpm runtime set node ${NODE_VERSION} -g --config.store-dir=/pnpm/runtime-store
WORKDIR /app
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
PNPM_HOME="/pnpm" \
PATH="/pnpm:$PATH" \
TURBO_TELEMETRY_DISABLED=1
RUN corepack enable
ENV TURBO_TELEMETRY_DISABLED=1
FROM base AS pruner
COPY . .
+7 -7
View File
@@ -1,19 +1,19 @@
# syntax=docker/dockerfile:1.7
ARG PNPM_VERSION=11.21.0
ARG NODE_VERSION=24
FROM node:${NODE_VERSION}-slim AS dev
FROM ghcr.io/pnpm/pnpm:${PNPM_VERSION} AS dev
ARG NODE_VERSION
RUN pnpm runtime set node ${NODE_VERSION} -g --config.store-dir=/pnpm/runtime-store
WORKDIR /app
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
PNPM_HOME="/pnpm" \
PATH="/pnpm:$PATH" \
NODE_ENV=development \
ENV NODE_ENV=development \
TURBO_TELEMETRY_DISABLED=1
RUN corepack enable
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
COPY patches ./patches
COPY apps/server/package.json ./apps/server/package.json
+36 -36
View File
@@ -18,35 +18,35 @@
"#react-pdf-renderer": "@react-pdf/renderer"
},
"dependencies": {
"@ai-sdk/anthropic": "^4.0.24",
"@ai-sdk/cerebras": "^3.0.17",
"@ai-sdk/cohere": "^4.0.15",
"@ai-sdk/deepseek": "^3.0.16",
"@ai-sdk/fireworks": "^3.0.18",
"@ai-sdk/google": "^4.0.28",
"@ai-sdk/groq": "^4.0.16",
"@ai-sdk/mistral": "^4.0.17",
"@ai-sdk/openai": "^4.0.24",
"@ai-sdk/openai-compatible": "^3.0.17",
"@ai-sdk/perplexity": "^4.0.17",
"@ai-sdk/togetherai": "^3.0.18",
"@ai-sdk/xai": "^4.0.22",
"@aws-sdk/client-s3": "^3.1098.0",
"@better-auth/api-key": "^1.6.25",
"@better-auth/drizzle-adapter": "^1.6.25",
"@ai-sdk/anthropic": "^4.0.36",
"@ai-sdk/cerebras": "^3.0.28",
"@ai-sdk/cohere": "^4.0.25",
"@ai-sdk/deepseek": "^3.0.26",
"@ai-sdk/fireworks": "^3.0.30",
"@ai-sdk/google": "^4.0.39",
"@ai-sdk/groq": "^4.0.26",
"@ai-sdk/mistral": "^4.0.27",
"@ai-sdk/openai": "^4.0.36",
"@ai-sdk/openai-compatible": "^3.0.28",
"@ai-sdk/perplexity": "^4.0.27",
"@ai-sdk/togetherai": "^3.0.29",
"@ai-sdk/xai": "^4.0.33",
"@aws-sdk/client-s3": "^3.1106.0",
"@better-auth/api-key": "^1.6.26",
"@better-auth/drizzle-adapter": "^1.6.26",
"@better-auth/infra": "^0.3.7",
"@better-auth/oauth-provider": "^1.6.25",
"@better-auth/passkey": "^1.6.25",
"@better-auth/oauth-provider": "^1.6.26",
"@better-auth/passkey": "^1.6.26",
"@bramus/specificity": "^2.4.2",
"@hono/node-server": "^2.0.12",
"@hono/node-server": "^2.1.0",
"@modelcontextprotocol/sdk": "^1.30.0",
"@orpc/client": "^1.14.13",
"@orpc/experimental-ratelimit": "^1.14.13",
"@orpc/json-schema": "^1.14.13",
"@orpc/openapi": "^1.14.13",
"@orpc/server": "^1.14.13",
"@orpc/zod": "^1.14.13",
"@react-pdf/renderer": "^4.5.1",
"@orpc/client": "^1.15.0",
"@orpc/experimental-ratelimit": "^1.15.0",
"@orpc/json-schema": "^1.15.0",
"@orpc/openapi": "^1.15.0",
"@orpc/server": "^1.15.0",
"@orpc/zod": "^1.15.0",
"@react-pdf/renderer": "^4.6.0",
"@reactive-resume/api": "workspace:*",
"@reactive-resume/auth": "workspace:*",
"@reactive-resume/db": "workspace:*",
@@ -58,9 +58,9 @@
"@sindresorhus/slugify": "^3.0.0",
"@t3-oss/env-core": "^0.13.11",
"@uiw/color-convert": "^2.10.3",
"ai": "^7.0.42",
"ai": "^7.0.58",
"bcrypt": "^6.0.0",
"better-auth": "1.6.25",
"better-auth": "1.6.26",
"canonicalize": "^3.0.0",
"cjk-regex": "^3.4.0",
"css-tree": "^3.2.1",
@@ -69,16 +69,16 @@
"drizzle-zod": "1.0.0-beta.14-a36c63d",
"es-toolkit": "^1.50.0",
"fast-json-patch": "^3.1.1",
"hono": "^4.12.32",
"hono": "^4.13.1",
"jsonrepair": "^3.15.0",
"node-html-parser": "^9.0.1",
"nodemailer": "^9.0.3",
"nodemailer": "^9.0.5",
"ollama-ai-provider-v2": "^4.0.1",
"pdfjs-dist": "^6.2.108",
"pg": "^8.22.0",
"pg": "^8.23.0",
"phosphor-icons-react-pdf": "^0.1.3",
"react": "^19.2.8",
"react-email": "^6.9.1",
"react-email": "^6.9.2",
"react-pdf-html": "^2.1.5",
"resumable-stream": "^2.2.12",
"sharp": "^0.35.3",
@@ -89,12 +89,12 @@
},
"devDependencies": {
"@reactive-resume/config": "workspace:*",
"@types/node": "^26.1.2",
"@types/pg": "^8.20.0",
"@types/react": "^19.2.17",
"@types/node": "^26.2.0",
"@types/pg": "^8.21.0",
"@types/react": "^19.2.18",
"@typescript/native-preview": "7.0.0-dev.20260707.2",
"tsdown": "^0.22.14",
"tsx": "^4.23.1",
"tsx": "^4.23.12",
"typescript": "^7.0.2",
"vitest": "^4.1.10"
}
+58
View File
@@ -23,6 +23,7 @@ describe("handleResumePdfDownload", () => {
ok: true,
resumeId: "resume-1",
userId: "user-1",
target: "resume",
expiresAt: "2026-06-01T10:10:00.000Z",
});
mocks.createResumePdfDownload.mockResolvedValueOnce({
@@ -49,6 +50,7 @@ describe("handleResumePdfDownload", () => {
ok: true,
resumeId: "resume-1",
userId: "user-1",
target: "cover-letter",
expiresAt: "2026-06-01T10:10:00.000Z",
});
mocks.createResumePdfDownload.mockResolvedValueOnce({
@@ -68,6 +70,62 @@ describe("handleResumePdfDownload", () => {
});
});
it("defaults a legacy token without a target to resume", async () => {
mocks.verifyResumePdfDownloadToken.mockReturnValueOnce({
ok: true,
resumeId: "resume-1",
userId: "user-1",
expiresAt: "2026-06-01T10:10:00.000Z",
});
mocks.createResumePdfDownload.mockResolvedValueOnce({
headers: { "content-disposition": 'attachment; filename="Cover Letter.pdf"' },
body: new File([], "Cover Letter.pdf", { type: "application/pdf" }),
});
await handleResumePdfDownload(new Request("https://example.com/api/resumes/resume-1/pdf?token=legacy"), "resume-1");
expect(mocks.createResumePdfDownload).toHaveBeenCalledWith({
id: "resume-1",
userId: "user-1",
target: "resume",
});
});
it("rejects a cover-letter target for a legacy token without one", async () => {
mocks.verifyResumePdfDownloadToken.mockReturnValueOnce({
ok: true,
resumeId: "resume-1",
userId: "user-1",
expiresAt: "2026-06-01T10:10:00.000Z",
});
const response = await handleResumePdfDownload(
new Request("https://example.com/api/resumes/resume-1/pdf?token=legacy&target=cover-letter"),
"resume-1",
);
expect(response.status).toBe(401);
expect(mocks.createResumePdfDownload).not.toHaveBeenCalled();
});
it("rejects a target that differs from the signed token", async () => {
mocks.verifyResumePdfDownloadToken.mockReturnValueOnce({
ok: true,
resumeId: "resume-1",
userId: "user-1",
target: "resume",
expiresAt: "2026-06-01T10:10:00.000Z",
});
const response = await handleResumePdfDownload(
new Request("https://example.com/api/resumes/resume-1/pdf?token=signed&target=cover-letter"),
"resume-1",
);
expect(response.status).toBe(401);
expect(mocks.createResumePdfDownload).not.toHaveBeenCalled();
});
it("rejects missing, invalid, and expired tokens before rendering", async () => {
let response = await handleResumePdfDownload(
new Request("https://example.com/api/resumes/resume-1/pdf"),
+8 -1
View File
@@ -30,9 +30,16 @@ export async function handleResumePdfDownload(request: Request, id: string) {
const verification = verifyResumePdfDownloadToken({ resumeId: id, token });
if (!verification.ok) return verification.reason === "expired" ? expiredResponse() : unauthorizedResponse();
const queryTarget = searchParams.get("target");
if (
verification.target
? queryTarget !== null && queryTarget !== verification.target
: queryTarget && queryTarget !== "resume"
)
return unauthorizedResponse();
try {
const target = searchParams.get("target") === "cover-letter" ? "cover-letter" : "resume";
const target = verification.target ?? "resume";
const download = await createResumePdfDownload({ id, userId: verification.userId, target });
return new Response(download.body, {
+13
View File
@@ -2,6 +2,7 @@ import { pathToFileURL } from "node:url";
import { serve } from "@hono/node-server";
import { env } from "@reactive-resume/env/server";
import { createApp } from "./http/app";
import { stylesheetPreflightRunner } from "./services/stylesheet-preflight";
import { runStartupChecks } from "./startup/checks";
export { createApp } from "./http/app";
@@ -9,6 +10,14 @@ export { createApp } from "./http/app";
async function main() {
await runStartupChecks();
// Safety net: Node 24 crashes the whole process on an unhandled rejection. One request's
// stray promise must not take the server down for everyone, so log and keep serving.
// Registered after startup checks so a broken startup still fails loudly. (Left uncaught
// exceptions on Node's default crash-and-restart, since process state is unsafe after one.)
process.on("unhandledRejection", (reason) => {
console.error("[unhandledRejection]", reason);
});
const port =
process.env.NODE_ENV === "production" ? Number.parseInt(process.env.PORT ?? "3000", 10) : env.SERVER_PORT;
@@ -23,6 +32,10 @@ async function main() {
console.info(`🚀 Up and running on http://localhost:${info.port}`);
},
);
// Load the heavy PDF preflight runtime once, now, so the first semantic-CSS edit
// does not pay (and time out on) the cold worker start.
stylesheetPreflightRunner.warmup();
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
+19 -2
View File
@@ -1,5 +1,21 @@
import { auth, verifyOAuthToken } from "@reactive-resume/auth/config";
const OAUTH_WARN_THROTTLE_MS = 60_000;
let lastOAuthWarnAt = 0;
function warnOAuthThrottled(message: string, detail?: unknown): void {
const now = Date.now();
if (now - lastOAuthWarnAt < OAUTH_WARN_THROTTLE_MS) return;
lastOAuthWarnAt = now;
if (detail !== undefined) {
console.warn(message, detail);
return;
}
console.warn(message);
}
export class AuthError extends Error {
constructor() {
super("Unauthorized");
@@ -13,8 +29,9 @@ export async function authenticateRequest(request: Request): Promise<void> {
try {
const payload = await verifyOAuthToken(authHeader.slice(7));
if (payload?.sub) return;
} catch {
// Invalid or expired token; fall through to API key auth.
warnOAuthThrottled("[MCP] OAuth token verified but missing `sub` claim");
} catch (error) {
warnOAuthThrottled("[MCP] OAuth token verification failed:", error);
}
}
+1 -1
View File
@@ -53,7 +53,7 @@ export function createMcpServer(request: Request) {
`Read schema at \`resume://_meta/schema\`; read resume JSON via \`resume://{id}\` or \`${MCP_TOOL_NAME.getResume}\`.`,
`Apply body edits with JSON Patch through \`${MCP_TOOL_NAME.patchResume}\`.`,
`Change name, slug, tags, or public visibility with \`${MCP_TOOL_NAME.updateResume}\` (returns canonical share URL; anonymous access only when \`isPublic\` is true; passwords are managed in the web app only).`,
`Create short-lived authenticated PDF download URLs with \`${MCP_TOOL_NAME.downloadResumePdf}\`.`,
`Create short-lived authenticated PDF download URLs with \`${MCP_TOOL_NAME.downloadResumePdf}\`; set target to \`cover-letter\` to export a visible cover letter separately.`,
`Import full ResumeData JSON with \`${MCP_TOOL_NAME.importResume}\`; read saved AI analysis with \`${MCP_TOOL_NAME.getResumeAnalysis}\`.`,
].join(" "),
},
@@ -1,27 +0,0 @@
import { mkdtemp, readFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, expect, it } from "vitest";
import { generateOpenApiDocumentation } from "./generate-spec";
const temporaryDirectories: string[] = [];
const committedSpec = new URL("../../../../docs/spec.json", import.meta.url);
afterEach(async () => {
await Promise.all(temporaryDirectories.splice(0).map((path) => rm(path, { recursive: true, force: true })));
});
it("keeps the committed OpenAPI specification synchronized without rewriting it", async () => {
const directory = await mkdtemp(join(tmpdir(), "openapi-documentation-"));
temporaryDirectories.push(directory);
const firstTarget = join(directory, "first.json");
const secondTarget = join(directory, "second.json");
const before = await readFile(committedSpec, "utf8");
await generateOpenApiDocumentation(firstTarget);
await generateOpenApiDocumentation(secondTarget);
expect(await readFile(firstTarget, "utf8")).toBe(before);
expect(await readFile(secondTarget, "utf8")).toBe(before);
expect(await readFile(committedSpec, "utf8")).toBe(before);
});
@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { afterEach, describe, expect, it } from "vitest";
import { defaultResumeData } from "@reactive-resume/schema/resume/default";
import { createStylesheetPreflightRunner, STYLESHEET_PREFLIGHT_LIMITS } from "./stylesheet-preflight";
@@ -13,6 +13,17 @@ const input = {
stylesheet: validStylesheet,
} as const;
// Runners now own a long-lived, reused worker; destroy them so no worker thread
// outlives its test.
const runners: Array<{ destroy(): Promise<void> }> = [];
const track = <T extends { destroy(): Promise<void> }>(runner: T): T => {
runners.push(runner);
return runner;
};
afterEach(async () => {
await Promise.all(runners.splice(0).map((runner) => runner.destroy()));
});
const memoryExhaustionWorker = new URL(
`data:text/javascript,${encodeURIComponent(`
const retained = [];
@@ -27,35 +38,61 @@ const failedWorker = new URL(
`data:text/javascript,${encodeURIComponent('throw new Error("sensitive worker details");')}`,
);
// Counts how many preflights this single worker instance served so a reuse test
// can prove the worker is not respawned per request.
const reuseCountingWorker = new URL(
`data:text/javascript,${encodeURIComponent(`
import { parentPort } from "node:worker_threads";
let served = 0;
parentPort.postMessage({ type: "ready" });
parentPort.on("message", (message) => {
if (message?.type !== "preflight") return;
served += 1;
parentPort.postMessage({
type: "result",
requestId: message.requestId,
result: { ok: true, pageCount: 1, byteCount: served, diagnostics: [] },
});
});
`)}`,
);
const delayedSuccessfulWorker = new URL(
`data:text/javascript,${encodeURIComponent(`
import { parentPort, workerData } from "node:worker_threads";
import { parentPort } from "node:worker_threads";
parentPort.postMessage({ type: "ready" });
setTimeout(() => {
parentPort.postMessage({
ok: true,
pageCount: 1,
byteCount: Number(workerData.input.data.basics.name),
diagnostics: [],
});
}, 300);
parentPort.on("message", (message) => {
if (message?.type !== "preflight") return;
setTimeout(() => {
parentPort.postMessage({
type: "result",
requestId: message.requestId,
result: {
ok: true,
pageCount: 1,
byteCount: Number(message.input.data.basics.name),
diagnostics: [],
},
});
}, 300);
});
`)}`,
);
const delayedReadyWorker = new URL(
`data:text/javascript,${encodeURIComponent(`
import { parentPort } from "node:worker_threads";
setTimeout(() => {
parentPort.postMessage({ type: "ready" });
parentPort.on("message", (message) => {
if (message?.type !== "preflight") return;
setTimeout(() => {
parentPort.postMessage({
ok: true,
pageCount: 1,
byteCount: 1,
diagnostics: [],
type: "result",
requestId: message.requestId,
result: { ok: true, pageCount: 1, byteCount: 1, diagnostics: [] },
});
}, 10);
}, 50);
});
setTimeout(() => parentPort.postMessage({ type: "ready" }), 50);
`)}`,
);
@@ -101,7 +138,7 @@ const invalidInput = () => {
describe("stylesheet PDF preflight worker", () => {
it("keeps the production resource policy fixed and immutable", () => {
expect(STYLESHEET_PREFLIGHT_LIMITS).toEqual({
timeoutMs: 5_000,
timeoutMs: 30_000,
maxPages: 20,
maxBytes: 10_000_000,
maxPageWidthPt: 2_000,
@@ -115,7 +152,7 @@ describe("stylesheet PDF preflight worker", () => {
});
it("accepts a bounded candidate render in an isolated worker", async () => {
const runner = createStylesheetPreflightRunner({ timeoutMs: 15_000 });
const runner = track(createStylesheetPreflightRunner({ timeoutMs: 15_000 }));
const result = await runner.run(input);
@@ -131,8 +168,22 @@ describe("stylesheet PDF preflight worker", () => {
expect(runner.activeWorkerCount).toBe(0);
}, 45_000);
it("reuses one warm worker across sequential requests instead of cold-starting each one", async () => {
const runner = track(createStylesheetPreflightRunner({}, reuseCountingWorker));
const first = await runner.run(input);
const second = await runner.run(input);
const third = await runner.run(input);
// A single reused worker increments its per-instance counter; a per-request
// worker would report byteCount 1 every time.
expect([first, second, third].map((result) => (result.ok ? result.byteCount : -1))).toEqual([1, 2, 3]);
expect(runner.activeWorkerCount).toBe(0);
expect(runner.queuedPreflightCount).toBe(0);
});
it("preserves structured resume-data failures across the worker boundary", async () => {
const runner = createStylesheetPreflightRunner({ timeoutMs: 15_000 });
const runner = track(createStylesheetPreflightRunner({ timeoutMs: 15_000 }));
const result = runner.run(invalidInput());
@@ -145,7 +196,7 @@ describe("stylesheet PDF preflight worker", () => {
}, 20_000);
it("terminates a worker when the render exceeds its deadline", async () => {
const runner = createStylesheetPreflightRunner({ timeoutMs: 1 }, neverCompletesWorker);
const runner = track(createStylesheetPreflightRunner({ timeoutMs: 1 }, neverCompletesWorker));
const result = await runner.run(input);
@@ -155,15 +206,15 @@ describe("stylesheet PDF preflight worker", () => {
});
it("starts the authored render deadline after the worker runtime is ready", async () => {
const runner = createStylesheetPreflightRunner({ timeoutMs: 20 }, delayedReadyWorker);
const runner = track(createStylesheetPreflightRunner({ timeoutMs: 20 }, delayedReadyWorker));
await expect(runner.run(input)).resolves.toEqual(expect.objectContaining({ ok: true, pageCount: 1 }));
expect(runner.activeWorkerCount).toBe(0);
});
it("returns deterministic output byte and page limit codes", async () => {
const byteRunner = createStylesheetPreflightRunner({ maxBytes: 16 });
const pageRunner = createStylesheetPreflightRunner({ maxPages: 0 });
const byteRunner = track(createStylesheetPreflightRunner({ maxBytes: 16 }));
const pageRunner = track(createStylesheetPreflightRunner({ maxPages: 0 }));
await expect(byteRunner.run(input)).resolves.toEqual(
expect.objectContaining({ ok: false, code: "STYLESHEET_PREFLIGHT_BYTE_LIMIT" }),
@@ -176,9 +227,8 @@ describe("stylesheet PDF preflight worker", () => {
}, 30_000);
it("maps worker heap exhaustion to a controlled memory-limit result", async () => {
const runner = createStylesheetPreflightRunner(
{ maxOldGenerationMb: 8, timeoutMs: 10_000 },
memoryExhaustionWorker,
const runner = track(
createStylesheetPreflightRunner({ maxOldGenerationMb: 8, timeoutMs: 10_000 }, memoryExhaustionWorker),
);
const result = await runner.run(input);
@@ -187,8 +237,8 @@ describe("stylesheet PDF preflight worker", () => {
expect(runner.activeWorkerCount).toBe(0);
}, 15_000);
it("does not expose internal errors from a failed worker", async () => {
const runner = createStylesheetPreflightRunner({}, failedWorker);
it("does not expose internal errors from a failed worker bootstrap", async () => {
const runner = track(createStylesheetPreflightRunner({}, failedWorker));
const result = await runner.run(input);
@@ -202,14 +252,48 @@ describe("stylesheet PDF preflight worker", () => {
expect(runner.queuedPreflightCount).toBe(0);
});
it("surfaces sanitized render failures from inside the worker catch path", async () => {
const throwingWorker = new URL(
`data:text/javascript,${encodeURIComponent(`
import { parentPort } from "node:worker_threads";
parentPort.postMessage({ type: "ready" });
parentPort.on("message", (message) => {
if (message?.type !== "preflight") return;
parentPort.postMessage({
type: "result",
requestId: message.requestId,
result: {
ok: false,
code: "STYLESHEET_PREFLIGHT_WORKER_FAILED",
message: "The PDF preflight worker failed. (Error: Canvas is already closed)",
diagnostics: [],
},
});
});
`)}`,
);
const runner = track(createStylesheetPreflightRunner({ timeoutMs: 5_000 }, throwingWorker));
const result = await runner.run(input);
expect(result).toEqual({
ok: false,
code: "STYLESHEET_PREFLIGHT_WORKER_FAILED",
message: "The PDF preflight worker failed. (Error: Canvas is already closed)",
diagnostics: [],
});
});
it("bounds concurrent workers and queued requests without charging queue time to the worker deadline", async () => {
const runner = createStylesheetPreflightRunner(
{
timeoutMs: 500,
maxConcurrentWorkers: 1,
maxQueuedRequests: 2,
},
delayedSuccessfulWorker,
const runner = track(
createStylesheetPreflightRunner(
{
timeoutMs: 500,
maxConcurrentWorkers: 1,
maxQueuedRequests: 2,
},
delayedSuccessfulWorker,
),
);
const completionOrder: number[] = [];
const accepted = [1, 2, 3].map((number) =>
@@ -237,7 +321,7 @@ describe("stylesheet PDF preflight worker", () => {
}, 5_000);
it("does not leak a slot when the worker constructor throws synchronously", async () => {
const runner = createStylesheetPreflightRunner({}, synchronousFailureWorker);
const runner = track(createStylesheetPreflightRunner({}, synchronousFailureWorker));
await expect(runner.run(input)).resolves.toEqual(
expect.objectContaining({ ok: false, code: "STYLESHEET_PREFLIGHT_WORKER_FAILED" }),
+230 -93
View File
@@ -23,8 +23,12 @@ type StylesheetPreflightLimits = {
};
const SOURCE_WORKER_LOADER_HEAP_MB = 256;
const SOURCE_WORKER_STARTUP_TIMEOUT_MS = 30_000;
const WORKER_STARTUP_TIMEOUT_MS = 15_000;
// The worker is warmed once and reused, so the one-time cold load (which is
// super-linear in available CPU — measured ~9s at 0.5 vCPU, ~53s at 0.35, ~93s at
// 0.25) is paid at startup, not per request. This ceiling must exceed that cold
// load or warmup is killed mid-bootstrap and never completes on a throttled box;
// it only bounds a genuinely stuck bootstrap and is off the per-edit path.
const WORKER_READINESS_TIMEOUT_MS = 120_000;
type SerializedPreflightCause = {
name: string;
@@ -33,13 +37,16 @@ type SerializedPreflightCause = {
};
type StylesheetPreflightWorkerMessage =
| PdfPreflightResult
| { type: "ready" }
| { type: "preflight_error"; cause: SerializedPreflightCause };
| { type: "load_error"; message: string }
| { type: "result"; requestId: number; result: PdfPreflightResult }
| { type: "preflight_error"; requestId: number; cause: SerializedPreflightCause };
export type NodeStylesheetPreflightRunner = StylesheetPreflightRunner & {
readonly activeWorkerCount: number;
readonly queuedPreflightCount: number;
warmup(): void;
destroy(): Promise<void>;
};
const failure = (code: PdfPreflightFailure["code"], message: string): PdfPreflightFailure => ({
@@ -75,9 +82,10 @@ const workerLocation = () => {
url: source
? new URL("../workers/stylesheet-preflight.ts", import.meta.url)
: new URL("./stylesheet-preflight-worker.mjs", import.meta.url),
// Production must not inherit parent execArgv (e.g. --import/--input-type); source workers need tsx.
execArgv: source ? sourceWorkerExecArgv() : [],
...(source
? {
execArgv: sourceWorkerExecArgv(),
env: {
...process.env,
TSX_TSCONFIG_PATH: fileURLToPath(new URL("../../tsconfig.json", import.meta.url)),
@@ -87,129 +95,241 @@ const workerLocation = () => {
};
};
type PendingRequest = {
resolve: (result: PdfPreflightResult) => void;
reject: (cause: unknown) => void;
renderTimer?: ReturnType<typeof setTimeout>;
};
type Readiness = {
promise: Promise<Worker>;
resolve: (worker: Worker) => void;
reject: (error: Error) => void;
timer: ReturnType<typeof setTimeout>;
};
export function createStylesheetPreflightRunner(
overrides: Partial<StylesheetPreflightLimits> = {},
testWorkerUrl?: URL,
): NodeStylesheetPreflightRunner {
const limits = Object.freeze({ ...STYLESHEET_PREFLIGHT_LIMITS, ...overrides });
let activeWorkerCount = 0;
// ponytail: Keep admission process-local and bounded; upgrade to a distributed/pooled queue only for multi-process coordination.
let worker: Worker | undefined;
let ready = false;
let readiness: Readiness | undefined;
let destroyed = false;
let requestSeq = 0;
const pending = new Map<number, PendingRequest>();
// ponytail: process-local, bounded admission; upgrade to a pooled/distributed queue only for multi-process coordination.
const queue: Array<{
input: StylesheetPreflightInput;
resolve: (result: PdfPreflightResult) => void;
reject: (cause: unknown) => void;
resolve: PendingRequest["resolve"];
reject: PendingRequest["reject"];
}> = [];
const runWorker = (
input: StylesheetPreflightInput,
resolve: (result: PdfPreflightResult) => void,
reject: (cause: unknown) => void,
): boolean => {
// The URL seam is internal to the server package and keeps worker failure tests independent from the PDF renderer.
const location = testWorkerUrl ? { source: false, url: testWorkerUrl } : workerLocation();
let worker: Worker;
const teardownWorker = () => {
const dead = worker;
worker = undefined;
ready = false;
if (readiness) {
clearTimeout(readiness.timer);
readiness.reject(new Error("Stylesheet preflight worker did not become ready."));
readiness = undefined;
}
if (!dead) return;
dead.off("message", onMessage);
dead.off("error", onError);
dead.off("exit", onExit);
void dead.terminate().catch(() => undefined);
};
const clearPending = (requestId: number): PendingRequest | undefined => {
const entry = pending.get(requestId);
if (!entry) return undefined;
if (entry.renderTimer) clearTimeout(entry.renderTimer);
pending.delete(requestId);
return entry;
};
const drainQueue = () => {
while (!destroyed && pending.size < limits.maxConcurrentWorkers && queue.length > 0) {
const next = queue.shift();
if (!next) return;
dispatch(next.input, next.resolve, next.reject);
}
};
const resolveRequest = (requestId: number, result: PdfPreflightResult) => {
const entry = clearPending(requestId);
if (!entry) return;
entry.resolve(result);
drainQueue();
};
const rejectRequest = (requestId: number, cause: unknown) => {
const entry = clearPending(requestId);
if (!entry) return;
entry.reject(cause);
drainQueue();
};
// A crashed/exited/timed-out worker is torn down and its in-flight requests are
// failed; the next dispatch (including any queued requests) spawns a fresh one,
// so a poisoned render never lingers across requests.
const failWorker = (result: PdfPreflightFailure) => {
teardownWorker();
const stale = [...pending.keys()];
for (const requestId of stale) resolveRequest(requestId, result);
drainQueue();
};
function onMessage(message: StylesheetPreflightWorkerMessage) {
if (message.type === "ready") {
if (readiness) {
clearTimeout(readiness.timer);
ready = true;
const resolveReady = readiness.resolve;
const readyWorker = worker;
readiness = undefined;
if (readyWorker) resolveReady(readyWorker);
}
return;
}
if (message.type === "load_error") {
failWorker(failure("STYLESHEET_PREFLIGHT_WORKER_FAILED", message.message));
return;
}
if (message.type === "result") {
resolveRequest(message.requestId, message.result);
return;
}
if (message.type === "preflight_error") {
rejectRequest(
message.requestId,
Object.assign(new Error(message.cause.message), { name: message.cause.name, issues: message.cause.issues }),
);
}
}
function onError(error: Error) {
console.warn("[stylesheet-preflight] worker error:", error.message);
failWorker(workerFailure(error));
}
function onExit(code: number) {
if (destroyed || (!worker && pending.size === 0)) return;
console.warn(`[stylesheet-preflight] worker exited unexpectedly (code ${code})`);
failWorker(failure("STYLESHEET_PREFLIGHT_WORKER_FAILED", "The PDF preflight worker failed."));
}
const startWorker = (): Promise<Worker> => {
const location = testWorkerUrl ? { source: false, url: testWorkerUrl, execArgv: [] as string[] } : workerLocation();
let spawned: Worker;
try {
worker = new Worker(location.url, {
spawned = new Worker(location.url, {
name: "stylesheet-preflight",
workerData: { input, limits },
resourceLimits: {
// The source-only tsx compiler heap is outside the production render budget.
maxOldGenerationSizeMb: limits.maxOldGenerationMb + (location.source ? SOURCE_WORKER_LOADER_HEAP_MB : 0),
},
...("execArgv" in location ? { execArgv: location.execArgv } : {}),
execArgv: location.execArgv,
...("env" in location ? { env: location.env } : {}),
});
} catch (error) {
resolve(workerFailure(error instanceof Error ? error : new Error("Failed to start PDF preflight worker.")));
return false;
return Promise.reject(error instanceof Error ? error : new Error("Failed to start PDF preflight worker."));
}
activeWorkerCount += 1;
let settled = false;
let renderTimer: ReturnType<typeof setTimeout> | undefined;
let startupTimer: ReturnType<typeof setTimeout> | undefined;
worker = spawned;
ready = false;
// The idle reused worker must not keep the process (or a test run) alive; active
// requests stay alive through their ref'd readiness/render timers.
spawned.unref();
spawned.on("message", onMessage);
spawned.once("error", onError);
spawned.once("exit", onExit);
const cleanup = () => {
if (renderTimer) clearTimeout(renderTimer);
if (startupTimer) clearTimeout(startupTimer);
worker.off("message", onMessage);
worker.off("error", onError);
worker.off("exit", onExit);
activeWorkerCount -= 1;
};
const finish = async (result: PdfPreflightResult) => {
if (settled) return;
settled = true;
await worker.terminate().catch(() => undefined);
cleanup();
resolve(result);
drainQueue();
};
const fail = async (cause: SerializedPreflightCause) => {
if (settled) return;
settled = true;
await worker.terminate().catch(() => undefined);
cleanup();
reject(Object.assign(new Error(cause.message), { name: cause.name, issues: cause.issues }));
drainQueue();
};
const onMessage = (message: StylesheetPreflightWorkerMessage) => {
if ("type" in message) {
if (message.type === "preflight_error") {
void fail(message.cause);
return;
}
if (startupTimer) clearTimeout(startupTimer);
renderTimer = setTimeout(() => {
void finish(failure("STYLESHEET_PREFLIGHT_TIMEOUT", "The PDF preflight exceeded its deadline."));
}, limits.timeoutMs);
return;
}
void finish(message);
};
const onError = (error: Error) => {
void finish(workerFailure(error));
};
const onExit = () => {
if (!settled) {
void finish(failure("STYLESHEET_PREFLIGHT_WORKER_FAILED", "The PDF preflight worker failed."));
}
};
worker.on("message", onMessage);
worker.once("error", onError);
worker.once("exit", onExit);
startupTimer = setTimeout(
() => {
void finish(failure("STYLESHEET_PREFLIGHT_WORKER_FAILED", "The PDF preflight worker failed."));
},
location.source ? SOURCE_WORKER_STARTUP_TIMEOUT_MS : WORKER_STARTUP_TIMEOUT_MS,
);
return true;
let resolve!: (value: Worker) => void;
let reject!: (error: Error) => void;
const promise = new Promise<Worker>((resolvePromise, rejectPromise) => {
resolve = resolvePromise;
reject = rejectPromise;
});
const timer = setTimeout(() => {
console.warn(`[stylesheet-preflight] worker did not become ready within ${WORKER_READINESS_TIMEOUT_MS}ms`);
teardownWorker();
}, WORKER_READINESS_TIMEOUT_MS);
readiness = { promise, resolve, reject, timer };
return promise;
};
function drainQueue() {
while (activeWorkerCount < limits.maxConcurrentWorkers && queue.length > 0) {
const next = queue.shift();
if (!next) return;
runWorker(next.input, next.resolve, next.reject);
const getReadyWorker = (): Promise<Worker> => {
if (destroyed) return Promise.reject(new Error("Stylesheet preflight worker was terminated."));
if (worker && ready) return Promise.resolve(worker);
if (readiness) return readiness.promise;
return startWorker();
};
// One retry: a worker that failed to become ready is torn down; a second
// attempt spawns a fresh worker before the request gives up.
const waitUntilReady = async (): Promise<Worker> => {
try {
return await getReadyWorker();
} catch {
return await getReadyWorker();
}
};
function dispatch(
input: StylesheetPreflightInput,
resolve: PendingRequest["resolve"],
reject: PendingRequest["reject"],
) {
const requestId = ++requestSeq;
pending.set(requestId, { resolve, reject });
void waitUntilReady()
.then((readyWorker) => {
const entry = pending.get(requestId);
if (!entry) return;
entry.renderTimer = setTimeout(() => {
// A stuck render poisons the reused worker: tear it down and respawn — but
// only the worker this request actually ran on, so a stale timer can never
// kill a newer worker already serving other requests.
clearPending(requestId);
if (worker === readyWorker) teardownWorker();
resolve(failure("STYLESHEET_PREFLIGHT_TIMEOUT", "The PDF preflight exceeded its deadline."));
drainQueue();
}, limits.timeoutMs);
readyWorker.postMessage({ type: "preflight", requestId, input, limits });
})
.catch((error: unknown) => {
resolveRequest(
requestId,
workerFailure(error instanceof Error ? error : new Error("Failed to start PDF preflight worker.")),
);
});
}
return {
get activeWorkerCount() {
return activeWorkerCount;
return pending.size;
},
get queuedPreflightCount() {
return queue.length;
},
warmup() {
void waitUntilReady().catch(() => undefined);
},
run(input: StylesheetPreflightInput): Promise<PdfPreflightResult> {
return new Promise<PdfPreflightResult>((resolve, reject) => {
if (activeWorkerCount < limits.maxConcurrentWorkers) {
runWorker(input, resolve, reject);
if (destroyed) {
resolve(failure("STYLESHEET_PREFLIGHT_WORKER_FAILED", "The PDF preflight worker was terminated."));
return;
}
if (pending.size < limits.maxConcurrentWorkers) {
dispatch(input, resolve, reject);
return;
}
if (queue.length >= limits.maxQueuedRequests) {
@@ -219,6 +339,23 @@ export function createStylesheetPreflightRunner(
queue.push({ input, resolve, reject });
});
},
async destroy() {
destroyed = true;
const dead = worker;
teardownWorker();
await dead?.terminate().catch(() => undefined);
for (const requestId of [...pending.keys()]) {
resolveRequest(
requestId,
failure("STYLESHEET_PREFLIGHT_WORKER_FAILED", "The PDF preflight worker was terminated."),
);
}
while (queue.length > 0) {
const next = queue.shift();
next?.resolve(failure("STYLESHEET_PREFLIGHT_WORKER_FAILED", "The PDF preflight worker was terminated."));
}
},
};
}
@@ -1,4 +1,8 @@
import type { PdfPreflightPageLimits, PdfPreflightResult, RenderPreflightPdfResult } from "@reactive-resume/pdf/server";
import type {
PdfPreflightPageLimits,
PdfPreflightResult,
RenderPreflightPdfResult,
} from "@reactive-resume/pdf/preflight";
import { getDocument } from "pdfjs-dist/legacy/build/pdf.mjs";
type StylesheetPreflightInspectionLimits = PdfPreflightPageLimits & {
+55 -25
View File
@@ -1,7 +1,10 @@
import type { PdfPreflightPageLimits, PdfPreflightResult, StylesheetPreflightInput } from "@reactive-resume/pdf/server";
import { parentPort, workerData } from "node:worker_threads";
import type {
PdfPreflightPageLimits,
PdfPreflightResult,
StylesheetPreflightInput,
} from "@reactive-resume/pdf/preflight";
import { parentPort } from "node:worker_threads";
import * as React from "react";
import { renderPreflightPdf } from "@reactive-resume/pdf/server";
import { inspectPreflightPdf } from "./stylesheet-preflight-inspection";
(globalThis as typeof globalThis & { React: typeof React }).React = React;
@@ -11,7 +14,12 @@ type StylesheetPreflightWorkerLimits = PdfPreflightPageLimits & {
maxBytes: number;
};
type StylesheetPreflightWorkerData = {
// The worker is long-lived and reused across requests: the heavy PDF runtime is
// loaded once at startup and each preflight arrives as a message (input can no
// longer come from `workerData`, which is fixed at construction time).
type StylesheetPreflightWorkerRequest = {
type: "preflight";
requestId: number;
input: StylesheetPreflightInput;
limits: StylesheetPreflightWorkerLimits;
};
@@ -22,8 +30,11 @@ type SerializedPreflightCause = {
issues: readonly unknown[];
};
const send = (result: PdfPreflightResult) => {
parentPort?.postMessage(result);
const sanitizeWorkerCause = (cause: unknown): string => {
if (!(cause instanceof Error)) return "The PDF preflight worker failed.";
const detail = cause.message.replace(/\s+/g, " ").trim().slice(0, 200);
if (!detail) return "The PDF preflight worker failed.";
return `The PDF preflight worker failed. (${cause.name}: ${detail})`;
};
const serializeZodCause = (cause: unknown): SerializedPreflightCause | undefined => {
@@ -33,28 +44,47 @@ const serializeZodCause = (cause: unknown): SerializedPreflightCause | undefined
return { name: cause.name, message: cause.message, issues: cause.issues };
};
parentPort?.postMessage({ type: "ready" });
// Load the heavy PDF runtime once. A rejection here (missing/broken dependency in
// a pruned production install) is reported explicitly instead of becoming an
// unhandled rejection that silently kills the worker and surfaces as an opaque
// runner-side failure.
const initialization = import("@reactive-resume/pdf/preflight");
async function run(): Promise<PdfPreflightResult> {
const { input, limits } = workerData as StylesheetPreflightWorkerData;
const rendered = await renderPreflightPdf(input, limits);
return rendered.ok ? inspectPreflightPdf(rendered, limits) : rendered;
}
void initialization.then(
() => parentPort?.postMessage({ type: "ready" }),
(cause: unknown) => {
console.error("[stylesheet-preflight] worker runtime failed to load", cause);
parentPort?.postMessage({ type: "load_error", message: sanitizeWorkerCause(cause) });
},
);
if (parentPort) {
void run()
.then(send)
.catch((cause: unknown) => {
const serializedCause = serializeZodCause(cause);
if (serializedCause) {
parentPort?.postMessage({ type: "preflight_error", cause: serializedCause });
return;
}
send({
const handle = async (request: StylesheetPreflightWorkerRequest): Promise<void> => {
try {
const { renderPreflightPdf } = await initialization;
const rendered = await renderPreflightPdf(request.input, request.limits);
const result: PdfPreflightResult = rendered.ok ? await inspectPreflightPdf(rendered, request.limits) : rendered;
parentPort?.postMessage({ type: "result", requestId: request.requestId, result });
} catch (cause) {
const serializedCause = serializeZodCause(cause);
if (serializedCause) {
parentPort?.postMessage({ type: "preflight_error", requestId: request.requestId, cause: serializedCause });
return;
}
console.error("[stylesheet-preflight]", cause);
parentPort?.postMessage({
type: "result",
requestId: request.requestId,
result: {
ok: false,
code: "STYLESHEET_PREFLIGHT_WORKER_FAILED",
message: "The PDF preflight worker failed.",
message: sanitizeWorkerCause(cause),
diagnostics: [],
});
},
});
}
}
};
parentPort?.on("message", (message: StylesheetPreflightWorkerRequest) => {
if (message.type !== "preflight") return;
void handle(message);
});
+3
View File
@@ -45,6 +45,9 @@ export default defineConfig({
shims: true,
dts: false,
define: { __APP_VERSION__: JSON.stringify(rootPackageJson.version ?? "0.0.0") },
// The flagged dynamic imports are deliberate: they defer evaluation of env-dependent
// modules so tests can run without env vars, not to split chunks.
suppressWarnings: [/dynamic import will not move module into another chunk/],
outExtensions: () => ({ js: ".mjs" }),
deps: {
alwaysBundle: [/^@reactive-resume\//],
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: af\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Afrikaans\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Aansoek gedoen"
msgid "Applied on"
msgstr "Toegepas op"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Toegepaste Reëls"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Toegepas met waarskuwings"
@@ -1010,6 +1006,11 @@ msgstr "Kopieer rugsteunkodes"
msgid "Copy JSON"
msgstr "Kopieer JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopieer geheim"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopieer stylblad"
@@ -2946,10 +2947,6 @@ msgstr "Geen gestoorde weergawes nog nie."
msgid "No source data yet."
msgstr "Geen brondata nog nie."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Geen stylreëls nog nie."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Geen getoetste verskaffer nie"
@@ -2968,7 +2965,7 @@ msgstr "Nie gekoppel nie"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Nie seker wat om te skryf nie?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktiewe CV v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Lees die gids oor die toepassing van persoonlike style."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Herstel"
msgid "Reset Password"
msgstr "Herstel wagwoord"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Stel styl terug"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Stel terug na toegepaste stylblad"
@@ -3687,14 +3680,6 @@ msgstr "Roemeens"
msgid "Rotation"
msgstr "Rotasie"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "reël"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "reëls"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Voer jou eerste ontleding uit om 'n puntkaart, sterkpunte en geprioritiseerde voorstelle te kry."
@@ -3876,10 +3861,6 @@ msgstr "Self-aanbieding met Docker"
msgid "Semantic CSS stylesheet"
msgstr "Semantiese CSS-stylblad"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantiese style bly aktief"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Stuur boodskap"
@@ -4482,10 +4463,6 @@ msgstr "Hierdie inskrywing sal permanent uitgevee word. Dit kan nie ongedaan gem
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Hierdie kenmerk vereis 'n gekoppelde KI-verskaffer. Stel asseblief een op in die instellings."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Hierdie instansie laat tans nie Semantiese CSS-redigering toe nie."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Dit is 'n URL-vriendelike naam vir jou CV."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: am\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Amharic\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
@@ -494,10 +494,6 @@ msgstr "ተመልክቷል"
msgid "Applied on"
msgstr "የተተገበረው በ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "የተተገበሩ ህጎች"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "ከማስጠንቀቂያዎች ጋር ተተግብሯል"
@@ -1010,6 +1006,11 @@ msgstr "የመከላከያ ኮዶችን ቅጂ አድርግ"
msgid "Copy JSON"
msgstr "JSONን ይቅዱ"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "ሚስጥርን ይቅዱ"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "የቅጥ ሉህን ቅዳ"
@@ -2946,10 +2947,6 @@ msgstr "እስካሁን ምንም የተቀመጡ ስሪቶች የሉም።"
msgid "No source data yet."
msgstr "እስካሁን ምንም የምንጭ ውሂብ የለም።"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "እስካሁን የቅጥ ደንቦች የሉም።"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "የተፈተነ አቅራቢ የለም"
@@ -2968,7 +2965,7 @@ msgstr "አልተገናኘም"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "ምን መጻፍ እንዳለብህ እርግጠኛ አይደለህም?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "የአጠቃቀም ብጁ ቅጦች መመሪያን ያንብቡ።"
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "ዳግም ለመጀመር"
msgid "Reset Password"
msgstr "የይለፍ ቃል ዳግም አስጀምር"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "ቅጥን ዳግም አስጀምር"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "ወደ ተተገበረ የቅጥ ሉህ ዳግም አስጀምር"
@@ -3687,14 +3680,6 @@ msgstr "ሮማኒያንኛ"
msgid "Rotation"
msgstr "ማሽከርከር"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "ደንብ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "ደንቦች"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "የውጤት ካርድ፣ ጥንካሬዎች እና ቅድሚያ የተሰጣቸው አስተያየቶችን ለማግኘት የመጀመሪያ ትንተናዎን ያከናውኑ።"
@@ -3876,10 +3861,6 @@ msgstr "በ Docker ራስህን አስተናግድ"
msgid "Semantic CSS stylesheet"
msgstr "የትርጓሜ CSS የቅጥ ሉህ"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "የትርጓሜ ቅጦች ንቁ ሆነው ይቆያሉ"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "መልእክት ላክ"
@@ -4482,10 +4463,6 @@ msgstr "ይህ ግቤት በቋሚነት ይሰረዛል። ይህን መመለ
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "ይህ ባህሪ የተገናኘ የAI አቅራቢ ያስፈልገዋል። እባክዎ በቅንብሮች ውስጥ አንድ ያዋቅሩ።"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "ይህ አጋጣሚ በአሁኑ ጊዜ የሴማንቲክ CSS አርትዖትን አይፈቅድም።"
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "ይህ ለየታሪክዎ ተመቻቹ የ URL ስም ነው።"
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: ar\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Arabic\n"
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
@@ -494,10 +494,6 @@ msgstr "تم التقديم"
msgid "Applied on"
msgstr "تم التقديم في"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "القواعد المطبقة"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "تم استخدامه مع التحذيرات"
@@ -1010,6 +1006,11 @@ msgstr "نسخ رموز النسخ الاحتياطي"
msgid "Copy JSON"
msgstr "نسخ JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "حقوق الطبع والنشر"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "انسخ ورقة الأنماط"
@@ -2946,10 +2947,6 @@ msgstr "لا توجد نسخ محفوظة حتى الآن."
msgid "No source data yet."
msgstr "لا توجد بيانات مصدرية حتى الآن."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "لا توجد قواعد أسلوبية حتى الآن."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "لم يتم اختبار أي مزود خدمة"
@@ -2968,7 +2965,7 @@ msgstr "غير متصل"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "لست متأكدًا مما يجب كتابته؟"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "استئناف تفاعلي الإصدار 4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "اقرأ دليل تطبيق الأنماط المخصصة."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "إعادة تعيين"
msgid "Reset Password"
msgstr "إعادة تعيين كلمة المرور"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "إعادة ضبط النمط"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "إعادة ضبط نمط التنسيق المُطبق"
@@ -3687,14 +3680,6 @@ msgstr "الرومانية"
msgid "Rotation"
msgstr "الدوران"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "قاعدة"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "قواعد"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "قم بإجراء تحليلك الأول للحصول على بطاقة الأداء ونقاط القوة والاقتراحات ذات الأولوية."
@@ -3876,10 +3861,6 @@ msgstr "الاستضافة الذاتية مع Docker"
msgid "Semantic CSS stylesheet"
msgstr "ورقة أنماط CSS الدلالية"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "لا تزال الأساليب الدلالية نشطة"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "إرسال الرسائل"
@@ -4482,10 +4463,6 @@ msgstr "سيتم حذف هذا الإدخال نهائيًا. لا يمكن ال
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "تتطلب هذه الميزة وجود موفر ذكاء اصطناعي متصل. يرجى إعداد واحد في الإعدادات."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "لا تسمح هذه النسخة حاليًا بتحرير CSS الدلالي."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "هذا اسم مناسب لعناوين URL لسيرتك الذاتية."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: az\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Azerbaijani\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Müraciət edildi"
msgid "Applied on"
msgstr "Tətbiq edildiyi tarix"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Tətbiq olunan Qaydalar"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Xəbərdarlıqlarla tətbiq olunur"
@@ -1010,6 +1006,11 @@ msgstr "Ehtiyat Kodlarını Kopyala"
msgid "Copy JSON"
msgstr "JSON-u kopyalayın"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Sirri kopyalayın"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Stil cədvəlini kopyalayın"
@@ -2946,10 +2947,6 @@ msgstr "Hələ ki, yadda saxlanılan versiya yoxdur."
msgid "No source data yet."
msgstr "Hələlik mənbə məlumatları yoxdur."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Hələ ki, stil qaydaları yoxdur."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Test edilmiş provayder yoxdur"
@@ -2968,7 +2965,7 @@ msgstr "Qoşulmamışdır"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Nə yazacağınızdan əmin deyilsiniz?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktiv Rezume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Xüsusi Stillərin Tətbiqi təlimatını oxuyun."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Sıfırla"
msgid "Reset Password"
msgstr "Parolu Sıfırla"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Stilini Sıfırla"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Tətbiq olunmuş stil cədvəlinə sıfırlayın"
@@ -3687,14 +3680,6 @@ msgstr "Rumın"
msgid "Rotation"
msgstr "Döndürmə"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "qayda"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "qaydalar"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "İlk təhlilinizi işə salın, skor kartı, güclü tərəflər və prioritetləşdirilmiş təkliflər əldə edin."
@@ -3876,10 +3861,6 @@ msgstr "Docker ilə Özün‑host et"
msgid "Semantic CSS stylesheet"
msgstr "Semantik CSS stil cədvəli"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantik üslublar aktiv olaraq qalır"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Mesaj göndərin"
@@ -4482,10 +4463,6 @@ msgstr "Bu qeyd həmişəlik silinəcək. Bunu geri qaytarmaq mümkün deyil."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Bu funksiya qoşulmuş süni intellekt provayderi tələb edir. Zəhmət olmasa, parametrlərdə birini quraşdırın."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Bu nümunə hazırda semantik CSS redaktəsinə icazə vermir."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Bu, özgeçmişiniz üçün URL‑ə uyğun bir addır."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: bg\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Bulgarian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Кандидатствано"
msgid "Applied on"
msgstr "Приложено на"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Приложени правила"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Прилага се с предупреждения"
@@ -1010,6 +1006,11 @@ msgstr "Копиране на резервни кодове"
msgid "Copy JSON"
msgstr "Копиране на JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Копиране на тайна"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Копиране на стилов лист"
@@ -2946,10 +2947,6 @@ msgstr "Все още няма запазени версии."
msgid "No source data yet."
msgstr "Все още няма данни за източника."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Все още няма стилови правила."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Няма тестван доставчик"
@@ -2968,7 +2965,7 @@ msgstr "Няма връзка"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Не сте сигурни какво да напишете?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Прочетете ръководството за прилагане на персонализирани стилове."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Нулиране"
msgid "Reset Password"
msgstr "Нулиране на паролата"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Нулиране на стила"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Възстановяване към приложения стилов лист"
@@ -3687,14 +3680,6 @@ msgstr "Румънски"
msgid "Rotation"
msgstr "Завъртане"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "правило"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "правила"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Извършете първия си анализ, за да получите карта с резултати, силни страни и предложения по приоритети."
@@ -3876,10 +3861,6 @@ msgstr "Самостоятелно хостване с Docker"
msgid "Semantic CSS stylesheet"
msgstr "Семантичен CSS стилов лист"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Семантичните стилове остават активни"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Изпрати съобщение"
@@ -4482,10 +4463,6 @@ msgstr "Този запис ще бъде изтрит за постоянно.
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Тази функция изисква свързан доставчик на изкуствен интелект. Моля, настройте такъв в настройките."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Този екземпляр в момента не позволява редактиране на семантичен CSS."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Това е име, подходящо за URL, за вашата автобиография."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: bn\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Bengali\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "আবেদন করা হয়েছে"
msgid "Applied on"
msgstr "প্রয়োগ করা হয়েছে"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "প্রয়োগকৃত নিয়মাবলী"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "সতর্কতাসহ প্রয়োগ করা হয়েছে"
@@ -1010,6 +1006,11 @@ msgstr "ব্যাকআপ কোড কপি করুন"
msgid "Copy JSON"
msgstr "JSON কপি করুন"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "গোপন অনুলিপি"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "স্টাইলশিট কপি করুন"
@@ -2946,10 +2947,6 @@ msgstr "এখনো কোনো সংরক্ষিত সংস্করণ
msgid "No source data yet."
msgstr "এখনো কোনো উৎস ডেটা নেই।"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "এখনো কোনো স্টাইল নিয়ম ঠিক করা হয়নি।"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "কোন পরীক্ষিত সরবরাহকারী নেই"
@@ -2968,7 +2965,7 @@ msgstr "সংযুক্ত নয়"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "কী লিখবেন বুঝতে পারছেন না?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "প্রতিক্রিয়াশীল রিজ্যুম v4 (
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "কাস্টম স্টাইল প্রয়োগ করার নির্দেশিকাটি পড়ুন।"
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "রিসেট"
msgid "Reset Password"
msgstr "পাসওয়ার্ড রিসেট করুন"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "স্টাইল রিসেট করুন"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "প্রয়োগকৃত স্টাইলশীটে রিসেট করুন"
@@ -3687,14 +3680,6 @@ msgstr "রোমানিয়ান"
msgid "Rotation"
msgstr "রোটেশন"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "নিয়ম"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "নিয়ম"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "আপনার প্রথম বিশ্লেষণ চালান একটি স্কোরকার্ড, শক্তি এবং অগ্রাধিকারপ্রাপ্ত পরামর্শ পেতে।"
@@ -3876,10 +3861,6 @@ msgstr "ডকার দিয়ে নিজে হোস্ট করুন"
msgid "Semantic CSS stylesheet"
msgstr "সিমান্টিক সিএসএস স্টাইলশিট"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "শব্দার্থিক শৈলী সক্রিয় থাকে"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "বার্তা পাঠান"
@@ -4482,10 +4463,6 @@ msgstr "এই এন্ট্রি স্থায়ীভাবে মুছ
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "এই ফিচারটি ব্যবহারের জন্য একটি সংযুক্ত এআই প্রোভাইডার প্রয়োজন। অনুগ্রহ করে সেটিংস থেকে একটি সেট আপ করুন।"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "এই ইনস্ট্যান্সটিতে বর্তমানে সিমান্টিক সিএসএস সম্পাদনার অনুমতি নেই।"
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "এটি আপনার জীবনবৃত্তান্তের জন্য একটি URL‑বান্ধব নাম।"
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: ca\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Catalan\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Sol·licitada"
msgid "Applied on"
msgstr "Aplicat a"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Normes aplicades"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Aplicat amb avisos"
@@ -1010,6 +1006,11 @@ msgstr "Copia els codis de reserva"
msgid "Copy JSON"
msgstr "Copia JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Copia el secret"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Copiar full d'estils"
@@ -2946,10 +2947,6 @@ msgstr "Encara no hi ha versions desades."
msgid "No source data yet."
msgstr "Encara no hi ha dades d'origen."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Encara no hi ha regles d'estil."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Cap proveïdor provat"
@@ -2968,7 +2965,7 @@ msgstr "No connectat"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "No saps què escriure?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Llegiu la guia Aplicació d'estils personalitzats."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Restableix"
msgid "Reset Password"
msgstr "Restableix la contrasenya"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Restableix l'estil"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Restableix al full d'estils aplicat"
@@ -3687,14 +3680,6 @@ msgstr "Romanès"
msgid "Rotation"
msgstr "Rotació"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "regla"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "regles"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Executa la teva primera anàlisi per obtenir un quadre de comandament, els punts forts i suggeriments prioritzats."
@@ -3876,10 +3861,6 @@ msgstr "Allotjament propi amb Docker"
msgid "Semantic CSS stylesheet"
msgstr "Full d'estil CSS semàntic"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Els estils semàntics romanen actius"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Enviar missatge"
@@ -4482,10 +4463,6 @@ msgstr "Aquesta entrada se suprimirà permanentment. Això no es pot desfer."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Aquesta funció requereix un proveïdor d'IA connectat. Configura'n un a la configuració."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Aquesta instància actualment no permet l'edició semàntica de CSS."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Aquest és un nom d’URL fàcil d’utilitzar per al currículum."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: cs\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Czech\n"
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
@@ -494,10 +494,6 @@ msgstr "Podáno"
msgid "Applied on"
msgstr "Aplikováno na"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Použitá pravidla"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Použito s varováním"
@@ -1010,6 +1006,11 @@ msgstr "Zkopírovat záložní kódy"
msgid "Copy JSON"
msgstr "Kopírovat JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopírovat tajný kód"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopírovat stylový list"
@@ -2946,10 +2947,6 @@ msgstr "Zatím žádné uložené verze."
msgid "No source data yet."
msgstr "Zatím žádné zdrojové údaje."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Zatím žádná stylistická pravidla."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Žádný ověřený poskytovatel"
@@ -2968,7 +2965,7 @@ msgstr "Nepřipojeno"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Nejste si jisti, co napsat?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktivní životopis v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Přečtěte si průvodce Použití vlastních stylů."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Resetovat"
msgid "Reset Password"
msgstr "Obnovit heslo"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Obnovit styl"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Obnovit použitý stylový list"
@@ -3687,14 +3680,6 @@ msgstr "Rumunština"
msgid "Rotation"
msgstr "Otočení"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "pravidlo"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "pravidla"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Proveďte první analýzu a získejte hodnotící tabulku, silné stránky a návrhy priorit."
@@ -3876,10 +3861,6 @@ msgstr "Vlastní hosting pomocí Dockeru"
msgid "Semantic CSS stylesheet"
msgstr "Sémantický CSS stylový list"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Sémantické styly zůstávají aktivní"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Odeslat zprávu"
@@ -4482,10 +4463,6 @@ msgstr "Tento záznam bude trvale odstraněn. Tuto akci nelze vrátit zpět."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Tato funkce vyžaduje připojeného poskytovatele umělé inteligence. Nastavte si ho prosím v nastavení."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Tato instance aktuálně neumožňuje úpravy sémantického CSS."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Toto je název vašeho životopisu vhodný pro URL adresu."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: da\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Danish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Ansøgt"
msgid "Applied on"
msgstr "Anvendt den"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Anvendte regler"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Anvendt med advarsler"
@@ -1010,6 +1006,11 @@ msgstr "Kopiér backup-koder"
msgid "Copy JSON"
msgstr "Kopiér JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopiér hemmelighed"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopiér stylesheet"
@@ -2946,10 +2947,6 @@ msgstr "Ingen gemte versioner endnu."
msgid "No source data yet."
msgstr "Ingen kildedata endnu."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Ingen stilregler endnu."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Ingen testet udbyder"
@@ -2968,7 +2965,7 @@ msgstr "Ikke forbundet"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Ikke sikker på, hvad du skal skrive?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktivt CV v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Læs vejledningen til anvendelse af brugerdefinerede stilarter."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Nulstil"
msgid "Reset Password"
msgstr "Nulstil adgangskode"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Nulstil stil"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Nulstil til anvendt stylesheet"
@@ -3687,14 +3680,6 @@ msgstr "Rumænsk"
msgid "Rotation"
msgstr "Rotation"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "herske"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "regler"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Kør din første analyse for at få et scorekort, styrker og prioriterede forslag."
@@ -3876,10 +3861,6 @@ msgstr "Selvhostning med Docker"
msgid "Semantic CSS stylesheet"
msgstr "Semantisk CSS-stilark"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantiske stilarter forbliver aktive"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Send besked"
@@ -4482,10 +4463,6 @@ msgstr "Denne post slettes permanent. Dette kan ikke fortrydes."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Denne funktion kræver en tilsluttet AI-udbyder. Opsæt venligst en i indstillingerne."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Denne instans tillader i øjeblikket ikke semantisk CSS-redigering."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Dette er et URL-venligt navn til dit CV."
+15 -38
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: de\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-13 07:27\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -401,7 +401,7 @@ msgstr "Und viele weitere ..."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "Anthropic Claude"
msgstr "Anthropischer Claude"
msgstr "Anthropic Claude"
#: src/routes/dashboard/applications/index.tsx
msgid "Any tag"
@@ -494,10 +494,6 @@ msgstr "Beworben"
msgid "Applied on"
msgstr "Beworben am"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Angewandte Regeln"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Mit Warnungen angewendet"
@@ -768,7 +764,7 @@ msgstr "Zentriert"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "Cerebras"
msgstr "Großhirn"
msgstr "Cerebras"
#: src/dialogs/resume/sections/custom.tsx
#: src/libs/resume/section-title.ts
@@ -876,7 +872,7 @@ msgstr "Schließen Sie den KI-Assistenten"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "Cohere"
msgstr "Zusammenhängen"
msgstr "Cohere"
#: src/routes/builder/$resumeId/-sidebar/left/sections/custom.tsx
#: src/routes/builder/$resumeId/-sidebar/left/shared/section-menu.tsx
@@ -1010,6 +1006,11 @@ msgstr "Backup-Codes kopieren"
msgid "Copy JSON"
msgstr "JSON kopieren"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Geheimnis kopieren"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Stylesheet kopieren"
@@ -1449,7 +1450,7 @@ msgstr "Discord"
#: src/components/ui/donation-toast.tsx
#: src/features/applications/components/application-ai-copilot.tsx
msgid "Dismiss"
msgstr "Zurückweisen"
msgstr "Ausblenden"
#: src/routes/_home/-sections/footer.tsx
#: src/routes/builder/$resumeId/-sidebar/right/sections/information.tsx
@@ -2142,7 +2143,7 @@ msgstr "Google"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "Google Gemini"
msgstr "Google Zwillinge"
msgstr "Google Gemini"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "gpt-4.1"
@@ -2946,10 +2947,6 @@ msgstr "Bisher keine gespeicherten Versionen."
msgid "No source data yet."
msgstr "Noch keine Quelldaten."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Noch keine Stilregeln."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Kein geprüfter Anbieter"
@@ -2968,7 +2965,7 @@ msgstr "Nicht verbunden"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Sie wissen nicht, was Sie schreiben sollen?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3207,7 +3204,7 @@ msgstr "Zeitraum"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "Perplexity"
msgstr "Verwirrung"
msgstr "Perplexity"
#: src/libs/locale.ts
msgid "Persian"
@@ -3437,7 +3434,7 @@ msgstr "Reaktiver Lebenslauf v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Lesen Sie den Leitfaden zum Anwenden benutzerdefinierter Stile."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Zurücksetzen"
msgid "Reset Password"
msgstr "Passwort zurücksetzen"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Stil zurücksetzen"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Auf angewendetes Stylesheet zurücksetzen"
@@ -3687,14 +3680,6 @@ msgstr "Rumänisch"
msgid "Rotation"
msgstr "Drehung"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "Regel"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "Regeln"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Führen Sie Ihre erste Analyse durch, um eine Scorecard, Stärken und priorisierte Vorschläge zu erhalten."
@@ -3716,7 +3701,7 @@ msgstr "Gehaltsspanne"
#: src/features/applications/components/application-detail-sheet.tsx
#: src/features/settings/authentication/components/passkeys.tsx
msgid "Save"
msgstr "Speichern Sie"
msgstr "Speichern"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "Save & Test Provider"
@@ -3876,10 +3861,6 @@ msgstr "Selbst hosten mit Docker"
msgid "Semantic CSS stylesheet"
msgstr "Semantisches CSS-Stylesheet"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantische Stile bleiben aktiv"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Nachricht senden"
@@ -4482,10 +4463,6 @@ msgstr "Dieser Eintrag wird dauerhaft gelöscht. Das kann nicht rückgängig gem
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Diese Funktion erfordert einen verbundenen KI-Anbieter. Bitte richten Sie einen in den Einstellungen ein."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Diese Instanz erlaubt derzeit keine Bearbeitung von semantischem CSS."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Dies ist ein URL-freundlicher Name für Ihren Lebenslauf."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: el\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Greek\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Υποβλήθηκε"
msgid "Applied on"
msgstr "Ημερομηνία αίτησης"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Εφαρμοσμένοι κανόνες"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Εφαρμόζεται με προειδοποιήσεις"
@@ -1010,6 +1006,11 @@ msgstr "Αντιγραφή εφεδρικών κωδικών"
msgid "Copy JSON"
msgstr "Αντιγραφή JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Μυστικό αντιγραφής"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Αντιγραφή φύλλου στυλ"
@@ -2946,10 +2947,6 @@ msgstr "Δεν υπάρχουν ακόμη αποθηκευμένες εκδόσ
msgid "No source data yet."
msgstr "Δεν υπάρχουν ακόμη δεδομένα πηγής."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Δεν υπάρχουν ακόμα κανόνες στυλ."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Δεν υπάρχει δοκιμασμένος πάροχος"
@@ -2968,7 +2965,7 @@ msgstr "Δεν είναι συνδεδεμένο"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Δεν είστε σίγουροι τι να γράψετε;"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Αντιδραστικό βιογραφικό σημείωμα v4 (JSON)
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Διαβάστε τον οδηγό Εφαρμογή προσαρμοσμένων στυλ."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Επαναφορά"
msgid "Reset Password"
msgstr "Επαναφορά κωδικού πρόσβασης"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Επαναφορά στυλ"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Επαναφορά στο εφαρμοσμένο φύλλο στυλ"
@@ -3687,14 +3680,6 @@ msgstr "Ρουμανικά"
msgid "Rotation"
msgstr "Περιστροφή"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "κανόνας"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "κανόνες"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Εκτελέστε την πρώτη σας ανάλυση για να λάβετε έναν πίνακα βαθμολογίας, τα δυνατά σημεία και τις προτάσεις με προτεραιότητες."
@@ -3876,10 +3861,6 @@ msgstr "Αυτο-φιλοξενία με Docker"
msgid "Semantic CSS stylesheet"
msgstr "Φύλλο στυλ σημασιολογικού CSS"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Τα σημασιολογικά στυλ παραμένουν ενεργά"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Αποστολή μηνύματος"
@@ -4482,10 +4463,6 @@ msgstr "Αυτή η καταχώριση θα διαγραφεί οριστικ
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Αυτή η λειτουργία απαιτεί έναν συνδεδεμένο πάροχο τεχνητής νοημοσύνης. Ορίστε έναν στις ρυθμίσεις."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Αυτή η παρουσία δεν επιτρέπει προς το παρόν την επεξεργασία σημασιολογικού CSS."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Αυτό είναι ένα φιλικό προς το URL όνομα για το βιογραφικό σας σημείωμα."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: en_GB\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: English, United Kingdom\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Applied"
msgid "Applied on"
msgstr "Applied on"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Applied Rules"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Applied with warnings"
@@ -1010,6 +1006,11 @@ msgstr "Copy Backup Codes"
msgid "Copy JSON"
msgstr "Copy JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Copy secret"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Copy stylesheet"
@@ -2946,10 +2947,6 @@ msgstr "No saved versions yet."
msgid "No source data yet."
msgstr "No source data yet."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "No style rules yet."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "No tested provider"
@@ -2968,7 +2965,7 @@ msgstr "Not connected"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Not sure what to write?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Read the Applying Custom Styles guide."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Reset"
msgid "Reset Password"
msgstr "Reset Password"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Reset Style"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Reset to applied stylesheet"
@@ -3687,14 +3680,6 @@ msgstr "Romanian"
msgid "Rotation"
msgstr "Rotation"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "rule"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "rules"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
@@ -3876,10 +3861,6 @@ msgstr "Self-Host with Docker"
msgid "Semantic CSS stylesheet"
msgstr "Semantic CSS stylesheet"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantic styles remain active"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Send message"
@@ -4482,10 +4463,6 @@ msgstr "This entry will be permanently deleted. This can't be undone."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "This feature requires a connected AI provider. Please set one up in the settings."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "This instance does not currently allow Semantic CSS editing."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "This is a URL-friendly name for your resume."
+5 -28
View File
@@ -489,10 +489,6 @@ msgstr "Applied"
msgid "Applied on"
msgstr "Applied on"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Applied Rules"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Applied with warnings"
@@ -1005,6 +1001,11 @@ msgstr "Copy Backup Codes"
msgid "Copy JSON"
msgstr "Copy JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Copy secret"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Copy stylesheet"
@@ -2941,10 +2942,6 @@ msgstr "No saved versions yet."
msgid "No source data yet."
msgstr "No source data yet."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "No style rules yet."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "No tested provider"
@@ -3563,10 +3560,6 @@ msgstr "Reset"
msgid "Reset Password"
msgstr "Reset Password"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Reset Style"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Reset to applied stylesheet"
@@ -3682,14 +3675,6 @@ msgstr "Romanian"
msgid "Rotation"
msgstr "Rotation"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "rule"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "rules"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
@@ -3871,10 +3856,6 @@ msgstr "Self-Host with Docker"
msgid "Semantic CSS stylesheet"
msgstr "Semantic CSS stylesheet"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantic styles remain active"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Send message"
@@ -4477,10 +4458,6 @@ msgstr "This entry will be permanently deleted. This can't be undone."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "This feature requires a connected AI provider. Please set one up in the settings."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "This instance does not currently allow Semantic CSS editing."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "This is a URL-friendly name for your resume."
+7 -30
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: es\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Enviada"
msgid "Applied on"
msgstr "Postulado el"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Reglas aplicadas"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Aplicado con advertencias"
@@ -1010,6 +1006,11 @@ msgstr "Copiar códigos de respaldo"
msgid "Copy JSON"
msgstr "Copiar JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Copia secreta"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Copiar hoja de estilo"
@@ -2946,10 +2947,6 @@ msgstr "Aún no hay versiones guardadas."
msgid "No source data yet."
msgstr "Aún no hay datos de fuentes."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Aún no hay reglas de estilo."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "No hay ningún proveedor probado"
@@ -3437,7 +3434,7 @@ msgstr "Currículum reactivo v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Lea la guía sobre cómo aplicar estilos personalizados."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Restablecer"
msgid "Reset Password"
msgstr "Restablecer contraseña"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Restablecer estilo"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Restablecer a la hoja de estilos aplicada"
@@ -3687,14 +3680,6 @@ msgstr "Rumano"
msgid "Rotation"
msgstr "Rotación"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "regla"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "normas"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Realice su primer análisis para obtener un cuadro de mando, los puntos fuertes y las sugerencias priorizadas."
@@ -3876,10 +3861,6 @@ msgstr "Auto alojamiento con Docker"
msgid "Semantic CSS stylesheet"
msgstr "Hoja de estilo CSS semántica"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Los estilos semánticos siguen activos"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Enviar mensaje"
@@ -4482,10 +4463,6 @@ msgstr "Esta entrada se eliminará permanentemente. Esta acción no se puede des
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Esta función requiere un proveedor de IA conectado. Por favor, configure uno en los ajustes."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Actualmente, esta instancia no permite la edición de CSS semántico."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Este es un nombre compatible con URL para tu currículum."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: fa\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Persian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "ارسال‌شده"
msgid "Applied on"
msgstr "تاریخ درخواست"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "قوانین کاربردی"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "با هشدارها اعمال می‌شود"
@@ -1010,6 +1006,11 @@ msgstr "کپی کردن کدهای پشتیبان"
msgid "Copy JSON"
msgstr "کپی کردن JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "کپی کردن راز"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "کپی کردن شیوه‌نامه"
@@ -2946,10 +2947,6 @@ msgstr "هنوز نسخه‌های ذخیره‌شده‌ای وجود ندار
msgid "No source data yet."
msgstr "هنوز دادهٔ منبعی نیست."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "هنوز هیچ قانون سبکی وجود ندارد."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "هیچ ارائه دهنده آزمایش شده ای وجود ندارد"
@@ -2968,7 +2965,7 @@ msgstr "متصل نیست"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "مطمئن نیستید چه بنویسید؟"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "رزومهٔ واکنشی نسخهٔ ۴ (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "راهنمای اعمال سبک‌های سفارشی را مطالعه کنید."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "ریست"
msgid "Reset Password"
msgstr "تنظیم مجدد گذرواژه"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "تنظیم مجدد سبک"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "تنظیم مجدد به شیوه‌نامه اعمال شده"
@@ -3687,14 +3680,6 @@ msgstr "رومانیایی"
msgid "Rotation"
msgstr "چرخش"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "قاعده"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "قوانین"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "اولین تحلیل خود را اجرا کنید تا کارت امتیاز، نقاط قوت و پیشنهادهای اولویت‌بندی‌شده را دریافت کنید."
@@ -3876,10 +3861,6 @@ msgstr "میزبانی خودکار با Docker"
msgid "Semantic CSS stylesheet"
msgstr "شیوه‌نامه CSS معنایی"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "سبک‌های معنایی فعال می‌مانند"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "ارسال پیام"
@@ -4482,10 +4463,6 @@ msgstr "این ورودی برای همیشه حذف خواهد شد. این ک
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "این ویژگی به یک ارائه‌دهنده هوش مصنوعی متصل نیاز دارد. لطفاً یکی را در تنظیمات تنظیم کنید."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "این نمونه در حال حاضر امکان ویرایش CSS معنایی را فراهم نمی‌کند."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "این یک نام مناسب برای URLِ رزومه شما است."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: fi\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Finnish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Haettu"
msgid "Applied on"
msgstr "Haettu"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Sovelletut säännöt"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Käytetty varoituksilla"
@@ -1010,6 +1006,11 @@ msgstr "Kopioi varmuuskoodit"
msgid "Copy JSON"
msgstr "Kopioi JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopioi salaisuus"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopioi tyylitiedosto"
@@ -2946,10 +2947,6 @@ msgstr "Ei vielä tallennettuja versioita."
msgid "No source data yet."
msgstr "Lähdetietoja ei vielä ole."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Ei vielä tyylisääntöjä."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Ei testattua tarjoajaa"
@@ -2968,7 +2965,7 @@ msgstr "Ei yhdistetty"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Etkö ole varma, mitä kirjoittaa?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktiivinen ansioluettelo v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Lue opas Mukautettujen tyylien käyttäminen."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Palauta"
msgid "Reset Password"
msgstr "Palauta salasana"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Palauta tyyli"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Palauta käytettyyn tyylitiedostoon"
@@ -3687,14 +3680,6 @@ msgstr "romania"
msgid "Rotation"
msgstr "Kierrätys"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "sääntö"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "säännöt"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Suorita ensimmäinen analyysi, jotta saat tuloskortin, vahvuudet ja priorisoidut ehdotukset."
@@ -3876,10 +3861,6 @@ msgstr "Itse-isännöinti Dockerilla"
msgid "Semantic CSS stylesheet"
msgstr "Semanttinen CSS-tyylitiedosto"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semanttiset tyylit pysyvät aktiivisina"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Lähetä viesti"
@@ -4482,10 +4463,6 @@ msgstr "Tämä merkintä poistetaan pysyvästi. Tätä ei voi kumota."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Tämä ominaisuus vaatii yhdistetyn tekoälypalveluntarjoajan. Määritä sellainen asetuksissa."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Tämä instanssi ei tällä hetkellä salli semanttisen CSS:n muokkausta."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Tämä on URL-ystävällinen nimi ansioluettelollesi."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: fr\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
@@ -494,10 +494,6 @@ msgstr "Candidature envoyée"
msgid "Applied on"
msgstr "Postulé le"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Règles appliquées"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Appliqué avec avertissements"
@@ -1010,6 +1006,11 @@ msgstr "Copier les codes de secours"
msgid "Copy JSON"
msgstr "Copier le JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Copier le secret"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Copier la feuille de style"
@@ -2946,10 +2947,6 @@ msgstr "Aucune version enregistrée pour le moment."
msgid "No source data yet."
msgstr "Aucune donnée de source pour le moment."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Pas encore de règles de style."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Fournisseur non testé"
@@ -2968,7 +2965,7 @@ msgstr "Non connecté"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Vous ne savez pas quoi écrire ?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Consultez le guide « Application des styles personnalisés »."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Réinitialiser"
msgid "Reset Password"
msgstr "Réinitialiser le mot de passe"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Réinitialiser le style"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Réinitialiser la feuille de style appliquée"
@@ -3687,14 +3680,6 @@ msgstr "Roumain"
msgid "Rotation"
msgstr "Rotation"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "règle"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "règles"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Effectuez votre première analyse pour obtenir un tableau de bord, des points forts et des suggestions classées par ordre de priorité."
@@ -3876,10 +3861,6 @@ msgstr "Auto-hébergement avec Docker"
msgid "Semantic CSS stylesheet"
msgstr "Feuille de style CSS sémantique"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Les styles sémantiques restent actifs"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Envoyer un message"
@@ -4482,10 +4463,6 @@ msgstr "Cette entrée sera supprimée définitivement. Cette action est irréver
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Cette fonctionnalité nécessite un fournisseur d'IA connecté. Veuillez en configurer un dans les paramètres."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Cette instance ne permet actuellement pas l'édition CSS sémantique."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Il s'agit d'un nom convivial pour l'URL de votre CV."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: he\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Hebrew\n"
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n"
@@ -494,10 +494,6 @@ msgstr "הוגש"
msgid "Applied on"
msgstr "הוגש בתאריך"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "כללים יישומיים"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "יושם עם אזהרות"
@@ -1010,6 +1006,11 @@ msgstr "העתקת קודי גיבוי"
msgid "Copy JSON"
msgstr "העתקת JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "העתק סוד"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "העתקת גיליון סגנונות"
@@ -2946,10 +2947,6 @@ msgstr "עדיין אין גרסאות שנשמרו."
msgid "No source data yet."
msgstr "אין עדיין נתוני מקור."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "עדיין אין חוקי סגנון."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "אין ספק שנבדק"
@@ -2968,7 +2965,7 @@ msgstr "לא מחובר"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "לא בטוחים מה לכתוב?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "קורות חיים תגובתיים גרסה 4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "קרא את המדריך להחלת סגנונות מותאמים אישית."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "איפוס"
msgid "Reset Password"
msgstr "איפוס סיסמה"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "איפוס סגנון"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "איפוס לגיליון הסגנונות שהוחל"
@@ -3687,14 +3680,6 @@ msgstr "רומנית"
msgid "Rotation"
msgstr "סיבוב"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "כְּלָל"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "כללים"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "בצע את הניתוח הראשון שלך כדי לקבל דוח ביצועים, נקודות חוזק והצעות מסודרות לפי סדר עדיפויות."
@@ -3876,10 +3861,6 @@ msgstr "אירוח עצמי עם Docker"
msgid "Semantic CSS stylesheet"
msgstr "גיליון סגנונות CSS סמנטי"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "סגנונות סמנטיים נשארים פעילים"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "שלח הודעה"
@@ -4482,10 +4463,6 @@ msgstr "רשומה זו תימחק לצמיתות. לא ניתן לבטל פעו
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "תכונה זו דורשת ספק בינה מלאכותית מחובר. אנא הגדר ספק כזה בהגדרות."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "מופע זה אינו מאפשר כעת עריכת CSS סמנטי."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "זהו שם ידידותי לכתובת URL עבור קורות החיים שלך."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: hi\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Hindi\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "आवेदन किया"
msgid "Applied on"
msgstr "आवेदन की तारीख"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "लागू नियम"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "चेतावनी सहित लागू"
@@ -1010,6 +1006,11 @@ msgstr "बैकअप कोड कॉपी करें"
msgid "Copy JSON"
msgstr "JSON कॉपी करें"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "गुप्त प्रतिलिपि"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "स्टाइलशीट कॉपी करें"
@@ -2946,10 +2947,6 @@ msgstr "अभी तक कोई सहेजे गए संस्करण
msgid "No source data yet."
msgstr "अभी कोई स्रोत डेटा नहीं।"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "अभी तक कोई शैली संबंधी नियम नहीं हैं।"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "कोई परीक्षित प्रदाता नहीं"
@@ -2968,7 +2965,7 @@ msgstr "जुड़े नहीं हैं"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "मैं आश्वस्त नहीं हूं कि क्या लिखना है?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "प्रतिक्रियाशील रिज़्यूमे v
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "कस्टम स्टाइल लागू करने संबंधी गाइड पढ़ें।"
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "रीसेट"
msgid "Reset Password"
msgstr "पासवर्ड रीसेट करें"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "शैली रीसेट करें"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "लागू स्टाइलशीट पर रीसेट करें"
@@ -3687,14 +3680,6 @@ msgstr "रोमानियाई"
msgid "Rotation"
msgstr "रोटेशन"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "नियम"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "नियम"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "अपना पहला विश्लेषण चलाएँ ताकि आपको एक स्कोरकार्ड, ताकतें और प्राथमिकता-आधारित सुझाव मिल सकें।"
@@ -3876,10 +3861,6 @@ msgstr "डॉकर के साथ स्व‑मेज़बान"
msgid "Semantic CSS stylesheet"
msgstr "सिमेंटिक सीएसएस स्टाइलशीट"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "सिमेंटिक शैलियाँ सक्रिय रहती हैं"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "मेसेज भेजें"
@@ -4482,10 +4463,6 @@ msgstr "यह प्रविष्टि स्थायी रूप से
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "इस फ़ीचर के लिए एक कनेक्टेड एआई प्रदाता की आवश्यकता है। कृपया सेटिंग्स में जाकर इसे सेट अप करें।"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "यह इंस्टेंस फिलहाल सिमेंटिक सीएसएस संपादन की अनुमति नहीं देता है।"
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "यह आपके रेज़्यूमे के लिए एक URL‑फ्रेंडली नाम है।"
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: hu\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Hungarian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Jelentkezve"
msgid "Applied on"
msgstr "Jelentkezés dátuma"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Alkalmazott szabályok"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Figyelmeztetésekkel alkalmazva"
@@ -1010,6 +1006,11 @@ msgstr "Biztonsági kódok másolása"
msgid "Copy JSON"
msgstr "JSON másolása"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Titkos kód másolása"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Stíluslap másolása"
@@ -2946,10 +2947,6 @@ msgstr "Még nincsenek mentett verziók."
msgid "No source data yet."
msgstr "Még nincs forrásadat."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Stílusra még nincsenek szabályok."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Nincs tesztelt szolgáltató"
@@ -2968,7 +2965,7 @@ msgstr "Nincs csatlakoztatva"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Nem tudod, mit írj?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktív önéletrajz v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Olvasd el az Egyéni stílusok alkalmazása útmutatót."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Visszaállítás"
msgid "Reset Password"
msgstr "Jelszó visszaállítása"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Stílus visszaállítása"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Visszaállítás az alkalmazott stíluslapra"
@@ -3687,14 +3680,6 @@ msgstr "Román"
msgid "Rotation"
msgstr "Forgatás"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "szabály"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "szabályok"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Futtassa le az első elemzést, hogy kapjon egy értékelőlapot, erősségeket és rangsorolt javaslatokat."
@@ -3876,10 +3861,6 @@ msgstr "Önálló hosztolás Dockerrel"
msgid "Semantic CSS stylesheet"
msgstr "Szemantikus CSS stíluslap"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "A szemantikai stílusok továbbra is aktívak"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Üzenet küldése"
@@ -4482,10 +4463,6 @@ msgstr "Ez a bejegyzés véglegesen törlődik. Ezt nem lehet visszavonni."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Ehhez a funkcióhoz csatlakoztatott MI-szolgáltató szükséges. Kérjük, állítson be egyet a beállításokban."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Ez a példány jelenleg nem engedélyezi a szemantikus CSS szerkesztést."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Ez az önéletrajzod URL‑barát neve."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: id\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Indonesian\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -494,10 +494,6 @@ msgstr "Dilamar"
msgid "Applied on"
msgstr "Dilamar pada"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Aturan yang Diterapkan"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Diterapkan dengan peringatan"
@@ -1010,6 +1006,11 @@ msgstr "Salin Kode Cadangan"
msgid "Copy JSON"
msgstr "Salin JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Salin rahasia"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Salin stylesheet"
@@ -2946,10 +2947,6 @@ msgstr "Belum ada versi yang tersimpan."
msgid "No source data yet."
msgstr "Belum ada data sumber."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Belum ada aturan gaya."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Tidak ada penyedia yang teruji"
@@ -2968,7 +2965,7 @@ msgstr "Tidak terhubung"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Tidak yakin harus menulis apa?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Lanjutkan Reaktif v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Bacalah panduan Menerapkan Gaya Kustom."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Atur Ulang"
msgid "Reset Password"
msgstr "Atur Ulang Kata Sandi"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Atur Ulang Gaya"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Atur ulang ke stylesheet yang diterapkan"
@@ -3687,14 +3680,6 @@ msgstr "Rumania"
msgid "Rotation"
msgstr "Rotasi"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "aturan"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "aturan"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Jalankan analisis pertama Anda untuk mendapatkan kartu skor, kekuatan, dan saran yang diprioritaskan."
@@ -3876,10 +3861,6 @@ msgstr "Self-Host dengan Docker"
msgid "Semantic CSS stylesheet"
msgstr "Lembar gaya CSS semantik"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Gaya semantik tetap aktif."
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Kirim pesan"
@@ -4482,10 +4463,6 @@ msgstr "Entri ini akan dihapus secara permanen. Ini tidak dapat dibatalkan."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Fitur ini memerlukan penyedia AI yang terhubung. Silakan atur di pengaturan."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Instansi ini saat ini tidak mengizinkan pengeditan CSS Semantik."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Ini adalah nama yang ramah URL untuk resume Anda."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: it\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Italian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Candidatura inviata"
msgid "Applied on"
msgstr "Candidatura inviata il"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Regole applicate"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Applicato con avvertenze"
@@ -1010,6 +1006,11 @@ msgstr "Copia codici di backup"
msgid "Copy JSON"
msgstr "Copia JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Copia il segreto"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Copia foglio di stile"
@@ -2946,10 +2947,6 @@ msgstr "Nessuna versione salvata al momento."
msgid "No source data yet."
msgstr "Ancora nessun dato sorgente."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Non sono ancora state definite delle regole di stile."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Nessun fornitore segnalato"
@@ -2968,7 +2965,7 @@ msgstr "Non connesso"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Non sai cosa scrivere?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Ripresa reattiva v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Leggi la guida \"Applicazione di stili personalizzati\"."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Ripristina"
msgid "Reset Password"
msgstr "Reimposta password"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Ripristina stile"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Ripristina il foglio di stile applicato"
@@ -3687,14 +3680,6 @@ msgstr "Rumeno"
msgid "Rotation"
msgstr "Rotazione"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "regola"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "regole"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Esegua la prima analisi per ottenere una scorecard, i punti di forza e i suggerimenti prioritari."
@@ -3876,10 +3861,6 @@ msgstr "Self-host con Docker"
msgid "Semantic CSS stylesheet"
msgstr "Foglio di stile CSS semantico"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Gli stili semantici rimangono attivi"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Invia messaggio"
@@ -4482,10 +4463,6 @@ msgstr "Questa voce verrà eliminata definitivamente. L'azione non può essere a
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Questa funzionalità richiede un provider di intelligenza artificiale connesso. Configuralo nelle impostazioni."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Questa istanza al momento non consente la modifica del CSS semantico."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Questo è un nome adatto agli URL per il tuo curriculum."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: ja\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Japanese\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -494,10 +494,6 @@ msgstr "応募済み"
msgid "Applied on"
msgstr "応募日"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "適用中のルール"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "警告付きで適用"
@@ -1010,6 +1006,11 @@ msgstr "バックアップコードをコピー"
msgid "Copy JSON"
msgstr "JSONをコピー"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "コピーシークレット"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "スタイルシートをコピー"
@@ -2946,10 +2947,6 @@ msgstr "まだ保存されたバージョンはありません。"
msgid "No source data yet."
msgstr "ソースデータはまだありません。"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "まだスタイルに関するルールはありません。"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "テスト済みのプロバイダーはありません"
@@ -2968,7 +2965,7 @@ msgstr "接続されていません"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "何を書けばいいか分からない?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "カスタムスタイルの適用ガイドをお読みください。"
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "リセット"
msgid "Reset Password"
msgstr "パスワードをリセット"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "スタイルをリセット"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "適用済みのスタイルシートにリセットします"
@@ -3687,14 +3680,6 @@ msgstr "ルーマニア語"
msgid "Rotation"
msgstr "回転"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "ルール"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "ルール"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "分析を実行すると、スコアカード・強み・改善提案が表示されます。"
@@ -3876,10 +3861,6 @@ msgstr "Docker でセルフホスト"
msgid "Semantic CSS stylesheet"
msgstr "セマンティックCSSスタイルシート"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "セマンティックスタイルは引き続き有効です"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "メッセージを送信"
@@ -4482,10 +4463,6 @@ msgstr "この項目は完全に削除されます。元に戻すことはでき
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "この機能を使用するには、AIプロバイダーとの接続が必要です。設定画面でプロバイダーを設定してください。"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "このインスタンスでは現在、セマンティックCSSの編集はできません。"
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "URLに使用されるレジュメの識別名です。"
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: km\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Khmer\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -494,10 +494,6 @@ msgstr "បានដាក់ពាក្យ"
msgid "Applied on"
msgstr "បានដាក់ពាក្យនៅ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "ច្បាប់ដែលបានអនុវត្ត"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "អនុវត្តជាមួយការព្រមាន"
@@ -1010,6 +1006,11 @@ msgstr "ចម្លង​កូដ​បម្រុងទុក"
msgid "Copy JSON"
msgstr "ចម្លង JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "ចម្លងសម្ងាត់"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "ចម្លងសន្លឹករចនាប័ទ្ម"
@@ -2946,10 +2947,6 @@ msgstr "មិនទាន់មានកំណែដែលបានរក្ស
msgid "No source data yet."
msgstr "មិនទាន់មានទិន្នន័យប្រភពទេ។"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "មិនទាន់មានច្បាប់រចនាប័ទ្មនៅឡើយទេ។"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "គ្មានអ្នកផ្តល់សេវាដែលបានធ្វើតេស្តទេ"
@@ -2968,7 +2965,7 @@ msgstr "មិនបានភ្ជាប់"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "មិនប្រាកដថាត្រូវសរសេរអ្វីទេ?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "សូមអានការណែនាំអំពីការអនុវត្តរចនាប័ទ្មផ្ទាល់ខ្លួន។"
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "កំណត់​ឡើងវិញ"
msgid "Reset Password"
msgstr "កំណត់​ពាក្យសម្ងាត់​ឡើងវិញ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "កំណត់រចនាប័ទ្មឡើងវិញ"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "កំណត់ឡើងវិញទៅសន្លឹករចនាប័ទ្មដែលបានអនុវត្ត"
@@ -3687,14 +3680,6 @@ msgstr "Romanian"
msgid "Rotation"
msgstr "មុំ​បង្វែរ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "គ្រប់គ្រង"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "ច្បាប់"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "ដំណើរការវិភាគលើកដំបូងរបស់អ្នកដើម្បីទទួលបានតារាងពិន្ទុ ចំណុចខ្លាំង និងសំណើដែលបានកំណត់អាទិភាព។"
@@ -3876,10 +3861,6 @@ msgstr "ដំឡើង​ផ្ទាល់​ខ្លួន​ដោយ​ប
msgid "Semantic CSS stylesheet"
msgstr "សន្លឹករចនាប័ទ្ម CSS ន័យវិទ្យា"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "រចនាប័ទ្មន័យវិទ្យានៅតែសកម្ម"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "ផ្ញើសារ"
@@ -4482,10 +4463,6 @@ msgstr "ធាតុនេះនឹងត្រូវបានលុបជាអ
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "មុខងារនេះតម្រូវឱ្យមានអ្នកផ្តល់សេវា AI ដែលបានភ្ជាប់។ សូមដំឡើងមួយនៅក្នុងការកំណត់។"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "ឧទាហរណ៍នេះមិនអនុញ្ញាតឱ្យមានការកែសម្រួល CSS តាមន័យវិទ្យានៅពេលនេះទេ។"
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "នេះ​ជា​ឈ្មោះ​ងាយ​ស្រួល​សម្រាប់​ប្រើ​នៅ​ក្នុង URL សម្រាប់​ប្រវត្តិរូប​របស់​អ្នក។"
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: kn\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Kannada\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "ಅರ್ಜಿಸಲಾಗಿದೆ"
msgid "Applied on"
msgstr "ಅರ್ಜಿ ಸಲ್ಲಿಸಿದ ದಿನಾಂಕ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "ಅನ್ವಯವಾಗುವ ನಿಯಮಗಳು"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "ಎಚ್ಚರಿಕೆಗಳೊಂದಿಗೆ ಅನ್ವಯಿಸಲಾಗಿದೆ"
@@ -1010,6 +1006,11 @@ msgstr "ಬ್ಯಾಕಪ್ ಕೋಡ್‌ಗಳನ್ನು ನಕಲಿಸ
msgid "Copy JSON"
msgstr "JSON ನಕಲಿಸಿ"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "ರಹಸ್ಯವನ್ನು ನಕಲಿಸಿ"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "ಸ್ಟೈಲ್‌ಶೀಟ್ ನಕಲಿಸಿ"
@@ -2946,10 +2947,6 @@ msgstr "ಇನ್ನೂ ಯಾವುದೇ ಉಳಿಸಿದ ಆವೃತ್ತ
msgid "No source data yet."
msgstr "ಇನ್ನೂ ಮೂಲ ಡೇಟಾ ಇಲ್ಲ."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "ಇನ್ನೂ ಯಾವುದೇ ಶೈಲಿಯ ನಿಯಮಗಳಿಲ್ಲ."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "ಪರೀಕ್ಷಿಸದ ಪೂರೈಕೆದಾರರು ಇಲ್ಲ."
@@ -2968,7 +2965,7 @@ msgstr "ಸಂಪರ್ಕಗೊಂಡಿಲ್ಲ"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "ಏನು ಬರೆಯಬೇಕೆಂದು ಖಚಿತವಿಲ್ಲವೇ?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "ರಿಯಾಕ್ಟಿವ್ ರೆಸ್ಯೂಮೇ v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "ಕಸ್ಟಮ್ ಶೈಲಿಗಳನ್ನು ಅನ್ವಯಿಸುವ ಮಾರ್ಗದರ್ಶಿಯನ್ನು ಓದಿ."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "ಮರುಹೊಂದಿಸಿ"
msgid "Reset Password"
msgstr "ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರುಹೊಂದಿಸಿ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "ಶೈಲಿಯನ್ನು ಮರುಹೊಂದಿಸಿ"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "ಅನ್ವಯಿಸಲಾದ ಸ್ಟೈಲ್‌ಶೀಟ್‌ಗೆ ಮರುಹೊಂದಿಸಿ"
@@ -3687,14 +3680,6 @@ msgstr "ರೊಮೇನಿಯನ್"
msgid "Rotation"
msgstr "ಭ್ರಮನ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "ನಿಯಮ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "ನಿಯಮಗಳು"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "ಸ್ಕೋರ್‌ಕಾರ್ಡ್, ಬಲಗಳು ಮತ್ತು ಆದ್ಯತೆಯ ಸಲಹೆಗಳನ್ನು ಪಡೆಯಲು ನಿಮ್ಮ ಮೊದಲ ವಿಶ್ಲೇಷಣೆಯನ್ನು ಚಲಾಯಿಸಿ."
@@ -3876,10 +3861,6 @@ msgstr "ಡಾಕರ್ ಜೊತೆಗೆ ಸ್ವಯಂ ಹೋಸ್ಟ್"
msgid "Semantic CSS stylesheet"
msgstr "ಲಾಕ್ಷಣಿಕ CSS ಶೈಲಿ ಹಾಳೆ"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "ಶಬ್ದಾರ್ಥದ ಶೈಲಿಗಳು ಸಕ್ರಿಯವಾಗಿರುತ್ತವೆ"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "ಸಂದೇಶ ಕಳುಹಿಸಿ"
@@ -4482,10 +4463,6 @@ msgstr "ಈ ನಮೂದನ್ನು ಶಾಶ್ವತವಾಗಿ ಅಳಿಸ
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "ಈ ವೈಶಿಷ್ಟ್ಯಕ್ಕೆ ಸಂಪರ್ಕಿತ AI ಪೂರೈಕೆದಾರರ ಅಗತ್ಯವಿದೆ. ದಯವಿಟ್ಟು ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಒಂದನ್ನು ಹೊಂದಿಸಿ."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "ಈ ನಿದರ್ಶನವು ಪ್ರಸ್ತುತ ಲಾಕ್ಷಣಿಕ CSS ಸಂಪಾದನೆಯನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "ಇದು ನಿಮ್ಮ ರೆಸ್ಯೂಮ್‌ಗಾಗಿ URL ಗೆ ಅನುಕೂಲಕರವಾದ ಹೆಸರು."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: ko\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Korean\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -494,10 +494,6 @@ msgstr "지원함"
msgid "Applied on"
msgstr "지원일"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "적용된 규칙"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "경고와 함께 적용됨"
@@ -1010,6 +1006,11 @@ msgstr "백업 코드 복사"
msgid "Copy JSON"
msgstr "JSON 복사"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "비밀을 복사하세요"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "스타일시트 복사"
@@ -2946,10 +2947,6 @@ msgstr "아직 저장된 버전이 없습니다."
msgid "No source data yet."
msgstr "아직 소스 데이터가 없습니다."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "아직 스타일 규칙은 없습니다."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "검증되지 않은 제공업체"
@@ -2968,7 +2965,7 @@ msgstr "연결되지 않음"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "무엇을 써야 할지 모르겠나요?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "리액티브 이력서 v4(JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "사용자 지정 스타일 적용 가이드를 읽어보세요."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "초기화"
msgid "Reset Password"
msgstr "비밀번호 재설정"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "스타일 재설정"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "적용된 스타일시트로 재설정"
@@ -3687,14 +3680,6 @@ msgstr "루마니아어"
msgid "Rotation"
msgstr "회전"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "규칙"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "규칙"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "첫 번째 분석을 실행하여 스코어카드, 강점, 우선순위가 지정된 제안을 확인하세요."
@@ -3876,10 +3861,6 @@ msgstr "Docker로 자체 호스팅"
msgid "Semantic CSS stylesheet"
msgstr "시맨틱 CSS 스타일시트"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "의미 스타일은 계속 활성화되어 있습니다."
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "메시지 보내기"
@@ -4482,10 +4463,6 @@ msgstr "이 항목은 영구적으로 삭제됩니다. 되돌릴 수 없습니
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "이 기능을 사용하려면 연결된 AI 제공업체가 필요합니다. 설정에서 AI 제공업체를 설정해 주세요."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "이 인스턴스에서는 현재 시맨틱 CSS 편집을 지원하지 않습니다."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "이것은 이력서에 사용할 URL 친화적인 이름입니다."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: lt\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Lithuanian\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && (n%100>19 || n%100<11) ? 0 : (n%10>=2 && n%10<=9) && (n%100>19 || n%100<11) ? 1 : n%1!=0 ? 2: 3);\n"
@@ -494,10 +494,6 @@ msgstr "Pateikta"
msgid "Applied on"
msgstr "Pateikta"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Taikomos taisyklės"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Taikoma su įspėjimais"
@@ -1010,6 +1006,11 @@ msgstr "Kopijuoti atsarginius kodus"
msgid "Copy JSON"
msgstr "Kopijuoti JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopijuoti slaptą kodą"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopijuoti stiliaus lapą"
@@ -2946,10 +2947,6 @@ msgstr "Kol kas nėra išsaugotų versijų."
msgid "No source data yet."
msgstr "Šaltinio duomenų dar nėra."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Stiliaus taisyklių dar nėra."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Nėra patikrinto tiekėjo"
@@ -2968,7 +2965,7 @@ msgstr "Nesusijungta"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Nežinote, ką rašyti?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktyvusis CV v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Perskaitykite vadovą „Pasirinktinių stilių taikymas“."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Nustatyti iš naujo"
msgid "Reset Password"
msgstr "Atkurti slaptažodį"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Atstatyti stilių"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Atkurti pritaikytą stiliaus lapą"
@@ -3687,14 +3680,6 @@ msgstr "Rumunų"
msgid "Rotation"
msgstr "Sukimas"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "taisyklė"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "taisyklės"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Atlikite pirmąją analizę, kad gautumėte rezultatų lentelę, stipriąsias puses ir prioritetinius pasiūlymus."
@@ -3876,10 +3861,6 @@ msgstr "Savarankiškas talpinimas naudojant Docker"
msgid "Semantic CSS stylesheet"
msgstr "Semantinis CSS stiliaus lapas"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantiniai stiliai išlieka aktyvūs"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Siųsti žinutę"
@@ -4482,10 +4463,6 @@ msgstr "Šis įrašas bus visam laikui ištrintas. To negalima atšaukti."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Šiai funkcijai reikalingas prijungtas dirbtinio intelekto teikėjas. Nustatykite jį nustatymuose."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Šiuo metu šis egzempliorius neleidžia redaguoti semantinio CSS."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Tai URL draugiškas jūsų gyvenimo aprašymo pavadinimas."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: lv\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Latvian\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
@@ -494,10 +494,6 @@ msgstr "Pieteikts"
msgid "Applied on"
msgstr "Pieteikts"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Piemērotie noteikumi"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Pielietots ar brīdinājumiem"
@@ -1010,6 +1006,11 @@ msgstr "Kopēt rezerves kodus"
msgid "Copy JSON"
msgstr "Kopēt JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopēt slepeno informāciju"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopēt stila lapu"
@@ -2946,10 +2947,6 @@ msgstr "Vēl nav saglabātu versiju."
msgid "No source data yet."
msgstr "Avota datu vēl nav."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Vēl nav stila noteikumu."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Nav pārbaudīta pakalpojumu sniedzēja"
@@ -2968,7 +2965,7 @@ msgstr "Nav izveidots savienojums"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Neesat pārliecināts, ko rakstīt?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Izlasiet rokasgrāmatu Pielāgotu stilu lietošana."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Atiestatīt"
msgid "Reset Password"
msgstr "Atiestatīt paroli"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Atiestatīt stilu"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Atiestatīt uz lietoto stila lapu"
@@ -3687,14 +3680,6 @@ msgstr "Rumāņu"
msgid "Rotation"
msgstr "Rotācija"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "noteikums"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "noteikumi"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Veiciet pirmo analīzi, lai iegūtu rezultātu tabulu, stiprās puses un prioritizētus ieteikumus."
@@ -3876,10 +3861,6 @@ msgstr "Pašhostēšana ar Docker"
msgid "Semantic CSS stylesheet"
msgstr "Semantiskā CSS stila lapa"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantiskie stili paliek aktīvi"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Sūtīt ziņojumu"
@@ -4482,10 +4463,6 @@ msgstr "Šis ieraksts tiks neatgriezeniski dzēsts. To nevar atsaukt."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Šai funkcijai ir nepieciešams pievienots mākslīgā intelekta pakalpojumu sniedzējs. Lūdzu, iestatiet to iestatījumos."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Šajā instancē pašlaik nav atļauta semantiskās CSS rediģēšana."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Tas ir URL-draudzīgs nosaukums jūsu CV."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: ml\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Malayalam\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "അപേക്ഷിച്ചു"
msgid "Applied on"
msgstr "പ്രയോഗിച്ചു"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "ബാധകമായ നിയമങ്ങൾ"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "മുന്നറിയിപ്പുകൾ ഉപയോഗിച്ച് പ്രയോഗിച്ചു"
@@ -1010,6 +1006,11 @@ msgstr "ബാക്കപ്പ് കോഡുകൾ പകർത്തുക"
msgid "Copy JSON"
msgstr "JSON പകർത്തുക"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "രഹസ്യ കോപ്പി ചെയ്യുക"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "സ്റ്റൈൽഷീറ്റ് പകർത്തുക"
@@ -2946,10 +2947,6 @@ msgstr "ഇതുവരെ സംരക്ഷിച്ച പതിപ്പു
msgid "No source data yet."
msgstr "ഇതുവരെ ഉറവിട ഡാറ്റകളൊന്നുമില്ല."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "ഇതുവരെ സ്റ്റൈൽ നിയമങ്ങളൊന്നുമില്ല."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "പരിശോധിച്ച ദാതാവില്ല."
@@ -2968,7 +2965,7 @@ msgstr "കണക്റ്റ് ചെയ്തിട്ടില്ല"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "എന്ത് എഴുതണമെന്ന് ഉറപ്പില്ലേ?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "റിയാക്ടീവ് റെസ്യൂമെ v4 (ജെസൺ
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "ഇഷ്ടാനുസൃത ശൈലികൾ പ്രയോഗിക്കുന്നതിനുള്ള ഗൈഡ് വായിക്കുക."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "റീസെറ്റ് ചെയ്യുക"
msgid "Reset Password"
msgstr "പാസ്‌വേഡ് റീസെറ്റ് ചെയ്യുക"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "സ്റ്റൈൽ പുനഃസജ്ജമാക്കുക"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "പ്രയോഗിച്ച സ്റ്റൈൽഷീറ്റിലേക്ക് പുനഃസജ്ജമാക്കുക"
@@ -3687,14 +3680,6 @@ msgstr "റൊമാനിയൻ"
msgid "Rotation"
msgstr "ററോട്ടേഷൻ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "ഭരണം"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "നിയമങ്ങൾ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "നിങ്ങളുടെ ആദ്യ വിശകലനം നടത്തി ഒരു സ്കോർകാർഡ്, ശക്തികൾ, മുൻഗണനാ നിർദ്ദേശങ്ങൾ എന്നിവ നേടുക."
@@ -3876,10 +3861,6 @@ msgstr "Docker ഉപയോഗിച്ച് സ്വയം ഹോസ്റ്
msgid "Semantic CSS stylesheet"
msgstr "സെമാന്റിക് CSS സ്റ്റൈൽഷീറ്റ്"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "സെമാന്റിക് ശൈലികൾ സജീവമായി തുടരുന്നു"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "സന്ദേശം അയയ്ക്കുക"
@@ -4482,10 +4463,6 @@ msgstr "ഈ എൻട്രി ശാശ്വതമായി ഇല്ലാത
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "ഈ ഫീച്ചറിന് കണക്റ്റുചെയ്‌ത ഒരു AI ദാതാവ് ആവശ്യമാണ്. ക്രമീകരണങ്ങളിൽ ഒന്ന് സജ്ജീകരിക്കുക."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "ഈ സന്ദർഭം നിലവിൽ സെമാന്റിക് CSS എഡിറ്റിംഗ് അനുവദിക്കുന്നില്ല."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "ഇത് നിങ്ങളുടെ റിസ്യൂമിനുള്ള URL‑സൗഹൃദമായ ഒരു പേരാണ്."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: mr\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Marathi\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "अर्ज केला"
msgid "Applied on"
msgstr "वर अर्ज केला"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "लागू केलेले नियम"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "इशाऱ्यांसह लागू केले"
@@ -1010,6 +1006,11 @@ msgstr "बॅकअप कोड्स कॉपी करा"
msgid "Copy JSON"
msgstr "JSON कॉपी करा"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "गुप्त कॉपी करा"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "स्टाईलशीट कॉपी करा"
@@ -2946,10 +2947,6 @@ msgstr "अद्याप कोणतीही आवृत्ती जतन
msgid "No source data yet."
msgstr "अद्याप कोणताही स्त्रोत डेटा नाही."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "अद्याप शैलीचे नियम नाहीत."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "कोणताही तपासलेला प्रदाता नाही"
@@ -2968,7 +2965,7 @@ msgstr "जोडलेले नाही"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "काय लिहावे हे सुचत नाहीये?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "प्रतिक्रियाशील बायोडाटा v4 (
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "कस्टम स्टाईल लागू करण्याविषयीची मार्गदर्शिका वाचा."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "रीसेट करा"
msgid "Reset Password"
msgstr "पासवर्ड रीसेट करा"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "शैली रीसेट करा"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "लागू केलेल्या स्टाईलशीटवर रीसेट करा"
@@ -3687,14 +3680,6 @@ msgstr "रोमानियन"
msgid "Rotation"
msgstr "रोटेशन"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "नियम"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "नियम"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "तुमचे पहिले विश्लेषण चालवा आणि स्कोरकार्ड, सामर्थ्ये आणि प्राधान्यक्रमाने सुचवलेल्या सूचना मिळवा."
@@ -3876,10 +3861,6 @@ msgstr "Docker ने स्वतः होस्ट करा"
msgid "Semantic CSS stylesheet"
msgstr "सिमँटिक CSS स्टाईलशीट"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "अर्थात्मक शैली सक्रिय राहतात"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "संदेश पाठवा"
@@ -4482,10 +4463,6 @@ msgstr "ही नोंद कायमची हटवली जाईल. ह
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "या वैशिष्ट्यासाठी एका कनेक्टेड एआय प्रोव्हायडरची आवश्यकता आहे. कृपया सेटिंग्जमध्ये त्याची नोंदणी करा."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "या इन्स्टन्समध्ये सध्या सिमेंटिक CSS संपादनास परवानगी नाही."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "हा तुमच्या रेझ्युमेसाठी URL-फ्रेंडली नाव आहे."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: ms\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Malay\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -494,10 +494,6 @@ msgstr "Dimohon"
msgid "Applied on"
msgstr "Digunakan pada"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Peraturan yang Digunakan"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Digunakan dengan amaran"
@@ -1010,6 +1006,11 @@ msgstr "Salin Kod Sandaran"
msgid "Copy JSON"
msgstr "Salin JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Salin rahsia"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Salin helaian gaya"
@@ -2946,10 +2947,6 @@ msgstr "Tiada versi yang disimpan lagi."
msgid "No source data yet."
msgstr "Tiada data sumber lagi."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Tiada peraturan gaya lagi."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Tiada pembekal yang diuji"
@@ -2968,7 +2965,7 @@ msgstr "Tidak bersambung"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Tidak pasti apa yang perlu ditulis?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktif Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Baca panduan Menggunakan Gaya Tersuai."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Tetapkan Semula"
msgid "Reset Password"
msgstr "Tetapkan Semula Kata Laluan"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Tetapkan Semula Gaya"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Tetapkan semula kepada helaian gaya yang digunakan"
@@ -3687,14 +3680,6 @@ msgstr "Rom"
msgid "Rotation"
msgstr "Putaran"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "peraturan"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "peraturan"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Jalankan analisis pertama anda untuk mendapatkan kad skor, kekuatan, dan cadangan yang diutamakan."
@@ -3876,10 +3861,6 @@ msgstr "Hos Sendiri dengan Docker"
msgid "Semantic CSS stylesheet"
msgstr "Helaian gaya CSS semantik"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Gaya semantik kekal aktif"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Hantar mesej"
@@ -4482,10 +4463,6 @@ msgstr "Entri ini akan dipadam secara kekal. Ini tidak boleh dibuat asal."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Ciri ini memerlukan penyedia AI yang disambungkan. Sila sediakan satu dalam tetapan."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Keadaan ini pada masa ini tidak membenarkan pengeditan CSS Semantik."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Ini ialah nama mesra URL untuk resume anda."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: ne\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Nepali\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "आवेदन गरियो"
msgid "Applied on"
msgstr "मा लागू गरियो"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "लागू नियमहरू"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "चेतावनीहरू सहित लागू गरियो"
@@ -1010,6 +1006,11 @@ msgstr "ब्याकअप कोडहरू प्रतिलिपि ग
msgid "Copy JSON"
msgstr "JSON प्रतिलिपि गर्नुहोस्"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "गोप्य कुरा प्रतिलिपि गर्नुहोस्"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "स्टाइलसिट प्रतिलिपि गर्नुहोस्"
@@ -2946,10 +2947,6 @@ msgstr "अहिलेसम्म कुनै पनि सुरक्षि
msgid "No source data yet."
msgstr "अहिलेसम्म कुनै स्रोत डाटा छैन।"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "अहिलेसम्म कुनै शैली नियमहरू छैनन्।"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "परीक्षण गरिएको कुनै प्रदायक छैन"
@@ -2968,7 +2965,7 @@ msgstr "जडान गरिएको छैन"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "के लेख्ने भनेर निश्चित हुनुहुन्न?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "प्रतिक्रियाशील बायोडाटा v4 (
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "अनुकूलन शैलीहरू लागू गर्ने गाइड पढ्नुहोस्।"
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "रिसेट गर्नुहोस्"
msgid "Reset Password"
msgstr "पासवर्ड रिसेट गर्नुहोस्"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "शैली रिसेट गर्नुहोस्"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "लागू गरिएको शैली पानामा रिसेट गर्नुहोस्"
@@ -3687,14 +3680,6 @@ msgstr "रुमानियन"
msgid "Rotation"
msgstr "घुमाउने कोण (Rotation)"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "नियम"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "नियमहरू"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "स्कोरकार्ड, शक्तिहरू, र प्राथमिकता दिइएका सुझावहरू प्राप्त गर्न आफ्नो पहिलो विश्लेषण चलाउनुहोस्।"
@@ -3876,10 +3861,6 @@ msgstr "Docker प्रयोग गरेर आफैं होस्ट ग
msgid "Semantic CSS stylesheet"
msgstr "अर्थपूर्ण CSS शैली पाना"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "अर्थपूर्ण शैलीहरू सक्रिय रहन्छन्"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "सन्देश पठाउनुहोस्"
@@ -4482,10 +4463,6 @@ msgstr "यो प्रविष्टि स्थायी रूपमा
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "यो सुविधाको लागि जडान गरिएको AI प्रदायक आवश्यक पर्दछ। कृपया सेटिङहरूमा एउटा सेट अप गर्नुहोस्।"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "यो उदाहरणले हाल सिमेन्टिक CSS सम्पादनलाई अनुमति दिँदैन।"
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "यो तपाईंको बायोडाटाका लागि URL-मैत्री नाम हो।"
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: nl\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Dutch\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Gesolliciteerd"
msgid "Applied on"
msgstr "Toegepast op"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Toegepaste regels"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Toegepast met waarschuwingen"
@@ -1010,6 +1006,11 @@ msgstr "Back-upcodes kopiëren"
msgid "Copy JSON"
msgstr "JSON kopiëren"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopieer geheim"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Stijlpagina kopiëren"
@@ -2946,10 +2947,6 @@ msgstr "Er zijn nog geen opgeslagen versies."
msgid "No source data yet."
msgstr "Nog geen brongegevens."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Er zijn nog geen stijlregels."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Geen geteste provider"
@@ -2968,7 +2965,7 @@ msgstr "Niet verbonden"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Weet je niet wat je moet schrijven?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactieve cv v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Lees de handleiding 'Aangepaste stijlen toepassen'."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Resetten"
msgid "Reset Password"
msgstr "Wachtwoord resetten"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Stijl opnieuw instellen"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Terugzetten naar toegepaste stijlblad"
@@ -3687,14 +3680,6 @@ msgstr "Roemeens"
msgid "Rotation"
msgstr "Rotatie"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "regel"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "regels"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Voer uw eerste analyse uit om een scorekaart, sterke punten en geprioriteerde suggesties te krijgen."
@@ -3876,10 +3861,6 @@ msgstr "Zelf hosten met Docker"
msgid "Semantic CSS stylesheet"
msgstr "Semantische CSS-stijlpagina"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantische stijlen blijven actief."
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Bericht verzenden"
@@ -4482,10 +4463,6 @@ msgstr "Deze vermelding wordt permanent verwijderd. Dit kan niet ongedaan worden
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Voor deze functie is een gekoppelde AI-provider vereist. Stel er een in via de instellingen."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Deze instantie staat momenteel geen semantische CSS-bewerking toe."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Dit is een URL-vriendelijke naam voor uw cv."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: no\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Norwegian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Søkt"
msgid "Applied on"
msgstr "Påført på"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Anvendte regler"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Brukes med advarsler"
@@ -1010,6 +1006,11 @@ msgstr "Kopier sikkerhetskopieringskoder"
msgid "Copy JSON"
msgstr "Kopier JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopier hemmelighet"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopier stilark"
@@ -2946,10 +2947,6 @@ msgstr "Ingen lagrede versjoner ennå."
msgid "No source data yet."
msgstr "Ingen kildedata ennå."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Ingen stilregler ennå."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Ingen testet leverandør"
@@ -2968,7 +2965,7 @@ msgstr "Ikke tilkoblet"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Usikker på hva du skal skrive?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Les veiledningen for bruk av tilpassede stiler."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Tilbakestill"
msgid "Reset Password"
msgstr "Tilbakestill passord"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Tilbakestill stil"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Tilbakestill til brukt stilark"
@@ -3687,14 +3680,6 @@ msgstr "Rumensk"
msgid "Rotation"
msgstr "Rotasjon"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "regel"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "regler"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Kjør din første analyse for å få et poengkort, styrker og prioriterte forslag."
@@ -3876,10 +3861,6 @@ msgstr "Selvhosting med Docker"
msgid "Semantic CSS stylesheet"
msgstr "Semantisk CSS-stilark"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantiske stiler forblir aktive"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Send melding"
@@ -4482,10 +4463,6 @@ msgstr "Denne oppføringen slettes permanent. Dette kan ikke angres."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Denne funksjonen krever en tilkoblet AI-leverandør. Vennligst konfigurer en i innstillingene."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Denne instansen tillater for øyeblikket ikke semantisk CSS-redigering."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Dette er et URL-vennlig navn på CV-en din."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: or\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Odia\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "ଆବେଦନ କରାଯାଇଛି"
msgid "Applied on"
msgstr "ପ୍ରୟୋଗ ହୋଇଛି |"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "ଲାଗୁ ହୋଇଥିବା ନିୟମଗୁଡ଼ିକ"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "ଚେତାବନୀ ସହିତ ଲାଗୁ କରାଯାଇଛି"
@@ -1010,6 +1006,11 @@ msgstr "ବ୍ୟାକଅପ୍ କୋଡଗୁଡିକ କପି କରନ୍
msgid "Copy JSON"
msgstr "JSON କପି କରନ୍ତୁ"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "ଗୁପ୍ତ ଟୋକନ୍ କପି କରନ୍ତୁ"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "ଷ୍ଟାଇଲସିଟ୍ କପି କରନ୍ତୁ"
@@ -2946,10 +2947,6 @@ msgstr "ଏପର୍ଯ୍ୟନ୍ତ କୌଣସି ସେଭ୍ କରାଯ
msgid "No source data yet."
msgstr "ଏପର୍ଯ୍ୟନ୍ତ କ source ଣସି ଉତ୍ସ ତଥ୍ୟ ନାହିଁ |"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "ଏପର୍ଯ୍ୟନ୍ତ କୌଣସି ଷ୍ଟାଇଲ୍ ନିୟମ ନାହିଁ।"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "କୌଣସି ପରୀକ୍ଷିତ ପ୍ରଦାନକାରୀ ନାହାଁନ୍ତି"
@@ -2968,7 +2965,7 @@ msgstr "ସଂଯୁକ୍ତ ହୋଇନାହିଁ"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "କଣ ଲେଖିବେ ନିଶ୍ଚିତ ନୁହଁନ୍ତି?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "କଷ୍ଟମ୍ ଷ୍ଟାଇଲ୍ସ ପ୍ରୟୋଗ କରିବା ଗାଇଡ୍ ପଢ଼ନ୍ତୁ।"
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "ରିସେଟ୍ କରନ୍ତୁ"
msgid "Reset Password"
msgstr "ପାସୱାର୍ଡ ରିସେଟ୍ କରନ୍ତୁ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "ଷ୍ଟାଇଲ୍ ରିସେଟ୍ କରନ୍ତୁ"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "ଲାଗୁ ହୋଇଥିବା ଷ୍ଟାଇଲସିଟକୁ ରିସେଟ୍ କରନ୍ତୁ"
@@ -3687,14 +3680,6 @@ msgstr "ରୋମାନିଆନ୍"
msgid "Rotation"
msgstr "ଘୁର୍ଣ୍ଣନ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "ନିୟମ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "ନିୟମ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "ସ୍କୋରକାର୍ଡ, ଶକ୍ତି ଏବଂ ପ୍ରାଥମିକତାଭିତ୍ତିକ ପରାମର୍ଶ ପାଇବା ପାଇଁ ଆପଣଙ୍କ ପ୍ରଥମ ବିଶ୍ଳେଷଣ ଚଲାନ୍ତୁ।"
@@ -3876,10 +3861,6 @@ msgstr "Docker ସହ ସ୍ୱୟଂ‑ହୋଷ୍ଟ କରନ୍ତୁ"
msgid "Semantic CSS stylesheet"
msgstr "ଅର୍ଥଗତ CSS ଷ୍ଟାଇଲସିଟ୍"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "ଅର୍ଥାତ୍ମକ ଶୈଳୀ ସକ୍ରିୟ ରହିଥାଏ"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "ମେସେଜ୍ ପଠାନ୍ତୁ"
@@ -4482,10 +4463,6 @@ msgstr "ଏହି ପ୍ରବେଶ ସ୍ଥାୟୀଭାବେ ଡିଲି
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "ଏହି ବୈଶିଷ୍ଟ୍ୟ ପାଇଁ ଏକ ସଂଯୁକ୍ତ AI ପ୍ରଦାତା ଆବଶ୍ୟକ। ଦୟାକରି ସେଟିଂସରେ ଗୋଟିଏ ସେଟ୍ ଅପ୍ କରନ୍ତୁ।"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "ଏହି ଉଦାହରଣ ବର୍ତ୍ତମାନ ସିମାଣ୍ଟିକ୍ CSS ସମ୍ପାଦନାକୁ ଅନୁମତି ଦିଏ ନାହିଁ।"
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "ଏହା ଆପଣଙ୍କ ରେଜ୍ୟୁମେ ପାଇଁ URL‑ଫ୍ରେଣ୍ଡଲି ନାମ।"
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: pl\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Polish\n"
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
@@ -494,10 +494,6 @@ msgstr "Złożono aplikację"
msgid "Applied on"
msgstr "Zastosowano"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Zastosowane zasady"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Zastosowano z ostrzeżeniami"
@@ -1010,6 +1006,11 @@ msgstr "Skopiuj kody zapasowe"
msgid "Copy JSON"
msgstr "Kopiuj JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopiuj sekret"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopiuj arkusz stylów"
@@ -2946,10 +2947,6 @@ msgstr "Brak zapisanych wersji."
msgid "No source data yet."
msgstr "Brak jeszcze danych źródłowych."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Nie ma jeszcze reguł dotyczących stylu."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Brak sprawdzonego dostawcy"
@@ -2968,7 +2965,7 @@ msgstr "Nie połączony"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Nie wiesz co napisać?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Przeczytaj przewodnik Stosowanie niestandardowych stylów."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Zresetuj"
msgid "Reset Password"
msgstr "Zresetuj hasło"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Resetuj styl"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Resetuj do zastosowanego arkusza stylów"
@@ -3687,14 +3680,6 @@ msgstr "Rumuński"
msgid "Rotation"
msgstr "Obrót"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "reguła"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "zasady"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Proszę przeprowadzić pierwszą analizę, aby uzyskać kartę wyników, mocne strony i sugestie dotyczące priorytetów."
@@ -3876,10 +3861,6 @@ msgstr "Samodzielny hosting z Dockerem"
msgid "Semantic CSS stylesheet"
msgstr "Arkusz stylów CSS semantyczny"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Style semantyczne pozostają aktywne"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Wyślij wiadomość"
@@ -4482,10 +4463,6 @@ msgstr "Ten wpis zostanie trwale usunięty. Tej czynności nie można cofnąć."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Ta funkcja wymaga podłączonego dostawcy sztucznej inteligencji. Skonfiguruj go w ustawieniach."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "W tej instancji edycja semantycznego kodu CSS nie jest obecnie możliwa."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "To przyjazna dla adresu URL nazwa Twojego CV."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: pt\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Portuguese, Brazilian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Aplicado"
msgid "Applied on"
msgstr "Aplicado em"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Regras Aplicadas"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Aplicado com ressalvas."
@@ -1010,6 +1006,11 @@ msgstr "Copiar códigos de backup"
msgid "Copy JSON"
msgstr "Copiar JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Copiar segredo"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Copiar folha de estilo"
@@ -2946,10 +2947,6 @@ msgstr "Ainda não há versões salvas."
msgid "No source data yet."
msgstr "Ainda não há dados de origem."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Ainda não há regras de estilo."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Nenhum fornecedor testado"
@@ -2968,7 +2965,7 @@ msgstr "Não conectado"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Não sabe o que escrever?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Currículo reativo v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Leia o guia Aplicando Estilos Personalizados."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Redefinir"
msgid "Reset Password"
msgstr "Redefinir senha"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Redefinir estilo"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Redefinir para a folha de estilo aplicada"
@@ -3687,14 +3680,6 @@ msgstr "Romeno"
msgid "Rotation"
msgstr "Rotação"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "regra"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "regras"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Faça sua primeira análise para obter um quadro de resultados, pontos fortes e sugestões priorizadas."
@@ -3876,10 +3861,6 @@ msgstr "Auto-hospedagem com Docker"
msgid "Semantic CSS stylesheet"
msgstr "Folha de estilo CSS semântica"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Os estilos semânticos permanecem ativos"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Enviar mensagem"
@@ -4482,10 +4463,6 @@ msgstr "Esta entrada será excluída permanentemente. Isso não pode ser desfeit
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Este recurso requer um provedor de IA conectado. Configure um nas configurações."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Esta instância não permite, no momento, a edição de CSS semântico."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Este é um nome amigável para URL do seu currículo."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: pt\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Portuguese\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Candidatura enviada"
msgid "Applied on"
msgstr "Aplicado em"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Regras Aplicadas"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Aplicado com reservas."
@@ -1010,6 +1006,11 @@ msgstr "Copiar códigos de backup"
msgid "Copy JSON"
msgstr "Copiar JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Copiar segredo"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Copiar folha de estilo"
@@ -2946,10 +2947,6 @@ msgstr "Ainda não há versões guardadas."
msgid "No source data yet."
msgstr "Ainda não há dados de origem."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Ainda não existem regras de estilo."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Nenhum fornecedor testado"
@@ -2968,7 +2965,7 @@ msgstr "Não conectado"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Não sabe o que escrever?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Currículo reativo v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Leia o guia Aplicando Estilos Personalizados."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Repor"
msgid "Reset Password"
msgstr "Repor senha"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Redefinir estilo"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Repor para a folha de estilo aplicada"
@@ -3687,14 +3680,6 @@ msgstr "Romeno"
msgid "Rotation"
msgstr "Rotação"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "regra"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "regras"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Execute a sua primeira análise para obter um quadro de pontuação, pontos fortes e sugestões prioritárias."
@@ -3876,10 +3861,6 @@ msgstr "Faça auto-hospedagem com o Docker"
msgid "Semantic CSS stylesheet"
msgstr "Folha de estilo CSS semântica"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Os estilos semânticos permanecem ativos"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Enviar mensagem"
@@ -4482,10 +4463,6 @@ msgstr "Esta entrada será eliminada permanentemente. Isto não pode ser anulado
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Este recurso requer um fornecedor de IA conectado. Configure um nas definições."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Esta instância não permite, de momento, a edição de CSS semântico."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Este é um nome compatível com URL para o seu currículo."
+6 -29
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: ro\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Romanian\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100>0 && n%100<20)) ? 1 : 2);\n"
@@ -494,10 +494,6 @@ msgstr "Candidatură trimisă"
msgid "Applied on"
msgstr "Aplicat pe"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Reguli aplicate"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Aplicat cu avertismente"
@@ -1010,6 +1006,11 @@ msgstr "Copiază codurile de rezervă"
msgid "Copy JSON"
msgstr "Copiază JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Copiază secretul"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Copiați foaia de stil"
@@ -2946,10 +2947,6 @@ msgstr "Încă nu există versiuni salvate."
msgid "No source data yet."
msgstr "Nu există date sursă încă."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Încă nu există reguli de stil."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Niciun furnizor testat"
@@ -3568,10 +3565,6 @@ msgstr "Resetează"
msgid "Reset Password"
msgstr "Resetați parola"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Resetare stil"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Resetare la foaia de stil aplicată"
@@ -3687,14 +3680,6 @@ msgstr "Română"
msgid "Rotation"
msgstr "Rotire"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "regulă"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "reguli"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Efectuați prima analiză pentru a obține o fișă de evaluare, puncte forte și sugestii prioritizate."
@@ -3876,10 +3861,6 @@ msgstr "Self-host cu Docker"
msgid "Semantic CSS stylesheet"
msgstr "Foaie de stil CSS semantică"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Stilurile semantice rămân active"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Trimite mesaj"
@@ -4482,10 +4463,6 @@ msgstr "Această intrare va fi ștearsă definitiv. Această acțiune nu poate f
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Această funcție necesită un furnizor de inteligență artificială conectat. Vă rugăm să configurați unul în setări."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Această instanță nu permite în prezent editarea CSS semantică."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Acesta este un nume prietenos cu URL-ul pentru CV."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: ru\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Russian\n"
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
@@ -494,10 +494,6 @@ msgstr "Отклик отправлен"
msgid "Applied on"
msgstr "Применяется на"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Применяемые правила"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Применяется с предупреждениями."
@@ -1010,6 +1006,11 @@ msgstr "Скопировать резервные коды"
msgid "Copy JSON"
msgstr "Скопировать JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Скопировать секрет"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Скопировать таблицу стилей"
@@ -2946,10 +2947,6 @@ msgstr "Сохранённых версий пока нет."
msgid "No source data yet."
msgstr "Исходных данных пока нет."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Пока нет никаких правил стиля."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Нет проверенного поставщика"
@@ -2968,7 +2965,7 @@ msgstr "Не подключено"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Не знаете, что написать?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Ознакомьтесь с руководством по применению пользовательских стилей."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Сброс"
msgid "Reset Password"
msgstr "Сбросить пароль"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Сбросить стиль"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Сбросить до примененной таблицы стилей"
@@ -3687,14 +3680,6 @@ msgstr "Румынский"
msgid "Rotation"
msgstr "Поворот"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "правило"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "правила"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Проведите свой первый анализ, чтобы получить оценочный лист, сильные стороны и приоритетные предложения."
@@ -3876,10 +3861,6 @@ msgstr "Хостинг на Docker"
msgid "Semantic CSS stylesheet"
msgstr "Семантическая таблица стилей CSS"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Семантические стили остаются активными."
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Отправить сообщение"
@@ -4482,10 +4463,6 @@ msgstr "Эта запись будет удалена навсегда. Это
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Для работы этой функции требуется подключенный поставщик ИИ. Пожалуйста, настройте его в параметрах."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "В настоящее время данная версия не позволяет редактировать семантические CSS-стили."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Это удобное для URL название вашего резюме."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: sk\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Slovak\n"
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
@@ -494,10 +494,6 @@ msgstr "Odoslané"
msgid "Applied on"
msgstr "Aplikované dňa"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Použité pravidlá"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Použité s upozorneniami"
@@ -1010,6 +1006,11 @@ msgstr "Skopírovať záložné kódy"
msgid "Copy JSON"
msgstr "Kopírovať JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopírovať tajný kód"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopírovať šablónu so štýlmi"
@@ -2946,10 +2947,6 @@ msgstr "Zatiaľ nie sú uložené žiadne verzie."
msgid "No source data yet."
msgstr "Zatiaľ žiadne zdrojové údaje."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Zatiaľ žiadne pravidlá štýlu."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Žiadny testovaný poskytovateľ"
@@ -2968,7 +2965,7 @@ msgstr "Nepripojené"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Nie ste si istí, čo napísať?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktívny životopis v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Prečítajte si príručku Používanie vlastných štýlov."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Resetovať"
msgid "Reset Password"
msgstr "Obnoviť heslo"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Obnoviť štýl"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Obnoviť na použitý štýlový hárok"
@@ -3687,14 +3680,6 @@ msgstr "Rumunčina"
msgid "Rotation"
msgstr "Otočenie"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "pravidlo"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "pravidlá"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Spustite prvú analýzu, aby ste získali hodnotiacu tabuľku, silné stránky a prioritné návrhy."
@@ -3876,10 +3861,6 @@ msgstr "Vlastný hosting cez Docker"
msgid "Semantic CSS stylesheet"
msgstr "Sémantický CSS štýlový hárok"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Sémantické štýly zostávajú aktívne"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Odoslať správu"
@@ -4482,10 +4463,6 @@ msgstr "Tento záznam bude natrvalo odstránený. Túto akciu nie je možné vr
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Táto funkcia vyžaduje pripojeného poskytovateľa umelej inteligencie. Nastavte si ho v nastaveniach."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Táto inštancia momentálne neumožňuje úpravu sémantického CSS."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Toto je URL‑prívetivý názov tvojho životopisu."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: sl\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Slovenian\n"
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n"
@@ -494,10 +494,6 @@ msgstr "Prijavljeno"
msgid "Applied on"
msgstr "Uporabljeno na"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Uporabljena pravila"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Uporabljeno z opozorili"
@@ -1010,6 +1006,11 @@ msgstr "Kopiraj rezervne kode"
msgid "Copy JSON"
msgstr "Kopiraj JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopiraj skrivnost"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopiraj slogovno predlogo"
@@ -2946,10 +2947,6 @@ msgstr "Še ni shranjenih različic."
msgid "No source data yet."
msgstr "Izvornih podatkov še ni."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Še ni slogovnih pravil."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Ni preizkušenega ponudnika"
@@ -2968,7 +2965,7 @@ msgstr "Ni povezano"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Niste prepričani, kaj naj napišete?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktivni življenjepis v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Preberite vodnik Uporaba slogov po meri."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Ponastavi"
msgid "Reset Password"
msgstr "Ponastavi geslo"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Ponastavi slog"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Ponastavi na uporabljeno slogovno predlogo"
@@ -3687,14 +3680,6 @@ msgstr "romunščina"
msgid "Rotation"
msgstr "Rotacija"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "pravilo"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "pravila"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Izvedite prvo analizo in pridobite preglednico, prednosti in prednostne predloge."
@@ -3876,10 +3861,6 @@ msgstr "Lastno gostovanje z Dockerjem"
msgid "Semantic CSS stylesheet"
msgstr "Semantični CSS slogovni predlog"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantični slogi ostajajo aktivni"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Pošlji sporočilo"
@@ -4482,10 +4463,6 @@ msgstr "Ta vnos bo trajno izbrisan. Tega ni mogoče razveljaviti."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Ta funkcija zahteva povezanega ponudnika umetne inteligence. Nastavite ga v nastavitvah."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Ta primerek trenutno ne dovoljuje urejanja semantičnega CSS-ja."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "To je ime vašega življenjepisa, ki je prijazno do URL-jev."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: sq\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Albanian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Aplikuar"
msgid "Applied on"
msgstr "Aplikuar në"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Rregullat e zbatuara"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Zbatuar me paralajmërime"
@@ -1010,6 +1006,11 @@ msgstr "Kopjo kodet rezervë"
msgid "Copy JSON"
msgstr "Kopjo JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Sekreti i kopjimit"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopjo fletën e stilit"
@@ -2946,10 +2947,6 @@ msgstr "Nuk ka ende versione të ruajtura."
msgid "No source data yet."
msgstr "Nuk ka ende të dhëna burimore."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Ende nuk ka rregulla stili."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Asnjë ofrues i testuar"
@@ -2968,7 +2965,7 @@ msgstr "I palidhur"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Nuk jeni i sigurt se çfarë të shkruani?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reactive Resume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Lexoni udhëzuesin Zbatimi i Stileve të Personalizuara."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Rivendos"
msgid "Reset Password"
msgstr "Rivendos fjalëkalimin"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Rivendos stilin"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Rivendos në fletën e stilit të aplikuar"
@@ -3687,14 +3680,6 @@ msgstr "Rumanisht"
msgid "Rotation"
msgstr "Rrotullimi"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "sundoj"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "rregulla"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Ekzekutoni analizën tuaj të parë për të marrë një kartë rezultatesh, pikat e forta dhe sugjerime të prioritizuara."
@@ -3876,10 +3861,6 @@ msgstr "Self-host me Docker"
msgid "Semantic CSS stylesheet"
msgstr "Fletë stili semantike CSS"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Stilet semantike mbeten aktive"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Dërgo mesazh"
@@ -4482,10 +4463,6 @@ msgstr "Kjo hyrje do të fshihet përgjithmonë. Kjo nuk mund të zhbëhet."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Kjo veçori kërkon një ofrues të lidhur të inteligjencës artificiale. Ju lutemi konfiguroni një të tillë në cilësime."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Kjo instancë aktualisht nuk lejon redaktimin semantik të CSS-së."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Ky është një emër miqësor për URL për CV-në tuaj."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: sr\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Serbian (Cyrillic)\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
@@ -494,10 +494,6 @@ msgstr "Пријављено"
msgid "Applied on"
msgstr "Примењено на"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Примењена правила"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Примењено са упозорењима"
@@ -1010,6 +1006,11 @@ msgstr "Копирај резервне кодове"
msgid "Copy JSON"
msgstr "Копирај JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Копирај тајни"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Копирај стилски лист"
@@ -2946,10 +2947,6 @@ msgstr "Још нема сачуваних верзија."
msgid "No source data yet."
msgstr "Још нема изворних података."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Још нема стилских правила."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Нема тестираног добављача"
@@ -2968,7 +2965,7 @@ msgstr "Није повезано"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Нисте сигурни шта да напишете?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Реактивни резиме v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Прочитајте водич за примену прилагођених стилова."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Ресетуј"
msgid "Reset Password"
msgstr "Ресетуј лозинку"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Ресетуј стил"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Врати на примењени стилски лист"
@@ -3687,14 +3680,6 @@ msgstr "Румунски"
msgid "Rotation"
msgstr "Ротација"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "правило"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "правила"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Покрените прву анализу да бисте добили контролну таблу, снаге и приоритезоване предлоге."
@@ -3876,10 +3861,6 @@ msgstr "Самохостовање помоћу Docker-а"
msgid "Semantic CSS stylesheet"
msgstr "Семантички CSS стилски лист"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Семантички стилови остају активни"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Пошаљи поруку"
@@ -4482,10 +4463,6 @@ msgstr "Овај унос ће бити трајно избрисан. Ово с
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Ова функција захтева повезаног добављача вештачке интелигенције. Молимо вас да га подесите у подешавањима."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Ова инстанца тренутно не дозвољава уређивање семантичког CSS-а."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Ово је URL-пријатељско име за ваш резиме."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: sv\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Swedish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Ansökt"
msgid "Applied on"
msgstr "Tillämpas på"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Tillämpade regler"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Tillämpas med varningar"
@@ -1010,6 +1006,11 @@ msgstr "Kopiera säkerhetskoder"
msgid "Copy JSON"
msgstr "Kopiera JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopiera hemlighet"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Kopiera stilark"
@@ -2946,10 +2947,6 @@ msgstr "Inga sparade versioner ännu."
msgid "No source data yet."
msgstr "Inga källdata ännu."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Inga stilregler än."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Ingen testad leverantör"
@@ -2968,7 +2965,7 @@ msgstr "Inte ansluten"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Osäker på vad du ska skriva?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktivt CV v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Läs guiden för att tillämpa anpassade stilar."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Återställ"
msgid "Reset Password"
msgstr "Återställ lösenord"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Återställ stil"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Återställ till tillämpat formatmall"
@@ -3687,14 +3680,6 @@ msgstr "Rumänska"
msgid "Rotation"
msgstr "Rotation"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "regel"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "regler"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Kör din första analys för att få ett scorecard, styrkor och prioriterade förslag."
@@ -3876,10 +3861,6 @@ msgstr "Självhosting med Docker"
msgid "Semantic CSS stylesheet"
msgstr "Semantisk CSS-stilmall"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantiska stilar förblir aktiva"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Skicka meddelande"
@@ -4482,10 +4463,6 @@ msgstr "Den här posten tas bort permanent. Det går inte att ångra."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Den här funktionen kräver en ansluten AI-leverantör. Vänligen konfigurera en i inställningarna."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Den här instansen tillåter för närvarande inte semantisk CSS-redigering."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Detta är ett URL-vänligt namn för ditt CV."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: ta\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Tamil\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "விண்ணப்பிக்கப்பட்டது"
msgid "Applied on"
msgstr "அன்று விண்ணப்பித்தது"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "பயன்படுத்தப்பட்ட விதிகள்"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "எச்சரிக்கைகளுடன் கூடிய அறிவு"
@@ -1010,6 +1006,11 @@ msgstr "காப்பு குறியீடுகளை நகலெடு"
msgid "Copy JSON"
msgstr "JSON-ஐ நகலெடுக்கவும்"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "ரகசியத்தை நகலெடுக்கவும்"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "பாணித்தாளை நகலெடுக்கவும்"
@@ -2946,10 +2947,6 @@ msgstr "இன்னும் சேமிக்கப்பட்ட பதி
msgid "No source data yet."
msgstr "இதுவரை ஆதார தரவு இல்லை."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "இன்னும் பாணி விதிகள் எதுவும் இல்லை."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "சோதிக்கப்பட்ட வழங்குநர் இல்லை"
@@ -2968,7 +2965,7 @@ msgstr "இணைப்பு இல்லை"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "என்ன எழுதுவது என்று தெரியவில்லையா?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "எதிர்வினை ரெஸ்யூம் v4 (ஜேசன்
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "தனிப்பயன் பாணிகளைப் பயன்படுத்துதல் வழிகாட்டியைப் படிக்கவும்."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "மீட்டமை"
msgid "Reset Password"
msgstr "கடவுச்சொல்லை மீட்டமைக்கவும்"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "பாணியை மீட்டமைக்கவும்"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "பயன்படுத்தப்பட்ட பாணித் தாளுக்கு மீட்டமைக்கவும்"
@@ -3687,14 +3680,6 @@ msgstr "ரோமேனியன்"
msgid "Rotation"
msgstr "சுழற்சி"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "விதி"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "விதிகள்"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "மதிப்பெண் அட்டை, பலங்கள் மற்றும் முன்னுரிமைப்படுத்தப்பட்ட பரிந்துரைகளைப் பெற உங்கள் முதல் பகுப்பாய்வை இயக்கவும்."
@@ -3876,10 +3861,6 @@ msgstr "Docker-இன் உதவியுடன் தானே ஹோஸ்
msgid "Semantic CSS stylesheet"
msgstr "செமாண்டிக் CSS ஸ்டைல்ஷீட்"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "சொற்பொருள் பாணிகள் செயலில் உள்ளன"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "செய்திகளை அனுப்பு"
@@ -4482,10 +4463,6 @@ msgstr "இந்த உள்ளீடு நிரந்தரமாக நீ
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "இந்த அம்சத்திற்கு இணைக்கப்பட்ட AI வழங்குநர் தேவைப்படுகிறது. அமைப்புகளில் ஒன்றை அமைக்கவும்."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "இந்த இன்ஸ்டன்ஸ் தற்போது செமாண்டிக் CSS திருத்தத்தை அனுமதிக்காது."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "இது உங்கள் ரெஸ்யூமிக்கான URL-க்கு உகந்த பெயராகும்."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: te\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Telugu\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "దరఖాస్తు చేశారు"
msgid "Applied on"
msgstr "దరఖాస్తు చేసిన తేదీ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "వర్తింపజేసిన నియమాలు"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "హెచ్చరికలతో వర్తింపజేయబడింది"
@@ -1010,6 +1006,11 @@ msgstr "బ్యాకప్ కోడ్‌లను కాపీ చేయం
msgid "Copy JSON"
msgstr "JSONని కాపీ చేయండి"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "రహస్యాన్ని కాపీ చేయండి"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "స్టైల్‌షీట్‌ను కాపీ చేయండి"
@@ -2946,10 +2947,6 @@ msgstr "ఇంకా సేవ్ చేసిన వెర్షన్లు
msgid "No source data yet."
msgstr "ఇంకా మూల డేటా లేదు."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "ఇంకా శైలి నియమాలు ఏవీ లేవు."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "పరీక్షించిన ప్రొవైడర్ లేదు"
@@ -2968,7 +2965,7 @@ msgstr "కనెక్ట్ కాలేదు"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "ఏం రాయాలో తెలియడం లేదా?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "రియాక్టివ్ రెజ్యూమ్ v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "కస్టమ్ స్టైల్స్ వర్తింపజేయడం గైడ్‌ను చదవండి."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "రీసెట్ చేయండి"
msgid "Reset Password"
msgstr "పాస్‌వర్డ్ రీసెట్ చేయండి"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "శైలిని రీసెట్ చేయండి"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "వర్తింపజేసిన స్టైల్‌షీట్‌కు రీసెట్ చేయండి"
@@ -3687,14 +3680,6 @@ msgstr "రోమేనియన్"
msgid "Rotation"
msgstr "రోటేషన్"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "నియమం"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "నియమాలు"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "స్కోర్‌కార్డ్, బలాలు మరియు ప్రాధాన్యతా సూచనలను పొందడానికి మీ మొదటి విశ్లేషణను అమలు చేయండి."
@@ -3876,10 +3861,6 @@ msgstr "డాకర్‌తో స్వయంగా హోస్ట్ చే
msgid "Semantic CSS stylesheet"
msgstr "సెమాంటిక్ CSS స్టైల్‌షీట్"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "సెమాంటిక్ శైలులు చురుకుగా ఉంటాయి"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "సందేశం పంపండి"
@@ -4482,10 +4463,6 @@ msgstr "ఈ ఎంట్రీ శాశ్వతంగా తొలగించ
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "ఈ ఫీచర్‌కు అనుసంధానించబడిన AI ప్రొవైడర్ అవసరం. దయచేసి సెట్టింగ్స్‌లో ఒకదాన్ని ఏర్పాటు చేసుకోండి."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "ఈ ఇన్‌స్టాన్స్ ప్రస్తుతం సెమాంటిక్ CSS ఎడిటింగ్‌ను అనుమతించదు."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "ఇది మీ రెజ్యూమ్‌కి URL-ప్రియమైన పేరు."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: th\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Thai\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -494,10 +494,6 @@ msgstr "สมัครแล้ว"
msgid "Applied on"
msgstr "สมัครเมื่อ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "กฎที่ใช้"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "ใช้งานโดยมีคำเตือน"
@@ -1010,6 +1006,11 @@ msgstr "คัดลอกรหัสสำรอง"
msgid "Copy JSON"
msgstr "คัดลอก JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "คัดลอกความลับ"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "คัดลอกสไตล์ชีต"
@@ -2946,10 +2947,6 @@ msgstr "ยังไม่มีเวอร์ชันที่บันทึ
msgid "No source data yet."
msgstr "ยังไม่มีข้อมูลแหล่งที่มา"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "ยังไม่มีกฎเกณฑ์ด้านสไตล์ใดๆ"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "ไม่มีผู้ให้บริการที่ผ่านการทดสอบ"
@@ -2968,7 +2965,7 @@ msgstr "ไม่ได้เชื่อมต่อ"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "ไม่แน่ใจว่าจะเขียนอะไรดี?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "เรแอคทีฟ เรซูเม่ v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "โปรดอ่านคู่มือการใช้สไตล์ที่กำหนดเอง"
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "รีเซ็ต"
msgid "Reset Password"
msgstr "รีเซ็ตรหัสผ่าน"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "รีเซ็ตสไตล์"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "รีเซ็ตเป็นสไตล์ชีตที่ใช้งานอยู่"
@@ -3687,14 +3680,6 @@ msgstr "โรมาเนีย"
msgid "Rotation"
msgstr "การหมุน"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "กฎ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "กฎ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "ดำเนินการวิเคราะห์ครั้งแรกของคุณเพื่อรับสกอร์การ์ด จุดแข็ง และข้อเสนอแนะที่จัดลำดับความสำคัญ"
@@ -3876,10 +3861,6 @@ msgstr "โฮสต์ด้วยตนเองบน Docker"
msgid "Semantic CSS stylesheet"
msgstr "สไตล์ชีต CSS เชิงความหมาย"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "รูปแบบความหมายยังคงใช้งานอยู่"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "ส่งข้อความ"
@@ -4482,10 +4463,6 @@ msgstr "รายการนี้จะถูกลบอย่างถาว
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "ฟังก์ชันนี้ต้องใช้ผู้ให้บริการ AI ที่เชื่อมต่ออยู่ โปรดตั้งค่าผู้ให้บริการในส่วนการตั้งค่า"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "ขณะนี้ระบบยังไม่รองรับการแก้ไข CSS แบบ Semantic"
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "นี่คือชื่อเรซูเม่ที่เหมาะสำหรับใช้ใน URL"
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: tr\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Turkish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -494,10 +494,6 @@ msgstr "Başvuruldu"
msgid "Applied on"
msgstr "Başvuru tarihi"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Uygulanan Kurallar"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Uyarılarla birlikte uygulandı."
@@ -1010,6 +1006,11 @@ msgstr "Yedekleme Kodlarını Kopyala"
msgid "Copy JSON"
msgstr "JSON'u kopyala"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Kopyala gizli"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Stil sayfasını kopyala"
@@ -2946,10 +2947,6 @@ msgstr "Henüz kaydedilmiş sürüm yok."
msgid "No source data yet."
msgstr "Henüz kaynak verisi yok."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Henüz stil kuralları yok."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Test edilmiş sağlayıcı yok."
@@ -2968,7 +2965,7 @@ msgstr "Bağlı değil"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Ne yazacağınızdan emin değil misiniz?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktif Özgeçmiş v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Özel Stilleri Uygulama kılavuzunu okuyun."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Sıfırla"
msgid "Reset Password"
msgstr "Şifreyi Sıfırla"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Stili Sıfırla"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Uygulanan stil sayfasına sıfırla"
@@ -3687,14 +3680,6 @@ msgstr "Rumence"
msgid "Rotation"
msgstr "Döndürme"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "kural"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "tüzük"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Bir puan kartı, güçlü yönler ve önceliklendirilmiş öneriler elde etmek için ilk analizinizi çalıştırın."
@@ -3876,10 +3861,6 @@ msgstr "Docker ile kendi kendine barındırma"
msgid "Semantic CSS stylesheet"
msgstr "Anlamsal CSS stil sayfası"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantik stiller aktif kalmaya devam ediyor."
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Mesaj gönder"
@@ -4482,10 +4463,6 @@ msgstr "Bu girdi kalıcı olarak silinecek. Bu işlem geri alınamaz."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Bu özellik için bağlantılı bir yapay zeka sağlayıcısı gereklidir. Lütfen ayarlardan bir tane kurun."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Bu örnek şu anda Semantik CSS düzenlemesine izin vermiyor."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Bu, özgeçmişiniz için URL dostu bir isimdir."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: uk\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Ukrainian\n"
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
@@ -494,10 +494,6 @@ msgstr "Подано"
msgid "Applied on"
msgstr "Подано"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Застосовані правила"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Застосовується з попередженнями"
@@ -1010,6 +1006,11 @@ msgstr "Скопіювати резервні коди"
msgid "Copy JSON"
msgstr "Копіювати JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Скопіювати секретний код"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Копіювати таблицю стилів"
@@ -2946,10 +2947,6 @@ msgstr "Збережених версій поки що немає."
msgid "No source data yet."
msgstr "Даних джерел ще немає."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Поки що немає правил стилю."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Немає перевіреного постачальника"
@@ -2968,7 +2965,7 @@ msgstr "Не підключено"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Не знаєте, що написати?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Реактивне резюме v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Ознайомтеся з посібником із застосування власних стилів."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Скинути"
msgid "Reset Password"
msgstr "Скинути пароль"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Скинути стиль"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Скинути до застосованого таблиці стилів"
@@ -3687,14 +3680,6 @@ msgstr "Румунська"
msgid "Rotation"
msgstr "Обертання"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "правило"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "правила"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Проведіть перший аналіз, щоб отримати оціночну таблицю, сильні сторони та пріоритетні пропозиції."
@@ -3876,10 +3861,6 @@ msgstr "Самостійний хостинг з Docker"
msgid "Semantic CSS stylesheet"
msgstr "Семантична таблиця стилів CSS"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Семантичні стилі залишаються активними"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Надіслати повідомлення"
@@ -4482,10 +4463,6 @@ msgstr "Цей запис буде видалено назавжди. Цю ді
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Ця функція вимагає підключеного постачальника штучного інтелекту. Будь ласка, налаштуйте його в налаштуваннях."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Цей екземпляр наразі не дозволяє редагування семантичного CSS."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Це ім'я вашого резюме, пристосоване для використання у URL."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: uz\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Uzbek\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
@@ -494,10 +494,6 @@ msgstr "Topshirildi"
msgid "Applied on"
msgstr "Ariza sanasi"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Amaliy qoidalar"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Ogohlantirishlar bilan qo'llanildi"
@@ -1010,6 +1006,11 @@ msgstr "Zaxira kodlarini nusxalash"
msgid "Copy JSON"
msgstr "JSON nusxasini olish"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Maxfiy nusxa ko'chirish"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Uslublar jadvalini nusxalash"
@@ -2946,10 +2947,6 @@ msgstr "Hali saqlanmagan versiyalar mavjud."
msgid "No source data yet."
msgstr "Hali manba ma'lumotlari yo'q."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Hali uslub qoidalari yo'q."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Sinovdan o'tgan provayder yo'q"
@@ -2968,7 +2965,7 @@ msgstr "Ulanmagan"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Nima yozishni bilmayapsizmi?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Reaktiv Rezume v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Maxsus uslublarni qo'llash qo'llanmasini o'qing."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Tiklash"
msgid "Reset Password"
msgstr "Parolni tiklash"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Uslubni tiklash"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Qo'llanilgan uslublar jadvaliga qayta o'rnatish"
@@ -3687,14 +3680,6 @@ msgstr "Rumin tili"
msgid "Rotation"
msgstr "Aylantirish"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "qoida"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "qoidalar"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Birinchi tahlilingizni ishga tushiring va ballar jadvali, kuchli tomonlar hamda ustuvor tavsiyalarni oling."
@@ -3876,10 +3861,6 @@ msgstr "Docker bilan mustaqil joylashtirish"
msgid "Semantic CSS stylesheet"
msgstr "Semantik CSS uslublar jadvali"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Semantik uslublar faol bo'lib qolmoqda"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Xabar yuborish"
@@ -4482,10 +4463,6 @@ msgstr "Bu yozuv butunlay o‘chiriladi. Buni ortga qaytarib bo‘lmaydi."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Bu funksiya ulangan AI provayderini talab qiladi. Iltimos, sozlamalarda bittasini sozlang."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Bu misol hozirda semantik CSS tahrirlashga ruxsat bermaydi."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Bu rezyume uchun URL uchun qulay ism."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: vi\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Vietnamese\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -494,10 +494,6 @@ msgstr "Đã ứng tuyển"
msgid "Applied on"
msgstr "Đã ứng tuyển vào"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "Quy tắc áp dụng"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "Được áp dụng kèm theo cảnh báo"
@@ -1010,6 +1006,11 @@ msgstr "Sao chép mã Backup"
msgid "Copy JSON"
msgstr "Sao chép JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "Sao chép bí mật"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "Sao chép bảng định kiểu"
@@ -2946,10 +2947,6 @@ msgstr "Chưa có phiên bản nào được lưu."
msgid "No source data yet."
msgstr "Chưa có dữ liệu nguồn."
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "Chưa có quy tắc về phong cách nào cả."
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "Không có nhà cung cấp nào được kiểm thử"
@@ -2968,7 +2965,7 @@ msgstr "Không kết nối"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "Không biết nên viết gì?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "Sơ yếu lý lịch phản hồi phiên bản 4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "Hãy đọc hướng dẫn Áp dụng kiểu tùy chỉnh."
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "Thiết lập lại"
msgid "Reset Password"
msgstr "Đặt mật khẩu mới"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "Đặt lại kiểu"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "Đặt lại về kiểu định dạng đã áp dụng"
@@ -3687,14 +3680,6 @@ msgstr "Rumani"
msgid "Rotation"
msgstr "Xoay"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "luật lệ"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "quy tắc"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "Hãy thực hiện phân tích đầu tiên để nhận được bảng điểm, điểm mạnh và các đề xuất được sắp xếp theo mức độ ưu tiên."
@@ -3876,10 +3861,6 @@ msgstr "Tự dựng với Docker"
msgid "Semantic CSS stylesheet"
msgstr "Bảng định kiểu CSS ngữ nghĩa"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "Các kiểu ngữ nghĩa vẫn còn hiệu lực"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "Gửi tin nhắn"
@@ -4482,10 +4463,6 @@ msgstr "Mục này sẽ bị xóa vĩnh viễn. Không thể hoàn tác."
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "Tính năng này yêu cầu kết nối với nhà cung cấp AI. Vui lòng thiết lập nhà cung cấp này trong phần cài đặt."
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "Hiện tại, phiên bản này không cho phép chỉnh sửa CSS ngữ nghĩa."
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "Đây là tên thân thiện với URL cho hồ sơ của bạn."
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: zh\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Chinese Simplified\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -494,10 +494,6 @@ msgstr "已申请"
msgid "Applied on"
msgstr "申请日期"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "应用规则"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "附带警告"
@@ -1010,6 +1006,11 @@ msgstr "复制备份码"
msgid "Copy JSON"
msgstr "复制 JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "复制秘密"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "复制样式表"
@@ -2946,10 +2947,6 @@ msgstr "暂无已保存版本。"
msgid "No source data yet."
msgstr "还没有来源数据。"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "目前还没有风格规则。"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "没有经过测试的提供商"
@@ -2968,7 +2965,7 @@ msgstr "未连接"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "不知道该写些什么?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "反应式简历 v4(JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "请阅读“应用自定义样式”指南。"
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "重置"
msgid "Reset Password"
msgstr "重置密码"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "重置样式"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "重置为已应用的样式表"
@@ -3687,14 +3680,6 @@ msgstr "罗马尼亚语"
msgid "Rotation"
msgstr "旋转"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "规则"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "规则"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "进行首次分析,以获得记分卡、优势和优先建议。"
@@ -3876,10 +3861,6 @@ msgstr "使用 Docker 自托管"
msgid "Semantic CSS stylesheet"
msgstr "语义化 CSS 样式表"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "语义风格仍然活跃"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "发送消息"
@@ -4482,10 +4463,6 @@ msgstr "此条目将被永久删除。此操作无法撤销。"
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "此功能需要连接人工智能服务提供商。请在设置中进行设置。"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "此实例目前不支持语义化 CSS 编辑。"
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "这是一个适合放在 URL 中的简历名称。"
+8 -31
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: zh\n"
"Project-Id-Version: reactive-resume\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-07-30 10:57\n"
"PO-Revision-Date: 2026-08-09 13:09\n"
"Last-Translator: \n"
"Language-Team: Chinese Traditional\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -494,10 +494,6 @@ msgstr "已申請"
msgid "Applied on"
msgstr "應徵日期"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr "應用規則"
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr "附帶警告"
@@ -1010,6 +1006,11 @@ msgstr "複製備份代碼"
msgid "Copy JSON"
msgstr "複製 JSON"
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr "複製秘密"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr "複製樣式表"
@@ -2946,10 +2947,6 @@ msgstr "暫無已儲存版本。"
msgid "No source data yet."
msgstr "尚無來源資料。"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr "目前還沒有風格規則。"
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr "沒有經過測試的提供者"
@@ -2968,7 +2965,7 @@ msgstr "未連接"
#: src/features/resume/stylesheet/editor.tsx
msgid "Not sure what to write?"
msgstr ""
msgstr "不知道該寫些什麼?"
#: src/features/applications/components/application-form-sheet.tsx
#: src/libs/resume/section.tsx
@@ -3437,7 +3434,7 @@ msgstr "反應式履歷 v4 (JSON)"
#: src/features/resume/stylesheet/editor.tsx
msgid "Read the Applying Custom Styles guide."
msgstr ""
msgstr "請閱讀“套用自訂樣式”指南。"
#: src/features/applications/components/application-form-sheet.tsx
msgid "Reading…"
@@ -3568,10 +3565,6 @@ msgstr "重置"
msgid "Reset Password"
msgstr "重設密碼"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr "重設樣式"
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr "重設為已套用的樣式表"
@@ -3687,14 +3680,6 @@ msgstr "羅馬尼亞語"
msgid "Rotation"
msgstr "旋轉"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr "規則"
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr "規則"
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr "執行您的第一次分析,以獲得計分卡、優勢和優先建議。"
@@ -3876,10 +3861,6 @@ msgstr "使用 Docker 自行託管"
msgid "Semantic CSS stylesheet"
msgstr "語意化 CSS 樣式表"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr "語義風格仍然活躍"
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr "發送訊息"
@@ -4482,10 +4463,6 @@ msgstr "此項目將永久刪除。此操作無法復原。"
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr "此功能需要連接人工智慧服務提供者。請在設定中進行設定。"
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr "此實例目前不支援語義化 CSS 編輯。"
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr "這是用於履歷的 URL 友善名稱。"
+5 -28
View File
@@ -489,10 +489,6 @@ msgstr ""
msgid "Applied on"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Applied Rules"
msgstr ""
#: src/features/resume/stylesheet/status.tsx
msgid "Applied with warnings"
msgstr ""
@@ -1005,6 +1001,11 @@ msgstr ""
msgid "Copy JSON"
msgstr ""
#. Accessible label for the button that copies the two-factor secret key
#: src/dialogs/auth/enable-two-factor.tsx
msgid "Copy secret"
msgstr ""
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Copy stylesheet"
msgstr ""
@@ -2941,10 +2942,6 @@ msgstr ""
msgid "No source data yet."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "No style rules yet."
msgstr ""
#: src/features/settings/integrations/components/ai-section.tsx
msgid "No tested provider"
msgstr ""
@@ -3563,10 +3560,6 @@ msgstr ""
msgid "Reset Password"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "Reset Style"
msgstr ""
#: src/features/resume/stylesheet/toolbar.tsx
msgid "Reset to applied stylesheet"
msgstr ""
@@ -3682,14 +3675,6 @@ msgstr ""
msgid "Rotation"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rule"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/custom-styles.tsx
msgid "rules"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/resume-analysis.tsx
msgid "Run your first analysis to get a scorecard, strengths, and prioritized suggestions."
msgstr ""
@@ -3871,10 +3856,6 @@ msgstr ""
msgid "Semantic CSS stylesheet"
msgstr ""
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "Semantic styles remain active"
msgstr ""
#: src/routes/agent/-components/agent-chat.tsx
msgid "Send message"
msgstr ""
@@ -4477,10 +4458,6 @@ msgstr ""
msgid "This feature requires a connected AI provider. Please set one up in the settings."
msgstr ""
#: src/features/resume/stylesheet/legacy-banner.tsx
msgid "This instance does not currently allow Semantic CSS editing."
msgstr ""
#: src/dialogs/resume/index.tsx
msgid "This is a URL-friendly name for your resume."
msgstr ""
+25 -25
View File
@@ -16,12 +16,12 @@
"lingui:extract": "lingui extract --clean --overwrite"
},
"dependencies": {
"@ai-sdk/react": "^4.0.45",
"@base-ui/react": "^1.6.0",
"@better-auth/api-key": "^1.6.25",
"@ai-sdk/react": "^4.0.61",
"@base-ui/react": "^1.7.0",
"@better-auth/api-key": "^1.6.26",
"@better-auth/infra": "^0.3.7",
"@better-auth/oauth-provider": "^1.6.25",
"@better-auth/passkey": "^1.6.25",
"@better-auth/oauth-provider": "^1.6.26",
"@better-auth/passkey": "^1.6.26",
"@codemirror/autocomplete": "^6.20.3",
"@codemirror/commands": "^6.10.4",
"@codemirror/lang-css": "^6.3.1",
@@ -29,17 +29,17 @@
"@codemirror/lint": "^6.9.7",
"@codemirror/search": "^6.7.1",
"@codemirror/state": "^6.7.1",
"@codemirror/view": "^6.43.7",
"@codemirror/view": "^6.43.8",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@lingui/core": "^6.6.0",
"@lingui/react": "^6.6.0",
"@orpc/client": "^1.14.13",
"@orpc/server": "^1.14.13",
"@orpc/tanstack-query": "^1.14.13",
"@orpc/client": "^1.15.0",
"@orpc/server": "^1.15.0",
"@orpc/tanstack-query": "^1.15.0",
"@phosphor-icons/react": "^2.1.10",
"@react-pdf/renderer": "^4.5.1",
"@react-pdf/renderer": "^4.6.0",
"@reactive-resume/ai": "workspace:*",
"@reactive-resume/api": "workspace:*",
"@reactive-resume/auth": "workspace:*",
@@ -52,10 +52,10 @@
"@reactive-resume/ui": "workspace:*",
"@reactive-resume/utils": "workspace:*",
"@tailwindcss/vite": "^4.3.3",
"@tanstack/react-form": "^1.33.2",
"@tanstack/react-form": "^1.33.4",
"@tanstack/react-hotkeys": "^0.10.0",
"@tanstack/react-query": "^5.101.4",
"@tanstack/react-router": "^1.170.18",
"@tanstack/react-router": "^1.170.25",
"@tiptap/extension-color": "^3.29.2",
"@tiptap/extension-highlight": "^3.29.2",
"@tiptap/extension-text-align": "^3.29.2",
@@ -66,18 +66,18 @@
"@types/js-cookie": "^3.0.6",
"@uiw/color-convert": "^2.10.3",
"@uiw/react-color-colorful": "^2.10.3",
"ai": "^7.0.42",
"better-auth": "1.6.25",
"ai": "^7.0.58",
"better-auth": "1.6.26",
"buffer": "^6.0.3",
"cmdk": "^1.1.1",
"drizzle-orm": "1.0.0-rc.4",
"es-toolkit": "^1.50.0",
"fuse.js": "^7.5.0",
"immer": "^11.1.15",
"immer": "^11.1.16",
"js-cookie": "^3.0.8",
"motion": "^12.43.0",
"motion": "^13.0.0",
"pdfjs-dist": "6.2.108",
"pg": "^8.22.0",
"pg": "^8.23.0",
"prettier": "^3.9.6",
"qrcode.react": "^4.2.0",
"react": "^19.2.8",
@@ -86,9 +86,9 @@
"react-markdown": "^10.1.0",
"react-resizable-panels": "^4.12.2",
"react-window": "^2.3.0",
"react-zoom-pan-pinch": "^4.0.3",
"react-zoom-pan-pinch": "^4.0.4",
"remark-gfm": "^4.0.1",
"sonner": "^2.0.7",
"sonner": "^2.0.8",
"ts-pattern": "^5.9.0",
"usehooks-ts": "^3.1.1",
"zod": "^4.4.3",
@@ -105,18 +105,18 @@
"@tanstack/devtools-vite": "^0.8.3",
"@tanstack/react-devtools": "^0.10.9",
"@tanstack/react-query-devtools": "^5.101.4",
"@tanstack/react-router-devtools": "^1.167.0",
"@tanstack/router-plugin": "^1.168.23",
"@tanstack/react-router-devtools": "^1.167.1",
"@tanstack/router-plugin": "^1.168.29",
"@types/babel__core": "^7.20.5",
"@types/pg": "^8.20.0",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@types/pg": "^8.21.0",
"@types/react": "^19.2.18",
"@types/react-dom": "^19.2.4",
"@typescript/native-preview": "7.0.0-dev.20260707.2",
"@vitejs/plugin-react": "^6.0.5",
"babel-plugin-macros": "^3.1.0",
"babel-plugin-react-compiler": "^1.0.0",
"rimraf": "^6.1.3",
"typescript": "^7.0.2",
"vite": "^8.1.5"
"vite": "^8.2.1"
}
}
@@ -1,6 +1,6 @@
// @vitest-environment happy-dom
import { render } from "@testing-library/react";
import { fireEvent, render, screen } from "@testing-library/react";
import { beforeAll, describe, expect, it, vi } from "vitest";
import { i18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";
@@ -68,4 +68,17 @@ describe("IconPicker", () => {
const { container } = renderPicker();
expect(container.querySelectorAll("button").length).toBeGreaterThanOrEqual(1);
});
it("calls onChange with an empty string when the no-icon cell is clicked", () => {
const onChange = vi.fn();
render(
<I18nProvider i18n={i18n}>
<IconPicker value="globe" onChange={onChange} popoverProps={{ defaultOpen: true }} />
</I18nProvider>,
);
const firstCell = screen.getByTestId("grid").querySelector("button");
if (firstCell) fireEvent.click(firstCell);
expect(onChange).toHaveBeenCalledWith("");
});
});
@@ -58,7 +58,7 @@ function IconCellComponent({ columnIndex, rowIndex, style, icons, onChange }: Ic
style={style}
tabIndex={-1}
onClick={() => {
if (icon) onChange(icon);
if (typeof icon === "string") onChange(icon);
}}
className="flex size-full items-center justify-center hover:bg-accent"
>
+4 -1
View File
@@ -2,6 +2,7 @@ import type { DialogProps } from "../store";
import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro";
import { CopyIcon, PlusIcon } from "@phosphor-icons/react";
import { useStore } from "@tanstack/react-form";
import { useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { toast } from "sonner";
@@ -83,6 +84,8 @@ const CreateApiKeyForm = ({ setApiKey }: CreateApiKeyFormProps) => {
useFormBlocker(form);
const isSubmitting = useStore(form.store, (state) => state.isSubmitting);
return (
<DialogContent>
<DialogHeader>
@@ -176,7 +179,7 @@ const CreateApiKeyForm = ({ setApiKey }: CreateApiKeyFormProps) => {
</form.Field>
<DialogFooter>
<Button type="submit">
<Button type="submit" disabled={isSubmitting}>
<Trans comment="Create API key dialog submit action">Create</Trans>
</Button>
</DialogFooter>
@@ -254,6 +254,12 @@ export function EnableTwoFactorDialog(_: DialogProps<"auth.two-factor.enable">)
<div className="flex items-center gap-x-2">
<Input readOnly value={secret} className="font-mono text-sm" />
<Button size="icon" variant="ghost" type="button" onClick={handleCopySecret}>
<span className="sr-only">
{t({
comment: "Accessible label for the button that copies the two-factor secret key",
message: "Copy secret",
})}
</span>
<CopyIcon />
</Button>
</div>
@@ -0,0 +1,176 @@
// @vitest-environment happy-dom
import type { AnchorHTMLAttributes, ReactNode } from "react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
import { i18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Dialog } from "@reactive-resume/ui/components/dialog";
import { useDialogStore } from "@/dialogs/store";
import { ConfirmDialogProvider } from "@/hooks/use-confirm";
const navigate = vi.hoisted(() => vi.fn());
// Stands in for the navigation TanStack Router performs from inside <Link>. Keeping it separate
// from `navigate` lets a test tell "the router took us away" apart from "the dialog took us away".
const routerNavigate = vi.hoisted(() => vi.fn());
type MockLinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {
to: string;
children: ReactNode;
};
vi.mock("@tanstack/react-router", () => ({
useNavigate: () => navigate,
// Mirrors the part of <Link> this fix depends on: the router handles the click and navigates
// unless something already prevented the default. Without that, a missing preventDefault() in
// the dialog would go unnoticed here.
Link: ({ to, children, onClick, ...props }: MockLinkProps) => (
<a
href={to}
onClick={(event) => {
onClick?.(event);
if (event.defaultPrevented) return;
if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
routerNavigate({ to });
}}
{...props}
>
{children}
</a>
),
}));
vi.mock("@/features/settings/integrations/hooks/use-has-usable-ai-provider", () => ({
useHasUsableAiProvider: () => ({ hasUsableProvider: false, isLoading: false }),
}));
vi.mock("@/libs/orpc/client", () => ({
client: {},
orpc: { resume: { import: { mutationOptions: () => ({ mutationFn: vi.fn() }) } } },
}));
const { ImportResumeDialog } = await import("./import");
beforeAll(() => {
i18n.loadAndActivate({ locale: "en", messages: {} });
});
afterEach(() => {
navigate.mockReset();
routerNavigate.mockReset();
});
// Drive `open` from the store the way DialogManager does, so closing the dialog actually unmounts it.
function DialogHarness() {
const open = useDialogStore((state) => state.open);
return (
<Dialog open={open}>
<ImportResumeDialog />
</Dialog>
);
}
const renderDialog = () => {
useDialogStore.setState({ open: true, activeDialog: null, onBeforeClose: null });
return render(
<I18nProvider i18n={i18n}>
<QueryClientProvider client={new QueryClient()}>
<ConfirmDialogProvider>
<DialogHarness />
</ConfirmDialogProvider>
</QueryClientProvider>
</I18nProvider>,
);
};
// A real "%PDF" header so the dialog auto-detects the type and shows the provider notice.
const createPdfFile = () =>
new File([new Uint8Array([0x25, 0x50, 0x44, 0x46])], "resume.pdf", { type: "application/pdf" });
// The dialog renders through a portal, so query the document rather than the render container.
async function selectPdfFile() {
const input = document.querySelector<HTMLInputElement>('input[type="file"]');
if (!input) throw new Error("File input not found");
fireEvent.change(input, { target: { files: [createPdfFile()] } });
return await screen.findByText("Set up a provider");
}
describe("ImportResumeDialog — Set up a provider", () => {
// https://github.com/amruthpillai/reactive-resume/issues/3307
it("confirms before leaving instead of navigating behind the dialog", async () => {
renderDialog();
const link = await selectPdfFile();
fireEvent.click(link);
expect(await screen.findByText("Leave to set up an AI provider?")).toBeInTheDocument();
expect(routerNavigate).not.toHaveBeenCalled();
expect(navigate).not.toHaveBeenCalled();
expect(screen.getByText("Import an existing resume")).toBeInTheDocument();
});
it("stays put and keeps the selected file when the user cancels", async () => {
renderDialog();
const link = await selectPdfFile();
fireEvent.click(link);
fireEvent.click(await screen.findByText("Stay"));
await waitFor(() => {
expect(screen.queryByText("Leave to set up an AI provider?")).not.toBeInTheDocument();
});
expect(routerNavigate).not.toHaveBeenCalled();
expect(navigate).not.toHaveBeenCalled();
expect(useDialogStore.getState().open).toBe(true);
expect(screen.getByText("resume.pdf")).toBeInTheDocument();
});
it("closes the dialog and navigates once the user confirms", async () => {
renderDialog();
const link = await selectPdfFile();
fireEvent.click(link);
fireEvent.click(await screen.findByText("Leave"));
await waitFor(() => {
expect(navigate).toHaveBeenCalledWith({ to: "/dashboard/settings/integrations" });
});
expect(useDialogStore.getState().open).toBe(false);
await waitFor(() => {
expect(screen.queryByText("Set up a provider")).not.toBeInTheDocument();
});
});
it("leaves modifier clicks to the browser so the link can open in a new tab", async () => {
renderDialog();
const link = await selectPdfFile();
const event = new MouseEvent("click", { bubbles: true, cancelable: true, metaKey: true });
fireEvent(link, event);
expect(event.defaultPrevented).toBe(false);
expect(screen.queryByText("Leave to set up an AI provider?")).not.toBeInTheDocument();
expect(navigate).not.toHaveBeenCalled();
});
it("leaves middle clicks to the browser too", async () => {
renderDialog();
const link = await selectPdfFile();
const event = new MouseEvent("click", { bubbles: true, cancelable: true, button: 1 });
fireEvent(link, event);
expect(event.defaultPrevented).toBe(false);
expect(screen.queryByText("Leave to set up an AI provider?")).not.toBeInTheDocument();
expect(navigate).not.toHaveBeenCalled();
});
});
@@ -19,6 +19,7 @@ describe("detectJsonImportType", () => {
});
it("returns an empty string for unrecognized shapes", () => {
expect(detectJsonImportType({})).toBe("");
expect(detectJsonImportType({ foo: "bar" })).toBe("");
expect(detectJsonImportType(null)).toBe("");
expect(detectJsonImportType("nope")).toBe("");
+40 -14
View File
@@ -1,6 +1,7 @@
import type { ResumeData } from "@reactive-resume/schema/resume/data";
import type { DialogProps } from "../store";
import type { ImportType } from "./import.utils";
import type { ResumeJsonFormat } from "./parse-json";
import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro";
import { DownloadSimpleIcon, FileIcon, UploadSimpleIcon } from "@phosphor-icons/react";
@@ -10,9 +11,6 @@ import { Link, useNavigate } from "@tanstack/react-router";
import { useRef, useState } from "react";
import { toast } from "sonner";
import z from "zod";
import { parseJSONResume } from "@reactive-resume/import/json-resume";
import { parseReactiveResumeJSON } from "@reactive-resume/import/reactive-resume-json";
import { parseReactiveResumeV4JSON } from "@reactive-resume/import/reactive-resume-v4-json";
import { Badge } from "@reactive-resume/ui/components/badge";
import { Button } from "@reactive-resume/ui/components/button";
import {
@@ -27,12 +25,14 @@ import { Input } from "@reactive-resume/ui/components/input";
import { Spinner } from "@reactive-resume/ui/components/spinner";
import { Combobox } from "@/components/ui/combobox";
import { useHasUsableAiProvider } from "@/features/settings/integrations/hooks/use-has-usable-ai-provider";
import { useConfirm } from "@/hooks/use-confirm";
import { useFormBlocker } from "@/hooks/use-form-blocker";
import { getOrpcErrorMessage } from "@/libs/error-message";
import { client, orpc } from "@/libs/orpc/client";
import { useAppForm } from "@/libs/tanstack-form";
import { useDialogStore } from "../store";
import { detectJsonImportType } from "./import.utils";
import { parseResumeJson } from "./parse-json";
const formSchema = z.discriminatedUnion("type", [
z.object({
@@ -120,6 +120,7 @@ async function detectImportType(file: File): Promise<ImportType> {
}
export function ImportResumeDialog(_: DialogProps<"resume.import">) {
const confirm = useConfirm();
const navigate = useNavigate();
const closeDialog = useDialogStore((state) => state.closeDialog);
@@ -147,16 +148,12 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
try {
let data: ResumeData | undefined;
if (value.type === "json-resume-json") {
data = parseJSONResume(await value.file.text());
}
if (value.type === "reactive-resume-json") {
data = parseReactiveResumeJSON(await value.file.text());
}
if (value.type === "reactive-resume-v4-json") {
data = parseReactiveResumeV4JSON(await value.file.text());
if (
value.type === "json-resume-json" ||
value.type === "reactive-resume-json" ||
value.type === "reactive-resume-v4-json"
) {
data = parseResumeJson(await value.file.text(), value.type as ResumeJsonFormat);
}
if (value.type === "pdf") {
@@ -248,6 +245,31 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
// #6: only warn about unsaved changes once a file has actually been chosen — not on a bare type selection.
useFormBlocker(form, { shouldBlock: () => Boolean(file) });
// The provider link navigates away while this dialog stays mounted over the new page, so the
// unsaved-changes guard (which only runs on a close attempt) fires far too late. Confirm first,
// then close and navigate ourselves.
const onSetUpProvider = async (event: React.MouseEvent<HTMLAnchorElement>) => {
// Modifier and middle clicks open a new tab: the user is not leaving this page, so let the
// browser handle the link and keep the dialog exactly as it is.
if (event.defaultPrevented || event.button !== 0) return;
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
event.preventDefault();
if (file) {
const confirmed = await confirm(t`Leave to set up an AI provider?`, {
description: t`You'll be taken to the Integrations page. The file you selected won't be imported.`,
confirmText: t`Leave`,
cancelText: t`Stay`,
});
if (!confirmed) return;
}
closeDialog();
await navigate({ to: "/dashboard/settings/integrations" });
};
return (
<DialogContent>
<DialogHeader>
@@ -388,7 +410,11 @@ export function ImportResumeDialog(_: DialogProps<"resume.import">) {
size="sm"
variant="secondary"
nativeButton={false}
render={<Link to="/dashboard/settings/integrations">{t`Set up a provider`}</Link>}
render={
<Link to="/dashboard/settings/integrations" onClick={onSetUpProvider}>
{t`Set up a provider`}
</Link>
}
/>
</div>
)}
@@ -0,0 +1,8 @@
import { describe, expect, it } from "vitest";
import { parseResumeJson } from "./parse-json";
describe("parseResumeJson", () => {
it("keeps a selected v4 import from falling back to JSON Resume", () => {
expect(() => parseResumeJson("{}", "reactive-resume-v4-json")).toThrow(/v4/i);
});
});
+12
View File
@@ -0,0 +1,12 @@
import type { ResumeData } from "@reactive-resume/schema/resume/data";
import { parseJSONResume } from "@reactive-resume/import/json-resume";
import { parseReactiveResumeJSON } from "@reactive-resume/import/reactive-resume-json";
import { parseReactiveResumeV4JSON } from "@reactive-resume/import/reactive-resume-v4-json";
export type ResumeJsonFormat = "reactive-resume-json" | "reactive-resume-v4-json" | "json-resume-json";
export function parseResumeJson(text: string, format: ResumeJsonFormat): ResumeData {
if (format === "reactive-resume-json") return parseReactiveResumeJSON(text);
if (format === "reactive-resume-v4-json") return parseReactiveResumeV4JSON(text);
return parseJSONResume(text);
}
@@ -1,11 +1,9 @@
import type { ResumeData } from "@reactive-resume/schema/resume/data";
import type { Template } from "@reactive-resume/schema/templates";
import type { DialogProps } from "@/dialogs/store";
import type { TemplateMetadata } from "./data";
import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro";
import { SlideshowIcon } from "@phosphor-icons/react";
import { lazy, Suspense } from "react";
import { toast } from "sonner";
import { Badge } from "@reactive-resume/ui/components/badge";
import { DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@reactive-resume/ui/components/dialog";
@@ -16,14 +14,6 @@ import { useDialogStore } from "@/dialogs/store";
import { useCurrentResume, useUpdateResumeData } from "@/features/resume/builder/draft";
import { templates } from "./data";
// Lazy so the browser PDF pipeline (pdf.js) loads only when the gallery opens.
// All visible tiles share the same lazy chunk; only one PDF renders at a time via the shared serial queue.
const TemplateLivePreview = lazy(() =>
import("@/features/resume/preview/template-live-preview").then((module) => ({
default: module.TemplateLivePreview,
})),
);
export function TemplateGalleryDialog(_: DialogProps<"resume.template.gallery">) {
const closeDialog = useDialogStore((state) => state.closeDialog);
const resume = useCurrentResume();
@@ -76,7 +66,6 @@ export function TemplateGalleryDialog(_: DialogProps<"resume.template.gallery">)
{Object.entries(templates).map(([template, metadata]) => (
<TemplateCard
key={template}
data={resume.data}
metadata={metadata}
id={template as Template}
isActive={template === selectedTemplate}
@@ -91,13 +80,12 @@ export function TemplateGalleryDialog(_: DialogProps<"resume.template.gallery">)
type TemplateCardProps = {
id: Template;
data: ResumeData;
isActive?: boolean;
metadata: TemplateMetadata;
onSelect: (template: Template) => void;
};
function TemplateCard({ id, data, metadata, isActive, onSelect }: TemplateCardProps) {
function TemplateCard({ id, metadata, isActive, onSelect }: TemplateCardProps) {
return (
<CometCard translateDepth={3} rotateDepth={6} glareOpacity={0}>
<button
@@ -105,12 +93,11 @@ function TemplateCard({ id, data, metadata, isActive, onSelect }: TemplateCardPr
onClick={() => onSelect(id)}
className={cn(
"relative block aspect-page size-full cursor-pointer overflow-hidden rounded-md bg-popover outline-none",
"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
isActive && "ring-2 ring-ring ring-offset-4 ring-offset-background",
)}
>
<Suspense fallback={<img src={metadata.imageUrl} alt={metadata.name} className="size-full object-cover" />}>
<TemplateLivePreview data={data} template={id} fallbackSrc={metadata.imageUrl} alt={metadata.name} />
</Suspense>
<img src={metadata.imageUrl} alt={metadata.name} className="size-full object-cover" />
</button>
<div className="mt-1 flex items-center justify-center">
@@ -11,23 +11,7 @@ import { cn } from "@reactive-resume/utils/style";
import { authClient } from "@/libs/auth/client";
import { orpc } from "@/libs/orpc/client";
type SocialAuthProps = {
requestSignUp?: boolean;
};
type SocialSignInOptions = {
provider: string;
callbackURL: string;
requestSignUp?: true;
};
function getSocialSignInOptions(provider: string, requestSignUp: boolean): SocialSignInOptions {
const options: SocialSignInOptions = { provider, callbackURL: "/dashboard" };
if (requestSignUp) options.requestSignUp = true;
return options;
}
export function SocialAuth({ requestSignUp = false }: SocialAuthProps) {
export function SocialAuth() {
const { data: providers = {}, isLoading } = useQuery(orpc.auth.providers.list.queryOptions());
return (
@@ -42,7 +26,7 @@ export function SocialAuth({ requestSignUp = false }: SocialAuthProps) {
<hr className="flex-1" />
</div>
{isLoading ? <SocialAuthSkeleton /> : <SocialAuthButtons providers={providers} requestSignUp={requestSignUp} />}
{isLoading ? <SocialAuthSkeleton /> : <SocialAuthButtons providers={providers} />}
</>
);
}
@@ -60,10 +44,9 @@ function SocialAuthSkeleton() {
type SocialAuthButtonsProps = {
providers: RouterOutput["auth"]["providers"]["list"];
requestSignUp: boolean;
};
function SocialAuthButtons({ providers, requestSignUp }: SocialAuthButtonsProps) {
function SocialAuthButtons({ providers }: SocialAuthButtonsProps) {
const router = useRouter();
const runSignIn = async (fn: () => Promise<{ error: { message?: string } | null }>) => {
@@ -112,7 +95,7 @@ function SocialAuthButtons({ providers, requestSignUp }: SocialAuthButtonsProps)
</Button>
<Button
onClick={() => runSignIn(() => authClient.signIn.social(getSocialSignInOptions("google", requestSignUp)))}
onClick={() => runSignIn(() => authClient.signIn.social({ provider: "google", callbackURL: "/dashboard" }))}
className={cn(
"hidden flex-1 bg-[#4285F4] text-white hover:bg-[#4285F4]/80",
"google" in providers && "inline-flex",
@@ -123,7 +106,7 @@ function SocialAuthButtons({ providers, requestSignUp }: SocialAuthButtonsProps)
</Button>
<Button
onClick={() => runSignIn(() => authClient.signIn.social(getSocialSignInOptions("github", requestSignUp)))}
onClick={() => runSignIn(() => authClient.signIn.social({ provider: "github", callbackURL: "/dashboard" }))}
className={cn(
"hidden flex-1 bg-[#2b3137] text-white hover:bg-[#2b3137]/80",
"github" in providers && "inline-flex",
@@ -134,7 +117,7 @@ function SocialAuthButtons({ providers, requestSignUp }: SocialAuthButtonsProps)
</Button>
<Button
onClick={() => runSignIn(() => authClient.signIn.social(getSocialSignInOptions("linkedin", requestSignUp)))}
onClick={() => runSignIn(() => authClient.signIn.social({ provider: "linkedin", callbackURL: "/dashboard" }))}
className={cn(
"hidden flex-1 bg-[#0A66C2] text-white hover:bg-[#0A66C2]/80",
"linkedin" in providers && "inline-flex",
@@ -242,7 +242,7 @@ export function RegisterPage({ disableEmailAuth }: Props) {
</form>
)}
<SocialAuth requestSignUp />
<SocialAuth />
</>
);
}
@@ -1,106 +0,0 @@
import type { ResumeData } from "@reactive-resume/schema/resume/data";
import type { Template } from "@reactive-resume/schema/templates";
import { useEffect, useRef, useState } from "react";
import { Spinner } from "@reactive-resume/ui/components/spinner";
import { cn } from "@reactive-resume/utils/style";
import { createResumePdfBlob } from "@/features/resume/export/pdf-document";
import { createPdfFirstPageImageUrl } from "./pdf-thumbnail";
// Bounded FIFO cache of generated object URLs keyed by (data, template) reference. Evicted entries are
// revoked so blobs don't leak; stale-data entries (a new `data` object after an edit) age out via the cap.
// ponytail: cap-24 linear scan — gallery can show ~20 templates at once.
const PREVIEW_CACHE_LIMIT = 24;
type PreviewCacheEntry = { data: ResumeData; template: Template; url: string };
const previewCache: PreviewCacheEntry[] = [];
const getCachedPreview = (data: ResumeData, template: Template) =>
previewCache.find((entry) => entry.data === data && entry.template === template)?.url;
const setCachedPreview = (data: ResumeData, template: Template, url: string) => {
previewCache.push({ data, template, url });
while (previewCache.length > PREVIEW_CACHE_LIMIT) {
const evicted = previewCache.shift();
if (evicted) URL.revokeObjectURL(evicted.url);
}
};
// Serial render pipeline shared across all instances: PDFs generate one-at-a-time on the main thread
// (serialized through `renderQueue`) so the gallery doesn't spike CPU/memory when all tiles mount at once.
// Per-instance `latestRenderRequestId` ref (not global) ensures that if a component re-renders with new
// props it discards its own superseded work without cancelling renders for other tiles.
let renderQueue: Promise<void> = Promise.resolve();
type TemplateLivePreviewProps = {
alt: string;
className?: string;
data: ResumeData;
fallbackSrc: string;
template: Template;
};
/**
* Renders the first page of the user's actual resume data through a given template, lazily.
* Reuses the browser PDF pipeline (`createResumePdfBlob` + pdf.js first-page render). Falls back to the
* static template image while generating or if generation fails. Intended to be mounted on demand (e.g.
* inside a hover/preview card) so the render stays off the hover critical path.
*/
export function TemplateLivePreview({ alt, className, data, fallbackSrc, template }: TemplateLivePreviewProps) {
const [imageUrl, setImageUrl] = useState<string | null>(() => getCachedPreview(data, template) ?? null);
const [hasError, setHasError] = useState(false);
// Per-instance counter: only the latest render request for THIS tile commits its result.
const latestRequestId = useRef(0);
useEffect(() => {
const cached = getCachedPreview(data, template);
if (cached) {
setImageUrl(cached);
return;
}
let cancelled = false;
const requestId = ++latestRequestId.current;
renderQueue = renderQueue.then(async () => {
if (cancelled || requestId !== latestRequestId.current) return;
// Another instance may have cached this exact preview while we were queued.
const existing = getCachedPreview(data, template);
if (existing) {
setImageUrl(existing);
return;
}
try {
const blob = await createResumePdfBlob(data, template);
const url = await createPdfFirstPageImageUrl(blob);
if (cancelled || requestId !== latestRequestId.current) {
URL.revokeObjectURL(url);
return;
}
setCachedPreview(data, template, url);
setImageUrl(url);
} catch {
if (!cancelled) setHasError(true);
}
});
return () => {
cancelled = true;
};
}, [data, template]);
const isLoading = !imageUrl && !hasError;
return (
<div className={cn("relative aspect-page w-full overflow-hidden rounded-md bg-white", className)}>
<img src={imageUrl ?? fallbackSrc} alt={alt} className="size-full object-contain" />
{isLoading ? (
<div className="absolute inset-0 flex items-center justify-center bg-white/40">
<Spinner className="size-8" />
</div>
) : null}
</div>
);
}
@@ -310,7 +310,7 @@ export function StylesheetCodeEditor({
);
}
export type StylesheetEditorShellProps = {
type StylesheetEditorShellProps = {
readOnly?: boolean;
};
@@ -27,17 +27,3 @@ export function LegacyStylesheetBanner({ disabled, onActivate }: LegacyStyleshee
</Alert>
);
}
export function SemanticStylesheetReadOnlyNotice() {
return (
<Alert>
<InfoIcon />
<AlertTitle>
<Trans>Semantic styles remain active</Trans>
</AlertTitle>
<AlertDescription>
<Trans>This instance does not currently allow Semantic CSS editing.</Trans>
</AlertDescription>
</Alert>
);
}
@@ -55,4 +55,42 @@ describe("stylesheet preflight worker", () => {
cause: { name: "ZodError", message: "Invalid resume data", issues },
});
});
it("includes a sanitized cause when PDF preflight throws an unexpected error", async () => {
let handler: ((event: MessageEvent<PreflightWorkerRequest>) => Promise<void>) | undefined;
const postMessage = vi.fn();
vi.stubGlobal("self", {
postMessage,
addEventListener: vi.fn((_type, listener) => {
handler = listener as typeof handler;
}),
});
mocks.renderPreflightPdf.mockRejectedValueOnce(new Error("Canvas is already closed"));
vi.resetModules();
await import("./preflight.worker");
await handler?.({
data: {
type: "preflight",
requestId: 8,
editGeneration: 4,
input: {} as never,
limits: {} as never,
},
} as unknown as MessageEvent<PreflightWorkerRequest>);
expect(postMessage).toHaveBeenCalledWith(
expect.objectContaining({
type: "preflight_result",
requestId: 8,
editGeneration: 4,
result: expect.objectContaining({
ok: false,
code: "STYLESHEET_PREFLIGHT_WORKER_FAILED",
message: expect.stringContaining("Canvas is already closed"),
diagnostics: [],
}),
}),
);
});
});
@@ -20,6 +20,13 @@ const failure = (code: PdfPreflightFailure["code"], message: string): PdfPreflig
diagnostics: [],
});
const sanitizeWorkerCause = (cause: unknown): string => {
if (!(cause instanceof Error)) return "The PDF preflight worker failed.";
const detail = cause.message.replace(/\s+/g, " ").trim().slice(0, 200);
if (!detail) return "The PDF preflight worker failed.";
return `The PDF preflight worker failed. (${cause.name}: ${detail})`;
};
const serializeZodCause = (cause: unknown): SerializedPreflightCause | undefined => {
if (!(cause instanceof Error) || cause.name !== "ZodError" || !("issues" in cause) || !Array.isArray(cause.issues)) {
return;
@@ -49,7 +56,7 @@ self.addEventListener("message", async ({ data }: MessageEvent<PreflightWorkerRe
self.postMessage(response);
return;
}
const result = failure("STYLESHEET_PREFLIGHT_WORKER_FAILED", "The PDF preflight worker failed.");
const result = failure("STYLESHEET_PREFLIGHT_WORKER_FAILED", sanitizeWorkerCause(cause));
const response: PreflightWorkerResponse = {
type: "preflight_result",
requestId: data.requestId,
@@ -741,6 +741,157 @@ describe("stylesheet store runtime", () => {
);
});
it("does not leave Checking stuck when compile rejects for the current edit", async () => {
const runtime = createStylesheetStoreRuntime({
resumeId: "resume-1",
initial,
resumeData: defaultResumeData,
debounceMs: 0,
compile: () => Promise.reject(new Error("Discarded stale stylesheet compiler result.")),
preflight: vi.fn(),
mutate: vi.fn(),
});
runtime.store.getState().setSourceText("edited source");
await vi.runAllTimersAsync();
expect(runtime.store.getState().status).not.toBe("compiling");
expect(runtime.store.getState().status).toBe("error");
});
it("surfaces browser preflight failures as diagnostics when the worker returns an empty list", async () => {
let resolveMutate!: (value: MutationResult & { diagnostics: never[] }) => void;
const mutate = vi.fn(
() =>
new Promise<MutationResult & { diagnostics: never[] }>((resolve) => {
resolveMutate = resolve;
}),
);
const runtime = createStylesheetStoreRuntime({
resumeId: "resume-1",
initial,
resumeData: defaultResumeData,
debounceMs: 0,
compile: async ({ editGeneration }) => ({
type: "compile_result",
requestId: editGeneration,
editGeneration,
program: { languageVersion: 1, rules: [] },
diagnostics: [],
}),
preflight: async ({ editGeneration }) => ({
type: "preflight_result",
requestId: editGeneration,
editGeneration,
result: {
ok: false,
code: "STYLESHEET_PREFLIGHT_WORKER_FAILED",
message: "The PDF preflight worker failed.",
diagnostics: [],
},
}),
mutate,
});
runtime.store.getState().setSourceText("@version 1;\nsection { color: teal; }");
await vi.runAllTimersAsync();
expect(runtime.store.getState().diagnostics).toEqual([
expect.objectContaining({
code: "STYLESHEET_PREFLIGHT_WORKER_FAILED",
severity: "error",
message: "The PDF preflight worker failed.",
range: {
start: { line: 1, column: 1, offset: 0 },
end: { line: 1, column: 1, offset: 0 },
},
}),
]);
expect(runtime.store.getState().diagnostics.some(({ severity }) => severity === "error")).toBe(true);
expect(mutate).toHaveBeenCalled();
resolveMutate({
stylesheet: stylesheet("@version 1;\n"),
revision: 4,
renderDataVersion: 7,
editGeneration: 1,
diagnostics: [],
});
await Promise.resolve();
});
it("finishes an edit when refreshIntelligence interleaves through the shared compile client", async () => {
const { createCompileWorkerClient } = await import("./worker-client");
const listeners = new Map<string, Set<EventListener>>();
const fake = {
postMessage: vi.fn(),
terminate: vi.fn(),
addEventListener: vi.fn((type: string, listener: EventListener) => {
const bucket = listeners.get(type) ?? new Set();
bucket.add(listener);
listeners.set(type, bucket);
}),
removeEventListener: vi.fn((type: string, listener: EventListener) => {
listeners.get(type)?.delete(listener);
}),
emit(data: unknown) {
for (const listener of listeners.get("message") ?? []) {
(listener as (event: MessageEvent) => void)(new MessageEvent("message", { data }));
}
},
};
const client = createCompileWorkerClient(() => fake);
const runtime = createStylesheetStoreRuntime({
resumeId: "resume-1",
initial,
resumeData: defaultResumeData,
debounceMs: 0,
compile: client.compile,
preflight: async ({ editGeneration }) => ({
type: "preflight_result",
requestId: editGeneration,
editGeneration,
result: { ok: true, pageCount: 1, byteCount: 1, diagnostics: [], pdf: new ArrayBuffer(1) },
}),
mutate: async ({ editGeneration }) => ({
stylesheet: stylesheet("edited source"),
revision: 4,
renderDataVersion: 7,
editGeneration,
diagnostics: [],
}),
});
runtime.store.getState().setSourceText("edited source");
await vi.runAllTimersAsync();
expect(runtime.store.getState().status).toBe("compiling");
expect(fake.postMessage).toHaveBeenCalledTimes(1);
// Mobile Design remount / accordion reopen refreshes intelligence while the edit is compiling.
runtime.store.getState().refreshIntelligence();
expect(fake.postMessage).toHaveBeenCalledTimes(2);
fake.emit({
type: "compile_result",
requestId: 1,
editGeneration: 1,
program: { languageVersion: 1, rules: [] },
diagnostics: [],
colorTokens: [],
});
fake.emit({
type: "compile_result",
requestId: 2,
editGeneration: 1,
program: { languageVersion: 1, rules: [] },
diagnostics: [],
colorTokens: [],
});
await vi.runAllTimersAsync();
expect(runtime.store.getState().status).toBe("applied");
expect(runtime.store.getState().applied.text).toBe("edited source");
});
it("terminates both worker clients and clears the store on cleanup", () => {
const destroy = vi.fn();
let mutationSignal: AbortSignal | undefined;
@@ -113,6 +113,18 @@ const emptySemanticTree = (): SemanticNode => ({
const HISTORY_COALESCE_MS = 500;
const MAX_HISTORY_ENTRIES = 50;
const preflightFailureDiagnostic = (
result: Extract<PreflightWorkerResponse["result"], { ok: false }>,
): SemanticCssDiagnostic => ({
code: result.code,
severity: "error",
message: result.message,
range: {
start: { line: 1, column: 1, offset: 0 },
end: { line: 1, column: 1, offset: 0 },
},
});
const inactiveState = (): Omit<
StylesheetStoreState,
"setSourceText" | "setFocused" | "activate" | "deactivate" | "undo" | "redo" | "refreshIntelligence"
@@ -349,6 +361,9 @@ export function createStylesheetStoreRuntime(options: CreateStylesheetStoreRunti
compileInput(resumeData, source, candidate.generation, editorMetadata.semanticTree),
);
} catch {
if (candidateValidationEpoch !== validationEpoch) return;
if (destroyed || candidate.generation !== store.getState().editGeneration) return;
patch({ status: "error" });
return;
}
if (candidateValidationEpoch !== validationEpoch) return;
@@ -386,7 +401,14 @@ export function createStylesheetStoreRuntime(options: CreateStylesheetStoreRunti
if (candidateValidationEpoch !== validationEpoch) return;
if (destroyed || preflight.editGeneration !== store.getState().editGeneration) return;
if (!preflight.result.ok) {
patch({ diagnostics: [...compiled.diagnostics, ...preflight.result.diagnostics], status: "error" });
patch({
diagnostics: [
...compiled.diagnostics,
...preflight.result.diagnostics,
preflightFailureDiagnostic(preflight.result),
],
status: "error",
});
if (candidate.transition !== "edit_source") return;
}
}
@@ -5,20 +5,33 @@ import { createCompileWorkerClient, createPreflightWorkerClient } from "./worker
type Listener = (event: MessageEvent) => void;
function worker() {
const listeners = new Set<Listener>();
const listeners = new Map<string, Set<EventListener>>();
return {
postMessage: vi.fn(),
terminate: vi.fn(),
addEventListener: vi.fn((_type: string, listener: Listener) => listeners.add(listener)),
removeEventListener: vi.fn((_type: string, listener: Listener) => listeners.delete(listener)),
addEventListener: vi.fn((type: string, listener: EventListener) => {
const bucket = listeners.get(type) ?? new Set();
bucket.add(listener);
listeners.set(type, bucket);
}),
removeEventListener: vi.fn((type: string, listener: EventListener) => {
listeners.get(type)?.delete(listener);
}),
emit(data: unknown) {
for (const listener of listeners) listener(new MessageEvent("message", { data }));
for (const listener of listeners.get("message") ?? []) {
(listener as Listener)(new MessageEvent("message", { data }));
}
},
emitError(event: ErrorEvent) {
for (const listener of listeners.get("error") ?? []) {
listener(event);
}
},
};
}
describe("stylesheet worker clients", () => {
it("rejects stale compiler results by request id", async () => {
it("resolves older compiler results so callers can generation-check without aborting", async () => {
const fake = worker();
const client = createCompileWorkerClient(() => fake);
const first = client.compile({ editGeneration: 1 } as never);
@@ -27,8 +40,18 @@ describe("stylesheet worker clients", () => {
fake.emit({ type: "compile_result", requestId: 1, editGeneration: 1, program: null, diagnostics: [] });
fake.emit({ type: "compile_result", requestId: 2, editGeneration: 2, program: null, diagnostics: [] });
await expect(first).rejects.toThrow("stale");
await expect(second).resolves.toMatchObject({ requestId: 2 });
await expect(first).resolves.toMatchObject({ requestId: 1, editGeneration: 1 });
await expect(second).resolves.toMatchObject({ requestId: 2, editGeneration: 2 });
});
it("rejects pending compiles when the worker reports an error", async () => {
const fake = worker();
const client = createCompileWorkerClient(() => fake);
const pending = client.compile({ editGeneration: 1 } as never);
fake.emitError({ message: "Failed to load compiler worker" } as ErrorEvent);
await expect(pending).rejects.toThrow("Failed to load compiler worker");
});
it("terminates and recreates a timed-out preflight worker", async () => {
@@ -68,7 +91,9 @@ describe("stylesheet worker clients", () => {
client.warmup();
expect(createWorker).toHaveBeenCalledOnce();
expect(fake.addEventListener).toHaveBeenCalledOnce();
expect(fake.addEventListener).toHaveBeenCalledTimes(2);
expect(fake.addEventListener).toHaveBeenCalledWith("message", expect.any(Function));
expect(fake.addEventListener).toHaveBeenCalledWith("error", expect.any(Function));
expect(fake.postMessage).not.toHaveBeenCalled();
});
@@ -90,6 +115,20 @@ describe("stylesheet worker clients", () => {
vi.useRealTimers();
});
it("rejects pending preflight work when the worker emits an error event", async () => {
const fake = worker();
const client = createPreflightWorkerClient(() => fake, 5_000);
const pending = client.preflight({ editGeneration: 1 } as never);
const outcome = pending.catch((error: unknown) => error);
fake.emit({ type: "preflight_ready" });
await Promise.resolve();
fake.emitError({ message: "Worker crashed" } as ErrorEvent);
expect(await outcome).toMatchObject({ message: "Worker crashed" });
expect(fake.terminate).toHaveBeenCalled();
});
it("rejects structured resume-data failures without waiting for the timeout", async () => {
vi.useFakeTimers();
const fake = worker();
@@ -10,12 +10,15 @@ import type {
} from "./protocol";
type WorkerListener = (event: MessageEvent<unknown>) => void;
type WorkerErrorListener = (event: ErrorEvent) => void;
export type StylesheetWorker = {
postMessage(message: unknown, transfer?: Transferable[]): void;
terminate(): void;
addEventListener(type: "message", listener: WorkerListener): void;
addEventListener(type: "error", listener: WorkerErrorListener): void;
removeEventListener(type: "message", listener: WorkerListener): void;
removeEventListener(type: "error", listener: WorkerErrorListener): void;
};
type Pending<T> = {
@@ -34,13 +37,17 @@ export function createCompileWorkerClient(createWorker: () => StylesheetWorker)
const request = pending.get(response.requestId);
if (!request) return;
pending.delete(response.requestId);
if (response.requestId !== latestRequestId) {
request.reject(new Error("Discarded stale stylesheet compiler result."));
return;
}
// Resolve every in-flight compile. Callers already generation-check; rejecting "stale"
// results aborts the edit pipeline and can leave the editor stuck on Checking.
request.resolve(response);
};
const onError: WorkerErrorListener = (event) => {
const error = new Error(event.message || "Stylesheet compiler worker failed to load.");
for (const request of pending.values()) request.reject(error);
pending.clear();
};
worker.addEventListener("message", onMessage);
worker.addEventListener("error", onError);
return {
compile(input: CompileWorkerInput): Promise<CompileWorkerResponse> {
@@ -53,6 +60,7 @@ export function createCompileWorkerClient(createWorker: () => StylesheetWorker)
},
destroy() {
worker.removeEventListener("message", onMessage);
worker.removeEventListener("error", onError);
worker.terminate();
for (const request of pending.values()) request.reject(new Error("Stylesheet compiler worker was terminated."));
pending.clear();
@@ -120,10 +128,24 @@ export function createPreflightWorkerClient(
pending.delete(response.requestId);
request.resolve(response);
};
const failPending = (error: Error) => {
for (const request of pending.values()) {
if (request.timer) clearTimeout(request.timer);
request.reject(error);
}
pending.clear();
};
const onError: WorkerErrorListener = (event) => {
const error = new Error(event.message || "Stylesheet preflight worker failed.");
terminate();
failPending(error);
};
const terminate = () => {
if (!worker) return;
worker.removeEventListener("message", onMessage);
worker.removeEventListener("error", onError);
worker.terminate();
worker = undefined;
ready = false;
@@ -140,6 +162,7 @@ export function createPreflightWorkerClient(
if (readiness) return readiness.promise;
worker = createWorker();
worker.addEventListener("message", onMessage);
worker.addEventListener("error", onError);
let resolve!: (value: StylesheetWorker) => void;
let reject!: (error: Error) => void;
const promise = new Promise<StylesheetWorker>((resolvePromise, rejectPromise) => {
+152
View File
@@ -0,0 +1,152 @@
// @vitest-environment happy-dom
import type { ResumeData } from "@reactive-resume/schema/resume/data";
import { beforeAll, describe, expect, it } from "vitest";
import { i18n } from "@lingui/core";
import { ATS_RULE_CODES } from "@reactive-resume/resume/ats";
import { defaultResumeData } from "@reactive-resume/schema/resume/default";
import { atsFindingItemElementId, getAtsFindingLocation, getAtsFindingMessage, getAtsFindingTarget } from "./ats";
const experienceItem = (id: string) => ({
id,
hidden: false,
company: "Analytical Engines",
position: "Engineer",
location: "London",
period: "",
website: { url: "", label: "", inlineLink: false },
description: "",
roles: [],
});
function makeResume(): ResumeData {
const data = structuredClone(defaultResumeData);
data.sections.experience.items = [experienceItem("exp-a"), experienceItem("exp-b")] as never;
data.customSections = [
{
id: "custom-1",
type: "experience",
title: "Consulting",
icon: "",
columns: 1,
hidden: false,
keepTogether: false,
startOnNewPage: false,
items: [experienceItem("custom-item-a")],
},
] as never;
return data;
}
beforeAll(() => {
i18n.loadAndActivate({ locale: "en", messages: {} });
});
describe("getAtsFindingMessage", () => {
it("covers every rule in the catalog", () => {
for (const code of ATS_RULE_CODES) {
const message = getAtsFindingMessage(code);
expect(message.title.length, code).toBeGreaterThan(0);
expect(message.action.length, code).toBeGreaterThan(0);
}
});
it("gives each rule a distinct title", () => {
const titles = ATS_RULE_CODES.map((code) => getAtsFindingMessage(code).title);
expect(new Set(titles).size).toBe(titles.length);
});
});
describe("getAtsFindingTarget", () => {
it.each([
["/basics/email", { side: "left", section: "basics" }],
["/basics/customFields/0/link", { side: "left", section: "basics" }],
["/picture", { side: "left", section: "picture" }],
["/summary/content", { side: "left", section: "summary" }],
["/sections/experience/items/0/period", { side: "left", section: "experience" }],
["/customSections/2/items/1/period", { side: "left", section: "custom" }],
["/metadata/typography/body/fontSize", { side: "right", section: "typography" }],
["/metadata/page/marginX", { side: "right", section: "page" }],
["/metadata/layout/pages", { side: "right", section: "layout" }],
])("resolves %s", (pointer, expected) => {
expect(getAtsFindingTarget(pointer)).toEqual(expected);
});
it("returns null for a pointer with no sidebar home", () => {
expect(getAtsFindingTarget("/metadata/styleRules/0")).toBeNull();
});
it("decodes escaped pointer tokens", () => {
expect(getAtsFindingTarget("/sections/experience/items/0/period")).toEqual({
side: "left",
section: "experience",
});
});
});
describe("getAtsFindingTarget item resolution", () => {
it("resolves the item a finding belongs to", () => {
expect(getAtsFindingTarget("/sections/experience/items/0/period", makeResume())).toEqual({
side: "left",
section: "experience",
itemId: "exp-a",
});
});
it("sends two findings in the same section to different items", () => {
const data = makeResume();
const first = getAtsFindingTarget("/sections/experience/items/0/period", data);
const second = getAtsFindingTarget("/sections/experience/items/1/period", data);
expect(first?.itemId).toBe("exp-a");
expect(second?.itemId).toBe("exp-b");
expect(first?.section).toBe(second?.section);
});
it("resolves items inside custom sections", () => {
expect(getAtsFindingTarget("/customSections/0/items/0/period", makeResume())).toEqual({
side: "left",
section: "custom",
itemId: "custom-item-a",
});
});
it("omits the item when no resume data is supplied", () => {
expect(getAtsFindingTarget("/sections/experience/items/0/period")).toEqual({
side: "left",
section: "experience",
});
});
it("omits the item for a section-level pointer", () => {
expect(getAtsFindingTarget("/sections/experience", makeResume())).toEqual({
side: "left",
section: "experience",
});
});
it("omits the item when the index is out of range", () => {
expect(getAtsFindingTarget("/sections/experience/items/9/period", makeResume())).toEqual({
side: "left",
section: "experience",
});
});
it("builds a stable element id", () => {
expect(atsFindingItemElementId("exp-a")).toBe("resume-item-exp-a");
});
});
describe("getAtsFindingLocation", () => {
it("names the section for a section-level pointer", () => {
expect(getAtsFindingLocation("/basics/email")).toBe("Basics");
});
it("adds a one-based item position for an item-level pointer", () => {
expect(getAtsFindingLocation("/sections/experience/items/0/period")).toBe("Experience · Item 1");
});
it("returns null when the pointer has no sidebar home", () => {
expect(getAtsFindingLocation("/metadata/styleRules/0")).toBeNull();
});
});
+186
View File
@@ -0,0 +1,186 @@
import type { AtsRuleCode } from "@reactive-resume/resume/ats";
import type { ResumeData } from "@reactive-resume/schema/resume/data";
import type { LeftSidebarSection, SidebarSection } from "./section";
import { t } from "@lingui/core/macro";
import { match } from "ts-pattern";
import { getSectionTitle, leftSidebarSections } from "./section";
export type AtsFindingMessage = {
title: string;
action: string;
};
export type AtsFindingTarget = {
side: "left" | "right";
section: SidebarSection;
itemId?: string;
};
export const atsFindingItemElementId = (itemId: string) => `resume-item-${itemId}`;
export function getAtsFindingMessage(code: AtsRuleCode): AtsFindingMessage {
return match(code)
.with("MISSING_NAME", () => ({
title: t`Your resume has no name.`,
action: t`Add your full name under Basics.`,
}))
.with("MISSING_EMAIL", () => ({
title: t`Your resume has no email address.`,
action: t`Most systems file candidates by email. Add one under Basics.`,
}))
.with("MALFORMED_EMAIL", () => ({
title: t`This email address will not be recognized.`,
action: t`Use a plain address such as name@example.com, with no surrounding text.`,
}))
.with("MISSING_PHONE", () => ({
title: t`Your resume has no phone number.`,
action: t`Some application systems require one before you can submit.`,
}))
.with("MISSING_LOCATION", () => ({
title: t`Your resume has no location.`,
action: t`Add at least a city and country so roles can be matched to your region.`,
}))
.with("MALFORMED_URL", () => ({
title: t`This link is missing its protocol.`,
action: t`Write the full address, including https://.`,
}))
.with("PICTURE_PRESENT", () => ({
title: t`Your resume includes a photo.`,
action: t`Some parsers mishandle images, and photos are discouraged in some regions.`,
}))
.with("EMPTY_PERIOD", () => ({
title: t`This entry has no dates.`,
action: t`Add a period such as "Jan 2020 - Present" so it lands on your timeline.`,
}))
.with("UNPARSEABLE_PERIOD", () => ({
title: t`These dates will not be read correctly.`,
action: t`Use a recognized form such as "Jan 2020 - Mar 2022" or "2020 - 2022".`,
}))
.with("UNPARSEABLE_DATE", () => ({
title: t`This date will not be read correctly.`,
action: t`Use a recognized form such as "March 2022" or "2022".`,
}))
.with("REVERSED_PERIOD", () => ({
title: t`This period ends before it starts.`,
action: t`Swap the start and end dates.`,
}))
.with("FUTURE_DATED_PERIOD", () => ({
title: t`This period starts in the future.`,
action: t`Correct the year, or use "Present" for ongoing work.`,
}))
.with("SECTION_MISSING_FROM_LAYOUT", () => ({
title: t`This section has content but never appears.`,
action: t`Place it on a page from the Layout panel, or hide it if you meant to park it.`,
}))
.with("EMPTY_RENDERED_SECTION", () => ({
title: t`This section renders as an empty heading.`,
action: t`Add an item to it, or hide it.`,
}))
.with("NO_VISIBLE_EXPERIENCE", () => ({
title: t`Your resume shows no work experience.`,
action: t`Add an entry, or use projects and volunteer work to show equivalent history.`,
}))
.with("MISSING_EXPERIENCE_DESCRIPTION", () => ({
title: t`This role has no description.`,
action: t`Describe what you did so the entry contributes keywords for matching.`,
}))
.with("NON_STANDARD_SECTION_TITLE", () => ({
title: t`This heading is not one parsers look for.`,
action: t`Prefer a conventional heading such as "Work Experience" or "Education".`,
}))
.with("MULTI_COLUMN_PROSE_SECTION", () => ({
title: t`This section is split across columns.`,
action: t`Columns commonly scramble the order text is read in. Set it to a single column.`,
}))
.with("PROSE_SECTION_IN_SIDEBAR", () => ({
title: t`This section sits in the sidebar.`,
action: t`Move it into the main column and keep the sidebar for short lists.`,
}))
.with("SMALL_BODY_FONT", () => ({
title: t`Your body text is very small.`,
action: t`Use a size of at least 9pt so re-rendered copies stay accurate.`,
}))
.with("TIGHT_LINE_HEIGHT", () => ({
title: t`Your lines are packed very tightly.`,
action: t`Use a line height of at least 1.15 so lines are not merged together.`,
}))
.with("TIGHT_PAGE_MARGINS", () => ({
title: t`Your page margins are very narrow.`,
action: t`Increase them so content stays inside the reliably read area.`,
}))
.exhaustive();
}
function decodePointerToken(token: string): string {
return token.replace(/~1/g, "/").replace(/~0/g, "~");
}
function pointerTokens(pointer: string): string[] {
return pointer.split("/").slice(1).map(decodePointerToken);
}
const isLeftSidebarSection = (value: string): value is LeftSidebarSection =>
(leftSidebarSections as string[]).includes(value);
function resolveItemId(tokens: readonly string[], data?: ResumeData): string | undefined {
if (!data) return undefined;
const itemsIndex = tokens.indexOf("items");
if (itemsIndex === -1) return undefined;
const position = Number(tokens[itemsIndex + 1]);
if (!Number.isInteger(position)) return undefined;
const [head, next] = tokens;
let items: readonly unknown[] | undefined;
if (head === "sections" && next) {
items = (data.sections as Record<string, { items?: readonly unknown[] }>)[next]?.items;
} else if (head === "customSections") {
items = data.customSections[Number(next)]?.items;
}
const item = items?.[position] as { id?: unknown } | undefined;
return typeof item?.id === "string" ? item.id : undefined;
}
export function getAtsFindingTarget(pointer: string, data?: ResumeData): AtsFindingTarget | null {
const tokens = pointerTokens(pointer);
const [head, next] = tokens;
const itemId = resolveItemId(tokens, data);
const withItem = (target: AtsFindingTarget): AtsFindingTarget => (itemId ? { ...target, itemId } : target);
if (head === "basics") return { side: "left", section: "basics" };
if (head === "picture") return { side: "left", section: "picture" };
if (head === "summary") return { side: "left", section: "summary" };
if (head === "customSections") return withItem({ side: "left", section: "custom" });
if (head === "sections" && next && isLeftSidebarSection(next)) {
return withItem({ side: "left", section: next });
}
if (head === "metadata") {
if (next === "typography") return { side: "right", section: "typography" };
if (next === "page") return { side: "right", section: "page" };
if (next === "layout") return { side: "right", section: "layout" };
}
return null;
}
export function getAtsFindingLocation(pointer: string): string | null {
const target = getAtsFindingTarget(pointer);
if (!target) return null;
const tokens = pointerTokens(pointer);
const itemsIndex = tokens.indexOf("items");
const sectionTitle = getSectionTitle(target.section);
if (itemsIndex === -1) return sectionTitle;
const position = Number(tokens[itemsIndex + 1]);
if (!Number.isInteger(position)) return sectionTitle;
const itemNumber = position + 1;
return t`${sectionTitle} · Item ${itemNumber}`;
}
+5
View File
@@ -25,6 +25,7 @@ import {
PaletteIcon,
PhoneIcon,
ReadCvLogoIcon,
SealCheckIcon,
ShareFatIcon,
StarIcon,
TextTIcon,
@@ -52,6 +53,7 @@ export type RightSidebarSection =
| "notes"
| "sharing"
| "statistics"
| "ats"
| "analysis"
| "export"
| "information";
@@ -87,6 +89,7 @@ export const rightSidebarSections: RightSidebarSection[] = [
"styles",
"page",
"notes",
"ats",
"analysis",
"export",
"information",
@@ -126,6 +129,7 @@ export const getSectionTitle = (type: SidebarSection | CustomOnlyType): string =
.with("notes", () => t`Notes`)
.with("sharing", () => t`Sharing`)
.with("statistics", () => t`Statistics`)
.with("ats", () => t`ATS Check`)
.with("analysis", () => t`Resume Analysis`)
.with("export", () => t`Export`)
.with("information", () => t`Information`)
@@ -170,6 +174,7 @@ export const getSectionIcon = (type: SidebarSection | CustomOnlyType, props?: Ic
.with("notes", () => <NotepadIcon {...iconProps} />)
.with("sharing", () => <ShareFatIcon {...iconProps} />)
.with("statistics", () => <ChartLineIcon {...iconProps} />)
.with("ats", () => <SealCheckIcon {...iconProps} />)
.with("analysis", () => <BrainIcon {...iconProps} />)
.with("export", () => <DownloadIcon {...iconProps} />)
.with("information", () => <InfoIcon {...iconProps} />)
@@ -0,0 +1,61 @@
// @vitest-environment happy-dom
import { afterEach, describe, expect, it, vi } from "vitest";
import { blurFocusedElementOnPan } from "./pan-focus";
afterEach(() => {
document.body.innerHTML = "";
});
describe("blurFocusedElementOnPan", () => {
it("blurs the focused element", () => {
const button = document.createElement("button");
document.body.append(button);
button.focus();
expect(document.activeElement).toBe(button);
blurFocusedElementOnPan();
expect(document.activeElement).not.toBe(button);
});
it("blurs a focused text field so panning does not keep it active", () => {
const input = document.createElement("input");
document.body.append(input);
input.focus();
blurFocusedElementOnPan();
expect(document.activeElement).not.toBe(input);
});
it("does nothing when focus already rests on the body", () => {
const blur = vi.spyOn(document.body, "blur");
blurFocusedElementOnPan();
expect(blur).not.toHaveBeenCalled();
blur.mockRestore();
});
// The issue: closing a dialog restores focus to its trigger, and because react-zoom-pan-pinch
// preventDefault()s the canvas mousedown the browser never moves focus away. Space then
// activates the still-focused trigger on keyup and reopens the dialog.
// https://github.com/amruthpillai/reactive-resume/issues/3300
it("stops a Space keypress after panning from re-activating the last dialog trigger", () => {
const trigger = document.createElement("button");
const openDialog = vi.fn();
trigger.addEventListener("click", openDialog);
document.body.append(trigger);
// Focus restored to the trigger when the dialog closed.
trigger.focus();
blurFocusedElementOnPan();
// happy-dom does not synthesise the activation click that a browser fires on Space keyup,
// so assert the precondition for it instead: the trigger no longer holds focus.
expect(document.activeElement).not.toBe(trigger);
expect(openDialog).not.toHaveBeenCalled();
});
});
@@ -0,0 +1,20 @@
/**
* Drops focus from whatever element currently holds it, mirroring what the browser would have
* done natively when the user presses the mouse down on the (non-focusable) preview canvas.
*
* `react-zoom-pan-pinch` calls `preventDefault()` on its window-level `mousedown` listener so
* that dragging the canvas does not select text. That also cancels the browser's native focus
* shift, so focus stays on whatever was focused before the pan — typically the sidebar button
* that opened the last dialog, since closing a dialog restores focus to its trigger. A Space
* keypress then activates that still-focused button on keyup and the dialog reopens.
*
* @see https://github.com/amruthpillai/reactive-resume/issues/3300
*/
export function blurFocusedElementOnPan(): void {
if (typeof document === "undefined") return;
const element = document.activeElement;
if (!(element instanceof HTMLElement) || element === document.body) return;
element.blur();
}
@@ -8,6 +8,7 @@ import { LoadingScreen } from "@/components/layout/loading-screen";
import { ResumePreview } from "@/features/resume/preview/preview";
import { BuilderDock } from "./dock";
import { DEFAULT_BUILDER_PREVIEW_PAGE_LAYOUT, getNextBuilderPreviewPageLayout } from "./page-layout";
import { blurFocusedElementOnPan } from "./pan-focus";
export function PreviewPage() {
const [pageLayout, setPageLayout] = useState(DEFAULT_BUILDER_PREVIEW_PAGE_LAYOUT);
@@ -26,6 +27,7 @@ export function PreviewPage() {
initialScale={0.75}
limitToBounds={false}
wheel={{ step: 0.001 }}
onPanningStart={blurFocusedElementOnPan}
>
<TransformComponent wrapperClass="h-full! w-full!">
<ResumePreview showPageNumbers pageLayout={pageLayout} />
@@ -39,6 +39,7 @@ import { cn } from "@reactive-resume/utils/style";
import { useDialogStore } from "@/dialogs/store";
import { useCurrentResume, useUpdateResumeData } from "@/features/resume/builder/draft";
import { useConfirm } from "@/hooks/use-confirm";
import { atsFindingItemElementId } from "@/libs/resume/ats";
import {
addItemToSection,
createCustomSectionWithItem,
@@ -244,6 +245,7 @@ export function SectionItem<T extends CustomSectionItem | SectionItemType>({
return (
<Reorder.Item
key={item.id}
id={atsFindingItemElementId(item.id)}
value={item}
dragListener={false}
dragControls={controls}

Some files were not shown because too many files have changed in this diff Show More