diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c17a8260b56a..32bd1e18a1f7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -18,31 +18,26 @@ "source=mealie-devcontainer-workspace,target=/workspaces/mealie/frontend/node_modules,type=volume", "source=mealie-bashhistory,target=/home/vscode/commandhistory,type=volume" ], - // Set *default* container specific settings.json values on container create. - "settings": { - "python.defaultInterpreterPath": "/usr/local/bin/python", - "python.linting.enabled": true, - "python.linting.pylintEnabled": true, - "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", - "python.formatting.blackPath": "/usr/local/py-utils/bin/black", - "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", - "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", - "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", - "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", - "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", - "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", - "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint" + "customizations": { + "vscode": { + "settings": { + "python.defaultInterpreterPath": "/usr/local/bin/python", + "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", + "python.formatting.blackPath": "/usr/local/py-utils/bin/black", + "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", + }, + "extensions": [ + "dbaeumer.vscode-eslint", + "matangover.mypy", + "ms-python.black-formatter", + "ms-python.isort", + "ms-python.pylint", + "ms-python.python", + "ms-python.vscode-pylance", + "Vue.volar" + ] + } }, - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "dbaeumer.vscode-eslint", - "matangover.mypy", - "ms-python.black-formatter", - "ms-python.isort", - "ms-python.python", - "ms-python.vscode-pylance", - "Vue.volar" - ], // Use 'forwardPorts' to make a list of ports inside the container available locally. "forwardPorts": [ 3000, diff --git a/.vscode/settings.json b/.vscode/settings.json index 89b301f013c7..7a225c846d5f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -36,13 +36,6 @@ "i18n-ally.localesPaths": "frontend/lang/messages", "i18n-ally.sourceLanguage": "en-US", "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python", - "python.formatting.provider": "black", - "python.linting.enabled": true, - "python.linting.flake8Enabled": false, - "python.linting.pylintEnabled": false, - "python.linting.pylintArgs": [ - "--rcfile=${workspaceFolder}/.pylintrc" - ], "python.testing.autoTestDiscoverOnSaveEnabled": false, "python.testing.pytestArgs": [ "tests" @@ -50,7 +43,6 @@ "python.testing.pytestEnabled": true, "python.testing.unittestEnabled": false, "python.analysis.typeCheckingMode": "off", - "python.linting.mypyEnabled": true, "search.mode": "reuseEditor", "python.testing.unittestArgs": [ "-v", @@ -69,4 +61,7 @@ "[vue]": { "editor.formatOnSave": false }, + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter", + }, } diff --git a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPage.vue b/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPage.vue index 295f95c08b22..28b96d609696 100644 --- a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPage.vue +++ b/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPage.vue @@ -190,6 +190,8 @@ export default defineComponent({ const drag = ref(false); + const { i18n } = useContext(); + const { recipeAssetPath } = useStaticRoutes(); function assetURL(assetName: string) { @@ -198,7 +200,7 @@ export default defineComponent({ const state = reactive({ loading: true, - loadingText: "Loading recipe...", + loadingText: i18n.tc("general.loading-recipe"), tab: null, selectedRecipeField: "" as SelectedRecipeLeaves | "", canvasSelectedText: "", @@ -260,7 +262,7 @@ export default defineComponent({ onMounted(() => { invoke(async () => { await until(props.recipe).not.toBeNull(); - state.loadingText = "Loading OCR data..."; + state.loadingText = i18n.tc("general.loading-ocr-data"); const assetName = props.recipe.assets[0].fileName; const imagesrc = assetURL(assetName); diff --git a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageCanvas.vue b/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageCanvas.vue index b11ca92633b2..bcba5f4fce97 100644 --- a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageCanvas.vue +++ b/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageCanvas.vue @@ -379,7 +379,7 @@ export default defineComponent({ const toolbarIcons = ref>([ { - sectionTitle: "Toolbar", + sectionTitle: i18n.tc("ocr-editor.toolbar"), eventHandler: switchCanvasMode, highlight: state.canvasMode, icons: [ diff --git a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageHelp.vue b/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageHelp.vue index a14ba02e3e27..39ddf6e8338f 100644 --- a/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageHelp.vue +++ b/frontend/components/Domain/Recipe/RecipeOcrEditorPage/RecipeOcrEditorPageParts/RecipeOcrEditorPageHelp.vue @@ -4,11 +4,11 @@ {{ $globals.icons.help }} - Help + {{ $t("ocr-editor.help.help") }} -

Mouse modes

+

{{ $t("ocr-editor.help.mouse-modes") }}

{{ $globals.icons.selectMode }} {{ $t("ocr-editor.help.selection-mode") }} diff --git a/frontend/components/Domain/Recipe/RecipeOrganizerPage.vue b/frontend/components/Domain/Recipe/RecipeOrganizerPage.vue index 9d8c035fd9d9..d724e4796e0d 100644 --- a/frontend/components/Domain/Recipe/RecipeOrganizerPage.vue +++ b/frontend/components/Domain/Recipe/RecipeOrganizerPage.vue @@ -15,7 +15,7 @@ - + diff --git a/frontend/components/Domain/Recipe/RecipePage/RecipePage.vue b/frontend/components/Domain/Recipe/RecipePage/RecipePage.vue index 07361ac3e684..8191915c931c 100644 --- a/frontend/components/Domain/Recipe/RecipePage/RecipePage.vue +++ b/frontend/components/Domain/Recipe/RecipePage/RecipePage.vue @@ -142,7 +142,7 @@ export default defineComponent({ }, }, setup(props) { - const { $auth, $vuetify } = useContext(); + const { $auth } = useContext(); const route = useRoute(); const groupSlug = computed(() => route.value.params.groupSlug || $auth.user?.groupSlug || ""); const { isOwnGroup } = useLoggedInState(); @@ -168,8 +168,8 @@ export default defineComponent({ const isSame = JSON.stringify(props.recipe) === JSON.stringify(originalRecipe.value); if (isEditMode.value && !isSame && props.recipe?.slug !== undefined) { const save = window.confirm( - "You have unsaved changes. Do you want to save before leaving?\n\nOkay to save, Cancel to discard changes." - ); + i18n.tc("general.unsaved-changes"), + ); if (save) { await api.recipes.updateOne(props.recipe.slug, props.recipe); @@ -247,6 +247,7 @@ export default defineComponent({ /** ============================================================= * View Preferences */ + const { $vuetify, i18n } = useContext(); const landscape = computed(() => { const preferLandscape = props.recipe.settings.landscapeView; diff --git a/frontend/components/Domain/SearchFilter.vue b/frontend/components/Domain/SearchFilter.vue index 82ed48af15f8..44e0ef055095 100644 --- a/frontend/components/Domain/SearchFilter.vue +++ b/frontend/components/Domain/SearchFilter.vue @@ -10,7 +10,7 @@ - +
- No results found + {{ $tc('search.no-results') }}
diff --git a/frontend/components/global/DropZone.vue b/frontend/components/global/DropZone.vue index c00ae434a6d5..4db62890f562 100644 --- a/frontend/components/global/DropZone.vue +++ b/frontend/components/global/DropZone.vue @@ -2,7 +2,7 @@
-

Drop Image

+

{{ $t("recipe.drop-image") }}

diff --git a/frontend/lang/messages/en-US.json b/frontend/lang/messages/en-US.json index 899fe7c7f08e..07b577d6f700 100644 --- a/frontend/lang/messages/en-US.json +++ b/frontend/lang/messages/en-US.json @@ -76,7 +76,8 @@ "cookbook-events": "Cookbook Events", "tag-events": "Tag Events", "category-events": "Category Events", - "when-a-new-user-joins-your-group": "When a new user joins your group" + "when-a-new-user-joins-your-group": "When a new user joins your group", + "recipe-events": "Recipe Events" }, "general": { "cancel": "Cancel", @@ -114,6 +115,8 @@ "keyword": "Keyword", "link-copied": "Link Copied", "loading-events": "Loading Events", + "loading-recipe": "Loading recipe...", + "loading-ocr-data": "Loading OCR data...", "loading-recipes": "Loading Recipes", "message": "Message", "monday": "Monday", @@ -193,7 +196,8 @@ "export-all": "Export All", "refresh": "Refresh", "upload-file": "Upload File", - "created-on-date": "Created on: {0}" + "created-on-date": "Created on: {0}", + "unsaved-changes": "You have unsaved changes. Do you want to save before leaving? Okay to save, Cancel to discard changes." }, "group": { "are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete {groupName}?", @@ -208,6 +212,7 @@ "group-id-with-value": "Group ID: {groupID}", "group-name": "Group Name", "group-not-found": "Group not found", + "group-token": "Group Token", "group-with-value": "Group: {groupID}", "groups": "Groups", "manage-groups": "Manage Groups", @@ -243,6 +248,7 @@ "general-preferences": "General Preferences", "group-recipe-preferences": "Group Recipe Preferences", "report": "Report", + "report-with-id": "Report ID: {id}", "group-management": "Group Management", "admin-group-management": "Admin Group Management", "admin-group-management-text": "Changes to this group will be reflected immediately.", @@ -507,6 +513,7 @@ "message-key": "Message Key", "parse": "Parse", "attach-images-hint": "Attach images by dragging & dropping them into the editor", + "drop-image": "Drop image", "enable-ingredient-amounts-to-use-this-feature": "Enable ingredient amounts to use this feature", "recipes-with-units-or-foods-defined-cannot-be-parsed": "Recipes with units or foods defined cannot be parsed.", "parse-ingredients": "Parse ingredients", @@ -564,14 +571,17 @@ "tag-filter": "Tag Filter", "search-hint": "Press '/'", "advanced": "Advanced", - "auto-search": "Auto Search" + "auto-search": "Auto Search", + "no-results": "No results found" }, "settings": { "add-a-new-theme": "Add a New Theme", "admin-settings": "Admin Settings", "backup": { + "backup-created": "Backup created successfully", "backup-created-at-response-export_path": "Backup Created at {path}", "backup-deleted": "Backup deleted", + "restore-success": "Restore successful", "backup-tag": "Backup Tag", "create-heading": "Create A Backup", "delete-backup": "Delete Backup", @@ -680,11 +690,13 @@ "configuration": "Configuration", "docker-volume": "Docker Volume", "docker-volume-help": "Mealie requires that the frontend container and the backend share the same docker volume or storage. This ensures that the frontend container can properly access the images and assets stored on disk.", - "volumes-are-misconfigured": "Volumes are misconfigured", + "volumes-are-misconfigured": "Volumes are misconfigured.", "volumes-are-configured-correctly": "Volumes are configured correctly.", "status-unknown-try-running-a-validation": "Status Unknown. Try running a validation.", "validate": "Validate", "email-configuration-status": "Email Configuration Status", + "email-configured": "Email Configured", + "email-test-results": "Email Test Results", "ready": "Ready", "not-ready": "Not Ready - Check Environmental Variables", "succeeded": "Succeeded", @@ -819,6 +831,7 @@ "password-updated": "Password updated", "password": "Password", "password-strength": "Password is {strength}", + "please-enter-password": "Please enter your new password.", "register": "Register", "reset-password": "Reset Password", "sign-in": "Sign in", @@ -839,6 +852,7 @@ "username": "Username", "users-header": "USERS", "users": "Users", + "user-not-found": "User not found", "webhook-time": "Webhook Time", "webhooks-enabled": "Webhooks Enabled", "you-are-not-allowed-to-create-a-user": "You are not allowed to create a user", @@ -861,6 +875,7 @@ "user-management": "User Management", "reset-locked-users": "Reset Locked Users", "admin-user-creation": "Admin User Creation", + "admin-user-management": "Admin User Management", "user-details": "User Details", "user-name": "User Name", "authentication-method": "Authentication Method", @@ -872,7 +887,10 @@ "user-can-organize-group-data": "User can organize group data", "enable-advanced-features": "Enable advanced features", "it-looks-like-this-is-your-first-time-logging-in": "It looks like this is your first time logging in.", - "dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Don't want to see this anymore? Be sure to change your email in your user settings!" + "dont-want-to-see-this-anymore-be-sure-to-change-your-email": "Don't want to see this anymore? Be sure to change your email in your user settings!", + "forgot-password": "Forgot Password", + "forgot-password-text": "Please enter your email address and we will send you a link to reset your password.", + "changes-reflected-immediately": "Changes to this user will be reflected immediately." }, "language-dialog": { "translated": "translated", @@ -974,6 +992,7 @@ }, "user-registration": { "user-registration": "User Registration", + "registration-success": "Registration Success", "join-a-group": "Join a Group", "create-a-new-group": "Create a New Group", "provide-registration-token-description": "Please provide the registration token associated with the group that you'd like to join. You'll need to obtain this from an existing group member.", @@ -1020,6 +1039,7 @@ }, "ocr-editor": { "ocr-editor": "Ocr editor", + "toolbar": "Toolbar", "selection-mode": "Selection mode", "pan-and-zoom-picture": "Pan and zoom picture", "split-text": "Split text", @@ -1027,6 +1047,8 @@ "split-by-block": "Split by text block", "flatten": "Flatten regardless of original formating", "help": { + "help": "Help", + "mouse-modes": "Mouse modes", "selection-mode": "Selection Mode (default)", "selection-mode-desc": "The selection mode is the main mode that can be used to enter data:", "selection-mode-steps": { diff --git a/frontend/pages/admin/maintenance/index.vue b/frontend/pages/admin/maintenance/index.vue index ec3d8f1fb1d4..b569b52c20e5 100644 --- a/frontend/pages/admin/maintenance/index.vue +++ b/frontend/pages/admin/maintenance/index.vue @@ -27,7 +27,7 @@
- +
@@ -55,7 +55,7 @@ diff --git a/frontend/pages/group/notifiers.vue b/frontend/pages/group/notifiers.vue index 8c40865fb85c..732deedb64a6 100644 --- a/frontend/pages/group/notifiers.vue +++ b/frontend/pages/group/notifiers.vue @@ -181,7 +181,7 @@ export default defineComponent({ const optionsSections: OptionSection[] = [ { id: 1, - text: "Recipe Events", + text: i18n.tc("events.recipe-events"), options: [ { text: i18n.t("general.create") as string, diff --git a/frontend/pages/group/reports/_id.vue b/frontend/pages/group/reports/_id.vue index e92638eff9a8..e0333a119037 100644 --- a/frontend/pages/group/reports/_id.vue +++ b/frontend/pages/group/reports/_id.vue @@ -9,7 +9,7 @@ - Report Id: {{ id }} + {{ $t('group.report-with-id', { id:id }) }}