fix: ai preferences crashed and deleted stuff in preferences

This commit is contained in:
2026-07-07 22:43:05 +02:00
parent 4a03fc0ba2
commit dc35518bad
21 changed files with 1883 additions and 261 deletions

View File

@@ -3,6 +3,7 @@
@source "../css";
@source "../js";
@source "../../lib/bds/desktop";
@source "../../deps/live_toast/lib";
@import "./tokens.css";
@import "./shell.css";

View File

@@ -377,3 +377,8 @@
font: inherit;
}
/* Alert modal (errors) — reuses .confirm-delete-modal with a tone accent. */
.alert-modal-error {
border-top: 3px solid #ff6b6b;
}

View File

@@ -6,8 +6,10 @@ import { ColourPicker } from "./colour_picker.js";
import { MenuEditorTree } from "./menu_editor_tree.js";
import { MonacoEditor } from "./monaco_editor.js";
import { MonacoDiffEditor } from "./monaco_diff_editor.js";
import { createLiveToastHook } from "live_toast";
export const Hooks = {
LiveToast: createLiveToastHook(),
AppShell,
SidebarInteractions,
SettingsSectionScroll,

View File

@@ -54,13 +54,21 @@ defmodule BDS.AI do
model = MapUtils.attr(attrs, :model)
api_key = MapUtils.attr(attrs, :api_key)
with :ok <- put_setting("ai.#{kind_key}.url", url),
:ok <- put_setting("ai.#{kind_key}.model", model),
:ok <- put_secret("ai.#{kind_key}.api_key", api_key, backend) do
with :ok <- put_or_delete_setting("ai.#{kind_key}.url", url),
:ok <- put_or_delete_setting("ai.#{kind_key}.model", model),
:ok <- put_or_delete_secret("ai.#{kind_key}.api_key", api_key, backend) do
{:ok, %{kind: kind, url: url, api_key: api_key, model: model}}
end
end
# A nil field means "clear it" — writing nil into put_setting/2 would raise a
# FunctionClauseError and crash the caller (the preferences panel).
defp put_or_delete_setting(key, nil), do: delete_setting(key)
defp put_or_delete_setting(key, value) when is_binary(value), do: put_setting(key, value)
defp put_or_delete_secret(key, nil, _backend), do: delete_setting(encrypted_key(key))
defp put_or_delete_secret(key, value, backend), do: put_secret(key, value, backend)
@spec get_endpoint(endpoint_kind(), keyword()) ::
{:ok, endpoint() | nil} | {:error, term()}
def get_endpoint(kind, opts \\ []) when is_atom(kind) and is_list(opts) do

View File

@@ -719,6 +719,11 @@ defmodule BDS.Desktop.ShellLive do
{:noreply, refresh_sidebar(socket, socket.assigns.workbench)}
end
def handle_info({:shell_alert, title, message}, socket) do
overlay = %{kind: :alert, title: title, message: message, tone: "error"}
{:noreply, assign(socket, :shell_overlay, overlay)}
end
def handle_info(message, socket) do
Bridges.handle_info(message, socket, bridges_callbacks())
end
@@ -729,6 +734,20 @@ defmodule BDS.Desktop.ShellLive do
index(assigns)
end
# Dark-themed toast classes for LiveToast (its default is bg-white/text-black).
# Mirrors the library's structural classes but uses the app's dark palette.
@doc false
@spec toast_class_fn(map()) :: [String.t() | false]
def toast_class_fn(assigns) do
[
"group/toast z-100 pointer-events-auto relative w-full items-center justify-between origin-center overflow-hidden rounded-lg p-4 shadow-lg border col-start-1 col-end-1 row-start-1 row-end-2",
"bg-[#2d2d2d] text-[#f0f0f0] border-[#3c3c3c]",
"[@media(scripting:enabled)]:opacity-0 [@media(scripting:enabled){[data-phx-main]_&}]:opacity-100",
if(assigns[:rest][:hidden] == true, do: "hidden", else: "flex"),
assigns[:kind] == :error && "!bg-[#3a2020] !text-red-300 !border-[#5a2a2a]"
]
end
defp refresh_layout(socket, workbench), do: SocketState.refresh_layout(socket, workbench)
defp refresh_sidebar(socket, workbench), do: SocketState.refresh_sidebar(socket, workbench)

View File

@@ -678,5 +678,6 @@
</footer>
<ShellOverlayComponents.shell_overlay shell_overlay={@shell_overlay} />
<LiveToast.toast_group flash={@flash} connected={assigns[:socket] != nil} toasts_sync={assigns[:toasts_sync]} corner={:bottom_right} toast_class_fn={&toast_class_fn/1} />
<GitRun.git_run_modal git_run={@git_run} />
</div>

View File

@@ -20,6 +20,12 @@ defmodule BDS.Desktop.ShellLive.Notify do
:ok
end
@spec alert(String.t(), String.t()) :: :ok
def alert(title, message) do
send(self(), {:shell_alert, title, message})
:ok
end
@spec tab_meta(atom(), term(), String.t(), String.t()) :: :ok
def tab_meta(type, id, title, subtitle) do
send(self(), {:editor_tab_meta, type, id, %{title: title, subtitle: subtitle || ""}})

View File

@@ -186,6 +186,23 @@
</div>
</div>
<% :alert -> %>
<div class="shell-overlay-backdrop confirm-delete-modal-backdrop" data-testid="shell-overlay-backdrop" phx-window-keydown="overlay_keydown">
<button class="shell-overlay-dismiss" type="button" phx-click="close_overlay" aria-label={dgettext("ui", "Close")}></button>
<div class={["confirm-delete-modal", "alert-modal", "alert-modal-#{@shell_overlay.tone}"]} role="alertdialog" aria-modal="true">
<div class="confirm-delete-modal-header">
<h2><%= @shell_overlay.title %></h2>
<button class="confirm-delete-modal-close" type="button" phx-click="close_overlay">×</button>
</div>
<div class="confirm-delete-modal-body">
<div class="confirm-delete-message"><%= @shell_overlay.message %></div>
</div>
<div class="confirm-delete-modal-footer">
<button class="button-apply primary ui-button ui-button-primary" type="button" phx-click="close_overlay"><%= dgettext("ui", "OK") %></button>
</div>
</div>
</div>
<% :gallery -> %>
<div class="shell-overlay-backdrop gallery-overlay-backdrop" data-testid="shell-overlay-backdrop" phx-window-keydown="overlay_keydown">
<button class="shell-overlay-dismiss" type="button" phx-click="close_overlay" aria-label={dgettext("ui", "Cancel")}></button>

View File

@@ -4,6 +4,7 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.AISettings do
use Phoenix.Component
alias BDS.AI
alias BDS.Desktop.ShellLive.Notify
alias BDS.Desktop.ShellLive.SettingsEditor.EditorSettings
require Logger
use Gettext, backend: BDS.Gettext
@@ -71,6 +72,8 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.AISettings do
with {:ok, endpoint} <- endpoint_refresh_attrs(endpoint_key, attrs),
{:ok, models} <- AI.list_endpoint_models(endpoint) do
notify_models_loaded(models)
socket
|> assign(
:settings_editor_endpoint_models,
@@ -83,14 +86,25 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.AISettings do
|> reload.(socket.assigns.workbench)
else
{:error, reason} ->
message = ai_error_message(reason)
Notify.alert(dgettext("ui", "Could not load models"), message)
socket
|> append_output.(dgettext("ui", "AI Settings"), inspect(reason), nil, "error")
|> append_output.(dgettext("ui", "AI Settings"), message, nil, "error")
|> reload.(socket.assigns.workbench)
end
end
@spec save_ai(term(), term(), term()) :: term()
def save_ai(socket, reload, append_output) do
do_save_ai(socket, reload, append_output)
rescue
error ->
Logger.error("AI settings save crashed: #{Exception.format(:error, error, __STACKTRACE__)}")
surface_ai_error(socket, reload, append_output, error)
end
defp do_save_ai(socket, reload, append_output) do
attrs = ai_attrs(socket.assigns)
with :ok <-
@@ -142,18 +156,48 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.AISettings do
attrs.offline_chat_images
),
:ok <- EditorSettings.put_global_setting("ai.system_prompt", attrs.system_prompt) do
LiveToast.send_toast(:info, dgettext("ui", "AI settings saved."))
socket
|> assign(:settings_editor_ai_draft, %{})
|> assign(:offline_mode, attrs.offline_mode)
|> reload.(socket.assigns.workbench)
else
{:error, reason} ->
socket
|> append_output.(dgettext("ui", "AI Settings"), inspect(reason), nil, "error")
|> reload.(socket.assigns.workbench)
surface_ai_error(socket, reload, append_output, reason)
end
end
defp notify_models_loaded([]) do
LiveToast.send_toast(
:info,
dgettext(
"ui",
"The endpoint returned no models. You can still type a model name manually."
)
)
end
defp notify_models_loaded(models) do
LiveToast.send_toast(
:info,
dgettext("ui", "Loaded %{count} models.", count: length(models))
)
end
defp surface_ai_error(socket, reload, append_output, reason) do
message = ai_error_message(reason)
Notify.alert(dgettext("ui", "Could not save AI settings"), message)
socket
|> append_output.(dgettext("ui", "AI Settings"), message, nil, "error")
|> reload.(socket.assigns.workbench)
end
defp ai_error_message(%{__exception__: true} = error), do: Exception.message(error)
defp ai_error_message(reason) when is_binary(reason), do: reason
defp ai_error_message(reason), do: inspect(reason)
@spec reset_ai_prompt(term(), term(), term()) :: term()
def reset_ai_prompt(socket, reload, append_output) do
case EditorSettings.put_global_setting("ai.system_prompt", "") do
@@ -179,7 +223,9 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.AISettings do
end
defp ai_attrs(assigns) do
draft = Map.get(assigns, :settings_editor_ai_draft, %{})
# Merge the stored form with the edit draft so untouched fields (URLs, API
# keys) are preserved on save instead of being read as nil and wiped.
draft = Map.merge(ai_form(assigns), Map.get(assigns, :settings_editor_ai_draft, %{}))
%{
online_url: blank_to_nil(Map.get(draft, "online_url")),

View File

@@ -37,6 +37,7 @@ defmodule BDS.MixProject do
{:plug, "~> 1.18"},
{:bandit, "~> 1.5"},
{:req, "~> 0.5"},
{:live_toast, "~> 0.8.0"},
{:saxy, "~> 1.4"},
{:desktop, "~> 1.5"},
{:image, "~> 0.67"},

View File

@@ -43,6 +43,7 @@
"kday": {:hex, :kday, "1.1.0", "64efac85279a12283eaaf3ad6f13001ca2dff943eda8c53288179775a8c057a0", [:mix], [{:ex_doc, "~> 0.21", [hex: :ex_doc, repo: "hexpm", optional: true]}], "hexpm", "69703055d63b8d5b260479266c78b0b3e66f7aecdd2022906cd9bf09892a266d"},
"lazy_html": {:hex, :lazy_html, "0.1.11", "136c8e9cd616b4f4e9c1562daa683880891120b759606dc4c3b6b18058ba5d79", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.9.0", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1.0", [hex: :fine, repo: "hexpm", optional: false]}], "hexpm", "3b1be592929c31eca1a21673d25696e5c14cddfe922d9d1a3e3b48be4163883b"},
"liquex": {:hex, :liquex, "0.13.1", "49f90d0b85fb2908f2558f35cd49d78497fe77a895eb55b360889940e1d7afb9", [:mix], [{:date_time_parser, "~> 1.2", [hex: :date_time_parser, repo: "hexpm", optional: false]}, {:html_entities, "~> 0.5.2", [hex: :html_entities, repo: "hexpm", optional: false]}, {:html_sanitize_ex, "~> 1.4.3", [hex: :html_sanitize_ex, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "fbea5b9db264c1758a69bfafdcc8aaebcd56e168365bb9575392cd55d800108f"},
"live_toast": {:hex, :live_toast, "0.8.0", "d7e24801a9a966d8e48872767ac33c50fc14640ac5272128becfc534fabd99b7", [:mix], [{:ecto, ">= 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:gettext, ">= 0.26.2", [hex: :gettext, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.19", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_live_view, ">= 1.0.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "7e64435131b7731698908d59f7ba9f5092df8a3720814f26edf57e99d97a803c"},
"luerl": {:hex, :luerl, "1.5.1", "f6700420950fc6889137e7a0c11c4a8467dea04a8c23f707a40d83566d14e786", [:rebar3], [], "hexpm", "abf88d849baa0d5dca93b245a8688d4de2ee3d588159bb2faf51e15946509390"},
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},

View File

@@ -70,9 +70,9 @@ msgstr "KI"
msgid "AI Assistant"
msgstr "KI-Assistent"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:87
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:152
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:167
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:93
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:190
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:208
#, elixir-autogen, elixir-format
msgid "AI Settings"
msgstr "KI-Einstellungen"
@@ -336,7 +336,7 @@ msgstr "Autor"
msgid "Auto"
msgstr "Automatisch"
#: lib/bds/desktop/shell_live.ex:442
#: lib/bds/desktop/shell_live.ex:448
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -418,7 +418,7 @@ msgstr "Blogmark-Kategorie"
msgid "Bookmarklet copy support is wired through the desktop runtime and project public URL."
msgstr "Die Bookmarklet-Kopierfunktion ist über die Desktop-Laufzeit und die öffentliche Projekt-URL verdrahtet."
#: lib/bds/desktop/shell_live/git_run.ex:126
#: lib/bds/desktop/shell_live/git_run.ex:128
#: lib/bds/desktop/shell_live/import_editor.ex:1366
#: lib/bds/desktop/shell_live/media_editor_html/media_editor.html.heex:298
#: lib/bds/desktop/shell_live/menu_editor.ex:335
@@ -431,8 +431,8 @@ msgstr "Die Bookmarklet-Kopierfunktion ist über die Desktop-Laufzeit und die ö
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:165
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:173
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr "Abbrechen"
@@ -486,7 +486,7 @@ msgstr "Kategorie-Standards, Render-Flags und Template-Zuordnung"
msgid "Category name is required"
msgstr "Kategoriename ist erforderlich"
#: lib/bds/desktop/shell_live.ex:748
#: lib/bds/desktop/shell_live.ex:771
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -1052,7 +1052,7 @@ msgstr "Duplikate finden"
msgid "Force Reload"
msgstr "Erzwungenes Neuladen"
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:194
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:211
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:432
#, elixir-autogen, elixir-format
msgid "Gallery"
@@ -1063,7 +1063,7 @@ msgstr "Galerie"
msgid "Generate Site"
msgstr "Website generieren"
#: lib/bds/desktop/shell_live.ex:749
#: lib/bds/desktop/shell_live.ex:772
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/ui/sidebar.ex:789
#, elixir-autogen, elixir-format
@@ -1077,7 +1077,7 @@ msgid "Git Diff"
msgstr "Git-Diff"
#: lib/bds/desktop/shell_data.ex:226
#: lib/bds/desktop/shell_live.ex:745
#: lib/bds/desktop/shell_live.ex:768
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#, elixir-autogen, elixir-format
msgid "Git Log"
@@ -1200,9 +1200,9 @@ msgstr "Importdefinitionen"
msgid "Import failed: %{error}"
msgstr "Import fehlgeschlagen: %{error}"
#: lib/bds/desktop/shell_live.ex:592
#: lib/bds/desktop/shell_live.ex:861
#: lib/bds/desktop/shell_live.ex:867
#: lib/bds/desktop/shell_live.ex:598
#: lib/bds/desktop/shell_live.ex:884
#: lib/bds/desktop/shell_live.ex:890
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1784,7 +1784,7 @@ msgstr "Sonstige"
msgid "Other (%{count})"
msgstr "Andere (%{count})"
#: lib/bds/desktop/shell_live.ex:744
#: lib/bds/desktop/shell_live.ex:767
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#, elixir-autogen, elixir-format
msgid "Output"
@@ -2538,7 +2538,7 @@ msgstr "Schlagwortname"
msgid "Tags"
msgstr "Tags"
#: lib/bds/desktop/shell_live.ex:743
#: lib/bds/desktop/shell_live.ex:766
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -3218,12 +3218,12 @@ msgstr "Willkommen beim KI-Assistenten"
msgid "Comparing database and filesystem metadata"
msgstr "Vergleicht Datenbank- und Dateisystem-Metadaten"
#: lib/bds/desktop/shell_live.ex:668
#: lib/bds/desktop/shell_live.ex:674
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr "%{count} Bilder zum Beitrag hinzugefügt"
#: lib/bds/desktop/shell_live.ex:636
#: lib/bds/desktop/shell_live.ex:642
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr "%{title} hinzugefügt"
@@ -3243,18 +3243,18 @@ msgstr "Endbenutzer-Anleitung für redaktionelle Arbeitsabläufe, Medien, Vorlag
msgid "Image Import Concurrency"
msgstr "Gleichzeitige Bildimporte"
#: lib/bds/desktop/shell_live.ex:441
#: lib/bds/desktop/shell_live.ex:454
#: lib/bds/desktop/shell_live.ex:635
#: lib/bds/desktop/shell_live.ex:667
#: lib/bds/desktop/shell_live.ex:678
#: lib/bds/desktop/shell_live.ex:689
#: lib/bds/desktop/shell_live.ex:447
#: lib/bds/desktop/shell_live.ex:460
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:673
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:695
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr "Galerie-Bilder hinzufügen"
#: lib/bds/desktop/shell_live.ex:690
#: lib/bds/desktop/shell_live.ex:696
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr "%{path} konnte nicht verarbeitet werden: %{reason}"
@@ -3353,7 +3353,7 @@ msgid "Local only"
msgstr "Nur lokal"
#: lib/bds/desktop/shell_live/git_handler.ex:113
#: lib/bds/desktop/shell_live/git_run.ex:82
#: lib/bds/desktop/shell_live/git_run.ex:83
#, elixir-autogen, elixir-format
msgid "No active project"
msgstr "Kein aktives Projekt"
@@ -3445,12 +3445,12 @@ msgstr "umbenannt"
msgid "untracked"
msgstr "nicht verfolgt"
#: lib/bds/desktop/shell_live.ex:769
#: lib/bds/desktop/shell_live.ex:792
#, elixir-autogen, elixir-format
msgid "Blogmark"
msgstr "Blogmark"
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:835
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr "Öffnen Sie ein Projekt, bevor Sie ein Blogmark importieren."
@@ -3491,7 +3491,7 @@ msgstr "Loeschen"
msgid "Failed to copy bookmarklet to clipboard"
msgstr "Bookmarklet konnte nicht in die Zwischenablage kopiert werden"
#: lib/bds/desktop/shell_live.ex:781
#: lib/bds/desktop/shell_live.ex:804
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr "Das Projekt, auf das dieses Blogmark verweist, existiert hier nicht."
@@ -3537,12 +3537,13 @@ msgid "Zoom"
msgstr "Zoomen"
#: lib/bds/desktop/shell_live/git_run.ex:91
#: lib/bds/desktop/shell_live/git_run.ex:127
#: lib/bds/desktop/shell_live/git_run.ex:129
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#, elixir-autogen, elixir-format
msgid "Close"
msgstr "Schließen"
#: lib/bds/desktop/shell_live/git_run.ex:124
#: lib/bds/desktop/shell_live/git_run.ex:126
#, elixir-autogen, elixir-format
msgid "Failed (exit %{status})"
msgstr "Fehlgeschlagen (Exit %{status})"
@@ -3566,3 +3567,33 @@ msgstr "git pull"
#, elixir-autogen, elixir-format
msgid "git push"
msgstr "git push"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:159
#, elixir-autogen, elixir-format
msgid "AI settings saved."
msgstr "KI-Einstellungen gespeichert."
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:90
#, elixir-autogen, elixir-format
msgid "Could not load models"
msgstr "Modelle konnten nicht geladen werden"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:187
#, elixir-autogen, elixir-format
msgid "Could not save AI settings"
msgstr "KI-Einstellungen konnten nicht gespeichert werden"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:182
#, elixir-autogen, elixir-format
msgid "Loaded %{count} models."
msgstr "%{count} Modelle geladen."
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:201
#, elixir-autogen, elixir-format
msgid "OK"
msgstr "OK"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:173
#, elixir-autogen, elixir-format
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr "Der Endpunkt hat keine Modelle zurückgegeben. Sie können einen Modellnamen weiterhin manuell eingeben."

View File

@@ -70,9 +70,9 @@ msgstr ""
msgid "AI Assistant"
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:87
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:152
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:167
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:93
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:190
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:208
#, elixir-autogen, elixir-format
msgid "AI Settings"
msgstr ""
@@ -336,7 +336,7 @@ msgstr ""
msgid "Auto"
msgstr ""
#: lib/bds/desktop/shell_live.ex:442
#: lib/bds/desktop/shell_live.ex:448
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -418,7 +418,7 @@ msgstr ""
msgid "Bookmarklet copy support is wired through the desktop runtime and project public URL."
msgstr ""
#: lib/bds/desktop/shell_live/git_run.ex:126
#: lib/bds/desktop/shell_live/git_run.ex:128
#: lib/bds/desktop/shell_live/import_editor.ex:1366
#: lib/bds/desktop/shell_live/media_editor_html/media_editor.html.heex:298
#: lib/bds/desktop/shell_live/menu_editor.ex:335
@@ -431,8 +431,8 @@ msgstr ""
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:165
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:173
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr ""
@@ -486,7 +486,7 @@ msgstr ""
msgid "Category name is required"
msgstr ""
#: lib/bds/desktop/shell_live.ex:748
#: lib/bds/desktop/shell_live.ex:771
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -1052,7 +1052,7 @@ msgstr ""
msgid "Force Reload"
msgstr ""
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:194
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:211
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:432
#, elixir-autogen, elixir-format
msgid "Gallery"
@@ -1063,7 +1063,7 @@ msgstr ""
msgid "Generate Site"
msgstr ""
#: lib/bds/desktop/shell_live.ex:749
#: lib/bds/desktop/shell_live.ex:772
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/ui/sidebar.ex:789
#, elixir-autogen, elixir-format
@@ -1077,7 +1077,7 @@ msgid "Git Diff"
msgstr ""
#: lib/bds/desktop/shell_data.ex:226
#: lib/bds/desktop/shell_live.ex:745
#: lib/bds/desktop/shell_live.ex:768
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#, elixir-autogen, elixir-format
msgid "Git Log"
@@ -1200,9 +1200,9 @@ msgstr ""
msgid "Import failed: %{error}"
msgstr ""
#: lib/bds/desktop/shell_live.ex:592
#: lib/bds/desktop/shell_live.ex:861
#: lib/bds/desktop/shell_live.ex:867
#: lib/bds/desktop/shell_live.ex:598
#: lib/bds/desktop/shell_live.ex:884
#: lib/bds/desktop/shell_live.ex:890
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1784,7 +1784,7 @@ msgstr ""
msgid "Other (%{count})"
msgstr ""
#: lib/bds/desktop/shell_live.ex:744
#: lib/bds/desktop/shell_live.ex:767
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#, elixir-autogen, elixir-format
msgid "Output"
@@ -2538,7 +2538,7 @@ msgstr ""
msgid "Tags"
msgstr ""
#: lib/bds/desktop/shell_live.ex:743
#: lib/bds/desktop/shell_live.ex:766
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -3218,12 +3218,12 @@ msgstr ""
msgid "Comparing database and filesystem metadata"
msgstr "Comparing database and filesystem metadata"
#: lib/bds/desktop/shell_live.ex:668
#: lib/bds/desktop/shell_live.ex:674
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr "Added %{count} images to post"
#: lib/bds/desktop/shell_live.ex:636
#: lib/bds/desktop/shell_live.ex:642
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr "Added %{title}"
@@ -3243,18 +3243,18 @@ msgstr ""
msgid "Image Import Concurrency"
msgstr "Image Import Concurrency"
#: lib/bds/desktop/shell_live.ex:441
#: lib/bds/desktop/shell_live.ex:454
#: lib/bds/desktop/shell_live.ex:635
#: lib/bds/desktop/shell_live.ex:667
#: lib/bds/desktop/shell_live.ex:678
#: lib/bds/desktop/shell_live.ex:689
#: lib/bds/desktop/shell_live.ex:447
#: lib/bds/desktop/shell_live.ex:460
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:673
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:695
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr "Add Gallery Images"
#: lib/bds/desktop/shell_live.ex:690
#: lib/bds/desktop/shell_live.ex:696
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr "Failed to process %{path}: %{reason}"
@@ -3353,7 +3353,7 @@ msgid "Local only"
msgstr ""
#: lib/bds/desktop/shell_live/git_handler.ex:113
#: lib/bds/desktop/shell_live/git_run.ex:82
#: lib/bds/desktop/shell_live/git_run.ex:83
#, elixir-autogen, elixir-format
msgid "No active project"
msgstr ""
@@ -3445,12 +3445,12 @@ msgstr ""
msgid "untracked"
msgstr ""
#: lib/bds/desktop/shell_live.ex:769
#: lib/bds/desktop/shell_live.ex:792
#, elixir-autogen, elixir-format, fuzzy
msgid "Blogmark"
msgstr "Blogmark"
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:835
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr ""
@@ -3491,7 +3491,7 @@ msgstr ""
msgid "Failed to copy bookmarklet to clipboard"
msgstr ""
#: lib/bds/desktop/shell_live.ex:781
#: lib/bds/desktop/shell_live.ex:804
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr ""
@@ -3537,12 +3537,13 @@ msgid "Zoom"
msgstr ""
#: lib/bds/desktop/shell_live/git_run.ex:91
#: lib/bds/desktop/shell_live/git_run.ex:127
#: lib/bds/desktop/shell_live/git_run.ex:129
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#, elixir-autogen, elixir-format, fuzzy
msgid "Close"
msgstr ""
#: lib/bds/desktop/shell_live/git_run.ex:124
#: lib/bds/desktop/shell_live/git_run.ex:126
#, elixir-autogen, elixir-format
msgid "Failed (exit %{status})"
msgstr ""
@@ -3566,3 +3567,33 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "git push"
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:159
#, elixir-autogen, elixir-format
msgid "AI settings saved."
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:90
#, elixir-autogen, elixir-format
msgid "Could not load models"
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:187
#, elixir-autogen, elixir-format
msgid "Could not save AI settings"
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:182
#, elixir-autogen, elixir-format
msgid "Loaded %{count} models."
msgstr ""
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:201
#, elixir-autogen, elixir-format
msgid "OK"
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:173
#, elixir-autogen, elixir-format
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr ""

View File

@@ -70,9 +70,9 @@ msgstr "IA"
msgid "AI Assistant"
msgstr "Asistente de IA"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:87
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:152
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:167
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:93
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:190
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:208
#, elixir-autogen, elixir-format
msgid "AI Settings"
msgstr "Configuración de IA"
@@ -336,7 +336,7 @@ msgstr "Autor"
msgid "Auto"
msgstr "Automático"
#: lib/bds/desktop/shell_live.ex:442
#: lib/bds/desktop/shell_live.ex:448
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -418,7 +418,7 @@ msgstr "Categoría de blogmark"
msgid "Bookmarklet copy support is wired through the desktop runtime and project public URL."
msgstr "La copia del bookmarklet está conectada mediante el entorno de escritorio y la URL pública del proyecto."
#: lib/bds/desktop/shell_live/git_run.ex:126
#: lib/bds/desktop/shell_live/git_run.ex:128
#: lib/bds/desktop/shell_live/import_editor.ex:1366
#: lib/bds/desktop/shell_live/media_editor_html/media_editor.html.heex:298
#: lib/bds/desktop/shell_live/menu_editor.ex:335
@@ -431,8 +431,8 @@ msgstr "La copia del bookmarklet está conectada mediante el entorno de escritor
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:165
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:173
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr "Cancelar"
@@ -486,7 +486,7 @@ msgstr "Valores predeterminados de categoría, opciones de renderizado y conexi
msgid "Category name is required"
msgstr "El nombre de la categoría es obligatorio"
#: lib/bds/desktop/shell_live.ex:748
#: lib/bds/desktop/shell_live.ex:771
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -1052,7 +1052,7 @@ msgstr "Buscar duplicados"
msgid "Force Reload"
msgstr "Recarga forzada"
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:194
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:211
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:432
#, elixir-autogen, elixir-format
msgid "Gallery"
@@ -1063,7 +1063,7 @@ msgstr "Galeria"
msgid "Generate Site"
msgstr "Generar sitio"
#: lib/bds/desktop/shell_live.ex:749
#: lib/bds/desktop/shell_live.ex:772
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/ui/sidebar.ex:789
#, elixir-autogen, elixir-format
@@ -1077,7 +1077,7 @@ msgid "Git Diff"
msgstr "Diff de Git"
#: lib/bds/desktop/shell_data.ex:226
#: lib/bds/desktop/shell_live.ex:745
#: lib/bds/desktop/shell_live.ex:768
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#, elixir-autogen, elixir-format
msgid "Git Log"
@@ -1200,9 +1200,9 @@ msgstr "Definiciones de importación"
msgid "Import failed: %{error}"
msgstr "La importación falló: %{error}"
#: lib/bds/desktop/shell_live.ex:592
#: lib/bds/desktop/shell_live.ex:861
#: lib/bds/desktop/shell_live.ex:867
#: lib/bds/desktop/shell_live.ex:598
#: lib/bds/desktop/shell_live.ex:884
#: lib/bds/desktop/shell_live.ex:890
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1784,7 +1784,7 @@ msgstr "Otros"
msgid "Other (%{count})"
msgstr "Otros (%{count})"
#: lib/bds/desktop/shell_live.ex:744
#: lib/bds/desktop/shell_live.ex:767
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#, elixir-autogen, elixir-format
msgid "Output"
@@ -2538,7 +2538,7 @@ msgstr "Nombre de la etiqueta"
msgid "Tags"
msgstr "Etiquetas"
#: lib/bds/desktop/shell_live.ex:743
#: lib/bds/desktop/shell_live.ex:766
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -3218,12 +3218,12 @@ msgstr "Bienvenido al asistente de IA"
msgid "Comparing database and filesystem metadata"
msgstr "Comparando metadatos de la base de datos y del sistema de archivos"
#: lib/bds/desktop/shell_live.ex:668
#: lib/bds/desktop/shell_live.ex:674
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr "%{count} imágenes añadidas a la publicación"
#: lib/bds/desktop/shell_live.ex:636
#: lib/bds/desktop/shell_live.ex:642
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr "%{title} añadido"
@@ -3243,18 +3243,18 @@ msgstr "Guía del usuario para flujos editoriales, medios, plantillas, traducci
msgid "Image Import Concurrency"
msgstr "Importación simultánea de imágenes"
#: lib/bds/desktop/shell_live.ex:441
#: lib/bds/desktop/shell_live.ex:454
#: lib/bds/desktop/shell_live.ex:635
#: lib/bds/desktop/shell_live.ex:667
#: lib/bds/desktop/shell_live.ex:678
#: lib/bds/desktop/shell_live.ex:689
#: lib/bds/desktop/shell_live.ex:447
#: lib/bds/desktop/shell_live.ex:460
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:673
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:695
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr "Añadir imágenes a la galería"
#: lib/bds/desktop/shell_live.ex:690
#: lib/bds/desktop/shell_live.ex:696
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr "No se pudo procesar %{path}: %{reason}"
@@ -3353,7 +3353,7 @@ msgid "Local only"
msgstr "Solo local"
#: lib/bds/desktop/shell_live/git_handler.ex:113
#: lib/bds/desktop/shell_live/git_run.ex:82
#: lib/bds/desktop/shell_live/git_run.ex:83
#, elixir-autogen, elixir-format
msgid "No active project"
msgstr "Sin proyecto activo"
@@ -3445,12 +3445,12 @@ msgstr "renombrado"
msgid "untracked"
msgstr "sin seguimiento"
#: lib/bds/desktop/shell_live.ex:769
#: lib/bds/desktop/shell_live.ex:792
#, elixir-autogen, elixir-format
msgid "Blogmark"
msgstr "Blogmark"
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:835
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr "Abre un proyecto antes de importar un blogmark."
@@ -3491,7 +3491,7 @@ msgstr "Eliminar"
msgid "Failed to copy bookmarklet to clipboard"
msgstr "Error al copiar el bookmarklet al portapapeles"
#: lib/bds/desktop/shell_live.ex:781
#: lib/bds/desktop/shell_live.ex:804
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr "El proyecto al que apunta este blogmark no existe aquí."
@@ -3537,12 +3537,13 @@ msgid "Zoom"
msgstr "Ampliar/reducir"
#: lib/bds/desktop/shell_live/git_run.ex:91
#: lib/bds/desktop/shell_live/git_run.ex:127
#: lib/bds/desktop/shell_live/git_run.ex:129
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#, elixir-autogen, elixir-format
msgid "Close"
msgstr "Cerrar"
#: lib/bds/desktop/shell_live/git_run.ex:124
#: lib/bds/desktop/shell_live/git_run.ex:126
#, elixir-autogen, elixir-format
msgid "Failed (exit %{status})"
msgstr "Error (salida %{status})"
@@ -3566,3 +3567,33 @@ msgstr "git pull"
#, elixir-autogen, elixir-format
msgid "git push"
msgstr "git push"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:159
#, elixir-autogen, elixir-format
msgid "AI settings saved."
msgstr "Configuración de IA guardada."
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:90
#, elixir-autogen, elixir-format
msgid "Could not load models"
msgstr "No se pudieron cargar los modelos"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:187
#, elixir-autogen, elixir-format
msgid "Could not save AI settings"
msgstr "No se pudo guardar la configuración de IA"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:182
#, elixir-autogen, elixir-format
msgid "Loaded %{count} models."
msgstr "%{count} modelos cargados."
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:201
#, elixir-autogen, elixir-format
msgid "OK"
msgstr "OK"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:173
#, elixir-autogen, elixir-format
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr "El endpoint no devolvió ningún modelo. Aún puedes escribir el nombre de un modelo manualmente."

View File

@@ -70,9 +70,9 @@ msgstr "IA"
msgid "AI Assistant"
msgstr "Assistant IA"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:87
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:152
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:167
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:93
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:190
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:208
#, elixir-autogen, elixir-format
msgid "AI Settings"
msgstr "Paramètres IA"
@@ -336,7 +336,7 @@ msgstr "Auteur"
msgid "Auto"
msgstr "Automatique"
#: lib/bds/desktop/shell_live.ex:442
#: lib/bds/desktop/shell_live.ex:448
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -418,7 +418,7 @@ msgstr "Catégorie de blogmark"
msgid "Bookmarklet copy support is wired through the desktop runtime and project public URL."
msgstr "La copie du bookmarklet est reliée via lenvironnement desktop et lURL publique du projet."
#: lib/bds/desktop/shell_live/git_run.ex:126
#: lib/bds/desktop/shell_live/git_run.ex:128
#: lib/bds/desktop/shell_live/import_editor.ex:1366
#: lib/bds/desktop/shell_live/media_editor_html/media_editor.html.heex:298
#: lib/bds/desktop/shell_live/menu_editor.ex:335
@@ -431,8 +431,8 @@ msgstr "La copie du bookmarklet est reliée via lenvironnement desktop et l
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:165
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:173
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr "Annuler"
@@ -486,7 +486,7 @@ msgstr "Valeurs par défaut des catégories, options de rendu et liaison des mod
msgid "Category name is required"
msgstr "Le nom de la catégorie est requis"
#: lib/bds/desktop/shell_live.ex:748
#: lib/bds/desktop/shell_live.ex:771
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -1052,7 +1052,7 @@ msgstr "Trouver les doublons"
msgid "Force Reload"
msgstr "Recharger de force"
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:194
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:211
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:432
#, elixir-autogen, elixir-format
msgid "Gallery"
@@ -1063,7 +1063,7 @@ msgstr "Galerie"
msgid "Generate Site"
msgstr "Générer le site"
#: lib/bds/desktop/shell_live.ex:749
#: lib/bds/desktop/shell_live.ex:772
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/ui/sidebar.ex:789
#, elixir-autogen, elixir-format
@@ -1077,7 +1077,7 @@ msgid "Git Diff"
msgstr "Diff Git"
#: lib/bds/desktop/shell_data.ex:226
#: lib/bds/desktop/shell_live.ex:745
#: lib/bds/desktop/shell_live.ex:768
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#, elixir-autogen, elixir-format
msgid "Git Log"
@@ -1200,9 +1200,9 @@ msgstr "Définitions dimport"
msgid "Import failed: %{error}"
msgstr "Échec de limport : %{error}"
#: lib/bds/desktop/shell_live.ex:592
#: lib/bds/desktop/shell_live.ex:861
#: lib/bds/desktop/shell_live.ex:867
#: lib/bds/desktop/shell_live.ex:598
#: lib/bds/desktop/shell_live.ex:884
#: lib/bds/desktop/shell_live.ex:890
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1784,7 +1784,7 @@ msgstr "Autre"
msgid "Other (%{count})"
msgstr "Autres (%{count})"
#: lib/bds/desktop/shell_live.ex:744
#: lib/bds/desktop/shell_live.ex:767
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#, elixir-autogen, elixir-format
msgid "Output"
@@ -2538,7 +2538,7 @@ msgstr "Nom du mot-clé"
msgid "Tags"
msgstr "Tags"
#: lib/bds/desktop/shell_live.ex:743
#: lib/bds/desktop/shell_live.ex:766
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -3218,12 +3218,12 @@ msgstr "Bienvenue dans lassistant IA"
msgid "Comparing database and filesystem metadata"
msgstr "Comparaison des métadonnées entre la base et le système de fichiers"
#: lib/bds/desktop/shell_live.ex:668
#: lib/bds/desktop/shell_live.ex:674
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr "%{count} images ajoutées à l'article"
#: lib/bds/desktop/shell_live.ex:636
#: lib/bds/desktop/shell_live.ex:642
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr "%{title} ajouté"
@@ -3243,18 +3243,18 @@ msgstr "Guide utilisateur pour les flux éditoriaux, médias, modèles, traducti
msgid "Image Import Concurrency"
msgstr "Importation simultanée d'images"
#: lib/bds/desktop/shell_live.ex:441
#: lib/bds/desktop/shell_live.ex:454
#: lib/bds/desktop/shell_live.ex:635
#: lib/bds/desktop/shell_live.ex:667
#: lib/bds/desktop/shell_live.ex:678
#: lib/bds/desktop/shell_live.ex:689
#: lib/bds/desktop/shell_live.ex:447
#: lib/bds/desktop/shell_live.ex:460
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:673
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:695
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr "Ajouter des images à la galerie"
#: lib/bds/desktop/shell_live.ex:690
#: lib/bds/desktop/shell_live.ex:696
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr "Impossible de traiter %{path} : %{reason}"
@@ -3353,7 +3353,7 @@ msgid "Local only"
msgstr "Local uniquement"
#: lib/bds/desktop/shell_live/git_handler.ex:113
#: lib/bds/desktop/shell_live/git_run.ex:82
#: lib/bds/desktop/shell_live/git_run.ex:83
#, elixir-autogen, elixir-format
msgid "No active project"
msgstr "Aucun projet actif"
@@ -3445,12 +3445,12 @@ msgstr "renommé"
msgid "untracked"
msgstr "non suivi"
#: lib/bds/desktop/shell_live.ex:769
#: lib/bds/desktop/shell_live.ex:792
#, elixir-autogen, elixir-format
msgid "Blogmark"
msgstr "Blogmark"
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:835
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr "Ouvrez un projet avant dimporter un blogmark."
@@ -3491,7 +3491,7 @@ msgstr "Supprimer"
msgid "Failed to copy bookmarklet to clipboard"
msgstr "Échec de la copie du bookmarklet dans le presse-papiers"
#: lib/bds/desktop/shell_live.ex:781
#: lib/bds/desktop/shell_live.ex:804
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr "Le projet ciblé par ce blogmark n'existe pas ici."
@@ -3537,12 +3537,13 @@ msgid "Zoom"
msgstr "Réduire/agrandir"
#: lib/bds/desktop/shell_live/git_run.ex:91
#: lib/bds/desktop/shell_live/git_run.ex:127
#: lib/bds/desktop/shell_live/git_run.ex:129
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#, elixir-autogen, elixir-format
msgid "Close"
msgstr "Fermer"
#: lib/bds/desktop/shell_live/git_run.ex:124
#: lib/bds/desktop/shell_live/git_run.ex:126
#, elixir-autogen, elixir-format
msgid "Failed (exit %{status})"
msgstr "Échec (code %{status})"
@@ -3566,3 +3567,33 @@ msgstr "git pull"
#, elixir-autogen, elixir-format
msgid "git push"
msgstr "git push"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:159
#, elixir-autogen, elixir-format
msgid "AI settings saved."
msgstr "Paramètres IA enregistrés."
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:90
#, elixir-autogen, elixir-format
msgid "Could not load models"
msgstr "Impossible de charger les modèles"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:187
#, elixir-autogen, elixir-format
msgid "Could not save AI settings"
msgstr "Impossible d'enregistrer les paramètres IA"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:182
#, elixir-autogen, elixir-format
msgid "Loaded %{count} models."
msgstr "%{count} modèles chargés."
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:201
#, elixir-autogen, elixir-format
msgid "OK"
msgstr "OK"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:173
#, elixir-autogen, elixir-format
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr "Le point de terminaison n'a renvoyé aucun modèle. Vous pouvez toujours saisir un nom de modèle manuellement."

View File

@@ -70,9 +70,9 @@ msgstr "IA"
msgid "AI Assistant"
msgstr "Assistente IA"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:87
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:152
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:167
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:93
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:190
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:208
#, elixir-autogen, elixir-format
msgid "AI Settings"
msgstr "Impostazioni IA"
@@ -336,7 +336,7 @@ msgstr "Autore"
msgid "Auto"
msgstr "Automatico"
#: lib/bds/desktop/shell_live.ex:442
#: lib/bds/desktop/shell_live.ex:448
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -418,7 +418,7 @@ msgstr "Categoria blogmark"
msgid "Bookmarklet copy support is wired through the desktop runtime and project public URL."
msgstr "La copia del bookmarklet è collegata tramite il runtime desktop e lURL pubblica del progetto."
#: lib/bds/desktop/shell_live/git_run.ex:126
#: lib/bds/desktop/shell_live/git_run.ex:128
#: lib/bds/desktop/shell_live/import_editor.ex:1366
#: lib/bds/desktop/shell_live/media_editor_html/media_editor.html.heex:298
#: lib/bds/desktop/shell_live/menu_editor.ex:335
@@ -431,8 +431,8 @@ msgstr "La copia del bookmarklet è collegata tramite il runtime desktop e lU
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:165
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:173
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr "Annulla"
@@ -486,7 +486,7 @@ msgstr "Valori predefiniti delle categorie, opzioni di rendering e collegamento
msgid "Category name is required"
msgstr "Il nome della categoria è obbligatorio"
#: lib/bds/desktop/shell_live.ex:748
#: lib/bds/desktop/shell_live.ex:771
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -1052,7 +1052,7 @@ msgstr "Trova duplicati"
msgid "Force Reload"
msgstr "Ricarica forzata"
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:194
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:211
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:432
#, elixir-autogen, elixir-format
msgid "Gallery"
@@ -1063,7 +1063,7 @@ msgstr "Galleria"
msgid "Generate Site"
msgstr "Genera sito"
#: lib/bds/desktop/shell_live.ex:749
#: lib/bds/desktop/shell_live.ex:772
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/ui/sidebar.ex:789
#, elixir-autogen, elixir-format
@@ -1077,7 +1077,7 @@ msgid "Git Diff"
msgstr "Diff Git"
#: lib/bds/desktop/shell_data.ex:226
#: lib/bds/desktop/shell_live.ex:745
#: lib/bds/desktop/shell_live.ex:768
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#, elixir-autogen, elixir-format
msgid "Git Log"
@@ -1200,9 +1200,9 @@ msgstr "Definizioni di importazione"
msgid "Import failed: %{error}"
msgstr "Importazione non riuscita: %{error}"
#: lib/bds/desktop/shell_live.ex:592
#: lib/bds/desktop/shell_live.ex:861
#: lib/bds/desktop/shell_live.ex:867
#: lib/bds/desktop/shell_live.ex:598
#: lib/bds/desktop/shell_live.ex:884
#: lib/bds/desktop/shell_live.ex:890
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1784,7 +1784,7 @@ msgstr "Altro"
msgid "Other (%{count})"
msgstr "Altro (%{count})"
#: lib/bds/desktop/shell_live.ex:744
#: lib/bds/desktop/shell_live.ex:767
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#, elixir-autogen, elixir-format
msgid "Output"
@@ -2538,7 +2538,7 @@ msgstr "Nome del tag"
msgid "Tags"
msgstr "Tag"
#: lib/bds/desktop/shell_live.ex:743
#: lib/bds/desktop/shell_live.ex:766
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -3218,12 +3218,12 @@ msgstr "Benvenuto nellassistente IA"
msgid "Comparing database and filesystem metadata"
msgstr "Confronto tra i metadati del database e del filesystem"
#: lib/bds/desktop/shell_live.ex:668
#: lib/bds/desktop/shell_live.ex:674
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr "%{count} immagini aggiunte al post"
#: lib/bds/desktop/shell_live.ex:636
#: lib/bds/desktop/shell_live.ex:642
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr "%{title} aggiunto"
@@ -3243,18 +3243,18 @@ msgstr "Guida per l'utente finale per flussi editoriali, media, modelli, traduzi
msgid "Image Import Concurrency"
msgstr "Importazione simultanea immagini"
#: lib/bds/desktop/shell_live.ex:441
#: lib/bds/desktop/shell_live.ex:454
#: lib/bds/desktop/shell_live.ex:635
#: lib/bds/desktop/shell_live.ex:667
#: lib/bds/desktop/shell_live.ex:678
#: lib/bds/desktop/shell_live.ex:689
#: lib/bds/desktop/shell_live.ex:447
#: lib/bds/desktop/shell_live.ex:460
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:673
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:695
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr "Aggiungi immagini alla galleria"
#: lib/bds/desktop/shell_live.ex:690
#: lib/bds/desktop/shell_live.ex:696
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr "Impossibile elaborare %{path}: %{reason}"
@@ -3353,7 +3353,7 @@ msgid "Local only"
msgstr "Solo locale"
#: lib/bds/desktop/shell_live/git_handler.ex:113
#: lib/bds/desktop/shell_live/git_run.ex:82
#: lib/bds/desktop/shell_live/git_run.ex:83
#, elixir-autogen, elixir-format
msgid "No active project"
msgstr "Nessun progetto attivo"
@@ -3445,12 +3445,12 @@ msgstr "rinominato"
msgid "untracked"
msgstr "non tracciato"
#: lib/bds/desktop/shell_live.ex:769
#: lib/bds/desktop/shell_live.ex:792
#, elixir-autogen, elixir-format
msgid "Blogmark"
msgstr "Blogmark"
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:835
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr "Apri un progetto prima di importare un blogmark."
@@ -3491,7 +3491,7 @@ msgstr "Elimina"
msgid "Failed to copy bookmarklet to clipboard"
msgstr "Impossibile copiare il bookmarklet negli appunti"
#: lib/bds/desktop/shell_live.ex:781
#: lib/bds/desktop/shell_live.ex:804
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr "Il progetto a cui punta questo blogmark non esiste qui."
@@ -3537,12 +3537,13 @@ msgid "Zoom"
msgstr "Riduci/ingrandisci"
#: lib/bds/desktop/shell_live/git_run.ex:91
#: lib/bds/desktop/shell_live/git_run.ex:127
#: lib/bds/desktop/shell_live/git_run.ex:129
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#, elixir-autogen, elixir-format
msgid "Close"
msgstr "Chiudi"
#: lib/bds/desktop/shell_live/git_run.ex:124
#: lib/bds/desktop/shell_live/git_run.ex:126
#, elixir-autogen, elixir-format
msgid "Failed (exit %{status})"
msgstr "Non riuscito (uscita %{status})"
@@ -3566,3 +3567,33 @@ msgstr "git pull"
#, elixir-autogen, elixir-format
msgid "git push"
msgstr "git push"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:159
#, elixir-autogen, elixir-format
msgid "AI settings saved."
msgstr "Impostazioni IA salvate."
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:90
#, elixir-autogen, elixir-format
msgid "Could not load models"
msgstr "Impossibile caricare i modelli"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:187
#, elixir-autogen, elixir-format
msgid "Could not save AI settings"
msgstr "Impossibile salvare le impostazioni IA"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:182
#, elixir-autogen, elixir-format
msgid "Loaded %{count} models."
msgstr "Caricati %{count} modelli."
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:201
#, elixir-autogen, elixir-format
msgid "OK"
msgstr "OK"
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:173
#, elixir-autogen, elixir-format
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr "L'endpoint non ha restituito alcun modello. Puoi comunque digitare manualmente il nome di un modello."

View File

@@ -83,9 +83,9 @@ msgstr ""
msgid "AI Assistant"
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:87
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:152
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:167
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:93
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:190
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:208
#, elixir-autogen, elixir-format
msgid "AI Settings"
msgstr ""
@@ -349,7 +349,7 @@ msgstr ""
msgid "Auto"
msgstr ""
#: lib/bds/desktop/shell_live.ex:442
#: lib/bds/desktop/shell_live.ex:448
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -431,7 +431,7 @@ msgstr ""
msgid "Bookmarklet copy support is wired through the desktop runtime and project public URL."
msgstr ""
#: lib/bds/desktop/shell_live/git_run.ex:126
#: lib/bds/desktop/shell_live/git_run.ex:128
#: lib/bds/desktop/shell_live/import_editor.ex:1366
#: lib/bds/desktop/shell_live/media_editor_html/media_editor.html.heex:298
#: lib/bds/desktop/shell_live/menu_editor.ex:335
@@ -444,8 +444,8 @@ msgstr ""
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:165
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:173
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr ""
@@ -499,7 +499,7 @@ msgstr ""
msgid "Category name is required"
msgstr ""
#: lib/bds/desktop/shell_live.ex:748
#: lib/bds/desktop/shell_live.ex:771
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -1065,7 +1065,7 @@ msgstr ""
msgid "Force Reload"
msgstr ""
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:194
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:211
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:432
#, elixir-autogen, elixir-format
msgid "Gallery"
@@ -1076,7 +1076,7 @@ msgstr ""
msgid "Generate Site"
msgstr ""
#: lib/bds/desktop/shell_live.ex:749
#: lib/bds/desktop/shell_live.ex:772
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/ui/sidebar.ex:789
#, elixir-autogen, elixir-format
@@ -1090,7 +1090,7 @@ msgid "Git Diff"
msgstr ""
#: lib/bds/desktop/shell_data.ex:226
#: lib/bds/desktop/shell_live.ex:745
#: lib/bds/desktop/shell_live.ex:768
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#, elixir-autogen, elixir-format
msgid "Git Log"
@@ -1213,9 +1213,9 @@ msgstr ""
msgid "Import failed: %{error}"
msgstr ""
#: lib/bds/desktop/shell_live.ex:592
#: lib/bds/desktop/shell_live.ex:861
#: lib/bds/desktop/shell_live.ex:867
#: lib/bds/desktop/shell_live.ex:598
#: lib/bds/desktop/shell_live.ex:884
#: lib/bds/desktop/shell_live.ex:890
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1797,7 +1797,7 @@ msgstr ""
msgid "Other (%{count})"
msgstr ""
#: lib/bds/desktop/shell_live.ex:744
#: lib/bds/desktop/shell_live.ex:767
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#, elixir-autogen, elixir-format
msgid "Output"
@@ -2551,7 +2551,7 @@ msgstr ""
msgid "Tags"
msgstr ""
#: lib/bds/desktop/shell_live.ex:743
#: lib/bds/desktop/shell_live.ex:766
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -3231,12 +3231,12 @@ msgstr ""
msgid "Comparing database and filesystem metadata"
msgstr ""
#: lib/bds/desktop/shell_live.ex:668
#: lib/bds/desktop/shell_live.ex:674
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr ""
#: lib/bds/desktop/shell_live.ex:636
#: lib/bds/desktop/shell_live.ex:642
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr ""
@@ -3256,18 +3256,18 @@ msgstr ""
msgid "Image Import Concurrency"
msgstr ""
#: lib/bds/desktop/shell_live.ex:441
#: lib/bds/desktop/shell_live.ex:454
#: lib/bds/desktop/shell_live.ex:635
#: lib/bds/desktop/shell_live.ex:667
#: lib/bds/desktop/shell_live.ex:678
#: lib/bds/desktop/shell_live.ex:689
#: lib/bds/desktop/shell_live.ex:447
#: lib/bds/desktop/shell_live.ex:460
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:673
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:695
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr ""
#: lib/bds/desktop/shell_live.ex:690
#: lib/bds/desktop/shell_live.ex:696
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr ""
@@ -3366,7 +3366,7 @@ msgid "Local only"
msgstr ""
#: lib/bds/desktop/shell_live/git_handler.ex:113
#: lib/bds/desktop/shell_live/git_run.ex:82
#: lib/bds/desktop/shell_live/git_run.ex:83
#, elixir-autogen, elixir-format
msgid "No active project"
msgstr ""
@@ -3458,12 +3458,12 @@ msgstr ""
msgid "untracked"
msgstr ""
#: lib/bds/desktop/shell_live.ex:769
#: lib/bds/desktop/shell_live.ex:792
#, elixir-autogen, elixir-format
msgid "Blogmark"
msgstr ""
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:835
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr ""
@@ -3504,7 +3504,7 @@ msgstr ""
msgid "Failed to copy bookmarklet to clipboard"
msgstr ""
#: lib/bds/desktop/shell_live.ex:781
#: lib/bds/desktop/shell_live.ex:804
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr ""
@@ -3550,12 +3550,13 @@ msgid "Zoom"
msgstr ""
#: lib/bds/desktop/shell_live/git_run.ex:91
#: lib/bds/desktop/shell_live/git_run.ex:127
#: lib/bds/desktop/shell_live/git_run.ex:129
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:191
#, elixir-autogen, elixir-format
msgid "Close"
msgstr ""
#: lib/bds/desktop/shell_live/git_run.ex:124
#: lib/bds/desktop/shell_live/git_run.ex:126
#, elixir-autogen, elixir-format
msgid "Failed (exit %{status})"
msgstr ""
@@ -3579,3 +3580,33 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "git push"
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:159
#, elixir-autogen, elixir-format
msgid "AI settings saved."
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:90
#, elixir-autogen, elixir-format
msgid "Could not load models"
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:187
#, elixir-autogen, elixir-format
msgid "Could not save AI settings"
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:182
#, elixir-autogen, elixir-format
msgid "Loaded %{count} models."
msgstr ""
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:201
#, elixir-autogen, elixir-format
msgid "OK"
msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/ai_settings.ex:173
#, elixir-autogen, elixir-format
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr ""

View File

@@ -6,6 +6,12 @@
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
monospace;
--color-red-100: oklch(93.6% 0.032 17.717);
--color-red-200: oklch(88.5% 0.062 18.334);
--color-red-300: oklch(80.8% 0.114 19.571);
--color-red-700: oklch(50.5% 0.213 27.518);
--color-black: #000;
--color-white: #fff;
--spacing: 0.25rem;
--container-xs: 20rem;
--container-2xl: 42rem;
@@ -13,7 +19,15 @@
--text-xs--line-height: calc(1 / 0.75);
--text-sm: 0.875rem;
--text-sm--line-height: calc(1.25 / 0.875);
--font-weight-semibold: 600;
--tracking-wide: 0.025em;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--ease-in: cubic-bezier(0.4, 0, 1, 1);
--ease-out: cubic-bezier(0, 0, 0.2, 1);
--animate-spin: spin 1s linear infinite;
--default-transition-duration: 150ms;
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
--default-font-family: var(--font-sans);
--default-mono-font-family: var(--font-mono);
}
@@ -167,33 +181,105 @@
}
}
@layer utilities {
.pointer-events-auto {
pointer-events: auto;
}
.pointer-events-none {
pointer-events: none;
}
.visible {
visibility: visible;
}
.absolute {
position: absolute;
}
.fixed {
position: fixed;
}
.relative {
position: relative;
}
.static {
position: static;
}
.top-0 {
top: calc(var(--spacing) * 0);
}
.top-\[5px\] {
top: 5px;
}
.top-full {
top: 100%;
}
.right-0 {
right: calc(var(--spacing) * 0);
}
.right-\[5px\] {
right: 5px;
}
.bottom-0 {
bottom: calc(var(--spacing) * 0);
}
.left-0 {
left: calc(var(--spacing) * 0);
}
.left-1\/2 {
left: calc(1/2 * 100%);
}
.z-10 {
z-index: 10;
}
.z-50 {
z-index: 50;
}
.z-100 {
z-index: 100;
}
.col-start-1 {
grid-column-start: 1;
}
.col-end-1 {
grid-column-end: 1;
}
.row-start-1 {
grid-row-start: 1;
}
.row-end-2 {
grid-row-end: 2;
}
.container {
width: 100%;
@media (width >= 40rem) {
max-width: 40rem;
}
@media (width >= 48rem) {
max-width: 48rem;
}
@media (width >= 64rem) {
max-width: 64rem;
}
@media (width >= 80rem) {
max-width: 80rem;
}
@media (width >= 96rem) {
max-width: 96rem;
}
}
.mt-2 {
margin-top: calc(var(--spacing) * 2);
}
.mb-2 {
margin-bottom: calc(var(--spacing) * 2);
}
.ml-1 {
margin-left: calc(var(--spacing) * 1);
}
.block {
display: block;
}
.contents {
display: contents;
}
.flex {
display: flex;
}
@@ -206,12 +292,18 @@
.inline {
display: inline;
}
.inline-block {
display: inline-block;
}
.inline-flex {
display: inline-flex;
}
.table {
display: table;
}
.h-3 {
height: calc(var(--spacing) * 3);
}
.h-6 {
height: calc(var(--spacing) * 6);
}
@@ -224,6 +316,9 @@
.h-12 {
height: calc(var(--spacing) * 12);
}
.h-\[14px\] {
height: 14px;
}
.h-\[22px\] {
height: 22px;
}
@@ -236,6 +331,9 @@
.max-h-\[80vh\] {
max-height: 80vh;
}
.max-h-screen {
max-height: 100vh;
}
.min-h-0 {
min-height: calc(var(--spacing) * 0);
}
@@ -245,6 +343,9 @@
.min-h-\[16rem\] {
min-height: 16rem;
}
.w-3 {
width: calc(var(--spacing) * 3);
}
.w-6 {
width: calc(var(--spacing) * 6);
}
@@ -254,6 +355,9 @@
.w-12 {
width: calc(var(--spacing) * 12);
}
.w-\[14px\] {
width: 14px;
}
.w-full {
width: 100%;
}
@@ -287,9 +391,30 @@
.shrink-0 {
flex-shrink: 0;
}
.grow {
flex-grow: 1;
}
.origin-center {
transform-origin: center;
}
.-translate-x-1\/2 {
--tw-translate-x: calc(calc(1/2 * 100%) * -1);
translate: var(--tw-translate-x) var(--tw-translate-y);
}
.translate-y-0 {
--tw-translate-y: calc(var(--spacing) * 0);
translate: var(--tw-translate-x) var(--tw-translate-y);
}
.translate-y-4 {
--tw-translate-y: calc(var(--spacing) * 4);
translate: var(--tw-translate-x) var(--tw-translate-y);
}
.transform {
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
}
.animate-spin {
animation: var(--animate-spin);
}
.resize {
resize: both;
}
@@ -299,6 +424,9 @@
.flex-col {
flex-direction: column;
}
.flex-col-reverse {
flex-direction: column-reverse;
}
.flex-wrap {
flex-wrap: wrap;
}
@@ -358,13 +486,43 @@
.rounded {
border-radius: 0.25rem;
}
.rounded-lg {
border-radius: var(--radius-lg);
}
.rounded-md {
border-radius: var(--radius-md);
}
.border {
border-style: var(--tw-border-style);
border-width: 1px;
}
.\!border-\[\#5a2a2a\] {
border-color: #5a2a2a !important;
}
.border-\[\#3c3c3c\] {
border-color: #3c3c3c;
}
.border-red-200 {
border-color: var(--color-red-200);
}
.\!bg-\[\#3a2020\] {
background-color: #3a2020 !important;
}
.\!bg-red-100 {
background-color: var(--color-red-100) !important;
}
.bg-\[\#2d2d2d\] {
background-color: #2d2d2d;
}
.bg-white {
background-color: var(--color-white);
}
.p-4 {
padding: calc(var(--spacing) * 4);
}
.p-\[5px\] {
padding: 5px;
}
.px-3 {
padding-inline: calc(var(--spacing) * 3);
}
@@ -397,6 +555,18 @@
font-size: var(--text-xs);
line-height: var(--tw-leading, var(--text-xs--line-height));
}
.leading-5 {
--tw-leading: calc(var(--spacing) * 5);
line-height: calc(var(--spacing) * 5);
}
.leading-6 {
--tw-leading: calc(var(--spacing) * 6);
line-height: calc(var(--spacing) * 6);
}
.font-semibold {
--tw-font-weight: var(--font-weight-semibold);
font-weight: var(--font-weight-semibold);
}
.tracking-wide {
--tw-tracking: var(--tracking-wide);
letter-spacing: var(--tracking-wide);
@@ -404,9 +574,40 @@
.whitespace-nowrap {
white-space: nowrap;
}
.\!text-red-300 {
color: var(--color-red-300) !important;
}
.\!text-red-700 {
color: var(--color-red-700) !important;
}
.text-\[\#f0f0f0\] {
color: #f0f0f0;
}
.text-black {
color: var(--color-black);
}
.text-black\/50 {
color: color-mix(in srgb, #000 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
color: color-mix(in oklab, var(--color-black) 50%, transparent);
}
}
.uppercase {
text-transform: uppercase;
}
.opacity-0 {
opacity: 0%;
}
.opacity-40 {
opacity: 40%;
}
.opacity-100 {
opacity: 100%;
}
.shadow-lg {
--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.outline {
outline-style: var(--tw-outline-style);
outline-width: 1px;
@@ -419,6 +620,117 @@
--tw-invert: invert(100%);
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
.transition {
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
.transition-all {
transition-property: all;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
.transition-opacity {
transition-property: opacity;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
.duration-200 {
--tw-duration: 200ms;
transition-duration: 200ms;
}
.duration-300 {
--tw-duration: 300ms;
transition-duration: 300ms;
}
.ease-in {
--tw-ease: var(--ease-in);
transition-timing-function: var(--ease-in);
}
.ease-out {
--tw-ease: var(--ease-out);
transition-timing-function: var(--ease-out);
}
.group-hover\:opacity-70 {
&:is(:where(.group):hover *) {
@media (hover: hover) {
opacity: 70%;
}
}
}
.group-hover\:opacity-100 {
&:is(:where(.group):hover *) {
@media (hover: hover) {
opacity: 100%;
}
}
}
.group-has-\[\[data-part\=\'title\'\]\]\/toast\:absolute {
&:is(:where(.group\/toast):has(*:is([data-part='title'])) *) {
position: absolute;
}
}
.hover\:text-black {
&:hover {
@media (hover: hover) {
color: var(--color-black);
}
}
}
.focus\:opacity-100 {
&:focus {
opacity: 100%;
}
}
.focus\:ring-1 {
&:focus {
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
}
.focus\:outline-none {
&:focus {
--tw-outline-style: none;
outline-style: none;
}
}
.sm\:top-auto {
@media (width >= 40rem) {
top: auto;
}
}
.sm\:bottom-auto {
@media (width >= 40rem) {
bottom: auto;
}
}
.sm\:translate-y-0 {
@media (width >= 40rem) {
--tw-translate-y: calc(var(--spacing) * 0);
translate: var(--tw-translate-x) var(--tw-translate-y);
}
}
.sm\:scale-95 {
@media (width >= 40rem) {
--tw-scale-x: 95%;
--tw-scale-y: 95%;
--tw-scale-z: 95%;
scale: var(--tw-scale-x) var(--tw-scale-y);
}
}
.sm\:scale-100 {
@media (width >= 40rem) {
--tw-scale-x: 100%;
--tw-scale-y: 100%;
--tw-scale-z: 100%;
scale: var(--tw-scale-x) var(--tw-scale-y);
}
}
.md\:max-w-\[420px\] {
@media (width >= 48rem) {
max-width: 420px;
}
}
.md\:grid-cols-2 {
@media (width >= 48rem) {
grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -444,6 +756,11 @@
grid-template-columns: minmax(320px,1fr) minmax(0,1.2fr);
}
}
.\[\@media\(scripting\:enabled\)\]\:opacity-0 {
@media (scripting:enabled) {
opacity: 0%;
}
}
}
:root {
--accent-color: #007acc;
@@ -4744,6 +5061,9 @@ button svg, button svg * {
padding: 14px 20px;
font: inherit;
}
.alert-modal-error {
border-top: 3px solid #ff6b6b;
}
.menu-editor-header h2 {
margin: 0;
}
@@ -6492,6 +6812,21 @@ button.import-taxonomy-pill {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
}
}
@property --tw-translate-x {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-translate-y {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-translate-z {
syntax: "*";
inherits: false;
initial-value: 0;
}
@property --tw-rotate-x {
syntax: "*";
inherits: false;
@@ -6517,10 +6852,83 @@ button.import-taxonomy-pill {
inherits: false;
initial-value: solid;
}
@property --tw-leading {
syntax: "*";
inherits: false;
}
@property --tw-font-weight {
syntax: "*";
inherits: false;
}
@property --tw-tracking {
syntax: "*";
inherits: false;
}
@property --tw-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-shadow-color {
syntax: "*";
inherits: false;
}
@property --tw-shadow-alpha {
syntax: "<percentage>";
inherits: false;
initial-value: 100%;
}
@property --tw-inset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-shadow-color {
syntax: "*";
inherits: false;
}
@property --tw-inset-shadow-alpha {
syntax: "<percentage>";
inherits: false;
initial-value: 100%;
}
@property --tw-ring-color {
syntax: "*";
inherits: false;
}
@property --tw-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-inset-ring-color {
syntax: "*";
inherits: false;
}
@property --tw-inset-ring-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-ring-inset {
syntax: "*";
inherits: false;
}
@property --tw-ring-offset-width {
syntax: "<length>";
inherits: false;
initial-value: 0px;
}
@property --tw-ring-offset-color {
syntax: "*";
inherits: false;
initial-value: #fff;
}
@property --tw-ring-offset-shadow {
syntax: "*";
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-outline-style {
syntax: "*";
inherits: false;
@@ -6579,6 +6987,29 @@ button.import-taxonomy-pill {
syntax: "*";
inherits: false;
}
@property --tw-duration {
syntax: "*";
inherits: false;
}
@property --tw-ease {
syntax: "*";
inherits: false;
}
@property --tw-scale-x {
syntax: "*";
inherits: false;
initial-value: 1;
}
@property --tw-scale-y {
syntax: "*";
inherits: false;
initial-value: 1;
}
@property --tw-scale-z {
syntax: "*";
inherits: false;
initial-value: 1;
}
@keyframes spin {
to {
transform: rotate(360deg);
@@ -6587,13 +7018,32 @@ button.import-taxonomy-pill {
@layer properties {
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
*, ::before, ::after, ::backdrop {
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-translate-z: 0;
--tw-rotate-x: initial;
--tw-rotate-y: initial;
--tw-rotate-z: initial;
--tw-skew-x: initial;
--tw-skew-y: initial;
--tw-border-style: solid;
--tw-leading: initial;
--tw-font-weight: initial;
--tw-tracking: initial;
--tw-shadow: 0 0 #0000;
--tw-shadow-color: initial;
--tw-shadow-alpha: 100%;
--tw-inset-shadow: 0 0 #0000;
--tw-inset-shadow-color: initial;
--tw-inset-shadow-alpha: 100%;
--tw-ring-color: initial;
--tw-ring-shadow: 0 0 #0000;
--tw-inset-ring-color: initial;
--tw-inset-ring-shadow: 0 0 #0000;
--tw-ring-inset: initial;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-offset-shadow: 0 0 #0000;
--tw-outline-style: solid;
--tw-blur: initial;
--tw-brightness: initial;
@@ -6608,6 +7058,11 @@ button.import-taxonomy-pill {
--tw-drop-shadow-color: initial;
--tw-drop-shadow-alpha: 100%;
--tw-drop-shadow-size: initial;
--tw-duration: initial;
--tw-ease: initial;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-scale-z: 1;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -385,6 +385,28 @@ defmodule BDS.AITest do
assert Repo.get(Setting, "__encrypted_ai.online.api_key") == nil
end
test "put_endpoint clears fields on nil instead of crashing" do
assert {:ok, _endpoint} =
BDS.AI.put_endpoint(
:online,
%{url: "https://api.example.test/v1", api_key: "secret", model: "gpt-4o-mini"},
secret_backend: FakeSecretBackend
)
# A partial config (blank URL/model) must not raise — it clears those keys.
assert {:ok, endpoint} =
BDS.AI.put_endpoint(
:online,
%{url: nil, api_key: nil, model: nil},
secret_backend: FakeSecretBackend
)
assert endpoint.url == nil
assert Repo.get(Setting, "ai.online.url") == nil
assert Repo.get(Setting, "ai.online.model") == nil
assert Repo.get(Setting, "__encrypted_ai.online.api_key") == nil
end
test "airplane_endpoint_configured? reflects the airplane endpoint url and model" do
refute BDS.AI.airplane_endpoint_configured?()

View File

@@ -2085,6 +2085,50 @@ defmodule BDS.Desktop.ShellLiveTest do
BDS.AI.Catalog.model_capabilities("llama3.3")
end
test "saving ai settings without editing preserves stored endpoints" do
assert {:ok, _online} =
AI.put_endpoint(:online, %{
url: "https://api.example.test/v1",
api_key: "keep-me",
model: "gpt-4.1"
})
assert {:ok, _airplane} =
AI.put_endpoint(:airplane, %{
url: "http://localhost:11434/v1",
api_key: nil,
model: "llama3.3"
})
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
_html =
view
|> element("[data-testid='activity-button'][data-view='settings']")
|> render_click()
_html =
view
|> element("[data-testid='sidebar-open-item'][data-item-id='settings-project']")
|> render_click()
# Save with an untouched form (no change_settings_ai). The endpoints must
# survive instead of being wiped by an empty draft.
_html =
view
|> element("#settings-editor-shell button[phx-click='save_settings_ai']")
|> render_click()
assert {:ok, online} = AI.get_endpoint(:online)
assert online.url == "https://api.example.test/v1"
assert online.api_key == "keep-me"
assert online.model == "gpt-4.1"
assert {:ok, airplane} = AI.get_endpoint(:airplane)
assert airplane.url == "http://localhost:11434/v1"
assert airplane.model == "llama3.3"
end
test "ai settings refresh models from the configured endpoints" do
Application.put_env(:bds, :ai_http_client, FakeEndpointModelHttpClient)