feat: save language setting to localStorage

This commit is contained in:
KOWX712
2025-03-25 13:22:34 +08:00
parent d739bc2751
commit 1c93287b69
2 changed files with 53 additions and 43 deletions

View File

@@ -1,5 +1,3 @@
import { toast } from './main.js';
const languageButton = document.querySelector('.language-button'); const languageButton = document.querySelector('.language-button');
const languageMenu = document.querySelector('.language-menu'); const languageMenu = document.querySelector('.language-menu');
const languageOptions = document.querySelectorAll('.language-option'); const languageOptions = document.querySelectorAll('.language-option');
@@ -8,49 +6,55 @@ const languageOverlay = document.getElementById('language-overlay');
export let translations = {}; export let translations = {};
let availableLanguages = ['en-US']; let availableLanguages = ['en-US'];
// Function to check for available language /**
export async function initializeAvailableLanguages() { * Detect user's default language
try { * @returns {Promise<string>} - Detected language code
const response = await fetch('locales/available-lang.json'); */
const config = await response.json(); export async function detectUserLanguage() {
availableLanguages = config.languages;
generateLanguageMenu();
} catch (error) {
console.error('Failed to fetch available languages:', error);
availableLanguages = ['en-US'];
}
}
// Function to detect user's default language
export function detectUserLanguage() {
const userLang = navigator.language || navigator.userLanguage; const userLang = navigator.language || navigator.userLanguage;
const langCode = userLang.split('-')[0]; const langCode = userLang.split('-')[0];
if (availableLanguages.includes(userLang)) {
return userLang; try {
} else if (availableLanguages.includes(langCode)) { // Fetch available languages
return langCode; const availableResponse = await fetch('locales/available-lang.json');
} else { const availableData = await availableResponse.json();
availableLanguages = availableData.languages;
generateLanguageMenu();
// Fetch preferred language
const prefered_language_code = localStorage.getItem('trickyAddonLanguage');
// Check if preferred language is valid
if (prefered_language_code !== 'default' && availableLanguages.includes(prefered_language_code)) {
return prefered_language_code;
} else if (availableLanguages.includes(userLang)) {
return userLang;
} else if (availableLanguages.includes(langCode)) {
return langCode;
} else {
return 'en-US';
}
} catch (error) {
console.error('Error detecting user language:', error);
return 'en-US'; return 'en-US';
} }
} }
// Load translations dynamically based on the selected language /**
export async function loadTranslations(lang) { * Load translations dynamically based on the selected language
try { * @returns {Promise<void>}
const response = await fetch(`locales/${lang}.json`); */
translations = await response.json(); export async function loadTranslations() {
applyTranslations(); const lang = await detectUserLanguage();
} catch (error) { const response = await fetch(`locales/${lang}.json`);
toast(`Failed to load translation for ${lang}!`); translations = await response.json();
console.error(`Error loading translations for ${lang}:`, error); applyTranslations();
if (lang !== 'en-US') {
console.log("Falling back to English.");
loadTranslations('en-US');
}
}
} }
// Function to apply translations to all elements with data-i18n attributes /**
* Apply translations to all elements with data-i18n attributes
* @returns {void}
*/
function applyTranslations() { function applyTranslations() {
document.querySelectorAll("[data-i18n]").forEach((el) => { document.querySelectorAll("[data-i18n]").forEach((el) => {
const keyString = el.getAttribute("data-i18n"); const keyString = el.getAttribute("data-i18n");
@@ -65,7 +69,10 @@ function applyTranslations() {
}); });
} }
// Function to setup the language menu /**
* Function to setup the language menu
* @returns {void}
*/
export function setupLanguageMenu() { export function setupLanguageMenu() {
languageButton.addEventListener("click", (event) => { languageButton.addEventListener("click", (event) => {
event.stopPropagation(); event.stopPropagation();
@@ -104,13 +111,18 @@ export function setupLanguageMenu() {
languageMenu.addEventListener("click", (e) => { languageMenu.addEventListener("click", (e) => {
if (e.target.classList.contains("language-option")) { if (e.target.classList.contains("language-option")) {
const lang = e.target.getAttribute("data-lang"); const lang = e.target.getAttribute("data-lang");
localStorage.setItem('trickyAddonLanguage', lang);
loadTranslations(lang); loadTranslations(lang);
closeLanguageMenu(); closeLanguageMenu();
} }
}); });
} }
// Function to generate the language menu dynamically /**
* Generate the language menu dynamically
* Refer available-lang.json in ./locales for list of languages
* @returns {Promise<void>}
*/
async function generateLanguageMenu() { async function generateLanguageMenu() {
languageMenu.innerHTML = ''; languageMenu.innerHTML = '';
const languagePromises = availableLanguages.map(async (lang) => { const languagePromises = availableLanguages.map(async (lang) => {

View File

@@ -1,5 +1,5 @@
import { appListContainer, fetchAppList } from './applist.js'; import { appListContainer, fetchAppList } from './applist.js';
import { initializeAvailableLanguages, detectUserLanguage, loadTranslations, setupLanguageMenu, translations } from './language.js'; import { loadTranslations, setupLanguageMenu, translations } from './language.js';
import { aospkb, setupSystemAppMenu } from './menu_option.js'; import { aospkb, setupSystemAppMenu } from './menu_option.js';
import { searchMenuContainer, searchInput, clearBtn, setupMenuToggle } from './search_menu.js'; import { searchMenuContainer, searchInput, clearBtn, setupMenuToggle } from './search_menu.js';
import { updateCheck } from './update.js'; import { updateCheck } from './update.js';
@@ -357,9 +357,7 @@ window.addEventListener('scroll', () => {
// Initial load // Initial load
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
await initializeAvailableLanguages(); loadTranslations();
const userLang = detectUserLanguage();
await loadTranslations(userLang);
await checkMMRL(); await checkMMRL();
if (!MMRL_API) return; if (!MMRL_API) return;
await getBasePath(); await getBasePath();