fix: frontend error codes and translations

This commit is contained in:
2026-07-08 11:57:38 +02:00
parent 87bed4e1c7
commit c6bba8a40c
6 changed files with 403 additions and 357 deletions
+60 -60
View File
@@ -1,85 +1,85 @@
import { API_BASE } from "../../config/api.config"; import {API_BASE} from "../../config/api.config";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import type { TFunction } from "i18next"; import type {TFunction} from "i18next";
import { fetchSettings } from "./settings"; import {fetchSettings} from "./settings";
import type { ChangePasswordIntf } from "../../misc/interfaces"; import type {ChangePasswordIntf} from "../../misc/interfaces";
import { createApiError } from "./apiError"; import {createApiError} from "./apiError";
export async function isAuthenticated() { export async function isAuthenticated() {
if (Cookies.get("token")) { if (Cookies.get("token")) {
const result = await fetch(`${API_BASE}/users/verify-token`, { const result = await fetch(`${API_BASE}/users/verify-token`, {
method: "POST", method: "POST",
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}); });
if (result.status === 200) { if (result.status === 200) {
return true; return true;
}
} }
}
Cookies.remove("token"); Cookies.remove("token");
return false; return false;
} }
export async function signInUser( export async function signInUser(
username: string, username: string,
password: string, password: string,
t: TFunction, t: TFunction,
) { ) {
const result = await fetch(`${API_BASE}/users/login`, { const result = await fetch(`${API_BASE}/users/login`, {
method: "POST", method: "POST",
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
body: JSON.stringify({ username, password }), body: JSON.stringify({username, password}),
}); });
const response = await result.json(); const response = await result.json();
if (result.status === 202) { if (result.status === 202) {
Cookies.set("token", response.data.token); Cookies.set("token", response.data.token);
const settings = await fetchSettings(); const settings = await fetchSettings();
Cookies.set("app-name", settings?.data[0].value); Cookies.set("app-name", settings?.data[0].value);
Cookies.set("currency", settings?.data[1].value); Cookies.set("currency", settings?.data[1].value);
return { ok: true as const }; return {ok: true as const};
} }
Cookies.remove("token"); Cookies.remove("token");
throw createApiError(response.code, t(response.code || "unknown-error")); throw createApiError(response.code, t(response.code || "unknown-error"));
} }
export function signOutUser() { export function signOutUser() {
Cookies.remove("token"); Cookies.remove("token");
return { ok: true as const }; return {ok: true as const};
} }
export const mutatePassword = async (payload: ChangePasswordIntf) => { export const mutatePassword = async (payload: ChangePasswordIntf) => {
const result = await fetch(`${API_BASE}/users/change-password`, { const result = await fetch(`${API_BASE}/users/change-password`, {
method: "POST", method: "POST",
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
body: JSON.stringify({ body: JSON.stringify({
currentPassword: payload.currentPassword, currentPassword: payload.currentPassword,
newPassword: payload.newPassword, newPassword: payload.newPassword,
}), }),
}); });
const response = await result.json(); const response = await result.json();
if (response.code === "su005") { if (response.code === "SU005") {
return { code: response.code }; return {code: response.code};
} }
throw createApiError(response.code, "Change password failed"); throw createApiError(response.code, "Change password failed");
}; };
+88 -88
View File
@@ -1,121 +1,121 @@
import { API_BASE } from "../../config/api.config"; import {API_BASE} from "../../config/api.config";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import type { ProductFormValues } from "../../misc/interfaces"; import type {ProductFormValues} from "../../misc/interfaces";
import { createApiError } from "./apiError"; import {createApiError} from "./apiError";
export const getProducts = async () => { export const getProducts = async () => {
const result = await fetch(`${API_BASE}/products/all-products`, { const result = await fetch(`${API_BASE}/products/all-products`, {
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}); });
const response = await result.json(); const response = await result.json();
if (response.code === "sp002") { if (response.code === "SP002") {
return response.data; return response.data;
} }
throw createApiError(response.code, "Get products failed"); throw createApiError(response.code, "Get products failed");
}; };
export const getProductDetails = async (uuid: string) => { export const getProductDetails = async (uuid: string) => {
const result = await fetch(`${API_BASE}/products/view?uuid=${uuid}`, { const result = await fetch(`${API_BASE}/products/view?uuid=${uuid}`, {
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}); });
const response = await result.json(); const response = await result.json();
if (response.code === "sp003") { if (response.code === "SP003") {
return response.data; return response.data;
} }
throw createApiError(response.code, "Get product details failed"); throw createApiError(response.code, "Get product details failed");
}; };
export const mutateProduct = async ( export const mutateProduct = async (
values: ProductFormValues, values: ProductFormValues,
itemUUID: string, itemUUID: string,
) => { ) => {
const payload = { const payload = {
...values, ...values,
expiry_date: values.expiry_date || null, expiry_date: values.expiry_date || null,
bottling_date: values.bottling_date || null, bottling_date: values.bottling_date || null,
}; };
const result = await fetch( const result = await fetch(
`${API_BASE}/products/mutate/update-item?item=${itemUUID}`, `${API_BASE}/products/mutate/update-item?item=${itemUUID}`,
{ {
method: "POST", method: "POST",
body: JSON.stringify(payload), body: JSON.stringify(payload),
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}, },
); );
const response = await result.json(); const response = await result.json();
if (response.code === "sp005") { if (response.code === "SP005") {
return response.data; return response.data;
} }
throw createApiError(response.code, "Update product failed"); throw createApiError(response.code, "Update product failed");
}; };
export const deleteSelectedProducts = async (uuids: string[]) => { export const deleteSelectedProducts = async (uuids: string[]) => {
const result = await fetch(`${API_BASE}/products/delete-selection`, { const result = await fetch(`${API_BASE}/products/delete-selection`, {
method: "POST", method: "POST",
body: JSON.stringify(uuids), body: JSON.stringify(uuids),
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}); });
const response = await result.json(); const response = await result.json();
if (response.code === "sp006") { if (response.code === "SP006") {
return { success: true }; return {success: true};
} }
throw createApiError(response.code, "Delete products failed"); throw createApiError(response.code, "Delete products failed");
}; };
export const createProduct = async (values: ProductFormValues) => { export const createProduct = async (values: ProductFormValues) => {
const payload = { const payload = {
name: values.name, name: values.name,
description: values.description, description: values.description,
price: values.price, price: values.price,
amount: values.amount, amount: values.amount,
storage_location: values.storage_location_uuid, storage_location: values.storage_location_uuid,
expiry_date: values.expiry_date || null, expiry_date: values.expiry_date || null,
bottling_date: values.bottling_date || null, bottling_date: values.bottling_date || null,
}; };
const result = await fetch(`${API_BASE}/products/new-product`, { const result = await fetch(`${API_BASE}/products/new-product`, {
method: "POST", method: "POST",
body: JSON.stringify(payload), body: JSON.stringify(payload),
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}); });
const response = await result.json(); const response = await result.json();
if (response.code === "sp001") { if (response.code === "SP001") {
return response.data; return response.data;
} }
throw createApiError(response.code, "Create product failed"); throw createApiError(response.code, "Create product failed");
}; };
+30 -30
View File
@@ -1,43 +1,43 @@
import { API_BASE } from "../../config/api.config"; import {API_BASE} from "../../config/api.config";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import type { SettingsIntf } from "../../misc/interfaces"; import type {SettingsIntf} from "../../misc/interfaces";
import { createApiError } from "./apiError"; import {createApiError} from "./apiError";
export const fetchSettings = async () => { export const fetchSettings = async () => {
const result = await fetch(`${API_BASE}/users/settings`, { const result = await fetch(`${API_BASE}/users/settings`, {
method: "GET", method: "GET",
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}); });
const response = await result.json(); const response = await result.json();
if (response.code === "su004") { if (response.code === "SU004") {
return { success: true, data: response.data, code: response.code }; return {success: true, data: response.data, code: response.code};
} }
throw createApiError(response.code, "Fetch settings failed"); throw createApiError(response.code, "Fetch settings failed");
}; };
export const mutateSettings = async (payload: SettingsIntf) => { export const mutateSettings = async (payload: SettingsIntf) => {
const result = await fetch(`${API_BASE}/users/update-app-settings`, { const result = await fetch(`${API_BASE}/users/update-app-settings`, {
method: "POST", method: "POST",
body: JSON.stringify(payload), body: JSON.stringify(payload),
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}); });
const response = await result.json(); const response = await result.json();
if (response.code === "su003") { if (response.code === "SU003") {
return { success: true, code: response.code }; return {success: true, code: response.code};
} }
throw createApiError(response.code, "Update settings failed"); throw createApiError(response.code, "Update settings failed");
}; };
+61 -61
View File
@@ -1,87 +1,87 @@
import { API_BASE } from "../../config/api.config"; import {API_BASE} from "../../config/api.config";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import type { NewStorage, Storage } from "../../misc/interfaces"; import type {NewStorage, Storage} from "../../misc/interfaces";
import { createApiError } from "./apiError"; import {createApiError} from "./apiError";
export const getStorages = async () => { export const getStorages = async () => {
const result = await fetch(`${API_BASE}/storage/all-storages`, { const result = await fetch(`${API_BASE}/storage/all-storages`, {
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}); });
const response = await result.json(); const response = await result.json();
if (response.code === "ss001") { if (response.code === "SS001") {
return response.data; return response.data;
} }
throw createApiError(response.code, "Get storages failed"); throw createApiError(response.code, "Get storages failed");
}; };
export const mutateNewStorage = async (values: NewStorage) => { export const mutateNewStorage = async (values: NewStorage) => {
const result = await fetch(`${API_BASE}/storage/new-storage`, { const result = await fetch(`${API_BASE}/storage/new-storage`, {
method: "POST", method: "POST",
body: JSON.stringify(values), body: JSON.stringify(values),
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}); });
const response = await result.json(); const response = await result.json();
if (response.code === "ss002") { if (response.code === "SS002") {
return response.data; return response.data;
} }
throw createApiError(response.code, "Create storage failed"); throw createApiError(response.code, "Create storage failed");
}; };
export const updateStorage = async ( export const updateStorage = async (
uuid: string, uuid: string,
values: Pick<Storage, "name" | "description">, values: Pick<Storage, "name" | "description">,
) => { ) => {
const result = await fetch( const result = await fetch(
`${API_BASE}/storage/update-storage?storageUUID=${uuid}`, `${API_BASE}/storage/update-storage?storageUUID=${uuid}`,
{ {
method: "POST", method: "POST",
body: JSON.stringify(values), body: JSON.stringify(values),
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}, },
); );
const response = await result.json(); const response = await result.json();
if (response.code === "ss003") { if (response.code === "ss003") {
return response.data; return response.data;
} }
throw createApiError(response.code, "Update storage failed"); throw createApiError(response.code, "Update storage failed");
}; };
export const deleteStorage = async (uuid: string) => { export const deleteStorage = async (uuid: string) => {
const result = await fetch(`${API_BASE}/storage/delete?uuid=${uuid}`, { const result = await fetch(`${API_BASE}/storage/delete?uuid=${uuid}`, {
method: "DELETE", method: "DELETE",
headers: { headers: {
Authorization: `Bearer ${Cookies.get("token") || ""}`, Authorization: `Bearer ${Cookies.get("token") || ""}`,
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "application/json", Accept: "application/json",
}, },
}); });
const response = await result.json(); const response = await result.json();
if (response.code === "ss004") { if (response.code === "SS004") {
return { success: true, code: response.code }; return {success: true, code: response.code};
} }
throw createApiError(response.code, "Delete storage failed"); throw createApiError(response.code, "Delete storage failed");
}; };
+82 -59
View File
@@ -1,61 +1,84 @@
{ {
"app-title": "Stockhome", "app-title": "Stockhome",
"add": "Hinzufügen", "add": "Hinzufügen",
"storages": "Lager", "storages": "Lager",
"rows-per-page": "Zeilen pro Seite", "rows-per-page": "Zeilen pro Seite",
"details": "Details", "details": "Details",
"username": "Benutzername", "username": "Benutzername",
"password": "Passwort", "password": "Passwort",
"eu001": "Falscher Benutzername oder Passwort!", "login": "Login",
"login": "Login", "product-name": "Produktname",
"product-name": "Produktname", "price": "Preis",
"price": "Preis", "stock": "Bestand",
"stock": "Bestand", "storage-place": "Lagerplatz",
"storage-place": "Lagerplatz", "expiry-date": "Ablaufdatum",
"expiry-date": "Ablaufdatum", "bottling-date": "Abfüllungsdatum",
"bottling-date": "Abfüllungsdatum", "inventory": "Inventar",
"inventory": "Inventar", "actions": "Aktionen",
"actions": "Aktionen", "description": "Beschreibung",
"description": "Beschreibung", "product-details": "Produktdetails",
"product-details": "Produktdetails", "save": "Speichern",
"save": "Speichern", "profile": "Profil",
"profile": "Profil", "settings": "Einstellungen",
"settings": "Einstellungen", "storage-delete-info": "WARNUNG: Wenn Sie einen Lagerort entfernen, werden alle darin gespeicherten Artikel/Produkte ebenfalls entfernt. Das kann nicht rückgängig gemacht werden!",
"storage-delete-info": "WARNUNG: Wenn Sie einen Lagerort entfernen, werden alle darin gespeicherten Artikel/Produkte ebenfalls entfernt. Das kann nicht rückgängig gemacht werden!", "storage-name": "Lagername",
"storage-name": "Lagername", "created-at": "Erstellt am",
"created-at": "Erstellt am", "updated-at": "Aktualisiert am",
"updated-at": "Aktualisiert am", "delete": "Löschen",
"delete": "Löschen", "amount": "Menge",
"amount": "Menge", "inventory-subtitle": "Hier können Sie alle Ihre gelagerten Artikel einsehen.",
"inventory-subtitle": "Hier können Sie alle Ihre gelagerten Artikel einsehen.", "add-product": "Produkt hinzufügen",
"add-product": "Produkt hinzufügen", "add-product-subtitle": "Hier können Sie Informationen zu einem neuen Produkt eingeben.",
"add-product-subtitle": "Hier können Sie Informationen zu einem neuen Produkt eingeben.", "app-name": "App-Name",
"app-name": "App-Name", "app-name-sub": "Wird in der Seitenleiste und im Login-Bildschirm angezeigt.",
"app-name-sub": "Wird in der Seitenleiste und im Login-Bildschirm angezeigt.", "currency": "Währung",
"currency": "Währung", "currency-sub": "Wird für die Preisangaben in allen Inventaransichten verwendet.",
"currency-sub": "Wird für die Preisangaben in allen Inventaransichten verwendet.", "quick-tips": "Schnelle Tipps",
"quick-tips": "Schnelle Tipps", "quick-tips-1": "Aktualisieren Sie den App-Namen, um die Seitenleiste und den Login-Header zu personalisieren.",
"quick-tips-1": "Aktualisieren Sie den App-Namen, um die Seitenleiste und den Login-Header zu personalisieren.", "quick-tips-2": "Wählen Sie einen Währungscode, der zur Preisanzeige passt, z. B. EUR, CHF oder USD.",
"quick-tips-2": "Wählen Sie einen Währungscode, der zur Preisanzeige passt, z. B. EUR, CHF oder USD.", "settings-sub": "Verwalten Sie Ihre App-Einstellungen und Standardwerte.",
"settings-sub": "Verwalten Sie Ihre App-Einstellungen und Standardwerte.", "preferences": "Einstellungen",
"preferences": "Einstellungen", "selected": "ausgewählt",
"selected": "ausgewählt", "logout": "Abmelden",
"logout": "Abmelden", "pcs": "Stk.",
"pcs": "Stk.", "change-translation": "English",
"change-translation": "English", "new-storage-title": "Neuer Lagerort",
"new-storage-title": "Neuer Lagerort", "new-storage-content": "Geben Sie hier die Daten für einen neuen Lagerort ein.",
"new-storage-content": "Geben Sie hier die Daten für einen neuen Lagerort ein.", "menu": "Menü",
"menu": "Menü", "close": "Schließen",
"close": "Schließen", "product-details-quick": "Schnelle Produktdetails",
"product-details-quick": "Schnelle Produktdetails", "download-qr-code": "QR-Code herunterladen",
"download-qr-code": "QR-Code herunterladen", "change-password": "Passwort ändern",
"change-password": "Passwort ändern", "new-password-title": "Hier ändern Sie Ihr Passwort.",
"new-password-title": "Hier ändern Sie Ihr Passwort.", "current-password": "Aktuelles Passwort",
"current-password": "Aktuelles Passwort", "new-password": "Neues Passwort",
"new-password": "Neues Passwort", "new-password-rep": "Neues Passwort wiederholen",
"new-password-rep": "Neues Passwort wiederholen", "change": "Ändern",
"change": "Ändern", "error": "Fehler",
"error": "Fehler", "success": "Erfolg",
"success": "Erfolg", "submit": "Absenden",
"submit": "Absenden" "EG001": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.",
"EU001": "Falscher Benutzername oder Passwort!",
"EU002": "Ihr Konto wurde deaktiviert. Bitte wenden Sie sich an einen Administrator.",
"EU003": "Bitte geben Sie Benutzername und Passwort ein.",
"EU004": "Einige erforderliche Angaben fehlen. Bitte überprüfen Sie Ihre Eingabe.",
"EU005": "Anmeldung aufgrund eines technischen Problems fehlgeschlagen. Bitte versuchen Sie es erneut.",
"EU006": "Anmeldung fehlgeschlagen. Bitte versuchen Sie es erneut.",
"EU007": "Passwort konnte nicht geändert werden. Bitte versuchen Sie es erneut.",
"EU008": "Ihre Einstellungen konnten nicht gespeichert werden. Bitte versuchen Sie es erneut.",
"EU009": "Ihre Einstellungen konnten nicht geladen werden. Bitte versuchen Sie es erneut.",
"ES001": "Bitte füllen Sie alle erforderlichen Felder für den Lagerort aus.",
"ES002": "Einige erforderliche Lagerinformationen fehlen. Bitte überprüfen Sie Ihre Eingabe.",
"ES003": "Der Lagerort konnte nicht aktualisiert werden. Bitte versuchen Sie es erneut.",
"ES004": "Der Lagerort konnte nicht gelöscht werden. Bitte versuchen Sie es erneut.",
"ES005": "Keine Lagerorte gefunden.",
"ES006": "Der Lagerort konnte nicht erstellt werden. Bitte versuchen Sie es erneut.",
"EP001": "Das Produkt konnte nicht erstellt werden. Bitte versuchen Sie es erneut.",
"EP002": "Keine Produkte gefunden.",
"EP003": "Produkt nicht gefunden.",
"EP004": "Die Produktmenge konnte nicht aktualisiert werden. Bitte versuchen Sie es erneut.",
"EP005": "Das Produkt konnte nicht aktualisiert werden. Bitte versuchen Sie es erneut.",
"EP006": "Das Produkt konnte nicht gelöscht werden. Bitte versuchen Sie es erneut.",
"EP007": "Bitte geben Sie mindestens einen Produktnamen ein.",
"EP008": "Einige erforderliche Produktinformationen fehlen. Bitte überprüfen Sie Ihre Eingabe."
} }
+82 -59
View File
@@ -1,61 +1,84 @@
{ {
"app-title": "Stockhome", "app-title": "Stockhome",
"add": "Add", "add": "Add",
"storages": "Storages", "storages": "Storages",
"rows-per-page": "Rows per page", "rows-per-page": "Rows per page",
"details": "Details", "details": "Details",
"username": "Username", "username": "Username",
"password": "Password", "password": "Password",
"eu001": "Wrong username or password!", "login": "Login",
"login": "Login", "product-name": "Product name",
"product-name": "Product name", "price": "Price",
"price": "Price", "stock": "Stock",
"stock": "Stock", "storage-place": "Storage place",
"storage-place": "Storage place", "expiry-date": "Expiry Date",
"expiry-date": "Expiry Date", "bottling-date": "Bottling Date",
"bottling-date": "Bottling Date", "inventory": "Inventory",
"inventory": "Inventory", "actions": "Actions",
"actions": "Actions", "description": "Description",
"description": "Description", "product-details": "Product Details",
"product-details": "Product Details", "save": "Save",
"save": "Save", "profile": "Profile",
"profile": "Profile", "settings": "Settings",
"settings": "Settings", "storage-delete-info": "WARNING: If you remove a storage all items/products that are stored in this storage will also get removed. This cannot be undone!",
"storage-delete-info": "WARNING: If you remove a storage all items/products that are stored in this storage will also get removed. This cannot be undone!", "storage-name": "Storage name",
"storage-name": "Storage name", "created-at": "Created at",
"created-at": "Created at", "updated-at": "Updated at",
"updated-at": "Updated at", "delete": "Delete",
"delete": "Delete", "amount": "Amount",
"amount": "Amount", "inventory-subtitle": "Here you can inspect all of your stored items.",
"inventory-subtitle": "Here you can inspect all of your stored items.", "add-product": "Add product",
"add-product": "Add product", "add-product-subtitle": "Here you can enter information for a new product.",
"add-product-subtitle": "Here you can enter information for a new product.", "app-name": "App name",
"app-name": "App name", "app-name-sub": "Displayed in the sidebar and login screen.",
"app-name-sub": "Displayed in the sidebar and login screen.", "currency": "Currency",
"currency": "Currency", "currency-sub": "Used for pricing across inventory views.",
"currency-sub": "Used for pricing across inventory views.", "quick-tips": "Quick tips",
"quick-tips": "Quick tips", "quick-tips-1": "Update the app name to personalize the sidebar and login header.",
"quick-tips-1": "Update the app name to personalize the sidebar and login header.", "quick-tips-2": "Choose a currency code that matches your pricing display, e.g. EUR, CHF, or USD.",
"quick-tips-2": "Choose a currency code that matches your pricing display, e.g. EUR, CHF, or USD.", "settings-sub": "Manage your app preferences and store defaults.",
"settings-sub": "Manage your app preferences and store defaults.", "preferences": "Preferences",
"preferences": "Preferences", "selected": "selected",
"selected": "selected", "logout": "Logout",
"logout": "Logout", "pcs": "pcs.",
"pcs": "pcs.", "change-translation": "Deutsch",
"change-translation": "Deutsch", "new-storage-title": "New Storage location",
"new-storage-title": "New Storage location", "new-storage-content": "Enter the details for a new storage location here.",
"new-storage-content": "Enter the details for a new storage location here.", "menu": "Menu",
"menu": "Menu", "close": "Close",
"close": "Close", "product-details-quick": "Fast product details",
"product-details-quick": "Fast product details", "download-qr-code": "Download QR-Code",
"download-qr-code": "Download QR-Code", "change-password": "Change password",
"change-password": "Change password", "new-password-title": "Here you can change your password.",
"new-password-title": "Here you can change your password.", "current-password": "Current password",
"current-password": "Current password", "new-password": "New password",
"new-password": "New password", "new-password-rep": "Repeat new password",
"new-password-rep": "Repeat new password", "change": "Change",
"change": "Change", "error": "Error",
"error": "Error", "success": "Success",
"success": "Success", "submit": "Submit",
"submit": "Submit" "EG001": "An unexpected error occurred. Please try again later.",
"EU001": "Wrong username or password!",
"EU002": "Your account has been deactivated. Please contact an administrator.",
"EU003": "Please enter both username and password.",
"EU004": "Some required information is missing. Please check your input.",
"EU005": "Login failed due to a technical issue. Please try again.",
"EU006": "Login failed. Please try again.",
"EU007": "Failed to change your password. Please try again.",
"EU008": "Your settings could not be saved. Please try again.",
"EU009": "Your settings could not be loaded. Please try again.",
"ES001": "Please fill in all required fields for the storage location.",
"ES002": "Some required storage information is missing. Please check your input.",
"ES003": "The storage location could not be updated. Please try again.",
"ES004": "The storage location could not be deleted. Please try again.",
"ES005": "No storage locations found.",
"ES006": "The storage location could not be created. Please try again.",
"EP001": "The product could not be created. Please try again.",
"EP002": "No products found.",
"EP003": "Product not found.",
"EP004": "The product amount could not be updated. Please try again.",
"EP005": "The product could not be updated. Please try again.",
"EP006": "The product could not be deleted. Please try again.",
"EP007": "Please enter at least a product name.",
"EP008": "Some required product information is missing. Please check your input."
} }