mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-01-06 05:18:32 -05:00
Compare commits
182 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70b5865dce | ||
|
|
3be7056f2c | ||
|
|
1b57310535 | ||
|
|
2b15d9a515 | ||
|
|
adc9c0b970 | ||
|
|
bec1708891 | ||
|
|
66bb545454 | ||
|
|
c1ebf04291 | ||
|
|
3166060644 | ||
|
|
bde7cf6f9d | ||
|
|
8ea9bb19f6 | ||
|
|
6d0f9b0d35 | ||
|
|
df541c1924 | ||
|
|
9af92ff397 | ||
|
|
554d50b079 | ||
|
|
a00e2e8b68 | ||
|
|
4fcfbaff3b | ||
|
|
7792f0504d | ||
|
|
3ca6c67f25 | ||
|
|
2eb0fdc863 | ||
|
|
192d48c4a6 | ||
|
|
e4f38685b3 | ||
|
|
d02023e12c | ||
|
|
64d8786d8f | ||
|
|
0971d59fa6 | ||
|
|
9b799ca441 | ||
|
|
193b823688 | ||
|
|
c64c2d25e7 | ||
|
|
8b4111d68f | ||
|
|
9d601ea4b5 | ||
|
|
95e1bbce2b | ||
|
|
7b32508201 | ||
|
|
6ed85d72d7 | ||
|
|
cd2a522f25 | ||
|
|
6bd6400aba | ||
|
|
8b92d6ee04 | ||
|
|
7cc2ed75e5 | ||
|
|
cb7f46c0ad | ||
|
|
cb12aedf72 | ||
|
|
8c35a26ab0 | ||
|
|
b2d0f46dd2 | ||
|
|
2c4b7bf611 | ||
|
|
38e542bcd3 | ||
|
|
e53452c19c | ||
|
|
13213476d8 | ||
|
|
9925450173 | ||
|
|
efb9dae681 | ||
|
|
cee93d2a87 | ||
|
|
0d4a8654c1 | ||
|
|
95b1be07bb | ||
|
|
a6fc98fc82 | ||
|
|
6f03010f6c | ||
|
|
69397c91b8 | ||
|
|
798792dcdc | ||
|
|
cc32dd9fa6 | ||
|
|
0c64eb29f9 | ||
|
|
8baa5cc315 | ||
|
|
6f3a5c6c8f | ||
|
|
778078590b | ||
|
|
53c82e5491 | ||
|
|
fef114d97f | ||
|
|
e80cbfad7f | ||
|
|
99527ce738 | ||
|
|
08ccced734 | ||
|
|
43c2c9552b | ||
|
|
db5741c7ee | ||
|
|
a1e394cf36 | ||
|
|
bdbef1ab9e | ||
|
|
e5276f6c20 | ||
|
|
20a6e71b31 | ||
|
|
24c111af7b | ||
|
|
ab4559319e | ||
|
|
2f8625ac44 | ||
|
|
dd146afa57 | ||
|
|
91d15f671e | ||
|
|
7008b13246 | ||
|
|
1a1798cd88 | ||
|
|
64f47c1589 | ||
|
|
326bb1eb8e | ||
|
|
80dc2ecfb7 | ||
|
|
b72082663f | ||
|
|
f46ae423d3 | ||
|
|
05cdff8ae7 | ||
|
|
0facdf73be | ||
|
|
cbad569134 | ||
|
|
1063433aa9 | ||
|
|
0ba22c81e7 | ||
|
|
0667177a2e | ||
|
|
6fcf22869b | ||
|
|
20b45e57e0 | ||
|
|
7a38a52158 | ||
|
|
e27eca5571 | ||
|
|
a90b2ccafd | ||
|
|
e0d8104643 | ||
|
|
53ee64828b | ||
|
|
6f7fba5ac1 | ||
|
|
89aed15905 | ||
|
|
aac48287a4 | ||
|
|
34daaa0476 | ||
|
|
af56a3e69d | ||
|
|
0908812b47 | ||
|
|
d910fbafe8 | ||
|
|
c7692426d5 | ||
|
|
b7a615add9 | ||
|
|
3167e23b6b | ||
|
|
8b582f8682 | ||
|
|
05f648d7fb | ||
|
|
1f19133870 | ||
|
|
98273da16e | ||
|
|
f857ca18da | ||
|
|
22a0e6d608 | ||
|
|
ed806b9fec | ||
|
|
ae8b489f97 | ||
|
|
71732d4766 | ||
|
|
6695314588 | ||
|
|
c115e6d83f | ||
|
|
e3e970213c | ||
|
|
7fe358e5e7 | ||
|
|
c7f3334479 | ||
|
|
d4467f65fb | ||
|
|
27e61ec6b1 | ||
|
|
6c6dc8103d | ||
|
|
35963dad2e | ||
|
|
acd0c2cb3e | ||
|
|
28d00f7dd5 | ||
|
|
fdd3d4b37a | ||
|
|
b09a85dfab | ||
|
|
b6ceece901 | ||
|
|
54b8760d15 | ||
|
|
187e0300a0 | ||
|
|
c398316b55 | ||
|
|
eb093a755b | ||
|
|
2e982fad82 | ||
|
|
f5570bf9b2 | ||
|
|
ddd7ee0696 | ||
|
|
f1b5b999b9 | ||
|
|
47892f84be | ||
|
|
18002351b6 | ||
|
|
9605c448e7 | ||
|
|
9499c2942c | ||
|
|
f04bd7b777 | ||
|
|
710708ea68 | ||
|
|
bb196da83b | ||
|
|
d500fbf0b4 | ||
|
|
ca94ca973c | ||
|
|
454d1eff1c | ||
|
|
280be88fc5 | ||
|
|
e24c37957b | ||
|
|
46b069ba71 | ||
|
|
2caed5e192 | ||
|
|
406f44e6a7 | ||
|
|
f6787f18ba | ||
|
|
1d64f428db | ||
|
|
77906da9f1 | ||
|
|
35d470f5ea | ||
|
|
d7cdcfa734 | ||
|
|
bfbdf76c2d | ||
|
|
7cc0fafbaa | ||
|
|
5b65ceda93 | ||
|
|
07ecd88685 | ||
|
|
8f1ce1a1c3 | ||
|
|
3146e99b03 | ||
|
|
fe53cc28ba | ||
|
|
d85635997b | ||
|
|
1ca29df52e | ||
|
|
ee5de10ffb | ||
|
|
201ab4b8ac | ||
|
|
45af609161 | ||
|
|
c4a3068492 | ||
|
|
6d4f573526 | ||
|
|
3c14df453e | ||
|
|
9826f3483e | ||
|
|
caf0f5f441 | ||
|
|
b599de9c22 | ||
|
|
fd7aa44c13 | ||
|
|
82b7bacdb7 | ||
|
|
84f86c2682 | ||
|
|
527edb1a92 | ||
|
|
6e11b92e74 | ||
|
|
3f5b25a30e | ||
|
|
662d06b5a8 | ||
|
|
9003d0f1d1 |
@@ -13,6 +13,7 @@ RUN echo "export PROMPT_COMMAND='history -a'" >> /home/vscode/.bashrc \
|
||||
&& chown vscode:vscode -R /home/vscode/
|
||||
|
||||
RUN npm install -g @go-task/cli
|
||||
RUN npm install -g json-schema-to-typescript
|
||||
|
||||
# Install additional OS packages
|
||||
RUN apt-get update \
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
"settings": {
|
||||
"python.defaultInterpreterPath": "/usr/local/bin/python",
|
||||
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
|
||||
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
|
||||
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
|
||||
"mypy.runUsingActiveInterpreter": true
|
||||
},
|
||||
@@ -31,10 +30,10 @@
|
||||
"charliermarsh.ruff",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"matangover.mypy",
|
||||
"ms-python.black-formatter",
|
||||
"ms-python.pylint",
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"streetsidesoftware.code-spell-checker-cspell-bundled-dictionaries",
|
||||
"Vue.volar"
|
||||
]
|
||||
}
|
||||
@@ -42,6 +41,7 @@
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
3000,
|
||||
8000, // used by mkdocs
|
||||
9000,
|
||||
9091, // used by docker production
|
||||
24678 // used by nuxt when hot-reloading using polling
|
||||
@@ -56,5 +56,8 @@
|
||||
"dockerDashComposeVersion": "v2"
|
||||
}
|
||||
},
|
||||
"appPort": 3000
|
||||
"appPort": [
|
||||
"3000:3000",
|
||||
"9000:9000"
|
||||
]
|
||||
}
|
||||
|
||||
240
.github/copilot-instructions.md
vendored
Normal file
240
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
# Mealie Development Guide for AI Agents
|
||||
|
||||
## Project Overview
|
||||
|
||||
Mealie is a self-hosted recipe manager, meal planner, and shopping list application with a FastAPI backend (Python 3.12) and Nuxt 3 frontend (Vue 3 + TypeScript). It uses SQLAlchemy ORM with support for SQLite and PostgreSQL databases.
|
||||
|
||||
**Development vs Production:**
|
||||
- **Development:** Frontend (port 3000) and backend (port 9000) run as separate processes
|
||||
- **Production:** Frontend is statically generated and served via FastAPI's SPA module (`mealie/routes/spa/`) in a single container
|
||||
|
||||
## Architecture & Key Patterns
|
||||
|
||||
### Backend Architecture (mealie/)
|
||||
|
||||
**Repository-Service-Controller Pattern:**
|
||||
- **Controllers** (`mealie/routes/**/controller_*.py`): Inherit from `BaseUserController` or `BaseAdminController`, handle HTTP concerns, delegate to services
|
||||
- **Services** (`mealie/services/`): Business logic layer, inherit from `BaseService`, coordinate repos and external dependencies
|
||||
- **Repositories** (`mealie/repos/`): Data access layer using SQLAlchemy, accessed via `AllRepositories` factory
|
||||
- Get repos via dependency injection: `repos: AllRepositories = Depends(get_repositories)`
|
||||
- All repos scoped to group/household context automatically
|
||||
|
||||
**Route Organization:**
|
||||
- Routes in `mealie/routes/` organized by domain (auth, recipe, groups, households, admin)
|
||||
- Use `APIRouter` with FastAPI dependency injection
|
||||
- Apply `@router.get/post/put/delete` decorators with Pydantic response models
|
||||
- Route controllers use `HttpRepo` mixin for common CRUD operations (see `mealie/routes/_base/mixins.py`)
|
||||
|
||||
**Schemas & Type Generation:**
|
||||
- Pydantic schemas in `mealie/schema/` with strict separation: `*In`, `*Out`, `*Create`, `*Update` suffixes
|
||||
- Auto-exported from submodules via `__init__.py` files (generated by `task dev:generate`)
|
||||
- TypeScript types auto-generated from Pydantic schemas - **never manually edit** `frontend/lib/api/types/`
|
||||
|
||||
**Database & Sessions:**
|
||||
- Session management via `Depends(generate_session)` in FastAPI routes
|
||||
- Use `session_context()` context manager in services/scripts
|
||||
- SQLAlchemy models in `mealie/db/models/`, migrations in `mealie/alembic/`
|
||||
- Create migrations: `task py:migrate -- "description"`
|
||||
|
||||
### Frontend Architecture (frontend/)
|
||||
|
||||
**Component Organization (strict naming conventions):**
|
||||
- **Domain Components** (`components/Domain/`): Feature-specific, prefix with domain (e.g., `AdminDashboard`)
|
||||
- **Global Components** (`components/global/`): Reusable primitives, prefix with `Base` (e.g., `BaseButton`)
|
||||
- **Layout Components** (`components/Layout/`): Layout-only, prefix with `App` if props or `The` if singleton
|
||||
- **Page Components** (`components/` with page prefix): Last resort for breaking up complex pages
|
||||
|
||||
**API Client Pattern:**
|
||||
- API clients in `frontend/lib/api/` extend `BaseAPI`, `BaseCRUDAPI`, or `BaseCRUDAPIReadOnly`
|
||||
- Types imported from auto-generated `frontend/lib/api/types/` (DO NOT EDIT MANUALLY)
|
||||
- Composables in `frontend/composables/` for shared state and API logic (e.g., `use-mealie-auth.ts`)
|
||||
- Use `useAuthBackend()` for authentication state, `useMealieAuth()` for user management
|
||||
|
||||
**State Management:**
|
||||
- Nuxt 3 composables for state (no Vuex)
|
||||
- Auth state via `use-mealie-auth.ts` composable
|
||||
- Prefer composables over global state stores
|
||||
|
||||
## Essential Commands (via Task/Taskfile.yml)
|
||||
|
||||
**Development workflow:**
|
||||
```bash
|
||||
task setup # Install all dependencies (Python + Node)
|
||||
task dev:services # Start Postgres & Mailpit containers
|
||||
task py # Start FastAPI backend (port 9000)
|
||||
task ui # Start Nuxt frontend (port 3000)
|
||||
task docs # Start MkDocs documentation server
|
||||
```
|
||||
|
||||
**Code generation (REQUIRED after schema changes):**
|
||||
```bash
|
||||
task dev:generate # Generate TypeScript types, schema exports, test helpers
|
||||
```
|
||||
|
||||
**Testing & Quality:**
|
||||
```bash
|
||||
task py:test # Run pytest (supports args: task py:test -- -k test_name)
|
||||
task py:check # Format + lint + type-check + test (full validation)
|
||||
task py:format # Ruff format
|
||||
task py:lint # Ruff check
|
||||
task py:mypy # Type checking
|
||||
task ui:test # Vitest frontend tests
|
||||
task ui:check # Frontend lint + test
|
||||
```
|
||||
|
||||
**Database:**
|
||||
```bash
|
||||
task py:migrate -- "description" # Generate Alembic migration
|
||||
task py:postgres # Run backend with PostgreSQL config
|
||||
```
|
||||
|
||||
**Docker:**
|
||||
```bash
|
||||
task docker:prod # Build and run production Docker compose
|
||||
```
|
||||
|
||||
## Critical Development Practices
|
||||
|
||||
### Python Backend
|
||||
|
||||
1. **Always use `uv` for Python commands** (not `python` or `pip`):
|
||||
```bash
|
||||
uv run python mealie/app.py
|
||||
uv run pytest tests/
|
||||
```
|
||||
|
||||
2. **Type hints are mandatory:** Use mypy-compatible annotations, handle Optional types explicitly
|
||||
|
||||
3. **Dependency injection pattern:**
|
||||
```python
|
||||
from fastapi import Depends
|
||||
from mealie.repos.all_repositories import get_repositories, AllRepositories
|
||||
|
||||
def my_route(
|
||||
repos: AllRepositories = Depends(get_repositories),
|
||||
user: PrivateUser = Depends(get_current_user)
|
||||
):
|
||||
recipe = repos.recipes.get_one(recipe_id)
|
||||
```
|
||||
|
||||
4. **Settings & Configuration:**
|
||||
- Get settings: `settings = get_app_settings()` (cached singleton)
|
||||
- Get directories: `dirs = get_app_dirs()`
|
||||
- Never instantiate `AppSettings()` directly
|
||||
|
||||
5. **Testing:**
|
||||
- Fixtures in `tests/fixtures/`
|
||||
- Use `api_client` fixture for integration tests
|
||||
- Follow existing patterns in `tests/integration_tests/` and `tests/unit_tests/`
|
||||
|
||||
### Frontend
|
||||
|
||||
1. **Run code generation after backend schema changes:** `task dev:generate`
|
||||
|
||||
2. **TypeScript strict mode:** All code must pass type checking
|
||||
|
||||
3. **Component naming:** Follow strict conventions (see Architecture section above)
|
||||
|
||||
4. **API calls pattern:**
|
||||
```typescript
|
||||
const api = useUserApi();
|
||||
const recipe = await api.recipes.getOne(recipeId);
|
||||
```
|
||||
|
||||
5. **Composables for shared logic:** Prefer composables in `composables/` over inline code duplication
|
||||
|
||||
6. **Translations:** Only modify `en-US` locale files when adding new translation strings - other locales are managed via Crowdin and **must never be modified** (PRs modifying non-English locales will be rejected)
|
||||
|
||||
### Cross-Cutting Concerns
|
||||
|
||||
1. **Code generation is source of truth:** After Pydantic schema changes, run `task dev:generate` to update:
|
||||
- TypeScript types (`frontend/lib/api/types/`)
|
||||
- Schema exports (`mealie/schema/*/__init__.py`)
|
||||
- Test data paths and routes
|
||||
|
||||
2. **Multi-tenancy:** All data scoped to **groups** and **households**:
|
||||
- Groups contain multiple households
|
||||
- Households contain recipes, meal plans, shopping lists
|
||||
- Repositories automatically filter by group/household context
|
||||
|
||||
3. **Pre-commit hooks:** Install via `task setup:py`, enforces Ruff formatting/linting
|
||||
|
||||
4. **Testing before PRs:** Run `task py:check` and `task ui:check` before submitting PRs
|
||||
|
||||
## Pull Request Best Practices
|
||||
|
||||
### Before Submitting a PR
|
||||
|
||||
1. **Draft PRs are optional:** Create a draft PR early if you want feedback while working, or open directly as ready when complete
|
||||
2. **Verify code generation:** If you modified Pydantic schemas, ensure `task dev:generate` was run
|
||||
3. **Follow Conventional Commits:** Title your PR according to the conventional commits format (see PR template)
|
||||
4. **Add release notes:** Include user-facing changes in the PR description
|
||||
|
||||
### What to Review
|
||||
|
||||
**Architecture & Patterns:**
|
||||
- Does the code follow the repository-service-controller pattern?
|
||||
- Are controllers delegating business logic to services?
|
||||
- Are services coordinating repositories, not accessing the database directly?
|
||||
- Is dependency injection used properly (`Depends(get_repositories)`, `Depends(get_current_user)`)?
|
||||
|
||||
**Data Scoping:**
|
||||
- Are repositories correctly scoped to group/household context?
|
||||
- Do route handlers properly validate group/household ownership before operations?
|
||||
- Are multi-tenant boundaries enforced (users can't access other groups' data)?
|
||||
|
||||
**Type Safety:**
|
||||
- Are type hints present on all functions and methods?
|
||||
- Are Pydantic schemas using correct suffixes (`*In`, `*Out`, `*Create`, `*Update`)?
|
||||
- For frontend, does TypeScript code pass strict type checking?
|
||||
|
||||
**Generated Files:**
|
||||
- Verify `frontend/lib/api/types/` files weren't manually edited (they're auto-generated)
|
||||
- Check that `mealie/schema/*/__init__.py` exports match actual schema files (auto-generated)
|
||||
- If schemas changed, confirm generated files were updated via `task dev:generate`
|
||||
|
||||
**Code Quality:**
|
||||
- Is the code readable and well-organized?
|
||||
- Are complex operations documented with clear comments?
|
||||
- Do component names follow the strict naming conventions (Domain/Global/Layout/Page prefixes)?
|
||||
- Are composables used for shared frontend logic instead of duplication?
|
||||
|
||||
**Translations:**
|
||||
- Were only `en-US` locale files modified for new translation strings?
|
||||
- Verify no other locale files (managed by Crowdin) were touched
|
||||
|
||||
**Database Changes:**
|
||||
- Are Alembic migrations included for schema changes?
|
||||
- Are migrations tested against both SQLite and PostgreSQL?
|
||||
|
||||
### Review Etiquette
|
||||
|
||||
- Be constructive and specific in feedback
|
||||
- Suggest code examples when proposing changes
|
||||
- Focus on architecture and logic - formatting/linting is handled by CI
|
||||
- Use "Approve" when ready to merge, "Request Changes" for blocking issues, "Comment" for non-blocking suggestions
|
||||
|
||||
## Common Gotchas
|
||||
|
||||
- **Don't manually edit generated files:** `frontend/lib/api/types/`, schema `__init__.py` files
|
||||
- **Repository context:** Repos are group/household-scoped - passing wrong IDs causes 404s
|
||||
- **Session handling:** Don't create sessions manually, use dependency injection or `session_context()`
|
||||
- **Schema changes require codegen:** After changing Pydantic models, run `task dev:generate`
|
||||
- **Translation files:** Only modify `en-US` locale files - all other locales are managed by Crowdin
|
||||
- **Dev containers:** This project uses VS Code dev containers - leverage the pre-configured environment
|
||||
- **Task commands:** Use `task` commands instead of direct tool invocation for consistency
|
||||
|
||||
## Key Files to Reference
|
||||
|
||||
- `Taskfile.yml` - All development commands and workflows
|
||||
- `mealie/routes/_base/base_controllers.py` - Controller base classes and patterns
|
||||
- `mealie/repos/repository_factory.py` - Repository factory and available repos
|
||||
- `frontend/lib/api/base/base-clients.ts` - API client base classes
|
||||
- `tests/conftest.py` - Test fixtures and setup
|
||||
- `dev/code-generation/main.py` - Code generation entry point
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Documentation](https://docs.mealie.io/)
|
||||
- [Contributors Guide](https://nightly.mealie.io/contributors/developers-guide/code-contributions/)
|
||||
- [Discord](https://discord.gg/QuStdQGSGK)
|
||||
50
.github/workflows/docs.yml
vendored
Normal file
50
.github/workflows/docs.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: Deploy Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [mealie-next]
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '.github/workflows/docs.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: pages
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --only-group docs --no-install-project
|
||||
|
||||
- name: Build docs
|
||||
run: uv run --no-project mkdocs build -d site
|
||||
working-directory: docs
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: docs/site
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
132
.github/workflows/release.yml
vendored
132
.github/workflows/release.yml
vendored
@@ -5,17 +5,73 @@ on:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
commit-version-bump:
|
||||
name: Commit version bump to repository
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
outputs:
|
||||
commit-sha: ${{ steps.commit.outputs.commit-sha }}
|
||||
steps:
|
||||
- name: Generate GitHub App Token
|
||||
id: app-token
|
||||
uses: actions/create-github-app-token@v1
|
||||
with:
|
||||
app-id: ${{ secrets.COMMIT_BOT_APP_ID }}
|
||||
private-key: ${{ secrets.COMMIT_BOT_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Checkout 🛎
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- name: Extract Version From Tag Name
|
||||
run: echo "VERSION_NUM=$(echo ${{ github.event.release.tag_name }} | sed 's/^v//')" >> $GITHUB_ENV
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config user.name "mealie-commit-bot[bot]"
|
||||
git config user.email "mealie-commit-bot[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Update all version strings
|
||||
run: |
|
||||
sed -i 's/^version = "[^"]*"/version = "${{ env.VERSION_NUM }}"/' pyproject.toml
|
||||
sed -i '/^name = "mealie"$/,/^version = / s/^version = "[^"]*"/version = "${{ env.VERSION_NUM }}"/' uv.lock
|
||||
sed -i 's/\("version": "\)[^"]*"/\1${{ env.VERSION_NUM }}"/' frontend/package.json
|
||||
sed -i 's/:v[0-9]*\.[0-9]*\.[0-9]*/:v${{ env.VERSION_NUM }}/' docs/docs/documentation/getting-started/installation/installation-checklist.md
|
||||
sed -i 's/:v[0-9]*\.[0-9]*\.[0-9]*/:v${{ env.VERSION_NUM }}/' docs/docs/documentation/getting-started/installation/sqlite.md
|
||||
sed -i 's/:v[0-9]*\.[0-9]*\.[0-9]*/:v${{ env.VERSION_NUM }}/' docs/docs/documentation/getting-started/installation/postgres.md
|
||||
|
||||
- name: Commit and push changes
|
||||
id: commit
|
||||
run: |
|
||||
git add pyproject.toml frontend/package.json uv.lock docs/
|
||||
git commit -m "chore: bump version to ${{ github.event.release.tag_name }}"
|
||||
git push origin HEAD:${{ github.event.repository.default_branch }}
|
||||
echo "commit-sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Move release tag to new commit
|
||||
run: |
|
||||
git tag -f ${{ github.event.release.tag_name }}
|
||||
git push -f origin ${{ github.event.release.tag_name }}
|
||||
|
||||
backend-tests:
|
||||
name: "Backend Server Tests"
|
||||
uses: ./.github/workflows/test-backend.yml
|
||||
needs:
|
||||
- commit-version-bump
|
||||
|
||||
frontend-tests:
|
||||
name: "Frontend Tests"
|
||||
uses: ./.github/workflows/test-frontend.yml
|
||||
needs:
|
||||
- commit-version-bump
|
||||
|
||||
build-package:
|
||||
name: Build Package
|
||||
uses: ./.github/workflows/build-package.yml
|
||||
needs:
|
||||
- commit-version-bump
|
||||
with:
|
||||
tag: ${{ github.event.release.tag_name }}
|
||||
|
||||
@@ -43,10 +99,48 @@ jobs:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
rollback-on-failure:
|
||||
name: Rollback version commit if deployment fails
|
||||
needs:
|
||||
- commit-version-bump
|
||||
- publish
|
||||
if: always() && needs.publish.result == 'failure'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Generate GitHub App Token
|
||||
id: app-token
|
||||
uses: actions/create-github-app-token@v1
|
||||
with:
|
||||
app-id: ${{ secrets.COMMIT_BOT_APP_ID }}
|
||||
private-key: ${{ secrets.COMMIT_BOT_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Checkout 🛎
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config user.name "mealie-commit-bot[bot]"
|
||||
git config user.email "mealie-commit-bot[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Delete release tag
|
||||
run: |
|
||||
git push --delete origin ${{ github.event.release.tag_name }}
|
||||
|
||||
- name: Revert version bump commit
|
||||
run: |
|
||||
git revert --no-edit ${{ needs.commit-version-bump.outputs.commit-sha }}
|
||||
git push origin HEAD:${{ github.event.repository.default_branch }}
|
||||
|
||||
notify-discord:
|
||||
name: Notify Discord
|
||||
needs:
|
||||
- publish
|
||||
if: success()
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Discord notification
|
||||
@@ -55,41 +149,3 @@ jobs:
|
||||
uses: Ilshidur/action-discord@0.3.2
|
||||
with:
|
||||
args: "🚀 Version {{ EVENT_PAYLOAD.release.tag_name }} of Mealie has been released. See the release notes https://github.com/mealie-recipes/mealie/releases/tag/{{ EVENT_PAYLOAD.release.tag_name }}"
|
||||
|
||||
update-image-tags:
|
||||
name: Update image tag in sample docker-compose files
|
||||
needs:
|
||||
- publish
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout 🛎
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Extract Version From Tag Name
|
||||
run: echo "VERSION_NUM=$(echo ${{ github.event.release.tag_name }} | sed 's/^v//')" >> $GITHUB_ENV
|
||||
|
||||
- name: Modify version strings
|
||||
run: |
|
||||
sed -i 's/:v[0-9]*.[0-9]*.[0-9]*/:v${{ env.VERSION_NUM }}/' docs/docs/documentation/getting-started/installation/installation-checklist.md
|
||||
sed -i 's/:v[0-9]*.[0-9]*.[0-9]*/:v${{ env.VERSION_NUM }}/' docs/docs/documentation/getting-started/installation/sqlite.md
|
||||
sed -i 's/:v[0-9]*.[0-9]*.[0-9]*/:v${{ env.VERSION_NUM }}/' docs/docs/documentation/getting-started/installation/postgres.md
|
||||
sed -i 's/^version = "[^"]*"/version = "${{ env.VERSION_NUM }}"/' pyproject.toml
|
||||
sed -i 's/\("version": "\)[^"]*"/\1${{ env.VERSION_NUM }}"/' frontend/package.json
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
# This doesn't currently work for us because it creates the PR but the workflows don't run.
|
||||
# TODO: Provide a personal access token as a parameter here, that solves that problem.
|
||||
# https://github.com/peter-evans/create-pull-request
|
||||
with:
|
||||
commit-message: "Update image tag, for release ${{ github.event.release.tag_name }}"
|
||||
branch: "docs/newrelease-update-version-${{ github.event.release.tag_name }}"
|
||||
labels: |
|
||||
documentation
|
||||
delete-branch: true
|
||||
base: mealie-next
|
||||
title: "docs(auto): Update image tag, for release ${{ github.event.release.tag_name }}"
|
||||
body: "Auto-generated by `.github/workflows/release.yml`, on publish of release ${{ github.event.release.tag_name }}"
|
||||
|
||||
2
.github/workflows/test-frontend.yml
vendored
2
.github/workflows/test-frontend.yml
vendored
@@ -39,7 +39,7 @@ jobs:
|
||||
working-directory: "frontend"
|
||||
|
||||
- name: Run linter 👀
|
||||
run: yarn lint
|
||||
run: yarn lint --max-warnings=0
|
||||
working-directory: "frontend"
|
||||
|
||||
- name: Run tests 🧪
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -20,6 +20,7 @@ dev/data/backups/*
|
||||
dev/data/debug/*
|
||||
dev/data/img/*
|
||||
dev/data/migration/*
|
||||
dev/data/templates/*
|
||||
dev/data/users/*
|
||||
dev/data/groups/*
|
||||
|
||||
@@ -69,8 +70,11 @@ wheels/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# packaged output - temporarily written here by `uv build`
|
||||
/mealie-*
|
||||
|
||||
# frontend copied into Python module for packaging purposes
|
||||
/mealie/frontend/
|
||||
/mealie/frontend
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
|
||||
@@ -12,7 +12,7 @@ repos:
|
||||
exclude: ^tests/data/
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.14.4
|
||||
rev: v0.14.10
|
||||
hooks:
|
||||
- id: ruff
|
||||
- id: ruff-format
|
||||
|
||||
@@ -228,7 +228,7 @@ tasks:
|
||||
desc: runs the frontend linter
|
||||
dir: frontend
|
||||
cmds:
|
||||
- yarn lint
|
||||
- yarn lint --max-warnings=0
|
||||
|
||||
ui:test:
|
||||
desc: runs the frontend tests
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
###############################################
|
||||
# Frontend Build
|
||||
###############################################
|
||||
FROM node:24@sha256:7f80506b8225bcce2ce8202b1026fcde8f0bfb716b1b833f20250d79d4463276 \
|
||||
FROM node:24@sha256:b52a8d1206132b36d60e51e413d9a81336e8a0206d3b648cabd6d5a49c4c0f54 \
|
||||
AS frontend-builder
|
||||
|
||||
WORKDIR /frontend
|
||||
|
||||
@@ -4,22 +4,22 @@
|
||||
|
||||
### General
|
||||
|
||||
| Variables | Default | Description |
|
||||
| ----------------------------- | :-------------------: | -------------------------------------------------------------------------------------------------- |
|
||||
| PUID | 911 | UserID permissions between host OS and container |
|
||||
| PGID | 911 | GroupID permissions between host OS and container |
|
||||
| DEFAULT_GROUP | Home | The default group for users |
|
||||
| DEFAULT_HOUSEHOLD | Family | The default household for users in each group |
|
||||
| BASE_URL | http://localhost:8080 | Used for Notifications |
|
||||
| TOKEN_TIME | 48 | The time in hours that a login/auth token is valid. Must be <= 87600 (10 years, in hours). |
|
||||
| API_PORT | 9000 | The port exposed by backend API. **Do not change this if you're running in Docker** |
|
||||
| API_DOCS | True | Turns on/off access to the API documentation locally |
|
||||
| TZ | UTC | Must be set to get correct date/time on the server |
|
||||
| ALLOW_SIGNUP<super>\*</super> | false | Allow user sign-up without token |
|
||||
| ALLOW_PASSWORD_LOGIN | true | Whether or not to display the username+password input fields. Keep set to true unless you use OIDC authentication |
|
||||
| LOG_CONFIG_OVERRIDE | | Override the config for logging with a custom path |
|
||||
| LOG_LEVEL | info | Logging level (e.g. critical, error, warning, info, debug) |
|
||||
| DAILY_SCHEDULE_TIME | 23:45 | The time of day to run daily server tasks, in HH:MM format. Use the server's local time, *not* UTC |
|
||||
| Variables | Default | Description |
|
||||
| ----------------------------- | :-------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| PUID | 911 | UserID permissions between host OS and container |
|
||||
| PGID | 911 | GroupID permissions between host OS and container |
|
||||
| DEFAULT_GROUP | Home | The default group for users |
|
||||
| DEFAULT_HOUSEHOLD | Family | The default household for users in each group |
|
||||
| BASE_URL | http://localhost:8080 | Used for Notifications |
|
||||
| TOKEN_TIME | 48 | The time in hours that a login/auth token is valid. Must be <= 9600 (400 days, in hours). |
|
||||
| API_PORT | 9000 | The port exposed by backend API. **Do not change this if you're running in Docker** |
|
||||
| API_DOCS | True | Turns on/off access to the API documentation locally |
|
||||
| TZ | UTC | Must be set to get correct date/time on the server |
|
||||
| ALLOW_SIGNUP<super>\*</super> | false | Allow user sign-up without token |
|
||||
| ALLOW_PASSWORD_LOGIN | true | Whether or not to display the username+password input fields. Keep set to true unless you use OIDC authentication |
|
||||
| LOG_CONFIG_OVERRIDE | | Override the config for logging with a custom path |
|
||||
| LOG_LEVEL | info | Logging level (e.g. critical, error, warning, info, debug) |
|
||||
| DAILY_SCHEDULE_TIME | 23:45 | The time of day to run daily server tasks, in HH:MM format. Use the server's local time, *not* UTC |
|
||||
|
||||
<super>\*</super> Starting in v1.4.0 this was changed to default to `false` as part of a security review of the application.
|
||||
|
||||
@@ -145,22 +145,95 @@ Setting the following environmental variables will change the theme of the front
|
||||
|
||||
If using YAML sequence syntax, don't include any quotes:<br>`THEME_LIGHT_PRIMARY=#E58325` or `THEME_LIGHT_PRIMARY=E58325`
|
||||
|
||||
| Variables | Default | Description |
|
||||
| --------------------- | :-----: | --------------------------- |
|
||||
| THEME_LIGHT_PRIMARY | #E58325 | Light Theme Config Variable |
|
||||
| THEME_LIGHT_ACCENT | #007A99 | Light Theme Config Variable |
|
||||
| THEME_LIGHT_SECONDARY | #973542 | Light Theme Config Variable |
|
||||
| THEME_LIGHT_SUCCESS | #43A047 | Light Theme Config Variable |
|
||||
| THEME_LIGHT_INFO | #1976D2 | Light Theme Config Variable |
|
||||
| THEME_LIGHT_WARNING | #FF6D00 | Light Theme Config Variable |
|
||||
| THEME_LIGHT_ERROR | #EF5350 | Light Theme Config Variable |
|
||||
| THEME_DARK_PRIMARY | #E58325 | Dark Theme Config Variable |
|
||||
| THEME_DARK_ACCENT | #007A99 | Dark Theme Config Variable |
|
||||
| THEME_DARK_SECONDARY | #973542 | Dark Theme Config Variable |
|
||||
| THEME_DARK_SUCCESS | #43A047 | Dark Theme Config Variable |
|
||||
| THEME_DARK_INFO | #1976D2 | Dark Theme Config Variable |
|
||||
| THEME_DARK_WARNING | #FF6D00 | Dark Theme Config Variable |
|
||||
| THEME_DARK_ERROR | #EF5350 | Dark Theme Config Variable |
|
||||
| Variables | Default | Description |
|
||||
| --------------------- | :-----: | ---------------------------------- |
|
||||
| THEME_LIGHT_PRIMARY | #E58325 | Main brand color and headers |
|
||||
| THEME_LIGHT_ACCENT | #007A99 | Buttons and interactive elements |
|
||||
| THEME_LIGHT_SECONDARY | #973542 | Navigation and sidebar backgrounds |
|
||||
| THEME_LIGHT_SUCCESS | #43A047 | Success messages and confirmations |
|
||||
| THEME_LIGHT_INFO | #1976D2 | Information alerts and tooltips |
|
||||
| THEME_LIGHT_WARNING | #FF6D00 | Warning notifications |
|
||||
| THEME_LIGHT_ERROR | #EF5350 | Error messages and alerts |
|
||||
| THEME_DARK_PRIMARY | #E58325 | Main brand color and headers |
|
||||
| THEME_DARK_ACCENT | #007A99 | Buttons and interactive elements |
|
||||
| THEME_DARK_SECONDARY | #973542 | Navigation and sidebar backgrounds |
|
||||
| THEME_DARK_SUCCESS | #43A047 | Success messages and confirmations |
|
||||
| THEME_DARK_INFO | #1976D2 | Information alerts and tooltips |
|
||||
| THEME_DARK_WARNING | #FF6D00 | Warning notifications |
|
||||
| THEME_DARK_ERROR | #EF5350 | Error messages and alerts |
|
||||
|
||||
#### Theming Examples
|
||||
|
||||
The examples below provide copy-ready Docker Compose environment configurations for three different color palettes. Copy and paste the desired theme into your `docker-compose.yml` file's environment section.
|
||||
|
||||
!!! info
|
||||
These themes are functional and ready to use, but they are provided primarily as examples. The color palettes can be adjusted or refined to better suit your preferences.
|
||||
|
||||
=== "Blue Theme"
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
# Light mode colors
|
||||
THEME_LIGHT_PRIMARY: '#5E9BD1'
|
||||
THEME_LIGHT_ACCENT: '#A3C9E8'
|
||||
THEME_LIGHT_SECONDARY: '#4F89BA'
|
||||
THEME_LIGHT_SUCCESS: '#4CAF50'
|
||||
THEME_LIGHT_INFO: '#4A9ED8'
|
||||
THEME_LIGHT_WARNING: '#EAC46B'
|
||||
THEME_LIGHT_ERROR: '#E57373'
|
||||
# Dark mode colors
|
||||
THEME_DARK_PRIMARY: '#5A8FBF'
|
||||
THEME_DARK_ACCENT: '#90B8D9'
|
||||
THEME_DARK_SECONDARY: '#406D96'
|
||||
THEME_DARK_SUCCESS: '#81C784'
|
||||
THEME_DARK_INFO: '#78B2C0'
|
||||
THEME_DARK_WARNING: '#EBC86E'
|
||||
THEME_DARK_ERROR: '#E57373'
|
||||
```
|
||||
|
||||
=== "Green Theme"
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
# Light mode colors
|
||||
THEME_LIGHT_PRIMARY: '#75A86C'
|
||||
THEME_LIGHT_ACCENT: '#A8D0A6'
|
||||
THEME_LIGHT_SECONDARY: '#638E5E'
|
||||
THEME_LIGHT_SUCCESS: '#4CAF50'
|
||||
THEME_LIGHT_INFO: '#4A9ED8'
|
||||
THEME_LIGHT_WARNING: '#EAC46B'
|
||||
THEME_LIGHT_ERROR: '#E57373'
|
||||
# Dark mode colors
|
||||
THEME_DARK_PRIMARY: '#739B7A'
|
||||
THEME_DARK_ACCENT: '#9FBE9D'
|
||||
THEME_DARK_SECONDARY: '#56775E'
|
||||
THEME_DARK_SUCCESS: '#81C784'
|
||||
THEME_DARK_INFO: '#78B2C0'
|
||||
THEME_DARK_WARNING: '#EBC86E'
|
||||
THEME_DARK_ERROR: '#E57373'
|
||||
```
|
||||
|
||||
=== "Pink Theme"
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
# Light mode colors
|
||||
THEME_LIGHT_PRIMARY: '#D97C96'
|
||||
THEME_LIGHT_ACCENT: '#E891A7'
|
||||
THEME_LIGHT_SECONDARY: '#C86C88'
|
||||
THEME_LIGHT_SUCCESS: '#4CAF50'
|
||||
THEME_LIGHT_INFO: '#2196F3'
|
||||
THEME_LIGHT_WARNING: '#FFC107'
|
||||
THEME_LIGHT_ERROR: '#E57373'
|
||||
# Dark mode colors
|
||||
THEME_DARK_PRIMARY: '#C2185B'
|
||||
THEME_DARK_ACCENT: '#FF80AB'
|
||||
THEME_DARK_SECONDARY: '#AD1457'
|
||||
THEME_DARK_SUCCESS: '#81C784'
|
||||
THEME_DARK_INFO: '#64B5F6'
|
||||
THEME_DARK_WARNING: '#FFD54F'
|
||||
THEME_DARK_ERROR: '#E57373'
|
||||
```
|
||||
|
||||
### Docker Secrets
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ To deploy mealie on your local network, it is highly recommended to use Docker t
|
||||
We've gone through a few versions of Mealie v1 deployment targets. We have settled on a single container deployment, and we've begun publishing the nightly container on github containers. If you're looking to move from the old nightly (split containers _or_ the omni image) to the new nightly, there are a few things you need to do:
|
||||
|
||||
1. Take a backup just in case!
|
||||
2. Replace the image for the API container with `ghcr.io/mealie-recipes/mealie:v3.4.0`
|
||||
2. Replace the image for the API container with `ghcr.io/mealie-recipes/mealie:v3.9.2`
|
||||
3. Take the external port from the frontend container and set that as the port mapped to port `9000` on the new container. The frontend is now served on port 9000 from the new container, so it will need to be mapped for you to have access.
|
||||
4. Restart the container
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ PostgreSQL might be considered if you need to support many concurrent users. In
|
||||
```yaml
|
||||
services:
|
||||
mealie:
|
||||
image: ghcr.io/mealie-recipes/mealie:v3.4.0 # (3)
|
||||
image: ghcr.io/mealie-recipes/mealie:v3.9.2 # (3)
|
||||
container_name: mealie
|
||||
restart: always
|
||||
ports:
|
||||
|
||||
@@ -11,7 +11,7 @@ SQLite is a popular, open source, self-contained, zero-configuration database th
|
||||
```yaml
|
||||
services:
|
||||
mealie:
|
||||
image: ghcr.io/mealie-recipes/mealie:v3.4.0 # (3)
|
||||
image: ghcr.io/mealie-recipes/mealie:v3.9.2 # (3)
|
||||
container_name: mealie
|
||||
restart: always
|
||||
ports:
|
||||
|
||||
@@ -9,6 +9,23 @@
|
||||
- Create a Backup and Download from the UI
|
||||
- Upgrade
|
||||
|
||||
!!! info "Improved Image Processing"
|
||||
Starting with :octicons-tag-24: v3.7.0, we updated our image processing algorithm to improve image quality and compression. New image processing can be up to 40%-50% smaller on disk while providing higher resolution thumbnails. To take advantage of these improvements on older recipes, you can run our image-processing script:
|
||||
|
||||
```shell
|
||||
docker exec -it mealie bash
|
||||
python /opt/mealie/lib64/python3.12/site-packages/mealie/scripts/reprocess_images.py
|
||||
```
|
||||
|
||||
### Options
|
||||
- `--workers N`: Number of worker threads (default: 2, safe for low-powered devices)
|
||||
- `--force-all`: Reprocess all recipes regardless of current image state
|
||||
|
||||
### Example
|
||||
```shell
|
||||
python /opt/mealie/lib64/python3.12/site-packages/mealie/scripts/reprocess_images.py --workers 8
|
||||
```
|
||||
|
||||
## Upgrading to Mealie v1 or later
|
||||
If you are upgrading from pre-v1.0.0 to v1.0.0 or later (v2.0.0, etc.), make sure you read [Migrating to Mealie v1](./migrating-to-mealie-v1.md)!
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -32,8 +32,8 @@ theme:
|
||||
|
||||
markdown_extensions:
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:materialx.emoji.twemoji
|
||||
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||
- def_list
|
||||
- pymdownx.highlight
|
||||
- pymdownx.superfences
|
||||
|
||||
121
frontend/components/Domain/Admin/Setup/EndPageContent.vue
Normal file
121
frontend/components/Domain/Admin/Setup/EndPageContent.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<v-container max-width="880" class="end-page-content">
|
||||
<div class="d-flex flex-column ga-6">
|
||||
<div>
|
||||
<v-card-title class="text-h4 justify-center">
|
||||
{{ $t('admin.setup.setup-complete') }}
|
||||
</v-card-title>
|
||||
<v-card-subtitle class="justify-center">
|
||||
{{ $t('admin.setup.here-are-a-few-things-to-help-you-get-started') }}
|
||||
</v-card-subtitle>
|
||||
</div>
|
||||
<div
|
||||
v-for="section, idx in sections"
|
||||
:key="idx"
|
||||
class="d-flex flex-column ga-3"
|
||||
>
|
||||
<v-card-title class="text-h6 pl-0">
|
||||
{{ section.title }}
|
||||
</v-card-title>
|
||||
<div class="sections d-flex flex-column ga-2">
|
||||
<v-card
|
||||
v-for="link, linkIdx in section.links"
|
||||
:key="linkIdx"
|
||||
clas="link-card"
|
||||
:href="link.to"
|
||||
:title="link.text"
|
||||
:subtitle="link.description"
|
||||
:append-icon="$globals.icons.chevronRight"
|
||||
>
|
||||
<template #prepend>
|
||||
<v-avatar :icon="link.icon || undefined" variant="tonal" :color="section.color" />
|
||||
</template>
|
||||
</v-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineNuxtComponent({
|
||||
setup() {
|
||||
const i18n = useI18n();
|
||||
const $auth = useMealieAuth();
|
||||
const groupSlug = computed(() => $auth.user.value?.groupSlug);
|
||||
const { $globals } = useNuxtApp();
|
||||
|
||||
const sections = ref([
|
||||
{
|
||||
title: i18n.t("profile.data-migrations"),
|
||||
color: "info",
|
||||
links: [
|
||||
{
|
||||
icon: $globals.icons.backupRestore,
|
||||
to: "/admin/backups",
|
||||
text: i18n.t("settings.backup.backup-restore"),
|
||||
description: i18n.t("admin.setup.restore-from-v1-backup"),
|
||||
},
|
||||
{
|
||||
icon: $globals.icons.import,
|
||||
to: "/group/migrations",
|
||||
text: i18n.t("migration.recipe-migration"),
|
||||
description: i18n.t("migration.coming-from-another-application-or-an-even-older-version-of-mealie"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18n.t("recipe.create-recipes"),
|
||||
color: "success",
|
||||
links: [
|
||||
{
|
||||
icon: $globals.icons.createAlt,
|
||||
to: computed(() => `/g/${groupSlug.value || ""}/r/create/new`),
|
||||
text: i18n.t("recipe.create-recipe"),
|
||||
description: i18n.t("recipe.create-recipe-description"),
|
||||
},
|
||||
{
|
||||
icon: $globals.icons.link,
|
||||
to: computed(() => `/g/${groupSlug.value || ""}/r/create/url`),
|
||||
text: i18n.t("recipe.import-with-url"),
|
||||
description: i18n.t("recipe.scrape-recipe-description"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18n.t("user.manage-users"),
|
||||
color: "primary",
|
||||
links: [
|
||||
{
|
||||
icon: $globals.icons.group,
|
||||
to: "/admin/manage/users",
|
||||
text: i18n.t("user.manage-users"),
|
||||
description: i18n.t("user.manage-users-description"),
|
||||
},
|
||||
{
|
||||
icon: $globals.icons.user,
|
||||
to: "/user/profile",
|
||||
text: i18n.t("profile.manage-user-profile"),
|
||||
description: i18n.t("admin.setup.manage-profile-or-get-invite-link"),
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
return { sections };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.v-container {
|
||||
.v-card-title,
|
||||
.v-card-subtitle {
|
||||
padding: 0;
|
||||
white-space: unset;
|
||||
}
|
||||
|
||||
.v-card-item {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -83,6 +83,11 @@ const fieldDefs: FieldDefinition[] = [
|
||||
label: i18n.t("household.households"),
|
||||
type: Organizer.Household,
|
||||
},
|
||||
{
|
||||
name: "user_id",
|
||||
label: i18n.t("user.users"),
|
||||
type: Organizer.User,
|
||||
},
|
||||
{
|
||||
name: "created_at",
|
||||
label: i18n.t("general.date-created"),
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<BaseButton
|
||||
download
|
||||
size="small"
|
||||
:download-url="`/api/recipes/bulk-actions/export/download?path=${item.path}`"
|
||||
:download-url="`/api/recipes/bulk-actions/export/${item.id}/download`"
|
||||
/>
|
||||
</template>
|
||||
</v-data-table>
|
||||
|
||||
@@ -58,6 +58,9 @@ const MEAL_TYPE_OPTIONS = [
|
||||
{ title: i18n.t("meal-plan.lunch"), value: "lunch" },
|
||||
{ title: i18n.t("meal-plan.dinner"), value: "dinner" },
|
||||
{ title: i18n.t("meal-plan.side"), value: "side" },
|
||||
{ title: i18n.t("meal-plan.snack"), value: "snack" },
|
||||
{ title: i18n.t("meal-plan.drink"), value: "drink" },
|
||||
{ title: i18n.t("meal-plan.dessert"), value: "dessert" },
|
||||
{ title: i18n.t("meal-plan.type-any"), value: "unset" },
|
||||
];
|
||||
|
||||
@@ -103,6 +106,11 @@ const fieldDefs: FieldDefinition[] = [
|
||||
label: i18n.t("household.households"),
|
||||
type: Organizer.Household,
|
||||
},
|
||||
{
|
||||
name: "user_id",
|
||||
label: i18n.t("user.users"),
|
||||
type: Organizer.User,
|
||||
},
|
||||
{
|
||||
name: "last_made",
|
||||
label: i18n.t("general.last-made"),
|
||||
|
||||
@@ -1,283 +1,299 @@
|
||||
<template>
|
||||
<v-card class="ma-0" style="overflow-x: auto;">
|
||||
<v-card class="ma-0" flat fluid>
|
||||
<v-card-text class="ma-0 pa-0">
|
||||
<v-container fluid class="ma-0 pa-0">
|
||||
<VueDraggable
|
||||
v-model="fields"
|
||||
handle=".handle"
|
||||
:delay="250"
|
||||
:delay-on-touch-only="true"
|
||||
v-bind="{
|
||||
animation: 200,
|
||||
group: 'recipe-instructions',
|
||||
ghostClass: 'ghost',
|
||||
}"
|
||||
@start="drag = true"
|
||||
@end="onDragEnd"
|
||||
<VueDraggable
|
||||
v-model="fields"
|
||||
handle=".handle"
|
||||
:delay="250"
|
||||
:delay-on-touch-only="true"
|
||||
v-bind="{
|
||||
animation: 200,
|
||||
group: 'recipe-instructions',
|
||||
ghostClass: 'ghost',
|
||||
}"
|
||||
@start="drag = true"
|
||||
@end="onDragEnd"
|
||||
>
|
||||
<v-row
|
||||
v-for="(field, index) in fields"
|
||||
:key="field.id"
|
||||
class="d-flex flex-row flex-wrap mx-auto pb-2"
|
||||
:class="$vuetify.display.xs ? (Math.floor(index / 1) % 2 === 0 ? 'bg-dark' : 'bg-light') : ''"
|
||||
style="max-width: 100%;"
|
||||
>
|
||||
<v-row
|
||||
v-for="(field, index) in fields"
|
||||
:key="field.id"
|
||||
class="d-flex flex-nowrap"
|
||||
style="max-width: 100%;"
|
||||
<!-- drag handle -->
|
||||
<v-col
|
||||
:cols="config.items.icon.cols(index)"
|
||||
:sm="config.items.icon.sm(index)"
|
||||
:class="$vuetify.display.smAndDown ? 'd-flex pa-0' : 'd-flex justify-end pr-6'"
|
||||
>
|
||||
<!-- drag handle -->
|
||||
<v-col
|
||||
:cols="config.items.icon.cols"
|
||||
:class="config.col.class"
|
||||
:style="config.items.icon.style"
|
||||
<v-icon class="handle my-auto" :size="28" style="cursor: move;">
|
||||
{{ $globals.icons.arrowUpDown }}
|
||||
</v-icon>
|
||||
</v-col>
|
||||
|
||||
<!-- and / or -->
|
||||
<v-col
|
||||
v-if="index != 0 || $vuetify.display.smAndUp"
|
||||
:cols="config.items.logicalOperator.cols(index)"
|
||||
:sm="config.items.logicalOperator.sm(index)"
|
||||
:class="config.col.class"
|
||||
>
|
||||
<v-select
|
||||
v-if="index"
|
||||
:model-value="field.logicalOperator"
|
||||
:items="[logOps.AND, logOps.OR]"
|
||||
item-title="label"
|
||||
item-value="value"
|
||||
variant="underlined"
|
||||
@update:model-value="setLogicalOperatorValue(field, index, $event as unknown as LogicalOperator)"
|
||||
>
|
||||
<v-icon
|
||||
class="handle"
|
||||
:size="24"
|
||||
style="cursor: move;margin: auto;"
|
||||
>
|
||||
{{ $globals.icons.arrowUpDown }}
|
||||
</v-icon>
|
||||
</v-col>
|
||||
<!-- and / or -->
|
||||
<v-col
|
||||
:cols="config.items.logicalOperator.cols"
|
||||
:class="config.col.class"
|
||||
:style="config.items.logicalOperator.style"
|
||||
<template #chip="{ item }">
|
||||
<span :class="config.select.textClass" style="width: 100%;">
|
||||
{{ item.raw.label }}
|
||||
</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-col>
|
||||
|
||||
<!-- left parenthesis -->
|
||||
<v-col
|
||||
v-if="showAdvanced"
|
||||
:cols="config.items.leftParens.cols(index)"
|
||||
:sm="config.items.leftParens.sm(index)"
|
||||
:class="config.col.class"
|
||||
>
|
||||
<v-select
|
||||
:model-value="field.leftParenthesis"
|
||||
:items="['', '(', '((', '(((']"
|
||||
variant="underlined"
|
||||
@update:model-value="setLeftParenthesisValue(field, index, $event)"
|
||||
>
|
||||
<v-select
|
||||
v-if="index"
|
||||
:model-value="field.logicalOperator"
|
||||
:items="[logOps.AND, logOps.OR]"
|
||||
item-title="label"
|
||||
item-value="value"
|
||||
variant="underlined"
|
||||
@update:model-value="setLogicalOperatorValue(field, index, $event as unknown as LogicalOperator)"
|
||||
>
|
||||
<template #chip="{ item }">
|
||||
<span :class="config.select.textClass" style="width: 100%;">
|
||||
{{ item.raw.label }}
|
||||
</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-col>
|
||||
<!-- left parenthesis -->
|
||||
<v-col
|
||||
v-if="showAdvanced"
|
||||
:cols="config.items.leftParens.cols"
|
||||
:class="config.col.class"
|
||||
:style="config.items.leftParens.style"
|
||||
<template #chip="{ item }">
|
||||
<span :class="config.select.textClass" style="width: 100%;">
|
||||
{{ item.raw }}
|
||||
</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-col>
|
||||
|
||||
<!-- field name -->
|
||||
<v-col
|
||||
:cols="config.items.fieldName.cols(index)"
|
||||
:sm="config.items.fieldName.sm(index)"
|
||||
:class="config.col.class"
|
||||
>
|
||||
<v-select
|
||||
chips
|
||||
:model-value="field.label"
|
||||
:items="fieldDefs"
|
||||
variant="underlined"
|
||||
item-title="label"
|
||||
@update:model-value="setField(index, $event)"
|
||||
>
|
||||
<v-select
|
||||
:model-value="field.leftParenthesis"
|
||||
:items="['', '(', '((', '(((']"
|
||||
variant="underlined"
|
||||
@update:model-value="setLeftParenthesisValue(field, index, $event)"
|
||||
>
|
||||
<template #chip="{ item }">
|
||||
<span :class="config.select.textClass" style="width: 100%;">
|
||||
{{ item.raw }}
|
||||
</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-col>
|
||||
<!-- field name -->
|
||||
<v-col
|
||||
:cols="config.items.fieldName.cols"
|
||||
:class="config.col.class"
|
||||
:style="config.items.fieldName.style"
|
||||
<template #chip="{ item }">
|
||||
<span :class="config.select.textClass" style="width: 100%;">
|
||||
{{ item.raw.label }}
|
||||
</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-col>
|
||||
|
||||
<!-- relational operator -->
|
||||
<v-col
|
||||
:cols="config.items.relationalOperator.cols(index)"
|
||||
:sm="config.items.relationalOperator.sm(index)"
|
||||
:class="config.col.class"
|
||||
>
|
||||
<v-select
|
||||
v-if="field.type !== 'boolean'"
|
||||
:model-value="field.relationalOperatorValue"
|
||||
:items="field.relationalOperatorOptions"
|
||||
item-title="label"
|
||||
item-value="value"
|
||||
variant="underlined"
|
||||
@update:model-value="setRelationalOperatorValue(field, index, $event as unknown as RelationalKeyword | RelationalOperator)"
|
||||
>
|
||||
<v-select
|
||||
chips
|
||||
:model-value="field.label"
|
||||
:items="fieldDefs"
|
||||
variant="underlined"
|
||||
item-title="label"
|
||||
@update:model-value="setField(index, $event)"
|
||||
>
|
||||
<template #chip="{ item }">
|
||||
<span :class="config.select.textClass" style="width: 100%;">
|
||||
{{ item.raw.label }}
|
||||
</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-col>
|
||||
<!-- relational operator -->
|
||||
<v-col
|
||||
:cols="config.items.relationalOperator.cols"
|
||||
:class="config.col.class"
|
||||
:style="config.items.relationalOperator.style"
|
||||
<template #chip="{ item }">
|
||||
<span :class="config.select.textClass" style="width: 100%;">
|
||||
{{ item.raw.label }}
|
||||
</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-col>
|
||||
|
||||
<!-- field value -->
|
||||
<v-col
|
||||
:cols="config.items.fieldValue.cols(index)"
|
||||
:sm="config.items.fieldValue.sm(index)"
|
||||
:class="config.col.class"
|
||||
>
|
||||
<v-select
|
||||
v-if="field.fieldOptions"
|
||||
:model-value="field.values"
|
||||
:items="field.fieldOptions"
|
||||
item-title="label"
|
||||
item-value="value"
|
||||
multiple
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldValues(field, index, $event)"
|
||||
/>
|
||||
<v-text-field
|
||||
v-else-if="field.type === 'string'"
|
||||
:model-value="field.value"
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldValue(field, index, $event)"
|
||||
/>
|
||||
<v-number-input
|
||||
v-else-if="field.type === 'number'"
|
||||
:model-value="field.value"
|
||||
variant="underlined"
|
||||
control-variant="stacked"
|
||||
inset
|
||||
:precision="null"
|
||||
@update:model-value="setFieldValue(field, index, $event)"
|
||||
/>
|
||||
<v-checkbox
|
||||
v-else-if="field.type === 'boolean'"
|
||||
:model-value="field.value"
|
||||
@update:model-value="setFieldValue(field, index, $event!)"
|
||||
/>
|
||||
<v-menu
|
||||
v-else-if="field.type === 'date'"
|
||||
v-model="datePickers[index]"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
max-width="290px"
|
||||
min-width="auto"
|
||||
>
|
||||
<v-select
|
||||
v-if="field.type !== 'boolean'"
|
||||
:model-value="field.relationalOperatorValue"
|
||||
:items="field.relationalOperatorOptions"
|
||||
item-title="label"
|
||||
item-value="value"
|
||||
variant="underlined"
|
||||
@update:model-value="setRelationalOperatorValue(field, index, $event as unknown as RelationalKeyword | RelationalOperator)"
|
||||
>
|
||||
<template #chip="{ item }">
|
||||
<span :class="config.select.textClass" style="width: 100%;">
|
||||
{{ item.raw.label }}
|
||||
</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-col>
|
||||
<!-- field value -->
|
||||
<v-col
|
||||
:cols="config.items.fieldValue.cols"
|
||||
:class="config.col.class"
|
||||
:style="config.items.fieldValue.style"
|
||||
>
|
||||
<v-select
|
||||
v-if="field.fieldOptions"
|
||||
:model-value="field.values"
|
||||
:items="field.fieldOptions"
|
||||
item-title="label"
|
||||
item-value="value"
|
||||
multiple
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldValues(field, index, $event)"
|
||||
/>
|
||||
<v-text-field
|
||||
v-else-if="field.type === 'string'"
|
||||
:model-value="field.value"
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldValue(field, index, $event)"
|
||||
/>
|
||||
<v-text-field
|
||||
v-else-if="field.type === 'number'"
|
||||
:model-value="field.value"
|
||||
type="number"
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldValue(field, index, $event)"
|
||||
/>
|
||||
<v-checkbox
|
||||
v-else-if="field.type === 'boolean'"
|
||||
:model-value="field.value"
|
||||
@update:model-value="setFieldValue(field, index, $event!)"
|
||||
/>
|
||||
<v-menu
|
||||
v-else-if="field.type === 'date'"
|
||||
v-model="datePickers[index]"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
max-width="290px"
|
||||
min-width="auto"
|
||||
>
|
||||
<template #activator="{ props: activatorProps }">
|
||||
<v-text-field
|
||||
:model-value="field.value ? $d(new Date(field.value + 'T00:00:00')) : null"
|
||||
persistent-hint
|
||||
:prepend-icon="$globals.icons.calendar"
|
||||
variant="underlined"
|
||||
color="primary"
|
||||
v-bind="activatorProps"
|
||||
readonly
|
||||
/>
|
||||
</template>
|
||||
<v-date-picker
|
||||
:model-value="field.value ? new Date(field.value + 'T00:00:00') : null"
|
||||
hide-header
|
||||
:first-day-of-week="firstDayOfWeek"
|
||||
:local="$i18n.locale"
|
||||
@update:model-value="val => setFieldValue(field, index, val ? val.toISOString().slice(0, 10) : '')"
|
||||
<template #activator="{ props: activatorProps }">
|
||||
<v-text-field
|
||||
:model-value="field.value ? $d(new Date(field.value + 'T00:00:00')) : null"
|
||||
persistent-hint
|
||||
:prepend-icon="$globals.icons.calendar"
|
||||
variant="underlined"
|
||||
color="primary"
|
||||
v-bind="activatorProps"
|
||||
readonly
|
||||
/>
|
||||
</v-menu>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.Category"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.Category"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldOrganizers(field, index, $event)"
|
||||
</template>
|
||||
<v-date-picker
|
||||
:model-value="field.value ? new Date(field.value + 'T00:00:00') : null"
|
||||
hide-header
|
||||
:first-day-of-week="firstDayOfWeek"
|
||||
:local="$i18n.locale"
|
||||
@update:model-value="val => setFieldValue(field, index, val ? val.toISOString().slice(0, 10) : '')"
|
||||
/>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.Tag"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.Tag"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldOrganizers(field, index, $event)"
|
||||
/>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.Tool"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.Tool"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldOrganizers(field, index, $event)"
|
||||
/>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.Food"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.Food"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldOrganizers(field, index, $event)"
|
||||
/>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.Household"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.Household"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="setFieldOrganizers(field, index, $event)"
|
||||
/>
|
||||
</v-col>
|
||||
<!-- right parenthesis -->
|
||||
<v-col
|
||||
v-if="showAdvanced"
|
||||
:cols="config.items.rightParens.cols"
|
||||
:class="config.col.class"
|
||||
:style="config.items.rightParens.style"
|
||||
</v-menu>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.Category"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.Category"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="val => setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
|
||||
/>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.Tag"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.Tag"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="val => setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
|
||||
/>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.Tool"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.Tool"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="val => setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
|
||||
/>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.Food"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.Food"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="val => setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
|
||||
/>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.Household"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.Household"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="val => setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
|
||||
/>
|
||||
<RecipeOrganizerSelector
|
||||
v-else-if="field.type === Organizer.User"
|
||||
v-model="field.organizers"
|
||||
:selector-type="Organizer.User"
|
||||
:show-add="false"
|
||||
:show-label="false"
|
||||
:show-icon="false"
|
||||
variant="underlined"
|
||||
@update:model-value="val => setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<!-- right parenthesis -->
|
||||
<v-col
|
||||
v-if="showAdvanced"
|
||||
:cols="config.items.rightParens.cols(index)"
|
||||
:sm="config.items.rightParens.sm(index)"
|
||||
:class="config.col.class"
|
||||
>
|
||||
<v-select
|
||||
:model-value="field.rightParenthesis"
|
||||
:items="['', ')', '))', ')))']"
|
||||
variant="underlined"
|
||||
@update:model-value="setRightParenthesisValue(field, index, $event)"
|
||||
>
|
||||
<v-select
|
||||
:model-value="field.rightParenthesis"
|
||||
:items="['', ')', '))', ')))']"
|
||||
variant="underlined"
|
||||
@update:model-value="setRightParenthesisValue(field, index, $event)"
|
||||
>
|
||||
<template #chip="{ item }">
|
||||
<span :class="config.select.textClass" style="width: 100%;">
|
||||
{{ item.raw }}
|
||||
</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-col>
|
||||
<!-- field actions -->
|
||||
<v-col
|
||||
:cols="config.items.fieldActions.cols"
|
||||
:class="config.col.class"
|
||||
:style="config.items.fieldActions.style"
|
||||
>
|
||||
<BaseButtonGroup
|
||||
:buttons="[
|
||||
{
|
||||
icon: $globals.icons.delete,
|
||||
text: $t('general.delete'),
|
||||
event: 'delete',
|
||||
disabled: fields.length === 1,
|
||||
},
|
||||
]"
|
||||
class="my-auto"
|
||||
@delete="removeField(index)"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</VueDraggable>
|
||||
</v-container>
|
||||
<template #chip="{ item }">
|
||||
<span :class="config.select.textClass" style="width: 100%;">
|
||||
{{ item.raw }}
|
||||
</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-col>
|
||||
|
||||
<!-- field actions -->
|
||||
<v-col
|
||||
v-if="!$vuetify.display.smAndDown || index === fields.length - 1"
|
||||
:cols="config.items.fieldActions.cols(index)"
|
||||
:sm="config.items.fieldActions.sm(index)"
|
||||
:class="config.col.class"
|
||||
>
|
||||
<BaseButtonGroup
|
||||
:buttons="[
|
||||
{
|
||||
icon: $globals.icons.delete,
|
||||
text: $t('general.delete'),
|
||||
event: 'delete',
|
||||
disabled: fields.length === 1,
|
||||
},
|
||||
]"
|
||||
class="my-auto"
|
||||
@delete="removeField(index)"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</VueDraggable>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-row fluid class="d-flex justify-end pa-0 mx-2">
|
||||
<v-row fluid class="d-flex justify-end ma-2">
|
||||
<v-spacer />
|
||||
<v-checkbox
|
||||
v-model="showAdvanced"
|
||||
@@ -305,6 +321,7 @@ import RecipeOrganizerSelector from "~/components/Domain/Recipe/RecipeOrganizerS
|
||||
import { Organizer } from "~/lib/api/types/non-generated";
|
||||
import type { LogicalOperator, QueryFilterJSON, QueryFilterJSONPart, RelationalKeyword, RelationalOperator } from "~/lib/api/types/response";
|
||||
import { useCategoryStore, useFoodStore, useHouseholdStore, useTagStore, useToolStore } from "~/composables/store";
|
||||
import { useUserStore } from "~/composables/store/use-user-store";
|
||||
import { type Field, type FieldDefinition, type FieldValue, type OrganizerBase, useQueryFilterBuilder } from "~/composables/use-query-filter-builder";
|
||||
|
||||
const props = defineProps({
|
||||
@@ -344,6 +361,7 @@ const storeMap = {
|
||||
[Organizer.Tool]: useToolStore(),
|
||||
[Organizer.Food]: useFoodStore(),
|
||||
[Organizer.Household]: useHouseholdStore(),
|
||||
[Organizer.User]: useUserStore(),
|
||||
};
|
||||
|
||||
function onDragEnd(event: any) {
|
||||
@@ -602,46 +620,56 @@ function buildQueryFilterJSON(): QueryFilterJSON {
|
||||
}
|
||||
|
||||
const config = computed(() => {
|
||||
const baseColMaxWidth = 55;
|
||||
const multiple = fields.value.length > 1;
|
||||
const adv = state.showAdvanced;
|
||||
|
||||
return {
|
||||
col: {
|
||||
class: "d-flex justify-center align-end field-col pa-1",
|
||||
class: "d-flex justify-center align-end py-0",
|
||||
},
|
||||
select: {
|
||||
textClass: "d-flex justify-center text-center",
|
||||
},
|
||||
items: {
|
||||
icon: {
|
||||
cols: 1,
|
||||
cols: (_index: number) => 2,
|
||||
sm: (_index: number) => 1,
|
||||
style: "width: fit-content;",
|
||||
},
|
||||
leftParens: {
|
||||
cols: state.showAdvanced ? 1 : 0,
|
||||
style: `min-width: ${state.showAdvanced ? baseColMaxWidth : 0}px;`,
|
||||
cols: (index: number) => (adv ? (index === 0 ? 2 : 0) : 0),
|
||||
sm: (_index: number) => (adv ? 1 : 0),
|
||||
},
|
||||
logicalOperator: {
|
||||
cols: 1,
|
||||
style: `min-width: ${baseColMaxWidth}px;`,
|
||||
cols: (_index: number) => 0,
|
||||
sm: (_index: number) => (multiple ? 1 : 0),
|
||||
},
|
||||
fieldName: {
|
||||
cols: state.showAdvanced ? 2 : 3,
|
||||
style: `min-width: ${state.showAdvanced ? baseColMaxWidth * 2 : baseColMaxWidth * 3}px;`,
|
||||
cols: (index: number) => {
|
||||
if (adv) return index === 0 ? 8 : 12;
|
||||
return index === 0 ? 10 : 12;
|
||||
},
|
||||
sm: (_index: number) => (adv ? 2 : 3),
|
||||
},
|
||||
relationalOperator: {
|
||||
cols: 2,
|
||||
style: `min-width: ${baseColMaxWidth * 2}px;`,
|
||||
cols: (_index: number) => 12,
|
||||
sm: (_index: number) => 2,
|
||||
},
|
||||
fieldValue: {
|
||||
cols: state.showAdvanced ? 3 : 4,
|
||||
style: `min-width: ${state.showAdvanced ? baseColMaxWidth * 2 : baseColMaxWidth * 3}px;`,
|
||||
cols: (index: number) => {
|
||||
const last = index === fields.value.length - 1;
|
||||
if (adv) return last ? 8 : 10;
|
||||
return last ? 10 : 12;
|
||||
},
|
||||
sm: (_index: number) => (adv ? 3 : 4),
|
||||
},
|
||||
rightParens: {
|
||||
cols: state.showAdvanced ? 1 : 0,
|
||||
style: `min-width: ${state.showAdvanced ? baseColMaxWidth : 0}px;`,
|
||||
cols: (index: number) => (adv ? (index === fields.value.length - 1 ? 2 : 0) : 0),
|
||||
sm: (_index: number) => (adv ? 1 : 0),
|
||||
},
|
||||
fieldActions: {
|
||||
cols: 1,
|
||||
style: `min-width: ${baseColMaxWidth}px;`,
|
||||
cols: (index: number) => (index === fields.value.length - 1 ? 2 : 0),
|
||||
sm: (_index: number) => 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -651,5 +679,14 @@ const config = computed(() => {
|
||||
<style scoped>
|
||||
* {
|
||||
font-size: 1em;
|
||||
--bg-opactity: calc(var(--v-hover-opacity) * var(--v-theme-overlay-multiplier));
|
||||
}
|
||||
|
||||
.bg-dark {
|
||||
background-color: rgba(0, 0, 0, var(--bg-opactity));
|
||||
}
|
||||
|
||||
.bg-light {
|
||||
background-color: rgba(255, 255, 255, var(--bg-opactity));
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -126,7 +126,7 @@ withDefaults(defineProps<Props>(), {
|
||||
canEdit: false,
|
||||
});
|
||||
|
||||
const emit = defineEmits(["print", "input", "delete", "close", "edit"]);
|
||||
const emit = defineEmits(["print", "input", "save", "delete", "close", "json", "edit"]);
|
||||
|
||||
const deleteDialog = ref(false);
|
||||
|
||||
|
||||
@@ -28,11 +28,12 @@
|
||||
<v-list-item-title class="pl-2">
|
||||
{{ item.name }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-action>
|
||||
<template #append>
|
||||
<v-btn
|
||||
v-if="!edit"
|
||||
color="primary"
|
||||
icon
|
||||
size="small"
|
||||
:href="assetURL(item.fileName ?? '')"
|
||||
target="_blank"
|
||||
top
|
||||
@@ -43,6 +44,7 @@
|
||||
<v-btn
|
||||
color="error"
|
||||
icon
|
||||
size="small"
|
||||
top
|
||||
@click="model.splice(i, 1)"
|
||||
>
|
||||
@@ -53,7 +55,7 @@
|
||||
:copy-text="assetEmbed(item.fileName ?? '')"
|
||||
/>
|
||||
</div>
|
||||
</v-list-item-action>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-card>
|
||||
@@ -90,13 +92,12 @@
|
||||
item-value="name"
|
||||
class="mr-2"
|
||||
>
|
||||
<template #item="{ item }">
|
||||
<v-avatar>
|
||||
<v-icon class="mr-auto">
|
||||
{{ item.raw.icon }}
|
||||
</v-icon>
|
||||
</v-avatar>
|
||||
{{ item.title }}
|
||||
<template #item="{ item, props: itemProps }">
|
||||
<v-list-item v-bind="itemProps">
|
||||
<template #prepend>
|
||||
<v-icon>{{ item.raw.icon }}</v-icon>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</template>
|
||||
</v-select>
|
||||
<AppButtonUpload
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
@click.self="$emit('click')"
|
||||
>
|
||||
<RecipeCardImage
|
||||
small
|
||||
:icon-size="imageHeight"
|
||||
:height="imageHeight"
|
||||
:slug="slug"
|
||||
:recipe-id="recipeId"
|
||||
size="small"
|
||||
:image-version="image"
|
||||
>
|
||||
<v-expand-transition v-if="description">
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
cover
|
||||
>
|
||||
<RecipeCardImage
|
||||
tiny
|
||||
:icon-size="100"
|
||||
:slug="slug"
|
||||
:recipe-id="recipeId"
|
||||
size="small"
|
||||
:image-version="image"
|
||||
:height="height"
|
||||
/>
|
||||
@@ -41,11 +41,11 @@
|
||||
name="avatar"
|
||||
>
|
||||
<RecipeCardImage
|
||||
tiny
|
||||
:icon-size="100"
|
||||
:slug="slug"
|
||||
:recipe-id="recipeId"
|
||||
:image-version="image"
|
||||
size="small"
|
||||
width="125"
|
||||
:height="height"
|
||||
/>
|
||||
|
||||
@@ -90,6 +90,14 @@
|
||||
<v-list-item-title>{{ $t("general.last-made") }}</v-list-item-title>
|
||||
</div>
|
||||
</v-list-item>
|
||||
<v-list-item @click="sortRecipes(EVENTS.shuffle)">
|
||||
<div class="d-flex align-center flex-nowrap">
|
||||
<v-icon class="mr-2" inline>
|
||||
{{ $globals.icons.diceMultiple }}
|
||||
</v-icon>
|
||||
<v-list-item-title>{{ $t("general.random") }}</v-list-item-title>
|
||||
</div>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<ContextMenu
|
||||
@@ -223,6 +231,7 @@ const displayTitleIcon = computed(() => {
|
||||
});
|
||||
|
||||
const sortLoading = ref(false);
|
||||
const randomSeed = ref(Date.now().toString());
|
||||
|
||||
const route = useRoute();
|
||||
const groupSlug = computed(() => route.params.groupSlug as string || $auth.user.value?.groupSlug || "");
|
||||
@@ -256,13 +265,18 @@ const queryFilter = computed(() => {
|
||||
async function fetchRecipes(pageCount = 1) {
|
||||
const orderDir = props.query?.orderDirection || preferences.value.orderDirection;
|
||||
const orderByNullPosition = props.query?.orderByNullPosition || orderDir === "asc" ? "first" : "last";
|
||||
const orderBy = props.query?.orderBy || preferences.value.orderBy;
|
||||
const localQuery = { ...props.query };
|
||||
if (orderBy === "random") {
|
||||
localQuery._searchSeed = randomSeed.value;
|
||||
}
|
||||
return await fetchMore(
|
||||
page.value,
|
||||
perPage * pageCount,
|
||||
props.query?.orderBy || preferences.value.orderBy,
|
||||
orderBy,
|
||||
orderDir,
|
||||
orderByNullPosition,
|
||||
props.query,
|
||||
localQuery,
|
||||
// we use a computed queryFilter to filter out recipes that have a null value for the property we're sorting by
|
||||
queryFilter.value,
|
||||
);
|
||||
@@ -288,6 +302,9 @@ watch(
|
||||
);
|
||||
|
||||
async function initRecipes() {
|
||||
if (preferences.value.orderBy === "random") {
|
||||
randomSeed.value = Date.now().toString();
|
||||
}
|
||||
page.value = 1;
|
||||
hasMore.value = true;
|
||||
|
||||
@@ -380,6 +397,15 @@ async function sortRecipes(sortType: string) {
|
||||
true,
|
||||
);
|
||||
break;
|
||||
case EVENTS.shuffle:
|
||||
setter(
|
||||
"random",
|
||||
$globals.icons.diceMultiple,
|
||||
$globals.icons.diceMultiple, // icon in asc and desc is the same for random
|
||||
);
|
||||
// We update the seed value to have a different order
|
||||
randomSeed.value = Date.now().toString();
|
||||
break;
|
||||
default:
|
||||
console.log("Unknown Event", sortType);
|
||||
return;
|
||||
|
||||
@@ -45,31 +45,15 @@
|
||||
@confirm="addRecipeToPlan()"
|
||||
>
|
||||
<v-card-text>
|
||||
<v-menu
|
||||
v-model="pickerMenu"
|
||||
:close-on-content-click="false"
|
||||
transition="scale-transition"
|
||||
offset-y
|
||||
max-width="290px"
|
||||
min-width="auto"
|
||||
>
|
||||
<template #activator="{ props: activatorProps }">
|
||||
<v-text-field
|
||||
:model-value="$d(newMealdate)"
|
||||
:label="$t('general.date')"
|
||||
:prepend-icon="$globals.icons.calendar"
|
||||
v-bind="activatorProps"
|
||||
readonly
|
||||
/>
|
||||
</template>
|
||||
<v-date-picker
|
||||
v-model="newMealdate"
|
||||
hide-header
|
||||
:first-day-of-week="firstDayOfWeek"
|
||||
:local="$i18n.locale"
|
||||
@update:model-value="pickerMenu = false"
|
||||
/>
|
||||
</v-menu>
|
||||
<v-date-picker
|
||||
v-model="newMealdate"
|
||||
class="mx-auto mb-3"
|
||||
hide-header
|
||||
show-adjacent-months
|
||||
color="primary"
|
||||
:first-day-of-week="firstDayOfWeek"
|
||||
:local="$i18n.locale"
|
||||
/>
|
||||
<v-select
|
||||
v-model="newMealType"
|
||||
:return-object="false"
|
||||
@@ -207,7 +191,6 @@ const loading = ref(false);
|
||||
const menuItems = ref<ContextMenuItem[]>([]);
|
||||
const newMealdate = ref(new Date());
|
||||
const newMealType = ref<PlanEntryType>("dinner");
|
||||
const pickerMenu = ref(false);
|
||||
|
||||
const newMealdateString = computed(() => {
|
||||
// Format the date to YYYY-MM-DD in the same timezone as newMealdate
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
:title="$t('recipe.add-to-list')"
|
||||
:icon="$globals.icons.cartCheck"
|
||||
>
|
||||
<v-container v-if="!shoppingListChoices.length">
|
||||
<v-container v-if="!filteredShoppingLists.length">
|
||||
<BasePageTitle>
|
||||
<template #title>
|
||||
{{ $t('shopping-list.no-shopping-lists-found') }}
|
||||
@@ -15,7 +15,7 @@
|
||||
</v-container>
|
||||
<v-card-text>
|
||||
<v-card
|
||||
v-for="list in shoppingListChoices"
|
||||
v-for="list in filteredShoppingLists"
|
||||
:key="list.id"
|
||||
hover
|
||||
class="my-2 left-border"
|
||||
@@ -222,6 +222,10 @@ const api = useUserApi();
|
||||
const preferences = useShoppingListPreferences();
|
||||
const ready = ref(false);
|
||||
|
||||
// Capture values at initialization to avoid reactive updates
|
||||
const currentHouseholdSlug = ref("");
|
||||
const filteredShoppingLists = ref<ShoppingListSummary[]>([]);
|
||||
|
||||
const state = reactive({
|
||||
shoppingListDialog: true,
|
||||
shoppingListIngredientDialog: false,
|
||||
@@ -230,31 +234,25 @@ const state = reactive({
|
||||
|
||||
const { shoppingListDialog, shoppingListIngredientDialog, shoppingListShowAllToggled: _shoppingListShowAllToggled } = toRefs(state);
|
||||
|
||||
const userHousehold = computed(() => {
|
||||
return $auth.user.value?.householdSlug || "";
|
||||
});
|
||||
|
||||
const shoppingListChoices = computed(() => {
|
||||
return props.shoppingLists.filter(list => preferences.value.viewAllLists || list.userId === $auth.user.value?.id);
|
||||
});
|
||||
|
||||
const recipeIngredientSections = ref<ShoppingListRecipeIngredientSection[]>([]);
|
||||
const selectedShoppingList = ref<ShoppingListSummary | null>(null);
|
||||
|
||||
watchEffect(
|
||||
() => {
|
||||
if (shoppingListChoices.value.length === 1 && !state.shoppingListShowAllToggled) {
|
||||
selectedShoppingList.value = shoppingListChoices.value[0];
|
||||
watch(dialog, (newVal, oldVal) => {
|
||||
if (newVal && !oldVal) {
|
||||
currentHouseholdSlug.value = $auth.user.value?.householdSlug || "";
|
||||
filteredShoppingLists.value = props.shoppingLists.filter(
|
||||
list => preferences.value.viewAllLists || list.userId === $auth.user.value?.id,
|
||||
);
|
||||
|
||||
if (filteredShoppingLists.value.length === 1 && !state.shoppingListShowAllToggled) {
|
||||
selectedShoppingList.value = filteredShoppingLists.value[0];
|
||||
openShoppingListIngredientDialog(selectedShoppingList.value);
|
||||
}
|
||||
else {
|
||||
ready.value = true;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watch(dialog, (val) => {
|
||||
if (!val) {
|
||||
}
|
||||
else if (!newVal) {
|
||||
initState();
|
||||
}
|
||||
});
|
||||
@@ -274,22 +272,26 @@ async function consolidateRecipesIntoSections(recipes: RecipeWithScale[]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(recipe.id && recipe.name && recipe.recipeIngredient)) {
|
||||
const { data } = await api.recipes.getOne(recipe.slug);
|
||||
// Create a local copy to avoid mutating props
|
||||
let recipeData = { ...recipe };
|
||||
if (!(recipeData.id && recipeData.name && recipeData.recipeIngredient)) {
|
||||
const { data } = await api.recipes.getOne(recipeData.slug);
|
||||
if (!data?.recipeIngredient?.length) {
|
||||
continue;
|
||||
}
|
||||
recipe.id = data.id || "";
|
||||
recipe.name = data.name || "";
|
||||
recipe.recipeIngredient = data.recipeIngredient;
|
||||
recipeData = {
|
||||
...recipeData,
|
||||
id: data.id || "",
|
||||
name: data.name || "",
|
||||
recipeIngredient: data.recipeIngredient,
|
||||
};
|
||||
}
|
||||
else if (!recipe.recipeIngredient.length) {
|
||||
else if (!recipeData.recipeIngredient.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const shoppingListIngredients: ShoppingListIngredient[] = [];
|
||||
function flattenRecipeIngredients(ing: RecipeIngredient, parentTitle = ""): ShoppingListIngredient[] {
|
||||
const householdsWithFood = ing.food?.householdsWithIngredientFood || [];
|
||||
if (ing.referencedRecipe) {
|
||||
// Recursively flatten all ingredients in the referenced recipe
|
||||
return (ing.referencedRecipe.recipeIngredient ?? []).flatMap((subIng) => {
|
||||
@@ -303,8 +305,9 @@ async function consolidateRecipesIntoSections(recipes: RecipeWithScale[]) {
|
||||
}
|
||||
else {
|
||||
// Regular ingredient
|
||||
const householdsWithFood = ing.food?.householdsWithIngredientFood || [];
|
||||
return [{
|
||||
checked: !householdsWithFood.includes(userHousehold.value),
|
||||
checked: !householdsWithFood.includes(currentHouseholdSlug.value),
|
||||
ingredient: {
|
||||
...ing,
|
||||
title: ing.title || parentTitle,
|
||||
@@ -313,7 +316,7 @@ async function consolidateRecipesIntoSections(recipes: RecipeWithScale[]) {
|
||||
}
|
||||
}
|
||||
|
||||
recipe.recipeIngredient.forEach((ing) => {
|
||||
recipeData.recipeIngredient.forEach((ing) => {
|
||||
const flattened = flattenRecipeIngredients(ing, "");
|
||||
shoppingListIngredients.push(...flattened);
|
||||
});
|
||||
@@ -343,7 +346,7 @@ async function consolidateRecipesIntoSections(recipes: RecipeWithScale[]) {
|
||||
|
||||
// Store the on-hand ingredients for later
|
||||
const householdsWithFood = (ing.ingredient?.food?.householdsWithIngredientFood || []);
|
||||
if (householdsWithFood.includes(userHousehold.value)) {
|
||||
if (householdsWithFood.includes(currentHouseholdSlug.value)) {
|
||||
onHandIngs.push(ing);
|
||||
return sections;
|
||||
}
|
||||
@@ -357,9 +360,9 @@ async function consolidateRecipesIntoSections(recipes: RecipeWithScale[]) {
|
||||
shoppingListIngredientSections[shoppingListIngredientSections.length - 1].ingredients.push(...onHandIngs);
|
||||
|
||||
recipeSectionMap.set(recipe.slug, {
|
||||
recipeId: recipe.id,
|
||||
recipeName: recipe.name,
|
||||
recipeScale: recipe.scale,
|
||||
recipeId: recipeData.id,
|
||||
recipeName: recipeData.name,
|
||||
recipeScale: recipeData.scale,
|
||||
ingredientSections: shoppingListIngredientSections,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -101,4 +101,14 @@ const { store: tags } = isOwnGroup.value ? useTagStore() : usePublicTagStore(gro
|
||||
const { store: tools } = isOwnGroup.value ? useToolStore() : usePublicToolStore(groupSlug.value);
|
||||
const { store: foods } = isOwnGroup.value ? useFoodStore() : usePublicFoodStore(groupSlug.value);
|
||||
const { store: households } = isOwnGroup.value ? useHouseholdStore() : usePublicHouseholdStore(groupSlug.value);
|
||||
|
||||
watch(
|
||||
households,
|
||||
() => {
|
||||
// if exactly one household exists, then we shouldn't be filtering by household
|
||||
if (households.value.length == 1) {
|
||||
selectedHouseholds.value = [];
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
@@ -22,12 +22,15 @@
|
||||
cols="12"
|
||||
class="flex-grow-0 flex-shrink-0"
|
||||
>
|
||||
<v-text-field
|
||||
<v-number-input
|
||||
v-model="model.quantity"
|
||||
variant="solo"
|
||||
:precision="null"
|
||||
:min="0"
|
||||
hide-details
|
||||
control-variant="stacked"
|
||||
inset
|
||||
density="compact"
|
||||
type="number"
|
||||
:placeholder="$t('recipe.quantity')"
|
||||
@keypress="quantityFilter"
|
||||
>
|
||||
@@ -38,7 +41,7 @@
|
||||
{{ $globals.icons.arrowUpDown }}
|
||||
</v-icon>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</v-number-input>
|
||||
</v-col>
|
||||
<v-col
|
||||
v-if="!state.isRecipe"
|
||||
@@ -56,6 +59,7 @@
|
||||
variant="solo"
|
||||
return-object
|
||||
:items="units || []"
|
||||
:custom-filter="normalizeFilter"
|
||||
item-title="name"
|
||||
class="mx-1"
|
||||
:placeholder="$t('recipe.choose-unit')"
|
||||
@@ -114,6 +118,7 @@
|
||||
variant="solo"
|
||||
return-object
|
||||
:items="foods || []"
|
||||
:custom-filter="normalizeFilter"
|
||||
item-title="name"
|
||||
class="mx-1 py-0"
|
||||
:placeholder="$t('recipe.choose-food')"
|
||||
@@ -171,6 +176,7 @@
|
||||
variant="solo"
|
||||
return-object
|
||||
:items="search.data.value || []"
|
||||
:custom-filter="normalizeFilter"
|
||||
item-title="name"
|
||||
class="mx-1 py-0"
|
||||
:placeholder="$t('search.type-to-search')"
|
||||
@@ -225,6 +231,7 @@ import { ref, computed, reactive, toRefs } from "vue";
|
||||
import { useDisplay } from "vuetify";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useFoodStore, useFoodData, useUnitStore, useUnitData } from "~/composables/store";
|
||||
import { normalizeFilter } from "~/composables/use-utils";
|
||||
import { useNuxtApp } from "#app";
|
||||
import type { RecipeIngredient } from "~/lib/api/types/recipe";
|
||||
import { usePublicExploreApi, useUserApi } from "~/composables/api";
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
:title="$t('recipe.made-this')"
|
||||
:submit-text="$t('recipe.add-to-timeline')"
|
||||
can-submit
|
||||
disable-submit-on-enter
|
||||
@submit="createTimelineEvent"
|
||||
>
|
||||
<v-card-text>
|
||||
|
||||
@@ -10,14 +10,17 @@
|
||||
v-for="(item, key, index) in modelValue"
|
||||
:key="index"
|
||||
>
|
||||
<v-text-field
|
||||
density="compact"
|
||||
<v-number-input
|
||||
:model-value="modelValue[key]"
|
||||
:label="labels[key].label"
|
||||
:suffix="labels[key].suffix"
|
||||
type="number"
|
||||
density="compact"
|
||||
autocomplete="off"
|
||||
variant="underlined"
|
||||
control-variant="stacked"
|
||||
inset
|
||||
:precision="null"
|
||||
:min="0"
|
||||
@update:model-value="updateValue(key, $event)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -105,10 +105,9 @@
|
||||
<v-icon>
|
||||
{{ icon }}
|
||||
</v-icon>
|
||||
<v-card-title class="py-1">
|
||||
<v-card-title class="py-1 text-truncate flex-shrink-1 flex-grow-1">
|
||||
{{ item.name }}
|
||||
</v-card-title>
|
||||
<v-spacer />
|
||||
<ContextMenu
|
||||
:items="[presets.delete, presets.edit]"
|
||||
@delete="confirmDelete(item)"
|
||||
|
||||
@@ -4,17 +4,19 @@
|
||||
v-bind="inputAttrs"
|
||||
v-model:search="searchInput"
|
||||
:items="items"
|
||||
:custom-filter="normalizeFilter"
|
||||
:label="label"
|
||||
chips
|
||||
closable-chips
|
||||
item-title="name"
|
||||
:item-title="itemTitle"
|
||||
item-value="name"
|
||||
multiple
|
||||
:variant="variant"
|
||||
:prepend-inner-icon="icon"
|
||||
:append-icon="showAdd ? $globals.icons.create : undefined"
|
||||
return-object
|
||||
auto-select-first
|
||||
class="pa-0"
|
||||
class="pa-0 ma-0"
|
||||
@update:model-value="resetSearchInput"
|
||||
@click:append="dialog = true"
|
||||
>
|
||||
@@ -32,7 +34,6 @@
|
||||
{{ item.value }}
|
||||
</v-chip>
|
||||
</template>
|
||||
|
||||
<template
|
||||
v-if="showAdd"
|
||||
#append
|
||||
@@ -47,16 +48,17 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { IngredientFood, RecipeCategory, RecipeTag } from "~/lib/api/types/recipe";
|
||||
import type { RecipeTool } from "~/lib/api/types/admin";
|
||||
import type { IngredientFood, RecipeCategory, RecipeTag, RecipeTool } from "~/lib/api/types/recipe";
|
||||
import { Organizer, type RecipeOrganizer } from "~/lib/api/types/non-generated";
|
||||
import type { HouseholdSummary } from "~/lib/api/types/household";
|
||||
import { useCategoryStore, useFoodStore, useHouseholdStore, useTagStore, useToolStore } from "~/composables/store";
|
||||
import { useUserStore } from "~/composables/store/use-user-store";
|
||||
import { normalizeFilter } from "~/composables/use-utils";
|
||||
import type { UserSummary } from "~/lib/api/types/user";
|
||||
|
||||
interface Props {
|
||||
selectorType: RecipeOrganizer;
|
||||
inputAttrs?: Record<string, any>;
|
||||
returnObject?: boolean;
|
||||
showAdd?: boolean;
|
||||
showLabel?: boolean;
|
||||
showIcon?: boolean;
|
||||
@@ -65,7 +67,6 @@ interface Props {
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
inputAttrs: () => ({}),
|
||||
returnObject: true,
|
||||
showAdd: true,
|
||||
showLabel: true,
|
||||
showIcon: true,
|
||||
@@ -78,7 +79,7 @@ const selected = defineModel<(
|
||||
| RecipeCategory
|
||||
| RecipeTool
|
||||
| IngredientFood
|
||||
| string
|
||||
| UserSummary
|
||||
)[] | undefined>({ required: true });
|
||||
|
||||
onMounted(() => {
|
||||
@@ -106,6 +107,8 @@ const label = computed(() => {
|
||||
return i18n.t("general.foods");
|
||||
case Organizer.Household:
|
||||
return i18n.t("household.households");
|
||||
case Organizer.User:
|
||||
return i18n.t("user.users");
|
||||
default:
|
||||
return i18n.t("general.organizer");
|
||||
}
|
||||
@@ -127,11 +130,19 @@ const icon = computed(() => {
|
||||
return $globals.icons.foods;
|
||||
case Organizer.Household:
|
||||
return $globals.icons.household;
|
||||
case Organizer.User:
|
||||
return $globals.icons.user;
|
||||
default:
|
||||
return $globals.icons.tags;
|
||||
}
|
||||
});
|
||||
|
||||
const itemTitle = computed(() =>
|
||||
props.selectorType === Organizer.User
|
||||
? (i: any) => i?.fullName ?? i?.name ?? ""
|
||||
: "name",
|
||||
);
|
||||
|
||||
// ===========================================================================
|
||||
// Store & Items Setup
|
||||
|
||||
@@ -141,24 +152,24 @@ const storeMap = {
|
||||
[Organizer.Tool]: useToolStore(),
|
||||
[Organizer.Food]: useFoodStore(),
|
||||
[Organizer.Household]: useHouseholdStore(),
|
||||
[Organizer.User]: useUserStore(),
|
||||
};
|
||||
|
||||
const store = computed(() => {
|
||||
const activeStore = computed(() => {
|
||||
const { store } = storeMap[props.selectorType];
|
||||
return store.value;
|
||||
});
|
||||
|
||||
const items = computed(() => {
|
||||
if (!props.returnObject) {
|
||||
return store.value.map(item => item.name);
|
||||
}
|
||||
return store.value;
|
||||
const items = computed<any[]>(() => {
|
||||
const list = (activeStore.value as unknown as any[]) ?? [];
|
||||
return list;
|
||||
});
|
||||
|
||||
function removeByIndex(index: number) {
|
||||
if (selected.value === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newSelected = selected.value.filter((_, i) => i !== index);
|
||||
selected.value = [...newSelected];
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
v-show="isCookMode && !hasLinkedIngredients"
|
||||
key="cookmode"
|
||||
:height="$vuetify.display.smAndUp ? 'calc(100vh - 48px)' : 'auto'"
|
||||
className="overflow-hidden"
|
||||
class-name="overflow-hidden"
|
||||
>
|
||||
<!-- the calc is to account for the toolbar a more dynamic solution could be needed -->
|
||||
<v-row style="height: 100%" no-gutters class="overflow-hidden">
|
||||
|
||||
@@ -47,7 +47,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
landscape: false,
|
||||
});
|
||||
|
||||
defineEmits(["save", "delete"]);
|
||||
defineEmits(["save", "delete", "print"]);
|
||||
|
||||
const { recipeImage } = useStaticRoutes();
|
||||
const { imageKey, setMode, toggleEditMode, isEditMode } = usePageState(props.recipe.slug);
|
||||
|
||||
@@ -28,7 +28,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
});
|
||||
|
||||
const display = useDisplay();
|
||||
const { recipeImage } = useStaticRoutes();
|
||||
const { recipeImage, recipeSmallImage } = useStaticRoutes();
|
||||
const { imageKey } = usePageState(props.recipe.slug);
|
||||
const { user } = usePageUser();
|
||||
|
||||
@@ -46,7 +46,9 @@ const imageHeight = computed(() => {
|
||||
});
|
||||
|
||||
const recipeImageUrl = computed(() => {
|
||||
return recipeImage(props.recipe.id, props.recipe.image, imageKey.value);
|
||||
return display.smAndDown.value
|
||||
? recipeSmallImage(props.recipe.id, props.recipe.image, imageKey.value)
|
||||
: recipeImage(props.recipe.id, props.recipe.image, imageKey.value);
|
||||
});
|
||||
|
||||
watch(
|
||||
|
||||
@@ -11,27 +11,27 @@
|
||||
<v-container class="ma-0 pa-0">
|
||||
<v-row>
|
||||
<v-col cols="3">
|
||||
<v-text-field
|
||||
:model-value="recipeServings"
|
||||
type="number"
|
||||
<v-number-input
|
||||
:model-value="recipe.recipeServings"
|
||||
:min="0"
|
||||
hide-spin-buttons
|
||||
:precision="null"
|
||||
density="compact"
|
||||
:label="$t('recipe.servings')"
|
||||
variant="underlined"
|
||||
@update:model-value="validateInput($event, 'recipeServings')"
|
||||
control-variant="hidden"
|
||||
@update:model-value="recipe.recipeServings = $event"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="3">
|
||||
<v-text-field
|
||||
:model-value="recipeYieldQuantity"
|
||||
type="number"
|
||||
<v-number-input
|
||||
:model-value="recipe.recipeYieldQuantity"
|
||||
:min="0"
|
||||
hide-spin-buttons
|
||||
:precision="null"
|
||||
density="compact"
|
||||
:label="$t('recipe.yield')"
|
||||
variant="underlined"
|
||||
@update:model-value="validateInput($event, 'recipeYieldQuantity')"
|
||||
control-variant="hidden"
|
||||
@update:model-value="recipe.recipeYieldQuantity = $event"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
@@ -85,37 +85,4 @@ import type { NoUndefinedField } from "~/lib/api/types/non-generated";
|
||||
import type { Recipe } from "~/lib/api/types/recipe";
|
||||
|
||||
const recipe = defineModel<NoUndefinedField<Recipe>>({ required: true });
|
||||
|
||||
const recipeServings = computed<number>({
|
||||
get() {
|
||||
return recipe.value.recipeServings;
|
||||
},
|
||||
set(val) {
|
||||
validateInput(val.toString(), "recipeServings");
|
||||
},
|
||||
});
|
||||
|
||||
const recipeYieldQuantity = computed<number>({
|
||||
get() {
|
||||
return recipe.value.recipeYieldQuantity;
|
||||
},
|
||||
set(val) {
|
||||
validateInput(val.toString(), "recipeYieldQuantity");
|
||||
},
|
||||
});
|
||||
|
||||
function validateInput(value: string | null, property: "recipeServings" | "recipeYieldQuantity") {
|
||||
if (!value) {
|
||||
recipe.value[property] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const number = parseFloat(value.replace(/[^0-9.]/g, ""));
|
||||
if (isNaN(number) || number <= 0) {
|
||||
recipe.value[property] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
recipe.value[property] = number;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -196,7 +196,7 @@ import { VueDraggable } from "vue-draggable-plus";
|
||||
import type { IngredientFood, IngredientUnit, ParsedIngredient, RecipeIngredient } from "~/lib/api/types/recipe";
|
||||
import type { Parser } from "~/lib/api/user/recipes/recipe";
|
||||
import type { NoUndefinedField } from "~/lib/api/types/non-generated";
|
||||
import { useAppInfo, useUserApi } from "~/composables/api";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { parseIngredientText } from "~/composables/recipes";
|
||||
import { useFoodData, useFoodStore, useUnitData, useUnitStore } from "~/composables/store";
|
||||
import { useGlobalI18n } from "~/composables/use-global-i18n";
|
||||
@@ -213,9 +213,9 @@ const emit = defineEmits<{
|
||||
(e: "save", value: NoUndefinedField<RecipeIngredient[]>): void;
|
||||
}>();
|
||||
|
||||
const { $appInfo } = useNuxtApp();
|
||||
const i18n = useGlobalI18n();
|
||||
const api = useUserApi();
|
||||
const appInfo = useAppInfo();
|
||||
const drag = ref(false);
|
||||
|
||||
const unitStore = useUnitStore();
|
||||
@@ -238,7 +238,7 @@ const availableParsers = computed(() => {
|
||||
{
|
||||
text: i18n.t("recipe.parser.openai-parser"),
|
||||
value: "openai",
|
||||
hide: !appInfo.value?.enableOpenai,
|
||||
hide: !$appInfo.enableOpenai,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
@@ -65,13 +65,13 @@
|
||||
</v-card-title>
|
||||
<v-card-text class="mt-n5">
|
||||
<div class="mt-4 d-flex align-center">
|
||||
<v-text-field
|
||||
<v-number-input
|
||||
:model-value="yieldQuantity"
|
||||
type="number"
|
||||
:precision="null"
|
||||
:min="0"
|
||||
variant="underlined"
|
||||
hide-spin-buttons
|
||||
@update:model-value="recalculateScale(parseFloat($event) || 0)"
|
||||
control-variant="hidden"
|
||||
@update:model-value="recalculateScale($event || 0)"
|
||||
/>
|
||||
<v-tooltip
|
||||
location="end"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
:title="$t('recipe.edit-timeline-event')"
|
||||
:icon="$globals.icons.edit"
|
||||
can-submit
|
||||
disable-submit-on-enter
|
||||
:submit-text="$t('general.save')"
|
||||
@submit="submitEdit"
|
||||
>
|
||||
|
||||
@@ -119,7 +119,7 @@ defineEmits<{
|
||||
|
||||
const { $globals } = useNuxtApp();
|
||||
const display = useDisplay();
|
||||
const { recipeTimelineEventImage } = useStaticRoutes();
|
||||
const { recipeTimelineEventSmallImage } = useStaticRoutes();
|
||||
const { eventTypeOptions } = useTimelineEventTypes();
|
||||
|
||||
const { user: currentUser } = useMealieAuth();
|
||||
@@ -173,7 +173,7 @@ const eventImageUrl = computed<string>(() => {
|
||||
return "";
|
||||
}
|
||||
|
||||
return recipeTimelineEventImage(props.event.recipeId, props.event.id);
|
||||
return recipeTimelineEventSmallImage(props.event.recipeId, props.event.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
density="compact"
|
||||
class="mt-0 flex-shrink-0"
|
||||
color="null"
|
||||
@change="$emit('checked', listItem)"
|
||||
@click="() => {
|
||||
listItem.checked = !listItem.checked
|
||||
$emit('checked', listItem)
|
||||
}"
|
||||
/>
|
||||
<div
|
||||
class="ml-2 text-truncate"
|
||||
|
||||
@@ -4,7 +4,16 @@
|
||||
<v-card-text class="pb-3 pt-1">
|
||||
<div class="d-md-flex align-center mb-2" style="gap: 20px">
|
||||
<div>
|
||||
<InputQuantity v-model="listItem.quantity" />
|
||||
<v-number-input
|
||||
v-model="listItem.quantity"
|
||||
hide-details
|
||||
:label="$t('form.quantity-label-abbreviated')"
|
||||
:min="0"
|
||||
:precision="null"
|
||||
control-variant="stacked"
|
||||
inset
|
||||
style="width: 100px;"
|
||||
/>
|
||||
</div>
|
||||
<InputLabelType
|
||||
v-model="listItem.unit"
|
||||
@@ -158,6 +167,15 @@ export default defineNuxtComponent({
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.modelValue.quantity,
|
||||
() => {
|
||||
if (!props.modelValue.quantity) {
|
||||
listItem.value.quantity = 0;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.modelValue.food,
|
||||
(newFood) => {
|
||||
|
||||
@@ -97,7 +97,6 @@
|
||||
<script lang="ts">
|
||||
import { useLoggedInState } from "~/composables/use-logged-in-state";
|
||||
import type { SideBarLink } from "~/types/application-types";
|
||||
import { useAppInfo } from "~/composables/api";
|
||||
import { useCookbookPreferences } from "~/composables/use-users/preferences";
|
||||
import { useCookbookStore, usePublicCookbookStore } from "~/composables/store/use-cookbook-store";
|
||||
import type { ReadCookBook } from "~/lib/api/types/cookbook";
|
||||
@@ -105,7 +104,7 @@ import type { ReadCookBook } from "~/lib/api/types/cookbook";
|
||||
export default defineNuxtComponent({
|
||||
setup() {
|
||||
const i18n = useI18n();
|
||||
const { $globals } = useNuxtApp();
|
||||
const { $appInfo, $globals } = useNuxtApp();
|
||||
const display = useDisplay();
|
||||
const $auth = useMealieAuth();
|
||||
const { isOwnGroup } = useLoggedInState();
|
||||
@@ -135,9 +134,7 @@ export default defineNuxtComponent({
|
||||
return [];
|
||||
});
|
||||
|
||||
const appInfo = useAppInfo();
|
||||
const showImageImport = computed(() => appInfo.value?.enableOpenaiImageServices);
|
||||
|
||||
const showImageImport = computed(() => $appInfo.enableOpenaiImageServices);
|
||||
const languageDialog = ref<boolean>(false);
|
||||
|
||||
const sidebar = ref<boolean>(false);
|
||||
|
||||
@@ -149,6 +149,6 @@ export default defineNuxtComponent({
|
||||
|
||||
<style scoped>
|
||||
.v-toolbar {
|
||||
z-index: 1010 !important;
|
||||
z-index: 2010 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
item-title="name"
|
||||
return-object
|
||||
:items="items"
|
||||
:custom-filter="normalizeFilter"
|
||||
:prepend-icon="icon || $globals.icons.tags"
|
||||
auto-select-first
|
||||
clearable
|
||||
@@ -52,6 +53,7 @@
|
||||
|
||||
import type { MultiPurposeLabelSummary } from "~/lib/api/types/labels";
|
||||
import type { IngredientFood, IngredientUnit } from "~/lib/api/types/recipe";
|
||||
import { normalizeFilter } from "~/composables/use-utils";
|
||||
|
||||
export default defineNuxtComponent({
|
||||
props: {
|
||||
@@ -122,6 +124,7 @@ export default defineNuxtComponent({
|
||||
itemIdVal,
|
||||
searchInput,
|
||||
emitCreate,
|
||||
normalizeFilter,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
class="d-flex align-center"
|
||||
style="max-width: 60px"
|
||||
>
|
||||
<v-text-field
|
||||
v-model.number="quantity"
|
||||
hide-details
|
||||
:label="$t('form.quantity-label-abbreviated')"
|
||||
:min="min"
|
||||
:max="max"
|
||||
type="number"
|
||||
variant="plain"
|
||||
density="compact"
|
||||
style="width: 60px;"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineNuxtComponent({
|
||||
name: "VInputNumber",
|
||||
props: {
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 9999,
|
||||
},
|
||||
rules: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
modelValue: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
setup(props, context) {
|
||||
const quantity = computed({
|
||||
get: () => {
|
||||
return Number(props.modelValue);
|
||||
},
|
||||
set: (val) => {
|
||||
context.emit("update:modelValue", val);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
quantity,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -9,6 +9,7 @@
|
||||
<v-autocomplete
|
||||
v-model="selectedLocale"
|
||||
:items="locales"
|
||||
:custom-filter="normalizeFilter"
|
||||
item-title="name"
|
||||
item-value="value"
|
||||
class="my-3"
|
||||
@@ -44,6 +45,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { useLocales } from "~/composables/use-locales";
|
||||
import { normalizeFilter } from "~/composables/use-utils";
|
||||
|
||||
export default defineNuxtComponent({
|
||||
props: {
|
||||
@@ -83,6 +85,7 @@ export default defineNuxtComponent({
|
||||
locale,
|
||||
selectedLocale,
|
||||
onLocaleSelect,
|
||||
normalizeFilter,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -29,9 +29,9 @@ export default defineNuxtComponent({
|
||||
"ul", "ol", "li", "dl", "dt", "dd", "abbr", "a", "img", "blockquote", "iframe",
|
||||
"del", "ins", "table", "thead", "tbody", "tfoot", "tr", "th", "td", "colgroup",
|
||||
],
|
||||
ADD_ATTR: [
|
||||
ALLOWED_ATTR: [
|
||||
"href", "src", "alt", "height", "width", "class", "allow", "title", "allowfullscreen", "frameborder",
|
||||
"scrolling", "cite", "datetime", "name", "abbr", "target", "border",
|
||||
"scrolling", "cite", "datetime", "name", "abbr", "target", "border", "start",
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
export { useAppInfo } from "./use-app-info";
|
||||
export { useStaticRoutes } from "./static-routes";
|
||||
export { useAdminApi, usePublicApi, usePublicExploreApi, useUserApi } from "./api-client";
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import type { AppInfo } from "~/lib/api/types/admin";
|
||||
|
||||
export function useAppInfo(): Ref<AppInfo | null> {
|
||||
const i18n = useI18n();
|
||||
const { $axios } = useNuxtApp();
|
||||
$axios.defaults.headers.common["Accept-Language"] = i18n.locale.value;
|
||||
|
||||
const { data: appInfo } = useAsyncData("app-info", async () => {
|
||||
const data = await $axios.get<AppInfo>("/api/app/about");
|
||||
return data.data;
|
||||
});
|
||||
|
||||
return appInfo;
|
||||
}
|
||||
58
frontend/composables/partials/use-actions-factory.test.ts
Normal file
58
frontend/composables/partials/use-actions-factory.test.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import { ref } from "vue";
|
||||
import { useStoreActions } from "./use-actions-factory";
|
||||
import type { BaseCRUDAPI } from "~/lib/api/base/base-clients";
|
||||
|
||||
describe("useStoreActions", () => {
|
||||
const mockApi = {
|
||||
getAll: vi.fn(),
|
||||
createOne: vi.fn(),
|
||||
updateOne: vi.fn(),
|
||||
deleteOne: vi.fn(),
|
||||
} as unknown as BaseCRUDAPI<unknown, unknown, unknown>;
|
||||
|
||||
const mockStore = ref([]);
|
||||
const mockLoading = ref(false);
|
||||
|
||||
test("deleteMany calls deleteOne for each ID and refreshes once", async () => {
|
||||
const actions = useStoreActions("test-store", mockApi, mockStore, mockLoading);
|
||||
|
||||
mockApi.deleteOne = vi.fn().mockResolvedValue({ response: { data: {} } });
|
||||
mockApi.getAll = vi.fn().mockResolvedValue({ data: { items: [] } });
|
||||
|
||||
const ids = ["1", "2", "3"];
|
||||
await actions.deleteMany(ids);
|
||||
|
||||
expect(mockApi.deleteOne).toHaveBeenCalledTimes(3);
|
||||
expect(mockApi.deleteOne).toHaveBeenCalledWith("1");
|
||||
expect(mockApi.deleteOne).toHaveBeenCalledWith("2");
|
||||
expect(mockApi.deleteOne).toHaveBeenCalledWith("3");
|
||||
|
||||
expect(mockApi.getAll).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("deleteMany handles empty array", async () => {
|
||||
const actions = useStoreActions("test-store", mockApi, mockStore, mockLoading);
|
||||
|
||||
mockApi.deleteOne = vi.fn();
|
||||
mockApi.getAll = vi.fn().mockResolvedValue({ data: { items: [] } });
|
||||
|
||||
await actions.deleteMany([]);
|
||||
|
||||
expect(mockApi.deleteOne).not.toHaveBeenCalled();
|
||||
expect(mockApi.getAll).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("deleteMany sets loading state", async () => {
|
||||
const actions = useStoreActions("test-store", mockApi, mockStore, mockLoading);
|
||||
|
||||
mockApi.deleteOne = vi.fn().mockResolvedValue({});
|
||||
mockApi.getAll = vi.fn().mockResolvedValue({ data: { items: [] } });
|
||||
|
||||
const promise = actions.deleteMany(["1"]);
|
||||
expect(mockLoading.value).toBe(true);
|
||||
|
||||
await promise;
|
||||
expect(mockLoading.value).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -12,6 +12,7 @@ interface StoreActions<T extends BoundT> extends ReadOnlyStoreActions<T> {
|
||||
createOne(createData: T): Promise<T | null>;
|
||||
updateOne(updateData: T): Promise<T | null>;
|
||||
deleteOne(id: string | number): Promise<T | null>;
|
||||
deleteMany(ids: (string | number)[]): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,11 +166,23 @@ export function useStoreActions<T extends BoundT>(
|
||||
return response?.data || null;
|
||||
}
|
||||
|
||||
async function deleteMany(ids: (string | number)[]) {
|
||||
loading.value = true;
|
||||
for (const id of ids) {
|
||||
await api.deleteOne(id);
|
||||
}
|
||||
if (allRef?.value) {
|
||||
await refresh();
|
||||
}
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
getAll,
|
||||
refresh,
|
||||
createOne,
|
||||
updateOne,
|
||||
deleteOne,
|
||||
deleteMany,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ export const useStore = function <T extends BoundT>(
|
||||
return await storeActions.refresh(1, -1, params);
|
||||
},
|
||||
flushStore() {
|
||||
store = ref([]);
|
||||
store.value = [];
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -82,7 +82,6 @@ export function useParsedIngredientText(ingredient: RecipeIngredient, scale = 1,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add support for sub-recipes here?
|
||||
const unitName = useUnitName(unit || undefined, usePluralUnit);
|
||||
const ingName = referencedRecipe ? referencedRecipe.name || "" : useFoodName(food || undefined, usePluralFood);
|
||||
|
||||
|
||||
@@ -1,7 +1,31 @@
|
||||
export { useCategoryStore, usePublicCategoryStore, useCategoryData } from "./use-category-store";
|
||||
export { useFoodStore, usePublicFoodStore, useFoodData } from "./use-food-store";
|
||||
export { useHouseholdStore, usePublicHouseholdStore } from "./use-household-store";
|
||||
export { useLabelStore, useLabelData } from "./use-label-store";
|
||||
export { useTagStore, usePublicTagStore, useTagData } from "./use-tag-store";
|
||||
export { useToolStore, usePublicToolStore, useToolData } from "./use-tool-store";
|
||||
export { useUnitStore, useUnitData } from "./use-unit-store";
|
||||
import { resetCategoryStore } from "./use-category-store";
|
||||
import { resetFoodStore } from "./use-food-store";
|
||||
import { resetHouseholdStore } from "./use-household-store";
|
||||
import { resetLabelStore } from "./use-label-store";
|
||||
import { resetTagStore } from "./use-tag-store";
|
||||
import { resetToolStore } from "./use-tool-store";
|
||||
import { resetUnitStore } from "./use-unit-store";
|
||||
import { resetCookbookStore } from "./use-cookbook-store";
|
||||
import { resetUserStore } from "./use-user-store";
|
||||
|
||||
export { useCategoryStore, usePublicCategoryStore, useCategoryData, resetCategoryStore } from "./use-category-store";
|
||||
export { useFoodStore, usePublicFoodStore, useFoodData, resetFoodStore } from "./use-food-store";
|
||||
export { useHouseholdStore, usePublicHouseholdStore, resetHouseholdStore } from "./use-household-store";
|
||||
export { useLabelStore, useLabelData, resetLabelStore } from "./use-label-store";
|
||||
export { useTagStore, usePublicTagStore, useTagData, resetTagStore } from "./use-tag-store";
|
||||
export { useToolStore, usePublicToolStore, useToolData, resetToolStore } from "./use-tool-store";
|
||||
export { useUnitStore, useUnitData, resetUnitStore } from "./use-unit-store";
|
||||
export { useCookbookStore, usePublicCookbookStore, resetCookbookStore } from "./use-cookbook-store";
|
||||
export { useUserStore, resetUserStore } from "./use-user-store";
|
||||
|
||||
export function clearAllStores() {
|
||||
resetCategoryStore();
|
||||
resetFoodStore();
|
||||
resetHouseholdStore();
|
||||
resetLabelStore();
|
||||
resetTagStore();
|
||||
resetToolStore();
|
||||
resetUnitStore();
|
||||
resetCookbookStore();
|
||||
resetUserStore();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,12 @@ const store: Ref<RecipeCategory[]> = ref([]);
|
||||
const loading = ref(false);
|
||||
const publicLoading = ref(false);
|
||||
|
||||
export function resetCategoryStore() {
|
||||
store.value = [];
|
||||
loading.value = false;
|
||||
publicLoading.value = false;
|
||||
}
|
||||
|
||||
export const useCategoryData = function () {
|
||||
return useData<RecipeCategory>({
|
||||
id: "",
|
||||
|
||||
@@ -7,6 +7,12 @@ const cookbooks: Ref<ReadCookBook[]> = ref([]);
|
||||
const loading = ref(false);
|
||||
const publicLoading = ref(false);
|
||||
|
||||
export function resetCookbookStore() {
|
||||
cookbooks.value = [];
|
||||
loading.value = false;
|
||||
publicLoading.value = false;
|
||||
}
|
||||
|
||||
export const useCookbookStore = function (i18n?: Composer) {
|
||||
const api = useUserApi(i18n);
|
||||
const store = useStore<ReadCookBook>("cookbook", cookbooks, loading, api.cookbooks);
|
||||
|
||||
@@ -7,6 +7,12 @@ const store: Ref<IngredientFood[]> = ref([]);
|
||||
const loading = ref(false);
|
||||
const publicLoading = ref(false);
|
||||
|
||||
export function resetFoodStore() {
|
||||
store.value = [];
|
||||
loading.value = false;
|
||||
publicLoading.value = false;
|
||||
}
|
||||
|
||||
export const useFoodData = function () {
|
||||
return useData<IngredientFood>({
|
||||
id: "",
|
||||
|
||||
@@ -7,6 +7,12 @@ const store: Ref<HouseholdSummary[]> = ref([]);
|
||||
const loading = ref(false);
|
||||
const publicLoading = ref(false);
|
||||
|
||||
export function resetHouseholdStore() {
|
||||
store.value = [];
|
||||
loading.value = false;
|
||||
publicLoading.value = false;
|
||||
}
|
||||
|
||||
export const useHouseholdStore = function (i18n?: Composer) {
|
||||
const api = useUserApi(i18n);
|
||||
return useReadOnlyStore<HouseholdSummary>("household", store, loading, api.households);
|
||||
|
||||
@@ -6,6 +6,11 @@ import { useUserApi } from "~/composables/api";
|
||||
const store: Ref<MultiPurposeLabelOut[]> = ref([]);
|
||||
const loading = ref(false);
|
||||
|
||||
export function resetLabelStore() {
|
||||
store.value = [];
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
export const useLabelData = function () {
|
||||
return useData<MultiPurposeLabelOut>({
|
||||
groupId: "",
|
||||
|
||||
@@ -7,6 +7,12 @@ const store: Ref<RecipeTag[]> = ref([]);
|
||||
const loading = ref(false);
|
||||
const publicLoading = ref(false);
|
||||
|
||||
export function resetTagStore() {
|
||||
store.value = [];
|
||||
loading.value = false;
|
||||
publicLoading.value = false;
|
||||
}
|
||||
|
||||
export const useTagData = function () {
|
||||
return useData<RecipeTag>({
|
||||
id: "",
|
||||
|
||||
@@ -11,6 +11,12 @@ const store: Ref<RecipeTool[]> = ref([]);
|
||||
const loading = ref(false);
|
||||
const publicLoading = ref(false);
|
||||
|
||||
export function resetToolStore() {
|
||||
store.value = [];
|
||||
loading.value = false;
|
||||
publicLoading.value = false;
|
||||
}
|
||||
|
||||
export const useToolData = function () {
|
||||
return useData<RecipeToolWithOnHand>({
|
||||
id: "",
|
||||
|
||||
@@ -6,6 +6,11 @@ import { useUserApi } from "~/composables/api";
|
||||
const store: Ref<IngredientUnit[]> = ref([]);
|
||||
const loading = ref(false);
|
||||
|
||||
export function resetUnitStore() {
|
||||
store.value = [];
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
export const useUnitData = function () {
|
||||
return useData<IngredientUnit>({
|
||||
id: "",
|
||||
|
||||
@@ -7,6 +7,11 @@ import { BaseCRUDAPIReadOnly } from "~/lib/api/base/base-clients";
|
||||
const store: Ref<UserSummary[]> = ref([]);
|
||||
const loading = ref(false);
|
||||
|
||||
export function resetUserStore() {
|
||||
store.value = [];
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
class GroupUserAPIReadOnly extends BaseCRUDAPIReadOnly<UserSummary> {
|
||||
baseRoute = "/api/groups/members";
|
||||
itemRoute = (idOrUsername: string | number) => `/groups/members/${idOrUsername}`;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ref, computed } from "vue";
|
||||
import type { UserOut } from "~/lib/api/types/user";
|
||||
import { clearAllStores } from "~/composables/store";
|
||||
|
||||
interface AuthData {
|
||||
value: UserOut | null;
|
||||
@@ -23,10 +24,15 @@ const authUser = ref<UserOut | null>(null);
|
||||
const authStatus = ref<"loading" | "authenticated" | "unauthenticated">("loading");
|
||||
|
||||
export const useAuthBackend = function (): AuthState {
|
||||
const { $axios } = useNuxtApp();
|
||||
const { $appInfo, $axios } = useNuxtApp();
|
||||
const router = useRouter();
|
||||
const tokenName = useRuntimeConfig().public.AUTH_TOKEN;
|
||||
const tokenCookie = useCookie(tokenName);
|
||||
|
||||
const runtimeConfig = useRuntimeConfig();
|
||||
const tokenName = runtimeConfig.public.AUTH_TOKEN;
|
||||
const tokenCookie = useCookie(tokenName, {
|
||||
maxAge: $appInfo.tokenTime * 60 * 60,
|
||||
secure: $appInfo.production && window?.location?.protocol === "https:",
|
||||
});
|
||||
|
||||
function setToken(token: string | null) {
|
||||
tokenCookie.value = token;
|
||||
@@ -96,6 +102,13 @@ export const useAuthBackend = function (): AuthState {
|
||||
setToken(null);
|
||||
authUser.value = null;
|
||||
authStatus.value = "unauthenticated";
|
||||
|
||||
// Clear all cached store data to prevent data leakage between users
|
||||
clearAllStores();
|
||||
|
||||
// Clear Nuxt's useAsyncData cache
|
||||
clearNuxtData();
|
||||
|
||||
await router.push(callbackUrl || "/login");
|
||||
}
|
||||
}
|
||||
@@ -115,30 +128,6 @@ export const useAuthBackend = function (): AuthState {
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-refresh user data periodically when authenticated
|
||||
if (import.meta.client) {
|
||||
let refreshInterval: NodeJS.Timeout | null = null;
|
||||
|
||||
watch(() => authStatus.value, (status) => {
|
||||
if (status === "authenticated") {
|
||||
refreshInterval = setInterval(() => {
|
||||
if (tokenCookie.value) {
|
||||
getSession().catch(() => {
|
||||
// Ignore errors in background refresh
|
||||
});
|
||||
}
|
||||
}, 5 * 60 * 1000); // 5 minutes
|
||||
}
|
||||
else {
|
||||
// Clear interval when not authenticated
|
||||
if (refreshInterval) {
|
||||
clearInterval(refreshInterval);
|
||||
refreshInterval = null;
|
||||
}
|
||||
}
|
||||
}, { immediate: true });
|
||||
}
|
||||
|
||||
return {
|
||||
data: computed(() => authUser.value),
|
||||
status: computed(() => authStatus.value),
|
||||
@@ -15,6 +15,9 @@ export function usePlanTypeOptions() {
|
||||
{ text: i18n.t("meal-plan.lunch"), value: "lunch" },
|
||||
{ text: i18n.t("meal-plan.dinner"), value: "dinner" },
|
||||
{ text: i18n.t("meal-plan.side"), value: "side" },
|
||||
{ text: i18n.t("meal-plan.snack"), value: "snack" },
|
||||
{ text: i18n.t("meal-plan.drink"), value: "drink" },
|
||||
{ text: i18n.t("meal-plan.dessert"), value: "dessert" },
|
||||
] as PlanOption[];
|
||||
}
|
||||
|
||||
|
||||
@@ -21,19 +21,19 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Українська (Ukrainian)",
|
||||
value: "uk-UA",
|
||||
progress: 61,
|
||||
progress: 99,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Türkçe (Turkish)",
|
||||
value: "tr-TR",
|
||||
progress: 35,
|
||||
progress: 39,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Svenska (Swedish)",
|
||||
value: "sv-SE",
|
||||
progress: 66,
|
||||
progress: 67,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@@ -45,7 +45,7 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Slovenščina (Slovenian)",
|
||||
value: "sl-SI",
|
||||
progress: 40,
|
||||
progress: 41,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@@ -57,19 +57,19 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Pусский (Russian)",
|
||||
value: "ru-RU",
|
||||
progress: 43,
|
||||
progress: 46,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Română (Romanian)",
|
||||
value: "ro-RO",
|
||||
progress: 36,
|
||||
progress: 41,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Português (Portuguese)",
|
||||
value: "pt-PT",
|
||||
progress: 38,
|
||||
progress: 39,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@@ -81,7 +81,7 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Polski (Polish)",
|
||||
value: "pl-PL",
|
||||
progress: 43,
|
||||
progress: 52,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@@ -93,13 +93,13 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Nederlands (Dutch)",
|
||||
value: "nl-NL",
|
||||
progress: 53,
|
||||
progress: 58,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Latviešu (Latvian)",
|
||||
value: "lv-LV",
|
||||
progress: 36,
|
||||
progress: 35,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@@ -111,7 +111,7 @@ export const LOCALES = [
|
||||
{
|
||||
name: "한국어 (Korean)",
|
||||
value: "ko-KR",
|
||||
progress: 9,
|
||||
progress: 22,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@@ -123,13 +123,13 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Italiano (Italian)",
|
||||
value: "it-IT",
|
||||
progress: 46,
|
||||
progress: 48,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Íslenska (Icelandic)",
|
||||
value: "is-IS",
|
||||
progress: 37,
|
||||
progress: 45,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@@ -141,7 +141,7 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Hrvatski (Croatian)",
|
||||
value: "hr-HR",
|
||||
progress: 28,
|
||||
progress: 29,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@@ -159,13 +159,13 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Français (French)",
|
||||
value: "fr-FR",
|
||||
progress: 67,
|
||||
progress: 70,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Français canadien (Canadian French)",
|
||||
value: "fr-CA",
|
||||
progress: 38,
|
||||
progress: 99,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@@ -177,13 +177,13 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Suomi (Finnish)",
|
||||
value: "fi-FI",
|
||||
progress: 40,
|
||||
progress: 41,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Eesti (Estonian)",
|
||||
value: "et-EE",
|
||||
progress: 43,
|
||||
progress: 47,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
@@ -207,37 +207,37 @@ export const LOCALES = [
|
||||
{
|
||||
name: "Ελληνικά (Greek)",
|
||||
value: "el-GR",
|
||||
progress: 41,
|
||||
progress: 42,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Deutsch (German)",
|
||||
value: "de-DE",
|
||||
progress: 96,
|
||||
progress: 97,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Dansk (Danish)",
|
||||
value: "da-DK",
|
||||
progress: 46,
|
||||
progress: 52,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Čeština (Czech)",
|
||||
value: "cs-CZ",
|
||||
progress: 42,
|
||||
progress: 41,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Català (Catalan)",
|
||||
value: "ca-ES",
|
||||
progress: 38,
|
||||
progress: 39,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
name: "Български (Bulgarian)",
|
||||
value: "bg-BG",
|
||||
progress: 47,
|
||||
progress: 51,
|
||||
dir: "ltr",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ref, watch, computed } from "vue";
|
||||
import { useAuthBackend } from "~/composables/useAuthBackend";
|
||||
import { useAuthBackend } from "~/composables/use-auth-backend";
|
||||
import type { UserOut } from "~/lib/api/types/user";
|
||||
|
||||
export const useMealieAuth = function () {
|
||||
@@ -168,6 +168,7 @@ export function useQueryFilterBuilder() {
|
||||
|| type === Organizer.Tool
|
||||
|| type === Organizer.Food
|
||||
|| type === Organizer.Household
|
||||
|| type === Organizer.User
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ const userRatings = ref<UserRatingSummary[]>([]);
|
||||
const loading = ref(false);
|
||||
const ready = ref(false);
|
||||
|
||||
const $auth = useMealieAuth();
|
||||
|
||||
export const useUserSelfRatings = function () {
|
||||
const $auth = useMealieAuth();
|
||||
|
||||
async function refreshUserRatings() {
|
||||
if (!$auth.user.value || loading.value) {
|
||||
return;
|
||||
|
||||
34
frontend/composables/use-utils.test.ts
Normal file
34
frontend/composables/use-utils.test.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { normalize, normalizeFilter } from "./use-utils";
|
||||
|
||||
describe("test normalize", () => {
|
||||
test("base case", () => {
|
||||
expect(normalize("banana")).not.toEqual(normalize("Potatoes"));
|
||||
});
|
||||
test("diacritics", () => {
|
||||
expect(normalize("Rátàtôuile")).toEqual("ratatouile");
|
||||
});
|
||||
test("ligatures", () => {
|
||||
expect(normalize("IJ")).toEqual("ij");
|
||||
expect(normalize("æ")).toEqual("ae");
|
||||
expect(normalize("œ")).toEqual("oe");
|
||||
expect(normalize("ff")).toEqual("ff");
|
||||
expect(normalize("fi")).toEqual("fi");
|
||||
expect(normalize("st")).toEqual("st");
|
||||
});
|
||||
});
|
||||
|
||||
describe("test normalize filter", () => {
|
||||
test("base case", () => {
|
||||
const patternA = "Escargots persillés";
|
||||
const patternB = "persillés";
|
||||
|
||||
expect(normalizeFilter(patternA, patternB)).toBeTruthy();
|
||||
expect(normalizeFilter(patternB, patternA)).toBeFalsy();
|
||||
});
|
||||
test("normalize", () => {
|
||||
const value = "Cœur de bœuf";
|
||||
const query = "coeur";
|
||||
expect(normalizeFilter(value, query)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useDark, useToggle } from "@vueuse/core";
|
||||
import type { FilterFunction } from "vuetify";
|
||||
|
||||
export const useToggleDarkMode = () => {
|
||||
const isDark = useDark();
|
||||
@@ -18,6 +19,38 @@ export const titleCase = function (str: string) {
|
||||
.join(" ");
|
||||
};
|
||||
|
||||
const replaceAllBuilder = (map: Map<string, string>): ((str: string) => string) => {
|
||||
const re = new RegExp(Array.from(map.keys()).join("|"), "gi");
|
||||
return str => str.replace(re, matched => map.get(matched)!);
|
||||
};
|
||||
|
||||
const normalizeLigatures = replaceAllBuilder(new Map([
|
||||
["œ", "oe"],
|
||||
["æ", "ae"],
|
||||
["ij", "ij"],
|
||||
["ff", "ff"],
|
||||
["fi", "fi"],
|
||||
["fl", "fl"],
|
||||
["st", "st"],
|
||||
]));
|
||||
|
||||
export const normalize = (str: string) => {
|
||||
if (!str) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let normalized = str.normalize("NFKD").toLowerCase();
|
||||
normalized = normalized.replace(/\p{Diacritic}/gu, "");
|
||||
normalized = normalizeLigatures(normalized);
|
||||
return normalized;
|
||||
};
|
||||
|
||||
export const normalizeFilter: FilterFunction = (value: string, query: string) => {
|
||||
const normalizedValue = normalize(value);
|
||||
const normalizeQuery = normalize(query);
|
||||
return normalizedValue.includes(normalizeQuery);
|
||||
};
|
||||
|
||||
export function uuid4() {
|
||||
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
|
||||
(parseInt(c) ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (parseInt(c) / 4)))).toString(16),
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import type { RequestResponse } from "~/lib/api/types/non-generated";
|
||||
import type { ValidationResponse } from "~/lib/api/types/response";
|
||||
import { required, email, whitespace, url, minLength, maxLength } from "~/lib/validators";
|
||||
import { required, email, whitespace, url, urlOptional, minLength, maxLength } from "~/lib/validators";
|
||||
|
||||
export const validators = {
|
||||
required,
|
||||
email,
|
||||
whitespace,
|
||||
url,
|
||||
urlOptional,
|
||||
minLength,
|
||||
maxLength,
|
||||
};
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
"about-mealie": "Meer oor Mealie",
|
||||
"api-docs": "API Dokumentasie",
|
||||
"api-port": "API Poort",
|
||||
"application-mode": "Applikasie modues",
|
||||
"application-mode": "Applikasie Modus",
|
||||
"database-type": "Databasis Tipe",
|
||||
"database-url": "Databasis URL",
|
||||
"default-group": "Standaard groep",
|
||||
"default-group": "Standaard Groep",
|
||||
"default-household": "Default Household",
|
||||
"demo": "Demonstrasie",
|
||||
"demo-status": "Demonstrasie Status",
|
||||
@@ -65,7 +65,7 @@
|
||||
"something-went-wrong": "Iets het verkeerd geloop!",
|
||||
"subscribed-events": "Ingetekende Gebeure",
|
||||
"test-message-sent": "Toets Boodskap Gestuur",
|
||||
"message-sent": "Message Sent",
|
||||
"message-sent": "Boodskap Gestuur",
|
||||
"new-notification": "Nuwe kennisgewing",
|
||||
"event-notifiers": "Gebeurteniskennisgewers",
|
||||
"apprise-url-skipped-if-blank": "Apprise URL (oorgeslaan indien leeg)",
|
||||
@@ -84,7 +84,7 @@
|
||||
"label-events": "Label Events"
|
||||
},
|
||||
"general": {
|
||||
"add": "Add",
|
||||
"add": "Voeg by",
|
||||
"cancel": "Kanselleer",
|
||||
"clear": "Maak skoon",
|
||||
"close": "Maak toe",
|
||||
@@ -134,7 +134,7 @@
|
||||
"no-recipe-found": "Geen resep gevind nie",
|
||||
"ok": "OK",
|
||||
"options": "Opsies:",
|
||||
"plural-name": "Plural Name",
|
||||
"plural-name": "Meervoudsnaam",
|
||||
"print": "Druk",
|
||||
"print-preferences": "Drukvoorkeure",
|
||||
"random": "Willekeurig",
|
||||
@@ -148,23 +148,23 @@
|
||||
"save": "Stoor",
|
||||
"settings": "Verstellings",
|
||||
"share": "Deel",
|
||||
"show-all": "Show All",
|
||||
"show-all": "Wys Alles",
|
||||
"shuffle": "Skommel",
|
||||
"sort": "Sorteer",
|
||||
"sort-ascending": "Sort Ascending",
|
||||
"sort-descending": "Sort Descending",
|
||||
"sort-ascending": "Sorteer Oplopend",
|
||||
"sort-descending": "Sorteer Aflopend",
|
||||
"sort-alphabetically": "Alfabeties",
|
||||
"status": "Status",
|
||||
"subject": "Onderwerp",
|
||||
"submit": "Dien in",
|
||||
"success-count": "Sukses: {count}",
|
||||
"sunday": "Sondag",
|
||||
"system": "System",
|
||||
"system": "Sisteem",
|
||||
"templates": "Sjablone:",
|
||||
"test": "Toets",
|
||||
"themes": "Temas",
|
||||
"thursday": "Donderdag",
|
||||
"title": "Title",
|
||||
"title": "Titel",
|
||||
"token": "Token",
|
||||
"tuesday": "Dinsdag",
|
||||
"type": "Tipe",
|
||||
@@ -179,12 +179,12 @@
|
||||
"units": "Eenhede",
|
||||
"back": "Terug",
|
||||
"next": "Volgende",
|
||||
"start": "Start",
|
||||
"start": "Begin",
|
||||
"toggle-view": "Wissel aansig",
|
||||
"date": "Datum",
|
||||
"id": "Id",
|
||||
"owner": "Eienaar",
|
||||
"change-owner": "Change Owner",
|
||||
"change-owner": "Verander Eienaar",
|
||||
"date-added": "Datum bygevoeg",
|
||||
"none": "Geen",
|
||||
"run": "Hardloop",
|
||||
@@ -212,13 +212,13 @@
|
||||
"upload-file": "Laai dokument op",
|
||||
"created-on-date": "Geskep op: {0}",
|
||||
"unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes.",
|
||||
"clipboard-copy-failure": "Failed to copy to the clipboard.",
|
||||
"confirm-delete-generic-items": "Are you sure you want to delete the following items?",
|
||||
"organizers": "Organizers",
|
||||
"clipboard-copy-failure": "Kon nie kopieer na die knipbord toe nie.",
|
||||
"confirm-delete-generic-items": "Is jy seker jy wil die volgende items verwyder?",
|
||||
"organizers": "Organiseerders",
|
||||
"caution": "Caution",
|
||||
"show-advanced": "Show Advanced",
|
||||
"add-field": "Add Field",
|
||||
"date-created": "Date Created",
|
||||
"date-created": "Datum Geskep",
|
||||
"date-updated": "Date Updated"
|
||||
},
|
||||
"group": {
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Ontbyt",
|
||||
"lunch": "Middagete",
|
||||
"dinner": "Aandete",
|
||||
"snack": "Snack",
|
||||
"drink": "Drank",
|
||||
"dessert": "Nagereg",
|
||||
"type-any": "Enige",
|
||||
"day-any": "Enige",
|
||||
"editor": "Editor",
|
||||
@@ -438,10 +441,11 @@
|
||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Plak jou resepdata in. Elke reël sal as 'n item in 'n lys hanteer word",
|
||||
"recipe-markup-specification": "Resep formaat spesifikasie",
|
||||
"recipe-url": "Resep URL",
|
||||
"recipe-html-or-json": "Recipe HTML or JSON",
|
||||
"recipe-html-or-json": "Resep HTML of JSON",
|
||||
"upload-a-recipe": "Laai 'n resep op",
|
||||
"upload-individual-zip-file": "Laai 'n .zip-lêer op wat vanaf 'n ander Mealie-instansie uitgevoer is.",
|
||||
"url-form-hint": "Kopieer en plak 'n skakel vanaf jou gunstelingresepwebwerf",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "Bekyk opgespoorde data",
|
||||
"trim-whitespace-description": "Knip voorste en agterste witspasie sowel as leë reëls",
|
||||
"trim-prefix-description": "Knip die eerste karakter van elke reël af",
|
||||
@@ -450,7 +454,7 @@
|
||||
"create-manually": "Skep 'n resep met die hand",
|
||||
"make-recipe-image": "Maak dit die prentjie vir hierdie resep",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-recipe": "Voeg Resep By"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Bladsy nie gevind nie",
|
||||
@@ -517,8 +521,8 @@
|
||||
"recipe-deleted": "Resep uitgevee",
|
||||
"recipe-image": "Resep foto",
|
||||
"recipe-image-updated": "Resep foto is opgedateer",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"delete-image": "Verwyder Resep Beeld",
|
||||
"delete-image-confirmation": "Is jy seker jy wil dié beeld van die resep verwyder?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"recipe-name": "Resepnaam",
|
||||
"recipe-settings": "Resep verstellings",
|
||||
@@ -552,7 +556,7 @@
|
||||
"add-to-plan": "Voeg by plan",
|
||||
"add-to-timeline": "Voeg by tydlyn",
|
||||
"recipe-added-to-list": "Resep by lys gevoeg",
|
||||
"recipes-added-to-list": "Recipes added to list",
|
||||
"recipes-added-to-list": "Resepte toegevoeg tot lys",
|
||||
"successfully-added-to-list": "Successfully added to list",
|
||||
"recipe-added-to-mealplan": "Resep is by die maaltydplan gevoeg",
|
||||
"failed-to-add-recipes-to-list": "Failed to add recipe to list",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Kies 'n eenheid",
|
||||
"press-enter-to-create": "Druk Enter om te skep",
|
||||
"choose-food": "Keuse van kos",
|
||||
"choose-recipe": "Kies Resep",
|
||||
"notes": "Notas",
|
||||
"toggle-section": "Wissel afdeling",
|
||||
"see-original-text": "Sien oorspronklike teks",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Try out the bulk importer",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Have raw HTML or JSON data?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "You can import from raw data directly",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "Voer oorspronklike sleutelwoorde as merkers in",
|
||||
"stay-in-edit-mode": "Bly in redigeer modus",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
@@ -653,7 +660,7 @@
|
||||
"report-deletion-failed": "Kon nie verslag uitvee nie",
|
||||
"recipe-debugger": "Resep debugger",
|
||||
"recipe-debugger-description": "Gryp die URL van die resep wat jy wil debug en plak dit hier. Die URL sal deur die resepskraper geskraap word en die resultate sal vertoon word. As jy nie enige data terugstuur sien nie, word die webwerf wat jy probeer skraap nie deur Mealie of sy skraperbiblioteek ondersteun nie.",
|
||||
"use-openai": "Use OpenAI",
|
||||
"use-openai": "Gebruik OpenAI",
|
||||
"recipe-debugger-use-openai-description": "Use OpenAI to parse the results instead of relying on the scraper library. When creating a recipe via URL, this is done automatically if the scraper library fails, but you may test it manually here.",
|
||||
"debug": "Debug",
|
||||
"tree-view": "Boomstruktuur",
|
||||
@@ -664,8 +671,8 @@
|
||||
"upload-image": "Laai prent",
|
||||
"screen-awake": "Hou die skerm aan",
|
||||
"remove-image": "Verwyder prent",
|
||||
"nextStep": "Next step",
|
||||
"recipe-actions": "Recipe Actions",
|
||||
"nextStep": "Volgende stap",
|
||||
"recipe-actions": "Resep Aksies",
|
||||
"parser": {
|
||||
"ingredient-parser": "Ingredient Parser",
|
||||
"explanation": "To use the ingredient parser, click the 'Parse All' button to start the process. Once the processed ingredients are available, you can review the items and verify that they were parsed correctly. The model's confidence score is displayed on the right of the item title. This score is an average of all the individual scores and may not always be completely accurate.",
|
||||
@@ -675,7 +682,7 @@
|
||||
"brute-parser": "Brute Parser",
|
||||
"openai-parser": "OpenAI Parser",
|
||||
"parse-all": "Parse All",
|
||||
"no-unit": "No unit",
|
||||
"no-unit": "Geen eenheid",
|
||||
"missing-unit": "Create missing unit: {unit}",
|
||||
"missing-food": "Create missing food: {food}",
|
||||
"this-unit-could-not-be-parsed-automatically": "This unit could not be parsed automatically",
|
||||
@@ -686,12 +693,12 @@
|
||||
"ingredient-parser-description": "Your ingredients have been successfully parsed. Please review the ingredients we're not sure about.",
|
||||
"ingredient-parser-final-review-description": "Once all ingredients have been reviewed, you'll have one more chance to review all ingredients before applying the changes to your recipe.",
|
||||
"add-text-as-alias-for-item": "Add \"{text}\" as alias for {item}",
|
||||
"delete-item": "Delete Item"
|
||||
"delete-item": "Verwyder Item"
|
||||
},
|
||||
"reset-servings-count": "Reset Servings Count",
|
||||
"not-linked-ingredients": "Additional Ingredients",
|
||||
"not-linked-ingredients": "Bykomende Bestanddele",
|
||||
"upload-another-image": "Upload another image",
|
||||
"upload-images": "Upload images",
|
||||
"upload-images": "Laai beelde op",
|
||||
"upload-more-images": "Upload more images",
|
||||
"set-as-cover-image": "Set as recipe cover image",
|
||||
"cover-image": "Cover image",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Druk '/'",
|
||||
"advanced": "Gevorderd",
|
||||
"auto-search": "Outomatiese soektog",
|
||||
"no-results": "No results found"
|
||||
"no-results": "No results found",
|
||||
"type-to-search": "Type to search..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Voeg 'n nuwe tema by",
|
||||
@@ -882,7 +890,7 @@
|
||||
"oidc-ready": "OIDC Klar",
|
||||
"oidc-ready-error-text": "Ikke alle OIDC værdier er konfigureret. Dette kan ignoreres hvis du ikke bruger OIDC godkendelse.",
|
||||
"oidc-ready-success-text": "Krævede OIDC variabler er udfyldt.",
|
||||
"openai-ready": "OpenAI Ready",
|
||||
"openai-ready": "OpenAI Gereed",
|
||||
"openai-ready-error-text": "Not all OpenAI Values are configured. This can be ignored if you are not using OpenAI features.",
|
||||
"openai-ready-success-text": "Required OpenAI variables are all set."
|
||||
},
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "is like",
|
||||
"is-not-like": "is not like"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "الإفطار",
|
||||
"lunch": "الغداء",
|
||||
"dinner": "العشاء",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "أي",
|
||||
"day-any": "أي",
|
||||
"editor": "المحرر",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "تحميل وصفة",
|
||||
"upload-individual-zip-file": "تحميل مِلَفّ zip فردي تم تصديره من مثيل Malie آخر.",
|
||||
"url-form-hint": "نسخ ولصق رابط من موقعك المفضل للوصفة",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "عرض البيانات المحللة",
|
||||
"trim-whitespace-description": "قص المسافات البيضاء البادئة واللاحقة وكذلك الأسطر الفارغة",
|
||||
"trim-prefix-description": "قص الحرف الأول من كل سطر",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "اختر الوحدة",
|
||||
"press-enter-to-create": "",
|
||||
"choose-food": "اختيار الطعام",
|
||||
"choose-recipe": "Choose Recipe",
|
||||
"notes": "ملاحظات",
|
||||
"toggle-section": "",
|
||||
"see-original-text": "عرض النص الأصلي",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "جرب الإضافة بالجملة",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "هل لديك بيانات HTML أو JSON خام؟",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "يمكنك الإضافة مباشرة باستخدام بيانات خام",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "استيراد الكلمات المفتاحية الأصلية كوسوم",
|
||||
"stay-in-edit-mode": "البقاء في وضع التعديل",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "اضغط '/'",
|
||||
"advanced": "الإعدادات المتقدمة",
|
||||
"auto-search": "البحث التلقائي",
|
||||
"no-results": "لم يتم العثور على نتائج"
|
||||
"no-results": "لم يتم العثور على نتائج",
|
||||
"type-to-search": "Type to search..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "إضافة سمة جديدة",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "هو مثل",
|
||||
"is-not-like": "ليس مثل"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"about-mealie": "Относно Mealie",
|
||||
"api-docs": "API Документация",
|
||||
"api-port": "API Порт",
|
||||
"application-mode": "Режим на приложение",
|
||||
"application-mode": "Статус на приложението",
|
||||
"database-type": "Тип на база данни",
|
||||
"database-url": "URL адрес база данни",
|
||||
"default-group": "Група по подразбиране",
|
||||
@@ -128,7 +128,7 @@
|
||||
"message": "Съобщение",
|
||||
"monday": "Понеделник",
|
||||
"name": "Име",
|
||||
"new": "Нов",
|
||||
"new": "Добавяне",
|
||||
"never": "няма данни",
|
||||
"no": "Не",
|
||||
"no-recipe-found": "Няма намерени рецепти",
|
||||
@@ -159,7 +159,7 @@
|
||||
"submit": "Изпрати",
|
||||
"success-count": "Успешни: {count}",
|
||||
"sunday": "Неделя",
|
||||
"system": "Система",
|
||||
"system": "В хронологичен ред",
|
||||
"templates": "Шаблони:",
|
||||
"test": "Тест",
|
||||
"themes": "Теми",
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Закуска",
|
||||
"lunch": "Обяд",
|
||||
"dinner": "Вечеря",
|
||||
"snack": "Закуска",
|
||||
"drink": "Питие",
|
||||
"dessert": "Десерт",
|
||||
"type-any": "Всички",
|
||||
"day-any": "Всички",
|
||||
"editor": "Редактор",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Качи рецепта",
|
||||
"upload-individual-zip-file": "Качи като индивидуален .zip файлов формат от друга инстанция на Mealie.",
|
||||
"url-form-hint": "Копирай и постави линк от твоя любим сайт за рецепти",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Копирайте и поставете URL адреса на източника на вашите данни (по избор)",
|
||||
"view-scraped-data": "Виж събраните данни",
|
||||
"trim-whitespace-description": "Премахни интервалите в началото и края на текста, също така и празните редове",
|
||||
"trim-prefix-description": "Премахни първия символ от всеки ред",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Импортиране на рецепта от линк",
|
||||
"create-manually": "Създай рецепта ръчно",
|
||||
"make-recipe-image": "Задай като изображението на рецептата",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Добавяне на продукт",
|
||||
"add-recipe": "Добавяне на рецепта"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Страницата не е намерена",
|
||||
@@ -477,7 +481,7 @@
|
||||
"categories": "Категории",
|
||||
"cholesterol-content": "Холестерол",
|
||||
"comment-action": "Коментирай",
|
||||
"comment": "Коментар",
|
||||
"comment": "Добавен коментар",
|
||||
"comments": "Коментари",
|
||||
"delete-confirmation": "Сигурни ли сте, че желаете да изтриете тази рецепта?",
|
||||
"admin-delete-confirmation": "Ще изтриете рецепта, която не е ваша, използвайки администраторски права. Сигурни ли сте?",
|
||||
@@ -497,7 +501,7 @@
|
||||
"insert-section": "Въведете раздел",
|
||||
"insert-above": "Вмъкни отгоре",
|
||||
"insert-below": "Вмъкни отдолу",
|
||||
"instructions": "Инструкции",
|
||||
"instructions": "Начин на приготвяне",
|
||||
"key-name-required": "Ключовото име е задължително",
|
||||
"landscape-view-coming-soon": "Пейзажен изглед",
|
||||
"milligrams": "милиграма",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Рецептата е изтрита",
|
||||
"recipe-image": "Изображение на рецептата",
|
||||
"recipe-image-updated": "Изображението на рецептата беше обновено",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Итриване на изображението на рецептата",
|
||||
"delete-image-confirmation": "Сигурни ли сте, че желаете да изтриете изображението на рецептата?",
|
||||
"recipe-image-deleted": "Изображението на рецептата беше изтрито",
|
||||
"recipe-name": "Наименование",
|
||||
"recipe-settings": "Настройки на рецептата",
|
||||
"recipe-update-failed": "Обновяването на рецептата беше неуспешно",
|
||||
@@ -548,8 +552,8 @@
|
||||
"entry-type": "Тип на записа",
|
||||
"date-format-hint": "MM/DD/YYYY формат",
|
||||
"date-format-hint-yyyy-mm-dd": "YYYY-MM-DD формат",
|
||||
"add-to-list": "Добавяне към списък",
|
||||
"add-to-plan": "Добавяне към план",
|
||||
"add-to-list": "Добавяне към списък за пазаруване",
|
||||
"add-to-plan": "Добави към меню",
|
||||
"add-to-timeline": "Добавяне към историята на събитията",
|
||||
"recipe-added-to-list": "Рецептата е добавена към списъка",
|
||||
"recipes-added-to-list": "Рецептите са добавени към списъка",
|
||||
@@ -565,15 +569,16 @@
|
||||
"choose-unit": "Избери мерна единица",
|
||||
"press-enter-to-create": "Натисните Enter за да създадете",
|
||||
"choose-food": "Избери продукт",
|
||||
"choose-recipe": "Избор на рецепта",
|
||||
"notes": "Бележки",
|
||||
"toggle-section": "Превключване на раздела",
|
||||
"toggle-section": "Създай раздел",
|
||||
"see-original-text": "Виж оригиналния текст",
|
||||
"original-text-with-value": "Оригинален текст: {originalText}",
|
||||
"ingredient-linker": "Инструмент за свързване на съставки",
|
||||
"unlinked": "Все още не е свързано",
|
||||
"linked-to-other-step": "Свързано към друга стъпка",
|
||||
"auto": "Автоматично",
|
||||
"cook-mode": "Начин на приготвяне",
|
||||
"cook-mode": "Инструкции",
|
||||
"link-ingredients": "Свържи съставки",
|
||||
"merge-above": "Обедини с по-горната стъпка",
|
||||
"move-to-bottom": "Премести най-долу",
|
||||
@@ -588,11 +593,11 @@
|
||||
"timeline-is-empty": "Няма история на събитията. Опитайте да приготвите рецептата!",
|
||||
"timeline-no-events-found-try-adjusting-filters": "Няма намерени събития. Опитайте да промените филтрите си за търсене.",
|
||||
"group-global-timeline": "{groupName} История на събитията",
|
||||
"open-timeline": "История на събитията",
|
||||
"open-timeline": "Хронология на събитията",
|
||||
"made-this": "Сготвих рецептата",
|
||||
"how-did-it-turn-out": "Как се получи?",
|
||||
"user-made-this": "{user} направи това",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"user-made-this": "{user} сготви",
|
||||
"made-for-recipe": "Направено за {recipe}",
|
||||
"added-to-timeline": "Добавено към историята на събитията",
|
||||
"failed-to-add-to-timeline": "Неуспешно добавяне към историята на събитията",
|
||||
"failed-to-update-recipe": "Неуспешно актуализиране на рецептата",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Пробвайте масовото импорторане",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Имате ли сурови HTML или JSON данни?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Можете да импортирате директно от сурови данни",
|
||||
"scrape-recipe-website-being-blocked": "Блокиран ли е уебсайтът?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Опитайте вместо това да импортирате суровия HTML код.",
|
||||
"import-original-keywords-as-tags": "Добави оригиналните ключови думи като етикети",
|
||||
"stay-in-edit-mode": "Остани в режим на редакция",
|
||||
"parse-recipe-ingredients-after-import": "Анализиране на съставките на рецептата след импортиране",
|
||||
@@ -695,9 +702,9 @@
|
||||
"upload-more-images": "Качете още изображения",
|
||||
"set-as-cover-image": "Задай като изображение на корицата на рецептата",
|
||||
"cover-image": "Изображение на корицата",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"include-linked-recipes": "Влючване на свързаните рецепти",
|
||||
"include-linked-recipe-ingredients": "Включване на съставките от свързаните рецепти",
|
||||
"toggle-recipe": "Вмъкни рецепта"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Търсачка на рецепти",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Натисни '/'",
|
||||
"advanced": "Разширени",
|
||||
"auto-search": "Автоматично търсене",
|
||||
"no-results": "Не са намерени резултати"
|
||||
"no-results": "Не са намерени резултати",
|
||||
"type-to-search": "Въведете текст за търсене..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Добавяне на нова тема",
|
||||
@@ -801,7 +809,7 @@
|
||||
"error-creating-theme-see-log-file": "Грешка при създаването на темата. Виж лог файла.",
|
||||
"error-deleting-theme": "Грешка при изтриването на темата",
|
||||
"error-updating-theme": "Грешка при актуализирането на темата",
|
||||
"info": "Инфо",
|
||||
"info": "Информация",
|
||||
"light": "Светла",
|
||||
"primary": "Основен",
|
||||
"secondary": "Вторичен",
|
||||
@@ -866,7 +874,7 @@
|
||||
"failed": "Неуспешно",
|
||||
"general-about": "Основни настройки",
|
||||
"application-version": "Версия на приложението",
|
||||
"application-version-error-text": "Вашата текуща версия ({0}) не съответства на най-новата версия. Обмисляте актуализиране до най-новата версия ({1}).",
|
||||
"application-version-error-text": "Вашата текуща версия ({0}) не съответства на най-новата версия. Обмислете актуализиране до най-новата версия ({1}).",
|
||||
"mealie-is-up-to-date": "Mealie е обновен до актуалната версия",
|
||||
"secure-site": "Сигурен сайт",
|
||||
"secure-site-error-text": "Сервирайте чрез localhost или защитено с https. Клипбордът и допълнителните API на браузъра може да не работят.",
|
||||
@@ -967,14 +975,14 @@
|
||||
"tag": "Етикет"
|
||||
},
|
||||
"tool": {
|
||||
"tools": "Инструменти",
|
||||
"tools": "Прибори",
|
||||
"on-hand": "Наличности",
|
||||
"create-a-tool": "Създаване на инструмент",
|
||||
"tool-name": "Име на инструмента",
|
||||
"create-new-tool": "Създаване на нов инструмент",
|
||||
"on-hand-checkbox-label": "Показване като налични (отметнато)",
|
||||
"required-tools": "Задължителни инструменти",
|
||||
"tool": "Инструменти"
|
||||
"tool": "Прибори"
|
||||
},
|
||||
"user": {
|
||||
"admin": "Админ",
|
||||
@@ -1015,7 +1023,7 @@
|
||||
"please-enter-password": "Моля, въведете новата си парола.",
|
||||
"register": "Регистриране",
|
||||
"reset-password": "Забравена парола",
|
||||
"sign-in": "Вписване",
|
||||
"sign-in": "Вход в системата",
|
||||
"total-mealplans": "Хранителни планове общо",
|
||||
"total-users": "Общо потребители",
|
||||
"upload-photo": "Качете снимка",
|
||||
@@ -1054,7 +1062,7 @@
|
||||
"very-strong": "Много силна"
|
||||
},
|
||||
"user-management": "Управление на потребителя",
|
||||
"reset-locked-users": "Нулиране на заключените потребители",
|
||||
"reset-locked-users": "Отключване на заключените потребители",
|
||||
"admin-user-creation": "Създаване на администратор",
|
||||
"admin-user-management": "Управление на администраторите",
|
||||
"user-details": "Детайли за потребителя",
|
||||
@@ -1095,7 +1103,7 @@
|
||||
"create-food": "Създай продукт",
|
||||
"food-label": "Заглавие на храната",
|
||||
"edit-food": "Редактирай храна",
|
||||
"food-data": "Данни за храните",
|
||||
"food-data": "Продукти",
|
||||
"example-food-singular": "пример: Домат",
|
||||
"example-food-plural": "пример: Домати",
|
||||
"label-overwrite-warning": "Това ще присвои избрания етикет на всички избрани храни и евентуално ще презапише съществуващите ви етикети.",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "е като",
|
||||
"is-not-like": "не е като"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "Това поле е задължително",
|
||||
"invalid-email": "Email адресът трябва да бъде валиден",
|
||||
"invalid-url": "Линкът трябва да е валиден",
|
||||
"no-whitespace": "Не са позволени интервали",
|
||||
"min-length": "Трябва да съдържа поне {min} знака",
|
||||
"max-length": "Трябва да съдържа най-много {max} знака"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Esmorzar",
|
||||
"lunch": "Dinar",
|
||||
"dinner": "Sopar",
|
||||
"snack": "Piscolabis",
|
||||
"drink": "Beguda",
|
||||
"dessert": "Postres",
|
||||
"type-any": "Qualsevol",
|
||||
"day-any": "Qualsevol",
|
||||
"editor": "Editor",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Puja una recepta",
|
||||
"upload-individual-zip-file": "Puja només un arxiu zip, exportat d'altre Mealie.",
|
||||
"url-form-hint": "Copia i enganxa l'enllaç del teu lloc web de receptes preferit",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "Visualitza les dades recuperades",
|
||||
"trim-whitespace-description": "Elimina els espais a principi i final; i elimina les línies buides",
|
||||
"trim-prefix-description": "Elimina el primer caràcter de cada línia",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Importa per URL",
|
||||
"create-manually": "Crea una recepta manualment",
|
||||
"make-recipe-image": "Fes-la la imatge de la recepta",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Afegeix Aliment",
|
||||
"add-recipe": "Afegeix Recepta"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 - Pàgina no trobada",
|
||||
@@ -480,7 +484,7 @@
|
||||
"comment": "Comentari",
|
||||
"comments": "Comentaris",
|
||||
"delete-confirmation": "Estàs segur que vols suprimir-la?",
|
||||
"admin-delete-confirmation": "You're about to delete a recipe that isn't yours using admin permissions. Are you sure?",
|
||||
"admin-delete-confirmation": "Estàs a punt d'eliminar una recepta que no és teva utilitzant permisos d'administrador. N'estàs segur?",
|
||||
"delete-recipe": "Suprimeix la recepta",
|
||||
"description": "Descripció",
|
||||
"disable-amount": "Oculta les quantitats",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "S'ha suprimit la recepta",
|
||||
"recipe-image": "Imatge de la recepta",
|
||||
"recipe-image-updated": "S'ha actualitzat la imatge de la recepta",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Suprimir la imatge de la recepta",
|
||||
"delete-image-confirmation": "Estàs segur que vols suprimir la imatge d'aquesta recepta?",
|
||||
"recipe-image-deleted": "S'ha suprimit la imatge de la recepta",
|
||||
"recipe-name": "Nom de la recepta",
|
||||
"recipe-settings": "Opcions de la recepta",
|
||||
"recipe-update-failed": "S'ha produït un error a l'actualitzar la recepta",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Tria el tipus d'unitat",
|
||||
"press-enter-to-create": "Premeu enter per a crear-lo",
|
||||
"choose-food": "Tria un aliment",
|
||||
"choose-recipe": "Tria la recepta",
|
||||
"notes": "Notes",
|
||||
"toggle-section": "Nova secció",
|
||||
"see-original-text": "Mostra el text original",
|
||||
@@ -596,11 +601,11 @@
|
||||
"added-to-timeline": "Added to timeline",
|
||||
"failed-to-add-to-timeline": "Failed to add to timeline",
|
||||
"failed-to-update-recipe": "Failed to update recipe",
|
||||
"added-to-timeline-but-failed-to-add-image": "Added to timeline, but failed to add image",
|
||||
"added-to-timeline-but-failed-to-add-image": "S'ha afegit a la línia de temps, però no s'ha pogut afegir la imatge",
|
||||
"api-extras-description": "Els extres de receptes són una funcionalitat clau de l'API de Mealie. Permeten crear parells clau/valor JSON personalitzats dins una recepta, per referenciar-los des d'aplicacions de tercers. Pots emprar aquestes claus per proveir informació, per exemple per a desencadenar automatitzacions o missatges personlitzats per a propagar al teu dispositiu desitjat.",
|
||||
"message-key": "Clau del missatge",
|
||||
"parse": "Analitzar",
|
||||
"ingredients-not-parsed-description": "It looks like your ingredients aren't parsed yet. Click the \"{parse}\" button below to parse your ingredients into structured foods.",
|
||||
"ingredients-not-parsed-description": "Sembla que els teus ingredients encara no s'han analitzat. Feu clic al botó \"{parse}\" de sota per transformar els vostres ingredients en aliments estructurats.",
|
||||
"attach-images-hint": "Afegeix imatges arrossegant i deixant anar la imatge a l'editor",
|
||||
"drop-image": "Deixa anar la imatge",
|
||||
"enable-ingredient-amounts-to-use-this-feature": "Habilita les quantitats d'ingredients per a poder fer servir aquesta característica",
|
||||
@@ -618,10 +623,10 @@
|
||||
"create-recipe-from-an-image": "Crear una recepta a partir d'una imatge",
|
||||
"create-recipe-from-an-image-description": "Crear una recepta pujant una imatge d'ella. Mealie intentarà extreure el text de la imatge mitjançant IA i crear-ne la recepta.",
|
||||
"crop-and-rotate-the-image": "Retalla i rota la imatge, per tal que només el text sigui visible, i estigui orientat correctament.",
|
||||
"create-from-images": "Create from Images",
|
||||
"create-from-images": "Crear una recepta a partir d'una imatge",
|
||||
"should-translate-description": "Tradueix la recepta a la meva llengua",
|
||||
"please-wait-image-procesing": "Si us plau, esperi, la imatge s'està processant. Això pot tardar un temps.",
|
||||
"please-wait-images-processing": "Please wait, the images are processing. This may take some time.",
|
||||
"please-wait-images-processing": "Espereu, les imatges s'estan processant. Això pot trigar una estona.",
|
||||
"bulk-url-import": "Importació d'URL en massa",
|
||||
"debug-scraper": "Rastrejador de depuració",
|
||||
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "Crea la recepta proporcionant-ne un nom. Totes les receptes han de tenir un nom únic.",
|
||||
@@ -632,9 +637,11 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Prova l'importador a granel",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Teniu dades HTML o JSON pla?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Podeu importar directament des de les dades planes",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "Importa les paraules clau originals com a tags",
|
||||
"stay-in-edit-mode": "Segueix en el mode d'edició",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
"parse-recipe-ingredients-after-import": "Analitza els ingredients de la recepta després d'importar",
|
||||
"import-from-zip": "Importa des d'un ZIP",
|
||||
"import-from-zip-description": "Importa una sola recepta que ha estat importada d'una altra instància de Mealie.",
|
||||
"import-from-html-or-json": "Importar des d'un HTML o JSON",
|
||||
@@ -678,26 +685,26 @@
|
||||
"no-unit": "Sense unitat",
|
||||
"missing-unit": "Crear unitat que manca: {unit}",
|
||||
"missing-food": "Crear menjar que manca: {food}",
|
||||
"this-unit-could-not-be-parsed-automatically": "This unit could not be parsed automatically",
|
||||
"this-food-could-not-be-parsed-automatically": "This food could not be parsed automatically",
|
||||
"this-unit-could-not-be-parsed-automatically": "Aquesta unitat no s'ha pogut analitzar automàticament",
|
||||
"this-food-could-not-be-parsed-automatically": "Aquest aliment no s'ha pogut analitzar automàticament",
|
||||
"no-food": "Sense menjar",
|
||||
"review-parsed-ingredients": "Review parsed ingredients",
|
||||
"confidence-score": "Confidence Score",
|
||||
"ingredient-parser-description": "Your ingredients have been successfully parsed. Please review the ingredients we're not sure about.",
|
||||
"ingredient-parser-final-review-description": "Once all ingredients have been reviewed, you'll have one more chance to review all ingredients before applying the changes to your recipe.",
|
||||
"add-text-as-alias-for-item": "Add \"{text}\" as alias for {item}",
|
||||
"delete-item": "Delete Item"
|
||||
"review-parsed-ingredients": "Revisió d'ingredients analitzats",
|
||||
"confidence-score": "Puntuació de confiança",
|
||||
"ingredient-parser-description": "Els teus ingredients s'han analitzat correctament. Si us plau, revisa els ingredients dels quals no estem segurs.",
|
||||
"ingredient-parser-final-review-description": "Un cop revisats tots els ingredients, tindràs una oportunitat més de revisar tots els ingredients abans d'aplicar els canvis a la teva recepta.",
|
||||
"add-text-as-alias-for-item": "Afegeix \"{text}\" com a àlies de {item}",
|
||||
"delete-item": "Eliminar element"
|
||||
},
|
||||
"reset-servings-count": "Reiniciar racions servides",
|
||||
"not-linked-ingredients": "Ingredients addicionals",
|
||||
"upload-another-image": "Upload another image",
|
||||
"upload-images": "Upload images",
|
||||
"upload-more-images": "Upload more images",
|
||||
"set-as-cover-image": "Set as recipe cover image",
|
||||
"cover-image": "Cover image",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"upload-another-image": "Puja una altra imatge",
|
||||
"upload-images": "Puja imatges",
|
||||
"upload-more-images": "Puja més imatges",
|
||||
"set-as-cover-image": "Estableix com a imatge de portada de recepta",
|
||||
"cover-image": "Imatge de portada",
|
||||
"include-linked-recipes": "Inclou les receptes enllaçades",
|
||||
"include-linked-recipe-ingredients": "Inclou els ingredients de la recepta enllaçada",
|
||||
"toggle-recipe": "Alternar recepta"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Cercador de receptes",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Prem '/'",
|
||||
"advanced": "Avançat",
|
||||
"auto-search": "Cerca automàtica",
|
||||
"no-results": "No s'han trobat resultats"
|
||||
"no-results": "No s'han trobat resultats",
|
||||
"type-to-search": "Escriviu per cercar..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Afegiu un nou tema",
|
||||
@@ -1073,8 +1081,8 @@
|
||||
"forgot-password": "Contrasenya oblidada",
|
||||
"forgot-password-text": "Introdueix siusplau la teva adreça de correu electrònic i t'enviarem un enllaç per restablir la teva contrassenya.",
|
||||
"changes-reflected-immediately": "Els canvis en aquest usuari s'actualitzaran immediatament.",
|
||||
"default-activity": "Default Activity",
|
||||
"default-activity-hint": "Select which page you'd like to navigate to upon logging in from this device"
|
||||
"default-activity": "Activitat per defecte",
|
||||
"default-activity-hint": "Seleccioneu a quina pàgina voleu navegar en iniciar sessió des d'aquest dispositiu"
|
||||
},
|
||||
"language-dialog": {
|
||||
"translated": "traduït",
|
||||
@@ -1192,7 +1200,7 @@
|
||||
"group-details": "Detalls del grup",
|
||||
"group-details-description": "Abans de crear un compte heu de crear un grup. Al grup només hi serà vostè, però després podeu convidar d'altres. Els membres d'un grup poden compartir menús, llistes de la compra, receptes i molt més!",
|
||||
"use-seed-data": "Afegiu dades predeterminades",
|
||||
"use-seed-data-description": "Mealie ships with a collection of Foods, Units, and Labels that can be used to populate your group with helpful data for organizing your recipes. These are translated into the language you currently have selected. You can always add to or modify this data later.",
|
||||
"use-seed-data-description": "Mealie disposa d'una col·lecció d'aliments, unitats i etiquetes que es poden utilitzar per omplir el vostre grup amb dades útils per organitzar les vostres receptes. Aquests es tradueixen a l'idioma que heu seleccionat actualment. Sempre podeu afegir o modificar aquestes dades més endavant.",
|
||||
"account-details": "Detalls del compte"
|
||||
},
|
||||
"validation": {
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "és com",
|
||||
"is-not-like": "no és com"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Snídaně",
|
||||
"lunch": "Oběd",
|
||||
"dinner": "Večeře",
|
||||
"snack": "Svačina",
|
||||
"drink": "Nápoje",
|
||||
"dessert": "Dezerty",
|
||||
"type-any": "Libovolné",
|
||||
"day-any": "Libovolný",
|
||||
"editor": "Editor",
|
||||
@@ -400,7 +403,7 @@
|
||||
"title": "Recepty Tandoor"
|
||||
},
|
||||
"cookn": {
|
||||
"description-long": "Mealie can import recipes from DVO Cook'n X3. Export a cookbook or menu in the \"Cook'n\" format, rename the export extension to .zip, then upload the .zip below.",
|
||||
"description-long": "Mealie může importovat recept z DVO Cook'n X3. Exportujte kuchařku nebo menu ve formátu \"Cook'n\", přejmenujte rozšíření exportu na .zip, poté nahrajte .zip níže.",
|
||||
"title": "DVO Cook'n X3"
|
||||
},
|
||||
"recipe-data-migrations": "Migrace dat receptů",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Nahrát recept",
|
||||
"upload-individual-zip-file": "Nahrát individuální .zip soubor exportovaný z jiné instance Mealie.",
|
||||
"url-form-hint": "Zkopírujte a vložte odkaz z vaší oblíbené stránky s recepty",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Zkopírujte a vložte zdrojovou adresu URL vašich dat (volitelné)",
|
||||
"view-scraped-data": "Zobrazit scrapovaná data",
|
||||
"trim-whitespace-description": "Oříznout počáteční a koncové mezery stejně jako prázdné řádky",
|
||||
"trim-prefix-description": "Oříznout první znak z každé řádky",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Importovat recept podle URL",
|
||||
"create-manually": "Vytvořit recept ručně",
|
||||
"make-recipe-image": "Nastavit jako obrázek receptu",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Přidat jídlo",
|
||||
"add-recipe": "Přidat recept"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Stránka nebyla nalezena",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Recept smazán",
|
||||
"recipe-image": "Obrázek receptu",
|
||||
"recipe-image-updated": "Obrázek receptu aktualizován",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Smazat recept",
|
||||
"delete-image-confirmation": "Opravdu chcete smazat tento recept?",
|
||||
"recipe-image-deleted": "Recept smazán",
|
||||
"recipe-name": "Název receptu",
|
||||
"recipe-settings": "Nastavení receptu",
|
||||
"recipe-update-failed": "Aktualizace receptu se nezdařila",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Vybrat jednotku",
|
||||
"press-enter-to-create": "Stiskněte enter pro vytvoření",
|
||||
"choose-food": "Zvolte jídlo",
|
||||
"choose-recipe": "Vybrat recept",
|
||||
"notes": "Poznámky",
|
||||
"toggle-section": "Přidat/odebrat název sekce",
|
||||
"see-original-text": "Zobrazit původní text",
|
||||
@@ -592,7 +597,7 @@
|
||||
"made-this": "Toto jsem uvařil",
|
||||
"how-did-it-turn-out": "Jak to dopadlo?",
|
||||
"user-made-this": "{user} udělal toto",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"made-for-recipe": "Vytvořeno pro {recipe}",
|
||||
"added-to-timeline": "Přidáno na časovou osu",
|
||||
"failed-to-add-to-timeline": "Přidání na časovou osu selhalo",
|
||||
"failed-to-update-recipe": "Aktualizace receptu selhala",
|
||||
@@ -632,9 +637,11 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Vyzkoušejte hromadný import",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Máte surová data HTML nebo JSON?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Můžete importovat přímo ze surových dat",
|
||||
"scrape-recipe-website-being-blocked": "Webové stránky jsou blokovány?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Zkuste namísto toho importovat raw HTML.",
|
||||
"import-original-keywords-as-tags": "Importovat původní klíčová slova jako štítky",
|
||||
"stay-in-edit-mode": "Zůstat v režimu úprav",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
"parse-recipe-ingredients-after-import": "Po importu analyzovat ingredience receptu",
|
||||
"import-from-zip": "Importovat ze zipu",
|
||||
"import-from-zip-description": "Importovat jeden recept, který byl exportován z jiné instance Mealie.",
|
||||
"import-from-html-or-json": "Importovat z HTML nebo JSON",
|
||||
@@ -681,12 +688,12 @@
|
||||
"this-unit-could-not-be-parsed-automatically": "Tuto jednotku nelze analyzovat automaticky",
|
||||
"this-food-could-not-be-parsed-automatically": "Toto jídlo nelze analyzovat automaticky",
|
||||
"no-food": "Žádné jídlo",
|
||||
"review-parsed-ingredients": "Review parsed ingredients",
|
||||
"confidence-score": "Confidence Score",
|
||||
"ingredient-parser-description": "Your ingredients have been successfully parsed. Please review the ingredients we're not sure about.",
|
||||
"ingredient-parser-final-review-description": "Once all ingredients have been reviewed, you'll have one more chance to review all ingredients before applying the changes to your recipe.",
|
||||
"add-text-as-alias-for-item": "Add \"{text}\" as alias for {item}",
|
||||
"delete-item": "Delete Item"
|
||||
"review-parsed-ingredients": "Zkontrolovat analyzované ingredience",
|
||||
"confidence-score": "Skóre spolehlivosti",
|
||||
"ingredient-parser-description": "Vaše suroviny byly úspěšně analyzovány. Prosím zkontrolujte ingredience, o kterých si nejsme jisti.",
|
||||
"ingredient-parser-final-review-description": "Jakmile budou všechny ingredience zkontrolovány, budete mít ještě jednu šanci zkontrolovat všechny ingredience před použitím změn ve vašem receptu.",
|
||||
"add-text-as-alias-for-item": "Přidat \"{text}\" jako alias pro {item}",
|
||||
"delete-item": "Odstranit položku"
|
||||
},
|
||||
"reset-servings-count": "Resetovat počet porcí",
|
||||
"not-linked-ingredients": "Další ingredience",
|
||||
@@ -695,9 +702,9 @@
|
||||
"upload-more-images": "Nahrát více obrázků",
|
||||
"set-as-cover-image": "Nastavit recept jako úvodní obrázek",
|
||||
"cover-image": "Úvodní obrázek",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"include-linked-recipes": "Zahrnout připojené recepty",
|
||||
"include-linked-recipe-ingredients": "Zahrnout připojené ingredience",
|
||||
"toggle-recipe": "Přidat/odebrat název sekce"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Vyhledávač receptů",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Stiskněte '/'",
|
||||
"advanced": "Pokročilé",
|
||||
"auto-search": "Automatické vyhledávání",
|
||||
"no-results": "Nebyly nalezeny žádné výsledky"
|
||||
"no-results": "Nebyly nalezeny žádné výsledky",
|
||||
"type-to-search": "Zadejte hledaný výraz..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Přidat nový motiv",
|
||||
@@ -1073,8 +1081,8 @@
|
||||
"forgot-password": "Zapomenuté heslo",
|
||||
"forgot-password-text": "Zadejte prosím svou e-mailovou adresu a my vám zašleme odkaz pro obnovení hesla.",
|
||||
"changes-reflected-immediately": "Změny tohoto uživatele budou okamžitě zohledněny.",
|
||||
"default-activity": "Default Activity",
|
||||
"default-activity-hint": "Select which page you'd like to navigate to upon logging in from this device"
|
||||
"default-activity": "Výchozí aktivita",
|
||||
"default-activity-hint": "Vyberte stránku, na kterou chcete přejít po přihlášení z tohoto zařízení"
|
||||
},
|
||||
"language-dialog": {
|
||||
"translated": "přeloženo",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "je jako",
|
||||
"is-not-like": "není jako"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "Toto pole je povinné",
|
||||
"invalid-email": "E-mail musí být platný",
|
||||
"invalid-url": "Musí být platná URL adresa",
|
||||
"no-whitespace": "Prázdný prostor není povolen",
|
||||
"min-length": "Musí být alespoň {min} znaků",
|
||||
"max-length": "Musí být nejvíce {max} znaků"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Morgenmad",
|
||||
"lunch": "Frokost",
|
||||
"dinner": "Aftensmad",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Alle",
|
||||
"day-any": "Alle",
|
||||
"editor": "Redigeringsværktøj",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Upload en opskrift",
|
||||
"upload-individual-zip-file": "Upload en individuel .zip-fil, eksporteret fra en anden Mealie-instans.",
|
||||
"url-form-hint": "Kopiér og indsæt et link fra din foretrukne opskrifts hjemmeside",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "Vis dataudtræk",
|
||||
"trim-whitespace-description": "Fjern indledende og efterfølgende mellemrum samt blanke linjer",
|
||||
"trim-prefix-description": "Beskær første tegn fra hver linje",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Importér opskrift fra en webside",
|
||||
"create-manually": "Opret opskrift manuelt",
|
||||
"make-recipe-image": "Gør dette til opskriftsbillede",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Tilføj Mad",
|
||||
"add-recipe": "Tilføj opskrift"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Siden blev ikke fundet",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Opskrift slettet",
|
||||
"recipe-image": "Opskriftsbillede",
|
||||
"recipe-image-updated": "Opskriftsbillede ændret",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Slet Opskrift Billede",
|
||||
"delete-image-confirmation": "Er du sikker på, du vil slette dette opskrift billede?",
|
||||
"recipe-image-deleted": "Opskrift billede slettet",
|
||||
"recipe-name": "Opskriftens navn",
|
||||
"recipe-settings": "Opskriftsindstillinger",
|
||||
"recipe-update-failed": "Opdatering af opskrift fejlede",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Vælg enhed",
|
||||
"press-enter-to-create": "Tryk enter for at oprette",
|
||||
"choose-food": "Vælg fødevarer",
|
||||
"choose-recipe": "Vælg Opskrift",
|
||||
"notes": "Kommentarer",
|
||||
"toggle-section": "Sektion",
|
||||
"see-original-text": "Vis den oprindelige tekst",
|
||||
@@ -592,7 +597,7 @@
|
||||
"made-this": "Jeg har lavet denne",
|
||||
"how-did-it-turn-out": "Hvordan blev det?",
|
||||
"user-made-this": "{user} lavede denne",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"made-for-recipe": "Lavet til {recipe}",
|
||||
"added-to-timeline": "Tilføjet til tidslinjen",
|
||||
"failed-to-add-to-timeline": "Kunne ikke tilføje til tidslinjen",
|
||||
"failed-to-update-recipe": "Kunne ikke opdatere opskrift",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Prøv masseimport",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Har rå HTML- eller JSON-data?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Du kan importere direkte fra rå data",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "Importér originale nøgleord som mærker",
|
||||
"stay-in-edit-mode": "Bliv i redigeringstilstand",
|
||||
"parse-recipe-ingredients-after-import": "Fortolk opskrift ingredienser efter import",
|
||||
@@ -695,9 +702,9 @@
|
||||
"upload-more-images": "Upload flere billeder",
|
||||
"set-as-cover-image": "Angiv som opskriftens coverbillede",
|
||||
"cover-image": "Coverbillede",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"include-linked-recipes": "Inkluder Relaterede Opskrifter",
|
||||
"include-linked-recipe-ingredients": "Inkluder Relaterede Opskrift Ingredienser",
|
||||
"toggle-recipe": "Vis/Skjul Opskrift"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Opskriftssøger",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Tryk '/'",
|
||||
"advanced": "Avanceret",
|
||||
"auto-search": "Automatisk søgning",
|
||||
"no-results": "Ingen resultater fundet"
|
||||
"no-results": "Ingen resultater fundet",
|
||||
"type-to-search": "Skriv for at søge..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Tilføj et nyt tema",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "er ligesom",
|
||||
"is-not-like": "er ikke som"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"category": "Kategorie"
|
||||
},
|
||||
"events": {
|
||||
"apprise-url": "Apprise-URL",
|
||||
"apprise-url": "Apprise URL",
|
||||
"database": "Datenbank",
|
||||
"delete-event": "Ereignis löschen",
|
||||
"event-delete-confirmation": "Bist du dir sicher, dass du dieses Ereignis löschen möchtest?",
|
||||
@@ -191,7 +191,7 @@
|
||||
"menu": "Menü",
|
||||
"a-name-is-required": "Ein Name wird benötigt",
|
||||
"delete-with-name": "{name} löschen",
|
||||
"confirm-delete-generic-with-name": "Bist du dir sicher, dass du dies löschen möchtest?",
|
||||
"confirm-delete-generic-with-name": "Bist du dir sicher, dass du {name} löschen möchtest?",
|
||||
"confirm-delete-own-admin-account": "Bitte beachte, dass du versuchst, dein eigenes Administrator-Konto zu löschen! Diese Aktion kann nicht rückgängig gemacht werden und wird dein Konto dauerhaft löschen?",
|
||||
"organizer": "Organisator",
|
||||
"transfer": "Übertragen",
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Frühstück",
|
||||
"lunch": "Mittagessen",
|
||||
"dinner": "Abendessen",
|
||||
"snack": "Zwischenmahlzeit ",
|
||||
"drink": "Getränk",
|
||||
"dessert": "Nachspeise",
|
||||
"type-any": "Alle",
|
||||
"day-any": "Alle",
|
||||
"editor": "Bearbeiten",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Rezept hochladen",
|
||||
"upload-individual-zip-file": "Lade eine individuelle .zip-Datei hoch, die von einer anderen Mealie-Instanz exportiert wird.",
|
||||
"url-form-hint": "Kopiere einen Link von deiner Lieblingsrezept-Website und füge ihn ein",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Kopieren und fügen Sie die Quell-URL Ihrer Daten ein (optional)",
|
||||
"view-scraped-data": "Gesammelte Daten anzeigen",
|
||||
"trim-whitespace-description": "Leerzeichen am Anfang und Ende sowie leere Zeilen entfernen",
|
||||
"trim-prefix-description": "Erste Zeichen aus jeder Zeile entfernen",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Ein Rezept von einer Webseite importieren",
|
||||
"create-manually": "Ein Rezept manuell erstellen",
|
||||
"make-recipe-image": "Als Rezept-Titelbild verwenden",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Lebensmittel",
|
||||
"add-recipe": "Rezepte hinzufügen"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Seite nicht gefunden",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Rezept entfernt",
|
||||
"recipe-image": "Rezeptbild",
|
||||
"recipe-image-updated": "Rezeptbild aktualisiert",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Rezeptbild löschen",
|
||||
"delete-image-confirmation": "Bist du dir sicher, dass du dieses Rezept löschen möchtest?",
|
||||
"recipe-image-deleted": "Rezeptbild gelöscht",
|
||||
"recipe-name": "Rezeptname",
|
||||
"recipe-settings": "Rezepteinstellungen",
|
||||
"recipe-update-failed": "Aktualisieren des Rezepts fehlgeschlagen",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Einheit wählen",
|
||||
"press-enter-to-create": "Zum Erstellen Eingabetaste drücken",
|
||||
"choose-food": "Lebensmittel wählen",
|
||||
"choose-recipe": "Rezept wählen",
|
||||
"notes": "Notizen",
|
||||
"toggle-section": "Überschrift ein-/ausblenden",
|
||||
"see-original-text": "Originaltext anzeigen",
|
||||
@@ -592,7 +597,7 @@
|
||||
"made-this": "Ich hab's gemacht",
|
||||
"how-did-it-turn-out": "Wie ist es geworden?",
|
||||
"user-made-this": "{user} hat's gemacht",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"made-for-recipe": "Erstellt für {recipe}",
|
||||
"added-to-timeline": "Zur Zeitleiste hinzugefügt",
|
||||
"failed-to-add-to-timeline": "Fehler beim Hinzufügen zur Zeitleiste",
|
||||
"failed-to-update-recipe": "Fehler beim Aktualisieren des Rezepts",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Probiere den Massenimporter aus",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Hast du Roh-HTML oder JSON Daten?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Du kannst direkt von Rohdaten importieren",
|
||||
"scrape-recipe-website-being-blocked": "Die Website wird blockiert?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Versuchen Sie stattdessen das reine HTML zu importieren.",
|
||||
"import-original-keywords-as-tags": "Importiere ursprüngliche Stichwörter als Schlagwörter",
|
||||
"stay-in-edit-mode": "Im Bearbeitungsmodus bleiben",
|
||||
"parse-recipe-ingredients-after-import": "Zutaten nach dem Import parsen",
|
||||
@@ -695,9 +702,9 @@
|
||||
"upload-more-images": "Weitere Bilder hochladen",
|
||||
"set-as-cover-image": "Als Rezept-Titelbild setzen",
|
||||
"cover-image": "Titelbild",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"include-linked-recipes": "Verknüpfte Rezepte einbeziehen",
|
||||
"include-linked-recipe-ingredients": "Zutaten verknüpfter Rezepte einbeziehen",
|
||||
"toggle-recipe": "Rezept ein/aus"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Rezept-Suche",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "'/' drücken",
|
||||
"advanced": "Erweitert",
|
||||
"auto-search": "Automatische Suche",
|
||||
"no-results": "Keine Ergebnisse gefunden"
|
||||
"no-results": "Keine Ergebnisse gefunden",
|
||||
"type-to-search": "Suchbegriff eingeben..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Neues Thema hinzufügen",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "ist wie",
|
||||
"is-not-like": "ist nicht wie"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "Dieses Feld ist erforderlich",
|
||||
"invalid-email": "E-Mail muss gültig sein",
|
||||
"invalid-url": "Muss eine gültige URL sein",
|
||||
"no-whitespace": "Kein Leerzeichen erlaubt",
|
||||
"min-length": "Muss mindestens {min} Zeichen haben",
|
||||
"max-length": "Darf mindestens {max} Zeichen haben"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@
|
||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Μόνο συνταγές με αυτές τις κατηγορίες θα χρησιμοποιηθούν στα προγράμματα γευμάτων",
|
||||
"planner": "Προγραμματισμός",
|
||||
"quick-week": "Γρήγορη προβολή",
|
||||
"side": "Πλευρά",
|
||||
"side": "Συνοδευτικό",
|
||||
"sides": "Πλευρές",
|
||||
"start-date": "Ημερομηνία έναρξης",
|
||||
"rule-day": "Ημέρα/ες Κανόνα",
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Πρωινό",
|
||||
"lunch": "Μεσημεριανό",
|
||||
"dinner": "Βραδινό",
|
||||
"snack": "Σνακ",
|
||||
"drink": "Ποτό",
|
||||
"dessert": "Επιδόρπιο",
|
||||
"type-any": "Οτιδήποτε",
|
||||
"day-any": "Οποιαδήποτε",
|
||||
"editor": "Επεξεργαστής κειμένου",
|
||||
@@ -359,7 +362,7 @@
|
||||
"for-type-meal-types": "για γεύματα τύπου {0}",
|
||||
"meal-plan-rules": "Κανόνες Προγράμματος Γευμάτων",
|
||||
"new-rule": "Νέος κανόνας",
|
||||
"meal-plan-rules-description": "Μπορείτε να δημιουργήσετε κανόνες για την αυτόματη επιλογή συνταγών για τα προγράμματα γευμάτων. Αυτοί οι κανόνες χρησιμοποιούνται από το διακομιστή για τον προσδιορισμό της τυχαίας δεξαμενής συνταγών από τις οποίες μπορείτε να επιλέξετε κατά τη δημιουργία προγραμμάτων γευμάτων. Σημειώστε ότι αν οι κανόνες έχουν τους ίδιους περιορισμούς ημέρας/τύπου τότε τα φίλτρα κανόνων θα συγχωνευθούν. Στην πράξη, είναι περιττή η δημιουργία διπλότυπων κανόνων, είναι όμως εφικτή.",
|
||||
"meal-plan-rules-description": "Μπορείτε να δημιουργήσετε κανόνες για την αυτόματη επιλογή συνταγών για τα προγράμματα γευμάτων. Αυτοί οι κανόνες χρησιμοποιούνται από το διακομιστή για τον προσδιορισμό της δεξαμενής τυχαίας επιλογής συνταγής, κατά τη δημιουργία προγραμμάτων γευμάτων. Σημειώστε ότι αν οι κανόνες έχουν τους ίδιους περιορισμούς ημέρας/τύπου τότε τα φίλτρα κανόνων θα συγχωνευθούν. Στην πράξη, είναι περιττή η δημιουργία διπλότυπων κανόνων, είναι όμως εφικτή.",
|
||||
"new-rule-description": "Κατά τη δημιουργία ενός νέου κανόνα για ένα σχέδιο γεύματος, μπορείτε να περιορίσετε τον κανόνα ώστε να ισχύει για μια συγκεκριμένη ημέρα της εβδομάδας ή/και ένα συγκεκριμένο τύπο γεύματος. Για να εφαρμόσετε έναν κανόνα σε όλες τις ημέρες ή σε όλους τους τύπους γεύματος μπορείτε να ορίσετε τον κανόνα σε \"Ολα\" που θα τον εφαρμόσει σε όλες τις πιθανές τιμές για την ημέρα ή/και τον τύπο γεύματος.",
|
||||
"recipe-rules": "Κανόνες Συνταγής",
|
||||
"applies-to-all-days": "Εφαρμόζεται για όλες τις ημέρες",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Ανεβάστε μια συνταγή",
|
||||
"upload-individual-zip-file": "Ανεβάστε ένα μεμονωμένο αρχείο .zip που εξάγεται από μια άλλη περίπτωση Mealie.",
|
||||
"url-form-hint": "Αντιγράψτε και επικολλήστε έναν σύνδεσμο από την αγαπημένη σας ιστοσελίδα συνταγών",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Αντιγράψτε και επικολλήστε το πηγαίο URL των δεδομένων σας (προαιρετικό)",
|
||||
"view-scraped-data": "Προβολή Παραγόμενων Δεδομένων",
|
||||
"trim-whitespace-description": "Περικοπή κενών στην αρχή και το τέλος καθώς και των κενών γραμμών",
|
||||
"trim-prefix-description": "Περικοπή πρώτου χαρακτήρα από κάθε γραμμή",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Επιλέξτε μονάδα",
|
||||
"press-enter-to-create": "Πατήστε Enter για δημιουργία",
|
||||
"choose-food": "Επιλέξτε τρόφιμο",
|
||||
"choose-recipe": "Επιλέξτε συνταγή",
|
||||
"notes": "Σημειώσεις",
|
||||
"toggle-section": "Ενεργοποίηση/απενεργοποίηση τμήματος",
|
||||
"see-original-text": "Προβολή Αρχικού Κειμένου",
|
||||
@@ -601,7 +606,7 @@
|
||||
"message-key": "Κλειδί Μηνύματος",
|
||||
"parse": "Ανάλυση",
|
||||
"ingredients-not-parsed-description": "Φαίνεται ότι τα συστατικά σας δεν έχουν αναλυθεί ακόμα. Κάντε κλικ στο κουμπί \"{parse}\" παρακάτω για να αναλύσετε τα συστατικά σας σε δομημένα τρόφιμα.",
|
||||
"attach-images-hint": "Επισυνάψτε εικόνες σύροντας τις & αφήνοντάς τις στον επεξεργαστή",
|
||||
"attach-images-hint": "Επισυνάψτε εικόνες σύροντας & αφήνοντάς τες στον επεξεργαστή",
|
||||
"drop-image": "Απόθεση εικόνας",
|
||||
"enable-ingredient-amounts-to-use-this-feature": "Ενεργοποιήστε τις ποσότητες συστατικών για να χρησιμοποιήσετε αυτήν τη δυνατότητα",
|
||||
"recipes-with-units-or-foods-defined-cannot-be-parsed": "Δεν είναι δυνατή η ανάλυση συνταγών με καθορισμένες μονάδες ή τρόφιμα.",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Δοκιμάστε τον μαζικό εισαγωγέα συνταγών μας",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Εχουν ακατέργαστα δεδομένα HTML ή JSON;",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Μπορείτε να κάνετε εισαγωγή απευθείας από ακατέργαστα δεδομένα",
|
||||
"scrape-recipe-website-being-blocked": "Η ιστοσελίδα μπλοκάρεται;",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Δοκιμάστε να εισάγετε τον ακατέργαστο κώδικα HTML.",
|
||||
"import-original-keywords-as-tags": "Εισαγωγή αρχικών λέξεων-κλειδιών ως ετικέτες",
|
||||
"stay-in-edit-mode": "Παραμονή σε λειτουργία επεξεργασίας",
|
||||
"parse-recipe-ingredients-after-import": "Ανάλυση συστατικών συνταγής μετά την εισαγωγή",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Πατήστε '/'",
|
||||
"advanced": "Για προχωρημένους",
|
||||
"auto-search": "Αυτόματη Αναζήτηση",
|
||||
"no-results": "Δε βρέθηκαν αποτελέσματα"
|
||||
"no-results": "Δε βρέθηκαν αποτελέσματα",
|
||||
"type-to-search": "Πληκτρολογήστε για αναζήτηση…"
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Προσθήκη νέου θέματος",
|
||||
@@ -871,9 +879,9 @@
|
||||
"secure-site": "Ασφαλής Ιστοσελίδα",
|
||||
"secure-site-error-text": "Παροχή μέσω localhost ή ασφάλεια με https. Το πρόχειρο και τα πρόσθετα API προγράμματος περιήγησης μπορεί να μην λειτουργούν.",
|
||||
"secure-site-success-text": "Ο ιστότοπος έχει πρόσβαση από localhost ή https",
|
||||
"server-side-base-url": "Βασική Διεύθυνση URL Πλευράς Διακομιστή",
|
||||
"server-side-base-url": "Βασική διεύθυνση URL πλευράς διακομιστή",
|
||||
"server-side-base-url-error-text": "Το `BASE_URL` εξακολουθεί να είναι η προεπιλεγμένη τιμή στο διακομιστή API. Αυτό θα προκαλέσει προβλήματα με τις συνδέσεις ειδοποιήσεων που δημιουργούνται στο διακομιστή για email, κλπ.",
|
||||
"server-side-base-url-success-text": "Το URL Πλευράς Διακομιστή δεν ταιριάζει με την προεπιλογή",
|
||||
"server-side-base-url-success-text": "Η διεύθυνση URL πλευράς διακομιστή δεν ταιριάζει με την προεπιλεγμένη",
|
||||
"ldap-ready": "Ετοιμο για LDAP",
|
||||
"ldap-ready-error-text": "Δεν έχουν ρυθμιστεί όλες οι τιμές LDAP. Αυτό μπορεί να αγνοηθεί αν δεν χρησιμοποιείτε έλεγχο ταυτότητας LDAP.",
|
||||
"ldap-ready-success-text": "Ολες οι απαιτούμενες μεταβλητές LDAP έχουν οριστεί.",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "είναι όμοιο με",
|
||||
"is-not-like": "δεν είναι όμοιο με"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "Αυτό το πεδίο είναι υποχρεωτικό",
|
||||
"invalid-email": "Το e-mail πρέπει να είναι έγκυρο",
|
||||
"invalid-url": "Πρέπει να είναι μια έγκυρη διεύθυνση URL",
|
||||
"no-whitespace": "Δεν επιτρέπονται κενοί χαρακτήρες",
|
||||
"min-length": "Πρέπει να αποτελείται από τουλάχιστον {min} χαρακτήρες",
|
||||
"max-length": "Πρέπει να αποτελείται το πολύ από {max} χαρακτήρες"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Breakfast",
|
||||
"lunch": "Lunch",
|
||||
"dinner": "Dinner",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Any",
|
||||
"day-any": "Any",
|
||||
"editor": "Editor",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Upload a Recipe",
|
||||
"upload-individual-zip-file": "Upload an individual .zip file exported from another Mealie instance.",
|
||||
"url-form-hint": "Copy and paste a link from your favourite recipe website",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "View Scraped Data",
|
||||
"trim-whitespace-description": "Trim leading and trailing whitespace as well as blank lines",
|
||||
"trim-prefix-description": "Trim first character from each line",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Choose Unit",
|
||||
"press-enter-to-create": "Press Enter to Create",
|
||||
"choose-food": "Choose Food",
|
||||
"choose-recipe": "Choose Recipe",
|
||||
"notes": "Notes",
|
||||
"toggle-section": "Toggle Section",
|
||||
"see-original-text": "See Original Text",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Try out the bulk importer",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Have raw HTML or JSON data?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "You can import from raw data directly",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "Import original keywords as tags",
|
||||
"stay-in-edit-mode": "Stay in Edit mode",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Press '/'",
|
||||
"advanced": "Advanced",
|
||||
"auto-search": "Auto Search",
|
||||
"no-results": "No results found"
|
||||
"no-results": "No results found",
|
||||
"type-to-search": "Type to search..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Add a New Theme",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "is like",
|
||||
"is-not-like": "is not like"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Breakfast",
|
||||
"lunch": "Lunch",
|
||||
"dinner": "Dinner",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Any",
|
||||
"day-any": "Any",
|
||||
"editor": "Editor",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Upload a Recipe",
|
||||
"upload-individual-zip-file": "Upload an individual .zip file exported from another Mealie instance.",
|
||||
"url-form-hint": "Copy and paste a link from your favorite recipe website",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "View Scraped Data",
|
||||
"trim-whitespace-description": "Trim leading and trailing whitespace as well as blank lines",
|
||||
"trim-prefix-description": "Trim first character from each line",
|
||||
@@ -633,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Try out the bulk importer",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Have raw HTML or JSON data?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "You can import from raw data directly",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "Import original keywords as tags",
|
||||
"stay-in-edit-mode": "Stay in Edit mode",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
@@ -1422,5 +1428,13 @@
|
||||
"is-like": "is like",
|
||||
"is-not-like": "is not like"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Desayuno",
|
||||
"lunch": "Comida principal",
|
||||
"dinner": "Cena",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Cualquiera",
|
||||
"day-any": "Cualquier",
|
||||
"editor": "Editor",
|
||||
@@ -400,8 +403,8 @@
|
||||
"title": "Recetas de Tandoor"
|
||||
},
|
||||
"cookn": {
|
||||
"description-long": "Mealie can import recipes from DVO Cook'n X3. Export a cookbook or menu in the \"Cook'n\" format, rename the export extension to .zip, then upload the .zip below.",
|
||||
"title": "DVO Cook'n X3"
|
||||
"description-long": "Mealie no puede importar recetas de DVO Cook'n X3. Exporta un recetario o un menú en el formato \"Cook'n\", renómbralo a la extensión .zip y sube el .zip en la sección de abajo.",
|
||||
"title": "Cook'n DVO X3"
|
||||
},
|
||||
"recipe-data-migrations": "Migración de recetas",
|
||||
"recipe-data-migrations-explanation": "Las recetas pueden migrarse desde otra aplicación soportada a Mealie. Esta es una excelente manera de empezar con Mealie.",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Subir una receta",
|
||||
"upload-individual-zip-file": "Sube un archivo .zip individual exportado desde otra instancia de Mealie.",
|
||||
"url-form-hint": "Copia y pega un enlace desde tu página web favorita",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "Ver información recuperada",
|
||||
"trim-whitespace-description": "Eliminar espacios en blanco iniciales y finales así como líneas en blanco",
|
||||
"trim-prefix-description": "Eliminar el primer carácter de cada línea",
|
||||
@@ -450,7 +454,7 @@
|
||||
"create-manually": "Crear receta manualmente",
|
||||
"make-recipe-image": "Haz de esta la imagen de la receta",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-recipe": "Agregar receta"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Página no encontrada",
|
||||
@@ -517,8 +521,8 @@
|
||||
"recipe-deleted": "Receta eliminada",
|
||||
"recipe-image": "Imagen de la receta",
|
||||
"recipe-image-updated": "Imagen de la receta actualizada",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"delete-image": "Borra la imagen de la receta",
|
||||
"delete-image-confirmation": "¿Estás seguro de que quieres borrar esta imagen de la receta?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"recipe-name": "Nombre de la receta",
|
||||
"recipe-settings": "Ajustes de la receta",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Elija unidad",
|
||||
"press-enter-to-create": "Presione Intro para crear",
|
||||
"choose-food": "Elija comida",
|
||||
"choose-recipe": "Choose Recipe",
|
||||
"notes": "Notas",
|
||||
"toggle-section": "Activar sección",
|
||||
"see-original-text": "Mostrar Texto Original",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Prueba el importador masivo",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "¿Tiene datos HTML o JSON?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Puede importar directamente desde datos brutos",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "Importar palabras clave originales como etiquetas",
|
||||
"stay-in-edit-mode": "Permanecer en modo edición",
|
||||
"parse-recipe-ingredients-after-import": "Analizar los ingredientes de la receta después de importarla",
|
||||
@@ -697,7 +704,7 @@
|
||||
"cover-image": "Imagen de portada",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"toggle-recipe": "Alternar Receta"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Buscador de recetas",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Presione '/'",
|
||||
"advanced": "Avanzado",
|
||||
"auto-search": "Búsqueda automática",
|
||||
"no-results": "No se encontraron resultados"
|
||||
"no-results": "No se encontraron resultados",
|
||||
"type-to-search": "Type to search..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Añadir un nuevo tema",
|
||||
@@ -1073,8 +1081,8 @@
|
||||
"forgot-password": "Olvidé mi contraseña",
|
||||
"forgot-password-text": "Por favor, introduce tu correo electrónico y te enviaremos un enlace para restablecer tu contraseña.",
|
||||
"changes-reflected-immediately": "Los cambios en este grupo se reflejarán inmediatamente.",
|
||||
"default-activity": "Default Activity",
|
||||
"default-activity-hint": "Select which page you'd like to navigate to upon logging in from this device"
|
||||
"default-activity": "Actividad predeterminada",
|
||||
"default-activity-hint": "Selecciona la pagina a la que navegar al iniciar la sesion en este dispositivo"
|
||||
},
|
||||
"language-dialog": {
|
||||
"translated": "traducido",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "es como",
|
||||
"is-not-like": "no es como"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,14 +62,14 @@
|
||||
"notification": "Teade",
|
||||
"refresh": "Värskenda",
|
||||
"scheduled": "Ajastatud",
|
||||
"something-went-wrong": "Miski läks valesti",
|
||||
"something-went-wrong": "Miski läks valesti!",
|
||||
"subscribed-events": "Tellitud sündmused",
|
||||
"test-message-sent": "Test-sõnum saadetud",
|
||||
"message-sent": "Sõnum saadetud",
|
||||
"new-notification": "Uus teade",
|
||||
"event-notifiers": "Sündmuste märguanded",
|
||||
"apprise-url-skipped-if-blank": "Apprise URL (kui on tühi, jäetakse vahele)",
|
||||
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||
"apprise-url-is-left-intentionally-blank": "Kuna Apprise URL-id sisaldavad tavaliselt tundlikku teavet, jäetakse see väli redigeerimisel tahtlikult tühjaks. Kui soovite URL-i uuendada, sisestage siia uus URL, muidu jätke väli tühjaks, et säilitada praegune URL.",
|
||||
"enable-notifier": "Luba teavitaja",
|
||||
"what-events": "Millised sündmused peaks see teavitaja tellimaa?",
|
||||
"user-events": "Kasutaja sündmused",
|
||||
@@ -105,8 +105,8 @@
|
||||
"exception": "Erand",
|
||||
"failed-count": "Ebaõnnestunud: {count}",
|
||||
"failure-uploading-file": "Faili üleslaadimine ebaõnnestunud",
|
||||
"favorites": "Lemmiud",
|
||||
"field-required": "Väli nõutud",
|
||||
"favorites": "Lemmikud",
|
||||
"field-required": "Nõutud väli",
|
||||
"file-folder-not-found": "Faili/kausta ei leitud",
|
||||
"file-uploaded": "Fail üles laetud",
|
||||
"filter": "Filter",
|
||||
@@ -119,17 +119,17 @@
|
||||
"import": "Impordi",
|
||||
"json": "JSON",
|
||||
"keyword": "Otsingusõna",
|
||||
"link-copied": "Link kopeeritud!",
|
||||
"link-copied": "Link kopeeritud",
|
||||
"loading": "Laadimine",
|
||||
"loading-events": "Sündmuste laadimine",
|
||||
"loading-recipe": "Laeb retsepti...",
|
||||
"loading-ocr-data": "Laeb OCR admeid",
|
||||
"loading-recipes": "Laeb retsepte",
|
||||
"loading-recipe": "Retsepti laadimine...",
|
||||
"loading-ocr-data": "OCR admete laadimine...",
|
||||
"loading-recipes": "Retseptide laadimine",
|
||||
"message": "Sõnum",
|
||||
"monday": "Esmaspäev",
|
||||
"name": "Nimi",
|
||||
"new": "Uus",
|
||||
"never": "Uuem",
|
||||
"never": "Mitte kunagi",
|
||||
"no": "Ei",
|
||||
"no-recipe-found": "Retsepti ei leitud",
|
||||
"ok": "OK",
|
||||
@@ -192,7 +192,7 @@
|
||||
"a-name-is-required": "Nimi on kohustuslik",
|
||||
"delete-with-name": "Kustuta {name}",
|
||||
"confirm-delete-generic-with-name": "Kas olete kindel, et soovite kirje {name} kustutada?",
|
||||
"confirm-delete-own-admin-account": "Pane tähele, et sa proovid kustutada oma admin kasutajat! Seda tegevust ei saa tagasi võtta ning su kasutaja on jäädavalt kustutatud.",
|
||||
"confirm-delete-own-admin-account": "Pane tähele, et sa proovid kustutada oma admin kasutajat! Seda tegevust ei saa tagasi võtta ning see kustutab su kasutaja jäädavalt.",
|
||||
"organizer": "Korraldaja",
|
||||
"transfer": "Vii üle",
|
||||
"copy": "Kopeeri",
|
||||
@@ -203,8 +203,8 @@
|
||||
"this-feature-is-currently-inactive": "See funktsioon on hetkel mitte-aktiivne",
|
||||
"clipboard-not-supported": "Lõikelaud ei ole toetatud",
|
||||
"copied-to-clipboard": "Kopeeritud lõikelauale",
|
||||
"your-browser-does-not-support-clipboard": "Sinu lehitseja ei toeta lõikelauda.",
|
||||
"copied-items-to-clipboard": "Midagi ei kopeeritud lõikelauale | Üks asi kopeeritud lõikelauale | {count} asja kopeeritud lõikelauale",
|
||||
"your-browser-does-not-support-clipboard": "Sinu lehitseja ei toeta lõikelauda",
|
||||
"copied-items-to-clipboard": "Midagi ei kopeeritud lõikelauale|Üks asi kopeeritud lõikelauale|{count} asja kopeeritud lõikelauale",
|
||||
"actions": "Tegevused",
|
||||
"selected-count": "Valitud: {count}",
|
||||
"export-all": "Ekspordi kõik",
|
||||
@@ -212,7 +212,7 @@
|
||||
"upload-file": "Lae fail üles",
|
||||
"created-on-date": "Loodud: {0}",
|
||||
"unsaved-changes": "Sul on salvestamata muudatusi. Kas sa tahad salvestada enne lehelt lahkumist? Vajuta OK salvestamiseks või Tühista, et muudatused tühistada.",
|
||||
"clipboard-copy-failure": "Lõikepuhvrisse kopeerimine ebaõnnestus",
|
||||
"clipboard-copy-failure": "Lõikepuhvrisse kopeerimine ebaõnnestus.",
|
||||
"confirm-delete-generic-items": "Kas oled kindel, et tahad kustutada järgnevad asjad?",
|
||||
"organizers": "Korraldajad",
|
||||
"caution": "Ettevaatust",
|
||||
@@ -222,7 +222,7 @@
|
||||
"date-updated": "Üleslaadimise kuupäev"
|
||||
},
|
||||
"group": {
|
||||
"are-you-sure-you-want-to-delete-the-group": "Kas oled kindel, et tahad kustutada <b>{groupName}<b/>",
|
||||
"are-you-sure-you-want-to-delete-the-group": "Kas oled kindel, et tahad kustutada <b>{groupName}<b/>?",
|
||||
"cannot-delete-default-group": "Ei saa kustutada vaikegruppi",
|
||||
"cannot-delete-group-with-users": "Ei saa kustutada kasutajatega gruppi",
|
||||
"confirm-group-deletion": "Kinnita grupi kustutamine",
|
||||
@@ -251,15 +251,15 @@
|
||||
"manage-household": "Halda leibkonda",
|
||||
"invite": "Kutsu",
|
||||
"looking-to-update-your-profile": "Kas soovida uuendada oma profiili?",
|
||||
"default-recipe-preferences-description": "Need on lähteseaded kui loote uut retseepti oma grupis. Neid saab muuta iga retsepti jaoks individuaalselt retsepti sätete menüüs.",
|
||||
"default-recipe-preferences-description": "Need on lähteseaded kui loote uut retsepti oma grupis. Neid saab muuta iga retsepti jaoks individuaalselt retsepti sätete menüüs.",
|
||||
"default-recipe-preferences": "Retsepti vaikevalikud",
|
||||
"group-preferences": "Grupi sätted",
|
||||
"private-group": "Privaatne grupp",
|
||||
"private-group-description": "Grupi privaatseks määramine keelab kõik avaliku vaate valikud. See kirjutab üle kõik üksikud avaliku vaate seaded.",
|
||||
"private-group-description": "Grupi privaatseks määramine keelab kõik avaliku vaate valikud. See kirjutab üle kõik üksikud avaliku vaate seaded",
|
||||
"enable-public-access": "Luba avalik juurdepääs",
|
||||
"enable-public-access-description": "Teeb grupi retseptid vaikimisi avalikuks ja lubab külalistel vaadata retsepte ilma sisse logimata",
|
||||
"allow-users-outside-of-your-group-to-see-your-recipes": "Lubab kasutajatel väljaspool sinu gruppi näha retsepte",
|
||||
"allow-users-outside-of-your-group-to-see-your-recipes-description": "Kui see on lubatud, saate konkreetsete retseptide jagamiseks ilma kasutaja loata kasutada avalikku jagamislinki. Kui see on keelatud, saate retsepte jagada ainult nende kasutajatega, kes on teie rühmas või kellel on eelnevalt loodud privaatne link.",
|
||||
"allow-users-outside-of-your-group-to-see-your-recipes-description": "Kui see on lubatud, saate konkreetsete retseptide jagamiseks ilma kasutaja loata kasutada avalikku jagamislinki. Kui see on keelatud, saate retsepte jagada ainult nende kasutajatega, kes on teie rühmas või kellel on eelnevalt loodud privaatne link",
|
||||
"show-nutrition-information": "Näita toitumisalast teavet",
|
||||
"show-nutrition-information-description": "Kui see on lubatud, kuvatakse saadavuse korral toitumisalane teave retseptis. Kui toitumisalane teave pole saadaval, siis toitumisalast teavet ei kuvata",
|
||||
"show-recipe-assets": "Näita retsepti manuseid",
|
||||
@@ -294,13 +294,13 @@
|
||||
"admin-household-management-text": "Selle leibkonna muudatused on koheselt nähtaval",
|
||||
"household-id-value": "Leibkonna ID: {0}",
|
||||
"private-household": "Privaatne leibkond",
|
||||
"private-household-description": "Grupi privaatseks määramine keelab kõik avaliku vaate valikud. See kirjutab üle kõik üksikud avaliku vaate seaded.",
|
||||
"private-household-description": "Grupi privaatseks määramine keelab kõik avaliku vaate valikud. See kirjutab üle kõik üksikud avaliku vaate seaded",
|
||||
"lock-recipe-edits-from-other-households": "Lukusta retsepti muudatused teiste leibkondade eest",
|
||||
"lock-recipe-edits-from-other-households-description": "Kui lubatud, ainult sinu leibkonna kasutajad saavad teha muudatusi sinu leibkonna retseptides",
|
||||
"household-recipe-preferences": "Leibkonna retseptide seaded",
|
||||
"default-recipe-preferences-description": "Need on vaikesätted uute retseptide loomiseks sinu leibkonnas. Neid saab muuta iga retsepti jaoks individuaalselt seadete menüü alt",
|
||||
"default-recipe-preferences-description": "Need on vaikesätted uute retseptide loomiseks sinu leibkonnas. Neid saab muuta iga retsepti jaoks individuaalselt seadete menüü alt.",
|
||||
"allow-users-outside-of-your-household-to-see-your-recipes": "Luba kasutajatel väljaspool sinu leibkonda näha sinu retsepte",
|
||||
"allow-users-outside-of-your-household-to-see-your-recipes-description": "Kui see on lubatud, saate konkreetsete retseptide jagamiseks ilma kasutaja loata kasutada avalikku jagamislinki. Kui see on keelatud, saate retsepte jagada ainult nende kasutajatega, kes on teie rühmas või kellel on eelnevalt loodud privaatne link.",
|
||||
"allow-users-outside-of-your-household-to-see-your-recipes-description": "Kui see on lubatud, saate konkreetsete retseptide jagamiseks ilma kasutaja loata kasutada avalikku jagamislinki. Kui see on keelatud, saate retsepte jagada ainult nende kasutajatega, kes on teie rühmas või kellel on eelnevalt loodud privaatne link",
|
||||
"household-preferences": "Leibkonna seaded"
|
||||
},
|
||||
"meal-plan": {
|
||||
@@ -314,7 +314,7 @@
|
||||
"group": "Grupp (beeta)",
|
||||
"main": "Pearoog",
|
||||
"meal-planner": "Toitumismplaneerija",
|
||||
"meal-plans": "Toitumismplanid",
|
||||
"meal-plans": "Toitumismplaanid",
|
||||
"mealplan-categories": "TOITUMISPLAANI KATEGOORIAD",
|
||||
"mealplan-created": "Toitumisplaan loodud",
|
||||
"mealplan-creation-failed": "Toitumisplaani loomine ebaõnnestus",
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Hommikusöök",
|
||||
"lunch": "Lõuna",
|
||||
"dinner": "Õhtusöök",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Kõik",
|
||||
"day-any": "Kõik",
|
||||
"editor": "Editor",
|
||||
@@ -400,7 +403,7 @@
|
||||
"title": "Tandoor-i retsptid"
|
||||
},
|
||||
"cookn": {
|
||||
"description-long": "Mealie can import recipes from DVO Cook'n X3. Export a cookbook or menu in the \"Cook'n\" format, rename the export extension to .zip, then upload the .zip below.",
|
||||
"description-long": "Mealie saab importida retsepte DVO Cook'n X3-st. Ekspordi kokaraamat või menüü „Cook'n“ formaadis, nimeta ekspordi laiendiks .zip ja lae seejärel .zip allpool üles.",
|
||||
"title": "DVO Cook'n X3"
|
||||
},
|
||||
"recipe-data-migrations": "Retsepti andmete ületoomised",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Retsepti üleslaadimne",
|
||||
"upload-individual-zip-file": "Lae üles üksik .zip fail, mis eksporditi teisest Mealie ekspemplarist.",
|
||||
"url-form-hint": "Kopeeri ja kleebi link oma lemmikust retsepti leheküljest",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "Kuva omandatud andmed",
|
||||
"trim-whitespace-description": "Eemalda alguses ning lõpus olevad tühikud ning tühjad read",
|
||||
"trim-prefix-description": "Eemalda esimene tähemärk igast reast",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Impordi retsept URL-lt",
|
||||
"create-manually": "Loo retsept manuaalselt",
|
||||
"make-recipe-image": "Sea see retsepti pildiks",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Lisa toit",
|
||||
"add-recipe": "Lisa retsept"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Lehte ei leitud",
|
||||
@@ -480,7 +484,7 @@
|
||||
"comment": "Kommentaar",
|
||||
"comments": "Kommentaarid",
|
||||
"delete-confirmation": "Kas sa oled kindel, et tahad seda retsepti kustutada?",
|
||||
"admin-delete-confirmation": "You're about to delete a recipe that isn't yours using admin permissions. Are you sure?",
|
||||
"admin-delete-confirmation": "Sa oled kustutamas sulle mittekuuluvat retsepti, kasutades administraatori õigusi. Oled kindel?",
|
||||
"delete-recipe": "Kustuta retsept",
|
||||
"description": "Kirjeldus",
|
||||
"disable-amount": "Deaktiveeri koostisosade kogused",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Retsept kustutatud",
|
||||
"recipe-image": "Retsepti pilt",
|
||||
"recipe-image-updated": "Retsepti pilt uuendatud",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Kustuta retsepti pilt",
|
||||
"delete-image-confirmation": "Kas sa oled kindel, et tahad seda retsepti pilti kustutada?",
|
||||
"recipe-image-deleted": "Retsepti pilt kustutatud",
|
||||
"recipe-name": "Retsepti nimi",
|
||||
"recipe-settings": "Retsepti seaded",
|
||||
"recipe-update-failed": "Retsepti uuendamine ebaõnnestus",
|
||||
@@ -550,7 +554,7 @@
|
||||
"date-format-hint-yyyy-mm-dd": "AAAA-KK-PP formaat",
|
||||
"add-to-list": "Lisa nimekirja",
|
||||
"add-to-plan": "Lisa plaani",
|
||||
"add-to-timeline": "Lisa ajateljele",
|
||||
"add-to-timeline": "Lisa ajajoonele",
|
||||
"recipe-added-to-list": "Retsept lisatud nimekirja",
|
||||
"recipes-added-to-list": "Retseptid lisatud nimekirja",
|
||||
"successfully-added-to-list": "Edukalt lisatud nimekirja",
|
||||
@@ -565,12 +569,13 @@
|
||||
"choose-unit": "Vali ühik",
|
||||
"press-enter-to-create": "Loomiseks vajuta Enter",
|
||||
"choose-food": "Vali toit",
|
||||
"choose-recipe": "Vali retsept",
|
||||
"notes": "Märkmed",
|
||||
"toggle-section": "Jaotise sisse- ja väljalülitamine",
|
||||
"see-original-text": "Vaata originaalteksti",
|
||||
"original-text-with-value": "Originaaltekst: {originalText}",
|
||||
"ingredient-linker": "Koostisosa linkija",
|
||||
"unlinked": "Not linked yet",
|
||||
"unlinked": "Pole viidatud veel",
|
||||
"linked-to-other-step": "Lingitud järgmise sammuga",
|
||||
"auto": "Automaatne",
|
||||
"cook-mode": "Küpsetusviis",
|
||||
@@ -583,7 +588,7 @@
|
||||
"increase-scale-label": "Suurenda skaalat ühe võrra",
|
||||
"locked": "Lukustatud",
|
||||
"public-link": "Avalik link",
|
||||
"edit-timeline-event": "Muuda sündmust ajasjoonel",
|
||||
"edit-timeline-event": "Muuda sündmust ajajoonel",
|
||||
"timeline": "Ajajoon",
|
||||
"timeline-is-empty": "Ajajoon on tühi. Proovi valmistada see retsept!",
|
||||
"timeline-no-events-found-try-adjusting-filters": "Sündmused puuduvad. Proovi kohandada oma otsingufiltreid.",
|
||||
@@ -592,15 +597,15 @@
|
||||
"made-this": "Olen seda valmistanud",
|
||||
"how-did-it-turn-out": "Kuidas tuli see välja?",
|
||||
"user-made-this": "{user} on seda valmistanud",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"added-to-timeline": "Added to timeline",
|
||||
"failed-to-add-to-timeline": "Failed to add to timeline",
|
||||
"failed-to-update-recipe": "Failed to update recipe",
|
||||
"added-to-timeline-but-failed-to-add-image": "Added to timeline, but failed to add image",
|
||||
"made-for-recipe": "Tehtud {recipe} jaoks",
|
||||
"added-to-timeline": "Lisatud ajajoonele",
|
||||
"failed-to-add-to-timeline": "Ajajoonele lisamine ebaõnnestus",
|
||||
"failed-to-update-recipe": "Retsepti uuendamine ebaõnnestus",
|
||||
"added-to-timeline-but-failed-to-add-image": "Lisatud ajajoonele, kuid pildi lisamine ebaõnnestus",
|
||||
"api-extras-description": "Retsepti väljavõtted on Meali API oluline funktsioon. Neid saab kasutada kohandatud JSON-võtme/väärtuse paaride loomiseks retseptis, et viidata kolmandate osapoolte rakendustele. Neid klahve saab kasutada teabe edastamiseks, näiteks automaatse toimingu või kohandatud sõnumi käivitamiseks teie valitud seadmele.",
|
||||
"message-key": "Sõnumi võti",
|
||||
"parse": "Analüüsi",
|
||||
"ingredients-not-parsed-description": "It looks like your ingredients aren't parsed yet. Click the \"{parse}\" button below to parse your ingredients into structured foods.",
|
||||
"ingredients-not-parsed-description": "Tundub, et teie koostisosad pole veel tuvastatud. Klõpsake allpool olevat nuppu „{parse}”, et tuvastada teie koostisosad struktureeritud toitudeks.",
|
||||
"attach-images-hint": "Lisa pildid manustesse neid lohistades ja vabastades need redaktorisse",
|
||||
"drop-image": "Vabasta pilt",
|
||||
"enable-ingredient-amounts-to-use-this-feature": "Luba koostisosa kogused, et kasutada seda omadust",
|
||||
@@ -618,10 +623,10 @@
|
||||
"create-recipe-from-an-image": "Retsepti loomine pildist",
|
||||
"create-recipe-from-an-image-description": "Retsepti loomiseks lae üles selle pilt. Mealie üritab ekstraheerida pildil oleva teksti ning luua retsepti sellest kasutades AI-d.",
|
||||
"crop-and-rotate-the-image": "Kärpige ja pöörake pilti nii, et ainult tekst oleks nähtaval ja see oleks suunatud ülespoole.",
|
||||
"create-from-images": "Create from Images",
|
||||
"create-from-images": "Retsepti loomine pildist",
|
||||
"should-translate-description": "Tõlgi retsept minu keelde",
|
||||
"please-wait-image-procesing": "Palun oota, pilti töödeldakse veel. See võib võtta veidi aega.",
|
||||
"please-wait-images-processing": "Please wait, the images are processing. This may take some time.",
|
||||
"please-wait-images-processing": "Palun oota, pilti töödeldakse veel. See võib võtta veidi aega.",
|
||||
"bulk-url-import": "Hulgiimport URL-ist",
|
||||
"debug-scraper": "Otsige Scraperis probleeme",
|
||||
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "Loo retsept selle nime kasutades. Igal retseptil peab olema unikaalne nimi",
|
||||
@@ -632,9 +637,11 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Proovi hulgiimportimist.",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Sul on töötlemata HTMLi või JSONi andmed?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Sa võid otse importida töötlemata andmetest",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "Impordi originaal võtmesõnad siltidena",
|
||||
"stay-in-edit-mode": "Püsige redigeerimisrežiimis",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
"parse-recipe-ingredients-after-import": "Tuvasta retsepti koostisosad pärast importimist",
|
||||
"import-from-zip": "Impordi .zip-st",
|
||||
"import-from-zip-description": "Impordi üks retsept, mis oli eksporditud teisest Mealie paigaldusest.",
|
||||
"import-from-html-or-json": "Impordi HTMLst või JSONist",
|
||||
@@ -678,26 +685,26 @@
|
||||
"no-unit": "Ilma ühikuta",
|
||||
"missing-unit": "Loo puuduv ühik: {unit}",
|
||||
"missing-food": "Loo puuduv toit: {food}",
|
||||
"this-unit-could-not-be-parsed-automatically": "This unit could not be parsed automatically",
|
||||
"this-food-could-not-be-parsed-automatically": "This food could not be parsed automatically",
|
||||
"this-unit-could-not-be-parsed-automatically": "Seda ühikut ei saanud automaatselt tuvastada",
|
||||
"this-food-could-not-be-parsed-automatically": "Seda toitu ei saanud automaatselt tuvastada",
|
||||
"no-food": "Toit puudub",
|
||||
"review-parsed-ingredients": "Review parsed ingredients",
|
||||
"confidence-score": "Confidence Score",
|
||||
"ingredient-parser-description": "Your ingredients have been successfully parsed. Please review the ingredients we're not sure about.",
|
||||
"ingredient-parser-final-review-description": "Once all ingredients have been reviewed, you'll have one more chance to review all ingredients before applying the changes to your recipe.",
|
||||
"add-text-as-alias-for-item": "Add \"{text}\" as alias for {item}",
|
||||
"delete-item": "Delete Item"
|
||||
"review-parsed-ingredients": "Vaata läbi tuvastatud koostisosad",
|
||||
"confidence-score": "Kindluse tase",
|
||||
"ingredient-parser-description": "Koostisosad on edukalt tuvastatud. Palun vaadake üle koostisosad, mille puhul me pole kindlad.",
|
||||
"ingredient-parser-final-review-description": "Kui kõik koostisosad on üle vaadatud, on teil enne muudatuste retsepti salvestamist veel üks võimalus kõik koostisosad üle vaadata.",
|
||||
"add-text-as-alias-for-item": "Lisa \"{text}\" kui teine nimetus {item} jaoks",
|
||||
"delete-item": "Kustuta element"
|
||||
},
|
||||
"reset-servings-count": "Lähtesta portsionite arv",
|
||||
"not-linked-ingredients": "Lisa-koostisosad",
|
||||
"upload-another-image": "Upload another image",
|
||||
"upload-images": "Upload images",
|
||||
"upload-more-images": "Upload more images",
|
||||
"set-as-cover-image": "Set as recipe cover image",
|
||||
"cover-image": "Cover image",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"upload-another-image": "Laadi üles veel üks pilt",
|
||||
"upload-images": "Lae üles pilte",
|
||||
"upload-more-images": "Lae üles veel pilte",
|
||||
"set-as-cover-image": "Määra retsepti kaanepildiks",
|
||||
"cover-image": "Kaanepilt",
|
||||
"include-linked-recipes": "Arva kaasa viidatud retseptid",
|
||||
"include-linked-recipe-ingredients": "Arva kaasa viidatud retseptide koostisosad",
|
||||
"toggle-recipe": "Lülita retsept"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Retsepti otsing",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Vajuta \"/\"",
|
||||
"advanced": "Lisavalikud",
|
||||
"auto-search": "Automaatotsing",
|
||||
"no-results": "Tulemusi ei leitud"
|
||||
"no-results": "Tulemusi ei leitud",
|
||||
"type-to-search": "Tippige otsimiseks..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Lisa uus teema",
|
||||
@@ -757,7 +765,7 @@
|
||||
"backup-restore": "Taasta tagavarakoopiast",
|
||||
"back-restore-description": "Selle varukoopia taastamisel kirjutatakse üle kõik teie andmebaasis ja andmebaasihalduris olevad andmed ning asendatakse need selle varukoopia sisuga. {cannot-be-undone} Kui taastamine õnnestub, logitakse teid välja.",
|
||||
"cannot-be-undone": "Seda tegevust ei saa tagasi võtta - kasuta ettevaatusega.",
|
||||
"postgresql-note": "If you are using PostgreSQL, please review the {backup-restore-process} prior to restoring.",
|
||||
"postgresql-note": "Kui kasutate PostgreSQL-i, vaadake enne taastamist läbi {backup-restore-process}.",
|
||||
"backup-restore-process-in-the-documentation": "varundamise/taastamise protsessi dokumentatsioonis",
|
||||
"irreversible-acknowledgment": "Ma saan aru, et seda tegevust ei ole võimalik tagasi võtta, on destruktiivne, ning võib põhjustada andmekadu",
|
||||
"restore-backup": "Taasta tagavarakoopiast"
|
||||
@@ -1073,8 +1081,8 @@
|
||||
"forgot-password": "Unustasid salasõna",
|
||||
"forgot-password-text": "Sisestage oma meiliaadress, et saada e-kiri uue salasõna määramiseks.",
|
||||
"changes-reflected-immediately": "Selle kasutaja muudatused on koheselt nähtaval",
|
||||
"default-activity": "Default Activity",
|
||||
"default-activity-hint": "Select which page you'd like to navigate to upon logging in from this device"
|
||||
"default-activity": "Vaikimisi tegevus",
|
||||
"default-activity-hint": "Valige, millisele lehele soovite navigeerida, kui logite sisse sellelt seadmelt"
|
||||
},
|
||||
"language-dialog": {
|
||||
"translated": "tõlgitud",
|
||||
@@ -1192,7 +1200,7 @@
|
||||
"group-details": "Grupi detailid",
|
||||
"group-details-description": "Sa pead looma grupi enne konto loomist. Sinu grupis oled vaid sina, kuid sa saad kutsuda teisi sinna hiljem. Su grupi liikmed saavad jagada toitumisplaane, ostunimekirju, retsepte ja muud!",
|
||||
"use-seed-data": "Kasuta baasandmete infot.",
|
||||
"use-seed-data-description": "Mealie ships with a collection of Foods, Units, and Labels that can be used to populate your group with helpful data for organizing your recipes. These are translated into the language you currently have selected. You can always add to or modify this data later.",
|
||||
"use-seed-data-description": "Mealie sisaldab toiduainete, ühikute ja siltide kogumit, mida saad enda gruppi kaasata, et hõlbustada retseptide organiseerimist. Need on tõlgitud teie valitud keelde. Neid andmeid saab alati hiljem täiendada või muuta.",
|
||||
"account-details": "Konto üksikasjad"
|
||||
},
|
||||
"validation": {
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "on nagu",
|
||||
"is-not-like": "ei ole nagu"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"about": {
|
||||
"about": "Tietoja",
|
||||
"about-mealie": "Tietoja Mealiestä",
|
||||
"api-docs": "API-dokumentit",
|
||||
"api-docs": "API-dokumentaatio",
|
||||
"api-port": "API-portti",
|
||||
"application-mode": "Sovellustila",
|
||||
"database-type": "Tietokannan tyyppi",
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Aamiainen",
|
||||
"lunch": "Lounas",
|
||||
"dinner": "Päivällinen",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Mikä tahansa",
|
||||
"day-any": "Koska tahansa",
|
||||
"editor": "Editori",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Lataa resepti",
|
||||
"upload-individual-zip-file": "Tuo yksittäinen pakattu kansio toisesta Mealie instanssista.",
|
||||
"url-form-hint": "Liitä linkki lempireseptiverkkosivultasi",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "Näytä hankittu data",
|
||||
"trim-whitespace-description": "Leikkaa alussa ja lopussa olevat välilyönnit sekä tyhjät rivit",
|
||||
"trim-prefix-description": "Poista joka rivin ensimmäinen merkki",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Tuo resepti osoitteesta",
|
||||
"create-manually": "Luo resepti manuaalisesti",
|
||||
"make-recipe-image": "Luo reseptikuva",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Lisää Ruoka",
|
||||
"add-recipe": "Lisää resepti"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 sivua ei löydy",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Resepti poistettu",
|
||||
"recipe-image": "Reseptikuva",
|
||||
"recipe-image-updated": "Reseptikuva päivitetty",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Poista Reseptin Kuva",
|
||||
"delete-image-confirmation": "Haluatko varmasti poistaa reseptikuvan?",
|
||||
"recipe-image-deleted": "Reseptikuva poistettu",
|
||||
"recipe-name": "Reseptin nimi",
|
||||
"recipe-settings": "Reseptiasetukset",
|
||||
"recipe-update-failed": "Reseptin päivitys epäonnistui",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Valitse Yksikkö",
|
||||
"press-enter-to-create": "Luo painamalla Enter",
|
||||
"choose-food": "Valitse Ruoka",
|
||||
"choose-recipe": "Valitse Resepti",
|
||||
"notes": "Merkinnät",
|
||||
"toggle-section": "Vaihda osio",
|
||||
"see-original-text": "Katso Alkuperäinen Teksti",
|
||||
@@ -592,7 +597,7 @@
|
||||
"made-this": "Tein tämän",
|
||||
"how-did-it-turn-out": "Miten se onnistui?",
|
||||
"user-made-this": "{user} teki tämän",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"made-for-recipe": "Tehty reseptille",
|
||||
"added-to-timeline": "Lisätty aikajanalle",
|
||||
"failed-to-add-to-timeline": "Aikajanaan lisääminen epäonnistui",
|
||||
"failed-to-update-recipe": "Reseptin päivitys epäonnistui",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Kokeile massasiirtotyökalua",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Onko sinulla raakaa HTML- tai JSON-dataa?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Voit tuoda raakadatan suoraan",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "Tuo alkuperäiset avainsanat tunnisteiksi",
|
||||
"stay-in-edit-mode": "Pysy muokkaustilassa",
|
||||
"parse-recipe-ingredients-after-import": "Jäsennä reseptin ainesosat tuonnin jälkeen",
|
||||
@@ -695,9 +702,9 @@
|
||||
"upload-more-images": "Lataa lisää kuvia",
|
||||
"set-as-cover-image": "Aseta reseptin kansikuvaksi",
|
||||
"cover-image": "Kansikuva",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"include-linked-recipes": "Sisällytä Linkitetyt Reseptit",
|
||||
"include-linked-recipe-ingredients": "Sisällytä Yhdistetyt Reseptin Ainesosat",
|
||||
"toggle-recipe": "Vaihda osio"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Reseptin etsijä",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Paina '/'",
|
||||
"advanced": "Lisäasetukset",
|
||||
"auto-search": "Automaattinen Haku",
|
||||
"no-results": "Ei tuloksia"
|
||||
"no-results": "Ei tuloksia",
|
||||
"type-to-search": "Kirjoita haettavaksi..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Lisää uusi teema",
|
||||
@@ -1073,8 +1081,8 @@
|
||||
"forgot-password": "Unohditko salasanasi",
|
||||
"forgot-password-text": "Syötä sähköpostiosoitteesi, niin voit muuttaa salasanaasi linkin kautta.",
|
||||
"changes-reflected-immediately": "Muutokset tähän käyttäjään astuvat välittömästi voimaan.",
|
||||
"default-activity": "Default Activity",
|
||||
"default-activity-hint": "Select which page you'd like to navigate to upon logging in from this device"
|
||||
"default-activity": "Oletus Toiminta",
|
||||
"default-activity-hint": "Valitse haluamasi sivu, johon haluat navigoida kirjautuessasi tältä laitteelta"
|
||||
},
|
||||
"language-dialog": {
|
||||
"translated": "käännetty",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "on kuin",
|
||||
"is-not-like": "ei ole kuin"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Petit-déjeuner",
|
||||
"lunch": "Déjeuner",
|
||||
"dinner": "Souper",
|
||||
"snack": "Goûter",
|
||||
"drink": "Boissons",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Tous",
|
||||
"day-any": "Tous",
|
||||
"editor": "Éditeur",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Télécharger une recette",
|
||||
"upload-individual-zip-file": "Chargez un fichier .zip exporté depuis une autre instance Mealie.",
|
||||
"url-form-hint": "Copiez et collez un lien depuis votre site de recettes favori",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copiez et collez l'URL source de vos données (facultatif)",
|
||||
"view-scraped-data": "Voir les données récupérées",
|
||||
"trim-whitespace-description": "Ajuster les espaces de début et de fin ainsi que les lignes vides",
|
||||
"trim-prefix-description": "Couper le premier caractère de chaque ligne",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Importer une recette par son URL",
|
||||
"create-manually": "Créer une recette manuellement",
|
||||
"make-recipe-image": "Faire de cette image l’image de recette",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Ajouter un aliment",
|
||||
"add-recipe": "Ajouter une recette"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Page introuvable",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Recette supprimée",
|
||||
"recipe-image": "Image de la recette",
|
||||
"recipe-image-updated": "L’image de la recette a été mise à jour",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Supprimer l'image de la recette",
|
||||
"delete-image-confirmation": "Êtes-vous sûr de vouloir supprimer l'image de cette recette ?",
|
||||
"recipe-image-deleted": "L’image de la recette a été supprimée",
|
||||
"recipe-name": "Nom de la recette",
|
||||
"recipe-settings": "Paramètres de la recette",
|
||||
"recipe-update-failed": "La mise à jour de la recette a échoué",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Choisissez une unité",
|
||||
"press-enter-to-create": "Clique sur Entrer pour créer",
|
||||
"choose-food": "Choisissez un aliment",
|
||||
"choose-recipe": "Choisissez la recette",
|
||||
"notes": "Notes",
|
||||
"toggle-section": "Activer/Désactiver la section",
|
||||
"see-original-text": "Afficher le texte original",
|
||||
@@ -592,7 +597,7 @@
|
||||
"made-this": "Je l’ai cuisiné",
|
||||
"how-did-it-turn-out": "C’était bon ?",
|
||||
"user-made-this": "{user} l’a cuisiné",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"made-for-recipe": "Fait pour {recipe}",
|
||||
"added-to-timeline": "Ajouté à la ligne du temps",
|
||||
"failed-to-add-to-timeline": "Impossible d'ajouter à la ligne du temps",
|
||||
"failed-to-update-recipe": "Impossible de modifier la recette",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Essayez l’importateur de masse",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Vous avez des données brutes en HTML ou JSON ?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Vous pouvez directement importer des données brutes",
|
||||
"scrape-recipe-website-being-blocked": "Le site web est bloqué ?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Essayez plutôt d'importer le code HTML brut.",
|
||||
"import-original-keywords-as-tags": "Importer les mots-clés d'origine en tant que tags",
|
||||
"stay-in-edit-mode": "Rester en mode édition",
|
||||
"parse-recipe-ingredients-after-import": "Analyser les ingrédients de la recette après l'import",
|
||||
@@ -695,9 +702,9 @@
|
||||
"upload-more-images": "Télécharger d'autres images",
|
||||
"set-as-cover-image": "Définir comme image de couverture de recette",
|
||||
"cover-image": "Image de couverture",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"include-linked-recipes": "Inclure les recettes liées",
|
||||
"include-linked-recipe-ingredients": "Inclure les ingrédients de la recette liée",
|
||||
"toggle-recipe": "Afficher/Masquer la recette"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Recherche de recette",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Appuyez sur « /»",
|
||||
"advanced": "Avancé",
|
||||
"auto-search": "Recherche automatique",
|
||||
"no-results": "Aucun résultat trouvé"
|
||||
"no-results": "Aucun résultat trouvé",
|
||||
"type-to-search": "Tapez pour chercher..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Ajouter un nouveau thème",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "est comme",
|
||||
"is-not-like": "n'est pas similaire à"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "Ce champ est obligatoire",
|
||||
"invalid-email": "L’e-mail doit être valide",
|
||||
"invalid-url": "Doit être une URL valide",
|
||||
"no-whitespace": "Aucun espace n'est autorisé",
|
||||
"min-length": "Doit contenir au moins {min} caractères",
|
||||
"max-length": "Doit contenir au maximum {max} caractères"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
"category-events": "Événements de catégories",
|
||||
"when-a-new-user-joins-your-group": "Lorsqu'un nouvel utilisateur rejoint votre groupe",
|
||||
"recipe-events": "Événements de recette",
|
||||
"label-events": "Étiquette des événements"
|
||||
"label-events": "Libellé des événements"
|
||||
},
|
||||
"general": {
|
||||
"add": "Ajouter",
|
||||
@@ -198,7 +198,7 @@
|
||||
"copy": "Copier",
|
||||
"color": "Couleur",
|
||||
"timestamp": "Horodatage",
|
||||
"last-made": "Cuisiné le",
|
||||
"last-made": "Cuisinée le",
|
||||
"learn-more": "En savoir plus",
|
||||
"this-feature-is-currently-inactive": "Cette fonctionnalité est actuellement inactive",
|
||||
"clipboard-not-supported": "Presse-papier non supporté",
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Petit déjeuner",
|
||||
"lunch": "Dîner",
|
||||
"dinner": "Souper",
|
||||
"snack": "Goûter",
|
||||
"drink": "Boissons",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Tous",
|
||||
"day-any": "Tous",
|
||||
"editor": "Éditeur",
|
||||
@@ -375,7 +378,7 @@
|
||||
"recipe-migration": "Migrer les recettes",
|
||||
"chowdown": {
|
||||
"description": "Importer des recettes depuis Chowdown",
|
||||
"description-long": "Mealie supporte nativement le format du dépôt chowdown. Téléchargez le dépôt de code en tant que fichier .zip et téléchargez-le ci-dessous.",
|
||||
"description-long": "Mealie supporte nativement le format du dépôt chowdown. Téléchargez le dépôt de code en tant que fichier .zip et téléverser-le ci-dessous.",
|
||||
"title": "Chowdown"
|
||||
},
|
||||
"nextcloud": {
|
||||
@@ -384,23 +387,23 @@
|
||||
"title": "Nextcloud Cookbook"
|
||||
},
|
||||
"copymethat": {
|
||||
"description-long": "Mealie peut importer des recettes à partir de Copy Me That. Exportez vos recettes au format HTML, puis téléchargez le .zip ci-dessous.",
|
||||
"description-long": "Mealie peut importer des recettes à partir de Copy Me That. Exportez vos recettes au format HTML, puis téléverser-le .zip ci-dessous.",
|
||||
"title": "Gestionnaire de recettes Copy Me That"
|
||||
},
|
||||
"paprika": {
|
||||
"description-long": "Mealie peut importer des recettes depuis l'application Paprika. Exportez vos recettes de paprika, renommez l'extension d'exportation en .zip et téléchargez-les ci-dessous.",
|
||||
"description-long": "Mealie peut importer des recettes depuis l'application Paprika. Exportez vos recettes de paprika, renommez l'extension d'exportation en .zip et téléverser-les ci-dessous.",
|
||||
"title": "Gestionnaire de recettes Paprika"
|
||||
},
|
||||
"mealie-pre-v1": {
|
||||
"description-long": "Mealie peut importer des recettes depuis l'application Mealie depuis une version antérieure à 1.0. Exportez vos recettes depuis votre ancienne instance, et téléchargez le fichier zip ci-dessous. Notez que seules les recettes peuvent être importées à partir de l'exportation.",
|
||||
"description-long": "Mealie peut importer des recettes depuis l'application Mealie depuis une version antérieure à 1.0. Exportez vos recettes depuis votre ancienne instance, et téléverser-le fichier zip ci-dessous. Notez que seules les recettes peuvent être importées à partir de l'exportation.",
|
||||
"title": "Mealie Pré-1.0"
|
||||
},
|
||||
"tandoor": {
|
||||
"description-long": "Mealie peut importer des recettes à partir de Tandoor. Exportez vos données dans le format « Défaut », puis téléchargez le .zip ci-dessous.",
|
||||
"description-long": "Mealie peut importer des recettes à partir de Tandoor. Exportez vos données dans le format « Défaut », puis téléverser-le .zip ci-dessous.",
|
||||
"title": "Recettes Tandoor"
|
||||
},
|
||||
"cookn": {
|
||||
"description-long": "Mealie peut importer des recettes de DVO Cook'n X3. Exportez un livre de recettes ou un menu au format \"Cook'n\", renommez l'extension d'exportation en .zip, puis téléchargez le .zip ci-dessous.",
|
||||
"description-long": "Mealie peut importer des recettes de DVO Cook'n X3. Exportez un livre de recettes ou un menu au format \"Cook'n\", renommez l'extension d'exportation en .zip, puis téléverser-le .zip ci-dessous.",
|
||||
"title": "DVO Cook'n X3"
|
||||
},
|
||||
"recipe-data-migrations": "Migration des données de recettes",
|
||||
@@ -409,22 +412,22 @@
|
||||
"choose-migration-type": "Choisissez le type de migration",
|
||||
"tag-all-recipes": "Étiquetez toutes les recettes avec le mot-clé {tag-name}",
|
||||
"nextcloud-text": "Les recettes Nextcloud peuvent être importées depuis un fichier zip qui contient les données stockées dans Nextcloud. Consultez la structure de dossiers d'exemple ci-dessous pour vous assurer que vos recettes peuvent être importées.",
|
||||
"chowdown-text": "Mealie prend en charge nativement le format de dépôt chowdown. Téléchargez le dépôt de code en tant que fichier .zip et téléchargez-le ci-dessous.",
|
||||
"chowdown-text": "Mealie prend en charge nativement le format de dépôt chowdown. Téléchargez le dépôt de code en tant que fichier .zip et téléverser-le ci-dessous.",
|
||||
"recipe-1": "Recette 1",
|
||||
"recipe-2": "Recette 2",
|
||||
"paprika-text": "Mealie peut importer des recettes depuis l'application Paprika. Exportez vos recettes de paprika, renommez l'extension d'exportation en .zip et téléchargez-les ci-dessous.",
|
||||
"mealie-text": "Mealie peut importer des recettes depuis l'application Mealie depuis une version antérieure à 1.0. Exportez vos recettes depuis votre ancienne instance, et téléchargez le fichier zip ci-dessous. Notez que seules les recettes peuvent être importées à partir de l'exportation.",
|
||||
"paprika-text": "Mealie peut importer des recettes depuis l'application Paprika. Exportez vos recettes de paprika, renommez l'extension d'exportation en .zip et téléverser-les ci-dessous.",
|
||||
"mealie-text": "Mealie peut importer des recettes depuis l'application Mealie depuis une version antérieure à 1.0. Exportez vos recettes depuis votre ancienne instance, et téléverser-le fichier zip ci-dessous. Notez que seules les recettes peuvent être importées à partir de l'exportation.",
|
||||
"plantoeat": {
|
||||
"title": "Plan to Eat",
|
||||
"description-long": "Mealie peut importer des recettes depuis Plan to Eat."
|
||||
},
|
||||
"myrecipebox": {
|
||||
"title": "My Recipe Box",
|
||||
"description-long": "Mealie peut importer des recettes depuis My Recipe Box. Exportez vos recettes au format CSV, puis téléchargez le fichier CSV ci-dessous."
|
||||
"description-long": "Mealie peut importer des recettes depuis My Recipe Box. Exportez vos recettes au format CSV, puis téléverser-le fichier CSV ci-dessous."
|
||||
},
|
||||
"recipekeeper": {
|
||||
"title": "Recipe Keeper",
|
||||
"description-long": "Mealie peut importer des recettes depuis Recipe Keeper. Exportez vos recettes au format Zip, puis téléversez le fichier .zip ci-dessous."
|
||||
"description-long": "Mealie peut importer des recettes depuis Recipe Keeper. Exportez vos recettes au format Zip, puis téléverser-le fichier .zip ci-dessous."
|
||||
}
|
||||
},
|
||||
"new-recipe": {
|
||||
@@ -440,8 +443,9 @@
|
||||
"recipe-url": "Adresse de la recette",
|
||||
"recipe-html-or-json": "Recette HTML ou JSON",
|
||||
"upload-a-recipe": "Télécharger une recette",
|
||||
"upload-individual-zip-file": "Chargez un fichier .zip exporté depuis une autre instance Mealie.",
|
||||
"upload-individual-zip-file": "Téléverser un fichier .zip exporté depuis une autre instance Mealie.",
|
||||
"url-form-hint": "Copiez et collez un lien depuis votre site de recettes favori",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copiez et collez l'URL source de vos données (facultatif)",
|
||||
"view-scraped-data": "Voir les données récupérées",
|
||||
"trim-whitespace-description": "Ajuster les espaces de début et de fin ainsi que les lignes vides",
|
||||
"trim-prefix-description": "Couper le premier caractère de chaque ligne",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Importer une recette par son URL",
|
||||
"create-manually": "Créer une recette manuellement",
|
||||
"make-recipe-image": "Faire de cette image l’image de recette",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Ajouter un aliment",
|
||||
"add-recipe": "Ajouter une recette"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Page introuvable",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Recette supprimée",
|
||||
"recipe-image": "Image de la recette",
|
||||
"recipe-image-updated": "L'image de la recette a été mise à jour",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Supprimer l'image de la recette",
|
||||
"delete-image-confirmation": "Êtes-vous sûr(e) de vouloir supprimer l'image de cette recette?",
|
||||
"recipe-image-deleted": "L'image de la recette a été supprimée",
|
||||
"recipe-name": "Nom de la recette",
|
||||
"recipe-settings": "Paramètres de la recette",
|
||||
"recipe-update-failed": "La mise à jour de la recette a échoué",
|
||||
@@ -560,17 +564,18 @@
|
||||
"failed-to-add-to-list": "Ajout dans la liste en échec",
|
||||
"yield": "Rendement",
|
||||
"yields-amount-with-text": "Produit {amount} {text}",
|
||||
"yield-text": "Unité",
|
||||
"yield-text": "Unité du rendement",
|
||||
"quantity": "Quantité",
|
||||
"choose-unit": "Choisir une unité",
|
||||
"press-enter-to-create": "Clique sur Entrer pour créer",
|
||||
"choose-food": "Choisir un aliment",
|
||||
"choose-recipe": "Choisir une recette",
|
||||
"notes": "Notes",
|
||||
"toggle-section": "Activer/désactiver la section",
|
||||
"see-original-text": "Afficher le texte original",
|
||||
"original-text-with-value": "Texte original: {originalText}",
|
||||
"ingredient-linker": "Association d’ingrédients",
|
||||
"unlinked": "Pas encore associée",
|
||||
"unlinked": "Pas encore lié",
|
||||
"linked-to-other-step": "Lié à une autre étape",
|
||||
"auto": "Auto",
|
||||
"cook-mode": "Mode Cuisine",
|
||||
@@ -592,10 +597,10 @@
|
||||
"made-this": "Je l’ai cuisiné",
|
||||
"how-did-it-turn-out": "C’était bon ?",
|
||||
"user-made-this": "{user} l’a cuisiné",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"made-for-recipe": "Cuisinée pour {recipe}",
|
||||
"added-to-timeline": "Ajouté à l’historique",
|
||||
"failed-to-add-to-timeline": "Ajout dans l’historique en échec",
|
||||
"failed-to-update-recipe": "Impossible de mettre à jour la recette",
|
||||
"failed-to-add-to-timeline": "Échec d'ajout à l'historique",
|
||||
"failed-to-update-recipe": "Échec de la mise à jour de la recette",
|
||||
"added-to-timeline-but-failed-to-add-image": "Ajouté à l’historique, mais impossible d’ajouter l’image",
|
||||
"api-extras-description": "Les suppléments des recettes sont une fonctionnalité clé de l’API Mealie. Ils permettent de créer des paires JSON clé/valeur personnalisées dans une recette, qui peuvent être référencées depuis des applications tierces. Ces clés peuvent être utilisées par exemple pour déclencher des tâches automatisées ou des messages personnalisés à transmettre à l’appareil souhaité.",
|
||||
"message-key": "Clé de message",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Essayez l’importateur de masse",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Vous avez des données brutes en HTML ou JSON ?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Vous pouvez directement importer des données brutes",
|
||||
"scrape-recipe-website-being-blocked": "Le site web est bloqué ?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Essayez plutôt d'importer le code HTML brut.",
|
||||
"import-original-keywords-as-tags": "Importer les mots-clés d'origine en tant que tags",
|
||||
"stay-in-edit-mode": "Rester en mode édition",
|
||||
"parse-recipe-ingredients-after-import": "Analyser les ingrédients de la recette après l'import",
|
||||
@@ -642,8 +649,8 @@
|
||||
"json-import-format-description-colon": "Pour importer via JSON, le format doit être valide :",
|
||||
"json-editor": "Éditeur JSON",
|
||||
"zip-files-must-have-been-exported-from-mealie": "Les fichiers .zip doivent avoir été exportés depuis Mealie",
|
||||
"create-a-recipe-by-uploading-a-scan": "Créer une recette en envoyant un scan.",
|
||||
"upload-a-png-image-from-a-recipe-book": "Importer une image png d'un livre de recettes",
|
||||
"create-a-recipe-by-uploading-a-scan": "Créer une recette en téléversant une image numérisée.",
|
||||
"upload-a-png-image-from-a-recipe-book": "Téléverser une image png d'un livre de recettes",
|
||||
"recipe-bulk-importer": "Importation en masse de recettes",
|
||||
"recipe-bulk-importer-description": "L'importateur en masse de recettes vous permet d'importer plusieurs recettes à la fois en lançant l'import en arrière-plan. Cela peut être utile lors de la migration vers Mealie, ou lorsque vous voulez importer un grand nombre de recettes.",
|
||||
"set-categories-and-tags": "Définir des catégories et des étiquettes",
|
||||
@@ -658,8 +665,8 @@
|
||||
"debug": "Déboguer",
|
||||
"tree-view": "Vue en arborescence",
|
||||
"recipe-servings": "Portions de la recette",
|
||||
"recipe-yield": "Nombre de parts",
|
||||
"recipe-yield-text": "Unité",
|
||||
"recipe-yield": "Rendement",
|
||||
"recipe-yield-text": "Unité du rendement",
|
||||
"unit": "Unité",
|
||||
"upload-image": "Ajouter une image",
|
||||
"screen-awake": "Garder l’écran allumé",
|
||||
@@ -685,19 +692,19 @@
|
||||
"confidence-score": "Score de confiance",
|
||||
"ingredient-parser-description": "Vos ingrédients ont été analysés avec succès. Veuillez vérifier les ingrédients dont nous ne sommes pas certains.",
|
||||
"ingredient-parser-final-review-description": "Une fois que tous les ingrédients ont été analysés, vous aurez encore une chance de vérifier tous les ingrédients avant de les appliquer à votre recette.",
|
||||
"add-text-as-alias-for-item": "Ajouter \"{text}\" comme alias pour {item}",
|
||||
"add-text-as-alias-for-item": "Ajouter \"{text}\" comme un alias pour {item}",
|
||||
"delete-item": "Supprimer l'élément"
|
||||
},
|
||||
"reset-servings-count": "Réinitialiser le nombre de portions",
|
||||
"not-linked-ingredients": "Ingrédients supplémentaires",
|
||||
"upload-another-image": "Télécharger une autre image",
|
||||
"upload-images": "Télécharger des images",
|
||||
"upload-more-images": "Télécharger d'autres images",
|
||||
"upload-another-image": "Téléverser une autre image",
|
||||
"upload-images": "Téléverser des images",
|
||||
"upload-more-images": "Téléverser d'autres images",
|
||||
"set-as-cover-image": "Définir comme image de couverture de la recette",
|
||||
"cover-image": "Image de couverture",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"include-linked-recipes": "Inclure les recettes liées",
|
||||
"include-linked-recipe-ingredients": "Inclure les ingrédients de la recette liée",
|
||||
"toggle-recipe": "Activer/désactiver la recette"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Recherche de recette",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Appuyez sur « /»",
|
||||
"advanced": "Avancé",
|
||||
"auto-search": "Recherche automatique",
|
||||
"no-results": "Pas de résultats trouvés"
|
||||
"no-results": "Pas de résultats trouvés",
|
||||
"type-to-search": "Tapez pour chercher..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Ajouter un nouveau thème",
|
||||
@@ -1073,7 +1081,7 @@
|
||||
"forgot-password": "Mot de passe oublié",
|
||||
"forgot-password-text": "Veuillez entrer votre adresse e-mail. Un e-mail vous sera envoyé afin de réinitialiser votre mot de passe.",
|
||||
"changes-reflected-immediately": "Les changements apportés à cet utilisateur seront immédiatement pris en compte.",
|
||||
"default-activity": "Activité par défaut ",
|
||||
"default-activity": "Activité principale",
|
||||
"default-activity-hint": "Sélectionnez la page que vous souhaitez ouvrir lors de la connexion sur cet appareil"
|
||||
},
|
||||
"language-dialog": {
|
||||
@@ -1343,7 +1351,7 @@
|
||||
"household-statistics": "Statistiques du foyer",
|
||||
"household-statistics-description": "Vos statistiques du foyer fournissent un aperçu sur la façon dont vous utilisez Mealie.",
|
||||
"storage-capacity": "Capacité de stockage",
|
||||
"storage-capacity-description": "Votre capacité de stockage est un calcul des images et des ressources que vous avez téléchargées.",
|
||||
"storage-capacity-description": "Votre capacité de stockage est un calcul des images et des ressources que vous avez téléversées.",
|
||||
"personal": "Personnel",
|
||||
"personal-description": "Il s'agit de paramètres qui vous sont personnels. Les modifications ici n'affecteront pas les autres utilisateurs.",
|
||||
"user-settings": "Paramètres utilisateur",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "est similaire à",
|
||||
"is-not-like": "n'est pas similaire à"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "Ce champ est obligatoire",
|
||||
"invalid-email": "L’e-mail doit être valide",
|
||||
"invalid-url": "Doit être une URL valide",
|
||||
"no-whitespace": "Aucun espace n'est autorisé",
|
||||
"min-length": "Doit contenir au moins {min} caractères",
|
||||
"max-length": "Doit contenir au maximum {max} caractères"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Petit-déjeuner",
|
||||
"lunch": "Déjeuner",
|
||||
"dinner": "Dîner",
|
||||
"snack": "Goûter",
|
||||
"drink": "Boissons",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Tous",
|
||||
"day-any": "Tous",
|
||||
"editor": "Éditeur",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Télécharger une recette",
|
||||
"upload-individual-zip-file": "Chargez un fichier .zip exporté depuis une autre instance Mealie.",
|
||||
"url-form-hint": "Copiez et collez un lien depuis votre site de recettes favori",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copiez et collez l'URL source de vos données (facultatif)",
|
||||
"view-scraped-data": "Voir les données récupérées",
|
||||
"trim-whitespace-description": "Ajuster les espaces de début et de fin ainsi que les lignes vides",
|
||||
"trim-prefix-description": "Couper le premier caractère de chaque ligne",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Importer une recette par son URL",
|
||||
"create-manually": "Créer une recette manuellement",
|
||||
"make-recipe-image": "Faire de cette image l’image de recette",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Ajouter un aliment",
|
||||
"add-recipe": "Ajouter une recette"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Page introuvable",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Recette supprimée",
|
||||
"recipe-image": "Image de la recette",
|
||||
"recipe-image-updated": "L’image de la recette a été mise à jour",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Supprimer l'image de la recette",
|
||||
"delete-image-confirmation": "Êtes-vous sûr de vouloir supprimer l'image de cette recette ?",
|
||||
"recipe-image-deleted": "L’image de la recette a été supprimée",
|
||||
"recipe-name": "Nom de la recette",
|
||||
"recipe-settings": "Paramètres de la recette",
|
||||
"recipe-update-failed": "La mise à jour de la recette a échoué",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Choisissez une unité",
|
||||
"press-enter-to-create": "Clique sur Entrer pour créer",
|
||||
"choose-food": "Choisissez un aliment",
|
||||
"choose-recipe": "Choisissez la recette",
|
||||
"notes": "Notes",
|
||||
"toggle-section": "Activer/Désactiver la section",
|
||||
"see-original-text": "Afficher le texte original",
|
||||
@@ -592,7 +597,7 @@
|
||||
"made-this": "Je l’ai cuisiné",
|
||||
"how-did-it-turn-out": "C’était bon ?",
|
||||
"user-made-this": "{user} l’a cuisiné",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"made-for-recipe": "Fait pour {recipe}",
|
||||
"added-to-timeline": "Ajouté à l’historique",
|
||||
"failed-to-add-to-timeline": "Ajout dans l’historique en échec",
|
||||
"failed-to-update-recipe": "Impossible de mettre à jour la recette",
|
||||
@@ -627,11 +632,13 @@
|
||||
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "Créer une recette en fournissant le nom. Toutes les recettes doivent avoir des noms uniques.",
|
||||
"new-recipe-names-must-be-unique": "Les noms de nouvelles recettes doivent être uniques",
|
||||
"scrape-recipe": "Récupérer une recette",
|
||||
"scrape-recipe-description": "Récupérer une recette par URL. Fournissez l'URL de la page que vous voulez récupérer, et Mealie essaiera d'en extraire la recette pour l'ajouter à votre collection.",
|
||||
"scrape-recipe-description": "Récupérer une recette par URL. Fournissez l'URL de la page que vous voulez récupérer et Mealie essaiera d'en extraire la recette pour l'ajouter à votre collection.",
|
||||
"scrape-recipe-have-a-lot-of-recipes": "Vous avez un tas de recettes à récupérer d’un coup ?",
|
||||
"scrape-recipe-suggest-bulk-importer": "Essayez l’importateur de masse",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Vous avez des données brutes en HTML ou JSON ?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Vous pouvez directement importer des données brutes",
|
||||
"scrape-recipe-website-being-blocked": "Le site web est bloqué ?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Essayez plutôt d'importer le code HTML brut.",
|
||||
"import-original-keywords-as-tags": "Importer les mots-clés d'origine en tant que tags",
|
||||
"stay-in-edit-mode": "Rester en mode édition",
|
||||
"parse-recipe-ingredients-after-import": "Analyser les ingrédients de la recette après l'import",
|
||||
@@ -695,9 +702,9 @@
|
||||
"upload-more-images": "Télécharger d'autres images",
|
||||
"set-as-cover-image": "Définir comme image de couverture de la recette",
|
||||
"cover-image": "Image de couverture",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"include-linked-recipes": "Inclure les recettes liées",
|
||||
"include-linked-recipe-ingredients": "Inclure les ingrédients de la recette liée",
|
||||
"toggle-recipe": "Afficher/Masquer la recette"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Recherche de recette",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Appuyez sur « /»",
|
||||
"advanced": "Avancé",
|
||||
"auto-search": "Recherche automatique",
|
||||
"no-results": "Aucun résultat trouvé"
|
||||
"no-results": "Aucun résultat trouvé",
|
||||
"type-to-search": "Tapez pour chercher..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Ajouter un nouveau thème",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "est comme",
|
||||
"is-not-like": "n'est pas similaire à"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "Ce champ est obligatoire",
|
||||
"invalid-email": "L’e-mail doit être valide",
|
||||
"invalid-url": "Doit être une URL valide",
|
||||
"no-whitespace": "Aucun espace n'est autorisé",
|
||||
"min-length": "Doit contenir au moins {min} caractères",
|
||||
"max-length": "Doit contenir au maximum {max} caractères"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Almorzo",
|
||||
"lunch": "Xantar",
|
||||
"dinner": "Cea",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Calquera",
|
||||
"day-any": "Calquera",
|
||||
"editor": "Editor",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Cargar unha Receita",
|
||||
"upload-individual-zip-file": "Cargar un ficheiro .zip individual, exportado de outra instancia do Mealie.",
|
||||
"url-form-hint": "Copie e pegue un link do seu site de receitas favorito",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "Ver datos recollidos",
|
||||
"trim-whitespace-description": "Eliminar os espazos en branco no início e no fin, asi como as liñas en branco",
|
||||
"trim-prefix-description": "Eliminar o primeiro caracter de cada liña",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Escolla Unidade",
|
||||
"press-enter-to-create": "Prema 'Enter' para Crear",
|
||||
"choose-food": "Escoller Alimento",
|
||||
"choose-recipe": "Choose Recipe",
|
||||
"notes": "Notas",
|
||||
"toggle-section": "Alternar Sección",
|
||||
"see-original-text": "Mostrar Texto Orixinal",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Prove o importador en masa",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Ten datos HTML ou JSON en bruto?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "É posível importar diretamente a partir de datos en bruto",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "Importar palavras-chave orixinais como etiquetas",
|
||||
"stay-in-edit-mode": "Permanecer no modo de edición",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Prema '/'",
|
||||
"advanced": "Avanzado",
|
||||
"auto-search": "Pesquisa Automática",
|
||||
"no-results": "Nengun resultado encontrado"
|
||||
"no-results": "Nengun resultado encontrado",
|
||||
"type-to-search": "Type to search..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Adicionar novo tema",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "é como",
|
||||
"is-not-like": "non é como"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "ארוחת בוקר",
|
||||
"lunch": "ארוחת צהריים",
|
||||
"dinner": "ארוחת ערב",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "הכל",
|
||||
"day-any": "הכל",
|
||||
"editor": "עורך",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "העלאת מתכון",
|
||||
"upload-individual-zip-file": "העלאת קובץ זיפ שיוצא ממילי אחר.",
|
||||
"url-form-hint": "העתק והדבק קישור מאתר המתכונים המועדף עליך",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "צפייה במידע שנאסף",
|
||||
"trim-whitespace-description": "הסר רווחים מתחילת / סוף שורה ושורות ריקות",
|
||||
"trim-prefix-description": "חתוך תו ראשון מכל שורה",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "ייבוא מתכון באמצעות לינק",
|
||||
"create-manually": "יצירת מתכון ידנית",
|
||||
"make-recipe-image": "הפוך תמונה זאת לתמונת המתכון",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "הוסף מאכל",
|
||||
"add-recipe": "הוסף מתכון"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 העמוד אינו נמצא",
|
||||
@@ -480,7 +484,7 @@
|
||||
"comment": "הערה",
|
||||
"comments": "הערות",
|
||||
"delete-confirmation": "למחוק את המתכון הזה?",
|
||||
"admin-delete-confirmation": "You're about to delete a recipe that isn't yours using admin permissions. Are you sure?",
|
||||
"admin-delete-confirmation": "אתה עומד למחוק מתכון שאינו שלך באמצעות הרשאות מנהל. האם אתה בטוח?",
|
||||
"delete-recipe": "מחיקת מתכון",
|
||||
"description": "תיאור",
|
||||
"disable-amount": "ביטול כמויות מרכיבים",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "מתכון נמחק",
|
||||
"recipe-image": "תמונת המתכון",
|
||||
"recipe-image-updated": "תמונת המתכון עודכנה",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "מחק תמונת מתכון",
|
||||
"delete-image-confirmation": "האם אתה בטוח שאתה רוצה למחוק את תמונת המתכון?",
|
||||
"recipe-image-deleted": "תמונת מתכון נמחקה",
|
||||
"recipe-name": "שם המתכון",
|
||||
"recipe-settings": "הגדרות המתכון",
|
||||
"recipe-update-failed": "עדכון מתכון נכשל",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "בחירת יחידת מידה",
|
||||
"press-enter-to-create": "הקש Enter כדי להוסיף",
|
||||
"choose-food": "בחר מזון",
|
||||
"choose-recipe": "בחר מתכון",
|
||||
"notes": "הערות",
|
||||
"toggle-section": "צור כותרת",
|
||||
"see-original-text": "הטקסט המקורי",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "נסה את יכולת קריאת רשימה",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "יש לך מידע גולמי ב-HTML או JSON?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "ניתן לייבא ישירות ממידע גולמי",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "ייבוא שמות מפתח מקוריות כתגיות",
|
||||
"stay-in-edit-mode": "השאר במצב עריכה",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "לחץ '/'",
|
||||
"advanced": "מתקדם",
|
||||
"auto-search": "חיפוש אוטומטי",
|
||||
"no-results": "לא נמצאו תוצאות"
|
||||
"no-results": "לא נמצאו תוצאות",
|
||||
"type-to-search": "הקלד לחיפוש..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "הוסף ערכת נושא חדשה",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "דומה ל-",
|
||||
"is-not-like": "לא דומה לא-"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Doručak",
|
||||
"lunch": "Ručak",
|
||||
"dinner": "Večera",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Bilo koji",
|
||||
"day-any": "Bilo koji",
|
||||
"editor": "Urednik",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Učitaj Recept",
|
||||
"upload-individual-zip-file": "Prenesite pojedinačnu .zip datoteku koja je izvezena iz druge instance Mealie aplikacije.",
|
||||
"url-form-hint": "Kopirajte i zalijepite poveznicu s vaše omiljene web stranice za recepte",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "Prikaz Prikupljenih Podataka",
|
||||
"trim-whitespace-description": "Ukloni vodeće i slijedeće praznine, kao i prazne linije",
|
||||
"trim-prefix-description": "Ukloni prvi znak sa svake linije",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Odaberi Jedinicu",
|
||||
"press-enter-to-create": "Pritisni Enter za Kreiranje",
|
||||
"choose-food": "Odaberi Hranu",
|
||||
"choose-recipe": "Choose Recipe",
|
||||
"notes": "Bilješke",
|
||||
"toggle-section": "Preklopi Odjeljak",
|
||||
"see-original-text": "Prikaži Izvorni Tekst",
|
||||
@@ -577,7 +582,7 @@
|
||||
"link-ingredients": "Poveži Sastojke",
|
||||
"merge-above": "Spoji prethodni korak",
|
||||
"move-to-bottom": "Move To Bottom",
|
||||
"move-to-top": "Move To Top",
|
||||
"move-to-top": "Na vrh",
|
||||
"reset-scale": "Vrati skaliranje na stare postavke",
|
||||
"decrease-scale-label": "Smanji skaliranje za 1",
|
||||
"increase-scale-label": "Povećaj skaliranje za 1",
|
||||
@@ -586,17 +591,17 @@
|
||||
"edit-timeline-event": "Uredi Događaj Vremenske Crte",
|
||||
"timeline": "Vremenska Crta",
|
||||
"timeline-is-empty": "Još nema ništa na vremenskoj crti. Pokušajte napraviti ovaj recept!",
|
||||
"timeline-no-events-found-try-adjusting-filters": "No events found. Try adjusting your search filters.",
|
||||
"timeline-no-events-found-try-adjusting-filters": "Nisu pronađeni događaji. Pokušaj promjeniti filtere za pretragu.",
|
||||
"group-global-timeline": "{groupName} Globalna vremenska crta",
|
||||
"open-timeline": "Otvori Vremensku Crtu",
|
||||
"made-this": "Napravio/la sam ovo",
|
||||
"how-did-it-turn-out": "Kako je ispalo?",
|
||||
"user-made-this": "{user} je napravio/la ovo",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"added-to-timeline": "Added to timeline",
|
||||
"failed-to-add-to-timeline": "Failed to add to timeline",
|
||||
"failed-to-update-recipe": "Failed to update recipe",
|
||||
"added-to-timeline-but-failed-to-add-image": "Added to timeline, but failed to add image",
|
||||
"made-for-recipe": "Napravljeno za {recipe}",
|
||||
"added-to-timeline": "Dodano na vremensku crtu",
|
||||
"failed-to-add-to-timeline": "Neuspješno dodavanje na vremensku crtu",
|
||||
"failed-to-update-recipe": "Neuspješno ažuriranje recepta",
|
||||
"added-to-timeline-but-failed-to-add-image": "Dodano na vremensku crtu, no nije uspjelo dodavanje fotografije",
|
||||
"api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom JSON key/value pairs within a recipe, to reference from 3rd party applications. You can use these keys to provide information, for example to trigger automations or custom messages to relay to your desired device.",
|
||||
"message-key": "Ključ poruke",
|
||||
"parse": "Razluči (parsiraj)",
|
||||
@@ -612,33 +617,35 @@
|
||||
"looking-for-migrations": "Tražite migracije?",
|
||||
"import-with-url": "Učitaj preko URL-a",
|
||||
"create-recipe": "Kreiraj recept",
|
||||
"create-recipe-description": "Create a new recipe from scratch.",
|
||||
"create-recipe-description": "Izradi novi recept od početka",
|
||||
"create-recipes": "Kreiraj recept",
|
||||
"import-with-zip": "Učitaj pomoću .zip-a",
|
||||
"create-recipe-from-an-image": "Create Recipe from an Image",
|
||||
"create-recipe-from-an-image-description": "Create a recipe by uploading an image of it. Mealie will attempt to extract the text from the image using AI and create a recipe from it.",
|
||||
"crop-and-rotate-the-image": "Crop and rotate the image so that only the text is visible, and it's in the correct orientation.",
|
||||
"create-from-images": "Create from Images",
|
||||
"should-translate-description": "Translate the recipe into my language",
|
||||
"please-wait-image-procesing": "Please wait, the image is processing. This may take some time.",
|
||||
"please-wait-images-processing": "Please wait, the images are processing. This may take some time.",
|
||||
"crop-and-rotate-the-image": "Obreži i rotiraj sliku tako da bude vidljiv samo tekst i da bude u ispravnoj orijentaciji.",
|
||||
"create-from-images": "Izradi na temelju fotografije",
|
||||
"should-translate-description": "Prevedi recept na moj jezik",
|
||||
"please-wait-image-procesing": "Molimo pričekajte, slika se obrađuje. Ovo može potrajati.",
|
||||
"please-wait-images-processing": "Molimo pričekajte, slike se obrađuju. Ovo može potrajati.",
|
||||
"bulk-url-import": "Uvoz više URL-ova",
|
||||
"debug-scraper": "Debugiranje skraper-a",
|
||||
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "Kreirajte recept pružajući naziv. Svi recepti moraju imati jedinstvena imena.",
|
||||
"new-recipe-names-must-be-unique": "Naziv novog recepta mora imati jedinstveno ime",
|
||||
"scrape-recipe": "Prikupi (skraperaj) recept",
|
||||
"scrape-recipe-description": "Prikupi (skraperaj) recept putem URL-a. Priložite URL web stranice s koje želite prikupiti recept, a Mealie će pokušati prikupiti recept s te stranice i dodati ga u vašu kolekciju.",
|
||||
"scrape-recipe-have-a-lot-of-recipes": "Have a lot of recipes you want to scrape at once?",
|
||||
"scrape-recipe-suggest-bulk-importer": "Try out the bulk importer",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Have raw HTML or JSON data?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "You can import from raw data directly",
|
||||
"scrape-recipe-have-a-lot-of-recipes": "Imate puno recepata koje želite odjednom preuzeti?",
|
||||
"scrape-recipe-suggest-bulk-importer": "Isprobajte masovni uvoz",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Imate neobrađene HTML ili JSON podatke?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Možete uvesti iz neobrađenih podataka izravno",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "Uvezi originalne ključne riječi kao oznake",
|
||||
"stay-in-edit-mode": "Ostanite u načinu uređivanja",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
"parse-recipe-ingredients-after-import": "Parsiranje sastojaka recepta nakon uvoza",
|
||||
"import-from-zip": "Uvoz iz Zip-a",
|
||||
"import-from-zip-description": "Uvezi pojedinačni recept koji je izvezen iz druge instance Mealie aplikacije.",
|
||||
"import-from-html-or-json": "Import from HTML or JSON",
|
||||
"import-from-html-or-json-description": "Import a single recipe from raw HTML or JSON. This is useful if you have a recipe from a site that Mealie can't scrape normally, or from some other external source.",
|
||||
"import-from-html-or-json": "Uvoz iz HTML-a ili JSON-a",
|
||||
"import-from-html-or-json-description": "Uvezite jedan recept iz neobrađenog HTML-a ili JSON-a. Ovo je korisno ako imate recept s web-stranice koju Mealie ne može normalno preuzeti ili iz nekog drugog vanjskog izvora.",
|
||||
"json-import-format-description-colon": "To import via JSON, it must be in valid format:",
|
||||
"json-editor": "JSON uređivač",
|
||||
"zip-files-must-have-been-exported-from-mealie": ".zip datoteke moraju biti izvezeni iz Mealie-a",
|
||||
@@ -712,7 +719,7 @@
|
||||
"max-missing-ingredients": "Max Missing Ingredients",
|
||||
"max-missing-tools": "Max Missing Tools",
|
||||
"selected-tools": "Selected Tools",
|
||||
"other-filters": "Other Filters",
|
||||
"other-filters": "Ostali filtri",
|
||||
"ready-to-make": "Ready to Make",
|
||||
"almost-ready-to-make": "Almost Ready to Make"
|
||||
},
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Pritisni '/'",
|
||||
"advanced": "Napredno",
|
||||
"auto-search": "Auto Pretraga",
|
||||
"no-results": "No results found"
|
||||
"no-results": "No results found",
|
||||
"type-to-search": "Type to search..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Dodaj Novu Temu",
|
||||
@@ -1382,7 +1390,7 @@
|
||||
},
|
||||
"cookbook": {
|
||||
"cookbooks": "Zbirka recepata",
|
||||
"description": "Cookbooks are another way to organize recipes by creating cross sections of recipes, organizers, and other filters. Creating a cookbook will add an entry to the side-bar and all the recipes with the filters chosen will be displayed in the cookbook.",
|
||||
"description": "Zbirke recepata su još jedan način organiziranja recepata stvaranjem presjeka recepata, organizatora i ostalih filtera. Izrada zbirke recepata dodat će stavku na bočnu traku, a svi recepti s odabranim filtrima bit će prikazani u zbirci recepata.",
|
||||
"hide-cookbooks-from-other-households": "Hide Cookbooks from Other Households",
|
||||
"hide-cookbooks-from-other-households-description": "When enabled, only cookbooks from your household will appear on the sidebar",
|
||||
"public-cookbook": "Javna zbirka recepata",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "is like",
|
||||
"is-not-like": "is not like"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Reggeli",
|
||||
"lunch": "Ebéd",
|
||||
"dinner": "Vacsora",
|
||||
"snack": "Rágcsa",
|
||||
"drink": "Ital",
|
||||
"dessert": "Desszert",
|
||||
"type-any": "Bármely",
|
||||
"day-any": "Bármely",
|
||||
"editor": "Szerkesztő",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Recept feltöltése",
|
||||
"upload-individual-zip-file": "Tölts fel egy .zíp archívumot, ami egy másik Mealie példányból lett exportálva.",
|
||||
"url-form-hint": "Másold be a linket a kedvenc recept weboldaladról",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Másolja és illessze be az adatok forrás URL-jét (opcionális)",
|
||||
"view-scraped-data": "Letöltött adat megtekintése",
|
||||
"trim-whitespace-description": "Vágja le a kezdő és a záró fehérjeleket, valamint az üres sorokat",
|
||||
"trim-prefix-description": "Minden sor első karakterének levágása",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Recept importálása URL-cím alapján",
|
||||
"create-manually": "Recept kézi létrehozása",
|
||||
"make-recipe-image": "Ez legyen a recept képe",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Étel hozzáadása",
|
||||
"add-recipe": "Recept hozzáadása"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404. Az oldal nem található",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Recept törölve",
|
||||
"recipe-image": "Recept képe",
|
||||
"recipe-image-updated": "Recept képe frissítve",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Receptkép törlése",
|
||||
"delete-image-confirmation": "Biztosan törli ezt a receptképet?",
|
||||
"recipe-image-deleted": "Receptkép törölve",
|
||||
"recipe-name": "Recept neve",
|
||||
"recipe-settings": "Recept beállítások",
|
||||
"recipe-update-failed": "Recept frissítése sikertelen",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Válasszon mennyiségi egységet",
|
||||
"press-enter-to-create": "Üssön Enter-t a létrehozáshoz",
|
||||
"choose-food": "Étel kiválasztása",
|
||||
"choose-recipe": "Recept kiválasztása",
|
||||
"notes": "Megjegyzések",
|
||||
"toggle-section": "Szakaszcím megjelenítése/kikapcsolása",
|
||||
"see-original-text": "Eredeti szöveg megjelenítése",
|
||||
@@ -592,7 +597,7 @@
|
||||
"made-this": "Elkészítettem ezt",
|
||||
"how-did-it-turn-out": "Hogyan sikerült?",
|
||||
"user-made-this": "ezt {user} készítette el",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"made-for-recipe": "Készült {recipe} számára",
|
||||
"added-to-timeline": "Idővonalhoz hozzáadva",
|
||||
"failed-to-add-to-timeline": "Nem sikerült az idővonalhoz hozzáadni",
|
||||
"failed-to-update-recipe": "Nem sikerült frissíteni a receptet",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Próbálja ki a tömeges importálót",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Nyers HTML vagy JSON adatai vannak?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "A nyers adatokból közvetlenül is importálhat",
|
||||
"scrape-recipe-website-being-blocked": "A weboldal blokkolva van?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Próbálja meg inkább a nyers HTML-t importálni.",
|
||||
"import-original-keywords-as-tags": "Eredeti kulcsszavak importálása címkeként",
|
||||
"stay-in-edit-mode": "Maradjon Szerkesztés módban",
|
||||
"parse-recipe-ingredients-after-import": "Recept összetevőinek elemzése importálás után",
|
||||
@@ -695,9 +702,9 @@
|
||||
"upload-more-images": "További képek feltöltése",
|
||||
"set-as-cover-image": "Beállítás a recept borítóképének",
|
||||
"cover-image": "Borítókép",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"include-linked-recipes": "Kapcsolódó receptek hozzáadása",
|
||||
"include-linked-recipe-ingredients": "Kapcsolódó recept hozzávalók hozzáadása",
|
||||
"toggle-recipe": "Recept váltása"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Receptkereső",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Üsse be '/'",
|
||||
"advanced": "Haladó mód",
|
||||
"auto-search": "Automatikus keresés",
|
||||
"no-results": "Nincs találat"
|
||||
"no-results": "Nincs találat",
|
||||
"type-to-search": "Írja be a keresett szót..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Új téma hozzáadása",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "hasonló",
|
||||
"is-not-like": "nem hasonló"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "Ez kötelező mező",
|
||||
"invalid-email": "E-mail-nek érvényesnek kell lennie",
|
||||
"invalid-url": "Érvényes URL-nek kell lennie",
|
||||
"no-whitespace": "Szóközt nem tartalmazhat",
|
||||
"min-length": "Legalább {min} karakter legyen",
|
||||
"max-length": "Legfeljebb {max} karakter legyen"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
"new-notification": "Ný tilkynning",
|
||||
"event-notifiers": "Viðburðar tilkynningar",
|
||||
"apprise-url-skipped-if-blank": "Apprise URL (sleppt ef tómt)",
|
||||
"apprise-url-is-left-intentionally-blank": "Þar sem \"Apprise\" slóðir innihalda yfirleitt viðkvæmar upplýsingar, er þessum reit viljandi skilið eftir auðum við breytingar. Ef þú vilt uppfæra slóðina skaltu slá inn þá nýju hér, annars skaltu skilja reitinn eftir auðan til að halda núverandi slóð.",
|
||||
"apprise-url-is-left-intentionally-blank": "Þar sem \"Apprise\" slóðir innihalda yfirleitt viðkvæmar upplýsingar, er þessi reitur viljandi skilinn eftir auður. Ef þú vilt uppfæra slóðina skaltu slá inn hana inn hér, annars skaltu skilja reitinn eftir auðan til að halda núverandi slóð.",
|
||||
"enable-notifier": "Virkja tilkynningar",
|
||||
"what-events": "Hvaða viðburði ætti þessi tilkynnir að vera áskrifandi að?",
|
||||
"user-events": "Notenda viðburðir",
|
||||
@@ -80,7 +80,7 @@
|
||||
"tag-events": "Merki viðburðir",
|
||||
"category-events": "Flokka viðburðir",
|
||||
"when-a-new-user-joins-your-group": "Þegar nýr notandi bætist við í þinn hóp",
|
||||
"recipe-events": "Uppskriftar viðburðir",
|
||||
"recipe-events": "Uppskriftarviðburðir",
|
||||
"label-events": "Merkja viðburð"
|
||||
},
|
||||
"general": {
|
||||
@@ -110,7 +110,7 @@
|
||||
"file-folder-not-found": "Skrá/mappe finnst ekki",
|
||||
"file-uploaded": "Skrá",
|
||||
"filter": "Sía",
|
||||
"friday": "Föstudagur",
|
||||
"friday": "Föstudag",
|
||||
"general": "Almennt",
|
||||
"get": "Sækja",
|
||||
"home": "Heim",
|
||||
@@ -126,7 +126,7 @@
|
||||
"loading-ocr-data": "Hleður OCR gögnum...",
|
||||
"loading-recipes": "Hleð uppskriftum",
|
||||
"message": "Skilaboð",
|
||||
"monday": "Mánudagur",
|
||||
"monday": "Mánudag",
|
||||
"name": "Nafn",
|
||||
"new": "Nýtt",
|
||||
"never": "Aldrei",
|
||||
@@ -144,7 +144,7 @@
|
||||
"recipes": "Uppskriftir",
|
||||
"rename-object": "Endurnefna {0}",
|
||||
"reset": "Endurstilla",
|
||||
"saturday": "Laugardagur",
|
||||
"saturday": "Laugardag",
|
||||
"save": "Vista",
|
||||
"settings": "Stillingar",
|
||||
"share": "Deila",
|
||||
@@ -158,22 +158,22 @@
|
||||
"subject": "Efni",
|
||||
"submit": "Staðfesta",
|
||||
"success-count": "Tókst: {count}",
|
||||
"sunday": "Sunnudagur",
|
||||
"sunday": "Sunnudag",
|
||||
"system": "Kerfi",
|
||||
"templates": "Sniðmót:",
|
||||
"test": "Prufa",
|
||||
"themes": "Þema",
|
||||
"thursday": "Fimmtudagur",
|
||||
"thursday": "Fimmtudag",
|
||||
"title": "Titill",
|
||||
"token": "Tóki",
|
||||
"tuesday": "Þriðjudagur",
|
||||
"tuesday": "Þriðjudag",
|
||||
"type": "Tegund",
|
||||
"update": "Uppfæra",
|
||||
"updated": "Uppfært",
|
||||
"upload": "Hlaða upp",
|
||||
"url": "URL",
|
||||
"view": "Skoða",
|
||||
"wednesday": "Miðvikudagur",
|
||||
"wednesday": "Miðvikudag",
|
||||
"yes": "Já",
|
||||
"foods": "Matvara",
|
||||
"units": "Mælieiningar",
|
||||
@@ -306,7 +306,7 @@
|
||||
"meal-plan": {
|
||||
"create-a-new-meal-plan": "Búa til nýtt matarplan",
|
||||
"update-this-meal-plan": "Uppfæra matarplan",
|
||||
"dinner-this-week": "Kvöldmaturinn í þessari viku",
|
||||
"dinner-this-week": "Kvöldmatur þessa viku",
|
||||
"dinner-today": "Kvöldmaturinn í dag",
|
||||
"dinner-tonight": "KVÖLDMATUR Í KVÖLD",
|
||||
"edit-meal-plan": "Breyta matarplani",
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Morgunverður",
|
||||
"lunch": "Hádegisverður",
|
||||
"dinner": "Kvöldverður",
|
||||
"snack": "Snarl",
|
||||
"drink": "Drykkur",
|
||||
"dessert": "Eftirréttur",
|
||||
"type-any": "Allir",
|
||||
"day-any": "Alla",
|
||||
"editor": "Ritill",
|
||||
@@ -367,7 +370,7 @@
|
||||
"meal-plan-settings": "Stillingar matarplans"
|
||||
},
|
||||
"migration": {
|
||||
"migration-data-removed": "Flutningsgögn fjarlægð",
|
||||
"migration-data-removed": "Gagnaflutningur fjarlægður",
|
||||
"new-migration": "Ný flutningsgögn",
|
||||
"no-file-selected": "Engin skrá valin",
|
||||
"no-migration-data-available": "Engin gögn tiltæk",
|
||||
@@ -397,7 +400,7 @@
|
||||
},
|
||||
"tandoor": {
|
||||
"description-long": "Mealie getur flutt inn uppskriftir frá Tandoor. Flyttu út gögnin í sjálfgefnu formi svo hleður þú upp .zip skránni hér fyrir neðan.",
|
||||
"title": "Tandoor uppskriftir"
|
||||
"title": "Tandoor Recipes"
|
||||
},
|
||||
"cookn": {
|
||||
"description-long": "Mealie getur flutt inn uppskriftir frá DVO Cook'n X3. Flyttu matreiðslubókina eða valmyndina í „Cook'n“ sniði, endurnefndu skráarendinguna í .zip og flyttu svo .zip skrána inn hér fyrir neðan.",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Hlaða inn uppskrift",
|
||||
"upload-individual-zip-file": "Hlaða inn .zip skrá sem er flutt úr annarri Mealie uppsetningu.",
|
||||
"url-form-hint": "Afritaðu og límdu tengil frá uppáhalds uppskriftar síðunni þinni",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "Skoða unnin gögn",
|
||||
"trim-whitespace-description": "Fjarlægja bil fremst og aftast í texta sem og auðum línum",
|
||||
"trim-prefix-description": "Eyða fyrsta staf úr hverri línu",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Hlaða inn uppskrift frá slóð",
|
||||
"create-manually": "Skrifa nýja uppskrift",
|
||||
"make-recipe-image": "Gera þessa að uppskriftar myndinni",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Bæta við matvöru",
|
||||
"add-recipe": "Bæta við uppskrift"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 síðan fannst ekki",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Uppskrift eytt",
|
||||
"recipe-image": "Mynd af uppskrift",
|
||||
"recipe-image-updated": "Mynd af uppskrift uppfærð",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Eyða mynd af uppskrift",
|
||||
"delete-image-confirmation": "Ertu viss um að þú viljir eyða myndinni úr uppskriftinni?",
|
||||
"recipe-image-deleted": "Mynd af uppskrift eytt",
|
||||
"recipe-name": "Nafn uppskriftar",
|
||||
"recipe-settings": "Stillingar uppskriftar",
|
||||
"recipe-update-failed": "Mistókst að uppfæra uppskrift",
|
||||
@@ -545,7 +549,7 @@
|
||||
"locked-by-owner": "Læst af eiganda",
|
||||
"join-the-conversation": "Taka þátt í samtalinu",
|
||||
"add-recipe-to-mealplan": "Bæta uppskrift við matarplan",
|
||||
"entry-type": "Entry Type",
|
||||
"entry-type": "Máltíðartegund",
|
||||
"date-format-hint": "MM/DD/ÁÁÁÁ snið",
|
||||
"date-format-hint-yyyy-mm-dd": "ÁÁÁÁ-MM-DD snið",
|
||||
"add-to-list": "Bæta á lista",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Veldu mælieiningu",
|
||||
"press-enter-to-create": "Ýttu á Enter til að stofna",
|
||||
"choose-food": "Veldu matvöru",
|
||||
"choose-recipe": "Veldu uppskrift",
|
||||
"notes": "Athugasemdir",
|
||||
"toggle-section": "Setja inn skiptingu",
|
||||
"see-original-text": "Sjá upprunalegan texta",
|
||||
@@ -609,14 +614,14 @@
|
||||
"edit-markdown": "Breyta markdown",
|
||||
"recipe-creation": "Setja inn uppskrift",
|
||||
"select-one-of-the-various-ways-to-create-a-recipe": "Veldu einn af möguleikunum til að setja inn uppskrift",
|
||||
"looking-for-migrations": "Ertu að leita af flutningsgögnum?",
|
||||
"looking-for-migrations": "Ertu að leita af gagnaflutningi?",
|
||||
"import-with-url": "Hlaða inn frá slóð",
|
||||
"create-recipe": "Stofna uppskrift",
|
||||
"create-recipe-description": "Stofna nýja uppskrift frá grunni.",
|
||||
"create-recipes": "Stofna uppskriftir",
|
||||
"import-with-zip": "Hlaða inn með .zip",
|
||||
"create-recipe-from-an-image": "Create Recipe from an Image",
|
||||
"create-recipe-from-an-image-description": "Create a recipe by uploading an image of it. Mealie will attempt to extract the text from the image using AI and create a recipe from it.",
|
||||
"create-recipe-from-an-image": "Stofna uppskrift út frá mynd",
|
||||
"create-recipe-from-an-image-description": "Stofna uppskrift með því hlaða inn myndum af uppskriftartextanum. Mealie mun reyna að vinna texta úr myndunum með gervigreind og stofna nýja uppskrift út frá textanum.",
|
||||
"crop-and-rotate-the-image": "Sníða og snúa mynd svo bara textinn sé sýnilegur og að myndin snúi rétt.",
|
||||
"create-from-images": "Stofna uppskrift frá mynd",
|
||||
"should-translate-description": "Þýða uppskrift á mitt tungumál",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Prófaðu að setja inn margar uppskriftir í einu",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Ertu með hrá HTML eða JSON gögn?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "Það er hægt að hlaða inn hráum gögnum beint",
|
||||
"scrape-recipe-website-being-blocked": "Er vefsíðan lokuð?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Reyndu að flytja inn HTML kóðann í staðinn.",
|
||||
"import-original-keywords-as-tags": "Nota upprunanleg merki",
|
||||
"stay-in-edit-mode": "Vera í breytingarham",
|
||||
"parse-recipe-ingredients-after-import": "Greina innhald uppskriftar eftir að búið er að hlaða inn uppskrift",
|
||||
@@ -654,7 +661,7 @@
|
||||
"recipe-debugger": "Yfirfara uppskrift",
|
||||
"recipe-debugger-description": "Náðu í slóðina af uppskriftinni sem þú villt yfirfara og límdu hana hér. Síðan með uppskriftinni verður greind með greiningarverkfærinu og þú munnt sjá niðurstöðuna. Ef þú sérð að engin gögn skila sér þá er slóðin sem þú ert að greina ekki studd af Mealie eða greiningarverkfærinu.",
|
||||
"use-openai": "Nota OpenAI",
|
||||
"recipe-debugger-use-openai-description": "Nota OpenAI til að greina í staðinn fyrir að treysta á greiningar verkfærið. Þegar er fengin af slóð þá gerist þetta sjálfkrafa ef almenn greining mistekst, en þú getur prófað það hér.",
|
||||
"recipe-debugger-use-openai-description": "Nota OpenAI til að greina í staðinn fyrir að treysta á greiningar verkfærið. Ef greiningar verkfærinu mistekst að greina uppskrift af vefslóð þá gerist það sjálfvirkt að OpenAI greinir uppskriftina en þú getur prófað þetta sjálfur hér.",
|
||||
"debug": "Villuleit",
|
||||
"tree-view": "Tré sýn",
|
||||
"recipe-servings": "Fjöldi skammta",
|
||||
@@ -697,7 +704,7 @@
|
||||
"cover-image": "Forsíðumynd",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"toggle-recipe": "Víxla uppskrift"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Uppskriftaleit",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Ýttu á '/'",
|
||||
"advanced": "Ítarlegt",
|
||||
"auto-search": "Sjálfvirk leit",
|
||||
"no-results": "Ekkert fannst"
|
||||
"no-results": "Ekkert fannst",
|
||||
"type-to-search": "Skrifa til að leita..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Bæta við nýju þema",
|
||||
@@ -781,7 +789,7 @@
|
||||
"latest": "Síðasta",
|
||||
"local-api": "Staðbundið API",
|
||||
"locale-settings": "Staðbundnar stillingar",
|
||||
"migrations": "Migrations",
|
||||
"migrations": "Gagnaflutningur",
|
||||
"new-page": "Ný síða",
|
||||
"notify": "Tilkynna",
|
||||
"organize": "Skipuleggja",
|
||||
@@ -841,29 +849,29 @@
|
||||
"webhooks": {
|
||||
"test-webhooks": "Test Webhooks",
|
||||
"the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "The URLs listed below will receive webhooks containing the recipe data for the meal plan on it's scheduled day. Currently Webhooks will execute at",
|
||||
"webhook-url": "Webhook URL",
|
||||
"webhook-url": "Vefkrækju URL",
|
||||
"webhooks-caps": "WEBHOOKS",
|
||||
"webhooks": "Webhook-vefkrækjur",
|
||||
"webhook-name": "Vefkrækju nafn",
|
||||
"description": "Vefkrækjur (webhooks) sem skilgreindar eru hér að neðan verða keyrðar þegar máltíð er skilgreind fyrir daginn. Á fyrirfram ákveðnum tíma verða vefkrækjurnar sendar með gögnum úr þeirri uppskrift sem skipulögð er í dag. Athugaðu að keyrsla vefkrækja er ekki alveg nákvæm, þær eru keyrðar á 5 mínútna fresti, þannig að sendingin getur farið fram allt að 5 mínútum fyrir eða eftir áætlaðan tíma."
|
||||
"description": "Vefkrækjur sem skilgreindar eru hér að neðan verða keyrðar þegar máltíð er skilgreind fyrir daginn. Á fyrirfram ákveðnum tíma verða vefkrækjurnar sendar með gögnum úr þeirri uppskrift sem skipulögð er í dag. Athugaðu að keyrsla vefkrækja er ekki alveg nákvæm, þær eru keyrðar á 5 mínútna fresti, þannig að sendingin getur farið fram allt að 5 mínútum fyrir eða eftir áætlaðan tíma."
|
||||
},
|
||||
"bug-report": "Villu skýrsla",
|
||||
"bug-report-information": "Notaður þessar upplýsingar til að tilkynna um villu. Með því að veita þróunaraðilum upplýsingar um þína uppsetningu hjálpar þú þeim að leysa vandamálið hraðar.",
|
||||
"tracker": "Tracker",
|
||||
"configuration": "Configuration",
|
||||
"tracker": "Rekjari",
|
||||
"configuration": "Stillingar",
|
||||
"docker-volume": "Docker Volume",
|
||||
"docker-volume-help": "Mealie requires that the frontend container and the backend share the same docker volume or storage. This ensures that the frontend container can properly access the images and assets stored on disk.",
|
||||
"docker-volume-help": "Mealie krefst þess að bæði frontend gámur og backend deili sama docker volume og geymslu. Það tryggir að froentend gámur getir nálgast myndir og önnur gögn sem geymd eru á disknum.",
|
||||
"volumes-are-misconfigured": "Volumes are misconfigured.",
|
||||
"volumes-are-configured-correctly": "Volumes are configured correctly.",
|
||||
"status-unknown-try-running-a-validation": "Status Unknown. Try running a validation.",
|
||||
"validate": "Validate",
|
||||
"email-configuration-status": "Email Configuration Status",
|
||||
"email-configured": "Email Configured",
|
||||
"email-configuration-status": "Tölvupóstsstillingar",
|
||||
"email-configured": "Tölvupóstur stilltur",
|
||||
"email-test-results": "Email Test Results",
|
||||
"ready": "Ready",
|
||||
"not-ready": "Not Ready - Check Environmental Variables",
|
||||
"succeeded": "Succeeded",
|
||||
"failed": "Failed",
|
||||
"ready": "Tilbúið",
|
||||
"not-ready": "Ekki tilbúið - athugið umhverfisbreytur",
|
||||
"succeeded": "Tókst",
|
||||
"failed": "Mistókst",
|
||||
"general-about": "Upplýsingar",
|
||||
"application-version": "Útgáfa forrits",
|
||||
"application-version-error-text": "Útgáfan þín ({0}) er ekki sú sama og nýjasta útgáfan. Athugaðu hvort þú villt uppfæra í nýjustu útgáfuna ({1}).",
|
||||
@@ -907,29 +915,29 @@
|
||||
"copy-as-markdown": "Afrita sem markdown",
|
||||
"delete-checked": "Eyða völdum",
|
||||
"toggle-label-sort": "Toggle Label Sort",
|
||||
"reorder-labels": "Reorder Labels",
|
||||
"uncheck-all-items": "Uncheck All Items",
|
||||
"check-all-items": "Check All Items",
|
||||
"linked-recipes-count": "No Linked Recipes|One Linked Recipe|{count} Linked Recipes",
|
||||
"items-checked-count": "No items checked|One item checked|{count} items checked",
|
||||
"reorder-labels": "Endurraða merkimiðum",
|
||||
"uncheck-all-items": "Taka hak af öllum vörum",
|
||||
"check-all-items": "Setja hak á allar vörur",
|
||||
"linked-recipes-count": "Engar tengdar uppskriftir|Ein tengd uppskrift|{count} tengdar uppskriftir",
|
||||
"items-checked-count": "Engar matvörur merktar|Ein matvara merkt|{count} matvörur merktar",
|
||||
"no-label": "Engir merkimiðar",
|
||||
"completed-on": "Completed on {date}",
|
||||
"completed-on": "Klárað þann {date}",
|
||||
"you-are-offline": "Þú ert ekki nettengdur",
|
||||
"you-are-offline-description": "Not all features are available while offline. You can still add, modify, and remove items, but you will not be able to sync your changes to the server until you are back online.",
|
||||
"are-you-sure-you-want-to-check-all-items": "Are you sure you want to check all items?",
|
||||
"are-you-sure-you-want-to-uncheck-all-items": "Are you sure you want to uncheck all items?",
|
||||
"are-you-sure-you-want-to-delete-checked-items": "Are you sure you want to delete all checked items?",
|
||||
"you-are-offline-description": "Ekki er hægt að framkvæma allt án nettengingar. Þú getur stofnað, breytt og eytt matvörum, en þú getur ekki samstillt breytingarnar þínar við þjóninn fyrr en tölvan er aftur orðin nettengd.",
|
||||
"are-you-sure-you-want-to-check-all-items": "Ertu viss um að þú viljir merkja við allar matvörurnar?",
|
||||
"are-you-sure-you-want-to-uncheck-all-items": "Ertu viss um að þú viljir taka merkingu af öllum matvörunum?",
|
||||
"are-you-sure-you-want-to-delete-checked-items": "Ertu viss um að þú viljir eyða öllum merktum matvörum?",
|
||||
"no-shopping-lists-found": "Enginn innkaupalisti fannst"
|
||||
},
|
||||
"sidebar": {
|
||||
"all-recipes": "All Recipes",
|
||||
"all-recipes": "Allar uppskriftir",
|
||||
"backups": "Öryggisafrit",
|
||||
"categories": "Flokkar",
|
||||
"cookbooks": "Cookbooks",
|
||||
"cookbooks": "Uppskriftabækur",
|
||||
"dashboard": "Dashboard",
|
||||
"home-page": "Home Page",
|
||||
"manage-users": "Manage Users",
|
||||
"migrations": "Migrations",
|
||||
"manage-users": "Umsjá notenda",
|
||||
"migrations": "Gagnaflutningur",
|
||||
"profile": "Notandaupplýsingar",
|
||||
"search": "Leita",
|
||||
"site-settings": "Kerfisstillingar",
|
||||
@@ -940,18 +948,18 @@
|
||||
"background-tasks": "Bakgrunnsverkefni",
|
||||
"parser": "Greinir",
|
||||
"developer": "Developer",
|
||||
"cookbook": "Cookbook",
|
||||
"create-cookbook": "Create a new cookbook"
|
||||
"cookbook": "Uppskriftarbók",
|
||||
"create-cookbook": "Stofna nýja uppskriftarbók"
|
||||
},
|
||||
"signup": {
|
||||
"error-signing-up": "Error Signing Up",
|
||||
"sign-up": "Sign Up",
|
||||
"sign-up-link-created": "Sign up link created",
|
||||
"sign-up-link-creation-failed": "Sign up link creation failed",
|
||||
"sign-up-links": "Sign Up Links",
|
||||
"error-signing-up": "Villa við að stofna aðgang",
|
||||
"sign-up": "Stofna aðgang",
|
||||
"sign-up-link-created": "Tengill til að stofna aðgang tilbúinn",
|
||||
"sign-up-link-creation-failed": "Mistókst að útbúa tengil til að stofna aðgang",
|
||||
"sign-up-links": "Tenglar til að stofna aðgang",
|
||||
"sign-up-token-deleted": "Aðgangslykli fyrir skráningu eytt",
|
||||
"sign-up-token-deletion-failed": "Mistókst að eyða aðgangslykli fyrir skráningu",
|
||||
"welcome-to-mealie": "Welcome to Mealie! To become a user of this instance you are required to have a valid invitation link. If you haven't recieved an invitation you are unable to sign-up. To recieve a link, contact the sites administrator."
|
||||
"welcome-to-mealie": "Velkominn í Mealie! Til að verða notandi af þessari síðu þá þarftu að hafa boðstengil. Ef þú hefur ekki fengið boð þá getur þú ekki skráð þig. Til að fá tengil hafðu þá samband við kerfisstjóra."
|
||||
},
|
||||
"tag": {
|
||||
"tag-created": "Merki stofnað",
|
||||
@@ -967,45 +975,45 @@
|
||||
"tag": "Merki"
|
||||
},
|
||||
"tool": {
|
||||
"tools": "Tools",
|
||||
"on-hand": "On Hand",
|
||||
"create-a-tool": "Create a Tool",
|
||||
"tool-name": "Tool Name",
|
||||
"create-new-tool": "Create New Tool",
|
||||
"on-hand-checkbox-label": "Show as On Hand (Checked)",
|
||||
"required-tools": "Required Tools",
|
||||
"tool": "Tool"
|
||||
"tools": "Áhöld",
|
||||
"on-hand": "Til á heimilinu",
|
||||
"create-a-tool": "Stofna áhald",
|
||||
"tool-name": "Nafn á áhaldi",
|
||||
"create-new-tool": "Stofna áhald",
|
||||
"on-hand-checkbox-label": "Merkja sem „til á heimilinu“",
|
||||
"required-tools": "Nauðsynlegt áhald",
|
||||
"tool": "Áhald"
|
||||
},
|
||||
"user": {
|
||||
"admin": "Stjórnandi",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Are you sure you want to delete the link <b>{link}<b/>?",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Are you sure you want to delete the user <b>{activeName} ID: {activeId}<b/>?",
|
||||
"auth-method": "Auth Method",
|
||||
"confirm-link-deletion": "Confirm Link Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Ertu viss um að þú viljir eyða tenglinum <b>{link}<b/>?",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Ertu viss um að þú viljir eyða notandanum <b>{activeName} ID: {activeId}<b/>?",
|
||||
"auth-method": "Auðkenningaraðferð",
|
||||
"confirm-link-deletion": "Staðfestu að eyða tenglinum",
|
||||
"confirm-password": "Staðfestu lykilorð",
|
||||
"confirm-user-deletion": "Confirm User Deletion",
|
||||
"confirm-user-deletion": "Staðfestu að eyða aðgangnum",
|
||||
"could-not-validate-credentials": "Could Not Validate Credentials",
|
||||
"create-link": "Create Link",
|
||||
"create-user": "Create User",
|
||||
"create-link": "Búa til tengil",
|
||||
"create-user": "Stofna notanda",
|
||||
"current-password": "Núverandi lykilorð",
|
||||
"e-mail-must-be-valid": "E-mail must be valid",
|
||||
"edit-user": "Edit User",
|
||||
"email": "Email",
|
||||
"error-cannot-delete-super-user": "Error! Cannot Delete Super User",
|
||||
"e-mail-must-be-valid": "Verður að nota gilt netfang",
|
||||
"edit-user": "Breyta notanda",
|
||||
"email": "Netfang",
|
||||
"error-cannot-delete-super-user": "Villa! Get ekki eytt ofur notanda",
|
||||
"existing-password-does-not-match": "Núverandi lykilorð stemmir ekki",
|
||||
"full-name": "Full Name",
|
||||
"full-name": "Fullt nafn",
|
||||
"generate-password-reset-link": "Gera tengil til að endurstilla lykilorð",
|
||||
"invite-only": "Invite Only",
|
||||
"invite-only": "Aðeins fyrir boðna",
|
||||
"link-id": "Link ID",
|
||||
"link-name": "Link Name",
|
||||
"login": "Login",
|
||||
"login-oidc": "Login with",
|
||||
"or": "or",
|
||||
"logout": "Logout",
|
||||
"login": "Innskráning",
|
||||
"login-oidc": "Innskáning með",
|
||||
"or": "eða",
|
||||
"logout": "Skrá út",
|
||||
"manage-users": "Manage Users",
|
||||
"manage-users-description": "Create and manage users.",
|
||||
"new-password": "Nýtt lykilorð",
|
||||
"new-user": "New User",
|
||||
"new-user": "Nýr notandi",
|
||||
"password-has-been-reset-to-the-default-password": "Lykilorð hefur verið endurstillt í sjálfgefið lykilorð",
|
||||
"password-must-match": "Lykilorð verða að vera eins",
|
||||
"password-reset-failed": "Mistókst að endurstilla lykilorð",
|
||||
@@ -1023,65 +1031,65 @@
|
||||
"user-created": "User created",
|
||||
"user-creation-failed": "User creation failed",
|
||||
"user-deleted": "User deleted",
|
||||
"user-id-with-value": "User ID: {id}",
|
||||
"user-id": "User ID",
|
||||
"user-id-with-value": "Notanda ID: {id}",
|
||||
"user-id": "Notanda ID",
|
||||
"user-password": "Lykilorð notanda",
|
||||
"user-successfully-logged-in": "User Successfully Logged In",
|
||||
"user-update-failed": "User update failed",
|
||||
"user-updated": "Notandaupplýsingar uppfærðar",
|
||||
"user": "User",
|
||||
"username": "Notandanafn",
|
||||
"users-header": "USERS",
|
||||
"users": "Users",
|
||||
"users-header": "NOTENDUR",
|
||||
"users": "Notendur",
|
||||
"user-not-found": "User not found",
|
||||
"webhook-time": "Webhook Time",
|
||||
"webhooks-enabled": "Webhooks Enabled",
|
||||
"you-are-not-allowed-to-create-a-user": "You are not allowed to create a user",
|
||||
"you-are-not-allowed-to-delete-this-user": "You are not allowed to delete this user",
|
||||
"webhook-time": "Vefkrækju tími",
|
||||
"webhooks-enabled": "Vefkrækjur virkjaðar",
|
||||
"you-are-not-allowed-to-create-a-user": "Þú hefur ekki réttindi til að stofna notanda",
|
||||
"you-are-not-allowed-to-delete-this-user": "Þú hefur ekki réttindi til að eyða þessum notanda",
|
||||
"enable-advanced-content": "Virkja ítarlegt efni",
|
||||
"enable-advanced-content-description": "Virkja ítarlegt efni eins og að stækka uppskrift, API keys, vefkrækjur (Webhooks) og gagnastýring. Það er alltaf hægt að breyta þessu síðar",
|
||||
"favorite-recipes": "Favorite Recipes",
|
||||
"enable-advanced-content-description": "Virkjar ítarlegt efni eins og að stækka uppskrift, API keys, vefkrækjur (Webhooks) og gagnastýring. Það er alltaf hægt að breyta þessu síðar",
|
||||
"favorite-recipes": "Uppáhalds uppskriftir",
|
||||
"email-or-username": "Tölvupóstur eða notandanafn",
|
||||
"remember-me": "Remember Me",
|
||||
"remember-me": "Geyma innskráningarupplýsingar",
|
||||
"please-enter-your-email-and-password": "Vinsamlegast sláðu inn netfangið þitt og lykilorð",
|
||||
"invalid-credentials": "Invalid Credentials",
|
||||
"account-locked-please-try-again-later": "Account Locked. Please try again later",
|
||||
"user-favorites": "User Favorites",
|
||||
"invalid-credentials": "Ógild auðkenni",
|
||||
"account-locked-please-try-again-later": "Aðgangurinn lokaður, vinsamlegast reyndu aftur síðar",
|
||||
"user-favorites": "Uppáhald notanda",
|
||||
"password-strength-values": {
|
||||
"weak": "Veikt",
|
||||
"good": "Gott",
|
||||
"strong": "Sterkt",
|
||||
"very-strong": "Mjög sterkt"
|
||||
},
|
||||
"user-management": "User Management",
|
||||
"reset-locked-users": "Reset Locked Users",
|
||||
"user-management": "Umsjá með notendum",
|
||||
"reset-locked-users": "Endurstilla læstan notanda",
|
||||
"admin-user-creation": "Búa til stjórnandaaðgang",
|
||||
"admin-user-management": "Stjórna notendum",
|
||||
"user-details": "User Details",
|
||||
"user-name": "User Name",
|
||||
"authentication-method": "Authentication Method",
|
||||
"authentication-method-hint": "This specifies how a user will authenticate with Mealie. If you're not sure, choose 'Mealie'",
|
||||
"permissions": "Permissions",
|
||||
"user-details": "Upplýsingar um notanda",
|
||||
"user-name": "Notandanafn",
|
||||
"authentication-method": "Auðkenningaraðferð",
|
||||
"authentication-method-hint": "Þetta skilgreinir hvernig notandinn auðkennir sig við Mealie. Ef þú ert ekki viss veldu þá „Mealie“",
|
||||
"permissions": "Réttindi",
|
||||
"administrator": "Stjórnandi",
|
||||
"user-can-invite-other-to-group": "User can invite others to group",
|
||||
"user-can-manage-group": "User can manage group",
|
||||
"user-can-manage-household": "User can manage household",
|
||||
"user-can-organize-group-data": "User can organize group data",
|
||||
"user-can-invite-other-to-group": "Notandinn getur boðið öðrum í hóp",
|
||||
"user-can-manage-group": "Notandi getur stjórnað hóp",
|
||||
"user-can-manage-household": "Notandi getur stjórnað heimili",
|
||||
"user-can-organize-group-data": "Notandi getur stjórnað hóp gögnum",
|
||||
"enable-advanced-features": "Virkja ítarlega eiginleika",
|
||||
"it-looks-like-this-is-your-first-time-logging-in": "It looks like this is your first time logging in.",
|
||||
"dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Don't want to see this anymore? Be sure to change your email in your user settings!",
|
||||
"it-looks-like-this-is-your-first-time-logging-in": "Það lítur út fyrir að þetta sé fyrsta skiptið sem þú skráir þig inn.",
|
||||
"dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Ef þú villt ekki sjá þessi skilaboð aftur þá þarftu að breyta lykilorðinu þínu í notandastillingum.",
|
||||
"forgot-password": "Gleymt Lykilorð",
|
||||
"forgot-password-text": "Vinsamlegast sláðu inn netfangið þitt og við munum senda þér tengil til að endursetja lykilorðið þitt.",
|
||||
"changes-reflected-immediately": "Changes to this user will be reflected immediately.",
|
||||
"default-activity": "Default Activity",
|
||||
"default-activity-hint": "Select which page you'd like to navigate to upon logging in from this device"
|
||||
"changes-reflected-immediately": "Breytingar á þessum notanda koma strax fram.",
|
||||
"default-activity": "Sjálfgefin upphafssíða",
|
||||
"default-activity-hint": "Veldu þá síðu sem þú vilt byrja á þegar þú skráir þig inn á þessu tæki"
|
||||
},
|
||||
"language-dialog": {
|
||||
"translated": "translated",
|
||||
"choose-language": "Choose Language",
|
||||
"select-description": "Choose the language for the Mealie UI. The setting only applies to you, not other users.",
|
||||
"how-to-contribute-description": "Is something not translated yet, mistranslated, or your language missing from the list? {read-the-docs-link} on how to contribute!",
|
||||
"read-the-docs": "Read the docs"
|
||||
"translated": "þýtt",
|
||||
"choose-language": "Veldu tungumál",
|
||||
"select-description": "Veldu tungumálið fyrir notendaviðmótið. Stillingin mun bara gilda fyrir þig, ekki aðra notendur.",
|
||||
"how-to-contribute-description": "Vantar þýðingu á einhverju, er eitthvað vitlaust þýtt eða vantar tungumálið þitt á listann? {read-the-docs-link} um hvernig á að taka þátt!",
|
||||
"read-the-docs": "Lestu handbókina"
|
||||
},
|
||||
"data-pages": {
|
||||
"foods": {
|
||||
@@ -1093,7 +1101,7 @@
|
||||
"source-food": "Upprunaleg matvara",
|
||||
"target-food": "Sameinuð matvara",
|
||||
"create-food": "Stofna matvöru",
|
||||
"food-label": "Merking",
|
||||
"food-label": "Merkimiði",
|
||||
"edit-food": "Breyta matvöru",
|
||||
"food-data": "Matvörur",
|
||||
"example-food-singular": "t.d. laukur",
|
||||
@@ -1125,52 +1133,52 @@
|
||||
},
|
||||
"labels": {
|
||||
"seed-dialog-text": "Bæta algengum merkimiðum á þínu tungumáli við gagnarunninn.",
|
||||
"edit-label": "Edit Label",
|
||||
"new-label": "New Label",
|
||||
"labels": "Labels",
|
||||
"assign-label": "Assign Label"
|
||||
"edit-label": "Breyta merkimiða",
|
||||
"new-label": "Nýr merkimiði",
|
||||
"labels": "Merkimiðar",
|
||||
"assign-label": "Setja merkimiða"
|
||||
},
|
||||
"recipes": {
|
||||
"purge-exports": "Purge Exports",
|
||||
"are-you-sure-you-want-to-delete-all-export-data": "Are you sure you want to delete all export data?",
|
||||
"confirm-delete-recipes": "Are you sure you want to delete the following recipes? This action cannot be undone.",
|
||||
"the-following-recipes-selected-length-will-be-exported": "The following recipes ({0}) will be exported.",
|
||||
"settings-chosen-explanation": "Settings chosen here, excluding the locked option, will be applied to all selected recipes.",
|
||||
"selected-length-recipe-s-settings-will-be-updated": "{count} recipe(s) settings will be updated.",
|
||||
"recipe-data": "Recipe Data",
|
||||
"purge-exports": "Eyða útfluttum gögnum",
|
||||
"are-you-sure-you-want-to-delete-all-export-data": "Ertu viss um að þú viljir eyða öllum útfluttum gögnum?",
|
||||
"confirm-delete-recipes": "Ertu viss um að þú viljir eyða eftirtöldum uppskriftum? Þessi aðgerð er varanleg.",
|
||||
"the-following-recipes-selected-length-will-be-exported": "Eftirtaldar uppskriftir ({0}) verða útfluttar.",
|
||||
"settings-chosen-explanation": "Stillingar sem eru valdar hér, fyrir utan að læsa, verður bætt við allar valdar uppskriftir.",
|
||||
"selected-length-recipe-s-settings-will-be-updated": "{count} uppskrift(um) verða uppfærðar.",
|
||||
"recipe-data": "Uppskriftar gögn",
|
||||
"recipe-data-description": "Notaðu þessa síðu til að breyta gögnum sem eru tengd við uppskriftirnar þínar. Þú getur framkvæmt margar aðgerðir samtímis meðal annars flytja út, eyða, merkja og setja í flokka.",
|
||||
"recipe-columns": "Recipe Columns",
|
||||
"data-exports-description": "This section provides links to available exports that are ready to download. These exports do expire, so be sure to grab them while they're still available.",
|
||||
"data-exports": "Data Exports",
|
||||
"recipe-columns": "Uppskrifta dálkar",
|
||||
"data-exports-description": "Þessi hluti geymir niðurhals tengla í gögn sem þegar hafa verið útflutt. Þessir útfluttu gögn eru tímabundin, sæktu þau meðan þau eru enn til staðar.",
|
||||
"data-exports": "Útflutt gögn",
|
||||
"tag": "Merki",
|
||||
"categorize": "Flokka",
|
||||
"update-settings": "Uppfæra stillingar",
|
||||
"tag-recipes": "Merkja uppskrift",
|
||||
"categorize-recipes": "Flokka uppskriftir",
|
||||
"export-recipes": "Export Recipes",
|
||||
"delete-recipes": "Delete Recipes",
|
||||
"export-recipes": "Flytja út uppskriftir",
|
||||
"delete-recipes": "Eyða uppskriftum",
|
||||
"source-unit-will-be-deleted": "Upprunalegri mælieiningu verður eytt"
|
||||
},
|
||||
"recipe-actions": {
|
||||
"recipe-actions-data": "Recipe Actions Data",
|
||||
"new-recipe-action": "New Recipe Action",
|
||||
"edit-recipe-action": "Edit Recipe Action",
|
||||
"action-type": "Action Type"
|
||||
"recipe-actions-data": "Gögn fyrir uppskriftaaðgerðir",
|
||||
"new-recipe-action": "Nú uppskriftaaðgerð",
|
||||
"edit-recipe-action": "Breyta uppskriftaaðgerð",
|
||||
"action-type": "Aðgerð"
|
||||
},
|
||||
"create-alias": "Create Alias",
|
||||
"manage-aliases": "Manage Aliases",
|
||||
"create-alias": "Stofna samheiti",
|
||||
"manage-aliases": "Vinna með samheiti",
|
||||
"seed-data": "Grunngögn",
|
||||
"seed": "Sækja grunngögn",
|
||||
"data-management": "Data Management",
|
||||
"data-management-description": "Select which data set you want to make changes to.",
|
||||
"select-data": "Select Data",
|
||||
"select-language": "Select Language",
|
||||
"columns": "Columns",
|
||||
"combine": "Combine",
|
||||
"data-management": "Gagnastýring",
|
||||
"data-management-description": "Veldu þau gögn sem þú vilt breyta.",
|
||||
"select-data": "Veldu gögn",
|
||||
"select-language": "Veldu tungumál",
|
||||
"columns": "Dálkar",
|
||||
"combine": "Sameina",
|
||||
"categories": {
|
||||
"edit-category": "Breyta flokkum",
|
||||
"new-category": "Nýr flokkur",
|
||||
"category-data": "Category Data"
|
||||
"category-data": "Flokkar"
|
||||
},
|
||||
"tags": {
|
||||
"new-tag": "Nýtt merki",
|
||||
@@ -1178,9 +1186,9 @@
|
||||
"tag-data": "Merkja upplýsingar"
|
||||
},
|
||||
"tools": {
|
||||
"new-tool": "New Tool",
|
||||
"edit-tool": "Edit Tool",
|
||||
"tool-data": "Tool Data"
|
||||
"new-tool": "Nýtt áhald",
|
||||
"edit-tool": "Breyta áhaldi",
|
||||
"tool-data": "Áhöld"
|
||||
}
|
||||
},
|
||||
"user-registration": {
|
||||
@@ -1203,30 +1211,30 @@
|
||||
},
|
||||
"export": {
|
||||
"export": "Flytja út",
|
||||
"file-name": "File Name",
|
||||
"size": "Size",
|
||||
"link-expires": "Link Expires"
|
||||
"file-name": "Skráarnafn",
|
||||
"size": "Stærð",
|
||||
"link-expires": "Tengill rennur út"
|
||||
},
|
||||
"recipe-share": {
|
||||
"expiration-date": "Expiration Date",
|
||||
"share-recipe": "Share Recipe",
|
||||
"default-30-days": "Default 30 Days",
|
||||
"expires-at": "Expires At",
|
||||
"recipe-link-copied-message": "Recipe link copied to clipboard"
|
||||
"expiration-date": "Gildistími",
|
||||
"share-recipe": "Deila uppskrift",
|
||||
"default-30-days": "Sjálfgefið er 30 dagar",
|
||||
"expires-at": "Rennur út:",
|
||||
"recipe-link-copied-message": "Tengill fyrir uppskriftina afritaður í klippispjald"
|
||||
},
|
||||
"banner-experimental": {
|
||||
"title": "Experimental Feature",
|
||||
"title": "Tilraunareiginleiki",
|
||||
"description": "This page contains experimental or still-baking features. Please excuse the mess.",
|
||||
"issue-link-text": "Track our progress here"
|
||||
},
|
||||
"form": {
|
||||
"quantity-label-abbreviated": "Qty"
|
||||
"quantity-label-abbreviated": "Fjöldi"
|
||||
},
|
||||
"markdown-editor": {
|
||||
"preview-markdown-button-label": "Skoða markdown"
|
||||
},
|
||||
"demo": {
|
||||
"info_message_with_version": "This is a Demo for version: {version}",
|
||||
"info_message_with_version": "Þetta er demó fyrir útgáfu: {version}",
|
||||
"demo_username": "Notandi: {username}",
|
||||
"demo_password": "Lykilorð: {password}"
|
||||
},
|
||||
@@ -1240,7 +1248,7 @@
|
||||
"split-by-block": "Split by text block",
|
||||
"flatten": "Flatten regardless of original formating",
|
||||
"help": {
|
||||
"help": "Help",
|
||||
"help": "Hjálp",
|
||||
"mouse-modes": "Mouse modes",
|
||||
"selection-mode": "Selection Mode (default)",
|
||||
"selection-mode-desc": "The selection mode is the main mode that can be used to enter data:",
|
||||
@@ -1264,84 +1272,84 @@
|
||||
},
|
||||
"admin": {
|
||||
"maintenance": {
|
||||
"storage-details": "Storage Details",
|
||||
"page-title": "Site Maintenance",
|
||||
"summary-title": "Summary",
|
||||
"button-label-get-summary": "Get Summary",
|
||||
"button-label-open-details": "Details",
|
||||
"info-description-data-dir-size": "Data Directory Size",
|
||||
"info-description-log-file-size": "Log File Size",
|
||||
"info-description-cleanable-directories": "Cleanable Directories",
|
||||
"info-description-cleanable-images": "Cleanable Images",
|
||||
"storage-details": "Geymslu upplýsingar",
|
||||
"page-title": "Viðhald á vefsvæðis",
|
||||
"summary-title": "Samantekt",
|
||||
"button-label-get-summary": "Fá samantekt",
|
||||
"button-label-open-details": "Nánari upplýsingar",
|
||||
"info-description-data-dir-size": "Gagnamöppustærð",
|
||||
"info-description-log-file-size": "Stærð á atvikaskrá",
|
||||
"info-description-cleanable-directories": "Möppur sem má hreinsa",
|
||||
"info-description-cleanable-images": "Myndir sem má hreinsa",
|
||||
"storage": {
|
||||
"title-temporary-directory": "Temporary Directory (.temp)",
|
||||
"title-temporary-directory": "Bráðabirgðamappa (.temp)",
|
||||
"title-backups-directory": "Mappa fyrir öryggisafrit",
|
||||
"title-groups-directory": "Groups Directory (groups)",
|
||||
"title-recipes-directory": "Recipes Directory (recipes)",
|
||||
"title-user-directory": "User Directory (user)"
|
||||
"title-groups-directory": "Hópa mappa (groups)",
|
||||
"title-recipes-directory": "Uppskriftar mappa (recipes)",
|
||||
"title-user-directory": "Notanda mappa (user)"
|
||||
},
|
||||
"action-delete-log-files-name": "Delete Log Files",
|
||||
"action-delete-log-files-description": "Deletes all the log files",
|
||||
"action-clean-directories-name": "Clean Directories",
|
||||
"action-clean-directories-description": "Removes all the recipe folders that are not valid UUIDs",
|
||||
"action-clean-temporary-files-name": "Clean Temporary Files",
|
||||
"action-clean-temporary-files-description": "Removes all files and folders in the .temp directory",
|
||||
"action-clean-images-name": "Clean Images",
|
||||
"action-clean-images-description": "Removes all the images that don't end with .webp",
|
||||
"actions-description": "Maintenance actions are {destructive_in_bold} and should be used with caution. Performing any of these actions is {irreversible_in_bold}.",
|
||||
"actions-description-destructive": "destructive",
|
||||
"actions-description-irreversible": "irreversible",
|
||||
"action-delete-log-files-name": "Eyða atvikaskrám",
|
||||
"action-delete-log-files-description": "Eyða öllum atvikaskrám",
|
||||
"action-clean-directories-name": "Hreinsa möppurnar",
|
||||
"action-clean-directories-description": "Eyðir öllum uppskriftarmöppum sem ekki eru með gilt UUID",
|
||||
"action-clean-temporary-files-name": "Eyðir bráðabirgðaskrám",
|
||||
"action-clean-temporary-files-description": "Eyðir öllum skrám og möppum í .temp möppunni",
|
||||
"action-clean-images-name": "Hreinsa myndir",
|
||||
"action-clean-images-description": "Eyðir öllum myndum sem ekki hafa endinguna .webp",
|
||||
"actions-description": "Viðhalds aðgerðir eru {destructive_in_bold} og þarf að nota með varúð. Allar þessar aðgerðir eru {irreversible_in_bold}.",
|
||||
"actions-description-destructive": "eyðileggjandi",
|
||||
"actions-description-irreversible": "varanlegar",
|
||||
"logs-action-refresh": "Refresh Logs",
|
||||
"logs-page-title": "Mealie Logs",
|
||||
"logs-tail-lines-label": "Tail Lines"
|
||||
},
|
||||
"mainentance": {
|
||||
"actions-title": "Actions"
|
||||
"actions-title": "Aðgerðir"
|
||||
},
|
||||
"ingredients-natural-language-processor": "Ingredients Natural Language Processor",
|
||||
"ingredients-natural-language-processor-explanation": "Mealie uses Conditional Random Fields (CRFs) for parsing and processing ingredients. The model used for ingredients is based off a data set of over 100,000 ingredients from a dataset compiled by the New York Times. Note that as the model is trained in English only, you may have varied results when using the model in other languages. This page is a playground for testing the model.",
|
||||
"ingredients-natural-language-processor-explanation-2": "It's not perfect, but it yields great results in general and is a good starting point for manually parsing ingredients into individual fields. Alternatively, you can also use the \"Brute\" processor that uses a pattern matching technique to identify ingredients.",
|
||||
"ingredients-natural-language-processor": "Innihaldsefna málgreining (Natural Language Processor)",
|
||||
"ingredients-natural-language-processor-explanation": "Mealie notar Conditional Random Fields (CRFs) til að greina og vinna með innihaldsefni. Líkanið sem notað er byggir á gagnasafni með yfir 100.000 innihaldsefnum úr gagnasafni sem New York Times tók saman. Athugaðu að þar sem líkanið er einungis þjálfað á ensku geturðu fengið misjafnar niðurstöður þegar það er notað á önnur tungumál. Þessi síða er ætluð til að prófa líkanið.",
|
||||
"ingredients-natural-language-processor-explanation-2": "Þetta er ekki fullkomið en skilar almennt góðum niðurstöðum og er góður grunnur fyrir handvirka greiningu innihaldsefna í einstaka reiti. Þú getur einnig notað „Grófgreinir“ vinnsluna, sem notar mynsturgreiningu til að bera kennsl á innihaldsefni.",
|
||||
"nlp": "NLP",
|
||||
"brute": "Brute",
|
||||
"brute": "Grófgreinir",
|
||||
"openai": "OpenAI",
|
||||
"show-individual-confidence": "Show individual confidence",
|
||||
"ingredient-text": "Ingredient Text",
|
||||
"show-individual-confidence": "Sýna öryggi",
|
||||
"ingredient-text": "Texti innihaldsefni",
|
||||
"average-confident": "{0} öryggi",
|
||||
"try-an-example": "Try an example",
|
||||
"parser": "Parser",
|
||||
"background-tasks": "Background Tasks",
|
||||
"try-an-example": "Reyndu dæmi",
|
||||
"parser": "Greinir",
|
||||
"background-tasks": "Bakgrunnsverk",
|
||||
"background-tasks-description": "Here you can view all the running background tasks and their status",
|
||||
"no-logs-found": "No Logs Found",
|
||||
"tasks": "Verkefni",
|
||||
"setup": {
|
||||
"first-time-setup": "First Time Setup",
|
||||
"welcome-to-mealie-get-started": "Welcome to Mealie! Let's get started",
|
||||
"already-set-up-bring-to-homepage": "I'm already set up, just bring me to the homepage",
|
||||
"common-settings-for-new-sites": "Here are some common settings for new sites",
|
||||
"setup-complete": "Setup Complete!",
|
||||
"here-are-a-few-things-to-help-you-get-started": "Here are a few things to help you get started with Mealie",
|
||||
"first-time-setup": "Fyrsta uppsetning",
|
||||
"welcome-to-mealie-get-started": "Mealie býður þig velkominn, kýlum á þetta",
|
||||
"already-set-up-bring-to-homepage": "Allt er þegar klárt hjá mér, sendu mig á heimasíðuna",
|
||||
"common-settings-for-new-sites": "Hér eru nokkrar algengar stillingar fyrir nýjar síður",
|
||||
"setup-complete": "Uppsetningu lokið",
|
||||
"here-are-a-few-things-to-help-you-get-started": "Hér eru nokkur atriði til að hjálpa þér að byrja á því að nota Mealie",
|
||||
"restore-from-v1-backup": "Ertu með öryggisafrit af eldri útgáfur af Mealie útgáfu 1? Þú getur endurheimt hana hér.",
|
||||
"manage-profile-or-get-invite-link": "Manage your own profile, or grab an invite link to share with others."
|
||||
"manage-profile-or-get-invite-link": "Stilltu eigin prófil, eða sæktu boðs-tengil til að deila með öðrum."
|
||||
},
|
||||
"debug-openai-services": "Debug OpenAI Services",
|
||||
"debug-openai-services-description": "Use this page to debug OpenAI services. You can test your OpenAI connection and see the results here. If you have image services enabled, you can also provide an image.",
|
||||
"run-test": "Run Test",
|
||||
"test-results": "Test Results",
|
||||
"group-delete-note": "Groups with users or households cannot be deleted",
|
||||
"household-delete-note": "Households with users cannot be deleted"
|
||||
"debug-openai-services": "Villugreina OpenAI þjónustur",
|
||||
"debug-openai-services-description": "Notaðu þessa síðu til að villugrein OpenAI þjónustur. Getur séð hvort OpenAI þjónustan er virk og séð niðurstöður úr greiningunni. Ef þú hefur virkjað mynd greininguna er hægt að setja inn mynd til að greina.",
|
||||
"run-test": "Ræsa prufu",
|
||||
"test-results": "Niðurstaða prufunnar",
|
||||
"group-delete-note": "Hópar sem innihalda notendur og heimili er ekki hægt að eyða",
|
||||
"household-delete-note": "Heimili með notendum er ekki hægt að eyða"
|
||||
},
|
||||
"profile": {
|
||||
"welcome-user": "👋 Welcome, {0}!",
|
||||
"description": "Manage your profile, recipes, and group settings.",
|
||||
"invite-link": "Invite Link",
|
||||
"get-invite-link": "Get Invite Link",
|
||||
"get-public-link": "Get Public Link",
|
||||
"account-summary": "Account Summary",
|
||||
"account-summary-description": "Here's a summary of your group's information.",
|
||||
"group-statistics": "Group Statistics",
|
||||
"welcome-user": "👋 Halló, {0}",
|
||||
"description": "Umsjá með prófíl, uppskriftum og hópstillingum.",
|
||||
"invite-link": "Boð tengill",
|
||||
"get-invite-link": "Fá boð tengil",
|
||||
"get-public-link": "Fá almennan tengil",
|
||||
"account-summary": "Samantekt á aðgang",
|
||||
"account-summary-description": "Hér er samantekt á upplýsingum um hópinn þinn.",
|
||||
"group-statistics": "Hóp tölfræði",
|
||||
"group-statistics-description": "Your Group Statistics provide some insight how you're using Mealie.",
|
||||
"household-statistics": "Household Statistics",
|
||||
"household-statistics-description": "Your Household Statistics provide some insight how you're using Mealie.",
|
||||
"household-statistics": "Tölfræði heimilis",
|
||||
"household-statistics-description": "Heimilis tölfræðin gefur einhverja innsýn í hvernig þú ert að nota Mealie.",
|
||||
"storage-capacity": "Geymslupláss",
|
||||
"storage-capacity-description": "Geymsluplássið þitt er samlagning á myndum og öðru sem þú hefur hlaðið inn.",
|
||||
"personal": "Eigin stillingar",
|
||||
@@ -1352,49 +1360,49 @@
|
||||
"group-description": "Þessar einingar er deilt innan hópsins þíns, að breyta hér hefur áhrif á stillingar fyrir allan hópinn!",
|
||||
"group-settings": "Hóp stillingar",
|
||||
"group-settings-description": "Sýsla með hóp stillingar, eins og friðhelgisstillingar.",
|
||||
"household-description": "These items are shared within your household. Editing one of them will change it for the whole household!",
|
||||
"household-settings": "Household Settings",
|
||||
"household-description": "Þessum einingum er deilt innan heimilis þíns, að breyta hér hefur áhrif á stillingar fyrir alla í heimilinu!",
|
||||
"household-settings": "Heimilis stillingar",
|
||||
"household-settings-description": "Stjórnaðu stillingum heimilis, eins og matarplani og persónuverndarstillingum.",
|
||||
"cookbooks-description": "Manage a collection of recipe categories and generate pages for them.",
|
||||
"members": "Members",
|
||||
"members-description": "See who's in your household and manage their permissions.",
|
||||
"webhooks-description": "Set up webhooks that trigger on days that you have mealplans scheduled.",
|
||||
"notifiers": "Notifiers",
|
||||
"notifiers-description": "Set up email and push notifications that trigger on specific events.",
|
||||
"manage-data": "Manage Data",
|
||||
"cookbooks-description": "Stjórna safni uppskriftaflokka og búa til síður fyrir þá.",
|
||||
"members": "Stillingasíða fyrir heimili",
|
||||
"members-description": "Sjáðu hverjir eru í þínu heimili og stjórnaðu réttindum þeirra.",
|
||||
"webhooks-description": "Settu upp vefkrækju sem virkjast á dögum sem þú hefur virkt matarplan.",
|
||||
"notifiers": "Tilkynningar",
|
||||
"notifiers-description": "Settu upp tölvupóst og push-tilkynningar sem virkjast við tiltekna atburði.",
|
||||
"manage-data": "Gagnastýring",
|
||||
"manage-data-description": "Stjórnaðu Mealie gögnunum þínum: matvörum, mælieiningum, flokkum, merkingum og fleiru.",
|
||||
"data-migrations": "Data Migrations",
|
||||
"data-migrations-description": "Migrate your existing data from other applications like Nextcloud Recipes and Chowdown.",
|
||||
"email-sent": "Email Sent",
|
||||
"error-sending-email": "Error Sending Email",
|
||||
"personal-information": "Personal Information",
|
||||
"preferences": "Preferences",
|
||||
"data-migrations": "Flutningur uppskrifta gagna",
|
||||
"data-migrations-description": "Flytur gögnin þín úr öðrum kerfum eins og Nextcloud Recipes og Chowdown.",
|
||||
"email-sent": "Tölvpóstur sendur",
|
||||
"error-sending-email": "Villa við að senda tölvupóst",
|
||||
"personal-information": "Persónuupplýsingar",
|
||||
"preferences": "Stillingar",
|
||||
"show-advanced-description": "Sýna ítarlega eiginleika (API lykla, vefkræjur (Webhook) og gagnastýringu)",
|
||||
"back-to-profile": "Til baka í prófíl",
|
||||
"looking-for-privacy-settings": "Þarftu að komast í friðhelgisstillingar?",
|
||||
"manage-your-api-tokens": "Umsjá með þínum API aðgangslyklum",
|
||||
"manage-user-profile": "Manage User Profile",
|
||||
"manage-cookbooks": "Manage Cookbooks",
|
||||
"manage-members": "Manage Members",
|
||||
"manage-webhooks": "Manage Webhooks",
|
||||
"manage-notifiers": "Manage Notifiers",
|
||||
"manage-data-migrations": "Manage Data Migrations"
|
||||
"manage-user-profile": "Umsjá notendaprófíls",
|
||||
"manage-cookbooks": "Umsjá uppskrifarbóka",
|
||||
"manage-members": "Umsjá meðlima",
|
||||
"manage-webhooks": "Umsjá vefkrækja",
|
||||
"manage-notifiers": "Umsjá tilkynninga",
|
||||
"manage-data-migrations": "Umsjá gagnaflutnings"
|
||||
},
|
||||
"cookbook": {
|
||||
"cookbooks": "Uppskriftabækur",
|
||||
"description": "Cookbooks are another way to organize recipes by creating cross sections of recipes, organizers, and other filters. Creating a cookbook will add an entry to the side-bar and all the recipes with the filters chosen will be displayed in the cookbook.",
|
||||
"hide-cookbooks-from-other-households": "Hide Cookbooks from Other Households",
|
||||
"hide-cookbooks-from-other-households-description": "When enabled, only cookbooks from your household will appear on the sidebar",
|
||||
"public-cookbook": "Public Cookbook",
|
||||
"public-cookbook-description": "Public Cookbooks can be shared with non-mealie users and will be displayed on your groups page.",
|
||||
"description": "Uppskriftarbækur er önnur leið til að skipuleggja uppskriftir með því að nota síur og flokka. Þegar búin er til uppskriftarbók þá birtist hún hér á hliðarstikunni og í henni eru allar þær uppskriftir sem falla undir skilgreiningu valdrar síu.",
|
||||
"hide-cookbooks-from-other-households": "Fela uppskriftarbækur frá öðrum heimilum",
|
||||
"hide-cookbooks-from-other-households-description": "Þegar þetta er valið þá munu aðeins uppskriftarbækur úr þínu heimili birtast á hliðarstikunni",
|
||||
"public-cookbook": "Opin uppskriftarbók",
|
||||
"public-cookbook-description": "Opnar uppskriftabækur er hægt að deila með þeim sem ekki eru notendur í Mealie kerfinu og eru þær sýnilegar á hópsíðunni þinni.",
|
||||
"filter-options": "Filter Options",
|
||||
"filter-options-description": "When require all is selected the cookbook will only include recipes that have all of the items selected. This applies to each subset of selectors and not a cross section of the selected items.",
|
||||
"require-all-categories": "Þarf alla flokka",
|
||||
"require-all-tags": "Require All Tags",
|
||||
"require-all-tools": "Require All Tools",
|
||||
"cookbook-name": "Cookbook Name",
|
||||
"cookbook-with-name": "Cookbook {0}",
|
||||
"household-cookbook-name": "{0} Cookbook {1}",
|
||||
"cookbook-name": "Nafn á uppskriftabók",
|
||||
"cookbook-with-name": "Uppskriftabók {0}",
|
||||
"household-cookbook-name": "Uppskriftabók {0} {1}",
|
||||
"create-a-cookbook": "Stofna uppskrifabók",
|
||||
"cookbook": "Uppskriftabók"
|
||||
},
|
||||
@@ -1404,21 +1412,29 @@
|
||||
"or": "EÐA"
|
||||
},
|
||||
"relational-operators": {
|
||||
"equals": "equals",
|
||||
"does-not-equal": "does not equal",
|
||||
"is-greater-than": "is greater than",
|
||||
"is-greater-than-or-equal-to": "is greater than or equal to",
|
||||
"is-less-than": "is less than",
|
||||
"is-less-than-or-equal-to": "is less than or equal to"
|
||||
"equals": "þann",
|
||||
"does-not-equal": "ekki þann",
|
||||
"is-greater-than": "eftir þann",
|
||||
"is-greater-than-or-equal-to": "þann eða eftir þann",
|
||||
"is-less-than": "fyrir þann",
|
||||
"is-less-than-or-equal-to": "fyrir þann eða þann"
|
||||
},
|
||||
"relational-keywords": {
|
||||
"is": "is",
|
||||
"is-not": "is not",
|
||||
"is-one-of": "is one of",
|
||||
"is-not-one-of": "is not one of",
|
||||
"contains-all-of": "contains all of",
|
||||
"is": "er",
|
||||
"is-not": "er ekki",
|
||||
"is-one-of": "er einn af",
|
||||
"is-not-one-of": "er ekki einn af",
|
||||
"contains-all-of": "inniheldur alla af",
|
||||
"is-like": "is like",
|
||||
"is-not-like": "is not like"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "Þessi reitur er nauðsynlegur",
|
||||
"invalid-email": "Verður að vera gilt netfang",
|
||||
"invalid-url": "Verður að vera gild vefslóð",
|
||||
"no-whitespace": "Engin bil leyfð",
|
||||
"min-length": "Verður að vera að lágmarki {min} stafir",
|
||||
"max-length": "Má vera að hámarki {max} stafir"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "Colazione",
|
||||
"lunch": "Pranzo",
|
||||
"dinner": "Cena",
|
||||
"snack": "Snack",
|
||||
"drink": "Bevanda",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "Qualsiasi",
|
||||
"day-any": "Qualsiasi",
|
||||
"editor": "Modifica",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "Carica una Ricetta",
|
||||
"upload-individual-zip-file": "Carica un singolo file .zip esportato da un'altra istanza di Mealie.",
|
||||
"url-form-hint": "Copia e incolla un link dal tuo sito di ricette preferito",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copia e incolla lo URL della fonte dei dati (opzionale)",
|
||||
"view-scraped-data": "Visualizza Dati Ottenuti dallo Scraping",
|
||||
"trim-whitespace-description": "Tagliare lo spazio bianco iniziale e finale così come le linee vuote",
|
||||
"trim-prefix-description": "Taglia il primo carattere da ogni riga",
|
||||
@@ -449,8 +453,8 @@
|
||||
"import-by-url": "Importa una ricetta tramite URL",
|
||||
"create-manually": "Crea una ricetta manualmente",
|
||||
"make-recipe-image": "Usa come immagine della ricetta",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "Aggiungi cibo",
|
||||
"add-recipe": "Aggiungi ricetta"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404 Pagina non Trovata",
|
||||
@@ -517,9 +521,9 @@
|
||||
"recipe-deleted": "Ricetta eliminata",
|
||||
"recipe-image": "Immagine Ricetta",
|
||||
"recipe-image-updated": "Immagine ricetta aggiornata",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"delete-image": "Elimina Immagine Ricetta",
|
||||
"delete-image-confirmation": "Sei sicuro di voler eliminare questa immagine della ricetta?",
|
||||
"recipe-image-deleted": "Immagine della ricetta eliminata",
|
||||
"recipe-name": "Nome Ricetta",
|
||||
"recipe-settings": "Impostazioni Ricetta",
|
||||
"recipe-update-failed": "Aggiornamento ricetta fallito",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "Scegli Unità",
|
||||
"press-enter-to-create": "Premi invio per creare",
|
||||
"choose-food": "Scegli Cibo",
|
||||
"choose-recipe": "Scegli Ricetta",
|
||||
"notes": "Note",
|
||||
"toggle-section": "Attiva Sezione",
|
||||
"see-original-text": "Vedi Testo Originale",
|
||||
@@ -592,7 +597,7 @@
|
||||
"made-this": "L'Ho Preparato",
|
||||
"how-did-it-turn-out": "Come è venuto?",
|
||||
"user-made-this": "{user} l'ha preparato",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"made-for-recipe": "Creato per {recipe}",
|
||||
"added-to-timeline": "Aggiunto alla cronologia",
|
||||
"failed-to-add-to-timeline": "Impossibile aggiungere alla cronologia",
|
||||
"failed-to-update-recipe": "Impossibile aggiornare la ricetta",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "Prova l'importatore massivo",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Hai dei dati grezzi HTML o JSON?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "È possibile importare direttamente dai dati grezzi",
|
||||
"scrape-recipe-website-being-blocked": "Il sito viene bloccato?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Prova a importare l'HTML puro.",
|
||||
"import-original-keywords-as-tags": "Importa parole chiave originali come tag",
|
||||
"stay-in-edit-mode": "Rimani in modalità Modifica",
|
||||
"parse-recipe-ingredients-after-import": "Analizza gli ingredienti della ricetta dopo l'importazione",
|
||||
@@ -695,9 +702,9 @@
|
||||
"upload-more-images": "Carica altre immagini",
|
||||
"set-as-cover-image": "Imposta come immagine di copertina della ricetta",
|
||||
"cover-image": "Immagine di copertina",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"include-linked-recipes": "Includi Ricette Collegate",
|
||||
"include-linked-recipe-ingredients": "Includi Ingredienti Della Ricetta Collegata",
|
||||
"toggle-recipe": "Attiva/Disattiva Ricetta"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Trova ricette",
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "Premi '/'",
|
||||
"advanced": "Ricerca Avanzata",
|
||||
"auto-search": "Ricerca automatica",
|
||||
"no-results": "Nessun risultato trovato"
|
||||
"no-results": "Nessun risultato trovato",
|
||||
"type-to-search": "Scrivi per cercare..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Aggiungi un Nuovo Tema",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "è simile",
|
||||
"is-not-like": "non è come"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "Questo Campo è Obbligatorio",
|
||||
"invalid-email": "L'Email Deve Essere Valida",
|
||||
"invalid-url": "Lo URL Deve Essere Valido",
|
||||
"no-whitespace": "Gli Spazi Non Sono Ammessi",
|
||||
"min-length": "Deve Essere Almeno {min} Caratteri",
|
||||
"max-length": "Deve Essere Al Massimo {max} Caratteri"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "朝食",
|
||||
"lunch": "昼食",
|
||||
"dinner": "夕食",
|
||||
"snack": "Snack",
|
||||
"drink": "Drink",
|
||||
"dessert": "Dessert",
|
||||
"type-any": "すべて",
|
||||
"day-any": "すべて",
|
||||
"editor": "エディタ",
|
||||
@@ -442,6 +445,7 @@
|
||||
"upload-a-recipe": "レシピのアップロード",
|
||||
"upload-individual-zip-file": "別のMealieインスタンスからエクスポートされた個別の.zipファイルをアップロードします。",
|
||||
"url-form-hint": "お気に入りのレシピサイトからリンクをコピーして貼り付け",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "Copy and paste the source URL of your data (optional)",
|
||||
"view-scraped-data": "スクライピングされたデータの表示",
|
||||
"trim-whitespace-description": "先頭と末尾の空白、空白行をトリミングします。",
|
||||
"trim-prefix-description": "各行の最初の文字をトリミングする",
|
||||
@@ -565,6 +569,7 @@
|
||||
"choose-unit": "単位を選択",
|
||||
"press-enter-to-create": "Enterキーを押して作成",
|
||||
"choose-food": "食料を選択",
|
||||
"choose-recipe": "Choose Recipe",
|
||||
"notes": "備考",
|
||||
"toggle-section": "セクションの切り替え",
|
||||
"see-original-text": "元のテキストを見る",
|
||||
@@ -632,6 +637,8 @@
|
||||
"scrape-recipe-suggest-bulk-importer": "一括インポートを試す",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "生の HTML または JSON データをお持ちですか?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "生データから直接インポートできます",
|
||||
"scrape-recipe-website-being-blocked": "Website being blocked?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "Try importing the raw HTML instead.",
|
||||
"import-original-keywords-as-tags": "元のキーワードをタグとしてインポート",
|
||||
"stay-in-edit-mode": "編集モードを維持",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
@@ -691,11 +698,11 @@
|
||||
"reset-servings-count": "サービング数をリセット",
|
||||
"not-linked-ingredients": "追加の材料",
|
||||
"upload-another-image": "Upload another image",
|
||||
"upload-images": "Upload images",
|
||||
"upload-images": "画像のアップロード",
|
||||
"upload-more-images": "Upload more images",
|
||||
"set-as-cover-image": "Set as recipe cover image",
|
||||
"cover-image": "Cover image",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"cover-image": "カバー画像",
|
||||
"include-linked-recipes": "リンクされたレシピを含める",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
},
|
||||
@@ -734,7 +741,8 @@
|
||||
"search-hint": "'/' を押す",
|
||||
"advanced": "詳細",
|
||||
"auto-search": "自動検索",
|
||||
"no-results": "結果は見つかりませんでした。"
|
||||
"no-results": "結果は見つかりませんでした。",
|
||||
"type-to-search": "Type to search..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "新しいテーマを追加",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "次のようなものです",
|
||||
"is-not-like": "というわけではありません"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
"new-notification": "새 알림",
|
||||
"event-notifiers": "이벤트 알림이",
|
||||
"apprise-url-skipped-if-blank": "Apprise URL (비워두면 생략합니다)",
|
||||
"apprise-url-is-left-intentionally-blank": "Since Apprise URLs typically contain sensitive information, this field is left intentionally blank while editing. If you wish to update the URL, please enter the new one here, otherwise leave it blank to keep the current URL.",
|
||||
"apprise-url-is-left-intentionally-blank": "Apprise URL에는 일반적으로 민감한 정보가 포함되므로, 편집 시 이 필드는 의도적으로 비워둡니다. URL을 업데이트하려면 여기에 새 주소를 입력하시고, 현재 URL을 유지하려면 비워두십시오.",
|
||||
"enable-notifier": "알림 활성화",
|
||||
"what-events": "이 알리미는 어떤 이벤트를 구독해야 합니까?",
|
||||
"user-events": "사용자 이벤트",
|
||||
@@ -81,7 +81,7 @@
|
||||
"category-events": "카테고리 이벤트",
|
||||
"when-a-new-user-joins-your-group": "새로운 사용자가 그룹에 가입하면",
|
||||
"recipe-events": "레시피 이벤트",
|
||||
"label-events": "Label Events"
|
||||
"label-events": "라벨 이벤트"
|
||||
},
|
||||
"general": {
|
||||
"add": "추가",
|
||||
@@ -99,7 +99,7 @@
|
||||
"delete": "삭제",
|
||||
"disabled": "비활성화됨",
|
||||
"download": "다운로드",
|
||||
"duplicate": "Duplicate",
|
||||
"duplicate": "복제",
|
||||
"edit": "편집",
|
||||
"enabled": "활성화됨",
|
||||
"exception": "예외",
|
||||
@@ -184,16 +184,16 @@
|
||||
"date": "날짜",
|
||||
"id": "",
|
||||
"owner": "작성자",
|
||||
"change-owner": "Change Owner",
|
||||
"change-owner": "소유자 변경",
|
||||
"date-added": "추가된 날짜",
|
||||
"none": "없음",
|
||||
"run": "실행",
|
||||
"menu": "메뉴",
|
||||
"a-name-is-required": "이름은 필수 항목 입니다.",
|
||||
"delete-with-name": "{name} 삭제",
|
||||
"confirm-delete-generic-with-name": "Are you sure you want to delete this {name}?",
|
||||
"confirm-delete-generic-with-name": "{name}을(를) 정말 삭제하시겠습니까?",
|
||||
"confirm-delete-own-admin-account": "본인의 관리자 계정을 삭제하려고 한다는 점에 유의하세요! 이 작업은 취소할 수 없으며 계정이 영구적으로 삭제됩니다.",
|
||||
"organizer": "Organizer",
|
||||
"organizer": "분류자",
|
||||
"transfer": "전송",
|
||||
"copy": "복사",
|
||||
"color": "색상",
|
||||
@@ -204,7 +204,7 @@
|
||||
"clipboard-not-supported": "클립보드가 지원되지 않음",
|
||||
"copied-to-clipboard": "클립보드에 복사되었습니다",
|
||||
"your-browser-does-not-support-clipboard": "브라우저가 클립보드를 지원하지 않습니다.",
|
||||
"copied-items-to-clipboard": "No item copied to clipboard|One item copied to clipboard|Copied {count} items to clipboard",
|
||||
"copied-items-to-clipboard": "클립보드에 항목이 복사되지 않았습니다|클립보드에 항목이 하나 복사되었습니다|클립보드에 {count}개 항목이 복사되었습니다",
|
||||
"actions": "동작",
|
||||
"selected-count": "선택됨: {count}",
|
||||
"export-all": "전체 내보내기",
|
||||
@@ -214,7 +214,7 @@
|
||||
"unsaved-changes": "저장되지 않은 변경 사항이 있습니다. 떠나기 전에 저장하시겠습니까? 저장하려면 확인을 클릭하고, 변경 사항을 삭제하려면 취소를 클릭합니다.",
|
||||
"clipboard-copy-failure": "클립보드에 복사하는 데 실패했습니다.",
|
||||
"confirm-delete-generic-items": "이 항목을 삭제하시겠습니까?",
|
||||
"organizers": "Organizers",
|
||||
"organizers": "분류자",
|
||||
"caution": "주의",
|
||||
"show-advanced": "고급 표시",
|
||||
"add-field": "필드 추가",
|
||||
@@ -240,59 +240,59 @@
|
||||
"manage-groups": "그룹 관리",
|
||||
"user-group": "사용자 그룹",
|
||||
"user-group-created": "사용자 그룹 생성됨",
|
||||
"user-group-creation-failed": "User Group Creation Failed",
|
||||
"user-group-creation-failed": "사용자 그룹 생성 실패",
|
||||
"settings": {
|
||||
"keep-my-recipes-private": "Keep My Recipes Private",
|
||||
"keep-my-recipes-private-description": "Sets your group and all recipes defaults to private. You can always change this later."
|
||||
"keep-my-recipes-private": "내 레시피를 비공개로 유지",
|
||||
"keep-my-recipes-private-description": "그룹 및 모든 레시피를 기본적으로 비공개로 설정합니다. 나중에 언제든지 변경할 수 있습니다."
|
||||
},
|
||||
"manage-members": "회원 관리",
|
||||
"manage-members-description": "Manage the permissions of the members in your household. {manage} allows the user to access the data-management page, and {invite} allows the user to generate invitation links for other users. Group owners cannot change their own permissions.",
|
||||
"manage": "Manage",
|
||||
"manage-household": "Manage Household",
|
||||
"manage-members-description": "가구 구성원의 권한을 관리하세요. {manage}는 데이터 관리 페이지에 접근할 수 있게 하며, {invite}는 다른 사용자를 위한 초대 링크를 생성할 수 있게 합니다. 그룹 소유자는 자신의 권한을 변경할 수 없습니다.",
|
||||
"manage": "관리",
|
||||
"manage-household": "가구 관리",
|
||||
"invite": "초대하기",
|
||||
"looking-to-update-your-profile": "Looking to Update Your Profile?",
|
||||
"default-recipe-preferences-description": "These are the default settings when a new recipe is created in your group. These can be changed for individual recipes in the recipe settings menu.",
|
||||
"default-recipe-preferences": "Default Recipe Preferences",
|
||||
"group-preferences": "Group Preferences",
|
||||
"looking-to-update-your-profile": "프로필을 업데이트하시겠습니까?",
|
||||
"default-recipe-preferences-description": "이 설정은 그룹에서 새 레시피를 생성할 때 적용되는 기본값입니다. 레시피 설정 메뉴에서 개별 레시피별로 변경할 수 있습니다.",
|
||||
"default-recipe-preferences": "기본 레시피 설정",
|
||||
"group-preferences": "그룹 설정",
|
||||
"private-group": "비공개 그룹",
|
||||
"private-group-description": "Setting your group to private will disable all public view options. This overrides any individual public view settings",
|
||||
"enable-public-access": "Enable Public Access",
|
||||
"enable-public-access-description": "Make group recipes public by default, and allow visitors to view recipes without logging-in",
|
||||
"allow-users-outside-of-your-group-to-see-your-recipes": "Allow users outside of your group to see your recipes",
|
||||
"allow-users-outside-of-your-group-to-see-your-recipes-description": "When enabled you can use a public share link to share specific recipes without authorizing the user. When disabled, you can only share recipes with users who are in your group or with a pre-generated private link",
|
||||
"show-nutrition-information": "Show nutrition information",
|
||||
"show-nutrition-information-description": "When enabled the nutrition information will be shown on the recipe if available. If there is no nutrition information available, the nutrition information will not be shown",
|
||||
"show-recipe-assets": "Show recipe assets",
|
||||
"show-recipe-assets-description": "When enabled the recipe assets will be shown on the recipe if available",
|
||||
"default-to-landscape-view": "Default to landscape view",
|
||||
"default-to-landscape-view-description": "When enabled the recipe header section will be shown in landscape view",
|
||||
"disable-users-from-commenting-on-recipes": "Disable users from commenting on recipes",
|
||||
"disable-users-from-commenting-on-recipes-description": "Hides the comment section on the recipe page and disables commenting",
|
||||
"disable-organizing-recipe-ingredients-by-units-and-food": "Disable organizing recipe ingredients by units and food",
|
||||
"disable-organizing-recipe-ingredients-by-units-and-food-description": "Hides the Food, Unit, and Amount fields for ingredients and treats ingredients as plain text fields",
|
||||
"general-preferences": "General Preferences",
|
||||
"group-recipe-preferences": "Group Recipe Preferences",
|
||||
"report": "Report",
|
||||
"report-with-id": "Report ID: {id}",
|
||||
"private-group-description": "그룹을 비공개로 설정하면 모든 공개 보기 옵션이 비활성화됩니다. 이는 개별 공개 보기 설정을 모두 무효화합니다.",
|
||||
"enable-public-access": "공개 액세스 활성화",
|
||||
"enable-public-access-description": "그룹 레시피를 기본적으로 공개 상태로 설정하고, 방문자가 로그인 없이 레시피를 볼 수 있도록 허용하세요.",
|
||||
"allow-users-outside-of-your-group-to-see-your-recipes": "그룹 외부 사용자가 여러분의 레시피를 볼 수 있도록 허용하세요",
|
||||
"allow-users-outside-of-your-group-to-see-your-recipes-description": "이 기능을 활성화하면 사용자에게 권한을 부여하지 않고도 공개 공유 링크를 통해 특정 레시피를 공유할 수 있습니다. 비활성화 시에는 본인 그룹에 속한 사용자나 미리 생성된 비공개 링크를 통해서만 레시피를 공유할 수 있습니다.",
|
||||
"show-nutrition-information": "영양 정보 표시",
|
||||
"show-nutrition-information-description": "영양 정보가 제공되는 경우 레시피에 표시됩니다. 영양 정보가 제공되지 않으면 표시되지 않습니다.",
|
||||
"show-recipe-assets": "레시피 에셋 표시",
|
||||
"show-recipe-assets-description": "이 기능이 활성화되면 레시피에 사용 가능한 레시피 에셋이 표시됩니다.",
|
||||
"default-to-landscape-view": "가로 보기로 기본 설정",
|
||||
"default-to-landscape-view-description": "활성화 시 레시피 헤더 섹션이 가로 보기 모드로 표시됩니다",
|
||||
"disable-users-from-commenting-on-recipes": "사용자가 레시피에 댓글을 달 수 없도록 설정",
|
||||
"disable-users-from-commenting-on-recipes-description": "레시피 페이지의 댓글 섹션을 숨기고 댓글 작성을 비활성화합니다",
|
||||
"disable-organizing-recipe-ingredients-by-units-and-food": "단위 및 음식별로 레시피 재료를 정렬하는 기능을 비활성화합니다",
|
||||
"disable-organizing-recipe-ingredients-by-units-and-food-description": "재료의 '음식', '단위', '양' 필드를 숨기고 재료를 일반 텍스트 필드로 처리합니다",
|
||||
"general-preferences": "일반 설정",
|
||||
"group-recipe-preferences": "그룹 레시피 설정",
|
||||
"report": "보고서",
|
||||
"report-with-id": "보고서 ID: {id}",
|
||||
"group-management": "그룹 관리",
|
||||
"admin-group-management": "Admin Group Management",
|
||||
"admin-group-management-text": "Changes to this group will be reflected immediately.",
|
||||
"group-id-value": "Group Id: {0}",
|
||||
"total-households": "Total Households",
|
||||
"you-must-select-a-group-before-selecting-a-household": "You must select a group before selecting a household"
|
||||
"admin-group-management": "관리자 그룹 관리",
|
||||
"admin-group-management-text": "이 그룹에 대한 변경 사항은 즉시 반영됩니다.",
|
||||
"group-id-value": "그룹 Id: {0}",
|
||||
"total-households": "전체 가구 수",
|
||||
"you-must-select-a-group-before-selecting-a-household": "가구를 선택하기 전에 반드시 그룹을 선택해야 합니다."
|
||||
},
|
||||
"household": {
|
||||
"household": "Household",
|
||||
"households": "Households",
|
||||
"user-household": "User Household",
|
||||
"create-household": "Create Household",
|
||||
"household-name": "Household Name",
|
||||
"household-group": "Household Group",
|
||||
"household-management": "Household Management",
|
||||
"manage-households": "Manage Households",
|
||||
"admin-household-management": "Admin Household Management",
|
||||
"admin-household-management-text": "Changes to this household will be reflected immediately.",
|
||||
"household-id-value": "Household Id: {0}",
|
||||
"household": "가구",
|
||||
"households": "가구",
|
||||
"user-household": "사용자 가구",
|
||||
"create-household": "가구 생성",
|
||||
"household-name": "가구 이름",
|
||||
"household-group": "가구 그룹",
|
||||
"household-management": "가구 관리",
|
||||
"manage-households": "가구 관리하기",
|
||||
"admin-household-management": "관리자 가구 관리",
|
||||
"admin-household-management-text": "이 가구에 대한 변경 사항은 즉시 반영됩니다.",
|
||||
"household-id-value": "가구 Id: {0}",
|
||||
"private-household": "개인 가정",
|
||||
"private-household-description": "귀하의 가구를 비공개로 설정하면 모든 공개 보기 옵션이 비활성화됩니다. 이는 개별 공개 보기 설정을 재정의합니다.",
|
||||
"lock-recipe-edits-from-other-households": "다른 가구의 레시피 편집 잠금",
|
||||
@@ -301,7 +301,7 @@
|
||||
"default-recipe-preferences-description": "이는 가정에서 새로운 레시피를 만들 때의 기본 설정입니다. 레시피 설정 메뉴에서 개별 레시피에 대해 이를 변경할 수 있습니다.",
|
||||
"allow-users-outside-of-your-household-to-see-your-recipes": "가족 외의 사용자에게도 요리법을 볼 수 있도록 허용",
|
||||
"allow-users-outside-of-your-household-to-see-your-recipes-description": "활성화하면 공개 공유 링크를 사용하여 사용자에게 권한을 부여하지 않고도 특정 레시피를 공유할 수 있습니다. 비활성화하면 가족 구성원 또는 사전 생성된 비공개 링크로만 레시피를 공유할 수 있습니다.",
|
||||
"household-preferences": "Household Preferences"
|
||||
"household-preferences": "가구 설정"
|
||||
},
|
||||
"meal-plan": {
|
||||
"create-a-new-meal-plan": "새로운 식사 계획 생성",
|
||||
@@ -342,6 +342,9 @@
|
||||
"breakfast": "조식",
|
||||
"lunch": "점심",
|
||||
"dinner": "저녁 식사",
|
||||
"snack": "간식",
|
||||
"drink": "음료",
|
||||
"dessert": "디저트",
|
||||
"type-any": "모두",
|
||||
"day-any": "모두",
|
||||
"editor": "편집기",
|
||||
@@ -349,74 +352,74 @@
|
||||
"meal-title": "식사 제목",
|
||||
"meal-note": "식사 노트",
|
||||
"note-only": "참고사항만",
|
||||
"random-meal": "Random Meal",
|
||||
"random-dinner": "Random Dinner",
|
||||
"random-side": "Random Side",
|
||||
"this-rule-will-apply": "This rule will apply {dayCriteria} {mealTypeCriteria}.",
|
||||
"to-all-days": "to all days",
|
||||
"on-days": "on {0}s",
|
||||
"for-all-meal-types": "for all meal types",
|
||||
"for-type-meal-types": "for {0} meal types",
|
||||
"meal-plan-rules": "Meal Plan Rules",
|
||||
"new-rule": "New Rule",
|
||||
"meal-plan-rules-description": "You can create rules for auto selecting recipes for your meal plans. These rules are used by the server to determine the random pool of recipes to select from when creating meal plans. Note that if rules have the same day/type constraints then the rule filters will be merged. In practice, it's unnecessary to create duplicate rules, but it's possible to do so.",
|
||||
"new-rule-description": "When creating a new rule for a meal plan you can restrict the rule to be applicable for a specific day of the week and/or a specific type of meal. To apply a rule to all days or all meal types you can set the rule to \"Any\" which will apply it to all the possible values for the day and/or meal type.",
|
||||
"recipe-rules": "Recipe Rules",
|
||||
"applies-to-all-days": "Applies to all days",
|
||||
"applies-on-days": "Applies on {0}s",
|
||||
"meal-plan-settings": "Meal Plan Settings"
|
||||
"random-meal": "랜덤 식사",
|
||||
"random-dinner": "랜덤 저녁식사",
|
||||
"random-side": "랜덤 사이드 메뉴",
|
||||
"this-rule-will-apply": "이 규칙은 {dayCriteria} {mealTypeCriteria}에 적용됩니다.",
|
||||
"to-all-days": "모든 날에",
|
||||
"on-days": "{0}에",
|
||||
"for-all-meal-types": "모든 식사 종류에",
|
||||
"for-type-meal-types": "{0} 식사 종류에",
|
||||
"meal-plan-rules": "식사 플랜 규칙",
|
||||
"new-rule": "새 규칙",
|
||||
"meal-plan-rules-description": "식사 플랜에 사용할 레시피를 자동 선택하는 규칙을 생성할 수 있습니다. 이 규칙들은 서버가 식사 플랜을 생성할 때 선택할 무작위 레시피 풀을 결정하는 데 사용됩니다. 동일한 요일/유형 제약 조건을 가진 규칙들은 필터가 병합된다는 점에 유의하세요. 실제로 중복 규칙을 생성할 필요는 없지만, 생성하는 것은 가능합니다.",
|
||||
"new-rule-description": "식사 플랜에 새 규칙을 생성할 때, 특정 요일 및/또는 특정 식사 유형에만 적용되도록 규칙을 제한할 수 있습니다. 모든 요일 또는 모든 식사 유형에 규칙을 적용하려면 규칙을 \"모든\"으로 설정하면 됩니다. 이렇게 하면 해당 요일 및/또는 식사 유형의 모든 가능한 값에 규칙이 적용됩니다.",
|
||||
"recipe-rules": "레시피 규칙",
|
||||
"applies-to-all-days": "모든 날짜에 적용됨",
|
||||
"applies-on-days": "{0}에 적용됨",
|
||||
"meal-plan-settings": "식사 플랜 설정"
|
||||
},
|
||||
"migration": {
|
||||
"migration-data-removed": "Migration data removed",
|
||||
"migration-data-removed": "이전된 데이터 제거됨",
|
||||
"new-migration": "새 마이그레이션",
|
||||
"no-file-selected": "No File Selected",
|
||||
"no-migration-data-available": "No Migration Data Available",
|
||||
"previous-migrations": "Previous Migrations",
|
||||
"recipe-migration": "Recipe Migration",
|
||||
"no-file-selected": "선택된 파일이 없습니다",
|
||||
"no-migration-data-available": "이전 데이터가 없습니다.",
|
||||
"previous-migrations": "이전 데이터 이전",
|
||||
"recipe-migration": "레시피 데이터 이전",
|
||||
"chowdown": {
|
||||
"description": "Migrate data from Chowdown",
|
||||
"description-long": "Mealie natively supports the chowdown repository format. Download the code repository as a .zip file and upload it below.",
|
||||
"description": "Chowdown에서 데이터를 이전합니다",
|
||||
"description-long": "Mealie는 기본적으로 Chowdown 저장소 형식을 지원합니다. 코드 저장소를 .zip 파일로 다운로드한 후 아래에 업로드하세요.",
|
||||
"title": "Chowdown"
|
||||
},
|
||||
"nextcloud": {
|
||||
"description": "Migrate data from a Nextcloud Cookbook instance",
|
||||
"description-long": "Nextcloud recipes can be imported from a zip file that contains the data stored in Nextcloud. See the example folder structure below to ensure your recipes are able to be imported.",
|
||||
"description": "Nextcloud Cookbook 인스턴스에서 데이터 이전",
|
||||
"description-long": "Nextcloud 레시피는 Nextcloud에 저장된 데이터를 포함하는 zip 파일에서 가져올 수 있습니다. 레시피를 가져올 수 있도록 하려면 아래의 예시 폴더 구조를 참조하십시오.",
|
||||
"title": "Nextcloud Cookbook"
|
||||
},
|
||||
"copymethat": {
|
||||
"description-long": "Mealie can import recipes from Copy Me That. Export your recipes in HTML format, then upload the .zip below.",
|
||||
"title": "Copy Me That Recipe Manager"
|
||||
"description-long": "Mealie는 Copy Me That에서 레시피를 가져올 수 있습니다. 레시피를 HTML 형식으로 내보낸 후, 아래의 .zip 파일을 업로드하세요.",
|
||||
"title": "Copy Me That 레시피 매니저"
|
||||
},
|
||||
"paprika": {
|
||||
"description-long": "Mealie can import recipes from the Paprika application. Export your recipes from paprika, rename the export extension to .zip and upload it below.",
|
||||
"title": "Paprika Recipe Manager"
|
||||
"description-long": "Mealie는 Paprika 애플리케이션에서 레시피를 가져올 수 있습니다. Paprika에서 레시피를 내보낸 후, 내보낸 파일의 확장자를 .zip으로 변경하여 아래에 업로드하세요.",
|
||||
"title": "Paprika 레시피 매니저"
|
||||
},
|
||||
"mealie-pre-v1": {
|
||||
"description-long": "Mealie can import recipes from the Mealie application from a pre v1.0 release. Export your recipes from your old instance, and upload the zip file below. Note that only recipes can be imported from the export.",
|
||||
"description-long": "Mealie는 v1.0 이전 버전의 Mealie 애플리케이션에서 레시피를 가져올 수 있습니다. 기존 인스턴스에서 레시피를 내보낸 후 아래의 zip 파일을 업로드하세요. 내보낸 파일에서 레시피만 가져올 수 있다는 점에 유의하십시오.",
|
||||
"title": "Mealie Pre v1.0"
|
||||
},
|
||||
"tandoor": {
|
||||
"description-long": "Mealie can import recipes from Tandoor. Export your data in the \"Default\" format, then upload the .zip below.",
|
||||
"title": "Tandoor Recipes"
|
||||
"description-long": "Mealie는 Tandoor에서 레시피를 가져올 수 있습니다. 데이터를 \"기본\" 형식으로 내보낸 후 아래의 .zip 파일을 업로드하세요.",
|
||||
"title": "Tandoor 레시피"
|
||||
},
|
||||
"cookn": {
|
||||
"description-long": "Mealie can import recipes from DVO Cook'n X3. Export a cookbook or menu in the \"Cook'n\" format, rename the export extension to .zip, then upload the .zip below.",
|
||||
"description-long": "Mealie는 DVO Cook'n X3의 레시피를 가져올 수 있습니다. \"Cook'n\" 형식으로 요리책이나 메뉴를 내보낸 후, 내보낸 파일의 확장자를 .zip으로 변경하고 아래에 .zip 파일을 업로드하세요.",
|
||||
"title": "DVO Cook'n X3"
|
||||
},
|
||||
"recipe-data-migrations": "Recipe Data Migrations",
|
||||
"recipe-data-migrations-explanation": "Recipes can be migrated from another supported application to Mealie. This is a great way to get started with Mealie.",
|
||||
"coming-from-another-application-or-an-even-older-version-of-mealie": "Coming from another application or an even older version of Mealie? Check out migrations and see if your data can be imported.",
|
||||
"choose-migration-type": "Choose Migration Type",
|
||||
"tag-all-recipes": "Tag all recipes with {tag-name} tag",
|
||||
"nextcloud-text": "Nextcloud recipes can be imported from a zip file that contains the data stored in Nextcloud. See the example folder structure below to ensure your recipes are able to be imported.",
|
||||
"chowdown-text": "Mealie natively supports the chowdown repository format. Download the code repository as a .zip file and upload it below.",
|
||||
"recipe-1": "Recipe 1",
|
||||
"recipe-2": "Recipe 2",
|
||||
"paprika-text": "Mealie can import recipes from the Paprika application. Export your recipes from paprika, rename the export extension to .zip and upload it below.",
|
||||
"mealie-text": "Mealie can import recipes from the Mealie application from a pre v1.0 release. Export your recipes from your old instance, and upload the zip file below. Note that only recipes can be imported from the export.",
|
||||
"recipe-data-migrations": "레시피 데이터 이전",
|
||||
"recipe-data-migrations-explanation": "다른 지원되는 애플리케이션에서 Mealie로 레시피를 이전할 수 있습니다. 이것은 Mealie를 시작하는 아주 좋은 방법입니다.",
|
||||
"coming-from-another-application-or-an-even-older-version-of-mealie": "다른 애플리케이션이나 더 오래된 버전의 Mealie에서 오셨나요? 데이터 이전 기능을 확인하고 데이터를 가져올 수 있는지 살펴보세요.",
|
||||
"choose-migration-type": "이전 종류 선택",
|
||||
"tag-all-recipes": "모든 레시피에 {태그 이름} 태그를 지정하세요",
|
||||
"nextcloud-text": "Nextcloud 레시피는 Nextcloud에 저장된 데이터를 포함하는 zip 파일에서 가져올 수 있습니다. 레시피를 가져올 수 있도록 하려면 아래의 예시 폴더 구조를 참조하십시오.",
|
||||
"chowdown-text": "Mealie는 기본적으로 Chowdown 저장소 형식을 지원합니다. 코드 저장소를 .zip 파일로 다운로드한 후 아래에 업로드하세요.",
|
||||
"recipe-1": "레시피 1",
|
||||
"recipe-2": "레시피 2",
|
||||
"paprika-text": "Mealie는 Paprika 애플리케이션에서 레시피를 가져올 수 있습니다. Paprika에서 레시피를 내보낸 후, 내보낸 파일의 확장자를 .zip으로 변경하여 아래에 업로드하세요.",
|
||||
"mealie-text": "Mealie는 v1.0 이전 버전의 Mealie 애플리케이션에서 레시피를 가져올 수 있습니다. 기존 인스턴스에서 레시피를 내보낸 후 아래의 zip 파일을 업로드하세요. 내보낸 파일에서 레시피만 가져올 수 있다는 점에 유의하십시오.",
|
||||
"plantoeat": {
|
||||
"title": "Plan to Eat",
|
||||
"description-long": "Mealie can import recipies from Plan to Eat."
|
||||
"description-long": "Mealie는 Plan to Eat에서 레시피를 가져올 수 있습니다."
|
||||
},
|
||||
"myrecipebox": {
|
||||
"title": "내 레시피 박스",
|
||||
@@ -432,8 +435,8 @@
|
||||
"error-details": "Mealie는 ld+json 또는 microdata를 포함하는 웹사이트만 가져올 수 있습니다. 대부분의 주요 레시피 웹사이트는 이 데이터 구조를 지원합니다. 사이트를 가져올 수 없지만 로그에 json 데이터가 있는 경우 URL과 데이터와 함께 github 이슈를 제출하세요.",
|
||||
"error-title": "아무것도 찾지 못한 것 같습니다",
|
||||
"from-url": "레시피 가져오기",
|
||||
"github-issues": "GitHub Issues",
|
||||
"google-ld-json-info": "Google ld+json Info",
|
||||
"github-issues": "GitHub 이슈",
|
||||
"google-ld-json-info": "Google ld+json 정보",
|
||||
"must-be-a-valid-url": "유효한 URL이어야 합니다.",
|
||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "레시피 데이터를 붙여넣습니다. 각 줄은 목록의 항목으로 처리됩니다.",
|
||||
"recipe-markup-specification": "레시피 마크업 사양",
|
||||
@@ -442,15 +445,16 @@
|
||||
"upload-a-recipe": "레시피 업로드",
|
||||
"upload-individual-zip-file": "다른 Mealie 인스턴스에서 내보낸 개별 .zip 파일을 업로드합니다.",
|
||||
"url-form-hint": "좋아하는 레시피 웹사이트에서 링크를 복사하여 붙여넣으세요",
|
||||
"copy-and-paste-the-source-url-of-your-data-optional": "데이터의 소스 URL을 복사하여 붙여넣으세요 (선택 사항)",
|
||||
"view-scraped-data": "스크랩된 데이터 보기",
|
||||
"trim-whitespace-description": "앞뒤 공백과 빈 줄을 잘라냅니다.",
|
||||
"trim-prefix-description": "Trim first character from each line",
|
||||
"trim-prefix-description": "각 줄의 첫 문자 제거하기",
|
||||
"split-by-numbered-line-description": "'1)' 또는 '1.' 패턴을 일치시켜 문단을 분할하려고 시도합니다.",
|
||||
"import-by-url": "URL로 레시피 가져오기",
|
||||
"create-manually": "수동으로 레시피 만들기",
|
||||
"make-recipe-image": "이것을 레시피 이미지로 만드세요.",
|
||||
"add-food": "Add Food",
|
||||
"add-recipe": "Add Recipe"
|
||||
"add-food": "식품 추가",
|
||||
"add-recipe": "레시피 추가"
|
||||
},
|
||||
"page": {
|
||||
"404-page-not-found": "404. 페이지를 찾을 수 없음",
|
||||
@@ -464,13 +468,13 @@
|
||||
"page-updated": "페이지 업데이트됨",
|
||||
"pages-update-failed": "페이지 업데이트 실패",
|
||||
"pages-updated": "페이지 업데이트됨",
|
||||
"404-not-found": "404 Not Found",
|
||||
"404-not-found": "404 찾을 수 없음",
|
||||
"an-error-occurred": "오류가 발생했습니다!"
|
||||
},
|
||||
"recipe": {
|
||||
"add-key": "키 추가",
|
||||
"add-to-favorites": "즐겨찾기에 추가",
|
||||
"api-extras": "API Extras",
|
||||
"api-extras": "API 기타",
|
||||
"calories": "칼로리",
|
||||
"calories-suffix": "칼로리",
|
||||
"carbohydrate-content": "탄수화물",
|
||||
@@ -480,7 +484,7 @@
|
||||
"comment": "댓글",
|
||||
"comments": "댓글",
|
||||
"delete-confirmation": "이 레시피를 정말 삭제하시겠습니까?",
|
||||
"admin-delete-confirmation": "You're about to delete a recipe that isn't yours using admin permissions. Are you sure?",
|
||||
"admin-delete-confirmation": "관리자 권한으로 본인 소유가 아닌 레시피를 삭제하려 합니다. 정말 삭제하시겠습니까?",
|
||||
"delete-recipe": "레시피 삭제",
|
||||
"description": "설명",
|
||||
"disable-amount": "재료량 비활성화",
|
||||
@@ -491,63 +495,63 @@
|
||||
"fat-content": "지방",
|
||||
"fiber-content": "섬유질",
|
||||
"grams": "그램",
|
||||
"ingredient": "Ingredient",
|
||||
"ingredients": "Ingredients",
|
||||
"insert-ingredient": "Insert Ingredient",
|
||||
"insert-section": "Insert Section",
|
||||
"insert-above": "Insert Above",
|
||||
"insert-below": "Insert Below",
|
||||
"instructions": "Instructions",
|
||||
"key-name-required": "Key Name Required",
|
||||
"ingredient": "재료",
|
||||
"ingredients": "재료",
|
||||
"insert-ingredient": "재료 추가",
|
||||
"insert-section": "섹션 추가",
|
||||
"insert-above": "위에 추가",
|
||||
"insert-below": "아래에 추가",
|
||||
"instructions": "지침",
|
||||
"key-name-required": "키 이름 필수",
|
||||
"landscape-view-coming-soon": "Landscape View (Coming Soon)",
|
||||
"milligrams": "milligrams",
|
||||
"new-key-name": "New Key Name",
|
||||
"no-white-space-allowed": "No White Space Allowed",
|
||||
"note": "Note",
|
||||
"nutrition": "Nutrition",
|
||||
"object-key": "Object Key",
|
||||
"object-value": "Object Value",
|
||||
"original-url": "Original URL",
|
||||
"perform-time": "Cook Time",
|
||||
"prep-time": "Prep Time",
|
||||
"protein-content": "Protein",
|
||||
"public-recipe": "Public Recipe",
|
||||
"recipe-created": "Recipe created",
|
||||
"recipe-creation-failed": "Recipe creation failed",
|
||||
"recipe-deleted": "Recipe deleted",
|
||||
"recipe-image": "Recipe Image",
|
||||
"recipe-image-updated": "Recipe image updated",
|
||||
"delete-image": "Delete Recipe Image",
|
||||
"delete-image-confirmation": "Are you sure you want to delete this recipe image?",
|
||||
"recipe-image-deleted": "Recipe image deleted",
|
||||
"recipe-name": "Recipe Name",
|
||||
"recipe-settings": "Recipe Settings",
|
||||
"recipe-update-failed": "Recipe update failed",
|
||||
"recipe-updated": "Recipe updated",
|
||||
"remove-from-favorites": "Remove from Favorites",
|
||||
"remove-section": "Remove Section",
|
||||
"saturated-fat-content": "Saturated fat",
|
||||
"save-recipe-before-use": "Save recipe before use",
|
||||
"section-title": "Section Title",
|
||||
"servings": "Servings",
|
||||
"serves-amount": "Serves {amount}",
|
||||
"share-recipe-message": "I wanted to share my {0} recipe with you.",
|
||||
"show-nutrition-values": "Show Nutrition Values",
|
||||
"sodium-content": "Sodium",
|
||||
"step-index": "Step: {step}",
|
||||
"sugar-content": "Sugar",
|
||||
"title": "Title",
|
||||
"total-time": "Total Time",
|
||||
"trans-fat-content": "Trans-fat",
|
||||
"unable-to-delete-recipe": "Unable to Delete Recipe",
|
||||
"unsaturated-fat-content": "Unsaturated fat",
|
||||
"milligrams": "밀리그램",
|
||||
"new-key-name": "새 키 이름",
|
||||
"no-white-space-allowed": "공백 허용 안 됨",
|
||||
"note": "메모",
|
||||
"nutrition": "영양성분",
|
||||
"object-key": "객체 키",
|
||||
"object-value": "객체 값",
|
||||
"original-url": "원래 URL",
|
||||
"perform-time": "요리 시간",
|
||||
"prep-time": "준비 시간",
|
||||
"protein-content": "단백질",
|
||||
"public-recipe": "공개 레시피",
|
||||
"recipe-created": "레시피 생성됨",
|
||||
"recipe-creation-failed": "레시피 생성 실패",
|
||||
"recipe-deleted": "레시피 삭제됨",
|
||||
"recipe-image": "레시피 사진",
|
||||
"recipe-image-updated": "레시피 사진 업데이트됨",
|
||||
"delete-image": "레시피 사진 삭제",
|
||||
"delete-image-confirmation": "이 레시피 이미지를 삭제하시겠습니까?",
|
||||
"recipe-image-deleted": "레시피 이미지 삭제됨",
|
||||
"recipe-name": "레시피 이름",
|
||||
"recipe-settings": "레시피 설정",
|
||||
"recipe-update-failed": "레시피 수정 실패",
|
||||
"recipe-updated": "레시피 수정됨",
|
||||
"remove-from-favorites": "즐겨찾기에서 제거",
|
||||
"remove-section": "섹션 제거",
|
||||
"saturated-fat-content": "포화지방",
|
||||
"save-recipe-before-use": "사용 전 레시피 저장",
|
||||
"section-title": "섹션 제목",
|
||||
"servings": "제공량",
|
||||
"serves-amount": "{amount}인분",
|
||||
"share-recipe-message": "{0} 레시피를 당신과 공유하고 싶었어요.",
|
||||
"show-nutrition-values": "영양 성분 표시",
|
||||
"sodium-content": "나트륨",
|
||||
"step-index": "단계: {step}",
|
||||
"sugar-content": "당류",
|
||||
"title": "제목",
|
||||
"total-time": "총 시간",
|
||||
"trans-fat-content": "트랜스지방",
|
||||
"unable-to-delete-recipe": "레시피를 삭제할 수 없음",
|
||||
"unsaturated-fat-content": "불포화지방",
|
||||
"no-recipe": "레시피 없음",
|
||||
"locked-by-owner": "소유자에 의해 잠김",
|
||||
"join-the-conversation": "대화에 참여하기",
|
||||
"add-recipe-to-mealplan": "식사 계획에 레시피 추가",
|
||||
"entry-type": "항목 유형",
|
||||
"date-format-hint": "MM/DD/YYYY format",
|
||||
"date-format-hint-yyyy-mm-dd": "YYYY-MM-DD format",
|
||||
"date-format-hint": "MM/DD/YYYY 형식",
|
||||
"date-format-hint-yyyy-mm-dd": "YYYY-MM-DD 형식",
|
||||
"add-to-list": "목록에 추가",
|
||||
"add-to-plan": "계획에 추가",
|
||||
"add-to-timeline": "타임라인에 추가하기",
|
||||
@@ -559,230 +563,234 @@
|
||||
"failed-to-add-recipe-to-mealplan": "식사 계획에 레시피를 추가하지 못했습니다.",
|
||||
"failed-to-add-to-list": "목록에 추가하지 못했습니다.",
|
||||
"yield": "용량",
|
||||
"yields-amount-with-text": "Yields {amount} {text}",
|
||||
"yield-text": "Yield Text",
|
||||
"yields-amount-with-text": "{amount} {text} 생성",
|
||||
"yield-text": "생성 단위",
|
||||
"quantity": "수량",
|
||||
"choose-unit": "단위 선택",
|
||||
"press-enter-to-create": "Enter 키를 눌러 생성하세요",
|
||||
"choose-food": "음식 선택",
|
||||
"choose-recipe": "레시피 선택",
|
||||
"notes": "노트",
|
||||
"toggle-section": "Toggle Section",
|
||||
"see-original-text": "See Original Text",
|
||||
"original-text-with-value": "Original Text: {originalText}",
|
||||
"ingredient-linker": "Ingredient Linker",
|
||||
"unlinked": "Not linked yet",
|
||||
"linked-to-other-step": "Linked to other step",
|
||||
"toggle-section": "섹션 활성화",
|
||||
"see-original-text": "원래 텍스트 보기",
|
||||
"original-text-with-value": "원래 텍스트: {originalText}",
|
||||
"ingredient-linker": "단계별로 재료 연결하기",
|
||||
"unlinked": "아직 연결되지 않음",
|
||||
"linked-to-other-step": "다른 단계와 연결됨",
|
||||
"auto": "자동",
|
||||
"cook-mode": "Cook Mode",
|
||||
"link-ingredients": "Link Ingredients",
|
||||
"merge-above": "Merge Above",
|
||||
"cook-mode": "요리 모드",
|
||||
"link-ingredients": "재료 연결하기",
|
||||
"merge-above": "위 항목과 합치기",
|
||||
"move-to-bottom": "맨 아래로 이동",
|
||||
"move-to-top": "맨 위로 이동",
|
||||
"reset-scale": "Reset Scale",
|
||||
"decrease-scale-label": "Decrease Scale by 1",
|
||||
"increase-scale-label": "Increase Scale by 1",
|
||||
"reset-scale": "배율 재설정",
|
||||
"decrease-scale-label": "배율 1만큼 감소",
|
||||
"increase-scale-label": "배율 1만큼 증가",
|
||||
"locked": "잠김",
|
||||
"public-link": "Public Link",
|
||||
"edit-timeline-event": "Edit Timeline Event",
|
||||
"public-link": "공개 링크",
|
||||
"edit-timeline-event": "타임라인 이벤트 수정",
|
||||
"timeline": "타임라인",
|
||||
"timeline-is-empty": "Nothing on the timeline yet. Try making this recipe!",
|
||||
"timeline-no-events-found-try-adjusting-filters": "No events found. Try adjusting your search filters.",
|
||||
"group-global-timeline": "{groupName} Global Timeline",
|
||||
"open-timeline": "Open Timeline",
|
||||
"made-this": "I Made This",
|
||||
"how-did-it-turn-out": "How did it turn out?",
|
||||
"user-made-this": "{user} made this",
|
||||
"made-for-recipe": "Made for {recipe}",
|
||||
"added-to-timeline": "Added to timeline",
|
||||
"failed-to-add-to-timeline": "Failed to add to timeline",
|
||||
"failed-to-update-recipe": "Failed to update recipe",
|
||||
"added-to-timeline-but-failed-to-add-image": "Added to timeline, but failed to add image",
|
||||
"api-extras-description": "Recipes extras are a key feature of the Mealie API. They allow you to create custom JSON key/value pairs within a recipe, to reference from 3rd party applications. You can use these keys to provide information, for example to trigger automations or custom messages to relay to your desired device.",
|
||||
"message-key": "Message Key",
|
||||
"parse": "Parse",
|
||||
"timeline-is-empty": "아직 타임라인에 아무것도 없습니다. 이 레시피를 만들어 보세요!",
|
||||
"timeline-no-events-found-try-adjusting-filters": "찾은 이벤트가 없습니다. 검색 필터를 조정해 보세요.",
|
||||
"group-global-timeline": "{groupName} 전체 타임라인",
|
||||
"open-timeline": "타임라인 열기",
|
||||
"made-this": "내가 만들었어!",
|
||||
"how-did-it-turn-out": "어떻게 완성됐나요?",
|
||||
"user-made-this": "{user}이(가) 이것을 만듦",
|
||||
"made-for-recipe": "{recipe}를 위해 만들어짐",
|
||||
"added-to-timeline": "타임라인에 추가됨",
|
||||
"failed-to-add-to-timeline": "타임라인에 추가 실패",
|
||||
"failed-to-update-recipe": "레시피 수정 실패",
|
||||
"added-to-timeline-but-failed-to-add-image": "타임라인에 추가되었으나, 이미지 추가에 실패했습니다.",
|
||||
"api-extras-description": "레시피 추가 항목은 Mealie API의 핵심 기능입니다. 이를 통해 레시피 내에서 사용자 정의 JSON 키/값 쌍을 생성하여 타사 애플리케이션에서 참조할 수 있습니다. 이러한 키를 활용하여 정보를 제공할 수 있으며, 예를 들어 자동화를 트리거하거나 원하는 기기로 전달할 사용자 정의 메시지를 설정하는 데 사용할 수 있습니다.",
|
||||
"message-key": "메시지 키",
|
||||
"parse": "추출하기",
|
||||
"ingredients-not-parsed-description": "It looks like your ingredients aren't parsed yet. Click the \"{parse}\" button below to parse your ingredients into structured foods.",
|
||||
"attach-images-hint": "Attach images by dragging & dropping them into the editor",
|
||||
"drop-image": "Drop image",
|
||||
"enable-ingredient-amounts-to-use-this-feature": "Enable ingredient amounts to use this feature",
|
||||
"recipes-with-units-or-foods-defined-cannot-be-parsed": "Recipes with units or foods defined cannot be parsed.",
|
||||
"parse-ingredients": "Parse ingredients",
|
||||
"edit-markdown": "Edit Markdown",
|
||||
"recipe-creation": "Recipe Creation",
|
||||
"select-one-of-the-various-ways-to-create-a-recipe": "Select one of the various ways to create a recipe",
|
||||
"looking-for-migrations": "Looking For Migrations?",
|
||||
"import-with-url": "Import with URL",
|
||||
"create-recipe": "Create Recipe",
|
||||
"create-recipe-description": "Create a new recipe from scratch.",
|
||||
"create-recipes": "Create Recipes",
|
||||
"import-with-zip": "Import with .zip",
|
||||
"attach-images-hint": "이미지를 편집기로 끌어다 놓아 첨부하세요",
|
||||
"drop-image": "이미지 끌어다 놓기",
|
||||
"enable-ingredient-amounts-to-use-this-feature": "이 기능을 사용하려면 재료 양을 활성화하세요",
|
||||
"recipes-with-units-or-foods-defined-cannot-be-parsed": "단위나 정의된 식품이 포함된 레시피는 추출할 수 없습니다.",
|
||||
"parse-ingredients": "재료 추출하기",
|
||||
"edit-markdown": "마크다운 수정",
|
||||
"recipe-creation": "레시피 생성",
|
||||
"select-one-of-the-various-ways-to-create-a-recipe": "레시피를 만드는 다양한 방법 중 하나를 선택하세요",
|
||||
"looking-for-migrations": "데이터 이전 기능을 찾고 계신가요?",
|
||||
"import-with-url": "URL로 가져오기",
|
||||
"create-recipe": "레시피 생성",
|
||||
"create-recipe-description": "처음부터 새로운 레시피를 만드세요.",
|
||||
"create-recipes": "레시피 생성",
|
||||
"import-with-zip": ".zip 파일로 가져오기",
|
||||
"create-recipe-from-an-image": "Create Recipe from an Image",
|
||||
"create-recipe-from-an-image-description": "Create a recipe by uploading an image of it. Mealie will attempt to extract the text from the image using AI and create a recipe from it.",
|
||||
"crop-and-rotate-the-image": "Crop and rotate the image so that only the text is visible, and it's in the correct orientation.",
|
||||
"create-from-images": "Create from Images",
|
||||
"should-translate-description": "Translate the recipe into my language",
|
||||
"please-wait-image-procesing": "Please wait, the image is processing. This may take some time.",
|
||||
"please-wait-images-processing": "Please wait, the images are processing. This may take some time.",
|
||||
"bulk-url-import": "Bulk URL Import",
|
||||
"debug-scraper": "Debug Scraper",
|
||||
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "Create a recipe by providing the name. All recipes must have unique names.",
|
||||
"new-recipe-names-must-be-unique": "New recipe names must be unique",
|
||||
"scrape-recipe": "Scrape Recipe",
|
||||
"scrape-recipe-description": "Scrape a recipe by url. Provide the url for the site you want to scrape, and Mealie will attempt to scrape the recipe from that site and add it to your collection.",
|
||||
"scrape-recipe-have-a-lot-of-recipes": "Have a lot of recipes you want to scrape at once?",
|
||||
"scrape-recipe-suggest-bulk-importer": "Try out the bulk importer",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "Have raw HTML or JSON data?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "You can import from raw data directly",
|
||||
"import-original-keywords-as-tags": "Import original keywords as tags",
|
||||
"stay-in-edit-mode": "Stay in Edit mode",
|
||||
"parse-recipe-ingredients-after-import": "Parse recipe ingredients after import",
|
||||
"import-from-zip": "Import from Zip",
|
||||
"import-from-zip-description": "Import a single recipe that was exported from another Mealie instance.",
|
||||
"import-from-html-or-json": "Import from HTML or JSON",
|
||||
"import-from-html-or-json-description": "Import a single recipe from raw HTML or JSON. This is useful if you have a recipe from a site that Mealie can't scrape normally, or from some other external source.",
|
||||
"json-import-format-description-colon": "To import via JSON, it must be in valid format:",
|
||||
"json-editor": "JSON Editor",
|
||||
"zip-files-must-have-been-exported-from-mealie": ".zip files must have been exported from Mealie",
|
||||
"create-a-recipe-by-uploading-a-scan": "Create a recipe by uploading a scan.",
|
||||
"upload-a-png-image-from-a-recipe-book": "Upload a png image from a recipe book",
|
||||
"recipe-bulk-importer": "Recipe Bulk Importer",
|
||||
"recipe-bulk-importer-description": "The Bulk recipe importer allows you to import multiple recipes at once by queueing the sites on the backend and running the task in the background. This can be useful when initially migrating to Mealie, or when you want to import a large number of recipes.",
|
||||
"set-categories-and-tags": "Set Categories and Tags",
|
||||
"bulk-imports": "Bulk Imports",
|
||||
"bulk-import-process-has-started": "Bulk Import process has started",
|
||||
"bulk-import-process-has-failed": "Bulk import process has failed",
|
||||
"report-deletion-failed": "Report deletion failed",
|
||||
"recipe-debugger": "Recipe Debugger",
|
||||
"recipe-debugger-description": "Grab the URL of the recipe you want to debug and paste it here. The URL will be scraped by the recipe scraper and the results will be displayed. If you don't see any data returned, the site you are trying to scrape is not supported by Mealie or its scraper library.",
|
||||
"use-openai": "Use OpenAI",
|
||||
"recipe-debugger-use-openai-description": "Use OpenAI to parse the results instead of relying on the scraper library. When creating a recipe via URL, this is done automatically if the scraper library fails, but you may test it manually here.",
|
||||
"debug": "Debug",
|
||||
"tree-view": "Tree View",
|
||||
"recipe-servings": "Recipe Servings",
|
||||
"recipe-yield": "Recipe Yield",
|
||||
"recipe-yield-text": "Recipe Yield Text",
|
||||
"unit": "Unit",
|
||||
"crop-and-rotate-the-image": "이미지를 잘라내고 회전시켜 텍스트만 보이도록 하고 올바른 방향으로 배치하십시오.",
|
||||
"create-from-images": "이미지에서 생성",
|
||||
"should-translate-description": "레시피를 내 언어로 번역하기",
|
||||
"please-wait-image-procesing": "잠시만 기다려 주세요, 이미지가 처리 중입니다. 시간이 다소 걸릴 수 있습니다.",
|
||||
"please-wait-images-processing": "잠시만 기다려 주세요, 이미지가 처리 중입니다. 시간이 다소 걸릴 수 있습니다.",
|
||||
"bulk-url-import": "대량 URL 가져오기",
|
||||
"debug-scraper": "스크랩퍼 디버깅하기",
|
||||
"create-a-recipe-by-providing-the-name-all-recipes-must-have-unique-names": "이름을 입력하여 레시피를 생성하세요. 모든 레시피는 고유한 이름을 가져야 합니다.",
|
||||
"new-recipe-names-must-be-unique": "새로운 레시피 이름은 반드시 고유해야 합니다",
|
||||
"scrape-recipe": "레시피 스크랩하기",
|
||||
"scrape-recipe-description": "URL로 레시피를 스크랩하세요. 스크랩하려는 사이트의 URL을 제공하면, Mealie가 해당 사이트에서 레시피를 스크랩하여 여러분의 컬렉션에 추가합니다.",
|
||||
"scrape-recipe-have-a-lot-of-recipes": "한 번에 스크랩하고 싶은 레시피가 많으신가요?",
|
||||
"scrape-recipe-suggest-bulk-importer": "대량 가져오기 도구를 사용해 보세요",
|
||||
"scrape-recipe-have-raw-html-or-json-data": "원본 HTML 또는 JSON 데이터를 가지고 계신가요?",
|
||||
"scrape-recipe-you-can-import-from-raw-data-directly": "원본 데이터에서 직접 가져올 수 있습니다",
|
||||
"scrape-recipe-website-being-blocked": "웹사이트가 차단되고 있나요?",
|
||||
"scrape-recipe-try-importing-raw-html-instead": "대신 원본 HTML 가져오기를 시도해보세요.",
|
||||
"import-original-keywords-as-tags": "원본 키워드를 태그로 가져오기",
|
||||
"stay-in-edit-mode": "편집 모드 유지",
|
||||
"parse-recipe-ingredients-after-import": "가져오기 후 레시피 재료 추출",
|
||||
"import-from-zip": "Zip 파일에서 가져오기",
|
||||
"import-from-zip-description": "다른 Mealie 인스턴스에서 내보낸 단일 레시피를 가져옵니다.",
|
||||
"import-from-html-or-json": "HTML 또는 JSON에서 가져오기",
|
||||
"import-from-html-or-json-description": "원본 HTML 또는 JSON에서 단일 레시피를 가져옵니다. 이는 Mealie가 일반적으로 스크랩할 수 없는 사이트나 기타 외부 출처의 레시피가 있을 때 유용합니다.",
|
||||
"json-import-format-description-colon": "JSON을 통해 가져오려면 유효한 형식이어야 합니다:",
|
||||
"json-editor": "JSON 편집기",
|
||||
"zip-files-must-have-been-exported-from-mealie": ".zip 파일은 Mealie에서 내보낸 파일이어야 합니다.",
|
||||
"create-a-recipe-by-uploading-a-scan": "스캔본을 업로드하여 레시피를 생성하세요.",
|
||||
"upload-a-png-image-from-a-recipe-book": "레시피 책에서 png 이미지를 업로드하세요",
|
||||
"recipe-bulk-importer": "레시피 대량 가져오기 도구",
|
||||
"recipe-bulk-importer-description": "대량 레시피 가져오기 도구는 백엔드에서 사이트를 대기열에 추가하고 백그라운드에서 작업을 실행함으로써 여러 레시피를 한 번에 가져올 수 있게 합니다. 이는 Mealie로 처음 이전할 때나 대량의 레시피를 가져오고 싶을 때 유용합니다.",
|
||||
"set-categories-and-tags": "카테고리 및 태그 설정",
|
||||
"bulk-imports": "대량 가져오기",
|
||||
"bulk-import-process-has-started": "대량 가져오기 시작됨",
|
||||
"bulk-import-process-has-failed": "대량 가져오기 실패함",
|
||||
"report-deletion-failed": "보고서 삭제 실패",
|
||||
"recipe-debugger": "레시피 디버깅 도구",
|
||||
"recipe-debugger-description": "디버깅하려는 레시피의 URL을 복사하여 여기에 붙여넣으세요. 레시피 스크랩 도구가 URL을 추출하여 결과를 표시합니다. 데이터가 반환되지 않는다면, 해당 사이트는 Mealie 또는 그 스크랩 라이브러리가 지원하지 않는 사이트입니다.",
|
||||
"use-openai": "OpenAI 사용하기",
|
||||
"recipe-debugger-use-openai-description": "스크랩 라이브러리에 의존하지 말고 OpenAI를 사용하여 결과를 파싱하세요. URL을 통해 레시피를 생성할 때 스크랩 라이브러리가 실패하면 이 작업이 자동으로 수행되지만, 여기에서 수동으로 테스트할 수 있습니다.",
|
||||
"debug": "디버그",
|
||||
"tree-view": "계층적 보기",
|
||||
"recipe-servings": "레시피 제공량",
|
||||
"recipe-yield": "레시피 생성량",
|
||||
"recipe-yield-text": "레시피 생성 단위",
|
||||
"unit": "단위",
|
||||
"upload-image": "이미지 업로드",
|
||||
"screen-awake": "화면을 항상 켠 상태로 유지",
|
||||
"remove-image": "이미지 제거",
|
||||
"nextStep": "다음 단계",
|
||||
"recipe-actions": "Recipe Actions",
|
||||
"recipe-actions": "레시피 액션",
|
||||
"parser": {
|
||||
"ingredient-parser": "Ingredient Parser",
|
||||
"explanation": "To use the ingredient parser, click the 'Parse All' button to start the process. Once the processed ingredients are available, you can review the items and verify that they were parsed correctly. The model's confidence score is displayed on the right of the item title. This score is an average of all the individual scores and may not always be completely accurate.",
|
||||
"alerts-explainer": "Alerts will be displayed if a matching foods or unit is found but does not exists in the database.",
|
||||
"select-parser": "Select Parser",
|
||||
"natural-language-processor": "Natural Language Processor",
|
||||
"brute-parser": "Brute Parser",
|
||||
"openai-parser": "OpenAI Parser",
|
||||
"parse-all": "Parse All",
|
||||
"no-unit": "No unit",
|
||||
"missing-unit": "Create missing unit: {unit}",
|
||||
"missing-food": "Create missing food: {food}",
|
||||
"this-unit-could-not-be-parsed-automatically": "This unit could not be parsed automatically",
|
||||
"this-food-could-not-be-parsed-automatically": "This food could not be parsed automatically",
|
||||
"no-food": "No Food",
|
||||
"review-parsed-ingredients": "Review parsed ingredients",
|
||||
"confidence-score": "Confidence Score",
|
||||
"ingredient-parser-description": "Your ingredients have been successfully parsed. Please review the ingredients we're not sure about.",
|
||||
"ingredient-parser-final-review-description": "Once all ingredients have been reviewed, you'll have one more chance to review all ingredients before applying the changes to your recipe.",
|
||||
"add-text-as-alias-for-item": "Add \"{text}\" as alias for {item}",
|
||||
"delete-item": "Delete Item"
|
||||
"ingredient-parser": "재료 분석기",
|
||||
"explanation": "재료 분석기를 사용하려면 '모두 분석' 버튼을 클릭하여 프로세스를 시작하세요. 처리된 재료가 준비되면 항목을 검토하고 올바르게 분석되었는지 확인할 수 있습니다. 항목 제목 오른쪽에는 모델의 신뢰도 점수가 표시됩니다. 이 점수는 개별 점수의 평균값으로 항상 완벽하게 정확한 것은 아닙니다.",
|
||||
"alerts-explainer": "일치하는 식품 또는 단위가 발견되었으나 데이터베이스에 존재하지 않을 경우 경고가 표시됩니다.",
|
||||
"select-parser": "분석기 선택",
|
||||
"natural-language-processor": "자연어 처리기",
|
||||
"brute-parser": "무차별 분석기",
|
||||
"openai-parser": "OpenAI 분석기",
|
||||
"parse-all": "모두 분석",
|
||||
"no-unit": "단위 없음",
|
||||
"missing-unit": "새 단위 생성: {unit}",
|
||||
"missing-food": "새 식품 생성: {food}",
|
||||
"this-unit-could-not-be-parsed-automatically": "이 단위는 자동으로 분석(추출)할 수 없습니다.",
|
||||
"this-food-could-not-be-parsed-automatically": "이 식품은 자동으로 분석(추출)할 수 없습니다.",
|
||||
"no-food": "식품 없음",
|
||||
"review-parsed-ingredients": "분석(추출)된 재료 확인",
|
||||
"confidence-score": "신뢰도 점수",
|
||||
"ingredient-parser-description": "재료가 성공적으로 분석되었습니다. 확실하지 않은 재료는 검토해 주세요.",
|
||||
"ingredient-parser-final-review-description": "모든 재료를 검토한 후, 레시피에 변경 사항을 적용하기 전에 모든 재료를 한 번 더 검토할 기회가 주어집니다.",
|
||||
"add-text-as-alias-for-item": "{text}을(를) {item}의 별칭으로 추가",
|
||||
"delete-item": "항목 삭제"
|
||||
},
|
||||
"reset-servings-count": "Reset Servings Count",
|
||||
"not-linked-ingredients": "Additional Ingredients",
|
||||
"upload-another-image": "Upload another image",
|
||||
"upload-images": "Upload images",
|
||||
"upload-more-images": "Upload more images",
|
||||
"set-as-cover-image": "Set as recipe cover image",
|
||||
"cover-image": "Cover image",
|
||||
"include-linked-recipes": "Include Linked Recipes",
|
||||
"include-linked-recipe-ingredients": "Include Linked Recipe Ingredients",
|
||||
"toggle-recipe": "Toggle Recipe"
|
||||
"reset-servings-count": "제공량 재설정",
|
||||
"not-linked-ingredients": "추가 재료",
|
||||
"upload-another-image": "추가 이미지 업로드",
|
||||
"upload-images": "이미지 업로드",
|
||||
"upload-more-images": "이미지 추가 업로드",
|
||||
"set-as-cover-image": "레시피 표지 이미지로 설정",
|
||||
"cover-image": "표지 이미지",
|
||||
"include-linked-recipes": "링크된 레시피 포함",
|
||||
"include-linked-recipe-ingredients": "링크된 레시피 재료 포함",
|
||||
"toggle-recipe": "레시피로 전환"
|
||||
},
|
||||
"recipe-finder": {
|
||||
"recipe-finder": "Recipe Finder",
|
||||
"recipe-finder-description": "Search for recipes based on ingredients you have on hand. You can also filter by tools you have available, and set a maximum number of missing ingredients or tools.",
|
||||
"selected-ingredients": "Selected Ingredients",
|
||||
"no-ingredients-selected": "No ingredients selected",
|
||||
"missing": "Missing",
|
||||
"no-recipes-found": "No recipes found",
|
||||
"no-recipes-found-description": "Try adding more ingredients to your search or adjusting your filters",
|
||||
"include-ingredients-on-hand": "Include Ingredients On Hand",
|
||||
"include-tools-on-hand": "Include Tools On Hand",
|
||||
"max-missing-ingredients": "Max Missing Ingredients",
|
||||
"max-missing-tools": "Max Missing Tools",
|
||||
"selected-tools": "Selected Tools",
|
||||
"other-filters": "Other Filters",
|
||||
"ready-to-make": "Ready to Make",
|
||||
"almost-ready-to-make": "Almost Ready to Make"
|
||||
"recipe-finder": "레시피 찾기",
|
||||
"recipe-finder-description": "가지고 있는 재료로 레시피를 검색하세요. 사용 가능한 도구로도 필터링할 수 있으며, 부족한 재료나 도구의 최대 개수를 설정할 수 있습니다.",
|
||||
"selected-ingredients": "선택된 재료",
|
||||
"no-ingredients-selected": "선택된 재료 없음",
|
||||
"missing": "없음",
|
||||
"no-recipes-found": "검색 결과가 없습니다.",
|
||||
"no-recipes-found-description": "검색어에 더 많은 항목을 추가하거나 필터를 조정해 보세요.",
|
||||
"include-ingredients-on-hand": "가지고 있는 재료 포함",
|
||||
"include-tools-on-hand": "가지고 있는 도구 포함",
|
||||
"max-missing-ingredients": "없는 재료 최대 수",
|
||||
"max-missing-tools": "없는 도구 최대 수",
|
||||
"selected-tools": "선택된 도구",
|
||||
"other-filters": "기타 필터",
|
||||
"ready-to-make": "만들 수 있음",
|
||||
"almost-ready-to-make": "거의 만들 수 있음"
|
||||
},
|
||||
"search": {
|
||||
"advanced-search": "고급 검색",
|
||||
"and": "and",
|
||||
"exclude": "Exclude",
|
||||
"include": "Include",
|
||||
"max-results": "Max Results",
|
||||
"or": "Or",
|
||||
"has-any": "Has Any",
|
||||
"has-all": "Has All",
|
||||
"clear-selection": "Clear Selection",
|
||||
"results": "Results",
|
||||
"and": "그리고",
|
||||
"exclude": "제외",
|
||||
"include": "포함",
|
||||
"max-results": "최대 결과 수",
|
||||
"or": "또는",
|
||||
"has-any": "적어도 하나 포함",
|
||||
"has-all": "전부 포함",
|
||||
"clear-selection": "모두 선택 취소",
|
||||
"results": "결과",
|
||||
"search": "검색",
|
||||
"search-mealie": "Search Mealie (press /)",
|
||||
"search-mealie": "Mealie 검색 (/를 누르세요)",
|
||||
"search-placeholder": "검색...",
|
||||
"tag-filter": "태그 필터",
|
||||
"search-hint": "Press '/'",
|
||||
"advanced": "Advanced",
|
||||
"search-hint": "'/'를 누르세요",
|
||||
"advanced": "고급",
|
||||
"auto-search": "자동 검색",
|
||||
"no-results": "검색 결과가 없습니다."
|
||||
"no-results": "검색 결과가 없습니다.",
|
||||
"type-to-search": "검색어를 입력하세요..."
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "새 테마 추가",
|
||||
"admin-settings": "관리자 설정",
|
||||
"backup": {
|
||||
"backup-created": "백업이 성공적으로 완료되었습니다.",
|
||||
"backup-created-at-response-export_path": "Backup Created at {path}",
|
||||
"backup-created-at-response-export_path": "백업 생성 위치: {path}",
|
||||
"backup-deleted": "백업 삭제됨",
|
||||
"restore-success": "복원 성공!",
|
||||
"restore-fail": "Restore failed. Check your server logs for more details",
|
||||
"backup-tag": "Backup Tag",
|
||||
"restore-fail": "복원이 실패했습니다. 자세한 내용은 서버 로그를 확인하십시오.",
|
||||
"backup-tag": "백업 태그",
|
||||
"create-heading": "Create a Backup",
|
||||
"delete-backup": "백업 삭제",
|
||||
"error-creating-backup-see-log-file": "Error Creating Backup. See Log File",
|
||||
"error-creating-backup-see-log-file": "백업 생성 중 오류 발생. 로그 파일을 참조하십시오.",
|
||||
"full-backup": "전체 백업",
|
||||
"import-summary": "Import Summary",
|
||||
"partial-backup": "Partial Backup",
|
||||
"unable-to-delete-backup": "Unable to Delete Backup.",
|
||||
"experimental-description": "Backups are total snapshots of the database and data directory of the site. This includes all data and cannot be set to exclude subsets of data. You can think of this as a snapshot of Mealie at a specific time. These serve as a database agnostic way to export and import data, or back up the site to an external location.",
|
||||
"import-summary": "가져오기 요약",
|
||||
"partial-backup": "부분 백업",
|
||||
"unable-to-delete-backup": "백업을 삭제할 수 없습니다.",
|
||||
"experimental-description": "백업은 사이트의 데이터베이스와 데이터 디렉터리의 전체 스냅샷입니다. 여기에는 모든 데이터가 포함되며 데이터의 일부를 제외하도록 설정할 수 없습니다. 특정 시점의 Mealie 스냅샷이라고 생각하시면 됩니다. 이는 데이터베이스에 구애받지 않는 방식으로 데이터를 내보내고 가져오거나, 사이트를 외부 위치에 백업하는 역할을 합니다.",
|
||||
"backup-restore": "백업/복원",
|
||||
"back-restore-description": "Restoring this backup will overwrite all the current data in your database and in the data directory and replace them with the contents of this backup. {cannot-be-undone} If the restoration is successful, you will be logged out.",
|
||||
"cannot-be-undone": "This action cannot be undone - use with caution.",
|
||||
"postgresql-note": "If you are using PostgreSQL, please review the {backup-restore-process} prior to restoring.",
|
||||
"backup-restore-process-in-the-documentation": "backup/restore process in the documentation",
|
||||
"irreversible-acknowledgment": "I understand that this action is irreversible, destructive and may cause data loss",
|
||||
"restore-backup": "Restore Backup"
|
||||
"back-restore-description": "이 백업을 복원하면 데이터베이스와 데이터 디렉터리의 현재 데이터가 모두 덮어쓰기되며, 해당 백업의 내용으로 대체됩니다. {cannot-be-undone} 복원이 성공하면 로그아웃됩니다.",
|
||||
"cannot-be-undone": "이 작업은 되돌릴 수 없습니다 - 주의해서 사용하십시오.",
|
||||
"postgresql-note": "PostgreSQL을 사용 중인 경우, 복원 전에 {backup-restore-process}를 검토하십시오.",
|
||||
"backup-restore-process-in-the-documentation": "공식 문서의 백업/복원 가이드",
|
||||
"irreversible-acknowledgment": "이 작업은 되돌릴 수 없으며 파괴적일 수 있고 데이터 손실을 초래할 수 있음을 이해합니다.",
|
||||
"restore-backup": "백업 복원"
|
||||
},
|
||||
"backup-and-exports": "Backups",
|
||||
"change-password": "Change Password",
|
||||
"current": "Version:",
|
||||
"custom-pages": "Custom Pages",
|
||||
"edit-page": "Edit Page",
|
||||
"events": "Events",
|
||||
"first-day-of-week": "First day of the week",
|
||||
"group-settings-updated": "Group Settings Updated",
|
||||
"backup-and-exports": "백업",
|
||||
"change-password": "비밀번호 변경",
|
||||
"current": "버전:",
|
||||
"custom-pages": "사용자 정의 페이지",
|
||||
"edit-page": "페이지 수정",
|
||||
"events": "이벤트",
|
||||
"first-day-of-week": "일주일의 시작 요일",
|
||||
"group-settings-updated": "그룹 설정 수정됨",
|
||||
"homepage": {
|
||||
"all-categories": "All Categories",
|
||||
"card-per-section": "Card Per Section",
|
||||
"home-page": "Home Page",
|
||||
"home-page-sections": "Home Page Sections",
|
||||
"show-recent": "Show Recent"
|
||||
"all-categories": "모든 카테고리",
|
||||
"card-per-section": "섹션당 카드",
|
||||
"home-page": "홈페이지",
|
||||
"home-page-sections": "홈페이지 섹션",
|
||||
"show-recent": "최근 표시"
|
||||
},
|
||||
"language": "언어",
|
||||
"latest": "Latest",
|
||||
"local-api": "Local API",
|
||||
"locale-settings": "Locale settings",
|
||||
"latest": "가장 최근",
|
||||
"local-api": "로컬 API",
|
||||
"locale-settings": "국가별 설정",
|
||||
"migrations": "마이그레이션",
|
||||
"new-page": "New Page",
|
||||
"new-page": "새 페이지",
|
||||
"notify": "알림",
|
||||
"organize": "Organize",
|
||||
"page-name": "Page Name",
|
||||
@@ -1420,5 +1428,13 @@
|
||||
"is-like": "is like",
|
||||
"is-not-like": "is not like"
|
||||
}
|
||||
},
|
||||
"validators": {
|
||||
"required": "This Field is Required",
|
||||
"invalid-email": "Email Must Be Valid",
|
||||
"invalid-url": "Must Be A Valid URL",
|
||||
"no-whitespace": "No Whitespace Allowed",
|
||||
"min-length": "Must Be At Least {min} Characters",
|
||||
"max-length": "Must Be At Most {max} Characters"
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user