mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-09-30 08:44:31 +10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
409d09809a | ||
|
|
6d9ebccc63 | ||
|
|
45303fb465 | ||
|
|
f64d02df7f | ||
|
|
bad431b2fc | ||
|
|
9f13638eab | ||
|
|
13e584d522 | ||
|
|
6035402832 | ||
|
|
69961210bd | ||
|
|
7eb6d3bdbf | ||
|
|
5fc9c3ee04 | ||
|
|
a8d1f5a685 | ||
|
|
dd9843172b | ||
|
|
28d698635f | ||
|
|
3635b3d578 | ||
|
|
5a75eda893 | ||
|
|
e4b28e9825 | ||
|
|
2d6ea9ce8d | ||
|
|
0e463883af | ||
|
|
3a5b12e2a4 | ||
|
|
035d94183b | ||
|
|
efd950bd93 | ||
|
|
04100aa9ef | ||
|
|
c292968314 | ||
|
|
ba1f469950 | ||
|
|
b4f245a38e | ||
|
|
e6a31aab97 | ||
|
|
88a19619da | ||
|
|
36232b631d | ||
|
|
9eec1520a1 | ||
|
|
131c1492cd | ||
|
|
ba8e1be2ab | ||
|
|
4a8f87ab8f | ||
|
|
186c400ab7 | ||
|
|
d314361ad6 | ||
|
|
b071a118a3 | ||
|
|
3589b534f5 | ||
|
|
1ee24e5a9f | ||
|
|
93bf1e882d |
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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" }),
|
||||
|
||||
@@ -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 & {
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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,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,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,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,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,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,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,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,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,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
@@ -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,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,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."
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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."
|
||||
|
||||
@@ -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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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 友善名稱。"
|
||||
|
||||
@@ -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
@@ -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"
|
||||
>
|
||||
|
||||
@@ -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("");
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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}`;
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user