mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-25 17:23:11 -05:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f35742d8b | ||
|
|
0f5a564ff3 |
2
.github/workflows/pytest.yml
vendored
2
.github/workflows/pytest.yml
vendored
@@ -11,6 +11,8 @@ on:
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
env:
|
||||
PRODUCTION: false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
#----------------------------------------------
|
||||
|
||||
@@ -20,7 +20,7 @@ RUN apk add --no-cache libxml2-dev \
|
||||
zlib-dev
|
||||
|
||||
|
||||
ENV ENV True
|
||||
ENV PRODUCTION true
|
||||
EXPOSE 80
|
||||
WORKDIR /app/
|
||||
|
||||
@@ -48,6 +48,7 @@ COPY ./dev/data/templates /app/data/templates
|
||||
COPY --from=build-stage /app/dist /app/dist
|
||||
|
||||
VOLUME [ "/app/data/" ]
|
||||
|
||||
RUN chmod +x /app/mealie/run.sh
|
||||
CMD /app/mealie/run.sh
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ FROM python:3
|
||||
|
||||
WORKDIR /app/
|
||||
|
||||
ENV PRODUCTION false
|
||||
|
||||
RUN apt-get update -y && \
|
||||
apt-get install -y python-pip python-dev
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
Mealie is a self hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in Vue for a pleasant user experience for the whole family. Easily add recipes into your database by providing the url and Mealie will automatically import the relevant data or add a family recipe with the UI editor. Mealie also provides an API for interactions from 3rd party applications.
|
||||
|
||||
[Remember to join the Discord](https://discord.gg/R6QDyJgbD2)!
|
||||
[Remember to join the Discord](https://discord.gg/QuStdQGSGK)!
|
||||
|
||||
|
||||
|
||||
|
||||
6
crowdin.yml
Normal file
6
crowdin.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
preserve_hierarchy: false
|
||||
files:
|
||||
- source: /frontend/src/locales/messages/en-US.json
|
||||
translation: /frontend/src/locales/messages/%locale%.json
|
||||
- source: /frontend/src/locales/dateTimeFormats/en-US.json
|
||||
translation: /frontend/src/locales/dateTimeFormats/%locale%.json
|
||||
34
docs/docs/changelog/v0.4.2.md
Normal file
34
docs/docs/changelog/v0.4.2.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# v0.4.2
|
||||
|
||||
**App Version: v0.4.2**
|
||||
|
||||
**Database Version: v0.4.0**
|
||||
|
||||
!!! error "Breaking Changes"
|
||||
1. With a recent refactor some users been experiencing issues with an environmental variable not being set correct. If you are experiencing issues, please provide your comments [Here](https://github.com/hay-kot/mealie/issues/281).
|
||||
|
||||
2. If you are a developer, you may experience issues with development as a new environmental variable has been introduced. Setting `PRODUCTION=false` will allow you to develop as normal.
|
||||
|
||||
## Bug Fixes
|
||||
- Fixed Initialization script (v0.4.1a Hot Fix) - Closes #274
|
||||
- Fixed nested list error on recipe scrape - Closes #306
|
||||
- Fixed ingredient checkboxes - Closes #304
|
||||
- Removed link on recent - Closes #297
|
||||
- Categories sidebar is auto generated if no pages are created - Closes #291
|
||||
- Fix tag issues on creating custom pages - Closes #290
|
||||
- Validate paths on export - Closes #275
|
||||
- Walk Nextcloud import directory - Closes #254
|
||||
|
||||
## General Improvements
|
||||
- Improved Nextcloud Migration. Mealie will now walk the directories in a zip file looking for directories that match the pattern of a Nextcloud Recipe. Closes #254
|
||||
- Rewrite Keywords to Tag Fields
|
||||
- Rewrite url to orgURL
|
||||
- Improved Chowdown Migration
|
||||
- Migration report is now similar to the Backup report
|
||||
- Tags/Categories are now title cased on import "dinner" -> "Dinner"
|
||||
- Depreciate `ENV` variable to `PRODUCTION`
|
||||
- Set `PRODUCTION` env variable to default to true
|
||||
- Unify Logger across the backend
|
||||
- mealie.log and last_recipe.json are now downloadable from the frontend from the /admin/about
|
||||
- New download schema where you request a token and then use that token to hit a single endpoint to download a file. This is a notable change if you are using the API to download backups.
|
||||
- Recipe images can now be added directly from a URL - [See #117 for details](https://github.com/hay-kot/mealie/issues/117)
|
||||
14
docs/docs/changelog/v0.4.3.md
Normal file
14
docs/docs/changelog/v0.4.3.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# v0.4.3
|
||||
|
||||
**App Version: v0.4.3**
|
||||
|
||||
**Database Version: v0.4.0**
|
||||
|
||||
## Bug Fixes
|
||||
- Fix Upload error for Migrations
|
||||
- Fixes #315 - Cannot select another language
|
||||
- Fixes #314 - case-sensitive emails
|
||||
- Fixes #312 - Profile Image Reload
|
||||
|
||||
## Improvements
|
||||
- New TOKEN_TIME and DEFAULT_EMAIL env variables
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contributing to Mealie
|
||||
|
||||
[Please Join the Discord](https://discord.gg/R6QDyJgbD2). We are building a community of developers working on the project.
|
||||
[Please Join the Discord](https://discord.gg/QuStdQGSGK). We are building a community of developers working on the project.
|
||||
|
||||
## We Develop with Github
|
||||
We use github to host code, to track issues and feature requests, as well as accept pull requests.
|
||||
|
||||
@@ -46,4 +46,4 @@ Once the prerequisites are installed you can cd into the project base directory
|
||||
|
||||
**Solution:** Create an empty /mealie/dist directory. This directory is served as static content by FastAPI. It is provided during the build process and may be missing in development.
|
||||
|
||||
Run into another issue? [Ask for help on discord](https://discord.gg/R6QDyJgbD2)
|
||||
Run into another issue? [Ask for help on discord](https://discord.gg/QuStdQGSGK)
|
||||
@@ -9,7 +9,7 @@ We love your input! We want to make contributing to this project as easy and tra
|
||||
- Becoming a maintainer
|
||||
- Help translate to a new language or improve current translations
|
||||
|
||||
[Remember to join the Discord and stay in touch with other developers working on the project](https://discord.gg/R6QDyJgbD2)!
|
||||
[Remember to join the Discord and stay in touch with other developers working on the project](https://discord.gg/QuStdQGSGK)!
|
||||
|
||||
Additionally, you can buy me a coffee and support the project. When I get financial support it helps me know that there's real interest in the project and that it's worth the time to keep developing.
|
||||
|
||||
|
||||
@@ -11,6 +11,6 @@ If your language is missing the translation for some strings, you can help out b
|
||||
## Tooling
|
||||
Currently we use Vue-i18n for translations. Translations are stored in json format located in [frontend/src/locales](https://github.com/hay-kot/mealie/tree/master/frontend/src/locales).
|
||||
|
||||
If you have experience with a good Translation Management System, please feel free to chime in on the [Discord](https://discord.gg/R6QDyJgbD2), as such a system could be helpful as the projects grow.
|
||||
If you have experience with a good Translation Management System, please feel free to chime in on the [Discord](https://discord.gg/QuStdQGSGK), as such a system could be helpful as the projects grow.
|
||||
Until then, [i18n Ally for VScode](https://marketplace.visualstudio.com/items?itemName=antfu.i18n-ally) is recommended to aid in translating. It also has a nice feature, which shows translations in-place when editing code.
|
||||
i18n Ally will also show which languages is missing translations.
|
||||
@@ -50,14 +50,16 @@ services:
|
||||
|
||||
## Env Variables
|
||||
|
||||
| Variables | Default | Description |
|
||||
| ---------------- | ---------- | ----------------------------------------------------------------------------------- |
|
||||
| DB_TYPE | sqlite | The database type to be used. Current Options 'sqlite' |
|
||||
| DEFAULT_GROUP | Home | The default group for users |
|
||||
| DEFAULT_PASSWORD | MyPassword | The default password for all users created in Mealie |
|
||||
| API_PORT | 9000 | The port exposed by backend API. **do not change this if you're running in docker** |
|
||||
| API_DOCS | True | Turns on/off access to the API documentation locally. |
|
||||
| TZ | UTC | Must be set to get correct date/time on the server |
|
||||
| Variables | Default | Description |
|
||||
| ---------------- | ------------------ | ----------------------------------------------------------------------------------- |
|
||||
| DB_TYPE | sqlite | The database type to be used. Current Options 'sqlite' |
|
||||
| DEFAULT_GROUP | Home | The default group for users |
|
||||
| DEFAULT_USERNAME | changeme@email.com | The default username for the superuser |
|
||||
| DEFAULT_PASSWORD | MyPassword | The default password for the superuser |
|
||||
| TOKEN_TIME | 2 | The time in hours that a login/auth token is valid |
|
||||
| API_PORT | 9000 | The port exposed by backend API. **do not change this if you're running in docker** |
|
||||
| API_DOCS | True | Turns on/off access to the API documentation locally. |
|
||||
| TZ | UTC | Must be set to get correct date/time on the server |
|
||||
|
||||
|
||||
|
||||
@@ -96,7 +98,7 @@ The Docker image provided by Mealie contains both the API and the html bundle in
|
||||
|
||||
## Deployed without Docker
|
||||
!!! error "Unsupported Deployment"
|
||||
If you are experiencing a problem with manual deployment, please do not submit a github issue unless it is related to an aspect of the application. For deployment help, the [discord server](https://discord.gg/R6QDyJgbD2) is a better place to find support.
|
||||
If you are experiencing a problem with manual deployment, please do not submit a github issue unless it is related to an aspect of the application. For deployment help, the [discord server](https://discord.gg/QuStdQGSGK) is a better place to find support.
|
||||
|
||||
Alternatively, this project is built on Python and SQLite so you may run it as a python application on your server. This is not a supported options for deployment and is only here as a reference for those who would like to do this on their own. To get started you can clone this repository into a directory of your choice and use the instructions below as a reference for how to get started.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Mealie is a self hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in Vue for a pleasant user experience for the whole family. Easily add recipes into your database by providing the url and Mealie will automatically import the relevant data or add a family recipe with the UI editor. Mealie also provides an API for interactions from 3rd party applications.
|
||||
|
||||
[Remember to join the Discord](https://discord.gg/R6QDyJgbD2)!
|
||||
[Remember to join the Discord](https://discord.gg/QuStdQGSGK)!
|
||||
|
||||
!!! note
|
||||
In some of the demo gifs the styling may be different than the finale application. demos were done during development prior to finale styling.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -77,6 +77,8 @@ nav:
|
||||
- Guidelines: "contributors/developers-guide/general-guidelines.md"
|
||||
- Development Road Map: "roadmap.md"
|
||||
- Change Log:
|
||||
- v0.4.3 Hot Fix: "changelog/v0.4.3.md"
|
||||
- v0.4.2 Backend/Migrations: "changelog/v0.4.2.md"
|
||||
- v0.4.1 Frontend/UI: "changelog/v0.4.1.md"
|
||||
- v0.4.0 Authentication: "changelog/v0.4.0.md"
|
||||
- v0.3.0 Improvements: "changelog/v0.3.0.md"
|
||||
|
||||
@@ -61,9 +61,16 @@ const apiReq = {
|
||||
processResponse(response);
|
||||
return response;
|
||||
},
|
||||
|
||||
async download(url) {
|
||||
const response = await this.get(url);
|
||||
const token = response.data.fileToken;
|
||||
|
||||
const tokenURL = baseURL + "utils/download?token=" + token;
|
||||
window.open(tokenURL, "_blank");
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
export { apiReq };
|
||||
export { baseURL };
|
||||
|
||||
@@ -4,7 +4,7 @@ import { store } from "@/store";
|
||||
|
||||
const backupBase = baseURL + "backups/";
|
||||
|
||||
const backupURLs = {
|
||||
export const backupURLs = {
|
||||
// Backup
|
||||
available: `${backupBase}available`,
|
||||
createBackup: `${backupBase}export/database`,
|
||||
@@ -13,6 +13,8 @@ const backupURLs = {
|
||||
downloadBackup: fileName => `${backupBase}${fileName}/download`,
|
||||
};
|
||||
|
||||
|
||||
|
||||
export const backupAPI = {
|
||||
/**
|
||||
* Request all backups available on the server
|
||||
@@ -43,19 +45,19 @@ export const backupAPI = {
|
||||
/**
|
||||
* Creates a backup on the serve given a set of options
|
||||
* @param {object} data
|
||||
* @returns
|
||||
* @returns
|
||||
*/
|
||||
async create(options) {
|
||||
let response = apiReq.post(backupURLs.createBackup, options);
|
||||
return response;
|
||||
},
|
||||
/**
|
||||
* Downloads a file from the server. I don't actually think this is used?
|
||||
* @param {string} fileName
|
||||
* Downloads a file from the server. I don't actually think this is used?
|
||||
* @param {string} fileName
|
||||
* @returns Download URL
|
||||
*/
|
||||
async download(fileName) {
|
||||
let response = await apiReq.get(backupURLs.downloadBackup(fileName));
|
||||
return response.data;
|
||||
const url = backupURLs.downloadBackup(fileName);
|
||||
apiReq.download(url);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -61,6 +61,11 @@ export const recipeAPI = {
|
||||
return response;
|
||||
},
|
||||
|
||||
async updateImagebyURL(slug, url) {
|
||||
const response = apiReq.post(recipeURLs.updateImage(slug), { url: url });
|
||||
return response;
|
||||
},
|
||||
|
||||
async update(data) {
|
||||
let response = await apiReq.put(recipeURLs.update(data.slug), data);
|
||||
store.dispatch("requestRecentRecipes");
|
||||
|
||||
@@ -3,6 +3,8 @@ import { apiReq } from "./api-utils";
|
||||
export const utilsAPI = {
|
||||
// import { api } from "@/api";
|
||||
async uploadFile(url, fileObject) {
|
||||
console.log("API Called");
|
||||
|
||||
let response = await apiReq.post(url, fileObject, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
|
||||
@@ -37,14 +37,7 @@
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-actions>
|
||||
<v-btn
|
||||
color="accent"
|
||||
text
|
||||
:loading="downloading"
|
||||
@click="downloadFile(`/api/backups/${name}/download`)"
|
||||
>
|
||||
{{ $t("general.download") }}
|
||||
</v-btn>
|
||||
<TheDownloadBtn :download-url="downloadUrl" />
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="error" text @click="raiseEvent('delete')">
|
||||
{{ $t("general.delete") }}
|
||||
@@ -66,9 +59,10 @@
|
||||
|
||||
<script>
|
||||
import ImportOptions from "@/components/Admin/Backup/ImportOptions";
|
||||
import axios from "axios";
|
||||
import TheDownloadBtn from "@/components/UI/TheDownloadBtn.vue";
|
||||
import { backupURLs } from "@/api/backup";
|
||||
export default {
|
||||
components: { ImportOptions },
|
||||
components: { ImportOptions, TheDownloadBtn },
|
||||
props: {
|
||||
name: {
|
||||
default: "Backup Name",
|
||||
@@ -92,6 +86,11 @@ export default {
|
||||
downloading: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
downloadUrl() {
|
||||
return backupURLs.downloadBackup(this.name);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateOptions(options) {
|
||||
this.options = options;
|
||||
@@ -116,23 +115,6 @@ export default {
|
||||
this.close();
|
||||
this.$emit(event, eventData);
|
||||
},
|
||||
async downloadFile(downloadURL) {
|
||||
this.downloading = true;
|
||||
const response = await axios({
|
||||
url: downloadURL,
|
||||
method: "GET",
|
||||
responseType: "blob", // important
|
||||
});
|
||||
|
||||
const url = window.URL.createObjectURL(new Blob([response.data]));
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.setAttribute("download", `${this.name}.zip`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
this.downloading = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DataTable from "./DataTable";
|
||||
import DataTable from "@/components/Admin/Backup/ImportSummaryDialog/DataTable";
|
||||
export default {
|
||||
components: {
|
||||
DataTable,
|
||||
@@ -145,4 +145,4 @@ export default {
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<v-text-field
|
||||
autofocus
|
||||
v-model="page.name"
|
||||
label="Page Name"
|
||||
:label="$t('settings.page-name')"
|
||||
></v-text-field>
|
||||
<CategoryTagSelector
|
||||
v-model="page.categories"
|
||||
ref="categoryFormSelector"
|
||||
@mounted="catMounted = true"
|
||||
tag-selector="false"
|
||||
:tag-selector="false"
|
||||
/>
|
||||
</v-card-text>
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<CreatePageDialog ref="createDialog" @refresh-page="getPages" />
|
||||
<v-card-text>
|
||||
<h2 class="mt-1 mb-1 ">
|
||||
Custom Pages
|
||||
{{$t('settings.custom-pages')}}
|
||||
<span>
|
||||
<v-btn color="success" @click="newPage" small class="ml-3">
|
||||
Create
|
||||
{{$t('general.create')}}
|
||||
</v-btn>
|
||||
</span>
|
||||
</h2>
|
||||
@@ -41,11 +41,11 @@
|
||||
|
||||
<v-card-actions>
|
||||
<v-btn text small color="error" @click="deletePage(item.id)">
|
||||
Delete
|
||||
{{$t('general.delete')}}
|
||||
</v-btn>
|
||||
<v-spacer> </v-spacer>
|
||||
<v-btn small text color="success" @click="editPage(index)">
|
||||
Edit
|
||||
{{$t('general.edit')}}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
@@ -55,7 +55,7 @@
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="success" @click="savePages">
|
||||
Save
|
||||
{{$t('general.save')}}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
@@ -76,8 +76,8 @@ export default {
|
||||
customPages: [],
|
||||
newPageData: {
|
||||
create: true,
|
||||
title: "New Page",
|
||||
buttonText: "Create",
|
||||
title: this.$t('settings.new-page'),
|
||||
buttonText: this.$t('general.create'),
|
||||
data: {
|
||||
name: "",
|
||||
categories: [],
|
||||
@@ -86,8 +86,8 @@ export default {
|
||||
},
|
||||
editPageData: {
|
||||
create: false,
|
||||
title: "Edit Page",
|
||||
buttonText: "Update",
|
||||
title: this.$t('settings.edit-page'),
|
||||
buttonText: this.$t('general.update'),
|
||||
data: {},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -162,6 +162,7 @@ export default {
|
||||
|
||||
methods: {
|
||||
writeLang(val) {
|
||||
this.$store.commit("setLang", val);
|
||||
this.settings.language = val;
|
||||
},
|
||||
deleteCategoryfromDatabase(category) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<v-card outlined class="my-2" :loading="loading">
|
||||
<MigrationDialog ref="migrationDialog" />
|
||||
<v-card-title>
|
||||
{{ title }}
|
||||
<v-spacer></v-spacer>
|
||||
@@ -9,6 +10,7 @@
|
||||
:url="`/api/migrations/${folder}/upload`"
|
||||
fileName="archive"
|
||||
@uploaded="$emit('refresh')"
|
||||
:post="true"
|
||||
/>
|
||||
</span>
|
||||
</v-card-title>
|
||||
@@ -67,6 +69,7 @@
|
||||
import UploadBtn from "../../UI/UploadBtn";
|
||||
import utils from "@/utils";
|
||||
import { api } from "@/api";
|
||||
import MigrationDialog from "@/components/Admin/Migration/MigrationDialog.vue";
|
||||
export default {
|
||||
props: {
|
||||
folder: String,
|
||||
@@ -76,6 +79,7 @@ export default {
|
||||
},
|
||||
components: {
|
||||
UploadBtn,
|
||||
MigrationDialog,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -90,7 +94,8 @@ export default {
|
||||
async importMigration(file_name) {
|
||||
this.loading = true;
|
||||
let response = await api.migrations.import(this.folder, file_name);
|
||||
this.$emit("imported", response.successful, response.failed);
|
||||
this.$refs.migrationDialog.open(response);
|
||||
// this.$emit("imported", response.successful, response.failed);
|
||||
this.loading = false;
|
||||
},
|
||||
readableTime(timestamp) {
|
||||
|
||||
109
frontend/src/components/Admin/Migration/MigrationDialog.vue
Normal file
109
frontend/src/components/Admin/Migration/MigrationDialog.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
|
||||
<template>
|
||||
<div class="text-center">
|
||||
<v-dialog v-model="dialog" width="70%">
|
||||
<v-card>
|
||||
<v-app-bar dark color="primary mb-2">
|
||||
<v-icon large left>
|
||||
mdi-import
|
||||
</v-icon>
|
||||
<v-toolbar-title class="headline">
|
||||
Migration Summary
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
</v-app-bar>
|
||||
<v-card-text class="mb-n4">
|
||||
<v-row>
|
||||
<div v-for="values in allNumbers" :key="values.title">
|
||||
<v-card-text>
|
||||
<div>
|
||||
<h3>{{ values.title }}</h3>
|
||||
</div>
|
||||
<div class="success--text">Success: {{ values.success }}</div>
|
||||
<div class="error--text">Failed: {{ values.failure }}</div>
|
||||
</v-card-text>
|
||||
</div>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-tabs v-model="tab">
|
||||
<v-tab>{{ $t("general.recipes") }}</v-tab>
|
||||
</v-tabs>
|
||||
<v-tabs-items v-model="tab">
|
||||
<v-tab-item v-for="(table, index) in allTables" :key="index">
|
||||
<v-card flat>
|
||||
<DataTable :data-headers="importHeaders" :data-set="table" />
|
||||
</v-card>
|
||||
</v-tab-item>
|
||||
</v-tabs-items>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DataTable from "@/components/Admin/Backup/ImportSummaryDialog/DataTable";
|
||||
export default {
|
||||
components: {
|
||||
DataTable,
|
||||
},
|
||||
data: () => ({
|
||||
tab: null,
|
||||
dialog: false,
|
||||
recipeData: [],
|
||||
themeData: [],
|
||||
settingsData: [],
|
||||
userData: [],
|
||||
groupData: [],
|
||||
pageData: [],
|
||||
importHeaders: [
|
||||
{
|
||||
text: "Status",
|
||||
value: "status",
|
||||
},
|
||||
{
|
||||
text: "Name",
|
||||
align: "start",
|
||||
sortable: true,
|
||||
value: "name",
|
||||
},
|
||||
|
||||
{ text: "Exception", value: "data-table-expand", align: "center" },
|
||||
],
|
||||
allDataTables: [],
|
||||
}),
|
||||
|
||||
computed: {
|
||||
recipeNumbers() {
|
||||
return this.calculateNumbers(this.$t("general.recipes"), this.recipeData);
|
||||
},
|
||||
allNumbers() {
|
||||
return [this.recipeNumbers];
|
||||
},
|
||||
allTables() {
|
||||
return [this.recipeData];
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
calculateNumbers(title, list_array) {
|
||||
if (!list_array) return;
|
||||
let numbers = { title: title, success: 0, failure: 0 };
|
||||
list_array.forEach(element => {
|
||||
if (element.status) {
|
||||
numbers.success++;
|
||||
} else numbers.failure++;
|
||||
});
|
||||
return numbers;
|
||||
},
|
||||
open(importData) {
|
||||
this.recipeData = importData;
|
||||
|
||||
this.dialog = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -90,7 +90,7 @@ export default {
|
||||
computed: {
|
||||
inputLabel() {
|
||||
if (!this.showLabel) return null;
|
||||
return this.tagSelector ? "Tags" : "Categories";
|
||||
return this.tagSelector ? this.$t('recipe.tags') : this.$t('recipe.categories');
|
||||
},
|
||||
activeItems() {
|
||||
let ItemObjects = [];
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div class="text-center">
|
||||
<v-menu offset-y top nudge-top="6" :close-on-content-click="false">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn color="accent" dark v-bind="attrs" v-on="on">
|
||||
Image
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card width="400">
|
||||
<v-card-title class="headline flex mb-0">
|
||||
<div>
|
||||
Recipe Image
|
||||
</div>
|
||||
<UploadBtn
|
||||
class="ml-auto"
|
||||
url="none"
|
||||
file-name="image"
|
||||
:text-btn="false"
|
||||
@uploaded="uploadImage"
|
||||
:post="false"
|
||||
/>
|
||||
</v-card-title>
|
||||
<v-card-text class="mt-n5">
|
||||
<div>
|
||||
<v-text-field label="URL" class="pt-5" clearable v-model="url">
|
||||
<template v-slot:append-outer>
|
||||
<v-btn
|
||||
class="ml-2"
|
||||
color="primary"
|
||||
@click="getImageFromURL"
|
||||
:loading="loading"
|
||||
>
|
||||
Get
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const REFRESH_EVENT = "refresh";
|
||||
const UPLOAD_EVENT = "upload";
|
||||
import UploadBtn from "@/components/UI/UploadBtn";
|
||||
import { api } from "@/api";
|
||||
// import axios from "axios";
|
||||
export default {
|
||||
components: {
|
||||
UploadBtn,
|
||||
},
|
||||
props: {
|
||||
slug: String,
|
||||
},
|
||||
data: () => ({
|
||||
items: [{ title: "Upload Image" }, { title: "From URL" }],
|
||||
url: "",
|
||||
loading: false,
|
||||
}),
|
||||
methods: {
|
||||
uploadImage(fileObject) {
|
||||
this.$emit(UPLOAD_EVENT, fileObject);
|
||||
},
|
||||
async getImageFromURL() {
|
||||
this.loading = true;
|
||||
const response = await api.recipes.updateImagebyURL(this.slug, this.url);
|
||||
if (response) this.$emit(REFRESH_EVENT);
|
||||
this.loading = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<div v-if="valueNotNull || edit">
|
||||
<h2 class="my-4">Nutrition</h2>
|
||||
<div v-if="edit">
|
||||
<div v-for="(item, key, index) in value" :key="index">
|
||||
<v-text-field
|
||||
dense
|
||||
:value="value[key]"
|
||||
:label="labels[key].label"
|
||||
:suffix="labels[key].suffix"
|
||||
type="number"
|
||||
autocomplete="off"
|
||||
@input="updateValue(key, $event)"
|
||||
></v-text-field>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showViewer">
|
||||
<v-list dense>
|
||||
<v-list-item-group color="primary">
|
||||
<v-list-item v-for="(item, key, index) in labels" :key="index">
|
||||
<v-list-item-content>
|
||||
<v-list-item-title class="pl-4 text-subtitle-1 flex row ">
|
||||
<div>{{ item.label }}</div>
|
||||
<div class="ml-auto mr-1">{{ value[key] }}</div>
|
||||
<div>{{ item.suffix }}</div>
|
||||
</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list-item-group>
|
||||
</v-list>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {},
|
||||
edit: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
labels: {
|
||||
calories: {
|
||||
label: "Calories",
|
||||
suffix: "calories",
|
||||
},
|
||||
fatContent: { label: "Fat Content", suffix: "grams" },
|
||||
fiberContent: { label: "Fiber Content", suffix: "grams" },
|
||||
proteinContent: { label: "Protein Content", suffix: "grams" },
|
||||
sodiumContent: { label: "Sodium Content", suffix: "milligrams" },
|
||||
sugarContent: { label: "Sugar Content", suffix: "grams" },
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
showViewer() {
|
||||
return !this.edit && this.valueNotNull;
|
||||
},
|
||||
valueNotNull() {
|
||||
for (const property in this.value) {
|
||||
const valueProperty = this.value[property];
|
||||
if (valueProperty && valueProperty !== "") return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateValue(key, value) {
|
||||
this.$emit("input", { ...this.value, [key]: value });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
@@ -2,16 +2,12 @@
|
||||
<v-form ref="form">
|
||||
<v-card-text>
|
||||
<v-row dense>
|
||||
<v-col cols="3"></v-col>
|
||||
<v-col>
|
||||
<v-file-input
|
||||
v-model="fileObject"
|
||||
:label="$t('general.image-file')"
|
||||
truncate-length="30"
|
||||
@change="uploadImage"
|
||||
></v-file-input>
|
||||
</v-col>
|
||||
<v-col cols="3"></v-col>
|
||||
<ImageUploadBtn
|
||||
class="mt-2"
|
||||
@upload="uploadImage"
|
||||
:slug="value.slug"
|
||||
@refresh="$emit('upload')"
|
||||
/>
|
||||
</v-row>
|
||||
<v-row dense>
|
||||
<v-col>
|
||||
@@ -92,7 +88,7 @@
|
||||
auto-grow
|
||||
solo
|
||||
dense
|
||||
rows="2"
|
||||
rows="1"
|
||||
>
|
||||
<v-icon
|
||||
class="mr-n1"
|
||||
@@ -165,6 +161,7 @@
|
||||
<v-btn class="mt-1" color="secondary" fab dark small @click="addNote">
|
||||
<v-icon>mdi-plus</v-icon>
|
||||
</v-btn>
|
||||
<NutritionEditor v-model="value.nutrition" :edit="true" />
|
||||
<ExtrasEditor :extras="value.extras" @save="saveExtras" />
|
||||
</v-col>
|
||||
|
||||
@@ -222,17 +219,20 @@
|
||||
|
||||
<script>
|
||||
import draggable from "vuedraggable";
|
||||
import { api } from "@/api";
|
||||
import utils from "@/utils";
|
||||
import BulkAdd from "./BulkAdd";
|
||||
import ExtrasEditor from "./ExtrasEditor";
|
||||
import CategoryTagSelector from "@/components/FormHelpers/CategoryTagSelector";
|
||||
import NutritionEditor from "./NutritionEditor";
|
||||
import ImageUploadBtn from "./ImageUploadBtn.vue";
|
||||
export default {
|
||||
components: {
|
||||
BulkAdd,
|
||||
ExtrasEditor,
|
||||
draggable,
|
||||
CategoryTagSelector,
|
||||
NutritionEditor,
|
||||
ImageUploadBtn,
|
||||
},
|
||||
props: {
|
||||
value: Object,
|
||||
@@ -251,12 +251,8 @@ export default {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
uploadImage() {
|
||||
this.$emit("upload", this.fileObject);
|
||||
},
|
||||
async updateImage() {
|
||||
const slug = this.value.slug;
|
||||
api.recipes.updateImage(slug, this.fileObject);
|
||||
uploadImage(fileObject) {
|
||||
this.$emit("upload", fileObject);
|
||||
},
|
||||
toggleDisabled(stepIndex) {
|
||||
if (this.disabledSteps.includes(stepIndex)) {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
v-model="ingredient.checked"
|
||||
class="pt-0 my-auto py-auto"
|
||||
color="secondary"
|
||||
:readonly="true"
|
||||
>
|
||||
</v-checkbox>
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
:isCategory="false"
|
||||
/>
|
||||
<Notes :notes="notes" />
|
||||
<NutritionEditor :value="nutrition" :edit="false" />
|
||||
</div>
|
||||
</v-col>
|
||||
<v-divider
|
||||
@@ -56,6 +57,7 @@
|
||||
<RecipeChips :title="$t('recipe.categories')" :items="categories" />
|
||||
<RecipeChips :title="$t('recipe.tags')" :items="tags" />
|
||||
<Notes :notes="notes" />
|
||||
<NutritionEditor :value="nutrition" :edit="false" />
|
||||
</div>
|
||||
<v-row class="mt-2 mb-1">
|
||||
<v-col></v-col>
|
||||
@@ -80,6 +82,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NutritionEditor from "@/components/Recipe/RecipeEditor/NutritionEditor";
|
||||
import VueMarkdown from "@adapttive/vue-markdown";
|
||||
import utils from "@/utils";
|
||||
import RecipeChips from "./RecipeChips";
|
||||
@@ -93,6 +96,7 @@ export default {
|
||||
Steps,
|
||||
Notes,
|
||||
Ingredients,
|
||||
NutritionEditor,
|
||||
},
|
||||
props: {
|
||||
name: String,
|
||||
@@ -105,6 +109,7 @@ export default {
|
||||
rating: Number,
|
||||
yields: String,
|
||||
orgURL: String,
|
||||
nutrition: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<v-row v-if="title != null">
|
||||
<v-col>
|
||||
<v-btn-toggle group>
|
||||
<v-btn text :to="`/recipes/${title.toLowerCase()}`">
|
||||
<v-btn text>
|
||||
{{ title.toUpperCase() }}
|
||||
</v-btn>
|
||||
</v-btn-toggle>
|
||||
|
||||
@@ -54,22 +54,11 @@ export default {
|
||||
{
|
||||
icon: "mdi-magnify",
|
||||
to: "/search",
|
||||
title: "search",
|
||||
title: this.$t('search.search'),
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
allCategories() {
|
||||
return this.$store.getters.getCategories;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
allCategories() {
|
||||
this.buildSidebar();
|
||||
},
|
||||
showSidebar() {},
|
||||
},
|
||||
mounted() {
|
||||
this.buildSidebar();
|
||||
this.mobile = this.viewScale();
|
||||
@@ -81,14 +70,27 @@ export default {
|
||||
this.links = [];
|
||||
this.links.push(...this.baseLinks);
|
||||
const pages = await api.siteSettings.getPages();
|
||||
pages.sort((a, b) => a.position - b.position);
|
||||
pages.forEach(async element => {
|
||||
this.links.push({
|
||||
title: element.name,
|
||||
to: `/pages/${element.slug}`,
|
||||
icon: "mdi-tag",
|
||||
if(pages.length > 0) {
|
||||
pages.sort((a, b) => a.position - b.position);
|
||||
pages.forEach(async element => {
|
||||
this.links.push({
|
||||
title: element.name,
|
||||
to: `/pages/${element.slug}`,
|
||||
icon: "mdi-tag",
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
const categories = await api.categories.getAll();
|
||||
categories.forEach(async element => {
|
||||
this.links.push({
|
||||
title: element.name,
|
||||
to: `/recipes/category/${element.slug}`,
|
||||
icon: "mdi-tag",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
viewScale() {
|
||||
switch (this.$vuetify.breakpoint.name) {
|
||||
|
||||
51
frontend/src/components/UI/TheDownloadBtn.vue
Normal file
51
frontend/src/components/UI/TheDownloadBtn.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<v-btn color="accent" text :loading="downloading" @click="downloadFile">
|
||||
{{ showButtonText }}
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* The download button used for the entire site
|
||||
* pass a URL to the endpoint that will return a
|
||||
* file_token which will then be used to request the file
|
||||
* from the server and open that link in a new tab
|
||||
*/
|
||||
import { apiReq } from "@/api/api-utils";
|
||||
export default {
|
||||
props: {
|
||||
/**
|
||||
* URL to get token from
|
||||
*/
|
||||
downloadUrl: {
|
||||
default: "",
|
||||
},
|
||||
/**
|
||||
* Override button text. Defaults to "Download"
|
||||
*/
|
||||
buttonText: {
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
downloading: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
showButtonText() {
|
||||
return this.buttonText || this.$t("general.download");
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async downloadFile() {
|
||||
this.downloading = true;
|
||||
await apiReq.download(this.downloadUrl);
|
||||
this.downloading = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
@@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<v-form ref="file">
|
||||
<input ref="uploader" class="d-none" type="file" @change="onFileChanged" />
|
||||
<v-btn :loading="isSelecting" @click="onButtonClick" color="accent" text>
|
||||
<v-btn
|
||||
:loading="isSelecting"
|
||||
@click="onButtonClick"
|
||||
color="accent"
|
||||
:text="textBtn"
|
||||
>
|
||||
<v-icon left> {{ icon }}</v-icon>
|
||||
{{ text ? text : defaultText }}
|
||||
</v-btn>
|
||||
@@ -13,10 +18,17 @@ const UPLOAD_EVENT = "uploaded";
|
||||
import { api } from "@/api";
|
||||
export default {
|
||||
props: {
|
||||
post: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
url: String,
|
||||
text: { default: "Upload" },
|
||||
icon: { default: "mdi-cloud-upload" },
|
||||
fileName: { default: "archive" },
|
||||
textBtn: {
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data: () => ({
|
||||
file: null,
|
||||
@@ -33,6 +45,13 @@ export default {
|
||||
async upload() {
|
||||
if (this.file != null) {
|
||||
this.isSelecting = true;
|
||||
|
||||
if (!this.post) {
|
||||
this.$emit(UPLOAD_EVENT, this.file);
|
||||
this.isSelecting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
let formData = new FormData();
|
||||
formData.append(this.fileName, this.file);
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ function loadDateTimeFormats() {
|
||||
|
||||
|
||||
export default new VueI18n({
|
||||
locale: "en",
|
||||
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en",
|
||||
locale: "en-US",
|
||||
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en-US",
|
||||
messages: loadLocaleMessages(),
|
||||
dateTimeFormats: loadDateTimeFormats()
|
||||
});
|
||||
|
||||
7
frontend/src/locales/dateTimeFormats/af-ZA.json
Normal file
7
frontend/src/locales/dateTimeFormats/af-ZA.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/ar-SA.json
Normal file
7
frontend/src/locales/dateTimeFormats/ar-SA.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/ca-ES.json
Normal file
7
frontend/src/locales/dateTimeFormats/ca-ES.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/cs-CZ.json
Normal file
7
frontend/src/locales/dateTimeFormats/cs-CZ.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/da-DK.json
Normal file
7
frontend/src/locales/dateTimeFormats/da-DK.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/de-DE.json
Normal file
7
frontend/src/locales/dateTimeFormats/de-DE.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/el-GR.json
Normal file
7
frontend/src/locales/dateTimeFormats/el-GR.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/en-US.json
Normal file
7
frontend/src/locales/dateTimeFormats/en-US.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/es-ES.json
Normal file
7
frontend/src/locales/dateTimeFormats/es-ES.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/fi-FI.json
Normal file
7
frontend/src/locales/dateTimeFormats/fi-FI.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/fr-FR.json
Normal file
7
frontend/src/locales/dateTimeFormats/fr-FR.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/he-IL.json
Normal file
7
frontend/src/locales/dateTimeFormats/he-IL.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/hu-HU.json
Normal file
7
frontend/src/locales/dateTimeFormats/hu-HU.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/it-IT.json
Normal file
7
frontend/src/locales/dateTimeFormats/it-IT.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/ja-JP.json
Normal file
7
frontend/src/locales/dateTimeFormats/ja-JP.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/ko-KR.json
Normal file
7
frontend/src/locales/dateTimeFormats/ko-KR.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/nl-NL.json
Normal file
7
frontend/src/locales/dateTimeFormats/nl-NL.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/no-NO.json
Normal file
7
frontend/src/locales/dateTimeFormats/no-NO.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/pl-PL.json
Normal file
7
frontend/src/locales/dateTimeFormats/pl-PL.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/pt-BR.json
Normal file
7
frontend/src/locales/dateTimeFormats/pt-BR.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/pt-PT.json
Normal file
7
frontend/src/locales/dateTimeFormats/pt-PT.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/ro-RO.json
Normal file
7
frontend/src/locales/dateTimeFormats/ro-RO.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/ru-RU.json
Normal file
7
frontend/src/locales/dateTimeFormats/ru-RU.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/sr-SP.json
Normal file
7
frontend/src/locales/dateTimeFormats/sr-SP.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/sv-SE.json
Normal file
7
frontend/src/locales/dateTimeFormats/sv-SE.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/tr-TR.json
Normal file
7
frontend/src/locales/dateTimeFormats/tr-TR.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/uk-UA.json
Normal file
7
frontend/src/locales/dateTimeFormats/uk-UA.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
7
frontend/src/locales/dateTimeFormats/vi-VN.json
Normal file
7
frontend/src/locales/dateTimeFormats/vi-VN.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"short": {
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
"month": "short",
|
||||
"day": "numeric",
|
||||
"weekday": "long"
|
||||
}
|
||||
}
|
||||
249
frontend/src/locales/messages/da-DK.json
Normal file
249
frontend/src/locales/messages/da-DK.json
Normal file
@@ -0,0 +1,249 @@
|
||||
{
|
||||
"404": {
|
||||
"page-not-found": "404 side blev ikke fundet",
|
||||
"take-me-home": "Tag mig hjem"
|
||||
},
|
||||
"new-recipe": {
|
||||
"from-url": "Fra URL",
|
||||
"recipe-url": "URL på opskrift",
|
||||
"url-form-hint": "Copy and paste a link from your favorite recipe website",
|
||||
"error-message": "Der opstod en fejl under indlæsning af opskriften. Tjek loggen og debug/last_recipe.json for at fejlsøge problemet.",
|
||||
"bulk-add": "Bulk Tilføj",
|
||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Indsæt dine opskriftsdata. \nHver linje behandles som et element på en liste"
|
||||
},
|
||||
"general": {
|
||||
"upload": "Upload",
|
||||
"submit": "Indsend",
|
||||
"name": "Navn",
|
||||
"settings": "Indstillinger",
|
||||
"close": "Luk",
|
||||
"save": "Gem",
|
||||
"image-file": "Billedfil",
|
||||
"update": "Opdater",
|
||||
"edit": "Rediger",
|
||||
"delete": "Slet",
|
||||
"select": "Vælg",
|
||||
"random": "Tilfældig",
|
||||
"new": "Ny",
|
||||
"create": "Opret",
|
||||
"cancel": "Annuller",
|
||||
"ok": "Ok",
|
||||
"enabled": "Aktiveret",
|
||||
"download": "Hent",
|
||||
"import": "Importere",
|
||||
"options": "Options",
|
||||
"templates": "Templates",
|
||||
"recipes": "Recipes",
|
||||
"themes": "Themes",
|
||||
"confirm": "Confirm",
|
||||
"sort": "Sort",
|
||||
"recent": "Recent",
|
||||
"sort-alphabetically": "A-Z",
|
||||
"reset": "Reset",
|
||||
"filter": "Filter",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"token": "Token",
|
||||
"field-required": "Field Required",
|
||||
"apply": "Apply",
|
||||
"current-parenthesis": "(Current)",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"about": "About"
|
||||
},
|
||||
"page": {
|
||||
"home-page": "Home Page",
|
||||
"all-recipes": "All Recipes",
|
||||
"recent": "Recent"
|
||||
},
|
||||
"user": {
|
||||
"stay-logged-in": "Forbliv logget ind",
|
||||
"email": "E-mail",
|
||||
"password": "Adgangskode",
|
||||
"sign-in": "Log ind",
|
||||
"sign-up": "Opret bruger",
|
||||
"logout": "Logout",
|
||||
"full-name": "Full Name",
|
||||
"user-group": "User Group",
|
||||
"user-password": "User Password",
|
||||
"admin": "Admin",
|
||||
"user-id": "User ID",
|
||||
"user-id-with-value": "User ID: {id}",
|
||||
"group": "Group",
|
||||
"new-user": "New User",
|
||||
"edit-user": "Edit User",
|
||||
"create-user": "Create User",
|
||||
"confirm-user-deletion": "Confirm User Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Are you sure you want to delete the user <b>{activeName} ID: {activeId}<b/>?",
|
||||
"confirm-group-deletion": "Confirm Group Deletion",
|
||||
"total-users": "Total Users",
|
||||
"total-mealplans": "Total MealPlans",
|
||||
"webhooks-enabled": "Webhooks Enabled",
|
||||
"webhook-time": "Webhook Time",
|
||||
"create-group": "Create Group",
|
||||
"sign-up-links": "Sign Up Links",
|
||||
"create-link": "Create Link",
|
||||
"link-name": "Link Name",
|
||||
"group-id-with-value": "Group ID: {groupID}",
|
||||
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
|
||||
"group-name": "Group Name",
|
||||
"confirm-link-deletion": "Confirm Link Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Are you sure you want to delete the link <b>{link}<b/>?",
|
||||
"link-id": "Link ID",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"could-not-validate-credentials": "Could Not Validate Credentials",
|
||||
"login": "Login",
|
||||
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators",
|
||||
"upload-photo": "Upload Photo",
|
||||
"reset-password": "Reset Password",
|
||||
"current-password": "Current Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password",
|
||||
"password-must-match": "Password must match",
|
||||
"e-mail-must-be-valid": "E-mail must be valid",
|
||||
"use-8-characters-or-more-for-your-password": "Use 8 characters or more for your password"
|
||||
},
|
||||
"meal-plan": {
|
||||
"shopping-list": "Shopping List",
|
||||
"dinner-this-week": "Madplan denne uge",
|
||||
"meal-planner": "Meal Planner",
|
||||
"dinner-today": "Madplan i dag",
|
||||
"planner": "Planlægger",
|
||||
"edit-meal-plan": "Rediger måltidsplan",
|
||||
"meal-plans": "Måltidsplaner",
|
||||
"create-a-new-meal-plan": "Opret en ny måltidsplan",
|
||||
"start-date": "Start dato",
|
||||
"end-date": "Slutdato",
|
||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans"
|
||||
},
|
||||
"recipe": {
|
||||
"description": "Beskrivelse",
|
||||
"ingredients": "Ingredienser",
|
||||
"categories": "Kategorier",
|
||||
"tags": "Mærker",
|
||||
"instructions": "Instruktioner",
|
||||
"step-index": "Trin: {step}",
|
||||
"recipe-name": "Opskriftens navn",
|
||||
"servings": "Portioner",
|
||||
"ingredient": "Ingrediens",
|
||||
"notes": "Bemærkninger",
|
||||
"note": "Bemærk",
|
||||
"original-url": "Oprindelig opskrift",
|
||||
"view-recipe": "Se opskrift",
|
||||
"title": "Title",
|
||||
"total-time": "Total Time",
|
||||
"prep-time": "Prep Time",
|
||||
"perform-time": "Cook Time",
|
||||
"api-extras": "API Extras",
|
||||
"object-key": "Object Key",
|
||||
"object-value": "Object Value",
|
||||
"new-key-name": "New Key Name",
|
||||
"add-key": "Add Key",
|
||||
"key-name-required": "Key Name Required",
|
||||
"no-white-space-allowed": "No White Space Allowed",
|
||||
"delete-recipe": "Delete Recipe",
|
||||
"delete-confirmation": "Are you sure you want to delete this recipe?"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "Search Mealie",
|
||||
"search-placeholder": "Search...",
|
||||
"max-results": "Max Results",
|
||||
"category-filter": "Category Filter",
|
||||
"tag-filter": "Tag Filter",
|
||||
"include": "Include",
|
||||
"exclude": "Exclude",
|
||||
"and": "And",
|
||||
"or": "Or",
|
||||
"search": "Search"
|
||||
},
|
||||
"settings": {
|
||||
"general-settings": "General Settings",
|
||||
"change-password": "Change Password",
|
||||
"admin-settings": "Admin Settings",
|
||||
"local-api": "Local API",
|
||||
"language": "Language",
|
||||
"add-a-new-theme": "Tilføj et nyt tema",
|
||||
"set-new-time": "Indstil ny tid",
|
||||
"current": "Version:",
|
||||
"latest": "Seneste:",
|
||||
"explore-the-docs": "Udforsk dokumentation",
|
||||
"contribute": "Bidrag",
|
||||
"backup-and-exports": "Backup og eksport",
|
||||
"backup-info": "Sikkerhedskopier eksporteres i standard JSON-format sammen med alle de billeder, der er gemt på filsystemet. \nI din sikkerhedskopimappe finder du en .zip-fil, der indeholder alle opskrifterne JSON og billeder fra databasen. \nDerudover, hvis du valgte en markdown-fil, gemmes disse også i .zip-filen. \nFor at importere en sikkerhedskopi skal den være placeret i din sikkerhedskopimappe. \nAutomatiske sikkerhedskopier udføres hver dag kl. 3:00.",
|
||||
"available-backups": "Available Backups",
|
||||
"theme": {
|
||||
"theme-name": "Theme Name",
|
||||
"theme-settings": "Temaindstillinger",
|
||||
"select-a-theme-from-the-dropdown-or-create-a-new-theme-note-that-the-default-theme-will-be-served-to-all-users-who-have-not-set-a-theme-preference": "Vælg et tema i rullemenuen, eller opret et nyt tema. \nBemærk, at standardtemaet serveres til alle brugere, der ikke har angivet en temapræference.",
|
||||
"dark-mode": "Mørk tilstand",
|
||||
"theme-is-required": "Tema er påkrævet",
|
||||
"primary": "Primær",
|
||||
"secondary": "Sekundær",
|
||||
"accent": "Accent",
|
||||
"success": "Succes",
|
||||
"info": "Info",
|
||||
"warning": "Advarsel",
|
||||
"error": "Fejl",
|
||||
"default-to-system": "Default to system",
|
||||
"light": "Lyst",
|
||||
"dark": "Mørkt",
|
||||
"theme": "Tema",
|
||||
"saved-color-theme": "Gemt farvetema",
|
||||
"delete-theme": "Slet tema",
|
||||
"are-you-sure-you-want-to-delete-this-theme": "Er du sikker på, at du vil slette dette tema?",
|
||||
"choose-how-mealie-looks-to-you-set-your-theme-preference-to-follow-your-system-settings-or-choose-to-use-the-light-or-dark-theme": "Vælg, hvordan Mealie ser ud for dig. \nIndstil dit tema til at følge dine systemindstillinger, eller vælg at bruge det lyse eller mørke tema.",
|
||||
"theme-name-is-required": "Theme Name is required."
|
||||
},
|
||||
"webhooks": {
|
||||
"meal-planner-webhooks": "Måltidsplanlægning 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": "Webadresserne, der er anført nedenfor, modtager webhooks, der indeholder opskriftsdataene for måltidsplanen på den planlagte dag. \nWebhooks udføres i øjeblikket på <strong> {time} </strong>",
|
||||
"test-webhooks": "Test Webhooks",
|
||||
"webhook-url": "Webhook adresse"
|
||||
},
|
||||
"new-version-available": "En ny version af Mealie er tilgængelig. <a {aContents}> Besøg repoen </a>",
|
||||
"backup": {
|
||||
"import-recipes": "Importer opskrifter",
|
||||
"import-themes": "Importer temaer",
|
||||
"import-settings": "Importindstillinger",
|
||||
"create-heading": "Create a Backup",
|
||||
"backup-tag": "Backup Tag",
|
||||
"full-backup": "Full Backup",
|
||||
"partial-backup": "Partial Backup",
|
||||
"backup-restore-report": "Backup Restore Report",
|
||||
"successfully-imported": "Successfully Imported",
|
||||
"failed-imports": "Failed Imports"
|
||||
},
|
||||
"homepage": {
|
||||
"card-per-section": "Card Per Section",
|
||||
"homepage-categories": "Homepage Categories",
|
||||
"home-page": "Home Page",
|
||||
"all-categories": "All Categories",
|
||||
"show-recent": "Show Recent",
|
||||
"home-page-sections": "Home Page Sections"
|
||||
},
|
||||
"site-settings": "Site Settings",
|
||||
"manage-users": "Manage Users",
|
||||
"migrations": "Migrations",
|
||||
"profile": "Profile",
|
||||
"custom-pages": "Custom Pages",
|
||||
"new-page": "New Page",
|
||||
"edit-page": "Edit Page",
|
||||
"page-name": "Page Name"
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "Migrering af opskrifter",
|
||||
"failed-imports": "Mislykket import",
|
||||
"migration-report": "Migration Report",
|
||||
"successful-imports": "Successful Imports",
|
||||
"no-migration-data-available": "No Migration Data Avaiable",
|
||||
"nextcloud": {
|
||||
"title": "Nextcloud Cookbook",
|
||||
"description": "Migrate data from a Nextcloud Cookbook intance"
|
||||
},
|
||||
"chowdown": {
|
||||
"title": "Chowdown",
|
||||
"description": "Migrate data from Chowdown"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
{
|
||||
"404": {
|
||||
"page-not-found": "404 side blev ikke fundet",
|
||||
"take-me-home": "Tag mig hjem"
|
||||
},
|
||||
"new-recipe": {
|
||||
"from-url": "Fra URL",
|
||||
"recipe-url": "URL på opskrift",
|
||||
"error-message": "Der opstod en fejl under indlæsning af opskriften. Tjek loggen og debug/last_recipe.json for at fejlsøge problemet.",
|
||||
"bulk-add": "Bulk Tilføj",
|
||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Indsæt dine opskriftsdata. \nHver linje behandles som et element på en liste"
|
||||
},
|
||||
"general": {
|
||||
"submit": "Indsend",
|
||||
"name": "Navn",
|
||||
"settings": "Indstillinger",
|
||||
"cancel": "Annuller",
|
||||
"close": "Luk",
|
||||
"create": "Opret",
|
||||
"delete": "Slet",
|
||||
"edit": "Rediger",
|
||||
"enabled": "Aktiveret",
|
||||
"image-file": "Billedfil",
|
||||
"new": "Ny",
|
||||
"ok": "Ok",
|
||||
"random": "Tilfældig",
|
||||
"save": "Gem",
|
||||
"select": "Vælg",
|
||||
"update": "Opdater",
|
||||
"download": "Hent",
|
||||
"import": "Importere"
|
||||
},
|
||||
"user": {
|
||||
"email": "E-mail",
|
||||
"password": "Adgangskode",
|
||||
"sign-in": "Log ind",
|
||||
"sign-up": "Opret bruger",
|
||||
"stay-logged-in": "Forbliv logget ind"
|
||||
},
|
||||
"meal-plan": {
|
||||
"dinner-this-week": "Madplan denne uge",
|
||||
"dinner-today": "Madplan i dag",
|
||||
"planner": "Planlægger",
|
||||
"create-a-new-meal-plan": "Opret en ny måltidsplan",
|
||||
"edit-meal-plan": "Rediger måltidsplan",
|
||||
"end-date": "Slutdato",
|
||||
"meal-plans": "Måltidsplaner",
|
||||
"start-date": "Start dato"
|
||||
},
|
||||
"recipe": {
|
||||
"description": "Beskrivelse",
|
||||
"categories": "Kategorier",
|
||||
"ingredient": "Ingrediens",
|
||||
"ingredients": "Ingredienser",
|
||||
"instructions": "Instruktioner",
|
||||
"note": "Bemærk",
|
||||
"notes": "Bemærkninger",
|
||||
"original-url": "Oprindelig opskrift",
|
||||
"recipe-name": "Opskriftens navn",
|
||||
"servings": "Portioner",
|
||||
"step-index": "Trin: {step}",
|
||||
"tags": "Mærker",
|
||||
"view-recipe": "Se opskrift"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "Search Mealie"
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "Migrering af opskrifter",
|
||||
"failed-imports": "Mislykket import"
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Tilføj et nyt tema",
|
||||
"backup-and-exports": "Backup og eksport",
|
||||
"backup-info": "Sikkerhedskopier eksporteres i standard JSON-format sammen med alle de billeder, der er gemt på filsystemet. \nI din sikkerhedskopimappe finder du en .zip-fil, der indeholder alle opskrifterne JSON og billeder fra databasen. \nDerudover, hvis du valgte en markdown-fil, gemmes disse også i .zip-filen. \nFor at importere en sikkerhedskopi skal den være placeret i din sikkerhedskopimappe. \nAutomatiske sikkerhedskopier udføres hver dag kl. 3:00.",
|
||||
"contribute": "Bidrag",
|
||||
"explore-the-docs": "Udforsk dokumentation",
|
||||
"new-version-available": "En ny version af Mealie er tilgængelig. <a {aContents}> Besøg repoen </a>",
|
||||
"set-new-time": "Indstil ny tid",
|
||||
"current": "Version:",
|
||||
"latest": "Seneste:",
|
||||
"theme": {
|
||||
"accent": "Accent",
|
||||
"dark-mode": "Mørk tilstand",
|
||||
"error": "Fejl",
|
||||
"info": "Info",
|
||||
"primary": "Primær",
|
||||
"secondary": "Sekundær",
|
||||
"select-a-theme-from-the-dropdown-or-create-a-new-theme-note-that-the-default-theme-will-be-served-to-all-users-who-have-not-set-a-theme-preference": "Vælg et tema i rullemenuen, eller opret et nyt tema. \nBemærk, at standardtemaet serveres til alle brugere, der ikke har angivet en temapræference.",
|
||||
"success": "Succes",
|
||||
"theme-is-required": "Tema er påkrævet",
|
||||
"theme-settings": "Temaindstillinger",
|
||||
"warning": "Advarsel",
|
||||
"are-you-sure-you-want-to-delete-this-theme": "Er du sikker på, at du vil slette dette tema?",
|
||||
"choose-how-mealie-looks-to-you-set-your-theme-preference-to-follow-your-system-settings-or-choose-to-use-the-light-or-dark-theme": "Vælg, hvordan Mealie ser ud for dig. \nIndstil dit tema til at følge dine systemindstillinger, eller vælg at bruge det lyse eller mørke tema.",
|
||||
"dark": "Mørkt",
|
||||
"delete-theme": "Slet tema",
|
||||
"light": "Lyst",
|
||||
"saved-color-theme": "Gemt farvetema",
|
||||
"theme": "Tema"
|
||||
},
|
||||
"webhooks": {
|
||||
"meal-planner-webhooks": "Måltidsplanlægning 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": "Webadresserne, der er anført nedenfor, modtager webhooks, der indeholder opskriftsdataene for måltidsplanen på den planlagte dag. \nWebhooks udføres i øjeblikket på <strong> {time} </strong>",
|
||||
"webhook-url": "Webhook adresse"
|
||||
},
|
||||
"backup": {
|
||||
"import-recipes": "Importer opskrifter",
|
||||
"import-settings": "Importindstillinger",
|
||||
"import-themes": "Importer temaer"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@
|
||||
"new": "Neu",
|
||||
"create": "Erstellen",
|
||||
"cancel": "Abbrechen",
|
||||
"ok": "OK",
|
||||
"ok": "Okay",
|
||||
"enabled": "Aktiviert",
|
||||
"download": "Herunterladen",
|
||||
"import": "Importieren",
|
||||
@@ -48,7 +48,8 @@
|
||||
"apply": "Anwenden",
|
||||
"current-parenthesis": "(Neueste)",
|
||||
"users": "Benutzer",
|
||||
"groups": "Gruppen"
|
||||
"groups": "Gruppen",
|
||||
"about": "Über"
|
||||
},
|
||||
"page": {
|
||||
"home-page": "Startseite",
|
||||
@@ -93,7 +94,7 @@
|
||||
"groups": "Gruppen",
|
||||
"could-not-validate-credentials": "Anmeldeinformationen konnten nicht validiert werden",
|
||||
"login": "Anmeldung",
|
||||
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators",
|
||||
"groups-can-only-be-set-by-administrators": "Gruppen können nur durch einen Administrator gesetzt werden",
|
||||
"upload-photo": "Foto hochladen",
|
||||
"reset-password": "Passwort zurücksetzen",
|
||||
"current-password": "Aktuelles Passwort",
|
||||
@@ -106,8 +107,8 @@
|
||||
"meal-plan": {
|
||||
"shopping-list": "Einkaufsliste",
|
||||
"dinner-this-week": "Essen diese Woche",
|
||||
"dinner-today": "Heutiges Essen",
|
||||
"meal-planner": "Essensplaner",
|
||||
"dinner-today": "Heutiges Essen",
|
||||
"planner": "Planer",
|
||||
"edit-meal-plan": "Essensplan bearbeiten",
|
||||
"meal-plans": "Essenspläne",
|
||||
@@ -128,7 +129,7 @@
|
||||
"ingredient": "Zutat",
|
||||
"notes": "Notizen",
|
||||
"note": "Notiz",
|
||||
"original-url": "Original URL",
|
||||
"original-url": "Ursprüngliche URL",
|
||||
"view-recipe": "Rezept anschauen",
|
||||
"title": "Titel",
|
||||
"total-time": "Gesamtzeit",
|
||||
@@ -145,7 +146,16 @@
|
||||
"delete-confirmation": "Bist du dir sicher, dass du dieses Rezept löschen möchtest?"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "Mealie durchsuchen"
|
||||
"search-mealie": "Mealie durchsuchen",
|
||||
"search-placeholder": "Suchen...",
|
||||
"max-results": "Max. Ergebnisse",
|
||||
"category-filter": "Kategoriefilter",
|
||||
"tag-filter": "Markierungs-Filter",
|
||||
"include": "Einbeziehen",
|
||||
"exclude": "Ausschließen",
|
||||
"and": "Und",
|
||||
"or": "Oder",
|
||||
"search": "Suchen"
|
||||
},
|
||||
"settings": {
|
||||
"general-settings": "Einstellungen",
|
||||
@@ -189,7 +199,7 @@
|
||||
"meal-planner-webhooks": "Essensplaner 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": "Die unten stehenden URL's erhalten Webhooks welche die Rezeptdaten für den Menüplan am geplanten Tag enthalten. Derzeit werden die Webhooks ausgeführt um",
|
||||
"test-webhooks": "Teste Webhooks",
|
||||
"webhook-url": "Webhook URL"
|
||||
"webhook-url": "Webhook-URL"
|
||||
},
|
||||
"new-version-available": "Eine neue Version von Mealie steht zur Verfügung, <a {aContents}> Besuche das Repository </a>",
|
||||
"backup": {
|
||||
@@ -215,7 +225,11 @@
|
||||
"site-settings": "Seiteneinstellungen",
|
||||
"manage-users": "Benutzer verwalten",
|
||||
"migrations": "Migrationen",
|
||||
"profile": "Profile"
|
||||
"profile": "Profil",
|
||||
"custom-pages": "Benutzerdefinierte Seiten",
|
||||
"new-page": "Neue Seite",
|
||||
"edit-page": "Seite bearbeiten",
|
||||
"page-name": "Seitenname"
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "Rezepte übertragen",
|
||||
@@ -48,7 +48,8 @@
|
||||
"apply": "Apply",
|
||||
"current-parenthesis": "(Current)",
|
||||
"users": "Users",
|
||||
"groups": "Groups"
|
||||
"groups": "Groups",
|
||||
"about": "About"
|
||||
},
|
||||
"page": {
|
||||
"home-page": "Home Page",
|
||||
@@ -145,7 +146,16 @@
|
||||
"delete-confirmation": "Are you sure you want to delete this recipe?"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "Search Mealie"
|
||||
"search-mealie": "Search Mealie",
|
||||
"search-placeholder": "Search...",
|
||||
"max-results": "Max Results",
|
||||
"category-filter": "Category Filter",
|
||||
"tag-filter": "Tag Filter",
|
||||
"include": "Include",
|
||||
"exclude": "Exclude",
|
||||
"and": "And",
|
||||
"or": "Or",
|
||||
"search": "Search"
|
||||
},
|
||||
"settings": {
|
||||
"general-settings": "General Settings",
|
||||
@@ -215,7 +225,11 @@
|
||||
"site-settings": "Site Settings",
|
||||
"manage-users": "Manage Users",
|
||||
"migrations": "Migrations",
|
||||
"profile": "Profile"
|
||||
"profile": "Profile",
|
||||
"custom-pages": "Custom Pages",
|
||||
"new-page": "New Page",
|
||||
"edit-page": "Edit Page",
|
||||
"page-name": "Page Name"
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "Recipe Migration",
|
||||
@@ -31,22 +31,25 @@
|
||||
"enabled": "Activé",
|
||||
"download": "Télécharger",
|
||||
"import": "Importer",
|
||||
"options": "Options",
|
||||
"options": "Paramètres",
|
||||
"templates": "Modèles",
|
||||
"recipes": "Recettes",
|
||||
"themes": "Thèmes",
|
||||
"confirm": "Confirmer",
|
||||
"recent": "Récent",
|
||||
"sort": "Trier",
|
||||
"recent": "Récent",
|
||||
"sort-alphabetically": "A-Z",
|
||||
"reset": "Réinitialiser",
|
||||
"filter": "Filtrer",
|
||||
"no": "Non",
|
||||
"yes": "Oui",
|
||||
"no": "Non",
|
||||
"token": "Jeton",
|
||||
"field-required": "Champ obligatoire",
|
||||
"apply": "Appliquer",
|
||||
"current-parenthesis": "(Actuel)"
|
||||
"current-parenthesis": "(Actuel)",
|
||||
"users": "Utilisateurs",
|
||||
"groups": "Groupes",
|
||||
"about": "À propos"
|
||||
},
|
||||
"page": {
|
||||
"home-page": "Accueil",
|
||||
@@ -60,45 +63,45 @@
|
||||
"sign-in": "Se connecter",
|
||||
"sign-up": "S'inscrire",
|
||||
"logout": "Déconnexion",
|
||||
"admin": "Admin",
|
||||
"edit-user": "Modifier l'utilisateur",
|
||||
"full-name": "Nom",
|
||||
"user-group": "Groupe utilisateur",
|
||||
"user-password": "Mot de passe de l'utilisateur",
|
||||
"admin": "Admin",
|
||||
"user-id": "ID utilisateur",
|
||||
"user-id-with-value": "ID utilisateur : {id}",
|
||||
"group": "Groupe",
|
||||
"new-user": "Nouvel utilisateur",
|
||||
"user-group": "Groupe utilisateur",
|
||||
"user-id": "ID utilisateur",
|
||||
"user-password": "Mot de passe de l'utilisateur",
|
||||
"edit-user": "Modifier l'utilisateur",
|
||||
"create-user": "Créer utilisateur",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Êtes-vous sûr de vouloir supprimer l'utilisateur <b>{activeName} ID : {activeId}<b/> ?",
|
||||
"confirm-user-deletion": "Confirmer la suppression",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Êtes-vous sûr de vouloir supprimer l'utilisateur <b>{activeName} ID : {activeId}<b/> ?",
|
||||
"confirm-group-deletion": "Confirmer la suppression du groupe",
|
||||
"total-users": "Nombre d'utilisateurs",
|
||||
"total-mealplans": "Nombre de repas planifiés",
|
||||
"webhooks-enabled": "Webhooks activés",
|
||||
"webhook-time": "Heure du Webhook",
|
||||
"create-group": "Créer un groupe",
|
||||
"sign-up-links": "Liens d'inscription",
|
||||
"create-link": "Créer un lien",
|
||||
"link-name": "Nom du lien",
|
||||
"group-id-with-value": "ID groupe : {groupID}",
|
||||
"are-you-sure-you-want-to-delete-the-group": "Êtes-vous sûr de vouloir supprimer <b>{groupName}<b/> ?",
|
||||
"link-name": "Nom du lien",
|
||||
"sign-up-links": "Liens d'inscription",
|
||||
"total-mealplans": "Nombre de repas planifiés",
|
||||
"total-users": "Nombre d'utilisateurs",
|
||||
"user-id-with-value": "ID utilisateur : {id}",
|
||||
"webhook-time": "Heure du Webhook",
|
||||
"webhooks-enabled": "Webhooks activés",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Êtes-vous sûr de vouloir supprimer le lien <b>{link}<b/> ?",
|
||||
"confirm-link-deletion": "Confirmer la suppresion du lien",
|
||||
"group-name": "Nom du groupe",
|
||||
"confirm-link-deletion": "Confirmer la suppresion du lien",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Êtes-vous sûr de vouloir supprimer le lien <b>{link}<b/> ?",
|
||||
"link-id": "ID du lien",
|
||||
"groups": "Groupes",
|
||||
"users": "Utilisateurs",
|
||||
"groups": "Groupes",
|
||||
"could-not-validate-credentials": "La vérification de vos identifiants a échoué",
|
||||
"login": "Connexion",
|
||||
"groups-can-only-be-set-by-administrators": "Les groupes sont assignés par les administrateurs",
|
||||
"confirm-password": "Confirmer mot de passe",
|
||||
"current-password": "Mot de passe actuel",
|
||||
"e-mail-must-be-valid": "L'e-mail doit être valide",
|
||||
"new-password": "Nouveau mot de passe",
|
||||
"password-must-match": "Les mots de passe doivent correspondre",
|
||||
"reset-password": "Réinitialiser le mot de passe",
|
||||
"upload-photo": "Importer une photo",
|
||||
"reset-password": "Réinitialiser le mot de passe",
|
||||
"current-password": "Mot de passe actuel",
|
||||
"new-password": "Nouveau mot de passe",
|
||||
"confirm-password": "Confirmer mot de passe",
|
||||
"password-must-match": "Les mots de passe doivent correspondre",
|
||||
"e-mail-must-be-valid": "L'e-mail doit être valide",
|
||||
"use-8-characters-or-more-for-your-password": "Utiliser au moins 8 caractères pour votre mot de passe"
|
||||
},
|
||||
"meal-plan": {
|
||||
@@ -120,7 +123,7 @@
|
||||
"categories": "Catégories",
|
||||
"tags": "Tags",
|
||||
"instructions": "Instructions",
|
||||
"step-index": "Etape: {step}",
|
||||
"step-index": "Étape : {step}",
|
||||
"recipe-name": "Nom de la recette",
|
||||
"servings": "Portions",
|
||||
"ingredient": "Ingrédient",
|
||||
@@ -143,7 +146,16 @@
|
||||
"delete-confirmation": "Êtes-vous sûr(e) de vouloir supprimer cette recette ?"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "Rechercher dans Mealie"
|
||||
"search-mealie": "Rechercher dans Mealie",
|
||||
"search-placeholder": "Rechercher...",
|
||||
"max-results": "Résultats max",
|
||||
"category-filter": "Filtre par catégories",
|
||||
"tag-filter": "Filtre par tags",
|
||||
"include": "Inclure",
|
||||
"exclude": "Exclure",
|
||||
"and": "Et",
|
||||
"or": "Ou",
|
||||
"search": "Rechercher"
|
||||
},
|
||||
"settings": {
|
||||
"general-settings": "Paramètres généraux",
|
||||
@@ -185,7 +197,7 @@
|
||||
},
|
||||
"webhooks": {
|
||||
"meal-planner-webhooks": "Webhooks du planificateur de repas",
|
||||
"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 plan de menu du jour défini. Actuellement, les webhooks s'executeront à <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": "Les liens dans cette liste recevront les webhooks contenant les recettes pour le plan de menu du jour défini. Actuellement, les webhooks s'exécuteront à",
|
||||
"test-webhooks": "Tester les webhooks",
|
||||
"webhook-url": "Lien du webhook"
|
||||
},
|
||||
@@ -203,17 +215,21 @@
|
||||
"failed-imports": "Importations échouées"
|
||||
},
|
||||
"homepage": {
|
||||
"all-categories": "Toutes les catégories",
|
||||
"card-per-section": "Tuiles par section",
|
||||
"home-page": "Page d'accueil",
|
||||
"homepage-categories": "Catégories de la page d'accueil",
|
||||
"home-page": "Page d'accueil",
|
||||
"all-categories": "Toutes les catégories",
|
||||
"show-recent": "Afficher les récentes",
|
||||
"home-page-sections": "Sections de la page d'accueil"
|
||||
},
|
||||
"site-settings": "Paramètres site",
|
||||
"manage-users": "Utilisateurs",
|
||||
"migrations": "Migrations",
|
||||
"profile": "Profil",
|
||||
"site-settings": "Paramètres site"
|
||||
"custom-pages": "Pages personnalisées",
|
||||
"new-page": "Nouvelle page",
|
||||
"edit-page": "Modifier la page",
|
||||
"page-name": "Nom de la page"
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "Migrer les recettes",
|
||||
@@ -229,6 +245,5 @@
|
||||
"title": "Chowdown",
|
||||
"description": "Importer des recettes depuis Chowdown"
|
||||
}
|
||||
},
|
||||
"auth": {}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
"new-recipe": {
|
||||
"from-url": "Z odnośnika",
|
||||
"recipe-url": "Odnośnik przepisu",
|
||||
"url-form-hint": "Copy and paste a link from your favorite recipe website",
|
||||
"error-message": "Wygląda na to, że wystąpił błąd. Sprawdź log i debug/last_recipe.json aby zasięgnąć po więcej informacji.",
|
||||
"bulk-add": "Dodanie zbiorcze",
|
||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Przeklej zawartość przepisu. Każda indywidualna linia traktowana będzie jako pozycja na liście"
|
||||
@@ -34,24 +35,87 @@
|
||||
"templates": "Szablony",
|
||||
"recipes": "Przepisy",
|
||||
"themes": "Motywy",
|
||||
"confirm": "Potwierdź"
|
||||
"confirm": "Potwierdź",
|
||||
"sort": "Sort",
|
||||
"recent": "Recent",
|
||||
"sort-alphabetically": "A-Z",
|
||||
"reset": "Reset",
|
||||
"filter": "Filter",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"token": "Token",
|
||||
"field-required": "Field Required",
|
||||
"apply": "Apply",
|
||||
"current-parenthesis": "(Current)",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"about": "About"
|
||||
},
|
||||
"page": {
|
||||
"home-page": "Home Page",
|
||||
"all-recipes": "All Recipes",
|
||||
"recent": "Recent"
|
||||
},
|
||||
"user": {
|
||||
"stay-logged-in": "Pozostań zalogowany",
|
||||
"email": "Email",
|
||||
"password": "Hasło",
|
||||
"sign-in": "Zaloguj się",
|
||||
"sign-up": "Zarejestruj się"
|
||||
"sign-up": "Zarejestruj się",
|
||||
"logout": "Logout",
|
||||
"full-name": "Full Name",
|
||||
"user-group": "User Group",
|
||||
"user-password": "User Password",
|
||||
"admin": "Admin",
|
||||
"user-id": "User ID",
|
||||
"user-id-with-value": "User ID: {id}",
|
||||
"group": "Group",
|
||||
"new-user": "New User",
|
||||
"edit-user": "Edit User",
|
||||
"create-user": "Create User",
|
||||
"confirm-user-deletion": "Confirm User Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Are you sure you want to delete the user <b>{activeName} ID: {activeId}<b/>?",
|
||||
"confirm-group-deletion": "Confirm Group Deletion",
|
||||
"total-users": "Total Users",
|
||||
"total-mealplans": "Total MealPlans",
|
||||
"webhooks-enabled": "Webhooks Enabled",
|
||||
"webhook-time": "Webhook Time",
|
||||
"create-group": "Create Group",
|
||||
"sign-up-links": "Sign Up Links",
|
||||
"create-link": "Create Link",
|
||||
"link-name": "Link Name",
|
||||
"group-id-with-value": "Group ID: {groupID}",
|
||||
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
|
||||
"group-name": "Group Name",
|
||||
"confirm-link-deletion": "Confirm Link Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Are you sure you want to delete the link <b>{link}<b/>?",
|
||||
"link-id": "Link ID",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"could-not-validate-credentials": "Could Not Validate Credentials",
|
||||
"login": "Login",
|
||||
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators",
|
||||
"upload-photo": "Upload Photo",
|
||||
"reset-password": "Reset Password",
|
||||
"current-password": "Current Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password",
|
||||
"password-must-match": "Password must match",
|
||||
"e-mail-must-be-valid": "E-mail must be valid",
|
||||
"use-8-characters-or-more-for-your-password": "Use 8 characters or more for your password"
|
||||
},
|
||||
"meal-plan": {
|
||||
"shopping-list": "Shopping List",
|
||||
"dinner-this-week": "Obiad w tym tygodniu",
|
||||
"meal-planner": "Meal Planner",
|
||||
"dinner-today": "Obiad dziś",
|
||||
"planner": "Planer",
|
||||
"edit-meal-plan": "Edytuj plan posiłku",
|
||||
"meal-plans": "Plany posiłku",
|
||||
"create-a-new-meal-plan": "Utwórz nowy plan posiłku",
|
||||
"start-date": "Data rozpoczęcia",
|
||||
"end-date": "Data zakończenia"
|
||||
"end-date": "Data zakończenia",
|
||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans"
|
||||
},
|
||||
"recipe": {
|
||||
"description": "Opis",
|
||||
@@ -82,10 +146,21 @@
|
||||
"delete-confirmation": "Czy jesteś pewien, że chcesz usunąć ten przepis?"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "Przeszukaj Mealie"
|
||||
"search-mealie": "Przeszukaj Mealie",
|
||||
"search-placeholder": "Search...",
|
||||
"max-results": "Max Results",
|
||||
"category-filter": "Category Filter",
|
||||
"tag-filter": "Tag Filter",
|
||||
"include": "Include",
|
||||
"exclude": "Exclude",
|
||||
"and": "And",
|
||||
"or": "Or",
|
||||
"search": "Search"
|
||||
},
|
||||
"settings": {
|
||||
"general-settings": "Ustawienia główne",
|
||||
"change-password": "Change Password",
|
||||
"admin-settings": "Admin Settings",
|
||||
"local-api": "Lokalne API",
|
||||
"language": "Język",
|
||||
"add-a-new-theme": "Dodaj nowy motyw",
|
||||
@@ -138,7 +213,23 @@
|
||||
"backup-restore-report": "Raport przywrócenia kopii zapasowej",
|
||||
"successfully-imported": "Import zakończony suckesem",
|
||||
"failed-imports": "Importy nieudane"
|
||||
}
|
||||
},
|
||||
"homepage": {
|
||||
"card-per-section": "Card Per Section",
|
||||
"homepage-categories": "Homepage Categories",
|
||||
"home-page": "Home Page",
|
||||
"all-categories": "All Categories",
|
||||
"show-recent": "Show Recent",
|
||||
"home-page-sections": "Home Page Sections"
|
||||
},
|
||||
"site-settings": "Site Settings",
|
||||
"manage-users": "Manage Users",
|
||||
"migrations": "Migrations",
|
||||
"profile": "Profile",
|
||||
"custom-pages": "Custom Pages",
|
||||
"new-page": "New Page",
|
||||
"edit-page": "Edit Page",
|
||||
"page-name": "Page Name"
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "Przenoszenie przepisów",
|
||||
@@ -6,7 +6,8 @@
|
||||
"new-recipe": {
|
||||
"from-url": "Do URL",
|
||||
"recipe-url": "URL da Receita",
|
||||
"error-message": "Ocorreu um erro ao ler o URL. Verifica os registos e o debug/last_recipe.json para perceber o que correu mal." ,
|
||||
"url-form-hint": "Copy and paste a link from your favorite recipe website",
|
||||
"error-message": "Ocorreu um erro ao ler o URL. Verifica os registos e o debug/last_recipe.json para perceber o que correu mal.",
|
||||
"bulk-add": "Adicionar Vários",
|
||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "Insira os dados da sua receita. Cada linha será tratada como um item numa lista."
|
||||
},
|
||||
@@ -34,14 +35,74 @@
|
||||
"templates": "Templates",
|
||||
"recipes": "Receitas",
|
||||
"themes": "Temas",
|
||||
"confirm": "Confirmar"
|
||||
"confirm": "Confirmar",
|
||||
"sort": "Sort",
|
||||
"recent": "Recent",
|
||||
"sort-alphabetically": "A-Z",
|
||||
"reset": "Reset",
|
||||
"filter": "Filter",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"token": "Token",
|
||||
"field-required": "Field Required",
|
||||
"apply": "Apply",
|
||||
"current-parenthesis": "(Current)",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"about": "About"
|
||||
},
|
||||
"login": {
|
||||
"stay-logged-in": "Manter a sessão iniciada?",
|
||||
"page": {
|
||||
"home-page": "Home Page",
|
||||
"all-recipes": "All Recipes",
|
||||
"recent": "Recent"
|
||||
},
|
||||
"user": {
|
||||
"stay-logged-in": "Stay logged in?",
|
||||
"email": "Email",
|
||||
"password": "Password",
|
||||
"sign-in": "Iniciar Sessão",
|
||||
"sign-up": "Criar Conta"
|
||||
"sign-in": "Sign in",
|
||||
"sign-up": "Sign up",
|
||||
"logout": "Logout",
|
||||
"full-name": "Full Name",
|
||||
"user-group": "User Group",
|
||||
"user-password": "User Password",
|
||||
"admin": "Admin",
|
||||
"user-id": "User ID",
|
||||
"user-id-with-value": "User ID: {id}",
|
||||
"group": "Group",
|
||||
"new-user": "New User",
|
||||
"edit-user": "Edit User",
|
||||
"create-user": "Create User",
|
||||
"confirm-user-deletion": "Confirm User Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Are you sure you want to delete the user <b>{activeName} ID: {activeId}<b/>?",
|
||||
"confirm-group-deletion": "Confirm Group Deletion",
|
||||
"total-users": "Total Users",
|
||||
"total-mealplans": "Total MealPlans",
|
||||
"webhooks-enabled": "Webhooks Enabled",
|
||||
"webhook-time": "Webhook Time",
|
||||
"create-group": "Create Group",
|
||||
"sign-up-links": "Sign Up Links",
|
||||
"create-link": "Create Link",
|
||||
"link-name": "Link Name",
|
||||
"group-id-with-value": "Group ID: {groupID}",
|
||||
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
|
||||
"group-name": "Group Name",
|
||||
"confirm-link-deletion": "Confirm Link Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Are you sure you want to delete the link <b>{link}<b/>?",
|
||||
"link-id": "Link ID",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"could-not-validate-credentials": "Could Not Validate Credentials",
|
||||
"login": "Login",
|
||||
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators",
|
||||
"upload-photo": "Upload Photo",
|
||||
"reset-password": "Reset Password",
|
||||
"current-password": "Current Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password",
|
||||
"password-must-match": "Password must match",
|
||||
"e-mail-must-be-valid": "E-mail must be valid",
|
||||
"use-8-characters-or-more-for-your-password": "Use 8 characters or more for your password"
|
||||
},
|
||||
"meal-plan": {
|
||||
"shopping-list": "Lista de Compras",
|
||||
@@ -53,7 +114,8 @@
|
||||
"meal-plans": "Planos de Refeições",
|
||||
"create-a-new-meal-plan": "Criar novo Plano de Refeições",
|
||||
"start-date": "Data de Inicio",
|
||||
"end-date": "Data de Fim"
|
||||
"end-date": "Data de Fim",
|
||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans"
|
||||
},
|
||||
"recipe": {
|
||||
"description": "Descrição",
|
||||
@@ -84,10 +146,21 @@
|
||||
"delete-confirmation": "Tem a certeza que deseja eliminar esta receita?"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "Pesquisar Mealie"
|
||||
"search-mealie": "Pesquisar Mealie",
|
||||
"search-placeholder": "Search...",
|
||||
"max-results": "Max Results",
|
||||
"category-filter": "Category Filter",
|
||||
"tag-filter": "Tag Filter",
|
||||
"include": "Include",
|
||||
"exclude": "Exclude",
|
||||
"and": "And",
|
||||
"or": "Or",
|
||||
"search": "Search"
|
||||
},
|
||||
"settings": {
|
||||
"general-settings": "Definições Gerais",
|
||||
"change-password": "Change Password",
|
||||
"admin-settings": "Admin Settings",
|
||||
"local-api": "API Local",
|
||||
"language": "Língua",
|
||||
"add-a-new-theme": "Adicionar novo tema",
|
||||
@@ -140,7 +213,23 @@
|
||||
"backup-restore-report": "Análise do Resultado do Backup",
|
||||
"successfully-imported": "Importado com Sucesso",
|
||||
"failed-imports": "Importações falhadas"
|
||||
}
|
||||
},
|
||||
"homepage": {
|
||||
"card-per-section": "Card Per Section",
|
||||
"homepage-categories": "Homepage Categories",
|
||||
"home-page": "Home Page",
|
||||
"all-categories": "All Categories",
|
||||
"show-recent": "Show Recent",
|
||||
"home-page-sections": "Home Page Sections"
|
||||
},
|
||||
"site-settings": "Site Settings",
|
||||
"manage-users": "Manage Users",
|
||||
"migrations": "Migrations",
|
||||
"profile": "Profile",
|
||||
"custom-pages": "Custom Pages",
|
||||
"new-page": "New Page",
|
||||
"edit-page": "Edit Page",
|
||||
"page-name": "Page Name"
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "Migração da Receita",
|
||||
249
frontend/src/locales/messages/sv-SE.json
Normal file
249
frontend/src/locales/messages/sv-SE.json
Normal file
@@ -0,0 +1,249 @@
|
||||
{
|
||||
"404": {
|
||||
"page-not-found": "404 sidan kan inte hittas",
|
||||
"take-me-home": "Ta mig hem"
|
||||
},
|
||||
"new-recipe": {
|
||||
"from-url": "Från länk",
|
||||
"recipe-url": "Recept URL",
|
||||
"url-form-hint": "Copy and paste a link from your favorite recipe website",
|
||||
"error-message": "Ett fel uppstod när receptet skulle läsas in. Undersök loggen och debug/last_recipe.json för att felsöka problemet.",
|
||||
"bulk-add": "Lägg till flera",
|
||||
"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"
|
||||
},
|
||||
"general": {
|
||||
"upload": "Upload",
|
||||
"submit": "Skicka",
|
||||
"name": "Namn",
|
||||
"settings": "Inställningar",
|
||||
"close": "Stäng",
|
||||
"save": "Spara",
|
||||
"image-file": "Bildfil",
|
||||
"update": "Uppdatera",
|
||||
"edit": "Redigera",
|
||||
"delete": "Ta bort",
|
||||
"select": "Välj",
|
||||
"random": "Slumpa",
|
||||
"new": "Ny",
|
||||
"create": "Skapa",
|
||||
"cancel": "Avbryt",
|
||||
"ok": "Ok",
|
||||
"enabled": "Aktiverad",
|
||||
"download": "Ladda ner",
|
||||
"import": "Importera",
|
||||
"options": "Options",
|
||||
"templates": "Templates",
|
||||
"recipes": "Recipes",
|
||||
"themes": "Themes",
|
||||
"confirm": "Confirm",
|
||||
"sort": "Sort",
|
||||
"recent": "Recent",
|
||||
"sort-alphabetically": "A-Z",
|
||||
"reset": "Reset",
|
||||
"filter": "Filter",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"token": "Token",
|
||||
"field-required": "Field Required",
|
||||
"apply": "Apply",
|
||||
"current-parenthesis": "(Current)",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"about": "About"
|
||||
},
|
||||
"page": {
|
||||
"home-page": "Home Page",
|
||||
"all-recipes": "All Recipes",
|
||||
"recent": "Recent"
|
||||
},
|
||||
"user": {
|
||||
"stay-logged-in": "Kom ihåg mig",
|
||||
"email": "E-mail",
|
||||
"password": "Lösenord",
|
||||
"sign-in": "Logga in",
|
||||
"sign-up": "Logga ut",
|
||||
"logout": "Logout",
|
||||
"full-name": "Full Name",
|
||||
"user-group": "User Group",
|
||||
"user-password": "User Password",
|
||||
"admin": "Admin",
|
||||
"user-id": "User ID",
|
||||
"user-id-with-value": "User ID: {id}",
|
||||
"group": "Group",
|
||||
"new-user": "New User",
|
||||
"edit-user": "Edit User",
|
||||
"create-user": "Create User",
|
||||
"confirm-user-deletion": "Confirm User Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Are you sure you want to delete the user <b>{activeName} ID: {activeId}<b/>?",
|
||||
"confirm-group-deletion": "Confirm Group Deletion",
|
||||
"total-users": "Total Users",
|
||||
"total-mealplans": "Total MealPlans",
|
||||
"webhooks-enabled": "Webhooks Enabled",
|
||||
"webhook-time": "Webhook Time",
|
||||
"create-group": "Create Group",
|
||||
"sign-up-links": "Sign Up Links",
|
||||
"create-link": "Create Link",
|
||||
"link-name": "Link Name",
|
||||
"group-id-with-value": "Group ID: {groupID}",
|
||||
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
|
||||
"group-name": "Group Name",
|
||||
"confirm-link-deletion": "Confirm Link Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Are you sure you want to delete the link <b>{link}<b/>?",
|
||||
"link-id": "Link ID",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"could-not-validate-credentials": "Could Not Validate Credentials",
|
||||
"login": "Login",
|
||||
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators",
|
||||
"upload-photo": "Upload Photo",
|
||||
"reset-password": "Reset Password",
|
||||
"current-password": "Current Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password",
|
||||
"password-must-match": "Password must match",
|
||||
"e-mail-must-be-valid": "E-mail must be valid",
|
||||
"use-8-characters-or-more-for-your-password": "Use 8 characters or more for your password"
|
||||
},
|
||||
"meal-plan": {
|
||||
"shopping-list": "Shopping List",
|
||||
"dinner-this-week": "Veckans middagar",
|
||||
"meal-planner": "Meal Planner",
|
||||
"dinner-today": "Middag idag",
|
||||
"planner": "Planeringkalender",
|
||||
"edit-meal-plan": "Redigera måltidsplan",
|
||||
"meal-plans": "Måltidsplaner",
|
||||
"create-a-new-meal-plan": "Skapa en ny måltidsplan",
|
||||
"start-date": "Startdatum",
|
||||
"end-date": "Slutdatum",
|
||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans"
|
||||
},
|
||||
"recipe": {
|
||||
"description": "Beskrivning",
|
||||
"ingredients": "Ingredienser",
|
||||
"categories": "Kategorier",
|
||||
"tags": "Taggar",
|
||||
"instructions": "Instruktioner",
|
||||
"step-index": "Steg: {step}",
|
||||
"recipe-name": "Receptets namn",
|
||||
"servings": "Portioner",
|
||||
"ingredient": "Ingrediens",
|
||||
"notes": "Anteckningar",
|
||||
"note": "Anteckning",
|
||||
"original-url": "Originalrecept",
|
||||
"view-recipe": "Visa recept",
|
||||
"title": "Title",
|
||||
"total-time": "Total Time",
|
||||
"prep-time": "Prep Time",
|
||||
"perform-time": "Cook Time",
|
||||
"api-extras": "API Extras",
|
||||
"object-key": "Object Key",
|
||||
"object-value": "Object Value",
|
||||
"new-key-name": "New Key Name",
|
||||
"add-key": "Add Key",
|
||||
"key-name-required": "Key Name Required",
|
||||
"no-white-space-allowed": "No White Space Allowed",
|
||||
"delete-recipe": "Delete Recipe",
|
||||
"delete-confirmation": "Are you sure you want to delete this recipe?"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "Search Mealie",
|
||||
"search-placeholder": "Search...",
|
||||
"max-results": "Max Results",
|
||||
"category-filter": "Category Filter",
|
||||
"tag-filter": "Tag Filter",
|
||||
"include": "Include",
|
||||
"exclude": "Exclude",
|
||||
"and": "And",
|
||||
"or": "Or",
|
||||
"search": "Search"
|
||||
},
|
||||
"settings": {
|
||||
"general-settings": "General Settings",
|
||||
"change-password": "Change Password",
|
||||
"admin-settings": "Admin Settings",
|
||||
"local-api": "Local API",
|
||||
"language": "Language",
|
||||
"add-a-new-theme": "Lägg till ett nytt tema",
|
||||
"set-new-time": "Välj ny tid",
|
||||
"current": "Version:",
|
||||
"latest": "Senaste",
|
||||
"explore-the-docs": "Utforska dokumentationen",
|
||||
"contribute": "Bidra",
|
||||
"backup-and-exports": "Backups",
|
||||
"backup-info": "Säkerhetskopior exporteras i JSON-format tillsammans med de bilder som finns i systemet. I din mapp för säkerhetskopior finner du en zip-fil som innehåller alla recept i JSON samt bilder från databasen. Om du dessutom valde att exportera till markdown så hittas också de i samma zip-fil. För att importera en säkerhetskopia så måste den ligga i din backup-mapp. Automatisk säkerhetskopiering genomförs varje dag kl. 03:00.",
|
||||
"available-backups": "Available Backups",
|
||||
"theme": {
|
||||
"theme-name": "Theme Name",
|
||||
"theme-settings": "Temainställningar",
|
||||
"select-a-theme-from-the-dropdown-or-create-a-new-theme-note-that-the-default-theme-will-be-served-to-all-users-who-have-not-set-a-theme-preference": "Välj ett tema från menyn eller skapa ett nytt. Standardtemat kommer att användas för alla användare som inte gjort något val.",
|
||||
"dark-mode": "Mörkt läge",
|
||||
"theme-is-required": "Tema krävs",
|
||||
"primary": "Primär",
|
||||
"secondary": "Sekundär",
|
||||
"accent": "Accent",
|
||||
"success": "Success",
|
||||
"info": "Info",
|
||||
"warning": "Varning",
|
||||
"error": "Error",
|
||||
"default-to-system": "Default to system",
|
||||
"light": "Ljust",
|
||||
"dark": "Mörkt",
|
||||
"theme": "Tema",
|
||||
"saved-color-theme": "Sparat färgschema",
|
||||
"delete-theme": "Radera tema",
|
||||
"are-you-sure-you-want-to-delete-this-theme": "Är du säker på att du vill radera temat?",
|
||||
"choose-how-mealie-looks-to-you-set-your-theme-preference-to-follow-your-system-settings-or-choose-to-use-the-light-or-dark-theme": "Välj hur Mealie ska se ut för dig. Låt Mealie följa dina systeminställningar, eller välj mörkt eller ljust tema.",
|
||||
"theme-name-is-required": "Theme Name is required."
|
||||
},
|
||||
"webhooks": {
|
||||
"meal-planner-webhooks": "Webhooks för denna måltidsplan",
|
||||
"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>",
|
||||
"test-webhooks": "Testa Webhooks",
|
||||
"webhook-url": "Webhook URL"
|
||||
},
|
||||
"new-version-available": "En ny version av Mealie finns tillgänglig, <a {aContents}> Besök repot </a>",
|
||||
"backup": {
|
||||
"import-recipes": "Importera recept",
|
||||
"import-themes": "Importera färgscheman",
|
||||
"import-settings": "Importera recept",
|
||||
"create-heading": "Skapa en säkerhetskopia",
|
||||
"backup-tag": "Backup tagg",
|
||||
"full-backup": "Full Backup",
|
||||
"partial-backup": "Partial Backup",
|
||||
"backup-restore-report": "Backup Restore Report",
|
||||
"successfully-imported": "Successfully Imported",
|
||||
"failed-imports": "Failed Imports"
|
||||
},
|
||||
"homepage": {
|
||||
"card-per-section": "Card Per Section",
|
||||
"homepage-categories": "Homepage Categories",
|
||||
"home-page": "Home Page",
|
||||
"all-categories": "All Categories",
|
||||
"show-recent": "Show Recent",
|
||||
"home-page-sections": "Home Page Sections"
|
||||
},
|
||||
"site-settings": "Site Settings",
|
||||
"manage-users": "Manage Users",
|
||||
"migrations": "Migrations",
|
||||
"profile": "Profile",
|
||||
"custom-pages": "Custom Pages",
|
||||
"new-page": "New Page",
|
||||
"edit-page": "Edit Page",
|
||||
"page-name": "Page Name"
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "Migrera recept",
|
||||
"failed-imports": "Misslyckade importer",
|
||||
"migration-report": "Migration Report",
|
||||
"successful-imports": "Successful Imports",
|
||||
"no-migration-data-available": "No Migration Data Avaiable",
|
||||
"nextcloud": {
|
||||
"title": "Nextcloud Cookbook",
|
||||
"description": "Migrate data from a Nextcloud Cookbook intance"
|
||||
},
|
||||
"chowdown": {
|
||||
"title": "Chowdown",
|
||||
"description": "Migrate data from Chowdown"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
{
|
||||
"404": {
|
||||
"page-not-found": "404 sidan kan inte hittas",
|
||||
"take-me-home": "Ta mig hem"
|
||||
},
|
||||
"new-recipe": {
|
||||
"from-url": "Från länk",
|
||||
"recipe-url": "Recept URL",
|
||||
"error-message": "Ett fel uppstod när receptet skulle läsas in. Undersök loggen och debug/last_recipe.json för att felsöka problemet.",
|
||||
"bulk-add": "Lägg till flera",
|
||||
"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"
|
||||
},
|
||||
"general": {
|
||||
"submit": "Skicka",
|
||||
"name": "Namn",
|
||||
"settings": "Inställningar",
|
||||
"cancel": "Avbryt",
|
||||
"close": "Stäng",
|
||||
"create": "Skapa",
|
||||
"delete": "Ta bort",
|
||||
"edit": "Redigera",
|
||||
"enabled": "Aktiverad",
|
||||
"image-file": "Bildfil",
|
||||
"new": "Ny",
|
||||
"ok": "Ok",
|
||||
"random": "Slumpa",
|
||||
"save": "Spara",
|
||||
"select": "Välj",
|
||||
"update": "Uppdatera",
|
||||
"download": "Ladda ner",
|
||||
"import": "Importera"
|
||||
},
|
||||
"user": {
|
||||
"email": "E-mail",
|
||||
"password": "Lösenord",
|
||||
"sign-in": "Logga in",
|
||||
"sign-up": "Logga ut",
|
||||
"stay-logged-in": "Kom ihåg mig"
|
||||
},
|
||||
"meal-plan": {
|
||||
"dinner-this-week": "Veckans middagar",
|
||||
"dinner-today": "Middag idag",
|
||||
"planner": "Planeringkalender",
|
||||
"create-a-new-meal-plan": "Skapa en ny måltidsplan",
|
||||
"edit-meal-plan": "Redigera måltidsplan",
|
||||
"end-date": "Slutdatum",
|
||||
"meal-plans": "Måltidsplaner",
|
||||
"start-date": "Startdatum"
|
||||
},
|
||||
"recipe": {
|
||||
"description": "Beskrivning",
|
||||
"categories": "Kategorier",
|
||||
"ingredient": "Ingrediens",
|
||||
"ingredients": "Ingredienser",
|
||||
"instructions": "Instruktioner",
|
||||
"note": "Anteckning",
|
||||
"notes": "Anteckningar",
|
||||
"original-url": "Originalrecept",
|
||||
"recipe-name": "Receptets namn",
|
||||
"servings": "Portioner",
|
||||
"step-index": "Steg: {step}",
|
||||
"tags": "Taggar",
|
||||
"view-recipe": "Visa recept"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "Search Mealie"
|
||||
},
|
||||
"settings": {
|
||||
"add-a-new-theme": "Lägg till ett nytt tema",
|
||||
"set-new-time": "Välj ny tid",
|
||||
"current": "Version:",
|
||||
"latest": "Senaste",
|
||||
"explore-the-docs": "Utforska dokumentationen",
|
||||
"contribute": "Bidra",
|
||||
"backup-and-exports": "Backups",
|
||||
"backup-info": "Säkerhetskopior exporteras i JSON-format tillsammans med de bilder som finns i systemet. I din mapp för säkerhetskopior finner du en zip-fil som innehåller alla recept i JSON samt bilder från databasen. Om du dessutom valde att exportera till markdown så hittas också de i samma zip-fil. För att importera en säkerhetskopia så måste den ligga i din backup-mapp. Automatisk säkerhetskopiering genomförs varje dag kl. 03:00.",
|
||||
"theme": {
|
||||
"theme-settings": "Temainställningar",
|
||||
"select-a-theme-from-the-dropdown-or-create-a-new-theme-note-that-the-default-theme-will-be-served-to-all-users-who-have-not-set-a-theme-preference": "Välj ett tema från menyn eller skapa ett nytt. Standardtemat kommer att användas för alla användare som inte gjort något val.",
|
||||
"dark-mode": "Mörkt läge",
|
||||
"theme-is-required": "Tema krävs",
|
||||
"primary": "Primär",
|
||||
"secondary": "Sekundär",
|
||||
"accent": "Accent",
|
||||
"success": "Success",
|
||||
"info": "Info",
|
||||
"warning": "Varning",
|
||||
"error": "Error",
|
||||
"light": "Ljust",
|
||||
"dark": "Mörkt",
|
||||
"theme": "Tema",
|
||||
"saved-color-theme": "Sparat färgschema",
|
||||
"delete-theme": "Radera tema",
|
||||
"are-you-sure-you-want-to-delete-this-theme": "Är du säker på att du vill radera temat?",
|
||||
"choose-how-mealie-looks-to-you-set-your-theme-preference-to-follow-your-system-settings-or-choose-to-use-the-light-or-dark-theme": "Välj hur Mealie ska se ut för dig. Låt Mealie följa dina systeminställningar, eller välj mörkt eller ljust tema."
|
||||
},
|
||||
"webhooks": {
|
||||
"meal-planner-webhooks": "Webhooks för denna måltidsplan",
|
||||
"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>",
|
||||
"test-webhooks": "Testa Webhooks",
|
||||
"webhook-url": "Webhook URL"
|
||||
},
|
||||
"new-version-available": "En ny version av Mealie finns tillgänglig, <a {aContents}> Besök repot </a>",
|
||||
"backup": {
|
||||
"import-recipes": "Importera recept",
|
||||
"import-themes": "Importera färgscheman",
|
||||
"import-settings": "Importera recept",
|
||||
"create-heading": "Skapa en säkerhetskopia",
|
||||
"backup-tag": "Backup tagg"
|
||||
}
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "Migrera recept",
|
||||
"failed-imports": "Misslyckade importer"
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
"new-recipe": {
|
||||
"from-url": "输入网址",
|
||||
"recipe-url": "食谱网址",
|
||||
"url-form-hint": "Copy and paste a link from your favorite recipe website",
|
||||
"error-message": "貌似在解析网址时出错。请检查log和debug/last_recipe.json文件并找寻更多有关资讯。",
|
||||
"bulk-add": "批量添加",
|
||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "请粘贴您的食谱资料。每行将被视为列表中的一项。"
|
||||
@@ -34,24 +35,87 @@
|
||||
"templates": "模板",
|
||||
"recipes": "食谱",
|
||||
"themes": "布景主题",
|
||||
"confirm": "确定"
|
||||
"confirm": "确定",
|
||||
"sort": "Sort",
|
||||
"recent": "Recent",
|
||||
"sort-alphabetically": "A-Z",
|
||||
"reset": "Reset",
|
||||
"filter": "Filter",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"token": "Token",
|
||||
"field-required": "Field Required",
|
||||
"apply": "Apply",
|
||||
"current-parenthesis": "(Current)",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"about": "About"
|
||||
},
|
||||
"page": {
|
||||
"home-page": "Home Page",
|
||||
"all-recipes": "All Recipes",
|
||||
"recent": "Recent"
|
||||
},
|
||||
"user": {
|
||||
"stay-logged-in": "保持登录状态?",
|
||||
"email": "电子邮件",
|
||||
"password": "密码",
|
||||
"sign-in": "登入",
|
||||
"sign-up": "注册"
|
||||
"sign-up": "注册",
|
||||
"logout": "Logout",
|
||||
"full-name": "Full Name",
|
||||
"user-group": "User Group",
|
||||
"user-password": "User Password",
|
||||
"admin": "Admin",
|
||||
"user-id": "User ID",
|
||||
"user-id-with-value": "User ID: {id}",
|
||||
"group": "Group",
|
||||
"new-user": "New User",
|
||||
"edit-user": "Edit User",
|
||||
"create-user": "Create User",
|
||||
"confirm-user-deletion": "Confirm User Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Are you sure you want to delete the user <b>{activeName} ID: {activeId}<b/>?",
|
||||
"confirm-group-deletion": "Confirm Group Deletion",
|
||||
"total-users": "Total Users",
|
||||
"total-mealplans": "Total MealPlans",
|
||||
"webhooks-enabled": "Webhooks Enabled",
|
||||
"webhook-time": "Webhook Time",
|
||||
"create-group": "Create Group",
|
||||
"sign-up-links": "Sign Up Links",
|
||||
"create-link": "Create Link",
|
||||
"link-name": "Link Name",
|
||||
"group-id-with-value": "Group ID: {groupID}",
|
||||
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
|
||||
"group-name": "Group Name",
|
||||
"confirm-link-deletion": "Confirm Link Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Are you sure you want to delete the link <b>{link}<b/>?",
|
||||
"link-id": "Link ID",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"could-not-validate-credentials": "Could Not Validate Credentials",
|
||||
"login": "Login",
|
||||
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators",
|
||||
"upload-photo": "Upload Photo",
|
||||
"reset-password": "Reset Password",
|
||||
"current-password": "Current Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password",
|
||||
"password-must-match": "Password must match",
|
||||
"e-mail-must-be-valid": "E-mail must be valid",
|
||||
"use-8-characters-or-more-for-your-password": "Use 8 characters or more for your password"
|
||||
},
|
||||
"meal-plan": {
|
||||
"shopping-list": "Shopping List",
|
||||
"dinner-this-week": "本周晚餐",
|
||||
"meal-planner": "Meal Planner",
|
||||
"dinner-today": "今日晚餐",
|
||||
"planner": "策划人",
|
||||
"edit-meal-plan": "编辑用餐计划",
|
||||
"meal-plans": "用餐计划",
|
||||
"create-a-new-meal-plan": "创建一个新的用餐计划",
|
||||
"start-date": "开始日期",
|
||||
"end-date": "结束日期"
|
||||
"end-date": "结束日期",
|
||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans"
|
||||
},
|
||||
"recipe": {
|
||||
"description": "描述",
|
||||
@@ -67,24 +131,38 @@
|
||||
"note": "贴士",
|
||||
"original-url": "原食谱链接",
|
||||
"view-recipe": "查看食谱",
|
||||
"add-key": "Add Key",
|
||||
"title": "标题",
|
||||
"total-time": "总时间",
|
||||
"prep-time": "准备时间",
|
||||
"perform-time": "烹饪时间 / 执行时间",
|
||||
"api-extras": "API Extras",
|
||||
"delete-confirmation": "您确定要删除此食谱吗?",
|
||||
"delete-recipe": "删除食谱",
|
||||
"key-name-required": "Key Name Required",
|
||||
"new-key-name": "New Key Name",
|
||||
"no-white-space-allowed": "No White Space Allowed",
|
||||
"object-key": "Object Key",
|
||||
"object-value": "Object Value",
|
||||
"perform-time": "烹饪时间 / 执行时间",
|
||||
"prep-time": "准备时间",
|
||||
"title": "标题",
|
||||
"total-time": "总时间"
|
||||
"new-key-name": "New Key Name",
|
||||
"add-key": "Add Key",
|
||||
"key-name-required": "Key Name Required",
|
||||
"no-white-space-allowed": "No White Space Allowed",
|
||||
"delete-recipe": "删除食谱",
|
||||
"delete-confirmation": "您确定要删除此食谱吗?"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "搜索Mealie"
|
||||
"search-mealie": "搜索Mealie",
|
||||
"search-placeholder": "Search...",
|
||||
"max-results": "Max Results",
|
||||
"category-filter": "Category Filter",
|
||||
"tag-filter": "Tag Filter",
|
||||
"include": "Include",
|
||||
"exclude": "Exclude",
|
||||
"and": "And",
|
||||
"or": "Or",
|
||||
"search": "Search"
|
||||
},
|
||||
"settings": {
|
||||
"general-settings": "基本设置",
|
||||
"change-password": "Change Password",
|
||||
"admin-settings": "Admin Settings",
|
||||
"local-api": "Local API",
|
||||
"language": "语言",
|
||||
"add-a-new-theme": "新增布景主题",
|
||||
"set-new-time": "设定新的时间",
|
||||
"current": "版本号:",
|
||||
@@ -93,7 +171,9 @@
|
||||
"contribute": "参与贡献",
|
||||
"backup-and-exports": "备份",
|
||||
"backup-info": "备份以标准JSON格式导出,并连同储存在系统文件中的所有图像。在备份文件夹中,您将找到一个.zip文件,其中包含数据库中的所有食谱JSON和图像。此外,如果您选择了Markdown文件,这些文件也将一并储存在.zip文件中。当需要要导入备份,它必须位于您的备份文件夹中。每天3:00 AM将进行自动备份。",
|
||||
"available-backups": "可用备份",
|
||||
"theme": {
|
||||
"theme-name": "主题名称",
|
||||
"theme-settings": "布景主题设置",
|
||||
"select-a-theme-from-the-dropdown-or-create-a-new-theme-note-that-the-default-theme-will-be-served-to-all-users-who-have-not-set-a-theme-preference": "从以下列表中选择一个主题或创建一个新主题。请注意,默认主题将提供给尚未设置主题首选的所有用户。",
|
||||
"dark-mode": "暗黑模式",
|
||||
@@ -105,6 +185,7 @@
|
||||
"info": "信息(Info)",
|
||||
"warning": "警告(Warning)",
|
||||
"error": "错误(Error)",
|
||||
"default-to-system": "默认为系统",
|
||||
"light": "浅色",
|
||||
"dark": "深色",
|
||||
"theme": "布景主题",
|
||||
@@ -112,8 +193,6 @@
|
||||
"delete-theme": "删除主题",
|
||||
"are-you-sure-you-want-to-delete-this-theme": "您确定要删除此主题吗?",
|
||||
"choose-how-mealie-looks-to-you-set-your-theme-preference-to-follow-your-system-settings-or-choose-to-use-the-light-or-dark-theme": "选择Mealie的外观模式。设置布景主题首选并依据您的主机系统设置,或者选择使用浅色或深色主题。",
|
||||
"default-to-system": "默认为系统",
|
||||
"theme-name": "主题名称",
|
||||
"theme-name-is-required": "主题名称是必填项。"
|
||||
},
|
||||
"webhooks": {
|
||||
@@ -129,30 +208,42 @@
|
||||
"import-settings": "导入设置",
|
||||
"create-heading": "创建备份",
|
||||
"backup-tag": "标签备份",
|
||||
"backup-restore-report": "备份还原报告",
|
||||
"failed-imports": "导入失败",
|
||||
"full-backup": "完整备份",
|
||||
"partial-backup": "部分备份",
|
||||
"successfully-imported": "成功导入"
|
||||
"backup-restore-report": "备份还原报告",
|
||||
"successfully-imported": "成功导入",
|
||||
"failed-imports": "导入失败"
|
||||
},
|
||||
"available-backups": "可用备份",
|
||||
"general-settings": "基本设置",
|
||||
"language": "语言",
|
||||
"local-api": "Local API"
|
||||
"homepage": {
|
||||
"card-per-section": "Card Per Section",
|
||||
"homepage-categories": "Homepage Categories",
|
||||
"home-page": "Home Page",
|
||||
"all-categories": "All Categories",
|
||||
"show-recent": "Show Recent",
|
||||
"home-page-sections": "Home Page Sections"
|
||||
},
|
||||
"site-settings": "Site Settings",
|
||||
"manage-users": "Manage Users",
|
||||
"migrations": "Migrations",
|
||||
"profile": "Profile",
|
||||
"custom-pages": "Custom Pages",
|
||||
"new-page": "New Page",
|
||||
"edit-page": "Edit Page",
|
||||
"page-name": "Page Name"
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "食谱迁移",
|
||||
"failed-imports": "导入失败",
|
||||
"chowdown": {
|
||||
"description": "从Chowdown迁移数据",
|
||||
"title": "Chowdown"
|
||||
},
|
||||
"migration-report": "迁移报告",
|
||||
"nextcloud": {
|
||||
"description": "从Nextcloud Cookbook迁移数据",
|
||||
"title": "Nextcloud Cookbook"
|
||||
},
|
||||
"successful-imports": "成功导入",
|
||||
"no-migration-data-available": "没有迁移数据可用",
|
||||
"successful-imports": "成功导入"
|
||||
"nextcloud": {
|
||||
"title": "Nextcloud Cookbook",
|
||||
"description": "从Nextcloud Cookbook迁移数据"
|
||||
},
|
||||
"chowdown": {
|
||||
"title": "Chowdown",
|
||||
"description": "从Chowdown迁移数据"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"new-recipe": {
|
||||
"from-url": "輸入網址",
|
||||
"recipe-url": "食譜網址",
|
||||
"url-form-hint": "Copy and paste a link from your favorite recipe website",
|
||||
"error-message": "貌似在解析網址時出錯。請檢查log和debug/last_recipe.json文件並找尋更多有關資訊。",
|
||||
"bulk-add": "批量添加",
|
||||
"paste-in-your-recipe-data-each-line-will-be-treated-as-an-item-in-a-list": "請粘貼您的食譜資料。每行將被視為列表中的一項。"
|
||||
@@ -34,24 +35,87 @@
|
||||
"templates": "模板",
|
||||
"recipes": "食譜",
|
||||
"themes": "佈景主題",
|
||||
"confirm": "確定"
|
||||
"confirm": "確定",
|
||||
"sort": "Sort",
|
||||
"recent": "Recent",
|
||||
"sort-alphabetically": "A-Z",
|
||||
"reset": "Reset",
|
||||
"filter": "Filter",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"token": "Token",
|
||||
"field-required": "Field Required",
|
||||
"apply": "Apply",
|
||||
"current-parenthesis": "(Current)",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"about": "About"
|
||||
},
|
||||
"page": {
|
||||
"home-page": "Home Page",
|
||||
"all-recipes": "All Recipes",
|
||||
"recent": "Recent"
|
||||
},
|
||||
"user": {
|
||||
"stay-logged-in": "保持登錄狀態?",
|
||||
"email": "電子郵件",
|
||||
"password": "密碼",
|
||||
"sign-in": "登入",
|
||||
"sign-up": "註冊"
|
||||
"sign-up": "註冊",
|
||||
"logout": "Logout",
|
||||
"full-name": "Full Name",
|
||||
"user-group": "User Group",
|
||||
"user-password": "User Password",
|
||||
"admin": "Admin",
|
||||
"user-id": "User ID",
|
||||
"user-id-with-value": "User ID: {id}",
|
||||
"group": "Group",
|
||||
"new-user": "New User",
|
||||
"edit-user": "Edit User",
|
||||
"create-user": "Create User",
|
||||
"confirm-user-deletion": "Confirm User Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Are you sure you want to delete the user <b>{activeName} ID: {activeId}<b/>?",
|
||||
"confirm-group-deletion": "Confirm Group Deletion",
|
||||
"total-users": "Total Users",
|
||||
"total-mealplans": "Total MealPlans",
|
||||
"webhooks-enabled": "Webhooks Enabled",
|
||||
"webhook-time": "Webhook Time",
|
||||
"create-group": "Create Group",
|
||||
"sign-up-links": "Sign Up Links",
|
||||
"create-link": "Create Link",
|
||||
"link-name": "Link Name",
|
||||
"group-id-with-value": "Group ID: {groupID}",
|
||||
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
|
||||
"group-name": "Group Name",
|
||||
"confirm-link-deletion": "Confirm Link Deletion",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Are you sure you want to delete the link <b>{link}<b/>?",
|
||||
"link-id": "Link ID",
|
||||
"users": "Users",
|
||||
"groups": "Groups",
|
||||
"could-not-validate-credentials": "Could Not Validate Credentials",
|
||||
"login": "Login",
|
||||
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators",
|
||||
"upload-photo": "Upload Photo",
|
||||
"reset-password": "Reset Password",
|
||||
"current-password": "Current Password",
|
||||
"new-password": "New Password",
|
||||
"confirm-password": "Confirm Password",
|
||||
"password-must-match": "Password must match",
|
||||
"e-mail-must-be-valid": "E-mail must be valid",
|
||||
"use-8-characters-or-more-for-your-password": "Use 8 characters or more for your password"
|
||||
},
|
||||
"meal-plan": {
|
||||
"shopping-list": "Shopping List",
|
||||
"dinner-this-week": "本週晚餐",
|
||||
"meal-planner": "Meal Planner",
|
||||
"dinner-today": "今日晚餐",
|
||||
"planner": "策劃人",
|
||||
"edit-meal-plan": "編輯用餐計劃",
|
||||
"meal-plans": "用餐計劃",
|
||||
"create-a-new-meal-plan": "創建一個新的用餐計劃",
|
||||
"start-date": "開始日期",
|
||||
"end-date": "結束日期"
|
||||
"end-date": "結束日期",
|
||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans"
|
||||
},
|
||||
"recipe": {
|
||||
"description": "描述",
|
||||
@@ -67,24 +131,38 @@
|
||||
"note": "貼士",
|
||||
"original-url": "原食譜鏈接",
|
||||
"view-recipe": "查看食譜",
|
||||
"add-key": "Add Key",
|
||||
"title": "標題",
|
||||
"total-time": "總時間",
|
||||
"prep-time": "準備時間",
|
||||
"perform-time": "烹飪時間 / 執行時間",
|
||||
"api-extras": "API Extras",
|
||||
"delete-confirmation": "您確定要刪除此食譜嗎?",
|
||||
"delete-recipe": "刪除食譜",
|
||||
"key-name-required": "Key Name Required",
|
||||
"new-key-name": "New Key Name",
|
||||
"no-white-space-allowed": "No White Space Allowed",
|
||||
"object-key": "Object Key",
|
||||
"object-value": "Object Value",
|
||||
"perform-time": "烹飪時間 / 執行時間",
|
||||
"prep-time": "準備時間",
|
||||
"title": "標題",
|
||||
"total-time": "總時間"
|
||||
"new-key-name": "New Key Name",
|
||||
"add-key": "Add Key",
|
||||
"key-name-required": "Key Name Required",
|
||||
"no-white-space-allowed": "No White Space Allowed",
|
||||
"delete-recipe": "刪除食譜",
|
||||
"delete-confirmation": "您確定要刪除此食譜嗎?"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "搜索Mealie"
|
||||
"search-mealie": "搜索Mealie",
|
||||
"search-placeholder": "Search...",
|
||||
"max-results": "Max Results",
|
||||
"category-filter": "Category Filter",
|
||||
"tag-filter": "Tag Filter",
|
||||
"include": "Include",
|
||||
"exclude": "Exclude",
|
||||
"and": "And",
|
||||
"or": "Or",
|
||||
"search": "Search"
|
||||
},
|
||||
"settings": {
|
||||
"general-settings": "基本設置",
|
||||
"change-password": "Change Password",
|
||||
"admin-settings": "Admin Settings",
|
||||
"local-api": "Local API",
|
||||
"language": "語言",
|
||||
"add-a-new-theme": "新增佈景主題",
|
||||
"set-new-time": "設定新的時間",
|
||||
"current": "版本號:",
|
||||
@@ -93,7 +171,9 @@
|
||||
"contribute": "參與貢獻",
|
||||
"backup-and-exports": "備份",
|
||||
"backup-info": "備份以標準JSON格式導出,並連同儲存在系統文件中的所有圖像。在備份文件夾中,您將找到一個.zip文件,其中包含數據庫中的所有食譜JSON和圖像。此外,如果您選擇了Markdown文件,這些文件也將一併儲存在.zip文件中。當需要要導入備份,它必須位於您的備份文件夾中。每天3:00 AM將進行自動備份。",
|
||||
"available-backups": "可用備份",
|
||||
"theme": {
|
||||
"theme-name": "主題名稱",
|
||||
"theme-settings": "佈景主題設置",
|
||||
"select-a-theme-from-the-dropdown-or-create-a-new-theme-note-that-the-default-theme-will-be-served-to-all-users-who-have-not-set-a-theme-preference": "從以下列表中選擇一個主題或創建一個新主題。請注意,默認主題將提供給尚未設置主題首選的所有用戶。",
|
||||
"dark-mode": "暗黑模式",
|
||||
@@ -105,6 +185,7 @@
|
||||
"info": "信息(Info)",
|
||||
"warning": "警告(Warning)",
|
||||
"error": "錯誤(Error)",
|
||||
"default-to-system": "默認爲系統",
|
||||
"light": "淺色",
|
||||
"dark": "深色",
|
||||
"theme": "佈景主題",
|
||||
@@ -112,8 +193,6 @@
|
||||
"delete-theme": "刪除主題",
|
||||
"are-you-sure-you-want-to-delete-this-theme": "您確定要刪除此主題嗎?",
|
||||
"choose-how-mealie-looks-to-you-set-your-theme-preference-to-follow-your-system-settings-or-choose-to-use-the-light-or-dark-theme": "選擇Mealie的外觀模式。設置佈景主題首選並依據您的主機系統設置,或者選擇使用淺色或深色主題。",
|
||||
"default-to-system": "默認爲系統",
|
||||
"theme-name": "主題名稱",
|
||||
"theme-name-is-required": "主題名稱是必填項。"
|
||||
},
|
||||
"webhooks": {
|
||||
@@ -129,30 +208,42 @@
|
||||
"import-settings": "導入設置",
|
||||
"create-heading": "創建備份",
|
||||
"backup-tag": "標籤備份",
|
||||
"backup-restore-report": "備份還原報告",
|
||||
"failed-imports": "導入失敗",
|
||||
"full-backup": "完整備份",
|
||||
"partial-backup": "部分備份",
|
||||
"successfully-imported": "成功導入"
|
||||
"backup-restore-report": "備份還原報告",
|
||||
"successfully-imported": "成功導入",
|
||||
"failed-imports": "導入失敗"
|
||||
},
|
||||
"available-backups": "可用備份",
|
||||
"general-settings": "基本設置",
|
||||
"language": "語言",
|
||||
"local-api": "Local API"
|
||||
"homepage": {
|
||||
"card-per-section": "Card Per Section",
|
||||
"homepage-categories": "Homepage Categories",
|
||||
"home-page": "Home Page",
|
||||
"all-categories": "All Categories",
|
||||
"show-recent": "Show Recent",
|
||||
"home-page-sections": "Home Page Sections"
|
||||
},
|
||||
"site-settings": "Site Settings",
|
||||
"manage-users": "Manage Users",
|
||||
"migrations": "Migrations",
|
||||
"profile": "Profile",
|
||||
"custom-pages": "Custom Pages",
|
||||
"new-page": "New Page",
|
||||
"edit-page": "Edit Page",
|
||||
"page-name": "Page Name"
|
||||
},
|
||||
"migration": {
|
||||
"recipe-migration": "食譜遷移",
|
||||
"failed-imports": "導入失敗",
|
||||
"chowdown": {
|
||||
"description": "從Chowdown遷移數據",
|
||||
"title": "Chowdown"
|
||||
},
|
||||
"migration-report": "遷移報告",
|
||||
"nextcloud": {
|
||||
"description": "從Nextcloud Cookbook遷移數據",
|
||||
"title": "Nextcloud Cookbook"
|
||||
},
|
||||
"successful-imports": "成功導入",
|
||||
"no-migration-data-available": "無遷移數據可用",
|
||||
"successful-imports": "成功導入"
|
||||
"nextcloud": {
|
||||
"title": "Nextcloud Cookbook",
|
||||
"description": "從Nextcloud Cookbook遷移數據"
|
||||
},
|
||||
"chowdown": {
|
||||
"title": "Chowdown",
|
||||
"description": "從Chowdown遷移數據"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,20 @@ const router = new VueRouter({
|
||||
mode: process.env.NODE_ENV === "production" ? "history" : "hash",
|
||||
});
|
||||
|
||||
const DEFAULT_TITLE = 'Mealie';
|
||||
const TITLE_SEPARATOR = '🍴';
|
||||
const TITLE_SUFFIX = " " + TITLE_SEPARATOR + " " + DEFAULT_TITLE;
|
||||
router.afterEach( (to) => {
|
||||
Vue.nextTick( async () => {
|
||||
if(typeof to.meta.title === 'function' ) {
|
||||
const title = await to.meta.title(to);
|
||||
document.title = title + TITLE_SUFFIX;
|
||||
} else {
|
||||
document.title = to.meta.title ? to.meta.title + TITLE_SUFFIX : DEFAULT_TITLE;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const vueApp = new Vue({
|
||||
vuetify,
|
||||
store,
|
||||
|
||||
@@ -20,6 +20,17 @@
|
||||
</v-list-item>
|
||||
</v-list-item-group>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<TheDownloadBtn
|
||||
button-text="Download Recipe JSON"
|
||||
download-url="/api/debug/last-recipe-json"
|
||||
/>
|
||||
<TheDownloadBtn
|
||||
button-text="Download Log"
|
||||
download-url="/api/debug/log"
|
||||
/>
|
||||
</v-card-actions>
|
||||
<v-divider></v-divider>
|
||||
</v-card>
|
||||
</div>
|
||||
@@ -27,7 +38,9 @@
|
||||
|
||||
<script>
|
||||
import { api } from "@/api";
|
||||
import TheDownloadBtn from "@/components/UI/TheDownloadBtn";
|
||||
export default {
|
||||
components: { TheDownloadBtn },
|
||||
data() {
|
||||
return {
|
||||
prettyInfo: [],
|
||||
|
||||
@@ -177,6 +177,7 @@ export default {
|
||||
|
||||
computed: {
|
||||
userProfileImage() {
|
||||
this.resetImage();
|
||||
return `api/users/${this.user.id}/image`;
|
||||
},
|
||||
},
|
||||
@@ -186,6 +187,9 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
resetImage() {
|
||||
this.hideImage = false;
|
||||
},
|
||||
async refreshProfile() {
|
||||
this.user = await api.users.self();
|
||||
},
|
||||
@@ -201,7 +205,7 @@ export default {
|
||||
this.$store.commit("setToken", newKey.access_token);
|
||||
this.refreshProfile();
|
||||
this.loading = false;
|
||||
this.$store.dispatch("requestUserData")
|
||||
this.$store.dispatch("requestUserData");
|
||||
},
|
||||
async changePassword() {
|
||||
this.paswordLoading = true;
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
:rating="recipeDetails.rating"
|
||||
:yields="recipeDetails.recipeYield"
|
||||
:orgURL="recipeDetails.orgURL"
|
||||
:nutrition="recipeDetails.nutrition"
|
||||
/>
|
||||
<VJsoneditor
|
||||
@error="logError()"
|
||||
@@ -151,6 +152,7 @@ export default {
|
||||
methods: {
|
||||
getImageFile(fileObject) {
|
||||
this.fileObject = fileObject;
|
||||
this.saveImage();
|
||||
},
|
||||
async getRecipeDetails() {
|
||||
this.recipeDetails = await api.recipes.requestDetails(this.currentRecipe);
|
||||
@@ -172,19 +174,21 @@ export default {
|
||||
return this.$refs.recipeEditor.validateRecipe();
|
||||
}
|
||||
},
|
||||
async saveImage() {
|
||||
if (this.fileObject) {
|
||||
await api.recipes.updateImage(this.recipeDetails.slug, this.fileObject);
|
||||
}
|
||||
this.imageKey += 1;
|
||||
},
|
||||
async saveRecipe() {
|
||||
if (this.validateRecipe()) {
|
||||
let slug = await api.recipes.update(this.recipeDetails);
|
||||
|
||||
if (this.fileObject) {
|
||||
await api.recipes.updateImage(
|
||||
this.recipeDetails.slug,
|
||||
this.fileObject
|
||||
);
|
||||
this.saveImage();
|
||||
}
|
||||
|
||||
this.form = false;
|
||||
this.imageKey += 1;
|
||||
if (slug != this.recipeDetails.slug) {
|
||||
this.$router.push(`/recipe/${slug}`);
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
mandatory
|
||||
>
|
||||
<v-btn :value="false">
|
||||
Include
|
||||
{{$t('search.include')}}
|
||||
</v-btn>
|
||||
|
||||
<v-btn :value="true">
|
||||
Exclude
|
||||
{{$t('search.exclude')}}
|
||||
</v-btn>
|
||||
</v-btn-toggle>
|
||||
<v-spacer></v-spacer>
|
||||
@@ -28,10 +28,10 @@
|
||||
mandatory
|
||||
>
|
||||
<v-btn :value="false">
|
||||
And
|
||||
{{$t('search.and')}}
|
||||
</v-btn>
|
||||
<v-btn :value="true">
|
||||
Or
|
||||
{{$t('search.or')}}
|
||||
</v-btn>
|
||||
</v-btn-toggle>
|
||||
</v-toolbar>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
v-model="searchString"
|
||||
outlined
|
||||
color="primary accent-3"
|
||||
placeholder="Placeholder"
|
||||
:placeholder="$t('search.search-placeholder')"
|
||||
append-icon="mdi-magnify"
|
||||
>
|
||||
</v-text-field>
|
||||
@@ -16,7 +16,7 @@
|
||||
<v-col cols="12" md="2" sm="12">
|
||||
<v-text-field
|
||||
class="mt-0 pt-0"
|
||||
label="Max Results"
|
||||
:label="$t('search.max-results')"
|
||||
v-model="maxResults"
|
||||
type="number"
|
||||
outlined
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<v-row dense class="mt-0 flex-row align-center justify-space-around">
|
||||
<v-col>
|
||||
<h3 class="pl-2 text-center headline">Category Filter</h3>
|
||||
<h3 class="pl-2 text-center headline">{{$t('search.category-filter')}}</h3>
|
||||
<FilterSelector class="mb-1" @update="updateCatParams" />
|
||||
<CategoryTagSelector
|
||||
:solo="true"
|
||||
@@ -36,7 +36,7 @@
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<h3 class="pl-2 text-center headline">Tag Filter</h3>
|
||||
<h3 class="pl-2 text-center headline">{{$t('search.tag-filter')}}</h3>
|
||||
<FilterSelector class="mb-1" @update="updateTagParams" />
|
||||
|
||||
<CategoryTagSelector
|
||||
|
||||
@@ -3,11 +3,16 @@ import Vuetify from "vuetify/lib";
|
||||
|
||||
Vue.use(Vuetify);
|
||||
|
||||
// language IDs should match those from VueI18n with _ instead of -
|
||||
import de_DE from 'vuetify/es5/locale/de';
|
||||
import en_US from 'vuetify/es5/locale/en';
|
||||
import fr_FR from 'vuetify/es5/locale/fr';
|
||||
import pl_PL from 'vuetify/es5/locale/pl';
|
||||
import pt_PT from 'vuetify/es5/locale/pt';
|
||||
import sv_SE from 'vuetify/es5/locale/sv';
|
||||
import zh_CN from 'vuetify/es5/locale/zh-Hans';
|
||||
import zh_TW from 'vuetify/es5/locale/zh-Hant';
|
||||
|
||||
import fr from 'vuetify/es5/locale/fr';
|
||||
import pl from 'vuetify/es5/locale/pl';
|
||||
import sv from 'vuetify/es5/locale/sv';
|
||||
import de from 'vuetify/es5/locale/de';
|
||||
|
||||
const vuetify = new Vuetify({
|
||||
theme: {
|
||||
@@ -37,9 +42,16 @@ const vuetify = new Vuetify({
|
||||
},
|
||||
lang: {
|
||||
locales: {
|
||||
fr, pl, sv, de
|
||||
de_DE,
|
||||
en_US,
|
||||
fr_FR,
|
||||
pl_PL,
|
||||
pt_PT,
|
||||
sv_SE,
|
||||
zh_CN,
|
||||
zh_TW
|
||||
},
|
||||
current: 'en',
|
||||
current: 'en_US',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import ManageUsers from "@/pages/Admin/ManageUsers";
|
||||
import Settings from "@/pages/Admin/Settings";
|
||||
import About from "@/pages/Admin/About";
|
||||
import { store } from "../store";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
export default {
|
||||
path: "/admin",
|
||||
@@ -25,35 +26,59 @@ export default {
|
||||
{
|
||||
path: "profile",
|
||||
component: Profile,
|
||||
meta: {
|
||||
title: i18n.t('settings.profile'),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
path: "backups",
|
||||
component: Backup,
|
||||
meta: {
|
||||
title: i18n.t('settings.backup-and-exports'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "themes",
|
||||
component: Theme,
|
||||
meta: {
|
||||
title: i18n.t('general.themes'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "meal-planner",
|
||||
component: MealPlanner,
|
||||
meta: {
|
||||
title: i18n.t('meal-plan.meal-planner'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "migrations",
|
||||
component: Migration,
|
||||
meta: {
|
||||
title: i18n.t('settings.migrations'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "manage-users",
|
||||
component: ManageUsers,
|
||||
meta: {
|
||||
title: i18n.t('settings.manage-users'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "settings",
|
||||
component: Settings,
|
||||
meta: {
|
||||
title: i18n.t('settings.site-settings'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "about",
|
||||
component: About,
|
||||
meta: {
|
||||
title: i18n.t('general.about'),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ import ThisWeek from "@/pages/MealPlan/ThisWeek";
|
||||
import { api } from "@/api";
|
||||
import Admin from "./admin";
|
||||
import { store } from "../store";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
export const routes = [
|
||||
{ path: "/", name: "home", component: HomePage },
|
||||
@@ -31,15 +32,43 @@ export const routes = [
|
||||
{ path: "/sign-up", redirect: "/" },
|
||||
{ path: "/sign-up/:token", component: SignUpPage },
|
||||
{ path: "/debug", component: Debug },
|
||||
{ path: "/search", component: SearchPage },
|
||||
{
|
||||
path: "/search",
|
||||
component: SearchPage,
|
||||
meta: {
|
||||
title: i18n.t('search.search'),
|
||||
},
|
||||
},
|
||||
{ path: "/recipes/all", component: AllRecipes },
|
||||
{ path: "/pages/:customPage", component: CustomPage },
|
||||
{ path: "/recipes/tag/:tag", component: TagPage },
|
||||
{ path: "/recipes/category/:category", component: CategoryPage },
|
||||
{ path: "/recipe/:recipe", component: ViewRecipe },
|
||||
{
|
||||
path: "/recipe/:recipe",
|
||||
component: ViewRecipe,
|
||||
meta: {
|
||||
title: async route => {
|
||||
const recipe = await api.recipes.requestDetails(route.params.recipe);
|
||||
return recipe.name;
|
||||
},
|
||||
}
|
||||
},
|
||||
{ path: "/new/", component: NewRecipe },
|
||||
{ path: "/meal-plan/planner", component: Planner },
|
||||
{ path: "/meal-plan/this-week", component: ThisWeek },
|
||||
{
|
||||
path: "/meal-plan/planner",
|
||||
component: Planner,
|
||||
meta: {
|
||||
title: i18n.t('meal-plan.meal-planner'),
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/meal-plan/this-week",
|
||||
component: ThisWeek,
|
||||
meta: {
|
||||
title: i18n.t('meal-plan.dinner-this-week'),
|
||||
}
|
||||
|
||||
},
|
||||
Admin,
|
||||
{
|
||||
path: "/meal-plan/today",
|
||||
|
||||
@@ -12,7 +12,7 @@ Vue.use(Vuex);
|
||||
const store = new Vuex.Store({
|
||||
plugins: [
|
||||
createPersistedState({
|
||||
paths: ["userSettings", "language", "SideSettings"],
|
||||
paths: ["userSettings", "language.lang", "siteSettings"],
|
||||
}),
|
||||
],
|
||||
modules: {
|
||||
|
||||
@@ -5,23 +5,23 @@ const state = {
|
||||
allLangs: [
|
||||
{
|
||||
name: "English",
|
||||
value: "en",
|
||||
value: "en-US",
|
||||
},
|
||||
{
|
||||
name: "Danish",
|
||||
value: "da",
|
||||
value: "da-DK",
|
||||
},
|
||||
{
|
||||
name: "French",
|
||||
value: "fr",
|
||||
value: "fr-FR",
|
||||
},
|
||||
{
|
||||
name: "Polish",
|
||||
value: "pl",
|
||||
value: "pl-PL",
|
||||
},
|
||||
{
|
||||
name: "Swedish",
|
||||
value: "sv",
|
||||
value: "sv-SE",
|
||||
},
|
||||
{
|
||||
name: "简体中文",
|
||||
@@ -33,7 +33,7 @@ const state = {
|
||||
},
|
||||
{
|
||||
name: "German",
|
||||
value: "de",
|
||||
value: "de-DE",
|
||||
},
|
||||
{
|
||||
name: "Português",
|
||||
@@ -52,7 +52,7 @@ const mutations = {
|
||||
const actions = {
|
||||
initLang({ getters }, { currentVueComponent }) {
|
||||
VueI18n.locale = getters.getActiveLang;
|
||||
currentVueComponent.$vuetify.lang.current = getters.getActiveLang;
|
||||
currentVueComponent.$vuetify.lang.current = getters.getActiveLang.replace('-', '_');
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from fastapi.logger import logger
|
||||
|
||||
from mealie.core import root_logger
|
||||
|
||||
# import utils.startup as startup
|
||||
from mealie.core.config import APP_VERSION, settings
|
||||
from mealie.routes import backup_routes, debug_routes, migration_routes, theme_routes
|
||||
from mealie.routes import backup_routes, debug_routes, migration_routes, theme_routes, utility_routes
|
||||
from mealie.routes.groups import groups
|
||||
from mealie.routes.mealplans import mealplans
|
||||
from mealie.routes.recipe import all_recipe_routes, category_routes, recipe_crud_routes, tag_routes
|
||||
from mealie.routes.site_settings import all_settings
|
||||
from mealie.routes.users import users
|
||||
|
||||
logger = root_logger.get_logger()
|
||||
|
||||
app = FastAPI(
|
||||
title="Mealie",
|
||||
description="A place for all your recipes",
|
||||
@@ -26,6 +29,7 @@ def start_scheduler():
|
||||
|
||||
def api_routers():
|
||||
# Authentication
|
||||
app.include_router(utility_routes.router)
|
||||
app.include_router(users.router)
|
||||
app.include_router(groups.router)
|
||||
# Recipes
|
||||
@@ -33,7 +37,6 @@ def api_routers():
|
||||
app.include_router(category_routes.router)
|
||||
app.include_router(tag_routes.router)
|
||||
app.include_router(recipe_crud_routes.router)
|
||||
|
||||
# Meal Routes
|
||||
app.include_router(mealplans.router)
|
||||
# Settings Routes
|
||||
@@ -50,8 +53,15 @@ api_routers()
|
||||
start_scheduler()
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
def system_startup():
|
||||
logger.info("-----SYSTEM STARTUP----- \n")
|
||||
logger.info("------APP SETTINGS------")
|
||||
logger.info(settings.json(indent=4, exclude={"SECRET", "DEFAULT_PASSWORD", "SFTP_PASSWORD", "SFTP_USERNAME"}))
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
|
||||
uvicorn.run(
|
||||
"app:app",
|
||||
host="0.0.0.0",
|
||||
@@ -60,11 +70,11 @@ def main():
|
||||
reload_dirs=["mealie"],
|
||||
debug=True,
|
||||
log_level="info",
|
||||
log_config=None,
|
||||
workers=1,
|
||||
forwarded_allow_ips="*",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info("-----SYSTEM STARTUP-----")
|
||||
main()
|
||||
|
||||
@@ -3,16 +3,19 @@ import secrets
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
|
||||
import dotenv
|
||||
from pydantic import BaseSettings, Field, validator
|
||||
|
||||
APP_VERSION = "v0.4.1"
|
||||
APP_VERSION = "v0.4.3"
|
||||
DB_VERSION = "v0.4.0"
|
||||
|
||||
CWD = Path(__file__).parent
|
||||
BASE_DIR = CWD.parent.parent
|
||||
|
||||
ENV = BASE_DIR.joinpath(".env")
|
||||
PRODUCTION = os.getenv("ENV", "False").lower() in ["true", "1"]
|
||||
|
||||
dotenv.load_dotenv(ENV)
|
||||
PRODUCTION = os.getenv("PRODUCTION", "True").lower() in ["true", "1"]
|
||||
|
||||
|
||||
def determine_data_dir(production: bool) -> Path:
|
||||
@@ -40,7 +43,6 @@ def determine_secrets(data_dir: Path, production: bool) -> str:
|
||||
|
||||
# General
|
||||
DATA_DIR = determine_data_dir(PRODUCTION)
|
||||
LOGGER_FILE = DATA_DIR.joinpath("mealie.log")
|
||||
|
||||
|
||||
class AppDirectories:
|
||||
@@ -84,7 +86,7 @@ app_dirs = AppDirectories(CWD, DATA_DIR)
|
||||
|
||||
class AppSettings(BaseSettings):
|
||||
global DATA_DIR
|
||||
PRODUCTION: bool = Field(False, env="ENV")
|
||||
PRODUCTION: bool = Field(True, env="PRODUCTION")
|
||||
IS_DEMO: bool = False
|
||||
API_PORT: int = 9000
|
||||
API_DOCS: bool = True
|
||||
@@ -115,8 +117,11 @@ class AppSettings(BaseSettings):
|
||||
return app_dirs.SQLITE_DIR.joinpath(f"mealie_{DB_VERSION}.sqlite")
|
||||
|
||||
DEFAULT_GROUP: str = "Home"
|
||||
DEFAULT_EMAIL: str = "changeme@email.com"
|
||||
DEFAULT_PASSWORD: str = "MyPassword"
|
||||
|
||||
TOKEN_TIME: int = 2 # Time in Hours
|
||||
|
||||
# Not Used!
|
||||
SFTP_USERNAME: Optional[str]
|
||||
SFTP_PASSWORD: Optional[str]
|
||||
|
||||
43
mealie/core/root_logger.py
Normal file
43
mealie/core/root_logger.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from mealie.core.config import DATA_DIR
|
||||
|
||||
LOGGER_FILE = DATA_DIR.joinpath("mealie.log")
|
||||
LOGGER_FORMAT = "%(levelname)s: \t%(message)s"
|
||||
DATE_FORMAT = "%d-%b-%y %H:%M:%S"
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format=LOGGER_FORMAT, datefmt="%d-%b-%y %H:%M:%S")
|
||||
|
||||
|
||||
def logger_init() -> logging.Logger:
|
||||
""" Returns the Root Loggin Object for Mealie """
|
||||
logger = logging.getLogger("mealie")
|
||||
logger.propagate = False
|
||||
|
||||
# File Handler
|
||||
output_file_handler = logging.FileHandler(LOGGER_FILE)
|
||||
handler_format = logging.Formatter(LOGGER_FORMAT, datefmt=DATE_FORMAT)
|
||||
output_file_handler.setFormatter(handler_format)
|
||||
|
||||
# Stdout
|
||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||
stdout_handler.setFormatter(handler_format)
|
||||
|
||||
logger.addHandler(output_file_handler)
|
||||
logger.addHandler(stdout_handler)
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
def get_logger(module=None) -> logging.Logger:
|
||||
""" Returns a child logger for mealie """
|
||||
global root_logger
|
||||
|
||||
if module is None:
|
||||
return root_logger
|
||||
|
||||
return root_logger.getChild(module)
|
||||
|
||||
|
||||
root_logger = logger_init()
|
||||
@@ -1,9 +1,10 @@
|
||||
from datetime import datetime, timedelta
|
||||
from mealie.schema.user import UserInDB
|
||||
from pathlib import Path
|
||||
|
||||
from jose import jwt
|
||||
from mealie.core.config import settings
|
||||
from mealie.db.database import db
|
||||
from mealie.schema.user import UserInDB
|
||||
from passlib.context import CryptContext
|
||||
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
@@ -12,16 +13,21 @@ ALGORITHM = "HS256"
|
||||
|
||||
def create_access_token(data: dict(), expires_delta: timedelta = None) -> str:
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=120)
|
||||
expires_delta = expires_delta or timedelta(hours=settings.TOKEN_TIME)
|
||||
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
|
||||
to_encode.update({"exp": expire})
|
||||
return jwt.encode(to_encode, settings.SECRET, algorithm=ALGORITHM)
|
||||
|
||||
|
||||
def create_file_token(file_path: Path) -> bool:
|
||||
token_data = {"file": str(file_path)}
|
||||
return create_access_token(token_data, expires_delta=timedelta(minutes=30))
|
||||
|
||||
|
||||
def authenticate_user(session, email: str, password: str) -> UserInDB:
|
||||
user: UserInDB = db.users.get(session, email, "email")
|
||||
user: UserInDB = db.users.get(session, email, "email", any_case=True)
|
||||
if not user:
|
||||
return False
|
||||
if not verify_password(password, user.password):
|
||||
|
||||
@@ -2,6 +2,7 @@ from typing import List
|
||||
|
||||
from mealie.db.models.model_base import SqlAlchemyBase
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy.orm import load_only
|
||||
from sqlalchemy.orm.session import Session
|
||||
|
||||
@@ -64,7 +65,9 @@ class BaseDocument:
|
||||
|
||||
return session.query(self.sql_model).filter_by(**{match_key: match_value}).one()
|
||||
|
||||
def get(self, session: Session, match_value: str, match_key: str = None, limit=1) -> BaseModel or List[BaseModel]:
|
||||
def get(
|
||||
self, session: Session, match_value: str, match_key: str = None, limit=1, any_case=False
|
||||
) -> BaseModel or List[BaseModel]:
|
||||
"""Retrieves an entry from the database by matching a key/value pair. If no
|
||||
key is provided the class objects primary key will be used to match against.
|
||||
|
||||
@@ -80,7 +83,13 @@ class BaseDocument:
|
||||
if match_key is None:
|
||||
match_key = self.primary_key
|
||||
|
||||
result = session.query(self.sql_model).filter_by(**{match_key: match_value}).limit(limit).all()
|
||||
if any_case:
|
||||
search_attr = getattr(self.sql_model, match_key)
|
||||
result = (
|
||||
session.query(self.sql_model).filter(func.lower(search_attr) == match_value.lower()).limit(limit).all()
|
||||
)
|
||||
else:
|
||||
result = session.query(self.sql_model).filter_by(**{match_key: match_value}).limit(limit).all()
|
||||
|
||||
if limit == 1:
|
||||
try:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user