callumalpass_tasknotes/scripts/add-translations.mjs
callumalpass 73fcaf30ea feat(i18n): complete missing translations and internationalize hardcoded strings
Complete missing translations for all languages:
- de, es, fr: All missing keys translated (100% coverage for existing keys)
- ja, ru, zh: Missing keys translated and stale keys updated

Add 159 new translation keys for previously hardcoded strings:
- modals.deviceCode (12 keys)
- modals.icsEventInfo (18 keys)
- modals.timeblockInfo (23 keys)
- modals.timeblockCreation (20 keys)
- modals.icsNoteCreation (16 keys)
- views.stats (25 keys)
- views.agenda, views.notes, views.kanban (additional keys)
- components.dateContextMenu (10 keys)
- components.subgroupMenuBuilder (10 keys)
- notices (23 keys)

Update source files to use i18n:
- 5 modal files
- 5 view files
- 3 component files
- OAuthService, FilterBar

Translation status:
- de, es: 100% (1704/1704)
- fr, ja, ru, zh: ~90% of new keys translated
2025-11-02 20:30:20 +11:00

662 lines
45 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from 'fs';
import path from 'path';
const RESOURCES_DIR = path.resolve('src/i18n/resources');
// Translation mappings
const translations = {
fr: {
"views.agenda.empty.helpText": "Créez des tâches avec des dates d'échéance ou programmées, ou ajoutez des notes pour les voir ici.",
"views.agenda.contextMenu.showOverdueSection": "Afficher la section en retard",
"views.agenda.contextMenu.showNotes": "Afficher les notes",
"views.agenda.contextMenu.calendarSubscriptions": "Abonnements au calendrier",
"views.agenda.periods.thisWeek": "Cette semaine",
"views.agenda.tipPrefix": "Astuce : ",
"views.notes.refreshingButton": "Actualisation...",
"views.notes.empty.helpText": "Aucune note trouvée pour la date sélectionnée. Essayez de sélectionner une date différente dans la vue Mini Calendrier ou créez quelques notes.",
"views.notes.loading": "Chargement des notes...",
"views.notes.refreshButtonAriaLabel": "Actualiser la liste des notes",
"views.kanban.uncategorized": "Non catégorisé",
"views.kanban.noProject": "Aucun projet",
"views.kanban.columnTitle": "Sans titre",
"notices.icsNoteCreatedSuccess": "Note créée avec succès",
"notices.icsCreationModalOpenFailed": "Échec de l'ouverture de la modale de création",
"notices.icsNoteLinkSuccess": "Note \"{fileName}\" liée à l'événement ICS",
"notices.icsTaskCreatedSuccess": "Tâche créée : {title}",
"notices.icsRelatedItemsRefreshed": "Notes associées actualisées",
"notices.icsFileNotFound": "Fichier introuvable ou invalide",
"notices.icsFileOpenFailed": "Échec de l'ouverture du fichier",
"notices.timeblockAttachmentExists": "\"{fileName}\" est déjà attaché",
"notices.timeblockAttachmentAdded": "\"{fileName}\" ajouté comme pièce jointe",
"notices.timeblockAttachmentRemoved": "\"{fileName}\" retiré des pièces jointes",
"notices.timeblockFileTypeNotSupported": "Impossible d'ouvrir \"{fileName}\" - type de fichier non pris en charge",
"notices.timeblockTitleRequired": "Veuillez saisir un titre pour le bloc de temps",
"notices.timeblockUpdatedSuccess": "Bloc de temps \"{title}\" mis à jour avec succès",
"notices.timeblockUpdateFailed": "Échec de la mise à jour du bloc de temps. Consultez la console pour plus de détails.",
"notices.timeblockDeletedSuccess": "Bloc de temps \"{title}\" supprimé avec succès",
"notices.timeblockDeleteFailed": "Échec de la suppression du bloc de temps. Consultez la console pour plus de détails.",
"notices.timeblockRequiredFieldsMissing": "Veuillez remplir tous les champs requis",
"notices.agendaLoadingFailed": "Erreur lors du chargement de l'agenda. Veuillez essayer d'actualiser.",
"notices.statsLoadingFailed": "Erreur lors du chargement des détails du projet.",
"modals.deviceCode.title": "Autorisation Google Calendar",
"modals.deviceCode.instructions.intro": "Pour connecter votre Google Calendar, veuillez suivre ces étapes :",
"modals.deviceCode.steps.open": "Ouvrir",
"modals.deviceCode.steps.inBrowser": "dans votre navigateur",
"modals.deviceCode.steps.enterCode": "Entrez ce code lorsque demandé :",
"modals.deviceCode.steps.signIn": "Connectez-vous avec votre compte Google et accordez l'accès",
"modals.deviceCode.steps.returnToObsidian": "Retournez à Obsidian (cette fenêtre se fermera automatiquement)",
"modals.deviceCode.codeLabel": "Votre code :",
"modals.deviceCode.copyCodeAriaLabel": "Copier le code",
"modals.deviceCode.waitingForAuthorization": "En attente d'autorisation...",
"modals.deviceCode.openBrowserButton": "Ouvrir le navigateur",
"modals.deviceCode.cancelButton": "Annuler",
"modals.deviceCode.expiresMinutesSeconds": "Le code expire dans {minutes}m {seconds}s",
"modals.deviceCode.expiresSeconds": "Le code expire dans {seconds}s",
"modals.icsEventInfo.calendarEventHeading": "Événement de calendrier",
"modals.icsEventInfo.titleLabel": "Titre",
"modals.icsEventInfo.calendarLabel": "Calendrier",
"modals.icsEventInfo.dateTimeLabel": "Date et heure",
"modals.icsEventInfo.locationLabel": "Lieu",
"modals.icsEventInfo.descriptionLabel": "Description",
"modals.icsEventInfo.urlLabel": "URL",
"modals.icsEventInfo.relatedNotesHeading": "Notes et tâches associées",
"modals.icsEventInfo.noRelatedItems": "Aucune note ou tâche associée trouvée pour cet événement.",
"modals.icsEventInfo.typeTask": "Tâche",
"modals.icsEventInfo.typeNote": "Note",
"modals.icsEventInfo.actionsHeading": "Actions",
"modals.icsEventInfo.createFromEventLabel": "Créer à partir de l'événement",
"modals.icsEventInfo.createFromEventDesc": "Créer une nouvelle note ou tâche à partir de cet événement de calendrier",
"modals.icsEventInfo.linkExistingLabel": "Lier existant",
"modals.icsEventInfo.linkExistingDesc": "Lier une note existante à cet événement de calendrier",
"modals.timeblockInfo.editHeading": "Modifier le bloc de temps",
"modals.timeblockInfo.dateTimeLabel": "Date et heure : ",
"modals.timeblockInfo.titleLabel": "Titre",
"modals.timeblockInfo.titleDesc": "Titre de votre bloc de temps",
"modals.timeblockInfo.titlePlaceholder": "ex., Session de travail approfondi",
"modals.timeblockInfo.descriptionLabel": "Description",
"modals.timeblockInfo.descriptionDesc": "Description optionnelle du bloc de temps",
"modals.timeblockInfo.descriptionPlaceholder": "Concentrez-vous sur les nouvelles fonctionnalités, sans interruptions",
"modals.timeblockInfo.colorLabel": "Couleur",
"modals.timeblockInfo.colorDesc": "Couleur optionnelle pour le bloc de temps",
"modals.timeblockInfo.colorPlaceholder": "#3b82f6",
"modals.timeblockInfo.attachmentsLabel": "Pièces jointes",
"modals.timeblockInfo.attachmentsDesc": "Fichiers ou notes liés à ce bloc de temps",
"modals.timeblockInfo.addAttachmentButton": "Ajouter une pièce jointe",
"modals.timeblockInfo.addAttachmentTooltip": "Sélectionnez un fichier ou une note en utilisant la recherche floue",
"modals.timeblockInfo.deleteButton": "Supprimer le bloc de temps",
"modals.timeblockInfo.saveButton": "Enregistrer les modifications",
"modals.timeblockInfo.deleteConfirmationTitle": "Supprimer le bloc de temps",
"modals.timeblockCreation.heading": "Créer un bloc de temps",
"modals.timeblockCreation.dateLabel": "Date : ",
"modals.timeblockCreation.titleLabel": "Titre",
"modals.timeblockCreation.titleDesc": "Titre de votre bloc de temps",
"modals.timeblockCreation.titlePlaceholder": "ex., Session de travail approfondi",
"modals.timeblockCreation.startTimeLabel": "Heure de début",
"modals.timeblockCreation.startTimeDesc": "Quand le bloc de temps commence",
"modals.timeblockCreation.startTimePlaceholder": "09:00",
"modals.timeblockCreation.endTimeLabel": "Heure de fin",
"modals.timeblockCreation.endTimeDesc": "Quand le bloc de temps se termine",
"modals.timeblockCreation.endTimePlaceholder": "11:00",
"modals.timeblockCreation.descriptionLabel": "Description",
"modals.timeblockCreation.descriptionDesc": "Description optionnelle du bloc de temps",
"modals.timeblockCreation.descriptionPlaceholder": "Concentrez-vous sur les nouvelles fonctionnalités, sans interruptions",
"modals.timeblockCreation.colorLabel": "Couleur",
"modals.timeblockCreation.colorDesc": "Couleur optionnelle pour le bloc de temps",
"modals.timeblockCreation.colorPlaceholder": "#3b82f6",
"modals.timeblockCreation.attachmentsLabel": "Pièces jointes",
"modals.timeblockCreation.attachmentsDesc": "Fichiers ou notes à lier à ce bloc de temps",
"modals.timeblockCreation.addAttachmentButton": "Ajouter une pièce jointe",
"modals.timeblockCreation.addAttachmentTooltip": "Sélectionnez un fichier ou une note en utilisant la recherche floue",
"modals.timeblockCreation.createButton": "Créer un bloc de temps",
"modals.icsNoteCreation.heading": "Créer à partir d'un événement ICS",
"modals.icsNoteCreation.titleLabel": "Titre",
"modals.icsNoteCreation.titleDesc": "Titre du nouveau contenu",
"modals.icsNoteCreation.folderLabel": "Dossier",
"modals.icsNoteCreation.folderDesc": "Dossier de destination (laisser vide pour la racine du coffre)",
"modals.icsNoteCreation.folderPlaceholder": "dossier/sous-dossier",
"modals.icsNoteCreation.createButton": "Créer",
"modals.icsNoteCreation.startLabel": "Début : ",
"modals.icsNoteCreation.endLabel": "Fin : ",
"modals.icsNoteCreation.locationLabel": "Lieu : ",
"modals.icsNoteCreation.calendarLabel": "Calendrier : ",
"modals.icsNoteCreation.useTemplateLabel": "Utiliser un modèle",
"modals.icsNoteCreation.useTemplateDesc": "Appliquer un modèle lors de la création du contenu",
"modals.icsNoteCreation.templatePathLabel": "Chemin du modèle",
"modals.icsNoteCreation.templatePathDesc": "Chemin vers le fichier de modèle",
"modals.icsNoteCreation.templatePathPlaceholder": "templates/ics-note-template.md",
"ui.filterBar.subgroupLabel": "SOUS-GROUPE",
"components.dateContextMenu.weekdays": "Jours de semaine",
"components.dateContextMenu.clearDate": "Effacer la date",
"components.dateContextMenu.today": "Aujourd'hui",
"components.dateContextMenu.tomorrow": "Demain",
"components.dateContextMenu.thisWeekend": "Ce week-end",
"components.dateContextMenu.nextWeek": "La semaine prochaine",
"components.dateContextMenu.nextMonth": "Le mois prochain",
"components.dateContextMenu.setDateTime": "Définir la date et l'heure",
"components.dateContextMenu.dateLabel": "Date",
"components.dateContextMenu.timeLabel": "Heure (optionnelle)",
"components.subgroupMenuBuilder.none": "Aucun",
"components.subgroupMenuBuilder.status": "Statut",
"components.subgroupMenuBuilder.priority": "Priorité",
"components.subgroupMenuBuilder.context": "Contexte",
"components.subgroupMenuBuilder.project": "Projet",
"components.subgroupMenuBuilder.dueDate": "Date d'échéance",
"components.subgroupMenuBuilder.scheduledDate": "Date programmée",
"components.subgroupMenuBuilder.tags": "Étiquettes",
"components.subgroupMenuBuilder.completedDate": "Date de finalisation",
"components.subgroupMenuBuilder.subgroup": "SOUS-GROUPE",
},
ja: {
// Japanese translations with polite です/ます form
"views.agenda.empty.helpText": "期限や予定日を持つタスクを作成するか、ノートを追加してここに表示します。",
"views.agenda.contextMenu.showOverdueSection": "期限切れセクションを表示",
"views.agenda.contextMenu.showNotes": "ノートを表示",
"views.agenda.contextMenu.calendarSubscriptions": "カレンダーサブスクリプション",
"views.agenda.periods.thisWeek": "今週",
"views.agenda.tipPrefix": "ヒント:",
"views.notes.refreshingButton": "更新中...",
"views.notes.empty.helpText": "選択した日付のノートが見つかりませんでした。ミニカレンダービューで別の日付を選択するか、ノートを作成してください。",
"views.notes.loading": "ノートを読み込み中...",
"views.notes.refreshButtonAriaLabel": "ノートリストを更新",
"views.kanban.uncategorized": "未分類",
"views.kanban.noProject": "プロジェクトなし",
"views.kanban.columnTitle": "無題",
"notices.icsNoteCreatedSuccess": "ノートが正常に作成されました",
"notices.icsCreationModalOpenFailed": "作成モーダルを開けませんでした",
"notices.icsNoteLinkSuccess": "ノート「{fileName}」をICSイベントにリンクしました",
"notices.icsTaskCreatedSuccess": "タスクを作成しました:{title}",
"notices.icsRelatedItemsRefreshed": "関連ノートを更新しました",
"notices.icsFileNotFound": "ファイルが見つからないか無効です",
"notices.icsFileOpenFailed": "ファイルを開けませんでした",
"notices.timeblockAttachmentExists": "「{fileName}」は既に添付されています",
"notices.timeblockAttachmentAdded": "「{fileName}」を添付ファイルとして追加しました",
"notices.timeblockAttachmentRemoved": "「{fileName}」を添付ファイルから削除しました",
"notices.timeblockFileTypeNotSupported": "「{fileName}」を開けません - ファイルタイプがサポートされていません",
"notices.timeblockTitleRequired": "タイムブロックのタイトルを入力してください",
"notices.timeblockUpdatedSuccess": "タイムブロック「{title}」を正常に更新しました",
"notices.timeblockUpdateFailed": "タイムブロックの更新に失敗しました。詳細はコンソールを確認してください。",
"notices.timeblockDeletedSuccess": "タイムブロック「{title}」を正常に削除しました",
"notices.timeblockDeleteFailed": "タイムブロックの削除に失敗しました。詳細はコンソールを確認してください。",
"notices.timeblockRequiredFieldsMissing": "必須フィールドをすべて入力してください",
"notices.agendaLoadingFailed": "アジェンダの読み込みエラー。更新をお試しください。",
"notices.statsLoadingFailed": "プロジェクトの詳細の読み込みエラー。",
"modals.deviceCode.title": "Google Calendar認証",
"modals.deviceCode.instructions.intro": "Google Calendarに接続するには、次の手順に従ってください",
"modals.deviceCode.steps.open": "開く",
"modals.deviceCode.steps.inBrowser": "ブラウザで",
"modals.deviceCode.steps.enterCode": "プロンプトが表示されたら、このコードを入力してください:",
"modals.deviceCode.steps.signIn": "Googleアカウントでサインインし、アクセスを許可してください",
"modals.deviceCode.steps.returnToObsidian": "Obsidianに戻るこのウィンドウは自動的に閉じます",
"modals.deviceCode.codeLabel": "あなたのコード:",
"modals.deviceCode.copyCodeAriaLabel": "コードをコピー",
"modals.deviceCode.waitingForAuthorization": "認証を待機中...",
"modals.deviceCode.openBrowserButton": "ブラウザを開く",
"modals.deviceCode.cancelButton": "キャンセル",
"modals.deviceCode.expiresMinutesSeconds": "コードは{minutes}分{seconds}秒後に期限切れになります",
"modals.deviceCode.expiresSeconds": "コードは{seconds}秒後に期限切れになります",
"modals.icsEventInfo.calendarEventHeading": "カレンダーイベント",
"modals.icsEventInfo.titleLabel": "タイトル",
"modals.icsEventInfo.calendarLabel": "カレンダー",
"modals.icsEventInfo.dateTimeLabel": "日時",
"modals.icsEventInfo.locationLabel": "場所",
"modals.icsEventInfo.descriptionLabel": "説明",
"modals.icsEventInfo.urlLabel": "URL",
"modals.icsEventInfo.relatedNotesHeading": "関連するノートとタスク",
"modals.icsEventInfo.noRelatedItems": "このイベントに関連するノートまたはタスクが見つかりませんでした。",
"modals.icsEventInfo.typeTask": "タスク",
"modals.icsEventInfo.typeNote": "ノート",
"modals.icsEventInfo.actionsHeading": "アクション",
"modals.icsEventInfo.createFromEventLabel": "イベントから作成",
"modals.icsEventInfo.createFromEventDesc": "このカレンダーイベントから新しいノートまたはタスクを作成します",
"modals.icsEventInfo.linkExistingLabel": "既存をリンク",
"modals.icsEventInfo.linkExistingDesc": "既存のノートをこのカレンダーイベントにリンクします",
"modals.timeblockInfo.editHeading": "タイムブロックを編集",
"modals.timeblockInfo.dateTimeLabel": "日時:",
"modals.timeblockInfo.titleLabel": "タイトル",
"modals.timeblockInfo.titleDesc": "タイムブロックのタイトル",
"modals.timeblockInfo.titlePlaceholder": "例:集中作業セッション",
"modals.timeblockInfo.descriptionLabel": "説明",
"modals.timeblockInfo.descriptionDesc": "タイムブロックのオプション説明",
"modals.timeblockInfo.descriptionPlaceholder": "新機能に集中、中断なし",
"modals.timeblockInfo.colorLabel": "色",
"modals.timeblockInfo.colorDesc": "タイムブロックのオプションの色",
"modals.timeblockInfo.colorPlaceholder": "#3b82f6",
"modals.timeblockInfo.attachmentsLabel": "添付ファイル",
"modals.timeblockInfo.attachmentsDesc": "このタイムブロックにリンクされたファイルまたはノート",
"modals.timeblockInfo.addAttachmentButton": "添付ファイルを追加",
"modals.timeblockInfo.addAttachmentTooltip": "ファジー検索を使用してファイルまたはノートを選択",
"modals.timeblockInfo.deleteButton": "タイムブロックを削除",
"modals.timeblockInfo.saveButton": "変更を保存",
"modals.timeblockInfo.deleteConfirmationTitle": "タイムブロックを削除",
"modals.timeblockCreation.heading": "タイムブロックを作成",
"modals.timeblockCreation.dateLabel": "日付:",
"modals.timeblockCreation.titleLabel": "タイトル",
"modals.timeblockCreation.titleDesc": "タイムブロックのタイトル",
"modals.timeblockCreation.titlePlaceholder": "例:集中作業セッション",
"modals.timeblockCreation.startTimeLabel": "開始時刻",
"modals.timeblockCreation.startTimeDesc": "タイムブロックが開始する時刻",
"modals.timeblockCreation.startTimePlaceholder": "09:00",
"modals.timeblockCreation.endTimeLabel": "終了時刻",
"modals.timeblockCreation.endTimeDesc": "タイムブロックが終了する時刻",
"modals.timeblockCreation.endTimePlaceholder": "11:00",
"modals.timeblockCreation.descriptionLabel": "説明",
"modals.timeblockCreation.descriptionDesc": "タイムブロックのオプション説明",
"modals.timeblockCreation.descriptionPlaceholder": "新機能に集中、中断なし",
"modals.timeblockCreation.colorLabel": "色",
"modals.timeblockCreation.colorDesc": "タイムブロックのオプションの色",
"modals.timeblockCreation.colorPlaceholder": "#3b82f6",
"modals.timeblockCreation.attachmentsLabel": "添付ファイル",
"modals.timeblockCreation.attachmentsDesc": "このタイムブロックにリンクするファイルまたはノート",
"modals.timeblockCreation.addAttachmentButton": "添付ファイルを追加",
"modals.timeblockCreation.addAttachmentTooltip": "ファジー検索を使用してファイルまたはノートを選択",
"modals.timeblockCreation.createButton": "タイムブロックを作成",
"modals.icsNoteCreation.heading": "ICSイベントから作成",
"modals.icsNoteCreation.titleLabel": "タイトル",
"modals.icsNoteCreation.titleDesc": "新しいコンテンツのタイトル",
"modals.icsNoteCreation.folderLabel": "フォルダ",
"modals.icsNoteCreation.folderDesc": "保存先フォルダ空欄の場合はVaultルート",
"modals.icsNoteCreation.folderPlaceholder": "フォルダ/サブフォルダ",
"modals.icsNoteCreation.createButton": "作成",
"modals.icsNoteCreation.startLabel": "開始:",
"modals.icsNoteCreation.endLabel": "終了:",
"modals.icsNoteCreation.locationLabel": "場所:",
"modals.icsNoteCreation.calendarLabel": "カレンダー:",
"modals.icsNoteCreation.useTemplateLabel": "テンプレートを使用",
"modals.icsNoteCreation.useTemplateDesc": "コンテンツ作成時にテンプレートを適用",
"modals.icsNoteCreation.templatePathLabel": "テンプレートパス",
"modals.icsNoteCreation.templatePathDesc": "テンプレートファイルへのパス",
"modals.icsNoteCreation.templatePathPlaceholder": "templates/ics-note-template.md",
"ui.filterBar.subgroupLabel": "サブグループ",
"components.dateContextMenu.weekdays": "平日",
"components.dateContextMenu.clearDate": "日付をクリア",
"components.dateContextMenu.today": "今日",
"components.dateContextMenu.tomorrow": "明日",
"components.dateContextMenu.thisWeekend": "今週末",
"components.dateContextMenu.nextWeek": "来週",
"components.dateContextMenu.nextMonth": "来月",
"components.dateContextMenu.setDateTime": "日時を設定",
"components.dateContextMenu.dateLabel": "日付",
"components.dateContextMenu.timeLabel": "時刻(オプション)",
"components.subgroupMenuBuilder.none": "なし",
"components.subgroupMenuBuilder.status": "ステータス",
"components.subgroupMenuBuilder.priority": "優先度",
"components.subgroupMenuBuilder.context": "コンテキスト",
"components.subgroupMenuBuilder.project": "プロジェクト",
"components.subgroupMenuBuilder.dueDate": "期限",
"components.subgroupMenuBuilder.scheduledDate": "予定日",
"components.subgroupMenuBuilder.tags": "タグ",
"components.subgroupMenuBuilder.completedDate": "完了日",
"components.subgroupMenuBuilder.subgroup": "サブグループ",
},
ru: {
// Russian translations with formal address forms
"views.agenda.empty.helpText": "Создайте задачи с датами выполнения или планирования, или добавьте заметки, чтобы увидеть их здесь.",
"views.agenda.contextMenu.showOverdueSection": "Показать раздел просроченных",
"views.agenda.contextMenu.showNotes": "Показать заметки",
"views.agenda.contextMenu.calendarSubscriptions": "Подписки календаря",
"views.agenda.periods.thisWeek": "Эта неделя",
"views.agenda.tipPrefix": "Совет: ",
"views.notes.refreshingButton": "Обновление...",
"views.notes.empty.helpText": "Заметки для выбранной даты не найдены. Попробуйте выбрать другую дату в мини-календаре или создайте несколько заметок.",
"views.notes.loading": "Загрузка заметок...",
"views.notes.refreshButtonAriaLabel": "Обновить список заметок",
"views.kanban.uncategorized": "Без категории",
"views.kanban.noProject": "Без проекта",
"views.kanban.columnTitle": "Без названия",
"notices.icsNoteCreatedSuccess": "Заметка успешно создана",
"notices.icsCreationModalOpenFailed": "Не удалось открыть модальное окно создания",
"notices.icsNoteLinkSuccess": "Заметка \"{fileName}\" связана с событием ICS",
"notices.icsTaskCreatedSuccess": "Задача создана: {title}",
"notices.icsRelatedItemsRefreshed": "Связанные заметки обновлены",
"notices.icsFileNotFound": "Файл не найден или недействителен",
"notices.icsFileOpenFailed": "Не удалось открыть файл",
"notices.timeblockAttachmentExists": "\"{fileName}\" уже прикреплен",
"notices.timeblockAttachmentAdded": "\"{fileName}\" добавлен как вложение",
"notices.timeblockAttachmentRemoved": "\"{fileName}\" удален из вложений",
"notices.timeblockFileTypeNotSupported": "Невозможно открыть \"{fileName}\" - тип файла не поддерживается",
"notices.timeblockTitleRequired": "Пожалуйста, введите название для временного блока",
"notices.timeblockUpdatedSuccess": "Временной блок \"{title}\" успешно обновлен",
"notices.timeblockUpdateFailed": "Не удалось обновить временной блок. Проверьте консоль для подробностей.",
"notices.timeblockDeletedSuccess": "Временной блок \"{title}\" успешно удален",
"notices.timeblockDeleteFailed": "Не удалось удалить временной блок. Проверьте консоль для подробностей.",
"notices.timeblockRequiredFieldsMissing": "Пожалуйста, заполните все обязательные поля",
"notices.agendaLoadingFailed": "Ошибка при загрузке повестки. Пожалуйста, попробуйте обновить.",
"notices.statsLoadingFailed": "Ошибка при загрузке деталей проекта.",
"modals.deviceCode.title": "Авторизация Google Calendar",
"modals.deviceCode.instructions.intro": "Чтобы подключить ваш Google Calendar, пожалуйста, выполните следующие шаги:",
"modals.deviceCode.steps.open": "Откройте",
"modals.deviceCode.steps.inBrowser": "в вашем браузере",
"modals.deviceCode.steps.enterCode": "Введите этот код при запросе:",
"modals.deviceCode.steps.signIn": "Войдите с помощью вашего аккаунта Google и предоставьте доступ",
"modals.deviceCode.steps.returnToObsidian": "Вернитесь в Obsidian (это окно закроется автоматически)",
"modals.deviceCode.codeLabel": "Ваш код:",
"modals.deviceCode.copyCodeAriaLabel": "Скопировать код",
"modals.deviceCode.waitingForAuthorization": "Ожидание авторизации...",
"modals.deviceCode.openBrowserButton": "Открыть браузер",
"modals.deviceCode.cancelButton": "Отмена",
"modals.deviceCode.expiresMinutesSeconds": "Код истекает через {minutes}м {seconds}с",
"modals.deviceCode.expiresSeconds": "Код истекает через {seconds}с",
"modals.icsEventInfo.calendarEventHeading": "Событие календаря",
"modals.icsEventInfo.titleLabel": "Название",
"modals.icsEventInfo.calendarLabel": "Календарь",
"modals.icsEventInfo.dateTimeLabel": "Дата и время",
"modals.icsEventInfo.locationLabel": "Место",
"modals.icsEventInfo.descriptionLabel": "Описание",
"modals.icsEventInfo.urlLabel": "URL",
"modals.icsEventInfo.relatedNotesHeading": "Связанные заметки и задачи",
"modals.icsEventInfo.noRelatedItems": "Для этого события не найдено связанных заметок или задач.",
"modals.icsEventInfo.typeTask": "Задача",
"modals.icsEventInfo.typeNote": "Заметка",
"modals.icsEventInfo.actionsHeading": "Действия",
"modals.icsEventInfo.createFromEventLabel": "Создать из события",
"modals.icsEventInfo.createFromEventDesc": "Создать новую заметку или задачу из этого события календаря",
"modals.icsEventInfo.linkExistingLabel": "Связать существующее",
"modals.icsEventInfo.linkExistingDesc": "Связать существующую заметку с этим событием календаря",
"modals.timeblockInfo.editHeading": "Редактировать временной блок",
"modals.timeblockInfo.dateTimeLabel": "Дата и время: ",
"modals.timeblockInfo.titleLabel": "Название",
"modals.timeblockInfo.titleDesc": "Название вашего временного блока",
"modals.timeblockInfo.titlePlaceholder": "напр., Сессия глубокой работы",
"modals.timeblockInfo.descriptionLabel": "Описание",
"modals.timeblockInfo.descriptionDesc": "Необязательное описание временного блока",
"modals.timeblockInfo.descriptionPlaceholder": "Сосредоточиться на новых функциях, без прерываний",
"modals.timeblockInfo.colorLabel": "Цвет",
"modals.timeblockInfo.colorDesc": "Необязательный цвет для временного блока",
"modals.timeblockInfo.colorPlaceholder": "#3b82f6",
"modals.timeblockInfo.attachmentsLabel": "Вложения",
"modals.timeblockInfo.attachmentsDesc": "Файлы или заметки, связанные с этим временным блоком",
"modals.timeblockInfo.addAttachmentButton": "Добавить вложение",
"modals.timeblockInfo.addAttachmentTooltip": "Выберите файл или заметку с помощью нечеткого поиска",
"modals.timeblockInfo.deleteButton": "Удалить временной блок",
"modals.timeblockInfo.saveButton": "Сохранить изменения",
"modals.timeblockInfo.deleteConfirmationTitle": "Удалить временной блок",
"modals.timeblockCreation.heading": "Создать временной блок",
"modals.timeblockCreation.dateLabel": "Дата: ",
"modals.timeblockCreation.titleLabel": "Название",
"modals.timeblockCreation.titleDesc": "Название вашего временного блока",
"modals.timeblockCreation.titlePlaceholder": "напр., Сессия глубокой работы",
"modals.timeblockCreation.startTimeLabel": "Время начала",
"modals.timeblockCreation.startTimeDesc": "Когда начинается временной блок",
"modals.timeblockCreation.startTimePlaceholder": "09:00",
"modals.timeblockCreation.endTimeLabel": "Время окончания",
"modals.timeblockCreation.endTimeDesc": "Когда заканчивается временной блок",
"modals.timeblockCreation.endTimePlaceholder": "11:00",
"modals.timeblockCreation.descriptionLabel": "Описание",
"modals.timeblockCreation.descriptionDesc": "Необязательное описание временного блока",
"modals.timeblockCreation.descriptionPlaceholder": "Сосредоточиться на новых функциях, без прерываний",
"modals.timeblockCreation.colorLabel": "Цвет",
"modals.timeblockCreation.colorDesc": "Необязательный цвет для временного блока",
"modals.timeblockCreation.colorPlaceholder": "#3b82f6",
"modals.timeblockCreation.attachmentsLabel": "Вложения",
"modals.timeblockCreation.attachmentsDesc": "Файлы или заметки для связи с этим временным блоком",
"modals.timeblockCreation.addAttachmentButton": "Добавить вложение",
"modals.timeblockCreation.addAttachmentTooltip": "Выберите файл или заметку с помощью нечеткого поиска",
"modals.timeblockCreation.createButton": "Создать временной блок",
"modals.icsNoteCreation.heading": "Создать из события ICS",
"modals.icsNoteCreation.titleLabel": "Название",
"modals.icsNoteCreation.titleDesc": "Название нового содержимого",
"modals.icsNoteCreation.folderLabel": "Папка",
"modals.icsNoteCreation.folderDesc": "Папка назначения (оставьте пустым для корня хранилища)",
"modals.icsNoteCreation.folderPlaceholder": "папка/подпапка",
"modals.icsNoteCreation.createButton": "Создать",
"modals.icsNoteCreation.startLabel": "Начало: ",
"modals.icsNoteCreation.endLabel": "Окончание: ",
"modals.icsNoteCreation.locationLabel": "Место: ",
"modals.icsNoteCreation.calendarLabel": "Календарь: ",
"modals.icsNoteCreation.useTemplateLabel": "Использовать шаблон",
"modals.icsNoteCreation.useTemplateDesc": "Применить шаблон при создании содержимого",
"modals.icsNoteCreation.templatePathLabel": "Путь к шаблону",
"modals.icsNoteCreation.templatePathDesc": "Путь к файлу шаблона",
"modals.icsNoteCreation.templatePathPlaceholder": "templates/ics-note-template.md",
"ui.filterBar.subgroupLabel": "ПОДГРУППА",
"components.dateContextMenu.weekdays": "Будние дни",
"components.dateContextMenu.clearDate": "Очистить дату",
"components.dateContextMenu.today": "Сегодня",
"components.dateContextMenu.tomorrow": "Завтра",
"components.dateContextMenu.thisWeekend": "Эти выходные",
"components.dateContextMenu.nextWeek": "Следующая неделя",
"components.dateContextMenu.nextMonth": "Следующий месяц",
"components.dateContextMenu.setDateTime": "Установить дату и время",
"components.dateContextMenu.dateLabel": "Дата",
"components.dateContextMenu.timeLabel": "Время (необязательно)",
"components.subgroupMenuBuilder.none": "Нет",
"components.subgroupMenuBuilder.status": "Статус",
"components.subgroupMenuBuilder.priority": "Приоритет",
"components.subgroupMenuBuilder.context": "Контекст",
"components.subgroupMenuBuilder.project": "Проект",
"components.subgroupMenuBuilder.dueDate": "Срок выполнения",
"components.subgroupMenuBuilder.scheduledDate": "Запланированная дата",
"components.subgroupMenuBuilder.tags": "Теги",
"components.subgroupMenuBuilder.completedDate": "Дата завершения",
"components.subgroupMenuBuilder.subgroup": "ПОДГРУППА",
},
zh: {
// Simplified Chinese translations
"views.agenda.empty.helpText": "创建具有截止日期或计划日期的任务,或添加笔记以在此处查看它们。",
"views.agenda.contextMenu.showOverdueSection": "显示逾期部分",
"views.agenda.contextMenu.showNotes": "显示笔记",
"views.agenda.contextMenu.calendarSubscriptions": "日历订阅",
"views.agenda.periods.thisWeek": "本周",
"views.agenda.tipPrefix": "提示:",
"views.notes.refreshingButton": "刷新中...",
"views.notes.empty.helpText": "未找到所选日期的笔记。请尝试在迷你日历视图中选择其他日期或创建一些笔记。",
"views.notes.loading": "加载笔记中...",
"views.notes.refreshButtonAriaLabel": "刷新笔记列表",
"views.kanban.uncategorized": "未分类",
"views.kanban.noProject": "无项目",
"views.kanban.columnTitle": "无标题",
"notices.icsNoteCreatedSuccess": "笔记创建成功",
"notices.icsCreationModalOpenFailed": "无法打开创建模态框",
"notices.icsNoteLinkSuccess": "已将笔记"{fileName}"链接到ICS事件",
"notices.icsTaskCreatedSuccess": "任务已创建:{title}",
"notices.icsRelatedItemsRefreshed": "相关笔记已刷新",
"notices.icsFileNotFound": "文件未找到或无效",
"notices.icsFileOpenFailed": "无法打开文件",
"notices.timeblockAttachmentExists": ""{fileName}"已经附加",
"notices.timeblockAttachmentAdded": "已将"{fileName}"添加为附件",
"notices.timeblockAttachmentRemoved": "已从附件中移除"{fileName}"",
"notices.timeblockFileTypeNotSupported": "无法打开"{fileName}" - 不支持的文件类型",
"notices.timeblockTitleRequired": "请为时间块输入标题",
"notices.timeblockUpdatedSuccess": "时间块"{title}"更新成功",
"notices.timeblockUpdateFailed": "无法更新时间块。请查看控制台以获取详细信息。",
"notices.timeblockDeletedSuccess": "时间块"{title}"删除成功",
"notices.timeblockDeleteFailed": "无法删除时间块。请查看控制台以获取详细信息。",
"notices.timeblockRequiredFieldsMissing": "请填写所有必填字段",
"notices.agendaLoadingFailed": "加载议程时出错。请尝试刷新。",
"notices.statsLoadingFailed": "加载项目详情时出错。",
"modals.deviceCode.title": "Google Calendar授权",
"modals.deviceCode.instructions.intro": "要连接您的Google Calendar请按照以下步骤操作",
"modals.deviceCode.steps.open": "打开",
"modals.deviceCode.steps.inBrowser": "在您的浏览器中",
"modals.deviceCode.steps.enterCode": "在提示时输入此代码:",
"modals.deviceCode.steps.signIn": "使用您的Google帐户登录并授予访问权限",
"modals.deviceCode.steps.returnToObsidian": "返回Obsidian此窗口将自动关闭",
"modals.deviceCode.codeLabel": "您的代码:",
"modals.deviceCode.copyCodeAriaLabel": "复制代码",
"modals.deviceCode.waitingForAuthorization": "等待授权中...",
"modals.deviceCode.openBrowserButton": "打开浏览器",
"modals.deviceCode.cancelButton": "取消",
"modals.deviceCode.expiresMinutesSeconds": "代码将在{minutes}分{seconds}秒后过期",
"modals.deviceCode.expiresSeconds": "代码将在{seconds}秒后过期",
"modals.icsEventInfo.calendarEventHeading": "日历事件",
"modals.icsEventInfo.titleLabel": "标题",
"modals.icsEventInfo.calendarLabel": "日历",
"modals.icsEventInfo.dateTimeLabel": "日期和时间",
"modals.icsEventInfo.locationLabel": "位置",
"modals.icsEventInfo.descriptionLabel": "描述",
"modals.icsEventInfo.urlLabel": "URL",
"modals.icsEventInfo.relatedNotesHeading": "相关笔记和任务",
"modals.icsEventInfo.noRelatedItems": "未找到此事件的相关笔记或任务。",
"modals.icsEventInfo.typeTask": "任务",
"modals.icsEventInfo.typeNote": "笔记",
"modals.icsEventInfo.actionsHeading": "操作",
"modals.icsEventInfo.createFromEventLabel": "从事件创建",
"modals.icsEventInfo.createFromEventDesc": "从此日历事件创建新笔记或任务",
"modals.icsEventInfo.linkExistingLabel": "链接现有",
"modals.icsEventInfo.linkExistingDesc": "将现有笔记链接到此日历事件",
"modals.timeblockInfo.editHeading": "编辑时间块",
"modals.timeblockInfo.dateTimeLabel": "日期和时间:",
"modals.timeblockInfo.titleLabel": "标题",
"modals.timeblockInfo.titleDesc": "您的时间块标题",
"modals.timeblockInfo.titlePlaceholder": "例如,深度工作会话",
"modals.timeblockInfo.descriptionLabel": "描述",
"modals.timeblockInfo.descriptionDesc": "时间块的可选描述",
"modals.timeblockInfo.descriptionPlaceholder": "专注于新功能,无打扰",
"modals.timeblockInfo.colorLabel": "颜色",
"modals.timeblockInfo.colorDesc": "时间块的可选颜色",
"modals.timeblockInfo.colorPlaceholder": "#3b82f6",
"modals.timeblockInfo.attachmentsLabel": "附件",
"modals.timeblockInfo.attachmentsDesc": "链接到此时间块的文件或笔记",
"modals.timeblockInfo.addAttachmentButton": "添加附件",
"modals.timeblockInfo.addAttachmentTooltip": "使用模糊搜索选择文件或笔记",
"modals.timeblockInfo.deleteButton": "删除时间块",
"modals.timeblockInfo.saveButton": "保存更改",
"modals.timeblockInfo.deleteConfirmationTitle": "删除时间块",
"modals.timeblockCreation.heading": "创建时间块",
"modals.timeblockCreation.dateLabel": "日期:",
"modals.timeblockCreation.titleLabel": "标题",
"modals.timeblockCreation.titleDesc": "您的时间块标题",
"modals.timeblockCreation.titlePlaceholder": "例如,深度工作会话",
"modals.timeblockCreation.startTimeLabel": "开始时间",
"modals.timeblockCreation.startTimeDesc": "时间块开始的时间",
"modals.timeblockCreation.startTimePlaceholder": "09:00",
"modals.timeblockCreation.endTimeLabel": "结束时间",
"modals.timeblockCreation.endTimeDesc": "时间块结束的时间",
"modals.timeblockCreation.endTimePlaceholder": "11:00",
"modals.timeblockCreation.descriptionLabel": "描述",
"modals.timeblockCreation.descriptionDesc": "时间块的可选描述",
"modals.timeblockCreation.descriptionPlaceholder": "专注于新功能,无打扰",
"modals.timeblockCreation.colorLabel": "颜色",
"modals.timeblockCreation.colorDesc": "时间块的可选颜色",
"modals.timeblockCreation.colorPlaceholder": "#3b82f6",
"modals.timeblockCreation.attachmentsLabel": "附件",
"modals.timeblockCreation.attachmentsDesc": "要链接到此时间块的文件或笔记",
"modals.timeblockCreation.addAttachmentButton": "添加附件",
"modals.timeblockCreation.addAttachmentTooltip": "使用模糊搜索选择文件或笔记",
"modals.timeblockCreation.createButton": "创建时间块",
"modals.icsNoteCreation.heading": "从ICS事件创建",
"modals.icsNoteCreation.titleLabel": "标题",
"modals.icsNoteCreation.titleDesc": "新内容的标题",
"modals.icsNoteCreation.folderLabel": "文件夹",
"modals.icsNoteCreation.folderDesc": "目标文件夹(留空则为库根目录)",
"modals.icsNoteCreation.folderPlaceholder": "文件夹/子文件夹",
"modals.icsNoteCreation.createButton": "创建",
"modals.icsNoteCreation.startLabel": "开始:",
"modals.icsNoteCreation.endLabel": "结束:",
"modals.icsNoteCreation.locationLabel": "位置:",
"modals.icsNoteCreation.calendarLabel": "日历:",
"modals.icsNoteCreation.useTemplateLabel": "使用模板",
"modals.icsNoteCreation.useTemplateDesc": "创建内容时应用模板",
"modals.icsNoteCreation.templatePathLabel": "模板路径",
"modals.icsNoteCreation.templatePathDesc": "模板文件的路径",
"modals.icsNoteCreation.templatePathPlaceholder": "templates/ics-note-template.md",
"ui.filterBar.subgroupLabel": "子组",
"components.dateContextMenu.weekdays": "工作日",
"components.dateContextMenu.clearDate": "清除日期",
"components.dateContextMenu.today": "今天",
"components.dateContextMenu.tomorrow": "明天",
"components.dateContextMenu.thisWeekend": "本周末",
"components.dateContextMenu.nextWeek": "下周",
"components.dateContextMenu.nextMonth": "下个月",
"components.dateContextMenu.setDateTime": "设置日期和时间",
"components.dateContextMenu.dateLabel": "日期",
"components.dateContextMenu.timeLabel": "时间(可选)",
"components.subgroupMenuBuilder.none": "无",
"components.subgroupMenuBuilder.status": "状态",
"components.subgroupMenuBuilder.priority": "优先级",
"components.subgroupMenuBuilder.context": "上下文",
"components.subgroupMenuBuilder.project": "项目",
"components.subgroupMenuBuilder.dueDate": "截止日期",
"components.subgroupMenuBuilder.scheduledDate": "计划日期",
"components.subgroupMenuBuilder.tags": "标签",
"components.subgroupMenuBuilder.completedDate": "完成日期",
"components.subgroupMenuBuilder.subgroup": "子组",
},
};
// Helper to build nested object from dot notation
function setNestedValue(obj, path, value) {
const parts = path.split('.');
const last = parts.pop();
let current = obj;
for (const part of parts) {
if (!current[part]) {
current[part] = {};
}
current = current[part];
}
current[last] = value;
}
// Process each locale
for (const [locale, translationMap] of Object.entries(translations)) {
console.log(`\nProcessing ${locale}...`);
const filePath = path.join(RESOURCES_DIR, `${locale}.ts`);
let content = fs.readFileSync(filePath, 'utf8');
// Parse the existing structure to find insertion points
const lines = content.split('\n');
for (const [key, value] of Object.entries(translationMap)) {
const parts = key.split('.');
// Find where to insert this key
// Strategy: Find the parent section and insert alphabetically or at the end
let insertIndex = -1;
let indent = '';
// Build the search pattern for the parent
const parentPath = parts.slice(0, -1);
const lastKey = parts[parts.length - 1];
// Search for the parent section
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
// Check if we're in the right nested section
if (parentPath.length > 0) {
const parentPattern = parentPath[parentPath.length - 1] + ':';
if (line.includes(parentPattern) && line.includes('{')) {
// Found the parent, now find where to insert
insertIndex = i + 1;
// Get indentation
const match = line.match(/^(\s*)/);
indent = match ? match[1] + '\t' : '\t\t';
// Find the closing brace of this section
let braceCount = 1;
for (let j = i + 1; j < lines.length; j++) {
if (lines[j].includes('{')) braceCount++;
if (lines[j].includes('}')) {
braceCount--;
if (braceCount === 0) {
insertIndex = j;
break;
}
}
}
break;
}
}
}
// Escape special characters in value
const escapedValue = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
const newLine = `${indent}${lastKey}: "${escapedValue}",`;
// Insert the line
if (insertIndex > 0) {
lines.splice(insertIndex, 0, newLine);
console.log(` Added: ${key}`);
} else {
console.warn(` Warning: Could not find insertion point for ${key}`);
}
}
// Write back
fs.writeFileSync(filePath, lines.join('\n'));
console.log(`✓ Completed ${locale}`);
}
console.log('\n✓ All translations added!');