From c3edc3cc56aa86fdff4b678a2fb814aeb254acd2 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 21:48:01 +0100 Subject: [PATCH 01/27] Create i18n.ts --- src/i18n/i18n.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/i18n/i18n.ts diff --git a/src/i18n/i18n.ts b/src/i18n/i18n.ts new file mode 100644 index 00000000..1356ecfd --- /dev/null +++ b/src/i18n/i18n.ts @@ -0,0 +1,15 @@ +import { moment } from "obsidian"; +import en from "./locales/en.json"; +import fr from "./locales/fr.json"; + +const locales: { [key: string]: any } = { en, fr }; + +export function t(path: string): string { + const lang = moment.locale(); + const locale = locales[lang] || locales.en; + + // Permet d'accéder aux objets imbriqués (ex: "settings.headers.choices") + const value = path.split('.').reduce((obj, key) => obj?.[key], locale); + + return value || path; +} From d0e267da80ab047a38c0049b0ce18c9094e6b385 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 21:51:26 +0100 Subject: [PATCH 02/27] Create en.json --- src/i18n/locales/en.json | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/i18n/locales/en.json diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json new file mode 100644 index 00000000..ca2c3268 --- /dev/null +++ b/src/i18n/locales/en.json @@ -0,0 +1,34 @@ +{ + "commands": { + "run": "Run QuickAdd", + "reload": "Reload QuickAdd (dev)", + "test": "Test QuickAdd (dev)" + }, + "settings": { + "headers": { + "choices": "Choices & Packages", + "input": "Input", + "templates": "Templates & Properties", + "notifications": "Notifications", + "globals": "Global Variables", + "ai_online": "AI & Online", + "appearance": "Appearance", + "dev": "Developer" + }, + "packages": { + "name": "Packages", + "desc": "Bundle or import QuickAdd automations as reusable packages.", + "export": "Export package…", + "import": "Import package…" + }, + "announce": { + "name": "Announce Updates", + "desc": "Display release notes when a new version is installed." + } + }, + "builder": { + "open": "Open", + "viewMode": "View Mode", + "location": "File Opening Location" + } +} From cd798894a2536d71433f3760cd3d56b3e915b55c Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 21:51:51 +0100 Subject: [PATCH 03/27] Create fr.json --- src/i18n/locales/fr.json | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/i18n/locales/fr.json diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json new file mode 100644 index 00000000..abb33e5a --- /dev/null +++ b/src/i18n/locales/fr.json @@ -0,0 +1,34 @@ +{ + "commands": { + "run": "Lancer QuickAdd", + "reload": "Recharger QuickAdd (dev)", + "test": "Tester QuickAdd (dev)" + }, + "settings": { + "headers": { + "choices": "Choix & Packages", + "input": "Saisie (Input)", + "templates": "Modèles & Propriétés", + "notifications": "Notifications", + "globals": "Variables Globales", + "ai_online": "IA & En ligne", + "appearance": "Apparence", + "dev": "Développeur" + }, + "packages": { + "name": "Packages", + "desc": "Regroupez ou importez des automatisations QuickAdd sous forme de packages réutilisables.", + "export": "Exporter le package…", + "import": "Importer le package…" + }, + "announce": { + "name": "Annoncer les mises à jour", + "desc": "Affiche les notes de version lors de l'installation d'une nouvelle version." + } + }, + "builder": { + "open": "Ouvrir", + "viewMode": "Mode de vue", + "location": "Emplacement d'ouverture du fichier" + } +} From 68670b91ea8fff44887f45d94b50b69204d06a69 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 21:58:12 +0100 Subject: [PATCH 04/27] Update main.ts --- src/main.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main.ts b/src/main.ts index 8b46800a..904f65ca 100644 --- a/src/main.ts +++ b/src/main.ts @@ -23,6 +23,7 @@ import { CommandType } from "./types/macros/CommandType"; import { InfiniteAIAssistantCommandSettingsModal } from "./gui/MacroGUIs/AIAssistantInfiniteCommandSettingsModal"; import { FieldSuggestionCache } from "./utils/FieldSuggestionCache"; import { isMajorUpdate } from "./utils/semver"; +import { t } from "./i18n/i18n"; // Ajout de l'import // Parameters prefixed with `value-` get used as named values for the executed choice type CaptureValueParameters = { [key in `value-${string}`]?: string }; @@ -59,7 +60,7 @@ export default class QuickAdd extends Plugin { this.addCommand({ id: "runQuickAdd", - name: "Run QuickAdd", + name: t("commands.run"), callback: () => { ChoiceSuggester.Open(this, this.settings.choices); }, @@ -67,7 +68,7 @@ export default class QuickAdd extends Plugin { this.addCommand({ id: "reloadQuickAdd", - name: "Reload QuickAdd (dev)", + name: t("commands.reload"), checkCallback: (checking) => { if (checking) { return this.settings.devMode; @@ -87,7 +88,7 @@ export default class QuickAdd extends Plugin { this.addCommand({ id: "testQuickAdd", - name: "Test QuickAdd (dev)", + name: t("commands.test"), checkCallback: (checking) => { if (checking) { return this.settings.devMode; @@ -150,7 +151,7 @@ export default class QuickAdd extends Plugin { log.register(new ConsoleErrorLogger()).register(new GuiLogger(this)); if (this.settings.enableRibbonIcon) { - this.addRibbonIcon("file-plus", "QuickAdd", () => { + this.addRibbonIcon("file-plus", t("ribbon.icon"), () => { ChoiceSuggester.Open(this, this.settings.choices); }); } From 9d74da8efc55e4bd51c30bb737de024462861341 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:06:29 +0100 Subject: [PATCH 05/27] Update quickAddSettingsTab.ts --- src/quickAddSettingsTab.ts | 49 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/quickAddSettingsTab.ts b/src/quickAddSettingsTab.ts index 711fb1ba..86949da7 100644 --- a/src/quickAddSettingsTab.ts +++ b/src/quickAddSettingsTab.ts @@ -22,6 +22,7 @@ import { formatDateAliasLines, parseDateAliasLines, } from "./utils/dateAliases"; +import { t } from "./i18n/i18n"; type SettingGroupLike = { addSetting(cb: (setting: Setting) => void): void; @@ -50,37 +51,37 @@ export class QuickAddSettingsTab extends PluginSettingTab { const { containerEl } = this; containerEl.empty(); - const choicesGroup = this.createSettingGroup("Choices & Packages"); + const choicesGroup = this.createSettingGroup(t("settings.headers.choices")); this.addChoicesSetting(choicesGroup); this.addPackagesSetting(choicesGroup); - const inputGroup = this.createSettingGroup("Input"); + const inputGroup = this.createSettingGroup(t("settings.headers.input")); this.addUseMultiLineInputPromptSetting(inputGroup); this.addPersistInputPromptDraftsSetting(inputGroup); this.addUseSelectionAsValueSetting(inputGroup); this.addOnePageInputSetting(inputGroup); this.addDateAliasesSetting(inputGroup); - const templatesGroup = this.createSettingGroup("Templates & Properties"); + const templatesGroup = this.createSettingGroup(t("settings.headers.templates")); this.addTemplateFolderPathSetting(templatesGroup); this.addTemplatePropertyTypesSetting(templatesGroup); - const notificationsGroup = this.createSettingGroup("Notifications"); + const notificationsGroup = this.createSettingGroup(t("settings.headers.notifications")); this.addAnnounceUpdatesSetting(notificationsGroup); this.addShowCaptureNotificationSetting(notificationsGroup); this.addShowInputCancellationNotificationSetting(notificationsGroup); - const globalsGroup = this.createSettingGroup("Global Variables"); + const globalsGroup = this.createSettingGroup(t("settings.headers.globals")); this.addGlobalVariablesSetting(globalsGroup); - const onlineGroup = this.createSettingGroup("AI & Online"); + const onlineGroup = this.createSettingGroup(t("settings.headers.ai_online")); this.addDisableOnlineFeaturesSetting(onlineGroup); - const appearanceGroup = this.createSettingGroup("Appearance"); + const appearanceGroup = this.createSettingGroup(t("settings.headers.appearance")); this.addEnableRibbonIconSetting(appearanceGroup); if (__IS_DEV_BUILD__) { - const devGroup = this.createSettingGroup("Developer"); + const devGroup = this.createSettingGroup(t("settings.headers.dev")); this.addDevelopmentInfoSetting(devGroup); } } @@ -216,14 +217,14 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addPackagesSetting(group: SettingGroupLike): void { group.addSetting((setting) => { - setting.setName("Packages"); + setting.setName(t("settings.packages.name")); setting.setDesc( "Bundle or import QuickAdd automations as reusable packages.", ); setting.addButton((button) => button - .setButtonText("Export package…") + .setButtonText(t("settings.packages.export")) .setCta() .onClick(() => { const choicesSnapshot = settingsStore.getState().choices; @@ -237,7 +238,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { ); setting.addButton((button) => - button.setButtonText("Import package…").onClick(() => { + button.setButtonText(t("settings.packages.import")).onClick(() => { const modal = new ImportPackageModal(this.app); modal.open(); }), @@ -247,7 +248,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addAnnounceUpdatesSetting(group: SettingGroupLike) { group.addSetting((setting) => { - setting.setName("Announce Updates"); + setting.setName(t("settings.announce.name")); setting.setDesc( "Display release notes when a new version is installed. This includes new features, demo videos, and bug fixes.", ); @@ -272,7 +273,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addShowCaptureNotificationSetting(group: SettingGroupLike) { group.addSetting((setting) => { - setting.setName("Show Capture Notifications"); + setting.setName(t("settings.capture_notif.name")); setting.setDesc( "Display a notification when content is captured successfully to confirm the operation completed.", ); @@ -287,7 +288,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addShowInputCancellationNotificationSetting(group: SettingGroupLike) { group.addSetting((setting) => { - setting.setName("Show Input Cancellation Notifications"); + setting.setName(t("settings.cancel_notif.name")); setting.setDesc( "Display a notification when an input prompt is cancelled without submitting. Disable this to avoid extra notices when dismissing prompts.", ); @@ -330,14 +331,14 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addUseMultiLineInputPromptSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting - .setName("Use Multi-line Input Prompt") + .setName(t("settings.multiline.name")) .setDesc( "Use multi-line input prompt instead of single-line input prompt", ) .addToggle((toggle) => toggle .setValue(this.plugin.settings.inputPrompt === "multi-line") - .setTooltip("Use multi-line input prompt") + .setTooltip(t("settings.multiline.name")) .onChange((value) => { if (value) { settingsStore.setState({ @@ -356,7 +357,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addPersistInputPromptDraftsSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting - .setName("Persist Input Prompt Drafts") + .setName(t("settings.persist.name")) .setDesc( "Keep drafts when closing input prompts so they can be restored on reopen. Drafts are stored only for this session.", ) @@ -376,7 +377,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addUseSelectionAsValueSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting - .setName("Use editor selection as default Capture value") + .setName(t("settings.selection_capture.name")) .setDesc( "When enabled, Capture uses the current editor selection as {{VALUE}} and may skip the prompt. When disabled, Capture always prompts for {{VALUE}}.", ) @@ -392,7 +393,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addTemplateFolderPathSetting(group: SettingGroupLike) { group.addSetting((setting) => { - setting.setName("Template Folder Path"); + setting.setName(t("settings.template_folder.name")); setting.setDesc( "Path to the folder where templates are stored. Used to suggest template files when configuring QuickAdd.", ); @@ -423,7 +424,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addOnePageInputSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting - .setName("One-page input for choices (Beta)") + .setName(t("settings.one_page.name")) .setDesc( "Experimental. Resolve variables up front and show a single dynamic form before executing Template/Capture choices. See Advanced → One-page Inputs in docs.", ) @@ -439,7 +440,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addDateAliasesSetting(group: SettingGroupLike) { group.addSetting((setting) => { - setting.setName("Date aliases"); + setting.setName(t("settings.date_aliases.name")); setting.setDesc( "Shortcodes for natural language date parsing. " + "One per line: alias = phrase. Example: tm = tomorrow.", @@ -475,7 +476,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { setting.addButton((button) => { button - .setButtonText("Reset to defaults") + .setButtonText(t("settings.date_aliases.reset")) .onClick(() => { settingsStore.setState({ dateAliases: DEFAULT_DATE_ALIASES, @@ -495,7 +496,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addDisableOnlineFeaturesSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting - .setName("Disable AI & Online features") + .setName(t("settings.disable_online.name")) .setDesc( "This prevents the plugin from making requests to external providers like OpenAI. You can still use User Scripts to execute arbitrary code, including contacting external providers. However, this setting disables plugin features like the AI Assistant from doing so. You need to disable this setting to use the AI Assistant.", ) @@ -516,7 +517,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addEnableRibbonIconSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting - .setName("Show icon in sidebar") + .setName(t("settings.ribbon.name")) .setDesc( "Add QuickAdd icon to the sidebar ribbon. Requires a reload.", ) From 7057755e3ac1ad3187dc75b9a879403beb1cb37f Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:09:06 +0100 Subject: [PATCH 06/27] Update choiceBuilder.ts --- src/gui/ChoiceBuilder/choiceBuilder.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/gui/ChoiceBuilder/choiceBuilder.ts b/src/gui/ChoiceBuilder/choiceBuilder.ts index 3d31a30e..836590f4 100644 --- a/src/gui/ChoiceBuilder/choiceBuilder.ts +++ b/src/gui/ChoiceBuilder/choiceBuilder.ts @@ -5,6 +5,7 @@ import type IChoice from "../../types/choices/IChoice"; import type { FileViewMode2, OpenLocation } from "../../types/fileOpening"; import GenericInputPrompt from "../GenericInputPrompt/GenericInputPrompt"; import { GenericTextSuggester } from "../suggesters/genericTextSuggester"; +import { t } from "../../i18n/i18n"; export abstract class ChoiceBuilder extends Modal { private resolvePromise: (input: IChoice) => void; @@ -36,7 +37,7 @@ export abstract class ChoiceBuilder extends Modal { protected addOnePageOverrideSetting(choice: IChoice): void { new Setting(this.contentEl) - .setName("One-page input override") + .setName(t("builder.one_page_override")) .setDesc( "Override the global setting for this choice. 'Always' forces the one-page modal even if disabled globally; 'Never' disables it even if enabled globally.", ) @@ -111,7 +112,7 @@ export abstract class ChoiceBuilder extends Modal { if (choice.openFile === undefined) return; // Guard: nothing to configure new Setting(this.contentEl) - .setName("Open") + .setName(t("builder.open")) .setDesc(description) .addToggle((toggle) => { toggle.setValue(choice.openFile); @@ -149,7 +150,7 @@ export abstract class ChoiceBuilder extends Modal { // Location selector new Setting(this.contentEl) - .setName("File Opening Location") + .setName(t("builder.file_opening_location")) .setDesc(`Where to open the ${contextLabel} file`) .addDropdown((dropdown) => { dropdown.addOptions({ @@ -170,7 +171,7 @@ export abstract class ChoiceBuilder extends Modal { // Split direction – only if location === "split" if (fileOpening.location === "split") { new Setting(this.contentEl) - .setName("Split Direction") + .setName(t("builder.split_direction")) .setDesc("Direction for split panes") .addDropdown((dropdown) => { dropdown.addOptions({ @@ -186,7 +187,7 @@ export abstract class ChoiceBuilder extends Modal { // View mode selector new Setting(this.contentEl) - .setName("View Mode") + .setName(t("builder.view_mode")) .setDesc("How to display the opened file") .addDropdown((dropdown) => { dropdown.addOptions({ @@ -208,7 +209,7 @@ export abstract class ChoiceBuilder extends Modal { // Focus toggle – only show for non-reuse locations if (fileOpening.location !== "reuse") { new Setting(this.contentEl) - .setName("Focus new pane") + .setName(t("builder.focus_pane")) .setDesc("Focus the opened tab immediately after opening") .addToggle((toggle) => toggle.setValue(fileOpening.focus).onChange((value) => { From 46d9fa1b6d02b50977bad10f1bd80780e36f3223 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:12:26 +0100 Subject: [PATCH 07/27] Update en.json --- src/i18n/locales/en.json | 95 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index ca2c3268..d1bb133e 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -4,6 +4,9 @@ "reload": "Reload QuickAdd (dev)", "test": "Test QuickAdd (dev)" }, + "ribbon": { + "icon": "QuickAdd" + }, "settings": { "headers": { "choices": "Choices & Packages", @@ -23,12 +26,100 @@ }, "announce": { "name": "Announce Updates", - "desc": "Display release notes when a new version is installed." + "desc": "Display release notes when a new version is installed. This includes new features, demo videos, and bug fixes.", + "all": "Show updates on each new release", + "major": "Show updates only on major releases", + "none": "Don't show" + }, + "capture_notif": { + "name": "Show Capture Notifications", + "desc": "Display a notification when content is captured successfully to confirm the operation completed." + }, + "cancel_notif": { + "name": "Show Input Cancellation Notifications", + "desc": "Display a notification when an input prompt is cancelled without submitting. Disable this to avoid extra notices when dismissing prompts." + }, + "multiline": { + "name": "Use Multi-line Input Prompt", + "desc": "Use multi-line input prompt instead of single-line input prompt." + }, + "persist": { + "name": "Persist Input Prompt Drafts", + "desc": "Keep drafts when closing input prompts so they can be restored on reopen. Drafts are stored only for this session." + }, + "selection_capture": { + "name": "Use editor selection as default Capture value", + "desc": "When enabled, Capture uses the current editor selection as {{VALUE}} and may skip the prompt. When disabled, Capture always prompts for {{VALUE}}." + }, + "template_folder": { + "name": "Template Folder Path", + "desc": "Path to the folder where templates are stored. Used to suggest template files when configuring QuickAdd." + }, + "template_properties": { + "name": "Format template variables as proper property types (Beta)", + "desc": "When enabled, template variables in front matter will be formatted as proper Obsidian property types (Arrays, Numbers, Booleans)." + }, + "one_page": { + "name": "One-page input for choices (Beta)", + "desc": "Experimental. Resolve variables up front and show a single dynamic form before executing Template/Capture choices." + }, + "date_aliases": { + "name": "Date aliases", + "desc": "Shortcodes for natural language date parsing. One per line: alias = phrase. Example: tm = tomorrow.", + "reset": "Reset to defaults" + }, + "disable_online": { + "name": "Disable AI & Online features", + "desc": "Prevents the plugin from making requests to external providers like OpenAI. You need to disable this setting to use the AI Assistant." + }, + "ribbon": { + "name": "Show icon in sidebar", + "desc": "Add QuickAdd icon to the sidebar ribbon. Requires a reload." + }, + "dev": { + "info_name": "Development Information", + "info_desc": "Git information for developers.", + "branch": "Branch", + "commit": "Commit", + "changes": "Uncommitted changes", + "yes": "Yes", + "no": "No" } }, "builder": { "open": "Open", "viewMode": "View Mode", - "location": "File Opening Location" + "location": "File Opening Location", + "one_page_override": { + "name": "One-page input override", + "desc": "Override the global setting for this choice.", + "follow": "Follow global setting", + "always": "Always", + "never": "Never" + }, + "file_path_placeholder": "File path", + "choice_name": "Choice name", + "split_direction": "Split Direction", + "focus_pane": "Focus new pane", + "descriptions": { + "location": "Where to open the file", + "split": "Direction for split panes", + "view_mode": "How to display the opened file", + "focus": "Focus the opened tab immediately after opening" + }, + "options": { + "reuse": "Reuse current tab", + "tab": "New tab", + "split": "Split pane", + "window": "New window", + "left": "Left sidebar", + "right": "Right sidebar", + "source": "Source", + "preview": "Preview", + "live": "Live Preview", + "default": "Default", + "vertical": "Vertical", + "horizontal": "Horizontal" + } } } From 574ab2fa29e3d4ead7ae54ae25b21b0d1eeccb5c Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:12:49 +0100 Subject: [PATCH 08/27] Update fr.json --- src/i18n/locales/fr.json | 95 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index abb33e5a..7d900729 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -4,6 +4,9 @@ "reload": "Recharger QuickAdd (dev)", "test": "Tester QuickAdd (dev)" }, + "ribbon": { + "icon": "QuickAdd" + }, "settings": { "headers": { "choices": "Choix & Packages", @@ -23,12 +26,100 @@ }, "announce": { "name": "Annoncer les mises à jour", - "desc": "Affiche les notes de version lors de l'installation d'une nouvelle version." + "desc": "Affiche les notes de version lors de l'installation d'une nouvelle version (nouvelles fonctionnalités, correctifs, etc).", + "all": "Afficher à chaque nouvelle version", + "major": "Uniquement les versions majeures", + "none": "Ne jamais afficher" + }, + "capture_notif": { + "name": "Notifications de capture", + "desc": "Affiche une notification lorsqu'un contenu est capturé avec succès pour confirmer l'opération." + }, + "cancel_notif": { + "name": "Notifications d'annulation", + "desc": "Affiche une notification lorsqu'une invite de saisie est annulée. Désactivez ceci pour éviter les alertes superflues." + }, + "multiline": { + "name": "Saisie multiligne", + "desc": "Utilise une zone de texte multiligne au lieu d'une ligne simple pour les invites de saisie." + }, + "persist": { + "name": "Conserver les brouillons", + "desc": "Garde les brouillons lors de la fermeture des invites pour les restaurer à la réouverture (pour la session en cours)." + }, + "selection_capture": { + "name": "Utiliser la sélection comme valeur par défaut", + "desc": "Si activé, la capture utilise le texte sélectionné pour {{VALUE}} et peut sauter l'invite. Sinon, la capture demande toujours {{VALUE}}." + }, + "template_folder": { + "name": "Dossier des modèles", + "desc": "Chemin du dossier où sont stockés les modèles. Utilisé pour la suggestion de fichiers lors de la configuration." + }, + "template_properties": { + "name": "Formater les variables comme propriétés (Beta)", + "desc": "Si activé, les variables dans le frontmatter seront formatées selon le type de propriété Obsidian (Listes, Nombres, Cases à cocher)." + }, + "one_page": { + "name": "Saisie sur une page (Beta)", + "desc": "Expérimental. Résout les variables à l'avance et affiche un formulaire unique avant d'exécuter les choix de Modèle/Capture." + }, + "date_aliases": { + "name": "Alias de date", + "desc": "Raccourcis pour l'analyse des dates en langage naturel. Un par ligne : alias = phrase. Exemple : tm = tomorrow.", + "reset": "Réinitialiser" + }, + "disable_online": { + "name": "Désactiver IA & En ligne", + "desc": "Empêche le plugin de faire des requêtes externes (comme OpenAI). Vous devez désactiver cette option pour utiliser l'Assistant IA." + }, + "ribbon": { + "name": "Afficher l'icône latérale", + "desc": "Ajoute l'icône QuickAdd au ruban latéral gauche. Nécessite un rechargement." + }, + "dev": { + "info_name": "Informations de développement", + "info_desc": "Informations Git pour les développeurs.", + "branch": "Branche", + "commit": "Commit", + "changes": "Changements non validés", + "yes": "Oui", + "no": "Non" } }, "builder": { "open": "Ouvrir", "viewMode": "Mode de vue", - "location": "Emplacement d'ouverture du fichier" + "location": "Emplacement d'ouverture", + "one_page_override": { + "name": "Forçage de la saisie sur une page", + "desc": "Remplace le paramètre global pour ce choix.", + "follow": "Suivre le paramètre global", + "always": "Toujours", + "never": "Jamais" + }, + "file_path_placeholder": "Chemin du fichier", + "choice_name": "Nom du choix", + "split_direction": "Direction de la séparation", + "focus_pane": "Focus sur le nouveau panneau", + "descriptions": { + "location": "Où ouvrir le fichier", + "split": "Direction pour les panneaux séparés", + "view_mode": "Comment afficher le fichier ouvert", + "focus": "Mettre le focus sur l'onglet immédiatement après l'ouverture" + }, + "options": { + "reuse": "Réutiliser l'onglet actuel", + "tab": "Nouvel onglet", + "split": "Séparer le panneau", + "window": "Nouvelle fenêtre", + "left": "Barre latérale gauche", + "right": "Barre latérale droite", + "source": "Source", + "preview": "Lecture", + "live": "Live Preview", + "default": "Défaut", + "vertical": "Vertical", + "horizontal": "Horizontal" + } } } From 472a09bbb9c3d68501d5c2580e32b494b6aa23b3 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:13:41 +0100 Subject: [PATCH 09/27] Update quickAddSettingsTab.ts --- src/quickAddSettingsTab.ts | 82 +++++++++++--------------------------- 1 file changed, 24 insertions(+), 58 deletions(-) diff --git a/src/quickAddSettingsTab.ts b/src/quickAddSettingsTab.ts index 86949da7..100d222d 100644 --- a/src/quickAddSettingsTab.ts +++ b/src/quickAddSettingsTab.ts @@ -129,8 +129,8 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addDevelopmentInfoSetting(group: SettingGroupLike) { group.addSetting((setting) => { - setting.setName("Development Information"); - setting.setDesc("Git information for developers."); + setting.setName(t("settings.dev.info_name")); + setting.setDesc(t("settings.dev.info_desc")); const infoContainer = setting.settingEl.createDiv(); infoContainer.style.marginTop = "10px"; @@ -139,25 +139,25 @@ export class QuickAddSettingsTab extends PluginSettingTab { if (__DEV_GIT_BRANCH__ !== null) { const branchDiv = infoContainer.createDiv(); - branchDiv.innerHTML = `Branch: ${__DEV_GIT_BRANCH__}`; + branchDiv.innerHTML = `${t("settings.dev.branch")}: ${__DEV_GIT_BRANCH__}`; branchDiv.style.marginBottom = "5px"; } if (__DEV_GIT_COMMIT__ !== null) { const commitDiv = infoContainer.createDiv(); - commitDiv.innerHTML = `Commit: ${__DEV_GIT_COMMIT__}`; + commitDiv.innerHTML = `${t("settings.dev.commit")}: ${__DEV_GIT_COMMIT__}`; commitDiv.style.marginBottom = "5px"; } if (__DEV_GIT_DIRTY__ !== null) { const statusDiv = infoContainer.createDiv(); const statusText = __DEV_GIT_DIRTY__ - ? "Yes (uncommitted changes)" - : "No"; + ? `${t("settings.dev.yes")} (${t("settings.dev.changes")})` + : t("settings.dev.no"); const statusColor = __DEV_GIT_DIRTY__ ? "var(--text-warning)" : "var(--text-success)"; - statusDiv.innerHTML = `Uncommitted changes: ${statusText}`; + statusDiv.innerHTML = `${t("settings.dev.changes")}: ${statusText}`; } }); } @@ -218,9 +218,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addPackagesSetting(group: SettingGroupLike): void { group.addSetting((setting) => { setting.setName(t("settings.packages.name")); - setting.setDesc( - "Bundle or import QuickAdd automations as reusable packages.", - ); + setting.setDesc(t("settings.packages.desc")); setting.addButton((button) => button @@ -249,18 +247,13 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addAnnounceUpdatesSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting.setName(t("settings.announce.name")); - setting.setDesc( - "Display release notes when a new version is installed. This includes new features, demo videos, and bug fixes.", - ); + setting.setDesc(t("settings.announce.desc")); setting.addDropdown((dropdown) => { const currentValue = settingsStore.getState().announceUpdates; dropdown - .addOption("all", "Show updates on each new release") - .addOption( - "major", - "Show updates only on major releases (new features, breaking changes)", - ) - .addOption("none", "Don't show") + .addOption("all", t("settings.announce.all")) + .addOption("major", t("settings.announce.major")) + .addOption("none", t("settings.announce.none")) .setValue(currentValue) .onChange((value) => { settingsStore.setState({ @@ -274,9 +267,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addShowCaptureNotificationSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting.setName(t("settings.capture_notif.name")); - setting.setDesc( - "Display a notification when content is captured successfully to confirm the operation completed.", - ); + setting.setDesc(t("settings.capture_notif.desc")); setting.addToggle((toggle) => { toggle.setValue(settingsStore.getState().showCaptureNotification); toggle.onChange((value) => { @@ -289,9 +280,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addShowInputCancellationNotificationSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting.setName(t("settings.cancel_notif.name")); - setting.setDesc( - "Display a notification when an input prompt is cancelled without submitting. Disable this to avoid extra notices when dismissing prompts.", - ); + setting.setDesc(t("settings.cancel_notif.desc")); setting.addToggle((toggle) => { toggle.setValue( settingsStore.getState().showInputCancellationNotification, @@ -307,14 +296,8 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addTemplatePropertyTypesSetting(group: SettingGroupLike) { group.addSetting((setting) => { - setting.setName( - "Format template variables as proper property types (Beta)", - ); - setting.setDesc( - "When enabled, template variables in front matter will be formatted as proper Obsidian property types. " + - "Arrays become List properties, numbers become Number properties, booleans become Checkbox properties, etc. " + - "This is a beta feature that may have edge cases.", - ); + setting.setName(t("settings.template_properties.name")); + setting.setDesc(t("settings.template_properties.desc")); setting.addToggle((toggle) => { toggle.setValue(settingsStore.getState().enableTemplatePropertyTypes); toggle.onChange((value) => { @@ -332,9 +315,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { group.addSetting((setting) => { setting .setName(t("settings.multiline.name")) - .setDesc( - "Use multi-line input prompt instead of single-line input prompt", - ) + .setDesc(t("settings.multiline.desc")) .addToggle((toggle) => toggle .setValue(this.plugin.settings.inputPrompt === "multi-line") @@ -358,9 +339,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { group.addSetting((setting) => { setting .setName(t("settings.persist.name")) - .setDesc( - "Keep drafts when closing input prompts so they can be restored on reopen. Drafts are stored only for this session.", - ) + .setDesc(t("settings.persist.desc")) .addToggle((toggle) => toggle .setValue(settingsStore.getState().persistInputPromptDrafts) @@ -378,9 +357,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { group.addSetting((setting) => { setting .setName(t("settings.selection_capture.name")) - .setDesc( - "When enabled, Capture uses the current editor selection as {{VALUE}} and may skip the prompt. When disabled, Capture always prompts for {{VALUE}}.", - ) + .setDesc(t("settings.selection_capture.desc")) .addToggle((toggle) => toggle .setValue(settingsStore.getState().useSelectionAsCaptureValue) @@ -394,9 +371,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addTemplateFolderPathSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting.setName(t("settings.template_folder.name")); - setting.setDesc( - "Path to the folder where templates are stored. Used to suggest template files when configuring QuickAdd.", - ); + setting.setDesc(t("settings.template_folder.desc")); setting.addText((text) => { text @@ -425,9 +400,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { group.addSetting((setting) => { setting .setName(t("settings.one_page.name")) - .setDesc( - "Experimental. Resolve variables up front and show a single dynamic form before executing Template/Capture choices. See Advanced → One-page Inputs in docs.", - ) + .setDesc(t("settings.one_page.desc")) .addToggle((toggle) => toggle .setValue(settingsStore.getState().onePageInputEnabled) @@ -441,10 +414,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addDateAliasesSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting.setName(t("settings.date_aliases.name")); - setting.setDesc( - "Shortcodes for natural language date parsing. " + - "One per line: alias = phrase. Example: tm = tomorrow.", - ); + setting.setDesc(t("settings.date_aliases.desc")); setting.settingEl.style.alignItems = "flex-start"; setting.controlEl.style.display = "flex"; setting.controlEl.style.flexWrap = "wrap"; @@ -497,9 +467,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { group.addSetting((setting) => { setting .setName(t("settings.disable_online.name")) - .setDesc( - "This prevents the plugin from making requests to external providers like OpenAI. You can still use User Scripts to execute arbitrary code, including contacting external providers. However, this setting disables plugin features like the AI Assistant from doing so. You need to disable this setting to use the AI Assistant.", - ) + .setDesc(t("settings.disable_online.desc")) .addToggle((toggle) => toggle .setValue(settingsStore.getState().disableOnlineFeatures) @@ -518,9 +486,7 @@ export class QuickAddSettingsTab extends PluginSettingTab { group.addSetting((setting) => { setting .setName(t("settings.ribbon.name")) - .setDesc( - "Add QuickAdd icon to the sidebar ribbon. Requires a reload.", - ) + .setDesc(t("settings.ribbon.desc")) .addToggle((toggle) => { toggle .setValue(settingsStore.getState().enableRibbonIcon) From 2726430368c90e5be21704ed0f97c47797b9e918 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:14:09 +0100 Subject: [PATCH 10/27] Update choiceBuilder.ts --- src/gui/ChoiceBuilder/choiceBuilder.ts | 52 +++++++++++++------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/src/gui/ChoiceBuilder/choiceBuilder.ts b/src/gui/ChoiceBuilder/choiceBuilder.ts index 836590f4..4d49d988 100644 --- a/src/gui/ChoiceBuilder/choiceBuilder.ts +++ b/src/gui/ChoiceBuilder/choiceBuilder.ts @@ -37,15 +37,13 @@ export abstract class ChoiceBuilder extends Modal { protected addOnePageOverrideSetting(choice: IChoice): void { new Setting(this.contentEl) - .setName(t("builder.one_page_override")) - .setDesc( - "Override the global setting for this choice. 'Always' forces the one-page modal even if disabled globally; 'Never' disables it even if enabled globally.", - ) + .setName(t("builder.one_page_override.name")) + .setDesc(t("builder.one_page_override.desc")) .addDropdown((dropdown) => { dropdown.addOptions({ - "": "Follow global setting", - always: "Always", - never: "Never", + "": t("builder.one_page_override.follow"), + always: t("builder.one_page_override.always"), + never: t("builder.one_page_override.never"), }); dropdown.setValue((choice.onePageInput ?? "") as string); dropdown.onChange((val: string) => { @@ -61,7 +59,7 @@ export abstract class ChoiceBuilder extends Modal { ): void { setting.addSearch((searchComponent) => { searchComponent.setValue(value); - searchComponent.setPlaceholder("File path"); + searchComponent.setPlaceholder(t("builder.file_path_placeholder")); const markdownFiles: string[] = this.app.vault .getMarkdownFiles() @@ -89,7 +87,7 @@ export abstract class ChoiceBuilder extends Modal { const newName: string = await GenericInputPrompt.Prompt( this.app, choice.name, - "Choice name", + t("builder.choice_name"), choice.name, ); if (newName !== choice.name) { @@ -150,16 +148,16 @@ export abstract class ChoiceBuilder extends Modal { // Location selector new Setting(this.contentEl) - .setName(t("builder.file_opening_location")) - .setDesc(`Where to open the ${contextLabel} file`) + .setName(t("builder.location")) + .setDesc(t("builder.descriptions.location")) .addDropdown((dropdown) => { dropdown.addOptions({ - reuse: "Reuse current tab", - tab: "New tab", - split: "Split pane", - window: "New window", - "left-sidebar": "Left sidebar", - "right-sidebar": "Right sidebar", + reuse: t("builder.options.reuse"), + tab: t("builder.options.tab"), + split: t("builder.options.split"), + window: t("builder.options.window"), + "left-sidebar": t("builder.options.left"), + "right-sidebar": t("builder.options.right"), }); dropdown.setValue(fileOpening.location); dropdown.onChange((value: any) => { @@ -172,11 +170,11 @@ export abstract class ChoiceBuilder extends Modal { if (fileOpening.location === "split") { new Setting(this.contentEl) .setName(t("builder.split_direction")) - .setDesc("Direction for split panes") + .setDesc(t("builder.descriptions.split")) .addDropdown((dropdown) => { dropdown.addOptions({ - vertical: "Vertical", - horizontal: "Horizontal", + vertical: t("builder.options.vertical"), + horizontal: t("builder.options.horizontal"), }); dropdown.setValue(fileOpening.direction); dropdown.onChange((value: any) => { @@ -187,14 +185,14 @@ export abstract class ChoiceBuilder extends Modal { // View mode selector new Setting(this.contentEl) - .setName(t("builder.view_mode")) - .setDesc("How to display the opened file") + .setName(t("builder.viewMode")) + .setDesc(t("builder.descriptions.view_mode")) .addDropdown((dropdown) => { dropdown.addOptions({ - source: "Source", - preview: "Preview", - live: "Live Preview", - default: "Default", + source: t("builder.options.source"), + preview: t("builder.options.preview"), + live: t("builder.options.live"), + default: t("builder.options.default"), }); dropdown.setValue( typeof fileOpening.mode === "string" @@ -210,7 +208,7 @@ export abstract class ChoiceBuilder extends Modal { if (fileOpening.location !== "reuse") { new Setting(this.contentEl) .setName(t("builder.focus_pane")) - .setDesc("Focus the opened tab immediately after opening") + .setDesc(t("builder.descriptions.focus")) .addToggle((toggle) => toggle.setValue(fileOpening.focus).onChange((value) => { fileOpening.focus = value; From 1219866a5d94e330f6dba9c5f7bad7453b697476 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:53:44 +0100 Subject: [PATCH 11/27] Update fr.json --- src/i18n/locales/fr.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index 7d900729..5c332fca 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -5,12 +5,12 @@ "test": "Tester QuickAdd (dev)" }, "ribbon": { - "icon": "QuickAdd" + "icon": "Ouvrir QuickAdd" }, "settings": { "headers": { "choices": "Choix & Packages", - "input": "Saisie (Input)", + "input": "Saisie", "templates": "Modèles & Propriétés", "notifications": "Notifications", "globals": "Variables Globales", @@ -21,8 +21,8 @@ "packages": { "name": "Packages", "desc": "Regroupez ou importez des automatisations QuickAdd sous forme de packages réutilisables.", - "export": "Exporter le package…", - "import": "Importer le package…" + "export": "Exporter le package...", + "import": "Importer le package..." }, "announce": { "name": "Annoncer les mises à jour", @@ -72,7 +72,7 @@ "name": "Désactiver IA & En ligne", "desc": "Empêche le plugin de faire des requêtes externes (comme OpenAI). Vous devez désactiver cette option pour utiliser l'Assistant IA." }, - "ribbon": { + "ribbon_options": { "name": "Afficher l'icône latérale", "desc": "Ajoute l'icône QuickAdd au ruban latéral gauche. Nécessite un rechargement." }, @@ -88,7 +88,7 @@ }, "builder": { "open": "Ouvrir", - "viewMode": "Mode de vue", + "viewMode": "Mode d'affichage", "location": "Emplacement d'ouverture", "one_page_override": { "name": "Forçage de la saisie sur une page", @@ -99,13 +99,13 @@ }, "file_path_placeholder": "Chemin du fichier", "choice_name": "Nom du choix", - "split_direction": "Direction de la séparation", - "focus_pane": "Focus sur le nouveau panneau", + "split_direction": "Orientation de la séparation", + "focus_pane": "Focus sur le panneau", "descriptions": { - "location": "Où ouvrir le fichier", - "split": "Direction pour les panneaux séparés", - "view_mode": "Comment afficher le fichier ouvert", - "focus": "Mettre le focus sur l'onglet immédiatement après l'ouverture" + "location": "Où ouvrir le fichier créé ou capturé.", + "split": "Direction si vous choisissez de séparer le panneau.", + "view_mode": "Comment afficher le fichier ouvert (Lecture ou Édition).", + "focus": "Mettre le focus sur l'onglet immédiatement après l'ouverture." }, "options": { "reuse": "Réutiliser l'onglet actuel", From 3daf652f78fa68e16b914da2ce2ff58cdee124f0 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:54:04 +0100 Subject: [PATCH 12/27] Update en.json --- src/i18n/locales/en.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index d1bb133e..5e2c04ca 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -21,8 +21,8 @@ "packages": { "name": "Packages", "desc": "Bundle or import QuickAdd automations as reusable packages.", - "export": "Export package…", - "import": "Import package…" + "export": "Export package...", + "import": "Import package..." }, "announce": { "name": "Announce Updates", @@ -72,7 +72,7 @@ "name": "Disable AI & Online features", "desc": "Prevents the plugin from making requests to external providers like OpenAI. You need to disable this setting to use the AI Assistant." }, - "ribbon": { + "ribbon_options": { "name": "Show icon in sidebar", "desc": "Add QuickAdd icon to the sidebar ribbon. Requires a reload." }, From 11540d63d9cf7f06272a4290cfdb46fcff7314e2 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:54:24 +0100 Subject: [PATCH 13/27] Update quickAddSettingsTab.ts --- src/quickAddSettingsTab.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/quickAddSettingsTab.ts b/src/quickAddSettingsTab.ts index 100d222d..97704ced 100644 --- a/src/quickAddSettingsTab.ts +++ b/src/quickAddSettingsTab.ts @@ -485,8 +485,8 @@ export class QuickAddSettingsTab extends PluginSettingTab { private addEnableRibbonIconSetting(group: SettingGroupLike) { group.addSetting((setting) => { setting - .setName(t("settings.ribbon.name")) - .setDesc(t("settings.ribbon.desc")) + .setName(t("settings.ribbon_options.name")) + .setDesc(t("settings.ribbon_options.desc")) .addToggle((toggle) => { toggle .setValue(settingsStore.getState().enableRibbonIcon) From ff6221d6b94630d54940d2b704cc69a91fce456d Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:55:11 +0100 Subject: [PATCH 14/27] Update choiceBuilder.ts From c9529c4ebce0752ce92a19f9a1e83839a1c1fd42 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:55:49 +0100 Subject: [PATCH 15/27] Update fr.json --- src/i18n/locales/fr.json | 121 +++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 23 deletions(-) diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index 5c332fca..fb8390bb 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -26,74 +26,149 @@ }, "announce": { "name": "Annoncer les mises à jour", - "desc": "Affiche les notes de version lors de l'installation d'une nouvelle version (nouvelles fonctionnalités, correctifs, etc).", + "desc": "Affiche les notes de version lors de l'installation d'une nouvelle version.", "all": "Afficher à chaque nouvelle version", "major": "Uniquement les versions majeures", "none": "Ne jamais afficher" }, "capture_notif": { "name": "Notifications de capture", - "desc": "Affiche une notification lorsqu'un contenu est capturé avec succès pour confirmer l'opération." + "desc": "Affiche une notification lorsqu'un contenu est capturé avec succès." }, "cancel_notif": { "name": "Notifications d'annulation", - "desc": "Affiche une notification lorsqu'une invite de saisie est annulée. Désactivez ceci pour éviter les alertes superflues." + "desc": "Affiche une notification lorsqu'une invite de saisie est annulée." }, "multiline": { "name": "Saisie multiligne", - "desc": "Utilise une zone de texte multiligne au lieu d'une ligne simple pour les invites de saisie." + "desc": "Utilise une zone de texte multiligne pour les invites de saisie." }, "persist": { "name": "Conserver les brouillons", - "desc": "Garde les brouillons lors de la fermeture des invites pour les restaurer à la réouverture (pour la session en cours)." + "desc": "Garde les brouillons lors de la fermeture des invites pour les restaurer." }, "selection_capture": { "name": "Utiliser la sélection comme valeur par défaut", - "desc": "Si activé, la capture utilise le texte sélectionné pour {{VALUE}} et peut sauter l'invite. Sinon, la capture demande toujours {{VALUE}}." + "desc": "Si activé, la capture utilise le texte sélectionné pour {{VALUE}}." }, "template_folder": { "name": "Dossier des modèles", - "desc": "Chemin du dossier où sont stockés les modèles. Utilisé pour la suggestion de fichiers lors de la configuration." + "desc": "Chemin du dossier où sont stockés les modèles." }, "template_properties": { "name": "Formater les variables comme propriétés (Beta)", - "desc": "Si activé, les variables dans le frontmatter seront formatées selon le type de propriété Obsidian (Listes, Nombres, Cases à cocher)." + "desc": "Formate les variables du frontmatter selon le type de propriété Obsidian." }, "one_page": { "name": "Saisie sur une page (Beta)", - "desc": "Expérimental. Résout les variables à l'avance et affiche un formulaire unique avant d'exécuter les choix de Modèle/Capture." + "desc": "Affiche un formulaire unique avant d'exécuter les choix." }, "date_aliases": { "name": "Alias de date", - "desc": "Raccourcis pour l'analyse des dates en langage naturel. Un par ligne : alias = phrase. Exemple : tm = tomorrow.", + "desc": "Raccourcis pour l'analyse des dates (ex: tm = tomorrow).", "reset": "Réinitialiser" }, "disable_online": { "name": "Désactiver IA & En ligne", - "desc": "Empêche le plugin de faire des requêtes externes (comme OpenAI). Vous devez désactiver cette option pour utiliser l'Assistant IA." + "desc": "Empêche le plugin de faire des requêtes externes (comme OpenAI)." }, "ribbon_options": { "name": "Afficher l'icône latérale", - "desc": "Ajoute l'icône QuickAdd au ruban latéral gauche. Nécessite un rechargement." + "desc": "Ajoute l'icône QuickAdd au ruban latéral gauche." }, "dev": { - "info_name": "Informations de développement", - "info_desc": "Informations Git pour les développeurs.", + "info_name": "Infos dev", + "info_desc": "Infos Git.", "branch": "Branche", "commit": "Commit", - "changes": "Changements non validés", + "changes": "Changements", "yes": "Oui", "no": "Non" } }, "builder": { + "common": { + "template": "Modèle", + "location": "Emplacement", + "linking": "Liaison (Links)", + "behavior": "Comportement", + "content": "Contenu", + "position": "Position", + "preview": "Aperçu : ", + "loading": "Chargement...", + "unavailable": "Indisponible" + }, + "template": { + "path": "Chemin du modèle", + "path_desc": "Chemin vers le fichier modèle.", + "file_name_format": "Format du nom de fichier", + "folder": "Créer dans le dossier", + "folder_desc": "Créer le fichier dans ce dossier.", + "choose_folder": "Choisir le dossier lors de la création", + "include_subfolders": "Inclure les sous-dossiers", + "same_folder": "Créer dans le même dossier que le fichier actif", + "conflict": "Comportement si le fichier existe déjà", + "conflict_desc": "Action par défaut au lieu de demander à l'utilisateur.", + "conflict_options": { + "nothing": "Ne rien faire", + "overwrite": "Écraser", + "increment": "Incrémenter le nom", + "append_bottom": "Ajouter à la fin", + "append_top": "Ajouter au début" + } + }, + "capture": { + "to": "Capturer vers", + "to_desc": "Chemin du fichier cible. Supporte la syntaxe de format.", + "active_file": "Capturer vers le fichier actif", + "task": "Tâche", + "task_desc": "Formate la valeur comme une tâche à cocher.", + "format": "Format de capture", + "format_desc": "Définir le format du texte capturé.", + "create_if_missing": "Créer le fichier s'il n'existe pas", + "create_with_template": "Créer avec un modèle spécifique", + "write_pos": "Position d'écriture", + "write_pos_desc": "Où placer la capture dans le fichier.", + "pos_options": { + "top": "Haut du fichier", + "bottom": "Bas du fichier", + "cursor": "Au curseur", + "after": "Après la ligne...", + "active_top": "Haut (après frontmatter)", + "newline_above": "Nouvelle ligne au-dessus", + "newline_below": "Nouvelle ligne en-dessous" + }, + "insert_after": "Insérer après", + "insert_after_desc": "Insérer après le texte spécifié. Accepte la syntaxe de format.", + "inline": "Insertion en ligne (Inline)", + "inline_desc": "Insère sur la même ligne, juste après le texte trouvé.", + "insert_end_section": "Insérer à la fin de la section", + "consider_subsections": "Inclure les sous-sections" + }, + "append_link": { + "name": "Lien vers le fichier créé/capturé", + "desc": "Insérer un lien vers ce fichier dans la note actuelle.", + "placement": "Placement du lien", + "type": "Type de lien", + "options": { + "required": "Activé (requiert un fichier actif)", + "optional": "Activé (ignorer si aucun fichier actif)", + "disabled": "Désactivé", + "replace": "Remplacer la sélection", + "after": "Après la sélection", + "eol": "Fin de ligne", + "newline": "Nouvelle ligne", + "link": "Lien", + "embed": "Intégration (Embed)" + } + }, "open": "Ouvrir", "viewMode": "Mode d'affichage", "location": "Emplacement d'ouverture", "one_page_override": { "name": "Forçage de la saisie sur une page", "desc": "Remplace le paramètre global pour ce choix.", - "follow": "Suivre le paramètre global", + "follow": "Suivre global", "always": "Toujours", "never": "Jamais" }, @@ -102,18 +177,18 @@ "split_direction": "Orientation de la séparation", "focus_pane": "Focus sur le panneau", "descriptions": { - "location": "Où ouvrir le fichier créé ou capturé.", - "split": "Direction si vous choisissez de séparer le panneau.", - "view_mode": "Comment afficher le fichier ouvert (Lecture ou Édition).", - "focus": "Mettre le focus sur l'onglet immédiatement après l'ouverture." + "location": "Où ouvrir le fichier.", + "split": "Direction de la séparation.", + "view_mode": "Comment afficher le fichier.", + "focus": "Mettre le focus sur l'onglet." }, "options": { - "reuse": "Réutiliser l'onglet actuel", + "reuse": "Réutiliser l'onglet", "tab": "Nouvel onglet", "split": "Séparer le panneau", "window": "Nouvelle fenêtre", - "left": "Barre latérale gauche", - "right": "Barre latérale droite", + "left": "Barre gauche", + "right": "Barre droite", "source": "Source", "preview": "Lecture", "live": "Live Preview", From 4abcadc6141a6c149223818f9e4271001da9f051 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:56:07 +0100 Subject: [PATCH 16/27] Update en.json --- src/i18n/locales/en.json | 101 ++++++++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 13 deletions(-) diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 5e2c04ca..612b9e7b 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -26,18 +26,18 @@ }, "announce": { "name": "Announce Updates", - "desc": "Display release notes when a new version is installed. This includes new features, demo videos, and bug fixes.", + "desc": "Display release notes when a new version is installed.", "all": "Show updates on each new release", "major": "Show updates only on major releases", "none": "Don't show" }, "capture_notif": { "name": "Show Capture Notifications", - "desc": "Display a notification when content is captured successfully to confirm the operation completed." + "desc": "Display a notification when content is captured successfully." }, "cancel_notif": { "name": "Show Input Cancellation Notifications", - "desc": "Display a notification when an input prompt is cancelled without submitting. Disable this to avoid extra notices when dismissing prompts." + "desc": "Display a notification when an input prompt is cancelled." }, "multiline": { "name": "Use Multi-line Input Prompt", @@ -45,40 +45,40 @@ }, "persist": { "name": "Persist Input Prompt Drafts", - "desc": "Keep drafts when closing input prompts so they can be restored on reopen. Drafts are stored only for this session." + "desc": "Keep drafts when closing input prompts so they can be restored on reopen." }, "selection_capture": { "name": "Use editor selection as default Capture value", - "desc": "When enabled, Capture uses the current editor selection as {{VALUE}} and may skip the prompt. When disabled, Capture always prompts for {{VALUE}}." + "desc": "When enabled, Capture uses the current editor selection as {{VALUE}}." }, "template_folder": { "name": "Template Folder Path", - "desc": "Path to the folder where templates are stored. Used to suggest template files when configuring QuickAdd." + "desc": "Path to the folder where templates are stored." }, "template_properties": { "name": "Format template variables as proper property types (Beta)", - "desc": "When enabled, template variables in front matter will be formatted as proper Obsidian property types (Arrays, Numbers, Booleans)." + "desc": "When enabled, template variables in front matter will be formatted as proper Obsidian property types." }, "one_page": { "name": "One-page input for choices (Beta)", - "desc": "Experimental. Resolve variables up front and show a single dynamic form before executing Template/Capture choices." + "desc": "Resolve variables up front and show a single dynamic form." }, "date_aliases": { "name": "Date aliases", - "desc": "Shortcodes for natural language date parsing. One per line: alias = phrase. Example: tm = tomorrow.", - "reset": "Reset to defaults" + "desc": "Shortcodes for natural language date parsing (e.g. tm = tomorrow).", + "reset": "Reset" }, "disable_online": { "name": "Disable AI & Online features", - "desc": "Prevents the plugin from making requests to external providers like OpenAI. You need to disable this setting to use the AI Assistant." + "desc": "Prevents the plugin from making requests to external providers like OpenAI." }, "ribbon_options": { "name": "Show icon in sidebar", - "desc": "Add QuickAdd icon to the sidebar ribbon. Requires a reload." + "desc": "Add QuickAdd icon to the sidebar ribbon." }, "dev": { "info_name": "Development Information", - "info_desc": "Git information for developers.", + "info_desc": "Git information.", "branch": "Branch", "commit": "Commit", "changes": "Uncommitted changes", @@ -87,6 +87,81 @@ } }, "builder": { + "common": { + "template": "Template", + "location": "Location", + "linking": "Linking", + "behavior": "Behavior", + "content": "Content", + "position": "Position", + "preview": "Preview: ", + "loading": "Loading...", + "unavailable": "Unavailable" + }, + "template": { + "path": "Template Path", + "path_desc": "Path to the Template.", + "file_name_format": "File name format", + "folder": "Create in folder", + "folder_desc": "Create the file in the specified folder.", + "choose_folder": "Choose folder when creating a new note", + "include_subfolders": "Include subfolders", + "same_folder": "Create in same folder as active file", + "conflict": "Set default behavior if file already exists", + "conflict_desc": "Set default behavior rather then prompting user.", + "conflict_options": { + "nothing": "Do nothing", + "overwrite": "Overwrite", + "increment": "Increment file name", + "append_bottom": "Append to bottom", + "append_top": "Append to top" + } + }, + "capture": { + "to": "Capture to", + "to_desc": "Target file path. Supports format syntax.", + "active_file": "Capture to active file", + "task": "Task", + "task_desc": "Formats the value as a task.", + "format": "Capture format", + "format_desc": "Set the format of the capture.", + "create_if_missing": "Create file if it doesn't exist", + "create_with_template": "Create file with given template", + "write_pos": "Write position", + "write_pos_desc": "Where to place the capture in the file.", + "pos_options": { + "top": "Top of file", + "bottom": "Bottom of file", + "cursor": "At cursor", + "after": "After line...", + "active_top": "Top (after frontmatter)", + "newline_above": "New line above", + "newline_below": "New line below" + }, + "insert_after": "Insert after", + "insert_after_desc": "Insert capture after specified text. Accepts format syntax.", + "inline": "Inline insertion", + "inline_desc": "Insert captured content on the same line.", + "insert_end_section": "Insert at end of section", + "consider_subsections": "Consider subsections" + }, + "append_link": { + "name": "Link to file", + "desc": "Choose how QuickAdd should insert a link to the file in the current note.", + "placement": "Link placement", + "type": "Link type", + "options": { + "required": "Enabled (requires active file)", + "optional": "Enabled (skip if no active file)", + "disabled": "Disabled", + "replace": "Replace selection", + "after": "After selection", + "eol": "End of line", + "newline": "New line", + "link": "Link", + "embed": "Embed" + } + }, "open": "Open", "viewMode": "View Mode", "location": "File Opening Location", From 9e6dc4480a7c23d1c87b5f5590e495467e44dc15 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:56:52 +0100 Subject: [PATCH 17/27] Update templateChoiceBuilder.ts --- .../ChoiceBuilder/templateChoiceBuilder.ts | 83 +++++++++---------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/src/gui/ChoiceBuilder/templateChoiceBuilder.ts b/src/gui/ChoiceBuilder/templateChoiceBuilder.ts index 437a06fe..a0f5bc85 100644 --- a/src/gui/ChoiceBuilder/templateChoiceBuilder.ts +++ b/src/gui/ChoiceBuilder/templateChoiceBuilder.ts @@ -28,6 +28,7 @@ import { ExclusiveSuggester } from "../suggesters/exclusiveSuggester"; import { FormatSyntaxSuggester } from "../suggesters/formatSyntaxSuggester"; import { ChoiceBuilder } from "./choiceBuilder"; import FolderList from "./FolderList.svelte"; +import { t } from "../../i18n/i18n"; export class TemplateChoiceBuilder extends ChoiceBuilder { choice: ITemplateChoice; @@ -48,22 +49,22 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { this.addCenteredChoiceNameHeader(this.choice); // Template - new Setting(this.contentEl).setName("Template").setHeading(); + new Setting(this.contentEl).setName(t("builder.common.template")).setHeading(); this.addTemplatePathSetting(); this.addFileNameFormatSetting(); // Location - new Setting(this.contentEl).setName("Location").setHeading(); + new Setting(this.contentEl).setName(t("builder.common.location")).setHeading(); this.addFolderSetting(); // Linking - new Setting(this.contentEl).setName("Linking").setHeading(); + new Setting(this.contentEl).setName(t("builder.common.linking")).setHeading(); this.addAppendLinkSetting(); // Behavior - new Setting(this.contentEl).setName("Behavior").setHeading(); + new Setting(this.contentEl).setName(t("builder.common.behavior")).setHeading(); this.addFileAlreadyExistsSetting(); - this.addOpenFileSetting("Open the created file."); + this.addOpenFileSetting(t("builder.descriptions.location")); if (this.choice.openFile) { this.addFileOpeningSetting("created"); } @@ -72,8 +73,8 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { private addTemplatePathSetting(): void { new Setting(this.contentEl) - .setName("Template Path") - .setDesc("Path to the Template."); + .setName(t("builder.template.path")) + .setDesc(t("builder.template.path_desc")); const templates: string[] = this.plugin .getTemplateFiles() @@ -83,7 +84,7 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { app: this.app, parent: this.contentEl, initialValue: this.choice.templatePath, - placeholder: "Template path", + placeholder: t("builder.template.path"), suggestions: templates, maxSuggestions: 50, validator: (raw) => { @@ -101,7 +102,7 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { let textField: TextComponent; const enableSetting = new Setting(this.contentEl); enableSetting - .setName("File name format") + .setName(t("builder.template.file_name_format")) .setDesc("Set the file name format.") .addToggle((toggleComponent) => { toggleComponent @@ -114,24 +115,24 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { // Desc + preview row const previewRow = this.contentEl.createDiv({ cls: "qa-preview-row" }); - previewRow.createEl("span", { text: "Preview: ", cls: "qa-preview-label" }); + previewRow.createEl("span", { text: t("builder.common.preview"), cls: "qa-preview-label" }); const formatDisplay = previewRow.createEl("span"); formatDisplay.setAttr("aria-live", "polite"); const displayFormatter: FileNameDisplayFormatter = new FileNameDisplayFormatter(this.app, this.plugin); - formatDisplay.textContent = "Loading preview…"; + formatDisplay.textContent = t("builder.common.loading"); void (async () => { try { formatDisplay.textContent = await displayFormatter.format( this.choice.fileNameFormat.format, ); } catch { - formatDisplay.textContent = "Preview unavailable"; + formatDisplay.textContent = t("builder.common.unavailable"); } })(); const formatInput = new TextComponent(this.contentEl); - formatInput.setPlaceholder("File name format"); + formatInput.setPlaceholder(t("builder.template.file_name_format")); textField = formatInput; formatInput.inputEl.style.width = "100%"; formatInput.inputEl.style.marginBottom = "8px"; @@ -144,7 +145,7 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { try { formatDisplay.textContent = await displayFormatter.format(value); } catch { - formatDisplay.textContent = "Preview unavailable"; + formatDisplay.textContent = t("builder.common.unavailable"); } }); @@ -154,10 +155,8 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { private addFolderSetting(): void { const folderSetting: Setting = new Setting(this.contentEl); folderSetting - .setName("Create in folder") - .setDesc( - "Create the file in the specified folder. If multiple folders are specified, you will be prompted for which folder to create the file in.", - ) + .setName(t("builder.template.folder")) + .setDesc(t("builder.template.folder_desc")) .addToggle((toggle) => { toggle.setValue(this.choice.folder.enabled); toggle.onChange((value) => { @@ -175,7 +174,7 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { "chooseFolderWhenCreatingNoteContainer", ); chooseFolderWhenCreatingNoteContainer.createEl("span", { - text: "Choose folder when creating a new note", + text: t("builder.template.choose_folder"), }); const chooseFolderWhenCreatingNote: ToggleComponent = new ToggleComponent( chooseFolderWhenCreatingNoteContainer, @@ -196,7 +195,7 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { const stn = new Setting(chooseFolderFromSubfolderContainer); stn - .setName("Include subfolders") + .setName(t("builder.template.include_subfolders")) .setDesc( "Get prompted to choose from both the selected folders and their subfolders when creating the note.", ) @@ -215,7 +214,7 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { this.contentEl, ); createInSameFolderAsActiveFileSetting - .setName("Create in same folder as active file") + .setName(t("builder.template.same_folder")) .setDesc( "Creates the file in the same folder as the currently active file. Will not create the file if there is no active file.", ) @@ -316,12 +315,12 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { const appendLinkSetting: Setting = new Setting(this.contentEl); appendLinkSetting - .setName("Link to created file") - .setDesc("Choose how QuickAdd should insert a link to the created file in the current note.") + .setName(t("builder.append_link.name")) + .setDesc(t("builder.append_link.desc")) .addDropdown((dropdown) => { - dropdown.addOption("required", "Enabled (requires active file)"); - dropdown.addOption("optional", "Enabled (skip if no active file)"); - dropdown.addOption("disabled", "Disabled"); + dropdown.addOption("required", t("builder.append_link.options.required")); + dropdown.addOption("optional", t("builder.append_link.options.optional")); + dropdown.addOption("disabled", t("builder.append_link.options.disabled")); dropdown.setValue(currentMode); dropdown.onChange((value: AppendLinkMode) => { @@ -354,13 +353,13 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { if (currentMode !== "disabled") { const placementSetting: Setting = new Setting(this.contentEl); placementSetting - .setName("Link placement") + .setName(t("builder.append_link.placement")) .setDesc("Where to place the link when appending") .addDropdown((dropdown) => { - dropdown.addOption("replaceSelection", "Replace selection"); - dropdown.addOption("afterSelection", "After selection"); - dropdown.addOption("endOfLine", "End of line"); - dropdown.addOption("newLine", "New line"); + dropdown.addOption("replaceSelection", t("builder.append_link.options.replace")); + dropdown.addOption("afterSelection", t("builder.append_link.options.after")); + dropdown.addOption("endOfLine", t("builder.append_link.options.eol")); + dropdown.addOption("newLine", t("builder.append_link.options.newline")); dropdown.setValue(normalizedOptions.placement); dropdown.onChange((value: LinkPlacement) => { @@ -390,11 +389,11 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { if (placementSupportsEmbed(normalizedOptions.placement)) { const linkTypeSetting: Setting = new Setting(this.contentEl); linkTypeSetting - .setName("Link type") + .setName(t("builder.append_link.type")) .setDesc("Choose whether replacing the selection should insert a link or an embed.") .addDropdown((dropdown) => { - dropdown.addOption("link", "Link"); - dropdown.addOption("embed", "Embed"); + dropdown.addOption("link", t("builder.append_link.options.link")); + dropdown.addOption("embed", t("builder.append_link.options.embed")); dropdown.setValue(normalizedLinkType); dropdown.onChange((value: LinkType) => { const currentValue = this.choice.appendLink; @@ -422,10 +421,8 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { private addFileAlreadyExistsSetting(): void { const fileAlreadyExistsSetting: Setting = new Setting(this.contentEl); fileAlreadyExistsSetting - .setName("Set default behavior if file already exists") - .setDesc( - "Set default behavior rather then prompting user on what to do if a file already exists.", - ) + .setName(t("builder.template.conflict")) + .setDesc(t("builder.template.conflict_desc")) .addToggle((toggle) => { toggle.setValue(this.choice.setFileExistsBehavior); toggle.onChange((value) => { @@ -439,11 +436,11 @@ export class TemplateChoiceBuilder extends ChoiceBuilder { this.choice.fileExistsMode = fileExistsDoNothing; dropdown - .addOption(fileExistsAppendToBottom, fileExistsAppendToBottom) - .addOption(fileExistsAppendToTop, fileExistsAppendToTop) - .addOption(fileExistsIncrement, fileExistsIncrement) - .addOption(fileExistsOverwriteFile, fileExistsOverwriteFile) - .addOption(fileExistsDoNothing, fileExistsDoNothing) + .addOption(fileExistsAppendToBottom, t("builder.template.conflict_options.append_bottom")) + .addOption(fileExistsAppendToTop, t("builder.template.conflict_options.append_top")) + .addOption(fileExistsIncrement, t("builder.template.conflict_options.increment")) + .addOption(fileExistsOverwriteFile, t("builder.template.conflict_options.overwrite")) + .addOption(fileExistsDoNothing, t("builder.template.conflict_options.nothing")) .setValue(this.choice.fileExistsMode) .onChange( (value: (typeof fileExistsChoices)[number]) => From 36b61ce702ce6e1caedce0e4594a3f761071ae01 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 22:57:12 +0100 Subject: [PATCH 18/27] Update captureChoiceBuilder.ts --- src/gui/ChoiceBuilder/captureChoiceBuilder.ts | 129 ++++++++---------- 1 file changed, 58 insertions(+), 71 deletions(-) diff --git a/src/gui/ChoiceBuilder/captureChoiceBuilder.ts b/src/gui/ChoiceBuilder/captureChoiceBuilder.ts index c11f750c..655e719a 100644 --- a/src/gui/ChoiceBuilder/captureChoiceBuilder.ts +++ b/src/gui/ChoiceBuilder/captureChoiceBuilder.ts @@ -18,6 +18,7 @@ import { import { createValidatedInput } from "../components/validatedInput"; import { FormatSyntaxSuggester } from "../suggesters/formatSyntaxSuggester"; import { ChoiceBuilder } from "./choiceBuilder"; +import { t } from "../../i18n/i18n"; export class CaptureChoiceBuilder extends ChoiceBuilder { choice: ICaptureChoice; @@ -40,7 +41,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { this.addCenteredChoiceNameHeader(this.choice); // Location - new Setting(this.contentEl).setName("Location").setHeading(); + new Setting(this.contentEl).setName(t("builder.common.location")).setHeading(); this.addCapturedToSetting(); if (!this.choice?.captureToActiveFile) { this.addCreateIfNotExistsSetting(); @@ -49,20 +50,20 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { } // Position - new Setting(this.contentEl).setName("Position").setHeading(); + new Setting(this.contentEl).setName(t("builder.common.position")).setHeading(); this.addWritePositionSetting(); // Linking - new Setting(this.contentEl).setName("Linking").setHeading(); + new Setting(this.contentEl).setName(t("builder.common.linking")).setHeading(); this.addAppendLinkSetting(); // Content - new Setting(this.contentEl).setName("Content").setHeading(); + new Setting(this.contentEl).setName(t("builder.common.content")).setHeading(); this.addTaskSetting(); this.addFormatSetting(); // Behavior - new Setting(this.contentEl).setName("Behavior").setHeading(); + new Setting(this.contentEl).setName(t("builder.common.behavior")).setHeading(); if (!this.choice.captureToActiveFile) { this.addOpenFileSetting("Open the captured file."); @@ -94,13 +95,11 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { private addSelectionAsValueSetting() { new Setting(this.contentEl) - .setName("Use editor selection as default value") - .setDesc( - "Controls whether this Capture uses the current editor selection as {{VALUE}}. Does not affect {{SELECTED}}.", - ) + .setName(t("settings.selection_capture.name")) + .setDesc(t("settings.selection_capture.desc")) .addDropdown((dropdown) => { dropdown.addOptions({ - "": "Follow global setting", + "": t("builder.one_page_override.follow"), enabled: "Use selection", disabled: "Ignore selection", }); @@ -124,8 +123,8 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { private addCapturedToSetting() { new Setting(this.contentEl) - .setName("Capture to") - .setDesc("Target file path. Supports format syntax."); + .setName(t("builder.capture.to")) + .setDesc(t("builder.capture.to_desc")); const captureToContainer: HTMLDivElement = this.contentEl.createDiv("captureToContainer"); @@ -134,7 +133,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { captureToContainer.createDiv("captureToActiveFileContainer"); const captureToActiveFileText: HTMLSpanElement = captureToActiveFileContainer.createEl("span"); - captureToActiveFileText.textContent = "Capture to active file"; + captureToActiveFileText.textContent = t("builder.capture.active_file"); const captureToActiveFileToggle: ToggleComponent = new ToggleComponent( captureToActiveFileContainer, ); @@ -143,7 +142,6 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { this.choice.captureToActiveFile = value; // Reset new line capture settings when switching away from active file - // since those options are only available for active file capture if (!value && this.choice.newLineCapture?.enabled) { this.choice.newLineCapture.enabled = false; } @@ -163,10 +161,10 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { new FileNameDisplayFormatter(this.app, this.plugin); const previewRow = captureToFileContainer.createDiv({ cls: "qa-preview-row" }); - previewRow.createEl("span", { text: "Preview: ", cls: "qa-preview-label" }); + previewRow.createEl("span", { text: t("builder.common.preview"), cls: "qa-preview-label" }); const formatDisplay = previewRow.createEl("span"); formatDisplay.setAttr("aria-live", "polite"); - formatDisplay.textContent = "Loading preview…"; + formatDisplay.textContent = t("builder.common.loading"); const markdownFilesAndFormatSyntax = [ ...this.app.vault.getMarkdownFiles().map((f) => f.path), @@ -188,7 +186,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { try { formatDisplay.textContent = await displayFormatter.format(value); } catch { - formatDisplay.textContent = "Preview unavailable"; + formatDisplay.textContent = t("builder.common.unavailable"); } }, }); @@ -199,7 +197,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { this.choice.captureTo, ); } catch { - formatDisplay.textContent = "Preview unavailable"; + formatDisplay.textContent = t("builder.common.unavailable"); } })(); } @@ -208,8 +206,8 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { private addTaskSetting() { const taskSetting: Setting = new Setting(this.contentEl); taskSetting - .setName("Task") - .setDesc("Formats the value as a task.") + .setName(t("builder.capture.task")) + .setDesc(t("builder.capture.task_desc")) .addToggle((toggle) => { toggle.setValue(this.choice.task); toggle.onChange((value) => (this.choice.task = value)); @@ -232,12 +230,12 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { const appendLinkSetting: Setting = new Setting(this.contentEl); appendLinkSetting - .setName("Link to captured file") - .setDesc("Choose how QuickAdd should insert a link to the captured file in the current note.") + .setName(t("builder.append_link.name")) + .setDesc(t("builder.append_link.desc")) .addDropdown((dropdown) => { - dropdown.addOption("required", "Enabled (requires active file)"); - dropdown.addOption("optional", "Enabled (skip if no active file)"); - dropdown.addOption("disabled", "Disabled"); + dropdown.addOption("required", t("builder.append_link.options.required")); + dropdown.addOption("optional", t("builder.append_link.options.optional")); + dropdown.addOption("disabled", t("builder.append_link.options.disabled")); dropdown.setValue(currentMode); dropdown.onChange((value: AppendLinkMode) => { @@ -270,13 +268,13 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { if (currentMode !== "disabled") { const placementSetting: Setting = new Setting(this.contentEl); placementSetting - .setName("Link placement") + .setName(t("builder.append_link.placement")) .setDesc("Where to place the link when appending") .addDropdown((dropdown) => { - dropdown.addOption("replaceSelection", "Replace selection"); - dropdown.addOption("afterSelection", "After selection"); - dropdown.addOption("endOfLine", "End of line"); - dropdown.addOption("newLine", "New line"); + dropdown.addOption("replaceSelection", t("builder.append_link.options.replace")); + dropdown.addOption("afterSelection", t("builder.append_link.options.after")); + dropdown.addOption("endOfLine", t("builder.append_link.options.eol")); + dropdown.addOption("newLine", t("builder.append_link.options.newline")); dropdown.setValue(normalizedOptions.placement); dropdown.onChange((value: LinkPlacement) => { @@ -307,11 +305,11 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { if (placementSupportsEmbed(normalizedOptions.placement)) { const linkTypeSetting: Setting = new Setting(this.contentEl); linkTypeSetting - .setName("Link type") + .setName(t("builder.append_link.type")) .setDesc("Choose whether to insert a regular link or an embed when replacing the selection.") .addDropdown((dropdown) => { - dropdown.addOption("link", "Link"); - dropdown.addOption("embed", "Embed"); + dropdown.addOption("link", t("builder.append_link.options.link")); + dropdown.addOption("embed", t("builder.append_link.options.embed")); dropdown.setValue(normalizedLinkType); dropdown.onChange((value: LinkType) => { const currentValue = this.choice.appendLink; @@ -345,12 +343,8 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { } positionSetting - .setName("Write position") - .setDesc( - isActiveFile - ? "Where to place the capture in the current file." - : "Where to place the capture in the target file.", - ) + .setName(t("builder.capture.write_pos")) + .setDesc(t("builder.capture.write_pos_desc")) .addDropdown((dropdown) => { const current = this.choice.insertAfter?.enabled @@ -365,16 +359,16 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { ? "activeTop" : "top"; - dropdown.addOption("top", isActiveFile ? "At cursor" : "Top of file"); + dropdown.addOption("top", isActiveFile ? t("builder.capture.pos_options.cursor") : t("builder.capture.pos_options.top")); if (isActiveFile) { - dropdown.addOption("activeTop", "Top of file (after frontmatter)"); - dropdown.addOption("newLineAbove", "New line above cursor"); - dropdown.addOption("newLineBelow", "New line below cursor"); + dropdown.addOption("activeTop", t("builder.capture.pos_options.active_top")); + dropdown.addOption("newLineAbove", t("builder.capture.pos_options.newline_above")); + dropdown.addOption("newLineBelow", t("builder.capture.pos_options.newline_below")); } - dropdown.addOption("after", "After line…"); - dropdown.addOption("bottom", "Bottom of file"); + dropdown.addOption("after", t("builder.capture.pos_options.after")); + dropdown.addOption("bottom", t("builder.capture.pos_options.bottom")); dropdown.setValue(current); dropdown.onChange((value: string) => { const v = value as @@ -438,14 +432,9 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { } private addInsertAfterFields() { - const descText = - "Insert capture after specified text. Accepts format syntax. " + - "Tip: use a heading (starts with #) to target a section. " + - "Blank line handling is configurable below."; - new Setting(this.contentEl) - .setName("Insert after") - .setDesc(descText); + .setName(t("builder.capture.insert_after")) + .setDesc(t("builder.capture.insert_after_desc")); const displayFormatter: FormatDisplayFormatter = new FormatDisplayFormatter( this.app, @@ -453,10 +442,10 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { ); const previewRow = this.contentEl.createDiv({ cls: "qa-preview-row" }); - previewRow.createEl("span", { text: "Preview: ", cls: "qa-preview-label" }); + previewRow.createEl("span", { text: t("builder.common.preview"), cls: "qa-preview-label" }); const previewValue = previewRow.createEl("span"); previewValue.setAttribute("aria-live", "polite"); - previewValue.innerText = "Loading preview…"; + previewValue.innerText = t("builder.common.loading"); createValidatedInput({ app: this.app, @@ -473,7 +462,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { try { previewValue.innerText = await displayFormatter.format(value); } catch { - previewValue.innerText = "Preview unavailable"; + previewValue.innerText = t("builder.common.unavailable"); } }, }); @@ -484,7 +473,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { this.choice.insertAfter.after, ); } catch { - previewValue.innerText = "Preview unavailable"; + previewValue.innerText = t("builder.common.unavailable"); } })(); @@ -497,10 +486,8 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { } new Setting(this.contentEl) - .setName("Inline insertion") - .setDesc( - "Insert captured content on the same line, immediately after the matched text (no newline added).", - ) + .setName(t("builder.capture.inline")) + .setDesc(t("builder.capture.inline_desc")) .addToggle((toggle) => toggle .setValue(!!this.choice.insertAfter?.inline) @@ -528,7 +515,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { if (!inlineEnabled) { const insertAtEndSetting: Setting = new Setting(this.contentEl); insertAtEndSetting - .setName("Insert at end of section") + .setName(t("builder.capture.insert_end_section")) .setDesc( "Place the text at the end of the matched section instead of the top.", ) @@ -575,9 +562,9 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { blankLineModeSetting.setDisabled(insertAtEndEnabled); new Setting(this.contentEl) - .setName("Consider subsections") + .setName(t("builder.capture.consider_subsections")) .setDesc( - "Also include the section’s subsections (requires target to be a heading starting with #). Subsections are headings inside the section.", + "Also include the section’s subsections (requires target to be a heading starting with #).", ) .addToggle((toggle) => toggle @@ -638,8 +625,8 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { private addFormatSetting() { const enableSetting = new Setting(this.contentEl); enableSetting - .setName("Capture format") - .setDesc("Set the format of the capture.") + .setName(t("builder.capture.format")) + .setDesc(t("builder.capture.format_desc")) .addToggle((toggleComponent) => { toggleComponent .setValue(this.choice.format.enabled) @@ -656,10 +643,10 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { ); const previewRow = this.contentEl.createDiv({ cls: "qa-preview-row" }); - previewRow.createEl("span", { text: "Preview: ", cls: "qa-preview-label" }); + previewRow.createEl("span", { text: t("builder.common.preview"), cls: "qa-preview-label" }); const formatDisplay = previewRow.createEl("span"); formatDisplay.setAttr("aria-live", "polite"); - formatDisplay.innerText = "Loading preview…"; + formatDisplay.innerText = t("builder.common.loading"); const formatHandle = createValidatedInput({ app: this.app, @@ -677,7 +664,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { try { formatDisplay.innerText = await displayFormatter.format(value); } catch { - formatDisplay.innerText = "Preview unavailable"; + formatDisplay.innerText = t("builder.common.unavailable"); } }, }); @@ -690,7 +677,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { this.choice.format.format, ); } catch { - formatDisplay.innerText = "Preview unavailable"; + formatDisplay.innerText = t("builder.common.unavailable"); } })(); } @@ -705,7 +692,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { const createFileIfItDoesntExist: Setting = new Setting(this.contentEl); createFileIfItDoesntExist - .setName("Create file if it doesn't exist") + .setName(t("builder.capture.create_if_missing")) .addToggle((toggle) => toggle .setValue(this.choice?.createFileIfItDoesntExist?.enabled) @@ -721,7 +708,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { let templateSelector: TextComponent; const createWithTemplateSetting = new Setting(this.contentEl); createWithTemplateSetting - .setName("Create file with given template.") + .setName(t("builder.capture.create_with_template")) .addToggle((toggle) => toggle .setValue(this.choice.createFileIfItDoesntExist?.createWithTemplate) From 9ff7cfcb6e8adb0363000ae7076c3505df21b02f Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 23:00:09 +0100 Subject: [PATCH 19/27] Update tsconfig.json --- tsconfig.json | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index b5050303..487718d7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,20 +1,22 @@ { - "compilerOptions": { - "baseUrl": ".", - "inlineSourceMap": true, - "inlineSources": true, - "module": "ESNext", - "target": "ES2020", - "allowJs": true, - "noImplicitAny": true, - "moduleResolution": "node", - "importHelpers": true, - "isolatedModules": true, - "types": ["svelte", "node"], - "strictNullChecks": true, - "lib": ["DOM", "ES5", "ES6", "ES7", "ES2022"], - "experimentalDecorators": true, - "verbatimModuleSyntax": true - }, - "include": ["**/*.ts"] + "compilerOptions": { + "baseUrl": ".", + "inlineSourceMap": true, + "inlineSources": true, + "module": "ESNext", + "target": "ES2020", + "allowJs": true, + "noImplicitAny": true, + "moduleResolution": "node", + "importHelpers": true, + "isolatedModules": true, + "types": ["svelte", "node"], + "strictNullChecks": true, + "lib": ["DOM", "ES5", "ES6", "ES7", "ES2022"], + "experimentalDecorators": true, + "verbatimModuleSyntax": true, + "resolveJsonModule": true, + "esModuleInterop": true + }, + "include": ["**/*.ts"] } From 90199ad8f812474e9da000080802d4597de4c714 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 23:06:36 +0100 Subject: [PATCH 20/27] Update fr.json --- src/i18n/locales/fr.json | 94 +++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index fb8390bb..45adba81 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -4,13 +4,10 @@ "reload": "Recharger QuickAdd (dev)", "test": "Tester QuickAdd (dev)" }, - "ribbon": { - "icon": "Ouvrir QuickAdd" - }, "settings": { "headers": { "choices": "Choix & Packages", - "input": "Saisie", + "input": "Saisie (Input)", "templates": "Modèles & Propriétés", "notifications": "Notifications", "globals": "Variables Globales", @@ -21,15 +18,12 @@ "packages": { "name": "Packages", "desc": "Regroupez ou importez des automatisations QuickAdd sous forme de packages réutilisables.", - "export": "Exporter le package...", - "import": "Importer le package..." + "export": "Exporter le package…", + "import": "Importer le package…" }, "announce": { "name": "Annoncer les mises à jour", - "desc": "Affiche les notes de version lors de l'installation d'une nouvelle version.", - "all": "Afficher à chaque nouvelle version", - "major": "Uniquement les versions majeures", - "none": "Ne jamais afficher" + "desc": "Affiche les notes de version lors de l'installation d'une nouvelle version." }, "capture_notif": { "name": "Notifications de capture", @@ -72,7 +66,7 @@ "name": "Désactiver IA & En ligne", "desc": "Empêche le plugin de faire des requêtes externes (comme OpenAI)." }, - "ribbon_options": { + "ribbon": { "name": "Afficher l'icône latérale", "desc": "Ajoute l'icône QuickAdd au ruban latéral gauche." }, @@ -87,6 +81,40 @@ } }, "builder": { + "open": "Ouvrir", + "viewMode": "Mode de vue", + "location": "Emplacement d'ouverture", + "one_page_override": { + "name": "Forçage de la saisie sur une page", + "desc": "Remplace le paramètre global pour ce choix.", + "follow": "Suivre global", + "always": "Toujours", + "never": "Jamais" + }, + "file_path_placeholder": "Chemin du fichier", + "choice_name": "Nom du choix", + "split_direction": "Orientation de la séparation", + "focus_pane": "Focus sur le panneau", + "descriptions": { + "location": "Où ouvrir le fichier.", + "split": "Direction de la séparation.", + "view_mode": "Comment afficher le fichier.", + "focus": "Mettre le focus sur l'onglet." + }, + "options": { + "reuse": "Réutiliser l'onglet", + "tab": "Nouvel onglet", + "split": "Séparer le panneau", + "window": "Nouvelle fenêtre", + "left": "Barre gauche", + "right": "Barre droite", + "source": "Source", + "preview": "Lecture", + "live": "Live Preview", + "default": "Défaut", + "vertical": "Vertical", + "horizontal": "Horizontal" + }, "common": { "template": "Modèle", "location": "Emplacement", @@ -161,40 +189,16 @@ "link": "Lien", "embed": "Intégration (Embed)" } - }, - "open": "Ouvrir", - "viewMode": "Mode d'affichage", - "location": "Emplacement d'ouverture", - "one_page_override": { - "name": "Forçage de la saisie sur une page", - "desc": "Remplace le paramètre global pour ce choix.", - "follow": "Suivre global", - "always": "Toujours", - "never": "Jamais" - }, - "file_path_placeholder": "Chemin du fichier", - "choice_name": "Nom du choix", - "split_direction": "Orientation de la séparation", - "focus_pane": "Focus sur le panneau", - "descriptions": { - "location": "Où ouvrir le fichier.", - "split": "Direction de la séparation.", - "view_mode": "Comment afficher le fichier.", - "focus": "Mettre le focus sur l'onglet." - }, - "options": { - "reuse": "Réutiliser l'onglet", - "tab": "Nouvel onglet", - "split": "Séparer le panneau", - "window": "Nouvelle fenêtre", - "left": "Barre gauche", - "right": "Barre droite", - "source": "Source", - "preview": "Lecture", - "live": "Live Preview", - "default": "Défaut", - "vertical": "Vertical", - "horizontal": "Horizontal" + } + }, + "macro": { + "run_on_startup": "Lancer au démarrage", + "run_on_startup_desc": "Exécute cette macro au démarrage d'Obsidian.", + "renaming": "Renommer", + "branches": { + "then": "Branche Alors (Then)", + "else": "Branche Sinon (Else)", + "edit": "Modifier :" } } } From 4ede40f0fcde489f41d9c53e3a5ce62171710bfa Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 23:06:48 +0100 Subject: [PATCH 21/27] Update en.json --- src/i18n/locales/en.json | 92 +++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 612b9e7b..dc4b9d04 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -4,9 +4,6 @@ "reload": "Reload QuickAdd (dev)", "test": "Test QuickAdd (dev)" }, - "ribbon": { - "icon": "QuickAdd" - }, "settings": { "headers": { "choices": "Choices & Packages", @@ -21,15 +18,12 @@ "packages": { "name": "Packages", "desc": "Bundle or import QuickAdd automations as reusable packages.", - "export": "Export package...", - "import": "Import package..." + "export": "Export package…", + "import": "Import package…" }, "announce": { "name": "Announce Updates", - "desc": "Display release notes when a new version is installed.", - "all": "Show updates on each new release", - "major": "Show updates only on major releases", - "none": "Don't show" + "desc": "Display release notes when a new version is installed." }, "capture_notif": { "name": "Show Capture Notifications", @@ -72,7 +66,7 @@ "name": "Disable AI & Online features", "desc": "Prevents the plugin from making requests to external providers like OpenAI." }, - "ribbon_options": { + "ribbon": { "name": "Show icon in sidebar", "desc": "Add QuickAdd icon to the sidebar ribbon." }, @@ -87,6 +81,40 @@ } }, "builder": { + "open": "Open", + "viewMode": "View Mode", + "location": "File Opening Location", + "one_page_override": { + "name": "One-page input override", + "desc": "Override the global setting for this choice.", + "follow": "Follow global setting", + "always": "Always", + "never": "Never" + }, + "file_path_placeholder": "File path", + "choice_name": "Choice name", + "split_direction": "Split Direction", + "focus_pane": "Focus new pane", + "descriptions": { + "location": "Where to open the file", + "split": "Direction for split panes", + "view_mode": "How to display the opened file", + "focus": "Focus the opened tab immediately after opening" + }, + "options": { + "reuse": "Reuse current tab", + "tab": "New tab", + "split": "Split pane", + "window": "New window", + "left": "Left sidebar", + "right": "Right sidebar", + "source": "Source", + "preview": "Preview", + "live": "Live Preview", + "default": "Default", + "vertical": "Vertical", + "horizontal": "Horizontal" + }, "common": { "template": "Template", "location": "Location", @@ -161,40 +189,16 @@ "link": "Link", "embed": "Embed" } - }, - "open": "Open", - "viewMode": "View Mode", - "location": "File Opening Location", - "one_page_override": { - "name": "One-page input override", - "desc": "Override the global setting for this choice.", - "follow": "Follow global setting", - "always": "Always", - "never": "Never" - }, - "file_path_placeholder": "File path", - "choice_name": "Choice name", - "split_direction": "Split Direction", - "focus_pane": "Focus new pane", - "descriptions": { - "location": "Where to open the file", - "split": "Direction for split panes", - "view_mode": "How to display the opened file", - "focus": "Focus the opened tab immediately after opening" - }, - "options": { - "reuse": "Reuse current tab", - "tab": "New tab", - "split": "Split pane", - "window": "New window", - "left": "Left sidebar", - "right": "Right sidebar", - "source": "Source", - "preview": "Preview", - "live": "Live Preview", - "default": "Default", - "vertical": "Vertical", - "horizontal": "Horizontal" + } + }, + "macro": { + "run_on_startup": "Run on startup", + "run_on_startup_desc": "Execute this macro when Obsidian starts.", + "renaming": "Update name for", + "branches": { + "then": "Then branch", + "else": "Else branch", + "edit": "Edit" } } } From 6ca0f37e135ec0b3b7bad77a14087b406023c74b Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 23:07:24 +0100 Subject: [PATCH 22/27] Update MacroBuilder.ts --- src/gui/MacroGUIs/MacroBuilder.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/gui/MacroGUIs/MacroBuilder.ts b/src/gui/MacroGUIs/MacroBuilder.ts index b7f45b1a..ffa1cfc6 100644 --- a/src/gui/MacroGUIs/MacroBuilder.ts +++ b/src/gui/MacroGUIs/MacroBuilder.ts @@ -13,6 +13,7 @@ import { import type { IConditionalCommand } from "../../types/macros/Conditional/IConditionalCommand"; import { ConditionalCommandSettingsModal } from "./ConditionalCommandSettingsModal"; import { ConditionalBranchEditorModal } from "./ConditionalBranchEditorModal"; +import { t } from "../../i18n/i18n"; function getChoicesAsList(nestedChoices: IChoice[]): IChoice[] { const arr: IChoice[] = []; @@ -83,7 +84,7 @@ export class MacroBuilder extends Modal { headerEl.addEventListener("click", async () => { const newName: string = await GenericInputPrompt.Prompt( this.app, - `Update name for ${this.choice.name}`, + `${t("macro.renaming")} ${this.choice.name}`, this.choice.name, this.choice.name ); @@ -98,8 +99,8 @@ export class MacroBuilder extends Modal { private addRunOnStartupSetting(): void { new Setting(this.contentEl) - .setName("Run on startup") - .setDesc("Execute this macro when Obsidian starts") + .setName(t("macro.run_on_startup")) + .setDesc(t("macro.run_on_startup_desc")) .addToggle(toggle => toggle .setValue(this.choice.runOnStartup) .onChange(value => { @@ -153,12 +154,12 @@ export class MacroBuilder extends Modal { command: IConditionalCommand, branch: "then" | "else" ): Promise { - const title = branch === "then" ? "Then branch" : "Else branch"; + const title = branch === "then" ? t("macro.branches.then") : t("macro.branches.else"); const modal = new ConditionalBranchEditorModal({ app: this.app, plugin: this.plugin, choices: this.choices, - title: `Edit ${title} commands`, + title: `${t("macro.branches.edit")} ${title}`, commands: branch === "then" ? command.thenCommands : command.elseCommands, conditionalHandlers: this.buildConditionalHandlers(), }); From fd937b8185cb5c774b40cb2f544c3a21a865c18c Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 23:19:25 +0100 Subject: [PATCH 23/27] Update en.json --- src/i18n/locales/en.json | 71 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index dc4b9d04..e080479a 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -4,6 +4,9 @@ "reload": "Reload QuickAdd (dev)", "test": "Test QuickAdd (dev)" }, + "ribbon": { + "icon": "QuickAdd" + }, "settings": { "headers": { "choices": "Choices & Packages", @@ -18,8 +21,8 @@ "packages": { "name": "Packages", "desc": "Bundle or import QuickAdd automations as reusable packages.", - "export": "Export package…", - "import": "Import package…" + "export": "Export package...", + "import": "Import package..." }, "announce": { "name": "Announce Updates", @@ -66,7 +69,7 @@ "name": "Disable AI & Online features", "desc": "Prevents the plugin from making requests to external providers like OpenAI." }, - "ribbon": { + "ribbon_options": { "name": "Show icon in sidebar", "desc": "Add QuickAdd icon to the sidebar ribbon." }, @@ -117,6 +120,9 @@ }, "common": { "template": "Template", + "template_path": "Template path", + "template_not_found": "Template not found", + "add": "Add", "location": "Location", "linking": "Linking", "behavior": "Behavior", @@ -130,11 +136,15 @@ "path": "Template Path", "path_desc": "Path to the Template.", "file_name_format": "File name format", + "file_name_format_desc": "Set the file name format.", "folder": "Create in folder", "folder_desc": "Create the file in the specified folder.", + "folder_path": "Folder path", "choose_folder": "Choose folder when creating a new note", "include_subfolders": "Include subfolders", + "include_subfolders_desc": "Get prompted to choose from both the selected folders and their subfolders when creating the note.", "same_folder": "Create in same folder as active file", + "same_folder_desc": "Creates the file in the same folder as the currently active file.", "conflict": "Set default behavior if file already exists", "conflict_desc": "Set default behavior rather then prompting user.", "conflict_options": { @@ -149,12 +159,20 @@ "to": "Capture to", "to_desc": "Target file path. Supports format syntax.", "active_file": "Capture to active file", + "file_path": "File path / format", + "file_path_desc": "Choose a file or use format syntax (e.g., {{DATE}})", + "file_name_format": "File name format", + "open_file_desc": "Open the captured file.", "task": "Task", "task_desc": "Formats the value as a task.", "format": "Capture format", "format_desc": "Set the format of the capture.", + "format_required": "Capture format is required when enabled", "create_if_missing": "Create file if it doesn't exist", + "create_if_missing_tooltip": "Create file if it doesn't exist", "create_with_template": "Create file with given template", + "templater_after_capture": "Run Templater on entire destination file after capture", + "templater_after_capture_desc": "Advanced / legacy: this executes any `<% %>` anywhere in the destination file.", "write_pos": "Write position", "write_pos_desc": "Where to place the capture in the file.", "pos_options": { @@ -166,18 +184,45 @@ "newline_above": "New line above", "newline_below": "New line below" }, + "selection_options": { + "use": "Use selection", + "ignore": "Ignore selection" + }, "insert_after": "Insert after", "insert_after_desc": "Insert capture after specified text. Accepts format syntax.", + "insert_after_required": "Insert after text is required", "inline": "Inline insertion", "inline_desc": "Insert captured content on the same line.", + "replace_existing": "Replace existing value", + "replace_existing_desc": "Replace everything after the matched text up to end-of-line.", "insert_end_section": "Insert at end of section", - "consider_subsections": "Consider subsections" + "insert_end_section_desc": "Place the text at the end of the matched section instead of the top.", + "blank_lines_after_match": "Blank lines after match", + "blank_lines_desc": "Controls whether Insert After skips existing blank lines after the matched line.", + "blank_lines_not_used": "Not used when inserting at end of section.", + "blank_lines_options": { + "auto": "Auto (headings only)", + "skip": "Always skip", + "none": "Never skip" + }, + "consider_subsections": "Consider subsections", + "consider_subsections_desc": "Also include the section's subsections (requires target to be a heading starting with #).", + "consider_subsections_notice": "Consider subsections requires the target to be a heading (starts with #)", + "create_line_if_not_found": "Create line if not found", + "create_line_if_not_found_desc": "Creates the 'insert after' line if it is not found.", + "position_options": { + "top": "Top", + "bottom": "Bottom", + "cursor": "Cursor" + } }, "append_link": { "name": "Link to file", "desc": "Choose how QuickAdd should insert a link to the file in the current note.", "placement": "Link placement", + "placement_desc": "Where to place the link when appending", "type": "Link type", + "type_desc": "Choose whether replacing the selection should insert a link or an embed.", "options": { "required": "Enabled (requires active file)", "optional": "Enabled (skip if no active file)", @@ -199,6 +244,24 @@ "then": "Then branch", "else": "Else branch", "edit": "Edit" + }, + "abort": "Macro execution aborted", + "input_cancelled": "Input cancelled by user", + "errors": { + "no_commands": "No commands in the macro for choice: ", + "load_script_failed": "Failed to load user script: ", + "run_script_failed": "Failed to run user script: ", + "script_invalid": "User script is invalid for choice: ", + "script_empty": "User script is an empty object for choice: ", + "choice_not_found": "Choice could not be found.", + "nested_choice_invalid": "Choice is invalid in: ", + "ai_disabled": "Blocking request to OpenAI: Online features are disabled in settings.", + "model_not_found": "Model not found: ", + "provider_not_found": "Provider not found for model: ", + "conditional_boolean": "Conditional script must return a boolean result: ", + "open_file_traversal": "OpenFile: Path traversal not allowed in ", + "open_file_missing": "OpenFile: Does not exist or is not a file: ", + "open_file_failed": "OpenFile: Failed to open file: " } } } From 80c4773853110320e68fa5aa77c2c9fb8684c916 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 23:19:49 +0100 Subject: [PATCH 24/27] Update fr.json --- src/i18n/locales/fr.json | 67 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index 45adba81..18f2758f 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -4,6 +4,9 @@ "reload": "Recharger QuickAdd (dev)", "test": "Tester QuickAdd (dev)" }, + "ribbon": { + "icon": "QuickAdd" + }, "settings": { "headers": { "choices": "Choix & Packages", @@ -66,7 +69,7 @@ "name": "Désactiver IA & En ligne", "desc": "Empêche le plugin de faire des requêtes externes (comme OpenAI)." }, - "ribbon": { + "ribbon_options": { "name": "Afficher l'icône latérale", "desc": "Ajoute l'icône QuickAdd au ruban latéral gauche." }, @@ -117,6 +120,9 @@ }, "common": { "template": "Modèle", + "template_path": "Chemin du modèle", + "template_not_found": "Modèle introuvable", + "add": "Ajouter", "location": "Emplacement", "linking": "Liaison (Links)", "behavior": "Comportement", @@ -130,11 +136,15 @@ "path": "Chemin du modèle", "path_desc": "Chemin vers le fichier modèle.", "file_name_format": "Format du nom de fichier", + "file_name_format_desc": "Définir le format du nom de fichier.", "folder": "Créer dans le dossier", "folder_desc": "Créer le fichier dans ce dossier.", + "folder_path": "Chemin du dossier", "choose_folder": "Choisir le dossier lors de la création", "include_subfolders": "Inclure les sous-dossiers", + "include_subfolders_desc": "Proposer de choisir parmi les dossiers sélectionnés et leurs sous-dossiers.", "same_folder": "Créer dans le même dossier que le fichier actif", + "same_folder_desc": "Crée le fichier dans le même dossier que le fichier actuellement actif.", "conflict": "Comportement si le fichier existe déjà", "conflict_desc": "Action par défaut au lieu de demander à l'utilisateur.", "conflict_options": { @@ -149,12 +159,20 @@ "to": "Capturer vers", "to_desc": "Chemin du fichier cible. Supporte la syntaxe de format.", "active_file": "Capturer vers le fichier actif", + "file_path": "Chemin / Format", + "file_path_desc": "Choisir un fichier ou utiliser une syntaxe (ex: {{DATE}})", + "file_name_format": "Format du nom de fichier", + "open_file_desc": "Ouvrir le fichier capturé.", "task": "Tâche", "task_desc": "Formate la valeur comme une tâche à cocher.", "format": "Format de capture", "format_desc": "Définir le format du texte capturé.", + "format_required": "Le format de capture est requis s'il est activé", "create_if_missing": "Créer le fichier s'il n'existe pas", + "create_if_missing_tooltip": "Créer le fichier s'il n'existe pas", "create_with_template": "Créer avec un modèle spécifique", + "templater_after_capture": "Lancer Templater après la capture", + "templater_after_capture_desc": "Avancé : exécute les codes `<% %>` dans tout le fichier de destination.", "write_pos": "Position d'écriture", "write_pos_desc": "Où placer la capture dans le fichier.", "pos_options": { @@ -166,18 +184,45 @@ "newline_above": "Nouvelle ligne au-dessus", "newline_below": "Nouvelle ligne en-dessous" }, + "selection_options": { + "use": "Utiliser la sélection", + "ignore": "Ignorer la sélection" + }, "insert_after": "Insérer après", "insert_after_desc": "Insérer après le texte spécifié. Accepte la syntaxe de format.", + "insert_after_required": "Le texte 'Insérer après' est requis", "inline": "Insertion en ligne (Inline)", "inline_desc": "Insère sur la même ligne, juste après le texte trouvé.", + "replace_existing": "Remplacer la valeur existante", + "replace_existing_desc": "Remplace tout après le texte trouvé jusqu'à la fin de la ligne.", "insert_end_section": "Insérer à la fin de la section", - "consider_subsections": "Inclure les sous-sections" + "insert_end_section_desc": "Place le texte à la fin de la section trouvée au lieu du début.", + "blank_lines_after_match": "Lignes vides après correspondance", + "blank_lines_desc": "Contrôle si l'insertion doit sauter les lignes vides existantes.", + "blank_lines_not_used": "Non utilisé lors de l'insertion en fin de section.", + "blank_lines_options": { + "auto": "Auto (titres uniquement)", + "skip": "Toujours sauter", + "none": "Ne jamais sauter" + }, + "consider_subsections": "Inclure les sous-sections", + "consider_subsections_desc": "Inclure aussi les sous-sections (nécessite que la cible soit un titre #).", + "consider_subsections_notice": "L'option nécessite que la cible soit un titre (commence par #)", + "create_line_if_not_found": "Créer la ligne si non trouvée", + "create_line_if_not_found_desc": "Crée la ligne 'Insérer après' si elle n'existe pas.", + "position_options": { + "top": "Haut", + "bottom": "Bas", + "cursor": "Curseur" + } }, "append_link": { "name": "Lien vers le fichier créé/capturé", "desc": "Insérer un lien vers ce fichier dans la note actuelle.", "placement": "Placement du lien", + "placement_desc": "Où placer le lien lors de l'ajout.", "type": "Type de lien", + "type_desc": "Choisir entre un lien simple ou une intégration (embed) lors du remplacement.", "options": { "required": "Activé (requiert un fichier actif)", "optional": "Activé (ignorer si aucun fichier actif)", @@ -199,6 +244,24 @@ "then": "Branche Alors (Then)", "else": "Branche Sinon (Else)", "edit": "Modifier :" + }, + "abort": "Exécution de la macro interrompue", + "input_cancelled": "Saisie annulée par l'utilisateur", + "errors": { + "no_commands": "Aucune commande dans la macro pour le choix : ", + "load_script_failed": "Échec du chargement du script utilisateur : ", + "run_script_failed": "Échec de l'exécution du script utilisateur : ", + "script_invalid": "Le script utilisateur est invalide pour le choix : ", + "script_empty": "Le script utilisateur est un objet vide pour le choix : ", + "choice_not_found": "Le choix n'a pas pu être trouvé.", + "nested_choice_invalid": "Le choix imbriqué est invalide dans : ", + "ai_disabled": "Requête OpenAI bloquée : Les fonctionnalités en ligne sont désactivées dans les paramètres.", + "model_not_found": "Modèle introuvable : ", + "provider_not_found": "Fournisseur introuvable pour le modèle : ", + "conditional_boolean": "Le script conditionnel doit renvoyer un booléen : ", + "open_file_traversal": "OpenFile : Traversée de chemin interdite dans ", + "open_file_missing": "OpenFile : Fichier inexistant ou invalide : ", + "open_file_failed": "OpenFile : Échec de l'ouverture du fichier : " } } } From 746360fc9693f620147729811ea59ef54cb35ee1 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 23:20:13 +0100 Subject: [PATCH 25/27] Update captureChoiceBuilder.ts --- src/gui/ChoiceBuilder/captureChoiceBuilder.ts | 76 ++++++++----------- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/src/gui/ChoiceBuilder/captureChoiceBuilder.ts b/src/gui/ChoiceBuilder/captureChoiceBuilder.ts index 655e719a..51ade8ff 100644 --- a/src/gui/ChoiceBuilder/captureChoiceBuilder.ts +++ b/src/gui/ChoiceBuilder/captureChoiceBuilder.ts @@ -65,7 +65,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { // Behavior new Setting(this.contentEl).setName(t("builder.common.behavior")).setHeading(); if (!this.choice.captureToActiveFile) { - this.addOpenFileSetting("Open the captured file."); + this.addOpenFileSetting(t("builder.capture.open_file_desc")); if (this.choice.openFile) { this.addFileOpeningSetting("captured"); @@ -78,10 +78,8 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { private addTemplaterAfterCaptureSetting() { new Setting(this.contentEl) - .setName("Run Templater on entire destination file after capture") - .setDesc( - "Advanced / legacy: this executes any `<% %>` anywhere in the destination file (including inside code blocks).", - ) + .setName(t("builder.capture.templater_after_capture")) + .setDesc(t("builder.capture.templater_after_capture_desc")) .addToggle((toggle) => { toggle.setValue(this.choice.templater?.afterCapture === "wholeFile"); toggle.onChange((value) => { @@ -100,8 +98,8 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { .addDropdown((dropdown) => { dropdown.addOptions({ "": t("builder.one_page_override.follow"), - enabled: "Use selection", - disabled: "Ignore selection", + enabled: t("builder.capture.selection_options.use"), + disabled: t("builder.capture.selection_options.ignore"), }); const override = this.choice.useSelectionAsCaptureValue; dropdown.setValue( @@ -154,8 +152,8 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { captureToContainer.createDiv("captureToFileContainer"); new Setting(captureToFileContainer) - .setName("File path / format") - .setDesc("Choose a file or use format syntax (e.g., {{DATE}})"); + .setName(t("builder.capture.file_path")) + .setDesc(t("builder.capture.file_path_desc")); const displayFormatter: FileNameDisplayFormatter = new FileNameDisplayFormatter(this.app, this.plugin); @@ -175,7 +173,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { app: this.app, parent: captureToFileContainer, initialValue: this.choice.captureTo, - placeholder: "File name format", + placeholder: t("builder.capture.file_name_format"), suggestions: markdownFilesAndFormatSyntax, maxSuggestions: 50, attachSuggesters: [ @@ -269,7 +267,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { const placementSetting: Setting = new Setting(this.contentEl); placementSetting .setName(t("builder.append_link.placement")) - .setDesc("Where to place the link when appending") + .setDesc(t("builder.append_link.placement_desc")) .addDropdown((dropdown) => { dropdown.addOption("replaceSelection", t("builder.append_link.options.replace")); dropdown.addOption("afterSelection", t("builder.append_link.options.after")); @@ -306,7 +304,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { const linkTypeSetting: Setting = new Setting(this.contentEl); linkTypeSetting .setName(t("builder.append_link.type")) - .setDesc("Choose whether to insert a regular link or an embed when replacing the selection.") + .setDesc(t("builder.append_link.type_desc")) .addDropdown((dropdown) => { dropdown.addOption("link", t("builder.append_link.options.link")); dropdown.addOption("embed", t("builder.append_link.options.embed")); @@ -451,9 +449,9 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { app: this.app, parent: this.contentEl, initialValue: this.choice.insertAfter.after, - placeholder: "Insert after", + placeholder: t("builder.capture.insert_after"), required: true, - requiredMessage: "Insert after text is required", + requiredMessage: t("builder.capture.insert_after_required"), attachSuggesters: [ (el) => new FormatSyntaxSuggester(this.app, el, this.plugin), ], @@ -499,8 +497,8 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { if (this.choice.insertAfter.inline) { new Setting(this.contentEl) - .setName("Replace existing value") - .setDesc("Replace everything after the matched text up to end-of-line.") + .setName(t("builder.capture.replace_existing")) + .setDesc(t("builder.capture.replace_existing_desc")) .addToggle((toggle) => toggle .setValue(!!this.choice.insertAfter?.replaceExisting) @@ -516,9 +514,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { const insertAtEndSetting: Setting = new Setting(this.contentEl); insertAtEndSetting .setName(t("builder.capture.insert_end_section")) - .setDesc( - "Place the text at the end of the matched section instead of the top.", - ) + .setDesc(t("builder.capture.insert_end_section_desc")) .addToggle((toggle) => toggle .setValue(this.choice.insertAfter?.insertAtEnd) @@ -532,22 +528,20 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { this.choice.insertAfter.blankLineAfterMatchMode = "auto"; } - const blankLineModeDesc = - "Controls whether Insert After skips existing blank lines after the matched line."; const insertAtEndEnabled = !!this.choice.insertAfter?.insertAtEnd; const blankLineModeSetting: Setting = new Setting(this.contentEl); blankLineModeSetting - .setName("Blank lines after match") + .setName(t("builder.capture.blank_lines_after_match")) .setDesc( insertAtEndEnabled - ? "Not used when inserting at end of section." - : blankLineModeDesc, + ? t("builder.capture.blank_lines_not_used") + : t("builder.capture.blank_lines_desc"), ) .addDropdown((dropdown) => { dropdown - .addOption("auto", "Auto (headings only)") - .addOption("skip", "Always skip") - .addOption("none", "Never skip") + .addOption("auto", t("builder.capture.blank_lines_options.auto")) + .addOption("skip", t("builder.capture.blank_lines_options.skip")) + .addOption("none", t("builder.capture.blank_lines_options.none")) .setValue( this.choice.insertAfter?.blankLineAfterMatchMode ?? "auto", ) @@ -563,9 +557,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { new Setting(this.contentEl) .setName(t("builder.capture.consider_subsections")) - .setDesc( - "Also include the section’s subsections (requires target to be a heading starting with #).", - ) + .setDesc(t("builder.capture.consider_subsections_desc")) .addToggle((toggle) => toggle .setValue(this.choice.insertAfter?.considerSubsections) @@ -583,9 +575,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { this.choice.insertAfter.considerSubsections = false; // reset the toggle to match state and inform user toggle.setValue(false); - new Notice( - "Consider subsections requires the target to be a heading (starts with #)", - ); + new Notice(t("builder.capture.consider_subsections_notice")); } }), ); @@ -593,8 +583,8 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { const createLineIfNotFound: Setting = new Setting(this.contentEl); createLineIfNotFound - .setName("Create line if not found") - .setDesc("Creates the 'insert after' line if it is not found.") + .setName(t("builder.capture.create_line_if_not_found")) + .setDesc(t("builder.capture.create_line_if_not_found_desc")) .addToggle((toggle) => { if (!this.choice.insertAfter?.createIfNotFound) this.choice.insertAfter.createIfNotFound = false; // Set to default @@ -611,9 +601,9 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { CREATE_IF_NOT_FOUND_TOP; // Set to default dropdown - .addOption(CREATE_IF_NOT_FOUND_TOP, "Top") - .addOption(CREATE_IF_NOT_FOUND_BOTTOM, "Bottom") - .addOption(CREATE_IF_NOT_FOUND_CURSOR, "Cursor") + .addOption(CREATE_IF_NOT_FOUND_TOP, t("builder.capture.position_options.top")) + .addOption(CREATE_IF_NOT_FOUND_BOTTOM, t("builder.capture.position_options.bottom")) + .addOption(CREATE_IF_NOT_FOUND_CURSOR, t("builder.capture.position_options.cursor")) .setValue(this.choice.insertAfter?.createIfNotFoundLocation) .onChange( (value) => @@ -653,9 +643,9 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { parent: this.contentEl, inputKind: "textarea", initialValue: this.choice.format.format, - placeholder: "Format", + placeholder: t("builder.capture.format"), required: this.choice.format.enabled, - requiredMessage: "Capture format is required when enabled", + requiredMessage: t("builder.capture.format_required"), attachSuggesters: [ (el) => new FormatSyntaxSuggester(this.app, el, this.plugin), ], @@ -696,7 +686,7 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { .addToggle((toggle) => toggle .setValue(this.choice?.createFileIfItDoesntExist?.enabled) - .setTooltip("Create file if it doesn't exist") + .setTooltip(t("builder.capture.create_if_missing_tooltip")) .onChange((value) => { this.choice.createFileIfItDoesntExist.enabled = value; this.reload(); @@ -726,13 +716,13 @@ export class CaptureChoiceBuilder extends ChoiceBuilder { app: this.app, parent: this.contentEl, initialValue: this.choice?.createFileIfItDoesntExist?.template ?? "", - placeholder: "Template path", + placeholder: t("builder.common.template_path"), suggestions: templateFilePaths, maxSuggestions: 50, validator: (raw) => { const v = raw.trim(); if (!v) return true; - return templateFilePaths.includes(v) || "Template not found"; + return templateFilePaths.includes(v) || t("builder.common.template_not_found"); }, onChange: (value) => { this.choice.createFileIfItDoesntExist.template = value; From f8d1451cffde486eae57c5d4c6ecdb8bae3b29da Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 23:21:12 +0100 Subject: [PATCH 26/27] Update main.ts --- src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 904f65ca..3801a97d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -23,7 +23,7 @@ import { CommandType } from "./types/macros/CommandType"; import { InfiniteAIAssistantCommandSettingsModal } from "./gui/MacroGUIs/AIAssistantInfiniteCommandSettingsModal"; import { FieldSuggestionCache } from "./utils/FieldSuggestionCache"; import { isMajorUpdate } from "./utils/semver"; -import { t } from "./i18n/i18n"; // Ajout de l'import +import { t } from "./i18n/i18n"; // Parameters prefixed with `value-` get used as named values for the executed choice type CaptureValueParameters = { [key in `value-${string}`]?: string }; From c90d015bafb764479c9624a1df2efbe2527379e0 Mon Sep 17 00:00:00 2001 From: Amato21 Date: Mon, 29 Dec 2025 23:21:36 +0100 Subject: [PATCH 27/27] Update quickAddSettingsTab.ts --- src/quickAddSettingsTab.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/quickAddSettingsTab.ts b/src/quickAddSettingsTab.ts index 97704ced..5a44a4d6 100644 --- a/src/quickAddSettingsTab.ts +++ b/src/quickAddSettingsTab.ts @@ -139,25 +139,32 @@ export class QuickAddSettingsTab extends PluginSettingTab { if (__DEV_GIT_BRANCH__ !== null) { const branchDiv = infoContainer.createDiv(); - branchDiv.innerHTML = `${t("settings.dev.branch")}: ${__DEV_GIT_BRANCH__}`; + const branchLabel = branchDiv.createEl("strong"); + branchLabel.textContent = `${t("settings.dev.branch")}:`; + branchDiv.appendText(` ${__DEV_GIT_BRANCH__}`); branchDiv.style.marginBottom = "5px"; } if (__DEV_GIT_COMMIT__ !== null) { const commitDiv = infoContainer.createDiv(); - commitDiv.innerHTML = `${t("settings.dev.commit")}: ${__DEV_GIT_COMMIT__}`; + const commitLabel = commitDiv.createEl("strong"); + commitLabel.textContent = `${t("settings.dev.commit")}:`; + commitDiv.appendText(` ${__DEV_GIT_COMMIT__}`); commitDiv.style.marginBottom = "5px"; } if (__DEV_GIT_DIRTY__ !== null) { const statusDiv = infoContainer.createDiv(); + const statusLabel = statusDiv.createEl("strong"); + statusLabel.textContent = `${t("settings.dev.changes")}:`; const statusText = __DEV_GIT_DIRTY__ ? `${t("settings.dev.yes")} (${t("settings.dev.changes")})` : t("settings.dev.no"); - const statusColor = __DEV_GIT_DIRTY__ + const statusSpan = statusDiv.createEl("span"); + statusSpan.textContent = ` ${statusText}`; + statusSpan.style.color = __DEV_GIT_DIRTY__ ? "var(--text-warning)" : "var(--text-success)"; - statusDiv.innerHTML = `${t("settings.dev.changes")}: ${statusText}`; } }); }