Allows setting max lines and max line length, enables DeepL, adds user setup bridge

This commit is contained in:
Guillaume Tâche
2024-08-20 21:31:10 +02:00
parent 273a6e996f
commit 44c317f207
49 changed files with 752 additions and 298 deletions

View File

@@ -1,38 +0,0 @@
package com.github.gtache.autosubtitle.deepl;
import com.github.gtache.autosubtitle.Language;
import com.github.gtache.autosubtitle.Translator;
import com.github.gtache.autosubtitle.subtitle.Subtitle;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import javax.inject.Inject;
/**
* DeepL implementation of {@link Translator}
*/
public class DeepLTranslator implements Translator<Subtitle> {
@Inject
DeepLTranslator() {
}
@Override
public Language getLanguage(final String text) {
return null;
}
@Override
public String translate(final String text, final Language to) {
return "";
}
@Override
public Subtitle translate(final Subtitle subtitle, final Language to) {
return null;
}
@Override
public SubtitleCollection<Subtitle> translate(final SubtitleCollection<?> collection, final Language to) {
return null;
}
}

View File

@@ -1,16 +1,28 @@
package com.github.gtache.autosubtitle.modules.deepl;
import com.github.gtache.autosubtitle.Translator;
import com.github.gtache.autosubtitle.deepl.DeepLTranslator;
import com.github.gtache.autosubtitle.modules.setup.deepl.DeepLSetupModule;
import com.github.gtache.autosubtitle.translation.Translator;
import com.github.gtache.autosubtitle.translation.deepl.DeepLTranslator;
import com.github.pemistahl.lingua.api.LanguageDetector;
import com.github.pemistahl.lingua.api.LanguageDetectorBuilder;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import javax.inject.Singleton;
/**
* Dagger module for DeepL
*/
@Module
public interface DeepLModule {
@Module(includes = DeepLSetupModule.class)
public abstract class DeepLModule {
@Binds
Translator bindsTranslator(final DeepLTranslator translator);
abstract Translator bindsTranslator(final DeepLTranslator translator);
@Provides
@Singleton
static LanguageDetector providesLanguageDetector() {
return LanguageDetectorBuilder.fromAllSpokenLanguages().build();
}
}

View File

@@ -0,0 +1,21 @@
package com.github.gtache.autosubtitle.modules.setup.deepl;
import com.github.gtache.autosubtitle.modules.setup.impl.TranslatorSetup;
import com.github.gtache.autosubtitle.setup.SetupManager;
import com.github.gtache.autosubtitle.setup.deepl.DeepLSetupManager;
import dagger.Binds;
import dagger.Module;
/**
* Dagger module for DeepL setup
*/
@Module
public abstract class DeepLSetupModule {
private DeepLSetupModule() {
}
@Binds
@TranslatorSetup
abstract SetupManager bindsSetupManager(final DeepLSetupManager setupManager);
}

View File

@@ -0,0 +1,70 @@
package com.github.gtache.autosubtitle.setup.deepl;
import com.github.gtache.autosubtitle.setup.SetupException;
import com.github.gtache.autosubtitle.setup.SetupManager;
import com.github.gtache.autosubtitle.setup.SetupStatus;
import com.github.gtache.autosubtitle.setup.SetupUserBridge;
import com.github.gtache.autosubtitle.setup.impl.AbstractSetupManager;
import javax.inject.Inject;
import java.util.Objects;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
/**
* {@link SetupManager} for DeepL
*/
public class DeepLSetupManager extends AbstractSetupManager {
private static final String DEEPL_API_KEY = "deepl.api.key";
private final SetupUserBridge userBridge;
private final Preferences preferences;
@Inject
DeepLSetupManager(final SetupUserBridge userBridge, final Preferences preferences) {
this.userBridge = Objects.requireNonNull(userBridge);
this.preferences = Objects.requireNonNull(preferences);
}
@Override
protected SetupStatus getStatus() throws SetupException {
final var key = preferences.get(DEEPL_API_KEY, null);
return key == null ? SetupStatus.NOT_INSTALLED : SetupStatus.BUNDLE_INSTALLED;
}
@Override
public String name() {
return "DeepL";
}
@Override
public void install() throws SetupException {
final var key = userBridge.askForUserInput("Please enter your DeepL API key - https://www.deepl.com/pro-api? (It will be stored unencrypted)");
if (key == null) {
throw new SetupException("API key cannot be null");
} else {
preferences.put(DEEPL_API_KEY, key);
try {
preferences.flush();
} catch (final BackingStoreException e) {
throw new SetupException(e);
}
}
}
@Override
public void uninstall() throws SetupException {
preferences.remove(DEEPL_API_KEY);
try {
preferences.flush();
} catch (final BackingStoreException e) {
throw new SetupException(e);
}
}
@Override
public void update() throws SetupException {
//No need to update
}
}

View File

@@ -0,0 +1,78 @@
package com.github.gtache.autosubtitle.translation.deepl;
import com.deepl.api.DeepLException;
import com.github.gtache.autosubtitle.Language;
import com.github.gtache.autosubtitle.subtitle.Subtitle;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
import com.github.gtache.autosubtitle.translation.TranslationException;
import com.github.gtache.autosubtitle.translation.Translator;
import com.github.pemistahl.lingua.api.LanguageDetector;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Objects;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;
/**
* DeepL implementation of {@link Translator}
*/
public class DeepLTranslator implements Translator<Subtitle> {
private final Preferences preferences;
private final LanguageDetector languageDetector;
private com.deepl.api.Translator translator;
@Inject
DeepLTranslator(final Preferences preferences, final LanguageDetector languageDetector) {
this.preferences = Objects.requireNonNull(preferences);
this.languageDetector = Objects.requireNonNull(languageDetector);
}
@Override
public Language getLanguage(final String text) {
return Language.getLanguage(languageDetector.detectLanguageOf(text).getIsoCode639_1().toString());
}
@Override
public String translate(final String text, final Language from, final Language to) throws TranslationException {
final var currentTranslator = getTranslator();
if (currentTranslator == null) {
throw new TranslationException("DeepL API key is not set");
}
try {
final var translated = currentTranslator.translateText(text, from.iso2(), to.iso2());
return translated.getText();
} catch (final DeepLException e) {
throw new TranslationException(e);
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
throw new TranslationException(e);
}
}
@Override
public Subtitle translate(final Subtitle subtitle, final Language from, final Language to) throws TranslationException {
final var translated = translate(subtitle.content(), from, to);
return new SubtitleImpl(translated, subtitle.start(), subtitle.end(), subtitle.font(), subtitle.bounds());
}
@Override
public SubtitleCollection<Subtitle> translate(final SubtitleCollection<?> collection, final Language from, final Language to) throws TranslationException {
final var subtitles = new ArrayList<Subtitle>(collection.subtitles().size());
for (final var subtitle : collection.subtitles()) {
subtitles.add(translate(subtitle, from, to));
}
final var text = subtitles.stream().map(Subtitle::content).collect(Collectors.joining(""));
return new SubtitleCollectionImpl<>(text, subtitles, to);
}
private com.deepl.api.Translator getTranslator() {
if (translator == null && preferences.get("deepl.api.key", null) != null) {
translator = new com.deepl.api.Translator(preferences.get("deepl.api.key", null));
}
return translator;
}
}

View File

@@ -3,6 +3,10 @@
*/
module com.github.gtache.autosubtitle.deepl {
requires transitive com.github.gtache.autosubtitle.core;
exports com.github.gtache.autosubtitle.deepl;
requires transitive deepl.java;
requires transitive com.github.pemistahl.lingua;
requires transitive java.prefs;
exports com.github.gtache.autosubtitle.modules.deepl;
exports com.github.gtache.autosubtitle.translation.deepl;
exports com.github.gtache.autosubtitle.setup.deepl;
}