mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-09-30 16:54:26 +10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcbe70d231 | ||
|
|
8b52b9d8fc | ||
|
|
4ecc66d081 | ||
|
|
10d58175f1 | ||
|
|
923f5f6173 | ||
|
|
9332e1e3ff | ||
|
|
77f31fa127 | ||
|
|
4fd43657dc | ||
|
|
d9a24448e8 | ||
|
|
69ff78b656 | ||
|
|
0794b5c955 | ||
|
|
5c986cc68d | ||
|
|
688c002822 | ||
|
|
ced49d5314 |
@@ -30,6 +30,10 @@ GOOGLE_CLIENT_SECRET=""
|
||||
GITHUB_CLIENT_ID=""
|
||||
GITHUB_CLIENT_SECRET=""
|
||||
|
||||
# Social Auth (LinkedIn, optional)
|
||||
LINKEDIN_CLIENT_ID=""
|
||||
LINKEDIN_CLIENT_SECRET=""
|
||||
|
||||
# Custom OAuth Provider (optional)
|
||||
OAUTH_PROVIDER_NAME=""
|
||||
OAUTH_CLIENT_ID=""
|
||||
@@ -78,3 +82,7 @@ FLAG_DISABLE_IMAGE_PROCESSING="false"
|
||||
# This is not used within Reactive Resume, but in src/scripts/fonts/generate.ts to generate a list of fonts served by Google Fonts.
|
||||
# Note: Make sure "Google Fonts Developer API" is unrestricted.
|
||||
GOOGLE_CLOUD_API_KEY=""
|
||||
|
||||
# --- Crowdin ---
|
||||
CROWDIN_PROJECT_ID=""
|
||||
CROWDIN_API_TOKEN=""
|
||||
@@ -8,6 +8,9 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
autofix:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -9,6 +9,7 @@ concurrency:
|
||||
|
||||
env:
|
||||
IMAGE: ${{ github.repository }}
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -41,16 +42,16 @@ jobs:
|
||||
run: echo "version=$(jq -r .version package.json)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
@@ -58,7 +59,7 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/${{ env.IMAGE }}
|
||||
@@ -68,7 +69,7 @@ jobs:
|
||||
|
||||
- name: Build and Push by Digest
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
sbom: true
|
||||
@@ -88,7 +89,7 @@ jobs:
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: digests-${{ matrix.arch }}
|
||||
path: /tmp/digests/*
|
||||
@@ -118,23 +119,23 @@ jobs:
|
||||
run: echo "version=$(jq -r .version package.json)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v7
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
@@ -152,7 +153,7 @@ jobs:
|
||||
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/${{ env.IMAGE }}
|
||||
@@ -189,7 +190,7 @@ jobs:
|
||||
echo "docker_digest=$DOCKER_DIGEST" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Install Cosign
|
||||
uses: sigstore/cosign-installer@v3
|
||||
uses: sigstore/cosign-installer@v4
|
||||
|
||||
- name: Sign images with Cosign
|
||||
run: |
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Overview
|
||||
|
||||
Reactive Resume is a single-package full-stack TypeScript app (not a monorepo) built with [TanStack Start](https://tanstack.com/start/latest/docs/framework/react/overview) (React, Vite, Nitro). It serves both frontend and API on port 3000.
|
||||
@@ -130,4 +128,4 @@ Copy `.env.example` to `.env` if not present. Key notes for local dev:
|
||||
## Review Checklist for Agents
|
||||
|
||||
- [ ] Run `vp install` after pulling remote changes and before getting started.
|
||||
- [ ] Run `vp check` and `vp test` to validate changes.
|
||||
- [ ] Run `pnpm lint:fix`, `pnpm fmt:fix`, `pnpm typecheck` and `vp test` to validate changes.
|
||||
|
||||
+7
-5
@@ -1,10 +1,12 @@
|
||||
preserve_hierarchy: true
|
||||
api_token_env: CROWDIN_API_TOKEN
|
||||
project_id_env: CROWDIN_PROJECT_ID
|
||||
commit_message: "[ci skip]"
|
||||
|
||||
pull_request_title: "Sync Translations from Crowdin"
|
||||
pull_request_labels: ["l10n"]
|
||||
pull_request_reviewers: ["amruthpillai"]
|
||||
|
||||
pull_request_title: Sync Translations from Crowdin
|
||||
pull_request_labels:
|
||||
- l10n
|
||||
pull_request_reviewers:
|
||||
- amruthpillai
|
||||
files:
|
||||
- source: /locales/en-US.po
|
||||
translation: /locales/%locale%.%file_extension%
|
||||
|
||||
@@ -4,6 +4,51 @@ description: "List of all notable changes and updates to Reactive Resume"
|
||||
rss: true
|
||||
---
|
||||
|
||||
<Update label="v5.0.16" description="4th April 2026">
|
||||
## Features & Improvements
|
||||
- Updated shared resume item layouts (Experience, Education, Awards, Certifications, Publications, References, Volunteer) for better alignment and spacing consistency.
|
||||
- Generated printer pages now set a meaningful document title from the resume owner's name (`<Name> - Resume`) for cleaner PDF metadata and tab titles. [#2863](https://github.com/amruthpillai/reactive-resume/pull/2863)
|
||||
|
||||
## Fixes
|
||||
- Fixed [#2733](https://github.com/amruthpillai/reactive-resume/issues/2733), where date ranges could appear on a separate line unexpectedly in resume items. [#2862](https://github.com/amruthpillai/reactive-resume/pull/2862)
|
||||
- Adjusted Experience section form field ordering/labels so `Location`, `Position`, and `Period` are mapped and displayed correctly.
|
||||
|
||||
## Maintenance & Localization
|
||||
- Synced translation catalogs across all supported locales.
|
||||
- Updated dependencies and lockfile, including AI SDK, TipTap, TanStack Query, and Vite+ package aliases.
|
||||
</Update>
|
||||
|
||||
<Update label="v5.0.15" description="1st April 2026">
|
||||
## Features & Improvements
|
||||
- Added **LinkedIn sign-in** support for self-hosted instances, including sign-in on the auth page and account linking in settings.
|
||||
- Improved the sign-in experience by showing loading placeholders while social login providers are being fetched.
|
||||
- Resume builder panel sizes are now persisted more reliably, making the layout feel more consistent between sessions.
|
||||
- Added clearer labels for resume sorting and filtering controls on the dashboard.
|
||||
|
||||
## Fixes
|
||||
- Improved autosave reliability in the resume builder:
|
||||
- Unsaved edits are flushed before page unload.
|
||||
- You now get a clear persistent warning if changes fail to save (for example, due to network issues).
|
||||
- Strengthened authentication defaults by increasing the minimum password length requirement to 8 characters.
|
||||
- Improved reliability around resume deletion and server-side error handling for create/update operations.
|
||||
- Fixed a rare language mix-up during printing/export when multiple print jobs run at the same time, so each PDF/screenshot now reliably uses the correct locale.
|
||||
- Improved print stability under heavy usage by reusing in-progress PDF and screenshot generation requests for the same resume instead of starting duplicate jobs.
|
||||
- Hardened printer token signing and token/session/API-key verification paths for better security.
|
||||
- Improved resilience in AI tailoring output parsing and JSON Resume import normalization.
|
||||
- Printer service now provides descriptive error messages ("Failed to generate PDF" / "Failed to capture screenshot") instead of generic internal server errors.
|
||||
- Job descriptions in the job detail sheet now render HTML formatting (headings, lists, bold text) instead of showing raw tags.
|
||||
- Fixed the "Tailor Resume" button being incorrectly disabled when AI is not configured — the dialog already supports plain resume duplication as a fallback.
|
||||
- Fixed the tailor resume flow to open the resume builder in a new tab while keeping the job listing open for reference, instead of navigating away and auto-opening the application page.
|
||||
- Apply option links in the job detail sheet are now validated before rendering, preventing malformed or potentially unsafe URLs.
|
||||
- Improved job card loading skeletons to match the actual card layout (logo, title, badges) for a smoother loading experience.
|
||||
- Centered the "Configure Job Search" empty state on the page.
|
||||
- Extracted the `JobCard` component into its own file for better code organization.
|
||||
|
||||
## Docs & Localization
|
||||
- Updated self-hosting and environment variable documentation to include LinkedIn OAuth configuration.
|
||||
- Synced translations across locales for the latest authentication and save-status messaging.
|
||||
</Update>
|
||||
|
||||
<Update label="v5.0.14" description="24th March 2026">
|
||||
## Features
|
||||
- Implemented OAuth 2.1 support for MCP authentication, thanks to @5queezer. [#2829](https://github.com/amruthpillai/reactive-resume/pull/2829)
|
||||
|
||||
@@ -138,6 +138,8 @@ Here's a complete list of environment variables you can configure:
|
||||
| `GOOGLE_CLIENT_SECRET` | Google OAuth Client Secret | — |
|
||||
| `GITHUB_CLIENT_ID` | GitHub OAuth Client ID | — |
|
||||
| `GITHUB_CLIENT_SECRET` | GitHub OAuth Client Secret | — |
|
||||
| `LINKEDIN_CLIENT_ID` | LinkedIn OAuth Client ID | — |
|
||||
| `LINKEDIN_CLIENT_SECRET` | LinkedIn OAuth Client Secret | — |
|
||||
| `OAUTH_PROVIDER_NAME` | Custom OAuth Provider Name | — |
|
||||
| `OAUTH_CLIENT_ID` | Custom OAuth Client ID | — |
|
||||
| `OAUTH_CLIENT_SECRET` | Custom OAuth Client Secret | — |
|
||||
|
||||
@@ -73,6 +73,10 @@ GOOGLE_CLIENT_SECRET=""
|
||||
GITHUB_CLIENT_ID=""
|
||||
GITHUB_CLIENT_SECRET=""
|
||||
|
||||
# Social Auth (LinkedIn, optional)
|
||||
LINKEDIN_CLIENT_ID=""
|
||||
LINKEDIN_CLIENT_SECRET=""
|
||||
|
||||
# Custom OAuth Provider
|
||||
OAUTH_PROVIDER_NAME=""
|
||||
OAUTH_CLIENT_ID=""
|
||||
@@ -338,6 +342,8 @@ openssl rand -hex 32
|
||||
|
||||
**`GITHUB_CLIENT_ID`** / **`GITHUB_CLIENT_SECRET`** (optional): Enables GitHub sign-in.
|
||||
|
||||
**`LINKEDIN_CLIENT_ID`** / **`LINKEDIN_CLIENT_SECRET`** (optional): Enables LinkedIn sign-in.
|
||||
|
||||
**Custom OAuth provider** (optional):
|
||||
- **`OAUTH_PROVIDER_NAME`**: Display name in the UI
|
||||
- **`OAUTH_CLIENT_ID`** / **`OAUTH_CLIENT_SECRET`**: Required for any custom OAuth provider
|
||||
@@ -375,7 +381,7 @@ openssl rand -hex 32
|
||||
<Accordion title="Feature Flags">
|
||||
- **`FLAG_DEBUG_PRINTER`**: Bypasses the printer-only access restriction (useful when debugging `/printer/{resumeId}`). Recommended: keep `"false"` in production.
|
||||
- **`FLAG_DISABLE_SIGNUPS`**: Disables new signups (web app and server). Useful for private instances.
|
||||
- **`FLAG_DISABLE_EMAIL_AUTH`**: Disables email/password login entirely. Also disables email verification, forgot password, and reset password flows. Users can still sign up via social auth (Google/GitHub/Custom OAuth), unless FLAG_DISABLE_SIGNUPS is also set to true. Useful when only SSO is required.
|
||||
- **`FLAG_DISABLE_EMAIL_AUTH`**: Disables email/password login entirely. Also disables email verification, forgot password, and reset password flows. Users can still sign up via social auth (Google/GitHub/LinkedIn/Custom OAuth), unless FLAG_DISABLE_SIGNUPS is also set to true. Useful when only SSO is required.
|
||||
- **`FLAG_DISABLE_IMAGE_PROCESSING`**: Disables image processing. This is useful if you are using a machine with limited resources, like a Raspberry Pi.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@@ -405,6 +405,8 @@ services:
|
||||
- GOOGLE_CLIENT_SECRET=$GOOGLE_CLIENT_SECRET
|
||||
- GITHUB_CLIENT_ID=$GITHUB_CLIENT_ID
|
||||
- GITHUB_CLIENT_SECRET=$GITHUB_CLIENT_SECRET
|
||||
- LINKEDIN_CLIENT_ID=$LINKEDIN_CLIENT_ID
|
||||
- LINKEDIN_CLIENT_SECRET=$LINKEDIN_CLIENT_SECRET
|
||||
- SMTP_HOST=$SMTP_HOST
|
||||
- SMTP_PORT=$SMTP_PORT
|
||||
- SMTP_USER=$SMTP_USER
|
||||
|
||||
@@ -253,6 +253,8 @@ AUTH_SECRET="your-32-byte-hex-secret"
|
||||
# GOOGLE_CLIENT_SECRET=""
|
||||
# GITHUB_CLIENT_ID=""
|
||||
# GITHUB_CLIENT_SECRET=""
|
||||
# LINKEDIN_CLIENT_ID=""
|
||||
# LINKEDIN_CLIENT_SECRET=""
|
||||
|
||||
# Custom OAuth Provider (e.g., Authentik)
|
||||
OAUTH_PROVIDER_NAME="Company SSO"
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: af\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Afrikaans\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Vaardighede kon nie gesinchroniseer word nie"
|
||||
msgid "Features"
|
||||
msgstr "Funksies"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filter volgens"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Genommerde lys"
|
||||
msgid "Organization"
|
||||
msgstr "Organisasie"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Totale tydperk"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Algehele titel (opsioneel)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Bladsy"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Verfris"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Onthou jy jou wagwoord? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Afgeleë"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slak"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Iets het verkeerd geloop. Probeer asseblief weer."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sorteer volgens"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Jou data word plaaslik gestoor"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Jou data word veilig gestoor en nooit met derde partye gedeel nie. Jy kan ook Reactive Resume self-host op jou eie bedieners vir volledige beheer oor jou data."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Jou wagwoord is suksesvol herstel. Jy kan nou met jou nuwe wagwoord aanmeld."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: am\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Amharic\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr ""
|
||||
msgid "Features"
|
||||
msgstr "መለያዎች"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "መመርመሪያ በ"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "ተደራሽ ዝርዝር"
|
||||
msgid "Organization"
|
||||
msgstr "ድርጅት"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "አጠቃላይ ጊዜ"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "አጠቃላይ ርዕስ (አማራጭ)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "ገጽ"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "ዳስ አድርግ"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "የይለፍ ቃልዎን ያስታውሳሉ? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr ""
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "የተሳሳተ ነገር ተፈጥሯል። እባክዎን ደግመው ይሞክሩ።"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "መደብ በ"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "መረጃዎ በአካባቢዎ መሣሪያ ላይ ይቀመጣል"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "መረጃዎ በደህና ይከማቻል እና ከሶስተኛ ወገኖች ጋር አይተካፈልም። ደግሞም በራስዎ ሰርቨር ላይ Reactive Resumeን በመጫን በመረጃዎ ላይ ሙሉ ቁጥጥር ማግኘት ትችላላችሁ።"
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "የይለፍ ቃልዎ በተሳካ ሁኔታ ዳግም ተጀምሯል። አሁን በአዲሱ የይለፍ ቃል መግባት ትችላላችሁ።"
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ar\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\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"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "فشل في مزامنة المهارات"
|
||||
msgid "Features"
|
||||
msgstr "الميزات"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "تصفية حسب"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "قائمة مرتبة"
|
||||
msgid "Organization"
|
||||
msgstr "المنظمة"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "الفترة الإجمالية"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "العنوان الإجمالي (اختياري)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "صفحة"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "تحديث"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "تتذكر كلمة المرور؟ <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "جهاز التحكم عن بُعد"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "المعرّف النصي (Slug)"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "حدث خطأ ما. يُرجى المحاولة مرة أخرى."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "فرز حسب"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "تُخزَّن بياناتك محليًا"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "تُخزَّن بياناتك بأمان ولا تتم مشاركتها أبدًا مع أطراف ثالثة. يمكنك أيضًا استضافة Reactive Resume ذاتيًا على خوادمك الخاصة للتحكم الكامل في بياناتك."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "تمت إعادة تعيين كلمة المرور الخاصة بك بنجاح. يمكنك الآن تسجيل الدخول باستخدام كلمة المرور الجديدة."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: az\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Azerbaijani\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Bacarıqları sinxronlaşdırmaq mümkün olmadı"
|
||||
msgid "Features"
|
||||
msgstr "Xüsusiyyətlər"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrlə"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Nömrələnmiş Siyahı"
|
||||
msgid "Organization"
|
||||
msgstr "Təşkilat"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Ümumi dövr"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Ümumi başlıq (isteğe bağlı)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Səhifə"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Yenilə"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Şifrənizi xatırlayırsınız? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Uzaqdan"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Nəsə səhv getdi. Zəhmət olmasa, yenidən cəhd edin."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sırala"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Məlumatlarınız lokal olaraq saxlanılır"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Məlumatlarınız təhlükəsiz şəkildə saxlanılır və heç vaxt üçüncü tərəflərlə paylaşılmır. Məlumatlarınıza tam nəzarət üçün Reactive Resume‑ni öz serverlərinizdə də host edə bilərsiniz."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Parolunuz uğurla sıfırlandı. İndi yeni parolunuzla daxil ola bilərsiniz."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: bg\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Bulgarian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Неуспешно синхронизиране на умения"
|
||||
msgid "Features"
|
||||
msgstr "Функции"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Филтриране по"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Подреден списък"
|
||||
msgid "Organization"
|
||||
msgstr "Организация"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Общ период"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Обща длъжност (незадължително)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Страница"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Опресняване"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Спомняте ли си паролата? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Отдалечен"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Слъг"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Нещо се обърка. Моля, опитайте отново."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Сортиране по"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Вашите данни се съхраняват локално"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Вашите данни се съхраняват сигурно и никога не се споделят с трети страни. Можете също да хоствате Reactive Resume самостоятелно на свои сървъри за пълен контрол върху данните си."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Паролата ви беше нулирана успешно. Сега можете да влезете с новата си парола."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: bn\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Bengali\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "দক্ষতা সিঙ্ক করতে ব্যর্থ হ
|
||||
msgid "Features"
|
||||
msgstr "বৈশিষ্ট্যসমূহ"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "ফিল্টার করুন"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "ক্রমযুক্ত লিস্ট"
|
||||
msgid "Organization"
|
||||
msgstr "প্রতিষ্ঠান"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "সামগ্রিক সময়কাল"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "সামগ্রিক শিরোনাম (ঐচ্ছিক)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "পৃষ্ঠা"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "রিফ্রেশ"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "আপনার পাসওয়ার্ড মনে আছে? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "দূরবর্তী"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "স্লাগ"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "কিছু একটা ভুল হয়েছে। অনুগ্রহ করে আবার চেষ্টা করুন।"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "সর্ট করুন"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "আপনার ডেটা স্থানীয়ভাবে সং
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "আপনার ডেটা নিরাপদভাবে সংরক্ষিত হয় এবং কখনোই তৃতীয় পক্ষের সঙ্গে শেয়ার করা হয় না। চাইলে আপনি নিজের সার্ভারে Reactive Resume নিজে হোস্ট করেও ডেটার পূর্ণ নিয়ন্ত্রণ রাখতে পারেন।"
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "আপনার পাসওয়ার্ড সফলভাবে রিসেট হয়েছে। এখন আপনি নতুন পাসওয়ার্ড দিয়ে সাইন ইন করতে পারবেন।"
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ca\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Catalan\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Sincronització d'habilitats fallida"
|
||||
msgid "Features"
|
||||
msgstr "Funcions"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtra per"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Llista ordenada"
|
||||
msgid "Organization"
|
||||
msgstr "Organització"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Període total"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Títol global (opcional)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Pàgina"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Actualitza"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Recordeu la contrasenya? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "A distància"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Identificador llegible (slug)"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Alguna cosa ha anat malament. Torna-ho a provar."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Ordena per"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Les dades es desen localment"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Les dades s’emmagatzemen de manera segura i mai no es comparteixen amb tercers. També pots autoallotjar Reactive Resume als teus propis servidors per tenir un control total sobre les dades."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "La contrasenya s’ha restablert correctament. Ara ja pots iniciar sessió amb la contrasenya nova."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: cs\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Czech\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Nepodařilo se synchronizovat dovednosti"
|
||||
msgid "Features"
|
||||
msgstr "Funkce"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrovat podle"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Číslovaný seznam"
|
||||
msgid "Organization"
|
||||
msgstr "Organizace"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Celkové období"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Celkový titul (volitelné)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Stránka"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Obnovit"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Vzpomínáte si na heslo? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Vzdálený"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Něco se pokazilo. Zkuste to prosím znovu."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Seřadit podle"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Vaše data jsou ukládána lokálně"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Vaše data jsou ukládána bezpečně a nikdy nejsou sdílena s třetími stranami. Reactive Resume si můžete také hostovat sami na vlastních serverech a mít tak nad svými daty plnou kontrolu."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Vaše heslo bylo úspěšně obnoveno. Nyní se můžete přihlásit pomocí nového hesla."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: da\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Danish\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Kunne ikke synkronisere færdigheder"
|
||||
msgid "Features"
|
||||
msgstr "Funktioner"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrér efter"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Nummereret liste"
|
||||
msgid "Organization"
|
||||
msgstr "Organisation"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Samlet periode"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Overordnet titel (valgfrit)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Side"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Opdater"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Husker du din adgangskode? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Fjernbetjening"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "URL-segment"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Noget gik galt. Prøv igen."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sortér efter"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Dine data gemmes lokalt"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Dine data lagres sikkert og deles aldrig med tredjeparter. Du kan også selv-hoste Reactive Resume på dine egne servere for fuld kontrol over dine data."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Din adgangskode er blevet nulstillet. Du kan nu logge ind med din nye adgangskode."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: de\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: German\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Synchronisierung der Fähigkeiten fehlgeschlagen"
|
||||
msgid "Features"
|
||||
msgstr "Funktionen"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtern nach"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Nummerierte Liste"
|
||||
msgid "Organization"
|
||||
msgstr "Organisation"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Gesamtzeitraum"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Gesamttitel (optional)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Seite"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Aktualisieren"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Passwort noch parat? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Fernbedienung"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sortieren nach"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Deine Daten werden lokal gespeichert"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Deine Daten werden sicher gespeichert und niemals an Dritte weitergegeben. Du kannst Reactive Resume außerdem auf deinen eigenen Servern selbst hosten, um die vollständige Kontrolle über deine Daten zu behalten."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Ihr Passwort wurde erfolgreich zurückgesetzt. Sie können sich nun mit Ihrem neuen Passwort anmelden."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: el\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Greek\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Αποτυχία συγχρονισμού δεξιοτήτων"
|
||||
msgid "Features"
|
||||
msgstr "Λειτουργίες"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Φιλτράρισμα κατά"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Αριθμημένη λίστα"
|
||||
msgid "Organization"
|
||||
msgstr "Οργανισμός"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Συνολική περίοδος"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Γενικός τίτλος (προαιρετικό)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Σελίδα"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Ανανέωση"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Θυμάστε τον κωδικό σας; <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Απομακρυσμένο"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Κάτι πήγε στραβά. Παρακαλώ δοκιμάστε ξανά."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Ταξινόμηση κατά"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Τα δεδομένα σας αποθηκεύονται τοπικά"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Τα δεδομένα σας αποθηκεύονται με ασφάλεια και δεν κοινοποιούνται ποτέ σε τρίτους. Μπορείτε επίσης να φιλοξενήσετε μόνοι σας το Reactive Resume στους δικούς σας διακομιστές για πλήρη έλεγχο των δεδομένων σας."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Ο κωδικός πρόσβασής σας επαναφέρθηκε με επιτυχία. Τώρα μπορείτε να συνδεθείτε με τον νέο σας κωδικό πρόσβασης."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: en_GB\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: English, United Kingdom\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Failed to sync skills"
|
||||
msgid "Features"
|
||||
msgstr "Features"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filter by"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Ordered List"
|
||||
msgid "Organization"
|
||||
msgstr "Organisation"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Overall Period"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Overall Title (optional)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Page"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Refresh"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Remember your password? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Remote"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Something went wrong. Please try again."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sort by"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Your data is stored locally"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Your password has been reset successfully. You can now sign in with your new password."
|
||||
|
||||
Generated
+7
-9
@@ -1229,6 +1229,7 @@ msgstr "Failed to sync skills"
|
||||
msgid "Features"
|
||||
msgstr "Features"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filter by"
|
||||
@@ -1906,14 +1907,6 @@ msgstr "Ordered List"
|
||||
msgid "Organization"
|
||||
msgstr "Organization"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Overall Period"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Overall Title (optional)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Page"
|
||||
@@ -2162,9 +2155,9 @@ msgstr "Refresh"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Remember your password? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Remote"
|
||||
|
||||
@@ -2512,6 +2505,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Something went wrong. Please try again."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sort by"
|
||||
@@ -3181,6 +3175,10 @@ msgstr "Your data is stored locally"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Your password has been reset successfully. You can now sign in with your new password."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: es\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Spanish\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Fallo en la sincronización de habilidades"
|
||||
msgid "Features"
|
||||
msgstr "Funciones"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrar por"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Lista ordenada"
|
||||
msgid "Organization"
|
||||
msgstr "Organización"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Periodo general"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Título general (opcional)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Página"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Actualizar"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "¿Recuerdas tu contraseña? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Remoto"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Algo salió mal. Vuelve a intentarlo."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Ordenar por"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Tus datos se almacenan localmente"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Tus datos se almacenan de forma segura y nunca se comparten con terceros. También puedes auto alojar Reactive Resume en tus propios servidores para tener un control total sobre tus datos."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Tu contraseña se ha restablecido correctamente. Ahora puedes iniciar sesión con tu nueva contraseña."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: fa\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Persian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "همگامسازی مهارتها ناموفق بود"
|
||||
msgid "Features"
|
||||
msgstr "امکانات"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "فیلتر بر اساس"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "فهرست شمارهدار"
|
||||
msgid "Organization"
|
||||
msgstr "سازمان"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "دوره کلی"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "عنوان کلی (اختیاری)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "صفحه"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "تازهسازی"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "رمز عبور را به خاطر دارید؟ <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "از راه دور"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "نام یکتا"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "مشکلی پیش آمد. لطفاً دوباره تلاش کنید."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "مرتبسازی بر اساس"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "دادههای شما بهصورت محلی ذخیره میشو
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "دادههای شما بهطور ایمن ذخیره شده و هرگز با اشخاص ثالث به اشتراک گذاشته نمیشوند. همچنین میتوانید Reactive Resume را روی سرورهای خود میزبانی کنید تا کنترل کامل بر دادههای خود داشته باشید."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "گذرواژهٔ شما با موفقیت تنظیم مجدد شد. اکنون میتوانید با گذرواژهٔ جدید خود وارد شوید."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: fi\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Finnish\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Taitojen synkronointi epäonnistui"
|
||||
msgid "Features"
|
||||
msgstr "Ominaisuudet"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Suodata"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Numeroitu lista"
|
||||
msgid "Organization"
|
||||
msgstr "Organisaatio"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Kokonaisajanjakso"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Yleinen nimike (valinnainen)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Sivu"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Päivitä"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Muistatko salasanasi? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Kaukosäädin"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Polkutunnus"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Jokin meni pieleen. Yritä uudelleen."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Lajittele"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Tietosi tallennetaan paikallisesti"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Tietosi tallennetaan turvallisesti eikä niitä koskaan jaeta kolmansille osapuolille. Voit myös itseisännöidä Reactive Resumen omilla palvelimillasi täydellisen tietokontrollin takaamiseksi."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Salasanasi on palautettu onnistuneesti. Voit nyt kirjautua sisään uudella salasanallasi."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: fr\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-22 11:27\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: French\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Échec de la synchronisation des compétences"
|
||||
msgid "Features"
|
||||
msgstr "Fonctionnalités"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrer par"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Liste triée"
|
||||
msgid "Organization"
|
||||
msgstr "Organisation"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Période globale"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Titre global (optionnel)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Page"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Actualiser"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Vous vous souvenez de votre mot de passe ? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "A distance"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Une erreur s'est produite. Veuillez réessayer."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Trier par"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Vos données sont stockées localement"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Vos données sont stockées en toute sécurité et ne sont jamais partagées avec des tiers. Vous pouvez également héberger Reactive Resume sur vos propres serveurs pour un contrôle total de vos données."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Votre mot de passe a été réinitialisé avec succès. Vous pouvez maintenant vous connecter avec votre nouveau mot de passe."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: he\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\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"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "לא הצליח לסנכרן מיומנויות"
|
||||
msgid "Features"
|
||||
msgstr "יכולות"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "סינון לפי"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "רשימה ממוספרת"
|
||||
msgid "Organization"
|
||||
msgstr "ארגון"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "תקופה כוללת"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "כותרת כוללת (רשות)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "עמוד"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "רענון"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "זוכר את הסיסמה? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "מרחוק"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "שם ייצוגי"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "משהו השתבש. נא לנסות שוב."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "מיון לפי"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "הנתונים שלך מאוחסנים באופן מקומי"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "הנתונים שלך מאוחסנים בצורה מאובטחת ולעולם אינם משותפים עם צדדים שלישיים. אפשר גם לארח את Reactive Resume בשרתים שלך כדי לשלוט לחלוטין בנתונים שלך."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "הסיסמה שלך אופסה בהצלחה. כעת אפשר להתחבר עם הסיסמה החדשה שלך."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: hi\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Hindi\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "कौशल सिंक करने में असफल"
|
||||
msgid "Features"
|
||||
msgstr "विशेषताएँ"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "फ़िल्टर करें"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "क्रमबद्ध सूची"
|
||||
msgid "Organization"
|
||||
msgstr "संगठन"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "कुल अवधि"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "समग्र शीर्षक (वैकल्पिक)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "पृष्ठ"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "रिफ़्रेश"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "अपना पासवर्ड याद है? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "दूरस्थ"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "काउंटर"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "कुछ गड़बड़ हो गई। कृपया फिर से प्रयास करें।"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "क्रमबद्ध करें"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "आपका डेटा लोकल रूप से संग्र
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "आपका डेटा सुरक्षित रूप से संग्रहीत है और कभी भी थर्ड पार्टियों के साथ साझा नहीं किया जाता। आप अपने सर्वर्स पर Reactive Resume को स्व‑होस्ट भी कर सकते हैं ताकि अपने डेटा पर पूर्ण नियंत्रण रख सकें।"
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "आपका पासवर्ड सफलतापूर्वक रीसेट कर दिया गया है। अब आप अपने नए पासवर्ड से साइन इन कर सकते हैं।"
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: hu\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Hungarian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Nem sikerült szinkronizálni a készségeket"
|
||||
msgid "Features"
|
||||
msgstr "Funkciók"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Szűrés alapja"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Sorszámozott lista"
|
||||
msgid "Organization"
|
||||
msgstr "Szervezet"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Teljes időszak"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Teljes cím (opcionális)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Oldal"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Frissítés"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Emlékszik a jelszavára? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Távoli"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Keresőbarát azonosító"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Valami hiba történt. Kérjük, próbáld újra."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Rendezés alapja"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Az adataid helyben tárolódnak"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Az adataid biztonságosan tároljuk, és soha nem osztjuk meg harmadik felekkel. A Reactive Resume‑t saját szervereiden is hosztolhatod, hogy teljes kontrollod legyen az adataid felett."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "A jelszavadat sikeresen visszaállítottuk. Mostantól az új jelszóval jelentkezhetsz be."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: id\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Indonesian\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Gagal menyinkronkan keterampilan"
|
||||
msgid "Features"
|
||||
msgstr "Fitur"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filter berdasarkan"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Daftar Bernomor"
|
||||
msgid "Organization"
|
||||
msgstr "Organisasi"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Periode Keseluruhan"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Judul Keseluruhan (opsional)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Halaman"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Muat Ulang"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Ingat kata sandi Anda? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Jarak jauh"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Terjadi sesuatu yang salah. Silakan coba lagi."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Urutkan berdasarkan"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Data Anda disimpan secara lokal"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Data Anda disimpan dengan aman dan tidak pernah dibagikan dengan pihak ketiga. Anda juga dapat self-host Reactive Resume di server Anda sendiri untuk kontrol penuh atas data Anda."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Kata sandi Anda telah berhasil diatur ulang. Anda sekarang dapat masuk dengan kata sandi baru Anda."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: it\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Italian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Impossibile sincronizzare le competenze"
|
||||
msgid "Features"
|
||||
msgstr "Funzionalità"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtra per"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Elenco numerato"
|
||||
msgid "Organization"
|
||||
msgstr "Organizzazione"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Periodo complessivo"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Titolo complessivo (opzionale)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Pagina"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Aggiorna"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Ricordi la tua password? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Remoto"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Qualcosa è andato storto. Riprova."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Ordina per"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "I tuoi dati vengono memorizzati localmente"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "I tuoi dati sono archiviati in modo sicuro e non vengono mai condivisi con terze parti. Puoi anche fare self-host di Reactive Resume sui tuoi server per avere il pieno controllo dei tuoi dati."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "La tua password è stata reimpostata correttamente. Ora puoi accedere con la tua nuova password."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ja\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Japanese\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "スキルの同期に失敗"
|
||||
msgid "Features"
|
||||
msgstr "機能"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "絞り込み条件"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "番号付きリスト"
|
||||
msgid "Organization"
|
||||
msgstr "団体名"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "全体の期間"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "全体タイトル(任意)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "ページ"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "再読み込み"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "パスワードを思い出しましたか? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "リモート"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "スラッグ"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "問題が発生しました。もう一度お試しください。"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "並べ替え条件"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "あなたのデータはローカルに保存されます。"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "あなたのデータは安全に保存され、第三者と共有されることはありません。また、完全にデータを管理したい場合は、Reactive Resume を自分のサーバーにセルフホストすることもできます。"
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "パスワードを正常にリセットしました。新しいパスワードでサインインできます。"
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: km\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Khmer\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr ""
|
||||
msgid "Features"
|
||||
msgstr "មុខងារ"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "ត្រងតាម"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "បញ្ជីមានលេខ"
|
||||
msgid "Organization"
|
||||
msgstr "អង្គការ"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "រយៈពេលទាំងមូល"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "ចំណងជើងទាំងមូល (ជាជម្រើស)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "ទំព័រ"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "ផ្ទៀងផ្ទាត់ម្ដងទៀត"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "ចាំពាក្យសម្ងាត់របស់អ្នក? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr ""
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "មានអ្វីមួយខុសប្រក្រតី។ សូមព្យាយាមម្ដងទៀត។"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "តម្រៀបតាម"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "ទិន្នន័យរបស់អ្នកត្រូវ
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "ទិន្នន័យរបស់អ្នកត្រូវបានរក្សាទុកដោយសុវត្ថិភាព ហើយមិនដែលត្រូវបានចែករំលែកជាមួយភាគីទីបីទេ។ អ្នកក៏អាចដំឡើង Reactive Resume លើម៉ាស៊ីនបម្រើផ្ទាល់ខ្លួនរបស់អ្នក ដើម្បីមានសិទ្ធિត្រួតត្រាលើទិន្នន័យរបស់អ្នកដល់ខ្ពស់បំផុតផងដែរ។"
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "ពាក្យសម្ងាត់របស់អ្នកត្រូវបានកំណត់ឡើងវិញដោយជោគជ័យ។ ឥឡូវអ្នកអាចចូលដោយប្រើពាក្យសម្ងាត់ថ្មីរបស់អ្នកបានហើយ។"
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: kn\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Kannada\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr ""
|
||||
msgid "Features"
|
||||
msgstr "ವೈಶಿಷ್ಟ್ಯಗಳು"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "ಫಿಲ್ಟರ್ ಆಧಾರಿತವಾಗಿ"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "ಕ್ರಮಿತ ಪಟ್ಟ್ತಿ"
|
||||
msgid "Organization"
|
||||
msgstr "ಸಂಸ್ಥೆ"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "ಒಟ್ಟಾರೆ ಅವಧಿ"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "ಒಟ್ಟಾರೆ ಶೀರ್ಷಿಕೆ (ಐಚ್ಛಿಕ)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "ಪುಟ"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "ರಿಫ್ರೆಶ್ ಮಾಡಿ"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "ನಿಮ್ಮ ಪಾಸ್ವರ್ಡ್ ನೆನಪಿದೆಯೇ? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr ""
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "ಸ್ಲಗ್"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "ಏನೋ ತಪ್ಪಾಗಿದೆ. ದಯವಿಟ್ಟು ಮರುಪ್ರಯತ್ನಿಸಿ."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "ವಿನ್ಯಾಸ ಆಧಾರದ ಮೇಲೆ ವಿಂಗಡಿಸಿ"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಸ್ಥಳೀಯವಾಗ
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ ಮತ್ತು ಎಂದಿಗೂ ತೃತೀಯಪಕ್ಷಗಳೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಲಾಗುವುದಿಲ್ಲ. ನಿಮ್ಮ ಡೇಟಾದ ಮೇಲೆ ಸಂಪೂರ್ಣ ನಿಯಂತ್ರಣಕ್ಕಾಗಿ ನಿಮ್ಮದೇ ಸರ್ವರ್ಗಳಲ್ಲಿ Reactive Resume ಅನ್ನು ಸ್ವಯಂ-ಹೋಸ್ಟ್ ಮಾಡಬಹುದು."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "ನಿಮ್ಮ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಮರುಹೊಂದಿಸಲಾಗಿದೆ. ಈಗ ನೀವು ನಿಮ್ಮ ಹೊಸ ಪಾಸ್ವರ್ಡ್ ಬಳಸಿಕೊಂಡು ಸೈನ್ ಇನ್ ಮಾಡಬಹುದು."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ko\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Korean\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "스킬 동기화에 실패했습니다."
|
||||
msgid "Features"
|
||||
msgstr "기능"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "다음 기준으로 필터링"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "번호 매기기 목록"
|
||||
msgid "Organization"
|
||||
msgstr "기관"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "전체 기간"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "전체 제목 (선택 사항)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "페이지"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "새로고침"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "비밀번호가 기억나시나요? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "원격"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "슬러그"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "문제가 발생했습니다. 다시 시도해 주세요."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "정렬 기준"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "데이터는 브라우저에 로컬로 저장됩니다"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "데이터는 안전하게 저장되며 제3자와 공유되지 않습니다. 또한 Reactive Resume를 직접 서버에 호스팅해 데이터에 대한 완전한 제어권을 가질 수 있습니다."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "비밀번호가 성공적으로 재설정되었습니다. 이제 새 비밀번호로 로그인할 수 있습니다."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: lt\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\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"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Nepavyko sinchronizuoti įgūdžių"
|
||||
msgid "Features"
|
||||
msgstr "Funkcijos"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtruoti pagal"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Sunumeruotas sąrašas"
|
||||
msgid "Organization"
|
||||
msgstr "Organizacija"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Bendras laikotarpis"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Bendrasis pavadinimas (neprivaloma)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Puslapis"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Perkrauti"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Prisimenate slaptažodį? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Nuotolinis"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Nuorodos dalis"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Kažkas nepavyko. Bandykite dar kartą."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Rikiuoti pagal"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Jūsų duomenys saugomi vietoje"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Jūsų duomenys saugiai laikomi ir niekada nebendrinami su trečiosiomis šalimis. Taip pat galite savarankiškai talpinti „Reactive Resume“ savo serveriuose ir visiškai kontroliuoti savo duomenis."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Jūsų slaptažodis sėkmingai atstatytas. Dabar galite prisijungti naudodami naują slaptažodį."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: lv\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\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"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Neizdevās sinhronizēt prasmes"
|
||||
msgid "Features"
|
||||
msgstr "Funkcijas"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrēt pēc"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Numurēts saraksts"
|
||||
msgid "Organization"
|
||||
msgstr "Organizācija"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Kopējais periods"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Kopējais nosaukums (neobligāts)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Lapa"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Atsvaidzināt"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Atceraties paroli? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Tālvadības pults"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Tīmekļa adrese (slug)"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Kaut kas nogāja greizi. Lūdzu, mēģiniet vēlreiz."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Kārtot pēc"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Jūsu dati tiek glabāti lokāli"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Jūsu dati tiek glabāti droši un nekad netiek kopīgoti ar trešajām pusēm. Reactive Resume varat arī pašhostēt uz saviem serveriem, lai pilnībā kontrolētu savus datus."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Jūsu parole ir veiksmīgi atiestatīta. Tagad varat pieteikties ar jauno paroli."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ml\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Malayalam\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "നൈപുണ്യങ്ങൾ സിങ്ക് ചെയ്യു
|
||||
msgid "Features"
|
||||
msgstr "സവിശേഷതകൾ"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "ഫിൽറ്റർ ചെയ്യുക"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "ഓർഡേർഡ് ലിസ്റ്റ്"
|
||||
msgid "Organization"
|
||||
msgstr "സ്ഥാപനം"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "മൊത്തം കാലയളവ്"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "മൊത്തം ശീർഷകം (ഐച്ഛികം)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "പേജ്"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "റിഫ്രെഷ് ചെയ്യുക"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "നിങ്ങളുടെ പാസ്വേഡ് ഓർമ്മയുണ്ടോ? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "ദൂരസ്ഥ"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "സ്ലഗ്"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "എന്തോ പിശക് സംഭവിച്ചു. ദയവായി വീണ്ടും ശ്രമിക്കുക."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "സോർട്ട് ചെയ്യുക"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "നിങ്ങളുടെ ഡാറ്റ നിങ്ങളുടെ
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "നിങ്ങളുടെ ഡാറ്റ സുരക്ഷിതമായി സൂക്ഷിക്കപ്പെടുന്നു, ഒരിക്കലും മൂന്നാം കക്ഷികളുമായി പങ്കിടുന്നില്ല. നിങ്ങളുടെ ഡാറ്റയ്ക്ക് പൂർണ്ണ നിയന്ത്രണം നേടാൻ Reactive Resume നിങ്ങളുടെ സ്വന്തം സെർവറുകളിൽ സെൽഫ്‑ഹോസ്റ്റ് ചെയ്യാനും നിങ്ങൾക്ക് കഴിയും."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "നിങ്ങളുടെ പാസ്വേഡ് വിജയകരമായി റീസെറ്റ് ചെയ്തിട്ടുണ്ട്. ഇനി നിങ്ങൾക്ക് പുതിയ പാസ്വേഡ് ഉപയോഗിച്ച് സൈൻ ഇൻ ചെയ്യാം."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: mr\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Marathi\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "कौशल्ये समक्रमित करण्यात अ
|
||||
msgid "Features"
|
||||
msgstr "वैशिष्ट्ये"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "यावरून फिल्टर करा"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "क्रमबद्ध यादी"
|
||||
msgid "Organization"
|
||||
msgstr "संघटना"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "एकूण कालावधी"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "एकूण शीर्षक (पर्यायी)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "पान"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "ताजेतवाने करा"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "तुमचा पासवर्ड आठवतो? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "दूरस्थ"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "युआरएल"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "काही तरी चूक झाली. कृपया पुन्हा प्रयत्न करा."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "यावरून क्रम लावा"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "तुमचा डेटा लोकली साठवला जा
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "तुमचा डेटा सुरक्षितपणे साठवला जातो आणि तृतीय पक्षांसोबत कधीही शेअर केला जात नाही. तुम्ही पूर्ण डेटा कंट्रोलसाठी Reactive Resume स्वतःच्या सर्व्हरवरही होस्ट करू शकता."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "तुमचा पासवर्ड यशस्वीरित्या रिसेट केला गेला आहे. तुम्ही आता नवीन पासवर्डने साइन इन करू शकता."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ms\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Malay\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Gagal menyegerakkan kemahiran"
|
||||
msgid "Features"
|
||||
msgstr "Ciri"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Tapis mengikut"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Senarai Bernombor"
|
||||
msgid "Organization"
|
||||
msgstr "Organisasi"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Tempoh Keseluruhan"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Tajuk Keseluruhan (pilihan)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Halaman"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Muat semula"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Ingat kata laluan anda? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Jauh"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Ada sesuatu yang tidak kena. Sila cuba lagi."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Isih mengikut"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Data anda disimpan secara setempat"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Data anda disimpan dengan selamat dan tidak pernah dikongsi dengan pihak ketiga. Anda juga boleh menghoskan sendiri Reactive Resume pada pelayan anda untuk kawalan penuh ke atas data anda."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Kata laluan anda telah berjaya ditetapkan semula. Anda kini boleh log masuk dengan kata laluan baharu anda."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ne\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Nepali\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "कौशलहरू सिङ्क गर्न असफल भय
|
||||
msgid "Features"
|
||||
msgstr "विशेषताहरू"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "यसद्वारा फिल्टर गर्नुहोस्"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "क्रमबद्ध सूची"
|
||||
msgid "Organization"
|
||||
msgstr "संस्था"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "समग्र अवधि"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "समग्र शीर्षक (ऐच्छिक)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "पृष्ठ"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "रिफ्रेस गर्नुहोस्"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "पासवर्ड सम्झनुभयो? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "दूरस्थ"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "स्लग"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "केही समस्या भयो। कृपया पुनः प्रयास गर्नुहोस्।"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "यसअनुसार क्रमबद्ध गर्नुहोस्"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "तपाईंको डाटा स्थानीय रूपमा
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "तपाईंको डाटा सुरक्षित रूपमा भण्डारण गरिएको छ र तेस्रो पक्षसँग कहिल्यै सेयर गरिँदैन। तपाईंले चाहनु भएमा आफ्नै सर्भरमा Reactive Resume लाई self-host गरेर आफ्नो डाटामा पूर्ण नियन्त्रण राख्न सक्नुहुन्छ।"
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "तपाईंको पासवर्ड सफलतापूर्वक रिसेट भयो। अब नयाँ पासवर्ड प्रयोग गरेर साइन इन गर्न सक्नुहुन्छ।"
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: nl\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Dutch\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Synchronisatie van vaardigheden mislukt"
|
||||
msgid "Features"
|
||||
msgstr "Functies"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filteren op"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Genummerde lijst"
|
||||
msgid "Organization"
|
||||
msgstr "Organisatie"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Totale periode"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Algemene titel (optioneel)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Pagina"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Vernieuwen"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Wachtwoord nog weten? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Op afstand"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Korte naam"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Er is iets misgegaan. Probeer het alstublieft opnieuw."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sorteren op"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Uw gegevens worden lokaal opgeslagen"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Uw gegevens worden veilig opgeslagen en nooit met derden gedeeld. U kunt Reactive Resume ook zelf op uw eigen servers hosten voor volledige controle over uw gegevens."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Uw wachtwoord is succesvol gereset. U kunt nu met uw nieuwe wachtwoord inloggen."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: no\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Norwegian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr ""
|
||||
msgid "Features"
|
||||
msgstr "Funksjoner"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrer etter"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Nummerert liste"
|
||||
msgid "Organization"
|
||||
msgstr "Organisasjon"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Samlet periode"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Overordnet tittel (valgfritt)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Side"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Oppdater"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Husker du passordet ditt? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr ""
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Forkortelse"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Noe gikk galt. Vennligst prøv igjen."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sorter etter"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Dataene dine lagres lokalt"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Dataene dine lagres sikkert og deles aldri med tredjeparter. Du kan også selv-hoste Reactive Resume på egne servere for full kontroll over dataene dine."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Passordet ditt er tilbakestilt. Du kan nå logge inn med det nye passordet ditt."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: or\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Odia\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr ""
|
||||
msgid "Features"
|
||||
msgstr "ବିଶେଷତାଗୁଡିକ"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "ଏହା ଦ୍ୱାରା ଫିଲ୍ଟର୍ କରନ୍ତୁ"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "କ୍ରମିକ ତାଲିକା"
|
||||
msgid "Organization"
|
||||
msgstr "ସଂଗଠନ"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "ସାମଗ୍ରିକ ସମୟସୀମା"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "ସାମଗ୍ରିକ ଶୀର୍ଷକ (ଐଚ୍ଛିକ)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "ପେଜ୍"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "ରିଫ୍ରେଶ କରନ୍ତୁ"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "ଆପଣଙ୍କ ପାସୱାର୍ଡ ମନେ ଅଛି? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr ""
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "ସ୍ଲଗ୍"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "କିଛି ଭୁଲ୍ ହୋଇଛି। ଦୟାକରି ପୁନଃ ଚେଷ୍ଟା କରନ୍ତୁ।"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "ଏହା ଦ୍ୱାରା ସଜାଇବେ"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "ଆପଣଙ୍କ ତଥ୍ୟ ସ୍ଥାନୀୟ ଭାବରେ
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "ଆପଣଙ୍କ ତଥ୍ୟ ସୁରକ୍ଷିତ ଭାବରେ ସଞ୍ଚୟ ହୋଇଛି ଏବଂ କେବେ ମଧ୍ୟ ତୃତୀୟ ପକ୍ଷ ସହ ସେୟାର ହୋଇନାହିଁ। ଆପଣ ଆପଣଙ୍କ ତଥ୍ୟ ଉପରେ ପୂର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣ ପାଇଁ ଆପଣଙ୍କ ନିଜ ସର୍ଭରଗୁଡିକରେ Reactive Resume କୁ ସ୍ୱୟଂ‑ହୋଷ୍ଟ କରିପାରିବେ।"
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "ଆପଣଙ୍କ ପାସୱାର୍ଡ ସଫଳତାର ସହ ପୁନଃ ସେଟ୍ କରାଯାଇଛି। ଆପଣ ଏବେ ନୂତନ ପାସୱାର୍ଡ ସହ ସାଇନ୍ ଇନ୍ କରିପାରିବେ।"
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: pl\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\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"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Nie udało się zsynchronizować umiejętności"
|
||||
msgid "Features"
|
||||
msgstr "Funkcje"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtruj według"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Lista numerowana"
|
||||
msgid "Organization"
|
||||
msgstr "Organizacja"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Okres ogólny"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Ogólny tytuł (opcjonalnie)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Strona"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Odśwież"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Pamiętasz hasło? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Zdalny"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Krótka nazwa"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Coś poszło nie tak. Spróbuj ponownie."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sortuj według"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Twoje dane są przechowywane lokalnie"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Twoje dane są przechowywane w bezpieczny sposób i nigdy nie są udostępniane podmiotom trzecim. Możesz też samodzielnie hostować Reactive Resume na własnych serwerach, aby mieć pełną kontrolę nad swoimi danymi."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Twoje hasło zostało pomyślnie zresetowane. Możesz teraz zalogować się przy użyciu nowego hasła."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: pt\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese, Brazilian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Falha na sincronização de habilidades"
|
||||
msgid "Features"
|
||||
msgstr "Recursos"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrar por"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Lista numerada"
|
||||
msgid "Organization"
|
||||
msgstr "Organização"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Período geral"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Título geral (opcional)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Página"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Atualizar"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Lembrou sua senha? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Remoto"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Permalink"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Algo deu errado. Tente novamente."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Ordenar por"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Seus dados são armazenados localmente"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Seus dados são armazenados com segurança e nunca são compartilhados com terceiros. Você também pode auto-hospedar o Reactive Resume em seus próprios servidores para ter controle total sobre seus dados."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Sua senha foi redefinida com sucesso. Agora você pode entrar com sua nova senha."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: pt\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Falha na sincronização de competências"
|
||||
msgid "Features"
|
||||
msgstr "Funcionalidades"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrar por"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Lista ordenada"
|
||||
msgid "Organization"
|
||||
msgstr "Organização"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Período geral"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Título geral (opcional)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Página"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Recarregar"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Lembra-se da sua palavra-passe? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Remoto"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Algo correu mal. Tente novamente."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Ordenar por"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Os seus dados são armazenados localmente"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Os seus dados são armazenados em segurança e nunca são partilhados com terceiros. Também pode auto-hospedar o Reactive Resume nos seus próprios servidores para ter controlo total sobre os seus dados."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "A sua senha foi reposta com sucesso. Já pode iniciar sessão com a sua nova senha."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ro\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\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"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "A eșuat sincronizarea competențelor"
|
||||
msgid "Features"
|
||||
msgstr "Funcționalități"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrați după"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Listă ordonată"
|
||||
msgid "Organization"
|
||||
msgstr "Organizație"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Perioadă generală"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Titlu general (opțional)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Pagină"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Reîncarcă"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Îți amintești parola? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "La distanță"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Ceva nu a funcționat. Vă rugăm să încercați din nou."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sortați după"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Datele dvs. sunt stocate local"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Datele dvs. sunt stocate în siguranță și nu sunt niciodată partajate cu terți. De asemenea, puteți auto-găzdui Reactive Resume pe propriile servere pentru control complet asupra datelor."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Parola a fost resetată cu succes. Vă puteți autentifica acum cu noua parolă."
|
||||
|
||||
Generated
+9
-11
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ru\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:15\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"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Не удалось синхронизировать навыки"
|
||||
msgid "Features"
|
||||
msgstr "Возможности"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Фильтровать по"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Нумерованный список"
|
||||
msgid "Organization"
|
||||
msgstr "Организация"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Общий период"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Общее название (необязательно)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Страница"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Обновить"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Вспомнили пароль? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Удаленный"
|
||||
|
||||
@@ -2505,7 +2498,7 @@ msgstr "Словацкий"
|
||||
|
||||
#: src/utils/locale.ts
|
||||
msgid "Slovenian"
|
||||
msgstr ""
|
||||
msgstr "Английский"
|
||||
|
||||
#: src/dialogs/resume/index.tsx
|
||||
msgid "Slug"
|
||||
@@ -2517,6 +2510,7 @@ msgstr "URL"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Что-то пошло не так. Пожалуйста, попробуйте еще раз."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Сортировать по"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Ваши данные хранятся локально"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Ваши данные надежно хранятся и никогда не передаются третьим лицам. Вы также можете развернуть Reactive Resume на своих серверах, чтобы полностью контролировать свои данные."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Ваш пароль был успешно сброшен. Теперь вы можете войти с новым паролем."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: sk\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Slovak\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Nepodarilo sa synchronizovať zručnosti"
|
||||
msgid "Features"
|
||||
msgstr "Funkcie"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrovať podľa"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Číslovaný zoznam"
|
||||
msgid "Organization"
|
||||
msgstr "Organizácia"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Celkové obdobie"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Celkový titul (voliteľné)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Strana"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Obnoviť"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Pamätáte si heslo? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Vzdialená adresa"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Niečo sa pokazilo. Skús to, prosím, znova."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Zoradiť podľa"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Tvoje dáta sú uložené lokálne"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Tvoje dáta sú bezpečne uložené a nikdy sa nezdieľajú s tretími stranami. Reactive Resume si môžeš tiež hostovať na vlastných serveroch a mať nad dátami úplnú kontrolu."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Tvoje heslo bolo úspešne obnovené. Teraz sa môžeš prihlásiť s novým heslom."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: sl\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\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"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Ni uspelo sinhronizirati veščin"
|
||||
msgid "Features"
|
||||
msgstr "Funkcionalnosti"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtriraj po"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Oštevilčen seznam"
|
||||
msgid "Organization"
|
||||
msgstr "Organizacija"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Skupno obdobje"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Skupni naziv (neobvezno)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Stran"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Osveži"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Oddaljena stran"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Polž"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Nekaj je šlo narobe. Prosimo, poskusite znova."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Razvrsti po"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Vaši podatki so shranjeni lokalno"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Vaši podatki so varno shranjeni in se nikoli ne delijo s tretjimi osebami. Reactive Življenjepis lahko tudi gostite sami na svojih strežnikih za popoln nadzor nad svojimi podatki."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Vaše geslo je bilo uspešno ponastavljeno. Zdaj se lahko prijavite z novim geslom."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: sq\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Albanian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Dështoi sinkronizimi i aftësive"
|
||||
msgid "Features"
|
||||
msgstr "Veçori"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtro sipas"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Listë e renditur"
|
||||
msgid "Organization"
|
||||
msgstr "Organizata"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Periudha e përgjithshme"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Titulli i përgjithshëm (opsional)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Faqja"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Rifresko"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Ju kujtohet fjalëkalimi? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Në distancë"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Linku i normalizuar"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Diçka shkoi keq. Ju lutemi provoni përsëri."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Rendit sipas"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Të dhënat tuaja ruhen lokalisht"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Të dhënat tuaja ruhen në mënyrë të sigurt dhe nuk ndahen kurrë me palë të treta. Ju gjithashtu mund ta self-host-oni Reactive Resume në serverët tuaj për kontroll të plotë mbi të dhënat tuaja."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Fjalëkalimi juaj u rivendos me sukses. Tani mund të hyni me fjalëkalimin tuaj të ri."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: sr\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\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"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Синхронизација вештина није успела"
|
||||
msgid "Features"
|
||||
msgstr "Функције"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Филтрирај по"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Нумерисана листа"
|
||||
msgid "Organization"
|
||||
msgstr "Организација"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Укупан период"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Укупна титула (опционо)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Страница"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Освежи"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Сећате се лозинке? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Даљински"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Идентификатор (slug)"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Нешто је пошло наопако. Покушајте поново."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Сортирај по"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Ваши подаци се чувају локално"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Ваши подаци се чувају безбедно и никада се не деле са трећим странама. Такође можете самостално хостовати Реактивни Резиме на сопственим серверима за потпуну контролу над подацима."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Ваша лозинка је успешно ресетована. Сада можете да се пријавите новом лозинком."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: sv\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Swedish\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Misslyckades med att synkronisera färdigheter"
|
||||
msgid "Features"
|
||||
msgstr "Funktioner"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrera efter"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Numrerad lista"
|
||||
msgid "Organization"
|
||||
msgstr "Organisation"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Övergripande period"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Övergripande titel (valfritt)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Sida"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Uppdatera"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Kommer du ihåg ditt lösenord? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Fjärrkontroll"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Något gick fel. Försök igen."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sortera efter"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Dina data lagras lokalt"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Dina data lagras säkert och delas aldrig med tredje part. Du kan också själv hosta Reactive Resume på dina egna servrar för full kontroll över dina data."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Ditt lösenord har återställts. Du kan nu logga in med ditt nya lösenord."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ta\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Tamil\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "திறன்களை ஒத்திசைக்கத் தவற
|
||||
msgid "Features"
|
||||
msgstr "அம்சங்கள்"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "இதன்படி வடிகட்டு"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "வரிசைப்படுத்தப்பட்ட பட்ட
|
||||
msgid "Organization"
|
||||
msgstr "நிறுவனம் / அமைப்பு"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "ஒட்டுமொத்த காலம்"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "ஒட்டுமொத்த தலைப்பு (விருப்பத்தேர்வு)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "பக்கம்"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "மீண்டும் ஏற்று"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "உங்கள் கடவுச்சொல் நினைவிருக்கிறதா? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "தொலைநிலை"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "ஸ்லக்"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "ஏதோ தவறு நடந்துள்ளது. தயவுசெய்து மீண்டும் முயற்சிக்கவும்."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "இதன்படி வரிசைப்படுத்து"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "உங்கள் தரவு உங்கள் உலாவியி
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "உங்கள் தரவு பாதுகாப்பாக சேமிக்கப்படுகிறது மற்றும் மூன்றாம் தரப்புகளுடன் ஒருபோதும் பகிரப்படாது. உங்கள் தரவு மீது முழு கட்டுப்பாட்டிற்காக Reactive Resume-ஐ உங்கள் சொந்த சேவையகங்களில் தானே ஹோஸ்ட் செய்யவும் முடியும்."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "உங்கள் கடவுச்சொல் வெற்றிகரமாக மீட்டமைக்கப்பட்டுள்ளது. இப்போது உங்கள் புதிய கடவுச்சொல்லைப் பயன்படுத்தி உள்நுழையலாம்."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: te\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Telugu\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "నైపుణ్యాలను సింక్ చేయడంలో
|
||||
msgid "Features"
|
||||
msgstr "ఫీచర్లు"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "ద్వారా ఫిల్టర్ చేయండి"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "ఆర్డర్డ్ లిస్ట్"
|
||||
msgid "Organization"
|
||||
msgstr "ఆర్గనైజేషన్"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "మొత్తం కాలం"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "మొత్తం శీర్షిక (ఐచ్ఛికం)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "పేజ్"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "రిఫ్రెష్ చేయండి"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "మీ పాస్వర్డ్ గుర్తుందా? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "రిమోట్"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "స్లగ్"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "ఏదో తప్పు జరిగింది. దయచేసి మళ్లీ ప్రయత్నించండి."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "సორტ్ చేయండి"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "మీ డేటా లోకల్గా నిల్వ చేయ
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "మీ డేటా భద్రంగా నిల్వ చేయబడుతుంది, మూడవ పక్షాలతో ఎప్పుడూ పంచుకోబడదు. మీ డేటాపై పూర్తి నియంత్రణ కోసం మీరు Reactive Resumeను మీ సొంత సర్వర్లపై హోస్ట్ చేసుకోవచ్చు."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "మీ పాస్వర్డ్ విజయవంతంగా రీసెట్ చేయబడింది. ఇప్పుడు మీ కొత్త పాస్వర్డ్తో సైన్ ఇన్ చేయవచ్చు."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: th\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Thai\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "ไม่สามารถซิงค์ทักษะได้"
|
||||
msgid "Features"
|
||||
msgstr "คุณสมบัติ"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "กรองโดย"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "ลำดับรายการแบบเรียงลำดับ
|
||||
msgid "Organization"
|
||||
msgstr "องค์กร"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "ช่วงเวลาโดยรวม"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "ตำแหน่งโดยรวม (ไม่บังคับ)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "หน้า"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "รีเฟรช"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "จำรหัสผ่านได้? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "ระยะไกล"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "ชื่อ"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "เกิดข้อผิดพลาดบางอย่าง กรุณาลองใหม่อีกครั้ง"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "เรียงตาม"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "ข้อมูลของคุณถูกจัดเก็บไว
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "ข้อมูลของคุณถูกจัดเก็บไว้อย่างปลอดภัยและจะไม่ถูกแชร์กับบุคคลที่สาม คุณยังสามารถโฮสต์ Reactive Resume ด้วยตัวเองบนเซิร์ฟเวอร์ของคุณเพื่อควบคุมข้อมูลได้อย่างสมบูรณ์."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "รหัสผ่านของคุณถูกรีเซ็ตเรียบร้อยแล้ว ตอนนี้คุณสามารถเข้าสู่ระบบด้วยรหัสผ่านใหม่ของคุณได้."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: tr\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Turkish\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Beceriler senkronize edilemedi"
|
||||
msgid "Features"
|
||||
msgstr "Özellikler"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Filtrele"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Sıralı Liste"
|
||||
msgid "Organization"
|
||||
msgstr "Organizasyon"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Genel Dönem"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Genel Başlık (isteğe bağlı)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Sayfa"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Yenile"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Şifrenizi hatırladınız mı? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Uzaktan Kumanda"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Bir hata oluştu. Lütfen tekrar deneyin."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sırala"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Verileriniz yerel olarak depolanıyor"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Verileriniz güvenli bir şekilde saklanır ve asla üçüncü partilerle paylaşılmaz. Kendi sunucularınızda Reactive Resume'u barındırarak verileriniz üzerinde tam kontrol sahibi olabilirsiniz."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Şifreniz başarıyla sıfırlandı. Artık yeni şifrenizle giriş yapabilirsiniz."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: uk\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\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"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Не вдалося синхронізувати навички"
|
||||
msgid "Features"
|
||||
msgstr "Функції"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Фільтрувати за"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Нумерований список"
|
||||
msgid "Organization"
|
||||
msgstr "Організація"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Загальний період"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Загальна назва (необов'язково)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Сторінка"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Оновити"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Пригадали пароль? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Пульт дистанційного керування"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Посилання"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Щось пішло не так. Будь ласка, спробуйте ще раз."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Сортувати за"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Ваші дані зберігаються локально"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Ваші дані зберігаються безпечно і ніколи не передаються третім особам. Ви також можете самостійно розгорнути Reactive Resume на власних серверах для повного контролю над своїми даними."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Ваш пароль було успішно скинуто. Тепер ви можете увійти з новим паролем."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: uz\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:08\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Uzbek\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Mahoratlarni sinxronlashtirish muvaffaqiyatsiz bo'ldi"
|
||||
msgid "Features"
|
||||
msgstr "Xususiyatlar"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Saralash"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Tartibli roʻyxat"
|
||||
msgid "Organization"
|
||||
msgstr "Tashkilot"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Umumiy davr"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Umumiy sarlavha (ixtiyoriy)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Sahifa"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Yangilash"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Parolingizni eslaysizmi? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Masofaviy"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Nimadir xato ketdi. Iltimos, qayta urinib koʻring."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Saralash boʻyicha"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Maʼlumotlaringiz lokal tarzda saqlanadi"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Maʼlumotlaringiz xavfsiz saqlanadi va uchinchi tomonlarga hech qachon ulashilmaydi. Shuningdek, rezyume qurilmasini o‘z serverlaringizda mustaqil joylashtirishingiz va maʼlumotlaringiz ustidan to‘liq nazorat qilishingiz mumkin."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Parolingiz muvaffaqiyatli tiklandi. Endi yangi parolingiz bilan tizimga kirishingiz mumkin."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: vi\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Vietnamese\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "Không đồng bộ hóa được các kỹ năng"
|
||||
msgid "Features"
|
||||
msgstr "Tính năng"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "Lọc theo"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "Danh sách có thứ tự"
|
||||
msgid "Organization"
|
||||
msgstr "Tổ chức"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "Thời gian tổng thể"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "Chức danh tổng thể (tùy chọn)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "Trang"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "Làm mới"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "Nhớ mật khẩu? <0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "Từ xa"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "Slug"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "Đã xảy ra lỗi. Vui lòng thử lại."
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "Sắp xếp theo"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "Dữ liệu của bạn được lưu trữ cục bộ"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "Dữ liệu của bạn được lưu trữ an toàn và không bao giờ chia sẻ với bên thứ ba. Bạn cũng có thể tự host Reactive Resume trên máy chủ của riêng mình để kiểm soát hoàn toàn dữ liệu của mình."
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "Mật khẩu của bạn đã được đặt lại thành công. Bây giờ bạn có thể đăng nhập bằng mật khẩu mới."
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: zh\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "同步技能失败"
|
||||
msgid "Features"
|
||||
msgstr "功能"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "筛选条件"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "有序列表"
|
||||
msgid "Organization"
|
||||
msgstr "组织"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "总时间段"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "总标题(可选)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "页面"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "刷新"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "记得密码?<0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "远程"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "短链接"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "出现了一些问题。请重试。"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "排序方式"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "你的数据将存储在本地"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "你的数据会被安全存储,且绝不会与第三方共享。你也可以在自己的服务器上自托管 Reactive Resume,以完全掌控你的数据。"
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "你的密码已成功重置。你现在可以使用新密码登录。"
|
||||
|
||||
Generated
+8
-10
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: zh\n"
|
||||
"Project-Id-Version: reactive-resume\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-03-19 09:07\n"
|
||||
"PO-Revision-Date: 2026-03-29 21:05\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Traditional\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -1234,6 +1234,7 @@ msgstr "同步技能失敗"
|
||||
msgid "Features"
|
||||
msgstr "功能"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr "篩選條件"
|
||||
@@ -1911,14 +1912,6 @@ msgstr "編號清單"
|
||||
msgid "Organization"
|
||||
msgstr "組織"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr "整體期間"
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr "整體標題(選填)"
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr "頁"
|
||||
@@ -2167,9 +2160,9 @@ msgstr "重新整理"
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr "記得密碼?<0/>"
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr "遙控"
|
||||
|
||||
@@ -2517,6 +2510,7 @@ msgstr "標示碼"
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr "發生錯誤。請再試一次。"
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr "排序方式"
|
||||
@@ -3186,6 +3180,10 @@ msgstr "您的資料將儲存在本機裝置中"
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr "您的資料會被安全保存,且絕不會分享給第三方。您也可以在自有伺服器上自行託管 Reactive Resume,完全掌控自己的資料。"
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr "您的密碼已成功重設。您現在可以使用新密碼登入。"
|
||||
|
||||
Generated
+7
-9
@@ -1229,6 +1229,7 @@ msgstr ""
|
||||
msgid "Features"
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Filter by"
|
||||
msgstr ""
|
||||
@@ -1906,14 +1907,6 @@ msgstr ""
|
||||
msgid "Organization"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Period"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs/resume/sections/experience.tsx
|
||||
msgid "Overall Title (optional)"
|
||||
msgstr ""
|
||||
|
||||
#: src/utils/resume/section.tsx
|
||||
msgid "Page"
|
||||
msgstr ""
|
||||
@@ -2162,9 +2155,9 @@ msgstr ""
|
||||
msgid "Remember your password? <0/>"
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/dashboard/job-search/-components/job-card.tsx
|
||||
#: src/routes/dashboard/job-search/-components/job-detail.tsx
|
||||
#: src/routes/dashboard/job-search/-components/search-filters.tsx
|
||||
#: src/routes/dashboard/job-search/index.tsx
|
||||
msgid "Remote"
|
||||
msgstr ""
|
||||
|
||||
@@ -2512,6 +2505,7 @@ msgstr ""
|
||||
msgid "Something went wrong. Please try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
#: src/routes/dashboard/resumes/index.tsx
|
||||
msgid "Sort by"
|
||||
msgstr ""
|
||||
@@ -3181,6 +3175,10 @@ msgstr ""
|
||||
msgid "Your data is stored securely and is never shared with third parties. You can also self-host Reactive Resume on your own servers for complete control over your data."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/resume/store/resume.ts
|
||||
msgid "Your latest changes could not be saved. Please make sure you are connected to the internet and try again."
|
||||
msgstr ""
|
||||
|
||||
#: src/routes/auth/reset-password.tsx
|
||||
msgid "Your password has been reset successfully. You can now sign in with your new password."
|
||||
msgstr ""
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE "session" ADD COLUMN "impersonated_by" text;--> statement-breakpoint
|
||||
ALTER TABLE "user" ADD COLUMN "role" text DEFAULT 'user';--> statement-breakpoint
|
||||
ALTER TABLE "user" ADD COLUMN "banned" boolean DEFAULT false;--> statement-breakpoint
|
||||
ALTER TABLE "user" ADD COLUMN "ban_reason" text;--> statement-breakpoint
|
||||
ALTER TABLE "user" ADD COLUMN "ban_expires" timestamp(6) with time zone;
|
||||
File diff suppressed because it is too large
Load Diff
+48
-46
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "reactive-resume",
|
||||
"version": "5.0.14",
|
||||
"version": "5.0.16",
|
||||
"description": "Reactive Resume is a free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume.",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
@@ -31,13 +31,14 @@
|
||||
"preview": "vp preview",
|
||||
"start": "node .output/server/index.mjs",
|
||||
"test": "vp test",
|
||||
"test:coverage": "vp test --coverage --run",
|
||||
"typecheck": "tsgo --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "^3.0.64",
|
||||
"@ai-sdk/google": "^3.0.53",
|
||||
"@ai-sdk/openai": "^3.0.48",
|
||||
"@aws-sdk/client-s3": "^3.1015.0",
|
||||
"@ai-sdk/anthropic": "^3.0.66",
|
||||
"@ai-sdk/google": "^3.0.58",
|
||||
"@ai-sdk/openai": "^3.0.50",
|
||||
"@aws-sdk/client-s3": "^3.1024.0",
|
||||
"@base-ui/react": "^1.3.0",
|
||||
"@better-auth/api-key": "^1.5.6",
|
||||
"@better-auth/drizzle-adapter": "^1.5.6",
|
||||
@@ -48,34 +49,34 @@
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@fontsource-variable/ibm-plex-sans": "^5.2.8",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@lingui/core": "^5.9.3",
|
||||
"@lingui/react": "^5.9.3",
|
||||
"@modelcontextprotocol/sdk": "^1.27.1",
|
||||
"@lingui/core": "^5.9.4",
|
||||
"@lingui/react": "^5.9.4",
|
||||
"@modelcontextprotocol/sdk": "^1.29.0",
|
||||
"@monaco-editor/react": "4.8.0-rc.3",
|
||||
"@orpc/client": "^1.13.9",
|
||||
"@orpc/json-schema": "^1.13.9",
|
||||
"@orpc/openapi": "^1.13.9",
|
||||
"@orpc/server": "^1.13.9",
|
||||
"@orpc/tanstack-query": "^1.13.9",
|
||||
"@orpc/zod": "^1.13.9",
|
||||
"@orpc/client": "^1.13.13",
|
||||
"@orpc/json-schema": "^1.13.13",
|
||||
"@orpc/openapi": "^1.13.13",
|
||||
"@orpc/server": "^1.13.13",
|
||||
"@orpc/tanstack-query": "^1.13.13",
|
||||
"@orpc/zod": "^1.13.13",
|
||||
"@phosphor-icons/react": "^2.1.10",
|
||||
"@phosphor-icons/web": "^2.1.2",
|
||||
"@sindresorhus/slugify": "^3.0.0",
|
||||
"@t3-oss/env-core": "^0.13.11",
|
||||
"@tanstack/react-query": "^5.95.2",
|
||||
"@tanstack/react-router": "^1.168.3",
|
||||
"@tanstack/react-query": "^5.96.2",
|
||||
"@tanstack/react-router": "^1.168.10",
|
||||
"@tanstack/react-router-ssr-query": "^1.166.10",
|
||||
"@tanstack/react-start": "^1.167.5",
|
||||
"@tanstack/react-start": "^1.167.16",
|
||||
"@tanstack/zod-adapter": "^1.166.9",
|
||||
"@tiptap/extension-highlight": "^3.20.4",
|
||||
"@tiptap/extension-table": "^3.20.4",
|
||||
"@tiptap/extension-text-align": "^3.20.4",
|
||||
"@tiptap/pm": "^3.20.4",
|
||||
"@tiptap/react": "^3.20.4",
|
||||
"@tiptap/starter-kit": "^3.20.4",
|
||||
"@tiptap/extension-highlight": "^3.22.1",
|
||||
"@tiptap/extension-table": "^3.22.1",
|
||||
"@tiptap/extension-text-align": "^3.22.1",
|
||||
"@tiptap/pm": "^3.22.1",
|
||||
"@tiptap/react": "^3.22.1",
|
||||
"@tiptap/starter-kit": "^3.22.1",
|
||||
"@uiw/color-convert": "^2.9.6",
|
||||
"@uiw/react-color-colorful": "^2.9.6",
|
||||
"ai": "^6.0.137",
|
||||
"ai": "^6.0.146",
|
||||
"ai-sdk-ollama": "^3.8.2",
|
||||
"bcrypt": "^6.0.0",
|
||||
"better-auth": "^1.5.6",
|
||||
@@ -84,32 +85,32 @@
|
||||
"cmdk": "^1.1.1",
|
||||
"docx": "^9.6.1",
|
||||
"dompurify": "^3.3.3",
|
||||
"drizzle-orm": "1.0.0-beta.19",
|
||||
"drizzle-zod": "^1.0.0-beta.14-a36c63d",
|
||||
"drizzle-orm": "1.0.0-beta.20",
|
||||
"drizzle-zod": "1.0.0-beta.9-e89174b",
|
||||
"es-toolkit": "^1.45.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-json-patch": "^3.1.1",
|
||||
"fuse.js": "^7.1.0",
|
||||
"fuse.js": "^7.2.0",
|
||||
"immer": "^11.1.4",
|
||||
"js-cookie": "^3.0.5",
|
||||
"jsonrepair": "^3.13.3",
|
||||
"monaco-editor": "^0.55.1",
|
||||
"motion": "^12.38.0",
|
||||
"nodemailer": "^8.0.3",
|
||||
"nodemailer": "^8.0.4",
|
||||
"pg": "^8.20.0",
|
||||
"puppeteer-core": "^24.40.0",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-hook-form": "^7.72.0",
|
||||
"react-hook-form": "^7.72.1",
|
||||
"react-hotkeys-hook": "^5.2.4",
|
||||
"react-resizable-panels": "^4.7.5",
|
||||
"react-resizable-panels": "^4.9.0",
|
||||
"react-window": "^2.2.7",
|
||||
"react-zoom-pan-pinch": "^3.7.0",
|
||||
"shadcn": "^4.1.0",
|
||||
"shadcn": "^4.1.2",
|
||||
"sharp": "^0.34.5",
|
||||
"sonner": "^2.0.7",
|
||||
"srvx": "^0.11.13",
|
||||
"srvx": "^0.11.15",
|
||||
"tailwind-merge": "^3.5.0",
|
||||
"tailwindcss": "^4.2.2",
|
||||
"ts-pattern": "^5.9.0",
|
||||
@@ -124,36 +125,37 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.29.0",
|
||||
"@lingui/babel-plugin-lingui-macro": "^5.9.3",
|
||||
"@lingui/cli": "^5.9.3",
|
||||
"@lingui/vite-plugin": "^5.9.3",
|
||||
"@lingui/babel-plugin-lingui-macro": "^5.9.4",
|
||||
"@lingui/cli": "^5.9.4",
|
||||
"@lingui/vite-plugin": "^5.9.4",
|
||||
"@rolldown/plugin-babel": "^0.2.2",
|
||||
"@tailwindcss/vite": "^4.2.2",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@types/bcrypt": "^6.0.0",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^25.5.0",
|
||||
"@types/node": "^25.5.2",
|
||||
"@types/nodemailer": "^7.0.11",
|
||||
"@types/pg": "^8.20.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260324.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260404.1",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"@vitest/coverage-v8": "^4.1.2",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"drizzle-kit": "1.0.0-beta.19",
|
||||
"drizzle-kit": "1.0.0-beta.20",
|
||||
"happy-dom": "^20.8.9",
|
||||
"jose": "^6.2.2",
|
||||
"jsdom": "^29.0.1",
|
||||
"knip": "^6.0.4",
|
||||
"knip": "^6.3.0",
|
||||
"nitro": "3.0.260311-beta",
|
||||
"node-addon-api": "^8.6.0",
|
||||
"node-addon-api": "^8.7.0",
|
||||
"node-gyp": "^12.2.0",
|
||||
"npm-check-updates": "^19.6.5",
|
||||
"tsx": "^4.21.0",
|
||||
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
|
||||
"npm-check-updates": "^20.0.0",
|
||||
"vite": "npm:@voidzero-dev/vite-plus-core@^0.1.15",
|
||||
"vite-plugin-pwa": "^1.2.0",
|
||||
"vite-plus": "latest",
|
||||
"vitest": "npm:@voidzero-dev/vite-plus-test@latest"
|
||||
"vitest": "npm:@voidzero-dev/vite-plus-test@^0.1.15"
|
||||
},
|
||||
"packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be",
|
||||
"packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319",
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"@isaacs/brace-expansion": "^5.0.1",
|
||||
|
||||
Generated
+2369
-2053
File diff suppressed because it is too large
Load Diff
@@ -192,8 +192,7 @@ export async function migrateResumes() {
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
process.on("SIGINT", handleShutdown);
|
||||
process.on("SIGTERM", handleShutdown);
|
||||
process.on("exit", handleShutdown);
|
||||
|
||||
// Initialize the importer
|
||||
const importer = new ReactiveResumeV4JSONImporter();
|
||||
@@ -465,8 +464,7 @@ export async function migrateResumes() {
|
||||
}
|
||||
|
||||
// Remove signal handlers
|
||||
process.off("SIGINT", handleShutdown);
|
||||
process.off("SIGTERM", handleShutdown);
|
||||
process.off("exit", handleShutdown);
|
||||
|
||||
const migrationEnd = performance.now();
|
||||
const migrationDurationMs = migrationEnd - migrationStart;
|
||||
|
||||
@@ -186,8 +186,7 @@ export async function migrateUsers() {
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
process.on("SIGINT", handleShutdown);
|
||||
process.on("SIGTERM", handleShutdown);
|
||||
process.on("exit", handleShutdown);
|
||||
|
||||
while (hasMore) {
|
||||
// Check if shutdown was requested
|
||||
@@ -409,8 +408,7 @@ export async function migrateUsers() {
|
||||
}
|
||||
|
||||
// Remove signal handlers
|
||||
process.off("SIGINT", handleShutdown);
|
||||
process.off("SIGTERM", handleShutdown);
|
||||
process.off("exit", handleShutdown);
|
||||
|
||||
const migrationEnd = performance.now();
|
||||
const migrationDurationMs = migrationEnd - migrationStart;
|
||||
|
||||
@@ -69,28 +69,18 @@ export const CometCard = ({
|
||||
<motion.div
|
||||
ref={ref}
|
||||
initial={{ scale: 1, z: 0 }}
|
||||
className="relative rounded-md"
|
||||
style={{
|
||||
rotateX: rotateX,
|
||||
rotateY: rotateY,
|
||||
translateX: translateX,
|
||||
translateY: translateY,
|
||||
willChange: "transform",
|
||||
}}
|
||||
whileHover={{ z: 50, scale: scaleFactor, transition: { duration: 0.2 } }}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
className="relative rounded-md will-change-transform"
|
||||
whileHover={{ z: 50, scale: scaleFactor, transition: { duration: 0.2 } }}
|
||||
style={{ rotateX: rotateX, rotateY: rotateY, translateX: translateX, translateY: translateY }}
|
||||
>
|
||||
{children}
|
||||
|
||||
<motion.div
|
||||
transition={{ duration: 0.2 }}
|
||||
style={{
|
||||
background: glareBackground,
|
||||
opacity: glareOpacity,
|
||||
willChange: "opacity",
|
||||
}}
|
||||
className="pointer-events-none absolute inset-0 z-50 h-full w-full rounded-md mix-blend-overlay"
|
||||
style={{ background: glareBackground, opacity: glareOpacity }}
|
||||
className="pointer-events-none absolute inset-0 z-50 h-full w-full rounded-md mix-blend-overlay will-change-[opacity]"
|
||||
/>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
@@ -33,8 +33,7 @@ export const Spotlight = ({
|
||||
<motion.div
|
||||
animate={{ x: [0, xOffset, 0] }}
|
||||
transition={{ duration, repeat: Infinity, repeatType: "reverse", ease: "easeInOut" }}
|
||||
className="pointer-events-none absolute inset-s-0 top-0 z-40 h-svh w-svw"
|
||||
style={{ willChange: "transform" }}
|
||||
className="pointer-events-none absolute inset-s-0 top-0 z-40 h-svh w-svw will-change-transform"
|
||||
>
|
||||
<div
|
||||
className="absolute inset-s-0 top-0"
|
||||
@@ -69,14 +68,8 @@ export const Spotlight = ({
|
||||
|
||||
<motion.div
|
||||
animate={{ x: [0, -xOffset, 0] }}
|
||||
className="pointer-events-none absolute inset-e-0 top-0 z-40 h-svh w-svw"
|
||||
transition={{
|
||||
duration,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
repeatType: "reverse",
|
||||
}}
|
||||
style={{ willChange: "transform" }}
|
||||
transition={{ duration, repeat: Infinity, ease: "easeInOut", repeatType: "reverse" }}
|
||||
className="pointer-events-none absolute inset-e-0 top-0 z-40 h-svh w-svw will-change-transform"
|
||||
>
|
||||
<div
|
||||
className="absolute inset-e-0 top-0"
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, it, vi } from "vite-plus/test";
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
// Mock dnd-kit
|
||||
vi.mock("@dnd-kit/core", () => ({
|
||||
DndContext: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
||||
closestCenter: vi.fn(),
|
||||
KeyboardSensor: vi.fn(),
|
||||
PointerSensor: vi.fn(),
|
||||
useSensor: vi.fn(() => ({})),
|
||||
useSensors: vi.fn(() => []),
|
||||
}));
|
||||
|
||||
vi.mock("@dnd-kit/sortable", () => ({
|
||||
SortableContext: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
||||
horizontalListSortingStrategy: vi.fn(),
|
||||
sortableKeyboardCoordinates: vi.fn(),
|
||||
useSortable: () => ({
|
||||
attributes: {},
|
||||
listeners: {},
|
||||
setNodeRef: vi.fn(),
|
||||
transform: null,
|
||||
transition: null,
|
||||
isDragging: false,
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("@dnd-kit/utilities", () => ({
|
||||
CSS: { Transform: { toString: () => "" } },
|
||||
}));
|
||||
|
||||
// Mock framer motion
|
||||
vi.mock("motion/react", () => ({
|
||||
motion: {
|
||||
div: ({ children, ...props }: any) => <div {...props}>{children}</div>,
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock lingui
|
||||
vi.mock("@lingui/react/macro", () => ({
|
||||
Trans: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
||||
}));
|
||||
|
||||
// Mock phosphor icons
|
||||
vi.mock("@phosphor-icons/react", () => ({
|
||||
PencilSimpleIcon: ({ className }: any) => <span data-testid="edit-icon" className={className} />,
|
||||
XIcon: ({ className }: any) => <span data-testid="remove-icon" className={className} />,
|
||||
}));
|
||||
|
||||
import { ChipInput } from "./chip-input";
|
||||
|
||||
describe("ChipInput", () => {
|
||||
describe("rendering", () => {
|
||||
it("renders the input field", () => {
|
||||
render(<ChipInput />);
|
||||
expect(screen.getByRole("textbox")).toBeDefined();
|
||||
});
|
||||
|
||||
it("renders existing chips", () => {
|
||||
render(<ChipInput value={["React", "TypeScript", "Node"]} />);
|
||||
expect(screen.getByText("React")).toBeDefined();
|
||||
expect(screen.getByText("TypeScript")).toBeDefined();
|
||||
expect(screen.getByText("Node")).toBeDefined();
|
||||
});
|
||||
|
||||
it("renders no chips when value is empty", () => {
|
||||
render(<ChipInput value={[]} />);
|
||||
|
||||
// Only the input area, no chip badges
|
||||
expect(screen.queryByText("React")).toBeNull();
|
||||
});
|
||||
|
||||
it("shows description by default", () => {
|
||||
render(<ChipInput />);
|
||||
expect(screen.getByText(/Enter/)).toBeDefined();
|
||||
});
|
||||
|
||||
it("hides description when hideDescription is true", () => {
|
||||
render(<ChipInput hideDescription />);
|
||||
expect(screen.queryByText(/Enter/)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("adding chips via Enter key", () => {
|
||||
it("adds a chip when Enter is pressed", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<ChipInput value={[]} onChange={onChange} />);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
fireEvent.change(input, { target: { value: "React" } });
|
||||
fireEvent.keyDown(input, { key: "Enter" });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(["React"]);
|
||||
});
|
||||
|
||||
it("does not add empty chips", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<ChipInput value={[]} onChange={onChange} />);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
fireEvent.change(input, { target: { value: " " } });
|
||||
fireEvent.keyDown(input, { key: "Enter" });
|
||||
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("trims whitespace from chips", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<ChipInput value={[]} onChange={onChange} />);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
fireEvent.change(input, { target: { value: " React " } });
|
||||
fireEvent.keyDown(input, { key: "Enter" });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(["React"]);
|
||||
});
|
||||
|
||||
it("prevents duplicate chips", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<ChipInput value={["React"]} onChange={onChange} />);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
fireEvent.change(input, { target: { value: "React" } });
|
||||
fireEvent.keyDown(input, { key: "Enter" });
|
||||
|
||||
// Set is used, so duplicates are filtered — onChange should be called with same array
|
||||
expect(onChange).toHaveBeenCalledWith(["React"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("adding chips via comma", () => {
|
||||
it("adds a chip when comma is typed in the input", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<ChipInput value={[]} onChange={onChange} />);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
fireEvent.change(input, { target: { value: "React," } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(["React"]);
|
||||
});
|
||||
|
||||
it("handles multiple comma-separated values", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<ChipInput value={[]} onChange={onChange} />);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
fireEvent.change(input, { target: { value: "React,TypeScript," } });
|
||||
|
||||
// First call adds "React", second call adds "TypeScript"
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("removing chips", () => {
|
||||
it("calls onChange without the removed chip when remove button is clicked", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<ChipInput value={["React", "Vue", "Angular"]} onChange={onChange} />);
|
||||
|
||||
// Find all remove buttons
|
||||
const removeButtons = screen.getAllByLabelText(/Remove/);
|
||||
fireEvent.click(removeButtons[1]); // Remove "Vue"
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(["React", "Angular"]);
|
||||
});
|
||||
|
||||
it("removes the first chip correctly", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<ChipInput value={["A", "B", "C"]} onChange={onChange} />);
|
||||
|
||||
const removeButtons = screen.getAllByLabelText(/Remove/);
|
||||
fireEvent.click(removeButtons[0]);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(["B", "C"]);
|
||||
});
|
||||
|
||||
it("removes the last chip correctly", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<ChipInput value={["A", "B", "C"]} onChange={onChange} />);
|
||||
|
||||
const removeButtons = screen.getAllByLabelText(/Remove/);
|
||||
fireEvent.click(removeButtons[2]);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(["A", "B"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("editing chips", () => {
|
||||
it("enters edit mode when edit button is clicked", () => {
|
||||
render(<ChipInput value={["React", "Vue"]} />);
|
||||
|
||||
const editButtons = screen.getAllByLabelText(/Edit/);
|
||||
fireEvent.click(editButtons[0]);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
expect((input as HTMLInputElement).value).toBe("React");
|
||||
expect(input.getAttribute("aria-label")).toBe("Edit keyword");
|
||||
});
|
||||
|
||||
it("exits edit mode with Escape key", () => {
|
||||
render(<ChipInput value={["React"]} />);
|
||||
|
||||
const editButton = screen.getByLabelText("Edit React");
|
||||
fireEvent.click(editButton);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
fireEvent.keyDown(input, { key: "Escape" });
|
||||
|
||||
expect((input as HTMLInputElement).value).toBe("");
|
||||
expect(input.getAttribute("aria-label")).toBe("Add keyword");
|
||||
});
|
||||
|
||||
it("saves edit when Enter is pressed", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<ChipInput value={["React"]} onChange={onChange} />);
|
||||
|
||||
const editButton = screen.getByLabelText("Edit React");
|
||||
fireEvent.click(editButton);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
fireEvent.change(input, { target: { value: "React.js" } });
|
||||
fireEvent.keyDown(input, { key: "Enter" });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(["React.js"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("input placeholder", () => {
|
||||
it("shows 'Add a keyword...' by default", () => {
|
||||
render(<ChipInput />);
|
||||
expect(screen.getByPlaceholderText("Add a keyword...")).toBeDefined();
|
||||
});
|
||||
|
||||
it("shows 'Editing keyword...' in edit mode", () => {
|
||||
render(<ChipInput value={["Test"]} />);
|
||||
|
||||
const editButton = screen.getByLabelText("Edit Test");
|
||||
fireEvent.click(editButton);
|
||||
|
||||
expect(screen.getByPlaceholderText("Editing keyword...")).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("uncontrolled mode", () => {
|
||||
it("works with defaultValue", () => {
|
||||
render(<ChipInput defaultValue={["Initial"]} />);
|
||||
expect(screen.getByText("Initial")).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -70,11 +70,10 @@ function ChipItem({ id, chip, index, isEditing, onEdit, onRemove }: ChipItemProp
|
||||
>
|
||||
<span className="max-w-32 truncate">{chip}</span>
|
||||
<motion.div
|
||||
initial={false}
|
||||
initial="false"
|
||||
animate={isHovered ? { opacity: 1, scaleX: 1, x: 0 } : { opacity: 0, scaleX: 0.95, x: -3 }}
|
||||
transition={{ duration: 0.12, ease: "easeOut" }}
|
||||
className="ms-2 flex w-10 shrink-0 origin-left items-center gap-x-1 overflow-hidden"
|
||||
style={{ willChange: "transform, opacity" }}
|
||||
className="ms-2 flex w-10 shrink-0 origin-left items-center gap-x-1 overflow-hidden will-change-[transform,opacity]"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, it, vi } from "vite-plus/test";
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
// Mock lingui macros
|
||||
vi.mock("@lingui/core/macro", () => ({
|
||||
t: (strings: TemplateStringsArray) => strings[0],
|
||||
}));
|
||||
vi.mock("@lingui/react/macro", () => ({
|
||||
Trans: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
||||
}));
|
||||
|
||||
// Mock phosphor icons
|
||||
vi.mock("@phosphor-icons/react", () => ({
|
||||
TagIcon: () => <span data-testid="tag-icon" />,
|
||||
}));
|
||||
|
||||
import { URLInput } from "./url-input";
|
||||
|
||||
describe("URLInput", () => {
|
||||
describe("URL prefix handling", () => {
|
||||
it("displays URL without https:// prefix", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<URLInput value={{ url: "https://example.com", label: "" }} onChange={onChange} />);
|
||||
|
||||
const input = screen.getByDisplayValue("example.com");
|
||||
expect(input).toBeDefined();
|
||||
});
|
||||
|
||||
it("displays empty string when URL is empty", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<URLInput value={{ url: "", label: "" }} onChange={onChange} />);
|
||||
|
||||
const inputs = screen.getAllByRole("textbox");
|
||||
const urlInput = inputs[0];
|
||||
expect((urlInput as HTMLInputElement).value).toBe("");
|
||||
});
|
||||
|
||||
it("adds https:// prefix when user types", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<URLInput value={{ url: "", label: "" }} onChange={onChange} />);
|
||||
|
||||
const inputs = screen.getAllByRole("textbox");
|
||||
fireEvent.change(inputs[0], { target: { value: "example.com" } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
url: "https://example.com",
|
||||
label: "",
|
||||
});
|
||||
});
|
||||
|
||||
it("does not double-prefix when user types https://", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<URLInput value={{ url: "", label: "" }} onChange={onChange} />);
|
||||
|
||||
const inputs = screen.getAllByRole("textbox");
|
||||
fireEvent.change(inputs[0], { target: { value: "https://example.com" } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
url: "https://example.com",
|
||||
label: "",
|
||||
});
|
||||
});
|
||||
|
||||
it("sends empty URL when input is cleared", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<URLInput value={{ url: "https://example.com", label: "" }} onChange={onChange} />);
|
||||
|
||||
const inputs = screen.getAllByRole("textbox");
|
||||
fireEvent.change(inputs[0], { target: { value: "" } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
url: "",
|
||||
label: "",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("label preservation", () => {
|
||||
it("preserves label when URL changes", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<URLInput value={{ url: "https://old.com", label: "My Site" }} onChange={onChange} />);
|
||||
|
||||
const inputs = screen.getAllByRole("textbox");
|
||||
fireEvent.change(inputs[0], { target: { value: "new.com" } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
url: "https://new.com",
|
||||
label: "My Site",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("hideLabelButton prop", () => {
|
||||
it("hides the label button when hideLabelButton is true", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<URLInput value={{ url: "", label: "" }} onChange={onChange} hideLabelButton={true} />);
|
||||
|
||||
expect(screen.queryByTestId("tag-icon")).toBeNull();
|
||||
});
|
||||
|
||||
it("shows the label button by default", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<URLInput value={{ url: "", label: "" }} onChange={onChange} />);
|
||||
|
||||
expect(screen.getByTestId("tag-icon")).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("displays the https:// prefix text", () => {
|
||||
it("shows https:// as static text", () => {
|
||||
const onChange = vi.fn();
|
||||
render(<URLInput value={{ url: "", label: "" }} onChange={onChange} />);
|
||||
|
||||
expect(screen.getByText("https://")).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,142 @@
|
||||
import { cleanup, render, screen } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, it, vi } from "vite-plus/test";
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
// Mock @lingui/core/macro
|
||||
vi.mock("@lingui/core/macro", () => ({
|
||||
t: (strings: TemplateStringsArray, ...values: unknown[]) => {
|
||||
let result = strings[0];
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
result += String(values[i]) + strings[i + 1];
|
||||
}
|
||||
return result;
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock PageIcon to avoid deep dependency chain
|
||||
vi.mock("../resume/shared/page-icon", () => ({
|
||||
PageIcon: ({ icon, className }: { icon: string; className?: string }) => (
|
||||
<span data-testid="page-icon" data-icon={icon} className={className} />
|
||||
),
|
||||
}));
|
||||
|
||||
import { LevelDisplay } from "./display";
|
||||
|
||||
describe("LevelDisplay", () => {
|
||||
describe("returns null for invalid states", () => {
|
||||
it("returns null when level is 0", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="circle" level={0} />);
|
||||
expect(container.firstChild).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null when type is 'hidden'", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="hidden" level={3} />);
|
||||
expect(container.firstChild).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null when icon is empty string", () => {
|
||||
const { container } = render(<LevelDisplay icon="" type="circle" level={3} />);
|
||||
expect(container.firstChild).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("renders correct number of elements", () => {
|
||||
it("always renders 5 elements for non-zero level", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="circle" level={3} />);
|
||||
const wrapper = container.firstChild as HTMLElement;
|
||||
expect(wrapper.children).toHaveLength(5);
|
||||
});
|
||||
|
||||
it("renders 5 elements for level 1", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="square" level={1} />);
|
||||
const wrapper = container.firstChild as HTMLElement;
|
||||
expect(wrapper.children).toHaveLength(5);
|
||||
});
|
||||
|
||||
it("renders 5 elements for level 5", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="circle" level={5} />);
|
||||
const wrapper = container.firstChild as HTMLElement;
|
||||
expect(wrapper.children).toHaveLength(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe("active state for circle/square/rectangle types", () => {
|
||||
it("marks correct number of items as active for level 3", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="circle" level={3} />);
|
||||
const items = Array.from((container.firstChild as HTMLElement).children);
|
||||
const activeItems = items.filter((el) => el.getAttribute("data-active") === "true");
|
||||
expect(activeItems).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("marks 1 item active for level 1", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="square" level={1} />);
|
||||
const items = Array.from((container.firstChild as HTMLElement).children);
|
||||
const activeItems = items.filter((el) => el.getAttribute("data-active") === "true");
|
||||
expect(activeItems).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("marks all 5 items active for level 5", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="circle" level={5} />);
|
||||
const items = Array.from((container.firstChild as HTMLElement).children);
|
||||
const activeItems = items.filter((el) => el.getAttribute("data-active") === "true");
|
||||
expect(activeItems).toHaveLength(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe("progress-bar type", () => {
|
||||
it("renders progress bar elements", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="progress-bar" level={3} />);
|
||||
const wrapper = container.firstChild as HTMLElement;
|
||||
expect(wrapper.children).toHaveLength(5);
|
||||
});
|
||||
|
||||
it("has correct active count for progress-bar", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="progress-bar" level={2} />);
|
||||
const items = Array.from((container.firstChild as HTMLElement).children);
|
||||
const activeItems = items.filter((el) => el.getAttribute("data-active") === "true");
|
||||
expect(activeItems).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("icon type", () => {
|
||||
it("renders PageIcon components", () => {
|
||||
render(<LevelDisplay icon="star" type="icon" level={3} />);
|
||||
const icons = screen.getAllByTestId("page-icon");
|
||||
expect(icons).toHaveLength(5);
|
||||
});
|
||||
|
||||
it("passes the icon name to PageIcon", () => {
|
||||
render(<LevelDisplay icon="star" type="icon" level={2} />);
|
||||
const icons = screen.getAllByTestId("page-icon");
|
||||
expect(icons[0].getAttribute("data-icon")).toBe("star");
|
||||
});
|
||||
|
||||
it("applies opacity to inactive icons", () => {
|
||||
render(<LevelDisplay icon="star" type="icon" level={2} />);
|
||||
const icons = screen.getAllByTestId("page-icon");
|
||||
// First 2 should be active (no opacity-40), last 3 inactive (opacity-40)
|
||||
expect(icons[0].className).not.toContain("opacity-40");
|
||||
expect(icons[1].className).not.toContain("opacity-40");
|
||||
expect(icons[2].className).toContain("opacity-40");
|
||||
expect(icons[3].className).toContain("opacity-40");
|
||||
expect(icons[4].className).toContain("opacity-40");
|
||||
});
|
||||
});
|
||||
|
||||
describe("aria attributes", () => {
|
||||
it("has aria-label showing level out of 5", () => {
|
||||
render(<LevelDisplay icon="star" type="circle" level={3} />);
|
||||
const el = screen.getByRole("presentation");
|
||||
expect(el.getAttribute("aria-label")).toContain("3");
|
||||
expect(el.getAttribute("aria-label")).toContain("5");
|
||||
});
|
||||
});
|
||||
|
||||
describe("className prop", () => {
|
||||
it("applies custom className to the wrapper", () => {
|
||||
const { container } = render(<LevelDisplay icon="star" type="circle" level={3} className="custom-level" />);
|
||||
expect((container.firstChild as HTMLElement).className).toContain("custom-level");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -13,10 +13,19 @@ export const useCSSVariables = ({ picture, metadata }: UseCssVariablesProps) =>
|
||||
const lowestBodyFontWeight = Math.min(...metadata.typography.body.fontWeights.map(Number));
|
||||
const lowestHeadingFontWeight = Math.min(...metadata.typography.heading.fontWeights.map(Number));
|
||||
|
||||
const highestBodyFontWeight = Math.max(...metadata.typography.body.fontWeights.map(Number));
|
||||
const highestHeadingFontWeight = Math.max(...metadata.typography.heading.fontWeights.map(Number));
|
||||
const rawHighestBodyFontWeight = Math.max(...metadata.typography.body.fontWeights.map(Number));
|
||||
const rawHighestHeadingFontWeight = Math.max(...metadata.typography.heading.fontWeights.map(Number));
|
||||
|
||||
return { lowestBodyFontWeight, lowestHeadingFontWeight, highestBodyFontWeight, highestHeadingFontWeight };
|
||||
const highestBodyFontWeight = rawHighestBodyFontWeight <= lowestBodyFontWeight ? 700 : rawHighestBodyFontWeight;
|
||||
const highestHeadingFontWeight =
|
||||
rawHighestHeadingFontWeight <= lowestHeadingFontWeight ? 700 : rawHighestHeadingFontWeight;
|
||||
|
||||
return {
|
||||
lowestBodyFontWeight,
|
||||
lowestHeadingFontWeight,
|
||||
highestBodyFontWeight,
|
||||
highestHeadingFontWeight,
|
||||
};
|
||||
}, [metadata.typography.body.fontWeights, metadata.typography.heading.fontWeights]);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { SectionItem } from "@/schema/resume/data";
|
||||
|
||||
import { TiptapContent } from "@/components/input/rich-input";
|
||||
import { filterFieldValues } from "@/utils/field";
|
||||
import { stripHtml } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -12,24 +13,44 @@ type AwardsItemProps = SectionItem<"awards"> & {
|
||||
};
|
||||
|
||||
export function AwardsItem({ className, ...item }: AwardsItemProps) {
|
||||
const headerValues = {
|
||||
title: item.title,
|
||||
date: item.date,
|
||||
awarder: item.awarder,
|
||||
};
|
||||
const headerFields = filterFieldValues(
|
||||
headerValues,
|
||||
{
|
||||
key: "title",
|
||||
content: (
|
||||
<LinkedTitle
|
||||
title={item.title}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title awards-item-title"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "date",
|
||||
content: <span className="section-item-metadata awards-item-date">{item.date}</span>,
|
||||
},
|
||||
{
|
||||
key: "awarder",
|
||||
content: <span className="section-item-metadata awards-item-awarder">{item.awarder}</span>,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cn("awards-item", className)}>
|
||||
{/* Header */}
|
||||
<div className="section-item-header awards-item-header">
|
||||
{/* Row 1 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<LinkedTitle
|
||||
title={item.title}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title awards-item-title"
|
||||
/>
|
||||
<span className="section-item-metadata awards-item-date shrink-0 text-end">{item.date}</span>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<span className="section-item-metadata awards-item-awarder">{item.awarder}</span>
|
||||
<div className="grid grid-cols-2 items-start justify-between gap-x-2">
|
||||
{headerFields.map((field, index) => (
|
||||
<div key={field.key} className={cn(index % 2 === 1 && "text-end whitespace-nowrap")}>
|
||||
{field.content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { SectionItem } from "@/schema/resume/data";
|
||||
|
||||
import { TiptapContent } from "@/components/input/rich-input";
|
||||
import { filterFieldValues } from "@/utils/field";
|
||||
import { stripHtml } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -12,24 +13,44 @@ type CertificationsItemProps = SectionItem<"certifications"> & {
|
||||
};
|
||||
|
||||
export function CertificationsItem({ className, ...item }: CertificationsItemProps) {
|
||||
const headerValues = {
|
||||
title: item.title,
|
||||
date: item.date,
|
||||
issuer: item.issuer,
|
||||
};
|
||||
const headerFields = filterFieldValues(
|
||||
headerValues,
|
||||
{
|
||||
key: "title",
|
||||
content: (
|
||||
<LinkedTitle
|
||||
title={item.title}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title certifications-item-title"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "date",
|
||||
content: <span className="section-item-metadata certifications-item-date">{item.date}</span>,
|
||||
},
|
||||
{
|
||||
key: "issuer",
|
||||
content: <span className="section-item-metadata certifications-item-issuer">{item.issuer}</span>,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cn("certifications-item", className)}>
|
||||
{/* Header */}
|
||||
<div className="section-item-header certifications-item-header">
|
||||
{/* Row 1 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<LinkedTitle
|
||||
title={item.title}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title certifications-item-title"
|
||||
/>
|
||||
<span className="section-item-metadata certifications-item-date shrink-0 text-end">{item.date}</span>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<span className="section-item-metadata certifications-item-issuer">{item.issuer}</span>
|
||||
<div className="grid grid-cols-2 items-start justify-between gap-x-2">
|
||||
{headerFields.map((field, index) => (
|
||||
<div key={field.key} className={cn(index % 2 === 1 && "text-end whitespace-nowrap")}>
|
||||
{field.content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { SectionItem } from "@/schema/resume/data";
|
||||
|
||||
import { TiptapContent } from "@/components/input/rich-input";
|
||||
import { filterFieldValues } from "@/utils/field";
|
||||
import { stripHtml } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -12,29 +13,51 @@ type EducationItemProps = SectionItem<"education"> & {
|
||||
};
|
||||
|
||||
export function EducationItem({ className, ...item }: EducationItemProps) {
|
||||
const degreeAndGrade = [item.degree, item.grade].filter(Boolean).join(" • ");
|
||||
const locationAndPeriod = [item.location, item.period].filter(Boolean).join(" • ");
|
||||
const headerValues = {
|
||||
school: item.school,
|
||||
degreeAndGrade,
|
||||
area: item.area,
|
||||
locationAndPeriod,
|
||||
};
|
||||
const headerFields = filterFieldValues(
|
||||
headerValues,
|
||||
{
|
||||
key: "school",
|
||||
content: (
|
||||
<LinkedTitle
|
||||
title={item.school}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title education-item-title"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "degreeAndGrade",
|
||||
content: <span className="section-item-metadata education-item-degree-grade">{degreeAndGrade}</span>,
|
||||
},
|
||||
{
|
||||
key: "area",
|
||||
content: <span className="section-item-metadata education-item-area">{item.area}</span>,
|
||||
},
|
||||
{
|
||||
key: "locationAndPeriod",
|
||||
content: <span className="section-item-metadata education-item-location-period">{locationAndPeriod}</span>,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cn("education-item", className)}>
|
||||
{/* Header */}
|
||||
<div className="section-item-header education-item-header mb-2">
|
||||
{/* Row 1 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<LinkedTitle
|
||||
title={item.school}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title education-item-title"
|
||||
/>
|
||||
<span className="section-item-metadata education-item-degree-grade shrink-0 text-end">
|
||||
{[item.degree, item.grade].filter(Boolean).join(" • ")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<span className="section-item-metadata education-item-area">{item.area}</span>
|
||||
<span className="section-item-metadata education-item-location-period shrink-0 text-end">
|
||||
{[item.location, item.period].filter(Boolean).join(" • ")}
|
||||
</span>
|
||||
<div className="grid grid-cols-2 items-start justify-between gap-x-2">
|
||||
{headerFields.map((field, index) => (
|
||||
<div key={field.key} className={cn(index % 2 === 1 && "text-end whitespace-nowrap")}>
|
||||
{field.content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { SectionItem } from "@/schema/resume/data";
|
||||
|
||||
import { TiptapContent } from "@/components/input/rich-input";
|
||||
import { filterFieldValues } from "@/utils/field";
|
||||
import { stripHtml } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -13,36 +14,50 @@ type ExperienceItemProps = SectionItem<"experience"> & {
|
||||
|
||||
export function ExperienceItem({ className, ...item }: ExperienceItemProps) {
|
||||
const hasRoles = Array.isArray(item.roles) && item.roles.length > 0;
|
||||
const headerValues = {
|
||||
company: item.company,
|
||||
location: item.location,
|
||||
position: item.position,
|
||||
period: item.period,
|
||||
};
|
||||
const headerFields = filterFieldValues(
|
||||
headerValues,
|
||||
{
|
||||
key: "company",
|
||||
content: (
|
||||
<LinkedTitle
|
||||
title={item.company}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title experience-item-title"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "location",
|
||||
content: <span className="section-item-metadata experience-item-location">{item.location}</span>,
|
||||
},
|
||||
{
|
||||
key: "position",
|
||||
content: <span className="section-item-metadata experience-item-position">{item.position}</span>,
|
||||
},
|
||||
{
|
||||
key: "period",
|
||||
content: <span className="section-item-metadata experience-item-period">{item.period}</span>,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cn("experience-item", className)}>
|
||||
{/* Header */}
|
||||
<div className="section-item-header experience-item-header">
|
||||
{/* Row 1: Company + Location */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<LinkedTitle
|
||||
title={item.company}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title experience-item-title"
|
||||
/>
|
||||
<span className="section-item-metadata experience-item-location shrink-0 text-end">{item.location}</span>
|
||||
<div className="grid grid-cols-2 items-start justify-between gap-x-2">
|
||||
{headerFields.map((field, index) => (
|
||||
<div key={field.key} className={cn(index % 2 === 1 && "text-end whitespace-nowrap")}>
|
||||
{field.content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Row 2: Position + Period */}
|
||||
{(!hasRoles || item.position) && (
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<span className="section-item-metadata experience-item-position">{item.position}</span>
|
||||
<span className="section-item-metadata experience-item-period shrink-0 text-end">{item.period}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Overall period when hasRoles and no summary position */}
|
||||
{hasRoles && !item.position && item.period && (
|
||||
<div className="flex items-start justify-end gap-x-2">
|
||||
<span className="section-item-metadata experience-item-period shrink-0 text-end">{item.period}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Role Progression */}
|
||||
@@ -50,11 +65,11 @@ export function ExperienceItem({ className, ...item }: ExperienceItemProps) {
|
||||
<div className="experience-item-roles mt-0 flex flex-col gap-y-1">
|
||||
{item.roles.map((role) => (
|
||||
<div key={role.id} className="experience-item-role">
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<span className="section-item-metadata experience-item-role-position">{role.position}</span>
|
||||
<span className="section-item-metadata experience-item-role-period shrink-0 text-end">
|
||||
<div className="grid grid-cols-2 items-start justify-between gap-x-2">
|
||||
<div className="section-item-metadata experience-item-role-position">{role.position}</div>
|
||||
<div className="section-item-metadata experience-item-role-period text-end whitespace-nowrap">
|
||||
{role.period}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{stripHtml(role.description) && (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { SectionItem } from "@/schema/resume/data";
|
||||
|
||||
import { TiptapContent } from "@/components/input/rich-input";
|
||||
import { filterFieldValues } from "@/utils/field";
|
||||
import { stripHtml } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -12,24 +13,44 @@ type PublicationsItemProps = SectionItem<"publications"> & {
|
||||
};
|
||||
|
||||
export function PublicationsItem({ className, ...item }: PublicationsItemProps) {
|
||||
const headerValues = {
|
||||
title: item.title,
|
||||
date: item.date,
|
||||
publisher: item.publisher,
|
||||
};
|
||||
const headerFields = filterFieldValues(
|
||||
headerValues,
|
||||
{
|
||||
key: "title",
|
||||
content: (
|
||||
<LinkedTitle
|
||||
title={item.title}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title publications-item-title"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "date",
|
||||
content: <span className="section-item-metadata publications-item-date">{item.date}</span>,
|
||||
},
|
||||
{
|
||||
key: "publisher",
|
||||
content: <span className="section-item-metadata publications-item-publisher">{item.publisher}</span>,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cn("publications-item", className)}>
|
||||
{/* Header */}
|
||||
<div className="section-item-header publications-item-header">
|
||||
{/* Row 1 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<LinkedTitle
|
||||
title={item.title}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title publications-item-title"
|
||||
/>
|
||||
<span className="section-item-metadata publications-item-date shrink-0 text-end">{item.date}</span>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<span className="section-item-metadata publications-item-publisher">{item.publisher}</span>
|
||||
<div className="grid grid-cols-2 items-start justify-between gap-x-2">
|
||||
{headerFields.map((field, index) => (
|
||||
<div key={field.key} className={cn(index % 2 === 1 && "text-end whitespace-nowrap")}>
|
||||
{field.content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { SectionItem } from "@/schema/resume/data";
|
||||
|
||||
import { TiptapContent } from "@/components/input/rich-input";
|
||||
import { filterFieldValues } from "@/utils/field";
|
||||
import { stripHtml } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -12,23 +13,39 @@ type ReferencesItemProps = SectionItem<"references"> & {
|
||||
};
|
||||
|
||||
export function ReferencesItem({ className, ...item }: ReferencesItemProps) {
|
||||
const headerValues = {
|
||||
name: item.name,
|
||||
position: item.position,
|
||||
};
|
||||
const headerFields = filterFieldValues(
|
||||
headerValues,
|
||||
{
|
||||
key: "name",
|
||||
content: (
|
||||
<LinkedTitle
|
||||
title={item.name}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title references-item-name"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "position",
|
||||
content: <span className="section-item-metadata references-item-position">{item.position}</span>,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cn("references-item", className)}>
|
||||
{/* Header */}
|
||||
<div className="section-item-header references-item-header">
|
||||
{/* Row 1 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<LinkedTitle
|
||||
title={item.name}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title references-item-name"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<span className="section-item-metadata references-item-position">{item.position}</span>
|
||||
<div className="grid grid-cols-2 items-start justify-between gap-x-2">
|
||||
{headerFields.map((field, index) => (
|
||||
<div key={field.key} className={cn(index % 2 === 1 && "text-end whitespace-nowrap")}>
|
||||
{field.content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { SectionItem } from "@/schema/resume/data";
|
||||
|
||||
import { TiptapContent } from "@/components/input/rich-input";
|
||||
import { filterFieldValues } from "@/utils/field";
|
||||
import { stripHtml } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -12,24 +13,44 @@ type VolunteerItemProps = SectionItem<"volunteer"> & {
|
||||
};
|
||||
|
||||
export function VolunteerItem({ className, ...item }: VolunteerItemProps) {
|
||||
const headerValues = {
|
||||
organization: item.organization,
|
||||
period: item.period,
|
||||
location: item.location,
|
||||
};
|
||||
const headerFields = filterFieldValues(
|
||||
headerValues,
|
||||
{
|
||||
key: "organization",
|
||||
content: (
|
||||
<LinkedTitle
|
||||
title={item.organization}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title volunteer-item-title"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "period",
|
||||
content: <span className="section-item-metadata volunteer-item-period">{item.period}</span>,
|
||||
},
|
||||
{
|
||||
key: "location",
|
||||
content: <span className="section-item-metadata volunteer-item-location">{item.location}</span>,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cn("volunteer-item", className)}>
|
||||
{/* Header */}
|
||||
<div className="section-item-header volunteer-item-header">
|
||||
{/* Row 1 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<LinkedTitle
|
||||
title={item.organization}
|
||||
website={item.website}
|
||||
showLinkInTitle={item.options?.showLinkInTitle}
|
||||
className="section-item-title volunteer-item-title"
|
||||
/>
|
||||
<span className="section-item-metadata volunteer-item-period shrink-0 text-end">{item.period}</span>
|
||||
</div>
|
||||
|
||||
{/* Row 2 */}
|
||||
<div className="flex items-start justify-between gap-x-2">
|
||||
<span className="section-item-metadata volunteer-item-location">{item.location}</span>
|
||||
<div className="grid grid-cols-2 items-start justify-between gap-x-2">
|
||||
{headerFields.map((field, index) => (
|
||||
<div key={field.key} className={cn(index % 2 === 1 && "text-end whitespace-nowrap")}>
|
||||
{field.content}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import { cleanup, render, screen } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, it } from "vite-plus/test";
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
import { LinkedTitle } from "./linked-title";
|
||||
|
||||
describe("LinkedTitle", () => {
|
||||
describe("renders as link when showLinkInTitle and website.url are provided", () => {
|
||||
it("renders an anchor tag", () => {
|
||||
render(
|
||||
<LinkedTitle title="Acme Corp" website={{ url: "https://acme.com", label: "Acme" }} showLinkInTitle={true} />,
|
||||
);
|
||||
|
||||
const link = screen.getByRole("link", { name: "Acme Corp" });
|
||||
expect(link).toBeDefined();
|
||||
expect(link.getAttribute("href")).toBe("https://acme.com");
|
||||
});
|
||||
|
||||
it("sets target=_blank and rel=noopener on the link", () => {
|
||||
render(
|
||||
<LinkedTitle title="Company" website={{ url: "https://example.com", label: "" }} showLinkInTitle={true} />,
|
||||
);
|
||||
|
||||
const link = screen.getByRole("link");
|
||||
expect(link.getAttribute("target")).toBe("_blank");
|
||||
expect(link.getAttribute("rel")).toBe("noopener");
|
||||
});
|
||||
|
||||
it("wraps the title in a strong tag inside the link", () => {
|
||||
render(
|
||||
<LinkedTitle title="Bold Title" website={{ url: "https://example.com", label: "" }} showLinkInTitle={true} />,
|
||||
);
|
||||
|
||||
const strong = screen.getByText("Bold Title");
|
||||
expect(strong.tagName).toBe("STRONG");
|
||||
});
|
||||
});
|
||||
|
||||
describe("renders as plain strong tag otherwise", () => {
|
||||
it("renders strong when showLinkInTitle is false", () => {
|
||||
render(
|
||||
<LinkedTitle title="Plain Title" website={{ url: "https://example.com", label: "" }} showLinkInTitle={false} />,
|
||||
);
|
||||
|
||||
const strong = screen.getByText("Plain Title");
|
||||
expect(strong.tagName).toBe("STRONG");
|
||||
expect(screen.queryByRole("link")).toBeNull();
|
||||
});
|
||||
|
||||
it("renders strong when showLinkInTitle is undefined", () => {
|
||||
render(<LinkedTitle title="No Link" />);
|
||||
|
||||
expect(screen.getByText("No Link").tagName).toBe("STRONG");
|
||||
expect(screen.queryByRole("link")).toBeNull();
|
||||
});
|
||||
|
||||
it("renders strong when website is undefined", () => {
|
||||
render(<LinkedTitle title="No Website" showLinkInTitle={true} />);
|
||||
|
||||
expect(screen.getByText("No Website").tagName).toBe("STRONG");
|
||||
expect(screen.queryByRole("link")).toBeNull();
|
||||
});
|
||||
|
||||
it("renders strong when website.url is empty", () => {
|
||||
render(<LinkedTitle title="Empty URL" website={{ url: "", label: "" }} showLinkInTitle={true} />);
|
||||
|
||||
expect(screen.getByText("Empty URL").tagName).toBe("STRONG");
|
||||
expect(screen.queryByRole("link")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("className prop", () => {
|
||||
it("applies className to the link element", () => {
|
||||
render(
|
||||
<LinkedTitle
|
||||
title="Styled"
|
||||
website={{ url: "https://x.com", label: "" }}
|
||||
showLinkInTitle={true}
|
||||
className="custom-class"
|
||||
/>,
|
||||
);
|
||||
|
||||
const link = screen.getByRole("link");
|
||||
expect(link.className).toContain("custom-class");
|
||||
});
|
||||
|
||||
it("applies className to the strong element", () => {
|
||||
render(<LinkedTitle title="Styled Strong" className="my-class" />);
|
||||
|
||||
const strong = screen.getByText("Styled Strong");
|
||||
expect(strong.className).toContain("my-class");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,272 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vite-plus/test";
|
||||
|
||||
// Mock dependencies before importing the store
|
||||
vi.mock("@lingui/core/macro", () => ({
|
||||
t: (strings: TemplateStringsArray) => strings[0],
|
||||
}));
|
||||
|
||||
vi.mock("sonner", () => ({
|
||||
toast: {
|
||||
error: vi.fn(() => "toast-id"),
|
||||
dismiss: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@/integrations/orpc/client", () => ({
|
||||
orpc: {
|
||||
resume: {
|
||||
update: {
|
||||
call: vi.fn(() => Promise.resolve()),
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
import { defaultResumeData } from "@/schema/resume/data";
|
||||
|
||||
import { useResumeStore } from "./resume";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function makeResume(overrides?: Record<string, unknown>) {
|
||||
return {
|
||||
id: "test-resume-id",
|
||||
name: "Test Resume",
|
||||
slug: "test-resume",
|
||||
tags: ["test"],
|
||||
isLocked: false,
|
||||
data: structuredClone(defaultResumeData),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
// Reset store between tests
|
||||
useResumeStore.getState().initialize(null);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// initialize
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("useResumeStore — initialize", () => {
|
||||
it("sets resume and isReady to true", () => {
|
||||
const resume = makeResume();
|
||||
useResumeStore.getState().initialize(resume);
|
||||
|
||||
const state = useResumeStore.getState();
|
||||
expect(state.isReady).toBe(true);
|
||||
expect(state.resume.id).toBe("test-resume-id");
|
||||
expect(state.resume.name).toBe("Test Resume");
|
||||
});
|
||||
|
||||
it("sets isReady to false when initialized with null", () => {
|
||||
useResumeStore.getState().initialize(null);
|
||||
|
||||
const state = useResumeStore.getState();
|
||||
expect(state.isReady).toBe(false);
|
||||
});
|
||||
|
||||
it("replaces previous resume data", () => {
|
||||
useResumeStore.getState().initialize(makeResume({ name: "First" }));
|
||||
expect(useResumeStore.getState().resume.name).toBe("First");
|
||||
|
||||
useResumeStore.getState().initialize(makeResume({ name: "Second" }));
|
||||
expect(useResumeStore.getState().resume.name).toBe("Second");
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// updateResumeData
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("useResumeStore — updateResumeData", () => {
|
||||
it("updates resume data via immer draft", () => {
|
||||
useResumeStore.getState().initialize(makeResume());
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.basics.name = "Jane Doe";
|
||||
});
|
||||
|
||||
expect(useResumeStore.getState().resume.data.basics.name).toBe("Jane Doe");
|
||||
});
|
||||
|
||||
it("can update nested fields", () => {
|
||||
useResumeStore.getState().initialize(makeResume());
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.basics.website.url = "https://example.com";
|
||||
draft.basics.email = "jane@example.com";
|
||||
});
|
||||
|
||||
expect(useResumeStore.getState().resume.data.basics.website.url).toBe("https://example.com");
|
||||
expect(useResumeStore.getState().resume.data.basics.email).toBe("jane@example.com");
|
||||
});
|
||||
|
||||
it("can add items to sections", () => {
|
||||
useResumeStore.getState().initialize(makeResume());
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.sections.skills.items.push({
|
||||
id: "s1",
|
||||
hidden: false,
|
||||
icon: "",
|
||||
name: "TypeScript",
|
||||
proficiency: "Advanced",
|
||||
level: 4,
|
||||
keywords: [],
|
||||
});
|
||||
});
|
||||
|
||||
expect(useResumeStore.getState().resume.data.sections.skills.items).toHaveLength(1);
|
||||
expect(useResumeStore.getState().resume.data.sections.skills.items[0].name).toBe("TypeScript");
|
||||
});
|
||||
|
||||
it("does not update when resume is not initialized", () => {
|
||||
// Store starts with null resume
|
||||
useResumeStore.getState().initialize(null);
|
||||
|
||||
// Should not throw
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.basics.name = "Should not apply";
|
||||
});
|
||||
});
|
||||
|
||||
it("blocks updates when resume is locked", async () => {
|
||||
const { toast } = await import("sonner");
|
||||
useResumeStore.getState().initialize(makeResume({ isLocked: true }));
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.basics.name = "Should not apply";
|
||||
});
|
||||
|
||||
// Name should remain unchanged
|
||||
expect(useResumeStore.getState().resume.data.basics.name).toBe("");
|
||||
// Should show error toast
|
||||
expect(toast.error).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not block updates on unlocked resume", () => {
|
||||
useResumeStore.getState().initialize(makeResume({ isLocked: false }));
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.basics.name = "Updated";
|
||||
});
|
||||
|
||||
expect(useResumeStore.getState().resume.data.basics.name).toBe("Updated");
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Multiple updates
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("useResumeStore — multiple updates", () => {
|
||||
it("applies sequential updates correctly", () => {
|
||||
useResumeStore.getState().initialize(makeResume());
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.basics.name = "First Update";
|
||||
});
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.basics.headline = "Developer";
|
||||
});
|
||||
|
||||
const data = useResumeStore.getState().resume.data;
|
||||
expect(data.basics.name).toBe("First Update");
|
||||
expect(data.basics.headline).toBe("Developer");
|
||||
});
|
||||
|
||||
it("preserves unmodified sections across updates", () => {
|
||||
useResumeStore.getState().initialize(makeResume());
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.basics.name = "Jane";
|
||||
});
|
||||
|
||||
// Metadata and other sections should be untouched
|
||||
expect(useResumeStore.getState().resume.data.metadata.template).toBe("onyx");
|
||||
expect(useResumeStore.getState().resume.data.sections.skills.items).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Temporal store (undo/redo)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("useResumeStore — temporal", () => {
|
||||
it("has a temporal store accessible", () => {
|
||||
expect(useResumeStore.temporal).toBeDefined();
|
||||
expect(useResumeStore.temporal.getState).toBeDefined();
|
||||
});
|
||||
|
||||
it("temporal store has undo/redo actions", () => {
|
||||
const temporal = useResumeStore.temporal.getState();
|
||||
expect(typeof temporal.undo).toBe("function");
|
||||
expect(typeof temporal.redo).toBe("function");
|
||||
expect(typeof temporal.clear).toBe("function");
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Edge cases
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("useResumeStore — edge cases", () => {
|
||||
it("can update metadata fields", () => {
|
||||
useResumeStore.getState().initialize(makeResume());
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.metadata.template = "pikachu";
|
||||
});
|
||||
|
||||
expect(useResumeStore.getState().resume.data.metadata.template).toBe("pikachu");
|
||||
});
|
||||
|
||||
it("can update picture settings", () => {
|
||||
useResumeStore.getState().initialize(makeResume());
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.picture.url = "https://example.com/photo.jpg";
|
||||
draft.picture.size = 120;
|
||||
});
|
||||
|
||||
expect(useResumeStore.getState().resume.data.picture.url).toBe("https://example.com/photo.jpg");
|
||||
expect(useResumeStore.getState().resume.data.picture.size).toBe(120);
|
||||
});
|
||||
|
||||
it("can remove all items from a section", () => {
|
||||
const resume = makeResume();
|
||||
resume.data.sections.skills.items = [
|
||||
{ id: "s1", hidden: false, icon: "", name: "JS", proficiency: "", level: 0, keywords: [] },
|
||||
];
|
||||
useResumeStore.getState().initialize(resume);
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.sections.skills.items = [];
|
||||
});
|
||||
|
||||
expect(useResumeStore.getState().resume.data.sections.skills.items).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("can update custom sections", () => {
|
||||
useResumeStore.getState().initialize(makeResume());
|
||||
|
||||
useResumeStore.getState().updateResumeData((draft) => {
|
||||
draft.customSections.push({
|
||||
id: "custom-1",
|
||||
type: "experience",
|
||||
title: "Freelance",
|
||||
columns: 1,
|
||||
hidden: false,
|
||||
items: [],
|
||||
});
|
||||
});
|
||||
|
||||
expect(useResumeStore.getState().resume.data.customSections).toHaveLength(1);
|
||||
expect(useResumeStore.getState().resume.data.customSections[0].title).toBe("Freelance");
|
||||
});
|
||||
});
|
||||
@@ -32,12 +32,37 @@ type ResumeStore = ResumeStoreState & ResumeStoreActions;
|
||||
const controller = new AbortController();
|
||||
const signal = controller.signal;
|
||||
|
||||
const _syncResume = (resume: Resume) => {
|
||||
void orpc.resume.update.call({ id: resume.id, data: resume.data }, { signal });
|
||||
let syncErrorToastId: string | number | undefined;
|
||||
|
||||
const _syncResume = async (resume: Resume) => {
|
||||
try {
|
||||
await orpc.resume.update.call({ id: resume.id, data: resume.data }, { signal });
|
||||
|
||||
// Dismiss error toast on successful sync
|
||||
if (syncErrorToastId !== undefined) {
|
||||
toast.dismiss(syncErrorToastId);
|
||||
syncErrorToastId = undefined;
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
// Ignore aborted requests (e.g. page navigation)
|
||||
if (error instanceof DOMException && error.name === "AbortError") return;
|
||||
|
||||
syncErrorToastId = toast.error(
|
||||
t`Your latest changes could not be saved. Please make sure you are connected to the internet and try again.`,
|
||||
{ id: syncErrorToastId, duration: Infinity },
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const syncResume = debounce(_syncResume, 500, { signal });
|
||||
|
||||
// Flush pending sync before the page unloads to prevent data loss
|
||||
if (typeof window !== "undefined") {
|
||||
window.addEventListener("beforeunload", () => {
|
||||
syncResume.flush();
|
||||
});
|
||||
}
|
||||
|
||||
let errorToastId: string | number | undefined;
|
||||
|
||||
type PartializedState = { resume: Resume | null };
|
||||
|
||||
@@ -38,7 +38,7 @@ function AccordionContent({ className, children, ...props }: AccordionPrimitive.
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"h-(--accordion-panel-height) pt-0 pb-4 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
||||
"h-(--accordion-panel-height) pt-0 pb-4 data-ending-style:h-0 data-starting-style:h-0 [&_p:not(:last-child)]:mb-4",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { awardItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = awardItemSchema;
|
||||
@@ -44,12 +45,7 @@ export function CreateAwardDialog({ data }: DialogProps<"resume.sections.awards.
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.awards.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "awards", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -105,15 +101,7 @@ export function UpdateAwardDialog({ data }: DialogProps<"resume.sections.awards.
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.awards.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.awards.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "awards", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { certificationItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = certificationItemSchema;
|
||||
@@ -44,12 +45,7 @@ export function CreateCertificationDialog({ data }: DialogProps<"resume.sections
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.certifications.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "certifications", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -105,15 +101,7 @@ export function UpdateCertificationDialog({ data }: DialogProps<"resume.sections
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.certifications.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.certifications.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "certifications", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { educationItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = educationItemSchema;
|
||||
@@ -47,12 +48,7 @@ export function CreateEducationDialog({ data }: DialogProps<"resume.sections.edu
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.education.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "education", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -111,15 +107,7 @@ export function UpdateEducationDialog({ data }: DialogProps<"resume.sections.edu
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.education.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.education.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "education", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -176,11 +164,11 @@ function EducationForm() {
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="degree"
|
||||
name="area"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
<Trans>Degree</Trans>
|
||||
<Trans>Area of Study</Trans>
|
||||
</FormLabel>
|
||||
<FormControl render={<Input {...field} />} />
|
||||
<FormMessage />
|
||||
@@ -190,11 +178,11 @@ function EducationForm() {
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="area"
|
||||
name="degree"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
<Trans>Area of Study</Trans>
|
||||
<Trans>Degree</Trans>
|
||||
</FormLabel>
|
||||
<FormControl render={<Input {...field} />} />
|
||||
<FormMessage />
|
||||
|
||||
@@ -21,6 +21,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { experienceItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = experienceItemSchema;
|
||||
@@ -49,14 +50,8 @@ export function CreateExperienceDialog({ data }: DialogProps<"resume.sections.ex
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.experience.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "experience", formData, data?.customSectionId);
|
||||
});
|
||||
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -113,17 +108,8 @@ export function UpdateExperienceDialog({ data }: DialogProps<"resume.sections.ex
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.experience.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.experience.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "experience", formData, data?.customSectionId);
|
||||
});
|
||||
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -276,20 +262,6 @@ function ExperienceForm() {
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="position"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{hasRoles ? <Trans>Overall Title (optional)</Trans> : <Trans>Position</Trans>}</FormLabel>
|
||||
<FormControl
|
||||
render={<Input {...field} placeholder={hasRoles ? "e.g. Software Engineer → Senior Engineer" : ""} />}
|
||||
/>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="location"
|
||||
@@ -304,13 +276,29 @@ function ExperienceForm() {
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="position"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
<Trans>Position</Trans>
|
||||
</FormLabel>
|
||||
<FormControl render={<Input {...field} />} />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="period"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{hasRoles ? <Trans>Overall Period</Trans> : <Trans>Period</Trans>}</FormLabel>
|
||||
<FormControl render={<Input {...field} placeholder={hasRoles ? "e.g. 2018 – Present" : ""} />} />
|
||||
<FormLabel>
|
||||
<Trans>Period</Trans>
|
||||
</FormLabel>
|
||||
<FormControl render={<Input {...field} />} />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Input } from "@/components/ui/input";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { interestItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -42,12 +43,7 @@ export function CreateInterestDialog({ data }: DialogProps<"resume.sections.inte
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.interests.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "interests", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -100,15 +96,7 @@ export function UpdateInterestDialog({ data }: DialogProps<"resume.sections.inte
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.interests.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.interests.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "interests", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Slider } from "@/components/ui/slider";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { languageItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = languageItemSchema;
|
||||
@@ -40,12 +41,7 @@ export function CreateLanguageDialog({ data }: DialogProps<"resume.sections.lang
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.languages.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "languages", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -98,15 +94,7 @@ export function UpdateLanguageDialog({ data }: DialogProps<"resume.sections.lang
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.languages.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.languages.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "languages", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { type DialogProps, useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { profileItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
import { cn } from "@/utils/style";
|
||||
|
||||
@@ -44,12 +45,7 @@ export function CreateProfileDialog({ data }: DialogProps<"resume.sections.profi
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.profiles.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "profiles", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -104,15 +100,7 @@ export function UpdateProfileDialog({ data }: DialogProps<"resume.sections.profi
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.profiles.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.profiles.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "profiles", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { projectItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = projectItemSchema;
|
||||
@@ -43,12 +44,7 @@ export function CreateProjectDialog({ data }: DialogProps<"resume.sections.proje
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.projects.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "projects", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -103,15 +99,7 @@ export function UpdateProjectDialog({ data }: DialogProps<"resume.sections.proje
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.projects.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.projects.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "projects", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { publicationItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = publicationItemSchema;
|
||||
@@ -44,12 +45,7 @@ export function CreatePublicationDialog({ data }: DialogProps<"resume.sections.p
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.publications.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "publications", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -105,15 +101,7 @@ export function UpdatePublicationDialog({ data }: DialogProps<"resume.sections.p
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.publications.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.publications.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "publications", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useDialogStore } from "@/dialogs/store";
|
||||
import { useFormBlocker } from "@/hooks/use-form-blocker";
|
||||
import { referenceItemSchema } from "@/schema/resume/data";
|
||||
import { createSectionItem, updateSectionItem } from "@/utils/resume/section-actions";
|
||||
import { generateId } from "@/utils/string";
|
||||
|
||||
const formSchema = referenceItemSchema;
|
||||
@@ -44,12 +45,7 @@ export function CreateReferenceDialog({ data }: DialogProps<"resume.sections.ref
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (section) section.items.push(formData);
|
||||
} else {
|
||||
draft.sections.references.items.push(formData);
|
||||
}
|
||||
createSectionItem(draft, "references", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
@@ -105,15 +101,7 @@ export function UpdateReferenceDialog({ data }: DialogProps<"resume.sections.ref
|
||||
|
||||
const onSubmit = (formData: FormValues) => {
|
||||
updateResumeData((draft) => {
|
||||
if (data?.customSectionId) {
|
||||
const section = draft.customSections.find((s) => s.id === data.customSectionId);
|
||||
if (!section) return;
|
||||
const index = section.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) section.items[index] = formData;
|
||||
} else {
|
||||
const index = draft.sections.references.items.findIndex((item) => item.id === formData.id);
|
||||
if (index !== -1) draft.sections.references.items[index] = formData;
|
||||
}
|
||||
updateSectionItem(draft, "references", formData, data?.customSectionId);
|
||||
});
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user