@@ -86,7 +86,16 @@ const OptionsMenu = react.memo(({ options, onSelect, selected, defaultValue, bol
8686 ) ;
8787} ) ;
8888
89- const TranslationMenu = react . memo ( ( { friendlyLanguage, hasTranslation } ) => {
89+ function getMusixmatchTranslationPrefix ( ) {
90+ if ( typeof window !== "undefined" && typeof window . __lyricsPlusMusixmatchTranslationPrefix === "string" ) {
91+ return window . __lyricsPlusMusixmatchTranslationPrefix ;
92+ }
93+
94+ return "musixmatchTranslation:" ;
95+ }
96+
97+ const TranslationMenu = react . memo ( ( { friendlyLanguage, hasTranslation, musixmatchLanguages, musixmatchSelectedLanguage } ) => {
98+ const musixmatchTranslationPrefix = getMusixmatchTranslationPrefix ( ) ;
9099 const items = useMemo ( ( ) => {
91100 let sourceOptions = {
92101 none : "None" ,
@@ -109,16 +118,20 @@ const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation }) => {
109118 none : "None" ,
110119 } ;
111120
112- if ( hasTranslation . musixmatch ) {
113- const selectedLanguage = CONFIG . visual [ "musixmatch-translation-language" ] ;
114- if ( selectedLanguage === "none" ) return ;
115- const languageName = new Intl . DisplayNames ( [ selectedLanguage ] , {
116- type : "language" ,
117- } ) . of ( selectedLanguage ) ;
118- sourceOptions = {
119- ...sourceOptions ,
120- musixmatchTranslation : `${ languageName } (Musixmatch)` ,
121- } ;
121+ const musixmatchDisplay = new Intl . DisplayNames ( [ "en" ] , { type : "language" } ) ;
122+ const availableMusixmatchLanguages = Array . isArray ( musixmatchLanguages ) ? [ ...new Set ( musixmatchLanguages . filter ( Boolean ) ) ] : [ ] ;
123+ const activeMusixmatchLanguage = musixmatchSelectedLanguage && musixmatchSelectedLanguage !== "none" ? musixmatchSelectedLanguage : null ;
124+ if ( hasTranslation . musixmatch && activeMusixmatchLanguage ) {
125+ availableMusixmatchLanguages . push ( activeMusixmatchLanguage ) ;
126+ }
127+
128+ if ( availableMusixmatchLanguages . length ) {
129+ const musixmatchOptions = availableMusixmatchLanguages . reduce ( ( acc , code ) => {
130+ const label = musixmatchDisplay . of ( code ) || code . toUpperCase ( ) ;
131+ acc [ `${ musixmatchTranslationPrefix } ${ code } ` ] = `${ label } (Musixmatch)` ;
132+ return acc ;
133+ } , { } ) ;
134+ sourceOptions = { ...sourceOptions , ...musixmatchOptions } ;
122135 }
123136
124137 if ( hasTranslation . netease ) {
@@ -154,7 +167,7 @@ const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation }) => {
154167 }
155168 }
156169
157- return [
170+ const configItems = [
158171 {
159172 desc : "Translation Provider" ,
160173 key : "translate:translated-lyrics-source" ,
@@ -198,7 +211,16 @@ const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation }) => {
198211 when : ( ) => friendlyLanguage ,
199212 } ,
200213 ] ;
201- } , [ friendlyLanguage ] ) ;
214+
215+ return configItems ;
216+ } , [
217+ friendlyLanguage ,
218+ hasTranslation . musixmatch ,
219+ hasTranslation . netease ,
220+ Array . isArray ( musixmatchLanguages ) ? musixmatchLanguages . join ( "," ) : "" ,
221+ musixmatchSelectedLanguage || "" ,
222+ musixmatchTranslationPrefix ,
223+ ] ) ;
202224
203225 useEffect ( ( ) => {
204226 // Currently opened Context Menu does not receive prop changes
@@ -210,7 +232,7 @@ const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation }) => {
210232 } ,
211233 } ) ;
212234 document . dispatchEvent ( event ) ;
213- } , [ friendlyLanguage ] ) ;
235+ } , [ friendlyLanguage , items ] ) ;
214236
215237 return react . createElement (
216238 Spicetify . ReactComponent . TooltipWrapper ,
@@ -233,14 +255,27 @@ const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation }) => {
233255 type : "translation-menu" ,
234256 items,
235257 onChange : ( name , value ) => {
236- if ( name === "translate:translated-lyrics-source" && friendlyLanguage ) {
237- CONFIG . visual . translate = false ;
238- localStorage . setItem ( `${ APP_NAME } :visual:translate` , false ) ;
239- }
240258 if ( name === "translate" ) {
241259 CONFIG . visual [ "translate:translated-lyrics-source" ] = "none" ;
242260 localStorage . setItem ( `${ APP_NAME } :visual:translate:translated-lyrics-source` , "none" ) ;
243261 }
262+ if ( name === "translate:translated-lyrics-source" ) {
263+ const hasTranslationProvider = typeof value === "string" && value !== "none" ;
264+ if ( hasTranslationProvider && CONFIG . visual . translate ) {
265+ CONFIG . visual . translate = false ;
266+ localStorage . setItem ( `${ APP_NAME } :visual:translate` , "false" ) ;
267+ }
268+
269+ let nextMusixmatchLanguage = "none" ;
270+ if ( typeof value === "string" && value . startsWith ( musixmatchTranslationPrefix ) ) {
271+ nextMusixmatchLanguage = value . slice ( musixmatchTranslationPrefix . length ) || "none" ;
272+ }
273+
274+ if ( CONFIG . visual [ "musixmatch-translation-language" ] !== nextMusixmatchLanguage ) {
275+ CONFIG . visual [ "musixmatch-translation-language" ] = nextMusixmatchLanguage ;
276+ localStorage . setItem ( `${ APP_NAME } :visual:musixmatch-translation-language` , nextMusixmatchLanguage ) ;
277+ }
278+ }
244279
245280 CONFIG . visual [ name ] = value ;
246281 localStorage . setItem ( `${ APP_NAME } :visual:${ name } ` , value ) ;
0 commit comments