Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b9dcf95f9 | ||
|
|
e82020b7e0 | ||
|
|
cfa5c9606d | ||
|
|
951f92e1ba | ||
|
|
8a8ee40f4f | ||
|
|
9d9de3aa77 | ||
|
|
bee7a910b7 | ||
|
|
7f03b1bea8 | ||
|
|
d6cd5df449 | ||
|
|
cc2b53a211 | ||
|
|
5936c919c4 | ||
|
|
00bc9a15ec | ||
|
|
8154ee548a | ||
|
|
591bf9d98f | ||
|
|
f202b1f922 | ||
|
|
17b2e37e4e | ||
|
|
0ec8087ac6 | ||
|
|
e580d6f904 | ||
|
|
56d9cafb68 | ||
|
|
32c864c703 | ||
|
|
37280a3da0 | ||
|
|
7f850fba98 | ||
|
|
b40f201430 | ||
|
|
a0d796551c |
38
.github/ISSUE_TEMPLATE/v1-task.yaml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
name: v1.0.0b Task
|
||||||
|
description: "CONTRIBUTORS ONLY: Submit a Task that needs to be completed"
|
||||||
|
title: "[v1.0.0b] [Task] - TASK DESCRIPTION"
|
||||||
|
labels:
|
||||||
|
- task
|
||||||
|
- v1
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for your interest in Mealie! 🚀
|
||||||
|
|
||||||
|
This is a place for Mealie contributors to find tasks that need to get done around the repository. Tasks are different than issues as they are generally related to providing a new feature or improve an existing feature. They are _generally_ not related to an issue.
|
||||||
|
|
||||||
|
**DO NOT** create a task unless
|
||||||
|
- You are a contributors who has prior approval via discord/discussions
|
||||||
|
- You have otherwise been given approval to post the tasks
|
||||||
|
|
||||||
|
Otherwise, your post will be closed/deleted.
|
||||||
|
|
||||||
|
**Interested in Taking This?**
|
||||||
|
|
||||||
|
If you're interested in completing this tasks and it hasn't already been taken, comment below and to let others know you're working on it. As you work through the task, I ask that you submit a draft pull request as soon as possible, and tag this issue so we can all collaborate as best as possible.
|
||||||
|
- type: textarea
|
||||||
|
id: problem
|
||||||
|
attributes:
|
||||||
|
label: What is the problem this task addresses?
|
||||||
|
placeholder: A clear and concise description of what the problem this task will address.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: solution
|
||||||
|
attributes:
|
||||||
|
label: Proposed/Possible Solution(s)?
|
||||||
|
placeholder: Provide as much context around the idea as possible with potential files and roadblocks that may come up
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
9
.github/workflows/dockerbuild.release.yml
vendored
@@ -54,3 +54,12 @@ jobs:
|
|||||||
docker build --push \
|
docker build --push \
|
||||||
--tag hkotel/mealie:${{ steps.mealie_version.outputs.tag }} \
|
--tag hkotel/mealie:${{ steps.mealie_version.outputs.tag }} \
|
||||||
--platform linux/amd64,linux/arm64 .
|
--platform linux/amd64,linux/arm64 .
|
||||||
|
#
|
||||||
|
# Release Discord Notification
|
||||||
|
#
|
||||||
|
- name: Discord notification
|
||||||
|
env:
|
||||||
|
DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }}
|
||||||
|
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/hay-kot/mealie/releases/tag/{{ EVENT_PAYLOAD.release.tag_name }}'
|
||||||
1
.github/workflows/test-all.yml
vendored
@@ -57,6 +57,7 @@ jobs:
|
|||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
|
sudo apt-get install libsasl2-dev libldap2-dev libssl-dev
|
||||||
poetry install
|
poetry install
|
||||||
poetry add "psycopg2-binary==2.8.6"
|
poetry add "psycopg2-binary==2.8.6"
|
||||||
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
|
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ RUN apt-get update \
|
|||||||
build-essential \
|
build-essential \
|
||||||
libpq-dev \
|
libpq-dev \
|
||||||
libwebp-dev \
|
libwebp-dev \
|
||||||
|
# LDAP Dependencies
|
||||||
|
libsasl2-dev libldap2-dev libssl-dev \
|
||||||
gnupg gnupg2 gnupg1 \
|
gnupg gnupg2 gnupg1 \
|
||||||
debian-keyring \
|
debian-keyring \
|
||||||
debian-archive-keyring \
|
debian-archive-keyring \
|
||||||
|
|||||||
28
docs/docs/changelog/v0.5.4.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# v0.5.4 - Bug Fixes
|
||||||
|
|
||||||
|
**App Version: v0.5.4**
|
||||||
|
|
||||||
|
**Database Version: v0.5.0**
|
||||||
|
|
||||||
|
## Breaking Changes
|
||||||
|
|
||||||
|
!!! error "Breaking Changes"
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
## What's Changed
|
||||||
|
* Add support for new languages by @sephrat in https://github.com/hay-kot/mealie/pull/781
|
||||||
|
* Allow arrow keys to function when SearchDialog is not open by @asymworks in https://github.com/hay-kot/mealie/pull/777
|
||||||
|
* Use firefox user agent when making requests by @cadamswaite in https://github.com/hay-kot/mealie/pull/780
|
||||||
|
* Improve the SWAG Community Guide by @BryceStevenWilley in https://github.com/hay-kot/mealie/pull/793
|
||||||
|
* New Crowdin updates by @hay-kot in https://github.com/hay-kot/mealie/pull/818
|
||||||
|
* Add LDAP authentication support (v2, onto dev) by @dvdkon in https://github.com/hay-kot/mealie/pull/803
|
||||||
|
* Auto backup is now disabled by default. Enable it by setting the AUTO_BACKUP_ENABLED env variable to true.
|
||||||
|
|
||||||
|
|
||||||
|
## New Contributors
|
||||||
|
* @asymworks made their first contribution in https://github.com/hay-kot/mealie/pull/777
|
||||||
|
* @dvdkon made their first contribution in https://github.com/hay-kot/mealie/pull/803
|
||||||
|
|
||||||
|
**Full Changelog**: https://github.com/hay-kot/mealie/compare/v0.5.3...v0.5.4
|
||||||
|
|
||||||
31
docs/docs/changelog/v0.5.5.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# v0.5.5 - Bug Fixes
|
||||||
|
|
||||||
|
**App Version: v0.5.5**
|
||||||
|
|
||||||
|
**Database Version: v0.5.0**
|
||||||
|
|
||||||
|
## Breaking Changes
|
||||||
|
|
||||||
|
!!! error "Breaking Changes"
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
## What's Changed
|
||||||
|
* Allow schema to give images as dict by @cadamswaite in https://github.com/hay-kot/mealie/pull/859
|
||||||
|
* New Crowdin updates by @hay-kot in https://github.com/hay-kot/mealie/pull/854
|
||||||
|
* White background favicons-2 by @cadamswaite in https://github.com/hay-kot/mealie/pull/860
|
||||||
|
* Add support for fr-CA language by @sephrat in https://github.com/hay-kot/mealie/pull/865
|
||||||
|
* New Crowdin updates by @hay-kot in https://github.com/hay-kot/mealie/pull/886
|
||||||
|
* Adjusts the image view from height to min-height by @MidnightRising in https://github.com/hay-kot/mealie/pull/908
|
||||||
|
* Trims URL when importing a recipe by @MidnightRising in https://github.com/hay-kot/mealie/pull/909
|
||||||
|
* New Crowdin updates by @hay-kot in https://github.com/hay-kot/mealie/pull/930
|
||||||
|
* remove leading and trailing whitespaces from bulk add entries by @StevenMassaro in https://github.com/hay-kot/mealie/pull/921
|
||||||
|
* add a line to the docs that clarifies that the run.sh file must have LF line endings by @StevenMassaro in https://github.com/hay-kot/mealie/pull/922
|
||||||
|
* Fix version number for 0.5.4 by @fleaz in https://github.com/hay-kot/mealie/pull/957
|
||||||
|
* Bump versions (properly) @hay-kot
|
||||||
|
|
||||||
|
## New Contributors
|
||||||
|
* @StevenMassaro made their first contribution in https://github.com/hay-kot/mealie/pull/921
|
||||||
|
* @fleaz made their first contribution in https://github.com/hay-kot/mealie/pull/957
|
||||||
|
|
||||||
|
**Full Changelog**: https://github.com/hay-kot/mealie/compare/v0.5.4...v0.5.5
|
||||||
@@ -10,6 +10,8 @@ Prerequisites
|
|||||||
|
|
||||||
You can easily start the development stack by running `make docker-dev` in the root of the project directory. This will run and build the docker-compose.dev.yml file.
|
You can easily start the development stack by running `make docker-dev` in the root of the project directory. This will run and build the docker-compose.dev.yml file.
|
||||||
|
|
||||||
|
On Windows, the `mealie/run.sh` file must have LF line endings, or the mealie-api container will fail to start with the error: `/app/mealie/run.sh: not found`.
|
||||||
|
|
||||||
## Without Docker
|
## Without Docker
|
||||||
Prerequisites
|
Prerequisites
|
||||||
|
|
||||||
|
|||||||
@@ -4,89 +4,96 @@
|
|||||||
This guide was submitted by a community member. Find something wrong? Submit a PR to get it fixed!
|
This guide was submitted by a community member. Find something wrong? Submit a PR to get it fixed!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
To make the setup of a Reverse Proxy much easier, Linuxserver.io developed [SWAG](https://github.com/linuxserver/docker-swag)
|
To make the setup of a Reverse Proxy much easier, Linuxserver.io developed [SWAG](https://github.com/linuxserver/docker-swag)
|
||||||
SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx web server and reverse proxy with PHP support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention.
|
SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx web server and reverse proxy with PHP support and a built-in certbot client that automates free TLS server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention.
|
||||||
|
|
||||||
## Step 1: Get a domain
|
## Step 1: Get a domain
|
||||||
|
|
||||||
The first step is to grab a dynamic DNS if you don't have your own subdomain already. You can get this from for example [DuckDNS](https://www.duckdns.org).
|
The first step is to grab a dynamic DNS if you don't have your own subdomain already. You can get this from for example [DuckDNS](https://www.duckdns.org).
|
||||||
|
If you already own a domain, you'll need to create an `A` record that points to the machine that SWAG is running on. See
|
||||||
|
the [SWAG documentation](https://docs.linuxserver.io/general/swag#create-container-via-http-validation) for more details.
|
||||||
|
|
||||||
## Step 2: Set-up SWAG
|
## Step 2: Set-up SWAG
|
||||||
|
|
||||||
Then you will need to set up SWAG, the variables of the docker-compose are explained on the Github page of [SWAG](https://github.com/linuxserver/docker-swag).
|
Then you will need to set up SWAG, the variables of the docker-compose are explained on the Github page of [SWAG](https://github.com/linuxserver/docker-swag).
|
||||||
This is an example of how to set it up using duckdns and docker-compose.
|
This is an example of how to set it up using DuckDNS and docker-compose.
|
||||||
|
|
||||||
!!! example "docker-compose.yml"
|
!!! example "docker-compose.yml"
|
||||||
```yaml
|
```yaml
|
||||||
version: "2.1"
|
version: "2.1"
|
||||||
services:
|
services:
|
||||||
swag:
|
swag:
|
||||||
image: ghcr.io/linuxserver/swag
|
image: ghcr.io/linuxserver/swag
|
||||||
container_name: swag
|
container_name: swag
|
||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=1000
|
||||||
- PGID=1000
|
- PGID=1000
|
||||||
- TZ=Europe/Brussels
|
# valid TZs at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||||
- URL=<mydomain.duckdns>
|
- TZ=Europe/Brussels
|
||||||
- SUBDOMAINS=wildcard
|
- URL=<mydomain.duckdns>
|
||||||
- VALIDATION=duckdns
|
- SUBDOMAINS=wildcard
|
||||||
- CERTPROVIDER= #optional
|
- VALIDATION=duckdns
|
||||||
- DNSPLUGIN= #optional
|
- CERTPROVIDER= #optional
|
||||||
- DUCKDNSTOKEN=<duckdnstoken>
|
- DNSPLUGIN= #optional
|
||||||
- EMAIL=<e-mail> #optional
|
- DUCKDNSTOKEN=<duckdnstoken>
|
||||||
- ONLY_SUBDOMAINS=false #optional
|
- EMAIL=<e-mail> #optional
|
||||||
- EXTRA_DOMAINS=<extradomains> #optional
|
- ONLY_SUBDOMAINS=false #optional
|
||||||
- STAGING=false #optional
|
- EXTRA_DOMAINS=<extradomains> #optional
|
||||||
volumes:
|
- STAGING=false #optional
|
||||||
- /etc/config/swag:/config
|
volumes:
|
||||||
ports:
|
- /etc/config/swag:/config
|
||||||
- 443:443
|
ports:
|
||||||
restart: unless-stopped
|
- 443:443
|
||||||
|
# required if VALIDATION=http above, if you aren't using DuckDNS
|
||||||
|
- 80:80
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Don't forget to change the <code>mydomain.duckns</code> into your personal domain and the <code>duckdnstoken</code> into your token and remove the brackets.
|
Don't forget to change the `mydomain.duckns` into your personal domain and the `duckdnstoken` into your token and remove the brackets.
|
||||||
|
|
||||||
|
You can also include the contents of the [mealie docker-compose](mealie/documentation/getting-started/install/#docker-compose-with-sqlite) in the SWAG
|
||||||
|
docker-compose, without the `ports` section under mealie. This allows SWAG and mealie to communicate on the same docker network, without
|
||||||
|
making mealie visible to other applications on your machine.
|
||||||
|
|
||||||
## Step 3: Change the config files
|
## Step 3: Change the config files
|
||||||
|
|
||||||
Navigate to the config folder of SWAG and head to <code>proxy-confs</code>. If you used the example above, you should navigate to: <code>/etc/config/swag/nginx/proxy-confs/</code>.
|
Navigate to the config folder of SWAG and head to `proxy-confs`. If you used the example above, you should navigate to: `/etc/config/swag/nginx/proxy-confs/`.
|
||||||
There are a lot of preconfigured files to use for different apps such as radarr, sonarr, overseerr, ...
|
There are a lot of preconfigured files to use for different apps such as radarr, sonarr, overseerr, ...
|
||||||
|
|
||||||
To use the bundled configuration file, simply rename <code>mealie.subdomain.conf.sample</code> in the proxy-confs folder to <code>mealie.subdomain.conf</code>.
|
To use the bundled configuration file, simply rename `mealie.subdomain.conf.sample` in the proxy-confs folder to `mealie.subdomain.conf`.
|
||||||
Alternatively, you can create a new file <code>mealie.subdomain.conf</code> in proxy-confs with the following configuration:
|
Alternatively, you can create a new file `mealie.subdomain.conf` in proxy-confs with the following configuration:
|
||||||
|
|
||||||
!!! example "mealie.subdomain.conf"
|
!!! example "mealie.subdomain.conf"
|
||||||
```yaml
|
```nginx
|
||||||
server {
|
server {
|
||||||
listen 443 ssl http2;
|
listen 443 ssl http2;
|
||||||
listen [::]:443 ssl http2;
|
listen [::]:443 ssl http2;
|
||||||
|
|
||||||
server_name mealie.*;
|
server_name mealie.*;
|
||||||
|
|
||||||
include /config/nginx/ssl.conf;
|
include /config/nginx/ssl.conf;
|
||||||
|
|
||||||
client_max_body_size 0;
|
client_max_body_size 0;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
include /config/nginx/proxy.conf;
|
include /config/nginx/proxy.conf;
|
||||||
include /config/nginx/resolver.conf;
|
include /config/nginx/resolver.conf;
|
||||||
set $upstream_app mealie;
|
set $upstream_app mealie;
|
||||||
set $upstream_port 80;
|
set $upstream_port 80;
|
||||||
set $upstream_proto http;
|
set $upstream_proto http;
|
||||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 4: Port-forward port 443
|
## Step 4: Port-forward port 443
|
||||||
|
|
||||||
Since SWAG allows you to set up a secure connection, you will need to open port 443 on your router for encrypted traffic. This is way more secure than port 80 for http.
|
Since SWAG allows you to set up a secure connection, you will need to open port 443 on your router for encrypted traffic. This is way more secure than port 80 for http. For more information about using TLS on port 443, see [SWAG's documentation](https://docs.linuxserver.io/general/swag#cert-provider-lets-encrypt-vs-zerossl) on cert providers and port forwarding.
|
||||||
|
|
||||||
## Step 5: Restart SWAG
|
## Step 5: Restart SWAG
|
||||||
|
|
||||||
When you change anything in the config of Nginx, you will need to restart the container using <code>docker restart swag</code>.
|
When you change anything in the config of Nginx, you will need to restart the container using `docker restart swag`.
|
||||||
If everything went well, you can now access mealie on the subdomain you configured: mealie.mydomain.duckdns.org
|
If everything went well, you can now access mealie on the subdomain you configured: `mealie.mydomain.duckdns.org`
|
||||||
|
|||||||
@@ -128,12 +128,17 @@ services:
|
|||||||
| POSTGRES_PORT | 5432 | Postgres database port |
|
| POSTGRES_PORT | 5432 | Postgres database port |
|
||||||
| POSTGRES_DB | mealie | Postgres database name |
|
| POSTGRES_DB | mealie | Postgres database name |
|
||||||
| TOKEN_TIME | 2 | The time in hours that a login/auth token is valid |
|
| TOKEN_TIME | 2 | The time in hours that a login/auth token is valid |
|
||||||
|
| LDAP_AUTH_ENABLED | False | Authenticate via an external LDAP server in addidion to built-in Mealie auth |
|
||||||
|
| LDAP_SERVER_URL | None | LDAP server URL (e.g. ldap://ldap.example.com) |
|
||||||
|
| LDAP_BIND_TEMPLATE | None | Templated DN for users, `{}` will be replaced with the username (e.g. `cn={},dc=example,dc=com`) |
|
||||||
|
| LDAP_ADMIN_FILTER | None | Optional LDAP filter, which tells Mealie the LDAP user is an admin (e.g. `(memberOf=cn=admins,dc=example,dc=com)`) |
|
||||||
| RECIPE_PUBLIC | True | Default Recipe Settings - Make Recipe Public |
|
| RECIPE_PUBLIC | True | Default Recipe Settings - Make Recipe Public |
|
||||||
| RECIPE_SHOW_NUTRITION | True | Default Recipe Settings - Show Recipe Nutrition |
|
| RECIPE_SHOW_NUTRITION | True | Default Recipe Settings - Show Recipe Nutrition |
|
||||||
| RECIPE_SHOW_ASSETS | True | Default Recipe Settings - Show Recipe Assets |
|
| RECIPE_SHOW_ASSETS | True | Default Recipe Settings - Show Recipe Assets |
|
||||||
| RECIPE_LANDSCAPE_VIEW | True | Default Recipe Settings - Set Landscape View |
|
| RECIPE_LANDSCAPE_VIEW | True | Default Recipe Settings - Set Landscape View |
|
||||||
| RECIPE_DISABLE_COMMENTS | False | Default Recipe Settings - Disable Comments |
|
| RECIPE_DISABLE_COMMENTS | False | Default Recipe Settings - Disable Comments |
|
||||||
| RECIPE_DISABLE_AMOUNT | False | Default Recipe Settings - Disable Amount |
|
| RECIPE_DISABLE_AMOUNT | False | Default Recipe Settings - Disable Amount |
|
||||||
|
| AUTO_BACKUP_ENABLED | False | Disable/Enable Mealie's Auto Backup Function |
|
||||||
| API_PORT | 9000 | The port exposed by backend API. **Do not change this if you're running in Docker** |
|
| 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. |
|
| 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 |
|
| TZ | UTC | Must be set to get correct date/time on the server |
|
||||||
|
|||||||
@@ -94,7 +94,9 @@ nav:
|
|||||||
- Style Guide: "contributors/developers-guide/style-guide.md"
|
- Style Guide: "contributors/developers-guide/style-guide.md"
|
||||||
- Development Road Map: "roadmap.md"
|
- Development Road Map: "roadmap.md"
|
||||||
- Change Log:
|
- Change Log:
|
||||||
- v0.5.3 - Bug Fixes: "changelog/v0.5.3.md"
|
- v0.5.5 Bug Fixes: "changelog/v0.5.5.md"
|
||||||
|
- v0.5.4 Bug Fixes: "changelog/v0.5.4.md"
|
||||||
|
- v0.5.3 Bug Fixes: "changelog/v0.5.3.md"
|
||||||
- v0.5.2 Misc Updates: "changelog/v0.5.2.md"
|
- v0.5.2 Misc Updates: "changelog/v0.5.2.md"
|
||||||
- v0.5.1 Bug Fixes: "changelog/v0.5.1.md"
|
- v0.5.1 Bug Fixes: "changelog/v0.5.1.md"
|
||||||
- v0.5.0 General Upgrades: "changelog/v0.5.0.md"
|
- v0.5.0 General Upgrades: "changelog/v0.5.0.md"
|
||||||
|
|||||||
3
frontend/package-lock.json
generated
@@ -5,7 +5,6 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "frontend",
|
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adapttive/vue-markdown": "^4.0.1",
|
"@adapttive/vue-markdown": "^4.0.1",
|
||||||
@@ -20542,7 +20541,6 @@
|
|||||||
"integrity": "sha512-pM7CR3yXB6L8Gfn6EmX7FLNE3+V/15I3o33GkSNsWvgsMp6HVGXKkXgojrcfUUauyL1LZOdvTmu4enU2RePGHw==",
|
"integrity": "sha512-pM7CR3yXB6L8Gfn6EmX7FLNE3+V/15I3o33GkSNsWvgsMp6HVGXKkXgojrcfUUauyL1LZOdvTmu4enU2RePGHw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/core": "^7.11.0",
|
|
||||||
"@babel/helper-compilation-targets": "^7.9.6",
|
"@babel/helper-compilation-targets": "^7.9.6",
|
||||||
"@babel/helper-module-imports": "^7.8.3",
|
"@babel/helper-module-imports": "^7.8.3",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||||
@@ -20555,7 +20553,6 @@
|
|||||||
"@vue/babel-plugin-jsx": "^1.0.3",
|
"@vue/babel-plugin-jsx": "^1.0.3",
|
||||||
"@vue/babel-preset-jsx": "^1.2.4",
|
"@vue/babel-preset-jsx": "^1.2.4",
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||||
"core-js": "^3.6.5",
|
|
||||||
"core-js-compat": "^3.6.5",
|
"core-js-compat": "^3.6.5",
|
||||||
"semver": "^6.1.0"
|
"semver": "^6.1.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
"vuex-persistedstate": "^4.0.0-beta.3"
|
"vuex-persistedstate": "^4.0.0-beta.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typeface-roboto": "^1.1.13",
|
|
||||||
"@intlify/vue-i18n-loader": "^1.1.0",
|
"@intlify/vue-i18n-loader": "^1.1.0",
|
||||||
"@mdi/font": "^5.9.55",
|
"@mdi/font": "^5.9.55",
|
||||||
"@mdi/js": "^5.9.55",
|
"@mdi/js": "^5.9.55",
|
||||||
@@ -40,6 +39,7 @@
|
|||||||
"preload-webpack-plugin": "^2.3.0",
|
"preload-webpack-plugin": "^2.3.0",
|
||||||
"sass": "^1.34.1",
|
"sass": "^1.34.1",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "^8.0.2",
|
||||||
|
"typeface-roboto": "^1.1.13",
|
||||||
"vue-cli-plugin-i18n": "~1.0.1",
|
"vue-cli-plugin-i18n": "~1.0.1",
|
||||||
"vue-cli-plugin-vuetify": "^2.4.1",
|
"vue-cli-plugin-vuetify": "^2.4.1",
|
||||||
"vue-cli-plugin-webpack-bundle-analyzer": "^4.0.0",
|
"vue-cli-plugin-webpack-bundle-analyzer": "^4.0.0",
|
||||||
@@ -72,4 +72,4 @@
|
|||||||
"last 2 versions",
|
"last 2 versions",
|
||||||
"not dead"
|
"not dead"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 574 B After Width: | Height: | Size: 883 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 2.5 KiB |
@@ -1,3 +1,28 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256" version="1.1">
|
<?xml version="1.0" standalone="no"?>
|
||||||
<path d="M 162.083 54.642 C 148.745 68.272, 137.170 80.703, 136.362 82.266 C 133.689 87.435, 133.522 94.130, 135.929 99.573 C 137.122 102.269, 139.070 105.510, 140.258 106.775 L 142.418 109.074 90.974 160.526 L 39.529 211.979 46.999 219.499 L 54.470 227.020 91.235 190.265 L 128 153.510 164.765 190.265 L 201.530 227.020 209 219.500 L 216.470 211.980 179.725 175.225 L 142.980 138.470 150.320 131.178 C 156.858 124.685, 157.808 124.063, 159.001 125.501 C 162.066 129.195, 168.873 132.163, 174.392 132.213 C 183.508 132.295, 186.374 130.174, 212.477 104.038 L 236.454 80.030 231.501 75.001 L 226.548 69.973 209.288 87.212 L 192.027 104.452 187 99.500 L 181.973 94.548 199.212 77.288 L 216.452 60.027 211.500 55 L 206.548 49.973 189.288 67.212 L 172.027 84.452 167 79.500 L 161.973 74.548 179.225 57.275 L 196.477 40.001 191.406 34.930 L 186.335 29.859 162.083 54.642 M 38.429 41.250 C 31.557 49.376, 28.011 62.815, 29.835 73.824 C 31.955 86.615, 34.508 90.093, 61.720 117.253 L 86.520 142.005 101.501 126.999 L 116.482 111.993 79.496 74.996 C 59.154 54.648, 42.210 38, 41.844 38 C 41.478 38, 39.941 39.462, 38.429 41.250" stroke="none" fill="black" fill-rule="evenodd"/>
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
</svg>
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<metadata>
|
||||||
|
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
||||||
|
</metadata>
|
||||||
|
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M4948 6348 c-662 -677 -956 -982 -1123 -1168 -32 -36 -62 -67 -65
|
||||||
|
-70 -3 -3 -31 -35 -62 -71 -127 -151 -157 -391 -77 -600 26 -68 117 -233 137
|
||||||
|
-249 4 -3 25 -25 47 -48 l40 -42 -1679 -1679 -1678 -1678 244 -246 243 -247
|
||||||
|
1200 1200 1199 1199 1192 -1192 c656 -655 1197 -1193 1202 -1195 10 -3 473
|
||||||
|
459 480 478 2 5 -534 547 -1191 1204 l-1194 1195 185 183 c250 248 262 258
|
||||||
|
296 258 11 0 41 -19 66 -43 139 -131 331 -199 538 -190 160 6 273 63 475 236
|
||||||
|
132 114 199 179 845 822 l642 640 -161 163 c-88 90 -162 162 -164 160 -3 -1
|
||||||
|
-256 -254 -564 -561 l-560 -559 -160 158 c-89 87 -161 162 -161 165 0 4 251
|
||||||
|
259 559 567 l558 560 -159 161 c-87 89 -161 161 -164 161 -3 0 -258 -252 -566
|
||||||
|
-559 l-560 -560 -164 162 -164 162 560 560 c308 308 560 563 560 566 0 5 -194
|
||||||
|
202 -292 297 l-34 32 -326 -332z"/>
|
||||||
|
<path d="M489 6349 c-108 -115 -190 -257 -254 -440 -20 -57 -35 -104 -34 -104
|
||||||
|
1 0 -3 -22 -9 -50 -42 -181 -46 -400 -11 -568 72 -343 178 -493 781 -1102 199
|
||||||
|
-202 1018 -1020 1054 -1055 6 -5 974 962 974 973 0 9 -1704 1713 -2130 2130
|
||||||
|
-156 152 -291 277 -299 277 -9 0 -41 -27 -72 -61z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -3,77 +3,29 @@
|
|||||||
"short_name": "Mealie",
|
"short_name": "Mealie",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "./img/icons/android-chrome-192x192.png",
|
"src": "./img/icons/android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png",
|
||||||
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "./img/icons/android-chrome-512x512.png",
|
"src": "./img/icons/android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png",
|
||||||
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "./img/icons/android-chrome-maskable-192x192.png",
|
"src": "./img/icons/android-chrome-maskable-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "./img/icons/android-chrome-maskable-512x512.png",
|
"src": "./img/icons/android-chrome-maskable-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
},
|
}
|
||||||
{
|
|
||||||
"src": "./img/icons/apple-touch-icon-60x60.png",
|
|
||||||
"sizes": "60x60",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "./img/icons/apple-touch-icon-76x76.png",
|
|
||||||
"sizes": "76x76",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "./img/icons/apple-touch-icon-120x120.png",
|
|
||||||
"sizes": "120x120",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "./img/icons/apple-touch-icon-152x152.png",
|
|
||||||
"sizes": "152x152",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "./img/icons/apple-touch-icon-180x180.png",
|
|
||||||
"sizes": "180x180",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "./img/icons/apple-touch-icon.png",
|
|
||||||
"sizes": "180x180",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "./img/icons/favicon-16x16.png",
|
|
||||||
"sizes": "16x16",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "./img/icons/favicon-32x32.png",
|
|
||||||
"sizes": "32x32",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "./img/icons/msapplication-icon-144x144.png",
|
|
||||||
"sizes": "144x144",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "./img/icons/mstile-150x150.png",
|
|
||||||
"sizes": "150x150",
|
|
||||||
"type": "image/png"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"start_url": ".",
|
"start_url": ".",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<v-main>
|
<v-main>
|
||||||
<v-banner v-if="demo" sticky>
|
<v-banner v-if="demo" sticky>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<b> This is a Demo of the v0.5.4 (BETA) </b> | Username: changeme@email.com | Password: demo
|
<b> This is a Demo of the v0.5.6 (BETA) </b> | Username: changeme@email.com | Password: demo
|
||||||
</div>
|
</div>
|
||||||
</v-banner>
|
</v-banner>
|
||||||
<GlobalSnackbar />
|
<GlobalSnackbar />
|
||||||
@@ -136,4 +136,3 @@ export default {
|
|||||||
scrollbar-color: transparent transparent;
|
scrollbar-color: transparent transparent;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return split;
|
return split.map((element) => element.trim());
|
||||||
},
|
},
|
||||||
save() {
|
save() {
|
||||||
this.$emit("bulk-data", this.splitText());
|
this.$emit("bulk-data", this.splitText());
|
||||||
|
|||||||
@@ -136,16 +136,18 @@ export default {
|
|||||||
this.$emit(SELECTED_EVENT, recipe);
|
this.$emit(SELECTED_EVENT, recipe);
|
||||||
},
|
},
|
||||||
onUpDown(e) {
|
onUpDown(e) {
|
||||||
if (e.keyCode === 38) {
|
if (this.dialog) {
|
||||||
e.preventDefault();
|
if (e.keyCode === 38) {
|
||||||
this.selectedIndex--;
|
e.preventDefault();
|
||||||
} else if (e.keyCode === 40) {
|
this.selectedIndex--;
|
||||||
e.preventDefault();
|
} else if (e.keyCode === 40) {
|
||||||
this.selectedIndex++;
|
e.preventDefault();
|
||||||
} else {
|
this.selectedIndex++;
|
||||||
return;
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.selectRecipe();
|
||||||
}
|
}
|
||||||
this.selectRecipe();
|
|
||||||
},
|
},
|
||||||
resetSelected() {
|
resetSelected() {
|
||||||
this.searchString = "";
|
this.searchString = "";
|
||||||
@@ -169,4 +171,4 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style >
|
<style >
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
recipeURL: {
|
recipeURL: {
|
||||||
set(recipe_import_url) {
|
set(recipe_import_url) {
|
||||||
|
recipe_import_url = recipe_import_url.trim()
|
||||||
this.$router.replace({ query: { ...this.$route.query, recipe_import_url } });
|
this.$router.replace({ query: { ...this.$route.query, recipe_import_url } });
|
||||||
},
|
},
|
||||||
get() {
|
get() {
|
||||||
@@ -234,7 +235,7 @@ export default {
|
|||||||
this.processing = false;
|
this.processing = false;
|
||||||
},
|
},
|
||||||
isValidWebUrl(url) {
|
isValidWebUrl(url) {
|
||||||
let regEx = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,256}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$/gm;
|
let regEx = /^\s*https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,256}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)\s*$/gm;
|
||||||
return regEx.test(url) ? true : this.$t('new-recipe.must-be-a-valid-url');
|
return regEx.test(url) ? true : this.$t('new-recipe.must-be-a-valid-url');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
21
frontend/src/locales/dateTimeFormats/fr-CA.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"short": {
|
||||||
|
"month": "short",
|
||||||
|
"day": "numeric",
|
||||||
|
"weekday": "long"
|
||||||
|
},
|
||||||
|
"medium": {
|
||||||
|
"month": "long",
|
||||||
|
"day": "numeric",
|
||||||
|
"weekday": "long",
|
||||||
|
"year": "numeric"
|
||||||
|
},
|
||||||
|
"long": {
|
||||||
|
"year": "numeric",
|
||||||
|
"month": "long",
|
||||||
|
"day": "numeric",
|
||||||
|
"weekday": "long",
|
||||||
|
"hour": "numeric",
|
||||||
|
"minute": "numeric"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -123,8 +123,8 @@
|
|||||||
"token": "Token",
|
"token": "Token",
|
||||||
"tuesday": "Tirsdag",
|
"tuesday": "Tirsdag",
|
||||||
"type": "Type",
|
"type": "Type",
|
||||||
"update": "Opdater",
|
"update": "Gem",
|
||||||
"updated": "Opdateret",
|
"updated": "Ændret",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
"view": "Se",
|
"view": "Se",
|
||||||
@@ -137,7 +137,7 @@
|
|||||||
"cannot-delete-group-with-users": "En gruppe med brugere i kan ikke blive slettet",
|
"cannot-delete-group-with-users": "En gruppe med brugere i kan ikke blive slettet",
|
||||||
"confirm-group-deletion": "Bekræft sletning af gruppe",
|
"confirm-group-deletion": "Bekræft sletning af gruppe",
|
||||||
"create-group": "Opret gruppe",
|
"create-group": "Opret gruppe",
|
||||||
"error-updating-group": "Fejl ved opdatering af gruppe",
|
"error-updating-group": "Fejl ved ændring af gruppe",
|
||||||
"group": "Gruppe",
|
"group": "Gruppe",
|
||||||
"group-deleted": "Gruppe slettet",
|
"group-deleted": "Gruppe slettet",
|
||||||
"group-deletion-failed": "Sletning af gruppe fejlede",
|
"group-deletion-failed": "Sletning af gruppe fejlede",
|
||||||
@@ -168,8 +168,8 @@
|
|||||||
"mealplan-deleted": "Madplan slettet",
|
"mealplan-deleted": "Madplan slettet",
|
||||||
"mealplan-deletion-failed": "Sletning af madplan fejlede",
|
"mealplan-deletion-failed": "Sletning af madplan fejlede",
|
||||||
"mealplan-settings": "Madplansindstillinger",
|
"mealplan-settings": "Madplansindstillinger",
|
||||||
"mealplan-update-failed": "Opdatering af madplanen fejlede",
|
"mealplan-update-failed": "Ændring af madplanen fejlede",
|
||||||
"mealplan-updated": "Madplanen blev opdateret",
|
"mealplan-updated": "Madplanen blev ændret",
|
||||||
"no-meal-plan-defined-yet": "Ingen madplan er defineret",
|
"no-meal-plan-defined-yet": "Ingen madplan er defineret",
|
||||||
"no-meal-planned-for-today": "Ingen ret er planlagt til i dag",
|
"no-meal-planned-for-today": "Ingen ret er planlagt til i dag",
|
||||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Kun opskrifter med disse kategorier vil blive brugt i madplaner",
|
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Kun opskrifter med disse kategorier vil blive brugt i madplaner",
|
||||||
@@ -248,7 +248,7 @@
|
|||||||
"milligrams": "milligram",
|
"milligrams": "milligram",
|
||||||
"new-key-name": "Nyt nøglenavn",
|
"new-key-name": "Nyt nøglenavn",
|
||||||
"no-white-space-allowed": "Mellemrum er ikke tilladt",
|
"no-white-space-allowed": "Mellemrum er ikke tilladt",
|
||||||
"note": "Bemærk",
|
"note": "Bemærkninger",
|
||||||
"nutrition": "Ernæring",
|
"nutrition": "Ernæring",
|
||||||
"object-key": "Objektnøgle",
|
"object-key": "Objektnøgle",
|
||||||
"object-value": "Objektværdi",
|
"object-value": "Objektværdi",
|
||||||
@@ -261,7 +261,7 @@
|
|||||||
"recipe-creation-failed": "Oprettelse af opskrift fejlede",
|
"recipe-creation-failed": "Oprettelse af opskrift fejlede",
|
||||||
"recipe-deleted": "Opskrift slettet",
|
"recipe-deleted": "Opskrift slettet",
|
||||||
"recipe-image": "Opskriftsbillede",
|
"recipe-image": "Opskriftsbillede",
|
||||||
"recipe-image-updated": "Opskriftsbillede opdateret",
|
"recipe-image-updated": "Opskriftsbillede ændret",
|
||||||
"recipe-name": "Opskriftens navn",
|
"recipe-name": "Opskriftens navn",
|
||||||
"recipe-settings": "Opskriftsindstillinger",
|
"recipe-settings": "Opskriftsindstillinger",
|
||||||
"recipe-update-failed": "Opdatering af opskrift fejlede",
|
"recipe-update-failed": "Opdatering af opskrift fejlede",
|
||||||
|
|||||||
489
frontend/src/locales/messages/fr-CA.json
Normal file
@@ -0,0 +1,489 @@
|
|||||||
|
{
|
||||||
|
"about": {
|
||||||
|
"about": "À propos",
|
||||||
|
"about-mealie": "À propos de Mealie",
|
||||||
|
"api-docs": "Documentation de l'API",
|
||||||
|
"api-port": "Port de l'API",
|
||||||
|
"application-mode": "Mode de l'application",
|
||||||
|
"database-type": "Type de base de données",
|
||||||
|
"database-url": "URL de la base de données",
|
||||||
|
"default-group": "Groupe par défaut",
|
||||||
|
"demo": "Oui",
|
||||||
|
"demo-status": "Mode démo",
|
||||||
|
"development": "Développement",
|
||||||
|
"docs": "Documentation",
|
||||||
|
"download-log": "Télécharger les logs",
|
||||||
|
"download-recipe-json": "Dernier JSON récupéré",
|
||||||
|
"github": "GitHub",
|
||||||
|
"log-lines": "Lignes de log",
|
||||||
|
"not-demo": "Non",
|
||||||
|
"portfolio": "Portfolio",
|
||||||
|
"production": "Production",
|
||||||
|
"support": "Soutenir",
|
||||||
|
"version": "Version"
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"assets": "Ressources",
|
||||||
|
"code": "Code",
|
||||||
|
"file": "Fichier",
|
||||||
|
"image": "Image",
|
||||||
|
"new-asset": "Nouvelle ressource",
|
||||||
|
"pdf": "PDF",
|
||||||
|
"recipe": "Recette",
|
||||||
|
"show-assets": "Afficher les ressources"
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"category-created": "Catégorie créée",
|
||||||
|
"category-creation-failed": "La création de la catégorie a échoué",
|
||||||
|
"category-deleted": "Catégorie supprimée",
|
||||||
|
"category-deletion-failed": "La suppression de la catégorie a échoué",
|
||||||
|
"category-filter": "Filtre par catégories",
|
||||||
|
"category-update-failed": "La mise à jour de la catégorie a échoué",
|
||||||
|
"category-updated": "Catégorie mise à jour",
|
||||||
|
"uncategorized-count": "{count} non catégorisée|{count} non catégorisées"
|
||||||
|
},
|
||||||
|
"events": {
|
||||||
|
"apprise-url": "URL apprise",
|
||||||
|
"database": "Base de données",
|
||||||
|
"delete-event": "Supprimer l’évènement",
|
||||||
|
"new-notification-form-description": "Mealie utilise la bibliothèque apprise pour générer des notifications. Elle propose de nombreux services à utiliser pour les notifications. Consultez leur wiki pour un guide complet sur la façon de créer l'URL de votre service. Si disponible, sélectionner le type de votre notification peut inclure des fonctionnalités supplémentaires.",
|
||||||
|
"new-version": "Nouvelle version disponible!",
|
||||||
|
"notification": "Notification",
|
||||||
|
"refresh": "Rafraîchir",
|
||||||
|
"scheduled": "Planifié",
|
||||||
|
"something-went-wrong": "Une erreur s'est produite!",
|
||||||
|
"subscribed-events": "Évènements suivis",
|
||||||
|
"test-message-sent": "Message de test envoyé"
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"cancel": "Annuler",
|
||||||
|
"clear": "Effacer",
|
||||||
|
"close": "Fermer",
|
||||||
|
"confirm": "Confirmer",
|
||||||
|
"confirm-delete-generic": "Voulez-vous vraiment supprimer ceci?",
|
||||||
|
"copied": "Copié",
|
||||||
|
"create": "Créer",
|
||||||
|
"created": "Créé",
|
||||||
|
"custom": "Personnalisé",
|
||||||
|
"dashboard": "Tableau de bord",
|
||||||
|
"delete": "Supprimer",
|
||||||
|
"disabled": "Désactivé",
|
||||||
|
"download": "Télécharger",
|
||||||
|
"edit": "Modifier",
|
||||||
|
"enabled": "Activé",
|
||||||
|
"exception": "Exception",
|
||||||
|
"failed-count": "Échec : {count}",
|
||||||
|
"failure-uploading-file": "Échec de l'envoi du fichier",
|
||||||
|
"favorites": "Favoris",
|
||||||
|
"field-required": "Champ obligatoire",
|
||||||
|
"file-folder-not-found": "Fichier/dossier introuvable",
|
||||||
|
"file-uploaded": "Fichier envoyé",
|
||||||
|
"filter": "Filtrer",
|
||||||
|
"friday": "Vendredi",
|
||||||
|
"general": "Général",
|
||||||
|
"get": "Envoyer",
|
||||||
|
"home": "Page d'accueil",
|
||||||
|
"image": "Image",
|
||||||
|
"image-upload-failed": "Le téléchargement de l'image a échoué",
|
||||||
|
"import": "Importer",
|
||||||
|
"json": "JSON",
|
||||||
|
"keyword": "Mot-clé",
|
||||||
|
"link-copied": "Lien copié",
|
||||||
|
"loading-recipes": "Chargement des recettes",
|
||||||
|
"monday": "Lundi",
|
||||||
|
"name": "Nom",
|
||||||
|
"new": "Nouveau",
|
||||||
|
"no": "Non",
|
||||||
|
"no-recipe-found": "Aucune recette trouvée",
|
||||||
|
"ok": "OK",
|
||||||
|
"options": "Options :",
|
||||||
|
"print": "Imprimer",
|
||||||
|
"random": "Aléatoire",
|
||||||
|
"rating": "Note",
|
||||||
|
"recent": "Récent",
|
||||||
|
"recipe": "Recette",
|
||||||
|
"recipes": "Recettes",
|
||||||
|
"rename-object": "Renommer {0}",
|
||||||
|
"reset": "Réinitialiser",
|
||||||
|
"saturday": "Samedi",
|
||||||
|
"save": "Sauvegarder",
|
||||||
|
"settings": "Paramètres",
|
||||||
|
"share": "Partager",
|
||||||
|
"shuffle": "Aléatoire",
|
||||||
|
"sort": "Trier",
|
||||||
|
"sort-alphabetically": "Alphabétique",
|
||||||
|
"status": "Statut",
|
||||||
|
"submit": "Importer",
|
||||||
|
"success-count": "Succès : {count}",
|
||||||
|
"sunday": "Dimanche",
|
||||||
|
"templates": "Modèles :",
|
||||||
|
"test": "Tester",
|
||||||
|
"themes": "Thèmes",
|
||||||
|
"thursday": "Jeudi",
|
||||||
|
"token": "Jeton",
|
||||||
|
"tuesday": "Mardi",
|
||||||
|
"type": "Type",
|
||||||
|
"update": "Mettre à jour",
|
||||||
|
"updated": "Mis à jour",
|
||||||
|
"upload": "Importer",
|
||||||
|
"url": "URL",
|
||||||
|
"view": "Afficher",
|
||||||
|
"wednesday": "Mercredi",
|
||||||
|
"yes": "Oui"
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
"are-you-sure-you-want-to-delete-the-group": "Êtes-vous certain de vouloir supprimer <b>{groupName}<b/>?",
|
||||||
|
"cannot-delete-default-group": "Vous ne pouvez pas supprimer le groupe par défaut",
|
||||||
|
"cannot-delete-group-with-users": "Impossible de supprimer un groupe avec des utilisateurs",
|
||||||
|
"confirm-group-deletion": "Confirmer la suppression du groupe",
|
||||||
|
"create-group": "Créer un groupe",
|
||||||
|
"error-updating-group": "Erreur lors de la mise à jour du groupe",
|
||||||
|
"group": "Groupe",
|
||||||
|
"group-deleted": "Groupe supprimé",
|
||||||
|
"group-deletion-failed": "Échec de la suppression du groupe",
|
||||||
|
"group-id-with-value": "ID groupe : {groupID}",
|
||||||
|
"group-name": "Nom du groupe",
|
||||||
|
"group-not-found": "Groupe non trouvé",
|
||||||
|
"group-with-value": "Groupe : {groupID}",
|
||||||
|
"groups": "Groupes",
|
||||||
|
"manage-groups": "Gérer les groupes",
|
||||||
|
"user-group": "Groupe d'utilisateurs",
|
||||||
|
"user-group-created": "Groupe d'utilisateurs créé",
|
||||||
|
"user-group-creation-failed": "La création du groupe d'utilisateur a échoué"
|
||||||
|
},
|
||||||
|
"meal-plan": {
|
||||||
|
"create-a-new-meal-plan": "Créer un nouveau menu",
|
||||||
|
"dinner-this-week": "Menu de la semaine",
|
||||||
|
"dinner-today": "Menu du jour",
|
||||||
|
"dinner-tonight": "AU MENU CE SOIR",
|
||||||
|
"edit-meal-plan": "Modifier le menu",
|
||||||
|
"end-date": "Date de fin",
|
||||||
|
"group": "Regrouper (Bêta)",
|
||||||
|
"main": "Plat principal",
|
||||||
|
"meal-planner": "Menus",
|
||||||
|
"meal-plans": "Menus",
|
||||||
|
"mealplan-categories": "CATÉGORIES DES MENUS",
|
||||||
|
"mealplan-created": "Menu créé",
|
||||||
|
"mealplan-creation-failed": "La création du menu a échoué",
|
||||||
|
"mealplan-deleted": "Menu supprimé",
|
||||||
|
"mealplan-deletion-failed": "La suppression du menu a échoué",
|
||||||
|
"mealplan-settings": "Paramètres des menus",
|
||||||
|
"mealplan-update-failed": "La mise à jour du menu a échoué",
|
||||||
|
"mealplan-updated": "Menu mis à jour",
|
||||||
|
"no-meal-plan-defined-yet": "Aucun menu planifié",
|
||||||
|
"no-meal-planned-for-today": "Aucun repas prévu pour aujourd'hui",
|
||||||
|
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Seules les recettes appartenant à ces catégories seront utilisées dans les menus",
|
||||||
|
"planner": "Planificateur",
|
||||||
|
"quick-week": "Semaine rapide",
|
||||||
|
"side": "Accompagnement",
|
||||||
|
"sides": "Accompagnements",
|
||||||
|
"start-date": "Date de début"
|
||||||
|
},
|
||||||
|
"migration": {
|
||||||
|
"chowdown": {
|
||||||
|
"description": "Importer des recettes depuis Chowdown",
|
||||||
|
"title": "Chowdown"
|
||||||
|
},
|
||||||
|
"migration-data-removed": "Données de migration supprimées",
|
||||||
|
"nextcloud": {
|
||||||
|
"description": "Importer des recettes depuis un livre de recettes Nextcloud existant",
|
||||||
|
"title": "Nextcloud Cookbook"
|
||||||
|
},
|
||||||
|
"no-migration-data-available": "Aucune donnée d'importation n'est disponible",
|
||||||
|
"recipe-migration": "Migrer les recettes"
|
||||||
|
},
|
||||||
|
"new-recipe": {
|
||||||
|
"bulk-add": "Ajouter en masse",
|
||||||
|
"error-details": "Seuls les sites Web contenant ld+json ou des microdonnées peuvent être importés par Mealie. La plupart des grands sites web de recettes sont compatibles avec cette structure de données. Si votre site ne peut pas être importé mais qu'il y a des données JSON dans le journal, veuillez soumettre un problème GitHub avec l'URL et les données.",
|
||||||
|
"error-title": "On dirait qu'on n'a pas pu trouver quoi que ce soit",
|
||||||
|
"from-url": "Depuis une adresse Web",
|
||||||
|
"github-issues": "Anomalies GitHub",
|
||||||
|
"google-ld-json-info": "Infos Json-Ld Google",
|
||||||
|
"must-be-a-valid-url": "Doit être une URL valide",
|
||||||
|
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Copiez votre recette ici. Chaque ligne sera traitée comme un objet de la liste",
|
||||||
|
"recipe-markup-specification": "Spécification du marquage des recettes",
|
||||||
|
"recipe-url": "Adresse de la recette",
|
||||||
|
"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",
|
||||||
|
"view-scraped-data": "Voir les données récupérées"
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"404-page-not-found": "404 Page introuvable",
|
||||||
|
"all-recipes": "Toutes les recettes",
|
||||||
|
"new-page-created": "Nouvelle page créée",
|
||||||
|
"page": "Page",
|
||||||
|
"page-creation-failed": "La création de la page a échoué",
|
||||||
|
"page-deleted": "Page supprimée",
|
||||||
|
"page-deletion-failed": "La suppression de la page a échoué",
|
||||||
|
"page-update-failed": "La mise à jour de la page a échoué",
|
||||||
|
"page-updated": "Page mise à jour",
|
||||||
|
"pages-update-failed": "La mise à jour des pages a échoué",
|
||||||
|
"pages-updated": "Pages mises à jour"
|
||||||
|
},
|
||||||
|
"recipe": {
|
||||||
|
"add-key": "Ajouter une clé",
|
||||||
|
"add-to-favorites": "Ajouter aux favoris",
|
||||||
|
"api-extras": "Extras API",
|
||||||
|
"calories": "Calories",
|
||||||
|
"calories-suffix": "calories",
|
||||||
|
"carbohydrate-content": "Glucides",
|
||||||
|
"categories": "Catégories",
|
||||||
|
"comment-action": "Commenter",
|
||||||
|
"comments": "Commentaires",
|
||||||
|
"delete-confirmation": "Êtes-vous sûr(e) de vouloir supprimer cette recette?",
|
||||||
|
"delete-recipe": "Supprimer la recette",
|
||||||
|
"description": "Description",
|
||||||
|
"disable-amount": "Désactiver les quantités d'ingrédients",
|
||||||
|
"disable-comments": "Désactiver les commentaires",
|
||||||
|
"fat-content": "Matières grasses",
|
||||||
|
"fiber-content": "Fibres",
|
||||||
|
"grams": "grammes",
|
||||||
|
"ingredient": "Ingrédient",
|
||||||
|
"ingredients": "Ingrédients",
|
||||||
|
"insert-section": "Insérer une section",
|
||||||
|
"instructions": "Instructions",
|
||||||
|
"key-name-required": "Un nom de clé est requis",
|
||||||
|
"landscape-view-coming-soon": "Vue paysage (bientôt disponible)",
|
||||||
|
"milligrams": "milligrammes",
|
||||||
|
"new-key-name": "Nouveau nom de clé",
|
||||||
|
"no-white-space-allowed": "Aucun espace blanc autorisé",
|
||||||
|
"note": "Note",
|
||||||
|
"nutrition": "Valeurs nutritionnelles",
|
||||||
|
"object-key": "Clé d'objet",
|
||||||
|
"object-value": "Valeur d'objet",
|
||||||
|
"original-url": "Recette originale",
|
||||||
|
"perform-time": "Temps de cuisson",
|
||||||
|
"prep-time": "Temps de préparation",
|
||||||
|
"protein-content": "Protéines",
|
||||||
|
"public-recipe": "Recette publique",
|
||||||
|
"recipe-created": "Recette créée",
|
||||||
|
"recipe-creation-failed": "La création de la recette a échoué",
|
||||||
|
"recipe-deleted": "Recette supprimée",
|
||||||
|
"recipe-image": "Image de la recette",
|
||||||
|
"recipe-image-updated": "L'image de la recette a été mise à jour",
|
||||||
|
"recipe-name": "Nom de la recette",
|
||||||
|
"recipe-settings": "Paramètres de la recette",
|
||||||
|
"recipe-update-failed": "La mise à jour de la recette a échoué",
|
||||||
|
"recipe-updated": "Recette mise à jour",
|
||||||
|
"remove-from-favorites": "Supprimer des favoris",
|
||||||
|
"remove-section": "Supprimer une section",
|
||||||
|
"save-recipe-before-use": "Enregistrez la recette avant utilisation",
|
||||||
|
"section-title": "Titre de la section",
|
||||||
|
"servings": "Portions",
|
||||||
|
"share-recipe-message": "Je voulais partager ma recette de {0} avec vous.",
|
||||||
|
"show-nutrition-values": "Afficher les valeurs nutritionnelles",
|
||||||
|
"sodium-content": "Sodium",
|
||||||
|
"step-index": "Étape {step}",
|
||||||
|
"sugar-content": "Sucres",
|
||||||
|
"title": "Titre",
|
||||||
|
"total-time": "Temps total",
|
||||||
|
"unable-to-delete-recipe": "Impossible de supprimer la recette"
|
||||||
|
},
|
||||||
|
"reicpe": {
|
||||||
|
"no-recipe": "Pas de recette"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"advanced-search": "Recherche avancée",
|
||||||
|
"and": "et",
|
||||||
|
"exclude": "Exclure",
|
||||||
|
"include": "Inclure",
|
||||||
|
"max-results": "Nombre de résultats maximum",
|
||||||
|
"or": "Ou",
|
||||||
|
"results": "Résultats",
|
||||||
|
"search": "Rechercher",
|
||||||
|
"search-mealie": "Rechercher dans Mealie (appuyez sur /)",
|
||||||
|
"search-placeholder": "Rechercher...",
|
||||||
|
"tag-filter": "Filtre par mots-clés"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"add-a-new-theme": "Ajouter un nouveau thème",
|
||||||
|
"admin-settings": "Paramètres d'administration",
|
||||||
|
"backup": {
|
||||||
|
"backup-created-at-response-export_path": "Sauvegarde créée dans {path}",
|
||||||
|
"backup-deleted": "Sauvegarde supprimée",
|
||||||
|
"backup-tag": "Tag de la sauvegarde",
|
||||||
|
"create-heading": "Créer une sauvegarde",
|
||||||
|
"delete-backup": "Supprimer la sauvegarde",
|
||||||
|
"error-creating-backup-see-log-file": "Erreur de création de la sauvegarde. Voir les logs",
|
||||||
|
"full-backup": "Sauvegarde complète",
|
||||||
|
"import-summary": "Résumé de l'importation",
|
||||||
|
"partial-backup": "Sauvegarde partielle",
|
||||||
|
"unable-to-delete-backup": "Impossible de supprimer la sauvegarde."
|
||||||
|
},
|
||||||
|
"backup-and-exports": "Sauvegardes",
|
||||||
|
"change-password": "Modifier le mot de passe",
|
||||||
|
"current": "Version :",
|
||||||
|
"custom-pages": "Pages personnalisées",
|
||||||
|
"edit-page": "Modifier la page",
|
||||||
|
"events": "Évènements",
|
||||||
|
"first-day-of-week": "Premier jour de la semaine",
|
||||||
|
"group-settings-updated": "Paramètres du groupe mis à jour",
|
||||||
|
"homepage": {
|
||||||
|
"all-categories": "Toutes les catégories",
|
||||||
|
"card-per-section": "Tuiles par section",
|
||||||
|
"home-page": "Page d'accueil",
|
||||||
|
"home-page-sections": "Sections de la page d'accueil",
|
||||||
|
"show-recent": "Afficher les récentes"
|
||||||
|
},
|
||||||
|
"language": "Langue",
|
||||||
|
"latest": "Dernière",
|
||||||
|
"local-api": "API locale",
|
||||||
|
"locale-settings": "Paramètres régionaux",
|
||||||
|
"migrations": "Migrations",
|
||||||
|
"new-page": "Nouvelle page",
|
||||||
|
"notify": "Notifier",
|
||||||
|
"organize": "Organiser",
|
||||||
|
"page-name": "Nom de la page",
|
||||||
|
"pages": "Pages",
|
||||||
|
"profile": "Profil",
|
||||||
|
"remove-existing-entries-matching-imported-entries": "Supprimer les entrées existantes correspondant aux entrées importées",
|
||||||
|
"set-new-time": "Indiquer une nouvelle heure",
|
||||||
|
"settings-update-failed": "La mise à jour des paramètres a échoué",
|
||||||
|
"settings-updated": "Paramètres mis à jour",
|
||||||
|
"site-settings": "Paramètres du site",
|
||||||
|
"theme": {
|
||||||
|
"accent": "Accentué",
|
||||||
|
"dark": "Sombre",
|
||||||
|
"default-to-system": "Identique au système",
|
||||||
|
"error": "Erreur",
|
||||||
|
"error-creating-theme-see-log-file": "Erreur lors de la création du thème. Consultez les logs.",
|
||||||
|
"error-deleting-theme": "Erreur lors de la suppression du thème",
|
||||||
|
"error-updating-theme": "Erreur lors de la mise à jour du thème",
|
||||||
|
"info": "Information",
|
||||||
|
"light": "Clair",
|
||||||
|
"primary": "Primaire",
|
||||||
|
"secondary": "Secondaire",
|
||||||
|
"success": "Succès",
|
||||||
|
"switch-to-dark-mode": "Basculer en mode sombre",
|
||||||
|
"switch-to-light-mode": "Basculer en mode clair",
|
||||||
|
"theme-deleted": "Thème supprimé",
|
||||||
|
"theme-name": "Nom du thème",
|
||||||
|
"theme-name-is-required": "Un nom de thème est requis.",
|
||||||
|
"theme-saved": "Thème enregistré",
|
||||||
|
"theme-updated": "Thème mis à jour",
|
||||||
|
"warning": "Avertissement"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"active-tokens": "JETONS ACTIFS",
|
||||||
|
"api-token": "Jeton de l'API",
|
||||||
|
"api-tokens": "Jetons de l'API",
|
||||||
|
"copy-this-token-for-use-with-an-external-application-this-token-will-not-be-viewable-again": "Copiez ce jeton pour l'utiliser avec une application externe. Ce jeton ne sera plus consultable.",
|
||||||
|
"create-an-api-token": "Créer un jeton API",
|
||||||
|
"token-name": "Nom du jeton"
|
||||||
|
},
|
||||||
|
"toolbox": {
|
||||||
|
"assign-all": "Assigner tout",
|
||||||
|
"bulk-assign": "Assigner en masse",
|
||||||
|
"new-name": "Nouveau nom",
|
||||||
|
"no-unused-items": "Aucun élément inutilisé",
|
||||||
|
"recipes-affected": "Aucune recette affectée|Une recette affectée|{count} recettes affectées",
|
||||||
|
"remove-unused": "Supprimer orphelins",
|
||||||
|
"title-case-all": "Majuscules partout",
|
||||||
|
"toolbox": "Boîte à outils",
|
||||||
|
"unorganized": "Non organisé(s)"
|
||||||
|
},
|
||||||
|
"webhooks": {
|
||||||
|
"test-webhooks": "Tester les 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": "Les liens dans cette liste recevront les webhooks contenant les recettes pour le menu du jour. Actuellement, les webhooks se lancent à",
|
||||||
|
"webhook-url": "Lien du webhook",
|
||||||
|
"webhooks-caps": "WEBHOOKS"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shopping-list": {
|
||||||
|
"all-lists": "Toutes les listes",
|
||||||
|
"create-shopping-list": "Créer une liste d'épicerie",
|
||||||
|
"from-recipe": "À partir d'une recette",
|
||||||
|
"list-name": "Nom de la liste",
|
||||||
|
"new-list": "Nouvelle liste",
|
||||||
|
"quantity": "Quantité : {0}",
|
||||||
|
"shopping-list": "Liste d'épicerie",
|
||||||
|
"shopping-lists": "Listes d'épicerie"
|
||||||
|
},
|
||||||
|
"sidebar": {
|
||||||
|
"all-recipes": "Les recettes",
|
||||||
|
"categories": "Catégories",
|
||||||
|
"dashboard": "Console",
|
||||||
|
"home-page": "Accueil",
|
||||||
|
"manage-users": "Utilisateurs",
|
||||||
|
"migrations": "Migrations",
|
||||||
|
"profile": "Profil",
|
||||||
|
"search": "Rechercher",
|
||||||
|
"site-settings": "Paramètres",
|
||||||
|
"tags": "Mots-clés",
|
||||||
|
"toolbox": "Boîte à outils"
|
||||||
|
},
|
||||||
|
"signup": {
|
||||||
|
"error-signing-up": "Erreur lors de l'inscription",
|
||||||
|
"sign-up": "S'inscrire",
|
||||||
|
"sign-up-link-created": "Lien d'inscription créé",
|
||||||
|
"sign-up-link-creation-failed": "La création du lien d'inscription a échoué",
|
||||||
|
"sign-up-links": "Liens d'inscription",
|
||||||
|
"sign-up-token-deleted": "Jeton d'inscription supprimé",
|
||||||
|
"sign-up-token-deletion-failed": "La suppression du jeton d'inscription a échoué",
|
||||||
|
"welcome-to-mealie": "Bienvenue sur Mealie! Pour devenir un utilisateur de cette instance, vous devez avoir un lien d'invitation valide. Si vous n'avez pas reçu d'invitation, vous ne pouvez pas vous inscrire. Pour recevoir un lien, contactez l'administrateur du site."
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"tag-created": "Mot-clé créé",
|
||||||
|
"tag-creation-failed": "La création du mot-clé a échoué",
|
||||||
|
"tag-deleted": "Mot-clé supprimé",
|
||||||
|
"tag-deletion-failed": "La suppression du mot-clé a échoué",
|
||||||
|
"tag-update-failed": "La mise à jour du mot-clé a échoué",
|
||||||
|
"tag-updated": "Mot-clé mis à jour",
|
||||||
|
"tags": "Mots-clés",
|
||||||
|
"untagged-count": "{count} sans mot-clés"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"admin": "Administrateur",
|
||||||
|
"are-you-sure-you-want-to-delete-the-link": "Voulez-vous réellement supprimer le lien <b>{link}<b/>?",
|
||||||
|
"are-you-sure-you-want-to-delete-the-user": "Voulez-vous réellement supprimer l'utilisateur <b>{activeName} ID : {activeId}<b/>?",
|
||||||
|
"confirm-link-deletion": "Confirmer la suppression du lien",
|
||||||
|
"confirm-password": "Confirmer mot de passe",
|
||||||
|
"confirm-user-deletion": "Confirmer la suppression",
|
||||||
|
"could-not-validate-credentials": "La vérification de vos identifiants a échoué",
|
||||||
|
"create-link": "Créer un lien",
|
||||||
|
"create-user": "Créer utilisateur",
|
||||||
|
"current-password": "Mot de passe actuel",
|
||||||
|
"e-mail-must-be-valid": "Le courriel doit être valide",
|
||||||
|
"edit-user": "Modifier l'utilisateur",
|
||||||
|
"email": "Courriel",
|
||||||
|
"error-cannot-delete-super-user": "Erreur! Impossible de supprimer le super utilisateur",
|
||||||
|
"existing-password-does-not-match": "Le mot de passe actuel ne correspond pas",
|
||||||
|
"full-name": "Nom",
|
||||||
|
"link-id": "ID du lien",
|
||||||
|
"link-name": "Nom du lien",
|
||||||
|
"login": "Connexion",
|
||||||
|
"logout": "Déconnexion",
|
||||||
|
"manage-users": "Gérer les utilisateurs",
|
||||||
|
"new-password": "Nouveau mot de passe",
|
||||||
|
"new-user": "Nouvel utilisateur",
|
||||||
|
"password": "Mot de passe",
|
||||||
|
"password-has-been-reset-to-the-default-password": "Le mot de passe a été réinitialisé à la valeur par défaut",
|
||||||
|
"password-must-match": "Les mots de passe doivent correspondre",
|
||||||
|
"password-reset-failed": "Échec de la réinitialisation du mot de passe",
|
||||||
|
"password-updated": "Mot de passe mis à jour",
|
||||||
|
"reset-password": "Réinitialiser le mot de passe",
|
||||||
|
"sign-in": "Se connecter",
|
||||||
|
"total-mealplans": "Nombre de menus",
|
||||||
|
"total-users": "Nombre d'utilisateurs",
|
||||||
|
"upload-photo": "Importer une photo",
|
||||||
|
"use-8-characters-or-more-for-your-password": "Utilisez au moins 8 caractères pour votre mot de passe",
|
||||||
|
"user": "Utilisateur",
|
||||||
|
"user-created": "Utilisateur créé",
|
||||||
|
"user-creation-failed": "La création de l'utilisateur a échoué",
|
||||||
|
"user-deleted": "Utilisateur supprimé",
|
||||||
|
"user-id": "ID utilisateur",
|
||||||
|
"user-id-with-value": "ID utilisateur : {id}",
|
||||||
|
"user-password": "Mot de passe de l'utilisateur",
|
||||||
|
"user-successfully-logged-in": "Connexion réussie",
|
||||||
|
"user-update-failed": "La mise à jour de l'utilisateur a échoué",
|
||||||
|
"user-updated": "Utilisateur mis à jour",
|
||||||
|
"username": "Nom d'utilisateur",
|
||||||
|
"users": "Utilisateurs",
|
||||||
|
"users-header": "UTILISATEURS",
|
||||||
|
"webhook-time": "Heure du Webhook",
|
||||||
|
"webhooks-enabled": "Webhooks activés",
|
||||||
|
"you-are-not-allowed-to-create-a-user": "Vous n'avez pas le droit de créer un utilisateur",
|
||||||
|
"you-are-not-allowed-to-delete-this-user": "Vous n'avez pas le droit de supprimer cet utilisateur"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,11 +47,11 @@
|
|||||||
"database": "Base de données",
|
"database": "Base de données",
|
||||||
"delete-event": "Supprimer l’évènement",
|
"delete-event": "Supprimer l’évènement",
|
||||||
"new-notification-form-description": "Mealie utilise la bibliothèque Apprise pour générer des notifications. Elle propose de nombreux services à utiliser pour les notifications. Consultez leur wiki pour un guide complet sur la façon de créer l'URL de votre service. Si disponible, sélectionner le type de votre notification peut inclure des fonctionnalités supplémentaires.",
|
"new-notification-form-description": "Mealie utilise la bibliothèque Apprise pour générer des notifications. Elle propose de nombreux services à utiliser pour les notifications. Consultez leur wiki pour un guide complet sur la façon de créer l'URL de votre service. Si disponible, sélectionner le type de votre notification peut inclure des fonctionnalités supplémentaires.",
|
||||||
"new-version": "Nouvelle version disponible!",
|
"new-version": "Nouvelle version disponible !",
|
||||||
"notification": "Notification",
|
"notification": "Notification",
|
||||||
"refresh": "Rafraîchir",
|
"refresh": "Rafraîchir",
|
||||||
"scheduled": "Planifié",
|
"scheduled": "Planifié",
|
||||||
"something-went-wrong": "Une erreur s'est produite!",
|
"something-went-wrong": "Une erreur s'est produite !",
|
||||||
"subscribed-events": "Évènements suivis",
|
"subscribed-events": "Évènements suivis",
|
||||||
"test-message-sent": "Message de test envoyé"
|
"test-message-sent": "Message de test envoyé"
|
||||||
},
|
},
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
"clear": "Effacer",
|
"clear": "Effacer",
|
||||||
"close": "Fermer",
|
"close": "Fermer",
|
||||||
"confirm": "Confirmer",
|
"confirm": "Confirmer",
|
||||||
"confirm-delete-generic": "Voulez-vous vraiment supprimer ceci?",
|
"confirm-delete-generic": "Voulez-vous vraiment supprimer ceci ?",
|
||||||
"copied": "Copié",
|
"copied": "Copié",
|
||||||
"create": "Créer",
|
"create": "Créer",
|
||||||
"created": "Créé",
|
"created": "Créé",
|
||||||
@@ -316,7 +316,7 @@
|
|||||||
"current": "Version :",
|
"current": "Version :",
|
||||||
"custom-pages": "Pages personnalisées",
|
"custom-pages": "Pages personnalisées",
|
||||||
"edit-page": "Modifier la page",
|
"edit-page": "Modifier la page",
|
||||||
"events": "Evènements",
|
"events": "Évènements",
|
||||||
"first-day-of-week": "Premier jour de la semaine",
|
"first-day-of-week": "Premier jour de la semaine",
|
||||||
"group-settings-updated": "Paramètres du groupe mis à jour",
|
"group-settings-updated": "Paramètres du groupe mis à jour",
|
||||||
"homepage": {
|
"homepage": {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"api-docs": "Документация API",
|
"api-docs": "Документация API",
|
||||||
"api-port": "Порт API",
|
"api-port": "Порт API",
|
||||||
"application-mode": "Статус приложения",
|
"application-mode": "Статус приложения",
|
||||||
"database-type": "Тип БД",
|
"database-type": "Тип базы данных",
|
||||||
"database-url": "URL базы данных",
|
"database-url": "URL базы данных",
|
||||||
"default-group": "Группа по умолчанию",
|
"default-group": "Группа по умолчанию",
|
||||||
"demo": "Демо",
|
"demo": "Демо",
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"log-lines": "Строки журнала",
|
"log-lines": "Строки журнала",
|
||||||
"not-demo": "Не демо",
|
"not-demo": "Не демо",
|
||||||
"portfolio": "Портфолио",
|
"portfolio": "Портфолио",
|
||||||
"production": "Создание",
|
"production": "Пользовательский",
|
||||||
"support": "Поддержка",
|
"support": "Поддержка",
|
||||||
"version": "Версия"
|
"version": "Версия"
|
||||||
},
|
},
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
"recipe-markup-specification": "Спецификация разметки рецепта",
|
"recipe-markup-specification": "Спецификация разметки рецепта",
|
||||||
"recipe-url": "URL-адрес рецепта",
|
"recipe-url": "URL-адрес рецепта",
|
||||||
"upload-a-recipe": "Загрузить рецепт",
|
"upload-a-recipe": "Загрузить рецепт",
|
||||||
"upload-individual-zip-file": "Загрузить отдельный .zip файл, экспортированный из другой инстанции Mealie.",
|
"upload-individual-zip-file": "Загрузить отдельный .zip файл, экспортированный из другой Mealie.",
|
||||||
"url-form-hint": "Скопируйте и вставьте ссылку из вашего любимого сайта рецептов",
|
"url-form-hint": "Скопируйте и вставьте ссылку из вашего любимого сайта рецептов",
|
||||||
"view-scraped-data": "Просмотр собранных данных"
|
"view-scraped-data": "Просмотр собранных данных"
|
||||||
},
|
},
|
||||||
@@ -415,7 +415,7 @@
|
|||||||
},
|
},
|
||||||
"signup": {
|
"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": "Ссылки для регистрации",
|
||||||
|
|||||||
@@ -201,7 +201,7 @@
|
|||||||
"google-ld-json-info": "Google ld+json Info",
|
"google-ld-json-info": "Google ld+json Info",
|
||||||
"must-be-a-valid-url": "Måste vara en korrekt URL",
|
"must-be-a-valid-url": "Måste vara en korrekt URL",
|
||||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Klistra in din receptdata, varje rad kommer att hanteras som ett listelement",
|
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Klistra in din receptdata, varje rad kommer att hanteras som ett listelement",
|
||||||
"recipe-markup-specification": "Recipe Markup Specification",
|
"recipe-markup-specification": "Specifikation för receptmärkning",
|
||||||
"recipe-url": "Recept URL",
|
"recipe-url": "Recept URL",
|
||||||
"upload-a-recipe": "Ladda upp ett recept",
|
"upload-a-recipe": "Ladda upp ett recept",
|
||||||
"upload-individual-zip-file": "Ladda upp en individuell .zip-fil som exporteras från en annan Mealie-instans.",
|
"upload-individual-zip-file": "Ladda upp en individuell .zip-fil som exporteras från en annan Mealie-instans.",
|
||||||
@@ -385,7 +385,7 @@
|
|||||||
},
|
},
|
||||||
"webhooks": {
|
"webhooks": {
|
||||||
"test-webhooks": "Testa Webhooks",
|
"test-webhooks": "Testa 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": "Följande URLer kommer att mottaga webhooks med receptdata för dagens planerade måltid. Datan kommer att skickas klockan <strong>{ time }</strong>",
|
"the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "Följande webbadresser kommer att mottaga webhooks med receptdata för dagens planerade måltid. För närvarande körs webhooks klockan",
|
||||||
"webhook-url": "Webhook URL",
|
"webhook-url": "Webhook URL",
|
||||||
"webhooks-caps": "WEBHOOKS"
|
"webhooks-caps": "WEBHOOKS"
|
||||||
}
|
}
|
||||||
@@ -405,11 +405,11 @@
|
|||||||
"categories": "Kategorier",
|
"categories": "Kategorier",
|
||||||
"dashboard": "Startsida",
|
"dashboard": "Startsida",
|
||||||
"home-page": "Startsida",
|
"home-page": "Startsida",
|
||||||
"manage-users": "Manage Users",
|
"manage-users": "Användare",
|
||||||
"migrations": "Importer",
|
"migrations": "Importer",
|
||||||
"profile": "Profil",
|
"profile": "Profil",
|
||||||
"search": "Sök",
|
"search": "Sök",
|
||||||
"site-settings": "Site Settings",
|
"site-settings": "Inställningar",
|
||||||
"tags": "Taggar",
|
"tags": "Taggar",
|
||||||
"toolbox": "Verktygslåda"
|
"toolbox": "Verktygslåda"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,63 +1,63 @@
|
|||||||
{
|
{
|
||||||
"about": {
|
"about": {
|
||||||
"about": "About",
|
"about": "Hakkında",
|
||||||
"about-mealie": "About Mealie",
|
"about-mealie": "Mealie hakkında",
|
||||||
"api-docs": "API Docs",
|
"api-docs": "API Dökümentasyonu",
|
||||||
"api-port": "API Port",
|
"api-port": "API port",
|
||||||
"application-mode": "Application Mode",
|
"application-mode": "Uygulama Modu",
|
||||||
"database-type": "Database Type",
|
"database-type": "Veritabanı Türü",
|
||||||
"database-url": "Database URL",
|
"database-url": "Veritabanı Sunucu URL'si",
|
||||||
"default-group": "Default Group",
|
"default-group": "Varsayılan Grup",
|
||||||
"demo": "Demo",
|
"demo": "Demo",
|
||||||
"demo-status": "Demo Status",
|
"demo-status": "Demo durumu",
|
||||||
"development": "Development",
|
"development": "Geliştirme",
|
||||||
"docs": "Docs",
|
"docs": "Dökümanlar",
|
||||||
"download-log": "Download Log",
|
"download-log": "Logu indir",
|
||||||
"download-recipe-json": "Last Scraped JSON",
|
"download-recipe-json": "Son Kazınmış JSON",
|
||||||
"github": "Github",
|
"github": "GitHub",
|
||||||
"log-lines": "Log Lines",
|
"log-lines": "Log satırlar",
|
||||||
"not-demo": "Not Demo",
|
"not-demo": "Demo Değil",
|
||||||
"portfolio": "Portfolio",
|
"portfolio": "Portföy",
|
||||||
"production": "Production",
|
"production": "Üretim",
|
||||||
"support": "Support",
|
"support": "Destek",
|
||||||
"version": "Version"
|
"version": "Versiyon"
|
||||||
},
|
},
|
||||||
"asset": {
|
"asset": {
|
||||||
"assets": "Assets",
|
"assets": "Varlıklar",
|
||||||
"code": "Code",
|
"code": "Kod",
|
||||||
"file": "File",
|
"file": "Dosya",
|
||||||
"image": "Image",
|
"image": "Resim",
|
||||||
"new-asset": "New Asset",
|
"new-asset": "Yeni Varlık",
|
||||||
"pdf": "PDF",
|
"pdf": "PDF",
|
||||||
"recipe": "Recipe",
|
"recipe": "Tarif",
|
||||||
"show-assets": "Show Assets"
|
"show-assets": "Show Assets"
|
||||||
},
|
},
|
||||||
"category": {
|
"category": {
|
||||||
"category-created": "Category created",
|
"category-created": "Kategori oluşturuldu",
|
||||||
"category-creation-failed": "Category creation failed",
|
"category-creation-failed": "Kategori oluşturma başarısız",
|
||||||
"category-deleted": "Category Deleted",
|
"category-deleted": "Kategori silindi",
|
||||||
"category-deletion-failed": "Category deletion failed",
|
"category-deletion-failed": "Kategori silinme başarısız",
|
||||||
"category-filter": "Category Filter",
|
"category-filter": "Kategori Filteri",
|
||||||
"category-update-failed": "Category update failed",
|
"category-update-failed": "Kategori güncellemesi başarısız oldu",
|
||||||
"category-updated": "Category updated",
|
"category-updated": "Kategori güncellendi",
|
||||||
"uncategorized-count": "Uncategorized {count}"
|
"uncategorized-count": "{count} Kategorize edilmemiş"
|
||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
"apprise-url": "Apprise URL",
|
"apprise-url": "Url'yi bildir",
|
||||||
"database": "Database",
|
"database": "Veritabanı",
|
||||||
"delete-event": "Delete Event",
|
"delete-event": "Etkinlik Sil",
|
||||||
"new-notification-form-description": "Mealie uses the Apprise library to generate notifications. They offer many options for services to use for notifications. Refer to their wiki for a comprehensive guide on how to create the URL for your service. If available, selecting the type of your notification may include extra features.",
|
"new-notification-form-description": "Mealie uses the Apprise library to generate notifications. They offer many options for services to use for notifications. Refer to their wiki for a comprehensive guide on how to create the URL for your service. If available, selecting the type of your notification may include extra features.",
|
||||||
"new-version": "New version available!",
|
"new-version": "Yeni bir sürüm var!",
|
||||||
"notification": "Notification",
|
"notification": "Bildirimler",
|
||||||
"refresh": "Refresh",
|
"refresh": "Yenile",
|
||||||
"scheduled": "Scheduled",
|
"scheduled": "Planlandı",
|
||||||
"something-went-wrong": "Something Went Wrong!",
|
"something-went-wrong": "Bir sorun oluştu!",
|
||||||
"subscribed-events": "Subscribed Events",
|
"subscribed-events": "Abone Olunan Etkinlikler",
|
||||||
"test-message-sent": "Test Message Sent"
|
"test-message-sent": "Test Mesajı Gönderildi"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"cancel": "Cancel",
|
"cancel": "İptal",
|
||||||
"clear": "Clear",
|
"clear": "Temizle",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"confirm-delete-generic": "Are you sure you want to delete this?",
|
"confirm-delete-generic": "Are you sure you want to delete this?",
|
||||||
|
|||||||
@@ -1,489 +1,489 @@
|
|||||||
{
|
{
|
||||||
"about": {
|
"about": {
|
||||||
"about": "About",
|
"about": "Про програму",
|
||||||
"about-mealie": "About Mealie",
|
"about-mealie": "Про Mealie",
|
||||||
"api-docs": "API Docs",
|
"api-docs": "Документація API",
|
||||||
"api-port": "API Port",
|
"api-port": "Порт API",
|
||||||
"application-mode": "Application Mode",
|
"application-mode": "Режим додатку",
|
||||||
"database-type": "Database Type",
|
"database-type": "Тип бази данних",
|
||||||
"database-url": "Database URL",
|
"database-url": "URL-адреса бази даних",
|
||||||
"default-group": "Default Group",
|
"default-group": "Групи за замовчуванням",
|
||||||
"demo": "Demo",
|
"demo": "Демо",
|
||||||
"demo-status": "Demo Status",
|
"demo-status": "Статус демо",
|
||||||
"development": "Development",
|
"development": "Розробка",
|
||||||
"docs": "Docs",
|
"docs": "Документація",
|
||||||
"download-log": "Download Log",
|
"download-log": "Завантажити лог",
|
||||||
"download-recipe-json": "Last Scraped JSON",
|
"download-recipe-json": "Останній зібраний JSON",
|
||||||
"github": "Github",
|
"github": "Github",
|
||||||
"log-lines": "Log Lines",
|
"log-lines": "Журнал рядків",
|
||||||
"not-demo": "Not Demo",
|
"not-demo": "Не демо",
|
||||||
"portfolio": "Portfolio",
|
"portfolio": "Портфоліо",
|
||||||
"production": "Production",
|
"production": "Користувацький",
|
||||||
"support": "Support",
|
"support": "Підтримка",
|
||||||
"version": "Version"
|
"version": "Версія"
|
||||||
},
|
},
|
||||||
"asset": {
|
"asset": {
|
||||||
"assets": "Assets",
|
"assets": "Медіа-ресурси",
|
||||||
"code": "Code",
|
"code": "Код",
|
||||||
"file": "File",
|
"file": "Файл",
|
||||||
"image": "Image",
|
"image": "Зображення",
|
||||||
"new-asset": "New Asset",
|
"new-asset": "Новий медіа-ресурс",
|
||||||
"pdf": "PDF",
|
"pdf": "PDF",
|
||||||
"recipe": "Recipe",
|
"recipe": "Рецепт",
|
||||||
"show-assets": "Show Assets"
|
"show-assets": "Показати медіа-ресурси"
|
||||||
},
|
},
|
||||||
"category": {
|
"category": {
|
||||||
"category-created": "Category created",
|
"category-created": "Категорія створена",
|
||||||
"category-creation-failed": "Category creation failed",
|
"category-creation-failed": "Не вдалося створити категорію",
|
||||||
"category-deleted": "Category Deleted",
|
"category-deleted": "Категорію видалено",
|
||||||
"category-deletion-failed": "Category deletion failed",
|
"category-deletion-failed": "Не вдалося видалити категорію",
|
||||||
"category-filter": "Category Filter",
|
"category-filter": "Фільтр категорій",
|
||||||
"category-update-failed": "Category update failed",
|
"category-update-failed": "Не вдалося оновити категорію",
|
||||||
"category-updated": "Category updated",
|
"category-updated": "Категорію оновлено",
|
||||||
"uncategorized-count": "Uncategorized {count}"
|
"uncategorized-count": "Без категорії {count}"
|
||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
"apprise-url": "Apprise URL",
|
"apprise-url": "URL-адреса Apprise",
|
||||||
"database": "Database",
|
"database": "База даних",
|
||||||
"delete-event": "Delete Event",
|
"delete-event": "Видалити подію",
|
||||||
"new-notification-form-description": "Mealie uses the Apprise library to generate notifications. They offer many options for services to use for notifications. Refer to their wiki for a comprehensive guide on how to create the URL for your service. If available, selecting the type of your notification may include extra features.",
|
"new-notification-form-description": "Mealie використовує бібліотеку Apprise для створення сповіщень. Вони пропонують багато варіантів використання служб для сповіщень. Зверніться до wiki бібліотеки Apprise, щоб отримати повну інструкцію про те, як створити URL-адресу для вашого сервісу. При наявності вибраний тип вашого сповіщення може включати додаткові функції.",
|
||||||
"new-version": "New version available!",
|
"new-version": "Доступна нова версія!",
|
||||||
"notification": "Notification",
|
"notification": "Сповіщення",
|
||||||
"refresh": "Refresh",
|
"refresh": "Оновлення",
|
||||||
"scheduled": "Scheduled",
|
"scheduled": "Заплановано",
|
||||||
"something-went-wrong": "Something Went Wrong!",
|
"something-went-wrong": "Щось пішло не так!",
|
||||||
"subscribed-events": "Subscribed Events",
|
"subscribed-events": "Події, на які підписано",
|
||||||
"test-message-sent": "Test Message Sent"
|
"test-message-sent": "Тестове повідомлення надіслано"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"cancel": "Cancel",
|
"cancel": "Скасувати",
|
||||||
"clear": "Clear",
|
"clear": "Очистити",
|
||||||
"close": "Close",
|
"close": "Закрити",
|
||||||
"confirm": "Confirm",
|
"confirm": "Підтвердити",
|
||||||
"confirm-delete-generic": "Are you sure you want to delete this?",
|
"confirm-delete-generic": "Ви дійсно бажаєте видалити це?",
|
||||||
"copied": "Copied",
|
"copied": "Скопійовано",
|
||||||
"create": "Create",
|
"create": "Створити",
|
||||||
"created": "Created",
|
"created": "Створено",
|
||||||
"custom": "Custom",
|
"custom": "Власний",
|
||||||
"dashboard": "Dashboard",
|
"dashboard": "Панель керування",
|
||||||
"delete": "Delete",
|
"delete": "Видалити",
|
||||||
"disabled": "Disabled",
|
"disabled": "Вимкнено",
|
||||||
"download": "Download",
|
"download": "Завантажити",
|
||||||
"edit": "Edit",
|
"edit": "Редагувати",
|
||||||
"enabled": "Enabled",
|
"enabled": "Увімкнено",
|
||||||
"exception": "Exception",
|
"exception": "Виняток",
|
||||||
"failed-count": "Failed: {count}",
|
"failed-count": "Не вдалося: {count}",
|
||||||
"failure-uploading-file": "Failure uploading file",
|
"failure-uploading-file": "Помилка відвантаження файлу",
|
||||||
"favorites": "Favorites",
|
"favorites": "Улюблені",
|
||||||
"field-required": "Field Required",
|
"field-required": "Обов'язкове поле",
|
||||||
"file-folder-not-found": "File/folder not found",
|
"file-folder-not-found": "Файл/теку не знайдено",
|
||||||
"file-uploaded": "File uploaded",
|
"file-uploaded": "Файл відвантажено",
|
||||||
"filter": "Filter",
|
"filter": "Фільтр",
|
||||||
"friday": "Friday",
|
"friday": "П'ятниця",
|
||||||
"general": "General",
|
"general": "Загальне",
|
||||||
"get": "Get",
|
"get": "Отримати",
|
||||||
"home": "Home",
|
"home": "Головна",
|
||||||
"image": "Image",
|
"image": "Зображення",
|
||||||
"image-upload-failed": "Image upload failed",
|
"image-upload-failed": "Не вдалося відвантажити зображення",
|
||||||
"import": "Import",
|
"import": "Імпорт",
|
||||||
"json": "JSON",
|
"json": "JSON",
|
||||||
"keyword": "Keyword",
|
"keyword": "Ключове слово",
|
||||||
"link-copied": "Link Copied",
|
"link-copied": "Посилання скопійовано",
|
||||||
"loading-recipes": "Loading Recipes",
|
"loading-recipes": "Завантаження рецептів",
|
||||||
"monday": "Monday",
|
"monday": "Понеділок",
|
||||||
"name": "Name",
|
"name": "Назва",
|
||||||
"new": "New",
|
"new": "Створити",
|
||||||
"no": "No",
|
"no": "Ні",
|
||||||
"no-recipe-found": "No Recipe Found",
|
"no-recipe-found": "Рецепти не знайдені",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"options": "Options:",
|
"options": "Опції:",
|
||||||
"print": "Print",
|
"print": "Друк",
|
||||||
"random": "Random",
|
"random": "Випадково",
|
||||||
"rating": "Rating",
|
"rating": "Рейтинг",
|
||||||
"recent": "Recent",
|
"recent": "Нещодавні",
|
||||||
"recipe": "Recipe",
|
"recipe": "Рецепт",
|
||||||
"recipes": "Recipes",
|
"recipes": "Рецепти",
|
||||||
"rename-object": "Rename {0}",
|
"rename-object": "Перейменувати {0}",
|
||||||
"reset": "Reset",
|
"reset": "Скинути",
|
||||||
"saturday": "Saturday",
|
"saturday": "Субота",
|
||||||
"save": "Save",
|
"save": "Зберегти",
|
||||||
"settings": "Settings",
|
"settings": "Налаштування",
|
||||||
"share": "Share",
|
"share": "Поділитись",
|
||||||
"shuffle": "Shuffle",
|
"shuffle": "Перемішати",
|
||||||
"sort": "Sort",
|
"sort": "Сортувати",
|
||||||
"sort-alphabetically": "Alphabetical",
|
"sort-alphabetically": "За алфавітом",
|
||||||
"status": "Status",
|
"status": "Статус",
|
||||||
"submit": "Submit",
|
"submit": "Надіслати",
|
||||||
"success-count": "Success: {count}",
|
"success-count": "Успіх: {count}",
|
||||||
"sunday": "Sunday",
|
"sunday": "Неділя",
|
||||||
"templates": "Templates:",
|
"templates": "Шаблони:",
|
||||||
"test": "Test",
|
"test": "Тест",
|
||||||
"themes": "Themes",
|
"themes": "Теми",
|
||||||
"thursday": "Thursday",
|
"thursday": "Четвер",
|
||||||
"token": "Token",
|
"token": "Токен",
|
||||||
"tuesday": "Tuesday",
|
"tuesday": "Вівторок",
|
||||||
"type": "Type",
|
"type": "Тип",
|
||||||
"update": "Update",
|
"update": "Оновити",
|
||||||
"updated": "Updated",
|
"updated": "Оновлено",
|
||||||
"upload": "Upload",
|
"upload": "Відвантажити",
|
||||||
"url": "URL",
|
"url": "URL-адреса",
|
||||||
"view": "View",
|
"view": "Перегляд",
|
||||||
"wednesday": "Wednesday",
|
"wednesday": "Середа",
|
||||||
"yes": "Yes"
|
"yes": "Так"
|
||||||
},
|
},
|
||||||
"group": {
|
"group": {
|
||||||
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
|
"are-you-sure-you-want-to-delete-the-group": "Ви дійсно бажаєте видалити <b>{groupName}<b/>?",
|
||||||
"cannot-delete-default-group": "Cannot delete default group",
|
"cannot-delete-default-group": "Неможливо видалити групу за замовчуванням",
|
||||||
"cannot-delete-group-with-users": "Cannot delete group with users",
|
"cannot-delete-group-with-users": "Неможливо видалити групу з користувачами",
|
||||||
"confirm-group-deletion": "Confirm Group Deletion",
|
"confirm-group-deletion": "Підтвердіть видалення групи",
|
||||||
"create-group": "Create Group",
|
"create-group": "Створити групу",
|
||||||
"error-updating-group": "Error updating group",
|
"error-updating-group": "Помилка оновлення групи",
|
||||||
"group": "Group",
|
"group": "Група",
|
||||||
"group-deleted": "Group deleted",
|
"group-deleted": "Групу видалено",
|
||||||
"group-deletion-failed": "Group deletion failed",
|
"group-deletion-failed": "Не вдалося видалити групу",
|
||||||
"group-id-with-value": "Group ID: {groupID}",
|
"group-id-with-value": "ID групи: {groupID}",
|
||||||
"group-name": "Group Name",
|
"group-name": "Назва групи",
|
||||||
"group-not-found": "Group not found",
|
"group-not-found": "Групу не знайдено",
|
||||||
"group-with-value": "Group: {groupID}",
|
"group-with-value": "Група: {groupID}",
|
||||||
"groups": "Groups",
|
"groups": "Групи",
|
||||||
"manage-groups": "Manage Groups",
|
"manage-groups": "Керування групами",
|
||||||
"user-group": "User Group",
|
"user-group": "Група користувача",
|
||||||
"user-group-created": "User Group Created",
|
"user-group-created": "Групу користувача створено",
|
||||||
"user-group-creation-failed": "User Group Creation Failed"
|
"user-group-creation-failed": "Не вдалося створити групу користувача"
|
||||||
},
|
},
|
||||||
"meal-plan": {
|
"meal-plan": {
|
||||||
"create-a-new-meal-plan": "Create a New Meal Plan",
|
"create-a-new-meal-plan": "Створити новий план харчування",
|
||||||
"dinner-this-week": "Dinner This Week",
|
"dinner-this-week": "Обід цього тижня",
|
||||||
"dinner-today": "Dinner Today",
|
"dinner-today": "Обід сьогодні",
|
||||||
"dinner-tonight": "DINNER TONIGHT",
|
"dinner-tonight": "Вечеря сьогодні",
|
||||||
"edit-meal-plan": "Edit Meal Plan",
|
"edit-meal-plan": "Редагувати план харчування",
|
||||||
"end-date": "End Date",
|
"end-date": "Дата завершення",
|
||||||
"group": "Group (Beta)",
|
"group": "Група (бета)",
|
||||||
"main": "Main",
|
"main": "Основне",
|
||||||
"meal-planner": "Meal Planner",
|
"meal-planner": "Планувальник харчування",
|
||||||
"meal-plans": "Meal Plans",
|
"meal-plans": "Плани харчування",
|
||||||
"mealplan-categories": "MEALPLAN CATEGORIES",
|
"mealplan-categories": "КАТЕГОРІЇ",
|
||||||
"mealplan-created": "Mealplan created",
|
"mealplan-created": "План харчування створено",
|
||||||
"mealplan-creation-failed": "Mealplan creation failed",
|
"mealplan-creation-failed": "Не вдалося створити план харчування",
|
||||||
"mealplan-deleted": "Mealplan Deleted",
|
"mealplan-deleted": "План харчування видалено",
|
||||||
"mealplan-deletion-failed": "Mealplan deletion failed",
|
"mealplan-deletion-failed": "Не вдалося видалити план харчування",
|
||||||
"mealplan-settings": "Mealplan Settings",
|
"mealplan-settings": "Налаштування плану харчування",
|
||||||
"mealplan-update-failed": "Mealplan update failed",
|
"mealplan-update-failed": "Не вдалося оновити план харчування",
|
||||||
"mealplan-updated": "Mealplan Updated",
|
"mealplan-updated": "План харчування оновлено",
|
||||||
"no-meal-plan-defined-yet": "No meal plan defined yet",
|
"no-meal-plan-defined-yet": "Не створено жодного плану харчування",
|
||||||
"no-meal-planned-for-today": "No meal planned for today",
|
"no-meal-planned-for-today": "Не заплановано харчування на сьогодні",
|
||||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans",
|
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Лише рецепти з цими категоріями будуть використані в планах харчування",
|
||||||
"planner": "Planner",
|
"planner": "Планувальник",
|
||||||
"quick-week": "Quick Week",
|
"quick-week": "Швидкий тиждень",
|
||||||
"side": "Side",
|
"side": "Закуска",
|
||||||
"sides": "Sides",
|
"sides": "Закуска",
|
||||||
"start-date": "Start Date"
|
"start-date": "Дата початку"
|
||||||
},
|
},
|
||||||
"migration": {
|
"migration": {
|
||||||
"chowdown": {
|
"chowdown": {
|
||||||
"description": "Migrate data from Chowdown",
|
"description": "Міграція даних з Chowdown",
|
||||||
"title": "Chowdown"
|
"title": "Chowdown"
|
||||||
},
|
},
|
||||||
"migration-data-removed": "Migration data removed",
|
"migration-data-removed": "Дані міграції видалені",
|
||||||
"nextcloud": {
|
"nextcloud": {
|
||||||
"description": "Migrate data from a Nextcloud Cookbook instance",
|
"description": "Міграція даних з Nextcloud Cookbook",
|
||||||
"title": "Nextcloud Cookbook"
|
"title": "Nextcloud Cookbook"
|
||||||
},
|
},
|
||||||
"no-migration-data-available": "No Migration Data Available",
|
"no-migration-data-available": "Дані для міграції відсутні",
|
||||||
"recipe-migration": "Recipe Migration"
|
"recipe-migration": "Міграція рецептів"
|
||||||
},
|
},
|
||||||
"new-recipe": {
|
"new-recipe": {
|
||||||
"bulk-add": "Bulk Add",
|
"bulk-add": "Масове додавання",
|
||||||
"error-details": "Only websites containing ld+json or microdata can be imported by Mealie. Most major recipe websites support this data structure. If your site cannot be imported but there is json data in the log, please submit a github issue with the URL and data.",
|
"error-details": "Лише веб-сайти, що містять ld+json або мікродані, можуть бути імпортовані Mealie. Більшість кулінарних веб-сайтів підтримують цю структуру даних. Якщо ваш сайт не може бути імпортовано, але в журналі є json, будь ласка, створіть GitHub задачу з URL-адресою та даними.",
|
||||||
"error-title": "Looks Like We Couldn't Find Anything",
|
"error-title": "Схоже, ми не змогли нічого знайти",
|
||||||
"from-url": "Import a Recipe",
|
"from-url": "Імпорт рецепту",
|
||||||
"github-issues": "GitHub Issues",
|
"github-issues": "GitHub Issues",
|
||||||
"google-ld-json-info": "Google ld+json Info",
|
"google-ld-json-info": "Google ld+json дані",
|
||||||
"must-be-a-valid-url": "Must be a Valid URL",
|
"must-be-a-valid-url": "Має бути дійсною URL-адресою",
|
||||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Paste in your recipe data. Each line will be treated as an item in a list",
|
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Вставте дані рецепту. Кожен рядок буде використаний як елемент у списку",
|
||||||
"recipe-markup-specification": "Recipe Markup Specification",
|
"recipe-markup-specification": "Налаштування розмітки рецептів",
|
||||||
"recipe-url": "Recipe URL",
|
"recipe-url": "URL-адреса рецепту",
|
||||||
"upload-a-recipe": "Upload a Recipe",
|
"upload-a-recipe": "Відвантажити рецепт",
|
||||||
"upload-individual-zip-file": "Upload an individual .zip file exported from another Mealie instance.",
|
"upload-individual-zip-file": "Відвантажити окремий .zip файл, експортований з іншого Mealie.",
|
||||||
"url-form-hint": "Copy and paste a link from your favorite recipe website",
|
"url-form-hint": "Скопіюйте та вставте посилання з вашого улюбленого кулінарного веб-сайту",
|
||||||
"view-scraped-data": "View Scraped Data"
|
"view-scraped-data": "Переглянути зібрані дані"
|
||||||
},
|
},
|
||||||
"page": {
|
"page": {
|
||||||
"404-page-not-found": "404 Page not found",
|
"404-page-not-found": "404 - Сторінка не знайдена",
|
||||||
"all-recipes": "All Recipes",
|
"all-recipes": "Всі рецепти",
|
||||||
"new-page-created": "New page created",
|
"new-page-created": "Нова сторінка створена",
|
||||||
"page": "Page",
|
"page": "Сторінка",
|
||||||
"page-creation-failed": "Page creation failed",
|
"page-creation-failed": "Не вдалося створити сторінку",
|
||||||
"page-deleted": "Page deleted",
|
"page-deleted": "Сторінка видалена",
|
||||||
"page-deletion-failed": "Page deletion failed",
|
"page-deletion-failed": "Не вдалося видалити сторінку",
|
||||||
"page-update-failed": "Page update failed",
|
"page-update-failed": "Не вдалося оновити сторінку",
|
||||||
"page-updated": "Page updated",
|
"page-updated": "Сторінку оновлено",
|
||||||
"pages-update-failed": "Pages update failed",
|
"pages-update-failed": "Не вдалося оновити сторінки",
|
||||||
"pages-updated": "Pages updated"
|
"pages-updated": "Сторінки оновлено"
|
||||||
},
|
},
|
||||||
"recipe": {
|
"recipe": {
|
||||||
"add-key": "Add Key",
|
"add-key": "Додати ключ",
|
||||||
"add-to-favorites": "Add to Favorites",
|
"add-to-favorites": "Додати в улюблені",
|
||||||
"api-extras": "API Extras",
|
"api-extras": "Додаткове API",
|
||||||
"calories": "Calories",
|
"calories": "Калорії",
|
||||||
"calories-suffix": "calories",
|
"calories-suffix": "калорії",
|
||||||
"carbohydrate-content": "Carbohydrate",
|
"carbohydrate-content": "Вуглеводи",
|
||||||
"categories": "Categories",
|
"categories": "Категорії",
|
||||||
"comment-action": "Comment",
|
"comment-action": "Коментар",
|
||||||
"comments": "Comments",
|
"comments": "Коментарі",
|
||||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
"delete-confirmation": "Ви впевнені, що хочете видалити цей рецепт?",
|
||||||
"delete-recipe": "Delete Recipe",
|
"delete-recipe": "Видалити рецепт",
|
||||||
"description": "Description",
|
"description": "Опис",
|
||||||
"disable-amount": "Disable Ingredient Amounts",
|
"disable-amount": "Сховати кількість інгредієнтів",
|
||||||
"disable-comments": "Disable Comments",
|
"disable-comments": "Вимкнути коментарі",
|
||||||
"fat-content": "Fat",
|
"fat-content": "Жири",
|
||||||
"fiber-content": "Fiber",
|
"fiber-content": "Волокна",
|
||||||
"grams": "grams",
|
"grams": "грами",
|
||||||
"ingredient": "Ingredient",
|
"ingredient": "Інгредієнт",
|
||||||
"ingredients": "Ingredients",
|
"ingredients": "Інгредієнти",
|
||||||
"insert-section": "Insert Section",
|
"insert-section": "Вставити розділ",
|
||||||
"instructions": "Instructions",
|
"instructions": "Інструкції",
|
||||||
"key-name-required": "Key Name Required",
|
"key-name-required": "Необхідно вказати назву ключа",
|
||||||
"landscape-view-coming-soon": "Landscape View (Coming Soon)",
|
"landscape-view-coming-soon": "Вид в ландшафтному режимі (незабаром буде)",
|
||||||
"milligrams": "milligrams",
|
"milligrams": "міліграми",
|
||||||
"new-key-name": "New Key Name",
|
"new-key-name": "Назва нового ключа",
|
||||||
"no-white-space-allowed": "No White Space Allowed",
|
"no-white-space-allowed": "Проміжки не дозволені",
|
||||||
"note": "Note",
|
"note": "Нотатка",
|
||||||
"nutrition": "Nutrition",
|
"nutrition": "Харчова цінність",
|
||||||
"object-key": "Object Key",
|
"object-key": "Ключ об'єкту",
|
||||||
"object-value": "Object Value",
|
"object-value": "Значення об'єкту",
|
||||||
"original-url": "Original URL",
|
"original-url": "Оригінальна URL-адреса",
|
||||||
"perform-time": "Cook Time",
|
"perform-time": "Час приготування",
|
||||||
"prep-time": "Prep Time",
|
"prep-time": "Час підготовки",
|
||||||
"protein-content": "Protein",
|
"protein-content": "Білки",
|
||||||
"public-recipe": "Public Recipe",
|
"public-recipe": "Публічний рецепт",
|
||||||
"recipe-created": "Recipe created",
|
"recipe-created": "Рецепт створено",
|
||||||
"recipe-creation-failed": "Recipe creation failed",
|
"recipe-creation-failed": "Не вдалося створити рецепт",
|
||||||
"recipe-deleted": "Recipe deleted",
|
"recipe-deleted": "Рецепт видалено",
|
||||||
"recipe-image": "Recipe Image",
|
"recipe-image": "Зображення рецепту",
|
||||||
"recipe-image-updated": "Recipe image updated",
|
"recipe-image-updated": "Зображення рецепту оновлено",
|
||||||
"recipe-name": "Recipe Name",
|
"recipe-name": "Назва рецепта",
|
||||||
"recipe-settings": "Recipe Settings",
|
"recipe-settings": "Налаштування рецепта",
|
||||||
"recipe-update-failed": "Recipe update failed",
|
"recipe-update-failed": "Не вдалося оновити рецепт",
|
||||||
"recipe-updated": "Recipe updated",
|
"recipe-updated": "Рецепт оновлено",
|
||||||
"remove-from-favorites": "Remove from Favorites",
|
"remove-from-favorites": "Видалити з улюбленого",
|
||||||
"remove-section": "Remove Section",
|
"remove-section": "Видалити розділ",
|
||||||
"save-recipe-before-use": "Save recipe before use",
|
"save-recipe-before-use": "Зберегти рецепт перед використанням",
|
||||||
"section-title": "Section Title",
|
"section-title": "Назва розділу",
|
||||||
"servings": "Servings",
|
"servings": "Порції",
|
||||||
"share-recipe-message": "I wanted to share my {0} recipe with you.",
|
"share-recipe-message": "Я хотів би поділитися з тобою своїм рецептом {0}.",
|
||||||
"show-nutrition-values": "Show Nutrition Values",
|
"show-nutrition-values": "Показати харчову цінність",
|
||||||
"sodium-content": "Sodium",
|
"sodium-content": "Натрій",
|
||||||
"step-index": "Step: {step}",
|
"step-index": "Крок: {step}",
|
||||||
"sugar-content": "Sugar",
|
"sugar-content": "Цукор",
|
||||||
"title": "Title",
|
"title": "Назва",
|
||||||
"total-time": "Total Time",
|
"total-time": "Загальний час",
|
||||||
"unable-to-delete-recipe": "Unable to Delete Recipe"
|
"unable-to-delete-recipe": "Не вдалося видалити рецепт"
|
||||||
},
|
},
|
||||||
"reicpe": {
|
"reicpe": {
|
||||||
"no-recipe": "No Recipe"
|
"no-recipe": "Немає рецепту"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"advanced-search": "Advanced Search",
|
"advanced-search": "Розширений пошук",
|
||||||
"and": "and",
|
"and": "та",
|
||||||
"exclude": "Exclude",
|
"exclude": "Виключаючи",
|
||||||
"include": "Include",
|
"include": "Включаючи",
|
||||||
"max-results": "Max Results",
|
"max-results": "Максимальна кількість результатів",
|
||||||
"or": "Or",
|
"or": "Або",
|
||||||
"results": "Results",
|
"results": "Результати",
|
||||||
"search": "Search",
|
"search": "Пошук",
|
||||||
"search-mealie": "Search Mealie (press /)",
|
"search-mealie": "Пошук по Mealie (натисніть /)",
|
||||||
"search-placeholder": "Search...",
|
"search-placeholder": "Пошук...",
|
||||||
"tag-filter": "Tag Filter"
|
"tag-filter": "Фільтр міток"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"add-a-new-theme": "Add a New Theme",
|
"add-a-new-theme": "Додати нову тему",
|
||||||
"admin-settings": "Admin Settings",
|
"admin-settings": "Адміністративні налаштування",
|
||||||
"backup": {
|
"backup": {
|
||||||
"backup-created-at-response-export_path": "Backup Created at {path}",
|
"backup-created-at-response-export_path": "Резервна копія створена {path}",
|
||||||
"backup-deleted": "Backup deleted",
|
"backup-deleted": "Резервна копія видалена",
|
||||||
"backup-tag": "Backup Tag",
|
"backup-tag": "Мітка резервної копії",
|
||||||
"create-heading": "Create a Backup",
|
"create-heading": "Створити резервну копію",
|
||||||
"delete-backup": "Delete Backup",
|
"delete-backup": "Видалити резервну копію",
|
||||||
"error-creating-backup-see-log-file": "Error Creating Backup. See Log File",
|
"error-creating-backup-see-log-file": "Помилка створення резервної копії. Перегляньте файл журналу",
|
||||||
"full-backup": "Full Backup",
|
"full-backup": "Повна резервна копія",
|
||||||
"import-summary": "Import Summary",
|
"import-summary": "Резюме імпорту",
|
||||||
"partial-backup": "Partial Backup",
|
"partial-backup": "Часткова резервна копія",
|
||||||
"unable-to-delete-backup": "Unable to Delete Backup."
|
"unable-to-delete-backup": "Не вдалося видалити резервну копію."
|
||||||
},
|
},
|
||||||
"backup-and-exports": "Backups",
|
"backup-and-exports": "Резервні копії",
|
||||||
"change-password": "Change Password",
|
"change-password": "Змінити пароль",
|
||||||
"current": "Version:",
|
"current": "Версія:",
|
||||||
"custom-pages": "Custom Pages",
|
"custom-pages": "Власні сторінки",
|
||||||
"edit-page": "Edit Page",
|
"edit-page": "Редагувати сторінку",
|
||||||
"events": "Events",
|
"events": "Події",
|
||||||
"first-day-of-week": "First day of the week",
|
"first-day-of-week": "Перший день тижня",
|
||||||
"group-settings-updated": "Group Settings Updated",
|
"group-settings-updated": "Налаштування групи оновлено",
|
||||||
"homepage": {
|
"homepage": {
|
||||||
"all-categories": "All Categories",
|
"all-categories": "Всі категорії",
|
||||||
"card-per-section": "Card Per Section",
|
"card-per-section": "Карток в розділі",
|
||||||
"home-page": "Home Page",
|
"home-page": "Домашня сторінка",
|
||||||
"home-page-sections": "Home Page Sections",
|
"home-page-sections": "Розділи на головній сторінці",
|
||||||
"show-recent": "Show Recent"
|
"show-recent": "Показати недавні"
|
||||||
},
|
},
|
||||||
"language": "Language",
|
"language": "Мова",
|
||||||
"latest": "Latest",
|
"latest": "Недавні",
|
||||||
"local-api": "Local API",
|
"local-api": "Локальний API",
|
||||||
"locale-settings": "Locale settings",
|
"locale-settings": "Налаштування локалі",
|
||||||
"migrations": "Migrations",
|
"migrations": "Міграції",
|
||||||
"new-page": "New Page",
|
"new-page": "Нова сторінка",
|
||||||
"notify": "Notify",
|
"notify": "Сповіщення",
|
||||||
"organize": "Organize",
|
"organize": "Впорядкувати",
|
||||||
"page-name": "Page Name",
|
"page-name": "Назва сторінки",
|
||||||
"pages": "Pages",
|
"pages": "Сторінки",
|
||||||
"profile": "Profile",
|
"profile": "Профіль",
|
||||||
"remove-existing-entries-matching-imported-entries": "Remove existing entries matching imported entries",
|
"remove-existing-entries-matching-imported-entries": "Видалити існуючі записи, відповідні до імпортованих даних",
|
||||||
"set-new-time": "Set New Time",
|
"set-new-time": "Встановити новий час",
|
||||||
"settings-update-failed": "Settings update failed",
|
"settings-update-failed": "Не вдалося оновити налаштування",
|
||||||
"settings-updated": "Settings updated",
|
"settings-updated": "Налаштування оновлено",
|
||||||
"site-settings": "Site Settings",
|
"site-settings": "Налаштування сайту",
|
||||||
"theme": {
|
"theme": {
|
||||||
"accent": "Accent",
|
"accent": "Акцент",
|
||||||
"dark": "Dark",
|
"dark": "Темна",
|
||||||
"default-to-system": "Default to system",
|
"default-to-system": "За замовчуванням системи",
|
||||||
"error": "Error",
|
"error": "Помилка",
|
||||||
"error-creating-theme-see-log-file": "Error creating theme. See log file.",
|
"error-creating-theme-see-log-file": "Помилка створення теми. Перегляньте файл журналу.",
|
||||||
"error-deleting-theme": "Error deleting theme",
|
"error-deleting-theme": "Помилка видалення теми",
|
||||||
"error-updating-theme": "Error updating theme",
|
"error-updating-theme": "Помилка оновлення теми",
|
||||||
"info": "Info",
|
"info": "Інформація",
|
||||||
"light": "Light",
|
"light": "Світла",
|
||||||
"primary": "Primary",
|
"primary": "Основний",
|
||||||
"secondary": "Secondary",
|
"secondary": "Додатковий",
|
||||||
"success": "Success",
|
"success": "Успіх",
|
||||||
"switch-to-dark-mode": "Switch to dark mode",
|
"switch-to-dark-mode": "Перейти в темний режим",
|
||||||
"switch-to-light-mode": "Switch to light mode",
|
"switch-to-light-mode": "Перейти в світлий режим",
|
||||||
"theme-deleted": "Theme deleted",
|
"theme-deleted": "Тему видалено",
|
||||||
"theme-name": "Theme Name",
|
"theme-name": "Назва теми",
|
||||||
"theme-name-is-required": "Theme Name is required.",
|
"theme-name-is-required": "Назва обов'язкова.",
|
||||||
"theme-saved": "Theme Saved",
|
"theme-saved": "Тему збережено",
|
||||||
"theme-updated": "Theme updated",
|
"theme-updated": "Тему оновлено",
|
||||||
"warning": "Warning"
|
"warning": "Попередження"
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"active-tokens": "ACTIVE TOKENS",
|
"active-tokens": "АКТИВНІ КЛЮЧІ",
|
||||||
"api-token": "API Token",
|
"api-token": "Ключ API",
|
||||||
"api-tokens": "API Tokens",
|
"api-tokens": "Ключі API",
|
||||||
"copy-this-token-for-use-with-an-external-application-this-token-will-not-be-viewable-again": "Copy this token for use with an external application. This token will not be viewable again.",
|
"copy-this-token-for-use-with-an-external-application-this-token-will-not-be-viewable-again": "Скопіюйте цей ключ для використання з зовнішнім додатком. Цей ключ не буде доступним для перегляду знову.",
|
||||||
"create-an-api-token": "Create an API Token",
|
"create-an-api-token": "Створити новий API ключ",
|
||||||
"token-name": "Token Name"
|
"token-name": "Назва ключа"
|
||||||
},
|
},
|
||||||
"toolbox": {
|
"toolbox": {
|
||||||
"assign-all": "Assign All",
|
"assign-all": "Призначити все",
|
||||||
"bulk-assign": "Bulk Assign",
|
"bulk-assign": "Масове призначення",
|
||||||
"new-name": "New Name",
|
"new-name": "Нова назва",
|
||||||
"no-unused-items": "No Unused Items",
|
"no-unused-items": "Немає невикористаних елементів",
|
||||||
"recipes-affected": "No Recipes Affected|One Recipe Affected|{count} Recipes Affected",
|
"recipes-affected": "Жоден рецепт не змінено|Один рецепт змінено|{count} рецептів змінено",
|
||||||
"remove-unused": "Remove Unused",
|
"remove-unused": "Видалити невикористані",
|
||||||
"title-case-all": "Title Case All",
|
"title-case-all": "Все З Великих Літер",
|
||||||
"toolbox": "Toolbox",
|
"toolbox": "Інструменти",
|
||||||
"unorganized": "Unorganized"
|
"unorganized": "Неорганізовані"
|
||||||
},
|
},
|
||||||
"webhooks": {
|
"webhooks": {
|
||||||
"test-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",
|
"the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "URL-адреси, перераховані нижче, будуть отримувати вебхуки, що містять дані рецепта для плану харчування на запланований день. В даний час Вебхуки будуть виконуватися о",
|
||||||
"webhook-url": "Webhook URL",
|
"webhook-url": "URL-адреса вебхука",
|
||||||
"webhooks-caps": "WEBHOOKS"
|
"webhooks-caps": "ВЕБХУКИ"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"shopping-list": {
|
"shopping-list": {
|
||||||
"all-lists": "All Lists",
|
"all-lists": "Всі списки",
|
||||||
"create-shopping-list": "Create Shopping List",
|
"create-shopping-list": "Сторити список покупок",
|
||||||
"from-recipe": "From Recipe",
|
"from-recipe": "З рецепту",
|
||||||
"list-name": "List Name",
|
"list-name": "Назва списку",
|
||||||
"new-list": "New List",
|
"new-list": "Новий список",
|
||||||
"quantity": "Quantity: {0}",
|
"quantity": "Кількість: {0}",
|
||||||
"shopping-list": "Shopping List",
|
"shopping-list": "Список покупок",
|
||||||
"shopping-lists": "Shopping Lists"
|
"shopping-lists": "Списки покупок"
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"all-recipes": "All Recipes",
|
"all-recipes": "Всі рецепти",
|
||||||
"categories": "Categories",
|
"categories": "Категорії",
|
||||||
"dashboard": "Dashboard",
|
"dashboard": "Панель",
|
||||||
"home-page": "Home Page",
|
"home-page": "Головна",
|
||||||
"manage-users": "Manage Users",
|
"manage-users": "Користувачі",
|
||||||
"migrations": "Migrations",
|
"migrations": "Міграції",
|
||||||
"profile": "Profile",
|
"profile": "Профіль",
|
||||||
"search": "Search",
|
"search": "Пошук",
|
||||||
"site-settings": "Site Settings",
|
"site-settings": "Налаштування",
|
||||||
"tags": "Tags",
|
"tags": "Мітки",
|
||||||
"toolbox": "Toolbox"
|
"toolbox": "Інструменти"
|
||||||
},
|
},
|
||||||
"signup": {
|
"signup": {
|
||||||
"error-signing-up": "Error Signing Up",
|
"error-signing-up": "Помилка реєстрації",
|
||||||
"sign-up": "Sign Up",
|
"sign-up": "Зареєструватися",
|
||||||
"sign-up-link-created": "Sign up link created",
|
"sign-up-link-created": "Посилання для реєстрації створено",
|
||||||
"sign-up-link-creation-failed": "Sign up link creation failed",
|
"sign-up-link-creation-failed": "Не вдалося створити посилання для реєстрації",
|
||||||
"sign-up-links": "Sign Up Links",
|
"sign-up-links": "Посилання для реєстрації",
|
||||||
"sign-up-token-deleted": "Sign Up Token Deleted",
|
"sign-up-token-deleted": "Ключ реєстрації видалено",
|
||||||
"sign-up-token-deletion-failed": "Sign up token deletion failed",
|
"sign-up-token-deletion-failed": "Не вдалося видалити ключ реєстрації",
|
||||||
"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": "Ласкаво просимо до Mealie! Щоб стати користувачем цього серверу, вам необхідно мати дійсне посилання-запрошення. Якщо ви не отримали запрошення, вам не вдасться зареєструватися. Щоб отримати посилання, зв'яжіться з адміністратором сайту."
|
||||||
},
|
},
|
||||||
"tag": {
|
"tag": {
|
||||||
"tag-created": "Tag created",
|
"tag-created": "Мітка створена",
|
||||||
"tag-creation-failed": "Tag creation failed",
|
"tag-creation-failed": "Не вдалося створити мітку",
|
||||||
"tag-deleted": "Tag deleted",
|
"tag-deleted": "Мітка видалена",
|
||||||
"tag-deletion-failed": "Tag deletion failed",
|
"tag-deletion-failed": "Не вдалося видалити мітку",
|
||||||
"tag-update-failed": "Tag update failed",
|
"tag-update-failed": "Не вдалося оновити мітку",
|
||||||
"tag-updated": "Tag updated",
|
"tag-updated": "Мітку оновлено",
|
||||||
"tags": "Tags",
|
"tags": "Мітки",
|
||||||
"untagged-count": "Untagged {count}"
|
"untagged-count": "Без мітки {count}"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"admin": "Admin",
|
"admin": "Адміністратор",
|
||||||
"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-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/>?",
|
"are-you-sure-you-want-to-delete-the-user": "Ви впевнені, що хочете видалити користувача <b>{activeName} ID: {activeId}<b/>?",
|
||||||
"confirm-link-deletion": "Confirm Link Deletion",
|
"confirm-link-deletion": "Підтвердіть видалення посилання",
|
||||||
"confirm-password": "Confirm Password",
|
"confirm-password": "Підтвердьте пароль",
|
||||||
"confirm-user-deletion": "Confirm User Deletion",
|
"confirm-user-deletion": "Підтвердіть видалення користувача",
|
||||||
"could-not-validate-credentials": "Could Not Validate Credentials",
|
"could-not-validate-credentials": "Не вдалося підтвердити облікові дані",
|
||||||
"create-link": "Create Link",
|
"create-link": "Створити посилання",
|
||||||
"create-user": "Create User",
|
"create-user": "Створити користувача",
|
||||||
"current-password": "Current Password",
|
"current-password": "Поточний пароль",
|
||||||
"e-mail-must-be-valid": "E-mail must be valid",
|
"e-mail-must-be-valid": "Електронна пошта має бути дійсною",
|
||||||
"edit-user": "Edit User",
|
"edit-user": "Редагувати користувача",
|
||||||
"email": "Email",
|
"email": "Електронна пошта",
|
||||||
"error-cannot-delete-super-user": "Error! Cannot Delete Super User",
|
"error-cannot-delete-super-user": "Помилка! Неможливо видалити суперкористувача",
|
||||||
"existing-password-does-not-match": "Existing password does not match",
|
"existing-password-does-not-match": "Існуючий пароль не збігається",
|
||||||
"full-name": "Full Name",
|
"full-name": "Повне Ім'я",
|
||||||
"link-id": "Link ID",
|
"link-id": "ID посилання",
|
||||||
"link-name": "Link Name",
|
"link-name": "Назва посилання",
|
||||||
"login": "Login",
|
"login": "Увійти",
|
||||||
"logout": "Logout",
|
"logout": "Вийти",
|
||||||
"manage-users": "Manage Users",
|
"manage-users": "Керування користувачами",
|
||||||
"new-password": "New Password",
|
"new-password": "Новий пароль",
|
||||||
"new-user": "New User",
|
"new-user": "Новий користувач",
|
||||||
"password": "Password",
|
"password": "Пароль",
|
||||||
"password-has-been-reset-to-the-default-password": "Password has been reset to the default password",
|
"password-has-been-reset-to-the-default-password": "Пароль було скинуто до стандартного",
|
||||||
"password-must-match": "Password must match",
|
"password-must-match": "Паролі повинні збігатися",
|
||||||
"password-reset-failed": "Password reset failed",
|
"password-reset-failed": "Не вдалося скинути пароль",
|
||||||
"password-updated": "Password updated",
|
"password-updated": "Пароль оновлено",
|
||||||
"reset-password": "Reset Password",
|
"reset-password": "Скинути пароль",
|
||||||
"sign-in": "Sign in",
|
"sign-in": "Увійти",
|
||||||
"total-mealplans": "Total MealPlans",
|
"total-mealplans": "Всього планів харчування",
|
||||||
"total-users": "Total Users",
|
"total-users": "Всього користувачів",
|
||||||
"upload-photo": "Upload Photo",
|
"upload-photo": "Відвантажити світлину",
|
||||||
"use-8-characters-or-more-for-your-password": "Use 8 characters or more for your password",
|
"use-8-characters-or-more-for-your-password": "Пароль повинен містити 8 або більше символів",
|
||||||
"user": "User",
|
"user": "Користувач",
|
||||||
"user-created": "User created",
|
"user-created": "Користувача створено",
|
||||||
"user-creation-failed": "User creation failed",
|
"user-creation-failed": "Не вдалося створити користувача",
|
||||||
"user-deleted": "User deleted",
|
"user-deleted": "Користувача видалено",
|
||||||
"user-id": "User ID",
|
"user-id": "ID Користувача",
|
||||||
"user-id-with-value": "User ID: {id}",
|
"user-id-with-value": "ID користувача: {id}",
|
||||||
"user-password": "User Password",
|
"user-password": "Пароль користувача",
|
||||||
"user-successfully-logged-in": "User Successfully Logged In",
|
"user-successfully-logged-in": "Користувач успішно увійшов",
|
||||||
"user-update-failed": "User update failed",
|
"user-update-failed": "Не вдалося оновити користувача",
|
||||||
"user-updated": "User updated",
|
"user-updated": "Користувача оновлено",
|
||||||
"username": "Username",
|
"username": "Ім'я користувача",
|
||||||
"users": "Users",
|
"users": "Користувачі",
|
||||||
"users-header": "USERS",
|
"users-header": "КОРИСТУВАЧІ",
|
||||||
"webhook-time": "Webhook Time",
|
"webhook-time": "Час вебхука",
|
||||||
"webhooks-enabled": "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-create-a-user": "Вам не дозволено створювати користувача",
|
||||||
"you-are-not-allowed-to-delete-this-user": "You are not allowed to delete this user"
|
"you-are-not-allowed-to-delete-this-user": "Вам не дозволено видаляти користувача"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<v-card v-else-if="!loadFailed" id="myRecipe" class="d-print-none">
|
<v-card v-else-if="!loadFailed" id="myRecipe" class="d-print-none">
|
||||||
<a :href="getImage(recipeDetails.slug)">
|
<a :href="getImage(recipeDetails.slug)">
|
||||||
<v-img
|
<v-img
|
||||||
:height="hideImage ? '50' : imageHeight"
|
:min-height="hideImage ? '50' : imageHeight"
|
||||||
@error="hideImage = true"
|
@error="hideImage = true"
|
||||||
:src="getImage(recipeDetails.slug)"
|
:src="getImage(recipeDetails.slug)"
|
||||||
class="d-print-none"
|
class="d-print-none"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import Vuetify from "vuetify/lib";
|
|||||||
|
|
||||||
Vue.use(Vuetify);
|
Vue.use(Vuetify);
|
||||||
|
|
||||||
|
import ca from "vuetify/es5/locale/ca";
|
||||||
import de from "vuetify/es5/locale/de";
|
import de from "vuetify/es5/locale/de";
|
||||||
import en from "vuetify/es5/locale/en";
|
import en from "vuetify/es5/locale/en";
|
||||||
import es from "vuetify/es5/locale/es";
|
import es from "vuetify/es5/locale/es";
|
||||||
@@ -10,7 +11,10 @@ import fr from "vuetify/es5/locale/fr";
|
|||||||
import hu from "vuetify/es5/locale/hu";
|
import hu from "vuetify/es5/locale/hu";
|
||||||
import it from "vuetify/es5/locale/it";
|
import it from "vuetify/es5/locale/it";
|
||||||
import nl from "vuetify/es5/locale/nl";
|
import nl from "vuetify/es5/locale/nl";
|
||||||
|
import no from "vuetify/es5/locale/no";
|
||||||
import pl from "vuetify/es5/locale/pl";
|
import pl from "vuetify/es5/locale/pl";
|
||||||
|
import ru from "vuetify/es5/locale/ru";
|
||||||
|
import sk from "vuetify/es5/locale/sk";
|
||||||
import sv from "vuetify/es5/locale/sv";
|
import sv from "vuetify/es5/locale/sv";
|
||||||
import zhHans from "vuetify/es5/locale/zh-Hans";
|
import zhHans from "vuetify/es5/locale/zh-Hans";
|
||||||
import zhHant from "vuetify/es5/locale/zh-Hant";
|
import zhHant from "vuetify/es5/locale/zh-Hant";
|
||||||
@@ -43,15 +47,21 @@ const vuetify = new Vuetify({
|
|||||||
},
|
},
|
||||||
lang: {
|
lang: {
|
||||||
locales: {
|
locales: {
|
||||||
|
"ca-ES": ca,
|
||||||
|
"da-DK": en, // language not supported by Vuetify
|
||||||
"de-DE": de,
|
"de-DE": de,
|
||||||
"en-US": en,
|
"en-US": en,
|
||||||
"en-GB": en,
|
"en-GB": en,
|
||||||
"es-ES": es,
|
"es-ES": es,
|
||||||
"fr-FR": fr,
|
"fr-FR": fr,
|
||||||
|
"fr-CA": fr,
|
||||||
"hu-HU": hu,
|
"hu-HU": hu,
|
||||||
"it-IT": it,
|
"it-IT": it,
|
||||||
"nl-NL": nl,
|
"nl-NL": nl,
|
||||||
|
"no-NO": no,
|
||||||
"pl-PL": pl,
|
"pl-PL": pl,
|
||||||
|
"ru-RU": ru,
|
||||||
|
"sk-SK": sk,
|
||||||
"sv-SE": sv,
|
"sv-SE": sv,
|
||||||
"zh-CN": zhHans,
|
"zh-CN": zhHans,
|
||||||
"zh-TW": zhHant,
|
"zh-TW": zhHant,
|
||||||
|
|||||||
@@ -9,6 +9,14 @@ const state = {
|
|||||||
name: "British English",
|
name: "British English",
|
||||||
value: "en-GB",
|
value: "en-GB",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Català (Catalan)",
|
||||||
|
value: "ca-ES",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Dansk (Danish)",
|
||||||
|
value: "da-DK",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Deutsch (German)",
|
name: "Deutsch (German)",
|
||||||
value: "de-DE",
|
value: "de-DE",
|
||||||
@@ -21,6 +29,10 @@ const state = {
|
|||||||
name: "Français (French)",
|
name: "Français (French)",
|
||||||
value: "fr-FR",
|
value: "fr-FR",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Français Canadien (Canadian French)",
|
||||||
|
value: "fr-CA",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Magyar (Hungarian)",
|
name: "Magyar (Hungarian)",
|
||||||
value: "hu-HU",
|
value: "hu-HU",
|
||||||
@@ -29,6 +41,10 @@ const state = {
|
|||||||
name: "Italiano (Italian)",
|
name: "Italiano (Italian)",
|
||||||
value: "it-IT",
|
value: "it-IT",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Norsk (Norwegian)",
|
||||||
|
value: "no-NO",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Nederlands (Dutch)",
|
name: "Nederlands (Dutch)",
|
||||||
value: "nl-NL",
|
value: "nl-NL",
|
||||||
@@ -37,6 +53,14 @@ const state = {
|
|||||||
name: "Polski (Polish)",
|
name: "Polski (Polish)",
|
||||||
value: "pl-PL",
|
value: "pl-PL",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Pусский (Russian)",
|
||||||
|
value: "ru-RU",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Slovenčina (Slovak)",
|
||||||
|
value: "sk-SK",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Svenska (Swedish)",
|
name: "Svenska (Swedish)",
|
||||||
value: "sv-SE",
|
value: "sv-SE",
|
||||||
|
|||||||
@@ -36,11 +36,19 @@ module.exports = {
|
|||||||
pwa: {
|
pwa: {
|
||||||
name: manifestJSON.short_name,
|
name: manifestJSON.short_name,
|
||||||
themeColor: manifestJSON.theme_color,
|
themeColor: manifestJSON.theme_color,
|
||||||
msTileColor: manifestJSON.background_color,
|
msTileColor: manifestJSON.theme_color,
|
||||||
appleMobileWebAppCapable: "yes",
|
appleMobileWebAppCapable: "yes",
|
||||||
appleMobileWebAppStatusBarStyle: "black",
|
appleMobileWebAppStatusBarStyle: "black",
|
||||||
manifestCrossorigin: "use-credentials",
|
manifestCrossorigin: "use-credentials",
|
||||||
|
|
||||||
|
iconPaths: {
|
||||||
|
maskicon: "img/icons/safari-pinned-tab.svg",
|
||||||
|
favicon32: "img/icons/favicon-32x32.png",
|
||||||
|
favicon16: "img/icons/favicon-16x16.png",
|
||||||
|
appleTouchIcon: "img/icons/apple-touch-icon.png",
|
||||||
|
msTileImage: "img/icons/mstile-150x150.png",
|
||||||
|
},
|
||||||
|
|
||||||
workboxPluginMode: "InjectManifest",
|
workboxPluginMode: "InjectManifest",
|
||||||
workboxOptions: {
|
workboxOptions: {
|
||||||
swSrc: "./src/sw.js",
|
swSrc: "./src/sw.js",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from typing import Any, Optional, Union
|
|||||||
import dotenv
|
import dotenv
|
||||||
from pydantic import BaseSettings, Field, PostgresDsn, validator
|
from pydantic import BaseSettings, Field, PostgresDsn, validator
|
||||||
|
|
||||||
APP_VERSION = "v0.5.3"
|
APP_VERSION = "v0.5.5"
|
||||||
DB_VERSION = "v0.5.0"
|
DB_VERSION = "v0.5.0"
|
||||||
|
|
||||||
CWD = Path(__file__).parent
|
CWD = Path(__file__).parent
|
||||||
@@ -151,6 +151,11 @@ class AppSettings(BaseSettings):
|
|||||||
DEFAULT_EMAIL: str = "changeme@email.com"
|
DEFAULT_EMAIL: str = "changeme@email.com"
|
||||||
DEFAULT_PASSWORD: str = "MyPassword"
|
DEFAULT_PASSWORD: str = "MyPassword"
|
||||||
|
|
||||||
|
LDAP_AUTH_ENABLED: bool = False
|
||||||
|
LDAP_SERVER_URL: str = None
|
||||||
|
LDAP_BIND_TEMPLATE: str = None
|
||||||
|
LDAP_ADMIN_FILTER: str = None
|
||||||
|
|
||||||
SCHEDULER_DATABASE = f"sqlite:///{app_dirs.DATA_DIR.joinpath('scheduler.db')}"
|
SCHEDULER_DATABASE = f"sqlite:///{app_dirs.DATA_DIR.joinpath('scheduler.db')}"
|
||||||
|
|
||||||
TOKEN_TIME: int = 2 # Time in Hours
|
TOKEN_TIME: int = 2 # Time in Hours
|
||||||
@@ -167,6 +172,8 @@ class AppSettings(BaseSettings):
|
|||||||
RECIPE_DISABLE_COMMENTS: bool = False
|
RECIPE_DISABLE_COMMENTS: bool = False
|
||||||
RECIPE_DISABLE_AMOUNT: bool = False
|
RECIPE_DISABLE_AMOUNT: bool = False
|
||||||
|
|
||||||
|
AUTO_BACKUP_ENABLED: bool = False
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
env_file = BASE_DIR.joinpath(".env")
|
env_file = BASE_DIR.joinpath(".env")
|
||||||
env_file_encoding = "utf-8"
|
env_file_encoding = "utf-8"
|
||||||
|
|||||||
@@ -11,6 +11,44 @@ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
|||||||
ALGORITHM = "HS256"
|
ALGORITHM = "HS256"
|
||||||
|
|
||||||
|
|
||||||
|
def user_from_ldap(session, username: str, password: str) -> UserInDB:
|
||||||
|
"""Given a username and password, tries to authenticate by BINDing to an
|
||||||
|
LDAP server
|
||||||
|
|
||||||
|
If the BIND succeeds, it will either create a new user of that username on
|
||||||
|
the server or return an existing one.
|
||||||
|
Returns False on failure.
|
||||||
|
"""
|
||||||
|
import ldap
|
||||||
|
|
||||||
|
conn = ldap.initialize(settings.LDAP_SERVER_URL)
|
||||||
|
user_dn = settings.LDAP_BIND_TEMPLATE.format(username)
|
||||||
|
try:
|
||||||
|
conn.simple_bind_s(user_dn, password)
|
||||||
|
except (ldap.INVALID_CREDENTIALS, ldap.NO_SUCH_OBJECT):
|
||||||
|
return False
|
||||||
|
|
||||||
|
user = db.users.get(session, username, "username", any_case=True)
|
||||||
|
if not user:
|
||||||
|
user = db.users.create(
|
||||||
|
session,
|
||||||
|
{
|
||||||
|
"username": username,
|
||||||
|
"password": "LDAP",
|
||||||
|
# Fill the next two values with something unique and vaguely
|
||||||
|
# relevant
|
||||||
|
"full_name": username,
|
||||||
|
"email": username,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if settings.LDAP_ADMIN_FILTER:
|
||||||
|
user.admin = len(conn.search_s(user_dn, ldap.SCOPE_BASE, settings.LDAP_ADMIN_FILTER, [])) > 0
|
||||||
|
db.users.update(session, user.id, user)
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
|
|
||||||
def create_access_token(data: dict(), expires_delta: timedelta = None) -> str:
|
def create_access_token(data: dict(), expires_delta: timedelta = None) -> str:
|
||||||
to_encode = data.copy()
|
to_encode = data.copy()
|
||||||
expires_delta = expires_delta or timedelta(hours=settings.TOKEN_TIME)
|
expires_delta = expires_delta or timedelta(hours=settings.TOKEN_TIME)
|
||||||
@@ -31,6 +69,8 @@ def authenticate_user(session, email: str, password: str) -> UserInDB:
|
|||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
user = db.users.get(session, email, "username", any_case=True)
|
user = db.users.get(session, email, "username", any_case=True)
|
||||||
|
if settings.LDAP_AUTH_ENABLED and (not user or user.password == "LDAP"):
|
||||||
|
return user_from_ldap(session, email, password)
|
||||||
if not user:
|
if not user:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ langs = {
|
|||||||
"ca-ES",
|
"ca-ES",
|
||||||
"sr-SP",
|
"sr-SP",
|
||||||
"cs-CZ",
|
"cs-CZ",
|
||||||
|
"fr-CA",
|
||||||
"fr-FR",
|
"fr-FR",
|
||||||
"zh-TW",
|
"zh-TW",
|
||||||
"af-ZA",
|
"af-ZA",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from typing import Union
|
|||||||
|
|
||||||
from jinja2 import Template
|
from jinja2 import Template
|
||||||
from mealie.core import root_logger
|
from mealie.core import root_logger
|
||||||
from mealie.core.config import app_dirs
|
from mealie.core.config import app_dirs, settings
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import create_session
|
from mealie.db.db_setup import create_session
|
||||||
from mealie.services.events import create_backup_event
|
from mealie.services.events import create_backup_event
|
||||||
@@ -153,6 +153,9 @@ def backup_all(
|
|||||||
|
|
||||||
|
|
||||||
def auto_backup_job():
|
def auto_backup_job():
|
||||||
|
if not settings.AUTO_BACKUP_ENABLED:
|
||||||
|
return
|
||||||
|
|
||||||
for backup in app_dirs.BACKUP_DIR.glob("Auto*.zip"):
|
for backup in app_dirs.BACKUP_DIR.glob("Auto*.zip"):
|
||||||
backup.unlink()
|
backup.unlink()
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ def write_image(recipe_slug: str, file_data: bytes, extension: str) -> Path:
|
|||||||
|
|
||||||
def scrape_image(image_url: str, slug: str) -> Path:
|
def scrape_image(image_url: str, slug: str) -> Path:
|
||||||
logger.info(f"Image URL: {image_url}")
|
logger.info(f"Image URL: {image_url}")
|
||||||
|
_FIREFOX_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0"
|
||||||
if isinstance(image_url, str): # Handles String Types
|
if isinstance(image_url, str): # Handles String Types
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -53,8 +54,10 @@ def scrape_image(image_url: str, slug: str) -> Path:
|
|||||||
|
|
||||||
all_image_requests = []
|
all_image_requests = []
|
||||||
for url in image_url:
|
for url in image_url:
|
||||||
|
if isinstance(url, dict):
|
||||||
|
url = url.get('url', "")
|
||||||
try:
|
try:
|
||||||
r = requests.get(url, stream=True, headers={"User-Agent": ""})
|
r = requests.get(url, stream=True, headers={"User-Agent": _FIREFOX_UA})
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("Image {url} could not be requested")
|
logger.exception("Image {url} could not be requested")
|
||||||
continue
|
continue
|
||||||
@@ -72,7 +75,7 @@ def scrape_image(image_url: str, slug: str) -> Path:
|
|||||||
filename = Recipe(slug=slug).image_dir.joinpath(filename)
|
filename = Recipe(slug=slug).image_dir.joinpath(filename)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = requests.get(image_url, stream=True)
|
r = requests.get(image_url, stream=True, headers={"User-Agent": _FIREFOX_UA})
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("Fatal Image Request Exception")
|
logger.exception("Fatal Image Request Exception")
|
||||||
return None
|
return None
|
||||||
|
|||||||
1302
poetry.lock
generated
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "mealie"
|
name = "mealie"
|
||||||
version = "0.5.2"
|
version = "0.5.5"
|
||||||
description = "A Recipe Manager"
|
description = "A Recipe Manager"
|
||||||
authors = ["Hayden <hay-kot@pm.me>"]
|
authors = ["Hayden <hay-kot@pm.me>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
@@ -9,7 +9,7 @@ license = "MIT"
|
|||||||
start = "mealie.app:main"
|
start = "mealie.app:main"
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.9"
|
python = "^3.9.9"
|
||||||
aiofiles = "0.5.0"
|
aiofiles = "0.5.0"
|
||||||
aniso8601 = "7.0.0"
|
aniso8601 = "7.0.0"
|
||||||
appdirs = "1.4.4"
|
appdirs = "1.4.4"
|
||||||
@@ -22,7 +22,7 @@ python-dotenv = "^0.15.0"
|
|||||||
python-slugify = "^4.0.1"
|
python-slugify = "^4.0.1"
|
||||||
requests = "^2.25.1"
|
requests = "^2.25.1"
|
||||||
PyYAML = "^5.3.1"
|
PyYAML = "^5.3.1"
|
||||||
extruct = "^0.12.0"
|
extruct = "^0.13.0"
|
||||||
python-multipart = "^0.0.5"
|
python-multipart = "^0.0.5"
|
||||||
fastapi-camelcase = "^1.0.2"
|
fastapi-camelcase = "^1.0.2"
|
||||||
bcrypt = "^3.2.0"
|
bcrypt = "^3.2.0"
|
||||||
@@ -32,8 +32,9 @@ lxml = "4.6.2"
|
|||||||
Pillow = "^8.2.0"
|
Pillow = "^8.2.0"
|
||||||
pathvalidate = "^2.4.1"
|
pathvalidate = "^2.4.1"
|
||||||
apprise = "0.9.3"
|
apprise = "0.9.3"
|
||||||
recipe-scrapers = "^13.2.7"
|
recipe-scrapers = "^13.7.0"
|
||||||
psycopg2-binary = {version = "^2.9.1", optional = true}
|
psycopg2-binary = {version = "^2.9.1", optional = true}
|
||||||
|
python-ldap = "^3.3.0"
|
||||||
gunicorn = "^20.1.0"
|
gunicorn = "^20.1.0"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
@@ -67,3 +68,4 @@ skip_empty = true
|
|||||||
|
|
||||||
[tool.poetry.extras]
|
[tool.poetry.extras]
|
||||||
pgsql = ["psycopg2-binary"]
|
pgsql = ["psycopg2-binary"]
|
||||||
|
ldap = ["python-ldap"]
|
||||||
|
|||||||
@@ -33,4 +33,10 @@ RECIPE_SHOW_NUTRITION=False
|
|||||||
RECIPE_SHOW_ASSETS=False
|
RECIPE_SHOW_ASSETS=False
|
||||||
RECIPE_LANDSCAPE_VIEW=False
|
RECIPE_LANDSCAPE_VIEW=False
|
||||||
RECIPE_DISABLE_COMMENTS=False
|
RECIPE_DISABLE_COMMENTS=False
|
||||||
RECIPE_DISABLE_AMOUNT=False
|
RECIPE_DISABLE_AMOUNT=False
|
||||||
|
|
||||||
|
# Configuration for authentication via an external LDAP server
|
||||||
|
LDAP_AUTH_ENABLED=False
|
||||||
|
LDAP_SERVER_URL=None
|
||||||
|
LDAP_BIND_TEMPLATE=None
|
||||||
|
LDAP_ADMIN_FILTER=None
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ from pathlib import Path
|
|||||||
|
|
||||||
from mealie.core import security
|
from mealie.core import security
|
||||||
from mealie.routes.deps import validate_file_token
|
from mealie.routes.deps import validate_file_token
|
||||||
|
from mealie.core.config import settings
|
||||||
|
from mealie.db.db_setup import create_session
|
||||||
|
|
||||||
|
|
||||||
def test_create_file_token():
|
def test_create_file_token():
|
||||||
@@ -9,3 +11,37 @@ def test_create_file_token():
|
|||||||
file_token = security.create_file_token(file_path)
|
file_token = security.create_file_token(file_path)
|
||||||
|
|
||||||
assert file_path == validate_file_token(file_token)
|
assert file_path == validate_file_token(file_token)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ldap_authentication_mocked(monkeypatch):
|
||||||
|
import ldap
|
||||||
|
|
||||||
|
user = "testinguser"
|
||||||
|
password = "testingpass"
|
||||||
|
bind_template = "cn={},dc=example,dc=com"
|
||||||
|
admin_filter = "(memberOf=cn=admins,dc=example,dc=com)"
|
||||||
|
monkeypatch.setattr(settings, "LDAP_AUTH_ENABLED", True)
|
||||||
|
monkeypatch.setattr(settings, "LDAP_SERVER_URL", "") # Not needed due to mocking
|
||||||
|
monkeypatch.setattr(settings, "LDAP_BIND_TEMPLATE", bind_template)
|
||||||
|
monkeypatch.setattr(settings, "LDAP_ADMIN_FILTER", admin_filter)
|
||||||
|
|
||||||
|
class LdapConnMock:
|
||||||
|
def simple_bind_s(self, dn, bind_pw):
|
||||||
|
assert dn == bind_template.format(user)
|
||||||
|
return bind_pw == password
|
||||||
|
|
||||||
|
def search_s(self, dn, scope, filter, attrlist):
|
||||||
|
assert attrlist == []
|
||||||
|
assert filter == admin_filter
|
||||||
|
assert dn == bind_template.format(user)
|
||||||
|
assert scope == ldap.SCOPE_BASE
|
||||||
|
return [()]
|
||||||
|
|
||||||
|
def ldap_initialize_mock(url):
|
||||||
|
assert url == ""
|
||||||
|
return LdapConnMock()
|
||||||
|
|
||||||
|
monkeypatch.setattr(ldap, "initialize", ldap_initialize_mock)
|
||||||
|
result = security.authenticate_user(create_session(), user, password)
|
||||||
|
assert result is not False
|
||||||
|
assert result.username == user
|
||||||
|
|||||||