From 1f35742d8bad8e9066cd40e7bff8f5a41c4cd2ba Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Tue, 20 Apr 2021 11:57:16 -0800 Subject: [PATCH] v0.4.3 (#326) * fix links * actually fix #238 * Feature/mkdocs version bump (#240) * fix links (#239) Co-authored-by: hay-kot * fix #238 * bump mkdocs version * light/dark toggle * light/dark mode css * API_DOCS defaults to True * disable build on push for master Co-authored-by: hay-kot * Feature/recipe viewer (#244) * fix dialog placement * markdown support in ingredients * fix line render issue * fix tag rendering bug * change ingredients to text area * no slug error * add tag pages * remove console.logs Co-authored-by: hay-kot * changelog v0.4.1 * bug/backup-download (#245) * fix blocked download * + download blocked Co-authored-by: hay-kot * Feature/meal planner (#246) * fixes duplicate recipes in meal-plan #221 * add quick week option * scope css * add mealplanner info Co-authored-by: hay-kot * Nextcloud Import Bugs - #248 (#250) * parses datetime properly + clean category - #248 * add default credentials to docs Co-authored-by: hay-kot * Add bulk import examples to docs. (#252) * Add bulk import examples to docs. * Update api-usage.md * Add Python example for bulk import. * Change IP address in API example. * Refactor/app settings (#251) * fix env setup bugs * remove unused import * fix layout issues * changelog Co-authored-by: hay-kot * env setup fixes * Feature/about api (#253) * fix settings * app info cleanup Co-authored-by: hay-kot * Feature/image minify (#256) * fix settings * app info cleanup * bottom-bar experiment * remove dup key * type hints * add dependency * updated image with query parameters * read image options * add image minification * add image minification step * alt image routes * add image minification * set mobile bar to top Co-authored-by: hay-kot * Feature/additional endpoints (#257) * new recipe summary route * add categories to cards * add pillow * show tags instead of categories * additional debug info * add todays meal image url * about page * fix reactive tag * changelog + docs * bump version Co-authored-by: hay-kot * add pillow dependencies (#258) Co-authored-by: hay-kot * Feature/search page (#259) * add pillow dependencies * advanced search page * advanced search apge * remove extra dependencies * add pre-run script Co-authored-by: hay-kot * no image assignment * advanced search * fix docker dev build * Do not force theme settings on login form (#260) * Fix docker dev db persistence (#264) * Fix docker dev db persistence * Make run.sh the only startup script for prod + dev Credits to @hay-kot for run.sh script logic * Restore dev backend initialization in non-docker setup * Make run.sh POSIX-friendly * Allow dev backend to auto-reload in Docker * Frontend Refactor + Bug Fixes * merge category and tag selector * unifiy category selector * add hint * spacing * fix nextcloud migration * simplify email validator #261 * formatting * cleanup * auto-gen * format * update run script * unified category/tag selector * rename component * Add advanced search link * remove old code * convert keywords to tags * add proper behavior on rename * proper image name association on rename * fix test cleanup * changelog * set docker comppand * minify on migration Co-authored-by: hay-kot * bug-fixes/category-tag-creator (#266) * fix category labels * set loader for migration * v0.4.1 Co-authored-by: hay-kot * Hot Fix (#269) * fix category labels * set loader for migration * v0.4.1 * reorganize API docs Co-authored-by: hay-kot * Fix some pytests (#265) * Fix encoding issue in cleaner unit test * Add VS Code task to run pytests * Fix FileExistsError when running Windows * Add Portuguese Translation (#232) * Add Portuguese Translation * add portuguese translation option * formatting * add missing } * specify absolute path * Feature/migration-rewrite (#278) * start * migration rewrite * update name * convert chowdown to new methods * refactor/remove duplicate code * refactor to unify logger + log to file * remove toolbox * Display report on UI Co-authored-by: hay-kot * refactor/image-minification (#285) * refactor image minification calls * remove nusiance logs Co-authored-by: hay-kot * feature/debug-info (#286) * rename 'ENV' to 'PRODUCTION' and default to true * set env PRODUCTION * refactor file download process * add last_recipe.json and log downloads * changelog + version bump * set env on workflows * bump version Co-authored-by: hay-kot * Basic nutrition editor (#288) * Basic nutrition editor * fix no image on scrape * nutrition display * add recipe images * update by url * new upload options Co-authored-by: hay-kot * Sanitize recipe backup filenames (#287) Fixes #275 * fix page creation fixes #290 * Display categories in sidebar if no pages set (#292) Fixes #291 * Enrich page title with context (#296) - Static pages have their own titles - The name of the recipe is displayed when viewing it * fix: translates phrase for locale de (#298) Co-authored-by: Jonas Schubert * Fix ingredient checkbox click (#305) Fixes #304 v-list-item already flips the checkbox * Localize custom pages and search page (#299) * Localize custom pages and search page * Fix FR translation for step * fixes #306 * fixes #297 * Update changelog * generate docs * fix broken upload button on migrations * docs update * bump version * fix discord link * add TOKEN_TIME and DEFAULT_EMAIL * docs * fixes #312 * fixes #314 * fixes #315 * fix language hydration * v0.4.3 docs * Crowdin integration (#319) * Fix portuguese localization files * Use 4-letter code for locales ID * Update Crowdin configuration file * Make vuetify locales match with new VueI18n standard * Fix old locale ID default setting * Hide project hierarchy from Crowdin * add dateTimeFormats to Crowdin * New Crowdin updates (#322) - Initial Merge * New translations en-US.json (French) * New translations en-US.json (French) * New translations en-US.json (Danish) * New translations en-US.json (Danish) * New translations en-US.json (German) * New translations en-US.json (German) * New translations en-US.json (Polish) * New translations en-US.json (Polish) * New translations en-US.json (Portuguese) * New translations en-US.json (Portuguese) * New translations en-US.json (Swedish) * New translations en-US.json (Swedish) * New translations en-US.json (Chinese Simplified) * New translations en-US.json (Chinese Simplified) * New translations en-US.json (Chinese Traditional) * New translations en-US.json (Chinese Traditional) * New Crowdin updates (#323) * New translations en-US.json (French) * New translations en-US.json (French) * New translations en-US.json (Danish) * New translations en-US.json (Danish) * New translations en-US.json (German) * New translations en-US.json (German) * New translations en-US.json (Polish) * New translations en-US.json (Polish) * New translations en-US.json (Portuguese) * New translations en-US.json (Portuguese) * New translations en-US.json (Swedish) * New translations en-US.json (Swedish) * New translations en-US.json (Chinese Simplified) * New translations en-US.json (Chinese Simplified) * New translations en-US.json (Chinese Traditional) * New translations en-US.json (Chinese Traditional) * New translations en-US.json (Romanian) * New translations en-US.json (Korean) * New translations en-US.json (Vietnamese) * New translations en-US.json (English) * New translations en-US.json (Ukrainian) * New translations en-US.json (Turkish) * New translations en-US.json (Serbian (Cyrillic)) * New translations en-US.json (Russian) * New translations en-US.json (Norwegian) * New translations en-US.json (Dutch) * New translations en-US.json (Japanese) * New translations en-US.json (Italian) * New translations en-US.json (Hungarian) * New translations en-US.json (Hebrew) * New translations en-US.json (Finnish) * New translations en-US.json (Greek) * New translations en-US.json (German) * New translations en-US.json (Czech) * New translations en-US.json (Catalan) * New translations en-US.json (Arabic) * New translations en-US.json (Afrikaans) * New translations en-US.json (Spanish) * New translations en-US.json (Portuguese, Brazilian) * New translations en-US.json (French) (#324) Co-authored-by: hay-kot Co-authored-by: Nat Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com> Co-authored-by: Pedro Mata Rodrigues Co-authored-by: JonasSchubert Co-authored-by: Jonas Schubert --- README.md | 2 +- crowdin.yml | 6 + docs/docs/changelog/v0.4.3.md | 14 + .../developers-guide/code-contributions.md | 2 +- .../developers-guide/starting-dev-server.md | 2 +- docs/docs/contributors/non-coders.md | 2 +- docs/docs/contributors/translating.md | 2 +- docs/docs/getting-started/install.md | 20 +- docs/docs/getting-started/introduction.md | 2 +- docs/docs/overrides/api.html | 2 +- docs/mkdocs.yml | 1 + frontend/src/api/upload.js | 2 + .../Admin/General/HomePageSettings.vue | 1 + .../Admin/Migration/MigrationCard.vue | 1 + .../Recipe/RecipeEditor/ImageUploadBtn.vue | 1 + frontend/src/components/UI/UploadBtn.vue | 3 +- frontend/src/i18n.js | 4 +- .../src/locales/dateTimeFormats/af-ZA.json | 7 + .../src/locales/dateTimeFormats/ar-SA.json | 7 + .../src/locales/dateTimeFormats/ca-ES.json | 7 + .../src/locales/dateTimeFormats/cs-CZ.json | 7 + .../src/locales/dateTimeFormats/da-DK.json | 7 + frontend/src/locales/dateTimeFormats/da.json | 7 - .../src/locales/dateTimeFormats/de-DE.json | 7 + frontend/src/locales/dateTimeFormats/de.json | 7 - .../src/locales/dateTimeFormats/el-GR.json | 7 + .../src/locales/dateTimeFormats/en-US.json | 7 + frontend/src/locales/dateTimeFormats/en.json | 7 - .../src/locales/dateTimeFormats/es-ES.json | 7 + .../src/locales/dateTimeFormats/fi-FI.json | 7 + .../src/locales/dateTimeFormats/fr-FR.json | 7 + frontend/src/locales/dateTimeFormats/fr.json | 7 - .../src/locales/dateTimeFormats/he-IL.json | 7 + .../src/locales/dateTimeFormats/hu-HU.json | 7 + .../src/locales/dateTimeFormats/it-IT.json | 7 + .../src/locales/dateTimeFormats/ja-JP.json | 7 + .../src/locales/dateTimeFormats/ko-KR.json | 7 + .../src/locales/dateTimeFormats/nl-NL.json | 7 + .../src/locales/dateTimeFormats/no-NO.json | 7 + .../src/locales/dateTimeFormats/pl-PL.json | 7 + frontend/src/locales/dateTimeFormats/pl.json | 7 - .../src/locales/dateTimeFormats/pt-BR.json | 7 + .../src/locales/dateTimeFormats/pt-PT.json | 7 + .../src/locales/dateTimeFormats/ro-RO.json | 7 + .../src/locales/dateTimeFormats/ru-RU.json | 7 + .../src/locales/dateTimeFormats/sr-SP.json | 7 + .../src/locales/dateTimeFormats/sv-SE.json | 7 + frontend/src/locales/dateTimeFormats/sv.json | 7 - .../src/locales/dateTimeFormats/tr-TR.json | 7 + .../src/locales/dateTimeFormats/uk-UA.json | 7 + .../src/locales/dateTimeFormats/vi-VN.json | 7 + .../src/locales/dateTimeFormats/zh-CN.json | 6 +- .../src/locales/dateTimeFormats/zh-TW.json | 6 +- frontend/src/locales/messages/da-DK.json | 249 ++++++++++++++++++ frontend/src/locales/messages/da.json | 114 -------- .../locales/messages/{de.json => de-DE.json} | 28 +- .../locales/messages/{en.json => en-US.json} | 0 .../locales/messages/{fr.json => fr-FR.json} | 73 +++-- .../locales/messages/{pl.json => pl-PL.json} | 101 ++++++- .../src/locales/{ => messages}/pt-PT.json | 107 +++++++- frontend/src/locales/messages/sv-SE.json | 249 ++++++++++++++++++ frontend/src/locales/messages/sv.json | 116 -------- frontend/src/locales/messages/zh-CN.json | 155 ++++++++--- frontend/src/locales/messages/zh-TW.json | 155 ++++++++--- frontend/src/pages/Admin/Profile/index.vue | 6 +- frontend/src/plugins/vuetify.js | 24 +- frontend/src/store/index.js | 2 +- frontend/src/store/modules/language.js | 14 +- mealie/core/config.py | 5 +- mealie/core/security.py | 10 +- mealie/db/db_base.py | 13 +- mealie/db/init_db.py | 2 +- mealie/routes/deps.py | 2 +- mealie/routes/users/auth.py | 4 +- mealie/routes/users/crud.py | 2 +- mealie/schema/auth.py | 6 +- mealie/schema/user.py | 5 +- template.env | 4 +- 78 files changed, 1311 insertions(+), 452 deletions(-) create mode 100644 crowdin.yml create mode 100644 docs/docs/changelog/v0.4.3.md create mode 100644 frontend/src/locales/dateTimeFormats/af-ZA.json create mode 100644 frontend/src/locales/dateTimeFormats/ar-SA.json create mode 100644 frontend/src/locales/dateTimeFormats/ca-ES.json create mode 100644 frontend/src/locales/dateTimeFormats/cs-CZ.json create mode 100644 frontend/src/locales/dateTimeFormats/da-DK.json delete mode 100644 frontend/src/locales/dateTimeFormats/da.json create mode 100644 frontend/src/locales/dateTimeFormats/de-DE.json delete mode 100644 frontend/src/locales/dateTimeFormats/de.json create mode 100644 frontend/src/locales/dateTimeFormats/el-GR.json create mode 100644 frontend/src/locales/dateTimeFormats/en-US.json delete mode 100644 frontend/src/locales/dateTimeFormats/en.json create mode 100644 frontend/src/locales/dateTimeFormats/es-ES.json create mode 100644 frontend/src/locales/dateTimeFormats/fi-FI.json create mode 100644 frontend/src/locales/dateTimeFormats/fr-FR.json delete mode 100644 frontend/src/locales/dateTimeFormats/fr.json create mode 100644 frontend/src/locales/dateTimeFormats/he-IL.json create mode 100644 frontend/src/locales/dateTimeFormats/hu-HU.json create mode 100644 frontend/src/locales/dateTimeFormats/it-IT.json create mode 100644 frontend/src/locales/dateTimeFormats/ja-JP.json create mode 100644 frontend/src/locales/dateTimeFormats/ko-KR.json create mode 100644 frontend/src/locales/dateTimeFormats/nl-NL.json create mode 100644 frontend/src/locales/dateTimeFormats/no-NO.json create mode 100644 frontend/src/locales/dateTimeFormats/pl-PL.json delete mode 100644 frontend/src/locales/dateTimeFormats/pl.json create mode 100644 frontend/src/locales/dateTimeFormats/pt-BR.json create mode 100644 frontend/src/locales/dateTimeFormats/pt-PT.json create mode 100644 frontend/src/locales/dateTimeFormats/ro-RO.json create mode 100644 frontend/src/locales/dateTimeFormats/ru-RU.json create mode 100644 frontend/src/locales/dateTimeFormats/sr-SP.json create mode 100644 frontend/src/locales/dateTimeFormats/sv-SE.json delete mode 100644 frontend/src/locales/dateTimeFormats/sv.json create mode 100644 frontend/src/locales/dateTimeFormats/tr-TR.json create mode 100644 frontend/src/locales/dateTimeFormats/uk-UA.json create mode 100644 frontend/src/locales/dateTimeFormats/vi-VN.json create mode 100644 frontend/src/locales/messages/da-DK.json delete mode 100644 frontend/src/locales/messages/da.json rename frontend/src/locales/messages/{de.json => de-DE.json} (94%) rename frontend/src/locales/messages/{en.json => en-US.json} (100%) rename frontend/src/locales/messages/{fr.json => fr-FR.json} (99%) rename frontend/src/locales/messages/{pl.json => pl-PL.json} (64%) rename frontend/src/locales/{ => messages}/pt-PT.json (64%) create mode 100644 frontend/src/locales/messages/sv-SE.json delete mode 100644 frontend/src/locales/messages/sv.json diff --git a/README.md b/README.md index e2a66b4e..3866eb43 100644 --- a/README.md +++ b/README.md @@ -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)! diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 00000000..4fc75068 --- /dev/null +++ b/crowdin.yml @@ -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 diff --git a/docs/docs/changelog/v0.4.3.md b/docs/docs/changelog/v0.4.3.md new file mode 100644 index 00000000..0893c8c8 --- /dev/null +++ b/docs/docs/changelog/v0.4.3.md @@ -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 \ No newline at end of file diff --git a/docs/docs/contributors/developers-guide/code-contributions.md b/docs/docs/contributors/developers-guide/code-contributions.md index 6168a7a7..eaf9ae4e 100644 --- a/docs/docs/contributors/developers-guide/code-contributions.md +++ b/docs/docs/contributors/developers-guide/code-contributions.md @@ -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. diff --git a/docs/docs/contributors/developers-guide/starting-dev-server.md b/docs/docs/contributors/developers-guide/starting-dev-server.md index 2ec547e5..f168229c 100644 --- a/docs/docs/contributors/developers-guide/starting-dev-server.md +++ b/docs/docs/contributors/developers-guide/starting-dev-server.md @@ -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) \ No newline at end of file +Run into another issue? [Ask for help on discord](https://discord.gg/QuStdQGSGK) \ No newline at end of file diff --git a/docs/docs/contributors/non-coders.md b/docs/docs/contributors/non-coders.md index 3040cb7d..f5e8a8de 100644 --- a/docs/docs/contributors/non-coders.md +++ b/docs/docs/contributors/non-coders.md @@ -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. diff --git a/docs/docs/contributors/translating.md b/docs/docs/contributors/translating.md index fa2106cb..bf09ec62 100644 --- a/docs/docs/contributors/translating.md +++ b/docs/docs/contributors/translating.md @@ -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. \ No newline at end of file diff --git a/docs/docs/getting-started/install.md b/docs/docs/getting-started/install.md index 737d20e4..9be8f56a 100644 --- a/docs/docs/getting-started/install.md +++ b/docs/docs/getting-started/install.md @@ -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. diff --git a/docs/docs/getting-started/introduction.md b/docs/docs/getting-started/introduction.md index 2c26bf99..490cf0cd 100644 --- a/docs/docs/getting-started/introduction.md +++ b/docs/docs/getting-started/introduction.md @@ -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. diff --git a/docs/docs/overrides/api.html b/docs/docs/overrides/api.html index a22ab4c1..8d1f2e77 100644 --- a/docs/docs/overrides/api.html +++ b/docs/docs/overrides/api.html @@ -14,7 +14,7 @@
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 2b1560f6..df5127f4 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -77,6 +77,7 @@ 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" diff --git a/frontend/src/api/upload.js b/frontend/src/api/upload.js index 8442cc74..d5475080 100644 --- a/frontend/src/api/upload.js +++ b/frontend/src/api/upload.js @@ -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", diff --git a/frontend/src/components/Admin/General/HomePageSettings.vue b/frontend/src/components/Admin/General/HomePageSettings.vue index 800add55..91aec8a5 100644 --- a/frontend/src/components/Admin/General/HomePageSettings.vue +++ b/frontend/src/components/Admin/General/HomePageSettings.vue @@ -162,6 +162,7 @@ export default { methods: { writeLang(val) { + this.$store.commit("setLang", val); this.settings.language = val; }, deleteCategoryfromDatabase(category) { diff --git a/frontend/src/components/Admin/Migration/MigrationCard.vue b/frontend/src/components/Admin/Migration/MigrationCard.vue index f0496cac..3f5848d0 100644 --- a/frontend/src/components/Admin/Migration/MigrationCard.vue +++ b/frontend/src/components/Admin/Migration/MigrationCard.vue @@ -10,6 +10,7 @@ :url="`/api/migrations/${folder}/upload`" fileName="archive" @uploaded="$emit('refresh')" + :post="true" /> diff --git a/frontend/src/components/Recipe/RecipeEditor/ImageUploadBtn.vue b/frontend/src/components/Recipe/RecipeEditor/ImageUploadBtn.vue index d3154c84..de9f063e 100644 --- a/frontend/src/components/Recipe/RecipeEditor/ImageUploadBtn.vue +++ b/frontend/src/components/Recipe/RecipeEditor/ImageUploadBtn.vue @@ -17,6 +17,7 @@ file-name="image" :text-btn="false" @uploaded="uploadImage" + :post="false" /> diff --git a/frontend/src/components/UI/UploadBtn.vue b/frontend/src/components/UI/UploadBtn.vue index b69b8a13..8f0eb3b1 100644 --- a/frontend/src/components/UI/UploadBtn.vue +++ b/frontend/src/components/UI/UploadBtn.vue @@ -46,11 +46,12 @@ export default { if (this.file != null) { this.isSelecting = true; - if (this.post) { + if (!this.post) { this.$emit(UPLOAD_EVENT, this.file); this.isSelecting = false; return; } + let formData = new FormData(); formData.append(this.fileName, this.file); diff --git a/frontend/src/i18n.js b/frontend/src/i18n.js index f5320dcc..e63f45a8 100644 --- a/frontend/src/i18n.js +++ b/frontend/src/i18n.js @@ -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() }); diff --git a/frontend/src/locales/dateTimeFormats/af-ZA.json b/frontend/src/locales/dateTimeFormats/af-ZA.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/af-ZA.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/ar-SA.json b/frontend/src/locales/dateTimeFormats/ar-SA.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/ar-SA.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/ca-ES.json b/frontend/src/locales/dateTimeFormats/ca-ES.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/ca-ES.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/cs-CZ.json b/frontend/src/locales/dateTimeFormats/cs-CZ.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/cs-CZ.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/da-DK.json b/frontend/src/locales/dateTimeFormats/da-DK.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/da-DK.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/da.json b/frontend/src/locales/dateTimeFormats/da.json deleted file mode 100644 index a0af56a4..00000000 --- a/frontend/src/locales/dateTimeFormats/da.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "short": { - "month": "short", - "day": "numeric", - "weekday": "long" - } -} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/de-DE.json b/frontend/src/locales/dateTimeFormats/de-DE.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/de-DE.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/de.json b/frontend/src/locales/dateTimeFormats/de.json deleted file mode 100644 index a0af56a4..00000000 --- a/frontend/src/locales/dateTimeFormats/de.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "short": { - "month": "short", - "day": "numeric", - "weekday": "long" - } -} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/el-GR.json b/frontend/src/locales/dateTimeFormats/el-GR.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/el-GR.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/en-US.json b/frontend/src/locales/dateTimeFormats/en-US.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/en-US.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/en.json b/frontend/src/locales/dateTimeFormats/en.json deleted file mode 100644 index a0af56a4..00000000 --- a/frontend/src/locales/dateTimeFormats/en.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "short": { - "month": "short", - "day": "numeric", - "weekday": "long" - } -} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/es-ES.json b/frontend/src/locales/dateTimeFormats/es-ES.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/es-ES.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/fi-FI.json b/frontend/src/locales/dateTimeFormats/fi-FI.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/fi-FI.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/fr-FR.json b/frontend/src/locales/dateTimeFormats/fr-FR.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/fr-FR.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/fr.json b/frontend/src/locales/dateTimeFormats/fr.json deleted file mode 100644 index a0af56a4..00000000 --- a/frontend/src/locales/dateTimeFormats/fr.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "short": { - "month": "short", - "day": "numeric", - "weekday": "long" - } -} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/he-IL.json b/frontend/src/locales/dateTimeFormats/he-IL.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/he-IL.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/hu-HU.json b/frontend/src/locales/dateTimeFormats/hu-HU.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/hu-HU.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/it-IT.json b/frontend/src/locales/dateTimeFormats/it-IT.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/it-IT.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/ja-JP.json b/frontend/src/locales/dateTimeFormats/ja-JP.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/ja-JP.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/ko-KR.json b/frontend/src/locales/dateTimeFormats/ko-KR.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/ko-KR.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/nl-NL.json b/frontend/src/locales/dateTimeFormats/nl-NL.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/nl-NL.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/no-NO.json b/frontend/src/locales/dateTimeFormats/no-NO.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/no-NO.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/pl-PL.json b/frontend/src/locales/dateTimeFormats/pl-PL.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/pl-PL.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/pl.json b/frontend/src/locales/dateTimeFormats/pl.json deleted file mode 100644 index a0af56a4..00000000 --- a/frontend/src/locales/dateTimeFormats/pl.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "short": { - "month": "short", - "day": "numeric", - "weekday": "long" - } -} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/pt-BR.json b/frontend/src/locales/dateTimeFormats/pt-BR.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/pt-BR.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/pt-PT.json b/frontend/src/locales/dateTimeFormats/pt-PT.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/pt-PT.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/ro-RO.json b/frontend/src/locales/dateTimeFormats/ro-RO.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/ro-RO.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/ru-RU.json b/frontend/src/locales/dateTimeFormats/ru-RU.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/ru-RU.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/sr-SP.json b/frontend/src/locales/dateTimeFormats/sr-SP.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/sr-SP.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/sv-SE.json b/frontend/src/locales/dateTimeFormats/sv-SE.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/sv-SE.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/sv.json b/frontend/src/locales/dateTimeFormats/sv.json deleted file mode 100644 index a0af56a4..00000000 --- a/frontend/src/locales/dateTimeFormats/sv.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "short": { - "month": "short", - "day": "numeric", - "weekday": "long" - } -} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/tr-TR.json b/frontend/src/locales/dateTimeFormats/tr-TR.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/tr-TR.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/uk-UA.json b/frontend/src/locales/dateTimeFormats/uk-UA.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/uk-UA.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/vi-VN.json b/frontend/src/locales/dateTimeFormats/vi-VN.json new file mode 100644 index 00000000..65941802 --- /dev/null +++ b/frontend/src/locales/dateTimeFormats/vi-VN.json @@ -0,0 +1,7 @@ +{ + "short": { + "month": "short", + "day": "numeric", + "weekday": "long" + } +} \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/zh-CN.json b/frontend/src/locales/dateTimeFormats/zh-CN.json index a0af56a4..65941802 100644 --- a/frontend/src/locales/dateTimeFormats/zh-CN.json +++ b/frontend/src/locales/dateTimeFormats/zh-CN.json @@ -1,7 +1,7 @@ { "short": { - "month": "short", - "day": "numeric", - "weekday": "long" + "month": "short", + "day": "numeric", + "weekday": "long" } } \ No newline at end of file diff --git a/frontend/src/locales/dateTimeFormats/zh-TW.json b/frontend/src/locales/dateTimeFormats/zh-TW.json index a0af56a4..65941802 100644 --- a/frontend/src/locales/dateTimeFormats/zh-TW.json +++ b/frontend/src/locales/dateTimeFormats/zh-TW.json @@ -1,7 +1,7 @@ { "short": { - "month": "short", - "day": "numeric", - "weekday": "long" + "month": "short", + "day": "numeric", + "weekday": "long" } } \ No newline at end of file diff --git a/frontend/src/locales/messages/da-DK.json b/frontend/src/locales/messages/da-DK.json new file mode 100644 index 00000000..ad4c080a --- /dev/null +++ b/frontend/src/locales/messages/da-DK.json @@ -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 {activeName} ID: {activeId}?", + "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 {groupName}?", + "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 {link}?", + "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å {time} ", + "test-webhooks": "Test Webhooks", + "webhook-url": "Webhook adresse" + }, + "new-version-available": "En ny version af Mealie er tilgængelig. Besøg repoen ", + "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" + } + } +} diff --git a/frontend/src/locales/messages/da.json b/frontend/src/locales/messages/da.json deleted file mode 100644 index 3c21ecaf..00000000 --- a/frontend/src/locales/messages/da.json +++ /dev/null @@ -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. Besøg repoen ", - "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å {time} ", - "webhook-url": "Webhook adresse" - }, - "backup": { - "import-recipes": "Importer opskrifter", - "import-settings": "Importindstillinger", - "import-themes": "Importer temaer" - } - } -} diff --git a/frontend/src/locales/messages/de.json b/frontend/src/locales/messages/de-DE.json similarity index 94% rename from frontend/src/locales/messages/de.json rename to frontend/src/locales/messages/de-DE.json index 9cf70f5b..6a120776 100644 --- a/frontend/src/locales/messages/de.json +++ b/frontend/src/locales/messages/de-DE.json @@ -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", @@ -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, Besuche das Repository ", "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", diff --git a/frontend/src/locales/messages/en.json b/frontend/src/locales/messages/en-US.json similarity index 100% rename from frontend/src/locales/messages/en.json rename to frontend/src/locales/messages/en-US.json diff --git a/frontend/src/locales/messages/fr.json b/frontend/src/locales/messages/fr-FR.json similarity index 99% rename from frontend/src/locales/messages/fr.json rename to frontend/src/locales/messages/fr-FR.json index bfeba824..3b6f357d 100644 --- a/frontend/src/locales/messages/fr.json +++ b/frontend/src/locales/messages/fr-FR.json @@ -31,24 +31,24 @@ "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)", - "groups": "Groupes", "users": "Utilisateurs", + "groups": "Groupes", "about": "À propos" }, "page": { @@ -63,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 {activeName} ID : {activeId} ?", "confirm-user-deletion": "Confirmer la suppression", + "are-you-sure-you-want-to-delete-the-user": "Êtes-vous sûr de vouloir supprimer l'utilisateur {activeName} ID : {activeId} ?", "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 {groupName} ?", - "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 {link} ?", - "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 {link} ?", "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": { @@ -148,13 +148,13 @@ "search": { "search-mealie": "Rechercher dans Mealie", "search-placeholder": "Rechercher...", - "and": "Et", - "category-filter": "Filtre par catégories", - "exclude": "Exclure", - "include": "Inclure", "max-results": "Résultats max", - "or": "Ou", + "category-filter": "Filtre par catégories", "tag-filter": "Filtre par tags", + "include": "Inclure", + "exclude": "Exclure", + "and": "Et", + "or": "Ou", "search": "Rechercher" }, "settings": { @@ -215,20 +215,20 @@ "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", - "edit-page": "Modifier la page", "new-page": "Nouvelle page", + "edit-page": "Modifier la page", "page-name": "Nom de la page" }, "migration": { @@ -245,6 +245,5 @@ "title": "Chowdown", "description": "Importer des recettes depuis Chowdown" } - }, - "auth": {} + } } diff --git a/frontend/src/locales/messages/pl.json b/frontend/src/locales/messages/pl-PL.json similarity index 64% rename from frontend/src/locales/messages/pl.json rename to frontend/src/locales/messages/pl-PL.json index 0c9cd35f..8b9af4f6 100644 --- a/frontend/src/locales/messages/pl.json +++ b/frontend/src/locales/messages/pl-PL.json @@ -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 {activeName} ID: {activeId}?", + "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 {groupName}?", + "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 {link}?", + "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", diff --git a/frontend/src/locales/pt-PT.json b/frontend/src/locales/messages/pt-PT.json similarity index 64% rename from frontend/src/locales/pt-PT.json rename to frontend/src/locales/messages/pt-PT.json index d10b4343..c867c4e4 100644 --- a/frontend/src/locales/pt-PT.json +++ b/frontend/src/locales/messages/pt-PT.json @@ -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 {activeName} ID: {activeId}?", + "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 {groupName}?", + "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 {link}?", + "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", diff --git a/frontend/src/locales/messages/sv-SE.json b/frontend/src/locales/messages/sv-SE.json new file mode 100644 index 00000000..34ccc60d --- /dev/null +++ b/frontend/src/locales/messages/sv-SE.json @@ -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 {activeName} ID: {activeId}?", + "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 {groupName}?", + "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 {link}?", + "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 { time }", + "test-webhooks": "Testa Webhooks", + "webhook-url": "Webhook URL" + }, + "new-version-available": "En ny version av Mealie finns tillgänglig, Besök repot ", + "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" + } + } +} diff --git a/frontend/src/locales/messages/sv.json b/frontend/src/locales/messages/sv.json deleted file mode 100644 index e4a19203..00000000 --- a/frontend/src/locales/messages/sv.json +++ /dev/null @@ -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 { time }", - "test-webhooks": "Testa Webhooks", - "webhook-url": "Webhook URL" - }, - "new-version-available": "En ny version av Mealie finns tillgänglig, Besök repot ", - "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" - } -} diff --git a/frontend/src/locales/messages/zh-CN.json b/frontend/src/locales/messages/zh-CN.json index 1acdd16a..f2d92213 100644 --- a/frontend/src/locales/messages/zh-CN.json +++ b/frontend/src/locales/messages/zh-CN.json @@ -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 {activeName} ID: {activeId}?", + "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 {groupName}?", + "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 {link}?", + "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迁移数据" + } } } diff --git a/frontend/src/locales/messages/zh-TW.json b/frontend/src/locales/messages/zh-TW.json index 07bc98bc..9f795077 100644 --- a/frontend/src/locales/messages/zh-TW.json +++ b/frontend/src/locales/messages/zh-TW.json @@ -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 {activeName} ID: {activeId}?", + "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 {groupName}?", + "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 {link}?", + "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遷移數據" + } } } diff --git a/frontend/src/pages/Admin/Profile/index.vue b/frontend/src/pages/Admin/Profile/index.vue index 5bdf5ba3..841af08b 100644 --- a/frontend/src/pages/Admin/Profile/index.vue +++ b/frontend/src/pages/Admin/Profile/index.vue @@ -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; diff --git a/frontend/src/plugins/vuetify.js b/frontend/src/plugins/vuetify.js index 1e8c87b6..522f30fd 100644 --- a/frontend/src/plugins/vuetify.js +++ b/frontend/src/plugins/vuetify.js @@ -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', }, }); diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index f8f17282..acb05434 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -12,7 +12,7 @@ Vue.use(Vuex); const store = new Vuex.Store({ plugins: [ createPersistedState({ - paths: ["userSettings", "language", "SideSettings"], + paths: ["userSettings", "language.lang", "siteSettings"], }), ], modules: { diff --git a/frontend/src/store/modules/language.js b/frontend/src/store/modules/language.js index 7eed2de8..963cfb1a 100644 --- a/frontend/src/store/modules/language.js +++ b/frontend/src/store/modules/language.js @@ -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('-', '_'); }, }; diff --git a/mealie/core/config.py b/mealie/core/config.py index 0d144629..c2d94cad 100644 --- a/mealie/core/config.py +++ b/mealie/core/config.py @@ -6,7 +6,7 @@ from typing import Optional, Union import dotenv from pydantic import BaseSettings, Field, validator -APP_VERSION = "v0.4.2" +APP_VERSION = "v0.4.3" DB_VERSION = "v0.4.0" CWD = Path(__file__).parent @@ -117,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] diff --git a/mealie/core/security.py b/mealie/core/security.py index 75758e60..4f9848ca 100644 --- a/mealie/core/security.py +++ b/mealie/core/security.py @@ -13,10 +13,10 @@ 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) @@ -27,7 +27,7 @@ def create_file_token(file_path: Path) -> bool: 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): diff --git a/mealie/db/db_base.py b/mealie/db/db_base.py index f9e9a03a..fe385f5a 100644 --- a/mealie/db/db_base.py +++ b/mealie/db/db_base.py @@ -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: diff --git a/mealie/db/init_db.py b/mealie/db/init_db.py index f63d20ed..f040ebe4 100644 --- a/mealie/db/init_db.py +++ b/mealie/db/init_db.py @@ -40,7 +40,7 @@ def default_group_init(session: Session): def default_user_init(session: Session): default_user = { "full_name": "Change Me", - "email": "changeme@email.com", + "email": settings.DEFAULT_EMAIL, "password": get_password_hash(settings.DEFAULT_PASSWORD), "group": settings.DEFAULT_GROUP, "admin": True, diff --git a/mealie/routes/deps.py b/mealie/routes/deps.py index c7d308f5..826c6dbc 100644 --- a/mealie/routes/deps.py +++ b/mealie/routes/deps.py @@ -29,7 +29,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme), session=Depends( except JWTError: raise credentials_exception - user = db.users.get(session, token_data.username, "email") + user = db.users.get(session, token_data.username, "email", any_case=True) if user is None: raise credentials_exception return user diff --git a/mealie/routes/users/auth.py b/mealie/routes/users/auth.py index db32a980..2bd04cc6 100644 --- a/mealie/routes/users/auth.py +++ b/mealie/routes/users/auth.py @@ -32,7 +32,7 @@ def get_token( headers={"WWW-Authenticate": "Bearer"}, ) - access_token = security.create_access_token(dict(sub=email), timedelta(hours=2)) + access_token = security.create_access_token(dict(sub=email)) return SnackResponse.success( "User Successfully Logged In", {"access_token": access_token, "token_type": "bearer"}, @@ -42,5 +42,5 @@ def get_token( @router.get("/refresh") async def refresh_token(current_user: UserInDB = Depends(get_current_user)): """ Use a valid token to get another token""" - access_token = security.create_access_token(data=dict(sub=current_user.email), expires_delta=timedelta(hours=1)) + access_token = security.create_access_token(data=dict(sub=current_user.email)) return {"access_token": access_token, "token_type": "bearer"} diff --git a/mealie/routes/users/crud.py b/mealie/routes/users/crud.py index 774d867c..806a7883 100644 --- a/mealie/routes/users/crud.py +++ b/mealie/routes/users/crud.py @@ -83,7 +83,7 @@ async def update_user( if current_user.id == id or current_user.admin: db.users.update(session, id, new_data.dict()) if current_user.id == id: - access_token = security.create_access_token(data=dict(sub=new_data.email), expires_delta=timedelta(hours=2)) + access_token = security.create_access_token(data=dict(sub=new_data.email)) token = {"access_token": access_token, "token_type": "bearer"} return SnackResponse.success("User Updated", token) diff --git a/mealie/schema/auth.py b/mealie/schema/auth.py index 22d8fc1c..0a3148fe 100644 --- a/mealie/schema/auth.py +++ b/mealie/schema/auth.py @@ -1,6 +1,8 @@ -from pydantic import BaseModel from typing import Optional +from pydantic import BaseModel +from pydantic.types import constr + class Token(BaseModel): access_token: str @@ -8,4 +10,4 @@ class Token(BaseModel): class TokenData(BaseModel): - username: Optional[str] = None + username: Optional[constr(to_lower=True, strip_whitespace=True)] = None diff --git a/mealie/schema/user.py b/mealie/schema/user.py index 197706e5..78d4f831 100644 --- a/mealie/schema/user.py +++ b/mealie/schema/user.py @@ -6,6 +6,7 @@ from mealie.db.models.group import Group from mealie.db.models.users import User from mealie.schema.category import CategoryBase from mealie.schema.meal import MealPlanInDB +from pydantic.types import constr from pydantic.utils import GetterDict @@ -23,7 +24,7 @@ class GroupBase(CamelModel): class UserBase(CamelModel): full_name: Optional[str] = None - email: str + email: constr(to_lower=True, strip_whitespace=True) admin: bool group: Optional[str] @@ -31,7 +32,7 @@ class UserBase(CamelModel): orm_mode = True @classmethod - def getter_dict(_cls, name_orm: User): + def getter_dict(cls, name_orm: User): return { **GetterDict(name_orm), "group": name_orm.group.name, diff --git a/template.env b/template.env index 4f85c393..4be787f0 100644 --- a/template.env +++ b/template.env @@ -3,7 +3,9 @@ DEFAULT_GROUP=Home ENV=False API_PORT=9000 API_DOCS=True -DB_TYPE='sqlite' +DB_TYPE=sqlite +DEFAULT_EMAIL=changeme@email.com DEFAULT_PASSWORD=MyPassword +TOKEN_TIME=2 SFTP_USERNAME=None SFTP_PASSWORD=None