Translations for Akkoma (#934)
* Translations for Akkoma * simplify akkoma translation code --------- Co-authored-by: sk <sk22@mailbox.org>
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
package org.joinmastodon.android.api.requests.statuses;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||||
|
import org.joinmastodon.android.model.AkkomaTranslation;
|
||||||
|
|
||||||
|
public class AkkomaTranslateStatus extends MastodonAPIRequest<AkkomaTranslation>{
|
||||||
|
public AkkomaTranslateStatus(String id, String lang){
|
||||||
|
super(HttpMethod.GET, "/statuses/"+id+"/translations/"+lang.toUpperCase(), AkkomaTranslation.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -19,12 +19,15 @@ import android.widget.Toolbar;
|
|||||||
import org.joinmastodon.android.E;
|
import org.joinmastodon.android.E;
|
||||||
import org.joinmastodon.android.GlobalUserPreferences;
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||||
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
|
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
|
||||||
import org.joinmastodon.android.api.requests.polls.SubmitPollVote;
|
import org.joinmastodon.android.api.requests.polls.SubmitPollVote;
|
||||||
|
import org.joinmastodon.android.api.requests.statuses.AkkomaTranslateStatus;
|
||||||
import org.joinmastodon.android.api.requests.statuses.TranslateStatus;
|
import org.joinmastodon.android.api.requests.statuses.TranslateStatus;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.events.PollUpdatedEvent;
|
import org.joinmastodon.android.events.PollUpdatedEvent;
|
||||||
import org.joinmastodon.android.model.Account;
|
import org.joinmastodon.android.model.Account;
|
||||||
|
import org.joinmastodon.android.model.AkkomaTranslation;
|
||||||
import org.joinmastodon.android.model.DisplayItemsParent;
|
import org.joinmastodon.android.model.DisplayItemsParent;
|
||||||
import org.joinmastodon.android.model.Poll;
|
import org.joinmastodon.android.model.Poll;
|
||||||
import org.joinmastodon.android.model.Relationship;
|
import org.joinmastodon.android.model.Relationship;
|
||||||
@@ -60,6 +63,7 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -855,38 +859,52 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
status.translationState=Status.TranslationState.SHOWN;
|
status.translationState=Status.TranslationState.SHOWN;
|
||||||
}else{
|
}else{
|
||||||
status.translationState=Status.TranslationState.LOADING;
|
status.translationState=Status.TranslationState.LOADING;
|
||||||
new TranslateStatus(status.getContentStatus().id, Locale.getDefault().getLanguage())
|
Consumer<Translation> successCallback=(result)->{
|
||||||
.setCallback(new Callback<>(){
|
status.translation=result;
|
||||||
|
status.translationState=Status.TranslationState.SHOWN;
|
||||||
|
updateTranslation(itemID);
|
||||||
|
};
|
||||||
|
MastodonAPIRequest<?> req=isInstanceAkkoma()
|
||||||
|
? new AkkomaTranslateStatus(status.getContentStatus().id, Locale.getDefault().getLanguage()).setCallback(new Callback<>(){
|
||||||
|
@Override
|
||||||
|
public void onSuccess(AkkomaTranslation result){
|
||||||
|
if(getActivity()!=null) successCallback.accept(result.toTranslation());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onError(ErrorResponse error){
|
||||||
|
if(getActivity()!=null) translationCallbackError(status, itemID);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
: new TranslateStatus(status.getContentStatus().id, Locale.getDefault().getLanguage()).setCallback(new Callback<>(){
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Translation result){
|
public void onSuccess(Translation result){
|
||||||
if(getActivity()==null)
|
if(getActivity()!=null) successCallback.accept(result);
|
||||||
return;
|
|
||||||
status.translation=result;
|
|
||||||
status.translationState=Status.TranslationState.SHOWN;
|
|
||||||
updateTranslation(itemID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(ErrorResponse error){
|
public void onError(ErrorResponse error){
|
||||||
if(getActivity()==null)
|
if(getActivity()!=null) translationCallbackError(status, itemID);
|
||||||
return;
|
|
||||||
status.translationState=Status.TranslationState.HIDDEN;
|
|
||||||
updateTranslation(itemID);
|
|
||||||
new M3AlertDialogBuilder(getActivity())
|
|
||||||
.setTitle(R.string.error)
|
|
||||||
.setMessage(R.string.translation_failed)
|
|
||||||
.setPositiveButton(R.string.ok, null)
|
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.setTimeout(60000) // 1 minute
|
|
||||||
.exec(accountID);
|
// 1 minute
|
||||||
|
req.setTimeout(60000).exec(accountID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateTranslation(itemID);
|
updateTranslation(itemID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void translationCallbackError(Status status, String itemID) {
|
||||||
|
status.translationState=Status.TranslationState.HIDDEN;
|
||||||
|
updateTranslation(itemID);
|
||||||
|
new M3AlertDialogBuilder(getActivity())
|
||||||
|
.setTitle(R.string.error)
|
||||||
|
.setMessage(R.string.translation_failed)
|
||||||
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void updateTranslation(String itemID) {
|
private void updateTranslation(String itemID) {
|
||||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
||||||
if(text!=null){
|
if(text!=null){
|
||||||
@@ -896,6 +914,9 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
notifyItemChanged(itemID, TextStatusDisplayItem.class);
|
notifyItemChanged(itemID, TextStatusDisplayItem.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isInstanceAkkoma())
|
||||||
|
return;
|
||||||
|
|
||||||
SpoilerStatusDisplayItem.Holder spoiler=findHolderOfType(itemID, SpoilerStatusDisplayItem.Holder.class);
|
SpoilerStatusDisplayItem.Holder spoiler=findHolderOfType(itemID, SpoilerStatusDisplayItem.Holder.class);
|
||||||
if(spoiler!=null){
|
if(spoiler!=null){
|
||||||
spoiler.rebind();
|
spoiler.rebind();
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.joinmastodon.android.model;
|
||||||
|
|
||||||
|
public class AkkomaTranslation extends BaseModel{
|
||||||
|
public String text;
|
||||||
|
public String detectedLanguage;
|
||||||
|
|
||||||
|
public Translation toTranslation() {
|
||||||
|
Translation translation=new Translation();
|
||||||
|
translation.content=text;
|
||||||
|
translation.detectedSourceLanguage=detectedLanguage;
|
||||||
|
translation.provider="Akkoma";
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -161,11 +161,15 @@ public class Instance extends BaseModel{
|
|||||||
case BUBBLE_TIMELINE -> pleromaFeatures
|
case BUBBLE_TIMELINE -> pleromaFeatures
|
||||||
.map(f -> f.contains("bubble_timeline"))
|
.map(f -> f.contains("bubble_timeline"))
|
||||||
.orElse(false);
|
.orElse(false);
|
||||||
|
case MACHINE_TRANSLATION -> pleromaFeatures
|
||||||
|
.map(f -> f.contains("akkoma:machine_translation"))
|
||||||
|
.orElse(false);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Feature {
|
public enum Feature {
|
||||||
BUBBLE_TIMELINE
|
BUBBLE_TIMELINE,
|
||||||
|
MACHINE_TRANSLATION
|
||||||
}
|
}
|
||||||
|
|
||||||
@Parcel
|
@Parcel
|
||||||
|
|||||||
@@ -220,10 +220,11 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
|||||||
|
|
||||||
public static final Pattern BOTTOM_TEXT_PATTERN = Pattern.compile("(?:[\uD83E\uDEC2\uD83D\uDC96✨\uD83E\uDD7A,]+|❤️)(?:\uD83D\uDC49\uD83D\uDC48(?:[\uD83E\uDEC2\uD83D\uDC96✨\uD83E\uDD7A,]+|❤️))*\uD83D\uDC49\uD83D\uDC48");
|
public static final Pattern BOTTOM_TEXT_PATTERN = Pattern.compile("(?:[\uD83E\uDEC2\uD83D\uDC96✨\uD83E\uDD7A,]+|❤️)(?:\uD83D\uDC49\uD83D\uDC48(?:[\uD83E\uDEC2\uD83D\uDC96✨\uD83E\uDD7A,]+|❤️))*\uD83D\uDC49\uD83D\uDC48");
|
||||||
public boolean isEligibleForTranslation(AccountSession session){
|
public boolean isEligibleForTranslation(AccountSession session){
|
||||||
Instance instanceInfo = AccountSessionManager.getInstance().getInstanceInfo(session.domain);
|
Instance instanceInfo=AccountSessionManager.getInstance().getInstanceInfo(session.domain);
|
||||||
boolean translateEnabled = instanceInfo != null &&
|
boolean translateEnabled=instanceInfo!=null && (
|
||||||
instanceInfo.v2 != null && instanceInfo.v2.configuration.translation != null &&
|
(instanceInfo.v2!=null && instanceInfo.v2.configuration.translation!=null && instanceInfo.v2.configuration.translation.enabled) ||
|
||||||
instanceInfo.v2.configuration.translation.enabled;
|
(instanceInfo.isAkkoma() && instanceInfo.hasFeature(Instance.Feature.MACHINE_TRANSLATION))
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Pair<String, List<String>> decoded=BOTTOM_TEXT_PATTERN.matcher(getStrippedText()).find()
|
Pair<String, List<String>> decoded=BOTTOM_TEXT_PATTERN.matcher(getStrippedText()).find()
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
|||||||
public void updateTranslation(boolean updateText){
|
public void updateTranslation(boolean updateText){
|
||||||
if(item.status==null)
|
if(item.status==null)
|
||||||
return;
|
return;
|
||||||
boolean translateEnabled=!item.disableTranslate && item.status.isEligibleForTranslation(item.parentFragment.getSession());
|
boolean translateEnabled=!item.disableTranslate && item.status.isEligibleForTranslation(item.parentFragment.getSession()) && !item.isForQuote;
|
||||||
if(translationFooter==null && translateEnabled){
|
if(translationFooter==null && translateEnabled){
|
||||||
translationFooter=translationFooterStub.inflate();
|
translationFooter=translationFooterStub.inflate();
|
||||||
translationInfo=findViewById(R.id.translation_info_text);
|
translationInfo=findViewById(R.id.translation_info_text);
|
||||||
|
|||||||
Reference in New Issue
Block a user