Skip to content

Commit 9c9ffbe

Browse files
committed
feat(lyrics-plus): Allow to change display of lyrics translation
1 parent 7a53725 commit 9c9ffbe

File tree

3 files changed

+159
-55
lines changed

3 files changed

+159
-55
lines changed

Diff for: CustomApps/lyrics-plus/OptionsMenu.js

+15
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation }) => {
9292
none: "None",
9393
};
9494

95+
const savedTranslationDisplay = localStorage.getItem(`${APP_NAME}:visual:translate:display-mode`) || "replace";
96+
CONFIG.visual["translate:display-mode"] = savedTranslationDisplay;
97+
const translationDisplayOptions = {
98+
replace: "Replace",
99+
below: "Below",
100+
};
101+
95102
const languageOptions = {
96103
off: "Off",
97104
"zh-hans": "Chinese (Simplified)",
@@ -151,6 +158,14 @@ const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation }) => {
151158
options: sourceOptions,
152159
renderInline: true,
153160
},
161+
{
162+
desc: "Display",
163+
key: "translate:display-mode",
164+
type: ConfigSelection,
165+
options: translationDisplayOptions,
166+
defaultValue: savedTranslationDisplay,
167+
renderInline: true,
168+
},
154169
{
155170
desc: "Language Override",
156171
key: "translate:detect-language-override",

Diff for: CustomApps/lyrics-plus/Pages.js

+143-55
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ const SyncedLyricsPage = react.memo(({ lyrics = [], provider, copyright, isKara
140140
},
141141
key: lyricsId,
142142
},
143-
activeLines.map(({ text, lineNumber, startTime }, i) => {
143+
activeLines.map(({ text, lineNumber, startTime, originalText }, i) => {
144144
if (i === 1 && activeLineIndex === 1) {
145145
return react.createElement(IdlingIndicator, {
146146
progress: position / activeLines[2].startTime,
@@ -169,33 +169,68 @@ const SyncedLyricsPage = react.memo(({ lyrics = [], provider, copyright, isKara
169169
if (paddingLine) {
170170
className += " lyrics-lyricsContainer-LyricsLine-paddingLine";
171171
}
172+
const showTranslatedBelow = CONFIG.visual["translate:display-mode"] === "below";
173+
// If we have original text and we are showing translated below, we should show the original text
174+
// Otherwise we should show the translated text
175+
const lineText = originalText && showTranslatedBelow ? originalText : text;
172176

173177
return react.createElement(
174-
"p",
178+
"div",
175179
{
176-
className,
177-
style: {
178-
cursor: "pointer",
179-
"--position-index": animationIndex,
180-
"--animation-index": (animationIndex < 0 ? 0 : animationIndex) + 1,
181-
"--blur-index": Math.abs(animationIndex),
182-
},
183-
key: lineNumber,
184-
dir: "auto",
185-
ref,
186-
onClick: (event) => {
187-
if (startTime) {
188-
Spicetify.Player.seek(startTime);
189-
}
190-
},
191-
onContextMenu: (event) => {
192-
event.preventDefault();
193-
Spicetify.Platform.ClipboardAPI.copy(rawLyrics)
194-
.then(() => Spicetify.showNotification("Lyrics copied to clipboard"))
195-
.catch(() => Spicetify.showNotification("Failed to copy lyrics to clipboard"));
196-
},
180+
className: "lyrics-lyricsContainer-LyricsLineContainer",
181+
key: i,
197182
},
198-
!isKara ? text : react.createElement(KaraokeLine, { text, startTime, position, isActive })
183+
react.createElement(
184+
"p",
185+
{
186+
className,
187+
style: {
188+
cursor: "pointer",
189+
"--position-index": animationIndex,
190+
"--animation-index": (animationIndex < 0 ? 0 : animationIndex) + 1,
191+
"--blur-index": Math.abs(animationIndex),
192+
},
193+
key: lineNumber,
194+
dir: "auto",
195+
ref,
196+
onClick: (event) => {
197+
if (startTime) {
198+
Spicetify.Player.seek(startTime);
199+
}
200+
},
201+
onContextMenu: (event) => {
202+
event.preventDefault();
203+
Spicetify.Platform.ClipboardAPI.copy(rawLyrics)
204+
.then(() => Spicetify.showNotification("Lyrics copied to clipboard"))
205+
.catch(() => Spicetify.showNotification("Failed to copy lyrics to clipboard"));
206+
},
207+
},
208+
!isKara ? lineText : react.createElement(KaraokeLine, { text, startTime, position, isActive })
209+
),
210+
showTranslatedBelow &&
211+
originalText &&
212+
(originalText !== text) &&
213+
react.createElement(
214+
"p",
215+
{
216+
className,
217+
style: {
218+
opacity: 0.5,
219+
cursor: "pointer",
220+
"--position-index": animationIndex,
221+
"--animation-index": (animationIndex < 0 ? 0 : animationIndex) + 1,
222+
"--blur-index": Math.abs(animationIndex),
223+
},
224+
dir: "auto",
225+
ref,
226+
onClick: (event) => {
227+
if (startTime) {
228+
Spicetify.Player.seek(startTime);
229+
}
230+
},
231+
},
232+
text
233+
)
199234
);
200235
})
201236
),
@@ -412,7 +447,7 @@ const SyncedExpandedLyricsPage = react.memo(({ lyrics, provider, copyright, isKa
412447
react.createElement("p", {
413448
className: "lyrics-lyricsContainer-LyricsUnsyncedPadding",
414449
}),
415-
padded.map(({ text, startTime }, i) => {
450+
padded.map(({ text, startTime, originalText }, i) => {
416451
if (i === 0) {
417452
return react.createElement(IdlingIndicator, {
418453
isActive: activeLineIndex === 0,
@@ -422,28 +457,57 @@ const SyncedExpandedLyricsPage = react.memo(({ lyrics, provider, copyright, isKa
422457
}
423458

424459
const isActive = i === activeLineIndex;
460+
const showTranslatedBelow = CONFIG.visual["translate:display-mode"] === "below";
461+
// If we have original text and we are showing translated below, we should show the original text
462+
// Otherwise we should show the translated text
463+
const lineText = originalText && showTranslatedBelow ? originalText : text;
425464
return react.createElement(
426-
"p",
465+
"div",
427466
{
428-
className: `lyrics-lyricsContainer-LyricsLine${i <= activeLineIndex ? " lyrics-lyricsContainer-LyricsLine-active" : ""}`,
429-
style: {
430-
cursor: "pointer",
431-
},
432-
dir: "auto",
433-
ref: isActive ? activeLineRef : null,
434-
onClick: (event) => {
435-
if (startTime) {
436-
Spicetify.Player.seek(startTime);
437-
}
438-
},
439-
onContextMenu: (event) => {
440-
event.preventDefault();
441-
Spicetify.Platform.ClipboardAPI.copy(rawLyrics)
442-
.then(() => Spicetify.showNotification("Lyrics copied to clipboard"))
443-
.catch(() => Spicetify.showNotification("Failed to copy lyrics to clipboard"));
444-
},
467+
className: "lyrics-lyricsContainer-LyricsLineContainer",
468+
key: i,
445469
},
446-
!isKara ? text : react.createElement(KaraokeLine, { text, startTime, position, isActive })
470+
react.createElement(
471+
"p",
472+
{
473+
className: `lyrics-lyricsContainer-LyricsLine${i <= activeLineIndex ? " lyrics-lyricsContainer-LyricsLine-active" : ""}`,
474+
style: {
475+
cursor: "pointer",
476+
},
477+
dir: "auto",
478+
ref: isActive ? activeLineRef : null,
479+
onClick: (event) => {
480+
if (startTime) {
481+
Spicetify.Player.seek(startTime);
482+
}
483+
},
484+
onContextMenu: (event) => {
485+
event.preventDefault();
486+
Spicetify.Platform.ClipboardAPI.copy(rawLyrics)
487+
.then(() => Spicetify.showNotification("Lyrics copied to clipboard"))
488+
.catch(() => Spicetify.showNotification("Failed to copy lyrics to clipboard"));
489+
},
490+
},
491+
!isKara ? lineText : react.createElement(KaraokeLine, { text, startTime, position, isActive })
492+
),
493+
showTranslatedBelow &&
494+
originalText &&
495+
(originalText !== text) &&
496+
react.createElement(
497+
"p",
498+
{
499+
className: `lyrics-lyricsContainer-LyricsLine${i <= activeLineIndex ? " lyrics-lyricsContainer-LyricsLine-active" : ""}`,
500+
style: { opacity: 0.5, cursor: "pointer" },
501+
dir: "auto",
502+
ref: isActive ? activeLineRef : null,
503+
onClick: (event) => {
504+
if (startTime) {
505+
Spicetify.Player.seek(startTime);
506+
}
507+
},
508+
},
509+
text
510+
)
447511
);
448512
}),
449513
react.createElement("p", {
@@ -468,20 +532,44 @@ const UnsyncedLyricsPage = react.memo(({ lyrics, provider, copyright }) => {
468532
react.createElement("p", {
469533
className: "lyrics-lyricsContainer-LyricsUnsyncedPadding",
470534
}),
471-
lyrics.map(({ text }) => {
535+
lyrics.map(({ text, originalText }, index) => {
536+
const showTranslatedBelow = CONFIG.visual["translate:display-mode"] === "below";
537+
// If we have original text and we are showing translated below, we should show the original text
538+
// Otherwise we should show the translated text
539+
const lineText = originalText && showTranslatedBelow ? originalText : text;
540+
472541
return react.createElement(
473-
"p",
542+
"div",
474543
{
475-
className: "lyrics-lyricsContainer-LyricsLine lyrics-lyricsContainer-LyricsLine-active",
476-
dir: "auto",
477-
onContextMenu: (event) => {
478-
event.preventDefault();
479-
Spicetify.Platform.ClipboardAPI.copy(rawLyrics)
480-
.then(() => Spicetify.showNotification("Lyrics copied to clipboard"))
481-
.catch(() => Spicetify.showNotification("Failed to copy lyrics to clipboard"));
482-
},
544+
className: "lyrics-lyricsContainer-LyricsLineContainer",
545+
key: index,
483546
},
484-
text
547+
react.createElement(
548+
"p",
549+
{
550+
className: "lyrics-lyricsContainer-LyricsLine lyrics-lyricsContainer-LyricsLine-active",
551+
dir: "auto",
552+
onContextMenu: (event) => {
553+
event.preventDefault();
554+
Spicetify.Platform.ClipboardAPI.copy(rawLyrics)
555+
.then(() => Spicetify.showNotification("Lyrics copied to clipboard"))
556+
.catch(() => Spicetify.showNotification("Failed to copy lyrics to clipboard"));
557+
},
558+
},
559+
lineText
560+
),
561+
showTranslatedBelow &&
562+
originalText &&
563+
(originalText !== text) &&
564+
react.createElement(
565+
"p",
566+
{
567+
className: "lyrics-lyricsContainer-LyricsLine lyrics-lyricsContainer-LyricsLine-active",
568+
style: { opacity: 0.5 },
569+
dir: "auto",
570+
},
571+
text
572+
)
485573
);
486574
}),
487575
react.createElement("p", {

Diff for: CustomApps/lyrics-plus/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const CONFIG = {
4141
"lines-after": localStorage.getItem("lyrics-plus:visual:lines-after") || "2",
4242
"font-size": localStorage.getItem("lyrics-plus:visual:font-size") || "32",
4343
"translate:translated-lyrics-source": localStorage.getItem("lyrics-plus:visual:translate:translated-lyrics-source") || "none",
44+
"translate:display-mode": localStorage.getItem("lyrics-plus:visual:translate:display-mode") || "replace",
4445
"translate:detect-language-override": localStorage.getItem("lyrics-plus:visual:translate:detect-language-override") || "off",
4546
"translation-mode:japanese": localStorage.getItem("lyrics-plus:visual:translation-mode:japanese") || "furigana",
4647
"translation-mode:korean": localStorage.getItem("lyrics-plus:visual:translation-mode:korean") || "hangul",

0 commit comments

Comments
 (0)