diff --git a/CustomApps/lyrics-plus/OptionsMenu.js b/CustomApps/lyrics-plus/OptionsMenu.js index 3bd13c6a9a..d998d1e2d0 100644 --- a/CustomApps/lyrics-plus/OptionsMenu.js +++ b/CustomApps/lyrics-plus/OptionsMenu.js @@ -96,6 +96,15 @@ function getMusixmatchTranslationPrefix() { const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation, musixmatchLanguages, musixmatchSelectedLanguage }) => { const musixmatchTranslationPrefix = getMusixmatchTranslationPrefix(); + + const [languageMap, setLanguageMap] = react.useState({}); + + react.useEffect(() => { + if (typeof ProviderMusixmatch !== "undefined") { + ProviderMusixmatch.getLanguages().then(setLanguageMap); + } + }, []); + const items = useMemo(() => { let sourceOptions = { none: "None", @@ -129,7 +138,11 @@ const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation, musixmat const musixmatchOptions = availableMusixmatchLanguages.reduce((acc, code) => { let label = ""; try { - label = musixmatchDisplay.of(code) ?? code.toUpperCase(); + if (languageMap && languageMap[code]) { + label = languageMap[code]; + } else { + label = musixmatchDisplay.of(code) ?? code.toUpperCase(); + } } catch (e) { label = code.toUpperCase(); } @@ -224,7 +237,9 @@ const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation, musixmat hasTranslation.netease, Array.isArray(musixmatchLanguages) ? musixmatchLanguages.join(",") : "", musixmatchSelectedLanguage || "", + musixmatchTranslationPrefix, + languageMap, ]); useEffect(() => { diff --git a/CustomApps/lyrics-plus/ProviderMusixmatch.js b/CustomApps/lyrics-plus/ProviderMusixmatch.js index b82f844906..98c75d3d26 100644 --- a/CustomApps/lyrics-plus/ProviderMusixmatch.js +++ b/CustomApps/lyrics-plus/ProviderMusixmatch.js @@ -237,5 +237,57 @@ const ProviderMusixmatch = (() => { })); } - return { findLyrics, getKaraoke, getSynced, getUnsynced, getTranslation }; + let languageMap = null; + async function getLanguages() { + if (languageMap) return languageMap; + + try { + const cached = localStorage.getItem("lyrics-plus:musixmatch-languages"); + if (cached) { + const tempMap = JSON.parse(cached); + // Check cache version + if (tempMap.__version === 1) { + delete tempMap.__version; + languageMap = tempMap; + return languageMap; + } + } + } catch (e) { + console.warn("Failed to parse cached languages", e); + } + + const baseURL = "https://apic-desktop.musixmatch.com/ws/1.1/languages.get?app_id=web-desktop-app-v1.0&get_romanized_info=1&"; + + const params = { + usertoken: CONFIG.providers.musixmatch.token, + }; + + const finalURL = + baseURL + + Object.keys(params) + .map((key) => `${key}=${encodeURIComponent(params[key])}`) + .join("&"); + + try { + let body = await Spicetify.CosmosAsync.get(finalURL, null, headers); + if (body?.message?.body?.language_list) { + languageMap = {}; + body.message.body.language_list.forEach((item) => { + const lang = item.language; + if (lang.language_name) { + const name = lang.language_name.charAt(0).toUpperCase() + lang.language_name.slice(1); + if (lang.language_iso_code_1) languageMap[lang.language_iso_code_1] = name; + if (lang.language_iso_code_3) languageMap[lang.language_iso_code_3] = name; + } + }); + localStorage.setItem("lyrics-plus:musixmatch-languages", JSON.stringify({ ...languageMap, __version: 1 })); + return languageMap; + } + } catch (e) { + console.error("Failed to fetch languages", e); + } + return {}; + } + + return { findLyrics, getKaraoke, getSynced, getUnsynced, getTranslation, getLanguages }; })();