mirror of
https://github.com/YuzuZensai/Crowdin-Localization-Tools.git
synced 2026-01-06 04:33:03 +00:00
🐛 fix: wrong update/download url
This commit is contained in:
@@ -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) {
|
||||||
Reference in New Issue
Block a user