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