feat: expand i18n locale support and fallback handling

This commit is contained in:
2026-03-11 16:40:14 +01:00
parent 2791f95fb4
commit 391f5dfbc2
13 changed files with 6332 additions and 2524 deletions

View File

@@ -1 +1,6 @@
docker buildx build --platform linux/amd64 -t appcreationgmbh/votianlt:0.8.0 --push . docker buildx build --platform linux/amd64 -t appcreationgmbh/votianlt:0.8.0 --push .
docker buildx build --platform linux/amd64 -t repository.assecutor.de/votianlt:0.9.10 --push .
adsg
G8m0T3vz

View File

@@ -9,6 +9,7 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.ResourceBundle.Control; import java.util.ResourceBundle.Control;
@@ -16,6 +17,7 @@ import java.util.ResourceBundle.Control;
public class TranslationProvider implements I18NProvider { public class TranslationProvider implements I18NProvider {
public static final String BUNDLE_PREFIX = "messages"; public static final String BUNDLE_PREFIX = "messages";
private static final Locale DEFAULT_LOCALE = Locale.GERMAN;
// Custom Control to map language codes to file names // Custom Control to map language codes to file names
private static final Control BUNDLE_CONTROL = new Control() { private static final Control BUNDLE_CONTROL = new Control() {
@@ -35,7 +37,7 @@ public class TranslationProvider implements I18NProvider {
case "es" -> Locale.of("es"); // Spanish -> messages_es.properties case "es" -> Locale.of("es"); // Spanish -> messages_es.properties
case "fr" -> Locale.of("fr"); // French -> messages_fr.properties case "fr" -> Locale.of("fr"); // French -> messages_fr.properties
case "en" -> Locale.of("en"); // English -> messages_en.properties case "en" -> Locale.of("en"); // English -> messages_en.properties
case "de" -> Locale.of("de"); // German -> messages.properties (default) case "de" -> Locale.of("de"); // German -> messages_de.properties
default -> locale; default -> locale;
}; };
@@ -57,19 +59,38 @@ public class TranslationProvider implements I18NProvider {
} }
try { try {
ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PREFIX, locale, BUNDLE_CONTROL); String value = findTranslation(key, locale);
String value = bundle.getString(key); if (value == null) {
return key;
}
if (params.length > 0) { if (params.length > 0) {
value = MessageFormat.format(value, params); value = MessageFormat.format(value, params);
} }
return value; return value;
} catch (Exception e) { } catch (MissingResourceException e) {
return key; return key;
} }
} }
private String findTranslation(String key, Locale locale) {
Locale effectiveLocale = locale != null ? locale : DEFAULT_LOCALE;
ResourceBundle localizedBundle = ResourceBundle.getBundle(BUNDLE_PREFIX, effectiveLocale, BUNDLE_CONTROL);
if (localizedBundle.containsKey(key)) {
return localizedBundle.getString(key);
}
if (!DEFAULT_LOCALE.getLanguage().equals(effectiveLocale.getLanguage())) {
ResourceBundle germanBundle = ResourceBundle.getBundle(BUNDLE_PREFIX, DEFAULT_LOCALE, BUNDLE_CONTROL);
if (germanBundle.containsKey(key)) {
return germanBundle.getString(key);
}
}
return null;
}
public String getTranslation(String key, Language language) { public String getTranslation(String key, Language language) {
Locale locale = switch (language) { Locale locale = switch (language) {
case DE -> Locale.GERMAN; case DE -> Locale.GERMAN;
@@ -85,4 +106,4 @@ public class TranslationProvider implements I18NProvider {
}; };
return getTranslation(key, locale); return getTranslation(key, locale);
} }
} }

View File

@@ -1,6 +1,7 @@
package de.assecutor.votianlt.service; package de.assecutor.votianlt.service;
import com.vaadin.flow.component.UI; import com.vaadin.flow.component.UI;
import de.assecutor.votianlt.config.TranslationProvider;
import de.assecutor.votianlt.model.Language; import de.assecutor.votianlt.model.Language;
import de.assecutor.votianlt.model.User; import de.assecutor.votianlt.model.User;
import de.assecutor.votianlt.repository.UserRepository; import de.assecutor.votianlt.repository.UserRepository;
@@ -8,16 +9,17 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Locale; import java.util.Locale;
import java.util.ResourceBundle;
@Service @Service
public class LanguageService { public class LanguageService {
private final UserRepository userRepository; private final UserRepository userRepository;
private final TranslationProvider translationProvider;
@Autowired @Autowired
public LanguageService(UserRepository userRepository) { public LanguageService(UserRepository userRepository, TranslationProvider translationProvider) {
this.userRepository = userRepository; this.userRepository = userRepository;
this.translationProvider = translationProvider;
} }
public void updateUserLanguage(User user, Language language) { public void updateUserLanguage(User user, Language language) {
@@ -30,31 +32,7 @@ public class LanguageService {
} }
public String getTranslation(String key, Language language) { public String getTranslation(String key, Language language) {
try { return translationProvider.getTranslation(key, language != null ? language : Language.DE);
Locale locale;
switch (language) {
case DE:
locale = Locale.GERMAN;
break;
case EN:
locale = Locale.ENGLISH;
break;
case FR:
locale = Locale.FRENCH;
break;
case ES:
locale = Locale.of("es", "ES");
break;
default:
locale = Locale.GERMAN;
}
ResourceBundle bundle = ResourceBundle.getBundle("messages", locale);
return bundle.getString(key);
} catch (Exception e) {
// Fallback to key itself if translation not found
return key;
}
} }
public String getTranslation(String key, User user) { public String getTranslation(String key, User user) {
@@ -78,6 +56,12 @@ public class LanguageService {
case EN -> Locale.ENGLISH; case EN -> Locale.ENGLISH;
case FR -> Locale.FRENCH; case FR -> Locale.FRENCH;
case ES -> Locale.of("es", "ES"); case ES -> Locale.of("es", "ES");
case TR -> Locale.of("tr", "TR");
case PL -> Locale.of("pl", "PL");
case RU -> Locale.of("ru", "RU");
case EE -> Locale.of("et", "EE");
case LV -> Locale.of("lv", "LV");
case LT -> Locale.of("lt", "LT");
default -> Locale.GERMAN; default -> Locale.GERMAN;
}; };
} }

View File

@@ -246,7 +246,7 @@ page.title.customer.create=Neuen Kunden anlegen
page.title.login=Bei VotianLT anmelden page.title.login=Bei VotianLT anmelden
page.title.jobs=Aufträge page.title.jobs=Aufträge
page.title.appuser.edit=App-Nutzer bearbeiten page.title.appuser.edit=App-Nutzer bearbeiten
page.title.statistics=KI-Statistiken page.title.statistics=Statistiken
page.title.password.forget=Passwort zurücksetzen page.title.password.forget=Passwort zurücksetzen
page.title.invoices=Rechnungen page.title.invoices=Rechnungen
page.title.appusers=App-Nutzer page.title.appusers=App-Nutzer
@@ -268,10 +268,7 @@ page.title.create.invoice=Rechnung erstellen
page.title.add.customer=Neuen Kunden anlegen page.title.add.customer=Neuen Kunden anlegen
page.title.edit.appuser=App-Nutzer bearbeiten page.title.edit.appuser=App-Nutzer bearbeiten
page.title.forget.password=Passwort zurücksetzen page.title.forget.password=Passwort zurücksetzen
page.title.job.history=Job Historie
page.title.admin.pricetable=Preis-Tabelle page.title.admin.pricetable=Preis-Tabelle
page.title.invoice.generator=Rechnungsgenerator
page.title.job.summary=Zusammenfassung
page.title.add.job=Neuen Auftrag anlegen page.title.add.job=Neuen Auftrag anlegen
# Dashboard # Dashboard
@@ -638,7 +635,6 @@ jobs.dialog.complete.text=Möchten Sie den Auftrag {0} manuell abschließen?
jobs.dialog.complete.confirm=Abschließen jobs.dialog.complete.confirm=Abschließen
jobs.dialog.delete.title=Auftrag löschen jobs.dialog.delete.title=Auftrag löschen
jobs.dialog.delete.text=Möchten Sie den Auftrag {0} wirklich löschen? jobs.dialog.delete.text=Möchten Sie den Auftrag {0} wirklich löschen?
jobs.notification.completed=Auftrag {0} wurde abgeschlossen
jobs.notification.complete.error=Fehler beim Abschließen: {0} jobs.notification.complete.error=Fehler beim Abschließen: {0}
jobs.notification.deleted=Auftrag {0} wurde gelöscht jobs.notification.deleted=Auftrag {0} wurde gelöscht
jobs.notification.delete.error=Fehler beim Löschen: {0} jobs.notification.delete.error=Fehler beim Löschen: {0}
@@ -721,7 +717,7 @@ appuser.column.appcode=App-Code
appuser.column.email=E-Mail appuser.column.email=E-Mail
# Statistics # Statistics
statistics.title=KI-Statistiken statistics.title=Statistiken
statistics.subtitle=Stellen Sie Fragen zu Ihren Aufträgen und Kunden statistics.subtitle=Stellen Sie Fragen zu Ihren Aufträgen und Kunden
statistics.prompt.placeholder=Frage eingeben... statistics.prompt.placeholder=Frage eingeben...
statistics.quick.jobcount=Anzahl Aufträge statistics.quick.jobcount=Anzahl Aufträge

File diff suppressed because it is too large Load Diff

View File

@@ -4,50 +4,50 @@ dialog.confirm=Confirm
# Navigation and Main Layout # Navigation and Main Layout
nav.jobs=Jobs nav.jobs=Jobs
nav.job.create=Create New Job nav.job.create=Create Job
nav.customers=Customers nav.customers=Customers
nav.appusers=App Users nav.appusers=App Users
nav.statistics=Statistics nav.statistics=Statistics
nav.invoices=Invoices nav.invoices=Invoices
nav.messages=Messages nav.messages=Messages
nav.profile=My Profile nav.profile=My Profile
nav.myinvoices=My Invoices nav.myinvoices=Invoices
nav.imprint=Imprint nav.imprint=Imprint
nav.management=Management nav.management=Management
nav.users=Users nav.users=Users
nav.showprofile=Show Profile nav.showprofile=Show Profile
nav.settings=Settings nav.settings=Settings
nav.logout=Logout nav.logout=Log Out
# Profile View # Profile View
profile.title=Edit Profile profile.title=Edit Profile
profile.language=Language profile.language=Language
profile.company=Company profile.company=Company
profile.companyadd=Company Addition profile.companyadd=Company Suffix
profile.firstname=First Name profile.firstname=First Name
profile.lastname=Last Name profile.lastname=Last Name
profile.phone=Phone Number profile.phone=Phone Number
profile.fax=Fax profile.fax=Phone (Fax)
profile.mobile=Mobile profile.mobile=Phone (Mobile)
profile.email=Email Address (Login)* profile.email=Email Address (Login)*
profile.street=Street profile.street=Street
profile.housenr=House No. profile.housenr=House No.
profile.addressadd=Address Addition profile.addressadd=Address Suffix
profile.zip=Zip Code profile.zip=Postal Code
profile.city=City profile.city=City
profile.diffinvoice=Different Invoice Address profile.diffinvoice=Different Billing Address
profile.basicdata=Basic Data profile.basicdata=Master Data
profile.map=Map profile.map=Map
profile.invoicecreation=Invoice Creation profile.invoicecreation=Invoice Creation
profile.settings=Settings profile.settings=Settings
profile.settings.digitalprocess=Digital Processing profile.settings.digitalprocess=Digital Processing
profile.settings.digitalprocess.info=Jobs are processed digitally via the app profile.settings.digitalprocess.info=Jobs are processed digitally via the app
profile.settings.locateappuser=Locate App User profile.settings.locateappuser=Locate App Users
profile.settings.locateappuser.info=Location of app users is regularly transmitted profile.settings.locateappuser.info=App user location is transmitted regularly
profile.account=Account profile.account=Account
profile.security=Security profile.security=Security
profile.security.twofactor=Two-Factor Authentication profile.security.twofactor=Two-Factor Authentication
profile.security.twofactor.info=An additional code is sent by email when logging in profile.security.twofactor.info=An additional code is sent via email when logging in
profile.services=Service Catalog profile.services=Service Catalog
profile.saved=Profile saved profile.saved=Profile saved
profile.save.error=Error saving: {0} profile.save.error=Error saving: {0}
@@ -55,14 +55,14 @@ profile.validation.required.fill=Please fill in all required fields correctly
# Profile Settings # Profile Settings
settings.digitalprocessing=Digital Processing via App settings.digitalprocessing=Digital Processing via App
settings.digitalprocessinginfo=Enables digital order processing through the mobile app settings.digitalprocessinginfo=Enables digital job processing via the mobile app
settings.locationtracking=Track App Users settings.locationtracking=Locate App Users
settings.locationtrackinginfo=Allows tracking of app users during order execution settings.locationtrackinginfo=Allows locating app users during job execution
settings.twofactor=Two-Factor Authentication settings.twofactor=2-Factor Authentication
settings.twofactorinfo=When enabled, a code will be sent via email for each login settings.twofactorinfo=When enabled, a code is sent via email at each login
# Profile Billing # Profile Billing
profile.billing.enabled=Billing via votianLT profile.billing.enabled=Invoicing via votianLT
profile.billing.prefix=Invoice Prefix profile.billing.prefix=Invoice Prefix
# Profile Validation # Profile Validation
@@ -72,21 +72,21 @@ profile.validation.lastname=Last name is a required field
profile.validation.phone=Phone number is a required field profile.validation.phone=Phone number is a required field
profile.validation.street=Street is a required field profile.validation.street=Street is a required field
profile.validation.housenr=House number is a required field profile.validation.housenr=House number is a required field
profile.validation.zip=Zip code is a required field profile.validation.zip=Postal code is a required field
profile.validation.city=City is a required field profile.validation.city=City is a required field
profile.validation.email.required=Email address is a required field profile.validation.email.required=Email address is a required field
profile.validation.email.invalid=Please enter a valid email address profile.validation.email.invalid=Please enter a valid email address
profile.validation.company.required=Company is required profile.validation.company.required=Company is required
profile.validation.street.required=Street is required profile.validation.street.required=Street is required
profile.validation.housenr.required=House number is required profile.validation.housenr.required=House number is required
profile.validation.zip.required=Zip code is required profile.validation.zip.required=Postal code is required
profile.validation.city.required=City is required profile.validation.city.required=City is required
profile.validation.firstname.required=First name is required profile.validation.firstname.required=First name is required
profile.validation.lastname.required=Last name is required profile.validation.lastname.required=Last name is required
profile.validation.phone.required=Phone number is required profile.validation.phone.required=Phone number is required
# Profile Invoice # Profile Invoice
profile.invoice.masterdata=My Data profile.invoice.masterdata=My Master Data
profile.invoice.name=Name profile.invoice.name=Name
profile.invoice.city=City profile.invoice.city=City
profile.invoice.email=Email profile.invoice.email=Email
@@ -94,7 +94,7 @@ profile.invoice.phone=Phone
profile.invoice.placeholder.company=Your Company profile.invoice.placeholder.company=Your Company
profile.invoice.placeholder.name=Your Name profile.invoice.placeholder.name=Your Name
profile.invoice.placeholder.street=Your Street profile.invoice.placeholder.street=Your Street
profile.invoice.placeholder.city=ZIP City profile.invoice.placeholder.city=Postal Code City
profile.invoice.placeholder.email=your@email.com profile.invoice.placeholder.email=your@email.com
profile.invoice.placeholder.phone=Your Phone Number profile.invoice.placeholder.phone=Your Phone Number
profile.invoice.services.list=List Services profile.invoice.services.list=List Services
@@ -119,7 +119,7 @@ profile.invoice.element.line=Line
profile.invoice.element.image=Image profile.invoice.element.image=Image
profile.invoice.element.invoicenumber=Invoice Number profile.invoice.element.invoicenumber=Invoice Number
profile.invoice.properties=Properties profile.invoice.properties=Properties
profile.invoice.properties.info=Click on an element in the canvas to edit its properties profile.invoice.properties.info=Click on an element in the canvas to edit its properties.
profile.invoice.type=Type profile.invoice.type=Type
profile.invoice.variable=Variable profile.invoice.variable=Variable
profile.invoice.xposition=X Position profile.invoice.xposition=X Position
@@ -133,8 +133,8 @@ profile.invoice.image.uploaded=Image uploaded successfully
profile.invoice.image.upload.error=Error uploading: {0} profile.invoice.image.upload.error=Error uploading: {0}
profile.invoice.file.rejected=File rejected: {0} profile.invoice.file.rejected=File rejected: {0}
profile.invoice.text.from.masterdata=Text comes from your master data profile.invoice.text.from.masterdata=Text comes from your master data
profile.invoice.canvas.cleared=Canvas cleared profile.invoice.canvas.cleared=Canvas has been cleared
profile.invoice.canvas.read.error=Error: Could not read canvas data profile.invoice.canvas.read.error=Error: Canvas data could not be read
profile.invoice.template.saved=Template saved successfully profile.invoice.template.saved=Template saved successfully
profile.invoice.pdf.error=Error generating PDF: {0} profile.invoice.pdf.error=Error generating PDF: {0}
profile.invoice.pdf.preview=Preview profile.invoice.pdf.preview=Preview
@@ -142,7 +142,7 @@ profile.invoice.pdf.preview.error=Error generating preview: {0}
# Profile Services # Profile Services
profile.services.label=Services profile.services.label=Services
profile.services.description=Manage your services that you offer to your customers profile.services.description=Manage your services that you offer to your customers here.
profile.services.add=Add New Service profile.services.add=Add New Service
profile.services.load.error=Error loading services: {0} profile.services.load.error=Error loading services: {0}
profile.services.saved=Service saved successfully profile.services.saved=Service saved successfully
@@ -152,14 +152,14 @@ profile.services.delete.error=Error deleting service: {0}
profile.services.dialog.create=Create New Service profile.services.dialog.create=Create New Service
profile.services.dialog.edit=Edit Service profile.services.dialog.edit=Edit Service
profile.services.basis=Calculation Basis profile.services.basis=Calculation Basis
profile.services.basis.distance=Distance (km) profile.services.basis.distance=Distance Driven
profile.services.basis.time=Time profile.services.basis.time=Time
profile.services.basis.flatrate=Flat Rate profile.services.basis.flatrate=Flat Rate
profile.services.vatrate=VAT Rate (%) profile.services.vatrate=VAT Rate (%)
profile.services.vatrate.percent=VAT Rate (%) profile.services.vatrate.percent=VAT Rate (%)
profile.services.price.flatrate=Flat Rate Price () profile.services.price.flatrate=Flat Rate Price (\u20ac)
profile.services.price.distance=Price per Kilometer () profile.services.price.distance=Price per Kilometer (\u20ac)
profile.services.price.time=Price per 15 Minutes () profile.services.price.time=Price per 15 Minutes (\u20ac)
profile.services.mandatory=Mandatory profile.services.mandatory=Mandatory
profile.services.calculated=Calculated profile.services.calculated=Calculated
profile.services.validation.name=Name is required profile.services.validation.name=Name is required
@@ -211,15 +211,15 @@ notification.error=Error saving
notification.languagechanged=Language changed notification.languagechanged=Language changed
# Login # Login
login.title=Login login.title=Log In
login.username=Username login.username=Username
login.password=Password login.password=Password
login.login=Login login.login=Log In
login.forgotpassword=Forgot password? login.forgotpassword=Forgot Password?
login.rememberme=Remember me login.rememberme=Remember Me
login.register=Register login.register=Register
login.2fa.helper=6-digit code login.2fa.helper=6-digit code
login.2fa.sent=Code sent via email login.2fa.sent=Code was sent via email
login.2fa.no.credentials=No credentials available login.2fa.no.credentials=No credentials available
login.2fa.invalid.code=Invalid code login.2fa.invalid.code=Invalid code
login.2fa.wrong.code=Wrong code login.2fa.wrong.code=Wrong code
@@ -233,7 +233,7 @@ error.validation=Validation error
page.title.dashboard=VotianLT - Dashboard page.title.dashboard=VotianLT - Dashboard
page.title.appuser.create=Create New App User page.title.appuser.create=Create New App User
page.title.messages=Messages page.title.messages=Messages
page.title.register=Register with VotianLT page.title.register=Register at VotianLT
page.title.customers=Customers page.title.customers=Customers
page.title.customer.edit=Edit Customer page.title.customer.edit=Edit Customer
page.title.verwaltung=Management page.title.verwaltung=Management
@@ -243,22 +243,22 @@ page.title.profile.edit=Edit Profile
page.title.admin.dashboard=Admin Dashboard page.title.admin.dashboard=Admin Dashboard
page.title.invoice.create=Create Invoice page.title.invoice.create=Create Invoice
page.title.customer.create=Create New Customer page.title.customer.create=Create New Customer
page.title.login=Login to VotianLT page.title.login=Log In to VotianLT
page.title.jobs=Jobs page.title.jobs=Jobs
page.title.appuser.edit=Edit App User page.title.appuser.edit=Edit App User
page.title.statistics=AI Statistics page.title.statistics=Statistics
page.title.password.forget=Reset Password page.title.password.forget=Reset Password
page.title.invoices=Invoices page.title.invoices=Invoices
page.title.appusers=App Users page.title.appusers=App Users
page.title.job.history=Job History page.title.job.history=Job History
page.title.message.history=Message History page.title.message.history=Message History
page.title.myinvoices=My Invoices page.title.myinvoices=Invoices
page.title.job.create=Create New Job page.title.job.create=Create New Job
page.title.job.summary=Summary page.title.job.summary=Summary
page.title.pricetable=Price Table page.title.pricetable=Price Table
page.title.invoice.generator=Invoice Generator page.title.invoice.generator=Invoice Generator
page.title.welcome=VotianLT - Welcome page.title.welcome=VotianLT - Welcome
page.title.password.reset=Reset Password - Enter Email page.title.password.reset=Reset Password \u2013 Enter Email
page.title.add.appuser=Create New App User page.title.add.appuser=Create New App User
page.title.user.messages=Messages page.title.user.messages=Messages
page.title.edit.customer=Edit Customer page.title.edit.customer=Edit Customer
@@ -268,16 +268,13 @@ page.title.create.invoice=Create Invoice
page.title.add.customer=Create New Customer page.title.add.customer=Create New Customer
page.title.edit.appuser=Edit App User page.title.edit.appuser=Edit App User
page.title.forget.password=Reset Password page.title.forget.password=Reset Password
page.title.job.history=Job History
page.title.admin.pricetable=Price Table page.title.admin.pricetable=Price Table
page.title.invoice.generator=Invoice Generator
page.title.job.summary=Summary
page.title.add.job=Create New Job page.title.add.job=Create New Job
# Dashboard # Dashboard
dashboard.welcome=Welcome, {0}! dashboard.welcome=Welcome, {0}!
dashboard.footer.copyright=© 2024 VotianLT. All rights reserved. dashboard.footer.copyright=\u00a9 2024 VotianLT. All rights reserved.
dashboard.description=Here you can manage your jobs, organize customers and use all important features of VotianLT. dashboard.description=Here you can manage your jobs, organize customers, and use all important features of VotianLT.
dashboard.system.title=System Overview dashboard.system.title=System Overview
dashboard.system.intro=Manage your business processes efficiently with the following features dashboard.system.intro=Manage your business processes efficiently with the following features
dashboard.feature.setup.title=Setup dashboard.feature.setup.title=Setup
@@ -287,7 +284,7 @@ dashboard.feature.customers.desc=Manage your customer relationships and contacts
dashboard.feature.jobs.title=Jobs dashboard.feature.jobs.title=Jobs
dashboard.feature.jobs.desc=Create and manage jobs efficiently dashboard.feature.jobs.desc=Create and manage jobs efficiently
dashboard.app.title=Mobile App dashboard.app.title=Mobile App
dashboard.app.description=Use the VotianLT app on the go and stay connected dashboard.app.description=Use the VotianLT App on the go and stay connected at all times
# Add App User # Add App User
addappuser.title=Create New App User addappuser.title=Create New App User
@@ -299,7 +296,7 @@ addappuser.button.submit=Create App User
addappuser.validation.designation=Designation is required addappuser.validation.designation=Designation is required
addappuser.validation.phone=Phone number is required addappuser.validation.phone=Phone number is required
addappuser.validation.password.required=Password is required addappuser.validation.password.required=Password is required
addappuser.validation.password.min=Password must be at least 6 characters addappuser.validation.password.min=Password must have at least 6 characters
addappuser.validation.password.confirm=Password confirmation is required addappuser.validation.password.confirm=Password confirmation is required
addappuser.validation.password.mismatch=Passwords do not match addappuser.validation.password.mismatch=Passwords do not match
addappuser.validation.email.required=Email is required addappuser.validation.email.required=Email is required
@@ -323,13 +320,13 @@ editappuser.notification.check=Please check your input
editappuser.notification.password.confirm=Please confirm the new password editappuser.notification.password.confirm=Please confirm the new password
editappuser.notification.password.enter=Please enter a new password editappuser.notification.password.enter=Please enter a new password
editappuser.notification.deleted=App user deleted successfully editappuser.notification.deleted=App user deleted successfully
editappuser.dialog.delete.text=Do you really want to delete this app user? editappuser.dialog.delete.text=Are you sure you want to delete this app user?
editappuser.dialog.delete.confirm=Delete editappuser.dialog.delete.confirm=Delete
# Customers # Customers
customers.title=Customers customers.title=Customers
customers.button.add=Add New Customer customers.button.add=Add New Customer
customers.hint.click=Click on a customer to view details customers.hint.click=Click on a customer to see details
customers.column.company=Company customers.column.company=Company
customers.column.name=Name customers.column.name=Name
customers.column.email=Email customers.column.email=Email
@@ -344,7 +341,7 @@ editcustomer.notification.invalid.id=Invalid customer ID
editcustomer.notification.saved=Customer saved successfully editcustomer.notification.saved=Customer saved successfully
editcustomer.notification.check=Please check your input editcustomer.notification.check=Please check your input
editcustomer.notification.deleted=Customer deleted successfully editcustomer.notification.deleted=Customer deleted successfully
editcustomer.dialog.delete.text=Do you really want to delete this customer? editcustomer.dialog.delete.text=Are you sure you want to delete this customer?
editcustomer.dialog.delete.confirm=Delete editcustomer.dialog.delete.confirm=Delete
# Add Customer # Add Customer
@@ -362,13 +359,13 @@ addcompany.button.submit=Create Company
# Verwaltung # Verwaltung
verwaltung.title=Management verwaltung.title=Management
verwaltung.description=Manage your companies, customers and system settings here verwaltung.description=Manage your companies, customers, and system settings here
# User Messages # User Messages
usermessages.title.with=Messages with {0} usermessages.title.with=Messages with {0}
usermessages.general.title=General Conversations usermessages.general.title=General Conversations
usermessages.general.conversation=General Conversation usermessages.general.conversation=General Conversation
usermessages.job.title=Job-related Messages usermessages.job.title=Job-Related Messages
usermessages.job.conversation=Job {0} usermessages.job.conversation=Job {0}
usermessages.no.job.messages=No job-related messages usermessages.no.job.messages=No job-related messages
usermessages.preview.empty=No preview available usermessages.preview.empty=No preview available
@@ -394,7 +391,7 @@ admindashboard.stat.inprogress=In Progress
admindashboard.stat.completed=Completed admindashboard.stat.completed=Completed
admindashboard.stat.cargo=Cargo Items admindashboard.stat.cargo=Cargo Items
admindashboard.stat.status.info=Status admindashboard.stat.status.info=Status
admindashboard.stat.status.unavailable=Not Available admindashboard.stat.status.unavailable=Unavailable
admindashboard.stat.totaltasks=Total Tasks admindashboard.stat.totaltasks=Total Tasks
admindashboard.stat.completedtasks=Completed admindashboard.stat.completedtasks=Completed
admindashboard.stat.pendingtasks=Pending admindashboard.stat.pendingtasks=Pending
@@ -415,7 +412,7 @@ admindashboard.stat.memory=Memory
# Messages # Messages
messages.title=Messages messages.title=Messages
messages.column.status=Status messages.column.status=Status
messages.column.client=Client messages.column.client=Customer
messages.column.email=Email messages.column.email=Email
messages.column.total=Total messages.column.total=Total
messages.column.unread=Unread messages.column.unread=Unread
@@ -424,51 +421,51 @@ messages.column.preview=Preview
messages.notification.error=Error loading messages messages.notification.error=Error loading messages
messages.preview.image=Image messages.preview.image=Image
messages.preview.empty=No preview messages.preview.empty=No preview
messages.sender.unknown=Unknown sender messages.sender.unknown=Unknown Sender
# Add Job # Add Job
addjob.title=Create New Job addjob.title=Create New Job
addjob.customer.label=Customer addjob.customer.label=Customer
addjob.customer.placeholder=Select customer addjob.customer.placeholder=Select Customer
addjob.customer.unnamed=Unnamed Customer addjob.customer.unnamed=Unnamed Customer
addjob.button.clearfields=Clear Fields addjob.button.clearfields=Clear Fields
addjob.button.submit=Create Job addjob.button.submit=Create Job
addjob.address.salutation=Salutation addjob.address.salutation=Salutation
addjob.address.salutation.placeholder=Select salutation addjob.address.salutation.placeholder=Select Salutation
addjob.salutation.mr=Mr addjob.salutation.mr=Mr
addjob.salutation.ms=Ms addjob.salutation.ms=Ms
addjob.salutation.other=Other addjob.salutation.other=Other
addjob.address.company.placeholder=Enter company addjob.address.company.placeholder=Enter company
addjob.address.street.placeholder=Enter street addjob.address.street.placeholder=Enter street
addjob.address.housenumber=House Number addjob.address.housenumber=House Number
addjob.address.addition.placeholder=Address addition addjob.address.addition.placeholder=Address suffix
addjob.address.city=City addjob.address.city=City
addjob.address.city.placeholder.pickup=City (Pickup) addjob.address.city.placeholder.pickup=City (Pickup)
addjob.address.city.placeholder.delivery=City (Delivery) addjob.address.city.placeholder.delivery=City (Delivery)
addjob.address.delivery.street.placeholder=Street (Delivery) addjob.address.delivery.street.placeholder=Street (Delivery)
addjob.address.delivery.addition.placeholder=Address addition (Delivery) addjob.address.delivery.addition.placeholder=Address suffix (Delivery)
addjob.address.save=Save Address addjob.address.save=Save Address
addjob.section.pickup=Pickup addjob.section.pickup=Pickup
addjob.section.delivery=Delivery addjob.section.delivery=Delivery
addjob.stations.apply=Apply Stations addjob.stations.apply=Apply Stations
addjob.station.delivery=Delivery Station {0} addjob.station.delivery=Delivery Station {0}
addjob.station.add=Add delivery station addjob.station.add=Add Delivery Station
addjob.station.remove.confirm=Really remove delivery station {0}? addjob.station.remove.confirm=Really remove delivery station {0}?
addjob.station.max.reached=Maximum of 25 delivery stations reached addjob.station.max.reached=Maximum number of 25 delivery stations reached
addjob.station.unused=Not used addjob.station.unused=Not used
addjob.appointment.delivery.info=Delivery dates are set directly in the delivery stations. addjob.appointment.delivery.info=Delivery dates are set directly in the delivery stations.
addjob.tab.addresses=Customer & Addresses addjob.tab.addresses=Client & Addresses
addjob.tab.appointments=Appointments & Processing addjob.tab.appointments=Appointments & Processing
addjob.tab.cargo=Cargo addjob.tab.cargo=Cargo
addjob.tab.tasks=Tasks addjob.tab.tasks=Tasks
addjob.tab.price=Price & Submit addjob.tab.price=Price & Completion
addjob.appointment.date=Date addjob.appointment.date=Date
addjob.appointment.time=Time addjob.appointment.time=Time
addjob.appointment.pickup=Pickup Appointment addjob.appointment.pickup=Pickup Date
addjob.appointment.delivery=Delivery Appointment addjob.appointment.delivery=Delivery Date
addjob.settings.digitalprocess=Digital Processing via App addjob.settings.digitalprocess=Digital Processing via App
addjob.appuser.label=App User addjob.appuser.label=App User
addjob.appuser.placeholder=Select app user addjob.appuser.placeholder=Select App User
addjob.cargo.description=Description addjob.cargo.description=Description
addjob.cargo.description.placeholder=Enter description addjob.cargo.description.placeholder=Enter description
addjob.cargo.quantity=Quantity addjob.cargo.quantity=Quantity
@@ -478,14 +475,14 @@ addjob.cargo.width=Width
addjob.cargo.height=Height addjob.cargo.height=Height
addjob.cargo.europalette=Euro Pallet addjob.cargo.europalette=Euro Pallet
addjob.cargo.disposablepalette=Disposable Pallet addjob.cargo.disposablepalette=Disposable Pallet
addjob.cargo.dusseldorfpalette=Düsseldorf Pallet addjob.cargo.dusseldorfpalette=Dusseldorf Pallet
addjob.cargo.gridboxpalette=Grid Box Pallet addjob.cargo.gridboxpalette=Grid Box Pallet
addjob.cargo.gridcart=Grid Cart addjob.cargo.gridcart=Grid Cart
addjob.cargo.parcel=Parcel addjob.cargo.parcel=Parcel
addjob.cargo.add=Add Cargo addjob.cargo.add=Add Cargo
addjob.tasks.title=Tasks addjob.tasks.title=Tasks
addjob.tasks.template.placeholder=Select template addjob.tasks.template.placeholder=Select Template
addjob.tasks.template.save.tooltip=Save as template addjob.tasks.template.save.tooltip=Save as Template
addjob.tasks.template.save.title=Save Template addjob.tasks.template.save.title=Save Template
addjob.tasks.template.name=Template Name addjob.tasks.template.name=Template Name
addjob.tasks.template.name.placeholder=Enter name addjob.tasks.template.name.placeholder=Enter name
@@ -495,14 +492,14 @@ addjob.tasks.template.save.error=Error saving: {0}
addjob.tasks.template.dialog.error=Error opening dialog: {0} addjob.tasks.template.dialog.error=Error opening dialog: {0}
addjob.tasks.template.no.tasks=No tasks to save addjob.tasks.template.no.tasks=No tasks to save
addjob.tasks.template.load.title=Load Template addjob.tasks.template.load.title=Load Template
addjob.tasks.template.load.text=Do you want to load template "{0}"? This will replace all current tasks. addjob.tasks.template.load.text=Do you want to load the template "{0}"? This action will replace all current tasks.
addjob.tasks.template.load.confirm=Load addjob.tasks.template.load.confirm=Load
addjob.tasks.template.loaded=Template "{0}" loaded addjob.tasks.template.loaded=Template "{0}" loaded
addjob.tasks.template.load.error=Error loading: {0} addjob.tasks.template.load.error=Error loading: {0}
addjob.tasks.template.load.templates.error=Error loading templates: {0} addjob.tasks.template.load.templates.error=Error loading templates: {0}
addjob.tasks.add=Add Task addjob.tasks.add=Add Task
addjob.tasks.tasktype=Task Type addjob.tasks.tasktype=Task Type
addjob.tasks.tasktype.placeholder=Select type addjob.tasks.tasktype.placeholder=Select Type
addjob.tasks.description=Description addjob.tasks.description=Description
addjob.tasks.description.placeholder=Enter description addjob.tasks.description.placeholder=Enter description
addjob.tasks.buttontext=Button Text addjob.tasks.buttontext=Button Text
@@ -524,14 +521,14 @@ addjob.tasks.optional=Task is optional
addjob.services.title=Services addjob.services.title=Services
addjob.services.add=Add Service addjob.services.add=Add Service
addjob.services.calculation=Calculation addjob.services.calculation=Calculation
addjob.services.basis.distance=Distance (km) addjob.services.basis.distance=Distance Driven
addjob.services.basis.time=Time addjob.services.basis.time=Time
addjob.services.basis.flatrate=Flat Rate addjob.services.basis.flatrate=Flat Rate
addjob.services.vat=VAT addjob.services.vat=VAT
addjob.services.route.missing=Route missing addjob.services.route.missing=Route missing
addjob.services.dialog.title=Select Service addjob.services.dialog.title=Select Service
addjob.services.dialog.placeholder=Select service addjob.services.dialog.placeholder=Select Service
addjob.services.dialog.station.placeholder=Select delivery station addjob.services.dialog.station.placeholder=Select Delivery Station
addjob.services.dialog.add=Add addjob.services.dialog.add=Add
addjob.services.deliverystation=Delivery Station addjob.services.deliverystation=Delivery Station
addjob.summary.title=Summary addjob.summary.title=Summary
@@ -543,34 +540,34 @@ addjob.route.distance=Distance
addjob.route.distance.km=Distance (km) addjob.route.distance.km=Distance (km)
addjob.route.distance.placeholder=e.g. 150.5 addjob.route.distance.placeholder=e.g. 150.5
addjob.route.duration=Duration addjob.route.duration=Duration
addjob.route.duration.min=Duration (Min.) addjob.route.duration.min=Duration (min.)
addjob.route.duration.placeholder=e.g. 120 addjob.route.duration.placeholder=e.g. 120
addjob.route.manual.title=Manual Route Entry addjob.route.manual.title=Manual Route Entry
addjob.route.manual.hint=Enter distance and duration manually if no route was calculated addjob.route.manual.hint=Enter distance and duration manually if no route was calculated
addjob.notification.success=Job {0} created successfully addjob.notification.success=Job {0} created successfully
addjob.notification.cleared=All fields cleared addjob.notification.cleared=All fields have been cleared
addjob.notification.draft.restored=Draft restored addjob.notification.draft.restored=Draft restored
addjob.validation.required.fields=Please fill in all required fields addjob.validation.required.fields=Please fill in all required fields
addjob.validation.appuser.required=Please select an app user addjob.validation.appuser.required=Please select an app user
addjob.validation.cargo.required=Please enter at least one cargo item addjob.validation.cargo.required=Please specify at least one cargo item
addjob.validation.pickupdate.future=Pickup date must be today or in the future addjob.validation.pickupdate.future=Pickup date must be today or in the future
addjob.validation.deliverydate.future=Delivery date must be today or in the future addjob.validation.deliverydate.future=Delivery date must be today or in the future
addjob.validation.dialog.title=Address Validation addjob.validation.dialog.title=Address Validation
addjob.validation.dialog.loading=Validating addresses... addjob.validation.dialog.loading=Validating addresses...
addjob.validation.dialog.back=Back addjob.validation.dialog.back=Back
addjob.validation.dialog.continue=Continue addjob.validation.dialog.continue=Continue
addjob.validation.dialog.continue.anyway=Continue anyway addjob.validation.dialog.continue.anyway=Continue Anyway
addjob.validation.pickup.address=Pickup Address addjob.validation.pickup.address=Pickup Address
addjob.validation.delivery.address=Delivery Address addjob.validation.delivery.address=Delivery Address
addjob.validation.route=Route addjob.validation.route=Route
addjob.validation.address.not.found.title=Address not found addjob.validation.address.not.found.title=Address Not Found
addjob.validation.address.not.found.message=The entered address could not be clearly found on Google. Do you still want to save? addjob.validation.address.not.found.message=The entered address could not be clearly found on Google. Do you want to save anyway?
addjob.validation.address.save.anyway=Save anyway addjob.validation.address.save.anyway=Save Anyway
addjob.validation.address.correct=Correct address addjob.validation.address.correct=Correct Address
# Job Summary # Job Summary
jobsummary.title=Summary jobsummary.title=Summary
jobsummary.error.noid=No job ID provided jobsummary.error.noid=No job ID specified
jobsummary.error.invalidid=Invalid job ID format: {0} jobsummary.error.invalidid=Invalid job ID format: {0}
jobsummary.error.notfound=Job with ID {0} not found jobsummary.error.notfound=Job with ID {0} not found
jobsummary.button.sendmessage=Send Message jobsummary.button.sendmessage=Send Message
@@ -580,9 +577,9 @@ jobsummary.dialog.complete.title=Complete Job
jobsummary.dialog.complete.text=Do you want to manually complete job {0}? jobsummary.dialog.complete.text=Do you want to manually complete job {0}?
jobsummary.dialog.complete.cancel=Cancel jobsummary.dialog.complete.cancel=Cancel
jobsummary.dialog.complete.confirm=Complete jobsummary.dialog.complete.confirm=Complete
jobsummary.notification.completed=Job {0} completed jobsummary.notification.completed=Job {0} has been completed
jobsummary.notification.complete.error=Error completing job: {0} jobsummary.notification.complete.error=Error completing: {0}
jobsummary.notification.noappuser=No app user assigned to this job jobsummary.notification.noappuser=No app user is assigned to this job
jobsummary.section.pickup=Pickup jobsummary.section.pickup=Pickup
jobsummary.section.delivery=Delivery jobsummary.section.delivery=Delivery
jobsummary.station.phone=Phone jobsummary.station.phone=Phone
@@ -590,17 +587,17 @@ jobsummary.section.tasks=Tasks to Confirm
jobsummary.section.cargo=Cargo to Transport jobsummary.section.cargo=Cargo to Transport
jobsummary.section.info=Additional Information jobsummary.section.info=Additional Information
jobsummary.tasks.none=No tasks jobsummary.tasks.none=No tasks
jobsummary.cargo.none=No cargo information jobsummary.cargo.none=No cargo details
jobsummary.info.netto=Net jobsummary.info.netto=Net
jobsummary.info.ust=VAT jobsummary.info.ust=VAT
jobsummary.info.gesamt=Total jobsummary.info.gesamt=Total
jobsummary.info.bemerkung=Remark jobsummary.info.bemerkung=Remark
jobsummary.info.digital=Digital Processing via App: enabled jobsummary.info.digital=Digital processing via app: enabled
jobsummary.info.appuser=App User jobsummary.info.appuser=App User
jobsummary.task.status.abgeschlossen=Completed jobsummary.task.status.abgeschlossen=Completed
jobsummary.task.status.offen=Open jobsummary.task.status.offen=Open
jobsummary.task.typ=Type jobsummary.task.typ=Type
jobsummary.task.completedAt=Completed at jobsummary.task.completedAt=Completed on
jobsummary.task.completedBy=Completed by jobsummary.task.completedBy=Completed by
jobsummary.task.todo.items=To-Do Items jobsummary.task.todo.items=To-Do Items
jobsummary.task.photo.info=Photos jobsummary.task.photo.info=Photos
@@ -621,7 +618,7 @@ jobs.filter.apply=Apply Filter
jobs.status.all=All jobs.status.all=All
jobs.status.open=Open jobs.status.open=Open
jobs.status.done=Done jobs.status.done=Done
jobs.notification.completed=Job {0} completed jobs.notification.completed=Job {0} has been completed
jobs.column.status=Status jobs.column.status=Status
jobs.column.customer=Customer jobs.column.customer=Customer
jobs.column.jobnumber=Job Number jobs.column.jobnumber=Job Number
@@ -637,11 +634,10 @@ jobs.dialog.complete.title=Complete Job
jobs.dialog.complete.text=Do you want to manually complete job {0}? jobs.dialog.complete.text=Do you want to manually complete job {0}?
jobs.dialog.complete.confirm=Complete jobs.dialog.complete.confirm=Complete
jobs.dialog.delete.title=Delete Job jobs.dialog.delete.title=Delete Job
jobs.dialog.delete.text=Do you really want to delete job {0}? jobs.dialog.delete.text=Are you sure you want to delete job {0}?
jobs.notification.completed=Job {0} completed jobs.notification.complete.error=Error completing: {0}
jobs.notification.complete.error=Error completing job: {0} jobs.notification.deleted=Job {0} has been deleted
jobs.notification.deleted=Job {0} deleted jobs.notification.delete.error=Error deleting: {0}
jobs.notification.delete.error=Error deleting job: {0}
# Create Invoice # Create Invoice
createinvoice.title=Create Invoice \u2013 Job {0} createinvoice.title=Create Invoice \u2013 Job {0}
@@ -657,12 +653,12 @@ createinvoice.field.customer=Customer
createinvoice.field.status=Status createinvoice.field.status=Status
createinvoice.field.price=Price createinvoice.field.price=Price
createinvoice.route.distance=Distance createinvoice.route.distance=Distance
createinvoice.route.duration=Duration createinvoice.route.duration=Travel Time
createinvoice.column.service=Service createinvoice.column.service=Service
createinvoice.column.basis=Calculation Basis createinvoice.column.basis=Calculation Basis
createinvoice.summary.net=Net Total createinvoice.summary.net=Net Total
createinvoice.summary.vat=VAT ({0}%) createinvoice.summary.vat=VAT ({0}%)
createinvoice.summary.total=Total Amount createinvoice.summary.total=Grand Total
createinvoice.notification.noservices=Please select at least one service createinvoice.notification.noservices=Please select at least one service
createinvoice.notification.nouser=User not found createinvoice.notification.nouser=User not found
createinvoice.notification.notemplate=No invoice template found createinvoice.notification.notemplate=No invoice template found
@@ -672,7 +668,7 @@ createinvoice.preview.title=Invoice Preview
createinvoice.preview.number=PREVIEW createinvoice.preview.number=PREVIEW
createinvoice.button.save=Save createinvoice.button.save=Save
createinvoice.confirm.save.title=Save Invoice createinvoice.confirm.save.title=Save Invoice
createinvoice.confirm.save.message=This invoice will be permanently saved and can no longer be modified. Continue? createinvoice.confirm.save.message=This invoice will be permanently saved and cannot be modified afterwards. Continue?
createinvoice.confirm.save.confirm=Yes, save createinvoice.confirm.save.confirm=Yes, save
# Invoices # Invoices
@@ -686,8 +682,8 @@ invoices.empty=No invoices have been created yet.
invoices.notification.pdf.missing=No PDF is stored for this invoice. invoices.notification.pdf.missing=No PDF is stored for this invoice.
# My Invoices # My Invoices
myinvoices.title=My Invoices myinvoices.title=Invoices
myinvoices.hint.noopen=You have no open invoices. All invoices are settled. myinvoices.hint.noopen=You have no open invoices. All invoices have been paid.
myinvoices.bank.institute=Bank myinvoices.bank.institute=Bank
myinvoices.bank.beneficiary=Beneficiary myinvoices.bank.beneficiary=Beneficiary
myinvoices.bank.iban=IBAN myinvoices.bank.iban=IBAN
@@ -695,10 +691,10 @@ myinvoices.recipient.name=Customer
myinvoices.recipient.department= myinvoices.recipient.department=
myinvoices.item.description=Item: {0} myinvoices.item.description=Item: {0}
myinvoices.card.open=Open Invoices myinvoices.card.open=Open Invoices
myinvoices.card.bank=Bank Account myinvoices.card.bank=Bank Details
myinvoices.bank.reference=Reference myinvoices.bank.reference=Payment Reference
myinvoices.section.title=All Invoices myinvoices.section.title=All Invoices
myinvoices.filter.pagesize=Entries per page myinvoices.filter.pagesize=Entries per Page
myinvoices.filter.search=Search myinvoices.filter.search=Search
myinvoices.filter.search.placeholder=Search invoice number... myinvoices.filter.search.placeholder=Search invoice number...
myinvoices.column.status=Status myinvoices.column.status=Status
@@ -721,7 +717,7 @@ appuser.column.appcode=App Code
appuser.column.email=Email appuser.column.email=Email
# Statistics # Statistics
statistics.title=AI Statistics statistics.title=Statistics
statistics.subtitle=Ask questions about your jobs and customers statistics.subtitle=Ask questions about your jobs and customers
statistics.prompt.placeholder=Enter question... statistics.prompt.placeholder=Enter question...
statistics.quick.jobcount=Number of Jobs statistics.quick.jobcount=Number of Jobs
@@ -729,9 +725,9 @@ statistics.quick.jobcount.prompt=How many jobs do I currently have?
statistics.quick.revenue=Revenue statistics.quick.revenue=Revenue
statistics.quick.revenue.prompt=What is my revenue this month? statistics.quick.revenue.prompt=What is my revenue this month?
statistics.quick.trend=Trends statistics.quick.trend=Trends
statistics.quick.trend.prompt=Show me trends in the last 3 months statistics.quick.trend.prompt=Show me trends from the last 3 months as a bar chart
statistics.ai.label=AI Response statistics.ai.label=AI Response
statistics.data.fetched=Data fetched statistics.data.fetched=Data has been retrieved
statistics.loading=Calculating... statistics.loading=Calculating...
# Job Status # Job Status
@@ -754,12 +750,12 @@ passwordreset.button.submit=Save Password
passwordreset.button.cancel=Cancel passwordreset.button.cancel=Cancel
passwordreset.button.send=Send Email passwordreset.button.send=Send Email
passwordreset.notification.enterpassword=Please enter a new password passwordreset.notification.enterpassword=Please enter a new password
passwordreset.notification.mismatch=Passwords do not match passwordreset.notification.mismatch=The passwords do not match
passwordreset.notification.success=Password changed successfully passwordreset.notification.success=Password has been changed successfully
passwordreset.notification.invalidtoken=Token invalid or expired passwordreset.notification.invalidtoken=Token invalid or expired
passwordreset.notification.entermail=Please enter email passwordreset.notification.entermail=Please enter email
passwordreset.notification.sent=If the email exists, a link has been sent passwordreset.notification.sent=If the email exists, a link has been sent
passwordreset.notification.wait=Please wait {0} seconds before sending the code again passwordreset.notification.wait=Please wait {0} seconds before resending the code
# Email # Email
email.2fa.subject=Your VotianLT Verification Code email.2fa.subject=Your VotianLT Verification Code
@@ -779,31 +775,31 @@ register.phone=Phone Number
register.company=Company register.company=Company
register.street=Street register.street=Street
register.housenr=House No. register.housenr=House No.
register.zip=Zip Code register.zip=Postal Code
register.city=City register.city=City
register.code.label=Verification Code (6 digits) register.code.label=Verification Code (6 digits)
register.code.placeholder=e.g. 123456 register.code.placeholder=e.g. 123456
register.button.submit=Register register.button.submit=Register
register.button.verify=Verify Code and Register register.button.verify=Verify Code and Register
register.button.resend=Resend Code register.button.resend=Resend Code
register.button.back=Back to Start Page register.button.back=Back to Home
register.notification.email.required=Please enter an email address register.notification.email.required=Please enter an email address
register.notification.email.invalid=Please enter a valid email address register.notification.email.invalid=Please enter a valid email address
register.notification.email.duplicate=A user with this email address already exists register.notification.email.duplicate=A user with this email address already exists
register.notification.password.required=Please enter a password register.notification.password.required=Please enter a password
register.notification.password.min=Password must be at least 6 characters long register.notification.password.min=The password must be at least 6 characters long
register.notification.password.mismatch=Passwords do not match register.notification.password.mismatch=The passwords do not match
register.notification.firstname.required=Please enter your first name register.notification.firstname.required=Please enter your first name
register.notification.lastname.required=Please enter your last name register.notification.lastname.required=Please enter your last name
register.notification.phone.required=Please enter your phone number register.notification.phone.required=Please enter your phone number
register.notification.company.required=Please enter the company name register.notification.company.required=Please enter the company name
register.notification.street.required=Please enter the street register.notification.street.required=Please enter the street
register.notification.housenr.required=Please enter the house number register.notification.housenr.required=Please enter the house number
register.notification.zip.required=Please enter the zip code register.notification.zip.required=Please enter the postal code
register.notification.city.required=Please enter the city register.notification.city.required=Please enter the city
register.notification.code.sent=A verification code has been sent to {0} register.notification.code.sent=A verification code has been sent to {0}
register.notification.code.emailerror=Error sending email: {0} register.notification.code.emailerror=Error sending email: {0}
register.notification.code.expired=The code has expired. Please request a new code. register.notification.code.expired=The code has expired. Please send a new code.
register.notification.code.invalid=The entered code is invalid register.notification.code.invalid=The entered code is invalid
register.notification.code.startfirst=Please start the registration first register.notification.code.startfirst=Please start the registration first
register.notification.code.required=Please enter the 6-digit code register.notification.code.required=Please enter the 6-digit code
@@ -812,29 +808,29 @@ register.notification.failed=Registration failed: {0}
# Start Page # Start Page
start.title=VotianLT - Your Digital Transport Partner start.title=VotianLT - Your Digital Transport Partner
start.button.login=Login start.button.login=Log In
start.button.register=Register start.button.register=Register
start.button.createorder=Create Order start.button.createorder=Create Job
start.button.notifications=Notifications start.button.notifications=Notifications
start.button.nonotifications=No new notifications start.button.nonotifications=No new notifications
start.hero.description=For solo self-employed and small business owners in the transport industry - fully digital and all-in-one. Focus on your business, we take care of the paperwork. start.hero.description=For solo self-employed and small business owners in the transport industry - fully digital and all-in-one. Focus on your business, we take care of the paperwork.
start.system.title=The System start.system.title=The System
start.system.intro=For solo self-employed and small business owners in the transport industry, it is crucial to focus primarily on their core business: winning customers and delivering goods from A to B. start.system.intro=For solo self-employed and small business owners in the transport industry, it is crucial that they can primarily focus on their actual business: winning customers and delivering goods from A to B.
start.feature.setup.title=Setup Assistant start.feature.setup.title=Setup Wizard
start.feature.setup.desc=Use the setup assistant to complete your user profile. start.feature.setup.desc=With the setup wizard, you can complete your user profile.
start.feature.customers.title=Customer and Job Management start.feature.customers.title=Customer & Job Management
start.feature.customers.desc=With customer and job management, you always have all contact details and job details in view. start.feature.customers.desc=With customer and job management, you always have all contact details and job details at a glance.
start.feature.jobs.title=Job Creation start.feature.jobs.title=Job Creation
start.feature.jobs.desc=Create jobs in the system with just a few clicks and determine which employee should process which transport job. start.feature.jobs.desc=Create jobs in the system with just a few clicks and assign which employee should handle which transport job.
start.app.title=The App start.app.title=The App
start.app.description=Every job can optionally be processed via the votianLT app - completely without "paperwork". All relevant job information goes directly to the driver's smartphone. start.app.description=Every job can optionally be processed via the votianLT app \u2013 completely paperless. All relevant job information is delivered directly to the driver's smartphone.
start.imprint.title=Imprint start.imprint.title=Imprint
start.imprint.company=Assecutor Data Service GmbH start.imprint.company=Assecutor Data Service GmbH
start.imprint.address=Ottensener Str. 8, 22525 Hamburg start.imprint.address=Ottensener Str. 8, 22525 Hamburg
start.imprint.phone=Phone: +49 40 18 123 771 0 start.imprint.phone=Phone: +49 40 18 123 771 0
start.imprint.email=Email: ahoi@assecutor.de start.imprint.email=Email: ahoi@assecutor.de
start.cta.text=Register today and use the free trial month to test the system thoroughly. start.cta.text=Register today and use the free trial month to put the system through its paces.
start.slogan=Run your business smart with votianLT! start.slogan=Run your business smart ... with votianLT!
start.version=Version start.version=Version
# Login View # Login View
@@ -847,14 +843,14 @@ login.version=Version
messagedetails.button.send=Send messagedetails.button.send=Send
messagedetails.placeholder=Enter message... messagedetails.placeholder=Enter message...
messagedetails.noimage=(no image content) messagedetails.noimage=(no image content)
messagedetails.imageerror=(image could not be loaded) messagedetails.imageerror=(Image could not be loaded)
# Invoice Generator # Invoice Generator
invoicegenerator.properties.title=Properties invoicegenerator.properties.title=Properties
invoicegenerator.properties.type=Type invoicegenerator.properties.type=Type
invoicegenerator.fontsize.label=Font Size invoicegenerator.fontsize.label=Font Size
invoicegenerator.color.label=Text Color invoicegenerator.color.label=Font Color
invoicegenerator.color.dialog.title=Choose Text Color invoicegenerator.color.dialog.title=Choose Font Color
invoicegenerator.color.dialog.hex=Hex Color Value invoicegenerator.color.dialog.hex=Hex Color Value
invoicegenerator.button.cancel=Cancel invoicegenerator.button.cancel=Cancel
invoicegenerator.button.apply=Apply invoicegenerator.button.apply=Apply
@@ -864,10 +860,11 @@ invoicegenerator.upload.drop=Drag image here or click
invoicegenerator.upload.success=Image uploaded successfully invoicegenerator.upload.success=Image uploaded successfully
invoicegenerator.upload.error=Error uploading: {0} invoicegenerator.upload.error=Error uploading: {0}
invoicegenerator.file.rejected=File rejected: {0} invoicegenerator.file.rejected=File rejected: {0}
invoicegenerator.properties.select.info=Click on an element in the canvas to edit its properties invoicegenerator.properties.select.info=Click on an element in the canvas to edit its properties.
invoicegenerator.template.vline=Vertical Line
# CSV Export # CSV Export
csv.header.customer=Customer csv.header.customer=Client
csv.header.jobnumber=Job Number csv.header.jobnumber=Job Number
csv.header.jobdate=Job Date csv.header.jobdate=Job Date
csv.header.destination=Destination csv.header.destination=Destination
@@ -876,7 +873,7 @@ csv.filename=jobs.csv
# DatePicker I18n # DatePicker I18n
datepicker.month.januar=January datepicker.month.januar=January
datepicker.month.februar=February datepicker.month.februar=February
datepicker.month.märz=March datepicker.month.m\u00e4rz=March
datepicker.month.april=April datepicker.month.april=April
datepicker.month.mai=May datepicker.month.mai=May
datepicker.month.juni=June datepicker.month.juni=June
@@ -893,13 +890,13 @@ datepicker.weekday.mittwoch=Wednesday
datepicker.weekday.donnerstag=Thursday datepicker.weekday.donnerstag=Thursday
datepicker.weekday.freitag=Friday datepicker.weekday.freitag=Friday
datepicker.weekday.samstag=Saturday datepicker.weekday.samstag=Saturday
datepicker.weekdayshort.so=Su datepicker.weekdayshort.so=Sun
datepicker.weekdayshort.mo=Mo datepicker.weekdayshort.mo=Mon
datepicker.weekdayshort.di=Tu datepicker.weekdayshort.di=Tue
datepicker.weekdayshort.mi=We datepicker.weekdayshort.mi=Wed
datepicker.weekdayshort.do=Th datepicker.weekdayshort.do=Thu
datepicker.weekdayshort.fr=Fr datepicker.weekdayshort.fr=Fri
datepicker.weekdayshort.sa=Sa datepicker.weekdayshort.sa=Sat
# Job History # Job History
jobhistory.status.pickupscheduled=Pickup Scheduled jobhistory.status.pickupscheduled=Pickup Scheduled
@@ -908,11 +905,11 @@ jobhistory.status.intransit=In Transit
jobhistory.status.delivered=Delivered jobhistory.status.delivered=Delivered
jobhistory.image.alt=Enlarged Photo jobhistory.image.alt=Enlarged Photo
jobhistory.title=Job History jobhistory.title=Job History
jobhistory.header=Job history for {0} jobhistory.header=Job History for {0}
jobhistory.info.customer=Customer: {0} jobhistory.info.customer=Customer: {0}
jobhistory.info.createdat=Created at: {0} jobhistory.info.createdat=Created on: {0}
jobhistory.info.status=Status: {0} jobhistory.info.status=Status: {0}
jobhistory.count={0} history entries jobhistory.count={0} entries in history
jobhistory.changedby=Changed by: {0} jobhistory.changedby=Changed by: {0}
# Version # Version
@@ -927,7 +924,7 @@ management.companies=Companies
# User Menu # User Menu
usermenu.profile=Show Profile usermenu.profile=Show Profile
usermenu.settings=Settings usermenu.settings=Settings
usermenu.logout=Logout usermenu.logout=Log Out
# CTA Button # CTA Button
cta.freetest=Try for free now cta.freetest=Try for free now
@@ -937,14 +934,14 @@ misc.toggle.hide=Hide
misc.toggle.show=Show misc.toggle.show=Show
misc.nodata=No data available misc.nodata=No data available
misc.loading=Loading data... misc.loading=Loading data...
misc.error=Error occurred misc.error=An error occurred
misc.retry=Retry misc.retry=Retry
# Admin Price Table # Admin Price Table
adminpricetable.title=Price Table adminpricetable.title=Price Table
adminpricetable.field.monthly=Monthly Base Package adminpricetable.field.monthly=Monthly Base Package
adminpricetable.field.applicense=App Usage License adminpricetable.field.applicense=App Usage License
adminpricetable.field.revenue=Revenue Participation adminpricetable.field.revenue=Revenue Share
adminpricetable.notification.saved=Price table has been saved adminpricetable.notification.saved=Price table has been saved
adminpricetable.notification.save.error=Error saving: {0} adminpricetable.notification.save.error=Error saving: {0}
adminpricetable.notification.load.error=Error loading: {0} adminpricetable.notification.load.error=Error loading: {0}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff