Release Notes
Unreleased
v1.8.0 (2026-06-09)
New Features
- Translate comments rendered in Shadow DOM (#252)
- Adds support for Web Components comment systems (open Shadow DOM) like Hyvor Talk. We found in real-world testing that lots of modern comment systems render straight into Shadow DOM rather than a cross-origin iframe like Disqus, so we handle that now.
- The content script walks
shadowRoot recursively to find, watch, and restore translatable elements (deepQuerySelectorAll). Whole-page translation, region select, undo, and dynamic-content watching all pierce Shadow DOM.
- Region select uses
composedPath() to highlight/translate the real element inside the shadow tree (not the host).
- Out of scope: auto-rule selector picking (you can’t write a CSS selector that crosses a shadow boundary) and closed Shadow DOM (unreachable from JS by spec). Decoration CSS isn’t applied inside shadow trees yet, but the feature works.
- Translate Disqus iframe comments (#250)
- The extension now injects its content script into
https://disqus.com/embed/comments/* iframes too, so comment sections on Disqus-powered sites (carscoops, etc.) get translated.
- Works with both whole-page translation and region select (element pick). In region-select mode each frame enters picking independently, so you can click a Disqus comment to translate it — and confirming or canceling in any frame clears the mode everywhere.
- The top frame forwards instructions to child iframes via
window.postMessage — no extra permissions needed.
- Accepted messages are restricted to a custom signature plus an allow-list of actions, and the top frame never runs translate actions from postMessage (only child iframes do) — so another page can’t drive page translation.
- Out of scope: selection translation, context-menu translation, the translate bar, and auto-rules (and other comment platforms like OpenWeb or Facebook Comments for now).
- Nudge you to pin the extension to your toolbar on install (#244 / #247)
- Opens a welcome page right after the first install, walking you through “puzzle-piece → pin icon.”
- Adds a banner at the top of the popup (dismiss it and it won’t come back).
- On browsers that can read the pin state (
chrome.action.getUserSettings(), supported on Chrome 91+, Firefox 116+, etc.), the banner only shows when unpinned and disappears once you pin.
- On older browsers that don’t support
getUserSettings, the banner still shows but stops after you’ve opened the popup a few times — so it never overstays its welcome.
- Browsers don’t let extensions force-pin themselves, so this is purely a UX nudge.
Bug Fixes
- Fix mini icon appearing far from the cursor on multi-line selections (#240)
- When selecting text that spans multiple lines,
getBoundingClientRect() returns the bounding box of the entire selection, so right reflects the longest line rather than the cursor position — making the icon appear offset to the right.
- Now uses
getClientRects() to get per-line rects and picks the last one, which matches the cursor position.
- Falls back to
getBoundingClientRect() in environments where getClientRects() returns an empty list (e.g. jsdom).
- Fix outer vertical bar showing up next to source lines in paired mode (#228)
- The PR #222 follow-up that forced an inline
border-left on .dvt-trans also made the outer bar visible alongside the source (English) lines in sentence-pair mode.
- In paired mode each
.dvt-pair-trans already has its own inner bar, so the outer one is redundant — we now clear it inline.
- Short single-sentence translations (non-paired mode) still keep the outer bar as before.
- Fix translation background color bleeding behind source lines in paired mode (#230)
- Same structural issue as #228: the outer
.dvt-trans’s faint orange background spanned the whole pair block in paired mode, so source (English) lines got the translation color behind them too.
- We now clear the outer
.dvt-trans background to transparent inline and move the faint translation color onto each .dvt-pair-trans so only the translation lines pick it up.
- Short single-sentence translations (non-paired mode) keep the outer translation-color background as before.
- Fix original text getting clipped by host line-clamp on region translate (#222 / closes #221)
- On sites like Reddit that truncate post bodies with
-webkit-line-clamp or max-height + overflow:hidden, inserting the translation pushed the tail of the original past the clamp so it disappeared.
- Now we walk up the ancestors when inserting a dual-view block, temporarily lift any clamp / max-height we find, and restore the original inline styles on undo or page reset.
- A refcount on the ancestor handles the case where multiple translated paragraphs share the same clamped container.
Improvements
- Mini icon on selection is now more visible (#235)
- Bumped size from 28px to 36px
- Changed background from white to blue (#1a73e8) so it stands out on any page
- Icon size also increased from 16px to 20px
- Selection translation panel now also supports sentence-pair display for long text (#233)
- The selection panel’s translation now uses the same paired layout as page translation when the translation is 80+ chars and both sides split into 2+ matching sentences — you get “source 1 → translation 1 → source 2 → translation 2…” instead of one big block.
- When paired display kicks in, the panel’s top-of-panel source preview gets hidden so you don’t see the source twice.
- Short text or mismatched sentence counts fall back to the regular single-block layout.
- The speak button only reads the translation lines (
.dvt-pair-trans) even in paired mode — it won’t read the source back to you.
- Instant translation when clicking the mini icon on selection (#234)
- Clicking the 🌐 mini icon that appears after text selection now starts translation immediately as the panel opens — no need to hit the “Translate” button.
- This used to be a 2-step flow: open panel → click “Translate”. Now it’s 1 click, matching the right-click context-menu translation behavior.
- Sentence-level pairing for long paragraphs (#214 / #219)
- Fixes the visual gap between the end of the source block and the start of the translation block in long paragraphs.
- Translation still happens at the paragraph level so accuracy isn’t compromised. When sentence counts match on both sides, we interleave them: “source 1 → translation 1 → source 2 → translation 2…”
- Falls back to the original single-pair layout when sentence counts don’t match, when the paragraph contains inline elements (e.g.
<a>), or when the paragraph is short.
- Same sentence-pair logic now also applies to the iOS / macOS Share Extension (#219).
- “dev” badge for unpacked developer-mode loads (#216)
- The popup now shows a red
dev badge next to the version number when the extension was loaded as an unpacked developer build, so you can tell at a glance whether you’re poking at the dev copy or the store-installed one.
- Detection uses
chrome.management.getSelf()’s installType === 'development' — no extra permission required.
- Store builds (Chrome Web Store / Firefox AMO / App Store) and enterprise sideloads don’t get the badge.
v1.7.1 (2026-05-20)
New features
- Sync settings across devices (#205)
- The Settings tab now has a “Sync between devices” section. Tick the checkbox to enable
chrome.storage.sync-backed syncing.
- Synced: target language, translation engine, summary engine, auto-translate rules, dismissed domains, UI language.
- API keys are NOT synced — they stay local to each device to avoid leaking them through the cloud account. Set them per device.
- Engines: Google account on Chrome / Edge, Firefox account on Firefox, iCloud Keychain on Safari (beta).
- First-time enable: cloud values win (so settings already synced from another device are kept), and any local-only keys get pushed up.
- Hits chrome.storage.sync limits (8KB per item / 100KB total) → shows an inline error.
- Settings export / import (#206)
- The Settings tab now has a “Settings backup” section.
- You can back up and restore target language, engine choices, auto-translate rules, dismissed domains, and UI language as a JSON file.
- API keys are not included by default. Tick “Include API keys” to opt in — it’s a separate toggle so you don’t leak them by accident.
- Import: on Chrome / Edge / Safari, hit “Load from file” to pick the JSON directly. The file picker button is hidden on Firefox because Firefox popups close themselves when alert(), confirm(), or a file picker opens — paste the JSON into the textarea instead. Status messages stay inline for the same reason.
- Import is a merge — only the keys in the JSON get written, keys not in the file (e.g. API keys when you exported without them) stay as they were. Mismatched versions are rejected, invalid values are silently dropped.
- Translation/summary caches and hit-rate stats aren’t included (too big, and device-specific anyway). Theme is also excluded — it’s re-derived from
prefers-color-scheme every page load.
Bug Fixes
- Fixed the translate bar showing up on pages with underscore-style lang codes like
<html lang="ja_JP"> (#204)
- With Japanese as the target language, you’d still see “This page is in ja_JP. Translate?” — same language, but the bar showed up anyway.
- Language-code comparison and display-name lookup now treat
_ the same as -, so ja_JP collapses to ja like it should.
- Apple Translation errors now show detail in the UI (#202 / PR #203)
- Previously a failed translation just said
[Translation failed] with no hint of why. Now the error message from the native handler is appended, so you can actually see what went wrong.
- Fixed a bug where
appleAvailable was set to true on iOS Safari even though the translate action isn’t implemented there (Extension processes don’t have a UIWindowScene). The ping response now includes a translateActionSupported flag (false on iOS), so Apple Translation no longer appears as an option on iPhone.
- Fixed Escape not canceling “Pick area to translate” on Firefox (#211)
- When you opened the popup and clicked the area-pick button, keyboard focus stayed in the browser chrome instead of returning to the page, so the
keydown listener on document never fired.
- We now call
window.focus() when entering the mode and listen on window with capture, so Escape cancels reliably. Same fix applied to the element picker in the Rules tab.
v1.7.0 (2026-05-13)
Improvements
- iOS / macOS Share Extension now shows results as a paragraph-by-paragraph dual view (#199 / PR #200)
- The share sheet used to dump the entire translation as a single block. Now it lines up each paragraph with its translation right below — same vibe as the browser extension.
- The translation side gets the same orange left bar (
border-left: 3px solid #f5a623) you already know from the web UI.
- Everything still ships in one API call — we slip a per-request UUID marker between paragraphs and split the response on the way back, so rate limits and translation context stay intact.
- Rendering switched to
WKWebView, which follows your system light/dark theme automatically.
- Shared text is HTML-escaped before rendering, and a CSP blocks any external resource loading — no surprises from untrusted input.
- If the marker split ever goes sideways, we fall back to the old single-block view, so the worst case is the previous behavior.
Bug fixes
- Fixed the translate bar showing “This page is written in null” (#195 / #197 / PR #198)
- Sites with bogus
<html lang> values like "null", "und", or "unknown" were dumping the raw string null straight into the bar where the language name should be.
- We now treat those bogus values as if
lang was missing and fall back to API-based detection.
- If API detection can’t figure out the language either, you’ll see a “Not sure what language this page uses. Want to translate it?” bar instead (localized into all 11 languages).
- Padded values like
<html lang="en "> and whitespace-only <html lang=" "> are now normalized (trim) so they don’t misbehave.
- As a side fix, the i18n placeholder substitution is now
null / undefined safe so the same class of bug can’t reappear elsewhere.
v1.6.2 (2026-05-07)
Bug fixes
- Fixed an App Store / TestFlight upload validation error (PR #192 / #193)
- The Share Extension’s
PRODUCT_NAME carried platform suffixes ((iOS) / (macOS)), which leaked parentheses into CFBundleExecutable — Apple rejected uploads with error 90121.
- Hardcoded
PRODUCT_NAME to "DualView Share Extension" (no parentheses) to resolve.
- No user-visible feature changes.
v1.6.1 (2026-05-07)
Improvements
- Container app startup screen is now localized (#188 / PR #189)
- The Safari-extension-enable prompt you see when you launch the iOS / macOS container app used to be English-only. Now it follows your device language across all 11 supported languages (ja / en / zh-CN / zh-TW / ko / fr / de / es / pt / ru / ar).
- The on/off state messages are localized too.
- macOS Sequoia’s “Safari Settings → Extensions” wording is handled.
- Arabic gets automatic right-to-left layout.
v1.6.0 (2026-05-07)
New features
- iOS / macOS Share Extension (Issue #89, PR #183 / #184 / #185 / #186)
- Pick “DualView Translator” from the share sheet and a side-by-side translation view pops up. Now you can translate text from outside Safari too — Notes, Mail, News, you name it.
- SwiftUI side-by-side view (original / translation) with Copy and Close buttons
- Translation engine is Google Translate for v1. Summarization, DeepL, and Apple Translation are coming in v2.
- Settings (target language, etc.) you set in the web extension are auto-shared via App Group, so you don’t need to configure anything again
- Minimum OS: iOS 15.0 / macOS 12.0 (the existing Safari Web Extension still supports macOS 10.14+)
- Text-to-speech for translations (#181)
- Every translation block now has a 🔊 button — click it and the translation gets read out in your target language
- Placement: selection panel (next to Copy, always visible), inline translation block (left of the ×, on hover), summary block (next to the badge, always visible)
- Icon flips to ⏹ while speaking — click again, press another speak button, hit
Esc, switch tabs, or leave the page to stop it
- Uses your browser’s built-in Web Speech API, so no extra API key or permission is required
- If the OS doesn’t have a voice for the target language, a toast tells you “Your environment does not support speaking {lang}”
Improvements
- Web extension now mirrors the major settings (
uiLang / targetLang / dvtTheme / translateEngine / deeplApiKey / llmEngine / claudeApiKey / geminiApiKey) into the App Group UserDefaults via the native handler. The new Share Extension and any future targets can read your settings without you having to configure anything again (PR #183).
- Inline speak button on the macOS Share Extension UI got better keyboard focus visibility, always-on display on touch environments, and
@media (hover: none) support.
Bug fixes
- Closing the selection panel was stopping the speak playback in inline / summary blocks even when the speak button inside the panel wasn’t the active one — fixed (PR #182).
- Same-language skip in the panel was also stopping playback in other blocks — fixed (same PR).
v1.5.0 (2026-05-01)
New features
- Apple Translation integration (macOS Safari only) (#144, #146, #148, #151)
- You can now pick Apple Translation as your translation engine. It uses the on-device
Translation.framework, so no API keys, no network — it just works offline.
- The new option only shows up in the engine picker on Safari (you won’t see it on Chrome / Firefox at all).
- We auto-detect Safari at startup with a
ping round-trip — no manual setup.
- Under the hood:
chrome.runtime.sendNativeMessage calls into SafariWebExtensionHandler, which hosts a hidden SwiftUI view via NSHostingController so we can pull a TranslationSession out of .translationTask and translate from the extension process.
- Automatic offline fallback (#150, #155)
- If you’re on Google or DeepL and your network drops, we automatically switch to Apple Translation (macOS Safari only).
- Cache-first: if Google / DeepL already has the chunks cached, we serve those instead of unnecessarily falling back.
- Offline language detection via Apple’s
NLLanguageRecognizer (NaturalLanguage framework) means sl='auto' keeps working even when you’re offline.
- We pop a small toast in the bottom-right when the fallback kicks in (just once per page load — no spam).
- Added
engineApple / fallbackToApple i18n keys across all 11 languages.
Milestones
- Now live on the Chrome Web Store (#142)
- Public URL: https://chromewebstore.google.com/detail/dualview-translator/hmnlfemcpbkcfppjnghiofddiiclkbmg
- macOS Safari extension is now live on the Mac App Store (2026-05-01)
- Public URL: https://apps.apple.com/app/dualview-translator/id6763488360
- All four of Chrome / Firefox / iOS Safari / macOS Safari are now served from official stores
Improvements
- Skip the translation block when the result is identical to the original (#138, #140)
- For things like symbol-only text, numbers, URLs, or emoji strings, the translation engine often returns the input unchanged. Now we just don’t render the empty-looking translation block in those cases.
- When the translation matches the original we now also tear down the wrapper so the original DOM structure is fully restored — this avoids the leftover blank line that #140 spotted.
- Applies to full-page / region / context-menu translation. Selection translation is left as-is since the user triggered it explicitly.
- Summary blocks created by region / context-menu translation can now be dismissed (#134)
- Each summary block now has a small × button in its top-right corner — click it to remove just that summary
- The popup’s “Reset translations” button now also clears every
.dvt-summary block (not only the page-summary one), so region-translation summaries are cleaned up too
- Added an
undoSummary i18n key across all 11 languages for the new button’s aria-label / title
Bug fixes
- Fix: “Pick a region to translate” button in the popup didn’t close the popup or enter region mode on macOS Safari (#157)
- Two macOS-Safari-specific issues: the content-script listener returned
true even though all responses were sync (so macOS Safari kept the message channel open and the popup never got the response), and the window.close() after await lost its user-gesture context (so it was silently ignored).
- Fix: drop the unconditional
return true from the listener, cache the active tab id at popup startup, and have the region buttons fire sendMessage synchronously before calling window.close().
- iOS Safari / Chrome / Firefox were unaffected and still behave the same.
v1.4.1 (2026-04-28)
Bug fixes
- Fix: mini translate icon didn’t show up on iOS Safari (#127)
- The selection detection was
mouseup-only, which doesn’t fire predictably for iOS text selection (long-press + range handles). Added a debounced selectionchange listener (300ms) so iOS picks up the selection too.
- The
selectionchange listener is only registered on touch devices ('ontouchstart' in document.documentElement), so desktop (Chrome / Firefox / macOS Safari) keeps its existing behavior of not showing the icon for keyboard selections (Shift+Arrow).
- As a side fix, pressing Escape now also cancels any pending debounce timer so the icon won’t unexpectedly reappear after dismissal.
Milestones
- iOS Safari extension is now live on the App Store (2026-04-28)
- Public URL: https://apps.apple.com/app/dualview-translator/id6763488360
- Submitted build: Safari Build 2 (Marketing Version 1.0)
- macOS Safari is still in Mac App Store review
v1.4.0 (2026-04-27)
Improvements
- Selection translation now starts from a tiny icon instead of an instant full panel (#102)
- Highlighting text used to pop the entire translate panel right under your selection — handy, but in the way when you were just trying to copy something
- Now you only get a small translate icon next to your selection. Click it and the full panel slides in like before
- Right-click “Translate” and
Ctrl+Shift+Y are explicit triggers, so they still open the full panel directly (no extra click)
- Added an i18n key
translateSelection (used as the icon’s aria-label / title) across all 11 languages
- Localized store description & shortcut hints via the browser’s built-in i18n (
_locales/) (#93)
- Replaced
manifest.json’s description and commands.*.description with __MSG_<key>__ placeholders
and shipped 11 language packs (ar / de / en / es / fr / ja / ko / pt_BR / ru / zh_CN / zh_TW) under _locales/
- Now the description in Chrome Web Store / Firefox Add-ons / Mac App Store / iOS App Store listings
and the shortcut hints in
chrome://extensions/shortcuts show up in the user’s browser language
default_locale is en — anything we haven’t translated falls back here
- The Safari Web Extension Xcode project also picks up
_locales/ as a build resource
Documentation
- English versions of extension descriptions (#91)
- Added
docs/chrome-web-store.en.md / docs/firefox-add-ons.en.md / README.en.md
- Targets English-speaking users and overseas distribution on Chrome Web Store / Firefox AMO
- Linked the published Firefox Add-ons page from the GitHub Pages landing pages (#94)
- The “Distribution” section in
docs/index.md / docs/index.en.md now points to the AMO page instead of saying “coming soon”
- Cleaned up release-notes links on the GitHub Pages landing pages so each language only shows its own (#95)
- Dropped the cross-language release-notes link from
docs/index.md / docs/index.en.md
- You can still hop between languages from the language toggle at the top of each release-notes page
- Added a “Developer” section to the GitHub Pages landing pages (#98)
- New “Developer” section on
docs/index.md / docs/index.en.md linking to Orangesoft Inc. and other products (safeAttach / xgate4)
Milestones
- Submitted Safari (macOS / iOS) to Mac App Store / iOS App Store (2026-04-25)
- Phase 4 complete (#1). Awaiting Apple review (typically 24–48 hours)
- Submitted build: Safari Build 2 (Marketing Version 1.0)
- Related PRs: #74 (HD icons) / #76 (submission setup) / #82 (App Group fix) / #84 (build number bump)
Bug Fixes
- Fixed: API keys and settings not saved on macOS Safari (#81)
- When App Sandbox was enabled in PR #76, the App Group entitlement was missing, so
storage.local failed with Disk I/O error
- Added App Group
group.jp.co.orangesoft.dualview-translator to both App and Extension to allow access to the shared Container
- Same App Group also added to iOS as a precaution
Improvements
- HD app icon for App Store submission (#49)
- Auto-generated all macOS sizes (16–1024) and iOS 1024 from a single 1024x1024 master
- iOS 1024 follows Apple’s recommendation: no baked-in rounded corners (system applies the mask)
- macOS uses a squircle-style rounded corner
- The browser-extension icons (
icons/icon{16,32,48,128}.png) are also regenerated from the same master
- Master data saved as
assets/app-icon.svg and the regeneration script assets/generate-icons.py
- Safari / iOS App Store submission setup (#75)
- Added App Sandbox + Outgoing Connections capability to the macOS App / Extension (required for Mac App Store)
- Removed the alpha channel from the iOS App Store large icon (per Apple’s large-icon requirements)
- Set App Category to Productivity
- Added the encryption export-compliance declaration (
ITSAppUsesNonExemptEncryption = NO) to Info.plist
- macOS / iOS Archive Upload to App Store Connect now succeeds
- Verified working on macOS Safari / iOS Safari devices via TestFlight
- Privacy Policy published on GitHub Pages (#77)
- Provides a stable public URL required for App Store submission
- Public URL:
https://hirokatsuhibino.github.io/dualview-translator/privacy-policy.html
v1.3.0 (2026-04-22)
New Features
- New “Rules” tab: auto-translation rules now have their own tab, separate from settings (#50)
- Tab layout: Translate / Rules / Settings
- Edit registered auto-translation rules: click an item in the list to edit it in the form below (#50)
- The “Add” button switches to “Update”, and a “Cancel” button appears to exit edit mode
- When the URL pattern, selector, or mode changes, the latest rule is re-evaluated and applied via
reapplyAutoRule to already-open pages
- Translation cache (#56)
- Caches Google Translate / DeepL results per chunk in
chrome.storage.local (key: tc:<engine>:<sl>:<tl>:<hash>)
- Skips API calls for re-translations of the same text → faster, saves DeepL Free character quota, easier on Google’s rate limit
- TTL 30 days / max 2,000 entries (LRU evicts 10% when over the limit)
- Settings tab shows the current cache count and a “Clear cache” button
- Summarization cache (#58)
- Caches Claude / Gemini summary results in
chrome.storage.local (key: sc:<engine>:<tl>:<hash>)
- Skips paid API calls for re-summarizations → cost reduction + faster responses
- TTL 30 days / max 500 entries (LRU evicts 10% when over the limit)
- The settings tab shows the combined translation + summary cache count
- Cache hit rate display (#64)
- Hit rates for translation and summarization shown with progress bars under the cache count in the settings tab
- Hits / misses are persisted in
chrome.storage.local and reset when the cache is cleared
- Hidden when there are no accesses yet
Improvements
- Switched the summary model to a more cost-effective one: Claude Sonnet → Claude Haiku (about 1/10 the cost) (#62)
v1.2.4 (2026-04-17)
New Features
- API key validation: a “Test” button on each of the DeepL / Claude / Gemini API key fields lets you check key validity in one click (#27)
- Shows “✓ Valid” (green) on success or “✗ Invalid” (red) on failure for 3 seconds
- Insufficient balance / rate limit are treated as valid keys
Fixes
- Claude model update: replaced the deprecated
claude-3-5-sonnet-20241022 with claude-sonnet-4-5-20250514 (#29)
- Translation bar display fix: fixed a regression where
<strong> tags appeared as literal text after innerHTML→DOM API conversion (#29)
- Test button layout: placed the Test button inside the input field on the right so it’s visible without horizontal scroll (#31, #33)
Improvements
- PRs required: direct push to main is now disallowed; all changes must go through a PR (#25)
v1.2.3 (2026-04-16)
Fixes
- Firefox compatibility: cleared all warnings raised during the Firefox Add-ons submission
- Replaced all
innerHTML usages with DOM APIs (createElement, etc.) to clear security warnings
- Moved the popup’s inline scripts to an external file (
popup-init.js) for CSP compliance
- Added
data_collection_permissions to manifest.json (now required for new Firefox extensions)
- Bumped Firefox minimum version from 109 to 112 (for
background.type support)
v1.2.2 (2026-04-16)
Fixes
- Double-translation bug fix: fixed an issue where already-translated text could be translated again (#24)
v1.2.1 (2026-04-14)
Fixes
- Chrome Web Store review compliance: removed the unused
scripting permission from manifest.json
v1.2.0 (2026-04-02)
New Features
- Auto-translation rules: auto-translate specific sites and elements via URL pattern + CSS selector (#17)
- The element picker generates a selector from a single click on the page
- Detects URL changes in SPAs (single-page apps) and re-checks
- Dynamic content support (waits up to 10 seconds for elements to appear)
- Webmail-style content rewriting handled (change detection → auto re-translation)
- Translation reset: stronger ways to undo translations (#18)
- Added an “×” button at the end of each translated element (per-element reset)
- The popup’s “Reset translations” button now resets both full-page and region translations
Improvements
- Drag and resize the selection translation panel: drag the header to move, drag the bottom-right handle to resize (#21)
- Disable UI when API key is missing: the summary button and menu are disabled when the LLM API key is missing (#19)
- Disable UI when DeepL API key is missing: with DeepL selected and the key missing, translation buttons and the context menu are disabled (#20)
- Refactor: extracted magic numbers as constants and consolidated duplicated code (content-page.js 606 → 511 lines)
- More tests: added tests for auto-translation rules,
waitForElement, and startAutoRuleObserver (171 total)
v1.1.0 (2026-04-01)
New Features
- Element selection translation & summary: click an element from the popup to translate it and get an AI summary (#15)
- Tabbed popup UI: split into “Translate” and “Settings” tabs so common actions are reachable in one click (#13)
- Auto-translate dynamic content: while a full-page translation is active, content added by lazy load or infinite scroll is auto-detected and translated (#14)
- Automated tests: introduced 126 unit tests with Vitest + jsdom
Changes
- Region selection method changed: from drag-rectangle selection to click-an-element selection. Hovering highlights the target element so you can pick the region intuitively (#12)
Translation modes (8 total)
| Mode |
How |
| Selection translation |
Drag-select text |
| Full-page translation |
From the popup |
| Full-page translation & summary |
From the popup |
| Element selection translation |
Click an element from the popup |
| Element selection translation & summary |
Click an element from the popup |
| Right-click translation |
Select text, then right-click |
| Element translation |
Right-click (with no text selected) |
| Element translation & summary |
Right-click (with no text selected) |
v1.0.0 (2026-03-31)
Initial Release
- Dual-view display (original text with translation right below)
- 7 translation modes (selection, full page & summary, region selection, right-click, element & summary)
- 2 translation engines (Google Translate / DeepL)
- AI summary (Claude / Gemini)
- Translation bar (auto-detect foreign-language pages)
- Keyboard shortcuts (Ctrl+Shift+T/Y/R)
- 11-language UI
- Auto-following dark / light theme
Copyright (c) Orangesoft Inc