translate hardcoded strings

This commit is contained in:
p0lycarpio 2023-10-26 15:26:14 +02:00
parent b1903aa205
commit 3e4a6ac93b
23 changed files with 103 additions and 68 deletions

View File

@ -190,6 +190,8 @@ export default defineComponent({
const drag = ref(false); const drag = ref(false);
const { i18n } = useContext();
const { recipeAssetPath } = useStaticRoutes(); const { recipeAssetPath } = useStaticRoutes();
function assetURL(assetName: string) { function assetURL(assetName: string) {
@ -198,7 +200,7 @@ export default defineComponent({
const state = reactive({ const state = reactive({
loading: true, loading: true,
loadingText: "Loading recipe...", loadingText: i18n.tc("general.loading-recipe"),
tab: null, tab: null,
selectedRecipeField: "" as SelectedRecipeLeaves | "", selectedRecipeField: "" as SelectedRecipeLeaves | "",
canvasSelectedText: "", canvasSelectedText: "",
@ -260,7 +262,7 @@ export default defineComponent({
onMounted(() => { onMounted(() => {
invoke(async () => { invoke(async () => {
await until(props.recipe).not.toBeNull(); 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 assetName = props.recipe.assets[0].fileName;
const imagesrc = assetURL(assetName); const imagesrc = assetURL(assetName);

View File

@ -379,7 +379,7 @@ export default defineComponent({
const toolbarIcons = ref<ToolbarIcons<CanvasModes | SelectedTextSplitModes>>([ const toolbarIcons = ref<ToolbarIcons<CanvasModes | SelectedTextSplitModes>>([
{ {
sectionTitle: "Toolbar", sectionTitle: i18n.tc("ocr-editor.toolbar"),
eventHandler: switchCanvasMode, eventHandler: switchCanvasMode,
highlight: state.canvasMode, highlight: state.canvasMode,
icons: [ icons: [

View File

@ -4,11 +4,11 @@
<v-icon large left> <v-icon large left>
{{ $globals.icons.help }} {{ $globals.icons.help }}
</v-icon> </v-icon>
<v-toolbar-title class="headline"> Help </v-toolbar-title> <v-toolbar-title class="headline"> {{ $t("ocr-editor.help.help") }} </v-toolbar-title>
<v-spacer></v-spacer> <v-spacer></v-spacer>
</v-app-bar> </v-app-bar>
<v-card-text> <v-card-text>
<h1>Mouse modes</h1> <h1> {{ $t("ocr-editor.help.mouse-modes") }}</h1>
<v-divider class="mb-2 mt-1" /> <v-divider class="mb-2 mt-1" />
<h2 class="my-2"> <h2 class="my-2">
<v-icon> {{ $globals.icons.selectMode }} </v-icon>{{ $t("ocr-editor.help.selection-mode") }} <v-icon> {{ $globals.icons.selectMode }} </v-icon>{{ $t("ocr-editor.help.selection-mode") }}

View File

@ -15,7 +15,7 @@
<BaseDialog v-if="updateTarget" v-model="dialogs.update" :title="$t('general.update')" @confirm="updateOne()"> <BaseDialog v-if="updateTarget" v-model="dialogs.update" :title="$t('general.update')" @confirm="updateOne()">
<v-card-text> <v-card-text>
<v-text-field v-model="updateTarget.name" label="Name"> </v-text-field> <v-text-field v-model="updateTarget.name" label="$t('general.name')"> </v-text-field>
<v-checkbox v-if="itemType === Organizer.Tool" v-model="updateTarget.onHand" :label="$t('tool.on-hand')"></v-checkbox> <v-checkbox v-if="itemType === Organizer.Tool" v-model="updateTarget.onHand" :label="$t('tool.on-hand')"></v-checkbox>
</v-card-text> </v-card-text>
</BaseDialog> </BaseDialog>

View File

@ -168,8 +168,8 @@ export default defineComponent({
const isSame = JSON.stringify(props.recipe) === JSON.stringify(originalRecipe.value); const isSame = JSON.stringify(props.recipe) === JSON.stringify(originalRecipe.value);
if (isEditMode.value && !isSame && props.recipe?.slug !== undefined) { if (isEditMode.value && !isSame && props.recipe?.slug !== undefined) {
const save = window.confirm( 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) { if (save) {
await api.recipes.updateOne(props.recipe.slug, props.recipe); await api.recipes.updateOne(props.recipe.slug, props.recipe);
@ -247,6 +247,7 @@ export default defineComponent({
/** ============================================================= /** =============================================================
* View Preferences * View Preferences
*/ */
const { $vuetify, i18n } = useContext();
const landscape = computed(() => { const landscape = computed(() => {
const preferLandscape = props.recipe.settings.landscapeView; const preferLandscape = props.recipe.settings.landscapeView;

View File

@ -10,7 +10,7 @@
</template> </template>
<v-card width="400"> <v-card width="400">
<v-card-text> <v-card-text>
<v-text-field v-model="state.search" class="mb-2" hide-details dense label="Search" clearable /> <v-text-field v-model="state.search" class="mb-2" hide-details dense :label="$tc('search.search')" clearable />
<v-switch <v-switch
v-if="requireAll != undefined" v-if="requireAll != undefined"
v-model="requireAllValue" v-model="requireAllValue"
@ -35,7 +35,7 @@
</v-virtual-scroll> </v-virtual-scroll>
</v-card> </v-card>
<div v-else> <div v-else>
<v-alert type="info" text> No results found </v-alert> <v-alert type="info" text> {{ $tc('search.no-results') }} </v-alert>
</div> </div>
</v-card-text> </v-card-text>
</v-card> </v-card>

View File

@ -2,7 +2,7 @@
<div ref="el" :class="isOverDropZone ? 'over' : ''"> <div ref="el" :class="isOverDropZone ? 'over' : ''">
<div v-if="isOverDropZone" class="overlay"></div> <div v-if="isOverDropZone" class="overlay"></div>
<div v-if="isOverDropZone" class="absolute text-container"> <div v-if="isOverDropZone" class="absolute text-container">
<p class="text-center drop-text">Drop Image</p> <p class="text-center drop-text"> {{ $t("recipe.drop-image") }} </p>
</div> </div>
<slot></slot> <slot></slot>
</div> </div>

View File

@ -76,7 +76,8 @@
"cookbook-events": "Cookbook Events", "cookbook-events": "Cookbook Events",
"tag-events": "Tag Events", "tag-events": "Tag Events",
"category-events": "Category 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": { "general": {
"cancel": "Cancel", "cancel": "Cancel",
@ -114,6 +115,8 @@
"keyword": "Keyword", "keyword": "Keyword",
"link-copied": "Link Copied", "link-copied": "Link Copied",
"loading-events": "Loading Events", "loading-events": "Loading Events",
"loading-recipe": "Loading recipe...",
"loading-ocr-data": "Loading OCR data...",
"loading-recipes": "Loading Recipes", "loading-recipes": "Loading Recipes",
"message": "Message", "message": "Message",
"monday": "Monday", "monday": "Monday",
@ -193,7 +196,8 @@
"export-all": "Export All", "export-all": "Export All",
"refresh": "Refresh", "refresh": "Refresh",
"upload-file": "Upload File", "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": { "group": {
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?", "are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
@ -208,6 +212,7 @@
"group-id-with-value": "Group ID: {groupID}", "group-id-with-value": "Group ID: {groupID}",
"group-name": "Group Name", "group-name": "Group Name",
"group-not-found": "Group not found", "group-not-found": "Group not found",
"group-token": "Group Token",
"group-with-value": "Group: {groupID}", "group-with-value": "Group: {groupID}",
"groups": "Groups", "groups": "Groups",
"manage-groups": "Manage Groups", "manage-groups": "Manage Groups",
@ -243,6 +248,7 @@
"general-preferences": "General Preferences", "general-preferences": "General Preferences",
"group-recipe-preferences": "Group Recipe Preferences", "group-recipe-preferences": "Group Recipe Preferences",
"report": "Report", "report": "Report",
"report-with-id": "Report ID: {id}",
"group-management": "Group Management", "group-management": "Group Management",
"admin-group-management": "Admin Group Management", "admin-group-management": "Admin Group Management",
"admin-group-management-text": "Changes to this group will be reflected immediately.", "admin-group-management-text": "Changes to this group will be reflected immediately.",
@ -507,6 +513,7 @@
"message-key": "Message Key", "message-key": "Message Key",
"parse": "Parse", "parse": "Parse",
"attach-images-hint": "Attach images by dragging & dropping them into the editor", "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", "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.", "recipes-with-units-or-foods-defined-cannot-be-parsed": "Recipes with units or foods defined cannot be parsed.",
"parse-ingredients": "Parse ingredients", "parse-ingredients": "Parse ingredients",
@ -564,14 +571,17 @@
"tag-filter": "Tag Filter", "tag-filter": "Tag Filter",
"search-hint": "Press '/'", "search-hint": "Press '/'",
"advanced": "Advanced", "advanced": "Advanced",
"auto-search": "Auto Search" "auto-search": "Auto Search",
"no-results": "No results found"
}, },
"settings": { "settings": {
"add-a-new-theme": "Add a New Theme", "add-a-new-theme": "Add a New Theme",
"admin-settings": "Admin Settings", "admin-settings": "Admin Settings",
"backup": { "backup": {
"backup-created": "Backup created successfully",
"backup-created-at-response-export_path": "Backup Created at {path}", "backup-created-at-response-export_path": "Backup Created at {path}",
"backup-deleted": "Backup deleted", "backup-deleted": "Backup deleted",
"restore-success": "Restore successful",
"backup-tag": "Backup Tag", "backup-tag": "Backup Tag",
"create-heading": "Create A Backup", "create-heading": "Create A Backup",
"delete-backup": "Delete Backup", "delete-backup": "Delete Backup",
@ -685,6 +695,8 @@
"status-unknown-try-running-a-validation": "Status Unknown. Try running a validation.", "status-unknown-try-running-a-validation": "Status Unknown. Try running a validation.",
"validate": "Validate", "validate": "Validate",
"email-configuration-status": "Email Configuration Status", "email-configuration-status": "Email Configuration Status",
"email-configured": "Email Configured",
"email-test-results": "Email Test Results",
"ready": "Ready", "ready": "Ready",
"not-ready": "Not Ready - Check Environmental Variables", "not-ready": "Not Ready - Check Environmental Variables",
"succeeded": "Succeeded", "succeeded": "Succeeded",
@ -819,6 +831,7 @@
"password-updated": "Password updated", "password-updated": "Password updated",
"password": "Password", "password": "Password",
"password-strength": "Password is {strength}", "password-strength": "Password is {strength}",
"please-enter-password": "Please enter your new password.",
"register": "Register", "register": "Register",
"reset-password": "Reset Password", "reset-password": "Reset Password",
"sign-in": "Sign in", "sign-in": "Sign in",
@ -839,6 +852,7 @@
"username": "Username", "username": "Username",
"users-header": "USERS", "users-header": "USERS",
"users": "Users", "users": "Users",
"user-not-found": "User not found",
"webhook-time": "Webhook Time", "webhook-time": "Webhook Time",
"webhooks-enabled": "Webhooks Enabled", "webhooks-enabled": "Webhooks Enabled",
"you-are-not-allowed-to-create-a-user": "You are not allowed to create a user", "you-are-not-allowed-to-create-a-user": "You are not allowed to create a user",
@ -861,6 +875,7 @@
"user-management": "User Management", "user-management": "User Management",
"reset-locked-users": "Reset Locked Users", "reset-locked-users": "Reset Locked Users",
"admin-user-creation": "Admin User Creation", "admin-user-creation": "Admin User Creation",
"admin-user-management": "Admin User Management",
"user-details": "User Details", "user-details": "User Details",
"user-name": "User Name", "user-name": "User Name",
"authentication-method": "Authentication Method", "authentication-method": "Authentication Method",
@ -872,7 +887,10 @@
"user-can-organize-group-data": "User can organize group data", "user-can-organize-group-data": "User can organize group data",
"enable-advanced-features": "Enable advanced features", "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.", "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": { "language-dialog": {
"translated": "translated", "translated": "translated",
@ -974,6 +992,7 @@
}, },
"user-registration": { "user-registration": {
"user-registration": "User Registration", "user-registration": "User Registration",
"registration-success": "Registration Success",
"join-a-group": "Join a Group", "join-a-group": "Join a Group",
"create-a-new-group": "Create a New 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.", "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": "Ocr editor", "ocr-editor": "Ocr editor",
"toolbar": "Toolbar",
"selection-mode": "Selection mode", "selection-mode": "Selection mode",
"pan-and-zoom-picture": "Pan and zoom picture", "pan-and-zoom-picture": "Pan and zoom picture",
"split-text": "Split text", "split-text": "Split text",
@ -1027,6 +1047,8 @@
"split-by-block": "Split by text block", "split-by-block": "Split by text block",
"flatten": "Flatten regardless of original formating", "flatten": "Flatten regardless of original formating",
"help": { "help": {
"help": "Help",
"mouse-modes": "Mouse modes",
"selection-mode": "Selection Mode (default)", "selection-mode": "Selection Mode (default)",
"selection-mode-desc": "The selection mode is the main mode that can be used to enter data:", "selection-mode-desc": "The selection mode is the main mode that can be used to enter data:",
"selection-mode-steps": { "selection-mode-steps": {
@ -1155,4 +1177,4 @@
"cookbook-name": "Cookbook Name", "cookbook-name": "Cookbook Name",
"cookbook-with-name": "Cookbook {0}" "cookbook-with-name": "Cookbook {0}"
} }
} }

View File

@ -27,7 +27,7 @@
</div> </div>
<section> <section>
<BaseCardSectionTitle class="pb-0" :icon="$globals.icons.wrench" :title="$t('admin.maintenance.summary-title')"> <BaseCardSectionTitle class="pb-0" :icon="$globals.icons.wrench" :title="$tc('admin.maintenance.summary-title')">
</BaseCardSectionTitle> </BaseCardSectionTitle>
<div class="mb-6 ml-2 d-flex" style="gap: 0.3rem"> <div class="mb-6 ml-2 d-flex" style="gap: 0.3rem">
<BaseButton color="info" @click="getSummary"> <BaseButton color="info" @click="getSummary">
@ -55,7 +55,7 @@
<BaseCardSectionTitle <BaseCardSectionTitle
class="pb-0 mt-8" class="pb-0 mt-8"
:icon="$globals.icons.wrench" :icon="$globals.icons.wrench"
:title="$t('admin.mainentance.actions-title')" :title="$tc('admin.mainentance.actions-title')"
> >
<i18n path="admin.maintenance.actions-description"> <i18n path="admin.maintenance.actions-description">
<template #destructive-in-bold> <template #destructive-in-bold>
@ -103,13 +103,14 @@ export default defineComponent({
}); });
const adminApi = useAdminApi(); const adminApi = useAdminApi();
const { i18n } = useContext();
// ========================================================================== // ==========================================================================
// General Info // General Info
const infoResults = ref<MaintenanceSummary>({ const infoResults = ref<MaintenanceSummary>({
dataDirSize: "unknown", dataDirSize: i18n.tc("about.unknown-version"),
logFileSize: "unknown", logFileSize: i18n.tc("about.unknown-version"),
cleanableDirs: 0, cleanableDirs: 0,
cleanableImages: 0, cleanableImages: 0,
}); });
@ -119,8 +120,8 @@ export default defineComponent({
const { data } = await adminApi.maintenance.getInfo(); const { data } = await adminApi.maintenance.getInfo();
infoResults.value = data ?? { infoResults.value = data ?? {
dataDirSize: "unknown", dataDirSize: i18n.tc("about.unknown-version"),
logFileSize: "unknown", logFileSize: i18n.tc("about.unknown-version"),
cleanableDirs: 0, cleanableDirs: 0,
cleanableImages: 0, cleanableImages: 0,
}; };
@ -128,7 +129,6 @@ export default defineComponent({
state.fetchingInfo = false; state.fetchingInfo = false;
} }
const { i18n } = useContext();
const info = computed(() => { const info = computed(() => {
return [ return [
@ -163,7 +163,7 @@ export default defineComponent({
}; };
function storageDetailsText(key: string) { function storageDetailsText(key: string) {
return storageTitles[key] ?? "unknown"; return storageTitles[key] ?? i18n.tc("about.unknown-version");
} }
const storageDetails = ref<MaintenanceStorageDetails | null>(null); const storageDetails = ref<MaintenanceStorageDetails | null>(null);

View File

@ -24,7 +24,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, useRoute, onMounted, ref } from "@nuxtjs/composition-api"; import { defineComponent, useRoute, onMounted, ref, useContext } from "@nuxtjs/composition-api";
import GroupPreferencesEditor from "~/components/Domain/Group/GroupPreferencesEditor.vue"; import GroupPreferencesEditor from "~/components/Domain/Group/GroupPreferencesEditor.vue";
import { useAdminApi } from "~/composables/api"; import { useAdminApi } from "~/composables/api";
import { alert } from "~/composables/use-toast"; import { alert } from "~/composables/use-toast";
@ -39,6 +39,8 @@ export default defineComponent({
setup() { setup() {
const route = useRoute(); const route = useRoute();
const { i18n } = useContext();
const groupId = route.value.params.id; const groupId = route.value.params.id;
// ============================================== // ==============================================
@ -56,7 +58,7 @@ export default defineComponent({
const { data, error } = await adminApi.groups.getOne(groupId); const { data, error } = await adminApi.groups.getOne(groupId);
if (error?.response?.status === 404) { if (error?.response?.status === 404) {
alert.error("User Not Found"); alert.error(i18n.tc("user.user-not-found"));
userError.value = true; userError.value = true;
} }

View File

@ -4,15 +4,15 @@
<template #header> <template #header>
<v-img max-height="125" max-width="125" :src="require('~/static/svgs/manage-profile.svg')"></v-img> <v-img max-height="125" max-width="125" :src="require('~/static/svgs/manage-profile.svg')"></v-img>
</template> </template>
<template #title> Admin User Management </template> <template #title> {{ $t("user.admin-user-management") }} </template>
Changes to this user will be reflected immediately. {{ $t("user.changes-reflected-immediately") }}
</BasePageTitle> </BasePageTitle>
<AppToolbar back> </AppToolbar> <AppToolbar back> </AppToolbar>
<v-form v-if="!userError" ref="refNewUserForm" @submit.prevent="handleSubmit"> <v-form v-if="!userError" ref="refNewUserForm" @submit.prevent="handleSubmit">
<v-card outlined> <v-card outlined>
<v-card-text> <v-card-text>
<div class="d-flex"> <div class="d-flex">
<p>User Id: {{ user.id }}</p> <p> {{ $t("user.user-id-with-value", {id: user.id} ) }}</p>
</div> </div>
<v-select <v-select
v-if="groups" v-if="groups"
@ -24,7 +24,7 @@
item-value="name" item-value="name"
:return-object="false" :return-object="false"
filled filled
label="User Group" :label="$tc('group.user-group')"
:rules="[validators.required]" :rules="[validators.required]"
></v-select> ></v-select>
<div class="d-flex py-2 pr-2"> <div class="d-flex py-2 pr-2">
@ -45,7 +45,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, useRoute, onMounted, ref } from "@nuxtjs/composition-api"; import { computed, defineComponent, useRoute, onMounted, ref, useContext } from "@nuxtjs/composition-api";
import { useAdminApi } from "~/composables/api"; import { useAdminApi } from "~/composables/api";
import { useGroups } from "~/composables/use-groups"; import { useGroups } from "~/composables/use-groups";
import { alert } from "~/composables/use-toast"; import { alert } from "~/composables/use-toast";
@ -59,6 +59,7 @@ export default defineComponent({
setup() { setup() {
const { userForm } = useUserForm(); const { userForm } = useUserForm();
const { groups } = useGroups(); const { groups } = useGroups();
const { i18n } = useContext();
const route = useRoute(); const route = useRoute();
const userId = route.value.params.id; const userId = route.value.params.id;
@ -84,7 +85,7 @@ export default defineComponent({
const { data, error } = await adminApi.users.getOne(userId); const { data, error } = await adminApi.users.getOne(userId);
if (error?.response?.status === 404) { if (error?.response?.status === 404) {
alert.error("User Not Found"); alert.error(i18n.tc("user.user-not-found"));
userError.value = true; userError.value = true;
} }

View File

@ -37,7 +37,7 @@
</div> </div>
<section> <section>
<BaseCardSectionTitle class="pb-0" :icon="$globals.icons.cog" :title="$t('settings.configuration')"> </BaseCardSectionTitle> <BaseCardSectionTitle class="pb-0" :icon="$globals.icons.cog" :title="$tc('settings.configuration')"> </BaseCardSectionTitle>
<v-card class="mb-4"> <v-card class="mb-4">
<template v-for="(check, idx) in simpleChecks"> <template v-for="(check, idx) in simpleChecks">
<v-list-item :key="`list-item-${idx}`"> <v-list-item :key="`list-item-${idx}`">
@ -61,7 +61,7 @@
</section> </section>
<section> <section>
<BaseCardSectionTitle class="pt-2" :icon="$globals.icons.docker" :title="$t('settings.docker-volume')" /> <BaseCardSectionTitle class="pt-2" :icon="$globals.icons.docker" :title="$tc('settings.docker-volume')" />
<v-alert <v-alert
border="left" border="left"
colored-border colored-border
@ -77,7 +77,7 @@
</HelpIcon> </HelpIcon>
</div> </div>
<div> <div>
<template v-if="docker.state === DockerVolumeState.Error"> {{ $t('settings.volumes-are-misconfigured') }}. </template> <template v-if="docker.state === DockerVolumeState.Error"> {{ $t('settings.volumes-are-misconfigured') }} </template>
<template v-else-if="docker.state === DockerVolumeState.Success"> <template v-else-if="docker.state === DockerVolumeState.Success">
{{ $t('settings.volumes-are-configured-correctly') }} {{ $t('settings.volumes-are-configured-correctly') }}
</template> </template>
@ -116,7 +116,7 @@
<template v-if="tested"> <template v-if="tested">
<v-divider class="my-x mt-6"></v-divider> <v-divider class="my-x mt-6"></v-divider>
<v-card-text class="px-0"> <v-card-text class="px-0">
<h4>Email Test Results</h4> <h4> {{ $tc("settings.email-test-results") }}</h4>
<span class="pl-4"> <span class="pl-4">
{{ success ? $t('settings.succeeded') : $t('settings.failed') }} {{ success ? $t('settings.succeeded') : $t('settings.failed') }}
</span> </span>
@ -128,7 +128,7 @@
<!-- General App Info --> <!-- General App Info -->
<section class="mt-4"> <section class="mt-4">
<BaseCardSectionTitle class="pb-0" :icon="$globals.icons.cog" :title="$t('settings.general-about')"> </BaseCardSectionTitle> <BaseCardSectionTitle class="pb-0" :icon="$globals.icons.cog" :title="$tc('settings.general-about')"> </BaseCardSectionTitle>
<v-card class="mb-4"> <v-card class="mb-4">
<template v-for="(property, idx) in appInfo"> <template v-for="(property, idx) in appInfo">
<v-list-item :key="property.name"> <v-list-item :key="property.name">
@ -466,12 +466,12 @@ export default defineComponent({
if (ignoreChecks[item.id]) { if (ignoreChecks[item.id]) {
return; return;
} }
const status = item.status ? "Yes" : "No"; const status = item.status ? i18n.tc("general.yes") : i18n.tc("general.no");
text += `${item.text.toString()}: ${status}\n`; text += `${item.text.toString()}: ${status}\n`;
}); });
text += `Email Configured: ${appConfig.value.emailReady ? "Yes" : "No"}\n`; text += `${i18n.tc("settings.email-configured")}: ${appConfig.value.emailReady ? i18n.tc("general.yes") : i18n.tc("general.no")}\n`;
text += `Docker Volumes: ${docker.state}`; text += `${i18n.tc("settings.docker-volume")}: ${docker.state}`;
return text; return text;
}); });

View File

@ -1,7 +1,7 @@
<template> <template>
<v-container fill-height fluid class="d-flex justify-center align-center"> <v-container fill-height fluid class="d-flex justify-center align-center">
<v-card color="background d-flex flex-column align-center" flat width="600px"> <v-card color="background d-flex flex-column align-center" flat width="600px">
<v-card-title class="headline justify-center"> Forgot Password </v-card-title> <v-card-title class="headline justify-center"> {{ $t('user.forgot-password') }} </v-card-title>
<BaseDivider /> <BaseDivider />
<v-card-text> <v-card-text>
<v-form @submit.prevent="requestLink()"> <v-form @submit.prevent="requestLink()">
@ -15,7 +15,7 @@
:label="$t('user.email')" :label="$t('user.email')"
type="text" type="text"
/> />
<p class="text-center">Please enter your email address and we will send you a link to reset your password.</p> <p class="text-center">{{ $t('user.forgot-password-text') }}</p>
<v-card-actions class="justify-center"> <v-card-actions class="justify-center">
<div class="max-button"> <div class="max-button">
<v-btn :loading="loading" color="primary" type="submit" large rounded class="rounded-xl" block> <v-btn :loading="loading" color="primary" type="submit" large rounded class="rounded-xl" block>
@ -34,7 +34,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, toRefs, reactive } from "@nuxtjs/composition-api"; import { defineComponent, toRefs, reactive, useContext } from "@nuxtjs/composition-api";
import { useUserApi } from "~/composables/api"; import { useUserApi } from "~/composables/api";
import { alert } from "~/composables/use-toast"; import { alert } from "~/composables/use-toast";
export default defineComponent({ export default defineComponent({
@ -47,6 +47,7 @@ export default defineComponent({
error: false, error: false,
}); });
const { i18n } = useContext();
const api = useUserApi(); const api = useUserApi();
async function requestLink() { async function requestLink() {
@ -57,11 +58,11 @@ export default defineComponent({
if (response?.status === 200) { if (response?.status === 200) {
state.loading = false; state.loading = false;
state.error = false; state.error = false;
alert.success("Link successfully sent"); alert.success(i18n.tc("profile.email-sent"));
} else { } else {
state.loading = false; state.loading = false;
state.error = true; state.error = true;
alert.error("Email failure"); alert.error(i18n.tc("profile.error-sending-email"));
} }
} }
@ -73,7 +74,7 @@ export default defineComponent({
head() { head() {
return { return {
title: this.$t("user.login") as string, title: this.$tc("user.login"),
}; };
}, },
}); });
@ -83,4 +84,4 @@ export default defineComponent({
.max-button { .max-button {
width: 300px; width: 300px;
} }
</style> </style>

View File

@ -115,7 +115,7 @@ export default defineComponent({
}, },
head() { head() {
return { return {
title: this.$t("settings.pages") as string, title: this.$t("cookbook.cookbooks") as string,
}; };
}, },
}); });

View File

@ -73,7 +73,7 @@
lockBulkImport = false; lockBulkImport = false;
" "
> >
Clear {{ $t('general.clear') }}
</BaseButton> </BaseButton>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<BaseButton class="mr-1 mb-1" color="info" @click="bulkUrls.push({ url: '', categories: [], tags: [] })"> <BaseButton class="mr-1 mb-1" color="info" @click="bulkUrls.push({ url: '', categories: [], tags: [] })">

View File

@ -121,7 +121,7 @@
<template #icon> <template #icon>
{{ $globals.icons.database }} {{ $globals.icons.database }}
</template> </template>
Import {{ $t('general.import') }}}
</BaseButton> </BaseButton>
<BaseButton <BaseButton
color="info" color="info"

View File

@ -392,6 +392,11 @@ export default defineComponent({
getMigrationReports, getMigrationReports,
}; };
}, },
head() {
return {
title: this.$tc("settings.migrations"),
};
},
}); });
</script> </script>

View File

@ -181,7 +181,7 @@ export default defineComponent({
const optionsSections: OptionSection[] = [ const optionsSections: OptionSection[] = [
{ {
id: 1, id: 1,
text: "Recipe Events", text: i18n.tc("events.recipe-events"),
options: [ options: [
{ {
text: i18n.t("general.create") as string, text: i18n.t("general.create") as string,

View File

@ -9,7 +9,7 @@
<v-container v-if="report"> <v-container v-if="report">
<BaseCardSectionTitle :title="report.name"> </BaseCardSectionTitle> <BaseCardSectionTitle :title="report.name"> </BaseCardSectionTitle>
<v-card-text> Report Id: {{ id }} </v-card-text> <v-card-text> {{ $t('group.report-with-id', { id:id }) }} </v-card-text>
<v-data-table :headers="itemHeaders" :items="report.entries" :items-per-page="50" show-expand> <v-data-table :headers="itemHeaders" :items="report.entries" :items-per-page="50" show-expand>
<template #item.success="{ item }"> <template #item.success="{ item }">

View File

@ -63,7 +63,7 @@
<v-card-text> <v-card-text>
{{ $t("user-registration.provide-registration-token-description") }} {{ $t("user-registration.provide-registration-token-description") }}
<v-form ref="domTokenForm" class="mt-4" @submit.prevent> <v-form ref="domTokenForm" class="mt-4" @submit.prevent>
<v-text-field v-model="token" v-bind="inputAttrs" label="Group Token" :rules="[validators.required]" /> <v-text-field v-model="token" v-bind="inputAttrs" :label="$t('group.group-token')" :rules="[validators.required]" />
</v-form> </v-form>
</v-card-text> </v-card-text>
<v-divider /> <v-divider />
@ -244,7 +244,7 @@
</div> </div>
<v-card-actions class="justify-center flex-column py-8"> <v-card-actions class="justify-center flex-column py-8">
<v-btn text class="mb-2" to="/login"> Login </v-btn> <v-btn text class="mb-2" to="/login"> {{ $t("user.login") }} </v-btn>
<BaseButton large color="primary" @click="langDialog = true"> <BaseButton large color="primary" @click="langDialog = true">
<template #icon> {{ $globals.icons.translate }}</template> <template #icon> {{ $globals.icons.translate }}</template>
{{ $t("language-dialog.choose-language") }} {{ $t("language-dialog.choose-language") }}
@ -472,7 +472,7 @@ export default defineComponent({
} }
const { response } = await api.register.register(payload); const { response } = await api.register.register(payload);
if (response?.status === 201) { if (response?.status === 201) {
alert.success("Registration Success"); alert.success(i18n.tc("user-registration.registration-success"));
router.push("/login"); router.push("/login");
} }
} }

View File

@ -1,7 +1,7 @@
<template> <template>
<v-container fill-height fluid class="d-flex justify-center align-center"> <v-container fill-height fluid class="d-flex justify-center align-center">
<v-card color="background d-flex flex-column align-center" flat width="600px"> <v-card color="background d-flex flex-column align-center" flat width="600px">
<v-card-title class="headline justify-center"> Reset Password </v-card-title> <v-card-title class="headline justify-center"> {{ $t("user.reset-password") }} </v-card-title>
<BaseDivider /> <BaseDivider />
<v-card-text> <v-card-text>
<v-form @submit.prevent="requestLink()"> <v-form @submit.prevent="requestLink()">
@ -23,7 +23,7 @@
class="rounded-lg" class="rounded-lg"
:prepend-icon="$globals.icons.lock" :prepend-icon="$globals.icons.lock"
name="password" name="password"
label="Password" :label="$t('user.password')"
type="password" type="password"
:rules="[validators.required]" :rules="[validators.required]"
/> />
@ -35,11 +35,11 @@
class="rounded-lg" class="rounded-lg"
:prepend-icon="$globals.icons.lock" :prepend-icon="$globals.icons.lock"
name="password" name="password"
label="Confirm Password" :label="$t('user.confirm-password')"
type="password" type="password"
:rules="[validators.required, passwordMatch]" :rules="[validators.required, passwordMatch]"
/> />
<p class="text-center">Please enter your new password.</p> <p class="text-center">{{ $t("user.please-enter-password") }}</p>
<v-card-actions class="justify-center"> <v-card-actions class="justify-center">
<div class="max-button"> <div class="max-button">
<v-btn <v-btn
@ -67,7 +67,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, toRefs, reactive } from "@nuxtjs/composition-api"; import { defineComponent, toRefs, reactive, useContext } from "@nuxtjs/composition-api";
import { useUserApi } from "~/composables/api"; import { useUserApi } from "~/composables/api";
import { alert } from "~/composables/use-toast"; import { alert } from "~/composables/use-toast";
import { validators } from "@/composables/use-validators"; import { validators } from "@/composables/use-validators";
@ -84,7 +84,8 @@ export default defineComponent({
error: false, error: false,
}); });
const passwordMatch = () => state.password === state.passwordConfirm || "Passwords do not match"; const { i18n } = useContext();
const passwordMatch = () => state.password === state.passwordConfirm || i18n.tc("user.password-must-match");
// =================== // ===================
// Token Getter // Token Getter
@ -108,11 +109,11 @@ export default defineComponent({
if (response?.status === 200) { if (response?.status === 200) {
state.loading = false; state.loading = false;
state.error = false; state.error = false;
alert.success("Password Reset Successful"); alert.success(i18n.tc("user.password-updated"));
} else { } else {
state.loading = false; state.loading = false;
state.error = true; state.error = true;
alert.error("Something Went Wrong"); alert.error(i18n.tc("events.something-went-wrong"));
} }
} }
@ -137,4 +138,4 @@ export default defineComponent({
.max-button { .max-button {
width: 300px; width: 300px;
} }
</style> </style>

View File

@ -393,8 +393,8 @@ export default defineComponent({
}; };
const contextMenu = [ const contextMenu = [
{ title: "Delete", action: contextActions.delete }, { title: i18n.tc("general.delete"), action: contextActions.delete },
{ title: "Ingredient", action: contextActions.setIngredient }, { title: i18n.tc("recipe.ingredient"), action: contextActions.setIngredient },
]; ];
function contextMenuAction(action: string, item: ShoppingListItemOut, idx: number) { function contextMenuAction(action: string, item: ShoppingListItemOut, idx: number) {

View File

@ -4,7 +4,7 @@
<template #header> <template #header>
<v-img max-height="200px" max-width="200px" :src="require('~/static/svgs/manage-api-tokens.svg')"></v-img> <v-img max-height="200px" max-width="200px" :src="require('~/static/svgs/manage-api-tokens.svg')"></v-img>
</template> </template>
<template #title> API Tokens </template> <template #title> {{ $tc("settings.token.api-tokens") }} </template>
{{ $tc('settings.token.you-have-token-count', user.tokens.length) }} {{ $tc('settings.token.you-have-token-count', user.tokens.length) }}
</BasePageTitle> </BasePageTitle>
<section class="d-flex justify-center"> <section class="d-flex justify-center">
@ -42,7 +42,7 @@
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</section> </section>
<BaseCardSectionTitle class="mt-10" title="Active Tokens"> </BaseCardSectionTitle> <BaseCardSectionTitle class="mt-10" :title="$tc('settings.token.active-tokens')"> </BaseCardSectionTitle>
<section class="d-flex flex-column"> <section class="d-flex flex-column">
<div v-for="(token, index) in $auth.user.tokens" :key="index"> <div v-for="(token, index) in $auth.user.tokens" :key="index">
<v-card outlined class="mb-2"> <v-card outlined class="mb-2">