2296
2297	  #[test]
2298	  fn projekt_wizard_doppelt_scheitert() {
2299	    let p = tmp_paths();
2300	    create_project_in(&p, "neu").unwrap();
2301	    let err =
2302	      create_project_full_in(&p, "neu", None, None, None, false, TerminalConfig::default(), false)
2303	        .unwrap_err();
2304	    assert!(err.contains("existiert bereits"));
2305	  }
2306
2307	  #[test]
2308	  fn projekt_wizard_fehlendes_workdir_scheitert() {
2309	    let p = tmp_paths();
2310	    let err = create_project_full_in(
2311	      &p,
2312	      "neu",
2313	      None,
2314	      Some("~/projects/gibtsnicht"),
2315	      false,
2316	      TerminalConfig::default(),
2317	      false,
2318	    )
2319	    .unwrap_err();
2320	    assert!(err.contains("Arbeitsverzeichnis fehlt"));
2321	    // kein halbes Projekt zurückgeblieben
2322	    assert!(!p.projects_dir().join("neu").exists());
2323	  }
2324
2325	  // -- Verbrauch --
2326
2327	  fn usage_line(id: &str, req: &str, ts: &str, model: &str, input: u64, output: u64) -> String {
2328	    serde_json::json!({
2329	      "type": "assistant",
2330	      "timestamp": ts,

  #[test]
  fn projekt_wizard_doppelt_scheitert() {
    let p = tmp_paths();
    create_project_in(&p, "neu").unwrap();
    let err =
      create_project_full_in(&p, "neu", None, None, None, false, TerminalConfig::default(), false)
        .unwrap_err();
    assert!(err.contains("existiert bereits"));
  }

  #[test]
  fn projekt_wizard_fehlendes_workdir_scheitert() {
    let p = tmp_paths();
    let err = create_project_full_in(
      &p,
      "neu",
      None,
      Some("~/projects/gibtsnicht"),
      false,
      TerminalConfig::default(),
      false,
    )
    .unwrap_err();
    assert!(err.contains("Arbeitsverzeichnis fehlt"));
    // kein halbes Projekt zurückgeblieben
    assert!(!p.projects_dir().join("neu").exists());
  }

  // -- Verbrauch --

  fn usage_line(id: &str, req: &str, ts: &str, model: &str, input: u64, output: u64) -> String {
    serde_json::json!({
      "type": "assistant",
      "timestamp": ts,


Edit

    let err = create_project_full_in(
      &p,
      "neu",
      None,
      Some("~/projects/gibtsnicht"),
      false,
      TerminalConfig::default(),
      false,
    )
    .unwrap_err();

    let err = create_project_full_in(
      &p,
      "neu",
      None,
      None,
      Some("~/projects/gibtsnicht"),
      false,
      TerminalConfig::default(),
      false,
    )
    .unwrap_err();


The file /Users/marcus.hinz/projects/ai-control/src-tauri/src/lib.rs has been updated successfully. (file state is current in your context — no need to Read it back)

    let err = create_project_full_in(
      &p,
      "neu",
      None,
      Some("~/projects/gibtsnicht"),
      false,
      TerminalConfig::default(),
      false,
    )
    .unwrap_err();

    let err = create_project_full_in(
      &p,
      "neu",
      None,
      None,
      Some("~/projects/gibtsnicht"),
      false,
      TerminalConfig::default(),
      false,
    )
    .unwrap_err();

&p,
"neu",
None,
+      None,
Some("~/projects/gibtsnicht"),
false,
TerminalConfig::default(),


Bash

export CARGO_HOME="$HOME/tools/.cargo" RUSTUP_HOME="$HOME/tools/.rustup" PATH="$HOME/tools/.cargo/bin:$PATH"; cargo test --manifest-path /Users/marcus.hinz/projects/ai-control/src-tauri/Cargo.toml 2>&1 | grep -E "FAILED|test result|panicked at|^---- " -A 2 | head -60

Run test suite again


test tests::projekt_arbeitsordner_auslesen ... FAILED
test tests::pool_key_status_aus_store ... ok
test tests::projekt_loeschen ... ok
--
test tests::projekt_loeschen_fehlender_arbeitsordner_scheitert ... FAILED
test tests::projekt_loeschen_laesst_arbeitsordner ... FAILED
test tests::projekt_loeschen_unbekannt_scheitert ... ok
test tests::projekt_rausnehmen_ohne_zuordnung_scheitert ... ok
test tests::projekt_loeschen_mit_arbeitsordner ... FAILED
test tests::pool_umbenennen_auf_vergebenen_namen_scheitert ... ok
test tests::projekt_wizard_doppelt_scheitert ... ok
--
test tests::projekt_wizard_minimal_ohne_pool_und_workdir ... FAILED
test tests::todo_ohne_settings_scheitert ... ok
test tests::todo_zuschalten_und_abschalten ... FAILED
test tests::projekt_wizard_scaffold ... FAILED
test tests::projekt_rausnehmen ... ok
test tests::pool_wechseln_typ_ist_projekt_egal ... ok
--
---- tests::projekt_arbeitsordner_auslesen stdout ----

thread 'tests::projekt_arbeitsordner_auslesen' (535904) panicked at src/lib.rs:2630:8:
called `Result::unwrap()` on an `Err` value: "Projekt existiert bereits: proj"
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
--
---- tests::projekt_loeschen_fehlender_arbeitsordner_scheitert stdout ----

thread 'tests::projekt_loeschen_fehlender_arbeitsordner_scheitert' (535919) panicked at src/lib.rs:2621:8:
called `Result::unwrap()` on an `Err` value: "Projekt existiert bereits: proj"

---- tests::projekt_loeschen_laesst_arbeitsordner stdout ----

thread 'tests::projekt_loeschen_laesst_arbeitsordner' (535920) panicked at src/lib.rs:2601:8:
called `Result::unwrap()` on an `Err` value: "Projekt existiert bereits: proj"

---- tests::projekt_loeschen_mit_arbeitsordner stdout ----

thread 'tests::projekt_loeschen_mit_arbeitsordner' (535921) panicked at src/lib.rs:2611:8:
called `Result::unwrap()` on an `Err` value: "Projekt existiert bereits: proj"

---- tests::projekt_wizard_minimal_ohne_pool_und_workdir stdout ----

thread 'tests::projekt_wizard_minimal_ohne_pool_und_workdir' (535928) panicked at src/lib.rs:2284:98:
called `Result::unwrap()` on an `Err` value: "Projekt existiert bereits: neu"

---- tests::todo_zuschalten_und_abschalten stdout ----

thread 'tests::todo_zuschalten_und_abschalten' (535934) panicked at src/lib.rs:2248:8:
called `Result::unwrap()` on an `Err` value: "Projekt existiert bereits: proj"

---- tests::projekt_wizard_scaffold stdout ----

thread 'tests::projekt_wizard_scaffold' (535929) panicked at src/lib.rs:2208:6:
called `Result::unwrap()` on an `Err` value: "Projekt existiert bereits: neu"

--
test result: FAILED. 41 passed; 7 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.24s

error: test failed, to rerun pass `--lib`


Edit

  check_name(name)?;
  let dir = match dir {
    Some(d) => expand_home(paths, d),
    None => paths.projects_dir().join(name),
  };
  if load_registry(paths)?.contains_key(name) {
    return Err(format!("Projekt existiert bereits: {name}"));
  }

  check_name(name)?;
  let dir = match dir {
    Some(d) => expand_home(paths, d),
    None => paths.projects_dir().join(name),
  };
  // Registry-Snapshot vor dem Anlegen — der Alt-Layout-Scan würde den frisch
  // angelegten Ordner sonst schon als bestehendes Projekt sehen.
  let mut reg = load_registry(paths)?;
  if reg.contains_key(name) {
    return Err(format!("Projekt existiert bereits: {name}"));
  }


  check_name(name)?;
  let dir = match dir {
    Some(d) => expand_home(paths, d),
    None => paths.projects_dir().join(name),
  };
  if load_registry(paths)?.contains_key(name) {
    return Err(format!("Projekt existiert bereits: {name}"));
  }

  check_name(name)?;
  let dir = match dir {
    Some(d) => expand_home(paths, d),
    None => paths.projects_dir().join(name),
  };
  // Registry-Snapshot vor dem Anlegen — der Alt-Layout-Scan würde den frisch
  // angelegten Ordner sonst schon als bestehendes Projekt sehen.
  let mut reg = load_registry(paths)?;
  if reg.contains_key(name) {
    return Err(format!("Projekt existiert bereits: {name}"));
  }

-  if load_registry(paths)?.contains_key(name) {

+  // Registry-Snapshot vor dem Anlegen — der Alt-Layout-Scan würde den frisch

+  // angelegten Ordner sonst schon als bestehendes Projekt sehen.


  register_project(paths, name, &dir)?;
  let cfg = ProjectConfig { pool: pool.map(str::to_string), terminal };

  reg.insert(name.to_string(), dir.clone());
  save_registry(paths, &reg)?;
  let cfg = ProjectConfig { pool: pool.map(str::to_string), terminal };


  register_project(paths, name, &dir)?;
  let cfg = ProjectConfig { pool: pool.map(str::to_string), terminal };

  reg.insert(name.to_string(), dir.clone());
  save_registry(paths, &reg)?;
  let cfg = ProjectConfig { pool: pool.map(str::to_string), terminal };

let raw = serde_json::to_string_pretty(&settings).map_err(|e| e.to_string())?;

fs::write(dir.join(".claude").join("settings.json"), raw + "\n").map_err(|e| e.to_string())?;

-  register_project(paths, name, &dir)?;

+  reg.insert(name.to_string(), dir.clone());

if cfg.pool.is_some() || !cfg.terminal.is_empty() {


TryMenü für Projektliste mit Start/Stop-Button


Bash

export CARGO_HOME="$HOME/tools/.cargo" RUSTUP_HOME="$HOME/tools/.rustup" PATH="$HOME/tools/.cargo/bin:$PATH"; cargo test --manifest-path /Users/marcus.hinz/projects/ai-control/src-tauri/Cargo.toml 2>&1 | grep -E "FAILED|test result|panicked at" -A 2 | head -30

Run test suite again


test result: ok. 48 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.59s

     Running unittests src/main.rs (/Users/marcus.hinz/projects/ai-control/src-tauri/target/debug/deps/ai_control-cb387f5a798b9c01)
--
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests app_lib
--
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


Backend fertig, alle 48 Tests grün. Jetzt das Frontend — i18n-Keys ansehen:


1	import { createI18n } from "vue-i18n";
2
3	const de = {
4	  app: {
5	    projects: "Projekte",
6	    pools: "Pools",
7	    usage: "Verbrauch",
8	    autostart: "Autostart",
9	  },
10	  usage: {
11	    days7: "7 Tage",
12	    days30: "30 Tage",
13	    pool: "Pool",
14	    project: "Projekt",
15	    input: "Input",
16	    output: "Output",
17	    cacheWrite: "Cache ↑",
18	    cacheRead: "Cache ↓",
19	    cost: "≈ Kosten",
20	    total: "Summe",
21	    empty: "Keine Verbrauchsdaten im Zeitraum.",
22	    estimateNote:
23	      "API-Gegenwert aus den lokalen Transcripts — keine Abrechnung, Historie nur solange claude sie vorhält.",
24	  },
25	  projects: {
26	    project: "Projekt",
27	    pool: "Pool",
28	    noPool: "– kein Pool –",
29	    start: "Starten",
30	    stop: "Beenden",
31	    terminalSettings: "Terminal-Einstellungen",
32	    stillRunning: "{name} läuft noch",
33	    poolChangeSaved:
34	      "Der Pool-Wechsel ist gespeichert. Die laufende Session arbeitet aber weiter im alten Pool — der neue gilt erst ab dem nächsten Start.",
35	    restartHint:
36	      "Der Neustart beendet die laufende Session. Der automatische commit+push von claude-sync nach Sessionende entfällt dabei.",
37	    keepRunning: "Weiterlaufen lassen",
38	    restartNow: "Jetzt neu starten",
39	    restarting: "Starte neu …",
40	    terminal: "Terminal — {name}",
41	    title: "Titel",
42	    theme: "Theme",
43	    dockIcon: "Dock-Icon",
44	    chooseFile: "Datei wählen …",
45	    remove: "Entfernen",
46	    defaultIcon: "Standard-Icon",
47	    appliesNextStart: "Gilt ab dem nächsten Terminal-Start.",
48	    cancel: "Abbrechen",
49	    save: "Speichern",
50	    noPoolAssigned: "kein Pool",
51	    needsPool: "Kein Pool zugeordnet",
52	    needsKey: "Pool hat keinen API-Key",
53	    newProject: "+ Projekt",
54	    wizardTitle: "Neues Projekt",
55	    name: "Name",
56	    workDir: "Arbeitsordner",
57	    workDirNone: "keiner",
58	    workDirCustom: "vorhandenen Ordner verknüpfen",
59	    chooseFolder: "Ordner wählen …",
60	    create: "Anlegen",
61	    wizardHint:
62	      "Angelegt werden Projektordner mit memory/, Sentinel-.gitignore, settings.json (Memory-Verzeichnis + Berechtigungen) und die Pool-/Terminal-Zuordnung.",
63	    delete: "Projekt löschen",
64	    deleteRunning: "Läuft noch — erst beenden",
65	    deleteTitle: "{name} löschen",
66	    deleteWarning:
67	      "Der Projektordner unter ~/claude-projects (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
68	    deleteWorkDirs: "Arbeitsordner mitlöschen:",
69	    workDirsStay: "Die Arbeitsordner bleiben unangetastet.",
70	    todo: "Todoliste",
71	    todoDesc: "OFFENE-PUNKTE.md bei jedem Sessionstart einspielen",
72	  },
73	  pools: {
74	    pool: "Pool",
75	    type: "Typ",
76	    actions: "Aktionen",
77	    newOauth: "+ oAuth",
78	    newApikey: "+ apiKey",
79	    relogin: "Zurücksetzen",
80	    rename: "Umbenennen",
81	    renameTitle: "{name} umbenennen",
82	    changeKey: "Key ändern",
83	    insertKey: "Key eintragen",
84	    delete: "Löschen",
85	    assigned: "kein Projekt | 1 Projekt | {count} Projekte",
86	    empty: "Noch keine Pools angelegt.",
87	    newOauthPool: "Neuen oAuth-Pool anlegen",
88	    newApikeyPool: "Neuen API-Key-Pool anlegen",
89	    editKey: "API-Key ändern – {name}",
90	    name: "Name",
91	    apiKey: "API-Key",
92	    oauthHint:
93	      "Der Pool wird angelegt; die Anmeldung macht claude beim ersten Start selbst per /login (Browser gegen dein Abo).",
94	    cancel: "Abbrechen",
95	    createPool: "Anlegen",
96	    reset: "Zurücksetzen",
97	    save: "Speichern",
98	    deletePool: "Pool löschen",
99	    deleteWarning:
100	      "Pool {name} und seine Credential-Datei werden gelöscht. Das lässt sich nicht rückgängig machen.",
101	    deleteUnassigns: "Diese Projekte verlieren ihre Pool-Zuordnung:",
102	    deleteBlockedTooltip:
103	      "Löschen gesperrt — {projects} läuft gerade. Erst beenden.",
104	    reloginTitle: "{name} zurücksetzen",
105	    reloginWarning:
106	      "Der im Schlüsselbund gespeicherte Zugriffstoken von {name} wird gelöscht. Beim nächsten Start verlangt claude erneut /login.",
107	    reloginNoEntry:
108	      "Kein Schlüsselbund-Eintrag vorhanden — beim nächsten Start meldet sich claude ohnehin per /login an.",
109	    reloginBlocked:
110	      "Zurücksetzen ist nur bei ungenutztem Pool möglich. Diese Projekte laufen noch:",
111	    keychainUnavailableTitle: "Keine sichere Ablage",
112	    keychainUnavailable:
113	      "Keychain/Keyring ist nicht verfügbar. Der Key kann stattdessen ungesichert als Datei im Pool-Ordner liegen (0600).",
114	    storeAsFile: "Als Datei ablegen",
115	  },
116	};
117
118	const en: typeof de = {
119	  app: {
120	    projects: "Projects",
121	    pools: "Pools",
122	    usage: "Usage",
123	    autostart: "Autostart",
124	  },
125	  usage: {
126	    days7: "7 days",
127	    days30: "30 days",
128	    pool: "Pool",
129	    project: "Project",
130	    input: "Input",
131	    output: "Output",
132	    cacheWrite: "Cache ↑",
133	    cacheRead: "Cache ↓",
134	    cost: "≈ cost",
135	    total: "Total",
136	    empty: "No usage data in this period.",
137	    estimateNote:
138	      "API equivalent from local transcripts — not a bill; history only as long as claude keeps it.",
139	  },
140	  projects: {
141	    project: "Project",
142	    pool: "Pool",
143	    noPool: "– no pool –",
144	    start: "Start",
145	    stop: "Stop",
146	    terminalSettings: "Terminal settings",
147	    stillRunning: "{name} is still running",
148	    poolChangeSaved:
149	      "The pool change is saved. The running session keeps working in the old pool — the new one applies from the next start.",
150	    restartHint:
151	      "Restarting ends the running session. The automatic commit+push by claude-sync after the session is skipped.",
152	    keepRunning: "Keep running",
153	    restartNow: "Restart now",
154	    restarting: "Restarting …",
155	    terminal: "Terminal — {name}",
156	    title: "Title",
157	    theme: "Theme",
158	    dockIcon: "Dock icon",
159	    chooseFile: "Choose file …",
160	    remove: "Remove",
161	    defaultIcon: "Default icon",
162	    appliesNextStart: "Applies from the next terminal start.",
163	    cancel: "Cancel",
164	    save: "Save",
165	    noPoolAssigned: "no pool",
166	    needsPool: "No pool assigned",
167	    needsKey: "Pool has no API key",
168	    newProject: "+ Project",
169	    wizardTitle: "New project",
170	    name: "Name",
171	    workDir: "Working folder",
172	    workDirNone: "none",
173	    workDirCustom: "link existing folder",
174	    chooseFolder: "Choose folder …",
175	    create: "Create",
176	    wizardHint:
177	      "Creates the project folder with memory/, sentinel .gitignore, settings.json (memory dir + permissions), and the pool/terminal assignment.",
178	    delete: "Delete project",
179	    deleteRunning: "Still running — stop it first",
180	    deleteTitle: "Delete {name}",
181	    deleteWarning:
182	      "The project folder under ~/claude-projects (incl. memory/, settings and pool assignment) will be deleted permanently.",
183	    deleteWorkDirs: "Also delete working folders:",
184	    workDirsStay: "The working folders stay untouched.",
185	    todo: "Todo list",
186	    todoDesc: "Inject OFFENE-PUNKTE.md at every session start",
187	  },
188	  pools: {
189	    pool: "Pool",
190	    type: "Type",
191	    actions: "Actions",
192	    newOauth: "+ oAuth",
193	    newApikey: "+ apiKey",
194	    relogin: "Reset",
195	    rename: "Rename",
196	    renameTitle: "Rename {name}",
197	    changeKey: "Change key",
198	    insertKey: "Insert key",
199	    delete: "Delete",
200	    assigned: "no projects | 1 project | {count} projects",
201	    empty: "No pools yet.",
202	    newOauthPool: "Create oAuth pool",
203	    newApikeyPool: "Create API key pool",
204	    editKey: "Change API key – {name}",
205	    name: "Name",
206	    apiKey: "API key",
207	    oauthHint:
208	      "The pool is created; claude signs in itself on first start via /login (browser against your subscription).",
209	    cancel: "Cancel",
210	    createPool: "Create",
211	    reset: "Reset",
212	    save: "Save",
213	    deletePool: "Delete pool",
214	    deleteWarning:
215	      "Pool {name} and its credential file will be deleted. This cannot be undone.",
216	    deleteUnassigns: "These projects lose their pool assignment:",
217	    deleteBlockedTooltip:
218	      "Deletion blocked — active: {projects}. Stop the session first.",
219	    reloginTitle: "Reset {name}",
220	    reloginWarning:
221	      "The access token for {name} stored in the keychain will be deleted. On the next start claude asks for /login again.",
222	    reloginNoEntry:
223	      "No keychain entry present — claude signs in via /login on the next start anyway.",
224	    reloginBlocked:
225	      "Resetting requires an unused pool. These projects are still running:",
226	    keychainUnavailableTitle: "No secure storage",
227	    keychainUnavailable:
228	      "Keychain/keyring is unavailable. The key can instead be stored unprotected as a file in the pool folder (0600).",
229	    storeAsFile: "Store as file",
230	  },
231	};
232
233	const stored = localStorage.getItem("lang");
234	const initial =
235	  stored === "de" || stored === "en"
236	    ? stored
237	    : navigator.language.startsWith("de")
238	      ? "de"
239	      : "en";
240
241	export const i18n = createI18n({
242	  legacy: false,
243	  globalInjection: true,
244	  locale: initial,
245	  fallbackLocale: "en",
246	  messages: { de, en },
247	});
248
249	export function setLocale(lang: "de" | "en") {
250	  i18n.global.locale.value = lang;
251	  localStorage.setItem("lang", lang);
252	}
253

import { createI18n } from "vue-i18n";

const de = {
  app: {
    projects: "Projekte",
    pools: "Pools",
    usage: "Verbrauch",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 Tage",
    days30: "30 Tage",
    pool: "Pool",
    project: "Projekt",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ Kosten",
    total: "Summe",
    empty: "Keine Verbrauchsdaten im Zeitraum.",
    estimateNote:
      "API-Gegenwert aus den lokalen Transcripts — keine Abrechnung, Historie nur solange claude sie vorhält.",
  },
  projects: {
    project: "Projekt",
    pool: "Pool",
    noPool: "– kein Pool –",
    start: "Starten",
    stop: "Beenden",
    terminalSettings: "Terminal-Einstellungen",
    stillRunning: "{name} läuft noch",
    poolChangeSaved:
      "Der Pool-Wechsel ist gespeichert. Die laufende Session arbeitet aber weiter im alten Pool — der neue gilt erst ab dem nächsten Start.",
    restartHint:
      "Der Neustart beendet die laufende Session. Der automatische commit+push von claude-sync nach Sessionende entfällt dabei.",
    keepRunning: "Weiterlaufen lassen",
    restartNow: "Jetzt neu starten",
    restarting: "Starte neu …",
    terminal: "Terminal — {name}",
    title: "Titel",
    theme: "Theme",
    dockIcon: "Dock-Icon",
    chooseFile: "Datei wählen …",
    remove: "Entfernen",
    defaultIcon: "Standard-Icon",
    appliesNextStart: "Gilt ab dem nächsten Terminal-Start.",
    cancel: "Abbrechen",
    save: "Speichern",
    noPoolAssigned: "kein Pool",
    needsPool: "Kein Pool zugeordnet",
    needsKey: "Pool hat keinen API-Key",
    newProject: "+ Projekt",
    wizardTitle: "Neues Projekt",
    name: "Name",
    workDir: "Arbeitsordner",
    workDirNone: "keiner",
    workDirCustom: "vorhandenen Ordner verknüpfen",
    chooseFolder: "Ordner wählen …",
    create: "Anlegen",
    wizardHint:
      "Angelegt werden Projektordner mit memory/, Sentinel-.gitignore, settings.json (Memory-Verzeichnis + Berechtigungen) und die Pool-/Terminal-Zuordnung.",
    delete: "Projekt löschen",
    deleteRunning: "Läuft noch — erst beenden",
    deleteTitle: "{name} löschen",
    deleteWarning:
      "Der Projektordner unter ~/claude-projects (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
    deleteWorkDirs: "Arbeitsordner mitlöschen:",
    workDirsStay: "Die Arbeitsordner bleiben unangetastet.",
    todo: "Todoliste",
    todoDesc: "OFFENE-PUNKTE.md bei jedem Sessionstart einspielen",
  },
  pools: {
    pool: "Pool",
    type: "Typ",
    actions: "Aktionen",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Zurücksetzen",
    rename: "Umbenennen",
    renameTitle: "{name} umbenennen",
    changeKey: "Key ändern",
    insertKey: "Key eintragen",
    delete: "Löschen",
    assigned: "kein Projekt | 1 Projekt | {count} Projekte",
    empty: "Noch keine Pools angelegt.",
    newOauthPool: "Neuen oAuth-Pool anlegen",
    newApikeyPool: "Neuen API-Key-Pool anlegen",
    editKey: "API-Key ändern – {name}",
    name: "Name",
    apiKey: "API-Key",
    oauthHint:
      "Der Pool wird angelegt; die Anmeldung macht claude beim ersten Start selbst per /login (Browser gegen dein Abo).",
    cancel: "Abbrechen",
    createPool: "Anlegen",
    reset: "Zurücksetzen",
    save: "Speichern",
    deletePool: "Pool löschen",
    deleteWarning:
      "Pool {name} und seine Credential-Datei werden gelöscht. Das lässt sich nicht rückgängig machen.",
    deleteUnassigns: "Diese Projekte verlieren ihre Pool-Zuordnung:",
    deleteBlockedTooltip:
      "Löschen gesperrt — {projects} läuft gerade. Erst beenden.",
    reloginTitle: "{name} zurücksetzen",
    reloginWarning:
      "Der im Schlüsselbund gespeicherte Zugriffstoken von {name} wird gelöscht. Beim nächsten Start verlangt claude erneut /login.",
    reloginNoEntry:
      "Kein Schlüsselbund-Eintrag vorhanden — beim nächsten Start meldet sich claude ohnehin per /login an.",
    reloginBlocked:
      "Zurücksetzen ist nur bei ungenutztem Pool möglich. Diese Projekte laufen noch:",
    keychainUnavailableTitle: "Keine sichere Ablage",
    keychainUnavailable:
      "Keychain/Keyring ist nicht verfügbar. Der Key kann stattdessen ungesichert als Datei im Pool-Ordner liegen (0600).",
    storeAsFile: "Als Datei ablegen",
  },
};

const en: typeof de = {
  app: {
    projects: "Projects",
    pools: "Pools",
    usage: "Usage",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 days",
    days30: "30 days",
    pool: "Pool",
    project: "Project",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ cost",
    total: "Total",
    empty: "No usage data in this period.",
    estimateNote:
      "API equivalent from local transcripts — not a bill; history only as long as claude keeps it.",
  },
  projects: {
    project: "Project",
    pool: "Pool",
    noPool: "– no pool –",
    start: "Start",
    stop: "Stop",
    terminalSettings: "Terminal settings",
    stillRunning: "{name} is still running",
    poolChangeSaved:
      "The pool change is saved. The running session keeps working in the old pool — the new one applies from the next start.",
    restartHint:
      "Restarting ends the running session. The automatic commit+push by claude-sync after the session is skipped.",
    keepRunning: "Keep running",
    restartNow: "Restart now",
    restarting: "Restarting …",
    terminal: "Terminal — {name}",
    title: "Title",
    theme: "Theme",
    dockIcon: "Dock icon",
    chooseFile: "Choose file …",
    remove: "Remove",
    defaultIcon: "Default icon",
    appliesNextStart: "Applies from the next terminal start.",
    cancel: "Cancel",
    save: "Save",
    noPoolAssigned: "no pool",
    needsPool: "No pool assigned",
    needsKey: "Pool has no API key",
    newProject: "+ Project",
    wizardTitle: "New project",
    name: "Name",
    workDir: "Working folder",
    workDirNone: "none",
    workDirCustom: "link existing folder",
    chooseFolder: "Choose folder …",
    create: "Create",
    wizardHint:
      "Creates the project folder with memory/, sentinel .gitignore, settings.json (memory dir + permissions), and the pool/terminal assignment.",
    delete: "Delete project",
    deleteRunning: "Still running — stop it first",
    deleteTitle: "Delete {name}",
    deleteWarning:
      "The project folder under ~/claude-projects (incl. memory/, settings and pool assignment) will be deleted permanently.",
    deleteWorkDirs: "Also delete working folders:",
    workDirsStay: "The working folders stay untouched.",
    todo: "Todo list",
    todoDesc: "Inject OFFENE-PUNKTE.md at every session start",
  },
  pools: {
    pool: "Pool",
    type: "Type",
    actions: "Actions",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Reset",
    rename: "Rename",
    renameTitle: "Rename {name}",
    changeKey: "Change key",
    insertKey: "Insert key",
    delete: "Delete",
    assigned: "no projects | 1 project | {count} projects",
    empty: "No pools yet.",
    newOauthPool: "Create oAuth pool",
    newApikeyPool: "Create API key pool",
    editKey: "Change API key – {name}",
    name: "Name",
    apiKey: "API key",
    oauthHint:
      "The pool is created; claude signs in itself on first start via /login (browser against your subscription).",
    cancel: "Cancel",
    createPool: "Create",
    reset: "Reset",
    save: "Save",
    deletePool: "Delete pool",
    deleteWarning:
      "Pool {name} and its credential file will be deleted. This cannot be undone.",
    deleteUnassigns: "These projects lose their pool assignment:",
    deleteBlockedTooltip:
      "Deletion blocked — active: {projects}. Stop the session first.",
    reloginTitle: "Reset {name}",
    reloginWarning:
      "The access token for {name} stored in the keychain will be deleted. On the next start claude asks for /login again.",
    reloginNoEntry:
      "No keychain entry present — claude signs in via /login on the next start anyway.",
    reloginBlocked:
      "Resetting requires an unused pool. These projects are still running:",
    keychainUnavailableTitle: "No secure storage",
    keychainUnavailable:
      "Keychain/keyring is unavailable. The key can instead be stored unprotected as a file in the pool folder (0600).",
    storeAsFile: "Store as file",
  },
};

const stored = localStorage.getItem("lang");
const initial =
  stored === "de" || stored === "en"
    ? stored
    : navigator.language.startsWith("de")
      ? "de"
      : "en";

export const i18n = createI18n({
  legacy: false,
  globalInjection: true,
  locale: initial,
  fallbackLocale: "en",
  messages: { de, en },
});

export function setLocale(lang: "de" | "en") {
  i18n.global.locale.value = lang;
  localStorage.setItem("lang", lang);
}


Edit

    newProject: "+ Projekt",
    wizardTitle: "Neues Projekt",
    name: "Name",
    workDir: "Arbeitsordner",

    newProject: "+ Projekt",
    addFolder: "+ Ordner",
    addFolderTitle: "Bestehenden Ordner als Projekt aufnehmen",
    wizardTitle: "Neues Projekt",
    name: "Name",
    projectDir: "Projektordner",
    projectDirCustom: "Ordner wählen …",
    workDir: "Arbeitsordner",


The file /Users/marcus.hinz/projects/ai-control/src/i18n.ts has been updated successfully. (file state is current in your context — no need to Read it back)

    newProject: "+ Projekt",
    addFolder: "+ Ordner",
    addFolderTitle: "Bestehenden Ordner als Projekt aufnehmen",
    wizardTitle: "Neues Projekt",
    name: "Name",
    projectDir: "Projektordner",
    projectDirCustom: "Ordner wählen …",
    workDir: "Arbeitsordner",

import { createI18n } from "vue-i18n";

const de = {
  app: {
    projects: "Projekte",
    pools: "Pools",
    usage: "Verbrauch",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 Tage",
    days30: "30 Tage",
    pool: "Pool",
    project: "Projekt",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ Kosten",
    total: "Summe",
    empty: "Keine Verbrauchsdaten im Zeitraum.",
    estimateNote:
      "API-Gegenwert aus den lokalen Transcripts — keine Abrechnung, Historie nur solange claude sie vorhält.",
  },
  projects: {
    project: "Projekt",
    pool: "Pool",
    noPool: "– kein Pool –",
    start: "Starten",
    stop: "Beenden",
    terminalSettings: "Terminal-Einstellungen",
    stillRunning: "{name} läuft noch",
    poolChangeSaved:
      "Der Pool-Wechsel ist gespeichert. Die laufende Session arbeitet aber weiter im alten Pool — der neue gilt erst ab dem nächsten Start.",
    restartHint:
      "Der Neustart beendet die laufende Session. Der automatische commit+push von claude-sync nach Sessionende entfällt dabei.",
    keepRunning: "Weiterlaufen lassen",
    restartNow: "Jetzt neu starten",
    restarting: "Starte neu …",
    terminal: "Terminal — {name}",
    title: "Titel",
    theme: "Theme",
    dockIcon: "Dock-Icon",
    chooseFile: "Datei wählen …",
    remove: "Entfernen",
    defaultIcon: "Standard-Icon",
    appliesNextStart: "Gilt ab dem nächsten Terminal-Start.",
    cancel: "Abbrechen",
    save: "Speichern",
    noPoolAssigned: "kein Pool",
    needsPool: "Kein Pool zugeordnet",
    needsKey: "Pool hat keinen API-Key",
    newProject: "+ Projekt",
    wizardTitle: "Neues Projekt",
    name: "Name",
    workDir: "Arbeitsordner",
    workDirNone: "keiner",
    workDirCustom: "vorhandenen Ordner verknüpfen",
    chooseFolder: "Ordner wählen …",
    create: "Anlegen",
    wizardHint:
      "Angelegt werden Projektordner mit memory/, Sentinel-.gitignore, settings.json (Memory-Verzeichnis + Berechtigungen) und die Pool-/Terminal-Zuordnung.",
    delete: "Projekt löschen",
    deleteRunning: "Läuft noch — erst beenden",
    deleteTitle: "{name} löschen",
    deleteWarning:
      "Der Projektordner unter ~/claude-projects (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
    deleteWorkDirs: "Arbeitsordner mitlöschen:",
    workDirsStay: "Die Arbeitsordner bleiben unangetastet.",
    todo: "Todoliste",
    todoDesc: "OFFENE-PUNKTE.md bei jedem Sessionstart einspielen",
  },
  pools: {
    pool: "Pool",
    type: "Typ",
    actions: "Aktionen",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Zurücksetzen",
    rename: "Umbenennen",
    renameTitle: "{name} umbenennen",
    changeKey: "Key ändern",
    insertKey: "Key eintragen",
    delete: "Löschen",
    assigned: "kein Projekt | 1 Projekt | {count} Projekte",
    empty: "Noch keine Pools angelegt.",
    newOauthPool: "Neuen oAuth-Pool anlegen",
    newApikeyPool: "Neuen API-Key-Pool anlegen",
    editKey: "API-Key ändern – {name}",
    name: "Name",
    apiKey: "API-Key",
    oauthHint:
      "Der Pool wird angelegt; die Anmeldung macht claude beim ersten Start selbst per /login (Browser gegen dein Abo).",
    cancel: "Abbrechen",
    createPool: "Anlegen",
    reset: "Zurücksetzen",
    save: "Speichern",
    deletePool: "Pool löschen",
    deleteWarning:
      "Pool {name} und seine Credential-Datei werden gelöscht. Das lässt sich nicht rückgängig machen.",
    deleteUnassigns: "Diese Projekte verlieren ihre Pool-Zuordnung:",
    deleteBlockedTooltip:
      "Löschen gesperrt — {projects} läuft gerade. Erst beenden.",
    reloginTitle: "{name} zurücksetzen",
    reloginWarning:
      "Der im Schlüsselbund gespeicherte Zugriffstoken von {name} wird gelöscht. Beim nächsten Start verlangt claude erneut /login.",
    reloginNoEntry:
      "Kein Schlüsselbund-Eintrag vorhanden — beim nächsten Start meldet sich claude ohnehin per /login an.",
    reloginBlocked:
      "Zurücksetzen ist nur bei ungenutztem Pool möglich. Diese Projekte laufen noch:",
    keychainUnavailableTitle: "Keine sichere Ablage",
    keychainUnavailable:
      "Keychain/Keyring ist nicht verfügbar. Der Key kann stattdessen ungesichert als Datei im Pool-Ordner liegen (0600).",
    storeAsFile: "Als Datei ablegen",
  },
};

const en: typeof de = {
  app: {
    projects: "Projects",
    pools: "Pools",
    usage: "Usage",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 days",
    days30: "30 days",
    pool: "Pool",
    project: "Project",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ cost",
    total: "Total",
    empty: "No usage data in this period.",
    estimateNote:
      "API equivalent from local transcripts — not a bill; history only as long as claude keeps it.",
  },
  projects: {
    project: "Project",
    pool: "Pool",
    noPool: "– no pool –",
    start: "Start",
    stop: "Stop",
    terminalSettings: "Terminal settings",
    stillRunning: "{name} is still running",
    poolChangeSaved:
      "The pool change is saved. The running session keeps working in the old pool — the new one applies from the next start.",
    restartHint:
      "Restarting ends the running session. The automatic commit+push by claude-sync after the session is skipped.",
    keepRunning: "Keep running",
    restartNow: "Restart now",
    restarting: "Restarting …",
    terminal: "Terminal — {name}",
    title: "Title",
    theme: "Theme",
    dockIcon: "Dock icon",
    chooseFile: "Choose file …",
    remove: "Remove",
    defaultIcon: "Default icon",
    appliesNextStart: "Applies from the next terminal start.",
    cancel: "Cancel",
    save: "Save",
    noPoolAssigned: "no pool",
    needsPool: "No pool assigned",
    needsKey: "Pool has no API key",
    newProject: "+ Project",
    wizardTitle: "New project",
    name: "Name",
    workDir: "Working folder",
    workDirNone: "none",
    workDirCustom: "link existing folder",
    chooseFolder: "Choose folder …",
    create: "Create",
    wizardHint:
      "Creates the project folder with memory/, sentinel .gitignore, settings.json (memory dir + permissions), and the pool/terminal assignment.",
    delete: "Delete project",
    deleteRunning: "Still running — stop it first",
    deleteTitle: "Delete {name}",
    deleteWarning:
      "The project folder under ~/claude-projects (incl. memory/, settings and pool assignment) will be deleted permanently.",
    deleteWorkDirs: "Also delete working folders:",
    workDirsStay: "The working folders stay untouched.",
    todo: "Todo list",
    todoDesc: "Inject OFFENE-PUNKTE.md at every session start",
  },
  pools: {
    pool: "Pool",
    type: "Type",
    actions: "Actions",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Reset",
    rename: "Rename",
    renameTitle: "Rename {name}",
    changeKey: "Change key",
    insertKey: "Insert key",
    delete: "Delete",
    assigned: "no projects | 1 project | {count} projects",
    empty: "No pools yet.",
    newOauthPool: "Create oAuth pool",
    newApikeyPool: "Create API key pool",
    editKey: "Change API key – {name}",
    name: "Name",
    apiKey: "API key",
    oauthHint:
      "The pool is created; claude signs in itself on first start via /login (browser against your subscription).",
    cancel: "Cancel",
    createPool: "Create",
    reset: "Reset",
    save: "Save",
    deletePool: "Delete pool",
    deleteWarning:
      "Pool {name} and its credential file will be deleted. This cannot be undone.",
    deleteUnassigns: "These projects lose their pool assignment:",
    deleteBlockedTooltip:
      "Deletion blocked — active: {projects}. Stop the session first.",
    reloginTitle: "Reset {name}",
    reloginWarning:
      "The access token for {name} stored in the keychain will be deleted. On the next start claude asks for /login again.",
    reloginNoEntry:
      "No keychain entry present — claude signs in via /login on the next start anyway.",
    reloginBlocked:
      "Resetting requires an unused pool. These projects are still running:",
    keychainUnavailableTitle: "No secure storage",
    keychainUnavailable:
      "Keychain/keyring is unavailable. The key can instead be stored unprotected as a file in the pool folder (0600).",
    storeAsFile: "Store as file",
  },
};

const stored = localStorage.getItem("lang");
const initial =
  stored === "de" || stored === "en"
    ? stored
    : navigator.language.startsWith("de")
      ? "de"
      : "en";

export const i18n = createI18n({
  legacy: false,
  globalInjection: true,
  locale: initial,
  fallbackLocale: "en",
  messages: { de, en },
});

export function setLocale(lang: "de" | "en") {
  i18n.global.locale.value = lang;
  localStorage.setItem("lang", lang);
}

+    addFolderTitle: "Bestehenden Ordner als Projekt aufnehmen",

+    projectDirCustom: "Ordner wählen …",


    delete: "Projekt löschen",
    deleteRunning: "Läuft noch — erst beenden",
    deleteTitle: "{name} löschen",
    deleteWarning:
      "Der Projektordner unter ~/claude-projects (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
    deleteWorkDirs: "Arbeitsordner mitlöschen:",
    workDirsStay: "Die Arbeitsordner bleiben unangetastet.",

    delete: "Projekt löschen",
    deleteRunning: "Läuft noch — erst beenden",
    deleteTitle: "{name} löschen",
    deleteWarning:
      "Der Projektordner (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
    deleteWorkDirs: "Arbeitsordner mitlöschen:",
    workDirsStay: "Die Arbeitsordner bleiben unangetastet.",
    unlink: "Nur aus Liste nehmen",
    unlinkHint:
      "„Nur aus Liste nehmen" entfernt den Eintrag; der Ordner bleibt unangetastet.",


    delete: "Projekt löschen",
    deleteRunning: "Läuft noch — erst beenden",
    deleteTitle: "{name} löschen",
    deleteWarning:
      "Der Projektordner (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
    deleteWorkDirs: "Arbeitsordner mitlöschen:",
    workDirsStay: "Die Arbeitsordner bleiben unangetastet.",
    unlink: "Nur aus Liste nehmen",
    unlinkHint:
      "„Nur aus Liste nehmen" entfernt den Eintrag; der Ordner bleibt unangetastet.",

import { createI18n } from "vue-i18n";

const de = {
  app: {
    projects: "Projekte",
    pools: "Pools",
    usage: "Verbrauch",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 Tage",
    days30: "30 Tage",
    pool: "Pool",
    project: "Projekt",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ Kosten",
    total: "Summe",
    empty: "Keine Verbrauchsdaten im Zeitraum.",
    estimateNote:
      "API-Gegenwert aus den lokalen Transcripts — keine Abrechnung, Historie nur solange claude sie vorhält.",
  },
  projects: {
    project: "Projekt",
    pool: "Pool",
    noPool: "– kein Pool –",
    start: "Starten",
    stop: "Beenden",
    terminalSettings: "Terminal-Einstellungen",
    stillRunning: "{name} läuft noch",
    poolChangeSaved:
      "Der Pool-Wechsel ist gespeichert. Die laufende Session arbeitet aber weiter im alten Pool — der neue gilt erst ab dem nächsten Start.",
    restartHint:
      "Der Neustart beendet die laufende Session. Der automatische commit+push von claude-sync nach Sessionende entfällt dabei.",
    keepRunning: "Weiterlaufen lassen",
    restartNow: "Jetzt neu starten",
    restarting: "Starte neu …",
    terminal: "Terminal — {name}",
    title: "Titel",
    theme: "Theme",
    dockIcon: "Dock-Icon",
    chooseFile: "Datei wählen …",
    remove: "Entfernen",
    defaultIcon: "Standard-Icon",
    appliesNextStart: "Gilt ab dem nächsten Terminal-Start.",
    cancel: "Abbrechen",
    save: "Speichern",
    noPoolAssigned: "kein Pool",
    needsPool: "Kein Pool zugeordnet",
    needsKey: "Pool hat keinen API-Key",
    newProject: "+ Projekt",
    addFolder: "+ Ordner",
    addFolderTitle: "Bestehenden Ordner als Projekt aufnehmen",
    wizardTitle: "Neues Projekt",
    name: "Name",
    projectDir: "Projektordner",
    projectDirCustom: "Ordner wählen …",
    workDir: "Arbeitsordner",
    workDirNone: "keiner",
    workDirCustom: "vorhandenen Ordner verknüpfen",
    chooseFolder: "Ordner wählen …",
    create: "Anlegen",
    wizardHint:
      "Angelegt werden Projektordner mit memory/, Sentinel-.gitignore, settings.json (Memory-Verzeichnis + Berechtigungen) und die Pool-/Terminal-Zuordnung.",
    delete: "Projekt löschen",
    deleteRunning: "Läuft noch — erst beenden",
    deleteTitle: "{name} löschen",
    deleteWarning:
      "Der Projektordner unter ~/claude-projects (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
    deleteWorkDirs: "Arbeitsordner mitlöschen:",
    workDirsStay: "Die Arbeitsordner bleiben unangetastet.",
    todo: "Todoliste",
    todoDesc: "OFFENE-PUNKTE.md bei jedem Sessionstart einspielen",
  },
  pools: {
    pool: "Pool",
    type: "Typ",
    actions: "Aktionen",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Zurücksetzen",
    rename: "Umbenennen",
    renameTitle: "{name} umbenennen",
    changeKey: "Key ändern",
    insertKey: "Key eintragen",
    delete: "Löschen",
    assigned: "kein Projekt | 1 Projekt | {count} Projekte",
    empty: "Noch keine Pools angelegt.",
    newOauthPool: "Neuen oAuth-Pool anlegen",
    newApikeyPool: "Neuen API-Key-Pool anlegen",
    editKey: "API-Key ändern – {name}",
    name: "Name",
    apiKey: "API-Key",
    oauthHint:
      "Der Pool wird angelegt; die Anmeldung macht claude beim ersten Start selbst per /login (Browser gegen dein Abo).",
    cancel: "Abbrechen",
    createPool: "Anlegen",
    reset: "Zurücksetzen",
    save: "Speichern",
    deletePool: "Pool löschen",
    deleteWarning:
      "Pool {name} und seine Credential-Datei werden gelöscht. Das lässt sich nicht rückgängig machen.",
    deleteUnassigns: "Diese Projekte verlieren ihre Pool-Zuordnung:",
    deleteBlockedTooltip:
      "Löschen gesperrt — {projects} läuft gerade. Erst beenden.",
    reloginTitle: "{name} zurücksetzen",
    reloginWarning:
      "Der im Schlüsselbund gespeicherte Zugriffstoken von {name} wird gelöscht. Beim nächsten Start verlangt claude erneut /login.",
    reloginNoEntry:
      "Kein Schlüsselbund-Eintrag vorhanden — beim nächsten Start meldet sich claude ohnehin per /login an.",
    reloginBlocked:
      "Zurücksetzen ist nur bei ungenutztem Pool möglich. Diese Projekte laufen noch:",
    keychainUnavailableTitle: "Keine sichere Ablage",
    keychainUnavailable:
      "Keychain/Keyring ist nicht verfügbar. Der Key kann stattdessen ungesichert als Datei im Pool-Ordner liegen (0600).",
    storeAsFile: "Als Datei ablegen",
  },
};

const en: typeof de = {
  app: {
    projects: "Projects",
    pools: "Pools",
    usage: "Usage",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 days",
    days30: "30 days",
    pool: "Pool",
    project: "Project",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ cost",
    total: "Total",
    empty: "No usage data in this period.",
    estimateNote:
      "API equivalent from local transcripts — not a bill; history only as long as claude keeps it.",
  },
  projects: {
    project: "Project",
    pool: "Pool",
    noPool: "– no pool –",
    start: "Start",
    stop: "Stop",
    terminalSettings: "Terminal settings",
    stillRunning: "{name} is still running",
    poolChangeSaved:
      "The pool change is saved. The running session keeps working in the old pool — the new one applies from the next start.",
    restartHint:
      "Restarting ends the running session. The automatic commit+push by claude-sync after the session is skipped.",
    keepRunning: "Keep running",
    restartNow: "Restart now",
    restarting: "Restarting …",
    terminal: "Terminal — {name}",
    title: "Title",
    theme: "Theme",
    dockIcon: "Dock icon",
    chooseFile: "Choose file …",
    remove: "Remove",
    defaultIcon: "Default icon",
    appliesNextStart: "Applies from the next terminal start.",
    cancel: "Cancel",
    save: "Save",
    noPoolAssigned: "no pool",
    needsPool: "No pool assigned",
    needsKey: "Pool has no API key",
    newProject: "+ Project",
    wizardTitle: "New project",
    name: "Name",
    workDir: "Working folder",
    workDirNone: "none",
    workDirCustom: "link existing folder",
    chooseFolder: "Choose folder …",
    create: "Create",
    wizardHint:
      "Creates the project folder with memory/, sentinel .gitignore, settings.json (memory dir + permissions), and the pool/terminal assignment.",
    delete: "Delete project",
    deleteRunning: "Still running — stop it first",
    deleteTitle: "Delete {name}",
    deleteWarning:
      "The project folder under ~/claude-projects (incl. memory/, settings and pool assignment) will be deleted permanently.",
    deleteWorkDirs: "Also delete working folders:",
    workDirsStay: "The working folders stay untouched.",
    todo: "Todo list",
    todoDesc: "Inject OFFENE-PUNKTE.md at every session start",
  },
  pools: {
    pool: "Pool",
    type: "Type",
    actions: "Actions",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Reset",
    rename: "Rename",
    renameTitle: "Rename {name}",
    changeKey: "Change key",
    insertKey: "Insert key",
    delete: "Delete",
    assigned: "no projects | 1 project | {count} projects",
    empty: "No pools yet.",
    newOauthPool: "Create oAuth pool",
    newApikeyPool: "Create API key pool",
    editKey: "Change API key – {name}",
    name: "Name",
    apiKey: "API key",
    oauthHint:
      "The pool is created; claude signs in itself on first start via /login (browser against your subscription).",
    cancel: "Cancel",
    createPool: "Create",
    reset: "Reset",
    save: "Save",
    deletePool: "Delete pool",
    deleteWarning:
      "Pool {name} and its credential file will be deleted. This cannot be undone.",
    deleteUnassigns: "These projects lose their pool assignment:",
    deleteBlockedTooltip:
      "Deletion blocked — active: {projects}. Stop the session first.",
    reloginTitle: "Reset {name}",
    reloginWarning:
      "The access token for {name} stored in the keychain will be deleted. On the next start claude asks for /login again.",
    reloginNoEntry:
      "No keychain entry present — claude signs in via /login on the next start anyway.",
    reloginBlocked:
      "Resetting requires an unused pool. These projects are still running:",
    keychainUnavailableTitle: "No secure storage",
    keychainUnavailable:
      "Keychain/keyring is unavailable. The key can instead be stored unprotected as a file in the pool folder (0600).",
    storeAsFile: "Store as file",
  },
};

const stored = localStorage.getItem("lang");
const initial =
  stored === "de" || stored === "en"
    ? stored
    : navigator.language.startsWith("de")
      ? "de"
      : "en";

export const i18n = createI18n({
  legacy: false,
  globalInjection: true,
  locale: initial,
  fallbackLocale: "en",
  messages: { de, en },
});

export function setLocale(lang: "de" | "en") {
  i18n.global.locale.value = lang;
  localStorage.setItem("lang", lang);
}

-      "Der Projektordner unter ~/claude-projects (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",

+      "Der Projektordner (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",

+      "„Nur aus Liste nehmen" entfernt den Eintrag; der Ordner bleibt unangetastet.",


    newProject: "+ Project",
    wizardTitle: "New project",
    name: "Name",
    workDir: "Working folder",

    newProject: "+ Project",
    addFolder: "+ Folder",
    addFolderTitle: "Add an existing folder as a project",
    wizardTitle: "New project",
    name: "Name",
    projectDir: "Project folder",
    projectDirCustom: "Choose folder …",
    workDir: "Working folder",


    newProject: "+ Project",
    addFolder: "+ Folder",
    addFolderTitle: "Add an existing folder as a project",
    wizardTitle: "New project",
    name: "Name",
    projectDir: "Project folder",
    projectDirCustom: "Choose folder …",
    workDir: "Working folder",

import { createI18n } from "vue-i18n";

const de = {
  app: {
    projects: "Projekte",
    pools: "Pools",
    usage: "Verbrauch",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 Tage",
    days30: "30 Tage",
    pool: "Pool",
    project: "Projekt",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ Kosten",
    total: "Summe",
    empty: "Keine Verbrauchsdaten im Zeitraum.",
    estimateNote:
      "API-Gegenwert aus den lokalen Transcripts — keine Abrechnung, Historie nur solange claude sie vorhält.",
  },
  projects: {
    project: "Projekt",
    pool: "Pool",
    noPool: "– kein Pool –",
    start: "Starten",
    stop: "Beenden",
    terminalSettings: "Terminal-Einstellungen",
    stillRunning: "{name} läuft noch",
    poolChangeSaved:
      "Der Pool-Wechsel ist gespeichert. Die laufende Session arbeitet aber weiter im alten Pool — der neue gilt erst ab dem nächsten Start.",
    restartHint:
      "Der Neustart beendet die laufende Session. Der automatische commit+push von claude-sync nach Sessionende entfällt dabei.",
    keepRunning: "Weiterlaufen lassen",
    restartNow: "Jetzt neu starten",
    restarting: "Starte neu …",
    terminal: "Terminal — {name}",
    title: "Titel",
    theme: "Theme",
    dockIcon: "Dock-Icon",
    chooseFile: "Datei wählen …",
    remove: "Entfernen",
    defaultIcon: "Standard-Icon",
    appliesNextStart: "Gilt ab dem nächsten Terminal-Start.",
    cancel: "Abbrechen",
    save: "Speichern",
    noPoolAssigned: "kein Pool",
    needsPool: "Kein Pool zugeordnet",
    needsKey: "Pool hat keinen API-Key",
    newProject: "+ Projekt",
    addFolder: "+ Ordner",
    addFolderTitle: "Bestehenden Ordner als Projekt aufnehmen",
    wizardTitle: "Neues Projekt",
    name: "Name",
    projectDir: "Projektordner",
    projectDirCustom: "Ordner wählen …",
    workDir: "Arbeitsordner",
    workDirNone: "keiner",
    workDirCustom: "vorhandenen Ordner verknüpfen",
    chooseFolder: "Ordner wählen …",
    create: "Anlegen",
    wizardHint:
      "Angelegt werden Projektordner mit memory/, Sentinel-.gitignore, settings.json (Memory-Verzeichnis + Berechtigungen) und die Pool-/Terminal-Zuordnung.",
    delete: "Projekt löschen",
    deleteRunning: "Läuft noch — erst beenden",
    deleteTitle: "{name} löschen",
    deleteWarning:
      "Der Projektordner (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
    deleteWorkDirs: "Arbeitsordner mitlöschen:",
    workDirsStay: "Die Arbeitsordner bleiben unangetastet.",
    unlink: "Nur aus Liste nehmen",
    unlinkHint:
      "„Nur aus Liste nehmen" entfernt den Eintrag; der Ordner bleibt unangetastet.",
    todo: "Todoliste",
    todoDesc: "OFFENE-PUNKTE.md bei jedem Sessionstart einspielen",
  },
  pools: {
    pool: "Pool",
    type: "Typ",
    actions: "Aktionen",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Zurücksetzen",
    rename: "Umbenennen",
    renameTitle: "{name} umbenennen",
    changeKey: "Key ändern",
    insertKey: "Key eintragen",
    delete: "Löschen",
    assigned: "kein Projekt | 1 Projekt | {count} Projekte",
    empty: "Noch keine Pools angelegt.",
    newOauthPool: "Neuen oAuth-Pool anlegen",
    newApikeyPool: "Neuen API-Key-Pool anlegen",
    editKey: "API-Key ändern – {name}",
    name: "Name",
    apiKey: "API-Key",
    oauthHint:
      "Der Pool wird angelegt; die Anmeldung macht claude beim ersten Start selbst per /login (Browser gegen dein Abo).",
    cancel: "Abbrechen",
    createPool: "Anlegen",
    reset: "Zurücksetzen",
    save: "Speichern",
    deletePool: "Pool löschen",
    deleteWarning:
      "Pool {name} und seine Credential-Datei werden gelöscht. Das lässt sich nicht rückgängig machen.",
    deleteUnassigns: "Diese Projekte verlieren ihre Pool-Zuordnung:",
    deleteBlockedTooltip:
      "Löschen gesperrt — {projects} läuft gerade. Erst beenden.",
    reloginTitle: "{name} zurücksetzen",
    reloginWarning:
      "Der im Schlüsselbund gespeicherte Zugriffstoken von {name} wird gelöscht. Beim nächsten Start verlangt claude erneut /login.",
    reloginNoEntry:
      "Kein Schlüsselbund-Eintrag vorhanden — beim nächsten Start meldet sich claude ohnehin per /login an.",
    reloginBlocked:
      "Zurücksetzen ist nur bei ungenutztem Pool möglich. Diese Projekte laufen noch:",
    keychainUnavailableTitle: "Keine sichere Ablage",
    keychainUnavailable:
      "Keychain/Keyring ist nicht verfügbar. Der Key kann stattdessen ungesichert als Datei im Pool-Ordner liegen (0600).",
    storeAsFile: "Als Datei ablegen",
  },
};

const en: typeof de = {
  app: {
    projects: "Projects",
    pools: "Pools",
    usage: "Usage",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 days",
    days30: "30 days",
    pool: "Pool",
    project: "Project",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ cost",
    total: "Total",
    empty: "No usage data in this period.",
    estimateNote:
      "API equivalent from local transcripts — not a bill; history only as long as claude keeps it.",
  },
  projects: {
    project: "Project",
    pool: "Pool",
    noPool: "– no pool –",
    start: "Start",
    stop: "Stop",
    terminalSettings: "Terminal settings",
    stillRunning: "{name} is still running",
    poolChangeSaved:
      "The pool change is saved. The running session keeps working in the old pool — the new one applies from the next start.",
    restartHint:
      "Restarting ends the running session. The automatic commit+push by claude-sync after the session is skipped.",
    keepRunning: "Keep running",
    restartNow: "Restart now",
    restarting: "Restarting …",
    terminal: "Terminal — {name}",
    title: "Title",
    theme: "Theme",
    dockIcon: "Dock icon",
    chooseFile: "Choose file …",
    remove: "Remove",
    defaultIcon: "Default icon",
    appliesNextStart: "Applies from the next terminal start.",
    cancel: "Cancel",
    save: "Save",
    noPoolAssigned: "no pool",
    needsPool: "No pool assigned",
    needsKey: "Pool has no API key",
    newProject: "+ Project",
    wizardTitle: "New project",
    name: "Name",
    workDir: "Working folder",
    workDirNone: "none",
    workDirCustom: "link existing folder",
    chooseFolder: "Choose folder …",
    create: "Create",
    wizardHint:
      "Creates the project folder with memory/, sentinel .gitignore, settings.json (memory dir + permissions), and the pool/terminal assignment.",
    delete: "Delete project",
    deleteRunning: "Still running — stop it first",
    deleteTitle: "Delete {name}",
    deleteWarning:
      "The project folder under ~/claude-projects (incl. memory/, settings and pool assignment) will be deleted permanently.",
    deleteWorkDirs: "Also delete working folders:",
    workDirsStay: "The working folders stay untouched.",
    todo: "Todo list",
    todoDesc: "Inject OFFENE-PUNKTE.md at every session start",
  },
  pools: {
    pool: "Pool",
    type: "Type",
    actions: "Actions",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Reset",
    rename: "Rename",
    renameTitle: "Rename {name}",
    changeKey: "Change key",
    insertKey: "Insert key",
    delete: "Delete",
    assigned: "no projects | 1 project | {count} projects",
    empty: "No pools yet.",
    newOauthPool: "Create oAuth pool",
    newApikeyPool: "Create API key pool",
    editKey: "Change API key – {name}",
    name: "Name",
    apiKey: "API key",
    oauthHint:
      "The pool is created; claude signs in itself on first start via /login (browser against your subscription).",
    cancel: "Cancel",
    createPool: "Create",
    reset: "Reset",
    save: "Save",
    deletePool: "Delete pool",
    deleteWarning:
      "Pool {name} and its credential file will be deleted. This cannot be undone.",
    deleteUnassigns: "These projects lose their pool assignment:",
    deleteBlockedTooltip:
      "Deletion blocked — active: {projects}. Stop the session first.",
    reloginTitle: "Reset {name}",
    reloginWarning:
      "The access token for {name} stored in the keychain will be deleted. On the next start claude asks for /login again.",
    reloginNoEntry:
      "No keychain entry present — claude signs in via /login on the next start anyway.",
    reloginBlocked:
      "Resetting requires an unused pool. These projects are still running:",
    keychainUnavailableTitle: "No secure storage",
    keychainUnavailable:
      "Keychain/keyring is unavailable. The key can instead be stored unprotected as a file in the pool folder (0600).",
    storeAsFile: "Store as file",
  },
};

const stored = localStorage.getItem("lang");
const initial =
  stored === "de" || stored === "en"
    ? stored
    : navigator.language.startsWith("de")
      ? "de"
      : "en";

export const i18n = createI18n({
  legacy: false,
  globalInjection: true,
  locale: initial,
  fallbackLocale: "en",
  messages: { de, en },
});

export function setLocale(lang: "de" | "en") {
  i18n.global.locale.value = lang;
  localStorage.setItem("lang", lang);
}

+    addFolderTitle: "Add an existing folder as a project",

+    projectDirCustom: "Choose folder …",


    delete: "Delete project",
    deleteRunning: "Still running — stop it first",
    deleteTitle: "Delete {name}",
    deleteWarning:
      "The project folder under ~/claude-projects (incl. memory/, settings and pool assignment) will be deleted permanently.",
    deleteWorkDirs: "Also delete working folders:",
    workDirsStay: "The working folders stay untouched.",

    delete: "Delete project",
    deleteRunning: "Still running — stop it first",
    deleteTitle: "Delete {name}",
    deleteWarning:
      "The project folder (incl. memory/, settings and pool assignment) will be deleted permanently.",
    deleteWorkDirs: "Also delete working folders:",
    workDirsStay: "The working folders stay untouched.",
    unlink: "Remove from list only",
    unlinkHint:
      "\"Remove from list only\" drops the entry; the folder stays untouched.",


    delete: "Delete project",
    deleteRunning: "Still running — stop it first",
    deleteTitle: "Delete {name}",
    deleteWarning:
      "The project folder (incl. memory/, settings and pool assignment) will be deleted permanently.",
    deleteWorkDirs: "Also delete working folders:",
    workDirsStay: "The working folders stay untouched.",
    unlink: "Remove from list only",
    unlinkHint:
      "\"Remove from list only\" drops the entry; the folder stays untouched.",

import { createI18n } from "vue-i18n";

const de = {
  app: {
    projects: "Projekte",
    pools: "Pools",
    usage: "Verbrauch",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 Tage",
    days30: "30 Tage",
    pool: "Pool",
    project: "Projekt",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ Kosten",
    total: "Summe",
    empty: "Keine Verbrauchsdaten im Zeitraum.",
    estimateNote:
      "API-Gegenwert aus den lokalen Transcripts — keine Abrechnung, Historie nur solange claude sie vorhält.",
  },
  projects: {
    project: "Projekt",
    pool: "Pool",
    noPool: "– kein Pool –",
    start: "Starten",
    stop: "Beenden",
    terminalSettings: "Terminal-Einstellungen",
    stillRunning: "{name} läuft noch",
    poolChangeSaved:
      "Der Pool-Wechsel ist gespeichert. Die laufende Session arbeitet aber weiter im alten Pool — der neue gilt erst ab dem nächsten Start.",
    restartHint:
      "Der Neustart beendet die laufende Session. Der automatische commit+push von claude-sync nach Sessionende entfällt dabei.",
    keepRunning: "Weiterlaufen lassen",
    restartNow: "Jetzt neu starten",
    restarting: "Starte neu …",
    terminal: "Terminal — {name}",
    title: "Titel",
    theme: "Theme",
    dockIcon: "Dock-Icon",
    chooseFile: "Datei wählen …",
    remove: "Entfernen",
    defaultIcon: "Standard-Icon",
    appliesNextStart: "Gilt ab dem nächsten Terminal-Start.",
    cancel: "Abbrechen",
    save: "Speichern",
    noPoolAssigned: "kein Pool",
    needsPool: "Kein Pool zugeordnet",
    needsKey: "Pool hat keinen API-Key",
    newProject: "+ Projekt",
    addFolder: "+ Ordner",
    addFolderTitle: "Bestehenden Ordner als Projekt aufnehmen",
    wizardTitle: "Neues Projekt",
    name: "Name",
    projectDir: "Projektordner",
    projectDirCustom: "Ordner wählen …",
    workDir: "Arbeitsordner",
    workDirNone: "keiner",
    workDirCustom: "vorhandenen Ordner verknüpfen",
    chooseFolder: "Ordner wählen …",
    create: "Anlegen",
    wizardHint:
      "Angelegt werden Projektordner mit memory/, Sentinel-.gitignore, settings.json (Memory-Verzeichnis + Berechtigungen) und die Pool-/Terminal-Zuordnung.",
    delete: "Projekt löschen",
    deleteRunning: "Läuft noch — erst beenden",
    deleteTitle: "{name} löschen",
    deleteWarning:
      "Der Projektordner (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
    deleteWorkDirs: "Arbeitsordner mitlöschen:",
    workDirsStay: "Die Arbeitsordner bleiben unangetastet.",
    unlink: "Nur aus Liste nehmen",
    unlinkHint:
      "„Nur aus Liste nehmen" entfernt den Eintrag; der Ordner bleibt unangetastet.",
    todo: "Todoliste",
    todoDesc: "OFFENE-PUNKTE.md bei jedem Sessionstart einspielen",
  },
  pools: {
    pool: "Pool",
    type: "Typ",
    actions: "Aktionen",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Zurücksetzen",
    rename: "Umbenennen",
    renameTitle: "{name} umbenennen",
    changeKey: "Key ändern",
    insertKey: "Key eintragen",
    delete: "Löschen",
    assigned: "kein Projekt | 1 Projekt | {count} Projekte",
    empty: "Noch keine Pools angelegt.",
    newOauthPool: "Neuen oAuth-Pool anlegen",
    newApikeyPool: "Neuen API-Key-Pool anlegen",
    editKey: "API-Key ändern – {name}",
    name: "Name",
    apiKey: "API-Key",
    oauthHint:
      "Der Pool wird angelegt; die Anmeldung macht claude beim ersten Start selbst per /login (Browser gegen dein Abo).",
    cancel: "Abbrechen",
    createPool: "Anlegen",
    reset: "Zurücksetzen",
    save: "Speichern",
    deletePool: "Pool löschen",
    deleteWarning:
      "Pool {name} und seine Credential-Datei werden gelöscht. Das lässt sich nicht rückgängig machen.",
    deleteUnassigns: "Diese Projekte verlieren ihre Pool-Zuordnung:",
    deleteBlockedTooltip:
      "Löschen gesperrt — {projects} läuft gerade. Erst beenden.",
    reloginTitle: "{name} zurücksetzen",
    reloginWarning:
      "Der im Schlüsselbund gespeicherte Zugriffstoken von {name} wird gelöscht. Beim nächsten Start verlangt claude erneut /login.",
    reloginNoEntry:
      "Kein Schlüsselbund-Eintrag vorhanden — beim nächsten Start meldet sich claude ohnehin per /login an.",
    reloginBlocked:
      "Zurücksetzen ist nur bei ungenutztem Pool möglich. Diese Projekte laufen noch:",
    keychainUnavailableTitle: "Keine sichere Ablage",
    keychainUnavailable:
      "Keychain/Keyring ist nicht verfügbar. Der Key kann stattdessen ungesichert als Datei im Pool-Ordner liegen (0600).",
    storeAsFile: "Als Datei ablegen",
  },
};

const en: typeof de = {
  app: {
    projects: "Projects",
    pools: "Pools",
    usage: "Usage",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 days",
    days30: "30 days",
    pool: "Pool",
    project: "Project",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ cost",
    total: "Total",
    empty: "No usage data in this period.",
    estimateNote:
      "API equivalent from local transcripts — not a bill; history only as long as claude keeps it.",
  },
  projects: {
    project: "Project",
    pool: "Pool",
    noPool: "– no pool –",
    start: "Start",
    stop: "Stop",
    terminalSettings: "Terminal settings",
    stillRunning: "{name} is still running",
    poolChangeSaved:
      "The pool change is saved. The running session keeps working in the old pool — the new one applies from the next start.",
    restartHint:
      "Restarting ends the running session. The automatic commit+push by claude-sync after the session is skipped.",
    keepRunning: "Keep running",
    restartNow: "Restart now",
    restarting: "Restarting …",
    terminal: "Terminal — {name}",
    title: "Title",
    theme: "Theme",
    dockIcon: "Dock icon",
    chooseFile: "Choose file …",
    remove: "Remove",
    defaultIcon: "Default icon",
    appliesNextStart: "Applies from the next terminal start.",
    cancel: "Cancel",
    save: "Save",
    noPoolAssigned: "no pool",
    needsPool: "No pool assigned",
    needsKey: "Pool has no API key",
    newProject: "+ Project",
    addFolder: "+ Folder",
    addFolderTitle: "Add an existing folder as a project",
    wizardTitle: "New project",
    name: "Name",
    projectDir: "Project folder",
    projectDirCustom: "Choose folder …",
    workDir: "Working folder",
    workDirNone: "none",
    workDirCustom: "link existing folder",
    chooseFolder: "Choose folder …",
    create: "Create",
    wizardHint:
      "Creates the project folder with memory/, sentinel .gitignore, settings.json (memory dir + permissions), and the pool/terminal assignment.",
    delete: "Delete project",
    deleteRunning: "Still running — stop it first",
    deleteTitle: "Delete {name}",
    deleteWarning:
      "The project folder under ~/claude-projects (incl. memory/, settings and pool assignment) will be deleted permanently.",
    deleteWorkDirs: "Also delete working folders:",
    workDirsStay: "The working folders stay untouched.",
    todo: "Todo list",
    todoDesc: "Inject OFFENE-PUNKTE.md at every session start",
  },
  pools: {
    pool: "Pool",
    type: "Type",
    actions: "Actions",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Reset",
    rename: "Rename",
    renameTitle: "Rename {name}",
    changeKey: "Change key",
    insertKey: "Insert key",
    delete: "Delete",
    assigned: "no projects | 1 project | {count} projects",
    empty: "No pools yet.",
    newOauthPool: "Create oAuth pool",
    newApikeyPool: "Create API key pool",
    editKey: "Change API key – {name}",
    name: "Name",
    apiKey: "API key",
    oauthHint:
      "The pool is created; claude signs in itself on first start via /login (browser against your subscription).",
    cancel: "Cancel",
    createPool: "Create",
    reset: "Reset",
    save: "Save",
    deletePool: "Delete pool",
    deleteWarning:
      "Pool {name} and its credential file will be deleted. This cannot be undone.",
    deleteUnassigns: "These projects lose their pool assignment:",
    deleteBlockedTooltip:
      "Deletion blocked — active: {projects}. Stop the session first.",
    reloginTitle: "Reset {name}",
    reloginWarning:
      "The access token for {name} stored in the keychain will be deleted. On the next start claude asks for /login again.",
    reloginNoEntry:
      "No keychain entry present — claude signs in via /login on the next start anyway.",
    reloginBlocked:
      "Resetting requires an unused pool. These projects are still running:",
    keychainUnavailableTitle: "No secure storage",
    keychainUnavailable:
      "Keychain/keyring is unavailable. The key can instead be stored unprotected as a file in the pool folder (0600).",
    storeAsFile: "Store as file",
  },
};

const stored = localStorage.getItem("lang");
const initial =
  stored === "de" || stored === "en"
    ? stored
    : navigator.language.startsWith("de")
      ? "de"
      : "en";

export const i18n = createI18n({
  legacy: false,
  globalInjection: true,
  locale: initial,
  fallbackLocale: "en",
  messages: { de, en },
});

export function setLocale(lang: "de" | "en") {
  i18n.global.locale.value = lang;
  localStorage.setItem("lang", lang);
}

-      "The project folder under ~/claude-projects (incl. memory/, settings and pool assignment) will be deleted permanently.",

+      "The project folder (incl. memory/, settings and pool assignment) will be deleted permanently.",

+      "\"Remove from list only\" drops the entry; the folder stays untouched.",


Jetzt ProjectList.vue:


interface Wizard {
  name: string;
  pool: string;
  workDirMode: "none" | "default" | "custom";
  workDir: string | null;
  title: string;
  theme: string;
  todo: boolean;
}

const wizard = ref<Wizard | null>(null);

function openWizard() {
  error.value = "";
  wizard.value = {
    name: "",
    pool: "",
    workDirMode: "none",
    workDir: null,
    title: "",
    theme: "mocha",
    todo: false,
  };
}

interface Wizard {
  name: string;
  pool: string;
  dirMode: "default" | "custom";
  dir: string | null;
  workDirMode: "none" | "default" | "custom";
  workDir: string | null;
  title: string;
  theme: string;
  todo: boolean;
}

const wizard = ref<Wizard | null>(null);

function openWizard() {
  error.value = "";
  wizard.value = {
    name: "",
    pool: "",
    dirMode: "default",
    dir: null,
    workDirMode: "none",
    workDir: null,
    title: "",
    theme: "mocha",
    todo: false,
  };
}

// Bestehenden Ordner als Projekt aufnehmen — Name ist der Ordnername.
async function addFolder() {
  const dir = await open({ directory: true, multiple: false });
  if (typeof dir !== "string") return;
  try {
    await invoke("add_project", { path: dir });
    await refresh();
  } catch (e) {
    error.value = String(e);
  }
}

async function pickProjectDir() {
  const dir = await open({ directory: true, multiple: false });
  if (typeof dir === "string") {
    wizard.value!.dir = dir;
    wizard.value!.dirMode = "custom";
  }
}


The file /Users/marcus.hinz/projects/ai-control/src/components/ProjectList.vue has been updated successfully. (file state is current in your context — no need to Read it back)

interface Wizard {
  name: string;
  pool: string;
  workDirMode: "none" | "default" | "custom";
  workDir: string | null;
  title: string;
  theme: string;
  todo: boolean;
}

const wizard = ref<Wizard | null>(null);

function openWizard() {
  error.value = "";
  wizard.value = {
    name: "",
    pool: "",
    workDirMode: "none",
    workDir: null,
    title: "",
    theme: "mocha",
    todo: false,
  };
}

interface Wizard {
  name: string;
  pool: string;
  dirMode: "default" | "custom";
  dir: string | null;
  workDirMode: "none" | "default" | "custom";
  workDir: string | null;
  title: string;
  theme: string;
  todo: boolean;
}

const wizard = ref<Wizard | null>(null);

function openWizard() {
  error.value = "";
  wizard.value = {
    name: "",
    pool: "",
    dirMode: "default",
    dir: null,
    workDirMode: "none",
    workDir: null,
    title: "",
    theme: "mocha",
    todo: false,
  };
}

// Bestehenden Ordner als Projekt aufnehmen — Name ist der Ordnername.
async function addFolder() {
  const dir = await open({ directory: true, multiple: false });
  if (typeof dir !== "string") return;
  try {
    await invoke("add_project", { path: dir });
    await refresh();
  } catch (e) {
    error.value = String(e);
  }
}

async function pickProjectDir() {
  const dir = await open({ directory: true, multiple: false });
  if (typeof dir === "string") {
    wizard.value!.dir = dir;
    wizard.value!.dirMode = "custom";
  }
}

wizard.value = {
name: "",
pool: "",
+    dirMode: "default",
+    dir: null,
workDirMode: "none",
workDir: null,
title: "",

+// Bestehenden Ordner als Projekt aufnehmen — Name ist der Ordnername.

+  const dir = await open({ directory: true, multiple: false });

+    await invoke("add_project", { path: dir });


async function createProject() {
  const w = wizard.value!;
  const name = w.name.trim();
  const workDir =
    w.workDirMode === "default"
      ? `~/projects/${name}`
      : w.workDirMode === "custom"
        ? w.workDir
        : null;
  const title = w.title.trim();
  try {
    await invoke("create_project_full", {
      name,
      pool: w.pool === "" ? null : w.pool,

async function createProject() {
  const w = wizard.value!;
  const name = w.name.trim();
  const workDir =
    w.workDirMode === "default"
      ? `~/projects/${name}`
      : w.workDirMode === "custom"
        ? w.workDir
        : null;
  const title = w.title.trim();
  try {
    await invoke("create_project_full", {
      name,
      // custom: gewählter Ordner ist der Ablageort, das Projekt entsteht darin
      dir: w.dirMode === "custom" ? `${w.dir}/${name}` : null,
      pool: w.pool === "" ? null : w.pool,


async function createProject() {
  const w = wizard.value!;
  const name = w.name.trim();
  const workDir =
    w.workDirMode === "default"
      ? `~/projects/${name}`
      : w.workDirMode === "custom"
        ? w.workDir
        : null;
  const title = w.title.trim();
  try {
    await invoke("create_project_full", {
      name,
      pool: w.pool === "" ? null : w.pool,

async function createProject() {
  const w = wizard.value!;
  const name = w.name.trim();
  const workDir =
    w.workDirMode === "default"
      ? `~/projects/${name}`
      : w.workDirMode === "custom"
        ? w.workDir
        : null;
  const title = w.title.trim();
  try {
    await invoke("create_project_full", {
      name,
      // custom: gewählter Ordner ist der Ablageort, das Projekt entsteht darin
      dir: w.dirMode === "custom" ? `${w.dir}/${name}` : null,
      pool: w.pool === "" ? null : w.pool,

+      // custom: gewählter Ordner ist der Ablageort, das Projekt entsteht darin

+      dir: w.dirMode === "custom" ? `${w.dir}/${name}` : null,

createWorkDir: w.workDirMode === "default",


async function confirmDelete() {
  const d = pendingDelete.value!;
  try {
    await invoke("delete_project", {
      name: d.name,
      deleteWorkDirs: d.deleteWorkDirs,
    });
    pendingDelete.value = null;
    await refresh();
  } catch (e) {
    error.value = String(e);
    pendingDelete.value = null;
  }
}

async function confirmDelete() {
  const d = pendingDelete.value!;
  try {
    await invoke("delete_project", {
      name: d.name,
      deleteWorkDirs: d.deleteWorkDirs,
    });
    pendingDelete.value = null;
    await refresh();
  } catch (e) {
    error.value = String(e);
    pendingDelete.value = null;
  }
}

// Nur den Registry-Eintrag entfernen; der Ordner bleibt.
async function unlinkProject() {
  const d = pendingDelete.value!;
  try {
    await invoke("remove_project", { name: d.name });
    pendingDelete.value = null;
    await refresh();
  } catch (e) {
    error.value = String(e);
    pendingDelete.value = null;
  }
}


async function confirmDelete() {
  const d = pendingDelete.value!;
  try {
    await invoke("delete_project", {
      name: d.name,
      deleteWorkDirs: d.deleteWorkDirs,
    });
    pendingDelete.value = null;
    await refresh();
  } catch (e) {
    error.value = String(e);
    pendingDelete.value = null;
  }
}

// Nur den Registry-Eintrag entfernen; der Ordner bleibt.
async function unlinkProject() {
  const d = pendingDelete.value!;
  try {
    await invoke("remove_project", { name: d.name });
    pendingDelete.value = null;
    await refresh();
  } catch (e) {
    error.value = String(e);
    pendingDelete.value = null;
  }
}

+// Nur den Registry-Eintrag entfernen; der Ordner bleibt.

+    await invoke("remove_project", { name: d.name });


    <button class="primary" @click="openWizard">
      {{ $t("projects.newProject") }}
    </button>

    <button class="primary" @click="openWizard">
      {{ $t("projects.newProject") }}
    </button>
    <button :title="$t('projects.addFolderTitle')" @click="addFolder">
      {{ $t("projects.addFolder") }}
    </button>


    <button class="primary" @click="openWizard">
      {{ $t("projects.newProject") }}
    </button>
    <button :title="$t('projects.addFolderTitle')" @click="addFolder">
      {{ $t("projects.addFolder") }}
    </button>

+    <button :title="$t('projects.addFolderTitle')" @click="addFolder">


      <label class="field">
        {{ $t("projects.name") }}
        <input v-model="wizard.name" autofocus required />
      </label>
      <label class="field">
        {{ $t("projects.pool") }}

        {{ $t("projects.name") }}
        <input v-model="wizard.name" autofocus required />

        {{ $t("projects.projectDir") }}

          <select v-model="wizard.dirMode">
            <option value="default">
              ~/claude-projects/{{ wizard.name.trim() || "…" }}
            </option>
            <option value="custom">{{ $t("projects.projectDirCustom") }}</option>
          </select>
          <button
            v-if="wizard.dirMode === 'custom'"
            type="button"
            @click="pickProjectDir"
          >
            {{ $t("projects.chooseFolder") }}
          </button>

        {{ wizard.dir }}/{{ wizard.name.trim() || "…" }}

        {{ $t("projects.pool") }}


      <label class="field">
        {{ $t("projects.name") }}
        <input v-model="wizard.name" autofocus required />
      </label>
      <label class="field">
        {{ $t("projects.pool") }}

        {{ $t("projects.name") }}
        <input v-model="wizard.name" autofocus required />

        {{ $t("projects.projectDir") }}

          <select v-model="wizard.dirMode">
            <option value="default">
              ~/claude-projects/{{ wizard.name.trim() || "…" }}
            </option>
            <option value="custom">{{ $t("projects.projectDirCustom") }}</option>
          </select>
          <button
            v-if="wizard.dirMode === 'custom'"
            type="button"
            @click="pickProjectDir"
          >
            {{ $t("projects.chooseFolder") }}
          </button>

        {{ wizard.dir }}/{{ wizard.name.trim() || "…" }}

        {{ $t("projects.pool") }}

+        {{ $t("projects.projectDir") }}

+          <select v-model="wizard.dirMode">

+              ~/claude-projects/{{ wizard.name.trim() || "…" }}

+            <option value="custom">{{ $t("projects.projectDirCustom") }}</option>

+            v-if="wizard.dirMode === 'custom'"

+            {{ $t("projects.chooseFolder") }}

+      <label v-if="wizard.dirMode === 'custom' && wizard.dir" class="field">

+        {{ wizard.dir }}/{{ wizard.name.trim() || "…" }}

<option value="">{{ $t("projects.noPool") }}</option>


        <button
          type="submit"
          class="primary"
          :disabled="
            wizard.name.trim() === '' ||
            (wizard.workDirMode === 'custom' && !wizard.workDir)
          "
        >
          {{ $t("projects.create") }}
        </button>

        <button
          type="submit"
          class="primary"
          :disabled="
            wizard.name.trim() === '' ||
            (wizard.dirMode === 'custom' && !wizard.dir) ||
            (wizard.workDirMode === 'custom' && !wizard.workDir)
          "
        >
          {{ $t("projects.create") }}
        </button>


        <button
          type="submit"
          class="primary"
          :disabled="
            wizard.name.trim() === '' ||
            (wizard.workDirMode === 'custom' && !wizard.workDir)
          "
        >
          {{ $t("projects.create") }}
        </button>

        <button
          type="submit"
          class="primary"
          :disabled="
            wizard.name.trim() === '' ||
            (wizard.dirMode === 'custom' && !wizard.dir) ||
            (wizard.workDirMode === 'custom' && !wizard.workDir)
          "
        >
          {{ $t("projects.create") }}
        </button>

+            (wizard.dirMode === 'custom' && !wizard.dir) ||


        <button type="button" @click="pendingDelete = null">
          {{ $t("projects.cancel") }}
        </button>
        <button class="danger" @click="confirmDelete">
          {{ $t("projects.delete") }}
        </button>

{{ $t("projects.unlinkHint") }}

        <button type="button" @click="pendingDelete = null">
          {{ $t("projects.cancel") }}
        </button>
        <button @click="unlinkProject">
          {{ $t("projects.unlink") }}
        </button>
        <button class="danger" @click="confirmDelete">
          {{ $t("projects.delete") }}
        </button>


        <button type="button" @click="pendingDelete = null">
          {{ $t("projects.cancel") }}
        </button>
        <button class="danger" @click="confirmDelete">
          {{ $t("projects.delete") }}
        </button>

{{ $t("projects.unlinkHint") }}

        <button type="button" @click="pendingDelete = null">
          {{ $t("projects.cancel") }}
        </button>
        <button @click="unlinkProject">
          {{ $t("projects.unlink") }}
        </button>
        <button class="danger" @click="confirmDelete">
          {{ $t("projects.delete") }}
        </button>

+        <button @click="unlinkProject">


Bash

cd /Users/marcus.hinz/projects/ai-control && npm run build 2>&1 | tail -15

Build frontend to validate TS/Vue changes


> vue-tsc -b && vite build

src/i18n.ts(76,31): error TS1005: ',' expected.
src/i18n.ts(76,40): error TS1005: ',' expected.
src/i18n.ts(76,44): error TS1005: ',' expected.
src/i18n.ts(76,51): error TS1005: ',' expected.
src/i18n.ts(76,57): error TS1005: ',' expected.
src/i18n.ts(76,64): error TS1005: ',' expected.
src/i18n.ts(76,71): error TS1005: ',' expected.
src/i18n.ts(76,83): error TS1005: ',' expected.
src/i18n.ts(76,84): error TS1003: Identifier expected.
src/i18n.ts(76,86): error TS1002: Unterminated string literal.
src/i18n.ts(77,5): error TS1005: ':' expected.
src/i18n.ts(77,9): error TS1005: ',' expected.
src/i18n.ts(77,22): error TS1005: ':' expected.


Edit

    unlink: "Nur aus Liste nehmen",
    unlinkHint:
      "„Nur aus Liste nehmen" entfernt den Eintrag; der Ordner bleibt unangetastet.",

    unlink: "Nur aus Liste nehmen",
    unlinkHint:
      "Nur aus Liste nehmen entfernt den Eintrag; der Ordner bleibt unangetastet.",


    unlink: "Nur aus Liste nehmen",
    unlinkHint:
      "Nur aus Liste nehmen entfernt den Eintrag; der Ordner bleibt unangetastet.",

import { createI18n } from "vue-i18n";

const de = {
  app: {
    projects: "Projekte",
    pools: "Pools",
    usage: "Verbrauch",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 Tage",
    days30: "30 Tage",
    pool: "Pool",
    project: "Projekt",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ Kosten",
    total: "Summe",
    empty: "Keine Verbrauchsdaten im Zeitraum.",
    estimateNote:
      "API-Gegenwert aus den lokalen Transcripts — keine Abrechnung, Historie nur solange claude sie vorhält.",
  },
  projects: {
    project: "Projekt",
    pool: "Pool",
    noPool: "– kein Pool –",
    start: "Starten",
    stop: "Beenden",
    terminalSettings: "Terminal-Einstellungen",
    stillRunning: "{name} läuft noch",
    poolChangeSaved:
      "Der Pool-Wechsel ist gespeichert. Die laufende Session arbeitet aber weiter im alten Pool — der neue gilt erst ab dem nächsten Start.",
    restartHint:
      "Der Neustart beendet die laufende Session. Der automatische commit+push von claude-sync nach Sessionende entfällt dabei.",
    keepRunning: "Weiterlaufen lassen",
    restartNow: "Jetzt neu starten",
    restarting: "Starte neu …",
    terminal: "Terminal — {name}",
    title: "Titel",
    theme: "Theme",
    dockIcon: "Dock-Icon",
    chooseFile: "Datei wählen …",
    remove: "Entfernen",
    defaultIcon: "Standard-Icon",
    appliesNextStart: "Gilt ab dem nächsten Terminal-Start.",
    cancel: "Abbrechen",
    save: "Speichern",
    noPoolAssigned: "kein Pool",
    needsPool: "Kein Pool zugeordnet",
    needsKey: "Pool hat keinen API-Key",
    newProject: "+ Projekt",
    addFolder: "+ Ordner",
    addFolderTitle: "Bestehenden Ordner als Projekt aufnehmen",
    wizardTitle: "Neues Projekt",
    name: "Name",
    projectDir: "Projektordner",
    projectDirCustom: "Ordner wählen …",
    workDir: "Arbeitsordner",
    workDirNone: "keiner",
    workDirCustom: "vorhandenen Ordner verknüpfen",
    chooseFolder: "Ordner wählen …",
    create: "Anlegen",
    wizardHint:
      "Angelegt werden Projektordner mit memory/, Sentinel-.gitignore, settings.json (Memory-Verzeichnis + Berechtigungen) und die Pool-/Terminal-Zuordnung.",
    delete: "Projekt löschen",
    deleteRunning: "Läuft noch — erst beenden",
    deleteTitle: "{name} löschen",
    deleteWarning:
      "Der Projektordner (inkl. memory/, Settings und Pool-Zuordnung) wird endgültig gelöscht.",
    deleteWorkDirs: "Arbeitsordner mitlöschen:",
    workDirsStay: "Die Arbeitsordner bleiben unangetastet.",
    unlink: "Nur aus Liste nehmen",
    unlinkHint:
      "„Nur aus Liste nehmen" entfernt den Eintrag; der Ordner bleibt unangetastet.",
    todo: "Todoliste",
    todoDesc: "OFFENE-PUNKTE.md bei jedem Sessionstart einspielen",
  },
  pools: {
    pool: "Pool",
    type: "Typ",
    actions: "Aktionen",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Zurücksetzen",
    rename: "Umbenennen",
    renameTitle: "{name} umbenennen",
    changeKey: "Key ändern",
    insertKey: "Key eintragen",
    delete: "Löschen",
    assigned: "kein Projekt | 1 Projekt | {count} Projekte",
    empty: "Noch keine Pools angelegt.",
    newOauthPool: "Neuen oAuth-Pool anlegen",
    newApikeyPool: "Neuen API-Key-Pool anlegen",
    editKey: "API-Key ändern – {name}",
    name: "Name",
    apiKey: "API-Key",
    oauthHint:
      "Der Pool wird angelegt; die Anmeldung macht claude beim ersten Start selbst per /login (Browser gegen dein Abo).",
    cancel: "Abbrechen",
    createPool: "Anlegen",
    reset: "Zurücksetzen",
    save: "Speichern",
    deletePool: "Pool löschen",
    deleteWarning:
      "Pool {name} und seine Credential-Datei werden gelöscht. Das lässt sich nicht rückgängig machen.",
    deleteUnassigns: "Diese Projekte verlieren ihre Pool-Zuordnung:",
    deleteBlockedTooltip:
      "Löschen gesperrt — {projects} läuft gerade. Erst beenden.",
    reloginTitle: "{name} zurücksetzen",
    reloginWarning:
      "Der im Schlüsselbund gespeicherte Zugriffstoken von {name} wird gelöscht. Beim nächsten Start verlangt claude erneut /login.",
    reloginNoEntry:
      "Kein Schlüsselbund-Eintrag vorhanden — beim nächsten Start meldet sich claude ohnehin per /login an.",
    reloginBlocked:
      "Zurücksetzen ist nur bei ungenutztem Pool möglich. Diese Projekte laufen noch:",
    keychainUnavailableTitle: "Keine sichere Ablage",
    keychainUnavailable:
      "Keychain/Keyring ist nicht verfügbar. Der Key kann stattdessen ungesichert als Datei im Pool-Ordner liegen (0600).",
    storeAsFile: "Als Datei ablegen",
  },
};

const en: typeof de = {
  app: {
    projects: "Projects",
    pools: "Pools",
    usage: "Usage",
    autostart: "Autostart",
  },
  usage: {
    days7: "7 days",
    days30: "30 days",
    pool: "Pool",
    project: "Project",
    input: "Input",
    output: "Output",
    cacheWrite: "Cache ↑",
    cacheRead: "Cache ↓",
    cost: "≈ cost",
    total: "Total",
    empty: "No usage data in this period.",
    estimateNote:
      "API equivalent from local transcripts — not a bill; history only as long as claude keeps it.",
  },
  projects: {
    project: "Project",
    pool: "Pool",
    noPool: "– no pool –",
    start: "Start",
    stop: "Stop",
    terminalSettings: "Terminal settings",
    stillRunning: "{name} is still running",
    poolChangeSaved:
      "The pool change is saved. The running session keeps working in the old pool — the new one applies from the next start.",
    restartHint:
      "Restarting ends the running session. The automatic commit+push by claude-sync after the session is skipped.",
    keepRunning: "Keep running",
    restartNow: "Restart now",
    restarting: "Restarting …",
    terminal: "Terminal — {name}",
    title: "Title",
    theme: "Theme",
    dockIcon: "Dock icon",
    chooseFile: "Choose file …",
    remove: "Remove",
    defaultIcon: "Default icon",
    appliesNextStart: "Applies from the next terminal start.",
    cancel: "Cancel",
    save: "Save",
    noPoolAssigned: "no pool",
    needsPool: "No pool assigned",
    needsKey: "Pool has no API key",
    newProject: "+ Project",
    addFolder: "+ Folder",
    addFolderTitle: "Add an existing folder as a project",
    wizardTitle: "New project",
    name: "Name",
    projectDir: "Project folder",
    projectDirCustom: "Choose folder …",
    workDir: "Working folder",
    workDirNone: "none",
    workDirCustom: "link existing folder",
    chooseFolder: "Choose folder …",
    create: "Create",
    wizardHint:
      "Creates the project folder with memory/, sentinel .gitignore, settings.json (memory dir + permissions), and the pool/terminal assignment.",
    delete: "Delete project",
    deleteRunning: "Still running — stop it first",
    deleteTitle: "Delete {name}",
    deleteWarning:
      "The project folder (incl. memory/, settings and pool assignment) will be deleted permanently.",
    deleteWorkDirs: "Also delete working folders:",
    workDirsStay: "The working folders stay untouched.",
    unlink: "Remove from list only",
    unlinkHint:
      "\"Remove from list only\" drops the entry; the folder stays untouched.",
    todo: "Todo list",
    todoDesc: "Inject OFFENE-PUNKTE.md at every session start",
  },
  pools: {
    pool: "Pool",
    type: "Type",
    actions: "Actions",
    newOauth: "+ oAuth",
    newApikey: "+ apiKey",
    relogin: "Reset",
    rename: "Rename",
    renameTitle: "Rename {name}",
    changeKey: "Change key",
    insertKey: "Insert key",
    delete: "Delete",
    assigned: "no projects | 1 project | {count} projects",
    empty: "No pools yet.",
    newOauthPool: "Create oAuth pool",
    newApikeyPool: "Create API key pool",
    editKey: "Change API key – {name}",
    name: "Name",
    apiKey: "API key",
    oauthHint:
      "The pool is created; claude signs in itself on first start via /login (browser against your subscription).",
    cancel: "Cancel",
    createPool: "Create",
    reset: "Reset",
    save: "Save",
    deletePool: "Delete pool",
    deleteWarning:
      "Pool {name} and its credential file will be deleted. This cannot be undone.",
    deleteUnassigns: "These projects lose their pool assignment:",
    deleteBlockedTooltip:
      "Deletion blocked — active: {projects}. Stop the session first.",
    reloginTitle: "Reset {name}",
    reloginWarning:
      "The access token for {name} stored in the keychain will be deleted. On the next start claude asks for /login again.",
    reloginNoEntry:
      "No keychain entry present — claude signs in via /login on the next start anyway.",
    reloginBlocked:
      "Resetting requires an unused pool. These projects are still running:",
    keychainUnavailableTitle: "No secure storage",
    keychainUnavailable:
      "Keychain/keyring is unavailable. The key can instead be stored unprotected as a file in the pool folder (0600).",
    storeAsFile: "Store as file",
  },
};

const stored = localStorage.getItem("lang");
const initial =
  stored === "de" || stored === "en"
    ? stored
    : navigator.language.startsWith("de")
      ? "de"
      : "en";

export const i18n = createI18n({
  legacy: false,
  globalInjection: true,
  locale: initial,
  fallbackLocale: "en",
  messages: { de, en },
});

export function setLocale(lang: "de" | "en") {
  i18n.global.locale.value = lang;
  localStorage.setItem("lang", lang);
}

-      "„Nur aus Liste nehmen" entfernt den Eintrag; der Ordner bleibt unangetastet.",

+      "Nur aus Liste nehmen entfernt den Eintrag; der Ordner bleibt unangetastet.",


    unlink: "Remove from list only",
    unlinkHint:
      "\"Remove from list only\" drops the entry; the folder stays untouched.",

    unlink: "Remove from list only",
    unlinkHint:
      "Remove from list only drops the entry; the folder stays untouched.",