This commit is contained in:
Amruth Pillai
2026-02-09 01:50:31 +01:00
committed by GitHub
parent 2b8fa9c7e8
commit 90c34ca572
95 changed files with 3615 additions and 450 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
const nextPackages = ["@monaco-editor/react"];
const betaPackages = ["drizzle-orm", "drizzle-kit", "@better-auth/core", "@better-auth/passkey", "better-auth"];
const betaPackages = ["vite", "drizzle-orm", "drizzle-kit", "@better-auth/core", "@better-auth/passkey", "better-auth"];
/** @type {import('npm-check-updates').RunOptions} */
module.exports = {
+7 -7
View File
@@ -10,19 +10,19 @@
"*.css": "tailwindcss"
},
"files.readonlyInclude": {
"pnpm-lock.yaml": true,
"**/routeTree.gen.ts": true
"**/routeTree.gen.ts": true,
"pnpm-lock.yaml": true
},
"files.watcherExclude": {
"pnpm-lock.yaml": true,
"**/routeTree.gen.ts": true
"**/routeTree.gen.ts": true,
"pnpm-lock.yaml": true
},
"i18n-ally.enabledParsers": ["po"],
"i18n-ally.localesPaths": ["locales"],
"i18n-ally.sourceLanguage": "en-US",
"search.exclude": {
"pnpm-lock.yaml": true,
"**/routeTree.gen.ts": true
"**/routeTree.gen.ts": true,
"pnpm-lock.yaml": true
},
"tailwindCSS.classFunctions": ["cn", "cva"],
"tailwindCSS.experimental.classRegex": [
@@ -31,5 +31,5 @@
["cn\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
],
"tailwindCSS.experimental.configFile": "src/styles/globals.css",
"typescript.tsdk": "node_modules/typescript/lib"
"typescript.experimental.useTsgo": true
}
+2 -3
View File
@@ -10,9 +10,9 @@
"ignoreUnknown": true,
"includes": [
"**",
"!**/docs/spec.json",
"!**/webfontlist.json",
"!**/schema/schema.json",
"!**/docs/spec.json",
"!**/src/routeTree.gen.ts"
]
},
@@ -24,8 +24,7 @@
"actions": {
"recommended": true,
"source": {
"organizeImports": "on",
"useSortedProperties": "on"
"organizeImports": "on"
}
}
},
+13
View File
@@ -4,6 +4,19 @@ description: "List of all notable changes and updates to Reactive Resume"
rss: true
---
<Update label="v5.0.7" description="9th February 2026">
- Introduce a new **MCP (Model Context Protocol) server** that lets you manage and edit resumes from any MCP-compatible AI tool — Claude Desktop, Cursor, Codex, and more. Supports listing, reading, creating, deleting, locking/unlocking, and patching resumes via natural language. [(guide)](/guides/using-the-mcp-server)
- Add an **AI Chat** panel to the resume builder, allowing you to modify your resume through conversational AI directly within the editor. The chat uses tool-calling to apply JSON Patch operations to your resume in real-time, with visual feedback for each change.
- Add a system prompt and `patch_resume` tool for the AI chat, enabling structured, minimal-diff resume edits following RFC 6902 JSON Patch operations.
- Chat history is now persisted per resume in localStorage, so conversations are preserved across sessions.
- Fix rendering issues in the Lapras and Onyx resume templates.
- Improvements to the Combobox and ScrollArea UI components.
- Fix an issue with skills item rendering in the shared resume components.
- Update authentication configuration and auth route handling.
- Update the JSON Schema to reflect the latest resume data model.
- Update dependencies to the latest versions.
</Update>
<Update label="v5.0.6" description="8th February 2026">
- Implement Atomic Resume Patching API for fine-grained resume updates, allowing partial, atomic updates to resumes via a new PATCH endpoint. [#2692](https://github.com/amruthpillai/reactive-resume/pull/2692)
- The API endpoint `PUT /resume/{id}` now returns the updated resume object instead of void. Also, resume routing/services now use explicit DTOs for input and output schemas. [#2688](https://github.com/amruthpillai/reactive-resume/pull/2688)
+1
View File
@@ -72,6 +72,7 @@
"pages": [
"guides/using-the-api",
"guides/using-the-patch-api",
"guides/using-the-mcp-server",
"guides/using-ai",
"guides/json-resume-schema"
]
+165
View File
@@ -0,0 +1,165 @@
---
title: "Using the MCP Server"
description: "Connect Reactive Resume to AI tools like Claude Desktop, Cursor, and Codex using the Model Context Protocol"
---
The Reactive Resume MCP server lets you manage and modify your resumes through any MCP-compatible AI tool — Claude Desktop, Cursor, Codex, and more. It connects to the Reactive Resume API and exposes tools for listing, reading, and patching resumes using natural language.
## What is MCP?
The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) is a standard that lets LLM-powered tools connect to external services. Instead of being limited to the built-in chat UI, you can use any MCP client to interact with your resumes.
## Prerequisites
<Steps>
<Step title="Create an API key">
Follow the [Using the API](/guides/using-the-api) guide to create an API key in your Reactive Resume dashboard.
</Step>
<Step title="Install Node.js">
The MCP server requires [Node.js](https://nodejs.org) version 18 or later.
</Step>
<Step title="Install dependencies">
From the Reactive Resume repository root, install dependencies (the MCP server uses the main project's dependencies):
```bash
cd /path/to/reactive-resume
pnpm install
```
</Step>
</Steps>
## Running the MCP server
The server is a single TypeScript entry point and is run with **tsx** (no build step). From the repository root:
```bash
npx tsx /path/to/reactive-resume/mcp/index.ts
```
The working directory must be the **repository root** so that `node_modules` (and thus `@modelcontextprotocol/sdk`) is resolved. Configure your MCP client with `cwd` set to the repo path.
## Configuration
### Claude Desktop
Add the following to your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"reactive-resume": {
"command": "npx",
"args": ["tsx", "/path/to/reactive-resume/mcp/index.ts"],
"cwd": "/path/to/reactive-resume",
"env": {
"REACTIVE_RESUME_API_KEY": "your-api-key",
"REACTIVE_RESUME_URL": "https://rxresu.me"
}
}
}
}
```
<Info>
Replace `/path/to/reactive-resume` with the actual path to your cloned repository, and `your-api-key` with the API key you created.
</Info>
### Cursor
Add the following to `.cursor/mcp.json` in your project or home directory:
```json
{
"mcpServers": {
"reactive-resume": {
"command": "npx",
"args": ["tsx", "/path/to/reactive-resume/mcp/index.ts"],
"cwd": "/path/to/reactive-resume",
"env": {
"REACTIVE_RESUME_API_KEY": "your-api-key",
"REACTIVE_RESUME_URL": "https://rxresu.me"
}
}
}
}
```
## Available Tools
The MCP server exposes three tools:
| Tool | Description |
| --- | --- |
| `list_resumes` | List all your resumes with their IDs, names, tags, and status |
| `get_resume` | Get the full data of a specific resume by ID |
| `patch_resume` | Apply JSON Patch operations to modify a resume |
## Available Resources
| Resource | Description |
| --- | --- |
| `resume://{id}` | The full resume data as a readable JSON resource |
| `resume://schema` | The ResumeData JSON schema for understanding the data structure |
## Usage Examples
Once your MCP client is connected, you can use natural language to interact with your resumes:
### Browsing
- "List my resumes"
- "Show me my resume named 'Software Engineer'"
- "What skills are listed on my resume?"
### Editing
- "Update my name to Jane Doe"
- "Change my headline to Senior Software Engineer"
- "Add TypeScript to my skills with an Advanced proficiency level"
- "Add a new experience entry for my role as Staff Engineer at Acme Corp from Jan 2024 to Present"
- "Remove the third item from my skills section"
### Styling
- "Change the template to bronzor"
- "Set the primary color to blue"
- "Hide the interests section"
<Tip>
The AI will use `get_resume` to inspect your current resume before making changes with `patch_resume`. This ensures the correct JSON paths are used.
</Tip>
## Self-Hosting
If you're running a self-hosted Reactive Resume instance, set `REACTIVE_RESUME_URL` to your instance URL:
```json
{
"env": {
"REACTIVE_RESUME_API_KEY": "your-api-key",
"REACTIVE_RESUME_URL": "https://resume.example.com"
}
}
```
## Environment Variables
| Variable | Required | Default | Description |
| --- | --- | --- | --- |
| `REACTIVE_RESUME_API_KEY` | Yes | — | API key from Reactive Resume settings |
| `REACTIVE_RESUME_URL` | No | `https://rxresu.me` | Base URL of the Reactive Resume instance |
| `TRANSPORT` | No | `stdio` | Transport mode: `stdio` or `http` |
| `PORT` | No | `3100` | Port for streamable HTTP transport |
## Troubleshooting
| Issue | Solution |
| --- | --- |
| "REACTIVE_RESUME_API_KEY is required" | Set the `REACTIVE_RESUME_API_KEY` environment variable in your MCP client configuration |
| "API error (401)" | Your API key is invalid or expired. Create a new one in the dashboard |
| "API error (404)" | The resume ID doesn't exist. Use `list_resumes` to find valid IDs |
| "API error (403)" | The resume is locked. Unlock it in the Reactive Resume dashboard |
| Connection refused | Check that `REACTIVE_RESUME_URL` is correct and the instance is running |
| Module not found / Cannot find package | Ensure `cwd` is the repository root so the main project's `node_modules` is used |
+1 -1
View File
File diff suppressed because one or more lines are too long
+7 -1
View File
@@ -4,6 +4,12 @@
"tailwind": { "entry": ["src/styles.css"] },
"project": ["src/**/*.{js,jsx,ts,tsx,mdx,css}"],
"ignoreBinaries": ["mint"],
"ignoreDependencies": ["npm-check-updates", "reflect-metadata", "node-addon-api", "node-gyp"],
"ignoreDependencies": [
"@modelcontextprotocol/sdk",
"npm-check-updates",
"reflect-metadata",
"node-addon-api",
"node-gyp"
],
"ignore": ["src/schema/**/*.ts", "src/components/**/*.{ts,tsx}", "src/routeTree.gen.ts"]
}
BIN
View File
Binary file not shown.
+32
View File
@@ -207,6 +207,10 @@ msgstr "ከዚህ በኋላ ረድፍ ያክሉ"
msgid "Add Row Before"
msgstr "ከዚህ በፊት ረድፍ ያክሉ"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "አፍሪካንስ"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "አልባኒኛ"
@@ -340,6 +348,10 @@ msgstr "የስልጠና መስክ"
msgid "Artificial Intelligence"
msgstr "አርቲፊሻል ኢንተለጀንስ"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "የመገናኛ መጠን"
@@ -534,6 +546,10 @@ msgstr "ቻይንኛ (ባለባለት)"
msgid "Circle"
msgstr "ክብ"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "ምርጫን ሰርዝ"
@@ -945,6 +961,10 @@ msgstr "የየታሪክዎን ቅጂ በመፍጠር ላይ…"
msgid "Dutch"
msgstr "ደች"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "ትምህርት"
@@ -1896,6 +1916,10 @@ msgstr "የይለፍ ቃልዎ አስታውሰዎ? <0><1>አሁን ይግቡ <2/
msgid "Remove Password"
msgstr "የይለፍ ቃል አስወግድ"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "የይለፍ ቃል ጥበቃን በማስወገድ ላይ…"
@@ -2357,6 +2381,10 @@ msgstr "ከዚያም መተግበሪያው ሰጥቶት የ 6 አሃዝ ኮድ
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF በማመንጨት ጊዜ ችግኝ ተፈጥሯል፣ እባክዎን ጥቂት ጊዜ በኋላ ደግመው ይሞክሩ።"
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "የየታሪክ ማቅረቢያን አዘምን"
msgid "Update your password"
msgstr "የይለፍ ቃልዎን አዘምኑ"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "የይለፍ ቃልዎን በመዘመን ላይ…"
+32
View File
@@ -207,6 +207,10 @@ msgstr "إضافة صف بعد"
msgid "Add Row Before"
msgstr "إضافة صف قبل"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "الأفريقانس"
msgid "AI"
msgstr "الذكاء الاصطناعي"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "الألبانية"
@@ -340,6 +348,10 @@ msgstr "مجال الدراسة"
msgid "Artificial Intelligence"
msgstr "الذكاء الاصطناعي"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "نسبة الأبعاد"
@@ -534,6 +546,10 @@ msgstr "الصينية (التقليدية)"
msgid "Circle"
msgstr "دائرة"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "مسح التحديد"
@@ -945,6 +961,10 @@ msgstr "جاري استنساخ سيرتك الذاتية..."
msgid "Dutch"
msgstr "الهولندية"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "التعليم"
@@ -1896,6 +1916,10 @@ msgstr "هل تذكّرت كلمة المرور؟ <0><1>سجّل الدخول ا
msgid "Remove Password"
msgstr "إزالة كلمة المرور"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "جاري إزالة حماية كلمة المرور..."
@@ -2357,6 +2381,10 @@ msgstr "بعد ذلك، أدخِل الرمز المكوَّن من 6 أرقام
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "حدثت مشكلة أثناء إنشاء ملف PDF، يُرجى المحاولة مرة أخرى بعد فترة."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "تحديث السيرة الذاتية"
msgid "Update your password"
msgstr "حدّث كلمة المرور الخاصة بك"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "جاري تحديث كلمة المرور..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Sonra Sətir əlavə et"
msgid "Add Row Before"
msgstr "Əvvəl Sətir əlavə et"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "Süni İntellekt"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanca"
@@ -340,6 +348,10 @@ msgstr "Təhsil sahəsi"
msgid "Artificial Intelligence"
msgstr "Süni İntellekt"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Propor­siya"
@@ -534,6 +546,10 @@ msgstr "Çin (Ənənəvi)"
msgid "Circle"
msgstr "Dairə"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Seçimi təmizlə"
@@ -945,6 +961,10 @@ msgstr "Özgeçmişiniz dublikat edilir..."
msgid "Dutch"
msgstr "Niderland"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Təhsil"
@@ -1896,6 +1916,10 @@ msgstr "Parolunuzu xatırladınız? <0><1>İndi daxil olun <2/></1></0>"
msgid "Remove Password"
msgstr "Parolu Sil"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Parol qorunması silinir..."
@@ -2357,6 +2381,10 @@ msgstr "Sonra, davam etmək üçün tətbiqin təqdim etdiyi 6 rəqəmli kodu da
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF yaradılarkən problem yarandı, zəhmət olmasa, bir müddət sonra yenidən cəhd edin."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Özgeçmişi Yenilə"
msgid "Update your password"
msgstr "Parolunuzu yeniləyin"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Parolunuz yenilənir..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Добавяне на ред след"
msgid "Add Row Before"
msgstr "Добавяне на ред преди"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Африканс"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Албански"
@@ -340,6 +348,10 @@ msgstr "Област на обучение"
msgid "Artificial Intelligence"
msgstr "Изкуствен интелект"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Съотношение на страните"
@@ -534,6 +546,10 @@ msgstr "Китайски (традиционен)"
msgid "Circle"
msgstr "Кръг"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Изчистване на избора"
@@ -945,6 +961,10 @@ msgstr "Вашата автобиография се дублира..."
msgid "Dutch"
msgstr "Нидерландски"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Образование"
@@ -1896,6 +1916,10 @@ msgstr "Спомнихте си паролата? <0><1>Влезте сега <2
msgid "Remove Password"
msgstr "Премахване на парола"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Премахване на защитата с парола..."
@@ -2357,6 +2381,10 @@ msgstr "След това въведете шестцифрения код, ко
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Възникна проблем при генерирането на PDF, моля, опитайте отново след известно време."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Актуализиране на автобиография"
msgid "Update your password"
msgstr "Актуализирайте паролата си"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Актуализиране на паролата ви..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "পরের দিকে সারি যোগ করুন"
msgid "Add Row Before"
msgstr "আগের দিকে সারি যোগ করুন"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "আফ্রিকান্স"
msgid "AI"
msgstr "এআই"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "আলবেনিয়ান"
@@ -340,6 +348,10 @@ msgstr "অধ্যয়নের এলাকা"
msgid "Artificial Intelligence"
msgstr "কৃত্রিম বুদ্ধিমত্তা"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "আকারের অনুপাত"
@@ -534,6 +546,10 @@ msgstr "চীনা (প্রচলিত)"
msgid "Circle"
msgstr "বৃত্ত"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "নির্বাচন মুছে ফেলুন"
@@ -945,6 +961,10 @@ msgstr "আপনার জীবনবৃত্তান্ত ডুপ্ল
msgid "Dutch"
msgstr "ডাচ"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "শিক্ষা"
@@ -1896,6 +1916,10 @@ msgstr "পাসওয়ার্ড মনে আছে? <0><1>এখনই
msgid "Remove Password"
msgstr "পাসওয়ার্ড সরিয়ে ফেলুন"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "পাসওয়ার্ড সুরক্ষা সরানো হচ্ছে..."
@@ -2357,6 +2381,10 @@ msgstr "তারপর, অ্যাপটি যে ৬ সংখ্যার
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF তৈরি করার সময় একটি সমস্যা হয়েছে, অনুগ্রহ করে কিছু সময় পরে আবার চেষ্টা করুন।"
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "জীবনবৃত্তান্ত আপডেট করুন"
msgid "Update your password"
msgstr "আপনার পাসওয়ার্ড আপডেট করুন"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "আপনার পাসওয়ার্ড আপডেট করা হচ্ছে..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Afegeix una fila després"
msgid "Add Row Before"
msgstr "Afegeix una fila abans"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "IA"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanès"
@@ -340,6 +348,10 @@ msgstr "Àrea d’estudi"
msgid "Artificial Intelligence"
msgstr "Intel·ligència artificial"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Relació d’aspecte"
@@ -534,6 +546,10 @@ msgstr "Xinès (tradicional)"
msgid "Circle"
msgstr "Cercle"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Esborra la selecció"
@@ -945,6 +961,10 @@ msgstr "S’està duplicant el currículum..."
msgid "Dutch"
msgstr "Neerlandès"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Educació"
@@ -1896,6 +1916,10 @@ msgstr "Recordes la contrasenya? <0><1>Inicia sessió ara <2/></1></0>"
msgid "Remove Password"
msgstr "Elimina la contrasenya"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "S’està desactivant la protecció amb contrasenya..."
@@ -2357,6 +2381,10 @@ msgstr "A continuació, introdueix el codi de 6 dígits que proporciona l’apli
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "S’ha produït un problema en generar el PDF, torna-ho a provar més tard."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Actualitza el currículum"
msgid "Update your password"
msgstr "Actualitza la contrasenya"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "S’està actualitzant la contrasenya..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Přidat řádek za"
msgid "Add Row Before"
msgstr "Přidat řádek před"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikánština"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albánština"
@@ -340,6 +348,10 @@ msgstr "Studijní obor"
msgid "Artificial Intelligence"
msgstr "Umělá inteligence"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Poměr stran"
@@ -534,6 +546,10 @@ msgstr "Čínština (tradiční)"
msgid "Circle"
msgstr "Kruh"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Zrušit výběr"
@@ -945,6 +961,10 @@ msgstr "Duplikování životopisu…"
msgid "Dutch"
msgstr "Nizozemština"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Vzdělání"
@@ -1896,6 +1916,10 @@ msgstr "Pamatujete si heslo? <0><1>Přihlaste se nyní <2/></1></0>"
msgid "Remove Password"
msgstr "Odebrat heslo"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Odstraňování ochrany heslem…"
@@ -2357,6 +2381,10 @@ msgstr "Poté zadejte šestimístný kód, který aplikace poskytne, abyste mohl
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Při generování PDF došlo k problému, zkuste to prosím znovu za chvíli."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Aktualizovat životopis"
msgid "Update your password"
msgstr "Aktualizujte své heslo"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Aktualizace hesla…"
+32
View File
@@ -207,6 +207,10 @@ msgstr "Tilføj række efter"
msgid "Add Row Before"
msgstr "Tilføj række før"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albansk"
@@ -340,6 +348,10 @@ msgstr "Studieområde"
msgid "Artificial Intelligence"
msgstr "Kunstig intelligens"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Billedformat"
@@ -534,6 +546,10 @@ msgstr "Kinesisk (traditionelt)"
msgid "Circle"
msgstr "Cirkel"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Ryd markering"
@@ -945,6 +961,10 @@ msgstr "Duplikerer dit CV..."
msgid "Dutch"
msgstr "Hollandsk"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Uddannelse"
@@ -1896,6 +1916,10 @@ msgstr "Kan du huske din adgangskode? <0><1>Log ind nu <2/></1></0>"
msgid "Remove Password"
msgstr "Fjern adgangskode"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Fjerner adgangskodebeskyttelse..."
@@ -2357,6 +2381,10 @@ msgstr "Indtast derefter den 6-cifrede kode, som appen giver, for at fortsætte.
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Der opstod et problem under generering af PDF'en, prøv igen om lidt."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Opdater CV"
msgid "Update your password"
msgstr "Opdater din adgangskode"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Opdaterer din adgangskode..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Zeile danach einfügen"
msgid "Add Row Before"
msgstr "Zeile davor einfügen"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "KI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanisch"
@@ -340,6 +348,10 @@ msgstr "Studienfach"
msgid "Artificial Intelligence"
msgstr "Künstliche Intelligenz"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Seitenverhältnis"
@@ -534,6 +546,10 @@ msgstr "Chinesisch (traditionell)"
msgid "Circle"
msgstr "Kreis"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Auswahl löschen"
@@ -945,6 +961,10 @@ msgstr "Ihr Lebenslauf wird dupliziert..."
msgid "Dutch"
msgstr "Niederländisch"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Ausbildung"
@@ -1896,6 +1916,10 @@ msgstr "Sie erinnern sich wieder an Ihr Passwort? <0><1>Jetzt anmelden <2/></1><
msgid "Remove Password"
msgstr "Passwort entfernen"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Passwortschutz wird entfernt..."
@@ -2357,6 +2381,10 @@ msgstr "Geben Sie dann den 6-stelligen Code ein, den die App bereitstellt, um fo
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Beim Erzeugen des PDFs ist ein Problem aufgetreten, bitte versuche es in einiger Zeit erneut."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Lebenslauf aktualisieren"
msgid "Update your password"
msgstr "Aktualisieren Sie Ihr Passwort"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Ihr Passwort wird aktualisiert..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Προσθήκη γραμμής μετά"
msgid "Add Row Before"
msgstr "Προσθήκη γραμμής πριν"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Αφρικάανς"
msgid "AI"
msgstr "ΤΝ"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Αλβανικά"
@@ -340,6 +348,10 @@ msgstr "Τομέας σπουδών"
msgid "Artificial Intelligence"
msgstr "Τεχνητή Νοημοσύνη"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Αναλογία διαστάσεων"
@@ -534,6 +546,10 @@ msgstr "Κινέζικα (Παραδοσιακά)"
msgid "Circle"
msgstr "Κύκλος"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Απαλοιφή επιλογής"
@@ -945,6 +961,10 @@ msgstr "Δημιουργία αντιγράφου του βιογραφικού
msgid "Dutch"
msgstr "Ολλανδικά"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Εκπαίδευση"
@@ -1896,6 +1916,10 @@ msgstr "Θυμάστε τον κωδικό πρόσβασής σας; <0><1>Συ
msgid "Remove Password"
msgstr "Κατάργηση κωδικού πρόσβασης"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Κατάργηση προστασίας με κωδικό πρόσβασης..."
@@ -2357,6 +2381,10 @@ msgstr "Στη συνέχεια, εισαγάγετε τον 6ψήφιο κωδ
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Παρουσιάστηκε πρόβλημα κατά τη δημιουργία του PDF, δοκιμάστε ξανά σε λίγο."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Ενημέρωση βιογραφικού σημειώματος"
msgid "Update your password"
msgstr "Ενημερώστε τον κωδικό πρόσβασής σας"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Ενημέρωση του κωδικού πρόσβασής σας..."
+32
View File
@@ -202,6 +202,10 @@ msgstr "Add Row After"
msgid "Add Row Before"
msgstr "Add Row Before"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr "Added"
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -220,6 +224,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr "AI Chat"
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanian"
@@ -335,6 +343,10 @@ msgstr "Area of Study"
msgid "Artificial Intelligence"
msgstr "Artificial Intelligence"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr "Ask me to update your resume..."
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Aspect Ratio"
@@ -529,6 +541,10 @@ msgstr "Chinese (Traditional)"
msgid "Circle"
msgstr "Circle"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr "Clear chat history"
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Clear selection"
@@ -940,6 +956,10 @@ msgstr "Duplicating your resume..."
msgid "Dutch"
msgstr "Dutch"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr "e.g. Change my name to..."
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Education"
@@ -1891,6 +1911,10 @@ msgstr "Remember your password? <0><1>Sign in now <2/></1></0>"
msgid "Remove Password"
msgstr "Remove Password"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr "Removed"
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Removing password protection..."
@@ -2352,6 +2376,10 @@ msgstr "Then, enter the 6 digit code that the app provides to continue."
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "There was a problem while generating the PDF, please try again in some time."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr "Thinking..."
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2615,6 +2643,10 @@ msgstr "Update Resume"
msgid "Update your password"
msgstr "Update your password"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr "Updated"
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Updating your password..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Añadir fila después"
msgid "Add Row Before"
msgstr "Añadir fila antes"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikáans"
msgid "AI"
msgstr "IA"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanés"
@@ -340,6 +348,10 @@ msgstr "Área de estudio"
msgid "Artificial Intelligence"
msgstr "Inteligencia artificial"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Relación de aspecto"
@@ -534,6 +546,10 @@ msgstr "Chino (tradicional)"
msgid "Circle"
msgstr "Círculo"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Borrar selección"
@@ -945,6 +961,10 @@ msgstr "Duplicando tu currículum..."
msgid "Dutch"
msgstr "Neerlandés"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Formación académica"
@@ -1896,6 +1916,10 @@ msgstr "¿Recuerdas tu contraseña? <0><1>Inicia sesión ahora <2/></1></0>"
msgid "Remove Password"
msgstr "Quitar contraseña"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Quitando la protección con contraseña..."
@@ -2357,6 +2381,10 @@ msgstr "Luego, introduce el código de 6 dígitos que te proporciona la aplicaci
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Ha habido un problema al generar el PDF, inténtalo de nuevo dentro de un rato."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Actualizar currículum"
msgid "Update your password"
msgstr "Actualiza tu contraseña"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Actualizando tu contraseña..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "افزودن ردیف بعد از این"
msgid "Add Row Before"
msgstr "افزودن ردیف قبل از این"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "آفریکانس"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "آلبانیایی"
@@ -340,6 +348,10 @@ msgstr "حوزهٔ تحصیل"
msgid "Artificial Intelligence"
msgstr "هوش مصنوعی"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "نسبت تصویر"
@@ -534,6 +546,10 @@ msgstr "چینی (سنتی)"
msgid "Circle"
msgstr "دایره"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "پاک کردن انتخاب"
@@ -945,6 +961,10 @@ msgstr "در حال تکثیر رزومه شما..."
msgid "Dutch"
msgstr "هلندی"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "تحصیلات"
@@ -1896,6 +1916,10 @@ msgstr "گذرواژه‌تان را به یاد آوردید؟ <0><1>همین
msgid "Remove Password"
msgstr "حذف گذرواژه"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "در حال حذف حفاظت با گذرواژه..."
@@ -2357,6 +2381,10 @@ msgstr "سپس، کد ۶ رقمی که اپ در اختیار شما می‌گذ
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "هنگام تولید PDF مشکلی پیش آمد، لطفاً بعداً دوباره تلاش کنید."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "به‌روزرسانی رزومه"
msgid "Update your password"
msgstr "گذرواژهٔ خود را به‌روزرسانی کنید"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "در حال به‌روزرسانی گذرواژه شما..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Lisää rivi jälkeen"
msgid "Add Row Before"
msgstr "Lisää rivi ennen"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "afrikaans"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "albania"
@@ -340,6 +348,10 @@ msgstr "Opintoala"
msgid "Artificial Intelligence"
msgstr "Tekoäly"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Kuvasuhde"
@@ -534,6 +546,10 @@ msgstr "kiina (perinteinen)"
msgid "Circle"
msgstr "Ympyrä"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Tyhjennä valinta"
@@ -945,6 +961,10 @@ msgstr "Monistetaan ansioluetteloasi..."
msgid "Dutch"
msgstr "hollanti"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Koulutus"
@@ -1896,6 +1916,10 @@ msgstr "Muistatko salasanasi? <0><1>Kirjaudu sisään nyt <2/></1></0>"
msgid "Remove Password"
msgstr "Poista salasana"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Poistetaan salasanasuojausta..."
@@ -2357,6 +2381,10 @@ msgstr "Syötä sitten sovelluksen antama kuusinumeroinen koodi jatkaaksesi."
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF:n luonnissa ilmeni ongelma, yritä hetken kuluttua uudelleen."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Päivitä ansioluettelo"
msgid "Update your password"
msgstr "Päivitä salasanasi"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Päivitetään salasanaasi..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Ajouter une ligne après"
msgid "Add Row Before"
msgstr "Ajouter une ligne avant"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "IA"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanais"
@@ -340,6 +348,10 @@ msgstr "Domaine d'étude"
msgid "Artificial Intelligence"
msgstr "Intelligence artificielle"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Format d'image"
@@ -534,6 +546,10 @@ msgstr "Chinois (traditionnel)"
msgid "Circle"
msgstr "Cercle"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Effacer la sélection"
@@ -945,6 +961,10 @@ msgstr "Duplication de votre CV..."
msgid "Dutch"
msgstr "Néerlandais"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Formation"
@@ -1896,6 +1916,10 @@ msgstr "Vous vous souvenez de votre mot de passe ? <0><1>Connectez-vous maintena
msgid "Remove Password"
msgstr "Supprimer le mot de passe"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Suppression de la protection par mot de passe..."
@@ -2357,6 +2381,10 @@ msgstr "Ensuite, entrez le code à 6 chiffres fourni par l'application pour cont
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Un problème est survenu lors de la génération du PDF, veuillez réessayer dans quelque temps."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Modifier le CV"
msgid "Update your password"
msgstr "Modifier votre mot de passe"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Mise à jour de votre mot de passe..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "הוספת שורה אחרי"
msgid "Add Row Before"
msgstr "הוספת שורה לפני"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "אפריקאנס"
msgid "AI"
msgstr "בינה מלאכותית"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "אלבנית"
@@ -340,6 +348,10 @@ msgstr "תחום לימודים"
msgid "Artificial Intelligence"
msgstr "בינה מלאכותית"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "יחס גובה־רוחב"
@@ -534,6 +546,10 @@ msgstr "סינית (מסורתית)"
msgid "Circle"
msgstr "עיגול"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "ניקוי הבחירה"
@@ -945,6 +961,10 @@ msgstr "משכפל את קורות החיים שלך..."
msgid "Dutch"
msgstr "הולנדית"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "השכלה"
@@ -1896,6 +1916,10 @@ msgstr "נזכרת בסיסמה? <0><1>התחברות עכשיו <2/></1></0>"
msgid "Remove Password"
msgstr "הסרת סיסמה"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "מסיר את ההגנה באמצעות סיסמה..."
@@ -2357,6 +2381,10 @@ msgstr "לאחר מכן, הזן את הקוד בן 6 הספרות שהאפליק
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "אירעה בעיה בעת יצירת קובץ ה־PDF, נא לנסות שוב מאוחר יותר."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "עדכון קורות חיים"
msgid "Update your password"
msgstr "עדכון הסיסמה שלך"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "מעדכן את הסיסמה שלך..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "इसके बाद पंक्ति जोड़ें"
msgid "Add Row Before"
msgstr "इसके पहले पंक्ति जोड़ें"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "अफ्रीकान्स"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "अल्बानियाई"
@@ -340,6 +348,10 @@ msgstr "अध्ययन का क्षेत्र"
msgid "Artificial Intelligence"
msgstr "कृत्रिम बुद्धिमत्ता"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "आकार अनुपात"
@@ -534,6 +546,10 @@ msgstr "चीनी (परंपरागत)"
msgid "Circle"
msgstr "गोला"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "चयन साफ़ करें"
@@ -945,6 +961,10 @@ msgstr "आपका रेज़्यूमे डुप्लिकेट क
msgid "Dutch"
msgstr "डच"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "शिक्षा"
@@ -1896,6 +1916,10 @@ msgstr "पासवर्ड याद है? <0><1>अभी साइन इ
msgid "Remove Password"
msgstr "पासवर्ड हटाएँ"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "पासवर्ड सुरक्षा हटाई जा रही है..."
@@ -2357,6 +2381,10 @@ msgstr "फिर, जारी रखने के लिए ऐप द्व
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF जेनरेट करते समय कोई समस्या आई, कृपया कुछ समय बाद फिर से प्रयास करें।"
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "रेज़्यूमे अपडेट करें"
msgid "Update your password"
msgstr "अपना पासवर्ड अपडेट करें"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "आपका पासवर्ड अपडेट किया जा रहा है..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Sor hozzáadása alá"
msgid "Add Row Before"
msgstr "Sor hozzáadása fölé"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "afrikaans"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "albán"
@@ -340,6 +348,10 @@ msgstr "Tanulmányok területe"
msgid "Artificial Intelligence"
msgstr "Mesterséges intelligencia"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Méretarány"
@@ -534,6 +546,10 @@ msgstr "kínai (hagyományos)"
msgid "Circle"
msgstr "Kör"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Kijelölés törlése"
@@ -945,6 +961,10 @@ msgstr "Önéletrajz duplikálása..."
msgid "Dutch"
msgstr "holland"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Tanulmányok"
@@ -1896,6 +1916,10 @@ msgstr "Eszébe jutott a jelszó? <0><1>Jelentkezz be most <2/></1></0>"
msgid "Remove Password"
msgstr "Jelszó eltávolítása"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Jelszóvédelem eltávolítása..."
@@ -2357,6 +2381,10 @@ msgstr "Ezután írd be a folytatáshoz az alkalmazás által megadott 6 számje
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Hiba történt a PDF generálása közben, kérjük, próbáld meg később újra."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Önéletrajz frissítése"
msgid "Update your password"
msgstr "Jelszó frissítése"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Jelszó frissítése..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Tambah Baris Setelah"
msgid "Add Row Before"
msgstr "Tambah Baris Sebelum"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "Kecerdasan Buatan"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albania"
@@ -340,6 +348,10 @@ msgstr "Bidang Studi"
msgid "Artificial Intelligence"
msgstr "Kecerdasan Buatan"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Rasio Aspek"
@@ -534,6 +546,10 @@ msgstr "Cina (Tradisional)"
msgid "Circle"
msgstr "Lingkaran"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Hapus pilihan"
@@ -945,6 +961,10 @@ msgstr "Menduplikasi resume Anda..."
msgid "Dutch"
msgstr "Belanda"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Pendidikan"
@@ -1896,6 +1916,10 @@ msgstr "Ingat kata sandi Anda? <0><1>Masuk sekarang <2/></1></0>"
msgid "Remove Password"
msgstr "Hapus Kata Sandi"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Menghapus perlindungan kata sandi..."
@@ -2357,6 +2381,10 @@ msgstr "Lalu, masukkan kode 6 digit yang diberikan aplikasi untuk melanjutkan."
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Terjadi masalah saat membuat PDF, silakan coba lagi nanti."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Perbarui Resume"
msgid "Update your password"
msgstr "Perbarui kata sandi Anda"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Memperbarui kata sandi Anda..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Aggiungi riga dopo"
msgid "Add Row Before"
msgstr "Aggiungi riga prima"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "IA"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanese"
@@ -340,6 +348,10 @@ msgstr "Area di studio"
msgid "Artificial Intelligence"
msgstr "Intelligenza artificiale"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Proporzioni"
@@ -534,6 +546,10 @@ msgstr "Cinese (tradizionale)"
msgid "Circle"
msgstr "Cerchio"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Pulisci selezione"
@@ -945,6 +961,10 @@ msgstr "Duplicazione del tuo curriculum in corso..."
msgid "Dutch"
msgstr "Olandese"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Formazione"
@@ -1896,6 +1916,10 @@ msgstr "Ti ricordi la password? <0><1>Accedi ora <2/></1></0>"
msgid "Remove Password"
msgstr "Rimuovi password"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Rimozione della protezione tramite password..."
@@ -2357,6 +2381,10 @@ msgstr "Quindi inserisci il codice a 6 cifre fornito dall'app per continuare."
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Si è verificato un problema durante la generazione del PDF, riprova tra qualche istante."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Aggiorna curriculum"
msgid "Update your password"
msgstr "Aggiorna la tua password"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Aggiornamento della tua password in corso..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "後に行を追加"
msgid "Add Row Before"
msgstr "前に行を追加"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "アフリカーンス語"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "アルバニア語"
@@ -340,6 +348,10 @@ msgstr "研究分野"
msgid "Artificial Intelligence"
msgstr "人工知能"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "アスペクト比"
@@ -534,6 +546,10 @@ msgstr "中国語(繁体字)"
msgid "Circle"
msgstr "円"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "選択をクリア"
@@ -945,6 +961,10 @@ msgstr "履歴書を複製しています..."
msgid "Dutch"
msgstr "オランダ語"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "学歴"
@@ -1896,6 +1916,10 @@ msgstr "パスワードを思い出しましたか?<0><1>今すぐサインイ
msgid "Remove Password"
msgstr "パスワードを削除"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "パスワード保護を解除しています..."
@@ -2357,6 +2381,10 @@ msgstr "次に、続行するためにアプリが表示する 6 桁のコード
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF の生成中に問題が発生しました。しばらくしてからもう一度お試しください。"
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "履歴書を更新"
msgid "Update your password"
msgstr "パスワードを更新してください。"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "パスワードを更新しています..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "បន្ថែម​ជួរដេក​នៅ​ក្រោយ"
msgid "Add Row Before"
msgstr "បន្ថែម​ជួរដេក​នៅ​មុខ"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanian"
@@ -340,6 +348,10 @@ msgstr "ជំនាញ​រៀន"
msgid "Artificial Intelligence"
msgstr "បញ្ញាសិប្បនិម្មិត"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "សមាមាត្រទ្រង់ទ្រាយ"
@@ -534,6 +546,10 @@ msgstr "Chinese (Traditional)"
msgid "Circle"
msgstr "រង្វង់"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "សម្អាត​ការ​ជ្រើសរើស"
@@ -945,6 +961,10 @@ msgstr "កំពុង​ស្ទួន​ប្រវត្តិរូប​
msgid "Dutch"
msgstr "Dutch"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "ការ​សិក្សា"
@@ -1896,6 +1916,10 @@ msgstr "ចង់​ចាំ​ពាក្យសម្ងាត់វិញ​
msgid "Remove Password"
msgstr "ដក​ពាក្យសម្ងាត់"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "កំពុង​ដក​ការ​ការពារ​ដោយ​ពាក្យសម្ងាត់..."
@@ -2357,6 +2381,10 @@ msgstr "បន្ទាប់មក បញ្ចូល​កូដ ៦ ខ្ទ
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "មាន​បញ្ហា​មួយ​កើតឡើង ខណៈពេល​កំពុង​បង្កើត PDF សូម​ព្យាយាម​ម្ដង​ទៀត​ក្រោយ​មក។"
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "បច្ចុប្បន្នភាព​ប្រវត្តិរ
msgid "Update your password"
msgstr "បច្ចុប្បន្នភាព​ពាក្យសម្ងាត់​របស់​អ្នក"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "កំពុង​បច្ចុប្បន្នភាព​ពាក្យសម្ងាត់​របស់​អ្នក..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "ಸಾಲನ್ನು ನಂತರ ಸೇರಿಸಿ"
msgid "Add Row Before"
msgstr "ಸಾಲನ್ನು ಮೊದಲು ಸೇರಿಸಿ"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "ಆಫ್ರಿಕಾನ್ಸ್"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "ಅಲ್ಬೇನಿಯನ್"
@@ -340,6 +348,10 @@ msgstr "ಅಧ್ಯಯನದ ಕ್ಷೇತ್ರ"
msgid "Artificial Intelligence"
msgstr "ಕೃತಕ ಬುದ್ಧಿವಂತಿಕೆ"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "ಆಕಾರ ಅನುಪಾತ"
@@ -534,6 +546,10 @@ msgstr "ಚೈನೀಸ್ (ಸಾಂಪ್ರದಾಯಿಕ)"
msgid "Circle"
msgstr "ವೃತ್ತ"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "ಆಯ್ಕೆಯನ್ನು ತೆರವುಗೊಳಿಸಿ"
@@ -945,6 +961,10 @@ msgstr "ನಿಮ್ಮ ರೆಸ್ಯೂಮ್ ನಕಲಿಸಲಾಗುತ
msgid "Dutch"
msgstr "ಡಚ್"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "ಶಿಕ್ಷಣ"
@@ -1896,6 +1916,10 @@ msgstr "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ನೆನಪಿದೆಯ
msgid "Remove Password"
msgstr "ಪಾಸ್‌ವರ್ಡ್ ತೆಗೆದುಹಾಕಿ"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "ಪಾಸ್‌ವರ್ಡ್ ರಕ್ಷಣೆಯನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತಿದೆ..."
@@ -2357,6 +2381,10 @@ msgstr "ನಂತರ, ಆ್ಯಪ್ ನೀಡುವ 6 ಅಂಕಿಯ ಕೋ
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF ರಚಿಸುವಾಗ ಒಂದು ಸಮಸ್ಯೆ ಉಂಟಾಯಿತು, ದಯವಿಟ್ಟು ಸ್ವಲ್ಪ ಸಮಯದ ಬಳಿಕ ಮರುಪ್ರಯತ್ನಿಸಿ."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "ರೆಸ್ಯೂಮ್ ನವೀಕರಿಸಿ"
msgid "Update your password"
msgstr "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನವೀಕರಿಸಿ"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನವೀಕರಿಸಲಾಗುತ್ತಿದೆ..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "뒤에 행 추가"
msgid "Add Row Before"
msgstr "앞에 행 추가"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "아프리칸스어"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "알바니아어"
@@ -340,6 +348,10 @@ msgstr "연구 분야"
msgid "Artificial Intelligence"
msgstr "인공지능"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "가로세로 비율"
@@ -534,6 +546,10 @@ msgstr "중국어(번체)"
msgid "Circle"
msgstr "원"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "선택 해제"
@@ -945,6 +961,10 @@ msgstr "이력서를 복제하는 중입니다..."
msgid "Dutch"
msgstr "네덜란드어"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "학력"
@@ -1896,6 +1916,10 @@ msgstr "비밀번호가 기억나시나요? <0><1>지금 로그인하기 <2/></1
msgid "Remove Password"
msgstr "비밀번호 제거"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "비밀번호 보호를 제거하는 중입니다..."
@@ -2357,6 +2381,10 @@ msgstr "그 다음, 앱에 표시된 6자리 코드를 입력해 계속 진행
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF를 생성하는 동안 문제가 발생했습니다. 잠시 후 다시 시도해 주세요."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "이력서 업데이트"
msgid "Update your password"
msgstr "비밀번호 업데이트"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "비밀번호를 업데이트하는 중입니다..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Pridėti eilutę po"
msgid "Add Row Before"
msgstr "Pridėti eilutę prieš"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikanso"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanų"
@@ -340,6 +348,10 @@ msgstr "Studijų sritis"
msgid "Artificial Intelligence"
msgstr "Dirbtinis intelektas"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Vaizdo santykis"
@@ -534,6 +546,10 @@ msgstr "Kinų (tradicinė)"
msgid "Circle"
msgstr "Apskritimas"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Išvalyti pasirinkimą"
@@ -945,6 +961,10 @@ msgstr "Dubliuojamas jūsų gyvenimo aprašymas..."
msgid "Dutch"
msgstr "Olandų"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Išsilavinimas"
@@ -1896,6 +1916,10 @@ msgstr "Prisiminate slaptažodį? <0><1>Prisijunkite dabar <2/></1></0>"
msgid "Remove Password"
msgstr "Pašalinti slaptažodį"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Šalinama apsauga slaptažodžiu..."
@@ -2357,6 +2381,10 @@ msgstr "Tada įveskite programos sugeneruotą 6 skaitmenų kodą, kad tęstumėt
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Kilo problema generuojant PDF. Bandykite dar kartą po kurio laiko."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Atnaujinti gyvenimo aprašymą"
msgid "Update your password"
msgstr "Atnaujinkite savo slaptažodį"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Atnaujinamas jūsų slaptažodis..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Pievienot rindu pēc"
msgid "Add Row Before"
msgstr "Pievienot rindu pirms"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikandu"
msgid "AI"
msgstr "MI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albāņu"
@@ -340,6 +348,10 @@ msgstr "Studiju joma"
msgid "Artificial Intelligence"
msgstr "Mākslīgais intelekts"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Proporcijas"
@@ -534,6 +546,10 @@ msgstr "Ķīniešu (tradicionālā)"
msgid "Circle"
msgstr "Aplis"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Notīrīt izvēli"
@@ -945,6 +961,10 @@ msgstr "Tiek dublēts jūsu CV..."
msgid "Dutch"
msgstr "Holandiešu"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Izglītība"
@@ -1896,6 +1916,10 @@ msgstr "Atceraties savu paroli? <0><1>Piesakieties tagad <2/></1></0>"
msgid "Remove Password"
msgstr "Noņemt paroli"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Tiek noņemta paroles aizsardzība..."
@@ -2357,6 +2381,10 @@ msgstr "Pēc tam ievadiet 6 ciparu kodu, ko nodrošina lietotne, lai turpinātu.
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Radās problēma, ģenerējot PDF, lūdzu, mēģiniet vēlreiz pēc kāda laika."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Atjaunināt CV"
msgid "Update your password"
msgstr "Atjauniniet savu paroli"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Tiek atjaunināta jūsu parole..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "വരി പിന്നീട് ചേർക്കുക"
msgid "Add Row Before"
msgstr "വരി മുമ്പ് ചേർക്കുക"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "ആഫ്രിക്കാൻസ്"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "അൽബേനിയൻ"
@@ -340,6 +348,10 @@ msgstr "പഠന മേഖല"
msgid "Artificial Intelligence"
msgstr "ആർട്ടിഫിഷ്യൽ ഇന്റലിജൻസ്"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "ആസ്പെക്ട് റേഷ്യോ"
@@ -534,6 +546,10 @@ msgstr "ചൈനീസ് (ട്രഡീഷണൽ)"
msgid "Circle"
msgstr "വൃത്തം"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "തിരഞ്ഞെടുപ്പ് ക്ലിയർ ചെയ്യുക"
@@ -945,6 +961,10 @@ msgstr "നിങ്ങളുടെ റിസ്യൂം ഡൂപ്ലിക
msgid "Dutch"
msgstr "ഡച്ച്"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "വിദ്യാഭ്യാസം"
@@ -1896,6 +1916,10 @@ msgstr "നിങ്ങളുടെ പാസ്‌വേഡ് ഓർമ്മ
msgid "Remove Password"
msgstr "പാസ്‌വേഡ് നീക്കുക"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "പാസ്‌വേഡ് സംരക്ഷണം നീക്കം ചെയ്യുന്നു..."
@@ -2357,6 +2381,10 @@ msgstr "ശേഷം, ആപ്പ് നൽകുന്ന 6 അക്ക ക
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF നിർമ്മിക്കുന്നതിനിടെ ഒരു പ്രശ്നം ഉണ്ടായി, ദയവായി കുറച്ചുസമയം കഴിഞ്ഞ് വീണ്ടും ശ്രമിക്കുക."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "റിസ്യൂം അപ്‌ഡേറ്റ് ചെയ്യു
msgid "Update your password"
msgstr "നിങ്ങളുടെ പാസ്‌വേഡ് അപ്‌ഡേറ്റ് ചെയ്യുക"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "നിങ്ങളുടെ പാസ്‌വേഡ് അപ്‌ഡേറ്റ് ചെയ്യുന്നു..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "नंतर ओळ जोडा"
msgid "Add Row Before"
msgstr "आधी ओळ जोडा"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "आफ्रिकान्स"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "अल्बेनियन"
@@ -340,6 +348,10 @@ msgstr "अभ्यासाचे क्षेत्र"
msgid "Artificial Intelligence"
msgstr "कृत्रिम बुद्धिमत्ता"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "प्रसर गुणोत्तर"
@@ -534,6 +546,10 @@ msgstr "चीनी (परंपरागत)"
msgid "Circle"
msgstr "गोलाकार"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "निवड साफ करा"
@@ -945,6 +961,10 @@ msgstr "तुमचा रेझ्युमे डुप्लिकेट क
msgid "Dutch"
msgstr "डच"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "शिक्षण"
@@ -1896,6 +1916,10 @@ msgstr "पासवर्ड आठवला? <0><1>आता साइन इ
msgid "Remove Password"
msgstr "पासवर्ड काढा"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "पासवर्ड संरक्षण काढून टाकले जात आहे..."
@@ -2357,6 +2381,10 @@ msgstr "त्यानंतर, पुढे जाण्यासाठी
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF तयार करताना समस्या आली, कृपया थोड्या वेळाने पुन्हा प्रयत्न करा."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "रेझ्युमे अपडेट करा"
msgid "Update your password"
msgstr "तुमचा पासवर्ड अपडेट करा"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "तुमचा पासवर्ड अपडेट केला जात आहे..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Tambah Baris Selepas"
msgid "Add Row Before"
msgstr "Tambah Baris Sebelum"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanian"
@@ -340,6 +348,10 @@ msgstr "Bidang Pengajian"
msgid "Artificial Intelligence"
msgstr "Kecerdasan Buatan"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Nisbah Aspek"
@@ -534,6 +546,10 @@ msgstr "Cina (Tradisional)"
msgid "Circle"
msgstr "Bulatan"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Kosongkan pilihan"
@@ -945,6 +961,10 @@ msgstr "Menduplikasi resume anda..."
msgid "Dutch"
msgstr "Belanda"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Pendidikan"
@@ -1896,6 +1916,10 @@ msgstr "Masih ingat kata laluan anda? <0><1>Log masuk sekarang <2/></1></0>"
msgid "Remove Password"
msgstr "Buang Kata Laluan"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Membuang perlindungan kata laluan..."
@@ -2357,6 +2381,10 @@ msgstr "Kemudian, masukkan kod 6 digit yang diberikan oleh apl untuk meneruskan.
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Terdapat masalah semasa menjana PDF, sila cuba lagi selepas beberapa ketika."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Kemas Kini Resume"
msgid "Update your password"
msgstr "Kemas kini kata laluan anda"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Mengemas kini kata laluan anda..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "पछि पङ्क्ति थप्नुहोस्"
msgid "Add Row Before"
msgstr "अघिल्लो पङ्क्ति थप्नुहोस्"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "अफ्रिकान्स"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "अल्बानियन"
@@ -340,6 +348,10 @@ msgstr "अध्ययन क्षेत्र"
msgid "Artificial Intelligence"
msgstr "कृत्रिम बौद्धिकता"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "आकार अनुपात (Aspect Ratio)"
@@ -534,6 +546,10 @@ msgstr "चिनियाँ (परम्परागत)"
msgid "Circle"
msgstr "वृत्त"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "चयन खाली गर्नुहोस्"
@@ -945,6 +961,10 @@ msgstr "तपाईंको बायोडाटा नक्कल हुँ
msgid "Dutch"
msgstr "डच"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "शिक्षा"
@@ -1896,6 +1916,10 @@ msgstr "पासवर्ड सम्झनुभयो? <0><1>अहिले
msgid "Remove Password"
msgstr "पासवर्ड हटाउनुहोस्"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "पासवर्ड सुरक्षा हटाइँदैछ..."
@@ -2357,6 +2381,10 @@ msgstr "त्यसपछि, जारी राख्न एपले दि
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF बनाउने क्रममा समस्या आयो, कृपया केही समयपछि पुनः प्रयास गर्नुहोस्।"
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "बायोडाटा अद्यावधिक गर्नुह
msgid "Update your password"
msgstr "तपाईंको पासवर्ड अद्यावधिक गर्नुहोस्"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "तपाईंको पासवर्ड अद्यावधिक हुँदैछ..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Rij erna toevoegen"
msgid "Add Row Before"
msgstr "Rij ervoor toevoegen"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanees"
@@ -340,6 +348,10 @@ msgstr "Studierichting"
msgid "Artificial Intelligence"
msgstr "Kunstmatige intelligentie"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Beeldverhouding"
@@ -534,6 +546,10 @@ msgstr "Chinees (traditioneel)"
msgid "Circle"
msgstr "Cirkel"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Selectie wissen"
@@ -945,6 +961,10 @@ msgstr "Uw cv wordt gedupliceerd..."
msgid "Dutch"
msgstr "Nederlands"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Opleiding"
@@ -1896,6 +1916,10 @@ msgstr "Herinnert u zich uw wachtwoord? <0><1>Meld u nu aan <2/></1></0>"
msgid "Remove Password"
msgstr "Wachtwoord verwijderen"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Wachtwoordbeveiliging wordt verwijderd..."
@@ -2357,6 +2381,10 @@ msgstr "Voer vervolgens de 6-cijferige code in die de app geeft om door te gaan.
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Er is een probleem opgetreden bij het genereren van de PDF, probeer het over enige tijd opnieuw."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Cv bijwerken"
msgid "Update your password"
msgstr "Werk uw wachtwoord bij"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Uw wachtwoord wordt bijgewerkt..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Legg til rad etter"
msgid "Add Row Before"
msgstr "Legg til rad før"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "KI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albansk"
@@ -340,6 +348,10 @@ msgstr "Studiefelt"
msgid "Artificial Intelligence"
msgstr "Kunstig intelligens"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Størrelsesforhold"
@@ -534,6 +546,10 @@ msgstr "Kinesisk (tradisjonell)"
msgid "Circle"
msgstr "Sirkel"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Fjern valg"
@@ -945,6 +961,10 @@ msgstr "Dupliserer CV-en din..."
msgid "Dutch"
msgstr "Nederlandsk"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Utdanning"
@@ -1896,6 +1916,10 @@ msgstr "Husker du passordet ditt? <0><1>Logg inn nå <2/></1></0>"
msgid "Remove Password"
msgstr "Fjern passord"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Fjerner passordbeskyttelse..."
@@ -2357,6 +2381,10 @@ msgstr "Skriv deretter inn den 6-sifrede koden som appen gir deg for å fortsett
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Det oppstod et problem under generering av PDF-en, prøv igjen om en stund."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Oppdater CV"
msgid "Update your password"
msgstr "Oppdater passordet ditt"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Oppdaterer passordet ditt..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "ପରେ ପଙ୍କ୍ତି ଯୋଡନ୍ତୁ"
msgid "Add Row Before"
msgstr "ପୂର୍ବେ ପଙ୍କ୍ତି ଯୋଡନ୍ତୁ"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "ଆଫ୍ରିକାନ୍ସ"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "ଆଲବାନିଆନ୍"
@@ -340,6 +348,10 @@ msgstr "ଅଧ୍ୟୟନ କ୍ଷେତ୍ର"
msgid "Artificial Intelligence"
msgstr "କୃତ୍ରିମ ବୁଦ୍ଧିମତ୍ତା"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "ଆସ୍ପେକ୍ଟ ଅନୁପାତ"
@@ -534,6 +546,10 @@ msgstr "ଚାଇନିଜ୍ (ପାରମ୍ପରିକ)"
msgid "Circle"
msgstr "ବୃତ୍ତ"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "ଚୟନ ସଫା କରନ୍ତୁ"
@@ -945,6 +961,10 @@ msgstr "ଆପଣଙ୍କ ରେଜ୍ୟୁମେ ନକଲ ହେଉଛି...
msgid "Dutch"
msgstr "ଡଚ୍"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "ଶିକ୍ଷା"
@@ -1896,6 +1916,10 @@ msgstr "ପାସୱାର୍ଡ ମନେ ପକାଇଲେ କି? <0><1>ଏ
msgid "Remove Password"
msgstr "ପାସୱାର୍ଡ ଅପସାରଣ କରନ୍ତୁ"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "ପାସୱାର୍ଡ ସୁରକ୍ଷା ଅପସାରଣ ହେଉଛି..."
@@ -2357,6 +2381,10 @@ msgstr "ତାପରେ, ଆଗକୁ ବଢ଼ିବା ପାଇଁ ଆପ୍
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF ସୃଷ୍ଟି କରୁଥିବା ସମୟରେ ସମସ୍ୟା ହୋଇଛି, ଦୟାକରି କିଛି ସମୟ ପରେ ପୁନଃ ଚେଷ୍ଟା କରନ୍ତୁ।"
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "ରେଜ୍ୟୁମେ ଅଦ୍ୟତନ କରନ୍ତୁ"
msgid "Update your password"
msgstr "ଆପଣଙ୍କ ପାସୱାର୍ଡ ଅଦ୍ୟତନ କରନ୍ତୁ"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "ଆପଣଙ୍କ ପାସୱାର୍ଡ ଅଦ୍ୟତନ ହେଉଛି..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Dodaj wiersz po"
msgid "Add Row Before"
msgstr "Dodaj wiersz przed"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albański"
@@ -340,6 +348,10 @@ msgstr "Kierunek studiów"
msgid "Artificial Intelligence"
msgstr "Sztuczna inteligencja"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Proporcje obrazu"
@@ -534,6 +546,10 @@ msgstr "Chiński (tradycyjny)"
msgid "Circle"
msgstr "Koło"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Wyczyść wybór"
@@ -945,6 +961,10 @@ msgstr "Duplikowanie CV..."
msgid "Dutch"
msgstr "Holenderski"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Wykształcenie"
@@ -1896,6 +1916,10 @@ msgstr "Pamiętasz hasło? <0><1>Zaloguj się teraz <2/></1></0>"
msgid "Remove Password"
msgstr "Usuń hasło"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Wyłączanie ochrony hasłem..."
@@ -2357,6 +2381,10 @@ msgstr "Następnie wpisz 6-cyfrowy kod podany przez aplikację, aby kontynuować
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Wystąpił problem podczas generowania pliku PDF, spróbuj ponownie za chwilę."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Zaktualizuj CV"
msgid "Update your password"
msgstr "Zaktualizuj swoje hasło"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Aktualizowanie hasła..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Adicionar linha depois"
msgid "Add Row Before"
msgstr "Adicionar linha antes"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Africâner"
msgid "AI"
msgstr "IA"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanês"
@@ -340,6 +348,10 @@ msgstr "Área de estudo"
msgid "Artificial Intelligence"
msgstr "Inteligência Artificial"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Proporção da imagem"
@@ -534,6 +546,10 @@ msgstr "Chinês (Tradicional)"
msgid "Circle"
msgstr "Círculo"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Limpar seleção"
@@ -945,6 +961,10 @@ msgstr "Duplicando seu currículo..."
msgid "Dutch"
msgstr "Holandês"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Formação"
@@ -1896,6 +1916,10 @@ msgstr "Lembrou da sua senha? <0><1>Entre agora <2/></1></0>"
msgid "Remove Password"
msgstr "Remover senha"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Removendo proteção por senha..."
@@ -2357,6 +2381,10 @@ msgstr "Em seguida, insira o código de 6 dígitos fornecido pelo aplicativo par
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Houve um problema ao gerar o PDF, tente novamente em alguns instantes."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Atualizar currículo"
msgid "Update your password"
msgstr "Atualize sua senha"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Atualizando sua senha..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Adicionar linha após"
msgid "Add Row Before"
msgstr "Adicionar linha antes"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Africâner"
msgid "AI"
msgstr "IA"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanês"
@@ -340,6 +348,10 @@ msgstr "Área de estudo"
msgid "Artificial Intelligence"
msgstr "Inteligência Artificial"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Proporção"
@@ -534,6 +546,10 @@ msgstr "Chinês (tradicional)"
msgid "Circle"
msgstr "Círculo"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Limpar seleção"
@@ -945,6 +961,10 @@ msgstr "A duplicar o seu currículo..."
msgid "Dutch"
msgstr "Neerlandês"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Formação"
@@ -1896,6 +1916,10 @@ msgstr "Lembra-se da sua senha? <0><1>Inicie sessão agora <2/></1></0>"
msgid "Remove Password"
msgstr "Remover senha"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "A remover a proteção por senha..."
@@ -2357,6 +2381,10 @@ msgstr "Em seguida, introduza o código de 6 dígitos fornecido pela aplicação
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Houve um problema ao gerar o PDF, tente novamente dentro de algum tempo."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Atualizar currículo"
msgid "Update your password"
msgstr "Atualize a sua senha"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "A atualizar a sua senha..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Adăugați rând după"
msgid "Add Row Before"
msgstr "Adăugați rând înainte"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albaneză"
@@ -340,6 +348,10 @@ msgstr "Domeniu de studiu"
msgid "Artificial Intelligence"
msgstr "Inteligență artificială"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Raport de aspect"
@@ -534,6 +546,10 @@ msgstr "Chineză (tradițională)"
msgid "Circle"
msgstr "Cerc"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Ștergeți selecția"
@@ -945,6 +961,10 @@ msgstr "Se duplică CV-ul..."
msgid "Dutch"
msgstr "Olandeză"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Educație"
@@ -1896,6 +1916,10 @@ msgstr "Vă amintiți parola? <0><1>Autentificați-vă acum <2/></1></0>"
msgid "Remove Password"
msgstr "Elimină parola"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Se elimină protecția prin parolă..."
@@ -2357,6 +2381,10 @@ msgstr "Apoi introduceți codul din 6 cifre oferit de aplicație pentru a contin
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "A apărut o problemă la generarea PDF-ului, vă rugăm să încercați din nou peste câteva momente."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Actualizați CV-ul"
msgid "Update your password"
msgstr "Actualizați-vă parola"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Se actualizează parola..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Добавить строку после"
msgid "Add Row Before"
msgstr "Добавить строку до"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Африкаанс"
msgid "AI"
msgstr "ИИ"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Албанский"
@@ -340,6 +348,10 @@ msgstr "Область обучения"
msgid "Artificial Intelligence"
msgstr "Искусственный интеллект"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Соотношение сторон"
@@ -534,6 +546,10 @@ msgstr "Китайский (традиционный)"
msgid "Circle"
msgstr "Круг"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Очистить выбор"
@@ -945,6 +961,10 @@ msgstr "Дублирование вашего резюме..."
msgid "Dutch"
msgstr "Нидерландский"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Образование"
@@ -1896,6 +1916,10 @@ msgstr "Вспомнили пароль? <0><1>Войдите сейчас <2/><
msgid "Remove Password"
msgstr "Удалить пароль"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Отключение защиты паролем..."
@@ -2357,6 +2381,10 @@ msgstr "Затем введите шестизначный код, предос
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Возникла проблема при генерации PDF, пожалуйста, попробуйте еще раз через некоторое время."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Обновить резюме"
msgid "Update your password"
msgstr "Обновите пароль"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Обновление пароля..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Pridať riadok za"
msgid "Add Row Before"
msgstr "Pridať riadok pred"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikánčina"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albánčina"
@@ -340,6 +348,10 @@ msgstr "Študijný odbor"
msgid "Artificial Intelligence"
msgstr "Umelá inteligencia"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Pomer strán"
@@ -534,6 +546,10 @@ msgstr "Čínština (tradičná)"
msgid "Circle"
msgstr "Kruh"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Zrušiť výber"
@@ -945,6 +961,10 @@ msgstr "Duplikujem tvoj životopis..."
msgid "Dutch"
msgstr "Holandčina"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Vzdelanie"
@@ -1896,6 +1916,10 @@ msgstr "Spomínaš si na heslo? <0><1>Prihlás sa teraz <2/></1></0>"
msgid "Remove Password"
msgstr "Odstrániť heslo"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Odstraňujem ochranu heslom..."
@@ -2357,6 +2381,10 @@ msgstr "Potom zadaj 6‑ciferný kód, ktorý ti aplikácia vygeneruje, aby si p
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Pri generovaní PDF sa vyskytol problém, skús to prosím znova o chvíľu."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Aktualizovať životopis"
msgid "Update your password"
msgstr "Aktualizuj svoje heslo"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Aktualizujem tvoje heslo..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Shto rresht pas"
msgid "Add Row Before"
msgstr "Shto rresht para"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikanisht"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Shqip"
@@ -340,6 +348,10 @@ msgstr "Fusha e studimit"
msgid "Artificial Intelligence"
msgstr "Inteligjenca Artificiale"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Proporcioni"
@@ -534,6 +546,10 @@ msgstr "Kinezçe (Tradicionale)"
msgid "Circle"
msgstr "Rreth"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Pastro përzgjedhjen"
@@ -945,6 +961,10 @@ msgstr "Po dyfishohet CV-ja juaj..."
msgid "Dutch"
msgstr "Holandisht"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Arsimimi"
@@ -1896,6 +1916,10 @@ msgstr "E kujtuat fjalëkalimin? <0><1>Hyni tani <2/></1></0>"
msgid "Remove Password"
msgstr "Hiq fjalëkalimin"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Po hiqet mbrojtja me fjalëkalim..."
@@ -2357,6 +2381,10 @@ msgstr "Më pas, futni kodin 6-shifror që jep aplikacioni për të vazhduar."
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Pati një problem gjatë gjenerimit të PDF-së, ju lutemi provoni përsëri pas pak."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Përditëso CV-në"
msgid "Update your password"
msgstr "Përditësoni fjalëkalimin tuaj"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Po përditësohet fjalëkalimi juaj..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Додај ред после"
msgid "Add Row Before"
msgstr "Додај ред пре"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Африканс"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Албански"
@@ -340,6 +348,10 @@ msgstr "Област студија"
msgid "Artificial Intelligence"
msgstr "Вештачка интелигенција"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Однос стране"
@@ -534,6 +546,10 @@ msgstr "Кинески (традиционални)"
msgid "Circle"
msgstr "Круг"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Обриши избор"
@@ -945,6 +961,10 @@ msgstr "Дуплирање вашег резимеа..."
msgid "Dutch"
msgstr "Холандски"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Образовање"
@@ -1896,6 +1916,10 @@ msgstr "Сећате се лозинке? <0><1>Пријавите се сада
msgid "Remove Password"
msgstr "Уклони лозинку"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Уклањање заштите лозинком..."
@@ -2357,6 +2381,10 @@ msgstr "Затим унесите шестоцифрени кôд који ап
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Дошло је до проблема током генерисања PDF-а, покушајте поново након неког времена."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Ажурирај резиме"
msgid "Update your password"
msgstr "Ажурирајте своју лозинку"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Ажурирање ваше лозинке..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Lägg till rad efter"
msgid "Add Row Before"
msgstr "Lägg till rad före"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikanska"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Albanska"
@@ -340,6 +348,10 @@ msgstr "Studieområde"
msgid "Artificial Intelligence"
msgstr "Artificiell intelligens"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Bildförhållande"
@@ -534,6 +546,10 @@ msgstr "Kinesiska (traditionell)"
msgid "Circle"
msgstr "Cirkel"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Rensa markering"
@@ -945,6 +961,10 @@ msgstr "Duplicerar ditt CV..."
msgid "Dutch"
msgstr "Nederländska"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Utbildning"
@@ -1896,6 +1916,10 @@ msgstr "Kommer du ihåg ditt lösenord? <0><1>Logga in nu <2/></1></0>"
msgid "Remove Password"
msgstr "Ta bort lösenord"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Tar bort lösenordsskydd..."
@@ -2357,6 +2381,10 @@ msgstr "Ange sedan den sexsiffriga kod som appen ger för att fortsätta."
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Det uppstod ett problem när PDF-filen skulle genereras, försök igen om en stund."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Uppdatera CV"
msgid "Update your password"
msgstr "Uppdatera ditt lösenord"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Uppdaterar ditt lösenord..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "பின் வரியைச் சேர்க்கவும்"
msgid "Add Row Before"
msgstr "முன் வரியைச் சேர்க்கவும்"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "ஆஃப்ரிகான்ஸ்"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "அல்பேனியன்"
@@ -340,6 +348,10 @@ msgstr "கற்றல் துறை"
msgid "Artificial Intelligence"
msgstr "செயற்கை நுண்ணறிவு"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "ஒப்புத்திணைவு விகிதம்"
@@ -534,6 +546,10 @@ msgstr "சீனம் (சம்பிரதாய)"
msgid "Circle"
msgstr "வட்டம்"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "தேர்வை அழிக்கவும்"
@@ -945,6 +961,10 @@ msgstr "உங்கள் ரெஸ்யூமியின் நகலை உ
msgid "Dutch"
msgstr "டச்சு"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "கல்வி"
@@ -1896,6 +1916,10 @@ msgstr "உங்கள் கடவுச்சொல் நினைவில
msgid "Remove Password"
msgstr "கடவுச்சொல்லை நீக்கு"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "கடவுச்சொல் பாதுகாப்பை நீக்கிக் கொண்டிருக்கிறது..."
@@ -2357,6 +2381,10 @@ msgstr "பின்னர், செயலி வழங்கும் 6 இல
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF உருவாக்கும் போது ஒரு பிரச்சனை ஏற்பட்டது, தயவுசெய்து சில நேரம் கழித்து மீண்டும் முயற்சிக்கவும்."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "ரெஸ்யூமியை புதுப்பிக்கவு
msgid "Update your password"
msgstr "உங்கள் கடவுச்சொல்லை புதுப்பிக்கவும்"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "உங்கள் கடவுச்சொல்லை புதுப்பித்து கொண்டிருக்கிறது..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "తరువాత వరుస చేర్చండి"
msgid "Add Row Before"
msgstr "ముందు వరుస చేర్చండి"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "ఆఫ్రికాన్స్"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "అల్బేనియన్"
@@ -340,6 +348,10 @@ msgstr "అధ్యయన విభాగం"
msgid "Artificial Intelligence"
msgstr "ఆర్టిఫిషియల్ ఇంటెలిజెన్స్"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "కారక నిష్పత్తి"
@@ -534,6 +546,10 @@ msgstr "చైనీస్ (సాంప్రదాయ)"
msgid "Circle"
msgstr "వృత్తం"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "ఎంపికను క్లియర్ చేయండి"
@@ -945,6 +961,10 @@ msgstr "మీ రిజ్యూమ్‌ను నకిలీ చేస్త
msgid "Dutch"
msgstr "డచ్"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "విద్య"
@@ -1896,6 +1916,10 @@ msgstr "మీకు పాస్‌వర్డ్ గుర్తుంది?
msgid "Remove Password"
msgstr "పాస్‌వర్డ్‌ను తీసివేయండి"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "పాస్‌వర్డ్ రక్షణను తీసివేస్తున్నాము..."
@@ -2357,6 +2381,10 @@ msgstr "తర్వాత, యాప్ ఇచ్చిన 6 అంకెల
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF రూపొందించడంలో సమస్య ఏర్పడింది, దయచేసి కొద్దిసేపటి తరువాత మళ్లీ ప్రయత్నించండి."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "రిజ్యూమ్‌ను నవీకరించండి"
msgid "Update your password"
msgstr "మీ పాస్‌వర్డ్‌ను నవీకరించండి"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "మీ పాస్‌వర్డ్‌ను నవీకరిస్తోంది..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "เพิ่มแถวหลัง"
msgid "Add Row Before"
msgstr "เพิ่มแวก่อน"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "อาฟรีกานส์"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "แอลเบเนีย"
@@ -340,6 +348,10 @@ msgstr "สาขาวิชา"
msgid "Artificial Intelligence"
msgstr "ปัญญาประดิษฐ์"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "อัตราส่วนภาพ"
@@ -534,6 +546,10 @@ msgstr "จีน (ตัวเต็ม)"
msgid "Circle"
msgstr "วงกลม"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "ล้างการเลือก"
@@ -945,6 +961,10 @@ msgstr "กำลังคัดลอกเรซูเม่ของคุณ
msgid "Dutch"
msgstr "ดัตช์"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "การศึกษา"
@@ -1896,6 +1916,10 @@ msgstr "จำรหัสผ่านของคุณได้หรือไ
msgid "Remove Password"
msgstr "ลบรหัสผ่าน"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "กำลังลบการป้องกันด้วยรหัสผ่าน..."
@@ -2357,6 +2381,10 @@ msgstr "จากนั้น กรอกรหัส 6 หลักที่
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "เกิดปัญหาในการสร้าง PDF โปรดลองใหม่อีกครั้งในภายหลัง"
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "อัปเดตประวัติย่อ"
msgid "Update your password"
msgstr "อัปเดตรหัสผ่านของคุณ"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "กำลังอัปเดตรหัสผ่านของคุณ..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Sonra Satır Ekle"
msgid "Add Row Before"
msgstr "Önce Satır Ekle"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "Yapay Zeka"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Arnavutça"
@@ -340,6 +348,10 @@ msgstr "Çalışma alanı"
msgid "Artificial Intelligence"
msgstr "Yapay Zekâ"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "En/Boy Oranı"
@@ -534,6 +546,10 @@ msgstr "Çince (Geleneksel)"
msgid "Circle"
msgstr "Daire"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Seçimi temizle"
@@ -945,6 +961,10 @@ msgstr "Özgeçmişiniz çoğaltılıyor..."
msgid "Dutch"
msgstr "Felemenkçe"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Eğitim"
@@ -1896,6 +1916,10 @@ msgstr "Şifrenizi hatırlıyor musunuz? <0><1>Şimdi giriş yapın <2/></1></0>
msgid "Remove Password"
msgstr "Şifreyi Kaldır"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Şifre koruması kaldırılıyor..."
@@ -2357,6 +2381,10 @@ msgstr "Daha sonra, devam etmek için uygulamanın verdiği 6 haneli kodu girin.
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF oluşturulurken bir sorun oluştu, lütfen daha sonra tekrar deneyin."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Özgeçmişi Güncelle"
msgid "Update your password"
msgstr "Şifrenizi güncelleyin"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Şifreniz güncelleniyor..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Додати Рядок Знизу"
msgid "Add Row Before"
msgstr "Додати Рядок Згори"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Африканська"
msgid "AI"
msgstr "ШІ"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Албанська"
@@ -340,6 +348,10 @@ msgstr "Освітня програма"
msgid "Artificial Intelligence"
msgstr "Штучний інтелект"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Пропорції"
@@ -534,6 +546,10 @@ msgstr "Китайська (традиційна)"
msgid "Circle"
msgstr "Кругле"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Очистити вибір"
@@ -945,6 +961,10 @@ msgstr "Дублювання резюме..."
msgid "Dutch"
msgstr "Голландська"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Освіта"
@@ -1896,6 +1916,10 @@ msgstr "Пам’ятаєте свій пароль? <0><1>Увійдіть за
msgid "Remove Password"
msgstr "Видалити пароль"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Видалення захисту паролем..."
@@ -2357,6 +2381,10 @@ msgstr "Далі введіть шестизначний код, який над
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Сталася проблема під час створення PDF, будь ласка, спробуйте ще раз пізніше."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Оновити резюме"
msgid "Update your password"
msgstr "Оновіть свій пароль"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Оновлення пароля..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Qatordan keyin qator qo‘shish"
msgid "Add Row Before"
msgstr "Qatordan oldin qator qo‘shish"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Afrikaans"
msgid "AI"
msgstr "SO"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Alban tili"
@@ -340,6 +348,10 @@ msgstr "Ta'lim sohasi"
msgid "Artificial Intelligence"
msgstr "Sun'iy intellekt"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Tomonlar nisbati"
@@ -534,6 +546,10 @@ msgstr "Xitoy (An’anaviy)"
msgid "Circle"
msgstr "Doira"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Tanlovni tozalash"
@@ -945,6 +961,10 @@ msgstr "Rezyume nusxalanmoqda..."
msgid "Dutch"
msgstr "Golland tili"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Ta'lim"
@@ -1896,6 +1916,10 @@ msgstr "Parolingiz esingizdami? <0><1>Hozir kiring <2/></1></0>"
msgid "Remove Password"
msgstr "Parolni olib tashlash"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Parol himoyasi olib tashlanmoqda..."
@@ -2357,6 +2381,10 @@ msgstr "Keyin, davom etish uchun ilova taqdim etgan 6 xonali kodni kiriting."
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "PDF yaratishda muammo yuzaga keldi, iltimos, birozdan so'ng qaytadan urinib ko'ring."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Rezyumeni yangilash"
msgid "Update your password"
msgstr "Parolingizni yangilash"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Parolingiz yangilanmoqda..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "Thêm dòng sau"
msgid "Add Row Before"
msgstr "Thêm dòng trước"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "Tiếng Afrikaans"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "Tiếng Albania"
@@ -340,6 +348,10 @@ msgstr "Lĩnh vực học tập"
msgid "Artificial Intelligence"
msgstr "Trí tuệ nhân tạo"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "Tỷ lệ khung hình"
@@ -534,6 +546,10 @@ msgstr "Tiếng Trung (Phồn thể)"
msgid "Circle"
msgstr "Vòng tròn"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "Xóa lựa chọn"
@@ -945,6 +961,10 @@ msgstr "Đang tạo bản sao bản lý lịch của bạn..."
msgid "Dutch"
msgstr "Tiếng Hà Lan"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "Giáo dục"
@@ -1896,6 +1916,10 @@ msgstr "Bạn nhớ mật khẩu? <0><1>Đăng nhập ngay <2/></1></0>"
msgid "Remove Password"
msgstr "Xóa mật khẩu"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "Đang xóa bảo vệ mật khẩu..."
@@ -2357,6 +2381,10 @@ msgstr "Sau đó, nhập mã 6 chữ số mà ứng dụng cung cấp để ti
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "Đã xảy ra sự cố khi tạo PDF, hãy thử lại sau."
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "Cập nhật resume"
msgid "Update your password"
msgstr "Cập nhật mật khẩu của bạn"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "Đang cập nhật mật khẩu của bạn..."
+32
View File
@@ -207,6 +207,10 @@ msgstr "在后面添加行"
msgid "Add Row Before"
msgstr "在前面添加行"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "南非语"
msgid "AI"
msgstr "AI(人工智能)"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "阿尔巴尼亚语"
@@ -340,6 +348,10 @@ msgstr "学习领域"
msgid "Artificial Intelligence"
msgstr "人工智能"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "宽高比"
@@ -534,6 +546,10 @@ msgstr "中文(繁体)"
msgid "Circle"
msgstr "圆形"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "清除选择"
@@ -945,6 +961,10 @@ msgstr "正在复制你的简历…"
msgid "Dutch"
msgstr "荷兰语"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "教育经历"
@@ -1896,6 +1916,10 @@ msgstr "想起你的密码了?<0><1>立即登录 <2/></1></0>"
msgid "Remove Password"
msgstr "移除密码"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "正在移除密码保护…"
@@ -2357,6 +2381,10 @@ msgstr "然后,输入应用提供的 6 位验证码以继续。"
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "生成 PDF 时出现问题,请稍后重试。"
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "更新简历"
msgid "Update your password"
msgstr "更新你的密码"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "正在更新你的密码…"
+32
View File
@@ -207,6 +207,10 @@ msgstr "在後方新增列"
msgid "Add Row Before"
msgstr "在前方新增列"
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -225,6 +229,10 @@ msgstr "南非荷蘭語"
msgid "AI"
msgstr "AI"
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr "阿爾巴尼亞語"
@@ -340,6 +348,10 @@ msgstr "學習領域"
msgid "Artificial Intelligence"
msgstr "人工智慧"
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr "顯示比例"
@@ -534,6 +546,10 @@ msgstr "中文(繁體)"
msgid "Circle"
msgstr "圓形"
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr "清除選取"
@@ -945,6 +961,10 @@ msgstr "正在複製您的履歷…"
msgid "Dutch"
msgstr "荷蘭語"
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr "學歷"
@@ -1896,6 +1916,10 @@ msgstr "想起密碼了嗎?<0><1>立即登入 <2/></1></0>"
msgid "Remove Password"
msgstr "移除密碼"
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr "正在移除密碼保護…"
@@ -2357,6 +2381,10 @@ msgstr "接著,請輸入應用程式提供的 6 位數驗證碼以繼續。"
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr "產生 PDF 時發生問題,請稍後再試一次。"
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2620,6 +2648,10 @@ msgstr "更新履歷"
msgid "Update your password"
msgstr "更新您的密碼"
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr "正在更新您的密碼…"
+32
View File
@@ -202,6 +202,10 @@ msgstr ""
msgid "Add Row Before"
msgstr ""
#: src/components/ai/chat.tsx
msgid "Added"
msgstr ""
#. placeholder {0}: passkey.createdAt.toLocaleDateString()
#: src/routes/dashboard/settings/authentication/-components/passkeys.tsx
msgid "Added on {0}"
@@ -220,6 +224,10 @@ msgstr ""
msgid "AI"
msgstr ""
#: src/components/ai/chat.tsx
msgid "AI Chat"
msgstr ""
#: src/utils/locale.ts
msgid "Albanian"
msgstr ""
@@ -335,6 +343,10 @@ msgstr ""
msgid "Artificial Intelligence"
msgstr ""
#: src/components/ai/chat.tsx
msgid "Ask me to update your resume..."
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/left/sections/picture.tsx
msgid "Aspect Ratio"
msgstr ""
@@ -529,6 +541,10 @@ msgstr ""
msgid "Circle"
msgstr ""
#: src/components/ai/chat.tsx
msgid "Clear chat history"
msgstr ""
#: src/components/ui/multiple-combobox.tsx
msgid "Clear selection"
msgstr ""
@@ -940,6 +956,10 @@ msgstr ""
msgid "Dutch"
msgstr ""
#: src/components/ai/chat.tsx
msgid "e.g. Change my name to..."
msgstr ""
#: src/utils/resume/section.tsx
msgid "Education"
msgstr ""
@@ -1891,6 +1911,10 @@ msgstr ""
msgid "Remove Password"
msgstr ""
#: src/components/ai/chat.tsx
msgid "Removed"
msgstr ""
#: src/routes/builder/$resumeId/-sidebar/right/sections/sharing.tsx
msgid "Removing password protection..."
msgstr ""
@@ -2352,6 +2376,10 @@ msgstr ""
msgid "There was a problem while generating the PDF, please try again in some time."
msgstr ""
#: src/components/ai/chat.tsx
msgid "Thinking..."
msgstr ""
#: src/routes/builder/$resumeId/-components/header.tsx
#: src/routes/dashboard/resumes/-components/menus/context-menu.tsx
#: src/routes/dashboard/resumes/-components/menus/dropdown-menu.tsx
@@ -2615,6 +2643,10 @@ msgstr ""
msgid "Update your password"
msgstr ""
#: src/components/ai/chat.tsx
msgid "Updated"
msgstr ""
#: src/dialogs/auth/change-password.tsx
msgid "Updating your password..."
msgstr ""
+434
View File
@@ -0,0 +1,434 @@
#!/usr/bin/env node
/**
* Reactive Resume MCP server — single entry point. Run with:
* npx tsx /path/to/reactive-resume/mcp
*
* Env: REACTIVE_RESUME_API_KEY (required), REACTIVE_RESUME_URL (default https://rxresu.me),
* TRANSPORT (stdio | http), PORT (default 3100).
*/
import * as http from "node:http";
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import type { Operation } from "fast-json-patch";
import { z } from "zod";
import type { RouterInput, RouterOutput } from "@/integrations/orpc/client";
import { jsonPatchOperationSchema } from "@/utils/resume/patch";
import schemaJSON from "../src/schema/schema.json";
// --- Env ---
const API_KEY = process.env.REACTIVE_RESUME_API_KEY;
const BASE_URL = (process.env.REACTIVE_RESUME_URL ?? "https://rxresu.me").replace(/\/$/, "");
const TRANSPORT = process.env.TRANSPORT ?? "stdio";
const PORT = Number.parseInt(process.env.PORT ?? "3100", 10);
if (!API_KEY) {
console.error("ERROR: REACTIVE_RESUME_API_KEY is required. Create one in Settings > API Keys.");
process.exit(1);
}
const apiKey = API_KEY;
// --- API client ---
async function apiRequest<T>(method: string, path: string, body?: unknown): Promise<T> {
const url = `${BASE_URL}${path}`;
const res = await fetch(url, {
method,
headers: {
"x-api-key": apiKey,
Accept: "application/json",
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : undefined,
});
if (!res.ok) {
const text = await res.text().catch(() => "Unknown error");
throw new Error(`Reactive Resume API error (${res.status}): ${text}`);
}
return res.json() as Promise<T>;
}
async function listResumes(): Promise<RouterOutput["resume"]["list"]> {
return apiRequest("GET", "/api/openapi/resumes");
}
async function getResume(id: string): Promise<RouterOutput["resume"]["getById"]> {
return apiRequest("GET", `/api/openapi/resumes/${encodeURIComponent(id)}`);
}
async function patchResume(id: string, operations: Operation[]): Promise<RouterOutput["resume"]["patch"]> {
return apiRequest("PATCH", `/api/openapi/resumes/${encodeURIComponent(id)}`, { operations });
}
async function createResume(input: RouterInput["resume"]["create"]): Promise<RouterOutput["resume"]["create"]> {
return apiRequest("POST", "/api/openapi/resumes", input);
}
async function deleteResume(id: string): Promise<RouterOutput["resume"]["delete"]> {
return apiRequest("DELETE", `/api/openapi/resumes/${encodeURIComponent(id)}`);
}
async function setResumeLocked(id: string, isLocked: boolean): Promise<RouterOutput["resume"]["setLocked"]> {
return apiRequest("POST", `/api/openapi/resumes/${encodeURIComponent(id)}/lock`, { isLocked });
}
// --- MCP server ---
const server = new McpServer({ name: "reactive-resume-mcp-server", version: "1.0.0" });
// Tool: list_resumes
server.registerTool(
"list_resumes",
{
title: "List Resumes",
description:
"List all resumes for the authenticated user. Returns id, name, slug, tags, visibility, lock status, timestamps.",
inputSchema: z.object({}).strict(),
},
async () => {
try {
const resumes = await listResumes();
if (resumes.length === 0)
return {
content: [{ type: "text", text: "No resumes found. Use create_resume to create one." }],
};
const lines = [`# Your Resumes (${resumes.length})`, ""];
for (const r of resumes) {
const tags = r.tags.length > 0 ? ` [${r.tags.join(", ")}]` : "";
const flags = [r.isPublic ? "public" : "private", r.isLocked ? "locked" : ""].filter(Boolean).join(", ");
lines.push(`- **${r.name}** (${r.id})${tags}`);
lines.push(` Status: ${flags} | Updated: ${r.updatedAt}`);
}
return { content: [{ type: "text", text: lines.join("\n") }] };
} catch (error) {
return {
isError: true,
content: [
{ type: "text", text: `Error listing resumes: ${error instanceof Error ? error.message : String(error)}` },
],
};
}
},
);
// Tool: get_resume
server.registerTool(
"get_resume",
{
title: "Get Resume",
description: "Get the full data of a specific resume by ID. Use list_resumes to find IDs.",
inputSchema: z.object({ id: z.string().min(1).describe("Resume ID") }).strict(),
},
async ({ id }: { id: string }) => {
try {
const resume = await getResume(id);
return { content: [{ type: "text", text: JSON.stringify(resume.data, null, 2) }] };
} catch (error) {
return {
isError: true,
content: [
{
type: "text",
text: `Error getting resume: ${error instanceof Error ? error.message : String(error)}. Use list_resumes to find valid IDs.`,
},
],
};
}
},
);
// Tool: patch_resume
server.registerTool(
"patch_resume",
{
title: "Patch Resume",
description:
"Apply JSON Patch (RFC 6902) operations. Use get_resume first to inspect structure. Paths like /basics/name, /sections/skills/items/-.",
inputSchema: z
.object({
id: z.string().min(1).describe("Resume ID"),
operations: z.array(jsonPatchOperationSchema).min(1).describe("JSON Patch operations"),
})
.strict(),
},
async ({ id, operations }: { id: string; operations: Operation[] }) => {
try {
const resume = await patchResume(id, operations);
const summary = operations.map((op) => `${op.op} ${op.path}`).join(", ");
return {
content: [{ type: "text", text: `Applied ${operations.length} operation(s) to "${resume.name}": ${summary}` }],
};
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
let hint = "";
if (msg.includes("400")) hint = " Use get_resume to check structure and paths.";
if (msg.includes("403")) hint = " Resume is locked. Use unlock_resume first.";
if (msg.includes("404")) hint = " Use list_resumes to find valid IDs.";
return { isError: true, content: [{ type: "text", text: `Error patching resume: ${msg}${hint}` }] };
}
},
);
// Tool: create_resume
server.registerTool(
"create_resume",
{
title: "Create Resume",
description:
"Create a new resume with a name, slug, and optional tags. Set withSampleData to true to pre-fill with example content.",
inputSchema: z
.object({
name: z.string().min(1).max(64).describe("Name for the new resume"),
slug: z.string().min(1).max(64).describe("URL-friendly slug (must be unique across your resumes)"),
tags: z.array(z.string()).optional().default([]).describe("Optional tags to categorize the resume"),
withSampleData: z.boolean().optional().default(false).describe("If true, pre-fill the resume with sample data"),
})
.strict(),
},
async ({
name,
slug,
tags,
withSampleData,
}: {
name: string;
slug: string;
tags: string[];
withSampleData: boolean;
}) => {
try {
const id = await createResume({ name, slug, tags, withSampleData });
return {
content: [
{
type: "text",
text: `Created resume "${name}" (${id}) with slug "${slug}".${withSampleData ? " Pre-filled with sample data." : ""} Use get_resume to view or patch_resume to edit it.`,
},
],
};
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
let hint = "";
if (msg.includes("400")) hint = " The slug may already be in use — try a different one.";
return { isError: true, content: [{ type: "text", text: `Error creating resume: ${msg}${hint}` }] };
}
},
);
// Tool: delete_resume
server.registerTool(
"delete_resume",
{
title: "Delete Resume",
description:
"Permanently delete a resume and its associated files (screenshots, PDFs). Locked resumes cannot be deleted — unlock first. This action is irreversible.",
inputSchema: z
.object({
id: z.string().min(1).describe("Resume ID to delete. Use list_resumes to find IDs."),
})
.strict(),
},
async ({ id }: { id: string }) => {
try {
await deleteResume(id);
return { content: [{ type: "text", text: `Successfully deleted resume (${id}) and its associated files.` }] };
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
let hint = "";
if (msg.includes("403")) hint = " The resume may be locked. Use unlock_resume first.";
if (msg.includes("404")) hint = " Use list_resumes to find valid IDs.";
return { isError: true, content: [{ type: "text", text: `Error deleting resume: ${msg}${hint}` }] };
}
},
);
// Tool: lock_resume
server.registerTool(
"lock_resume",
{
title: "Lock Resume",
description:
"Lock a resume to prevent edits, patches, or deletion. Useful for protecting finalized resumes from accidental changes.",
inputSchema: z
.object({
id: z.string().min(1).describe("Resume ID to lock. Use list_resumes to find IDs."),
})
.strict(),
},
async ({ id }: { id: string }) => {
try {
await setResumeLocked(id, true);
return {
content: [
{
type: "text",
text: `Resume (${id}) is now locked. It cannot be edited, patched, or deleted until unlocked.`,
},
],
};
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
let hint = "";
if (msg.includes("404")) hint = " Use list_resumes to find valid IDs.";
return { isError: true, content: [{ type: "text", text: `Error locking resume: ${msg}${hint}` }] };
}
},
);
// Tool: unlock_resume
server.registerTool(
"unlock_resume",
{
title: "Unlock Resume",
description: "Unlock a previously locked resume, allowing edits, patches, and deletion again.",
inputSchema: z
.object({
id: z.string().min(1).describe("Resume ID to unlock. Use list_resumes to find IDs."),
})
.strict(),
},
async ({ id }: { id: string }) => {
try {
await setResumeLocked(id, false);
return {
content: [{ type: "text", text: `Resume (${id}) is now unlocked. It can be edited, patched, and deleted.` }],
};
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
let hint = "";
if (msg.includes("404")) hint = " Use list_resumes to find valid IDs.";
return { isError: true, content: [{ type: "text", text: `Error unlocking resume: ${msg}${hint}` }] };
}
},
);
// Resource: resume://{id}
const resumeTemplate = new ResourceTemplate("resume://{id}", {
list: async () => {
const resumes = await listResumes();
return {
resources: resumes.map((r) => ({
uri: `resume://${r.id}`,
name: r.name,
mimeType: "application/json" as const,
description: `Resume: ${r.name}`,
})),
};
},
});
server.registerResource(
"resume",
resumeTemplate,
{
description: "Full resume data as JSON. Use resume://{id} with ID from list_resumes.",
mimeType: "application/json",
},
async (uri: URL) => {
const id = uri.href.replace(/^resume:\/\//, "");
if (!id) throw new Error("Invalid resume URI: resume://{id}");
const resume = await getResume(id);
return {
contents: [{ uri: uri.href, mimeType: "application/json" as const, text: JSON.stringify(resume.data, null, 2) }],
};
},
);
// Resource: resume://schema
server.registerResource(
"resume-schema",
"resume://schema",
{
description: "Resume Data JSON Schema for generating correct JSON Patch operations.",
mimeType: "application/json",
},
async (uri: URL) => ({
contents: [{ uri: uri.href, mimeType: "application/json" as const, text: JSON.stringify(schemaJSON, null, 2) }],
}),
);
// --- Transport: stdio (default) ---
async function runStdio(): Promise<void> {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Reactive Resume MCP server running via stdio");
}
// --- Transport: HTTP (Node http server) ---
function readBody(req: http.IncomingMessage): Promise<unknown> {
return new Promise((resolve, reject) => {
const chunks: Buffer[] = [];
req.on("data", (chunk) => chunks.push(chunk));
req.on("end", () => {
const raw = Buffer.concat(chunks).toString("utf8");
if (!raw.trim()) return resolve(undefined);
try {
resolve(JSON.parse(raw));
} catch {
reject(new Error("Invalid JSON body"));
}
});
req.on("error", reject);
});
}
async function runHttp(): Promise<void> {
const { StreamableHTTPServerTransport } = await import("@modelcontextprotocol/sdk/server/streamableHttp.js");
const httpServer = http.createServer(async (req, res) => {
if (req.method !== "POST" || req.url !== "/mcp") {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("Not Found");
return;
}
let body: unknown;
try {
body = await readBody(req);
} catch {
res.writeHead(400, { "Content-Type": "application/json" });
res.end(JSON.stringify({ jsonrpc: "2.0", error: { code: -32700, message: "Parse error" }, id: null }));
return;
}
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true,
});
res.on("close", () => transport.close());
await server.connect(transport);
await transport.handleRequest(req as never, res as never, body);
});
httpServer.listen(PORT, "127.0.0.1", () => {
console.error(`Reactive Resume MCP server running on http://127.0.0.1:${PORT}/mcp`);
});
}
if (TRANSPORT === "http") {
runHttp().catch((err) => {
console.error("Server error:", err);
process.exit(1);
});
} else {
runStdio().catch((err) => {
console.error("Server error:", err);
process.exit(1);
});
}
+13 -11
View File
@@ -1,7 +1,7 @@
{
"name": "reactive-resume",
"description": "Reactive Resume is a free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume.",
"version": "5.0.6",
"version": "5.0.7",
"license": "MIT",
"type": "module",
"packageManager": "pnpm@10.29.1+sha512.48dae233635a645768a3028d19545cacc1688639eeb1f3734e42d6d6b971afbf22aa1ac9af52a173d9c3a20c15857cfa400f19994d79a2f626fcc73fccda9bbc",
@@ -26,14 +26,15 @@
"docs:dev": "cd docs && npx mint dev",
"knip": "knip",
"lingui:extract": "lingui extract --clean --overwrite",
"lint": "biome check --write .",
"lint": "biome check --write",
"start": "node .output/server/index.mjs",
"typecheck": "tsc --noEmit"
"typecheck": "tsgo --noEmit"
},
"dependencies": {
"@ai-sdk/anthropic": "^3.0.38",
"@ai-sdk/anthropic": "^3.0.39",
"@ai-sdk/google": "^3.0.22",
"@ai-sdk/openai": "^3.0.26",
"@ai-sdk/react": "^3.0.79",
"@aws-sdk/client-s3": "^3.985.0",
"@better-auth/core": "1.5.0-beta.13",
"@better-auth/passkey": "1.5.0-beta.13",
@@ -56,10 +57,10 @@
"@sindresorhus/slugify": "^3.0.0",
"@t3-oss/env-core": "^0.13.10",
"@tanstack/react-query": "5.90.20",
"@tanstack/react-router": "^1.158.4",
"@tanstack/react-router-ssr-query": "^1.158.4",
"@tanstack/react-start": "^1.159.2",
"@tanstack/zod-adapter": "^1.158.4",
"@tanstack/react-router": "^1.159.3",
"@tanstack/react-router-ssr-query": "^1.159.3",
"@tanstack/react-start": "^1.159.3",
"@tanstack/zod-adapter": "^1.159.3",
"@tiptap/extension-highlight": "^3.19.0",
"@tiptap/extension-table": "^3.19.0",
"@tiptap/extension-text-align": "^3.19.0",
@@ -76,6 +77,7 @@
"dompurify": "^3.3.1",
"drizzle-orm": "^1.0.0-beta.15-859cf75",
"drizzle-zod": "^0.8.3",
"@modelcontextprotocol/sdk": "^1.26.0",
"es-toolkit": "^1.44.0",
"fast-deep-equal": "^3.1.3",
"fast-json-patch": "^3.1.1",
@@ -127,6 +129,7 @@
"@types/pg": "^8.16.0",
"@types/react": "^19.2.13",
"@types/react-dom": "^19.2.3",
"@typescript/native-preview": "7.0.0-dev.20260208.1",
"@vitejs/plugin-react": "^5.1.3",
"babel-plugin-macros": "^3.1.0",
"drizzle-kit": "^1.0.0-beta.15-859cf75",
@@ -136,13 +139,12 @@
"node-gyp": "^12.2.0",
"npm-check-updates": "^19.3.2",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"vite": "npm:rolldown-vite@latest",
"vite": "^8.0.0-beta.13",
"vite-plugin-pwa": "^1.2.0"
},
"pnpm": {
"overrides": {
"vite": "npm:rolldown-vite@latest"
"vite": "^8.0.0-beta.13"
},
"onlyBuiltDependencies": [
"@prisma/engines",
+361 -216
View File
File diff suppressed because it is too large Load Diff
+408
View File
@@ -0,0 +1,408 @@
import { useChat } from "@ai-sdk/react";
import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro";
import { eventIteratorToUnproxiedDataStream } from "@orpc/client";
import {
CheckCircleIcon,
CircleNotchIcon,
PaperPlaneRightIcon,
SparkleIcon,
StopIcon,
TrashSimpleIcon,
} from "@phosphor-icons/react";
import type { UIMessage } from "ai";
import type { Operation } from "fast-json-patch";
import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { ScrollArea } from "@/components/ui/scroll-area";
import { useAIStore } from "@/integrations/ai/store";
import { client } from "@/integrations/orpc/client";
import { applyResumePatches } from "@/utils/resume/patch";
import { cn } from "@/utils/style";
import { useResumeStore } from "../resume/store/resume";
/**
* Extract patch operations from the latest assistant messages' tool call parts.
* Returns operations that haven't been applied yet (tracked by processedToolCallIds).
*/
function extractNewPatchOperations(
messages: UIMessage[],
processedIds: Set<string>,
): { operations: Operation[]; newIds: string[] } {
const operations: Operation[] = [];
const newIds: string[] = [];
for (const message of messages) {
if (message.role !== "assistant") continue;
for (const part of message.parts) {
if (part.type !== "tool-patch_resume") continue;
// biome-ignore lint/suspicious/noExplicitAny: AI SDK tool parts have dynamic shapes
const toolPart = part as any;
if (toolPart.state !== "output-available") continue;
const callId = toolPart.toolCallId as string;
if (processedIds.has(callId)) continue;
const result = toolPart.output as { success: boolean; appliedOperations?: Operation[] } | undefined;
if (result?.success && result.appliedOperations) {
operations.push(...result.appliedOperations);
newIds.push(callId);
}
}
}
return { operations, newIds };
}
/**
* LocalStorage helpers for persisting chat messages per resume.
*/
const STORAGE_KEY_PREFIX = "ai-chat-messages";
function getStorageKey(resumeId: string): string {
return `${STORAGE_KEY_PREFIX}:${resumeId}`;
}
function loadStoredMessages(resumeId: string): UIMessage[] {
try {
const stored = localStorage.getItem(getStorageKey(resumeId));
if (!stored) return [];
return JSON.parse(stored) as UIMessage[];
} catch {
return [];
}
}
function saveStoredMessages(resumeId: string, messages: UIMessage[]): void {
try {
localStorage.setItem(getStorageKey(resumeId), JSON.stringify(messages));
} catch {
// Silently fail if localStorage is full or unavailable
}
}
function clearStoredMessages(resumeId: string): void {
localStorage.removeItem(getStorageKey(resumeId));
}
function formatPath(path: string): string {
return path.replace(/^\//, "").replace(/\//g, " › ");
}
function formatOperationLabel(op: string): string {
switch (op) {
case "replace":
return t`Updated`;
case "add":
return t`Added`;
case "remove":
return t`Removed`;
default:
return op;
}
}
function ToolBadge({ state, operations }: { state: string; operations?: { op: string; path: string }[] }) {
const isDone = state === "output-available";
return (
<div className="my-0.5 flex flex-col gap-1.5">
<span
data-state={state}
className={cn(
"inline-flex w-fit items-center gap-1.5 rounded-full border px-2.5 py-1 font-medium text-[11px]",
"data-[state=output-available]:border-emerald-500/30 data-[state=output-available]:bg-emerald-500/10 data-[state=output-available]:text-emerald-600 dark:data-[state=output-available]:text-emerald-400",
)}
>
{isDone ? (
<CheckCircleIcon weight="fill" className="size-3" />
) : (
<CircleNotchIcon className="size-3 animate-spin" />
)}
{isDone ? "Changes applied" : "Applying changes..."}
</span>
{isDone && operations && operations.length > 0 && (
<div className="flex flex-col gap-0.5 pl-1 text-[11px] text-muted-foreground">
{operations.map((op, i) => (
<span key={i} className="flex items-center gap-1">
<span className="opacity-40">•</span>
{formatOperationLabel(op.op)} {formatPath(op.path)}
</span>
))}
</div>
)}
</div>
);
}
function MessageParts({ message }: { message: UIMessage }) {
const parts = message.parts;
if (parts.length === 0) return null;
return (
<div className="flex flex-col gap-2">
{parts.map((part, i) => {
if (part.type === "step-start") {
if (i === 0) return null;
return <hr key={i} className="my-0.5 border-border/40" />;
}
if (part.type === "text" && part.text.trim()) {
return (
<p key={i} className="whitespace-pre-wrap text-[13px] leading-relaxed">
{part.text}
</p>
);
}
if (part.type === "reasoning" && part.text.trim()) {
return (
<p key={i} className="whitespace-pre-wrap text-[11px] text-muted-foreground italic leading-relaxed">
{part.text}
</p>
);
}
if (part.type === "tool-patch_resume") {
// biome-ignore lint/suspicious/noExplicitAny: AI SDK tool parts have dynamic shapes
const toolPart = part as any;
const state = toolPart.state as string;
const operations = toolPart.input?.operations as { op: string; path: string }[] | undefined;
return <ToolBadge key={i} state={state} operations={operations} />;
}
return null;
})}
</div>
);
}
export function AIChat() {
const enabled = useAIStore((s) => s.enabled);
const provider = useAIStore((s) => s.provider);
const model = useAIStore((s) => s.model);
const apiKey = useAIStore((s) => s.apiKey);
const baseURL = useAIStore((s) => s.baseURL);
const resumeId = useResumeStore((s) => s.resume.id);
const resumeData = useResumeStore((s) => s.resume.data);
const updateResumeData = useResumeStore((s) => s.updateResumeData);
const [input, setInput] = useState("");
const [open, setOpen] = useState(false);
const bottomRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const processedToolCallIds = useRef(new Set<string>());
// Load stored messages once on mount and pre-populate processedToolCallIds
// so that already-applied patches are not re-applied.
const [initialMessages] = useState(() => {
const stored = loadStoredMessages(resumeId);
for (const msg of stored) {
if (msg.role !== "assistant") continue;
for (const part of msg.parts) {
if (part.type !== "tool-patch_resume") continue;
// biome-ignore lint/suspicious/noExplicitAny: AI SDK tool parts have dynamic shapes
const toolPart = part as any;
if (toolPart.state === "output-available") {
processedToolCallIds.current.add(toolPart.toolCallId as string);
}
}
}
return stored;
});
const { messages, sendMessage, status, stop, setMessages } = useChat({
messages: initialMessages,
transport: {
async sendMessages(options) {
return eventIteratorToUnproxiedDataStream(
await client.ai.chat(
{
provider,
model,
apiKey,
baseURL,
messages: options.messages,
resumeData,
},
{ signal: options.abortSignal },
),
);
},
reconnectToStream() {
throw new Error("Unsupported");
},
},
onError(error) {
toast.error("AI chat error", { description: error.message });
},
});
// Apply patches when new tool results arrive
useEffect(() => {
const { operations, newIds } = extractNewPatchOperations(messages, processedToolCallIds.current);
if (operations.length === 0) return;
try {
const patched = applyResumePatches(resumeData, operations);
updateResumeData((draft) => {
Object.assign(draft, patched);
});
for (const id of newIds) processedToolCallIds.current.add(id);
} catch (error) {
toast.error("Failed to apply resume changes", {
description: error instanceof Error ? error.message : "Unknown error",
});
}
}, [messages, resumeData, updateResumeData]);
// Persist messages to localStorage whenever they change
useEffect(() => {
saveStoredMessages(resumeId, messages);
}, [resumeId, messages]);
// Auto-scroll to bottom (sentinel so it works with ScrollArea viewport)
useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);
// Refocus the input when the AI finishes responding
useEffect(() => {
if (status === "ready") inputRef.current?.focus();
}, [status]);
const handleOpenChange = useCallback((nextOpen: boolean) => {
setOpen(nextOpen);
}, []);
const handleClearMessages = useCallback(() => {
setMessages([]);
clearStoredMessages(resumeId);
processedToolCallIds.current.clear();
}, [resumeId, setMessages]);
const handleSubmit = useCallback(
(e: React.SubmitEvent) => {
e.preventDefault();
if (!input.trim() || status !== "ready") return;
sendMessage({ text: input });
setInput("");
},
[input, status, sendMessage],
);
if (!enabled) return null;
const isLoading = status === "submitted" || status === "streaming";
return (
<Popover open={open} onOpenChange={handleOpenChange}>
<PopoverTrigger asChild>
<Button size="icon" variant="ghost">
<SparkleIcon />
</Button>
</PopoverTrigger>
<PopoverContent className="flex h-128 w-md flex-col gap-y-0 overflow-hidden p-0" side="top" align="center">
{/* Header with clear button */}
<div className="flex shrink-0 items-center justify-between border-b px-3 py-1.5">
<p className="font-medium text-muted-foreground text-xs">
<Trans>AI Chat</Trans>
</p>
<Button
size="icon-sm"
variant="ghost"
className="size-7"
title={t`Clear chat history`}
onClick={handleClearMessages}
disabled={messages.length === 0 || isLoading}
>
<TrashSimpleIcon className="size-3" />
</Button>
</div>
{/* Message list — min-h-0 so flex constrains height and viewport scrolls */}
<ScrollArea className="min-h-0 flex-1 px-4">
<div className="flex flex-col gap-y-4 pt-4">
{messages.length === 0 && (
<div className="flex h-full items-center justify-center py-6">
<p className="text-center text-muted-foreground text-xs">
<Trans>Ask me to update your resume...</Trans>
</p>
</div>
)}
<div className="flex flex-col gap-4">
{messages.map((message) => (
<div key={message.id} className={cn("flex", message.role === "user" ? "justify-end" : "justify-start")}>
<div
data-role={message.role}
className={cn(
"max-w-[85%] rounded-xl px-3.5 py-2.5",
"data-[role=user]:rounded-br-sm data-[role=user]:bg-primary data-[role=user]:text-primary-foreground",
"data-[role=assistant]:rounded-bl-sm data-[role=assistant]:bg-muted data-[role=assistant]:text-foreground",
)}
>
{message.role === "user" ? (
<p className="text-[13px] leading-relaxed">
{message.parts.map((part, i) =>
part.type === "text" ? <span key={i}>{part.text}</span> : null,
)}
</p>
) : (
<MessageParts message={message} />
)}
</div>
</div>
))}
{status === "submitted" && (
<div className="flex justify-start">
<div className="rounded-xl rounded-bl-sm bg-muted px-3.5 py-2.5">
<div className="flex items-center gap-2 text-[13px] text-muted-foreground">
<CircleNotchIcon className="size-3 animate-spin" />
<span>
<Trans>Thinking...</Trans>
</span>
</div>
</div>
</div>
)}
<div ref={bottomRef} aria-hidden />
</div>
</div>
</ScrollArea>
{/* Input form — shrink-0 so it stays visible when content scrolls */}
<form onSubmit={handleSubmit} className="flex shrink-0 items-center gap-1.5 border-t px-3 py-2">
<input
ref={inputRef}
value={input}
disabled={!enabled || isLoading}
onChange={(e) => setInput(e.target.value)}
placeholder={t`e.g. Change my name to...`}
className="flex-1 bg-transparent text-[13px] outline-none placeholder:text-muted-foreground"
/>
{isLoading ? (
<Button type="button" size="icon" variant="ghost" onClick={stop} className="size-7 shrink-0">
<StopIcon className="size-3.5" />
</Button>
) : (
<Button type="submit" size="icon" variant="ghost" disabled={!input.trim()} className="size-7 shrink-0">
<PaperPlaneRightIcon className="size-3.5" />
</Button>
)}
</form>
</PopoverContent>
</Popover>
);
}
@@ -12,17 +12,13 @@ export function CoverLetterItem({ className, ...item }: CoverLetterItemProps) {
return (
<div className={cn("cover-letter-item", className)}>
{stripHtml(item.recipient) && (
<div className="cover-letter-item-recipient mb-4">
<TiptapContent content={item.recipient} />
</div>
)}
<div className={cn("cover-letter-item-recipient mb-4", !stripHtml(item.recipient) && "hidden")}>
<TiptapContent content={item.recipient} />
</div>
{stripHtml(item.content) && (
<div className="cover-letter-item-content">
<TiptapContent content={item.content} />
</div>
)}
<div className={cn("cover-letter-item-content", !stripHtml(item.content) && "hidden")}>
<TiptapContent content={item.content} />
</div>
</div>
);
}
@@ -17,15 +17,11 @@ export function SkillsItem({ className, ...item }: SkillsItemProps) {
</div>
{/* Proficiency */}
{item.proficiency && (
<span className="section-item-metadata skills-item-proficiency inline-block">{item.proficiency}</span>
)}
{item.proficiency && <div className="section-item-metadata skills-item-proficiency">{item.proficiency}</div>}
{/* Keywords */}
{item.keywords.length > 0 && (
<span className="section-item-keywords skills-item-keywords inline-block opacity-80">
{item.keywords.join(", ")}
</span>
<div className="section-item-keywords skills-item-keywords opacity-80">{item.keywords.join(", ")}</div>
)}
{/* Level */}
+1 -1
View File
@@ -65,7 +65,7 @@ function Header() {
return (
<div
className={cn(
"page-header flex items-center gap-x-(--page-gap-x)",
"page-header flex items-center gap-x-(--page-margin-x)",
"rounded-(--picture-border-radius) border border-(--page-text-color)/10 bg-(--page-background-color) p-4",
)}
>
+1 -1
View File
@@ -43,7 +43,7 @@ function Header() {
const basics = useResumeStore((state) => state.resume.data.basics);
return (
<div className="page-header flex items-center gap-x-(--page-gap-x) border-(--page-primary-color) border-b pb-(--page-margin-y)">
<div className="page-header flex items-center gap-x-(--page-margin-x) border-(--page-primary-color) border-b pb-(--page-margin-y)">
<PagePicture />
<div className="page-basics space-y-(--page-gap-y)">
+1 -1
View File
@@ -129,7 +129,7 @@ function Combobox<TValue extends string | number = string>({
<CommandGroup>
{options.map((option) => {
const isSelected = selectedValue === option.value;
const isDisabled = option.disabled ?? (false || disabled);
const isDisabled = option.disabled ?? disabled;
return (
<CommandItem
+1 -1
View File
@@ -7,7 +7,7 @@ function ScrollArea({ className, children, ...props }: React.ComponentProps<type
<ScrollAreaPrimitive.Root data-slot="scroll-area" className={cn("relative", className)} {...props}>
<ScrollAreaPrimitive.Viewport
data-slot="scroll-area-viewport"
className="size-full rounded-[inherit] outline-none transition-[color,box-shadow] focus-visible:outline-1 focus-visible:ring-[3px] focus-visible:ring-ring/50"
className="[&>div]:block! size-full rounded-[inherit] outline-none transition-[color,box-shadow] focus-visible:outline-1 focus-visible:ring-[3px] focus-visible:ring-ring/50"
>
{children}
</ScrollAreaPrimitive.Viewport>
@@ -0,0 +1,65 @@
You are an expert resume writer and a specialist in JSON Patch (RFC 6902) operations. Your role is to help the user improve and modify their resume through natural conversation.
## Your Capabilities
- You can read and understand the user's current resume data (provided below).
- You can modify the resume by calling the `patch_resume` tool with JSON Patch operations.
- You can advise on resume best practices, wording, and structure.
## Rules
1. **Always use the `patch_resume` tool** to make changes. Never output raw JSON or patch operations in your text response.
2. **Generate the minimal set of operations** needed for each change. Do not replace entire objects when only a single field needs updating.
3. **Preserve existing data** unless the user explicitly asks to remove or replace it.
4. **Confirm before destructive actions** like removing sections or clearing large amounts of content.
5. **Stay on topic.** Only discuss resume-related content. Politely decline off-topic requests.
6. **Do not fabricate content.** Only add information the user provides or explicitly asks you to generate. If generating content (e.g. a summary), make it clear you are drafting and ask for approval.
7. **HTML content fields** (description, summary content, cover letter content) must use valid HTML. Use `<p>` for paragraphs, `<ul>`/`<li>` for lists, `<strong>` for bold, `<em>` for italic.
8. **IDs for new items** must be valid UUIDs (use the format `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`).
## Resume Data Structure
The resume data is a JSON object with these top-level keys:
- `basics` — name, headline, email, phone, location, website, customFields
- `summary` — title, content (HTML), columns, hidden
- `picture` — url, size, rotation, aspectRatio, border/shadow settings
- `sections` — built-in sections, each with title, columns, hidden, items[]
- `profiles` — items: { network, username, icon, website }
- `experience` — items: { company, position, location, period, website, description }
- `education` — items: { school, degree, area, grade, location, period, website, description }
- `projects` — items: { name, period, website, description }
- `skills` — items: { name, proficiency, level, keywords[], icon }
- `languages` — items: { language, fluency, level }
- `interests` — items: { name, keywords[], icon }
- `awards` — items: { title, awarder, date, website, description }
- `certifications` — items: { title, issuer, date, website, description }
- `publications` — items: { title, publisher, date, website, description }
- `volunteer` — items: { organization, location, period, website, description }
- `references` — items: { name, position, website, phone, description }
- `customSections` — array of user-created sections with id, type, title, items[]
- `metadata` — template, layout, css, page, design, typography, notes
Every item in a section has: `id` (UUID), `hidden` (boolean), and optionally `options`.
Every `website` field is an object: `{ url: string, label: string }`.
## JSON Patch Path Examples
| Action | Operation |
|--------|-----------|
| Change name | `{ "op": "replace", "path": "/basics/name", "value": "Jane Doe" }` |
| Update headline | `{ "op": "replace", "path": "/basics/headline", "value": "Senior Engineer" }` |
| Replace summary content | `{ "op": "replace", "path": "/summary/content", "value": "<p>Experienced engineer...</p>" }` |
| Add experience item | `{ "op": "add", "path": "/sections/experience/items/-", "value": { ...full item object } }` |
| Remove skill at index 2 | `{ "op": "remove", "path": "/sections/skills/items/2" }` |
| Update a specific item field | `{ "op": "replace", "path": "/sections/experience/items/0/company", "value": "New Corp" }` |
| Change template | `{ "op": "replace", "path": "/metadata/template", "value": "bronzor" }` |
| Change primary color | `{ "op": "replace", "path": "/metadata/design/colors/primary", "value": "rgba(37, 99, 235, 1)" }` |
| Hide a section | `{ "op": "replace", "path": "/sections/interests/hidden", "value": true }` |
| Rename a section title | `{ "op": "replace", "path": "/sections/experience/title", "value": "Work History" }` |
## Current Resume Data
```json
{{RESUME_DATA}}
```
+22
View File
@@ -0,0 +1,22 @@
import type { Operation } from "fast-json-patch";
import z from "zod";
import type { ResumeData } from "@/schema/resume/data";
import { applyResumePatches, jsonPatchOperationSchema } from "@/utils/resume/patch";
export const patchResumeInputSchema = z.object({
operations: z
.array(jsonPatchOperationSchema)
.min(1)
.describe("Array of JSON Patch (RFC 6902) operations to apply to the resume"),
});
export const patchResumeDescription = `Apply JSON Patch (RFC 6902) operations to modify the user's resume data.
Use this tool whenever the user asks to change, add, or remove content from their resume.
Always generate the minimal set of operations needed. Prefer "replace" for updates, "add" for new content, "remove" for deletions.
Use the special "-" index to append to arrays (e.g. "/sections/experience/items/-").`;
export function executePatchResume(resumeData: ResumeData, operations: Operation[]) {
// Validates operations structurally and against the schema; throws on invalid
applyResumePatches(resumeData, operations);
return { success: true as const, appliedOperations: operations };
}
+2 -1
View File
@@ -2,7 +2,7 @@ import { BetterAuthError } from "@better-auth/core/error";
import { passkey } from "@better-auth/passkey";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { betterAuth } from "better-auth/minimal";
import { apiKey, type GenericOAuthConfig, genericOAuth, twoFactor } from "better-auth/plugins";
import { apiKey, type GenericOAuthConfig, genericOAuth, openAPI, twoFactor } from "better-auth/plugins";
import { username } from "better-auth/plugins/username";
import { tanstackStartCookies } from "better-auth/tanstack-start";
import { and, eq, or } from "drizzle-orm";
@@ -211,6 +211,7 @@ const getAuthConfig = () => {
},
plugins: [
openAPI(),
apiKey({
enableSessionForAPIKeys: true,
rateLimit: {
+21 -6
View File
@@ -1,6 +1,6 @@
import { createORPCClient } from "@orpc/client";
import { createORPCClient, onError } from "@orpc/client";
import { RPCLink } from "@orpc/client/fetch";
import { BatchLinkPlugin } from "@orpc/client/plugins";
import { BatchLinkPlugin, SimpleCsrfProtectionLinkPlugin } from "@orpc/client/plugins";
import { createRouterClient, type InferRouterInputs, type InferRouterOutputs, type RouterClient } from "@orpc/server";
import { createTanstackQueryUtils } from "@orpc/tanstack-query";
import { createIsomorphicFn } from "@tanstack/react-start";
@@ -11,6 +11,11 @@ import { getLocale } from "@/utils/locale";
export const getORPCClient = createIsomorphicFn()
.server((): RouterClient<typeof router> => {
return createRouterClient(router, {
interceptors: [
onError((error) => {
console.error(`ERROR [oRPC]: ${error}`);
}),
],
context: async () => {
const locale = await getLocale();
const reqHeaders = getRequestHeaders();
@@ -25,10 +30,20 @@ export const getORPCClient = createIsomorphicFn()
.client((): RouterClient<typeof router> => {
const link = new RPCLink({
url: `${window.location.origin}/api/rpc`,
plugins: [new BatchLinkPlugin({ groups: [{ condition: () => true, context: {} }] })],
fetch: (request, init) => {
return fetch(request, { ...init, credentials: "include" });
},
fetch: (request, init) => fetch(request, { ...init, credentials: "include" }),
plugins: [
new SimpleCsrfProtectionLinkPlugin(),
new BatchLinkPlugin({
mode: typeof window === "undefined" ? "buffered" : "streaming",
groups: [{ condition: () => true, context: {} }],
}),
],
interceptors: [
onError((error) => {
if (error instanceof DOMException && error.name === "AbortError") return;
console.error(`ERROR [oRPC]: ${error}`);
}),
],
});
return createORPCClient(link);
+88 -3
View File
@@ -1,11 +1,26 @@
import { ORPCError } from "@orpc/client";
import { AISDKError } from "ai";
import { type } from "@orpc/server";
import { AISDKError, type UIMessage } from "ai";
import { OllamaError } from "ai-sdk-ollama";
import z, { ZodError } from "zod";
import type { ResumeData } from "@/schema/resume/data";
import { protectedProcedure } from "../context";
import { aiCredentialsSchema, aiProviderSchema, aiService, fileInputSchema, formatZodError } from "../services/ai";
type AIProvider = z.infer<typeof aiProviderSchema>;
export const aiRouter = {
testConnection: protectedProcedure
.route({
method: "POST",
path: "/ai/test-connection",
tags: ["AI"],
operationId: "testAiConnection",
summary: "Test AI provider connection",
description:
"Validates the connection to an AI provider by sending a simple test prompt. Requires the provider type, model name, API key, and an optional base URL. Supported providers: OpenAI, Anthropic, Google Gemini, Ollama, and Vercel AI Gateway. Requires authentication.",
successDescription: "The AI provider connection was successful.",
})
.input(
z.object({
provider: aiProviderSchema,
@@ -14,11 +29,17 @@ export const aiRouter = {
baseURL: z.string(),
}),
)
.errors({
BAD_GATEWAY: {
message: "The AI provider returned an error or is unreachable.",
status: 502,
},
})
.handler(async ({ input }) => {
try {
return await aiService.testConnection(input);
} catch (error) {
if (error instanceof AISDKError) {
if (error instanceof AISDKError || error instanceof OllamaError) {
throw new ORPCError("BAD_GATEWAY", { message: error.message });
}
@@ -27,13 +48,29 @@ export const aiRouter = {
}),
parsePdf: protectedProcedure
.route({
method: "POST",
path: "/ai/parse-pdf",
tags: ["AI"],
operationId: "parseResumePdf",
summary: "Parse a PDF file into resume data",
description:
"Extracts structured resume data from a PDF file using the specified AI provider. The file should be sent as a base64-encoded string along with AI provider credentials. Returns a complete ResumeData object. Requires authentication.",
successDescription: "The PDF was successfully parsed into structured resume data.",
})
.input(
z.object({
...aiCredentialsSchema.shape,
file: fileInputSchema,
}),
)
.handler(async ({ input }) => {
.errors({
BAD_GATEWAY: {
message: "The AI provider returned an error or is unreachable.",
status: 502,
},
})
.handler(async ({ input }): Promise<ResumeData> => {
try {
return await aiService.parsePdf(input);
} catch (error) {
@@ -49,6 +86,16 @@ export const aiRouter = {
}),
parseDocx: protectedProcedure
.route({
method: "POST",
path: "/ai/parse-docx",
tags: ["AI"],
operationId: "parseResumeDocx",
summary: "Parse a DOCX file into resume data",
description:
"Extracts structured resume data from a DOCX or DOC file using the specified AI provider. The file should be sent as a base64-encoded string along with AI provider credentials and the document's media type. Returns a complete ResumeData object. Requires authentication.",
successDescription: "The DOCX was successfully parsed into structured resume data.",
})
.input(
z.object({
...aiCredentialsSchema.shape,
@@ -59,6 +106,12 @@ export const aiRouter = {
]),
}),
)
.errors({
BAD_GATEWAY: {
message: "The AI provider returned an error or is unreachable.",
status: 502,
},
})
.handler(async ({ input }) => {
try {
return await aiService.parseDocx(input);
@@ -71,6 +124,38 @@ export const aiRouter = {
throw new Error(formatZodError(error));
}
throw error;
}
}),
chat: protectedProcedure
.route({
method: "POST",
path: "/ai/chat",
tags: ["AI"],
operationId: "aiChat",
summary: "Chat with AI to modify resume",
description:
"Streams a chat response from the configured AI provider. The LLM can call the patch_resume tool to generate JSON Patch operations that modify the resume. Requires authentication and AI provider credentials.",
})
.input(
type<{
provider: AIProvider;
model: string;
apiKey: string;
baseURL: string;
messages: UIMessage[];
resumeData: ResumeData;
}>(),
)
.handler(async ({ input }) => {
try {
return await aiService.chat(input);
} catch (error) {
if (error instanceof AISDKError || error instanceof OllamaError) {
throw new ORPCError("BAD_GATEWAY", { message: error.message });
}
throw error;
}
}),
+10 -30
View File
@@ -1,4 +1,3 @@
import z from "zod";
import { protectedProcedure, publicProcedure } from "../context";
import { authService, type ProviderList } from "../services/auth";
@@ -7,48 +6,29 @@ export const authRouter = {
list: publicProcedure
.route({
method: "GET",
path: "/auth/providers/list",
path: "/auth/providers",
tags: ["Authentication"],
summary: "List all auth providers",
operationId: "listAuthProviders",
summary: "List authentication providers",
description:
"A list of all authentication providers, and their display names, supported by the instance of Reactive Resume.",
"Returns a list of all authentication providers enabled on this Reactive Resume instance, along with their display names. Possible providers include password-based credentials, Google, GitHub, and custom OAuth. No authentication required.",
successDescription: "A map of enabled authentication provider identifiers to their display names.",
})
.handler((): ProviderList => {
return authService.providers.list();
}),
},
verifyResumePassword: publicProcedure
.route({
method: "POST",
path: "/auth/verify-resume-password",
tags: ["Authentication", "Resume"],
summary: "Verify resume password",
description: "Verify a resume password, to grant access to the locked resume.",
})
.input(
z.object({
slug: z.string().min(1),
username: z.string().min(1),
password: z.string().min(1),
}),
)
.output(z.boolean())
.handler(async ({ input }): Promise<boolean> => {
return await authService.verifyResumePassword({
slug: input.slug,
username: input.username,
password: input.password,
});
}),
deleteAccount: protectedProcedure
.route({
method: "DELETE",
path: "/auth/delete-account",
path: "/auth/account",
tags: ["Authentication"],
operationId: "deleteAccount",
summary: "Delete user account",
description: "Delete the authenticated user's account and all associated data.",
description:
"Permanently deletes the authenticated user's account, including all resumes, uploaded files (profile pictures, screenshots, PDFs), and associated data. This action is irreversible. Requires authentication.",
successDescription: "The user account and all associated data have been successfully deleted.",
})
.handler(async ({ context }): Promise<void> => {
return await authService.deleteAccount({ userId: context.user.id });
+11 -1
View File
@@ -1,3 +1,4 @@
import z from "zod";
import { publicProcedure } from "../context";
import { type FeatureFlags, flagsService } from "../services/flags";
@@ -7,8 +8,17 @@ export const flagsRouter = {
method: "GET",
path: "/flags",
tags: ["Feature Flags"],
operationId: "getFeatureFlags",
summary: "Get feature flags",
description: "Returns the current feature flags for this instance.",
description:
"Returns the current feature flags for this Reactive Resume instance. Feature flags control instance-wide settings such as whether new user signups or email-based authentication are disabled. No authentication required.",
successDescription: "The current feature flags for this instance.",
})
.output(
z.object({
disableSignups: z.boolean().describe("Whether new user signups are disabled on this instance."),
disableEmailAuth: z.boolean().describe("Whether email-based authentication is disabled on this instance."),
}),
)
.handler((): FeatureFlags => flagsService.getFlags()),
};
+16 -10
View File
@@ -7,13 +7,16 @@ export const printerRouter = {
printResumeAsPDF: publicProcedure
.route({
method: "GET",
path: "/printer/resume/{id}/pdf",
tags: ["Resume", "Printer"],
path: "/resumes/{id}/pdf",
tags: ["Resume Export"],
operationId: "exportResumePdf",
summary: "Export resume as PDF",
description: "Export a resume as a PDF. Returns a URL to download the PDF.",
description:
"Generates a PDF from the specified resume and uploads it to storage. Returns a URL to download the generated PDF file. If the request is made by an unauthenticated user (e.g. via a public share link), the resume's download count is incremented. Authentication is optional.",
successDescription: "The PDF was generated successfully. Returns a URL to download the file.",
})
.input(z.object({ id: z.string() }))
.output(z.object({ url: z.string() }))
.input(z.object({ id: z.string().describe("The unique identifier of the resume to export.") }))
.output(z.object({ url: z.string().describe("The URL to download the generated PDF file.") }))
.handler(async ({ input, context }) => {
const { id, data, userId } = await resumeService.getByIdForPrinter({ id: input.id });
const url = await printerService.printResumeAsPDF({ id, data, userId });
@@ -28,13 +31,16 @@ export const printerRouter = {
getResumeScreenshot: protectedProcedure
.route({
method: "GET",
path: "/printer/resume/{id}/screenshot",
tags: ["Resume", "Printer"],
path: "/resumes/{id}/screenshot",
tags: ["Resume Export"],
operationId: "getResumeScreenshot",
summary: "Get resume screenshot",
description: "Get a screenshot of a resume. Returns a URL to the screenshot image.",
description:
"Returns a URL to a screenshot image of the first page of the specified resume. Screenshots are cached for up to 6 hours and regenerated automatically when the resume is updated. Returns null if the screenshot cannot be generated. Requires authentication.",
successDescription: "The screenshot URL, or null if the screenshot could not be generated.",
})
.input(z.object({ id: z.string() }))
.output(z.object({ url: z.string().nullable() }))
.input(z.object({ id: z.string().describe("The unique identifier of the resume.") }))
.output(z.object({ url: z.string().nullable().describe("The URL to the screenshot image, or null.") }))
.handler(async ({ input }) => {
try {
const { id, data, userId, updatedAt } = await resumeService.getByIdForPrinter({ id: input.id });
+125 -57
View File
@@ -9,10 +9,13 @@ const tagsRouter = {
list: protectedProcedure
.route({
method: "GET",
path: "/resume/tags/list",
tags: ["Resume"],
path: "/resumes/tags",
tags: ["Resumes"],
operationId: "listResumeTags",
summary: "List all resume tags",
description: "List all tags for the authenticated user's resumes. Used to populate the filter in the dashboard.",
description:
"Returns a sorted list of all unique tags across the authenticated user's resumes. Useful for populating tag filters in the dashboard. Requires authentication.",
successDescription: "A sorted array of unique tag strings.",
})
.output(z.array(z.string()))
.handler(async ({ context }) => {
@@ -24,19 +27,22 @@ const statisticsRouter = {
getById: protectedProcedure
.route({
method: "GET",
path: "/resume/statistics/{id}",
tags: ["Resume"],
path: "/resumes/{id}/statistics",
tags: ["Resume Statistics"],
operationId: "getResumeStatistics",
summary: "Get resume statistics",
description: "Get the statistics for a resume, such as number of views and downloads.",
description:
"Returns view and download statistics for the specified resume, including total counts and the timestamps of the last view and download. Requires authentication.",
successDescription: "The resume's view and download statistics.",
})
.input(z.object({ id: z.string() }))
.input(z.object({ id: z.string().describe("The unique identifier of the resume.") }))
.output(
z.object({
isPublic: z.boolean(),
views: z.number(),
downloads: z.number(),
lastViewedAt: z.date().nullable(),
lastDownloadedAt: z.date().nullable(),
isPublic: z.boolean().describe("Whether the resume is currently public."),
views: z.number().describe("Total number of times the resume has been viewed."),
downloads: z.number().describe("Total number of times the resume has been downloaded."),
lastViewedAt: z.date().nullable().describe("Timestamp of the last view, or null if never viewed."),
lastDownloadedAt: z.date().nullable().describe("Timestamp of the last download, or null if never downloaded."),
}),
)
.handler(async ({ context, input }) => {
@@ -44,7 +50,7 @@ const statisticsRouter = {
}),
increment: publicProcedure
.route({ tags: ["Internal"], summary: "Increment resume statistics" })
.route({ tags: ["Internal"], operationId: "incrementResumeStatistics", summary: "Increment resume statistics" })
.input(z.object({ id: z.string(), views: z.boolean().default(false), downloads: z.boolean().default(false) }))
.handler(async ({ input }) => {
return await resumeService.statistics.increment(input);
@@ -58,10 +64,13 @@ export const resumeRouter = {
list: protectedProcedure
.route({
method: "GET",
path: "/resume/list",
tags: ["Resume"],
path: "/resumes",
tags: ["Resumes"],
operationId: "listResumes",
summary: "List all resumes",
description: "List of all the resumes for the authenticated user.",
description:
"Returns a list of all resumes belonging to the authenticated user. Results can be filtered by tags and sorted by last updated date, creation date, or name. Resume data is not included in the response for performance; use the get endpoint to fetch full resume data. Requires authentication.",
successDescription: "A list of resumes with their metadata (without full resume data).",
})
.input(resumeDto.list.input.optional().default({ tags: [], sort: "lastUpdatedAt" }))
.output(resumeDto.list.output)
@@ -76,10 +85,13 @@ export const resumeRouter = {
getById: protectedProcedure
.route({
method: "GET",
path: "/resume/{id}",
tags: ["Resume"],
path: "/resumes/{id}",
tags: ["Resumes"],
operationId: "getResume",
summary: "Get resume by ID",
description: "Get a resume, along with its data, by its ID.",
description:
"Returns a single resume with its full data, identified by its unique ID. Only resumes belonging to the authenticated user can be retrieved. Requires authentication.",
successDescription: "The resume with its full data.",
})
.input(resumeDto.getById.input)
.output(resumeDto.getById.output)
@@ -88,7 +100,7 @@ export const resumeRouter = {
}),
getByIdForPrinter: serverOnlyProcedure
.route({ tags: ["Internal"], summary: "Get resume by ID for printer" })
.route({ tags: ["Internal"], operationId: "getResumeForPrinter", summary: "Get resume by ID for printer" })
.input(resumeDto.getById.input)
.handler(async ({ input }) => {
return await resumeService.getByIdForPrinter({ id: input.id });
@@ -97,10 +109,13 @@ export const resumeRouter = {
getBySlug: publicProcedure
.route({
method: "GET",
path: "/resume/{username}/{slug}",
tags: ["Resume"],
summary: "Get resume by username and slug",
description: "Get a resume, along with its data, by its username and slug.",
path: "/resumes/{username}/{slug}",
tags: ["Resume Sharing"],
operationId: "getResumeBySlug",
summary: "Get public resume by username and slug",
description:
"Returns a publicly shared resume identified by the owner's username and the resume's slug. If the resume is password-protected and the viewer has not yet verified the password, a 401 error with code NEED_PASSWORD is returned. No authentication required for public resumes; if authenticated as the owner, private resumes are also accessible.",
successDescription: "The public resume with its full data.",
})
.input(resumeDto.getBySlug.input)
.output(resumeDto.getBySlug.output)
@@ -111,10 +126,13 @@ export const resumeRouter = {
create: protectedProcedure
.route({
method: "POST",
path: "/resume/create",
tags: ["Resume"],
path: "/resumes",
tags: ["Resumes"],
operationId: "createResume",
summary: "Create a new resume",
description: "Create a new resume, with the ability to initialize it with sample data.",
description:
"Creates a new resume with the given name, slug, and tags. Optionally initializes the resume with sample data by setting withSampleData to true. The slug must be unique across the user's resumes. Returns the ID of the newly created resume. Requires authentication.",
successDescription: "The ID of the newly created resume.",
})
.input(resumeDto.create.input)
.output(resumeDto.create.output)
@@ -138,10 +156,13 @@ export const resumeRouter = {
import: protectedProcedure
.route({
method: "POST",
path: "/resume/import",
tags: ["Resume"],
path: "/resumes/import",
tags: ["Resumes"],
operationId: "importResume",
summary: "Import a resume",
description: "Import a resume from a file.",
description:
"Creates a new resume from an existing ResumeData object (e.g. from a previously exported JSON file). A random name and slug are generated automatically. Returns the ID of the imported resume. Requires authentication.",
successDescription: "The ID of the imported resume.",
})
.input(resumeDto.import.input)
.output(resumeDto.import.output)
@@ -168,10 +189,13 @@ export const resumeRouter = {
update: protectedProcedure
.route({
method: "PUT",
path: "/resume/{id}",
tags: ["Resume"],
path: "/resumes/{id}",
tags: ["Resumes"],
operationId: "updateResume",
summary: "Update a resume",
description: "Update a resume, along with its data, by its ID.",
description:
"Updates one or more fields of a resume identified by its ID. All fields are optional; only provided fields will be updated. Locked resumes cannot be updated. Requires authentication.",
successDescription: "The updated resume with its full data.",
})
.input(resumeDto.update.input)
.output(resumeDto.update.output)
@@ -196,11 +220,13 @@ export const resumeRouter = {
patch: protectedProcedure
.route({
method: "PATCH",
path: "/resume/{id}",
tags: ["Resume"],
summary: "Patch a resume",
path: "/resumes/{id}",
tags: ["Resumes"],
operationId: "patchResume",
summary: "Patch resume data",
description:
"Apply JSON Patch (RFC 6902) operations to partially update a resume's data. This allows you to make small, targeted changes without sending the entire resume object.",
"Applies JSON Patch (RFC 6902) operations to partially update a resume's data. This allows small, targeted changes (e.g. updating a single field) without sending the entire resume object. Locked resumes cannot be patched. Requires authentication.",
successDescription: "The patched resume with its full data.",
})
.input(resumeDto.patch.input)
.output(resumeDto.patch.output)
@@ -221,10 +247,13 @@ export const resumeRouter = {
setLocked: protectedProcedure
.route({
method: "POST",
path: "/resume/{id}/set-locked",
tags: ["Resume"],
summary: "Set resume locked status",
description: "Toggle the locked status of a resume, by its ID.",
path: "/resumes/{id}/lock",
tags: ["Resumes"],
operationId: "setResumeLocked",
summary: "Set resume lock status",
description:
"Toggles the locked status of a resume. When locked, a resume cannot be updated, patched, or deleted. Useful for protecting finalized resumes from accidental edits. Requires authentication.",
successDescription: "The resume lock status was updated successfully.",
})
.input(resumeDto.setLocked.input)
.output(resumeDto.setLocked.output)
@@ -238,11 +267,14 @@ export const resumeRouter = {
setPassword: protectedProcedure
.route({
method: "POST",
path: "/resume/{id}/set-password",
tags: ["Resume"],
summary: "Set password on a resume",
description: "Set a password on a resume to protect it from unauthorized access when shared publicly.",
method: "PUT",
path: "/resumes/{id}/password",
tags: ["Resume Sharing"],
operationId: "setResumePassword",
summary: "Set resume password",
description:
"Sets or updates a password on a resume. When a password is set, viewers of the public resume must enter the password before the resume data is revealed. The password must be between 6 and 64 characters. Requires authentication.",
successDescription: "The resume password was set successfully.",
})
.input(resumeDto.setPassword.input)
.output(resumeDto.setPassword.output)
@@ -254,13 +286,43 @@ export const resumeRouter = {
});
}),
removePassword: protectedProcedure
verifyPassword: publicProcedure
.route({
method: "POST",
path: "/resume/{id}/remove-password",
tags: ["Resume"],
summary: "Remove password from a resume",
description: "Remove password protection from a resume.",
path: "/resumes/{username}/{slug}/password/verify",
tags: ["Resume Sharing"],
operationId: "verifyResumePassword",
summary: "Verify resume password",
description:
"Verifies a password for a password-protected public resume. On success, the viewer is granted access to view the resume data for the duration of their session. No authentication required.",
successDescription: "The password was verified successfully and access has been granted.",
})
.input(
z.object({
username: z.string().min(1).describe("The username of the resume owner."),
slug: z.string().min(1).describe("The slug of the resume."),
password: z.string().min(1).describe("The password to verify."),
}),
)
.output(z.boolean())
.handler(async ({ input }): Promise<boolean> => {
return await resumeService.verifyPassword({
username: input.username,
slug: input.slug,
password: input.password,
});
}),
removePassword: protectedProcedure
.route({
method: "DELETE",
path: "/resumes/{id}/password",
tags: ["Resume Sharing"],
operationId: "removeResumePassword",
summary: "Remove resume password",
description:
"Removes password protection from a resume. After removal, the resume (if public) can be viewed without entering a password. Requires authentication.",
successDescription: "The resume password was removed successfully.",
})
.input(resumeDto.removePassword.input)
.output(resumeDto.removePassword.output)
@@ -274,10 +336,13 @@ export const resumeRouter = {
duplicate: protectedProcedure
.route({
method: "POST",
path: "/resume/{id}/duplicate",
tags: ["Resume"],
path: "/resumes/{id}/duplicate",
tags: ["Resumes"],
operationId: "duplicateResume",
summary: "Duplicate a resume",
description: "Duplicate a resume, by its ID.",
description:
"Creates a copy of an existing resume with the same data. Optionally override the name, slug, and tags for the duplicate. If not provided, the original resume's name, slug, and tags are used. Returns the ID of the duplicated resume. Requires authentication.",
successDescription: "The ID of the duplicated resume.",
})
.input(resumeDto.duplicate.input)
.output(resumeDto.duplicate.output)
@@ -297,10 +362,13 @@ export const resumeRouter = {
delete: protectedProcedure
.route({
method: "DELETE",
path: "/resume/{id}",
tags: ["Resume"],
path: "/resumes/{id}",
tags: ["Resumes"],
operationId: "deleteResume",
summary: "Delete a resume",
description: "Delete a resume, by its ID.",
description:
"Permanently deletes a resume and its associated files (screenshots, PDFs) from storage. Locked resumes cannot be deleted; unlock the resume first. Requires authentication.",
successDescription: "The resume and its associated files were deleted successfully.",
})
.input(resumeDto.delete.input)
.output(resumeDto.delete.output)
+21 -12
View File
@@ -6,12 +6,15 @@ const userRouter = {
getCount: publicProcedure
.route({
method: "GET",
path: "/statistics/user/count",
tags: ["Statistics"],
path: "/statistics/users",
tags: ["Platform Statistics"],
operationId: "getUserCount",
summary: "Get total number of users",
description: "Get the total number of users for the Reactive Resume.",
description:
"Returns the total number of registered users on this Reactive Resume instance. The count is cached for up to 6 hours for performance. No authentication required.",
successDescription: "The total number of registered users.",
})
.output(z.number())
.output(z.number().describe("The total number of registered users."))
.handler(async (): Promise<number> => {
return await statisticsService.user.getCount();
}),
@@ -21,12 +24,15 @@ const resumeRouter = {
getCount: publicProcedure
.route({
method: "GET",
path: "/statistics/resume/count",
tags: ["Statistics"],
path: "/statistics/resumes",
tags: ["Platform Statistics"],
operationId: "getResumeCount",
summary: "Get total number of resumes",
description: "Get the total number of resumes for the Reactive Resume.",
description:
"Returns the total number of resumes created on this Reactive Resume instance. The count is cached for up to 6 hours for performance. No authentication required.",
successDescription: "The total number of resumes created.",
})
.output(z.number())
.output(z.number().describe("The total number of resumes created."))
.handler(async (): Promise<number> => {
return await statisticsService.resume.getCount();
}),
@@ -37,11 +43,14 @@ const githubRouter = {
.route({
method: "GET",
path: "/statistics/github/stars",
tags: ["Statistics"],
summary: "Get GitHub Repository stargazers count",
description: "Get the stargazers count for the Reactive Resume GitHub repository, at the time of writing.",
tags: ["Platform Statistics"],
operationId: "getGitHubStarCount",
summary: "Get GitHub star count",
description:
"Returns the number of GitHub stars for the Reactive Resume repository. The count is cached for up to 6 hours and falls back to a last-known value if the GitHub API is unavailable. No authentication required.",
successDescription: "The number of GitHub stars for the Reactive Resume repository.",
})
.output(z.number())
.output(z.number().describe("The number of GitHub stars."))
.handler(async (): Promise<number> => {
return await statisticsService.github.getStarCount();
}),
+28 -6
View File
@@ -7,17 +7,26 @@ const storageService = getStorageService();
const fileSchema = z.file().max(10 * 1024 * 1024, "File size must be less than 10MB");
const filenameSchema = z.object({ filename: z.string().min(1) });
const filenameSchema = z.object({
filename: z.string().min(1).describe("The path or filename of the file to delete."),
});
export const storageRouter = {
uploadFile: protectedProcedure
.route({ tags: ["Internal"], summary: "Upload a file" })
.route({
tags: ["Internal"],
operationId: "uploadFile",
summary: "Upload a file",
description:
"Uploads a file to storage. Images are automatically resized and converted to WebP format. Maximum file size is 10MB. Requires authentication.",
successDescription: "The file was uploaded successfully.",
})
.input(fileSchema)
.output(
z.object({
url: z.string(),
path: z.string(),
contentType: z.string(),
url: z.string().describe("The public URL to access the uploaded file."),
path: z.string().describe("The storage path of the uploaded file."),
contentType: z.string().describe("The MIME type of the uploaded file."),
}),
)
.handler(async ({ context, input: file }) => {
@@ -52,9 +61,22 @@ export const storageRouter = {
}),
deleteFile: protectedProcedure
.route({ tags: ["Internal"], summary: "Delete a file" })
.route({
tags: ["Internal"],
operationId: "deleteFile",
summary: "Delete a file",
description:
"Deletes a file from storage by its filename or path. If the filename does not start with 'uploads/', the user's picture directory is assumed. Requires authentication.",
successDescription: "The file was deleted successfully.",
})
.input(filenameSchema)
.output(z.void())
.errors({
NOT_FOUND: {
message: "The specified file was not found in storage.",
status: 404,
},
})
.handler(async ({ context, input }): Promise<void> => {
// The filename is now the full path from the URL (e.g., "uploads/userId/pictures/timestamp.webp")
// We need to extract just the path portion that matches the storage key
+48 -1
View File
@@ -1,15 +1,31 @@
import { createAnthropic } from "@ai-sdk/anthropic";
import { createGoogleGenerativeAI } from "@ai-sdk/google";
import { createOpenAI } from "@ai-sdk/openai";
import { createGateway, generateText, Output } from "ai";
import { streamToEventIterator } from "@orpc/server";
import {
convertToModelMessages,
createGateway,
generateText,
Output,
stepCountIs,
streamText,
tool,
type UIMessage,
} from "ai";
import { createOllama } from "ai-sdk-ollama";
import { match } from "ts-pattern";
import type { ZodError } from "zod";
import z, { flattenError } from "zod";
import chatSystemPromptTemplate from "@/integrations/ai/prompts/chat-system.md?raw";
import docxParserSystemPrompt from "@/integrations/ai/prompts/docx-parser-system.md?raw";
import docxParserUserPrompt from "@/integrations/ai/prompts/docx-parser-user.md?raw";
import pdfParserSystemPrompt from "@/integrations/ai/prompts/pdf-parser-system.md?raw";
import pdfParserUserPrompt from "@/integrations/ai/prompts/pdf-parser-user.md?raw";
import {
executePatchResume,
patchResumeDescription,
patchResumeInputSchema,
} from "@/integrations/ai/tools/patch-resume";
import type { ResumeData } from "@/schema/resume/data";
import { defaultResumeData, resumeDataSchema } from "@/schema/resume/data";
@@ -141,8 +157,39 @@ export function formatZodError(error: ZodError): string {
return JSON.stringify(flattenError(error));
}
function buildChatSystemPrompt(resumeData: ResumeData): string {
return chatSystemPromptTemplate.replace("{{RESUME_DATA}}", JSON.stringify(resumeData, null, 2));
}
type ChatInput = z.infer<typeof aiCredentialsSchema> & {
messages: UIMessage[];
resumeData: ResumeData;
};
async function chat(input: ChatInput) {
const model = getModel(input);
const systemPrompt = buildChatSystemPrompt(input.resumeData);
const result = streamText({
model,
system: systemPrompt,
messages: await convertToModelMessages(input.messages),
tools: {
patch_resume: tool({
description: patchResumeDescription,
inputSchema: patchResumeInputSchema,
execute: async ({ operations }) => executePatchResume(input.resumeData, operations),
}),
},
stopWhen: stepCountIs(3),
});
return streamToEventIterator(result.toUIMessageStream());
}
export const aiService = {
testConnection,
parsePdf,
parseDocx,
chat,
};
+1 -28
View File
@@ -1,11 +1,9 @@
import { ORPCError } from "@orpc/client";
import { and, eq, isNotNull } from "drizzle-orm";
import { eq } from "drizzle-orm";
import type { AuthProvider } from "@/integrations/auth/types";
import { schema } from "@/integrations/drizzle";
import { db } from "@/integrations/drizzle/client";
import { env } from "@/utils/env";
import { verifyPassword } from "@/utils/password";
import { grantResumeAccess } from "../helpers/resume-access";
import { getStorageService } from "./storage";
export type ProviderList = Partial<Record<AuthProvider, string>>;
@@ -25,31 +23,6 @@ const providers = {
export const authService = {
providers,
verifyResumePassword: async (input: { slug: string; username: string; password: string }): Promise<boolean> => {
const [resume] = await db
.select({ id: schema.resume.id, password: schema.resume.password })
.from(schema.resume)
.innerJoin(schema.user, eq(schema.resume.userId, schema.user.id))
.where(
and(
isNotNull(schema.resume.password),
eq(schema.resume.slug, input.slug),
eq(schema.user.username, input.username),
),
);
if (!resume) throw new ORPCError("NOT_FOUND");
const passwordHash = resume.password as string;
const isValid = await verifyPassword(input.password, passwordHash);
if (!isValid) throw new ORPCError("INVALID_PASSWORD");
grantResumeAccess(resume.id, passwordHash);
return true;
},
deleteAccount: async (input: { userId: string }): Promise<void> => {
if (!input.userId || input.userId.length === 0) return;
+28 -3
View File
@@ -1,5 +1,5 @@
import { ORPCError } from "@orpc/client";
import { and, arrayContains, asc, desc, eq, sql } from "drizzle-orm";
import { and, arrayContains, asc, desc, eq, isNotNull, sql } from "drizzle-orm";
import { get } from "es-toolkit/compat";
import type { Operation } from "fast-json-patch";
import { match } from "ts-pattern";
@@ -9,10 +9,10 @@ import type { ResumeData } from "@/schema/resume/data";
import { defaultResumeData } from "@/schema/resume/data";
import { env } from "@/utils/env";
import type { Locale } from "@/utils/locale";
import { hashPassword } from "@/utils/password";
import { hashPassword, verifyPassword } from "@/utils/password";
import { applyResumePatches, ResumePatchError } from "@/utils/resume/patch";
import { generateId } from "@/utils/string";
import { hasResumeAccess } from "../helpers/resume-access";
import { grantResumeAccess, hasResumeAccess } from "../helpers/resume-access";
import { getStorageService } from "./storage";
const tags = {
@@ -383,6 +383,31 @@ export const resumeService = {
.where(and(eq(schema.resume.id, input.id), eq(schema.resume.userId, input.userId)));
},
verifyPassword: async (input: { slug: string; username: string; password: string }) => {
const [resume] = await db
.select({ id: schema.resume.id, password: schema.resume.password })
.from(schema.resume)
.innerJoin(schema.user, eq(schema.resume.userId, schema.user.id))
.where(
and(
isNotNull(schema.resume.password),
eq(schema.resume.slug, input.slug),
eq(schema.user.username, input.username),
),
);
if (!resume) throw new ORPCError("NOT_FOUND");
const passwordHash = resume.password as string;
const isValid = await verifyPassword(input.password, passwordHash);
if (!isValid) throw new ORPCError("INVALID_PASSWORD");
grantResumeAccess(resume.id, passwordHash);
return true;
},
removePassword: async (input: { id: string; userId: string }) => {
await db
.update(schema.resume)
+7 -1
View File
@@ -1,7 +1,13 @@
import { createFileRoute } from "@tanstack/react-router";
import { auth } from "@/integrations/auth/config";
function handler({ request }: { request: Request }) {
async function handler({ request }: { request: Request }) {
if (request.method === "GET" && request.url.endsWith("/spec.json")) {
const spec = await auth.api.generateOpenAPISchema();
return Response.json(spec);
}
return auth.handler(request);
}
+14 -8
View File
@@ -2,25 +2,28 @@ import { SmartCoercionPlugin } from "@orpc/json-schema";
import { OpenAPIGenerator } from "@orpc/openapi";
import { OpenAPIHandler } from "@orpc/openapi/fetch";
import { onError } from "@orpc/server";
import { RequestHeadersPlugin } from "@orpc/server/plugins";
import { BatchHandlerPlugin, RequestHeadersPlugin, StrictGetMethodPlugin } from "@orpc/server/plugins";
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4";
import { createFileRoute } from "@tanstack/react-router";
import router from "@/integrations/orpc/router";
import { resumeDataSchema } from "@/schema/resume/data";
import { env } from "@/utils/env";
import { getLocale } from "@/utils/locale";
const openAPIHandler = new OpenAPIHandler(router, {
plugins: [
new BatchHandlerPlugin(),
new RequestHeadersPlugin(),
new StrictGetMethodPlugin(),
new SmartCoercionPlugin({
schemaConverters: [new ZodToJsonSchemaConverter()],
}),
],
interceptors: [
onError((error) => {
console.error(`ERROR [OpenAPI]: ${error}`);
}),
],
plugins: [
new RequestHeadersPlugin(),
new SmartCoercionPlugin({
schemaConverters: [new ZodToJsonSchemaConverter()],
}),
],
});
const openAPIGenerator = new OpenAPIGenerator({
@@ -34,13 +37,16 @@ async function handler({ request }: { request: Request }) {
const spec = await openAPIGenerator.generate(router, {
info: {
title: "Reactive Resume",
version: "5.0.0",
version: __APP_VERSION__,
description: "Reactive Resume API",
license: { name: "MIT", url: "https://github.com/amruthpillai/reactive-resume/blob/main/LICENSE" },
contact: { name: "Amruth Pillai", email: "hello@amruthpillai.com", url: "https://amruthpillai.com" },
},
servers: [{ url: `${env.APP_URL}/api/openapi` }],
externalDocs: { url: "https://docs.rxresu.me", description: "Reactive Resume Documentation" },
commonSchemas: {
ResumeData: { schema: resumeDataSchema },
},
components: {
securitySchemes: {
apiKey: {
+12 -2
View File
@@ -1,17 +1,27 @@
import { onError } from "@orpc/server";
import { RPCHandler } from "@orpc/server/fetch";
import { BatchHandlerPlugin, RequestHeadersPlugin } from "@orpc/server/plugins";
import {
BatchHandlerPlugin,
RequestHeadersPlugin,
SimpleCsrfProtectionHandlerPlugin,
StrictGetMethodPlugin,
} from "@orpc/server/plugins";
import { createFileRoute } from "@tanstack/react-router";
import router from "@/integrations/orpc/router";
import { getLocale } from "@/utils/locale";
const rpcHandler = new RPCHandler(router, {
plugins: [
new BatchHandlerPlugin(),
new RequestHeadersPlugin(),
new StrictGetMethodPlugin(),
new SimpleCsrfProtectionHandlerPlugin(),
],
interceptors: [
onError((error) => {
console.error(`ERROR [oRPC]: ${error}`);
}),
],
plugins: [new BatchHandlerPlugin(), new RequestHeadersPlugin()],
});
async function handler({ request }: { request: Request }) {
+1 -1
View File
@@ -44,7 +44,7 @@ function RouteComponent() {
const { redirect } = Route.useSearch();
const [showPassword, toggleShowPassword] = useToggle(false);
const { mutate: verifyPassword } = useMutation(orpc.auth.verifyResumePassword.mutationOptions());
const { mutate: verifyPassword } = useMutation(orpc.resume.verifyPassword.mutationOptions());
const [username, slug] = useMemo(() => {
const [username, slug] = redirect.split("/").slice(1) as [string, string];
@@ -19,6 +19,7 @@ import { useHotkeys } from "react-hotkeys-hook";
import { useControls } from "react-zoom-pan-pinch";
import { toast } from "sonner";
import { useCopyToClipboard } from "usehooks-ts";
import { AIChat } from "@/components/ai/chat";
import { useTemporalStore } from "@/components/resume/store/resume";
import { Button } from "@/components/ui/button";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
@@ -121,6 +122,7 @@ export function BuilderDock() {
<DockIcon icon={MagnifyingGlassMinusIcon} title={t`Zoom out`} onClick={() => zoomOut(0.1)} />
<DockIcon icon={CubeFocusIcon} title={t`Center view`} onClick={() => centerView()} />
<div className="mx-1 h-8 w-px bg-border" />
<AIChat />
<DockIcon icon={LinkSimpleIcon} title={t`Copy URL`} onClick={() => onCopyUrl()} />
<DockIcon icon={FileJsIcon} title={t`Download JSON`} onClick={() => onDownloadJSON()} />
<DockIcon
+2 -2
View File
@@ -107,11 +107,11 @@ function BuilderLayout({ initialLayout, ...props }: BuilderLayoutProps) {
>
<BuilderSidebarLeft />
</ResizablePanel>
<ResizableSeparator withHandle className="z-20 border-s" />
<ResizableSeparator withHandle className="z-50 border-s" />
<ResizablePanel id="artboard" defaultSize={artboardSize} className="h-[calc(100svh-3.5rem)]">
<Outlet />
</ResizablePanel>
<ResizableSeparator withHandle className="z-20 border-e" />
<ResizableSeparator withHandle className="z-50 border-e" />
<ResizablePanel
collapsible
id="right"
File diff suppressed because one or more lines are too long
-15
View File
@@ -169,18 +169,3 @@
break-inside: avoid;
}
}
/* Fix for ScrollArea viewport width overflow */
[data-slot="scroll-area-viewport"] > div {
box-sizing: border-box !important;
display: block !important;
width: 100% !important;
min-width: 0 !important;
max-width: 100% !important;
}
[data-slot="scroll-area-viewport"] {
box-sizing: border-box !important;
width: 100% !important;
max-width: 100% !important;
}
+1 -1
View File
@@ -64,7 +64,7 @@ export function generateRandomName() {
* @param html - The HTML string to strip.
* @returns The text content without HTML tags.
*/
export function stripHtml(html: string | undefined) {
export function stripHtml(html: string | undefined): string {
if (!html) return "";
return html.replace(/<[^>]*>/g, "").trim();
}
-1
View File
@@ -25,7 +25,6 @@
"noUncheckedSideEffectImports": false,
/* Paths */
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}