Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Localization Support for Extension #5

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Taiizor
Copy link
Contributor

@Taiizor Taiizor commented Dec 7, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced localization support for the YouTube summarization extension, allowing users to select their preferred language.
    • Added error messages and user interface elements in multiple languages, including Turkish, English, Spanish, French, and German.
  • Improvements

    • Enhanced user interface elements for better localization, including buttons and notifications.
    • Updated error handling to display localized messages for a more user-friendly experience.
    • Improved the structure of user interface elements to support localization seamlessly.
  • Documentation

    • Added localization files for English and Turkish, containing necessary strings for the extension's functionality.

Screenshots

image
image

image
image

image
image

image
image

Copy link

coderabbitai bot commented Dec 7, 2024

Walkthrough

This pull request introduces localization support for a YouTube summarization extension by adding new JSON files for English and Turkish localization. It modifies several JavaScript files to utilize these localization strings, enhancing user interface elements and error handling. The manifest file is updated to reference localized messages for the extension's name and description. Additionally, HTML and JavaScript files are adjusted to support dynamic language selection and notifications, ensuring a more user-friendly experience for speakers of multiple languages.

Changes

File Change Summary
src/_locales/en/messages.json Added localization strings for English, including extension name, description, settings, language options, UI elements, and error messages.
src/_locales/tr/messages.json Added localization strings for Turkish, mirroring the structure of the English file with translations for the extension name, description, settings, language options, UI elements, and error messages.
src/content.js Updated showMessage function to use message keys for localization. Modified handleSummarizeButtonClick to display localized error messages. Restructured modal dialog creation for localization support.
src/manifest.json Changed extension name and description to use localized message placeholders. Added default_locale field set to "en".
src/popup.html Enhanced localization support by adding data-i18n attributes to the title, header, dropdown options, and notification elements for dynamic translation.
src/popup.js Updated language selection handling to utilize chrome.i18n.getMessage for logging and notifications. Added logic to apply internationalization to elements with data-i18n attributes upon DOM load.

Possibly related PRs

  • Icons & Transcript Modal Revised #1: The changes in src/manifest.json related to the localization of the extension's name and description are directly connected to the main PR's introduction of localization strings in messages.json.

🐰 "In the land of code, where bunnies dwell,
Localization blooms, oh what a spell!
With messages bright, in languages fair,
Summarizing videos, we all can share.
From Turkish to English, our voices unite,
In the world of YouTube, everything feels right!" 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Outside diff range and nitpick comments (10)
src/content.js (4)

177-177: Simplify conditional using optional chaining

You can simplify the condition by using optional chaining, which makes the code more concise and readable:

if (data?.summary) {
  // ...
}

Apply this diff:

-if (data && data.summary) {
+if (data?.summary) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 177-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


224-224: Consider removing console.log statements in production

The console.log statements used for debugging may not be necessary in the production environment and could clutter the console.

Consider removing or commenting out these statements:

// Line 224
-console.log(chrome.i18n.getMessage("summarizeButtonClicked"));

// Line 260
-console.log(chrome.i18n.getMessage("summarizeButtonClicked"));

Also applies to: 260-260


193-195: Use more robust selectors for YouTube elements

The DOM selector used to find the subscribe button is very specific and may break if YouTube updates their layout:

const subscribeBtnDiv = document.querySelector("#subscribe-button > ytd-button-renderer > yt-button-shape > a > yt-touch-feedback-shape > div");

Consider using a more resilient selector. For example, selecting by ID or using a query that is less likely to change:

const subscribeBtnDiv = document.querySelector("#subscribe-button");

Or use feature detection methods to ensure the button is accurately selected regardless of DOM changes.


3-3: Enhance getVideoIdFromUrl to handle different URL formats

The current implementation only extracts the video ID from URLs with a v parameter, but YouTube videos can have different URL formats, such as https://youtu.be/VIDEO_ID.

Consider enhancing the function to handle various YouTube URL formats:

function getVideoIdFromUrl(url) {
  const urlObj = new URL(url);
  let videoId = urlObj.searchParams.get('v');
  if (!videoId && urlObj.hostname === 'youtu.be') {
    videoId = urlObj.pathname.slice(1);
  }
  return videoId;
}
src/popup.html (1)

3-3: Update the lang attribute to match the default locale

The lang attribute is set to 'tr', but the default locale in your manifest is 'en'. This can affect accessibility tools and search engines.

Consider setting the lang attribute to 'en' or dynamically updating it based on the user's selected language:

-<html lang="tr">
+<html lang="en">

Or use JavaScript to set it dynamically:

<html id="html-root">
// In your popup.js
document.getElementById('html-root').setAttribute('lang', chrome.i18n.getUILanguage());
src/popup.js (3)

8-12: Add error handling for storage operations

While the implementation is correct, it would be beneficial to handle potential storage errors.

 chrome.storage.sync.get(['preferredLanguage'], (result) => {
+  if (chrome.runtime.lastError) {
+    console.error(chrome.i18n.getMessage("storageError"), chrome.runtime.lastError);
+    return;
+  }
   if (result.preferredLanguage) {
     languageSelect.value = result.preferredLanguage;
   }
 });

15-23: Add error handling for storage operations

Similar to the previous section, add error handling for the storage operation.

 chrome.storage.sync.set({
   preferredLanguage: selectedLanguage
 }, () => {
+  if (chrome.runtime.lastError) {
+    console.error(chrome.i18n.getMessage("storageError"), chrome.runtime.lastError);
+    return;
+  }
   console.log(chrome.i18n.getMessage("languageSavedConsoleLog"), selectedLanguage);
   showNotification(chrome.i18n.getMessage("languageSavedNotification"));
 });

57-67: Use optional chaining for safer access

The code can be improved using optional chaining as suggested by the static analysis.

-if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
+if (window.matchMedia?.('(prefers-color-scheme: dark)')?.matches) {
   document.body.classList.add('dark-mode');
 }
src/_locales/en/messages.json (1)

1-83: Consider adding placeholders for dynamic content

Several error messages might need to include dynamic content (e.g., error details). Consider using Chrome i18n placeholders.

Example for unexpectedError:

  "unexpectedError": {
-    "message": "An unexpected error occurred:"
+    "message": "An unexpected error occurred: $ERROR$",
+    "placeholders": {
+      "error": {
+        "content": "$1"
+      }
+    }
  }
src/_locales/tr/messages.json (1)

56-76: Consider adding RTL support for error messages

Turkish text might need RTL (Right-to-Left) support in some contexts. Consider adding dir="auto" in the HTML elements where these error messages are displayed.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 76cef41 and 48bb898.

📒 Files selected for processing (6)
  • src/_locales/en/messages.json (1 hunks)
  • src/_locales/tr/messages.json (1 hunks)
  • src/content.js (1 hunks)
  • src/manifest.json (1 hunks)
  • src/popup.html (1 hunks)
  • src/popup.js (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/popup.js

[error] 56-57: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/content.js

[error] 177-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (3)
src/popup.js (1)

26-40: LGTM! Well-implemented notification system

The notification system is well-implemented with proper animation handling and cleanup.

src/manifest.json (1)

2-2: LGTM! Verify i18n implementation completeness

The manifest changes correctly implement Chrome extension i18n support by:

  1. Adding the required default_locale field
  2. Using proper message reference format for name and description

Let's verify the i18n implementation is complete:

Also applies to: 5-6

✅ Verification successful

i18n implementation is complete and correctly structured

The verification confirms that:

  • Required locale structure exists with both English (en) and Turkish (tr) translations
  • Both referenced message keys (extensionName and extensionDescription) are properly defined in both language files
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify i18n implementation completeness

# Check if all required locale files exist
echo "Checking locale files structure..."
fd -t d . src/_locales

# Verify that messages referenced in manifest exist in locale files
echo "\nVerifying message keys exist in locale files..."
for key in "extensionName" "extensionDescription"; do
  echo "\nChecking $key in locale files:"
  rg "\"$key\"" src/_locales/*/messages.json
done

Length of output: 941

src/_locales/tr/messages.json (1)

1-83: Verify translation completeness and consistency

The Turkish translations look good, but let's ensure completeness and consistency with the English locale.

✅ Verification successful

Let me try a different approach to verify the translations.


Turkish translations are complete and consistent with English locale

The verification shows that:

  • All message keys from English locale are present in Turkish locale
  • Both files have identical set of 27 keys
  • No empty messages were found in Turkish translations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify translation completeness and consistency

# Compare message keys between English and Turkish files
echo "Checking for missing translations..."
diff <(jq 'keys' src/_locales/en/messages.json | jq -r '.[]' | sort) \
     <(jq 'keys' src/_locales/tr/messages.json | jq -r '.[]' | sort)

# Check for empty messages
echo "\nChecking for empty messages..."
jq -r 'to_entries[] | select(.value.message == "") | .key' src/_locales/tr/messages.json

Length of output: 493


Script:

#!/bin/bash
# Get all keys from English locale
echo "English keys:"
cat src/_locales/en/messages.json | jq 'keys[]' | sort

echo -e "\nTurkish keys:"
cat src/_locales/tr/messages.json | jq 'keys[]' | sort

echo -e "\nChecking for empty messages in Turkish locale:"
cat src/_locales/tr/messages.json | jq '.[] | select(.message == "")'

Length of output: 1376

src/content.js Outdated Show resolved Hide resolved
src/content.js Show resolved Hide resolved
src/content.js Outdated Show resolved Hide resolved
src/popup.js Show resolved Hide resolved
src/popup.js Show resolved Hide resolved
src/_locales/en/messages.json Show resolved Hide resolved
src/_locales/en/messages.json Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (4)
src/content.js (4)

8-10: Add null check for msgKey parameter

The showMessage function should handle null/undefined message keys gracefully.

 function showMessage(msgKey) {
+    if (!msgKey) {
+        console.warn('Message key is missing');
+        return;
+    }
     const message = chrome.i18n.getMessage(msgKey) || msgKey;
     alert(message);
 }

44-68: Extract button styling to a reusable function

Both close and copy buttons share identical styling code. Consider extracting this to a helper function to improve maintainability and reduce duplication.

+function createStyledButton(textKey, isDarkMode) {
+    const button = document.createElement('button');
+    button.textContent = chrome.i18n.getMessage(textKey);
+    button.style.marginTop = '10px';
+    button.style.padding = '5px 10px';
+    button.style.cursor = 'pointer';
+    button.style.backgroundColor = isDarkMode ? '#555' : '#f0f0f0';
+    button.style.color = isDarkMode ? 'white' : 'black';
+    button.style.border = isDarkMode ? '1px solid #777' : '1px solid #ccc';
+    button.style.borderRadius = '4px';
+    return button;
+}

-const closeButton = document.createElement('button');
-closeButton.textContent = chrome.i18n.getMessage("closeButtonText");
-closeButton.style.marginTop = '10px';
// ... (remove all styling)
+const closeButton = createStyledButton("closeButtonText", isDarkMode);
+closeButton.style.marginRight = '10px';

-const copyButton = document.createElement('button');
-copyButton.textContent = chrome.i18n.getMessage("copyButtonText");
-copyButton.style.marginTop = '10px';
// ... (remove all styling)
+const copyButton = createStyledButton("copyButtonText", isDarkMode);

176-181: Use optional chaining for safer property access

The data.summary check could be simplified using optional chaining.

-if (data && data.summary) {
+if (data?.summary) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 177-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


278-281: Extract i18n initialization to a separate function

Consider moving the data-i18n localization logic to a separate function for better code organization.

+function initializeI18n() {
+    document.querySelectorAll('[data-i18n]').forEach(element => {
+        const key = element.getAttribute('data-i18n');
+        element.textContent = chrome.i18n.getMessage(key);
+    });
+}

-document.querySelectorAll('[data-i18n]').forEach(element => {
-    const key = element.getAttribute('data-i18n');
-    element.textContent = chrome.i18n.getMessage(key);
-});
+initializeI18n();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 48bb898 and cab6475.

📒 Files selected for processing (1)
  • src/content.js (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/content.js

[error] 177-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (2)
src/content.js (2)

140-140: ⚠️ Potential issue

Use localization key for the error message

The error message is still hardcoded, breaking localization support.

-showMessage("No video ID found. Cannot get transcript.");
+showMessage("noVideoIdError");

155-163: ⚠️ Potential issue

Parameterize the server URL for different environments

The hardcoded localhost URL is not suitable for production use.

+const SERVER_URL = chrome.runtime.getURL('config.json');
+const config = await fetch(SERVER_URL).then(response => response.json());

-const response = await fetch(`http://localhost:8000/transcript?video_id=${videoId}&summary_language=${preferredLanguage}`, {
+const response = await fetch(`${config.apiUrl}/transcript?video_id=${videoId}&summary_language=${preferredLanguage}`, {

src/content.js Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (2)
src/content.js (2)

14-106: Extract common styles to reduce duplication

The modal dialog implementation has duplicate styling code for buttons. Consider extracting common styles into a helper function.

function applyCommonButtonStyles(button, isDarkMode) {
    const styles = {
        marginTop: '10px',
        padding: '5px 10px',
        cursor: 'pointer',
        backgroundColor: isDarkMode ? '#555' : '#f0f0f0',
        color: isDarkMode ? 'white' : 'black',
        border: isDarkMode ? '1px solid #777' : '1px solid #ccc',
        borderRadius: '4px'
    };
    Object.assign(button.style, styles);
}

// Usage:
applyCommonButtonStyles(closeButton, isDarkMode);
applyCommonButtonStyles(copyButton, isDarkMode);

278-281: Add error handling for invalid i18n keys

The localization of elements with data-i18n attributes should handle cases where the key doesn't exist.

 document.querySelectorAll('[data-i18n]').forEach(element => {
     const key = element.getAttribute('data-i18n');
-    element.textContent = chrome.i18n.getMessage(key);
+    const message = chrome.i18n.getMessage(key);
+    if (message) {
+        element.textContent = message;
+    } else {
+        console.warn(`Missing translation for key: ${key}`);
+    }
 });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between cab6475 and 46199b5.

📒 Files selected for processing (1)
  • src/content.js (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/content.js

[error] 177-177: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (3)
src/content.js (3)

3-4: LGTM! Robust URL parsing and proper localization implementation

The changes improve code reliability by:

  • Using the URL API for parsing instead of manual string manipulation
  • Properly implementing localization with a fallback mechanism

Also applies to: 8-10


155-163: ⚠️ Potential issue

Parameterize the server URL for different environments

The hardcoded localhost URL needs to be configurable for different environments.


191-263: 🛠️ Refactor suggestion

Extract summarize button creation logic to reduce duplication

The button creation and styling code is duplicated between the primary and fallback paths.

src/content.js Show resolved Hide resolved
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