diff --git a/.gitignore b/.gitignore index fdd0f7d..d92f248 100644 --- a/.gitignore +++ b/.gitignore @@ -88,4 +88,5 @@ lerna-debug.log # System Files .DS_Store -Thumbs.db \ No newline at end of file +Thumbs.db*.html +test-*.js diff --git a/I18N-README.md b/I18N-README.md new file mode 100644 index 0000000..5d4dbc4 --- /dev/null +++ b/I18N-README.md @@ -0,0 +1,153 @@ +# i18n (Internationalization) Implementation + +## Overview +This extension now supports multiple languages (Turkish and English) using Chrome's native i18n API. + +## Structure + +``` +src/ +├── _locales/ +│ ├── tr/ +│ │ └── messages.json # Turkish translations (55 keys) +│ └── en/ +│ └── messages.json # English translations (55 keys) +├── i18n.js # i18n helper utilities +├── manifest.json # Updated with i18n references +├── popup.html # Updated with data-i18n attributes +├── popup.js # Updated to use i18n +├── options.html # Updated with data-i18n attributes +├── options.js # Updated to use i18n +└── background.js # Updated for i18n messages +``` + +## Features + +### 1. Automatic Language Detection +- Detects browser's language setting on first use +- Defaults to Turkish if browser language is not English +- Supports `tr` (Turkish) and `en` (English) + +### 2. Manual Language Selection +- Dropdown selector in both popup and options pages +- Language preference saved in Chrome sync storage +- Persists across browser sessions +- Changes take effect immediately on reload + +### 3. Comprehensive Translation Coverage +- UI labels and buttons +- Error messages +- Status messages +- Jira issue descriptions (ADF format) +- Placeholder texts +- Tooltips and titles + +## Usage + +### For End Users +1. Open the extension popup or options page +2. Select your preferred language from the "Language" / "Dil" dropdown +3. The interface will reload in the selected language + +### For Developers + +#### Adding New Translations +1. Add the key-value pair to both `_locales/tr/messages.json` and `_locales/en/messages.json` +2. Use the key in your code: + +**In HTML:** +```html +
Default text
+``` + +**In JavaScript:** +```javascript +const text = i18n.getMessage("yourKey"); +// or in background.js: +const text = msg("yourKey"); +``` + +#### Available i18n Helper Functions + +**In popup.js and options.js:** +```javascript +i18n.getMessage(key, substitutions) // Get translated message +i18n.getPreferredLanguage() // Get user's preferred language +i18n.setPreferredLanguage(lang) // Set user's preferred language +i18n.translatePage() // Translate all elements with data-i18n attributes +``` + +**In background.js:** +```javascript +msg(key, substitutions) // Shorthand for chrome.i18n.getMessage +``` + +#### HTML Attributes for i18n +- `data-i18n`: Translates element's textContent +- `data-i18n-placeholder`: Translates input's placeholder +- `data-i18n-title`: Translates element's title attribute +- `data-i18n-value`: Translates input's value attribute +- `data-i18n-html`: Translates element's innerHTML (use with caution) + +## Translation Keys + +### UI Elements +- `extName`, `extDescription` - Extension metadata +- `popupTitle`, `popupSubtitle` - Popup header +- `optionsTitle`, `optionsSubtitle` - Options header +- `labelCookies`, `labelStorage` - Toggle labels +- `btnCreateIssue`, `btnSave` - Action buttons + +### Status Messages +- `statusCollecting` - "Collecting information..." +- `statusCreated` - "Created:" +- `statusError` - "Error:" +- `alertSaved` - "Saved" + +### Error Messages +- `errorMissingSettings` - Settings not configured +- `errorAlreadyRecording` - Recording already in progress +- `errorCaptureTabFailed` - Tab capture failed +- `errorIssueCreateFailed` - Issue creation failed +- `errorAttachmentFailed` - Attachment upload failed + +### Jira ADF Content +- `adfHeadingAutoReport` - "Automated Report" / "Otomatik Rapor" +- `adfSummaryUrl`, `adfSummaryTime`, etc. - Report field labels +- `adfIncluded`, `adfNotIncluded` - Status indicators +- `issueSummaryPrefix` - "[Bug]" prefix for issues + +### Language Selection +- `labelLanguage` - "Language:" / "Dil:" +- `languageTurkish` - "Türkçe" +- `languageEnglish` - "English" + +## Testing + +Run the validation script to ensure i18n implementation is correct: +```bash +node test-i18n.js +``` + +This verifies: +- Manifest has i18n references +- Both locale directories exist +- Locale files have matching keys +- All required keys are present +- HTML files reference i18n.js +- HTML files have data-i18n attributes +- Background.js uses chrome.i18n API + +## Browser Compatibility +- Chrome/Chromium: Full support +- Edge: Full support +- Other Chromium-based browsers: Full support + +## Default Language +The default locale is set to Turkish (`tr`) in `manifest.json`, matching the original extension's language. + +## Notes +- Language preference is synced across devices using Chrome sync storage +- When adding new UI text, always add it to both language files +- Keep translation keys consistent and descriptive +- The i18n system uses Chrome's native `chrome.i18n` API for best compatibility diff --git a/i18n-demo.html b/i18n-demo.html new file mode 100644 index 0000000..a082673 --- /dev/null +++ b/i18n-demo.html @@ -0,0 +1,230 @@ + + + + + i18n Demo - Jira Bug Reporter + + + +

🌍 Jira Bug Reporter - Multi-Language Support Demo

+ +
+ ✓ i18n Implementation Complete - Turkish & English Support Added! +
+ +
+
+

🇹🇷 Türkçe (Turkish)

+ +
+
Extension Name
+
Jira Bug Reporter
+
+ +
+
Extension Description
+
Aktif sayfadan hata ve ağ bilgilerini toplayıp Jira'da bilet açar.
+
+ +
+
Popup Title
+
Jira Bug Reporter
+
+ +
+
Popup Subtitle
+
Tek tıkla bu sayfanın ekran görüntüsü ve loglarını toplayıp Jira'da bilet açar.
+
+ +
+
Create Issue Button
+
Jira'da bilet aç
+
+ +
+
Settings Title
+
Jira Bug Reporter Ayarları
+
+ +
+
Language Label
+
Dil:
+
+ +
+
Language Options
+
Türkçe / English
+
+ +
+
Save Button
+
Kaydet
+
+ +
+
Status Messages
+
+ • Bilgiler toplanıyor...
+ • Oluşturuldu:
+ • Hata:
+ • Kaydedildi +
+
+
+ +
+

🇬🇧 English

+ +
+
Extension Name
+
Jira Bug Reporter
+
+ +
+
Extension Description
+
Collects error and network information from the active page and creates a Jira ticket.
+
+ +
+
Popup Title
+
Jira Bug Reporter
+
+ +
+
Popup Subtitle
+
Collect screenshot and logs from this page and create a Jira ticket with one click.
+
+ +
+
Create Issue Button
+
Create Jira Issue
+
+ +
+
Settings Title
+
Jira Bug Reporter Settings
+
+ +
+
Language Label
+
Language:
+
+ +
+
Language Options
+
Türkçe / English
+
+ +
+
Save Button
+
Save
+
+ +
+
Status Messages
+
+ • Collecting information...
+ • Created:
+ • Error:
+ • Saved +
+
+
+
+ +
+

📋 Implementation Summary

+ + +

🔧 How It Works

+ + +

🎯 Key Features

+ +
+ + diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json new file mode 100644 index 0000000..4e85f7a --- /dev/null +++ b/src/_locales/en/messages.json @@ -0,0 +1,172 @@ +{ + "extName": { + "message": "Jira Bug Reporter" + }, + "extDescription": { + "message": "Collects error and network information from the active page and creates a Jira ticket." + }, + "popupTitle": { + "message": "Jira Bug Reporter" + }, + "popupSubtitle": { + "message": "Collect screenshot and logs from this page and create a Jira ticket with one click." + }, + "labelCookies": { + "message": "Cookies" + }, + "hintCookies": { + "message": "Include cookies" + }, + "labelStorage": { + "message": "Storage Summary" + }, + "hintStorage": { + "message": "Include localStorage & sessionStorage summaries" + }, + "btnCreateIssue": { + "message": "Create Jira Issue" + }, + "btnCreateIssueTitle": { + "message": "Create new Jira issue" + }, + "statusCollecting": { + "message": "Collecting information..." + }, + "statusCreated": { + "message": "Created:" + }, + "statusError": { + "message": "Error:" + }, + "statusUnknown": { + "message": "Unknown" + }, + "optionsTitle": { + "message": "Jira Bug Reporter Settings" + }, + "optionsSubtitle": { + "message": "Configure the required settings for the extension to work." + }, + "labelJiraBaseUrl": { + "message": "Jira Server URL:" + }, + "placeholderJiraBaseUrl": { + "message": "https://company.atlassian.net" + }, + "labelEmail": { + "message": "Email Address:" + }, + "labelApiToken": { + "message": "API Token:" + }, + "apiTokenHint": { + "message": "You can get your API token from $URL$.", + "placeholders": { + "url": { + "content": "$1" + } + } + }, + "labelProjectKey": { + "message": "Project Key:" + }, + "placeholderProjectKey": { + "message": "KEY" + }, + "labelIssueType": { + "message": "Issue Type:" + }, + "defaultIssueType": { + "message": "Bug" + }, + "btnSave": { + "message": "Save" + }, + "btnSaveTitle": { + "message": "Save Settings" + }, + "alertSaved": { + "message": "Saved" + }, + "errorMissingSettings": { + "message": "Settings are incomplete. Please fill in your Jira information through the settings page." + }, + "errorAlreadyRecording": { + "message": "Already recording." + }, + "errorCaptureTabFailed": { + "message": "Tab capture failed." + }, + "errorIssueCreateFailed": { + "message": "Issue create failed:" + }, + "errorAttachmentFailed": { + "message": "Attachment failed:" + }, + "adfHeadingAutoReport": { + "message": "Automated Report" + }, + "adfHeadingSummaryJson": { + "message": "Summary JSON" + }, + "adfSummaryUrl": { + "message": "URL:" + }, + "adfSummaryTime": { + "message": "Time:" + }, + "adfSummaryUa": { + "message": "UA:" + }, + "adfSummaryViewport": { + "message": "Viewport:" + }, + "adfSummaryErrorCount": { + "message": "Error count:" + }, + "adfSummaryConsoleCount": { + "message": "Console entries:" + }, + "adfSummaryNetworkCount": { + "message": "Network entries:" + }, + "adfSummaryResources": { + "message": "resources:" + }, + "adfSummaryCookies": { + "message": "Cookies:" + }, + "adfSummaryStorage": { + "message": "Storage:" + }, + "adfSummaryRecording": { + "message": "Screen recording:" + }, + "adfIncluded": { + "message": "included" + }, + "adfNotIncluded": { + "message": "not included" + }, + "adfFooterNote": { + "message": "See attached 'page-report.json' and 'screenshot.png' files for full details." + }, + "issueSummaryPrefix": { + "message": "[Bug]" + }, + "labelLanguage": { + "message": "Language:" + }, + "languageTurkish": { + "message": "Türkçe" + }, + "languageEnglish": { + "message": "English" + }, + "footerDisclaimer": { + "message": "Jira Bug Reporter is a third-party open-source tool that integrates with Jira, a product of Atlassian. It is not affiliated with, endorsed by, or approved by Atlassian. \"Atlassian\" and \"Jira\" are registered trademarks of Atlassian. The use of these names does not imply any endorsement or sponsorship." + }, + "footerContribute": { + "message": "and you can contribute to the project." + } +} diff --git a/src/_locales/tr/messages.json b/src/_locales/tr/messages.json new file mode 100644 index 0000000..917a20e --- /dev/null +++ b/src/_locales/tr/messages.json @@ -0,0 +1,172 @@ +{ + "extName": { + "message": "Jira Bug Reporter" + }, + "extDescription": { + "message": "Aktif sayfadan hata ve ağ bilgilerini toplayıp Jira'da bilet açar." + }, + "popupTitle": { + "message": "Jira Bug Reporter" + }, + "popupSubtitle": { + "message": "Tek tıkla bu sayfanın ekran görüntüsü ve loglarını toplayıp Jira'da bilet açar." + }, + "labelCookies": { + "message": "Çerezler" + }, + "hintCookies": { + "message": "Cookies eklensin" + }, + "labelStorage": { + "message": "Depolama Özeti" + }, + "hintStorage": { + "message": "localStorage & sessionStorage özetleri eklensin" + }, + "btnCreateIssue": { + "message": "Jira'da bilet aç" + }, + "btnCreateIssueTitle": { + "message": "Jira'da yeni bilet aç" + }, + "statusCollecting": { + "message": "Bilgiler toplanıyor..." + }, + "statusCreated": { + "message": "Oluşturuldu:" + }, + "statusError": { + "message": "Hata:" + }, + "statusUnknown": { + "message": "Bilinmiyor" + }, + "optionsTitle": { + "message": "Jira Bug Reporter Ayarları" + }, + "optionsSubtitle": { + "message": "Uzantının çalışabilmesi için gerekli ayarları yapın." + }, + "labelJiraBaseUrl": { + "message": "Jira Sunucu Adresi:" + }, + "placeholderJiraBaseUrl": { + "message": "https://company.atlassian.net" + }, + "labelEmail": { + "message": "E-Posta Adresi:" + }, + "labelApiToken": { + "message": "API Belirteci:" + }, + "apiTokenHint": { + "message": "API Belirtecinizi $URL$ adresinden alabilirsiniz.", + "placeholders": { + "url": { + "content": "$1" + } + } + }, + "labelProjectKey": { + "message": "Proje Anahtarı:" + }, + "placeholderProjectKey": { + "message": "KEY" + }, + "labelIssueType": { + "message": "Issue Türü:" + }, + "defaultIssueType": { + "message": "Bug" + }, + "btnSave": { + "message": "Kaydet" + }, + "btnSaveTitle": { + "message": "Ayarları Kaydet" + }, + "alertSaved": { + "message": "Kaydedildi" + }, + "errorMissingSettings": { + "message": "Ayarlar eksik. Lütfen ayarlar sayfası üzerinden Jira bilgilerinizi doldurun." + }, + "errorAlreadyRecording": { + "message": "Zaten kayıt var." + }, + "errorCaptureTabFailed": { + "message": "Sekme yakalanamadı." + }, + "errorIssueCreateFailed": { + "message": "Issue create failed:" + }, + "errorAttachmentFailed": { + "message": "Attachment failed:" + }, + "adfHeadingAutoReport": { + "message": "Otomatik Rapor" + }, + "adfHeadingSummaryJson": { + "message": "Özet JSON" + }, + "adfSummaryUrl": { + "message": "URL:" + }, + "adfSummaryTime": { + "message": "Zaman:" + }, + "adfSummaryUa": { + "message": "UA:" + }, + "adfSummaryViewport": { + "message": "Viewport:" + }, + "adfSummaryErrorCount": { + "message": "Hata sayısı:" + }, + "adfSummaryConsoleCount": { + "message": "Console girdisi:" + }, + "adfSummaryNetworkCount": { + "message": "Network girdisi:" + }, + "adfSummaryResources": { + "message": "resources:" + }, + "adfSummaryCookies": { + "message": "Cookies:" + }, + "adfSummaryStorage": { + "message": "Storage:" + }, + "adfSummaryRecording": { + "message": "Ekran kaydı:" + }, + "adfIncluded": { + "message": "eklendi" + }, + "adfNotIncluded": { + "message": "yok" + }, + "adfFooterNote": { + "message": "Tam ayrıntılar için eklerdeki 'page-report.json' ve 'screenshot.png' dosyalarına bakınız." + }, + "issueSummaryPrefix": { + "message": "[Bug]" + }, + "labelLanguage": { + "message": "Dil:" + }, + "languageTurkish": { + "message": "Türkçe" + }, + "languageEnglish": { + "message": "English" + }, + "footerDisclaimer": { + "message": "Jira Bug Reporter, Atlassian'ın bir ürünü olan Jira ile entegrasyon sağlayan açık kaynak kodlu üçüncü taraf bir araçtır. Atlassian ile bağlantılı, ortak veya onaylı değildir. \"Atlassian\" ve \"Jira\", Atlassian'ın tescilli ticari markalarıdır. Bu adların kullanımı, herhangi bir destek veya sponsorluk anlamına gelmez." + }, + "footerContribute": { + "message": "üzerinden projeye siz de katkıda bulunabilirsiniz." + } +} diff --git a/src/background.js b/src/background.js index cb54b11..bde8a76 100644 --- a/src/background.js +++ b/src/background.js @@ -1,9 +1,14 @@ let rec = { mediaRecorder: null, chunks: [], stream: null }; +// Helper to get i18n message +function msg(key, substitutions) { + return chrome.i18n.getMessage(key, substitutions) || key; +} + async function getSettings() { const s = await chrome.storage.sync.get(["baseUrl","email","token","projectKey","issueType"]); if (!s.baseUrl || !s.email || !s.token || !s.projectKey || !s.issueType) { - throw new Error("Ayarlar eksik. Lütfen ayarlar sayfası üzerinden Jira bilgilerinizi doldurun."); + throw new Error(msg("errorMissingSettings")); } const auth = "Basic " + btoa(`${s.email}:${s.token}`); return { ...s, auth }; @@ -16,13 +21,13 @@ async function capturePng(tabId) { } async function recStart(tabId) { - if (rec.mediaRecorder) throw new Error("Zaten kayıt var."); + if (rec.mediaRecorder) throw new Error(msg("errorAlreadyRecording")); rec.stream = await chrome.tabCapture.capture({ audio: false, video: true, videoConstraints: { mandatory: { maxWidth: 1280, maxHeight: 720, maxFrameRate: 10 } } }); - if (!rec.stream) throw new Error("Sekme yakalanamadı."); + if (!rec.stream) throw new Error(msg("errorCaptureTabFailed")); rec.chunks = []; rec.mediaRecorder = new MediaRecorder(rec.stream, { mimeType: "video/webm;codecs=vp9" }); rec.mediaRecorder.ondataavailable = (e) => { if (e.data && e.data.size) rec.chunks.push(e.data); }; @@ -74,16 +79,16 @@ async function createIssue(settings, payload) { const host = new URL(url).hostname; const summaryItems = [ - `URL: ${url}`, - `Zaman: ${payload.meta.time}`, - `UA: ${payload.meta.userAgent}`, - `Viewport: ${payload.meta.viewport.w}x${payload.meta.viewport.h}`, - `Hata sayısı: ${payload.logs.errors.length}`, - `Console girdisi: ${payload.logs.console.length}`, - `Network girdisi: ${payload.logs.network.length} (resources: ${payload.resources.length})`, - `Cookies: ${payload.cookies ? "eklendi" : "yok"}`, - `Storage: ${payload.storage ? "eklendi" : "yok"}`, - `Ekran kaydı: ${payload._hasRecording ? "eklendi" : "yok"}` + `${msg("adfSummaryUrl")} ${url}`, + `${msg("adfSummaryTime")} ${payload.meta.time}`, + `${msg("adfSummaryUa")} ${payload.meta.userAgent}`, + `${msg("adfSummaryViewport")} ${payload.meta.viewport.w}x${payload.meta.viewport.h}`, + `${msg("adfSummaryErrorCount")} ${payload.logs.errors.length}`, + `${msg("adfSummaryConsoleCount")} ${payload.logs.console.length}`, + `${msg("adfSummaryNetworkCount")} ${payload.logs.network.length} (${msg("adfSummaryResources")} ${payload.resources.length})`, + `${msg("adfSummaryCookies")} ${payload.cookies ? msg("adfIncluded") : msg("adfNotIncluded")}`, + `${msg("adfSummaryStorage")} ${payload.storage ? msg("adfIncluded") : msg("adfNotIncluded")}`, + `${msg("adfSummaryRecording")} ${payload._hasRecording ? msg("adfIncluded") : msg("adfNotIncluded")}` ]; const previewJson = JSON.stringify( @@ -99,11 +104,11 @@ async function createIssue(settings, payload) { version: 1, type: "doc", content: [ - heading(3, "Otomatik Rapor"), + heading(3, msg("adfHeadingAutoReport")), bulletList(summaryItems), - heading(4, "Özet JSON"), + heading(4, msg("adfHeadingSummaryJson")), codeBlock("json", previewJson), - p("Tam ayrıntılar için eklerdeki 'page-report.json' ve 'screenshot.png' dosyalarına bakınız.") + p(msg("adfFooterNote")) ] }; @@ -111,7 +116,7 @@ async function createIssue(settings, payload) { fields: { project: { key: settings.projectKey }, issuetype: { name: settings.issueType }, - summary: `[Bug] ${payload.meta.title} @ ${host}`, + summary: `${msg("issueSummaryPrefix")} ${payload.meta.title} @ ${host}`, description: descriptionADF } }; @@ -126,7 +131,7 @@ async function createIssue(settings, payload) { body: JSON.stringify(body) }); - if (!r.ok) throw new Error(`Issue create failed: ${r.status} ${await r.text()}`); + if (!r.ok) throw new Error(`${msg("errorIssueCreateFailed")} ${r.status} ${await r.text()}`); return await r.json(); } @@ -144,7 +149,7 @@ async function uploadAttachment(settings, issueIdOrKey, files) { }, body: form }); - if (!r.ok) throw new Error(`Attachment failed: ${r.status} ${await r.text()}`); + if (!r.ok) throw new Error(`${msg("errorAttachmentFailed")} ${r.status} ${await r.text()}`); return await r.json(); } diff --git a/src/i18n.js b/src/i18n.js new file mode 100644 index 0000000..3b27a3d --- /dev/null +++ b/src/i18n.js @@ -0,0 +1,66 @@ +// i18n helper utilities +const i18n = { + // Get translated message + getMessage: (key, substitutions) => { + return chrome.i18n.getMessage(key, substitutions) || key; + }, + + // Get current UI language + getUILanguage: () => { + return chrome.i18n.getUILanguage(); + }, + + // Get user's preferred language from storage or browser default + getPreferredLanguage: async () => { + const stored = await chrome.storage.sync.get(['language']); + if (stored.language) { + return stored.language; + } + // Default to browser language (tr or en) + const browserLang = chrome.i18n.getUILanguage(); + return browserLang.startsWith('tr') ? 'tr' : 'en'; + }, + + // Set user's preferred language + setPreferredLanguage: async (lang) => { + await chrome.storage.sync.set({ language: lang }); + }, + + // Translate all elements with data-i18n attribute + translatePage: () => { + document.querySelectorAll('[data-i18n]').forEach(el => { + const key = el.getAttribute('data-i18n'); + el.textContent = i18n.getMessage(key); + }); + + document.querySelectorAll('[data-i18n-placeholder]').forEach(el => { + const key = el.getAttribute('data-i18n-placeholder'); + el.placeholder = i18n.getMessage(key); + }); + + document.querySelectorAll('[data-i18n-title]').forEach(el => { + const key = el.getAttribute('data-i18n-title'); + el.title = i18n.getMessage(key); + }); + + document.querySelectorAll('[data-i18n-value]').forEach(el => { + const key = el.getAttribute('data-i18n-value'); + el.value = i18n.getMessage(key); + }); + + document.querySelectorAll('[data-i18n-html]').forEach(el => { + const key = el.getAttribute('data-i18n-html'); + const url = el.getAttribute('data-i18n-url'); + if (url) { + el.innerHTML = i18n.getMessage(key, url); + } else { + el.innerHTML = i18n.getMessage(key); + } + }); + } +}; + +// Export for use in other scripts +if (typeof module !== 'undefined' && module.exports) { + module.exports = i18n; +} diff --git a/src/manifest.json b/src/manifest.json index 20478b7..a4a9cbe 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,8 +1,9 @@ { "manifest_version": 3, - "name": "Jira Bug Reporter", + "name": "__MSG_extName__", "version": "1.1.3", - "description": "Aktif sayfadan hata ve ağ bilgilerini toplayıp Jira'da bilet açar.", + "description": "__MSG_extDescription__", + "default_locale": "tr", "icons": { "16": "icons/icon16.png", "32": "icons/icon32.png", diff --git a/src/options.html b/src/options.html index 7af8818..02989dd 100644 --- a/src/options.html +++ b/src/options.html @@ -4,6 +4,7 @@ Jira Bug Reporter Ayarları +
@@ -12,8 +13,8 @@
-
Jira Bug Reporter Ayarları
-
+
Jira Bug Reporter Ayarları
+
Uzantının çalışabilmesi için gerekli ayarları yapın.
@@ -21,30 +22,39 @@
- - + + - + - - API Belirtecinizi https://id.atlassian.com/manage-profile/security/api-tokens adresinden alabilirsiniz. + + + + https://id.atlassian.com/manage-profile/security/api-tokens + - - + + - - + + + + +
- +
- \ No newline at end of file + diff --git a/src/options.js b/src/options.js index c084266..17a65fa 100644 --- a/src/options.js +++ b/src/options.js @@ -1,12 +1,38 @@ const $ = id => document.getElementById(id); + +// Initialize i18n and load settings (async function init(){ + // Translate the page + i18n.translatePage(); + + // Set API token hint with URL + const apiTokenUrl = 'https://id.atlassian.com/manage-profile/security/api-tokens'; + const hintText = i18n.getMessage('apiTokenHint', apiTokenUrl); + $('apiTokenHintText').textContent = hintText.replace(apiTokenUrl, '').trim(); + + // Get and set current language + const currentLang = await i18n.getPreferredLanguage(); + $('languageSelect').value = currentLang; + + // Load saved settings const s = await chrome.storage.sync.get(["baseUrl","email","token","projectKey","issueType"]); $("baseUrl").value = s.baseUrl || ""; $("email").value = s.email || ""; $("token").value = s.token || ""; $("projectKey").value = s.projectKey || ""; - $("issueType").value = s.issueType || "Bug"; + $("issueType").value = s.issueType || i18n.getMessage("defaultIssueType"); })(); + +// Language change handler +$('languageSelect').addEventListener('change', async (e) => { + const newLang = e.target.value; + await i18n.setPreferredLanguage(newLang); + + // Reload to apply new language + location.reload(); +}); + +// Save settings $("save").onclick = async () => { await chrome.storage.sync.set({ baseUrl: $("baseUrl").value.trim(), @@ -15,5 +41,5 @@ $("save").onclick = async () => { projectKey: $("projectKey").value.trim(), issueType: $("issueType").value.trim() }); - alert("Kaydedildi"); -}; \ No newline at end of file + alert(i18n.getMessage("alertSaved")); +}; diff --git a/src/popup.html b/src/popup.html index 577149a..c0e7190 100644 --- a/src/popup.html +++ b/src/popup.html @@ -5,6 +5,7 @@ Jira + @@ -18,9 +19,9 @@
-
Jira Bug Reporter
-
- Tek tıkla bu sayfanın ekran görüntüsü ve loglarını toplayıp Jira’da bilet açar. +
Jira Bug Reporter
+
+ Tek tıkla bu sayfanın ekran görüntüsü ve loglarını toplayıp Jira'da bilet açar.
@@ -30,8 +31,8 @@