diff --git a/.env.development b/.env.development
index 8c20778dd..b603dbc2b 100644
--- a/.env.development
+++ b/.env.development
@@ -222,6 +222,11 @@ CONTACTS_GOOGLE_REDIRECT_URI=http://localhost:5184/import?tab=google
CALENDAR_BACKEND_PORT=3014
CALENDAR_DATABASE_URL=postgresql://manacore:devpassword@localhost:5432/calendar
+# Speech-to-Text Service (mana-stt)
+# Production: https://stt-api.mana.how
+# Local dev: http://localhost:3020
+STT_URL=https://stt-api.mana.how
+
# ============================================
# STORAGE PROJECT (Cloud Drive)
# ============================================
diff --git a/apps/calendar/apps/web/src/hooks.server.ts b/apps/calendar/apps/web/src/hooks.server.ts
index 6d7a5089d..5215d05b8 100644
--- a/apps/calendar/apps/web/src/hooks.server.ts
+++ b/apps/calendar/apps/web/src/hooks.server.ts
@@ -11,6 +11,7 @@ const PUBLIC_MANA_CORE_AUTH_URL_CLIENT =
process.env.PUBLIC_MANA_CORE_AUTH_URL_CLIENT || process.env.PUBLIC_MANA_CORE_AUTH_URL || '';
const PUBLIC_BACKEND_URL_CLIENT =
process.env.PUBLIC_BACKEND_URL_CLIENT || process.env.PUBLIC_BACKEND_URL || '';
+const PUBLIC_STT_URL = process.env.PUBLIC_STT_URL || 'https://stt-api.mana.how';
export const handle: Handle = async ({ event, resolve }) => {
return resolve(event, {
@@ -20,6 +21,7 @@ export const handle: Handle = async ({ event, resolve }) => {
const envScript = ``;
return html.replace('
', `${envScript}`);
},
diff --git a/apps/calendar/apps/web/src/lib/components/settings/SettingsModal.svelte b/apps/calendar/apps/web/src/lib/components/settings/SettingsModal.svelte
index 00f234422..4bd9dd614 100644
--- a/apps/calendar/apps/web/src/lib/components/settings/SettingsModal.svelte
+++ b/apps/calendar/apps/web/src/lib/components/settings/SettingsModal.svelte
@@ -4,7 +4,7 @@
import { authStore } from '$lib/stores/auth.svelte';
import { userSettings } from '$lib/stores/user-settings.svelte';
import { settingsStore } from '$lib/stores/settings.svelte';
- import type { TimeFormat, AllDayDisplayMode } from '$lib/stores/settings.svelte';
+ import type { TimeFormat, AllDayDisplayMode, SttLanguage } from '$lib/stores/settings.svelte';
import { calendarsStore } from '$lib/stores/calendars.svelte';
import { toast } from '$lib/stores/toast.svelte';
import {
@@ -620,6 +620,48 @@
+
+
+ {#snippet icon()}
+
+ {/snippet}
+
+
+
+
+ Sprache der Spracherkennung
+ Sprache für die Transkription von Sprachaufnahmen
+
+
+
+
+
+
+
+
+
+
{#snippet icon()}
diff --git a/apps/calendar/apps/web/src/lib/services/stt.ts b/apps/calendar/apps/web/src/lib/services/stt.ts
index 1ed2c509d..037865503 100644
--- a/apps/calendar/apps/web/src/lib/services/stt.ts
+++ b/apps/calendar/apps/web/src/lib/services/stt.ts
@@ -7,11 +7,18 @@
import { browser } from '$app/environment';
/**
- * STT service URL - defaults to localhost for development
+ * STT service URL - uses runtime injection for production, env var for dev
*/
-const STT_URL = browser
- ? import.meta.env.PUBLIC_STT_URL || 'http://localhost:3020'
- : 'http://localhost:3020';
+function getSttUrl(): string {
+ if (!browser) return 'http://localhost:3020';
+ // Check runtime-injected variable first (production Docker)
+ const runtimeUrl = (window as any).__PUBLIC_STT_URL__;
+ if (runtimeUrl) return runtimeUrl;
+ // Fall back to build-time env var or default
+ return import.meta.env.PUBLIC_STT_URL || 'https://stt-api.mana.how';
+}
+
+const STT_URL = getSttUrl();
export interface TranscriptionResult {
/** The transcribed text */
diff --git a/apps/calendar/apps/web/src/lib/stores/settings.svelte.ts b/apps/calendar/apps/web/src/lib/stores/settings.svelte.ts
index 32de61472..b82b4b1d3 100644
--- a/apps/calendar/apps/web/src/lib/stores/settings.svelte.ts
+++ b/apps/calendar/apps/web/src/lib/stores/settings.svelte.ts
@@ -14,6 +14,7 @@ export type WeekStartDay = 0 | 1; // 0 = Sunday, 1 = Monday
export type TimeFormat = '24h' | '12h';
export type AllDayDisplayMode = 'header' | 'block'; // header = separate row, block = full day block in grid
export type WeekdayFormat = 'full' | 'short' | 'hidden';
+export type SttLanguage = 'de' | 'auto'; // Speech-to-text language setting
export interface CalendarAppSettings {
// View settings
@@ -64,6 +65,9 @@ export interface CalendarAppSettings {
// Event defaults
defaultEventDuration: number; // in minutes
defaultReminder: number; // in minutes before event
+
+ // Voice input settings
+ sttLanguage: SttLanguage; // Speech-to-text language ('de' or 'auto')
}
const DEFAULT_SETTINGS: CalendarAppSettings = {
@@ -106,6 +110,8 @@ const DEFAULT_SETTINGS: CalendarAppSettings = {
// Event defaults
defaultEventDuration: 60,
defaultReminder: 15,
+ // Voice input defaults
+ sttLanguage: 'de',
};
const STORAGE_KEY = 'calendar-settings';
@@ -275,6 +281,9 @@ export const settingsStore = {
get customDayCount() {
return settings.customDayCount;
},
+ get sttLanguage() {
+ return settings.sttLanguage;
+ },
get cloudSyncEnabled() {
return cloudSyncEnabled;
},
diff --git a/apps/calendar/apps/web/src/lib/utils/audio-recorder.ts b/apps/calendar/apps/web/src/lib/utils/audio-recorder.ts
index afd99c86c..9554bebe6 100644
--- a/apps/calendar/apps/web/src/lib/utils/audio-recorder.ts
+++ b/apps/calendar/apps/web/src/lib/utils/audio-recorder.ts
@@ -35,7 +35,12 @@ export interface AudioRecorder {
* Check if the browser supports audio recording
*/
export function isAudioRecordingSupported(): boolean {
- return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia && window.MediaRecorder);
+ return !!(
+ typeof navigator !== 'undefined' &&
+ navigator.mediaDevices &&
+ typeof navigator.mediaDevices.getUserMedia === 'function' &&
+ typeof MediaRecorder !== 'undefined'
+ );
}
/**
diff --git a/scripts/generate-env.mjs b/scripts/generate-env.mjs
index b0c8935d5..ba8fac561 100644
--- a/scripts/generate-env.mjs
+++ b/scripts/generate-env.mjs
@@ -391,6 +391,8 @@ const APP_CONFIGS = [
// Cross-app integration: Contacts service for birthdays
PUBLIC_CONTACTS_API_URL: (env) => `http://localhost:${env.CONTACTS_BACKEND_PORT || '3015'}`,
PUBLIC_CONTACTS_WEB_URL: () => 'http://localhost:5184',
+ // Speech-to-Text Service
+ PUBLIC_STT_URL: (env) => env.STT_URL || 'http://localhost:3020',
},
},