Skip to content

Conversation

snomiao
Copy link
Member

@snomiao snomiao commented Jul 26, 2025

Summary

  • Add useDynamicTranslate hook for experimental browser translation using Chrome's new Translator API
  • Implement toggle-able translation with visual indicators (🌐/🔄 emojis)
  • Apply dynamic translation to node descriptions and version changelogs in NodeDetails component
  • Convert i18n hook from TypeScript to TSX for React component support
  • Update dependencies to support new translation features

Test plan

  • Verify dynamic translation toggle works in Chrome 138+ browsers
  • Test that translation icons appear correctly in node descriptions
  • Confirm translation state persists across page reloads via localStorage
  • Validate fallback behavior in browsers without Translator API support
  • Test translation functionality with various languages

🤖 Generated with Claude Code

snomiao and others added 2 commits July 26, 2025 16:23
- Add missing key handler with experimental Translator API integration
- Translate node descriptions using t() function for internationalization
- Format code improvements for better readability

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Add useDynamicTranslate hook for experimental browser translation
- Implement toggle-able translation with visual indicators (🌐/🔄)
- Apply dynamic translation to node descriptions and version changelogs
- Convert i18n hook from TypeScript to TSX for React component support
- Update dependencies to support new translation features

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@Copilot Copilot AI review requested due to automatic review settings July 26, 2025 17:49
Copy link

vercel bot commented Jul 26, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Project Deployment Preview Comments Updated (UTC)
registry-web Ready Preview Comment Aug 12, 2025 2:31pm

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces experimental browser translation capabilities using Chrome's new Translator API, allowing dynamic translation of node descriptions and version changelogs with toggle functionality and visual indicators.

Key changes:

  • Added useDynamicTranslate hook for experimental browser translation with Chrome's Translator API
  • Converted i18n hook from TypeScript to TSX to support React component rendering
  • Applied dynamic translation to NodeDetails component with toggle switcher and emoji indicators

Reviewed Changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 9 comments.

File Description
src/hooks/i18n/index.tsx New TSX file implementing dynamic translation hook and enhanced i18n functionality
src/hooks/i18n/index.ts Removed original TypeScript i18n implementation
package.json Added dependencies for translation features (hot-memo, react-use, use-async)
components/nodes/NodeDetails.tsx Integrated dynamic translation for node descriptions and changelogs

import I18nextBrowserLanguageDetector from 'i18next-browser-languagedetector'
import i18nextResourcesToBackend from 'i18next-resources-to-backend'
import { useRouter } from 'next/router'
import { forEach } from 'rambda'
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The forEach import from rambda appears unused and should be removed.

Suggested change
import { forEach } from 'rambda'

Copilot uses AI. Check for mistakes.

@@ -0,0 +1,176 @@
import { LANGUAGE_STORAGE_KEY, SUPPORTED_LANGUAGES } from '@/src/constants'
import hotMemo from 'hot-memo'
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hotMemo import appears unused and should be removed.

Suggested change
import hotMemo from 'hot-memo'

Copilot uses AI. Check for mistakes.

console.log(
`Missing translation for key "${key}" in language "${lng}"`
)
// (Experimental) Try use broswer Translator API to handle missing keys
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in comment: 'broswer' should be 'browser'.

Suggested change
// (Experimental) Try use broswer Translator API to handle missing keys
// (Experimental) Try use browser Translator API to handle missing keys

Copilot uses AI. Check for mistakes.

// cons:
// 1. requires network access to the browser's translation service
// 2. not able to use in server-side rendering
// 3. not avaliable in china
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in comment: 'avaliable' should be 'available'.

Suggested change
// 3. not avaliable in china
// 3. not available in china

Copilot uses AI. Check for mistakes.

(key?: string) => {
if (!key) return key
if (!available) return key
return <>{enabled ? <>{t(key)}</> : <>{key}</>}</>
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This JSX structure is unnecessarily complex. Consider simplifying to return enabled ? t(key) : key since the hook returns JSX elements but could return strings directly for better composability.

Suggested change
return <>{enabled ? <>{t(key)}</> : <>{key}</>}</>
return enabled ? t(key) : key

Copilot uses AI. Check for mistakes.

Comment on lines +62 to +66
const Translator = globalThis.Translator as any
const translator = await Translator.create({
sourceLanguage: 'en',
targetLanguage: lng,
}).catch(() => null)
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using any type defeats TypeScript's type safety. Consider defining a proper interface for the Translator API or using a more specific type assertion.

Suggested change
const Translator = globalThis.Translator as any
const translator = await Translator.create({
sourceLanguage: 'en',
targetLanguage: lng,
}).catch(() => null)
interface TranslatorAPI {
create(options: { sourceLanguage: string; targetLanguage: string }): Promise<TranslatorInstance>;
}
interface TranslatorInstance {
translateStreaming(text: string): AsyncIterable<string>;
}
const Translator = globalThis.Translator as TranslatorAPI;
const translator = await Translator.create({
sourceLanguage: 'en',
targetLanguage: lng,
}).catch(() => null);

Copilot uses AI. Check for mistakes.

// 3. not avaliable in china
//
const [available, availableState] = useAsyncData(async () => {
const Translator = globalThis.Translator as any
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using any type defeats TypeScript's type safety. Consider defining a proper interface for the Translator API or using a more specific type assertion.

Suggested change
const Translator = globalThis.Translator as any
const Translator = globalThis.Translator as TranslatorAPI

Copilot uses AI. Check for mistakes.

Comment on lines +117 to +120
aria-label="translate"
onClick={() => {
setEnabled((e) => !e)
}}
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Switcher component lacks proper accessibility attributes. It should include tabIndex={0} and onKeyDown handler to support keyboard navigation, and a more descriptive aria-label.

Suggested change
aria-label="translate"
onClick={() => {
setEnabled((e) => !e)
}}
aria-label={enabled ? "Disable translation" : "Enable translation"}
tabIndex={0}
onClick={() => {
setEnabled((e) => !e)
}}
onKeyDown={(event) => {
if (event.key === "Enter" || event.key === " ") {
setEnabled((e) => !e)
}
}}

Copilot uses AI. Check for mistakes.

Copy link

🎨 Chromatic Visual Testing Results

Resource URL
🔍 Build Results Chromatic Build
📚 Storybook View Storybook

Check the visual changes and approve or request changes as needed.

Copy link

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addeduse-async@​1.2.06810010077100
Addedhot-memo@​1.1.1711008788100
Addedreact-use@​17.6.09610010078100

View full report

Copy link

🎨 Chromatic Visual Testing Results

Resource URL
🔍 Build Results Chromatic Build
📚 Storybook View Storybook

Check the visual changes and approve or request changes as needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant