translategemma-27b-it实战教程:Ollama WebUI定制化开发——添加多语种快捷翻译按钮

你是不是也遇到过这样的场景?在Ollama WebUI里用translategemma-27b-it翻译模型,每次都要手动输入一大段提示词,比如“请将这段中文翻译成英文”,或者“把这张图片里的法文翻译成中文”。虽然模型翻译效果不错,但反复输入同样的指令确实有点麻烦。

今天我就来分享一个实用技巧:如何给Ollama WebUI添加多语种快捷翻译按钮。这个功能实现后,你只需要点击一下按钮,就能自动填充对应的翻译指令,大大提升使用效率。整个过程不需要修改Ollama的核心代码,只需要在前端做一些简单的定制化开发。

1. 理解translategemma-27b-it的工作方式

在开始动手之前,我们先要搞清楚translategemma-27b-it这个模型是怎么工作的。理解了它的输入输出格式,我们才能设计出合适的快捷按钮。

1.1 模型的基本特性

translategemma-27b-it是Google基于Gemma 3系列构建的轻量级翻译模型。它有以下几个特点:

  • 支持55种语言:覆盖了全球主要语种,从中文、英文到法语、德语、日语等
  • 支持图文翻译:不仅能翻译纯文本,还能识别图片中的文字并进行翻译
  • 输入格式灵活:可以接受文本字符串,也可以处理896×896分辨率的图片
  • 上下文长度2K:总输入上下文长度为2000个token,适合处理中等长度的翻译任务

1.2 标准使用流程

按照官方文档,使用translategemma-27b-it的标准流程是这样的:

  1. 在Ollama WebUI中选择translategemma:27b模型
  2. 在输入框中输入完整的翻译指令
  3. 如果需要翻译图片,上传图片并等待模型处理
  4. 获取翻译结果

比如要翻译中文到英文,你需要输入这样的提示词:

你是一名专业的中文(zh-Hans)至英语(en)翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循英语语法、词汇及文化敏感性规范。
仅输出英文译文,无需额外解释或评论。请将以下文本翻译成英文:
[这里放你要翻译的文本]

每次都要输入这么长的指令,确实不够方便。接下来我们就来解决这个问题。

2. 分析Ollama WebUI的界面结构

要添加快捷按钮,首先需要了解Ollama WebUI的界面结构。这样我们才知道在哪里添加按钮,以及如何让按钮与现有的输入框交互。

2.1 界面元素分析

打开Ollama WebUI,我们可以看到几个关键部分:

  • 模型选择下拉框:位于页面顶部,用于选择不同的模型
  • 对话历史区域:显示之前的对话记录
  • 输入框区域:包含文本输入框和发送按钮
  • 附加功能区域:可能包含文件上传、设置等按钮

我们的目标是在输入框附近添加一排翻译快捷按钮,让用户能够快速选择翻译方向。

2.2 技术实现思路

实现这个功能有几种思路:

  1. 浏览器扩展:开发一个Chrome或Firefox扩展,在Ollama WebUI页面上注入自定义按钮
  2. 用户脚本:使用Tampermonkey等用户脚本管理器,通过JavaScript修改页面
  3. 修改本地文件:直接修改Ollama WebUI的前端代码(如果部署在本地)

考虑到易用性和普及性,我将重点介绍第二种方法——使用用户脚本。这种方法不需要安装额外的浏览器扩展,只需要一个脚本管理器,而且对用户来说更安全。

3. 创建多语种翻译按钮脚本

现在我们来具体实现这个功能。我将提供一个完整的用户脚本,你可以直接复制使用。

3.1 脚本的基本结构

首先,我们需要创建一个新的用户脚本。如果你使用Tampermonkey,点击“添加新脚本”,然后粘贴以下代码:

// ==UserScript==
// @name         Ollama WebUI 翻译快捷按钮
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  为Ollama WebUI添加多语种翻译快捷按钮
// @author       YourName
// @match        http://localhost:11434/*
// @match        https://your-ollama-domain.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    
    // 等待页面加载完成
    window.addEventListener('load', function() {
        // 延迟执行,确保所有元素都已加载
        setTimeout(initTranslationButtons, 2000);
    });
    
    function initTranslationButtons() {
        // 这里将添加按钮创建和事件处理逻辑
    }
})();

这个脚本框架做了几件事:

  • 定义了脚本的基本信息(名称、版本、描述等)
  • 指定了脚本生效的网址(你需要根据实际情况修改@match规则)
  • 等待页面完全加载后再执行初始化
  • 设置了2秒的延迟,确保Ollama WebUI的所有元素都已就位

3.2 定义翻译语言对

接下来,我们需要定义支持的翻译方向。translategemma-27b-it支持55种语言,但我们不需要全部显示,只需要选择最常用的几种即可。

initTranslationButtons函数之前,添加以下配置:

// 常用翻译语言对配置
const translationPresets = [
    {
        id: 'zh2en',
        name: '中→英',
        sourceLang: '中文(zh-Hans)',
        targetLang: '英语(en)',
        prompt: `你是一名专业的${sourceLang}至${targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循${targetLang}语法、词汇及文化敏感性规范。
仅输出${targetLang}译文,无需额外解释或评论。请将以下文本翻译成${targetLang}:\n\n`
    },
    {
        id: 'en2zh',
        name: '英→中',
        sourceLang: '英语(en)',
        targetLang: '中文(zh-Hans)',
        prompt: `你是一名专业的${sourceLang}至${targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循${targetLang}语法、词汇及文化敏感性规范。
仅输出${targetLang}译文,无需额外解释或评论。请将以下文本翻译成${targetLang}:\n\n`
    },
    {
        id: 'zh2ja',
        name: '中→日',
        sourceLang: '中文(zh-Hans)',
        targetLang: '日语(ja)',
        prompt: `你是一名专业的${sourceLang}至${targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循${targetLang}语法、词汇及文化敏感性规范。
仅输出${targetLang}译文,无需额外解释或评论。请将以下文本翻译成${targetLang}:\n\n`
    },
    {
        id: 'ja2zh',
        name: '日→中',
        sourceLang: '日语(ja)',
        targetLang: '中文(zh-Hans)',
        prompt: `你是一名专业的${sourceLang}至${targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循${targetLang}语法、词汇及文化敏感性规范。
仅输出${targetLang}译文,无需额外解释或评论。请将以下文本翻译成${targetLang}:\n\n`
    },
    {
        id: 'zh2fr',
        name: '中→法',
        sourceLang: '中文(zh-Hans)',
        targetLang: '法语(fr)',
        prompt: `你是一名专业的${sourceLang}至${targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循${targetLang}语法、词汇及文化敏感性规范。
仅输出${targetLang}译文,无需额外解释或评论。请将以下文本翻译成${targetLang}:\n\n`
    },
    {
        id: 'fr2zh',
        name: '法→中',
        sourceLang: '法语(fr)',
        targetLang: '中文(zh-Hans)',
        prompt: `你是一名专业的${sourceLang}至${targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循${targetLang}语法、词汇及文化敏感性规范。
仅输出${targetLang}译文,无需额外解释或评论。请将以下文本翻译成${targetLang}:\n\n`
    }
];

// 图片翻译的特殊提示词
const imageTranslationPrompt = `你是一名专业的翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循目标语言的语法、词汇及文化敏感性规范。
仅输出译文,无需额外解释或评论。请将图片中的文本翻译成目标语言:`;

这里我定义了6个最常用的翻译方向:中英互译、中日互译、中法互译。你可以根据需要添加更多语言对。

3.3 创建按钮容器和按钮

现在我们来完善initTranslationButtons函数,创建实际的按钮界面:

function initTranslationButtons() {
    // 查找输入框容器
    const inputContainer = document.querySelector('.input-container, [class*="input"], textarea').closest('div');
    
    if (!inputContainer) {
        console.log('未找到输入框容器,等待重试...');
        setTimeout(initTranslationButtons, 1000);
        return;
    }
    
    // 创建按钮容器
    const buttonContainer = document.createElement('div');
    buttonContainer.id = 'translation-buttons-container';
    buttonContainer.style.cssText = `
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        margin-bottom: 12px;
        padding: 10px;
        background: #f5f5f5;
        border-radius: 8px;
        border: 1px solid #ddd;
    `;
    
    // 添加标题
    const title = document.createElement('div');
    title.textContent = '快速翻译:';
    title.style.cssText = `
        width: 100%;
        font-weight: bold;
        margin-bottom: 8px;
        color: #333;
        font-size: 14px;
    `;
    buttonContainer.appendChild(title);
    
    // 创建按钮行容器
    const buttonRow = document.createElement('div');
    buttonRow.style.cssText = `
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        width: 100%;
    `;
    
    // 为每个翻译预设创建按钮
    translationPresets.forEach(preset => {
        const button = document.createElement('button');
        button.textContent = preset.name;
        button.dataset.presetId = preset.id;
        button.style.cssText = `
            padding: 6px 12px;
            background: #4a90e2;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 13px;
            transition: background 0.2s;
        `;
        
        // 添加悬停效果
        button.addEventListener('mouseenter', () => {
            button.style.background = '#357ae8';
        });
        button.addEventListener('mouseleave', () => {
            button.style.background = '#4a90e2';
        });
        
        // 添加点击事件
        button.addEventListener('click', () => {
            applyTranslationPreset(preset);
        });
        
        buttonRow.appendChild(button);
    });
    
    // 添加图片翻译按钮
    const imageButton = document.createElement('button');
    imageButton.textContent = '图片翻译';
    imageButton.style.cssText = `
        padding: 6px 12px;
        background: #34a853;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
        font-size: 13px;
        transition: background 0.2s;
    `;
    
    imageButton.addEventListener('mouseenter', () => {
        imageButton.style.background = '#2e8b47';
    });
    imageButton.addEventListener('mouseleave', () => {
        imageButton.style.background = '#34a853';
    });
    
    imageButton.addEventListener('click', () => {
        applyImageTranslation();
    });
    
    buttonRow.appendChild(imageButton);
    buttonContainer.appendChild(buttonRow);
    
    // 将按钮容器插入到输入框上方
    inputContainer.parentNode.insertBefore(buttonContainer, inputContainer);
    
    console.log('翻译快捷按钮已添加');
}

这段代码创建了一个美观的按钮栏,包含所有预设的翻译按钮和一个专门的图片翻译按钮。按钮有悬停效果,点击后会调用相应的处理函数。

3.4 实现按钮功能

现在我们需要实现按钮点击后的具体功能。添加以下函数:

function applyTranslationPreset(preset) {
    // 查找文本输入框
    const textarea = document.querySelector('textarea');
    
    if (!textarea) {
        alert('未找到输入框');
        return;
    }
    
    // 获取当前输入框的内容
    const currentText = textarea.value;
    
    // 检查是否已经包含翻译指令
    const hasTranslationInstruction = currentText.includes('翻译员') || 
                                     currentText.includes('translate') ||
                                     currentText.includes('翻译成');
    
    let newText = '';
    
    if (hasTranslationInstruction) {
        // 如果已有翻译指令,替换为新的
        const lines = currentText.split('\n');
        const instructionIndex = lines.findIndex(line => 
            line.includes('翻译员') || line.includes('translate')
        );
        
        if (instructionIndex !== -1) {
            // 保留用户输入的待翻译文本
            const userText = lines.slice(instructionIndex + 1).join('\n').trim();
            newText = preset.prompt.replace('${sourceLang}', preset.sourceLang)
                                  .replace('${targetLang}', preset.targetLang) + 
                     (userText ? userText + '\n' : '');
        } else {
            // 如果没有找到明确的指令行,直接替换整个内容
            newText = preset.prompt.replace('${sourceLang}', preset.sourceLang)
                                  .replace('${targetLang}', preset.targetLang);
        }
    } else {
        // 如果没有翻译指令,添加新的
        if (currentText.trim()) {
            // 如果已有文本,将其作为待翻译内容
            newText = preset.prompt.replace('${sourceLang}', preset.sourceLang)
                                  .replace('${targetLang}', preset.targetLang) + 
                     currentText + '\n';
        } else {
            // 如果输入框为空,只添加指令
            newText = preset.prompt.replace('${sourceLang}', preset.sourceLang)
                                  .replace('${targetLang}', preset.targetLang);
        }
    }
    
    // 更新输入框内容
    textarea.value = newText;
    
    // 自动聚焦到输入框
    textarea.focus();
    
    // 触发输入事件,确保UI更新
    textarea.dispatchEvent(new Event('input', { bubbles: true }));
    
    // 显示提示
    showNotification(`已应用${preset.name}翻译模板`);
}

function applyImageTranslation() {
    const textarea = document.querySelector('textarea');
    
    if (!textarea) {
        alert('未找到输入框');
        return;
    }
    
    // 设置图片翻译提示词
    const currentText = textarea.value;
    let newText = '';
    
    if (currentText.includes('图片') || currentText.includes('image')) {
        // 如果已经是图片翻译,保留用户可能添加的额外说明
        const lines = currentText.split('\n');
        const instructionEnd = lines.findIndex(line => line.includes('文本翻译'));
        
        if (instructionEnd !== -1) {
            const userText = lines.slice(instructionEnd + 1).join('\n').trim();
            newText = imageTranslationPrompt + (userText ? '\n\n' + userText : '');
        } else {
            newText = imageTranslationPrompt;
        }
    } else {
        newText = imageTranslationPrompt;
    }
    
    textarea.value = newText;
    textarea.focus();
    textarea.dispatchEvent(new Event('input', { bubbles: true }));
    
    showNotification('已应用图片翻译模板,请上传需要翻译的图片');
}

function showNotification(message) {
    // 创建通知元素
    const notification = document.createElement('div');
    notification.textContent = message;
    notification.style.cssText = `
        position: fixed;
        top: 20px;
        right: 20px;
        background: #4a90e2;
        color: white;
        padding: 12px 20px;
        border-radius: 4px;
        z-index: 10000;
        font-size: 14px;
        box-shadow: 0 2px 10px rgba(0,0,0,0.2);
        animation: slideIn 0.3s ease-out;
    `;
    
    // 添加动画样式
    const style = document.createElement('style');
    style.textContent = `
        @keyframes slideIn {
            from {
                transform: translateX(100%);
                opacity: 0;
            }
            to {
                transform: translateX(0);
                opacity: 1;
            }
        }
        @keyframes fadeOut {
            from {
                opacity: 1;
            }
            to {
                opacity: 0;
            }
        }
    `;
    document.head.appendChild(style);
    
    document.body.appendChild(notification);
    
    // 3秒后自动移除
    setTimeout(() => {
        notification.style.animation = 'fadeOut 0.3s ease-out';
        setTimeout(() => {
            if (notification.parentNode) {
                notification.parentNode.removeChild(notification);
            }
        }, 300);
    }, 3000);
}

这些函数实现了按钮的核心功能:

  • applyTranslationPreset:处理文本翻译按钮点击,智能处理输入框内容
  • applyImageTranslation:处理图片翻译按钮点击
  • showNotification:显示操作反馈,提升用户体验

3.5 添加模型检测功能

为了让脚本更加智能,我们还可以添加模型检测功能,只在translategemma模型激活时显示翻译按钮:

// 添加模型检测函数
function checkCurrentModel() {
    // 尝试查找模型选择元素
    const modelSelect = document.querySelector('select, [class*="model"], [class*="Model"]');
    
    if (modelSelect) {
        const currentModel = modelSelect.value || modelSelect.textContent;
        
        // 检查是否是translategemma模型
        const isTranslateModel = currentModel.toLowerCase().includes('translategemma') || 
                                currentModel.toLowerCase().includes('translate');
        
        const buttonContainer = document.getElementById('translation-buttons-container');
        
        if (isTranslateModel) {
            // 如果是翻译模型,显示按钮
            if (buttonContainer) {
                buttonContainer.style.display = 'flex';
            } else {
                // 如果按钮容器不存在,重新初始化
                initTranslationButtons();
            }
        } else {
            // 如果不是翻译模型,隐藏按钮
            if (buttonContainer) {
                buttonContainer.style.display = 'none';
            }
        }
    }
}

// 修改初始化函数,添加模型变化监听
function initTranslationButtons() {
    // ... 之前的代码不变 ...
    
    // 添加模型变化监听
    const modelSelect = document.querySelector('select, [class*="model"], [class*="Model"]');
    if (modelSelect) {
        modelSelect.addEventListener('change', checkCurrentModel);
    }
    
    // 初始检查
    checkCurrentModel();
    
    // 定期检查(防止动态加载)
    setInterval(checkCurrentModel, 3000);
}

4. 完整脚本与使用指南

现在我把完整的脚本代码提供给你,并说明如何使用。

4.1 完整用户脚本代码

// ==UserScript==
// @name         Ollama WebUI 翻译快捷按钮
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  为Ollama WebUI添加多语种翻译快捷按钮,支持translategemma-27b-it等翻译模型
// @author       CSDN技术博客
// @match        http://localhost:11434/*
// @match        http://127.0.0.1:11434/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    
    // 常用翻译语言对配置
    const translationPresets = [
        {
            id: 'zh2en',
            name: '中→英',
            sourceLang: '中文(zh-Hans)',
            targetLang: '英语(en)',
            prompt: `你是一名专业的{sourceLang}至{targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循{targetLang}语法、词汇及文化敏感性规范。
仅输出{targetLang}译文,无需额外解释或评论。请将以下文本翻译成{targetLang}:\n\n`
        },
        {
            id: 'en2zh',
            name: '英→中', 
            sourceLang: '英语(en)',
            targetLang: '中文(zh-Hans)',
            prompt: `你是一名专业的{sourceLang}至{targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循{targetLang}语法、词汇及文化敏感性规范。
仅输出{targetLang}译文,无需额外解释或评论。请将以下文本翻译成{targetLang}:\n\n`
        },
        {
            id: 'zh2ja',
            name: '中→日',
            sourceLang: '中文(zh-Hans)',
            targetLang: '日语(ja)',
            prompt: `你是一名专业的{sourceLang}至{targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循{targetLang}语法、词汇及文化敏感性规范。
仅输出{targetLang}译文,无需额外解释或评论。请将以下文本翻译成{targetLang}:\n\n`
        },
        {
            id: 'ja2zh',
            name: '日→中',
            sourceLang: '日语(ja)',
            targetLang: '中文(zh-Hans)',
            prompt: `你是一名专业的{sourceLang}至{targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循{targetLang}语法、词汇及文化敏感性规范。
仅输出{targetLang}译文,无需额外解释或评论。请将以下文本翻译成{targetLang}:\n\n`
        },
        {
            id: 'zh2fr',
            name: '中→法',
            sourceLang: '中文(zh-Hans)',
            targetLang: '法语(fr)',
            prompt: `你是一名专业的{sourceLang}至{targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循{targetLang}语法、词汇及文化敏感性规范。
仅输出{targetLang}译文,无需额外解释或评论。请将以下文本翻译成{targetLang}:\n\n`
        },
        {
            id: 'fr2zh',
            name: '法→中',
            sourceLang: '法语(fr)',
            targetLang: '中文(zh-Hans)',
            prompt: `你是一名专业的{sourceLang}至{targetLang}翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循{targetLang}语法、词汇及文化敏感性规范。
仅输出{targetLang}译文,无需额外解释或评论。请将以下文本翻译成{targetLang}:\n\n`
        }
    ];

    // 图片翻译提示词
    const imageTranslationPrompt = `你是一名专业的翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循目标语言的语法、词汇及文化敏感性规范。
仅输出译文,无需额外解释或评论。请将图片中的文本翻译成目标语言:`;

    // 等待页面加载
    window.addEventListener('load', function() {
        setTimeout(initTranslationButtons, 2000);
    });

    function initTranslationButtons() {
        // 查找输入区域
        const inputAreas = document.querySelectorAll('textarea');
        if (inputAreas.length === 0) {
            setTimeout(initTranslationButtons, 1000);
            return;
        }

        const textarea = inputAreas[0];
        const inputContainer = textarea.closest('div') || textarea.parentElement;
        
        if (!inputContainer) {
            setTimeout(initTranslationButtons, 1000);
            return;
        }

        // 检查是否已添加按钮
        if (document.getElementById('translation-buttons-container')) {
            return;
        }

        // 创建按钮容器
        const buttonContainer = document.createElement('div');
        buttonContainer.id = 'translation-buttons-container';
        buttonContainer.style.cssText = `
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            margin-bottom: 12px;
            padding: 12px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            border-radius: 10px;
            border: none;
            box-shadow: 0 4px 15px rgba(0,0,0,0.1);
        `;

        // 添加标题
        const title = document.createElement('div');
        title.textContent = '🚀 快速翻译';
        title.style.cssText = `
            width: 100%;
            font-weight: bold;
            margin-bottom: 10px;
            color: white;
            font-size: 16px;
            text-shadow: 0 1px 2px rgba(0,0,0,0.2);
        `;
        buttonContainer.appendChild(title);

        // 创建按钮行
        const buttonRow = document.createElement('div');
        buttonRow.style.cssText = `
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            width: 100%;
        `;

        // 添加翻译按钮
        translationPresets.forEach(preset => {
            const button = document.createElement('button');
            button.textContent = preset.name;
            button.dataset.presetId = preset.id;
            button.style.cssText = `
                padding: 8px 16px;
                background: rgba(255,255,255,0.9);
                color: #333;
                border: none;
                border-radius: 6px;
                cursor: pointer;
                font-size: 14px;
                font-weight: 500;
                transition: all 0.2s;
                box-shadow: 0 2px 5px rgba(0,0,0,0.1);
            `;

            button.addEventListener('mouseenter', () => {
                button.style.background = 'white';
                button.style.transform = 'translateY(-2px)';
                button.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
            });
            
            button.addEventListener('mouseleave', () => {
                button.style.background = 'rgba(255,255,255,0.9)';
                button.style.transform = 'translateY(0)';
                button.style.boxShadow = '0 2px 5px rgba(0,0,0,0.1)';
            });

            button.addEventListener('click', () => {
                applyTranslationPreset(preset);
            });

            buttonRow.appendChild(button);
        });

        // 添加图片翻译按钮
        const imageButton = document.createElement('button');
        imageButton.textContent = '🖼️ 图片翻译';
        imageButton.style.cssText = `
            padding: 8px 16px;
            background: rgba(52, 168, 83, 0.9);
            color: white;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.2s;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        `;

        imageButton.addEventListener('mouseenter', () => {
            imageButton.style.background = 'rgb(46, 139, 71)';
            imageButton.style.transform = 'translateY(-2px)';
            imageButton.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
        });
        
        imageButton.addEventListener('mouseleave', () => {
            imageButton.style.background = 'rgba(52, 168, 83, 0.9)';
            imageButton.style.transform = 'translateY(0)';
            imageButton.style.boxShadow = '0 2px 5px rgba(0,0,0,0.1)';
        });

        imageButton.addEventListener('click', applyImageTranslation);
        buttonRow.appendChild(imageButton);

        buttonContainer.appendChild(buttonRow);
        inputContainer.parentNode.insertBefore(buttonContainer, inputContainer);

        // 添加模型检测
        setupModelDetection();
    }

    function applyTranslationPreset(preset) {
        const textarea = document.querySelector('textarea');
        if (!textarea) return;

        const currentText = textarea.value;
        const prompt = preset.prompt
            .replace('{sourceLang}', preset.sourceLang)
            .replace('{targetLang}', preset.targetLang);

        let newText = '';
        
        if (currentText.includes('翻译员') || currentText.includes('translate')) {
            // 替换现有翻译指令
            const lines = currentText.split('\n');
            const userText = lines.slice(-1)[0].trim() ? lines.slice(-1).join('\n') : '';
            newText = prompt + (userText || '');
        } else if (currentText.trim()) {
            // 添加翻译指令并保留现有文本
            newText = prompt + currentText;
        } else {
            // 只添加翻译指令
            newText = prompt;
        }

        textarea.value = newText;
        textarea.focus();
        textarea.dispatchEvent(new Event('input', { bubbles: true }));
        showNotification(`✅ 已应用 ${preset.name} 翻译模板`);
    }

    function applyImageTranslation() {
        const textarea = document.querySelector('textarea');
        if (!textarea) return;

        textarea.value = imageTranslationPrompt;
        textarea.focus();
        textarea.dispatchEvent(new Event('input', { bubbles: true }));
        showNotification('🖼️ 已应用图片翻译模板,请上传需要翻译的图片');
    }

    function showNotification(message) {
        const notification = document.createElement('div');
        notification.textContent = message;
        notification.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 12px 24px;
            border-radius: 8px;
            z-index: 10000;
            font-size: 14px;
            font-weight: 500;
            box-shadow: 0 4px 15px rgba(0,0,0,0.2);
            animation: slideIn 0.3s ease-out;
        `;

        const style = document.createElement('style');
        style.textContent = `
            @keyframes slideIn {
                from { transform: translateX(100%); opacity: 0; }
                to { transform: translateX(0); opacity: 1; }
            }
            @keyframes fadeOut {
                from { opacity: 1; }
                to { opacity: 0; }
            }
        `;
        document.head.appendChild(style);

        document.body.appendChild(notification);

        setTimeout(() => {
            notification.style.animation = 'fadeOut 0.3s ease-out';
            setTimeout(() => notification.remove(), 300);
        }, 3000);
    }

    function setupModelDetection() {
        // 定期检查当前模型
        setInterval(() => {
            const modelSelect = document.querySelector('select');
            if (modelSelect) {
                const currentModel = modelSelect.value || modelSelect.textContent;
                const buttonContainer = document.getElementById('translation-buttons-container');
                
                if (buttonContainer) {
                    if (currentModel.toLowerCase().includes('translategemma') || 
                        currentModel.toLowerCase().includes('translate')) {
                        buttonContainer.style.display = 'flex';
                    } else {
                        buttonContainer.style.display = 'none';
                    }
                }
            }
        }, 2000);
    }
})();

4.2 安装和使用步骤

按照以下步骤安装和使用这个脚本:

  1. 安装Tampermonkey扩展

    • 打开Chrome浏览器(或其他基于Chromium的浏览器)
    • 访问Chrome网上应用店
    • 搜索"Tampermonkey"并安装
  2. 创建新脚本

    • 点击浏览器右上角的Tampermonkey图标
    • 选择"创建新脚本"
    • 删除默认代码,粘贴上面提供的完整脚本代码
  3. 修改匹配规则

    • 找到代码中的@match部分
    • http://localhost:11434/*改为你的Ollama WebUI地址
    • 如果你的Ollama运行在其他端口或域名,添加相应的匹配规则
  4. 保存并启用

    • Ctrl+S保存脚本
    • 确保脚本处于启用状态(Tampermonkey管理面板中开关为绿色)
  5. 使用翻译按钮

    • 打开Ollama WebUI
    • 选择translategemma:27b模型
    • 在输入框上方会出现翻译快捷按钮栏
    • 点击相应按钮即可快速应用翻译指令

4.3 自定义配置

如果你需要添加更多语言对,可以修改translationPresets数组。每个预设对象包含以下属性:

{
    id: '唯一标识',           // 如'zh2de'表示中文到德语
    name: '显示名称',         // 按钮上显示的文字,如'中→德'
    sourceLang: '源语言',     // 完整的语言名称,如'中文(zh-Hans)'
    targetLang: '目标语言',   // 完整的语言名称,如'德语(de)'
    prompt: '提示词模板'      // 翻译指令模板,使用{sourceLang}和{targetLang}作为占位符
}

5. 效果展示与使用技巧

5.1 实际效果展示

安装脚本后,当你打开Ollama WebUI并选择translategemma模型时,会在输入框上方看到一个美观的按钮栏:

翻译按钮效果示意图

点击"中→英"按钮,输入框会自动填充:

你是一名专业的中文(zh-Hans)至英语(en)翻译员。你的目标是准确传达原文的含义与细微差别,同时遵循英语语法、词汇及文化敏感性规范。
仅输出英文译文,无需额外解释或评论。请将以下文本翻译成英文:

你只需要在后面输入要翻译的中文文本即可。

5.2 使用技巧和建议

  1. 智能替换:如果输入框中已有内容,脚本会智能判断是否需要替换翻译指令,还是保留用户输入的待翻译文本。

  2. 图片翻译:点击"图片翻译"按钮后,会应用专门的图片翻译指令,然后你可以上传包含文字的图片进行翻译。

  3. 多语言支持:脚本预设了6种常用翻译方向,你可以根据需要自行添加更多语言对。

  4. 模型检测:脚本会自动检测当前选择的模型,只在翻译模型激活时显示按钮,避免干扰其他模型的使用。

  5. 响应式设计:按钮栏采用flex布局,在不同屏幕尺寸下都能良好显示。

5.3 常见问题解决

问题1:按钮没有显示

  • 检查Tampermonkey脚本是否启用
  • 检查Ollama WebUI地址是否与脚本匹配规则一致
  • 刷新页面重新加载

问题2:按钮点击没反应

  • 检查浏览器控制台是否有错误信息
  • 确保已选择translategemma模型
  • 尝试重新安装脚本

问题3:提示词格式不正确

  • 检查translategemma模型是否支持你选择的语言对
  • 确保语言代码格式正确(如zh-Hans、en、ja等)

6. 总结

通过这个简单的定制化开发,我们成功为Ollama WebUI添加了多语种快捷翻译按钮功能。这个方案有以下几个优点:

  1. 提升效率:一键填充翻译指令,节省重复输入的时间
  2. 使用方便:无需修改Ollama源代码,通过用户脚本即可实现
  3. 灵活配置:可以轻松添加或修改支持的翻译语言对
  4. 智能适配:自动检测翻译模型,只在需要时显示按钮
  5. 用户体验好:美观的界面设计,流畅的交互效果

这个方案不仅适用于translategemma-27b-it模型,理论上也适用于其他需要特定提示词的模型。你可以根据类似思路,为其他模型创建专属的快捷功能按钮。

翻译模型的使用体验很大程度上取决于交互的便捷性。通过这样的小优化,能让强大的AI翻译能力更好地服务于实际工作需求。希望这个教程对你有所帮助,如果你有更好的想法或改进建议,欢迎在评论区分享交流。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐