@@ -744,6 +744,7 @@ def scrape(cls, html: str) -> str | None:
744
744
class Translator (RequestHandler ):
745
745
TRANSLATE_URL = "https://api.cognitive.microsofttranslator.com/translate"
746
746
LINE_PARTS_RE = re .compile (r"^(\[\d\d:\d\d.\d\d\]|) *(.*)$" )
747
+ remove_translations = partial (re .compile (r" / [^\n]+" ).sub , "" )
747
748
748
749
_log : Logger
749
750
api_key : str
@@ -811,23 +812,45 @@ def append_translations(self, lines: Iterable[str]) -> list[str]:
811
812
# only add the space between non-empty timestamps and texts
812
813
return [" " .join (filter (None , p )) for p in zip (timestamps , texts )]
813
814
814
- def translate (self , lyrics : str ) -> str :
815
+ def translate (self , new_lyrics : str , old_lyrics : str ) -> str :
815
816
"""Translate the given lyrics to the target language.
816
817
818
+ Check old lyrics for existing translations and return them if their
819
+ original text matches the new lyrics. This is to avoid translating
820
+ the same lyrics multiple times.
821
+
817
822
If the lyrics are already in the target language or not in any of
818
823
of the source languages (if configured), they are returned as is.
819
824
820
825
The footer with the source URL is preserved, if present.
821
826
"""
822
- lyrics_language = langdetect . detect ( lyrics ). upper ()
823
- if lyrics_language == self . to_language or (
824
- self . from_languages and lyrics_language not in self .from_languages
827
+ if (
828
+ " / " in old_lyrics
829
+ and self .remove_translations ( old_lyrics ) == new_lyrics
825
830
):
826
- return lyrics
831
+ self .info ("🔵 Translations already exist" )
832
+ return old_lyrics
833
+
834
+ lyrics_language = langdetect .detect (new_lyrics ).upper ()
835
+ if lyrics_language == self .to_language :
836
+ self .info (
837
+ "🔵 Lyrics are already in the target language {}" ,
838
+ self .to_language ,
839
+ )
840
+ return new_lyrics
841
+
842
+ if self .from_languages and lyrics_language not in self .from_languages :
843
+ self .info (
844
+ "🔵 Configuration {} does not permit translating from {}" ,
845
+ self .from_languages ,
846
+ lyrics_language ,
847
+ )
848
+ return new_lyrics
827
849
828
- lyrics , * url = lyrics .split ("\n \n Source: " )
850
+ lyrics , * url = new_lyrics .split ("\n \n Source: " )
829
851
with self .handle_request ():
830
852
translated_lines = self .append_translations (lyrics .splitlines ())
853
+ self .info ("🟢 Translated lyrics to {}" , self .to_language )
831
854
return "\n \n Source: " .join (["\n " .join (translated_lines ), * url ])
832
855
833
856
@@ -1065,12 +1088,7 @@ def add_item_lyrics(self, item: Item, write: bool) -> None:
1065
1088
if lyrics := self .find_lyrics (item ):
1066
1089
self .info ("🟢 Found lyrics: {0}" , item )
1067
1090
if translator := self .translator :
1068
- initial_lyrics = lyrics
1069
- if (lyrics := translator .translate (lyrics )) != initial_lyrics :
1070
- self .info (
1071
- "🟢 Added translation to {}" ,
1072
- self .config ["translate_to" ].get ().upper (),
1073
- )
1091
+ lyrics = translator .translate (lyrics , item .lyrics )
1074
1092
else :
1075
1093
self .info ("🔴 Lyrics not found: {}" , item )
1076
1094
lyrics = self .config ["fallback" ].get ()
0 commit comments