Files
next-ai-draw-io/lib/i18n/dictionaries/ja.json
Dayuan Jiang 4dc774d03f feat: add chat session history with IndexedDB persistence (#500)
* feat(session): add chat session history with IndexedDB storage

- Add session-storage.ts with IndexedDB wrapper using idb library
- Add use-session-manager.ts hook for session state management
- Add session-history-dropdown.tsx for session selection UI
- Integrate session system into chat-panel.tsx
- Auto-generate session titles from first user message
- Auto-save sessions on message completion
- Support session switching, deletion, and creation
- Migrate existing localStorage data to IndexedDB
- Add i18n translations for session history UI

* feat(session): improve history dropdown and persist diagram history

- Add time-based grouping (Today, Yesterday, This Week, Earlier)
- Add thumbnail previews using Next.js Image component
- Add staggered entrance animations with fade-in effects
- Improve active session indicator with left border accent
- Fix scrolling by using native overflow instead of ScrollArea
- Persist diagram version history to IndexedDB sessions
- Remove redundant diagram XML from localStorage
- Add i18n strings for time group labels (en, ja, zh)

* fix(session): prevent data loss on theme change and tab close

- Add isDrawioReady effect to restore diagram after DrawIO remount
- Add visibilitychange handler to save session when page becomes hidden
- Fix missing currentSessionId in saveCurrentSession dependency array
- Remove unused sanitizeMessages import from use-session-manager

* fix(session): fix diagram save and migration data loss bugs

- Add diagramHistory to save effect dependency array so diagram-only
  edits trigger saves (previously only message changes did)
- Destructure stable sessionManager values to prevent unnecessary
  effect re-runs on every render
- Add try-catch wrapper around debounced async save operation
- Make saveSession() return boolean to indicate success/failure
- Verify IndexedDB write succeeded before deleting localStorage data
  during migration (prevents data loss if write silently fails)
- Keep localStorage data for retry if migration fails instead of
  marking as complete anyway

* refactor(session): extract helpers to reduce code duplication

- Add syncUIWithSession helper to consolidate 4 duplicate UI sync blocks
- Add buildSessionData helper to consolidate 4 duplicate save logic blocks
- Remove unused saveTimeoutRef and its cleanup effect
- Net reduction of ~80 lines of duplicate code

* style(ui): improve history dropdown and delete dialog styling

- Change destructive color from coral to muted rose for refined look
- Make session history panel taller (400px fixed height)
- Fix popover alignment to prevent truncation
- Style delete button with soft red outline instead of solid fill
- Make delete dialog more compact (max-w-sm)

* fix(session): reset refs on new chat and show recent sessions

- Fix cached example diagrams not displaying after creating new session
- Reset previousXML, lastProcessedXmlRef and processedToolCalls when
  messages become empty (new chat or session switch)
- Add recent chats section in empty chat state with collapsible examples
- Pass sessions and onSelectSession to ChatMessageDisplay
- Add loadedMessageIdsRef to skip animations on session restore
- Add debug console.log for diagram processing flow

* feat(session): add search bar and improve history UI

- Remove session history dropdown, use main panel instead
- Add search bar to filter history chats by title
- Show minutes (Xm ago) instead of "Just now" for recent sessions
- Scroll to top when switching to new/empty chat
- Remove title truncation limit for better searchability
- Remove debug console.log statements

* refactor: remove redundant code and fix nested button hydration error

- Remove unused 'sessions' from deleteSession dependency array
- Remove unused 'switchedTo' variable and simplify return type
- Remove unused 'restoredMessageIdsRef' (always empty)
- Fix nested button hydration error by using div with role=button
- Simplify handleDeleteSession callback

* fix(session): fix migration bug, improve metadata perf, truncate titles

- Fix migration retry loop when localStorage has empty array
- Use cursor-based iteration for getAllSessionMetadata
- Truncate session titles to 100 chars with ellipsis

* refactor: remove dead code and extract diagram length constant

- Remove unused exports: getAllSessions, createNewSession, updateSessionTitle
- Remove write-only CURRENT_SESSION_KEY and all localStorage calls
- Remove dead messagesEndRef and unused scroll effect
- Extract magic number 300 to MIN_REAL_DIAGRAM_LENGTH constant
- Add isRealDiagram() helper function for semantic clarity
2026-01-04 10:25:19 +09:00

295 lines
17 KiB
JSON
Raw 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.

{
"common": {
"save": "保存",
"cancel": "キャンセル",
"close": "閉じる",
"confirm": "確認",
"clear": "クリア",
"edit": "編集",
"delete": "削除",
"loading": "読み込み中..",
"new": "新規"
},
"nav": {
"about": "概要",
"editor": "エディタ",
"newChat": "新しいチャットを開始",
"github": "GitHub",
"settings": "設定",
"hidePanel": "チャットパネルを非表示 (Ctrl+B)",
"showPanel": "チャットパネルを表示 (Ctrl+B)",
"aiChat": "AI チャット"
},
"providers": {
"useServerDefault": "サーバーデフォルトを使用",
"openai": "OpenAI",
"anthropic": "Anthropic",
"google": "Google",
"azure": "Azure OpenAI",
"openrouter": "OpenRouter",
"deepseek": "DeepSeek",
"siliconflow": "SiliconFlow"
},
"chat": {
"placeholder": "ダイアグラムを説明するか、ファイルをアップロード...",
"send": "送信",
"sending": "送信中...",
"sendMessage": "メッセージを送信",
"clearConversation": "会話をクリア",
"diagramHistory": "ダイアグラム履歴",
"saveDiagram": "ダイアグラムを保存",
"uploadFile": "ファイルをアップロード画像、PDF、テキスト",
"minimalStyle": "ミニマル",
"styledMode": "スタイル付き",
"minimalTooltip": "高速生成のためミニマルを使用(色なし)",
"regenerate": "応答を再生成",
"copyResponse": "応答をコピー",
"copied": "コピーしました!",
"failedToCopy": "コピーに失敗しました",
"failedToCopyDetail": "メッセージのコピーに失敗しました。手動でコピーするか、クリップボードの権限を確認してください。",
"goodResponse": "良い応答",
"badResponse": "悪い応答",
"clickToEdit": "クリックして編集",
"editMessage": "メッセージを編集",
"saveAndSubmit": "保存して送信"
},
"examples": {
"title": "AI でダイアグラムを作成",
"subtitle": "作成したいものを説明するか、画像をアップロードして複製",
"quickExamples": "クイック例",
"paperToDiagram": "論文からダイアグラムへ",
"paperDescription": ".pdf, .txt, .md, .json, .csv, .py, .js, .ts などをアップロード",
"animatedDiagram": "アニメーション図",
"animatedDescription": "アニメーションコネクタ付きの Transformer アーキテクチャを描画",
"awsArchitecture": "AWS アーキテクチャ",
"awsDescription": "AWS アイコンでクラウドアーキテクチャ図を作成",
"replicateFlowchart": "フローチャートを複製",
"replicateDescription": "既存のフローチャートをアップロードして複製",
"creativeDrawing": "クリエイティブな描画",
"creativeDescription": "楽しくてクリエイティブなものを描く",
"cachedNote": "例はキャッシュされ、即座に応答します",
"mcpServer": "MCP サーバー",
"mcpDescription": "Claude Desktop、VS Code、Cursor で使用",
"preview": "プレビュー"
},
"settings": {
"title": "設定",
"description": "アプリケーション設定を構成します。",
"accessCode": "アクセスコード",
"accessCodePlaceholder": "アクセスコードを入力",
"accessCodeDescription": "このアプリケーションを使用するために必要です。",
"aiProvider": "AI プロバイダー設定",
"aiProviderDescription": "独自の API キーを使用して使用制限を回避できます。キーはブラウザのローカルに保存され、サーバーには保存されません。",
"provider": "プロバイダー",
"modelId": "モデル ID",
"apiKey": "API キー",
"apiKeyPlaceholder": "あなたの API キー",
"baseUrl": "ベース URLオプション",
"customEndpoint": "カスタムエンドポイント URL",
"overrides": "上書き",
"clearSettings": "設定をクリア",
"useServerDefault": "サーバーデフォルトを使用",
"language": "言語",
"languageDescription": "インターフェース言語を選択します。",
"theme": "テーマ",
"themeDescription": "インターフェースと DrawIO キャンバスのダーク/ライトモード。",
"drawioStyle": "DrawIO スタイル",
"drawioStyleDescription": "キャンバススタイル:",
"switchTo": "切り替え",
"minimal": "ミニマル",
"sketch": "スケッチ",
"closeProtection": "ページ離脱確認",
"closeProtectionDescription": "ページを離れる際に確認を表示します。",
"diagramStyle": "ダイアグラムスタイル",
"diagramStyleDescription": "ミニマルとスタイル付きの出力を切り替えます。",
"diagramActions": "ダイアグラム操作",
"diagramActionsDescription": "ダイアグラムの履歴とエクスポートを管理",
"history": "履歴",
"download": "ダウンロード"
},
"save": {
"title": "ダイアグラムを保存",
"description": "形式とファイル名を選択してダイアグラムを保存します。",
"format": "形式",
"filename": "ファイル名",
"filenamePlaceholder": "ファイル名を入力",
"formats": {
"drawio": "Draw.io XML",
"png": "PNG 画像",
"svg": "SVG 画像"
}
},
"history": {
"title": "ダイアグラム履歴",
"description": "AI 修正前に保存された各ダイアグラム。\nダイアグラムをクリックして復元",
"noHistory": "まだ履歴がありません。メッセージを送信してダイアグラム履歴を作成してください。",
"version": "バージョン",
"restoreTo": "バージョン {version} に復元しますか?"
},
"dialogs": {
"clearTitle": "すべてクリアしますか?",
"clearDescription": "現在の会話をクリアし、ダイアグラムをリセットします。この操作は元に戻せません。",
"clearEverything": "すべてクリア",
"clearSuccess": "新しいチャットを開始しました"
},
"errors": {
"maxFiles": "ファイルが多すぎます。最大 {max} 個まで許可されています。",
"onlyMoreAllowed": "あと {slots} 個のファイルのみ許可されています",
"fileExceeds": "「{name}」は {size} です({max}MB を超えています)",
"unsupportedType": "「{name}」はサポートされていないファイルタイプです",
"filesRejected": "{count} 個のファイルが拒否されました:",
"andMore": "...およびさらに {count} 個",
"invalidAccessCode": "無効または欠落したアクセスコード。設定で入力してください。",
"networkError": "ネットワークエラー。接続を確認してください。",
"retryLimit": "自動再試行制限に達しました({max})。手動で再試行してください。",
"continuationRetryLimit": "継続再試行制限に達しました({max})。ダイアグラムが複雑すぎる可能性があります。",
"validationFailed": "ダイアグラムの検証に失敗しました。再生成してみてください。",
"malformedXml": "AI が無効なダイアグラム XML を生成しました。再生成してみてください。",
"failedToProcess": "ダイアグラムの処理に失敗しました。再生成してみてください。",
"sessionCorrupted": "セッションデータが破損しました。最初からやり直します。",
"failedToSave": "localStorage へのメッセージの保存に失敗しました",
"failedToRestore": "localStorage からの復元に失敗しました",
"failedToPersist": "アンロード前の状態の永続化に失敗しました",
"failedToExport": "チャートデータの取得エラー",
"failedToLoadExample": "例の画像の読み込みエラー",
"failedToRecordFeedback": "フィードバックの記録に失敗しました。もう一度お試しください。",
"storageUpdateFailed": "チャットはクリアされましたが、ブラウザストレージを更新できませんでした"
},
"quota": {
"dailyLimit": "1日の割当量に達しました",
"tokenLimit": "1日のトークン制限に達しました",
"tpmLimit": "レート制限",
"tpmMessage": "リクエストが多すぎます。しばらくお待ちください。",
"tpmMessageDetailed": "レート制限に達しました({limit}トークン/分)。{seconds}秒待ってからもう一度リクエストしてください。",
"messageApi": "今日のデモ利用上限に達してしまったようです。楽しんでいただけて本当に嬉しいです。このデモはByteDance Doubaoのご厚意により提供されていますが、皆様に公平にご利用いただくため、少し制限を設けさせていただいております。",
"messageToken": "今日のトークン利用上限に達してしまったようです。楽しんでいただけて本当に嬉しいです。このデモはByteDance Doubaoのご厚意により提供されていますが、皆様に公平にご利用いただくため、少し制限を設けさせていただいております。",
"tip": "<strong>ヒント:</strong>独自の API キーを使用する(設定アイコンをクリック)か、プロジェクトをセルフホストしてこれらの制限を回避できます。",
"reset": "制限は明日リセットされます。ご理解ありがとうございます。",
"doubaoSponsorship": "<a href=\"{link}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"underline hover:text-foreground\">こちらから登録</a>すると、各モデルDoubao、DeepSeek、Kimi含むで50万トークンを無料で取得できます。モデル設定でAPIキーを設定してください。",
"configModel": "APIキーを使用",
"selfHost": "セルフホスト",
"sponsor": "スポンサー",
"learnMore": "詳細 →",
"usedOf": "{used}/{limit}"
},
"tools": {
"generateDiagram": "ダイアグラムを生成",
"editDiagram": "ダイアグラムを編集",
"appendDiagram": "ダイアグラムに追加",
"complete": "完了",
"error": "エラー",
"truncated": "切り捨て"
},
"file": {
"reading": "読み込み中...",
"chars": "文字",
"removeFile": "ファイルを削除"
},
"reasoning": {
"thinking": "考え中...",
"thoughtFor": "{duration} 秒考えました",
"thoughtBrief": "数秒考えました"
},
"dev": {
"title": "開発XMLストリーミングシミュレーター",
"preset": "プリセット:",
"selectPreset": "プリセットを選択...",
"clear": "クリア",
"placeholder": "ここに mxCell XML を貼り付けるか、プリセットを選択...",
"interval": "間隔:",
"chars": "文字:",
"streaming": "ストリーミング中...",
"simulate": "シミュレート",
"stop": "停止",
"testQuotaToast": "クォータトーストをテスト",
"simulatingMessage": "[開発] XMLストリーミングをシミュレート中",
"successMessage": "ダイアグラムの表示に成功しました。"
},
"about": {
"modelChange": "モデル変更と利用制限について",
"walletCrying": "(別名:お財布が悲鳴を上げています)",
"seekingSponsorship": "スポンサー募集",
"contactMe": "お問い合わせ",
"usageNotice": "利用量の増加に伴い、コスト削減のためモデルを Claude から minimax-m2 に変更し、いくつかの利用制限を設けました。詳細は概要ページをご覧ください。"
},
"sessionHistory": {
"tooltip": "チャット履歴",
"newChat": "新しいチャット",
"empty": "チャット履歴はまだありません",
"emptyHint": "会話を始めてください",
"today": "今日",
"yesterday": "昨日",
"thisWeek": "今週",
"earlier": "それ以前",
"deleteTitle": "このチャットを削除しますか?",
"deleteDescription": "このチャットセッションとダイアグラムは完全に削除されます。この操作は取り消せません。",
"recentChats": "最近のチャット",
"justNow": "たった今",
"searchPlaceholder": "チャットを検索...",
"noResults": "チャットが見つかりません"
},
"modelConfig": {
"title": "AIモデル設定",
"description": "複数のAIプロバイダーとモデルを設定",
"configure": "設定",
"addProvider": "プロバイダーを追加",
"addModel": "モデルを追加",
"modelId": "モデルID",
"modelLabel": "表示名",
"streaming": "ストリーミングを有効",
"deleteProvider": "プロバイダーを削除",
"deleteModel": "モデルを削除",
"noModels": "モデルが設定されていません。モデルを追加してください。",
"selectProvider": "プロバイダーを選択または追加してください",
"configureMultiple": "複数のAIプロバイダーを設定して簡単に切り替え",
"apiKeyStored": "APIキーはブラウザにローカル保存されます",
"test": "テスト",
"validationError": "検証に失敗しました",
"addModelFirst": "検証するには少なくとも1つのモデルを追加してください",
"providers": "プロバイダー",
"addProviderHint": "プロバイダーを追加して開始",
"verified": "検証済み",
"configuration": "設定",
"displayName": "表示名",
"awsAccessKeyId": "AWS アクセスキー ID",
"awsSecretAccessKey": "AWS シークレットアクセスキー",
"awsRegion": "AWS リージョン",
"selectRegion": "リージョンを選択",
"apiKey": "API キー",
"enterApiKey": "API キーを入力",
"enterSecretKey": "シークレットアクセスキーを入力",
"baseUrl": "ベース URL",
"optional": "(オプション)",
"customEndpoint": "カスタムエンドポイント URL",
"models": "モデル",
"customModelId": "カスタムモデル ID...",
"allAdded": "すべて追加済み",
"suggested": "おすすめ",
"noModelsConfigured": "モデルが設定されていません",
"modelIdEmpty": "モデル ID は空にできません",
"modelIdExists": "このモデル ID は既に存在します",
"configureProviders": "AI プロバイダーを設定",
"selectProviderHint": "リストからプロバイダーを選択するか、新規追加して API キーとモデルを設定",
"deleteConfirmDesc": "{name} を削除してもよろしいですか?設定されたすべてのモデルが削除され、元に戻せません。",
"typeToConfirm": "確認のため「{name}」と入力",
"typeProviderName": "プロバイダー名を入力...",
"modelsConfiguredCount": "{count} 個のモデルを設定済み",
"validationFailedCount": "{count} 個のモデルの検証に失敗",
"cancel": "キャンセル",
"delete": "削除",
"clickToChange": "(クリックして変更)",
"usingServerDefault": "サーバーデフォルトモデルを使用中",
"selectModel": "モデルを選択",
"searchModels": "モデルを検索...",
"noVerifiedModels": "検証済みのモデルがありません。先にモデルをテストしてください。",
"noModelsFound": "モデルが見つかりません。",
"default": "デフォルト",
"serverDefault": "サーバーデフォルト",
"configureModels": "モデルを設定...",
"onlyVerifiedShown": "検証済みのモデルのみ表示",
"showUnvalidatedModels": "未検証のモデルを表示",
"allModelsShown": "すべてのモデルを表示(未検証を含む)",
"unvalidatedModelWarning": "このモデルは検証されていません"
}
}