From 1e6699f1302a25bd4636973bc8f2862f43f5e9ab Mon Sep 17 00:00:00 2001 From: James Taylor Date: Fri, 14 Nov 2025 11:13:44 -0800 Subject: [PATCH 1/4] Added localization guide for context to Claude Code --- chrome-extension-localization-guide.md | 471 +++++++++++++++++++++++++ 1 file changed, 471 insertions(+) create mode 100644 chrome-extension-localization-guide.md diff --git a/chrome-extension-localization-guide.md b/chrome-extension-localization-guide.md new file mode 100644 index 0000000..78f06bd --- /dev/null +++ b/chrome-extension-localization-guide.md @@ -0,0 +1,471 @@ +# Chrome Extension Localization Implementation Guide + +## Overview +This guide outlines the implementation of internationalization (i18n) for the Chrome extension based on current user distribution data. + +## Install Distribution Analysis + +### Your Current User Base +Based on the extension analytics (October-November 2025): + +| Region | Installs | Percentage | Priority | +|--------|----------|------------|----------| +| United States | 24 | 66.7% | ✓ Default | +| Taiwan | 4 | 11.1% | ✓ High | +| Germany | 3 | 8.3% | ✓ High | +| Brazil | 2 | 5.6% | ✓ Medium | +| Malaysia | 1 | 2.8% | Low | +| Netherlands | 1 | 2.8% | Low | +| Ukraine | 1 | 2.8% | Low | + +**Total: 36 installs** + +### NotebookLM Global Usage Data +According to Google Analytics data, NotebookLM's most active markets are: + +| Region | Usage Percentage | Language Priority | +|--------|------------------|-------------------| +| United States | 29% | English (en) ✓ | +| India | 21% | **Hindi (hi)** ⚠️ Missing | +| United Kingdom | 13% | English (en_GB) | +| Brazil/Indonesia | Growing 180% YoY | Portuguese (pt_BR) ✓ | + +**Key Insight:** You're currently missing India, which represents **21% of all NotebookLM usage** - the second-largest market globally. Adding Hindi support could significantly expand your potential user base. + +### Combined Market Opportunity +When combining your actual installs with NotebookLM's global usage patterns, the opportunity becomes clear: + +1. **Existing Markets** (Your users): US, Taiwan, Germany, Brazil +2. **Large Untapped Markets** (NotebookLM users): India (Hindi), UK, Japan, France, Spain + +## Recommended Localization Strategy + +### Phase 1: Core Languages (Implement First) +Based on your install distribution AND NotebookLM's global usage patterns: + +1. **English (en)** - 66.7% of your users + 29% of NotebookLM - Default locale +2. **Hindi (hi)** - ⚠️ **21% of NotebookLM users** - Massive untapped market +3. **Traditional Chinese (zh_TW)** - 11.1% of your users - Taiwan +4. **German (de)** - 8.3% of your users + significant NotebookLM usage - Germany + +**Phase 1 Coverage:** Your existing users (86%) + India's 21% NotebookLM market + +### Phase 2: High-Growth Languages +These languages represent significant NotebookLM markets and potential growth: + +5. **Brazilian Portuguese (pt_BR)** - 5.6% of your users + 180% YoY growth in Brazil +6. **Japanese (ja)** - Major NotebookLM market (sources & chat supported) +7. **Spanish (es)** - Large global NotebookLM market (beta testing active) +8. **French (fr)** - Significant NotebookLM market (sources & chat supported) + +**Phase 2 Coverage:** Adds major European, Latin American, and Asian markets + +### Phase 3: Additional Languages (Optional) +If resources allow, consider: +- English (en_GB) - UK represents 13% of NotebookLM usage +- Malay (ms) - Malaysia +- Dutch (nl) - Netherlands +- Ukrainian (uk) - Ukraine + +### Strategic Rationale + +**Why Hindi is Critical:** +- India represents 21% of all NotebookLM usage (second-largest market globally) +- NotebookLM supports Hindi for sources, chat, and interface +- You currently have ZERO users from India, representing massive growth potential +- Adding Hindi could more than double your potential market reach + +**Why the Phase 1 + Phase 2 approach:** +- Phase 1: Covers 86% of current users + opens India market (21% of NotebookLM) +- Phase 2: Positions you for major markets where NotebookLM is actively expanding +- This strategy balances serving existing users with capturing high-growth markets + +## Implementation Steps + +### 1. Create Directory Structure + +``` +your-extension/ +├── _locales/ +│ ├── en/ +│ │ └── messages.json +│ ├── zh_TW/ +│ │ └── messages.json +│ ├── de/ +│ │ └── messages.json +│ ├── pt_BR/ +│ │ └── messages.json +│ ├── hi/ +│ │ └── messages.json +│ ├── ja/ +│ │ └── messages.json +│ ├── es/ +│ │ └── messages.json +│ └── fr/ +│ └── messages.json +├── manifest.json +├── popup.html +└── popup.js (or your script files) +``` + +### 2. Update manifest.json + +Add the default locale: + +```json +{ + "manifest_version": 3, + "name": "__MSG_extensionName__", + "description": "__MSG_extensionDescription__", + "default_locale": "en", + ... +} +``` + +### 3. Create Translation Files + +#### _locales/en/messages.json +```json +{ + "extensionName": { + "message": "Your Extension Name" + }, + "extensionDescription": { + "message": "Your extension description" + }, + "button1Label": { + "message": "Click Me", + "description": "Label for the first button" + }, + "button2Label": { + "message": "Submit", + "description": "Label for the second button (if applicable)" + } +} +``` + +#### _locales/zh_TW/messages.json +```json +{ + "extensionName": { + "message": "您的擴充功能名稱" + }, + "extensionDescription": { + "message": "您的擴充功能說明" + }, + "button1Label": { + "message": "點擊我" + }, + "button2Label": { + "message": "提交" + } +} +``` + +#### _locales/de/messages.json +```json +{ + "extensionName": { + "message": "Ihr Erweiterungsname" + }, + "extensionDescription": { + "message": "Ihre Erweiterungsbeschreibung" + }, + "button1Label": { + "message": "Klick mich" + }, + "button2Label": { + "message": "Absenden" + } +} +``` + +#### _locales/pt_BR/messages.json +```json +{ + "extensionName": { + "message": "Nome da sua extensão" + }, + "extensionDescription": { + "message": "Descrição da sua extensão" + }, + "button1Label": { + "message": "Clique em mim" + }, + "button2Label": { + "message": "Enviar" + } +} +``` + +#### _locales/hi/messages.json (Hindi - 21% of NotebookLM users!) +```json +{ + "extensionName": { + "message": "आपके एक्सटेंशन का नाम" + }, + "extensionDescription": { + "message": "आपके एक्सटेंशन का विवरण" + }, + "button1Label": { + "message": "मुझे क्लिक करें" + }, + "button2Label": { + "message": "जमा करें" + } +} +``` + +#### _locales/ja/messages.json (Japanese) +```json +{ + "extensionName": { + "message": "拡張機能の名前" + }, + "extensionDescription": { + "message": "拡張機能の説明" + }, + "button1Label": { + "message": "クリックしてください" + }, + "button2Label": { + "message": "送信" + } +} +``` + +#### _locales/es/messages.json (Spanish) +```json +{ + "extensionName": { + "message": "Nombre de tu extensión" + }, + "extensionDescription": { + "message": "Descripción de tu extensión" + }, + "button1Label": { + "message": "Haz clic aquí" + }, + "button2Label": { + "message": "Enviar" + } +} +``` + +#### _locales/fr/messages.json (French) +```json +{ + "extensionName": { + "message": "Nom de votre extension" + }, + "extensionDescription": { + "message": "Description de votre extension" + }, + "button1Label": { + "message": "Cliquez-moi" + }, + "button2Label": { + "message": "Soumettre" + } +} +``` + +### 4. Update HTML Files + +Replace hardcoded text with i18n attributes: + +**Before:** +```html + +``` + +**After (Option 1 - Data attribute method):** +```html + +``` + +**After (Option 2 - Direct substitution in HTML):** +```html + +``` + +Note: Option 1 requires JavaScript initialization (see step 5), while Option 2 works automatically in Chrome extension contexts. + +### 5. Update JavaScript Files + +Add localization initialization: + +```javascript +// Initialize i18n for all elements with data-i18n attribute +function initializeI18n() { + document.querySelectorAll('[data-i18n]').forEach(element => { + const key = element.getAttribute('data-i18n'); + const message = chrome.i18n.getMessage(key); + if (message) { + element.textContent = message; + } + }); +} + +// Run on DOM load +document.addEventListener('DOMContentLoaded', initializeI18n); + +// Or for dynamically created elements: +function createLocalizedButton() { + const button = document.createElement('button'); + button.textContent = chrome.i18n.getMessage('button1Label'); + return button; +} +``` + +### 6. Testing Localization + +To test different locales: + +1. **Chrome Settings Method:** + - Go to `chrome://settings/languages` + - Add and move your test language to the top + - Restart Chrome + - Reload your extension + +2. **Command Line Method:** + ```bash + # Linux/Mac + chrome --lang=de + + # Windows + chrome.exe --lang=de + ``` + +3. **Verify in Code:** + ```javascript + console.log('Current locale:', chrome.i18n.getUILanguage()); + console.log('Message:', chrome.i18n.getMessage('button1Label')); + ``` + +## Translation Quality Guidelines + +### For Professional Translations: + +1. **Use native speakers** or professional translation services +2. **Keep context in mind** - button labels should be concise +3. **Test with native speakers** - especially for Hindi (21% of NotebookLM), Chinese (11% of your users), and German (8% of your users) +4. **Consider cultural nuances** - what works in one culture may not in another + +### NotebookLM Language Support Context + +Understanding NotebookLM's language capabilities helps prioritize translation quality: + +- **Interface languages:** NotebookLM supports 108 languages including all Phase 1 & 2 languages +- **Sources and chat:** 38 languages supported including English, Hindi, Chinese, German, Portuguese, Japanese, Spanish, and French +- **User expectations:** NotebookLM users already work in multilingual environments +- **Quality matters:** Users expect professional-grade translations since they're using enterprise AI tools + +### Quick Translation Resources: + +- **DeepL** (often better than Google Translate for European languages) +- **Google Translate** (good baseline, but review carefully) +- **Community translators** - consider reaching out to users in those regions + +## Advanced Features (Optional) + +### Placeholder Substitution + +```json +{ + "greeting": { + "message": "Hello, $NAME$!", + "placeholders": { + "name": { + "content": "$1" + } + } + } +} +``` + +```javascript +const greeting = chrome.i18n.getMessage('greeting', ['Alice']); +// Result: "Hello, Alice!" +``` + +### RTL Language Support + +If you add Arabic or Hebrew in the future: + +```json +{ + "@@bidi_dir": "rtl" +} +``` + +## Maintenance Checklist + +### Phase 1 Languages (Priority - Deploy First) +- [ ] Create _locales directory structure +- [ ] Add default_locale to manifest.json +- [ ] Create messages.json for English (en) +- [ ] Create messages.json for Hindi (hi) - **Critical for India market (21% of NotebookLM)** +- [ ] Create messages.json for Traditional Chinese (zh_TW) +- [ ] Create messages.json for German (de) + +### Phase 2 Languages (High Growth Markets) +- [ ] Create messages.json for Brazilian Portuguese (pt_BR) +- [ ] Create messages.json for Japanese (ja) +- [ ] Create messages.json for Spanish (es) +- [ ] Create messages.json for French (fr) + +### Implementation Tasks +- [ ] Update HTML files with i18n keys +- [ ] Update JavaScript to load messages +- [ ] Test with each locale +- [ ] Get translations reviewed by native speakers +- [ ] Update Chrome Web Store listing in each language +- [ ] Document all message keys for future reference +- [ ] Monitor analytics to track adoption in new markets + +## Key Reminders + +1. **Chrome automatically selects** the appropriate locale based on the user's browser language +2. **Fallback is automatic** - if a translation doesn't exist, Chrome falls back to the default locale +3. **No external libraries needed** - Chrome's built-in i18n API handles everything +4. **Message keys are case-sensitive** - be consistent in naming +5. **Hindi is your biggest opportunity** - India represents 21% of NotebookLM usage but you have zero users there currently +6. **Test thoroughly** - especially with Phase 1 languages (en, hi, zh_TW, de) which cover your existing users plus the massive India market +7. **Phase 2 expands reach** - Japanese, Spanish, and French open major global markets where NotebookLM is actively growing + +## Quick Start Command Summary + +```bash +# Phase 1: Create directory structure for core languages +mkdir -p _locales/{en,hi,zh_TW,de} + +# Phase 2: Add high-growth market languages +mkdir -p _locales/{pt_BR,ja,es,fr} + +# Create all template files at once +touch _locales/en/messages.json +touch _locales/hi/messages.json +touch _locales/zh_TW/messages.json +touch _locales/de/messages.json +touch _locales/pt_BR/messages.json +touch _locales/ja/messages.json +touch _locales/es/messages.json +touch _locales/fr/messages.json +``` + +## Resources + +- [Chrome Extension i18n Documentation](https://developer.chrome.com/docs/extensions/reference/api/i18n) +- [Locale Codes Reference](https://developer.chrome.com/docs/extensions/reference/api/i18n#locales) +- Chrome Web Store supports listing in multiple languages for better discoverability + +--- + +**Implementation Priority:** + +**Phase 1 (Critical):** Focus on English, **Hindi**, Traditional Chinese, and German first. These four languages cover 86% of your current user base PLUS open the massive India market (21% of NotebookLM users - currently untapped). + +**Phase 2 (High Growth):** Add Brazilian Portuguese, Japanese, Spanish, and French to position your extension in major global markets where NotebookLM usage is significant and growing. + +**Market Impact:** By implementing all 8 languages, you'll be positioned to serve the vast majority of NotebookLM's global user base across North America, Europe, Asia, and Latin America. From 5d4e3a87539021b3f16a4709fe6240509582b7a7 Mon Sep 17 00:00:00 2001 From: James Taylor Date: Fri, 14 Nov 2025 11:31:41 -0800 Subject: [PATCH 2/4] Added localization text for existing elements. Needs verification --- _locales/de/messages.json | 30 ++++++++++++++++++++++++++++++ _locales/en/messages.json | 30 ++++++++++++++++++++++++++++++ _locales/es/messages.json | 30 ++++++++++++++++++++++++++++++ _locales/fr/messages.json | 30 ++++++++++++++++++++++++++++++ _locales/hi/messages.json | 30 ++++++++++++++++++++++++++++++ _locales/ja/messages.json | 30 ++++++++++++++++++++++++++++++ _locales/pt_BR/messages.json | 30 ++++++++++++++++++++++++++++++ _locales/zh_TW/messages.json | 30 ++++++++++++++++++++++++++++++ manifest.json | 7 ++++--- popup.html | 7 ++++--- popup.js | 24 ++++++++++++++++++++++++ 11 files changed, 272 insertions(+), 6 deletions(-) create mode 100644 _locales/de/messages.json create mode 100644 _locales/en/messages.json create mode 100644 _locales/es/messages.json create mode 100644 _locales/fr/messages.json create mode 100644 _locales/hi/messages.json create mode 100644 _locales/ja/messages.json create mode 100644 _locales/pt_BR/messages.json create mode 100644 _locales/zh_TW/messages.json diff --git a/_locales/de/messages.json b/_locales/de/messages.json new file mode 100644 index 0000000..4b359f3 --- /dev/null +++ b/_locales/de/messages.json @@ -0,0 +1,30 @@ +{ + "extensionName": { + "message": "NotebookLM Filter", + "description": "Name of the extension" + }, + "extensionDescription": { + "message": "Eine einfache NotebookLM-Filtererweiterung", + "description": "Description of the extension" + }, + "extensionTitle": { + "message": "NotebookLM Filter", + "description": "Default title shown in browser action" + }, + "addFilterButton": { + "message": "Neuen Filter hinzufügen", + "description": "Button to add a new filter" + }, + "backButton": { + "message": "←", + "description": "Back button symbol" + }, + "filterInputPlaceholder": { + "message": "Filterschlüsselwort eingeben...", + "description": "Placeholder text for filter input field" + }, + "confirmButton": { + "message": "Bestätigen", + "description": "Button to confirm adding a filter" + } +} diff --git a/_locales/en/messages.json b/_locales/en/messages.json new file mode 100644 index 0000000..cd2037d --- /dev/null +++ b/_locales/en/messages.json @@ -0,0 +1,30 @@ +{ + "extensionName": { + "message": "NotebookLM Filter", + "description": "Name of the extension" + }, + "extensionDescription": { + "message": "A simple NotebookLM filtering extension", + "description": "Description of the extension" + }, + "extensionTitle": { + "message": "NotebookLM Filter", + "description": "Default title shown in browser action" + }, + "addFilterButton": { + "message": "Add New Filter", + "description": "Button to add a new filter" + }, + "backButton": { + "message": "←", + "description": "Back button symbol" + }, + "filterInputPlaceholder": { + "message": "Enter filter keyword...", + "description": "Placeholder text for filter input field" + }, + "confirmButton": { + "message": "Confirm", + "description": "Button to confirm adding a filter" + } +} diff --git a/_locales/es/messages.json b/_locales/es/messages.json new file mode 100644 index 0000000..f82a01e --- /dev/null +++ b/_locales/es/messages.json @@ -0,0 +1,30 @@ +{ + "extensionName": { + "message": "Filtro NotebookLM", + "description": "Name of the extension" + }, + "extensionDescription": { + "message": "Una extensión simple de filtrado de NotebookLM", + "description": "Description of the extension" + }, + "extensionTitle": { + "message": "Filtro NotebookLM", + "description": "Default title shown in browser action" + }, + "addFilterButton": { + "message": "Agregar Nuevo Filtro", + "description": "Button to add a new filter" + }, + "backButton": { + "message": "←", + "description": "Back button symbol" + }, + "filterInputPlaceholder": { + "message": "Ingrese la palabra clave del filtro...", + "description": "Placeholder text for filter input field" + }, + "confirmButton": { + "message": "Confirmar", + "description": "Button to confirm adding a filter" + } +} diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json new file mode 100644 index 0000000..2ab2b2a --- /dev/null +++ b/_locales/fr/messages.json @@ -0,0 +1,30 @@ +{ + "extensionName": { + "message": "Filtre NotebookLM", + "description": "Name of the extension" + }, + "extensionDescription": { + "message": "Une extension simple de filtrage NotebookLM", + "description": "Description of the extension" + }, + "extensionTitle": { + "message": "Filtre NotebookLM", + "description": "Default title shown in browser action" + }, + "addFilterButton": { + "message": "Ajouter un Nouveau Filtre", + "description": "Button to add a new filter" + }, + "backButton": { + "message": "←", + "description": "Back button symbol" + }, + "filterInputPlaceholder": { + "message": "Entrez le mot-clé du filtre...", + "description": "Placeholder text for filter input field" + }, + "confirmButton": { + "message": "Confirmer", + "description": "Button to confirm adding a filter" + } +} diff --git a/_locales/hi/messages.json b/_locales/hi/messages.json new file mode 100644 index 0000000..ed539c4 --- /dev/null +++ b/_locales/hi/messages.json @@ -0,0 +1,30 @@ +{ + "extensionName": { + "message": "NotebookLM फ़िल्टर", + "description": "Name of the extension" + }, + "extensionDescription": { + "message": "एक सरल NotebookLM फ़िल्टरिंग एक्सटेंशन", + "description": "Description of the extension" + }, + "extensionTitle": { + "message": "NotebookLM फ़िल्टर", + "description": "Default title shown in browser action" + }, + "addFilterButton": { + "message": "नया फ़िल्टर जोड़ें", + "description": "Button to add a new filter" + }, + "backButton": { + "message": "←", + "description": "Back button symbol" + }, + "filterInputPlaceholder": { + "message": "फ़िल्टर कीवर्ड दर्ज करें...", + "description": "Placeholder text for filter input field" + }, + "confirmButton": { + "message": "पुष्टि करें", + "description": "Button to confirm adding a filter" + } +} diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json new file mode 100644 index 0000000..981f930 --- /dev/null +++ b/_locales/ja/messages.json @@ -0,0 +1,30 @@ +{ + "extensionName": { + "message": "NotebookLM フィルター", + "description": "Name of the extension" + }, + "extensionDescription": { + "message": "シンプルな NotebookLM フィルタリング拡張機能", + "description": "Description of the extension" + }, + "extensionTitle": { + "message": "NotebookLM フィルター", + "description": "Default title shown in browser action" + }, + "addFilterButton": { + "message": "新しいフィルターを追加", + "description": "Button to add a new filter" + }, + "backButton": { + "message": "←", + "description": "Back button symbol" + }, + "filterInputPlaceholder": { + "message": "フィルターキーワードを入力...", + "description": "Placeholder text for filter input field" + }, + "confirmButton": { + "message": "確認", + "description": "Button to confirm adding a filter" + } +} diff --git a/_locales/pt_BR/messages.json b/_locales/pt_BR/messages.json new file mode 100644 index 0000000..7471fd8 --- /dev/null +++ b/_locales/pt_BR/messages.json @@ -0,0 +1,30 @@ +{ + "extensionName": { + "message": "Filtro NotebookLM", + "description": "Name of the extension" + }, + "extensionDescription": { + "message": "Uma simples extensão de filtragem do NotebookLM", + "description": "Description of the extension" + }, + "extensionTitle": { + "message": "Filtro NotebookLM", + "description": "Default title shown in browser action" + }, + "addFilterButton": { + "message": "Adicionar Novo Filtro", + "description": "Button to add a new filter" + }, + "backButton": { + "message": "←", + "description": "Back button symbol" + }, + "filterInputPlaceholder": { + "message": "Digite a palavra-chave do filtro...", + "description": "Placeholder text for filter input field" + }, + "confirmButton": { + "message": "Confirmar", + "description": "Button to confirm adding a filter" + } +} diff --git a/_locales/zh_TW/messages.json b/_locales/zh_TW/messages.json new file mode 100644 index 0000000..c7d3ade --- /dev/null +++ b/_locales/zh_TW/messages.json @@ -0,0 +1,30 @@ +{ + "extensionName": { + "message": "NotebookLM 篩選器", + "description": "Name of the extension" + }, + "extensionDescription": { + "message": "簡單的 NotebookLM 篩選擴充功能", + "description": "Description of the extension" + }, + "extensionTitle": { + "message": "NotebookLM 篩選器", + "description": "Default title shown in browser action" + }, + "addFilterButton": { + "message": "新增篩選器", + "description": "Button to add a new filter" + }, + "backButton": { + "message": "←", + "description": "Back button symbol" + }, + "filterInputPlaceholder": { + "message": "輸入篩選關鍵字...", + "description": "Placeholder text for filter input field" + }, + "confirmButton": { + "message": "確認", + "description": "Button to confirm adding a filter" + } +} diff --git a/manifest.json b/manifest.json index 90c59f9..45a526b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,8 +1,9 @@ { "manifest_version": 3, - "name": "NotebookLM Filter", + "name": "__MSG_extensionName__", "version": "1.2.0", - "description": "A simple NotebookLM filtering extension", + "description": "__MSG_extensionDescription__", + "default_locale": "en", "permissions": ["activeTab", "storage"], "content_scripts": [ { @@ -13,7 +14,7 @@ ], "action": { "default_popup": "popup.html", - "default_title": "NotebookLM Filter" + "default_title": "__MSG_extensionTitle__" }, "icons": { "16": "icons/icon16.png", diff --git a/popup.html b/popup.html index 264037a..9848f97 100644 --- a/popup.html +++ b/popup.html @@ -7,7 +7,7 @@