mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-11 20:07:11 +02:00
fix(lyrics): honor caller language when Lyricsfile YAML omits it
parseLyricsfile discarded the caller's language argument, so a Lyricsfile YAML parsed from an embedded tag or plugin response with no metadata.language was labeled "xxx" even when ParseLyrics was given a language. The SRT and TTML parsers already use the caller language as their default; fall back to it here too, preferring the document's own metadata.language when present. Also reword a misleading TTML comment: isTTMLDocument still runs an XML decode (it stops at the first element), so the skip avoids the full TTML parse, not the XML decoder entirely.
This commit is contained in:
parent
225ceaad94
commit
e8a404ac76
3 changed files with 28 additions and 3 deletions
|
|
@ -20,7 +20,7 @@ import (
|
|||
// overlapping lines are attributed to synthetic voice agents via lowest-free
|
||||
// voice ID assignment so the OpenSubsonic v2 enhanced response can split
|
||||
// parallel vocals.
|
||||
func parseLyricsfile(_ string, contents []byte) (LyricList, error) {
|
||||
func parseLyricsfile(lang string, contents []byte) (LyricList, error) {
|
||||
var doc lyricsfileDocument
|
||||
dec := yaml.NewDecoder(bytes.NewReader(contents))
|
||||
dec.KnownFields(false)
|
||||
|
|
@ -32,10 +32,16 @@ func parseLyricsfile(_ string, contents []byte) (LyricList, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// Fall back to the caller's language when the document omits its own, matching
|
||||
// the SRT/TTML parsers; normalizeLyricLang yields "xxx" only if both are empty.
|
||||
docLang := doc.Metadata.Language
|
||||
if strings.TrimSpace(docLang) == "" {
|
||||
docLang = lang
|
||||
}
|
||||
lyrics := Lyrics{
|
||||
DisplayArtist: str.SanitizeText(doc.Metadata.Artist),
|
||||
DisplayTitle: str.SanitizeText(doc.Metadata.Title),
|
||||
Lang: normalizeLyricLang(doc.Metadata.Language),
|
||||
Lang: normalizeLyricLang(docLang),
|
||||
Kind: LyricKindMain,
|
||||
}
|
||||
if doc.Metadata.OffsetMs != 0 {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,24 @@ lines:
|
|||
Expect(l.Line[1].Cue).To(BeNil())
|
||||
})
|
||||
|
||||
DescribeTable("resolves the lyric language",
|
||||
func(metaLanguage, callerLang, want string) {
|
||||
input := "version: '1.0'\nmetadata:\n title: 'T'\n"
|
||||
if metaLanguage != "" {
|
||||
input += " language: '" + metaLanguage + "'\n"
|
||||
}
|
||||
input += "lines:\n - text: \"line\"\n start_ms: 0\n"
|
||||
|
||||
lyrics, err := parseLyricsfile(callerLang, []byte(input))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(lyrics).To(HaveLen(1))
|
||||
Expect(lyrics[0].Lang).To(Equal(want))
|
||||
},
|
||||
Entry("prefers the document's own language", "eng", "deu", "eng"),
|
||||
Entry("falls back to the caller language when metadata omits it", "", "deu", "deu"),
|
||||
Entry("uses xxx when neither is provided", "", "", "xxx"),
|
||||
)
|
||||
|
||||
It("parses plain-only Lyricsfile lyrics as unsynced lines", func() {
|
||||
input := `version: '1.0'
|
||||
metadata:
|
||||
|
|
|
|||
|
|
@ -118,7 +118,8 @@ func isTTMLDocument(contents []byte) bool {
|
|||
func parseTTMLWithDefaultLang(defaultLang string, contents []byte) (LyricList, error) {
|
||||
contents = xmlEncodingRegex.ReplaceAll(contents, []byte(`<?xml$1encoding="UTF-8"$2?>`))
|
||||
|
||||
// Skip non-TTML content so sniffing doesn't run the XML decoder on plain text.
|
||||
// Skip non-TTML content so sniffing doesn't run the full TTML parse on plain
|
||||
// text — isTTMLDocument does a cheap decode that stops at the first element.
|
||||
// Checked after the encoding fixup so UTF-16-declared documents are recognized.
|
||||
if !isTTMLDocument(contents) {
|
||||
return nil, nil
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue