mirror of
https://github.com/tiennm99/WPlace-AutoBOT.git
synced 2026-10-17 18:13:39 +00:00
test
This commit is contained in:
1 parent
745ce578b9
commit
ce0ac59ec2
1 file changed
+172
-43
+172
-43
@@ -277,71 +277,159 @@ function applyTheme() {
|
||||
// Available languages
|
||||
const AVAILABLE_LANGUAGES = ['en', 'ru', 'pt', 'vi', 'fr', 'id', 'tr', 'zh-CN', 'zh-TW', 'ja', 'ko', 'uk'];
|
||||
|
||||
// Function to load translations from JSON file
|
||||
const loadTranslations = async (language) => {
|
||||
// Function to load translations from JSON file with retry mechanism
|
||||
const loadTranslations = async (language, retryCount = 0) => {
|
||||
if (loadedTranslations[language]) {
|
||||
return loadedTranslations[language];
|
||||
}
|
||||
|
||||
// Load translations from CDN
|
||||
const url = `https://staninna.github.io/WPlace-AutoBOT/decoupled-translations/lang/${language}.json`;
|
||||
const maxRetries = 3;
|
||||
const baseDelay = 1000; // 1 second
|
||||
|
||||
try {
|
||||
console.log(`🔄 Loading ${language} translations from CDN...`);
|
||||
if (retryCount === 0) {
|
||||
console.log(`🔄 Loading ${language} translations from CDN...`);
|
||||
} else {
|
||||
console.log(`🔄 Retrying ${language} translations (attempt ${retryCount + 1}/${maxRetries + 1})...`);
|
||||
}
|
||||
|
||||
const response = await fetch(url);
|
||||
if (response.ok) {
|
||||
const translations = await response.json();
|
||||
loadedTranslations[language] = translations;
|
||||
console.log(`📚 Loaded ${language} translations successfully from CDN`);
|
||||
return translations;
|
||||
|
||||
// Validate that translations is an object with keys
|
||||
if (typeof translations === 'object' && translations !== null && Object.keys(translations).length > 0) {
|
||||
loadedTranslations[language] = translations;
|
||||
console.log(`📚 Loaded ${language} translations successfully from CDN (${Object.keys(translations).length} keys)`);
|
||||
return translations;
|
||||
} else {
|
||||
console.warn(`❌ Invalid translation format for ${language}`);
|
||||
throw new Error('Invalid translation format');
|
||||
}
|
||||
} else {
|
||||
console.warn(`❌ CDN returned HTTP ${response.status}: ${response.statusText} for ${language} translations`);
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ Failed to load ${language} translations from CDN:`, error);
|
||||
console.error(`❌ Failed to load ${language} translations from CDN (attempt ${retryCount + 1}):`, error);
|
||||
|
||||
// Retry with exponential backoff
|
||||
if (retryCount < maxRetries) {
|
||||
const delay = baseDelay * Math.pow(2, retryCount);
|
||||
console.log(`⏳ Retrying in ${delay}ms...`);
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
return loadTranslations(language, retryCount + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const loadLanguagePreference = async () => {
|
||||
const savedLanguage = localStorage.getItem("wplace_language")
|
||||
const savedLanguage = localStorage.getItem("wplace_language");
|
||||
const browserLocale = navigator.language;
|
||||
const browserLanguage = browserLocale.split("-")[0];
|
||||
|
||||
const browserLocale = navigator.language
|
||||
const browserLanguage = browserLocale.split("-")[0]
|
||||
let selectedLanguage = "en"; // Default fallback
|
||||
|
||||
// Check if we have the saved language available
|
||||
if (savedLanguage && AVAILABLE_LANGUAGES.includes(savedLanguage)) {
|
||||
state.language = savedLanguage
|
||||
await loadTranslations(savedLanguage)
|
||||
return
|
||||
try {
|
||||
// Check if we have the saved language available
|
||||
if (savedLanguage && AVAILABLE_LANGUAGES.includes(savedLanguage)) {
|
||||
selectedLanguage = savedLanguage;
|
||||
console.log(`🔄 Using saved language preference: ${selectedLanguage}`);
|
||||
}
|
||||
// Try full locale match (e.g. "zh-CN", "zh-TW" etc)
|
||||
else if (AVAILABLE_LANGUAGES.includes(browserLocale)) {
|
||||
selectedLanguage = browserLocale;
|
||||
localStorage.setItem("wplace_language", browserLocale);
|
||||
console.log(`🔄 Using browser locale: ${selectedLanguage}`);
|
||||
}
|
||||
// Try base language match (e.g. "en" for "en-US" or "en-GB" etc)
|
||||
else if (AVAILABLE_LANGUAGES.includes(browserLanguage)) {
|
||||
selectedLanguage = browserLanguage;
|
||||
localStorage.setItem("wplace_language", browserLanguage);
|
||||
console.log(`🔄 Using browser language: ${selectedLanguage}`);
|
||||
}
|
||||
// Use English as fallback
|
||||
else {
|
||||
console.log(`🔄 No matching language found, using English fallback`);
|
||||
}
|
||||
|
||||
// Set the language in state first
|
||||
state.language = selectedLanguage;
|
||||
|
||||
// Only load translations if not already loaded and not English (which should already be loaded)
|
||||
if (selectedLanguage !== "en" && !loadedTranslations[selectedLanguage]) {
|
||||
const loaded = await loadTranslations(selectedLanguage);
|
||||
if (!loaded) {
|
||||
console.warn(`⚠️ Failed to load ${selectedLanguage} translations, falling back to English`);
|
||||
state.language = "en";
|
||||
localStorage.setItem("wplace_language", "en");
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ Error in loadLanguagePreference:`, error);
|
||||
state.language = "en"; // Always ensure we have a valid language
|
||||
}
|
||||
|
||||
// Try full locale match (e.g. "zh-CN", "zh-TW" etc)
|
||||
if (AVAILABLE_LANGUAGES.includes(browserLocale)) {
|
||||
state.language = browserLocale
|
||||
localStorage.setItem("wplace_language", browserLocale)
|
||||
await loadTranslations(browserLocale)
|
||||
return
|
||||
}
|
||||
|
||||
// Try base language match (e.g. "en" for "en-US" or "en-GB" etc)
|
||||
if (AVAILABLE_LANGUAGES.includes(browserLanguage)) {
|
||||
state.language = browserLanguage
|
||||
localStorage.setItem("wplace_language", browserLanguage)
|
||||
await loadTranslations(browserLanguage)
|
||||
return
|
||||
}
|
||||
|
||||
// Fallback to English
|
||||
state.language = "en"
|
||||
await loadTranslations("en")
|
||||
}
|
||||
};
|
||||
|
||||
// Always ensure English is loaded as fallback
|
||||
if (!loadedTranslations["en"]) {
|
||||
await loadTranslations("en")
|
||||
}
|
||||
// Simple user notification function for critical issues
|
||||
const showTranslationWarning = (message) => {
|
||||
try {
|
||||
// Create a simple temporary notification banner
|
||||
const warning = document.createElement('div');
|
||||
warning.style.cssText = `
|
||||
position: fixed; top: 10px; right: 10px; z-index: 10001;
|
||||
background: rgba(255, 193, 7, 0.95); color: #212529; padding: 12px 16px;
|
||||
border-radius: 8px; font-size: 14px; font-weight: 500;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.3); border: 1px solid rgba(255, 193, 7, 0.8);
|
||||
max-width: 300px; word-wrap: break-word;
|
||||
`;
|
||||
warning.textContent = message;
|
||||
document.body.appendChild(warning);
|
||||
|
||||
// Auto-remove after 8 seconds
|
||||
setTimeout(() => {
|
||||
if (warning.parentNode) {
|
||||
warning.remove();
|
||||
}
|
||||
}, 8000);
|
||||
} catch (e) {
|
||||
// If DOM manipulation fails, just log
|
||||
console.warn("Failed to show translation warning UI:", e);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize translations function
|
||||
const initializeTranslations = async () => {
|
||||
try {
|
||||
console.log("🌐 Initializing translation system...");
|
||||
|
||||
// Always ensure English is loaded as fallback first
|
||||
if (!loadedTranslations["en"]) {
|
||||
const englishLoaded = await loadTranslations("en");
|
||||
if (!englishLoaded) {
|
||||
console.warn("⚠️ Failed to load English translations from CDN, using fallback");
|
||||
showTranslationWarning("⚠️ Translation loading failed, using basic fallbacks");
|
||||
}
|
||||
}
|
||||
|
||||
// Then load user's language preference
|
||||
await loadLanguagePreference();
|
||||
|
||||
console.log(`✅ Translation system initialized. Active language: ${state.language}`);
|
||||
} catch (error) {
|
||||
console.error("❌ Translation initialization failed:", error);
|
||||
// Ensure state has a valid language even if loading fails
|
||||
if (!state.language) {
|
||||
state.language = "en";
|
||||
}
|
||||
console.warn("⚠️ Using fallback translations due to initialization failure");
|
||||
showTranslationWarning("⚠️ Translation system error, using basic English");
|
||||
}
|
||||
};
|
||||
|
||||
// Emergency fallback TEXT (minimal)
|
||||
const FALLBACK_TEXT = {
|
||||
@@ -350,10 +438,45 @@ function applyTheme() {
|
||||
settings: "Settings",
|
||||
close: "Close",
|
||||
language: "Language",
|
||||
loadingError: "Loading translations failed, using fallback"
|
||||
loadingError: "Loading translations failed, using fallback",
|
||||
scanColors: "Scan Colors",
|
||||
uploadImage: "Upload Image",
|
||||
startPainting: "Start Painting",
|
||||
stopPainting: "Stop Painting",
|
||||
progress: "Progress",
|
||||
pixels: "Pixels",
|
||||
charges: "Charges",
|
||||
initMessage: "Click 'Upload Image' to begin"
|
||||
}
|
||||
};
|
||||
|
||||
// Safe translation function with multiple fallback levels
|
||||
const getText = (key, replacements = {}) => {
|
||||
// Try current language first
|
||||
let text = loadedTranslations[state.language]?.[key];
|
||||
|
||||
// Fallback to English translations
|
||||
if (!text && state.language !== 'en') {
|
||||
text = loadedTranslations['en']?.[key];
|
||||
}
|
||||
|
||||
// Fallback to hardcoded English
|
||||
if (!text) {
|
||||
text = FALLBACK_TEXT['en']?.[key];
|
||||
}
|
||||
|
||||
// Last resort - return the key itself
|
||||
if (!text) {
|
||||
console.warn(`⚠️ Missing translation for key: ${key}`);
|
||||
return key;
|
||||
}
|
||||
|
||||
// Handle string replacements like {count}, {time}, etc.
|
||||
return Object.entries(replacements).reduce((result, [placeholder, value]) => {
|
||||
return result.replace(new RegExp(`\\{${placeholder}\\}`, 'g'), value);
|
||||
}, text);
|
||||
};
|
||||
|
||||
// GLOBAL STATE
|
||||
const state = {
|
||||
running: false,
|
||||
@@ -1401,8 +1524,14 @@ function applyTheme() {
|
||||
// Final fallback to emergency fallback or key
|
||||
let text = FALLBACK_TEXT[state.language]?.[key] || FALLBACK_TEXT.en?.[key] || key;
|
||||
Object.keys(params).forEach((param) => {
|
||||
text = text.replace(`{${param}}`, params[param]);
|
||||
text = text.replace(new RegExp(`\\{${param}\\}`, 'g'), params[param]);
|
||||
});
|
||||
|
||||
// Log missing translations for debugging
|
||||
if (text === key && key !== 'undefined') {
|
||||
console.warn(`⚠️ Missing translation for key: ${key} (language: ${state.language})`);
|
||||
}
|
||||
|
||||
return text;
|
||||
},
|
||||
|
||||
@@ -2580,7 +2709,7 @@ function applyTheme() {
|
||||
if (existingResizeOverlay) existingResizeOverlay.remove()
|
||||
|
||||
loadThemePreference()
|
||||
await loadLanguagePreference()
|
||||
await initializeTranslations()
|
||||
|
||||
const theme = getCurrentTheme()
|
||||
applyTheme() // <- new: set CSS vars and theme class before building UI
|
||||
|
||||
Reference in new issue
Block a user