mirror of https://github.com/M66B/FairEmail.git
Added DeepL html support
This commit is contained in:
parent
74711292fa
commit
229111377a
|
@ -8155,7 +8155,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
|||
protected DeepL.Translation onExecute(Context context, Bundle args) throws Throwable {
|
||||
String text = args.getString("text");
|
||||
String target = args.getString("target");
|
||||
return DeepL.translate(text, target, context);
|
||||
return DeepL.translate(text, false, target, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,7 +28,10 @@ import android.graphics.Paint;
|
|||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -45,6 +48,7 @@ import androidx.preference.PreferenceManager;
|
|||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.jsoup.nodes.Document;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
@ -190,21 +194,41 @@ public class DeepL {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static Translation translate(String text, String target, Context context) throws IOException, JSONException {
|
||||
public static Translation translate(CharSequence text, boolean html, String target, Context context) throws IOException, JSONException {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean formality = prefs.getBoolean("deepl_formal", true);
|
||||
return translate(text, target, formality, context);
|
||||
boolean deepl_formal = prefs.getBoolean("deepl_formal", true);
|
||||
boolean deepl_html = prefs.getBoolean("deepl_html", false);
|
||||
return translate(text, html && deepl_html, target, deepl_formal, context);
|
||||
}
|
||||
|
||||
public static Translation translate(String text, String target, boolean formality, Context context) throws IOException, JSONException {
|
||||
public static Translation translate(CharSequence text, boolean html, String target, boolean formality, Context context) throws IOException, JSONException {
|
||||
if (!ConnectionHelper.getNetworkState(context).isConnected())
|
||||
throw new IllegalArgumentException(context.getString(R.string.title_no_internet));
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean small = prefs.getBoolean("deepl_small", false);
|
||||
String key = prefs.getString("deepl_key", null);
|
||||
|
||||
String input;
|
||||
if (html) {
|
||||
SpannableStringBuilder ssb = new SpannableStringBuilderEx(text);
|
||||
if (small)
|
||||
for (RelativeSizeSpan span : ssb.getSpans(0, ssb.length(), RelativeSizeSpan.class))
|
||||
if (span.getSizeChange() == HtmlHelper.FONT_SMALL)
|
||||
ssb.removeSpan(span);
|
||||
input = HtmlHelper.toHtml(ssb, context);
|
||||
} else
|
||||
input = text.toString();
|
||||
|
||||
// https://www.deepl.com/docs-api/translating-text/request/
|
||||
String request =
|
||||
"text=" + URLEncoder.encode(text, StandardCharsets.UTF_8.name()) +
|
||||
"text=" + URLEncoder.encode(input, StandardCharsets.UTF_8.name()) +
|
||||
"&target_lang=" + URLEncoder.encode(target, StandardCharsets.UTF_8.name());
|
||||
|
||||
// https://www.deepl.com/docs-api/handling-html-(beta)/
|
||||
if (html)
|
||||
request += "&tag_handling=html";
|
||||
|
||||
ensureLanguages(context);
|
||||
for (int i = 0; i < jlanguages.length(); i++) {
|
||||
JSONObject jlanguage = jlanguages.getJSONObject(i);
|
||||
|
@ -216,9 +240,6 @@ public class DeepL {
|
|||
}
|
||||
}
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
String key = prefs.getString("deepl_key", null);
|
||||
|
||||
URL url = new URL(getBaseUri(context) + "translate?auth_key=" + key);
|
||||
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
|
@ -258,7 +279,15 @@ public class DeepL {
|
|||
Translation result = new Translation();
|
||||
result.target_language = target;
|
||||
result.detected_language = jtranslation.getString("detected_source_language");
|
||||
result.translated_text = jtranslation.getString("text");
|
||||
|
||||
String output = jtranslation.getString("text");
|
||||
|
||||
if (html) {
|
||||
Document document = HtmlHelper.sanitizeCompose(context, output, false);
|
||||
result.translated_text = HtmlHelper.fromDocument(context, document, null, null);
|
||||
} else
|
||||
result.translated_text = output;
|
||||
|
||||
return result;
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
|
@ -335,7 +364,7 @@ public class DeepL {
|
|||
public static class Translation {
|
||||
public String detected_language;
|
||||
public String target_language;
|
||||
public String translated_text;
|
||||
public CharSequence translated_text;
|
||||
}
|
||||
|
||||
public static class FragmentDialogDeepL extends FragmentDialogBase {
|
||||
|
@ -348,6 +377,7 @@ public class DeepL {
|
|||
boolean pro = prefs.getBoolean("deepl_pro", false);
|
||||
boolean formal = prefs.getBoolean("deepl_formal", true);
|
||||
boolean small = prefs.getBoolean("deepl_small", false);
|
||||
boolean html = prefs.getBoolean("deepl_html", false);
|
||||
int subscription = prefs.getInt("deepl_subscription", BuildConfig.DEBUG ? 17 : 0);
|
||||
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.dialog_deepl, null);
|
||||
|
@ -357,6 +387,7 @@ public class DeepL {
|
|||
final CheckBox cbFormal = view.findViewById(R.id.cbFormal);
|
||||
final TextView tvFormal = view.findViewById(R.id.tvFormal);
|
||||
final CheckBox cbSmall = view.findViewById(R.id.cbSmall);
|
||||
final CheckBox cbHtml = view.findViewById(R.id.cbHtml);
|
||||
final TextView tvUsage = view.findViewById(R.id.tvUsage);
|
||||
final TextView tvPrivacy = view.findViewById(R.id.tvPrivacy);
|
||||
|
||||
|
@ -398,6 +429,7 @@ public class DeepL {
|
|||
}
|
||||
|
||||
cbSmall.setChecked(small);
|
||||
cbHtml.setChecked(html);
|
||||
|
||||
tvUsage.setVisibility(View.GONE);
|
||||
|
||||
|
@ -460,6 +492,7 @@ public class DeepL {
|
|||
editor.putBoolean("deepl_pro", cbPro.isChecked());
|
||||
editor.putBoolean("deepl_formal", cbFormal.isChecked());
|
||||
editor.putBoolean("deepl_small", cbSmall.isChecked());
|
||||
editor.putBoolean("deepl_html", cbHtml.isChecked());
|
||||
editor.apply();
|
||||
}
|
||||
})
|
||||
|
|
|
@ -2141,12 +2141,14 @@ public class FragmentCompose extends FragmentBase {
|
|||
if (paragraph == null)
|
||||
return;
|
||||
|
||||
etBody.clearComposingText();
|
||||
|
||||
Editable edit = etBody.getText();
|
||||
String text = edit.subSequence(paragraph.first, paragraph.second).toString();
|
||||
CharSequence text = edit.subSequence(paragraph.first, paragraph.second);
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putString("target", target);
|
||||
args.putString("text", text);
|
||||
args.putCharSequence("text", text);
|
||||
|
||||
new SimpleTask<DeepL.Translation>() {
|
||||
private Object highlightSpan;
|
||||
|
@ -2169,8 +2171,8 @@ public class FragmentCompose extends FragmentBase {
|
|||
@Override
|
||||
protected DeepL.Translation onExecute(Context context, Bundle args) throws Throwable {
|
||||
String target = args.getString("target");
|
||||
String text = args.getString("text");
|
||||
return DeepL.translate(text, target, context);
|
||||
CharSequence text = args.getCharSequence("text");
|
||||
return DeepL.translate(text, true, target, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2206,7 +2208,8 @@ public class FragmentCompose extends FragmentBase {
|
|||
at android.text.SpannableStringBuilder.insert(SpannableStringBuilder.java:38)
|
||||
*/
|
||||
int len = 2 + translation.translated_text.length();
|
||||
edit.insert(paragraph.second, "\n\n" + translation.translated_text);
|
||||
edit.insert(paragraph.second, translation.translated_text);
|
||||
edit.insert(paragraph.second, "\n\n");
|
||||
StyleHelper.markAsTranslated(edit, paragraph.second, paragraph.second + len);
|
||||
|
||||
etBody.setSelection(paragraph.second + len);
|
||||
|
|
|
@ -90,6 +90,25 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvFormal" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbHtml"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/title_translate_html"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cbSmall" />
|
||||
|
||||
<eu.faircode.email.FixedTextView
|
||||
android:id="@+id/tvHtml"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:text="@string/title_translate_html_hint"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cbHtml" />
|
||||
|
||||
<eu.faircode.email.FixedTextView
|
||||
android:id="@+id/tvUsage"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -98,7 +117,7 @@
|
|||
android:text="Usage"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cbSmall" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tvHtml" />
|
||||
|
||||
<eu.faircode.email.FixedTextView
|
||||
android:id="@+id/tvPrivacy"
|
||||
|
|
|
@ -1368,6 +1368,8 @@
|
|||
<string name="title_translating">Translating …</string>
|
||||
<string name="title_translate_formal">Use formal form</string>
|
||||
<string name="title_translate_small">Use a small font for the source text</string>
|
||||
<string name="title_translate_html">Preserve formatting</string>
|
||||
<string name="title_translate_html_hint">This will consume more characters</string>
|
||||
<string name="title_translate_usage">Usage: %1$s / %2$s (%3$d %%)</string>
|
||||
<string name="title_translate_tap">Tap the text to be translated</string>
|
||||
<string name="title_edit_plain_text">Edit as plain text</string>
|
||||
|
|
Loading…
Reference in New Issue