🐛 fix: wrong update/download url

This commit is contained in:
2025-02-16 03:54:23 +07:00
committed by GitHub
parent d2e79085b8
commit 75be2c41f5

View File

@@ -2,13 +2,13 @@
// @name Crowdin Localization Tools // @name Crowdin Localization Tools
// @namespace https://yuzu.kirameki.cafe/ // @namespace https://yuzu.kirameki.cafe/
// @version 1.0.0 // @version 1.0.0
// @description A tool for translating Crowdin projects // @description A tool for translating Crowdin projects using a CSV file
// @author Yuzu (YuzuZensai) // @author Yuzu (YuzuZensai)
// @match https://crowdin.com/editor/* // @match https://crowdin.com/editor/*
// @grant GM_addStyle // @grant GM_addStyle
// @grant GM_xmlhttpRequest // @grant GM_xmlhttpRequest
// @updateURL https://raw.githubusercontent.com/YuzuZensai/Crowdin-Localization-Tools/main/script.js // @updateURL https://raw.githubusercontent.com/YuzuZensai/Crowdin-Localization-Tools/main/script.user.js
// @downloadURL https://raw.githubusercontent.com/YuzuZensai/Crowdin-Localization-Tools/main/script.js // @downloadURL https://raw.githubusercontent.com/YuzuZensai/Crowdin-Localization-Tools/main/script.user.js
// ==/UserScript== // ==/UserScript==
// Global configuration // Global configuration
@@ -28,8 +28,8 @@ const CONFIG = {
// Remote CSV // Remote CSV
remoteCSVUrl: 'https://raw.githubusercontent.com/YuzuZensai/Crowdin-Localization-Tools/main/data/data.csv', remoteCSVUrl: 'https://raw.githubusercontent.com/YuzuZensai/Crowdin-Localization-Tools/main/data/data.csv',
allowLocalOverride: true, // Allow local file override allowLocalOverride: true,
allowUrlOverride: true, // Allow custom URL override allowUrlOverride: true,
// Crowdin editor // Crowdin editor
textboxSelector: '.editor-panel__editor-container textarea', textboxSelector: '.editor-panel__editor-container textarea',
@@ -48,10 +48,10 @@ const CONFIG = {
function log(type, message, data = null) { function log(type, message, data = null) {
if (!CONFIG.debug) return; if (!CONFIG.debug) return;
const timestamp = new Date().toLocaleTimeString(); const timestamp = new Date().toLocaleTimeString();
const prefix = `[Crowdin Localization Tools][${timestamp}]`; const prefix = `[Crowdin Localization Tools][${timestamp}]`;
switch (type.toLowerCase()) { switch (type.toLowerCase()) {
case 'info': case 'info':
console.log(`${prefix} ${message}`, data || ''); console.log(`${prefix} ${message}`, data || '');
@@ -84,13 +84,13 @@ function levenshteinDistance(a, b) {
for (let i = 1; i <= b.length; i++) { for (let i = 1; i <= b.length; i++) {
for (let j = 1; j <= a.length; j++) { for (let j = 1; j <= a.length; j++) {
if (b.charAt(i-1) === a.charAt(j-1)) { if (b.charAt(i - 1) === a.charAt(j - 1)) {
matrix[i][j] = matrix[i-1][j-1]; matrix[i][j] = matrix[i - 1][j - 1];
} else { } else {
matrix[i][j] = Math.min( matrix[i][j] = Math.min(
matrix[i-1][j-1] + 1, // substitution matrix[i - 1][j - 1] + 1, // substitution
matrix[i][j-1] + 1, // insertion matrix[i][j - 1] + 1, // insertion
matrix[i-1][j] + 1 // deletion matrix[i - 1][j] + 1 // deletion
); );
} }
} }
@@ -132,7 +132,7 @@ function TranslatorTool() {
if (!sourceToggle || !sourceToggle.checked) { if (!sourceToggle || !sourceToggle.checked) {
fetchRemoteCSV(CONFIG.remoteCSVUrl); fetchRemoteCSV(CONFIG.remoteCSVUrl);
} }
log('success', 'Crowdin Localization Tools version ' + CONFIG.metadata.version + ' by ' + CONFIG.metadata.authorGithub + ' initialized successfully'); log('success', 'Crowdin Localization Tools version ' + CONFIG.metadata.version + ' by ' + CONFIG.metadata.authorGithub + ' initialized successfully');
} }
@@ -182,7 +182,7 @@ function TranslatorTool() {
closeButton.style.color = '#666'; closeButton.style.color = '#666';
closeButton.style.padding = '0 4px'; closeButton.style.padding = '0 4px';
closeButton.style.lineHeight = '1'; closeButton.style.lineHeight = '1';
closeButton.addEventListener('click', function() { closeButton.addEventListener('click', function () {
log('info', 'Close button clicked'); log('info', 'Close button clicked');
toggleVisibility(); toggleVisibility();
}); });
@@ -243,7 +243,7 @@ function TranslatorTool() {
tab.style.fontWeight = '500'; tab.style.fontWeight = '500';
tab.style.transition = 'all 0.2s ease'; tab.style.transition = 'all 0.2s ease';
tab.addEventListener('click', function() { tab.addEventListener('click', function () {
switchTab(text.toLowerCase()); switchTab(text.toLowerCase());
}); });
@@ -281,21 +281,21 @@ function TranslatorTool() {
searchInput.style.backgroundColor = '#f8f9fa'; searchInput.style.backgroundColor = '#f8f9fa';
searchInput.style.outline = 'none'; searchInput.style.outline = 'none';
searchInput.addEventListener('mouseover', function() { searchInput.addEventListener('mouseover', function () {
if (document.activeElement !== this) { if (document.activeElement !== this) {
this.style.borderColor = '#ccc'; this.style.borderColor = '#ccc';
} }
}); });
searchInput.addEventListener('mouseout', function() { searchInput.addEventListener('mouseout', function () {
if (document.activeElement !== this) { if (document.activeElement !== this) {
this.style.borderColor = '#e0e0e0'; this.style.borderColor = '#e0e0e0';
} }
}); });
searchInput.addEventListener('focus', function() { searchInput.addEventListener('focus', function () {
this.style.borderColor = '#1a73e8'; this.style.borderColor = '#1a73e8';
this.style.backgroundColor = '#fff'; this.style.backgroundColor = '#fff';
}); });
searchInput.addEventListener('blur', function() { searchInput.addEventListener('blur', function () {
this.style.borderColor = '#e0e0e0'; this.style.borderColor = '#e0e0e0';
this.style.backgroundColor = '#f8f9fa'; this.style.backgroundColor = '#f8f9fa';
}); });
@@ -403,7 +403,7 @@ function TranslatorTool() {
localFileInput.style.width = '100%'; localFileInput.style.width = '100%';
localFileInput.style.fontSize = '14px'; localFileInput.style.fontSize = '14px';
localFileInput.addEventListener('change', function() { localFileInput.addEventListener('change', function () {
if (this.files.length > 0) { if (this.files.length > 0) {
readCSVFile(this.files[0]); readCSVFile(this.files[0]);
} }
@@ -412,7 +412,7 @@ function TranslatorTool() {
fileContainer.appendChild(fileLabel); fileContainer.appendChild(fileLabel);
fileContainer.appendChild(localFileInput); fileContainer.appendChild(localFileInput);
sourceToggle.addEventListener('change', function() { sourceToggle.addEventListener('change', function () {
urlContainer.style.display = this.checked ? 'none' : 'block'; urlContainer.style.display = this.checked ? 'none' : 'block';
fileContainer.style.display = this.checked ? 'block' : 'none'; fileContainer.style.display = this.checked ? 'block' : 'none';
@@ -448,7 +448,7 @@ function TranslatorTool() {
refreshButton.textContent = 'Refresh Data'; refreshButton.textContent = 'Refresh Data';
refreshButton.className = 'csv-translator-refresh-btn'; refreshButton.className = 'csv-translator-refresh-btn';
refreshButton.addEventListener('click', function() { refreshButton.addEventListener('click', function () {
refreshTranslationData(); refreshTranslationData();
}); });
@@ -482,7 +482,7 @@ function TranslatorTool() {
authorLink.style.textDecoration = 'none'; authorLink.style.textDecoration = 'none';
authorLink.style.cursor = 'pointer'; authorLink.style.cursor = 'pointer';
authorLink.target = '_blank'; authorLink.target = '_blank';
credits.appendChild(document.createTextNode('Made with 💖 by ')); credits.appendChild(document.createTextNode('Made with 💖 by '));
credits.appendChild(authorLink); credits.appendChild(authorLink);
credits.appendChild(document.createTextNode(` • v${CONFIG.metadata.version}`)); credits.appendChild(document.createTextNode(` • v${CONFIG.metadata.version}`));
@@ -493,7 +493,7 @@ function TranslatorTool() {
updateLink.style.color = '#1a73e8'; updateLink.style.color = '#1a73e8';
updateLink.style.textDecoration = 'none'; updateLink.style.textDecoration = 'none';
updateLink.style.cursor = 'pointer'; updateLink.style.cursor = 'pointer';
updateLink.addEventListener('click', function(e) { updateLink.addEventListener('click', function (e) {
e.preventDefault(); e.preventDefault();
checkForUpdates(); checkForUpdates();
}); });
@@ -529,7 +529,7 @@ function TranslatorTool() {
} }
function setupDraggable(element) { function setupDraggable(element) {
element.addEventListener('mousedown', function(e) { element.addEventListener('mousedown', function (e) {
isDragging = true; isDragging = true;
var rect = container.getBoundingClientRect(); var rect = container.getBoundingClientRect();
dragOffsetX = e.clientX - rect.left; dragOffsetX = e.clientX - rect.left;
@@ -538,7 +538,7 @@ function TranslatorTool() {
log('info', 'Started dragging window'); log('info', 'Started dragging window');
}); });
document.addEventListener('mousemove', function(e) { document.addEventListener('mousemove', function (e) {
if (isDragging) { if (isDragging) {
var x = e.clientX - dragOffsetX; var x = e.clientX - dragOffsetX;
var y = e.clientY - dragOffsetY; var y = e.clientY - dragOffsetY;
@@ -549,7 +549,7 @@ function TranslatorTool() {
} }
}); });
document.addEventListener('mouseup', function() { document.addEventListener('mouseup', function () {
if (isDragging) { if (isDragging) {
isDragging = false; isDragging = false;
log('info', 'Stopped dragging window'); log('info', 'Stopped dragging window');
@@ -579,7 +579,7 @@ function TranslatorTool() {
toggleButton.style.zIndex = '10000'; toggleButton.style.zIndex = '10000';
toggleButton.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)'; toggleButton.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)';
toggleButton.addEventListener('click', function() { toggleButton.addEventListener('click', function () {
log('info', 'Toggle button clicked'); log('info', 'Toggle button clicked');
toggleVisibility(); toggleVisibility();
}); });
@@ -602,7 +602,7 @@ function TranslatorTool() {
function setupEventListeners() { function setupEventListeners() {
log('info', 'Setting up event listeners'); log('info', 'Setting up event listeners');
searchInput.addEventListener('input', function() { searchInput.addEventListener('input', function () {
log('info', 'Search input detected'); log('info', 'Search input detected');
searchTranslations(); searchTranslations();
}); });
@@ -611,17 +611,17 @@ function TranslatorTool() {
function setupExternalTextboxListener() { function setupExternalTextboxListener() {
log('info', 'Setting up external textbox listener'); log('info', 'Setting up external textbox listener');
var observer = new MutationObserver(function(mutations) { var observer = new MutationObserver(function (mutations) {
var textbox = document.querySelector(CONFIG.textboxSelector); var textbox = document.querySelector(CONFIG.textboxSelector);
if (textbox && !textbox.dataset.translatorInitialized) { if (textbox && !textbox.dataset.translatorInitialized) {
log('info', 'Found target textbox', { selector: CONFIG.textboxSelector }); log('info', 'Found target textbox', { selector: CONFIG.textboxSelector });
textbox.dataset.translatorInitialized = 'true'; textbox.dataset.translatorInitialized = 'true';
textbox.addEventListener('input', function() { textbox.addEventListener('input', function () {
log('info', 'External textbox input detected'); log('info', 'External textbox input detected');
findMatches(textbox.value); findMatches(textbox.value);
}); });
textbox.addEventListener('mouseup', function() { textbox.addEventListener('mouseup', function () {
var selectedText = window.getSelection()?.toString(); var selectedText = window.getSelection()?.toString();
if (selectedText) { if (selectedText) {
log('info', 'Text selection detected', { selectedText: selectedText.substring(0, 20) + (selectedText.length > 20 ? '...' : '') }); log('info', 'Text selection detected', { selectedText: selectedText.substring(0, 20) + (selectedText.length > 20 ? '...' : '') });
@@ -649,7 +649,7 @@ function TranslatorTool() {
clearInterval(autoSearchIntervalId); clearInterval(autoSearchIntervalId);
} }
autoSearchIntervalId = setInterval(function() { autoSearchIntervalId = setInterval(function () {
checkForEditorContent(); checkForEditorContent();
}, CONFIG.autoSearchInterval); }, CONFIG.autoSearchInterval);
} }
@@ -678,7 +678,7 @@ function TranslatorTool() {
function parseEditorContent() { function parseEditorContent() {
const editorContainer = document.querySelector(CONFIG.editorSourceContainer); const editorContainer = document.querySelector(CONFIG.editorSourceContainer);
if (!editorContainer) return null; if (!editorContainer) return null;
const sourceContainer = document.querySelector(CONFIG.sourceStringContainer); const sourceContainer = document.querySelector(CONFIG.sourceStringContainer);
if (!sourceContainer) return null; if (!sourceContainer) return null;
@@ -720,7 +720,7 @@ function TranslatorTool() {
} }
result.fullText = result.fullText.trim(); result.fullText = result.fullText.trim();
return result; return result;
} catch (error) { } catch (error) {
log('error', 'Error parsing editor content:', error); log('error', 'Error parsing editor content:', error);
@@ -733,7 +733,7 @@ function TranslatorTool() {
const sourceToggle = document.querySelector('#source-toggle'); const sourceToggle = document.querySelector('#source-toggle');
const remoteUrlInput = document.querySelector('#translator-settings-content input[type="text"]'); const remoteUrlInput = document.querySelector('#translator-settings-content input[type="text"]');
const localFileInput = document.querySelector('#translator-settings-content input[type="file"]'); const localFileInput = document.querySelector('#translator-settings-content input[type="file"]');
if (sourceToggle.checked) { if (sourceToggle.checked) {
if (localFileInput && localFileInput.files.length > 0) { if (localFileInput && localFileInput.files.length > 0) {
readCSVFile(localFileInput.files[0]); readCSVFile(localFileInput.files[0]);
@@ -757,7 +757,7 @@ function TranslatorTool() {
GM_xmlhttpRequest({ GM_xmlhttpRequest({
method: 'GET', method: 'GET',
url: url, url: url,
onload: function(response) { onload: function (response) {
if (response.status === 200) { if (response.status === 200) {
parseCSV(response.responseText); parseCSV(response.responseText);
currentCSVSource = url; currentCSVSource = url;
@@ -767,7 +767,7 @@ function TranslatorTool() {
updateResults('Failed to fetch remote CSV. Please check the URL and try again.'); updateResults('Failed to fetch remote CSV. Please check the URL and try again.');
} }
}, },
onerror: function(error) { onerror: function (error) {
log('error', 'Error fetching remote CSV', error); log('error', 'Error fetching remote CSV', error);
updateResults('Error fetching remote CSV. Please check your connection and try again.'); updateResults('Error fetching remote CSV. Please check your connection and try again.');
} }
@@ -777,13 +777,13 @@ function TranslatorTool() {
function readCSVFile(file) { function readCSVFile(file) {
log('info', 'Reading CSV file'); log('info', 'Reading CSV file');
var reader = new FileReader(); var reader = new FileReader();
reader.onload = function(e) { reader.onload = function (e) {
var content = e.target?.result; var content = e.target?.result;
log('info', 'CSV file loaded, content length', { length: content.length }); log('info', 'CSV file loaded, content length', { length: content.length });
parseCSV(content); parseCSV(content);
currentCSVSource = file.name; currentCSVSource = file.name;
}; };
reader.onerror = function(error) { reader.onerror = function (error) {
log('error', 'Error reading file', error); log('error', 'Error reading file', error);
updateResults('Error reading CSV file. Please try again.'); updateResults('Error reading CSV file. Please try again.');
}; };
@@ -808,7 +808,7 @@ function TranslatorTool() {
for (var j = 0; j < line.length; j++) { for (var j = 0; j < line.length; j++) {
var char = line[j]; var char = line[j];
if (char === '"' && (j === 0 || line[j-1] !== '\\')) { if (char === '"' && (j === 0 || line[j - 1] !== '\\')) {
inQuotes = !inQuotes; inQuotes = !inQuotes;
} else if (char === ',' && !inQuotes) { } else if (char === ',' && !inQuotes) {
values.push(currentValue); values.push(currentValue);
@@ -822,7 +822,7 @@ function TranslatorTool() {
values.push(currentValue); values.push(currentValue);
// Remove quotes if present // Remove quotes if present
values = values.map(function(v) { values = values.map(function (v) {
return v.replace(/^"(.*)"$/, '$1'); return v.replace(/^"(.*)"$/, '$1');
}); });
@@ -836,7 +836,7 @@ function TranslatorTool() {
} }
} }
log('success', 'CSV parsing complete', { log('success', 'CSV parsing complete', {
entries: translationData.length, entries: translationData.length,
source: currentCSVSource || 'CSV' source: currentCSVSource || 'CSV'
}); });
@@ -848,7 +848,7 @@ function TranslatorTool() {
function findMatches(text) { function findMatches(text) {
if (!text || !translationData.length) return; if (!text || !translationData.length) return;
log('debug', 'Finding matches', { log('debug', 'Finding matches', {
text: text.substring(0, 50) + (text.length > 50 ? '...' : ''), text: text.substring(0, 50) + (text.length > 50 ? '...' : ''),
length: text.length length: text.length
}); });
@@ -857,7 +857,7 @@ function TranslatorTool() {
var matches = []; var matches = [];
var seenWords = new Set(); var seenWords = new Set();
words.forEach(function(word) { words.forEach(function (word) {
// Clean the word from punctuation // Clean the word from punctuation
var cleanWord = word.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, ""); var cleanWord = word.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
if (!cleanWord || cleanWord.length <= 1) return; // Skip single characters if (!cleanWord || cleanWord.length <= 1) return; // Skip single characters
@@ -866,13 +866,13 @@ function TranslatorTool() {
seenWords.add(cleanWord.toLowerCase()); seenWords.add(cleanWord.toLowerCase());
// Find matches // Find matches
translationData.forEach(function(entry) { translationData.forEach(function (entry) {
// For short words (2-3 chars), use stricter matching // For short words (2-3 chars), use stricter matching
if (cleanWord.length <= 3) { if (cleanWord.length <= 3) {
// Only match if it's a complete word match or surrounded by word boundaries // Only match if it's a complete word match or surrounded by word boundaries
const regex = new RegExp(`\\b${cleanWord}\\b`, 'i'); const regex = new RegExp(`\\b${cleanWord}\\b`, 'i');
if (regex.test(entry.source) && if (regex.test(entry.source) &&
!matches.some(function(m) { return m.entry.source === entry.source; })) { !matches.some(function (m) { return m.entry.source === entry.source; })) {
matches.push({ matches.push({
entry: entry, entry: entry,
score: 1, score: 1,
@@ -883,7 +883,7 @@ function TranslatorTool() {
// For longer words, use fuzzy match with higher threshold // For longer words, use fuzzy match with higher threshold
const score = similarity(entry.source.toLowerCase(), cleanWord.toLowerCase()); const score = similarity(entry.source.toLowerCase(), cleanWord.toLowerCase());
if (score >= CONFIG.fuzzyThreshold && if (score >= CONFIG.fuzzyThreshold &&
!matches.some(function(m) { return m.entry.source === entry.source; })) { !matches.some(function (m) { return m.entry.source === entry.source; })) {
matches.push({ matches.push({
entry: entry, entry: entry,
score: score, score: score,
@@ -894,7 +894,7 @@ function TranslatorTool() {
}); });
}); });
matches.sort(function(a, b) { matches.sort(function (a, b) {
if (b.score === a.score) { if (b.score === a.score) {
return b.matchedWord.length - a.matchedWord.length; return b.matchedWord.length - a.matchedWord.length;
} }
@@ -918,9 +918,9 @@ function TranslatorTool() {
var matches = []; var matches = [];
// Find matches // Find matches
translationData.forEach(function(entry) { translationData.forEach(function (entry) {
let score = 0; let score = 0;
// For short queries (2-3 chars), use stricter matching // For short queries (2-3 chars), use stricter matching
if (query.length <= 3) { if (query.length <= 3) {
// Only match if it's a complete word match or surrounded by word boundaries // Only match if it's a complete word match or surrounded by word boundaries
@@ -933,7 +933,7 @@ function TranslatorTool() {
const sourceScore = similarity(entry.source.toLowerCase(), query); const sourceScore = similarity(entry.source.toLowerCase(), query);
const targetScore = similarity(entry.target.toLowerCase(), query); const targetScore = similarity(entry.target.toLowerCase(), query);
const noteScore = entry.note ? similarity(entry.note.toLowerCase(), query) : 0; const noteScore = entry.note ? similarity(entry.note.toLowerCase(), query) : 0;
// Use the highest score // Use the highest score
score = Math.max(sourceScore, targetScore, noteScore); score = Math.max(sourceScore, targetScore, noteScore);
} }
@@ -948,7 +948,7 @@ function TranslatorTool() {
}); });
// Sort matches by score (highest first) and text length (longer matches first) // Sort matches by score (highest first) and text length (longer matches first)
matches.sort(function(a, b) { matches.sort(function (a, b) {
if (b.score === a.score) { if (b.score === a.score) {
return b.entry.source.length - a.entry.source.length; return b.entry.source.length - a.entry.source.length;
} }
@@ -1022,7 +1022,7 @@ function TranslatorTool() {
// Create table body // Create table body
var tbody = document.createElement('tbody'); var tbody = document.createElement('tbody');
matches.forEach(function(match) { matches.forEach(function (match) {
var row = document.createElement('tr'); var row = document.createElement('tr');
const scorePercentage = Math.round(match.score * 100); const scorePercentage = Math.round(match.score * 100);
const bgColor = `rgba(26, 115, 232, ${match.score * 0.1})`; const bgColor = `rgba(26, 115, 232, ${match.score * 0.1})`;
@@ -1093,36 +1093,36 @@ function TranslatorTool() {
GM_xmlhttpRequest({ GM_xmlhttpRequest({
method: 'GET', method: 'GET',
url: CONFIG.updateCheckUrl, url: CONFIG.updateCheckUrl,
onload: function(response) { onload: function (response) {
if (response.status === 200) { if (response.status === 200) {
try { try {
const versionInfo = JSON.parse(response.responseText); const versionInfo = JSON.parse(response.responseText);
const latestVersion = versionInfo.latest; const latestVersion = versionInfo.latest;
const needsVersionUpdate = latestVersion !== CONFIG.currentVersion; const needsVersionUpdate = latestVersion !== CONFIG.currentVersion;
log('info', 'Retrieved version info', { log('info', 'Retrieved version info', {
current: CONFIG.currentVersion, current: CONFIG.currentVersion,
latest: latestVersion latest: latestVersion
}); });
// Check CSV data // Check CSV data
const sourceToggle = document.querySelector('#source-toggle'); const sourceToggle = document.querySelector('#source-toggle');
const remoteUrlInput = document.querySelector('#translator-settings-content input[type="text"]'); const remoteUrlInput = document.querySelector('#translator-settings-content input[type="text"]');
const csvUrl = (!sourceToggle || !sourceToggle.checked) ? const csvUrl = (!sourceToggle || !sourceToggle.checked) ?
(remoteUrlInput && remoteUrlInput.value.trim() ? remoteUrlInput.value.trim() : CONFIG.remoteCSVUrl) : (remoteUrlInput && remoteUrlInput.value.trim() ? remoteUrlInput.value.trim() : CONFIG.remoteCSVUrl) :
null; null;
if (csvUrl) { if (csvUrl) {
log('info', 'Checking CSV updates from', { url: csvUrl }); log('info', 'Checking CSV updates from', { url: csvUrl });
GM_xmlhttpRequest({ GM_xmlhttpRequest({
method: 'GET', method: 'GET',
url: csvUrl, url: csvUrl,
onload: function(csvResponse) { onload: function (csvResponse) {
if (csvResponse.status === 200) { if (csvResponse.status === 200) {
try { try {
const newData = parseCSVToArray(csvResponse.responseText); const newData = parseCSVToArray(csvResponse.responseText);
const needsDataUpdate = JSON.stringify(translationData) !== JSON.stringify(newData); const needsDataUpdate = JSON.stringify(translationData) !== JSON.stringify(newData);
log('info', 'CSV check complete', { log('info', 'CSV check complete', {
needsUpdate: needsDataUpdate, needsUpdate: needsDataUpdate,
currentEntries: translationData.length, currentEntries: translationData.length,
newEntries: newData.length newEntries: newData.length
@@ -1137,7 +1137,7 @@ function TranslatorTool() {
updateUIAfterChecks(needsVersionUpdate, false, latestVersion, null); updateUIAfterChecks(needsVersionUpdate, false, latestVersion, null);
} }
}, },
onerror: function(csvError) { onerror: function (csvError) {
log('error', 'Error fetching CSV', csvError); log('error', 'Error fetching CSV', csvError);
updateUIAfterChecks(needsVersionUpdate, false, latestVersion, null); updateUIAfterChecks(needsVersionUpdate, false, latestVersion, null);
} }
@@ -1157,7 +1157,7 @@ function TranslatorTool() {
updateLink.style.color = '#F44336'; updateLink.style.color = '#F44336';
} }
}, },
onerror: function(error) { onerror: function (error) {
log('error', 'Error checking for updates', error); log('error', 'Error checking for updates', error);
updateLink.textContent = 'Error checking for updates'; updateLink.textContent = 'Error checking for updates';
updateLink.style.color = '#F44336'; updateLink.style.color = '#F44336';
@@ -1168,7 +1168,7 @@ function TranslatorTool() {
function parseCSVToArray(csvContent) { function parseCSVToArray(csvContent) {
const lines = csvContent.split('\n'); const lines = csvContent.split('\n');
const result = []; const result = [];
// Skip header // Skip header
for (let i = 1; i < lines.length; i++) { for (let i = 1; i < lines.length; i++) {
const line = lines[i].trim(); const line = lines[i].trim();
@@ -1180,7 +1180,7 @@ function TranslatorTool() {
for (let j = 0; j < line.length; j++) { for (let j = 0; j < line.length; j++) {
const char = line[j]; const char = line[j];
if (char === '"' && (j === 0 || line[j-1] !== '\\')) { if (char === '"' && (j === 0 || line[j - 1] !== '\\')) {
inQuotes = !inQuotes; inQuotes = !inQuotes;
} else if (char === ',' && !inQuotes) { } else if (char === ',' && !inQuotes) {
values.push(currentValue); values.push(currentValue);
@@ -1223,7 +1223,7 @@ function TranslatorTool() {
translationData = newData; translationData = newData;
log('success', 'Updated translation data', { entries: newData.length }); log('success', 'Updated translation data', { entries: newData.length });
updateResults(`Updated with ${newData.length} translations`); updateResults(`Updated with ${newData.length} translations`);
setTimeout(() => { setTimeout(() => {
updateLink.textContent = 'Translations updated ✓'; updateLink.textContent = 'Translations updated ✓';
updateLink.style.color = '#4CAF50'; updateLink.style.color = '#4CAF50';
@@ -1278,12 +1278,12 @@ function TranslatorTool() {
document.body.appendChild(notification); document.body.appendChild(notification);
document.getElementById('csv-translator-dismiss').addEventListener('click', function() { document.getElementById('csv-translator-dismiss').addEventListener('click', function () {
document.body.removeChild(notification); document.body.removeChild(notification);
}); });
if (hasVersionUpdate) { if (hasVersionUpdate) {
document.getElementById('csv-translator-update').addEventListener('click', function() { document.getElementById('csv-translator-update').addEventListener('click', function () {
window.open(CONFIG.metadata.repository, '_blank'); window.open(CONFIG.metadata.repository, '_blank');
document.body.removeChild(notification); document.body.removeChild(notification);
}); });
@@ -1299,7 +1299,7 @@ function TranslatorTool() {
init(); init();
} }
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function () {
log('info', 'DOMContentLoaded event fired'); log('info', 'DOMContentLoaded event fired');
try { try {
new TranslatorTool(); new TranslatorTool();
@@ -1311,7 +1311,7 @@ document.addEventListener('DOMContentLoaded', function() {
// Fallback initialization // Fallback initialization
if (document.readyState === 'complete' || document.readyState === 'interactive') { if (document.readyState === 'complete' || document.readyState === 'interactive') {
log('info', 'Document already loaded, initializing immediately'); log('info', 'Document already loaded, initializing immediately');
setTimeout(function() { setTimeout(function () {
try { try {
new TranslatorTool(); new TranslatorTool();
} catch (error) { } catch (error) {