translate_obsidian_note
Translate an Obsidian note from its obsidian:// URL and update the original file. Choose replace, append, or parallel mode for the target language translation.
Instructions
Translate an Obsidian note from obsidian:// URL and update the original file
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Obsidian URL in format: obsidian://open?vault=VaultName&file=path/to/note.md | |
| targetLanguage | No | Target language for translation (default: 日本語) | 日本語 |
| mode | No | Translation mode: replace original, append translation, or create parallel version | replace |
Implementation Reference
- src/tools/translate.ts:59-144 (handler)The main handler/execute method for the translate_obsidian_note tool. It parses the obsidian URL, validates the vault/path, reads the file, creates a backup, calls the translation service, and updates the file based on the mode (replace/append/parallel).
async execute(request: TranslationRequest): Promise<TranslationResult> { try { // URLを解析 const parsedUrl = ObsidianUrlParser.parse(request.url); // Vaultの検証 ObsidianUrlParser.validateVault(parsedUrl.vault, this.configuredVault); // パスの検証 ObsidianUrlParser.validatePath(parsedUrl.path); // ファイルの存在確認 if (!(await this.fileSystem.exists(parsedUrl.path))) { throw new Error(`${ErrorCode.FILE_NOT_FOUND}: File '${parsedUrl.path}' not found`); } // 元のファイルを読み込み const originalContent = await this.fileSystem.readFile(parsedUrl.path); // バックアップを作成 const backupInfo = await this.fileSystem.createBackup(parsedUrl.path); // 翻訳を実行 const translatedContent = await this.translationService.translateContent( originalContent, request.targetLanguage || '日本語' ); // 翻訳モードに応じてファイルを更新 await this.updateFileByMode( parsedUrl.path, originalContent, translatedContent, request.mode || 'replace' ); // 古いバックアップをクリーンアップ await this.fileSystem.cleanupOldBackups(parsedUrl.path.split('/').slice(0, -1).join('/')); return { originalContent, translatedContent, backupPath: backupInfo.backupPath, timestamp: backupInfo.timestamp }; } catch (error) { if (error instanceof Error) { throw error; } throw new Error(`${ErrorCode.TRANSLATION_FAILED}: Unknown error occurred`); } } /** * 翻訳モードに応じてファイルを更新 * @param filePath ファイルパス * @param originalContent 元のコンテンツ * @param translatedContent 翻訳されたコンテンツ * @param mode 翻訳モード */ private async updateFileByMode( filePath: string, originalContent: string, translatedContent: string, mode: 'replace' | 'append' | 'parallel' ): Promise<void> { switch (mode) { case 'replace': await this.fileSystem.writeFile(filePath, translatedContent); break; case 'append': const appendedContent = originalContent + '\\n\\n---\\n\\n# 翻訳版\\n\\n' + translatedContent; await this.fileSystem.writeFile(filePath, appendedContent); break; case 'parallel': // 並列表示用の新しいファイルを作成 const parallelPath = filePath.replace(/\\.md$/, '.ja.md'); await this.fileSystem.writeFile(parallelPath, translatedContent); break; default: throw new Error(`${ErrorCode.TRANSLATION_FAILED}: Invalid mode '${mode}'`); } } - src/index.ts:149-174 (handler)The MCP server's handler function that receives the tool call for 'translate_obsidian_note', extracts url/targetLanguage/mode from args, calls translateTool.execute(), and formats the result as a text response.
private async handleTranslateNote(args: any) { const { url, targetLanguage, mode } = args; if (!url) { throw new McpError(ErrorCode.InvalidParams, 'URL is required'); } const result = await this.translateTool.execute({ url, targetLanguage, mode }); return { content: [ { type: 'text', text: `✅ 翻訳が完了しました\\n\\n` + `📁 ファイル: ${url}\\n` + `🔄 バックアップ: ${result.backupPath}\\n` + `⏰ 実行時刻: ${result.timestamp}\\n\\n` + `翻訳後のコンテンツ:\\n${result.translatedContent.substring(0, 500)}${result.translatedContent.length > 500 ? '...' : ''}` } ] }; } - src/tools/translate.ts:26-52 (schema)The tool definition (schema) for translate_obsidian_note, including name, description, and inputSchema defining 'url' (required), 'targetLanguage' (optional, default 日本語), and 'mode' (optional, enum: replace/append/parallel).
static getToolDefinition(): Tool { return { name: 'translate_obsidian_note', description: 'Translate an Obsidian note from obsidian:// URL and update the original file', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Obsidian URL in format: obsidian://open?vault=VaultName&file=path/to/note.md' }, targetLanguage: { type: 'string', description: 'Target language for translation (default: 日本語)', default: '日本語' }, mode: { type: 'string', enum: ['replace', 'append', 'parallel'], description: 'Translation mode: replace original, append translation, or create parallel version', default: 'replace' } }, required: ['url'] } }; } - src/index.ts:108-109 (registration)Registration of translate_obsidian_note in the switch case of CallToolRequestSchema, dispatching to handleTranslateNote.
case 'translate_obsidian_note': return await this.handleTranslateNote(args); - src/tools/translate.ts:119-144 (helper)Helper method that updates the file according to the translation mode: 'replace' overwrites, 'append' adds at the end, 'parallel' creates a .ja.md file.
private async updateFileByMode( filePath: string, originalContent: string, translatedContent: string, mode: 'replace' | 'append' | 'parallel' ): Promise<void> { switch (mode) { case 'replace': await this.fileSystem.writeFile(filePath, translatedContent); break; case 'append': const appendedContent = originalContent + '\\n\\n---\\n\\n# 翻訳版\\n\\n' + translatedContent; await this.fileSystem.writeFile(filePath, appendedContent); break; case 'parallel': // 並列表示用の新しいファイルを作成 const parallelPath = filePath.replace(/\\.md$/, '.ja.md'); await this.fileSystem.writeFile(parallelPath, translatedContent); break; default: throw new Error(`${ErrorCode.TRANSLATION_FAILED}: Invalid mode '${mode}'`); } }