mirror of https://github.com/sk22/megalodon.git
Merge remote-tracking branch 'upstream/master' into try-to-merge-upstream
This commit is contained in:
commit
4ee229ea79
|
@ -16,7 +16,7 @@ android {
|
|||
minSdk 23
|
||||
targetSdk 33
|
||||
versionCode 99
|
||||
versionName "2.0.3+fork.99"
|
||||
versionName "2.1.4+fork.99"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
resourceConfigurations += ['ar-rSA', 'ar-rDZ', 'be-rBY', 'bn-rBD', 'bs-rBA', 'ca-rES', 'cs-rCZ', 'da-rDK', 'de-rDE', 'el-rGR', 'es-rES', 'eu-rES', 'fa-rIR', 'fi-rFI', 'fil-rPH', 'fr-rFR', 'ga-rIE', 'gd-rGB', 'gl-rES', 'hi-rIN', 'hr-rHR', 'hu-rHU', 'hy-rAM', 'ig-rNG', 'in-rID', 'is-rIS', 'it-rIT', 'iw-rIL', 'ja-rJP', 'kab', 'ko-rKR', 'my-rMM', 'nl-rNL', 'no-rNO', 'oc-rFR', 'pl-rPL', 'pt-rBR', 'pt-rPT', 'ro-rRO', 'ru-rRU', 'si-rLK', 'sl-rSI', 'sv-rSE', 'th-rTH', 'tr-rTR', 'uk-rUA', 'ur-rIN', 'vi-rVN', 'zh-rCN', 'zh-rTW']
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ public class MainActivity extends FragmentStackActivity implements ProvidesAssis
|
|||
}
|
||||
|
||||
public void openSearchQuery(String q, String accountID, int progressText, boolean fromSearch){
|
||||
new GetSearchResults(q, null, true)
|
||||
new GetSearchResults(q, null, true, null, 0, 0)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(SearchResults result){
|
||||
|
|
|
@ -176,6 +176,8 @@ public class PushNotificationReceiver extends BroadcastReceiver{
|
|||
List<NotificationChannel> channels=Arrays.stream(PushNotification.Type.values())
|
||||
.map(type->{
|
||||
NotificationChannel channel=new NotificationChannel(accountID+"_"+type, context.getString(type.localizedName), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
channel.setLightColor(context.getColor(R.color.primary_700));
|
||||
channel.enableLights(true);
|
||||
channel.setGroup(accountID);
|
||||
return channel;
|
||||
})
|
||||
|
@ -205,6 +207,7 @@ public class PushNotificationReceiver extends BroadcastReceiver{
|
|||
.setShowWhen(true)
|
||||
.setCategory(Notification.CATEGORY_SOCIAL)
|
||||
.setAutoCancel(true)
|
||||
.setLights(context.getColor(android.R.attr.colorAccent), 500, 1000)
|
||||
.setColor(UiUtils.getThemeColor(context, android.R.attr.colorAccent));
|
||||
|
||||
if (!GlobalUserPreferences.uniformNotificationIcon) {
|
||||
|
|
|
@ -6,18 +6,19 @@ import org.joinmastodon.android.model.Preferences;
|
|||
import org.joinmastodon.android.model.StatusPrivacy;
|
||||
|
||||
public class UpdateAccountCredentialsPreferences extends MastodonAPIRequest<Account>{
|
||||
public UpdateAccountCredentialsPreferences(Preferences preferences, Boolean locked, Boolean discoverable){
|
||||
public UpdateAccountCredentialsPreferences(Preferences preferences, Boolean locked, Boolean discoverable, Boolean indexable){
|
||||
super(HttpMethod.PATCH, "/accounts/update_credentials", Account.class);
|
||||
setRequestBody(new Request(locked, discoverable, new RequestSource(preferences.postingDefaultVisibility, preferences.postingDefaultLanguage)));
|
||||
setRequestBody(new Request(locked, discoverable, indexable, new RequestSource(preferences.postingDefaultVisibility, preferences.postingDefaultLanguage)));
|
||||
}
|
||||
|
||||
private static class Request{
|
||||
public Boolean locked, discoverable;
|
||||
public Boolean locked, discoverable, indexable;
|
||||
public RequestSource source;
|
||||
|
||||
public Request(Boolean locked, Boolean discoverable, RequestSource source){
|
||||
public Request(Boolean locked, Boolean discoverable, Boolean indexable, RequestSource source){
|
||||
this.locked=locked;
|
||||
this.discoverable=discoverable;
|
||||
this.indexable=indexable;
|
||||
this.source=source;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@ import org.joinmastodon.android.model.FilterContext;
|
|||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
@Keep
|
||||
class FilterRequest{
|
||||
public String title;
|
||||
public EnumSet<FilterContext> context;
|
||||
|
|
|
@ -4,13 +4,19 @@ import org.joinmastodon.android.api.MastodonAPIRequest;
|
|||
import org.joinmastodon.android.model.SearchResults;
|
||||
|
||||
public class GetSearchResults extends MastodonAPIRequest<SearchResults>{
|
||||
public GetSearchResults(String query, Type type, boolean resolve){
|
||||
public GetSearchResults(String query, Type type, boolean resolve, String maxID, int offset, int count){
|
||||
super(HttpMethod.GET, "/search", SearchResults.class);
|
||||
addQueryParameter("q", query);
|
||||
if(type!=null)
|
||||
addQueryParameter("type", type.name().toLowerCase());
|
||||
if(resolve)
|
||||
addQueryParameter("resolve", "true");
|
||||
if(maxID!=null)
|
||||
addQueryParameter("max_id", maxID);
|
||||
if(offset>0)
|
||||
addQueryParameter("offset", String.valueOf(offset));
|
||||
if(count>0)
|
||||
addQueryParameter("limit", String.valueOf(count));
|
||||
}
|
||||
|
||||
public GetSearchResults limit(int limit){
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package org.joinmastodon.android.api.requests.tags;
|
||||
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.model.Hashtag;
|
||||
|
||||
public class GetTag extends MastodonAPIRequest<Hashtag>{
|
||||
public GetTag(String tag){
|
||||
super(HttpMethod.GET, "/tags/"+tag, Hashtag.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.joinmastodon.android.api.requests.tags;
|
||||
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.model.Hashtag;
|
||||
|
||||
public class SetTagFollowed extends MastodonAPIRequest<Hashtag>{
|
||||
public SetTagFollowed(String tag, boolean followed){
|
||||
super(HttpMethod.POST, "/tags/"+tag+(followed ? "/follow" : "/unfollow"), Hashtag.class);
|
||||
setRequestBody(new Object());
|
||||
}
|
||||
}
|
|
@ -219,7 +219,7 @@ public class AccountSession{
|
|||
|
||||
public void savePreferencesIfPending(){
|
||||
if(preferencesNeedSaving){
|
||||
new UpdateAccountCredentialsPreferences(preferences, null, null)
|
||||
new UpdateAccountCredentialsPreferences(preferences, null, self.discoverable, self.source.indexable)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Account result){
|
||||
|
@ -303,6 +303,10 @@ public class AccountSession{
|
|||
});
|
||||
}
|
||||
|
||||
public void updateAccountInfo(){
|
||||
AccountSessionManager.getInstance().updateSessionLocalInfo(this);
|
||||
}
|
||||
|
||||
public Optional<Instance> getInstance() {
|
||||
return Optional.ofNullable(AccountSessionManager.getInstance().getInstanceInfo(domain));
|
||||
}
|
||||
|
|
|
@ -303,8 +303,7 @@ public class AccountSessionManager{
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateSessionLocalInfo(AccountSession session){
|
||||
/*package*/ void updateSessionLocalInfo(AccountSession session){
|
||||
new GetOwnAccount()
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
|
|
|
@ -1317,7 +1317,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||
boolean usePhotoPicker=photoPicker && UiUtils.isPhotoPickerAvailable();
|
||||
if(usePhotoPicker){
|
||||
intent=new Intent(MediaStore.ACTION_PICK_IMAGES);
|
||||
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, mediaViewController.getMaxAttachments()-mediaViewController.getMediaAttachmentsCount());
|
||||
if(mediaViewController.getMaxAttachments()-mediaViewController.getMediaAttachmentsCount()>1)
|
||||
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, mediaViewController.getMaxAttachments()-mediaViewController.getMediaAttachmentsCount());
|
||||
}else{
|
||||
intent=new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
|
|
|
@ -45,8 +45,8 @@ public class FeaturedHashtagsListFragment extends BaseStatusListFragment<Hashtag
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(String hashtag){
|
||||
UiUtils.openHashtagTimeline(getActivity(), accountID, hashtag, data.stream().filter(h -> Objects.equals(h.name, hashtag)).findAny().map(h -> h.following).orElse(null));
|
||||
public void onItemClick(String id){
|
||||
UiUtils.openHashtagTimeline(getActivity(), accountID, Objects.requireNonNull(findItemOfType(id, HashtagStatusDisplayItem.class)).tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -121,7 +121,7 @@ public class FollowedHashtagsFragment extends MastodonRecyclerFragment<Hashtag>
|
|||
|
||||
@Override
|
||||
public void onClick() {
|
||||
UiUtils.openHashtagTimeline(getActivity(), accountID, item.name, item.following);
|
||||
UiUtils.openHashtagTimeline(getActivity(), accountID, item.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,64 @@
|
|||
package org.joinmastodon.android.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.TypedArray;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.joinmastodon.android.E;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.tags.GetHashtag;
|
||||
import org.joinmastodon.android.api.requests.tags.SetHashtagFollowed;
|
||||
import org.joinmastodon.android.api.MastodonErrorResponse;
|
||||
import org.joinmastodon.android.api.requests.tags.GetTag;
|
||||
import org.joinmastodon.android.api.requests.tags.SetTagFollowed;
|
||||
import org.joinmastodon.android.api.requests.timelines.GetHashtagTimeline;
|
||||
import org.joinmastodon.android.events.HashtagUpdatedEvent;
|
||||
import org.joinmastodon.android.model.FilterContext;
|
||||
import org.joinmastodon.android.model.Hashtag;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.model.TimelineDefinition;
|
||||
import org.joinmastodon.android.ui.text.SpacerSpan;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.utils.StatusFilterPredicate;
|
||||
import org.joinmastodon.android.ui.views.ProgressBarButton;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
import me.grishka.appkit.api.SimpleCallback;
|
||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class HashtagTimelineFragment extends PinnableStatusListFragment {
|
||||
private String hashtag;
|
||||
public class HashtagTimelineFragment extends PinnableStatusListFragment{
|
||||
private Hashtag hashtag;
|
||||
private String hashtagName;
|
||||
private TextView headerTitle, headerSubtitle;
|
||||
private ProgressBarButton followButton;
|
||||
private ProgressBar followProgress;
|
||||
private MenuItem followMenuItem, pinMenuItem;
|
||||
private boolean followRequestRunning;
|
||||
private boolean toolbarContentVisible;
|
||||
|
||||
private List<String> any;
|
||||
private List<String> all;
|
||||
private List<String> none;
|
||||
private boolean following;
|
||||
private boolean localOnly;
|
||||
private MenuItem followButton;
|
||||
private Menu optionsMenu;
|
||||
private MenuInflater optionsMenuInflater;
|
||||
|
||||
@Override
|
||||
protected boolean wantsComposeButton() {
|
||||
|
@ -50,73 +68,19 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment {
|
|||
@Override
|
||||
public void onAttach(Activity activity){
|
||||
super.onAttach(activity);
|
||||
updateTitle(getArguments().getString("hashtag"));
|
||||
following=getArguments().getBoolean("following", false);
|
||||
localOnly=getArguments().getBoolean("localOnly", false);
|
||||
any=getArguments().getStringArrayList("any");
|
||||
all=getArguments().getStringArrayList("all");
|
||||
none=getArguments().getStringArrayList("none");
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
private void updateTitle(String hashtagName) {
|
||||
hashtag = hashtagName;
|
||||
setTitle('#'+hashtag);
|
||||
}
|
||||
|
||||
private void updateFollowingState(boolean newFollowing) {
|
||||
this.following = newFollowing;
|
||||
followButton.setTitle(getString(newFollowing ? R.string.unfollow_user : R.string.follow_user, "#" + hashtag));
|
||||
followButton.setIcon(newFollowing ? R.drawable.ic_fluent_person_delete_24_filled : R.drawable.ic_fluent_person_add_24_regular);
|
||||
E.post(new HashtagUpdatedEvent(hashtag, following));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.hashtag_timeline, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
followButton = menu.findItem(R.id.follow_hashtag);
|
||||
updateFollowingState(following);
|
||||
|
||||
new GetHashtag(hashtag).setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(Hashtag hashtag) {
|
||||
if (getActivity() == null) return;
|
||||
updateTitle(hashtag.name);
|
||||
updateFollowingState(hashtag.following);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error) {
|
||||
error.showToast(getActivity());
|
||||
}
|
||||
}).exec(accountID);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (super.onOptionsItemSelected(item)) return true;
|
||||
if (item.getItemId() == R.id.follow_hashtag) {
|
||||
updateFollowingState(!following);
|
||||
getToolbar().performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
|
||||
new SetHashtagFollowed(hashtag, following).setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(Hashtag i) {
|
||||
if (getActivity() == null) return;
|
||||
if (i.following == following) Toast.makeText(getActivity(), getString(i.following ? R.string.followed_user : R.string.unfollowed_user, "#" + i.name), Toast.LENGTH_SHORT).show();
|
||||
updateFollowingState(i.following);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error) {
|
||||
error.showToast(getActivity());
|
||||
updateFollowingState(!following);
|
||||
}
|
||||
}).exec(accountID);
|
||||
return true;
|
||||
if(getArguments().containsKey("hashtag")){
|
||||
hashtag=Parcels.unwrap(getArguments().getParcelable("hashtag"));
|
||||
hashtagName=hashtag.name;
|
||||
}else{
|
||||
hashtagName=getArguments().getString("hashtagName");
|
||||
}
|
||||
return false;
|
||||
setTitle('#'+hashtagName);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -126,12 +90,10 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment {
|
|||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){
|
||||
currentRequest=new GetHashtagTimeline(hashtag, offset==0 ? null : getMaxID(), null, count, any, all, none, localOnly, getLocalPrefs().timelineReplyVisibility)
|
||||
currentRequest=new GetHashtagTimeline(hashtagName, offset==0 ? null : getMaxID(), null, count, any, all, none, localOnly, getLocalPrefs().timelineReplyVisibility)
|
||||
.setCallback(new SimpleCallback<>(this){
|
||||
@Override
|
||||
public void onSuccess(List<Status> result){
|
||||
if (getActivity() == null) return;
|
||||
result=result.stream().filter(new StatusFilterPredicate(accountID, getFilterContext())).collect(Collectors.toList());
|
||||
onDataLoaded(result, !result.isEmpty());
|
||||
}
|
||||
})
|
||||
|
@ -146,15 +108,40 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onFabLongClick(View v) {
|
||||
return UiUtils.pickAccountForCompose(getActivity(), accountID, '#'+hashtag+' ');
|
||||
public void loadData(){
|
||||
reloadTag();
|
||||
super.loadData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState){
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
fab=view.findViewById(R.id.fab);
|
||||
fab.setOnClickListener(this::onFabClick);
|
||||
|
||||
if(getParentFragment() instanceof HomeTabFragment) return;
|
||||
|
||||
list.addOnScrollListener(new RecyclerView.OnScrollListener(){
|
||||
@Override
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){
|
||||
View topChild=recyclerView.getChildAt(0);
|
||||
int firstChildPos=recyclerView.getChildAdapterPosition(topChild);
|
||||
float newAlpha=firstChildPos>0 ? 1f : Math.min(1f, -topChild.getTop()/(float)headerTitle.getHeight());
|
||||
toolbarTitleView.setAlpha(newAlpha);
|
||||
boolean newToolbarVisibility=newAlpha>0.5f;
|
||||
if(newToolbarVisibility!=toolbarContentVisible){
|
||||
toolbarContentVisible=newToolbarVisibility;
|
||||
createOptionsMenu();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFabClick(View v){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putString("prefilledText", '#'+hashtag+' ');
|
||||
args.putString("prefilledText", '#'+hashtagName+' ');
|
||||
Nav.go(getActivity(), ComposeFragment.class, args);
|
||||
}
|
||||
|
||||
|
@ -170,6 +157,203 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment {
|
|||
|
||||
@Override
|
||||
public Uri getWebUri(Uri.Builder base) {
|
||||
return base.path((isInstanceAkkoma() ? "/tag/" : "/tags") + hashtag).build();
|
||||
return base.path((isInstanceAkkoma() ? "/tag/" : "/tags/") + hashtag).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecyclerView.Adapter getAdapter(){
|
||||
View header=getActivity().getLayoutInflater().inflate(R.layout.header_hashtag_timeline, list, false);
|
||||
headerTitle=header.findViewById(R.id.title);
|
||||
headerSubtitle=header.findViewById(R.id.subtitle);
|
||||
followButton=header.findViewById(R.id.profile_action_btn);
|
||||
followProgress=header.findViewById(R.id.action_progress);
|
||||
|
||||
headerTitle.setText("#"+hashtagName);
|
||||
followButton.setVisibility(View.GONE);
|
||||
followButton.setOnClickListener(v->{
|
||||
if(hashtag==null)
|
||||
return;
|
||||
setFollowed(!hashtag.following);
|
||||
});
|
||||
followButton.setOnLongClickListener(v->{
|
||||
if(hashtag==null) return false;
|
||||
UiUtils.pickAccount(getActivity(), accountID, R.string.sk_follow_as, R.drawable.ic_fluent_person_add_28_regular, session -> {
|
||||
new SetTagFollowed(hashtagName, true).setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Hashtag hashtag) {
|
||||
Toast.makeText(
|
||||
getActivity(),
|
||||
getString(R.string.sk_followed_as, session.self.getShortUsername()),
|
||||
Toast.LENGTH_SHORT
|
||||
).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error) {
|
||||
error.showToast(getActivity());
|
||||
}
|
||||
}).exec(session.getID());
|
||||
}, null);
|
||||
return true;
|
||||
});
|
||||
updateHeader();
|
||||
|
||||
MergeRecyclerAdapter mergeAdapter=new MergeRecyclerAdapter();
|
||||
if(!(getParentFragment() instanceof HomeTabFragment)){
|
||||
mergeAdapter.addAdapter(new SingleViewRecyclerAdapter(header));
|
||||
}
|
||||
mergeAdapter.addAdapter(super.getAdapter());
|
||||
return mergeAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getMainAdapterOffset(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
private void createOptionsMenu(){
|
||||
optionsMenu.clear();
|
||||
optionsMenuInflater.inflate(R.menu.hashtag_timeline, optionsMenu);
|
||||
followMenuItem=optionsMenu.findItem(R.id.follow_hashtag);
|
||||
pinMenuItem=optionsMenu.findItem(R.id.pin);
|
||||
followMenuItem.setVisible(toolbarContentVisible);
|
||||
followMenuItem.setTitle(getString(hashtag.following ? R.string.unfollow_user : R.string.follow_user, "#"+hashtagName));
|
||||
followMenuItem.setIcon(hashtag.following ? R.drawable.ic_fluent_person_delete_24_filled : R.drawable.ic_fluent_person_add_24_regular);
|
||||
pinMenuItem.setShowAsAction(toolbarContentVisible ? MenuItem.SHOW_AS_ACTION_NEVER : MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
if(toolbarContentVisible){
|
||||
UiUtils.enableOptionsMenuIcons(getContext(), optionsMenu);
|
||||
}else{
|
||||
UiUtils.enableOptionsMenuIcons(getContext(), optionsMenu, R.id.pin);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePinButton(MenuItem pin){
|
||||
super.updatePinButton(pin);
|
||||
UiUtils.insetPopupMenuIcon(getContext(), pin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
|
||||
inflater.inflate(R.menu.hashtag_timeline, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
optionsMenu=menu;
|
||||
optionsMenuInflater=inflater;
|
||||
createOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item){
|
||||
if (super.onOptionsItemSelected(item)) return true;
|
||||
if (item.getItemId() == R.id.follow_hashtag && hashtag!=null) {
|
||||
setFollowed(!hashtag.following);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUpdateToolbar(){
|
||||
super.onUpdateToolbar();
|
||||
toolbarTitleView.setAlpha(toolbarContentVisible ? 1f : 0f);
|
||||
createOptionsMenu();
|
||||
}
|
||||
|
||||
private void updateHeader(){
|
||||
if(hashtag==null)
|
||||
return;
|
||||
|
||||
if(hashtag.history!=null && !hashtag.history.isEmpty()){
|
||||
int weekPosts=hashtag.history.stream().mapToInt(h->h.uses).sum();
|
||||
int todayPosts=hashtag.history.get(0).uses;
|
||||
int numAccounts=hashtag.history.stream().mapToInt(h->h.accounts).sum();
|
||||
int hSpace=V.dp(8);
|
||||
SpannableStringBuilder ssb=new SpannableStringBuilder();
|
||||
ssb.append(getResources().getQuantityString(R.plurals.x_posts, weekPosts, weekPosts));
|
||||
ssb.append(" ", new SpacerSpan(hSpace, 0), 0);
|
||||
ssb.append('·');
|
||||
ssb.append(" ", new SpacerSpan(hSpace, 0), 0);
|
||||
ssb.append(getResources().getQuantityString(R.plurals.x_participants, numAccounts, numAccounts));
|
||||
ssb.append(" ", new SpacerSpan(hSpace, 0), 0);
|
||||
ssb.append('·');
|
||||
ssb.append(" ", new SpacerSpan(hSpace, 0), 0);
|
||||
ssb.append(getResources().getQuantityString(R.plurals.x_posts_today, todayPosts, todayPosts));
|
||||
headerSubtitle.setText(ssb);
|
||||
}
|
||||
|
||||
int styleRes;
|
||||
followButton.setVisibility(View.VISIBLE);
|
||||
if(hashtag.following){
|
||||
followButton.setText(R.string.button_following);
|
||||
styleRes=R.style.Widget_Mastodon_M3_Button_Tonal;
|
||||
}else{
|
||||
followButton.setText(R.string.button_follow);
|
||||
styleRes=R.style.Widget_Mastodon_M3_Button_Filled;
|
||||
}
|
||||
TypedArray ta=followButton.getContext().obtainStyledAttributes(styleRes, new int[]{android.R.attr.background});
|
||||
followButton.setBackground(ta.getDrawable(0));
|
||||
ta.recycle();
|
||||
ta=followButton.getContext().obtainStyledAttributes(styleRes, new int[]{android.R.attr.textColor});
|
||||
followButton.setTextColor(ta.getColorStateList(0));
|
||||
followProgress.setIndeterminateTintList(ta.getColorStateList(0));
|
||||
ta.recycle();
|
||||
|
||||
followButton.setTextVisible(true);
|
||||
followProgress.setVisibility(View.GONE);
|
||||
if(followMenuItem!=null){
|
||||
followMenuItem.setTitle(getString(hashtag.following ? R.string.unfollow_user : R.string.follow_user, "#"+hashtagName));
|
||||
followMenuItem.setIcon(hashtag.following ? R.drawable.ic_fluent_person_delete_24_filled : R.drawable.ic_fluent_person_add_24_regular);
|
||||
UiUtils.insetPopupMenuIcon(getContext(), followMenuItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void reloadTag(){
|
||||
new GetTag(hashtagName)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Hashtag result){
|
||||
hashtag=result;
|
||||
updateHeader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
}
|
||||
|
||||
private void setFollowed(boolean followed){
|
||||
if(followRequestRunning)
|
||||
return;
|
||||
getToolbar().performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
|
||||
followButton.setTextVisible(false);
|
||||
followProgress.setVisibility(View.VISIBLE);
|
||||
followRequestRunning=true;
|
||||
new SetTagFollowed(hashtagName, followed)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Hashtag result){
|
||||
if(getActivity()==null)
|
||||
return;
|
||||
hashtag=result;
|
||||
updateHeader();
|
||||
followRequestRunning=false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
if(getActivity()==null)
|
||||
return;
|
||||
if(error instanceof MastodonErrorResponse er && "Duplicate record".equals(er.error)){
|
||||
hashtag.following=true;
|
||||
}else{
|
||||
error.showToast(getActivity());
|
||||
}
|
||||
updateHeader();
|
||||
followRequestRunning=false;
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -184,6 +184,7 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
|
|||
});
|
||||
}
|
||||
}
|
||||
tabBar.selectTab(currentTab);
|
||||
|
||||
return content;
|
||||
}
|
||||
|
|
|
@ -524,9 +524,7 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
|
|||
if (list.repliesPolicy != null) args.putInt("repliesPolicy", list.repliesPolicy.ordinal());
|
||||
Nav.go(getActivity(), ListTimelineFragment.class, args);
|
||||
} else if ((hashtag = hashtagsItems.get(id)) != null) {
|
||||
args.putString("hashtag", hashtag.name);
|
||||
args.putBoolean("following", hashtag.following);
|
||||
Nav.go(getActivity(), HashtagTimelineFragment.class, args);
|
||||
UiUtils.openHashtagTimeline(getContext(), accountID, hashtag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -304,6 +304,12 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||
|
||||
tabbar.setTabTextColors(UiUtils.getThemeColor(getActivity(), R.attr.colorM3OnSurfaceVariant), UiUtils.getThemeColor(getActivity(), R.attr.colorM3Primary));
|
||||
tabbar.setTabTextSize(V.dp(14));
|
||||
tabLayoutMediator=new TabLayoutMediator(tabbar, pager, (tab, position)->tab.setText(switch(position){
|
||||
case 0 -> R.string.profile_featured;
|
||||
case 1 -> R.string.profile_timeline;
|
||||
case 2 -> R.string.profile_about;
|
||||
default -> throw new IllegalStateException();
|
||||
}));
|
||||
tabLayoutMediator=new TabLayoutMediator(tabbar, pager, new TabLayoutMediator.TabConfigurationStrategy(){
|
||||
@Override
|
||||
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position){
|
||||
|
@ -317,6 +323,19 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||
if (position == 4) tab.view.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
tabbar.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab){}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab){}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab){
|
||||
if(getFragmentForPage(tab.getPosition()) instanceof ScrollableToTop stt)
|
||||
stt.scrollToTop();
|
||||
}
|
||||
});
|
||||
|
||||
cover.setOutlineProvider(new ViewOutlineProvider(){
|
||||
@Override
|
||||
|
@ -1304,9 +1323,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||
@NonNull
|
||||
@Override
|
||||
public SimpleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
FrameLayout view=tabViews[viewType];
|
||||
if (view.getParent() != null) ((ViewGroup)view.getParent()).removeView(view);
|
||||
view.setVisibility(View.VISIBLE);
|
||||
FrameLayout view=new FrameLayout(parent.getContext());
|
||||
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
return new SimpleViewHolder(view);
|
||||
}
|
||||
|
@ -1314,8 +1331,13 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||
@Override
|
||||
public void onBindViewHolder(@NonNull SimpleViewHolder holder, int position){
|
||||
Fragment fragment=getFragmentForPage(position);
|
||||
FrameLayout fragmentView=tabViews[position];
|
||||
fragmentView.setVisibility(View.VISIBLE);
|
||||
if(fragmentView.getParent() instanceof ViewGroup parent)
|
||||
parent.removeView(fragmentView);
|
||||
((FrameLayout)holder.itemView).addView(fragmentView);
|
||||
if(!fragment.isAdded()){
|
||||
getChildFragmentManager().beginTransaction().add(holder.itemView.getId(), fragment).commit();
|
||||
getChildFragmentManager().beginTransaction().add(fragmentView.getId(), fragment).commit();
|
||||
holder.itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
|
||||
@Override
|
||||
public boolean onPreDraw(){
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.joinmastodon.android.ui.BetterItemAnimator;
|
|||
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.ReblogOrReplyLineStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.SpoilerStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.WarningFilteredStatusDisplayItem;
|
||||
|
@ -105,6 +106,12 @@ public class ThreadFragment extends StatusListFragment implements ProvidesAssist
|
|||
text.textSelectable=true;
|
||||
else if(item instanceof FooterStatusDisplayItem footer)
|
||||
footer.hideCounts=true;
|
||||
else if(item instanceof SpoilerStatusDisplayItem spoiler){
|
||||
for(StatusDisplayItem subItem:spoiler.contentItems){
|
||||
if(subItem instanceof TextStatusDisplayItem text)
|
||||
text.textSelectable=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ public class ComposeAccountSearchFragment extends BaseAccountListFragment{
|
|||
@Override
|
||||
protected void doLoadData(int offset, int count){
|
||||
refreshing=true;
|
||||
currentRequest=new GetSearchResults(currentQuery, GetSearchResults.Type.ACCOUNTS, false)
|
||||
currentRequest=new GetSearchResults(currentQuery, GetSearchResults.Type.ACCOUNTS, false, null, 0, 0)
|
||||
.setCallback(new SimpleCallback<>(this){
|
||||
@Override
|
||||
public void onSuccess(SearchResults result){
|
||||
|
|
|
@ -289,15 +289,19 @@ public class DiscoverFragment extends AppKitFragment implements ScrollableToTop,
|
|||
@NonNull
|
||||
@Override
|
||||
public SimpleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
FrameLayout view=tabViews[viewType];
|
||||
((ViewGroup)view.getParent()).removeView(view);
|
||||
view.setVisibility(View.VISIBLE);
|
||||
FrameLayout view=new FrameLayout(parent.getContext());
|
||||
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
return new SimpleViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull SimpleViewHolder holder, int position){}
|
||||
public void onBindViewHolder(@NonNull SimpleViewHolder holder, int position){
|
||||
FrameLayout view=tabViews[position];
|
||||
if(view.getParent() instanceof ViewGroup parent)
|
||||
parent.removeView(view);
|
||||
view.setVisibility(View.VISIBLE);
|
||||
((FrameLayout)holder.itemView).addView(view, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(){
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.joinmastodon.android.model.Status;
|
|||
import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.HashtagStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.tabs.TabLayout;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
|
@ -31,7 +30,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import me.grishka.appkit.Nav;
|
||||
|
@ -97,7 +96,7 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
|
|||
args.putParcelable("profileAccount", Parcels.wrap(res.account));
|
||||
Nav.go(getActivity(), ProfileFragment.class, args);
|
||||
}
|
||||
case HASHTAG -> UiUtils.openHashtagTimeline(getActivity(), accountID, res.hashtag.name, res.hashtag.following);
|
||||
case HASHTAG -> UiUtils.openHashtagTimeline(getActivity(), accountID, res.hashtag);
|
||||
case STATUS -> {
|
||||
Status status=res.status.getContentStatus();
|
||||
Bundle args=new Bundle();
|
||||
|
@ -113,7 +112,7 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){
|
||||
protected void doLoadData(int _offset, int count){
|
||||
GetSearchResults.Type type;
|
||||
if(currentFilter.size()==1){
|
||||
type=switch(currentFilter.iterator().next()){
|
||||
|
@ -128,7 +127,21 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
|
|||
dataLoaded();
|
||||
return;
|
||||
}
|
||||
currentRequest=new GetSearchResults(currentQuery, type, true)
|
||||
String maxID=null;
|
||||
// TODO server-side bug
|
||||
/*int offset=0;
|
||||
if(_offset>0){
|
||||
if(type==GetSearchResults.Type.STATUSES){
|
||||
if(!preloadedData.isEmpty())
|
||||
maxID=preloadedData.get(preloadedData.size()-1).status.id;
|
||||
else if(!data.isEmpty())
|
||||
maxID=data.get(data.size()-1).status.id;
|
||||
}else{
|
||||
offset=_offset;
|
||||
}
|
||||
}*/
|
||||
int offset=_offset;
|
||||
currentRequest=new GetSearchResults(currentQuery, type, type==null, maxID, offset, type==null ? 0 : count)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(SearchResults result){
|
||||
|
@ -142,12 +155,15 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
|
|||
results.add(new SearchResult(tag));
|
||||
}
|
||||
if(result.statuses!=null){
|
||||
for(Status status:result.statuses)
|
||||
results.add(new SearchResult(status));
|
||||
Set<String> alreadyLoadedStatuses=data.stream().filter(r->r.type==SearchResult.Type.STATUS).map(r->r.status.id).collect(Collectors.toSet());
|
||||
for(Status status:result.statuses){
|
||||
if(!alreadyLoadedStatuses.contains(status.id))
|
||||
results.add(new SearchResult(status));
|
||||
}
|
||||
}
|
||||
prevDisplayItems=new ArrayList<>(displayItems);
|
||||
unfilteredResults=results;
|
||||
onDataLoaded(filterSearchResults(results), false);
|
||||
onDataLoaded(filterSearchResults(results), type!=null && !results.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -122,7 +122,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
|
|||
recentsHeader.setVisible(!data.isEmpty());
|
||||
});
|
||||
}else{
|
||||
currentRequest=new GetSearchResults(currentQuery, null, false)
|
||||
currentRequest=new GetSearchResults(currentQuery, null, false, null, 0, 0)
|
||||
.limit(2)
|
||||
.setCallback(new SimpleCallback<>(this){
|
||||
@Override
|
||||
|
@ -378,7 +378,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
|
|||
|
||||
private void openHashtag(SearchResult res){
|
||||
wrapSuicideDialog(()->{
|
||||
UiUtils.openHashtagTimeline(getActivity(), accountID, res.hashtag.name, res.hashtag.following);
|
||||
UiUtils.openHashtagTimeline(getActivity(), accountID, res.hashtag);
|
||||
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putRecentSearch(res);
|
||||
});
|
||||
}
|
||||
|
@ -424,6 +424,8 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
|
|||
}
|
||||
|
||||
private void onSearchViewEnter(){
|
||||
if(TextUtils.isEmpty(currentQuery) || currentQuery.trim().isEmpty())
|
||||
return;
|
||||
wrapSuicideDialog(()->deliverResult(currentQuery, null));
|
||||
}
|
||||
|
||||
|
@ -436,7 +438,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
|
|||
String q=searchViewHelper.getQuery();
|
||||
if(q.startsWith("#"))
|
||||
q=q.substring(1);
|
||||
UiUtils.openHashtagTimeline(getActivity(), accountID, q, null);
|
||||
UiUtils.openHashtagTimeline(getActivity(), accountID, q);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ public class TrendingHashtagsFragment extends BaseRecyclerFragment<Hashtag> impl
|
|||
|
||||
@Override
|
||||
public void onClick(){
|
||||
UiUtils.openHashtagTimeline(getActivity(), accountID, item.name, item.following);
|
||||
UiUtils.openHashtagTimeline(getActivity(), accountID, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -271,7 +271,7 @@ public class SignupFragment extends ToolbarFragment{
|
|||
@Override
|
||||
public void tail(Node node, int depth){
|
||||
if(node instanceof Element){
|
||||
ssb.setSpan(new LinkSpan("", SignupFragment.this::onGoBackLinkClick, LinkSpan.Type.CUSTOM, null), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
ssb.setSpan(new LinkSpan("", SignupFragment.this::onGoBackLinkClick, LinkSpan.Type.CUSTOM, null, null, null), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
ssb.setSpan(new TypefaceSpan("sans-serif-medium"), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
|
|||
setTitle(getString(R.string.about_app, getString(R.string.sk_app_name)));
|
||||
AccountSession s=AccountSessionManager.get(accountID);
|
||||
onDataLoaded(List.of(
|
||||
new ListItem<>(R.string.sk_settings_donate, 0, R.drawable.ic_fluent_heart_24_regular, ()->UiUtils.openHashtagTimeline(getActivity(), accountID, getString(R.string.donate_hashtag), null)),
|
||||
new ListItem<>(R.string.sk_settings_donate, 0, R.drawable.ic_fluent_heart_24_regular, ()->UiUtils.openHashtagTimeline(getActivity(), accountID, getString(R.string.donate_hashtag))),
|
||||
new ListItem<>(R.string.sk_settings_contribute, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), getString(R.string.repo_url))),
|
||||
new ListItem<>(R.string.settings_tos, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/terms")),
|
||||
new ListItem<>(R.string.settings_privacy_policy, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), getString(R.string.privacy_policy_url)), 0, true),
|
||||
|
|
|
@ -55,6 +55,8 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
|
|||
onDataLoaded(List.of(
|
||||
new ListItem<>(R.string.settings_behavior, 0, R.drawable.ic_fluent_settings_24_regular, this::onBehaviorClick),
|
||||
new ListItem<>(R.string.settings_display, 0, R.drawable.ic_fluent_color_24_regular, this::onDisplayClick),
|
||||
new ListItem<>(R.string.settings_privacy, 0, R.drawable.ic_privacy_tip_24px, this::onPrivacyClick),
|
||||
new ListItem<>(R.string.settings_filters, 0, R.drawable.ic_filter_alt_24px, this::onFiltersClick),
|
||||
new ListItem<>(R.string.settings_notifications, 0, R.drawable.ic_fluent_alert_24_regular, this::onNotificationsClick),
|
||||
new ListItem<>(R.string.sk_settings_instance, 0, R.drawable.ic_fluent_server_24_regular, this::onInstanceClick),
|
||||
new ListItem<>(getString(R.string.about_app, getString(R.string.sk_app_name)), null, R.drawable.ic_fluent_info_24_regular, this::onAboutClick, null, 0, true),
|
||||
|
@ -69,7 +71,9 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
|
|||
data.add(0, new ListItem<>("Debug settings", null, R.drawable.ic_fluent_wrench_screwdriver_24_regular, ()->Nav.go(getActivity(), SettingsDebugFragment.class, makeFragmentArgs()), null, 0, true));
|
||||
}
|
||||
|
||||
account.reloadPreferences(null);
|
||||
AccountSession session=AccountSessionManager.get(accountID);
|
||||
session.reloadPreferences(null);
|
||||
session.updateAccountInfo();
|
||||
E.register(this);
|
||||
}
|
||||
|
||||
|
@ -133,6 +137,10 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
|
|||
Nav.go(getActivity(), SettingsDisplayFragment.class, makeFragmentArgs());
|
||||
}
|
||||
|
||||
private void onPrivacyClick(){
|
||||
Nav.go(getActivity(), SettingsPrivacyFragment.class, makeFragmentArgs());
|
||||
}
|
||||
|
||||
private void onFiltersClick(){
|
||||
Nav.go(getActivity(), SettingsFiltersFragment.class, makeFragmentArgs());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package org.joinmastodon.android.fragments.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SettingsPrivacyFragment extends BaseSettingsFragment<Void>{
|
||||
private CheckableListItem<Void> discoverableItem, indexableItem;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
setTitle(R.string.settings_privacy);
|
||||
Account self=AccountSessionManager.get(accountID).self;
|
||||
onDataLoaded(List.of(
|
||||
discoverableItem=new CheckableListItem<>(R.string.settings_discoverable, 0, CheckableListItem.Style.SWITCH, self.discoverable, R.drawable.ic_thumbs_up_down_24px, ()->toggleCheckableItem(discoverableItem)),
|
||||
indexableItem=new CheckableListItem<>(R.string.settings_indexable, 0, CheckableListItem.Style.SWITCH, self.source.indexable!=null ? self.source.indexable : true, R.drawable.ic_search_24px, ()->toggleCheckableItem(indexableItem))
|
||||
));
|
||||
if(self.source.indexable==null)
|
||||
indexableItem.isEnabled=false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){}
|
||||
|
||||
@Override
|
||||
public void onPause(){
|
||||
super.onPause();
|
||||
Account self=AccountSessionManager.get(accountID).self;
|
||||
if(self.discoverable!=discoverableItem.checked || (self.source.indexable!=null && self.source.indexable!=indexableItem.checked)){
|
||||
self.discoverable=discoverableItem.checked;
|
||||
self.source.indexable=indexableItem.checked;
|
||||
AccountSessionManager.get(accountID).savePreferencesLater();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -153,18 +153,21 @@ public class SettingsServerFragment extends AppKitFragment{
|
|||
@NonNull
|
||||
@Override
|
||||
public SimpleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
FrameLayout view=tabViews[viewType];
|
||||
((ViewGroup)view.getParent()).removeView(view);
|
||||
view.setVisibility(View.VISIBLE);
|
||||
FrameLayout view=new FrameLayout(parent.getContext());
|
||||
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
return new SimpleViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull SimpleViewHolder holder, int position){
|
||||
FrameLayout view=tabViews[position];
|
||||
if(view.getParent() instanceof ViewGroup parent)
|
||||
parent.removeView(view);
|
||||
view.setVisibility(View.VISIBLE);
|
||||
((FrameLayout)holder.itemView).addView(view, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
Fragment fragment=getFragmentForPage(position);
|
||||
if(!fragment.isAdded()){
|
||||
getChildFragmentManager().beginTransaction().add(holder.itemView.getId(), fragment).commit();
|
||||
getChildFragmentManager().beginTransaction().add(view.getId(), fragment).commit();
|
||||
holder.itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
|
||||
@Override
|
||||
public boolean onPreDraw(){
|
||||
|
|
|
@ -139,6 +139,7 @@ public class Account extends BaseModel implements Searchable{
|
|||
* When a timed mute will expire, if applicable.
|
||||
*/
|
||||
public Instant muteExpiresAt;
|
||||
public boolean noindex;
|
||||
|
||||
public List<Role> roles;
|
||||
|
||||
|
@ -238,6 +239,7 @@ public class Account extends BaseModel implements Searchable{
|
|||
", source="+source+
|
||||
", suspended="+suspended+
|
||||
", muteExpiresAt="+muteExpiresAt+
|
||||
", noindex="+noindex+
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ public class Hashtag extends BaseModel implements DisplayItemsParent{
|
|||
", following="+following+
|
||||
", history="+history+
|
||||
", statusesCount="+statusesCount+
|
||||
", following="+following+
|
||||
'}';
|
||||
}
|
||||
|
||||
|
@ -30,4 +31,19 @@ public class Hashtag extends BaseModel implements DisplayItemsParent{
|
|||
public String getID(){
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o){
|
||||
if(this==o) return true;
|
||||
if(o==null || getClass()!=o.getClass()) return false;
|
||||
|
||||
Hashtag hashtag=(Hashtag) o;
|
||||
|
||||
return name.equals(hashtag.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(){
|
||||
return name.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,4 +20,22 @@ public class Mention extends BaseModel{
|
|||
", url='"+url+'\''+
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o){
|
||||
if(this==o) return true;
|
||||
if(o==null || getClass()!=o.getClass()) return false;
|
||||
|
||||
Mention mention=(Mention) o;
|
||||
|
||||
if(!id.equals(mention.id)) return false;
|
||||
return url.equals(mention.url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(){
|
||||
int result=id.hashCode();
|
||||
result=31*result+url.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ public class Source extends BaseModel{
|
|||
* The number of pending follow requests.
|
||||
*/
|
||||
public int followRequestCount;
|
||||
public Boolean indexable;
|
||||
public boolean hideCollections;
|
||||
|
||||
@Override
|
||||
public void postprocess() throws ObjectValidationException{
|
||||
|
@ -54,6 +56,8 @@ public class Source extends BaseModel{
|
|||
", sensitive="+sensitive+
|
||||
", language='"+language+'\''+
|
||||
", followRequestCount="+followRequestCount+
|
||||
", indexable="+indexable+
|
||||
", hideCollections="+hideCollections+
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,17 @@ import static org.joinmastodon.android.api.MastodonAPIController.gsonWithoutDese
|
|||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.joinmastodon.android.api.ObjectValidationException;
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.github.bottomSoftwareFoundation.bottom.Bottom;
|
||||
|
|
|
@ -219,7 +219,7 @@ public class TimelineDefinition {
|
|||
args.putString("listID", listId);
|
||||
args.putBoolean("listIsExclusive", listIsExclusive);
|
||||
} else if (type == TimelineType.HASHTAG) {
|
||||
args.putString("hashtag", hashtagName);
|
||||
args.putString("hashtagName", hashtagName);
|
||||
args.putBoolean("localOnly", hashtagLocalOnly);
|
||||
args.putStringArrayList("any", hashtagAny == null ? new ArrayList<>() : new ArrayList<>(hashtagAny));
|
||||
args.putStringArrayList("all", hashtagAll == null ? new ArrayList<>() : new ArrayList<>(hashtagAll));
|
||||
|
|
|
@ -15,6 +15,7 @@ import android.widget.TextView;
|
|||
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Emoji;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
|
@ -53,7 +54,8 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
|||
public ReblogOrReplyLineStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, CharSequence text, List<Emoji> emojis, @DrawableRes int icon, StatusPrivacy visibility, @Nullable View.OnClickListener handleClick, CharSequence fullText, Status status) {
|
||||
super(parentID, parentFragment);
|
||||
SpannableStringBuilder ssb=new SpannableStringBuilder(text);
|
||||
HtmlParser.parseCustomEmoji(ssb, emojis);
|
||||
if(AccountSessionManager.get(parentFragment.getAccountID()).getLocalPreferences().customEmojiInNames)
|
||||
HtmlParser.parseCustomEmoji(ssb, emojis);
|
||||
this.text=ssb;
|
||||
emojiHelper.setText(ssb);
|
||||
this.icon=icon;
|
||||
|
|
|
@ -180,10 +180,8 @@ public abstract class StatusDisplayItem{
|
|||
.ifPresent(hashtag -> items.add(new ReblogOrReplyLineStatusDisplayItem(
|
||||
parentID, fragment, hashtag.name, List.of(),
|
||||
R.drawable.ic_fluent_number_symbol_20sp_filled, null,
|
||||
i -> {
|
||||
args.putString("hashtag", hashtag.name);
|
||||
Nav.go(fragment.getActivity(), HashtagTimelineFragment.class, args);
|
||||
}, status
|
||||
i->UiUtils.openHashtagTimeline(fragment.getActivity(), accountID, hashtag),
|
||||
status
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
|
@ -878,6 +878,8 @@ public class PhotoViewer implements ZoomPanView.Listener{
|
|||
|
||||
@Override
|
||||
public void onVideoSizeChanged(MediaPlayer mp, int width, int height){
|
||||
if(width<=0 || height<=0)
|
||||
return;
|
||||
FrameLayout.LayoutParams params=(FrameLayout.LayoutParams) wrap.getLayoutParams();
|
||||
params.width=width;
|
||||
params.height=height;
|
||||
|
|
|
@ -119,6 +119,9 @@ public class ZoomPanView extends FrameLayout implements ScaleGestureDetector.OnS
|
|||
|
||||
int width=right-left;
|
||||
int height=bottom-top;
|
||||
if(width==0 || height==0)
|
||||
return;
|
||||
|
||||
float scale=Math.min(width/(float)child.getWidth(), height/(float)child.getHeight());
|
||||
minScale=scale;
|
||||
maxScale=Math.max(3f, height/(float)child.getHeight());
|
||||
|
@ -306,8 +309,6 @@ public class ZoomPanView extends FrameLayout implements ScaleGestureDetector.OnS
|
|||
}, 1f).setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_ALPHA));
|
||||
}
|
||||
}else{
|
||||
if(animatingTransition)
|
||||
Log.w(TAG, "updateViewTransform: ", new Throwable().fillInStackTrace());
|
||||
child.setScaleX(matrixValues[Matrix.MSCALE_X]);
|
||||
child.setScaleY(matrixValues[Matrix.MSCALE_Y]);
|
||||
child.setTranslationX(matrixValues[Matrix.MTRANS_X]);
|
||||
|
|
|
@ -100,9 +100,10 @@ public class HtmlParser{
|
|||
}
|
||||
}
|
||||
|
||||
Map<String, String> idsByUrl=mentions.stream().collect(Collectors.toMap(m->m.url, m->m.id));
|
||||
Map<String, String> idsByUrl=mentions.stream().distinct().collect(Collectors.toMap(m->m.url, m->m.id));
|
||||
// Hashtags in remote posts have remote URLs, these have local URLs so they don't match.
|
||||
// Map<String, String> tagsByUrl=tags.stream().collect(Collectors.toMap(t->t.url, t->t.name));
|
||||
Map<String, Hashtag> tagsByTag=tags.stream().distinct().collect(Collectors.toMap(t->t.name.toLowerCase(), Function.identity()));
|
||||
|
||||
final SpannableStringBuilder ssb=new SpannableStringBuilder();
|
||||
Jsoup.parseBodyFragment(source).body().traverse(new NodeVisitor(){
|
||||
|
@ -115,6 +116,7 @@ public class HtmlParser{
|
|||
}else if(node instanceof Element el){
|
||||
switch(el.nodeName()){
|
||||
case "a" -> {
|
||||
Object linkObject=null;
|
||||
String href=el.attr("href");
|
||||
LinkSpan.Type linkType;
|
||||
String text=el.text();
|
||||
|
@ -122,6 +124,7 @@ public class HtmlParser{
|
|||
if(text.startsWith("#")){
|
||||
linkType=LinkSpan.Type.HASHTAG;
|
||||
href=text.substring(1);
|
||||
linkObject=tagsByTag.get(text.substring(1).toLowerCase());
|
||||
}else{
|
||||
linkType=LinkSpan.Type.URL;
|
||||
}
|
||||
|
@ -136,7 +139,7 @@ public class HtmlParser{
|
|||
}else{
|
||||
linkType=LinkSpan.Type.URL;
|
||||
}
|
||||
openSpans.add(new SpanInfo(new LinkSpan(href, null, linkType, accountID), ssb.length(), el));
|
||||
openSpans.add(new SpanInfo(new LinkSpan(href, null, linkType, accountID, linkObject, text), ssb.length(), el));
|
||||
}
|
||||
case "br" -> ssb.append('\n');
|
||||
case "span" -> {
|
||||
|
@ -271,7 +274,7 @@ public class HtmlParser{
|
|||
String url=matcher.group(3);
|
||||
if(TextUtils.isEmpty(matcher.group(4)))
|
||||
url="http://"+url;
|
||||
ssb.setSpan(new LinkSpan(url, null, LinkSpan.Type.URL, null), matcher.start(3), matcher.end(3), 0);
|
||||
ssb.setSpan(new LinkSpan(url, null, LinkSpan.Type.URL, null, null, null), matcher.start(3), matcher.end(3), 0);
|
||||
}while(matcher.find()); // Find more URLs
|
||||
return ssb;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.text.TextPaint;
|
|||
import android.text.style.CharacterStyle;
|
||||
import android.view.View;
|
||||
|
||||
import org.joinmastodon.android.model.Hashtag;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
public class LinkSpan extends CharacterStyle {
|
||||
|
@ -14,17 +15,15 @@ public class LinkSpan extends CharacterStyle {
|
|||
private String link;
|
||||
private Type type;
|
||||
private String accountID;
|
||||
private Object linkObject;
|
||||
private String text;
|
||||
|
||||
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID){
|
||||
this(link, listener, type, accountID, null);
|
||||
}
|
||||
|
||||
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, String text){
|
||||
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, Object linkObject, String text){
|
||||
this.listener=listener;
|
||||
this.link=link;
|
||||
this.type=type;
|
||||
this.accountID=accountID;
|
||||
this.linkObject=linkObject;
|
||||
this.text=text;
|
||||
}
|
||||
|
||||
|
@ -42,7 +41,12 @@ public class LinkSpan extends CharacterStyle {
|
|||
switch(getType()){
|
||||
case URL -> UiUtils.openURL(context, accountID, link);
|
||||
case MENTION -> UiUtils.openProfileByID(context, accountID, link);
|
||||
case HASHTAG -> UiUtils.openHashtagTimeline(context, accountID, link, null);
|
||||
case HASHTAG -> {
|
||||
if(linkObject instanceof Hashtag ht)
|
||||
UiUtils.openHashtagTimeline(context, accountID, ht);
|
||||
else
|
||||
UiUtils.openHashtagTimeline(context, accountID, text);
|
||||
}
|
||||
case CUSTOM -> listener.onLinkClick(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ import org.joinmastodon.android.model.AccountField;
|
|||
import org.joinmastodon.android.model.Emoji;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.Notification;
|
||||
import org.joinmastodon.android.model.Hashtag;
|
||||
import org.joinmastodon.android.model.Relationship;
|
||||
import org.joinmastodon.android.model.ScheduledStatus;
|
||||
import org.joinmastodon.android.model.SearchResults;
|
||||
|
@ -445,12 +446,18 @@ public class UiUtils {
|
|||
Nav.go((Activity) context, ProfileFragment.class, args);
|
||||
}
|
||||
|
||||
public static void openHashtagTimeline(Context context, String accountID, String hashtag, @Nullable Boolean following) {
|
||||
Bundle args = new Bundle();
|
||||
public static void openHashtagTimeline(Context context, String accountID, Hashtag hashtag){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putString("hashtag", hashtag);
|
||||
if (following != null) args.putBoolean("following", following);
|
||||
Nav.go((Activity) context, HashtagTimelineFragment.class, args);
|
||||
args.putParcelable("hashtag", Parcels.wrap(hashtag));
|
||||
Nav.go((Activity)context, HashtagTimelineFragment.class, args);
|
||||
}
|
||||
|
||||
public static void openHashtagTimeline(Context context, String accountID, String hashtag){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putString("hashtagName", hashtag);
|
||||
Nav.go((Activity)context, HashtagTimelineFragment.class, args);
|
||||
}
|
||||
|
||||
public static void showConfirmationAlert(Context context, @StringRes int title, @StringRes int message, @StringRes int confirmButton, Runnable onConfirmed) {
|
||||
|
@ -1157,7 +1164,7 @@ public class UiUtils {
|
|||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(new GetSearchResults(query.getQuery(), type, true).setCallback(new Callback<>() {
|
||||
return Optional.of(new GetSearchResults(query.getQuery(), type, true, null, 0, 0).setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(SearchResults results) {
|
||||
Optional<T> result = extractResult.apply(results);
|
||||
|
@ -1254,7 +1261,7 @@ public class UiUtils {
|
|||
}
|
||||
public static MastodonAPIRequest<SearchResults> lookupAccountHandle(Context context, String accountID, Pair<String, Optional<String>> queryHandle, BiConsumer<Class<? extends Fragment>, Bundle> go) {
|
||||
String fullHandle = ("@" + queryHandle.first) + (queryHandle.second.map(domain -> "@" + domain).orElse(""));
|
||||
return new GetSearchResults(fullHandle, GetSearchResults.Type.ACCOUNTS, true)
|
||||
return new GetSearchResults(fullHandle, GetSearchResults.Type.ACCOUNTS, true, null, 0, 0)
|
||||
.setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(SearchResults results) {
|
||||
|
@ -1317,7 +1324,7 @@ public class UiUtils {
|
|||
})
|
||||
.execNoAuth(uri.getHost()));
|
||||
} else if (looksLikeFediverseUrl(url)) {
|
||||
return Optional.of(new GetSearchResults(url, null, true)
|
||||
return Optional.of(new GetSearchResults(url, null, true, null, 0, 0)
|
||||
.setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(SearchResults results) {
|
||||
|
|
|
@ -15,15 +15,12 @@ import android.widget.TextView;
|
|||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.search.GetSearchResults;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Emoji;
|
||||
import org.joinmastodon.android.model.Hashtag;
|
||||
import org.joinmastodon.android.model.SearchResults;
|
||||
import org.joinmastodon.android.model.viewmodel.AccountViewModel;
|
||||
import org.joinmastodon.android.ui.BetterItemAnimator;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
import org.joinmastodon.android.ui.utils.HideableSingleViewRecyclerAdapter;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.ui.views.FilterChipView;
|
||||
|
@ -96,6 +93,24 @@ public class ComposeAutocompleteViewController{
|
|||
outRect.right=V.dp(8);
|
||||
}
|
||||
});
|
||||
// Set empty adapter to prevent NPEs
|
||||
list.setAdapter(new RecyclerView.Adapter<>(){
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(){
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
contentView.addView(list, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
emptyButton=new FilterChipView(activity);
|
||||
|
@ -222,11 +237,13 @@ public class ComposeAutocompleteViewController{
|
|||
}
|
||||
|
||||
private void doSearchUsers(){
|
||||
currentRequest=new GetSearchResults(lastText, GetSearchResults.Type.ACCOUNTS, false)
|
||||
currentRequest=new GetSearchResults(lastText, GetSearchResults.Type.ACCOUNTS, false, null, 0, 0)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(SearchResults result){
|
||||
currentRequest=null;
|
||||
if(mode!=Mode.USERS)
|
||||
return;
|
||||
List<AccountViewModel> oldList=users;
|
||||
users=result.accounts.stream().map(a->new AccountViewModel(a, accountID)).collect(Collectors.toList());
|
||||
if(isLoading){
|
||||
|
@ -256,7 +273,7 @@ public class ComposeAutocompleteViewController{
|
|||
}
|
||||
|
||||
private void doSearchHashtags(){
|
||||
currentRequest=new GetSearchResults(lastText, GetSearchResults.Type.HASHTAGS, false)
|
||||
currentRequest=new GetSearchResults(lastText, GetSearchResults.Type.HASHTAGS, false, null, 0, 0)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(SearchResults result){
|
||||
|
|
|
@ -75,14 +75,14 @@ public class ComposePollViewController{
|
|||
|
||||
Instance instance=fragment.instance;
|
||||
if (!instance.isAkkoma()) {
|
||||
if(instance.configuration!=null && instance.configuration.polls!=null && instance.configuration.polls.maxOptions>0)
|
||||
if(instance!=null && instance.configuration!=null && instance.configuration.polls!=null && instance.configuration.polls.maxOptions>0)
|
||||
maxPollOptions=instance.configuration.polls.maxOptions;
|
||||
if(instance.configuration!=null && instance.configuration.polls!=null && instance.configuration.polls.maxCharactersPerOption>0)
|
||||
if(instance!=null && instance.configuration!=null && instance.configuration.polls!=null && instance.configuration.polls.maxCharactersPerOption>0)
|
||||
maxPollOptionLength=instance.configuration.polls.maxCharactersPerOption;
|
||||
} else {
|
||||
if (instance.pollLimits!=null && instance.pollLimits.maxOptions>0)
|
||||
if(instance!=null && instance.pollLimits!=null && instance.pollLimits.maxOptions>0)
|
||||
maxPollOptions=instance.pollLimits.maxOptions;
|
||||
if(instance.pollLimits!=null && instance.pollLimits.maxOptionChars>0)
|
||||
if(instance!=null && instance.pollLimits!=null && instance.pollLimits.maxOptionChars>0)
|
||||
maxPollOptionLength=instance.pollLimits.maxOptionChars;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ public class MediaGridLayout extends ViewGroup{
|
|||
|
||||
private static final int GAP=2; // dp
|
||||
private PhotoLayoutHelper.TiledLayoutResult tiledLayout;
|
||||
private int[] columnStarts=new int[10], columnEnds=new int[10], rowStarts=new int[10], rowEnds=new int[10];
|
||||
private int[] columnStarts, columnEnds, rowStarts, rowEnds;
|
||||
|
||||
public MediaGridLayout(Context context){
|
||||
this(context, null);
|
||||
|
@ -41,6 +41,14 @@ public class MediaGridLayout extends ViewGroup{
|
|||
width=Math.round(width*(tiledLayout.width/(float)PhotoLayoutHelper.MAX_WIDTH));
|
||||
}
|
||||
|
||||
if(rowStarts==null || rowStarts.length<tiledLayout.rowSizes.length){
|
||||
rowStarts=new int[tiledLayout.rowSizes.length];
|
||||
rowEnds=new int[tiledLayout.rowSizes.length];
|
||||
}
|
||||
if(columnStarts==null || columnStarts.length<tiledLayout.columnSizes.length){
|
||||
columnStarts=new int[tiledLayout.columnSizes.length];
|
||||
columnEnds=new int[tiledLayout.columnSizes.length];
|
||||
}
|
||||
int offset=0;
|
||||
for(int i=0;i<tiledLayout.columnSizes.length;i++){
|
||||
columnStarts[i]=offset;
|
||||
|
@ -73,7 +81,7 @@ public class MediaGridLayout extends ViewGroup{
|
|||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b){
|
||||
if(tiledLayout==null)
|
||||
if(tiledLayout==null || rowStarts==null)
|
||||
return;
|
||||
|
||||
int maxWidth=UiUtils.MAX_WIDTH;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11,17H13V11H11ZM12,9Q12.425,9 12.713,8.712Q13,8.425 13,8Q13,7.575 12.713,7.287Q12.425,7 12,7Q11.575,7 11.288,7.287Q11,7.575 11,8Q11,8.425 11.288,8.712Q11.575,9 12,9ZM12,22Q8.525,21.125 6.263,18.012Q4,14.9 4,11.1V5L12,2L20,5V11.1Q20,14.9 17.738,18.012Q15.475,21.125 12,22ZM12,19.9Q14.6,19.075 16.3,16.6Q18,14.125 18,11.1V6.375L12,4.125L6,6.375V11.1Q6,14.125 7.7,16.6Q9.4,19.075 12,19.9ZM12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M2,14Q1.175,14 0.588,13.412Q0,12.825 0,12V6Q0,5.7 0.125,5.425Q0.25,5.15 0.45,4.95L5.4,0L6.15,0.75Q6.3,0.9 6.4,1.137Q6.5,1.375 6.5,1.6V1.8L5.8,5H11Q11.425,5 11.713,5.287Q12,5.575 12,6V7.25Q12,7.4 11.975,7.537Q11.95,7.675 11.9,7.8L9.65,13.1Q9.475,13.525 9.088,13.762Q8.7,14 8.25,14ZM7.95,12 L10,7.15V7Q10,7 10,7Q10,7 10,7H3.35L3.95,4.3L2,6.2V12Q2,12 2,12Q2,12 2,12ZM18.6,24 L17.85,23.25Q17.7,23.1 17.6,22.863Q17.5,22.625 17.5,22.4V22.2L18.2,19H13Q12.575,19 12.288,18.712Q12,18.425 12,18V16.75Q12,16.6 12.025,16.462Q12.05,16.325 12.1,16.2L14.35,10.9Q14.55,10.475 14.925,10.238Q15.3,10 15.75,10H22Q22.825,10 23.413,10.587Q24,11.175 24,12V18Q24,18.3 23.888,18.562Q23.775,18.825 23.55,19.05ZM16.05,12 L14,16.85V17Q14,17 14,17Q14,17 14,17H20.65L20.05,19.7L22,17.8V12Q22,12 22,12Q22,12 22,12ZM2,12V6.2V7Q2,7 2,7Q2,7 2,7V7.15V12Q2,12 2,12Q2,12 2,12ZM22,12V17.8V17Q22,17 22,17Q22,17 22,17V16.85V12Q22,12 22,12Q22,12 22,12Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toStartOf="@id/follow_btn_wrap"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAppearance="@style/m3_headline_small"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
android:maxLines="4"
|
||||
android:ellipsize="end"
|
||||
android:minHeight="48dp"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="#CatsOfMastodonButLong"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/follow_btn_wrap"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@id/title"
|
||||
android:layout_alignBottom="@id/title"
|
||||
android:layout_alignParentEnd="true">
|
||||
|
||||
<org.joinmastodon.android.ui.views.ProgressBarButton
|
||||
android:id="@+id/profile_action_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
style="@style/Widget.Mastodon.M3.Button.Filled"
|
||||
android:paddingHorizontal="16dp"
|
||||
tools:text="@string/button_follow" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/action_progress"
|
||||
style="?android:progressBarStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:elevation="10dp"
|
||||
android:indeterminate="true"
|
||||
android:outlineProvider="none"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
tools:text="123 posts"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -1,13 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/pin"
|
||||
android:title="@string/sk_pin_timeline"
|
||||
android:icon="@drawable/ic_fluent_pin_24_regular"
|
||||
android:showAsAction="always" />
|
||||
<item
|
||||
android:id="@+id/pin"
|
||||
android:title="@string/sk_pin_timeline"
|
||||
android:showAsAction="always"
|
||||
android:icon="@drawable/ic_fluent_pin_24_regular" />
|
||||
<item
|
||||
android:id="@+id/follow_hashtag"
|
||||
android:icon="@drawable/ic_fluent_person_add_24_regular"
|
||||
android:showAsAction="always"
|
||||
android:title="@string/button_follow"/>
|
||||
</menu>
|
|
@ -8,7 +8,7 @@
|
|||
<string name="ok">حسنًا</string>
|
||||
<string name="preparing_auth">جَارٍ الإعدَادُ لِلمُصادَقَة…</string>
|
||||
<string name="finishing_auth">يُنهي المصادقة…</string>
|
||||
<string name="user_boosted">%s إعادة نشر</string>
|
||||
<string name="user_boosted">قام %s بإعادة نشر</string>
|
||||
<string name="in_reply_to">ردًا على %s</string>
|
||||
<string name="notifications">الإشعارات</string>
|
||||
<string name="user_followed_you">%s بَدَأ بِمُتابَعَتِك</string>
|
||||
|
@ -242,7 +242,7 @@
|
|||
<string name="skip">تخطى</string>
|
||||
<string name="notification_type_follow">متابعُون جُدُد</string>
|
||||
<string name="notification_type_favorite">المفضلة</string>
|
||||
<string name="notification_type_reblog">المشاركات</string>
|
||||
<string name="notification_type_reblog">المعاد نشرها</string>
|
||||
<string name="notification_type_mention">الإشارات</string>
|
||||
<string name="notification_type_poll">استطلاع رأي</string>
|
||||
<string name="choose_account">اختر حسابًا</string>
|
||||
|
@ -277,7 +277,7 @@
|
|||
<string name="more_options">مزيد من الخيارات</string>
|
||||
<string name="new_post">منشور جديد</string>
|
||||
<string name="button_reply">ردّ</string>
|
||||
<string name="button_reblog">شارك</string>
|
||||
<string name="button_reblog">إعادة النشر</string>
|
||||
<string name="button_favorite">فضّل</string>
|
||||
<string name="button_share">شارك</string>
|
||||
<string name="media_no_description">وسائط بدون وصف</string>
|
||||
|
@ -292,8 +292,8 @@
|
|||
<string name="followed_user">أنت تتابع الآن %s</string>
|
||||
<string name="following_user_requested">طَلَبَ %s مُتابَعتك</string>
|
||||
<string name="open_in_browser">افتح في المتصفح</string>
|
||||
<string name="hide_boosts_from_user">اخف مشاركات %s</string>
|
||||
<string name="show_boosts_from_user">أظهر مشاركات %s</string>
|
||||
<string name="hide_boosts_from_user">أخفِ المعاد نشرها مِن %s</string>
|
||||
<string name="show_boosts_from_user">أظهر ما أعاد %s نشرَه</string>
|
||||
<string name="signup_reason">لماذا تريد الانضمام؟</string>
|
||||
<string name="signup_reason_note">هذا سوف يساعدنا في مراجعة تطبيقك.</string>
|
||||
<string name="clear">امسح</string>
|
||||
|
@ -346,10 +346,10 @@
|
|||
<item quantity="other">%,d تفضيل</item>
|
||||
</plurals>
|
||||
<plurals name="x_reblogs">
|
||||
<item quantity="zero">%,d إعادة نشر</item>
|
||||
<item quantity="zero">لم يُعد نشره</item>
|
||||
<item quantity="one">إعادة نشر واحدة</item>
|
||||
<item quantity="two">أعيد نشره مرّتان</item>
|
||||
<item quantity="few">أعيد نشره %,d مرة</item>
|
||||
<item quantity="few">أعيد نشره %,d مرات</item>
|
||||
<item quantity="many">أعيد نشره %,d مرات</item>
|
||||
<item quantity="other">أعيد نشره %,d مرات</item>
|
||||
</plurals>
|
||||
|
@ -698,4 +698,18 @@
|
|||
<string name="time_minutes_ago_short">مُنذُ %dد</string>
|
||||
<string name="time_hours_ago_short">مُنذُ %dسا</string>
|
||||
<string name="time_days_ago_short">مُنذُ %d أيام</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">تُرجِم مِن %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">مُترجَم مِن %1$s باستخدام %2$s</string>
|
||||
<string name="translation_show_original">إظهار الأصل</string>
|
||||
<string name="translation_failed">فشِلَت الترجَمة. قد لم يتمكّن مدير الخادم من تفعيل الترجمات على هذا الخادم أو أنّ هذا الخادم يُشغِّل نسخة قديمة من ماستدون حيث الترجمات غير مدعومة بعد.</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="zero">لا مُشارِك</item>
|
||||
<item quantity="one">مشارِك واحد</item>
|
||||
<item quantity="two">مشاركَيْنِ</item>
|
||||
<item quantity="few">مشاركين</item>
|
||||
<item quantity="many">مُشارِكًا</item>
|
||||
<item quantity="other">مُشارك</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -527,4 +527,6 @@
|
|||
<string name="time_minutes_ago_short">%d хв таму</string>
|
||||
<string name="time_hours_ago_short">%d г таму</string>
|
||||
<string name="time_days_ago_short">%d дз таму</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -199,4 +199,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -182,4 +182,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -293,4 +293,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -639,4 +639,6 @@
|
|||
<string name="time_minutes_ago_short">Před %dm</string>
|
||||
<string name="time_hours_ago_short">Před %dh</string>
|
||||
<string name="time_days_ago_short">Před %dd</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -503,4 +503,6 @@
|
|||
<string name="search_open_url">Åbn URL i Mastodon</string>
|
||||
<string name="posts_matching_hashtag">Indlæg med “%s”</string>
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -582,4 +582,6 @@
|
|||
<string name="time_minutes_ago_short">vor %d Minuten</string>
|
||||
<string name="time_hours_ago_short">vor %d Stunden</string>
|
||||
<string name="time_days_ago_short">vor %d Tagen</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -387,6 +387,7 @@
|
|||
<string name="welcome_to_mastodon">Καλώς ήρθες στο Mastodon</string>
|
||||
<string name="welcome_paragraph1">Το Mastodon είναι ένα αποκεντρωμένο κοινωνικό δίκτυο που σημαίνει ότι καμία εταιρεία δεν το ελέγχει. Αποτελείται από πολλούς ανεξάρτητους διακομιστές, όλοι συνδεδεμένοι μαζί.</string>
|
||||
<string name="what_are_servers">Τι είναι οι διακομιστές;</string>
|
||||
<string name="welcome_paragraph2">Κάθε λογαριασμός Mastodon φιλοξενείται σε ένα διακομιστή - ο καθένας με τις δικές του αξίες, κανόνες & διαχειριστές. Ανεξάρτητα από το ποιον μπορεί να επιλέξεις, μπορείς να ακολουθήσεις και να αλληλεπιδράσεις με άτομα από οποιονδήποτε διακομιστή.</string>
|
||||
<string name="opening_link">Άνοιγμα συνδέσμου…</string>
|
||||
<string name="link_not_supported">Αυτός ο σύνδεσμος δεν υποστηρίζεται στην εφαρμογή</string>
|
||||
<string name="log_out_all_accounts">Αποσύνδεση από όλους τους λογαριασμούς</string>
|
||||
|
@ -581,4 +582,21 @@
|
|||
<string name="time_minutes_ago_short">%dλ πριν</string>
|
||||
<string name="time_hours_ago_short">%dώ πριν</string>
|
||||
<string name="time_days_ago_short">%dημ πριν</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Μετάφραση από %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">Μεταφράστηκε από %1$s χρησιμοποιώντας %2$s</string>
|
||||
<string name="translation_show_original">Εμφάνιση αρχικού</string>
|
||||
<string name="translation_failed">Η μετάφραση απέτυχε. Ίσως ο διαχειριστής δεν έχει ενεργοποιήσει μεταφράσεις σε αυτόν τον διακομιστή ή αυτός ο διακομιστής εκτελεί μια παλαιότερη έκδοση του Mastodon όπου οι μεταφράσεις δεν υποστηρίζονται ακόμα.</string>
|
||||
<string name="settings_privacy">Ιδιωτικότητα και προσιτότητα</string>
|
||||
<string name="settings_discoverable">Παροχή προφίλ και δημοσιεύσεων σε αλγορίθμους ανακάλυψης</string>
|
||||
<string name="settings_indexable">Συμπερίληψη δημόσιων αναρτήσεων στα αποτελέσματα αναζήτησης</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="one">%,d συμμετέχων</item>
|
||||
<item quantity="other">%,d συμμετέχοντες</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="one">%,d ανάρτηση σήμερα</item>
|
||||
<item quantity="other">%,d αναρτήσεις σήμερα</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -573,4 +573,6 @@
|
|||
<string name="time_minutes_ago_short">hace %dm</string>
|
||||
<string name="time_hours_ago_short">hace %dh</string>
|
||||
<string name="time_days_ago_short">hace %dd</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -441,4 +441,6 @@
|
|||
<string name="clear_all">Garbitu dena</string>
|
||||
<string name="search_open_url">Ireki URLa Mastodonen</string>
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -387,6 +387,7 @@
|
|||
<string name="welcome_to_mastodon">به ماستودون خوش آمدید</string>
|
||||
<string name="welcome_paragraph1">ماستودون یک شبکه اجتماعی غیر متمرکز است،به این معنی که هیچ شرکتی آن را کنترل نمی کند. این از بسیاری از کارسازهای مستقل تشکیل شده است که همه به هم متصل هستند.</string>
|
||||
<string name="what_are_servers">کارساز شما کجاست؟</string>
|
||||
<string name="welcome_paragraph2">هر حساب ماستودون بر روی یک سرور میزبانی می شود — هر کدام با مقادیر، قوانین، & مدیران خاص خود. مهم نیست کدام یک را انتخاب می کنید، می توانید افراد را در هر کارسازی دنبال کنید و با آنها تعامل داشته باشید.</string>
|
||||
<string name="opening_link">باز کردن پیوند…</string>
|
||||
<string name="link_not_supported">این پیوند در کاره پشتیبانی نمی شود</string>
|
||||
<string name="log_out_all_accounts">از همه حسابها خارج شوید</string>
|
||||
|
@ -581,4 +582,21 @@
|
|||
<string name="time_minutes_ago_short">%dدقيقه پيش</string>
|
||||
<string name="time_hours_ago_short">%dساعت پيش</string>
|
||||
<string name="time_days_ago_short">%dروز پیش</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">ترجمه از %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">ترجمه از %1$s با %2$s</string>
|
||||
<string name="translation_show_original">نمایش اصلی</string>
|
||||
<string name="translation_failed">ترجمه ناموفق بود. شاید مدیر ترجمهها را در این کارساز فعال نکرده باشد یا این کارساز نسخه قدیمی ماستودون را اجرا می کند که در آن ترجمهها هنوز پشتیبانی نمی شوند.</string>
|
||||
<string name="settings_privacy">محرمانگی و دسترسی</string>
|
||||
<string name="settings_discoverable">مشخص کردن مشخصات و فرستهها در الگوریتمهای اکتشاف</string>
|
||||
<string name="settings_indexable">قرار دادن فرستههای عمومی در نتایج جستجو</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="one">%,d شرکت کننده</item>
|
||||
<item quantity="other">%,d شرکتکننده</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="one">%,d فرسته امروز</item>
|
||||
<item quantity="other">%,d فرسته امروز</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -2,13 +2,167 @@
|
|||
<resources>
|
||||
<string name="log_in">Kirjaudu sisään</string>
|
||||
<string name="next">Seuraava</string>
|
||||
<string name="loading_instance">Haetaan palvelimen tietoja…</string>
|
||||
<string name="error">Virhe</string>
|
||||
<string name="not_a_mastodon_instance">%s ei näytä olevan Mastodonin palvelin.</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="preparing_auth">Valmistellaan todennusta…</string>
|
||||
<string name="finishing_auth">Viimeistellään todennusta…</string>
|
||||
<string name="user_boosted">%s tehosti</string>
|
||||
<string name="in_reply_to">Vastauksessa %s</string>
|
||||
<string name="notifications">Ilmoitukset</string>
|
||||
<string name="user_followed_you">%s seurasi sinua</string>
|
||||
<string name="user_sent_follow_request">%s lähetti sinulle seurauspyynnön</string>
|
||||
<string name="user_favorited">%s tykkäsi julkaisustasi</string>
|
||||
<string name="notification_boosted">%s tehosti viestiäsi</string>
|
||||
<string name="poll_ended">Katso tulokset äänestyksestä johon osallistuit</string>
|
||||
<string name="share_toot_title">Jaa</string>
|
||||
<string name="settings">Asetukset</string>
|
||||
<string name="publish">Julkaise</string>
|
||||
<string name="discard_draft">Hylkää luonnos?</string>
|
||||
<string name="discard">Hylkää</string>
|
||||
<string name="cancel">Kumoa</string>
|
||||
<plurals name="followers">
|
||||
<item quantity="one">seuraaja</item>
|
||||
<item quantity="other">seuraajat</item>
|
||||
</plurals>
|
||||
<plurals name="following">
|
||||
<item quantity="one">seurataan</item>
|
||||
<item quantity="other">seurataan</item>
|
||||
</plurals>
|
||||
<string name="posts">Viestit</string>
|
||||
<string name="posts_and_replies">Viestit ja vastaukset</string>
|
||||
<string name="media">Media</string>
|
||||
<string name="profile_about">Tietoja</string>
|
||||
<string name="button_follow">Seuraa</string>
|
||||
<string name="button_following">Seurataan</string>
|
||||
<string name="edit_profile">Muokkaa profiilia</string>
|
||||
<string name="share_user">Jaa profiili</string>
|
||||
<string name="mute_user">Mykistä %s</string>
|
||||
<string name="unmute_user">Poista mykistys tililtä %s</string>
|
||||
<string name="block_user">Estä %s</string>
|
||||
<string name="unblock_user">Poista käyttäjän %s esto</string>
|
||||
<string name="report_user">Raportoi %s</string>
|
||||
<string name="block_domain">Estä %s</string>
|
||||
<string name="unblock_domain">Poista käyttäjän %s esto</string>
|
||||
<plurals name="x_posts">
|
||||
<item quantity="one">%,d julkaisu</item>
|
||||
<item quantity="other">%,d julkaisua</item>
|
||||
</plurals>
|
||||
<string name="profile_joined">Liittynyt</string>
|
||||
<string name="done">Valmis</string>
|
||||
<string name="loading">Ladataan…</string>
|
||||
<string name="field_label">Nimi</string>
|
||||
<string name="field_content">Sisältö</string>
|
||||
<string name="saving">Tallennetaan…</string>
|
||||
<string name="post_from_user">Julkaisu tililtä %s</string>
|
||||
<string name="poll_option_hint">Vaihtoehto %d</string>
|
||||
<plurals name="x_minutes">
|
||||
<item quantity="one">%d minuutti</item>
|
||||
<item quantity="other">%d minuuttia</item>
|
||||
</plurals>
|
||||
<plurals name="x_hours">
|
||||
<item quantity="one">%d tunti</item>
|
||||
<item quantity="other">%d tuntia</item>
|
||||
</plurals>
|
||||
<plurals name="x_days">
|
||||
<item quantity="one">%d päivä</item>
|
||||
<item quantity="other">%d päivää</item>
|
||||
</plurals>
|
||||
<plurals name="x_seconds_left">
|
||||
<item quantity="one">%d sekunti jäljellä</item>
|
||||
<item quantity="other">%d sekunttia jäljellä</item>
|
||||
</plurals>
|
||||
<plurals name="x_minutes_left">
|
||||
<item quantity="one">%d minuutti jäljellä</item>
|
||||
<item quantity="other">%d minuuttia jäljellä</item>
|
||||
</plurals>
|
||||
<plurals name="x_hours_left">
|
||||
<item quantity="one">%d tunti jäljellä</item>
|
||||
<item quantity="other">%d tuntia jäljellä</item>
|
||||
</plurals>
|
||||
<plurals name="x_days_left">
|
||||
<item quantity="one">%d päivä jäljellä</item>
|
||||
<item quantity="other">%d päivää jäljellä</item>
|
||||
</plurals>
|
||||
<plurals name="x_votes">
|
||||
<item quantity="one">%d ääni</item>
|
||||
<item quantity="other">%d ääntä</item>
|
||||
</plurals>
|
||||
<string name="poll_closed">Suljettu</string>
|
||||
<string name="confirm_mute_title">Mykistä tili</string>
|
||||
<string name="confirm_mute">Vahvista käyttäjän %s mykistys</string>
|
||||
<string name="do_mute">Mykistä</string>
|
||||
<string name="confirm_unmute_title">Poista tilin mykistys</string>
|
||||
<string name="confirm_unmute">Vahvista, että haluat poistaa mykistyksen tililtä %s</string>
|
||||
<string name="do_unmute">Poista mykistys</string>
|
||||
<string name="confirm_block_title">Estä tili</string>
|
||||
<string name="confirm_block_domain_title">Estä verkkotunnus</string>
|
||||
<string name="confirm_block">Vahvista käyttäjän %s esto</string>
|
||||
<string name="do_block">Estä</string>
|
||||
<string name="confirm_unblock_title">Poista tilin esto</string>
|
||||
<string name="confirm_unblock_domain_title">Poista verkkotunnuksen esto</string>
|
||||
<string name="confirm_unblock">Vahvista, että haluat poistaa tilin %s eston</string>
|
||||
<string name="do_unblock">Poista esto</string>
|
||||
<string name="button_blocked">Estetty</string>
|
||||
<string name="action_vote">Äänestä</string>
|
||||
<string name="delete">Poista</string>
|
||||
<string name="confirm_delete_title">Poista julkaisu</string>
|
||||
<string name="confirm_delete">Haluatko varmasti poistaa tämän julkaisun?</string>
|
||||
<string name="deleting">Poistetaan…</string>
|
||||
<string name="notification_channel_audio_player">Äänen toisto</string>
|
||||
<string name="play">Toista</string>
|
||||
<string name="pause">Tauko</string>
|
||||
<string name="log_out">Kirjaudu ulos</string>
|
||||
<string name="add_account">Lisää tili</string>
|
||||
<string name="search_hint">Haku</string>
|
||||
<string name="hashtags">Aihetunnisteet</string>
|
||||
<string name="news">Uutiset</string>
|
||||
<string name="for_you">Sinulle</string>
|
||||
<string name="all_notifications">Kaikki</string>
|
||||
<string name="mentions">Maininnat</string>
|
||||
<plurals name="x_people_talking">
|
||||
<item quantity="one">%d henkilö puhuu</item>
|
||||
<item quantity="other">%d henkilöä puhuu</item>
|
||||
</plurals>
|
||||
<string name="report_title">Raportoi %s</string>
|
||||
<string name="report_choose_reason">Mikä on väärin tässä julkaisussa?</string>
|
||||
<string name="report_choose_reason_account">Mikä on vialla käyttäjässä %s?</string>
|
||||
<string name="report_choose_reason_subtitle">Valitse se, mikä sopii parhaiten</string>
|
||||
<string name="report_reason_personal">En pidä siitä</string>
|
||||
<string name="report_reason_personal_subtitle">Tätä ei halua nähdä</string>
|
||||
<string name="report_reason_spam">Se on roskapostia</string>
|
||||
<string name="report_reason_spam_subtitle">Haitalliset linkit, väärennetyt sitoutumiset tai toistuvat vastaukset</string>
|
||||
<string name="report_reason_violation">Se rikkoo palvelimen sääntöjä</string>
|
||||
<string name="report_reason_violation_subtitle">Tiedät, että se rikkoo tiettyjä sääntöjä</string>
|
||||
<string name="report_reason_other">Jotain muuta</string>
|
||||
<string name="report_reason_other_subtitle">Ongelma ei sovi muihin kategorioihin</string>
|
||||
<string name="report_choose_rule">Mitä sääntöjä rikotaan?</string>
|
||||
<string name="report_choose_rule_subtitle">Valitse kaikki sopivat</string>
|
||||
<string name="report_choose_posts">Onko julkaisuja, jotka tukevat tätä raporttia?</string>
|
||||
<string name="report_choose_posts_subtitle">Valitse kaikki sopivat</string>
|
||||
<string name="report_comment_title">Olisiko jotain muuta, mitä meidän pitäisi tietää?</string>
|
||||
<string name="report_comment_hint">Lisäkommentit</string>
|
||||
<string name="sending_report">Lähetetään raporttia…</string>
|
||||
<string name="report_sent_title">Kiitos raportista, tutkimme asiaa.</string>
|
||||
<string name="report_sent_subtitle">Sillä välin kun tarkistamme tätä, voit ryhtyä toimenpiteisiin käyttäjää @%s vastaan:</string>
|
||||
<string name="unfollow_user">Lopeta käyttäjän %s seuraaminen</string>
|
||||
<string name="unfollow">Lopeta seuraaminen</string>
|
||||
<string name="mute_user_explain">Et näe hänen viestejään. Hän voi silti seurata sinua ja nähdä viestisi. Hän ei tiedä, että on mykistetty.</string>
|
||||
<string name="block_user_explain">Et näe hänen viestejään, eikä hän voi nähdä viestejäsi tai seurata sinua. Hän näkevät, että olet estänyt hänet.</string>
|
||||
<string name="report_personal_title">Etkö halua nähdä tätä?</string>
|
||||
<string name="report_personal_subtitle">Tässä on vaihtoehtosi hallita näkemääsi Mastodonissa:</string>
|
||||
<string name="back">Takaisin</string>
|
||||
<string name="search_communities">Palvelimen nimi tai URL-osoite</string>
|
||||
<string name="instance_rules_title">Palvelimen säännöt</string>
|
||||
<string name="instance_rules_subtitle">Jatkamalla sitoudut noudattamaan seuraavia sääntöjä, jotka %s moderaattorit ovat asettaneet ja valvoneet.</string>
|
||||
<string name="signup_title">Luo tili</string>
|
||||
<string name="display_name">Nimi</string>
|
||||
<string name="username">Käyttäjätunnus</string>
|
||||
<string name="email">Sähköposti</string>
|
||||
<string name="password">Salasana</string>
|
||||
<string name="confirm_password">Vahvista salasana</string>
|
||||
<string name="password_note">Sisällytä suuraakkoset, erikoismerkit, ja numerot, jotta voit lisätä salasanan voimaa.</string>
|
||||
<string name="category_academia">Akateeminen</string>
|
||||
<string name="category_activism">Aktivismi</string>
|
||||
<string name="category_all">Kaikki</string>
|
||||
|
@ -22,39 +176,424 @@
|
|||
<string name="category_music">Musiikki</string>
|
||||
<string name="category_regional">Alueellinen</string>
|
||||
<string name="category_tech">Teknologia</string>
|
||||
<string name="confirm_email_title">Tarkista sähköpostisi</string>
|
||||
<!-- %s is the email address -->
|
||||
<string name="confirm_email_subtitle">Napauta lähettämäämme linkkiä vahvistaaksesi tunnuksen %s. Odotamme täällä.</string>
|
||||
<string name="confirm_email_didnt_get">Etkö saanut linkkiä?</string>
|
||||
<string name="resend">Lähetä uudelleen</string>
|
||||
<string name="open_email_app">Avaa sähköpostiohjelma</string>
|
||||
<string name="resent_email">Vahvistusviesti lähetetty</string>
|
||||
<string name="compose_hint">Kirjoita tai liitä mitä mietit</string>
|
||||
<string name="content_warning">Sisältövaroitus</string>
|
||||
<string name="save">Tallenna</string>
|
||||
<string name="add_alt_text">Lisää selitys</string>
|
||||
<string name="visibility_public">Julkinen</string>
|
||||
<string name="visibility_followers_only">Vain seuraajat</string>
|
||||
<string name="visibility_private">Vain mainitsemani tilit</string>
|
||||
<string name="recent_searches">Viimeisimmät</string>
|
||||
<string name="skip">Ohita</string>
|
||||
<string name="notification_type_follow">Uudet seuraajat</string>
|
||||
<string name="notification_type_favorite">Suosikit</string>
|
||||
<string name="notification_type_reblog">Tehostukset</string>
|
||||
<string name="notification_type_mention">Maininnat</string>
|
||||
<string name="notification_type_poll">Kyselyt</string>
|
||||
<string name="choose_account">Valitse tili</string>
|
||||
<string name="err_not_logged_in">Kirjaudu ensin Mastodoniin</string>
|
||||
<plurals name="cant_add_more_than_x_attachments">
|
||||
<item quantity="one">Et voi lisätä enempää kuin %d medialiitteen</item>
|
||||
<item quantity="other">Et voi lisätä enempää kuin %d medialiitettä</item>
|
||||
</plurals>
|
||||
<string name="media_attachment_unsupported_type">Tiedosto %s on tyyppiä jota ei tueta</string>
|
||||
<string name="media_attachment_too_big">Tiedosto %1$s ylittää %2$s MB kokorajan</string>
|
||||
<string name="settings_theme">Ulkoasu</string>
|
||||
<string name="theme_auto">Käytä laitteen ulkoasua</string>
|
||||
<string name="theme_light">Vaalea</string>
|
||||
<string name="theme_dark">Tumma</string>
|
||||
<string name="settings_behavior">Toiminnot</string>
|
||||
<string name="settings_gif">Toista animoidut käyttäjäkuvat ja emojit</string>
|
||||
<string name="settings_custom_tabs">Käytä sovelluksen sisäistä selainta</string>
|
||||
<string name="settings_notifications">Ilmoitukset</string>
|
||||
<string name="settings_contribute">Osallistu Mastodoniin</string>
|
||||
<string name="settings_tos">Käyttöehdot</string>
|
||||
<string name="settings_privacy_policy">Tietosuojakäytäntö</string>
|
||||
<string name="settings_clear_cache">Tyhjennä median välimuisti</string>
|
||||
<string name="settings_app_version">Mastodon Android v%1$s (%2$d)</string>
|
||||
<string name="media_cache_cleared">Median välimuisti tyhjennetty</string>
|
||||
<string name="confirm_log_out">Kirjaudu ulos %s?</string>
|
||||
<string name="sensitive_content_explain">Kirjoittaja merkitsi tämän median arkaluontoiseksi.</string>
|
||||
<string name="avatar_description">Avaa profiili %s</string>
|
||||
<string name="more_options">Lisää asetuksia</string>
|
||||
<string name="new_post">Uusi julkaisu</string>
|
||||
<string name="button_reply">Vastaa</string>
|
||||
<string name="button_reblog">Tehosta</string>
|
||||
<string name="button_favorite">Suosikki</string>
|
||||
<string name="button_share">Jaa</string>
|
||||
<string name="media_no_description">Kuva ilma kuvausta</string>
|
||||
<string name="add_media">Lisää mediatiedosto</string>
|
||||
<string name="add_poll">Lisää kysely</string>
|
||||
<string name="emoji">Emoji</string>
|
||||
<string name="home_timeline">Kotiaikajana</string>
|
||||
<string name="my_profile">Oma profiili</string>
|
||||
<string name="media_viewer">Median katselin</string>
|
||||
<string name="follow_user">Follow %s</string>
|
||||
<string name="unfollowed_user">Käyttäjän %s seuraaminen lopetettu</string>
|
||||
<string name="followed_user">Seuraat nyt käyttäjää %s</string>
|
||||
<string name="following_user_requested">Käyttäjän %s seuraamista pyydetty</string>
|
||||
<string name="open_in_browser">Avaa selaimessa</string>
|
||||
<string name="hide_boosts_from_user">Piilota käyttäjän @%s tehostukset</string>
|
||||
<string name="show_boosts_from_user">Näytä tehostukset käyttäjältä @%s</string>
|
||||
<string name="signup_reason">Miksi haluat liittyä?</string>
|
||||
<string name="signup_reason_note">Tämä auttaa meitä arvioimaan hakemustasi.</string>
|
||||
<string name="clear">Tyhjennä</string>
|
||||
<string name="profile_header">Otsikon kuva</string>
|
||||
<string name="profile_picture">Profiilikuva</string>
|
||||
<string name="reorder">Järjestä uudelleen</string>
|
||||
<string name="download">Lataa</string>
|
||||
<string name="permission_required">Käyttöoikeus vaaditaan</string>
|
||||
<string name="storage_permission_to_download">Sovellus tarvitsee pääsyn tallennustilaan, jotta voit tallentaa tämän tiedoston.</string>
|
||||
<string name="open_settings">Avaa asetukset</string>
|
||||
<string name="error_saving_file">Virhe tallennettaessa tiedostoa</string>
|
||||
<string name="file_saved">Tiedosto tallennettu</string>
|
||||
<string name="downloading">Ladataan…</string>
|
||||
<string name="no_app_to_handle_action">Tätä toimintoa käsittelevää sovellusta ei ole</string>
|
||||
<string name="local_timeline">Paikallinen</string>
|
||||
<string name="trending_posts_info_banner">Nämä julkaisut ovat saamassa vetoa eri puolilla Mastodonia.</string>
|
||||
<string name="trending_links_info_banner">Näistä uutisista puhutaan Mastodonissa.</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Nämä ovat viestit kaikilta palvelimesi (%s) käyttäjiltä.</string>
|
||||
<string name="recommended_accounts_info_banner">Muiden seuraamiesi perusteella saattaisit pitää näistä tileistä.</string>
|
||||
<string name="see_new_posts">Uusia julkaisuja</string>
|
||||
<string name="load_missing_posts">Lataa puuttuvat julkaisut</string>
|
||||
<string name="follow_back">Seuraa takaisin</string>
|
||||
<string name="button_follow_pending">Pyydetty</string>
|
||||
<string name="follows_you">Seuraa sinua</string>
|
||||
<string name="manually_approves_followers">Hyväksyy seuraajat käsin</string>
|
||||
<!-- translators: %,d is a valid placeholder, it formats the number with locale-dependent grouping separators -->
|
||||
<plurals name="x_followers">
|
||||
<item quantity="one">%d seuraaja</item>
|
||||
<item quantity="other">%d seuraajaa</item>
|
||||
</plurals>
|
||||
<plurals name="x_following">
|
||||
<item quantity="one">%d seurattu</item>
|
||||
<item quantity="other">%d seurattua</item>
|
||||
</plurals>
|
||||
<plurals name="x_favorites">
|
||||
<item quantity="one">%,d suosikki</item>
|
||||
<item quantity="other">%,d suosikkia</item>
|
||||
</plurals>
|
||||
<plurals name="x_reblogs">
|
||||
<item quantity="one">%,d tehostus</item>
|
||||
<item quantity="other">%,d tehostusta</item>
|
||||
</plurals>
|
||||
<string name="timestamp_via_app">%1$s sovelluksella %2$s</string>
|
||||
<string name="time_now">nyt</string>
|
||||
<string name="edit_history">Muokkaushistoria</string>
|
||||
<string name="last_edit_at_x">Muokattiin viimeksi %s</string>
|
||||
<string name="time_just_now">juuri nyt</string>
|
||||
<plurals name="x_seconds_ago">
|
||||
<item quantity="one">%d sekunti sitten</item>
|
||||
<item quantity="other">%d sekuntia sitten</item>
|
||||
</plurals>
|
||||
<plurals name="x_minutes_ago">
|
||||
<item quantity="one">%d minuutti sitten</item>
|
||||
<item quantity="other">%d minuuttia sitten</item>
|
||||
</plurals>
|
||||
<string name="edited_timestamp">muokattu %s</string>
|
||||
<string name="edit_original_post">Alkuperäinen viesti</string>
|
||||
<string name="edit_text_edited">Tekstiä muokattu</string>
|
||||
<string name="edit_spoiler_added">Sisältövaroitus</string>
|
||||
<string name="edit_spoiler_edited">Sisältövaroitus muokattu</string>
|
||||
<string name="edit_spoiler_removed">Sisältövaroitus poistettu</string>
|
||||
<string name="edit_poll_added">Kysely lisätty</string>
|
||||
<string name="edit_poll_edited">Kyselyä muokattu</string>
|
||||
<string name="edit_poll_removed">Kysely poistettu</string>
|
||||
<string name="edit_media_added">Mediatiedosto lisätty</string>
|
||||
<string name="edit_media_removed">Mediatiedosto poistettu</string>
|
||||
<string name="edit_media_reordered">Mediatiedostoja järjestetty</string>
|
||||
<string name="edit_marked_sensitive">Merkitty arkaluontoiseksi</string>
|
||||
<string name="edit_marked_not_sensitive">Merkitty ei arkaluontoiseksi</string>
|
||||
<string name="edit_multiple_changed">Julkaisu muokattu</string>
|
||||
<string name="edit">Muokkaa</string>
|
||||
<string name="discard_changes">Hylätäänkö muutokset?</string>
|
||||
<string name="upload_failed">Lataus epäonnistui</string>
|
||||
<string name="file_size_bytes">%d tavua</string>
|
||||
<string name="file_size_kb">%.2f KB</string>
|
||||
<string name="file_size_mb">%.2f MB</string>
|
||||
<string name="file_size_gb">%.2f GB</string>
|
||||
<string name="upload_processing">Käsitellään…</string>
|
||||
<!-- %s is version like 1.2.3 -->
|
||||
<!-- %s is version like 1.2.3 -->
|
||||
<!-- %s is file size -->
|
||||
<string name="download_update">Lataa (%s)</string>
|
||||
<string name="install_update">Asenna</string>
|
||||
<string name="privacy_policy_title">Yksityisyytesi</string>
|
||||
<string name="privacy_policy_subtitle">Vaikka Mastodon-sovellus ei kerää mitään tietoja, palvelimella, jonka olet rekisteröitynyt, voi olla eri käytäntö.\n\nJos olet eri mieltä käytännöstä %s, voit palata ja valita eri palvelin.</string>
|
||||
<string name="i_agree">Hyväksyn</string>
|
||||
<string name="empty_list">Luettelo on tyhjä</string>
|
||||
<string name="instance_signup_closed">Tämä palvelin ei hyväksy uusia rekisteröintejä.</string>
|
||||
<string name="text_copied">Kopioitu leikepöydälle</string>
|
||||
<string name="add_bookmark">Kirjanmerkki</string>
|
||||
<string name="remove_bookmark">Poista kirjanmerkki</string>
|
||||
<string name="bookmarks">Kirjanmerkit</string>
|
||||
<string name="your_favorites">Omat suosikit</string>
|
||||
<string name="login_title">Tervetuloa takaisin</string>
|
||||
<string name="login_subtitle">Kirjaudu sisään palvelimella, jossa olet luonut tilisi.</string>
|
||||
<string name="server_url">Palvelimen URL-osoite</string>
|
||||
<string name="signup_random_server_explain">Palvelin valitaan kielesi perusteella, jos jatkat ilman valintaa.</string>
|
||||
<string name="server_filter_any_language">Millä tahansa kielellä</string>
|
||||
<string name="server_filter_instant_signup">Välitön rekisteröityminen</string>
|
||||
<string name="server_filter_manual_review">Manuaalinen hyväksyntä</string>
|
||||
<string name="server_filter_any_signup_speed">Mikä tahansa rekisteröintinopeus</string>
|
||||
<string name="server_filter_region_europe">Eurooppa</string>
|
||||
<string name="server_filter_region_north_america">Pohjois-Amerikka</string>
|
||||
<string name="server_filter_region_south_america">Etelä-Amerikka</string>
|
||||
<string name="server_filter_region_africa">Afrikka</string>
|
||||
<string name="server_filter_region_asia">Aasia</string>
|
||||
<string name="server_filter_region_oceania">Oseania</string>
|
||||
<string name="not_accepting_new_members">Ei hyväksy uusia jäseniä</string>
|
||||
<string name="category_special_interests">Erityiset Kiinnostukset</string>
|
||||
<string name="signup_passwords_dont_match">Salasanat eivät täsmää</string>
|
||||
<string name="pick_server_for_me">Valitse minulle</string>
|
||||
<string name="profile_add_row">Lisää rivi</string>
|
||||
<string name="profile_setup">Profiilin asetukset</string>
|
||||
<string name="profile_setup_subtitle">Voit myös täyttää tämän myöhemmin Profiili-välilehdellä.</string>
|
||||
<string name="profile_setup_explanation">Voit lisätä enintään neljä profiilikenttää joissa on mitä haluat. Sijainti, linkit, pronominit — taivas on rajana.</string>
|
||||
<string name="popular_on_mastodon">Suosittua Mastodonissa</string>
|
||||
<string name="follow_all">Seuraa kaikkia</string>
|
||||
<string name="server_rules_disagree">Eri mieltä</string>
|
||||
<string name="privacy_policy_explanation">TL;DR: Emme kerää tai käsittele mitään.</string>
|
||||
<!-- %s is server domain -->
|
||||
<string name="server_policy_disagree">Eri mieltä tästä %s</string>
|
||||
<string name="profile_bio">Kuvaus</string>
|
||||
<!-- Shown in a progress dialog when you tap "follow all" -->
|
||||
<string name="sending_follows">Seurataan käyttäjiä…</string>
|
||||
<!-- %1$s is server domain, %2$s is email domain. You can reorder these placeholders to fit your language better. -->
|
||||
<string name="signup_email_domain_blocked">%1$s ei salli ilmoittautumisia osoitteesta %2$s. Kokeile toista osoitetta tai <a>valitse toinen palvelin</a>.</string>
|
||||
<string name="spoiler_show">Näytä joka tapauksessa</string>
|
||||
<string name="spoiler_hide">Piilota uudelleen</string>
|
||||
<string name="poll_multiple_choice">Valitse yksi tai useampi</string>
|
||||
<string name="save_changes">Tallenna muutokset</string>
|
||||
<string name="profile_featured">Suositellut</string>
|
||||
<string name="profile_timeline">Aikajana</string>
|
||||
<string name="view_all">Näytä kaikki</string>
|
||||
<string name="profile_endorsed_accounts">Tilit</string>
|
||||
<string name="verified_link">Vahvistettu linkki</string>
|
||||
<string name="show">Näytä</string>
|
||||
<string name="hide">Piilota</string>
|
||||
<string name="join_default_server">Liity palvelimelle %s</string>
|
||||
<string name="pick_server">Valitse toinen palvelin</string>
|
||||
<string name="signup_or_login">tai</string>
|
||||
<string name="learn_more">Lue lisää</string>
|
||||
<string name="welcome_to_mastodon">Tervetuloa Mastodoniin</string>
|
||||
<string name="welcome_paragraph1">Mastodon on hajautettu sosiaalinen verkosto, joka tarkoittaa sitä, ettei sitä hallitse mikään yksittäinen yritys. Se koostuu monista itsenäisesti ylläpidetyistä palvelimista, jotka on liitetty yhteen.</string>
|
||||
<string name="what_are_servers">Mitä palvelimet ovat?</string>
|
||||
<string name="welcome_paragraph2">Jokainen Mastodon tili isännöi palvelimella - kullakin on omat arvot, säännöt, & ylläpitäjät. Riippumatta siitä, minkä valitset, voit seurata ja olla vuorovaikutuksessa ihmisten kanssa millä tahansa palvelimella.</string>
|
||||
<string name="opening_link">Avataan linkki…</string>
|
||||
<string name="link_not_supported">Tämä linkki ei ole tuettu sovelluksessa</string>
|
||||
<string name="log_out_all_accounts">Kirjaudu ulos kaikista tileistä</string>
|
||||
<string name="confirm_log_out_all_accounts">Kirjaudu ulos kaikista tileistä?</string>
|
||||
<string name="retry">Yritä uudelleen</string>
|
||||
<string name="post_failed">Viestin lähettäminen epäonnistui</string>
|
||||
<!-- %s is formatted file size ("467 KB image") -->
|
||||
<string name="attachment_description_image">%s kuva</string>
|
||||
<string name="attachment_description_video">%s video</string>
|
||||
<string name="attachment_description_audio">%s ääni</string>
|
||||
<string name="attachment_description_unknown">%s tiedosto</string>
|
||||
<string name="attachment_type_image">Kuva</string>
|
||||
<string name="attachment_type_video">Video</string>
|
||||
<string name="attachment_type_audio">Ääni</string>
|
||||
<string name="attachment_type_gif">GIF</string>
|
||||
<string name="attachment_type_unknown">Tiedosto</string>
|
||||
<string name="attachment_x_percent_uploaded">%d%% ladattu</string>
|
||||
<string name="add_poll_option">Lisää kyselyyn vaihtoehto</string>
|
||||
<string name="poll_length">Kyselyn kesto</string>
|
||||
<string name="poll_style">Tyyli</string>
|
||||
<string name="compose_poll_single_choice">Valitse yksi</string>
|
||||
<string name="compose_poll_multiple_choice">Monivalinta</string>
|
||||
<string name="delete_poll_option">Poista kyselyn vaihtoehto</string>
|
||||
<string name="poll_style_title">Kyselyn tyyli</string>
|
||||
<string name="alt_text">Selitys</string>
|
||||
<string name="help">Ohje</string>
|
||||
<string name="what_is_alt_text">Mikä on selitys?</string>
|
||||
<string name="alt_text_help">Kuvaselitys auttaa ihmisiä, joilla on näkövamma, hidas yhteys, tai jotka tarvitsevat lisäkontekstia. \n\nVoit parantaa saavutettavuutta ja kaikkien mahdollisuutta ymmärtää kirjoittamalla selkeän, lyhyen ja objektiivisen selityksen. \n\n<ul><li>Mainitse tärkeät elementit</li>\n<li>Anna tiivistelmä kuvissa olevista teksteistä</li>\n<li>Käytä normaalia lauserakennetta</li>\n<li>Vältä turhaa toistoa</li>\n<li>Keskity monimutkaisissa kuvioissa (kuten kartoissa ja taulukoissa) trendeihin ja tärkeimpiin tietoihin</li></ul></string>
|
||||
<string name="edit_post">Muokkaa julkaisua</string>
|
||||
<string name="no_verified_link">Ei todennettua linkkiä</string>
|
||||
<string name="compose_autocomplete_emoji_empty">Selaa emojeita</string>
|
||||
<string name="compose_autocomplete_users_empty">Löydä etsimäsi henkilöt</string>
|
||||
<string name="no_search_results">Näille hakusanoille ei löytynyt mitään</string>
|
||||
<string name="language">Kieli</string>
|
||||
<string name="language_default">Oletus</string>
|
||||
<string name="language_system">Järjestelmä</string>
|
||||
<string name="language_detecting">Tunnista kieli</string>
|
||||
<string name="language_cant_detect">Ei voi tunnistaa kieltä</string>
|
||||
<string name="language_detected">Tunnistettu</string>
|
||||
<string name="media_hidden">Media piilotettu</string>
|
||||
<string name="post_hidden">Julkaisu piilotettu</string>
|
||||
<string name="report_title_post">Raportoi julkaisu</string>
|
||||
<string name="forward_report_explanation">Tämä tili on toisella palvelimella. Haluatko lähettää nimettömän raportin myös sinne?</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="forward_report_to_server">Välitä kohteeseen %s</string>
|
||||
<!-- Shown on the "stamp" on the screen that appears after you report a post/user. Please keep the translation short, preferably a single word -->
|
||||
<string name="reported">Raportoitu</string>
|
||||
<string name="report_unfollow_explanation">Jos et enää halua nähdä tämän käyttäjän julkaisuja kotiaikajanallasi, lopeta seuraaminen.</string>
|
||||
<string name="muted_user">Käyttäjä %s mykistetty</string>
|
||||
<string name="report_sent_already_blocked">Olet jo estänyt tämän käyttäjän, sinun ei tarvitse tehdä muuta sillä aikaa kun tarkastamme raporttisi.</string>
|
||||
<string name="report_personal_already_blocked">Olet jo estänyt tämän käyttäjän, joten sinun ei tarvitse tehdä mitään muuta.\n\nKiitos, että autat pitämään Mastodonin turvallisena paikkana kaikille!</string>
|
||||
<string name="blocked_user">Estetty %s</string>
|
||||
<string name="mark_all_notifications_read">Merkitse kaikki luetuksi</string>
|
||||
<string name="settings_display">Näyttö</string>
|
||||
<string name="settings_filters">Suodattimet</string>
|
||||
<string name="settings_server_explanation">Yleiskatsaus, säännöt, valvojat</string>
|
||||
<!-- %s is the app name (Mastodon, key app_name). I made it a placeholder so everything Just Works™ with forks -->
|
||||
<string name="about_app">Tietoa: %s</string>
|
||||
<string name="default_post_language">Julkaisun oletuskieli</string>
|
||||
<string name="settings_alt_text_reminders">Lisää muistutus kuvaselityksestä</string>
|
||||
<string name="settings_confirm_unfollow">Kysy ennen kuin käyttäjän seuraaminen lopetetaan</string>
|
||||
<string name="settings_confirm_boost">Kysy ennen tehostusta</string>
|
||||
<string name="settings_confirm_delete_post">Kysy ennen julkaisujen poistamista</string>
|
||||
<string name="pause_all_notifications">Keskeytä kaikki</string>
|
||||
<string name="pause_notifications_off">Pois Päältä</string>
|
||||
<string name="notifications_policy_anyone">Kuka tahansa</string>
|
||||
<string name="notifications_policy_followed">Seuraajasi</string>
|
||||
<string name="notifications_policy_follower">Seuraamasi henkilöt</string>
|
||||
<string name="notifications_policy_no_one">Ei kukaan</string>
|
||||
<string name="settings_notifications_policy">Ota vastaan ilmoituksia käyttäjältä</string>
|
||||
<string name="notification_type_mentions_and_replies">Maininnat ja vastaukset</string>
|
||||
<string name="pause_all_notifications_title">Keskeytä kaikki ilmoitukset</string>
|
||||
<plurals name="x_weeks">
|
||||
<item quantity="one">%d viikko</item>
|
||||
<item quantity="other">%d viikkoa</item>
|
||||
</plurals>
|
||||
<!-- %1$s is the date (may be relative, e.g. "today" or "yesterday"), %2$s is the time. You can reorder these placeholders if that works better for your language -->
|
||||
<string name="date_at_time">%1$s klo %2$s</string>
|
||||
<string name="today">tänään</string>
|
||||
<string name="yesterday">eilen</string>
|
||||
<string name="tomorrow">huomenna</string>
|
||||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<string name="pause_notifications_ends">Päättyy %s</string>
|
||||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<string name="pause_notifications_banner">Ilmoitukset jatkuvat %s.</string>
|
||||
<string name="resume_notifications_now">Jatka nyt</string>
|
||||
<string name="open_system_notification_settings">Siirry ilmoitusasetuksiin</string>
|
||||
<string name="about_server">Tietoja</string>
|
||||
<string name="server_rules">Säännöt</string>
|
||||
<string name="server_administrator">Ylläpitäjä</string>
|
||||
<string name="send_email_to_server_admin">Viestin ylläpitäjä</string>
|
||||
<string name="notifications_disabled_in_system">Ota ilmoitukset käyttöön laitteesi asetuksista nähdäksesi päivityksiä mistä tahansa.</string>
|
||||
<string name="settings_even_more">Vielä enemmän asetuksia</string>
|
||||
<string name="settings_show_cws">Näytä sisältövaroitukset</string>
|
||||
<string name="settings_hide_sensitive_media">Piilota arkaluontoiseksi merkitty media</string>
|
||||
<string name="settings_show_interaction_counts">Näytä reaktiolaskurit</string>
|
||||
<string name="settings_show_emoji_in_names">Mukautetut emojit näyttönimissä</string>
|
||||
<plurals name="in_x_seconds">
|
||||
<item quantity="one">%d sekunnin kuluttua</item>
|
||||
<item quantity="other">%d sekunnin kuluttua</item>
|
||||
</plurals>
|
||||
<plurals name="in_x_minutes">
|
||||
<item quantity="one">%d minuutin kuluttua</item>
|
||||
<item quantity="other">%d minuutin kuluttua</item>
|
||||
</plurals>
|
||||
<plurals name="in_x_hours">
|
||||
<item quantity="one">%d tunnin kuluttua</item>
|
||||
<item quantity="other">%d tunnin kuluttua</item>
|
||||
</plurals>
|
||||
<plurals name="x_hours_ago">
|
||||
<item quantity="one">%d tunti sitten</item>
|
||||
<item quantity="other">%d tuntia sitten</item>
|
||||
</plurals>
|
||||
<string name="alt_text_reminder_title">Mediasta puuttuu selitysteksti</string>
|
||||
<plurals name="alt_text_reminder_x_images">
|
||||
<item quantity="one">%s kuvastasi puuttuu selitysteksti. Julkaistaanko silti?</item>
|
||||
<item quantity="other">%s kuvastasi puuttuu selitysteksti. Julkaistaanko silti?</item>
|
||||
</plurals>
|
||||
<plurals name="alt_text_reminder_x_attachments">
|
||||
<item quantity="one">%s mediatiedostostasi puuttuu selitysteksti. Julkaistaanko silti?</item>
|
||||
<item quantity="other">%s mediatiedostostasi puuttuu selitysteksti. Julkaistaanko silti?</item>
|
||||
</plurals>
|
||||
<string name="count_one">Yksi</string>
|
||||
<string name="count_two">Kaksi</string>
|
||||
<string name="count_three">Kolme</string>
|
||||
<string name="count_four">Neljä</string>
|
||||
<string name="alt_text_reminder_post_anyway">Julkaise</string>
|
||||
<!-- %s is the username -->
|
||||
<string name="unfollow_confirmation">Lopeta käyttäjän %s seuraaminen?</string>
|
||||
<string name="filter_active">Aktiivinen</string>
|
||||
<string name="filter_inactive">Ei käytössä</string>
|
||||
<string name="settings_add_filter">Lisää suodatin</string>
|
||||
<string name="settings_edit_filter">Muokkaa suodatinta</string>
|
||||
<string name="settings_filter_duration">Kesto</string>
|
||||
<string name="settings_filter_muted_words">Mykistetyt sanat</string>
|
||||
<string name="settings_filter_context">Mykistä alkaen</string>
|
||||
<string name="settings_filter_show_cw">Näytä sisältövaroituksella</string>
|
||||
<string name="settings_filter_show_cw_explanation">Näytä vielä viestejä, jotka täsmäävät tähän suodattimeen, mutta sisällönvaroituksen takana</string>
|
||||
<string name="settings_delete_filter">Poista suodatin</string>
|
||||
<string name="filter_duration_forever">Ikuisesti</string>
|
||||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<string name="settings_filter_ends">Päättyy %s</string>
|
||||
<plurals name="settings_x_muted_words">
|
||||
<item quantity="one">%d mykistetty sana tai lause</item>
|
||||
<item quantity="other">%d mykistettyä sanaa tai lauseita</item>
|
||||
</plurals>
|
||||
<string name="selection_2_options">%1$s ja %2$s</string>
|
||||
<string name="selection_3_options">%1$s, %2$s ja %3$s</string>
|
||||
<string name="selection_4_or_more">%1$s, %2$s, ja %3$d lisää</string>
|
||||
<string name="filter_context_home_lists">Koti & listat</string>
|
||||
<string name="filter_context_notifications">Ilmoitukset</string>
|
||||
<string name="filter_context_public_timelines">Julkiset aikajanat</string>
|
||||
<string name="filter_context_threads_replies">Langat & vastaukset</string>
|
||||
<string name="filter_context_profiles">Profiilit</string>
|
||||
<string name="settings_filter_title">Otsikko</string>
|
||||
<string name="settings_delete_filter_title">Poistetaanko suodatin “%s”?</string>
|
||||
<string name="settings_delete_filter_confirmation">Tämä suodatin poistetaan tililtäsi kaikissa laitteissa.</string>
|
||||
<string name="add_muted_word">Lisää mykistetty sana</string>
|
||||
<string name="edit_muted_word">Muokkaa mykistettyä sanaa</string>
|
||||
<string name="add">Lisää</string>
|
||||
<string name="filter_word_or_phrase">Sana tai lause</string>
|
||||
<string name="filter_add_word_help">Sanat ovat tapauskohtaisia ja vastaavat vain kokonaisia sanoja.\n\nJos suodattaa avainsana “Apple”, se piilottaa viestit sisältävät “omena” tai “aPPLe” mutta ei “ananas\".</string>
|
||||
<string name="settings_delete_filter_word">Poista sana “%s”?</string>
|
||||
<string name="enter_selection_mode">Valitse</string>
|
||||
<string name="select_all">Valitse kaikki</string>
|
||||
<string name="settings_filter_duration_title">Suodattimen kesto</string>
|
||||
<string name="filter_duration_custom">Mukautettu</string>
|
||||
<plurals name="settings_delete_x_filter_words">
|
||||
<item quantity="one">Poista %d sana?</item>
|
||||
<item quantity="other">Poista %d sanaa?</item>
|
||||
</plurals>
|
||||
<plurals name="x_items_selected">
|
||||
<item quantity="one">%d valittu</item>
|
||||
<item quantity="other">%d valittu</item>
|
||||
</plurals>
|
||||
<string name="required_form_field_blank">Tätä ei voi jättää tyhjäksi</string>
|
||||
<string name="filter_word_already_in_list">Jo luettelossa</string>
|
||||
<string name="app_update_ready">Sovelluksen päivitys valmis</string>
|
||||
<string name="app_update_version">Versio %s</string>
|
||||
<string name="downloading_update">Ladataan (%d%%)</string>
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<string name="post_matches_filter_x">Sopii suodattimeen ”%s”</string>
|
||||
<string name="search_mastodon">Etsi Mastodonista</string>
|
||||
<string name="clear_all">Tyhjennä kaikki</string>
|
||||
<string name="search_open_url">Avaa URL-osoite Mastodonissa</string>
|
||||
<string name="posts_matching_hashtag">Julkaisut joissa on \"%s\"</string>
|
||||
<string name="search_go_to_account">Siirry tiliin %s</string>
|
||||
<string name="posts_matching_string">Julkaisut joissa on \"%s\"</string>
|
||||
<string name="accounts_matching_string">Henkilöt jossa on \"%s\"</string>
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<string name="time_seconds_ago_short">%ds sitten</string>
|
||||
<string name="time_minutes_ago_short">%dm sitten</string>
|
||||
<string name="time_hours_ago_short">%dh sitten</string>
|
||||
<string name="time_days_ago_short">%dd sitten</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Käännetty kielestä %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">Käännetty kielestä %1$s käyttäen %2$s</string>
|
||||
<string name="translation_show_original">Näytä alkuperäinen</string>
|
||||
<string name="translation_failed">Käännös epäonnistui. Ehkä järjestelmänvalvoja ei ole ottanut käyttöön käännöksiä tällä palvelimella tai tällä palvelimella on käynnissä vanhempi versio Mastodonista, jossa käännöksiä ei vielä tueta.</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="one">%d osallistuja</item>
|
||||
<item quantity="other">%d osallistujaa</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="one">%,d viesti tänään</item>
|
||||
<item quantity="other">%,d viestiä tänään</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -211,12 +211,12 @@
|
|||
<item quantity="other">%,d tagasunod</item>
|
||||
</plurals>
|
||||
<plurals name="x_following">
|
||||
<item quantity="one">%, d Sumusunod</item>
|
||||
<item quantity="other">%, d Sumusunod</item>
|
||||
<item quantity="one">%,d Sumusunod</item>
|
||||
<item quantity="other">%,d Sumusunod</item>
|
||||
</plurals>
|
||||
<plurals name="x_favorites">
|
||||
<item quantity="one">%, d Paborito</item>
|
||||
<item quantity="other">%, d paborito</item>
|
||||
<item quantity="one">%,d Paborito</item>
|
||||
<item quantity="other">%,d paborito</item>
|
||||
</plurals>
|
||||
<string name="timestamp_via_app">%1$s sa pamamagitan ng %2$s</string>
|
||||
<string name="time_now">ngayon</string>
|
||||
|
@ -284,4 +284,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -582,4 +582,18 @@
|
|||
<string name="time_minutes_ago_short">il y a %dm</string>
|
||||
<string name="time_hours_ago_short">Il y a %dh</string>
|
||||
<string name="time_days_ago_short">Il y a %dj</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Traduire depuis %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">Traduit depuis %1$s via %2$s</string>
|
||||
<string name="translation_show_original">Afficher l’original</string>
|
||||
<string name="translation_failed">La traduction a échoué. Peut-être que l’administrateur n’a pas activé les traductions sur ce serveur ou que ce serveur utilise une ancienne version de Mastodon où les traductions ne sont pas encore prises en charge.</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="one">%,d participant</item>
|
||||
<item quantity="other">%,d participants</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="one">%,d message aujourd’hui</item>
|
||||
<item quantity="other">%,d messages aujourd’hui</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -20,4 +20,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -640,4 +640,6 @@
|
|||
<string name="time_minutes_ago_short">%dm air ais</string>
|
||||
<string name="time_hours_ago_short">%du air ais</string>
|
||||
<string name="time_days_ago_short">%dl air ais</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
<string name="next">Seguinte</string>
|
||||
<string name="loading_instance">Obtendo info do servidor…</string>
|
||||
<string name="error">Erro</string>
|
||||
<string name="not_a_mastodon_instance">%s non semella ser un servidor Mastodon.</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="preparing_auth">Preparándose para a autenticación…</string>
|
||||
<string name="finishing_auth">Rematando coa autenticación…</string>
|
||||
<string name="user_boosted">%s promoveu</string>
|
||||
<string name="in_reply_to">Como resposta a %s</string>
|
||||
<string name="notifications">Notificacións</string>
|
||||
<string name="user_followed_you">%s comezou a seguirte</string>
|
||||
<string name="share_toot_title">Compartir</string>
|
||||
<string name="settings">Axustes</string>
|
||||
<string name="publish">Publicar</string>
|
||||
|
@ -347,4 +349,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -47,4 +47,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -227,4 +227,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -372,4 +372,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -382,4 +382,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -20,4 +20,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -368,6 +368,7 @@
|
|||
<string name="welcome_to_mastodon">Selamat datang di Mastodon</string>
|
||||
<string name="welcome_paragraph1">Mastodon adalah jejaring sosial terdesentralisasi, tidak ada satu pun perusahaan yang mengontrol. Semua dijalankan oleh server independen, terkoneksi bersama.</string>
|
||||
<string name="what_are_servers">Apa itu server?</string>
|
||||
<string name="welcome_paragraph2">Semua akun Mastodon berada pada sebuah server — dengan nilai, aturan, & admin masing-masing. Mana pun yang Anda pilih, Anda dapat mengikuti dan berinteraksi dengan server mana pun.</string>
|
||||
<string name="opening_link">Membuka tautan…</string>
|
||||
<string name="link_not_supported">Tautan ini tidak didukung dalam aplikasi</string>
|
||||
<string name="log_out_all_accounts">Keluar dari semua akun</string>
|
||||
|
@ -552,4 +553,6 @@
|
|||
<string name="time_minutes_ago_short">%dm yang lalu</string>
|
||||
<string name="time_hours_ago_short">%dj yang lalu</string>
|
||||
<string name="time_days_ago_short">%dh yang lalu</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -582,4 +582,21 @@
|
|||
<string name="time_minutes_ago_short">fyrir %dm síðan</string>
|
||||
<string name="time_hours_ago_short">fyrir %dh síðan</string>
|
||||
<string name="time_days_ago_short">fyrir %dd síðan</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Þýða úr %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">Þýtt úr %1$s með %2$s</string>
|
||||
<string name="translation_show_original">Sýna upprunalegt</string>
|
||||
<string name="translation_failed">Þýðing mistókst. Mögulega hefur kerfisstjórinn ekki virkjað þýðingar á þessum netþjóni, eða að netþjónninn sé keyrður á eldri útgáfu Mastodon þar sem þýðingar séu ekki studdar.</string>
|
||||
<string name="settings_privacy">Gagnaleynd og útbreiðsla</string>
|
||||
<string name="settings_discoverable">Hafa notandasnið og færslur með í reikniritum leitar</string>
|
||||
<string name="settings_indexable">Hafa opinberar færslur með í leitarniðurstöðum</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="one">%,d þátttakandi</item>
|
||||
<item quantity="other">%,d þátttakendur</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="one">%,d færsla í dag</item>
|
||||
<item quantity="other">%,d færslur í dag</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -582,4 +582,19 @@
|
|||
<string name="time_minutes_ago_short">%dmin fa</string>
|
||||
<string name="time_hours_ago_short">%do fa</string>
|
||||
<string name="time_days_ago_short">%dg fa</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Traduci da %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">Tradotto da %1$s utilizzando %2$s</string>
|
||||
<string name="translation_show_original">Mostra originale</string>
|
||||
<string name="translation_failed">Traduzione fallita. Forse l\'amministratore non ha abilitato le traduzioni su questo server, o su questo server è in esecuzione una versione precedente di Mastodon in cui le traduzioni non sono ancora supportate.</string>
|
||||
<string name="settings_indexable">Includi i post pubblici nei risultati di ricerca</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="one">%,d participante</item>
|
||||
<item quantity="other">%,d partecipanti</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="one">%,d post oggi</item>
|
||||
<item quantity="other">%,d post oggi</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -88,4 +88,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -553,4 +553,19 @@
|
|||
<string name="time_minutes_ago_short">%d 分前</string>
|
||||
<string name="time_hours_ago_short">%d 時間前</string>
|
||||
<string name="time_days_ago_short">%d 日前</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">%s から翻訳</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">%2$s による %1$s からの翻訳</string>
|
||||
<string name="translation_show_original">原文を表示</string>
|
||||
<string name="translation_failed">翻訳に失敗しました。このサーバーは翻訳機能を有効にしていないか、翻訳機能のない旧バージョンの Mastodon を実行しているのかもしれません。</string>
|
||||
<string name="settings_privacy">プライバシーとつながりやすさ</string>
|
||||
<string name="settings_discoverable">アカウントを見つけやすくする</string>
|
||||
<string name="settings_indexable">公開投稿を検索できるようにする</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="other">参加者 %d 人</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="other">今日の投稿 %,d 件</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -242,4 +242,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -300,4 +300,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -180,4 +180,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -85,6 +85,10 @@
|
|||
<item quantity="one">%d dag resterend</item>
|
||||
<item quantity="other">%d dagen resterend</item>
|
||||
</plurals>
|
||||
<plurals name="x_votes">
|
||||
<item quantity="one">%,d stem</item>
|
||||
<item quantity="other">%,d stemmen</item>
|
||||
</plurals>
|
||||
<string name="poll_closed">Gesloten</string>
|
||||
<string name="confirm_mute_title">Account negeren</string>
|
||||
<string name="confirm_mute">Het negeren van %s bevestigen</string>
|
||||
|
@ -383,6 +387,7 @@
|
|||
<string name="welcome_to_mastodon">Welkom bij Mastodon</string>
|
||||
<string name="welcome_paragraph1">Mastodon is een gedecentraliseerd sociaal netwerk, wat betekent dat geen enkel bedrijf het controleert. Het bestaat uit veel onafhankelijk opererende servers, allemaal met elkaar verbonden.</string>
|
||||
<string name="what_are_servers">Wat zijn servers?</string>
|
||||
<string name="welcome_paragraph2">Elk Mastodon-account wordt gehost op een server – elk met diens eigen waarden, regels en beheerders. Het maakt niet uit welke server je kiest, je kunt mensen op elke server volgen en ermee communiceren.</string>
|
||||
<string name="opening_link">Koppeling aan het openen…</string>
|
||||
<string name="link_not_supported">Deze koppeling wordt niet ondersteund in de app</string>
|
||||
<string name="log_out_all_accounts">Bij alle accounts afmelden</string>
|
||||
|
@ -401,6 +406,7 @@
|
|||
<string name="attachment_type_unknown">Bestand</string>
|
||||
<string name="attachment_x_percent_uploaded">%d%% geüpload</string>
|
||||
<string name="add_poll_option">Enquete-optie toevoegen</string>
|
||||
<string name="poll_length">Lengte enquête</string>
|
||||
<string name="poll_style">Stijl</string>
|
||||
<string name="compose_poll_single_choice">Kies een</string>
|
||||
<string name="compose_poll_multiple_choice">Meerkeuze</string>
|
||||
|
@ -409,9 +415,38 @@
|
|||
<string name="alt_text">Alternatieve tekst</string>
|
||||
<string name="help">Hulp</string>
|
||||
<string name="what_is_alt_text">Wat is alternatieve tekst?</string>
|
||||
<string name="alt_text_help">Alt tekst biedt afbeeldingsbeschrijvingen voor mensen met een visiuele beperking en verbindingen met een lage bandbreedte of voor mensen die naar extra context zoeken.\n\nJe kunt de toegankelijkheid en het begrip voor iedereen verbeteren door duidelijk, beknopt en objectief te schrijven.\n\n<ul><li>Beschrijf belangrijke elementen</li>\n<li>Vat tekst in afbeeldingen samen</li>\n<li>Gebruik de reguliere zinsopbouw</li>\n<li>Vermijd overbodige informatie</li>\n<li>Focus op trends en belangrijke bevindingen in complexe beelden (zoals diagrammen of kaarten)</li></ul> \n</string>
|
||||
<string name="edit_post">Bericht bewerken</string>
|
||||
<string name="no_verified_link">Geen geverifieerde koppeling</string>
|
||||
<string name="compose_autocomplete_emoji_empty">Emoji doorzoeken</string>
|
||||
<string name="compose_autocomplete_users_empty">Vind wie je zoekt</string>
|
||||
<string name="no_search_results">Deze zoektermen leveren geen resultaat op</string>
|
||||
<string name="language">Taal</string>
|
||||
<string name="language_default">Standaard</string>
|
||||
<string name="language_system">Systeem</string>
|
||||
<string name="language_detecting">Taal detecteren</string>
|
||||
<string name="language_cant_detect">Kan taal niet detecteren</string>
|
||||
<string name="language_detected">Gedetecteerd</string>
|
||||
<string name="media_hidden">Media verborgen</string>
|
||||
<string name="post_hidden">Bericht verborgen</string>
|
||||
<string name="report_title_post">Bericht rapporteren</string>
|
||||
<string name="forward_report_explanation">De account bevindt zich op een andere server. Wil je daar eveneens een geanonimiseerde kopie van dit rapport naar toesturen?</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="forward_report_to_server">Doorsturen naar %s</string>
|
||||
<!-- Shown on the "stamp" on the screen that appears after you report a post/user. Please keep the translation short, preferably a single word -->
|
||||
<string name="reported">Gerapporteerd</string>
|
||||
<string name="report_unfollow_explanation">Als je hun berichten niet meer in je home feed wilt zien, moet je deze persoon niet meer volgen.</string>
|
||||
<string name="muted_user">%s gedempt</string>
|
||||
<string name="report_sent_already_blocked">Je hebt deze gebruiker al geblokkeerd, dus je hoeft niets meer te doen terwijl we je rapport beoordelen.</string>
|
||||
<string name="report_personal_already_blocked">Je hebt deze gebruiker al geblokkeerd, dus er is niets anders dat je hoeft te doen.\n\nBedankt voor het helpen om Mastodon een veilige plek voor iedereen te behouden!</string>
|
||||
<string name="blocked_user">%s geblokkeerd</string>
|
||||
<string name="mark_all_notifications_read">Alles als gelezen markeren</string>
|
||||
<string name="settings_display">Weergave</string>
|
||||
<string name="settings_filters">Filters</string>
|
||||
<string name="settings_server_explanation">Overzicht, regels, moderators</string>
|
||||
<!-- %s is the app name (Mastodon, key app_name). I made it a placeholder so everything Just Works™ with forks -->
|
||||
<string name="about_app">Over %s</string>
|
||||
<string name="default_post_language">Standaard taal bericht</string>
|
||||
<string name="settings_alt_text_reminders">Alt-tekst-herinneringen toevoegen</string>
|
||||
<string name="settings_confirm_unfollow">Vraag voor ontvolgen iemand</string>
|
||||
<string name="settings_confirm_boost">Vragen voor boosten</string>
|
||||
|
@ -437,6 +472,44 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<string name="pause_notifications_ends">Eindigt %s</string>
|
||||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<string name="pause_notifications_banner">Notificaties worden hervat %s.</string>
|
||||
<string name="resume_notifications_now">Nu hervatten</string>
|
||||
<string name="open_system_notification_settings">Ga naar de meldingsinstellingen</string>
|
||||
<string name="about_server">Over</string>
|
||||
<string name="server_rules">Regels</string>
|
||||
<string name="server_administrator">Beheerder</string>
|
||||
<string name="send_email_to_server_admin">Bericht aan beheerder</string>
|
||||
<string name="notifications_disabled_in_system">Schakel meldingen vanuit instellingen van uw apparaat in om van overal updates te zien.</string>
|
||||
<string name="settings_even_more">Nog meer instellingen</string>
|
||||
<string name="settings_show_cws">Inhoudswaarschuwingen tonen</string>
|
||||
<string name="settings_hide_sensitive_media">Als gevoelig gemarkeerde media verbergen</string>
|
||||
<string name="settings_show_interaction_counts">Aantal berichtinteracties</string>
|
||||
<string name="settings_show_emoji_in_names">Aangepaste emoji in weergavenamen</string>
|
||||
<plurals name="in_x_seconds">
|
||||
<item quantity="one">in %d seconde</item>
|
||||
<item quantity="other">in %d seconden</item>
|
||||
</plurals>
|
||||
<plurals name="in_x_minutes">
|
||||
<item quantity="one">in %d minuut</item>
|
||||
<item quantity="other">in %d minuten</item>
|
||||
</plurals>
|
||||
<plurals name="in_x_hours">
|
||||
<item quantity="one">in %d uur</item>
|
||||
<item quantity="other">in %d uur</item>
|
||||
</plurals>
|
||||
<plurals name="x_hours_ago">
|
||||
<item quantity="one">%d uur geleden</item>
|
||||
<item quantity="other">%d uur geleden</item>
|
||||
</plurals>
|
||||
<string name="alt_text_reminder_title">Media zonder alt-tekst</string>
|
||||
<plurals name="alt_text_reminder_x_images">
|
||||
<item quantity="one">%s van je afbeeldingen mist alt-tekst. Toch plaatsen?</item>
|
||||
<item quantity="other">%s van je afbeeldingen missen alt-tekst. Toch plaatsen?</item>
|
||||
</plurals>
|
||||
<plurals name="alt_text_reminder_x_attachments">
|
||||
<item quantity="one">%s van je mediabijlagen mist alt-tekst. Toch plaatsen?</item>
|
||||
<item quantity="other">%s van je mediabijlagen missen alt-tekst. Toch plaatsen?</item>
|
||||
</plurals>
|
||||
<string name="count_one">Een</string>
|
||||
<string name="count_two">Twee</string>
|
||||
<string name="count_three">Drie</string>
|
||||
|
@ -444,7 +517,83 @@
|
|||
<string name="alt_text_reminder_post_anyway">Plaatsen</string>
|
||||
<!-- %s is the username -->
|
||||
<string name="unfollow_confirmation">%s ontvolgen?</string>
|
||||
<string name="filter_active">Actief</string>
|
||||
<string name="filter_inactive">Inactief</string>
|
||||
<string name="settings_add_filter">Filter toevoegen</string>
|
||||
<string name="settings_edit_filter">Filter bewerken</string>
|
||||
<string name="settings_filter_duration">Duur</string>
|
||||
<string name="settings_filter_muted_words">Gedempte woorden</string>
|
||||
<string name="settings_filter_context">Gedempt van</string>
|
||||
<string name="settings_filter_show_cw">Toon met inhoudswaarschuwing</string>
|
||||
<string name="settings_filter_show_cw_explanation">Berichten die met dit filter overeenkomen, maar achter een inhoudswaarschuwing zitten toch tonen</string>
|
||||
<string name="settings_delete_filter">Filter verwijderen</string>
|
||||
<string name="filter_duration_forever">Voor altijd</string>
|
||||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<string name="settings_filter_ends">Eindigt %s</string>
|
||||
<plurals name="settings_x_muted_words">
|
||||
<item quantity="one">%d gedempt woord of zin</item>
|
||||
<item quantity="other">%d gedempte woorden of zinnen</item>
|
||||
</plurals>
|
||||
<string name="selection_2_options">%1$s en %2$s</string>
|
||||
<string name="selection_3_options">%1$s, %2$s en %3$s</string>
|
||||
<string name="selection_4_or_more">%1$s, %2$s en %3$d meer</string>
|
||||
<string name="filter_context_home_lists">Startpagina & lijsten</string>
|
||||
<string name="filter_context_notifications">Meldingen</string>
|
||||
<string name="filter_context_public_timelines">Openbare tijdlijnen</string>
|
||||
<string name="filter_context_threads_replies">Threads & antwoorden</string>
|
||||
<string name="filter_context_profiles">Profielen</string>
|
||||
<string name="settings_filter_title">Titel</string>
|
||||
<string name="settings_delete_filter_title">Filter ‘%s’ verwijderen?</string>
|
||||
<string name="settings_delete_filter_confirmation">Dit filter zal op al uw apparaten uit uw account worden verwijderd.</string>
|
||||
<string name="add_muted_word">Gedempte woord toevoegen</string>
|
||||
<string name="edit_muted_word">Gedempte woord bewerken</string>
|
||||
<string name="add">Toevoegen</string>
|
||||
<string name="filter_word_or_phrase">Woord of zin</string>
|
||||
<string name="filter_add_word_help">Woorden zijn niet hoofdlettergevoelig en komen alleen overeen met volledige woorden.\n\nAls je op de term ‘Apple’ filtert, verbergt het berichten die ‘apple’ of ‘aPpLe’ bevatten, maar niet ‘ananas’.</string>
|
||||
<string name="settings_delete_filter_word">‘%s’ verwijderen?</string>
|
||||
<string name="enter_selection_mode">Selecteren</string>
|
||||
<string name="select_all">Alles selecteren</string>
|
||||
<string name="settings_filter_duration_title">Filter tijdsduur</string>
|
||||
<string name="filter_duration_custom">Aangepast</string>
|
||||
<plurals name="settings_delete_x_filter_words">
|
||||
<item quantity="one">%d woord verwijderen?</item>
|
||||
<item quantity="other">%d woorden verwijderen?</item>
|
||||
</plurals>
|
||||
<plurals name="x_items_selected">
|
||||
<item quantity="one">%d geselecteerd</item>
|
||||
<item quantity="other">%d geselecteerd</item>
|
||||
</plurals>
|
||||
<string name="required_form_field_blank">Mag niet leeg zijn</string>
|
||||
<string name="filter_word_already_in_list">Al in de lijst</string>
|
||||
<string name="app_update_ready">App-update voltooid</string>
|
||||
<string name="app_update_version">Versie %s</string>
|
||||
<string name="downloading_update">Downloaden (%d%%)</string>
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<string name="post_matches_filter_x">Komt overeen met filter ‘%s’</string>
|
||||
<string name="search_mastodon">Mastodon doorzoeken</string>
|
||||
<string name="clear_all">Alles wissen</string>
|
||||
<string name="search_open_url">URL in Mastodon openen</string>
|
||||
<string name="posts_matching_hashtag">Berichten met ‘%s’</string>
|
||||
<string name="search_go_to_account">Ga naar %s</string>
|
||||
<string name="posts_matching_string">Berichten met ‘%s’</string>
|
||||
<string name="accounts_matching_string">Personen met ‘%s’</string>
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<string name="time_seconds_ago_short">%ds geleden</string>
|
||||
<string name="time_minutes_ago_short">%dm geleden</string>
|
||||
<string name="time_hours_ago_short">%du geleden</string>
|
||||
<string name="time_days_ago_short">%d dagen geleden</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Vanuit het %s vertalen</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">Vertaald vanuit het %1$s door %2$s</string>
|
||||
<string name="translation_show_original">Origineel bekijken</string>
|
||||
<string name="translation_failed">Vertaling mislukt. Mogelijk heeft de serverbeheerder vertalingen niet ingeschakeld op deze server, of draait deze server een oude versie van Mastodon waar vertalingen nog niet worden ondersteund.</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="one">%d deelnemer</item>
|
||||
<item quantity="other">%d deelnemers</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="one">%,d bericht vandaag</item>
|
||||
<item quantity="other">%,d berichten vandaag</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -581,4 +581,6 @@
|
|||
<string name="time_minutes_ago_short">%dm siden</string>
|
||||
<string name="time_hours_ago_short">%dt siden</string>
|
||||
<string name="time_days_ago_short">%dd siden</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -79,4 +79,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -457,4 +457,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<string name="ok">OK</string>
|
||||
<string name="preparing_auth">Preparando para autenticação…</string>
|
||||
<string name="finishing_auth">Finalizando autenticação…</string>
|
||||
<string name="user_boosted">%s impulsionado</string>
|
||||
<string name="user_boosted">%s impulsionou</string>
|
||||
<string name="in_reply_to">Em resposta à %s</string>
|
||||
<string name="notifications">Notificações</string>
|
||||
<string name="user_followed_you">%s seguiu você</string>
|
||||
|
@ -571,4 +571,6 @@
|
|||
<string name="time_minutes_ago_short">%dm atrás</string>
|
||||
<string name="time_hours_ago_short">%dh atrás</string>
|
||||
<string name="time_days_ago_short">%dd atrás</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -234,4 +234,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -48,4 +48,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -640,4 +640,25 @@
|
|||
<string name="time_minutes_ago_short">%d мин. назад</string>
|
||||
<string name="time_hours_ago_short">%d ч. назад</string>
|
||||
<string name="time_days_ago_short">%d д. назад</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Перевести %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">%1$s переведён с помощью %2$s</string>
|
||||
<string name="translation_show_original">Показать оригинал</string>
|
||||
<string name="translation_failed">Перевод не удался. Возможно, администратор не включил переводы на этом сервере или на этом сервере установлена более старая версия Mastodon, где переводы еще не поддерживаются.</string>
|
||||
<string name="settings_privacy">Приватность и доступ</string>
|
||||
<string name="settings_discoverable">Показывать профиль и посты в алгоритмах рекомендаций</string>
|
||||
<string name="settings_indexable">Включить публичные посты в результаты поиска</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="one">%,d участник</item>
|
||||
<item quantity="few">%,d участника</item>
|
||||
<item quantity="many">%,d участников</item>
|
||||
<item quantity="other">%,d участников</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="one">%,d пост сегодня</item>
|
||||
<item quantity="few">%,d поста сегодня</item>
|
||||
<item quantity="many">%,d постов сегодня</item>
|
||||
<item quantity="other">%,d постов сегодня</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -75,4 +75,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -274,6 +274,8 @@
|
|||
<string name="trending_posts_info_banner">To so objave, ki plenijo pozornost po Mastodonu.</string>
|
||||
<string name="trending_links_info_banner">To so novice, o katerih se govori na Mastodonu.</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">To so vse objave vseh uporabnikov na vašem strežniku (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Glede na to, komu sledite, vam bodo ti računi všeč.</string>
|
||||
<string name="see_new_posts">Pokaži nove objave</string>
|
||||
<string name="load_missing_posts">Naloži manjkajoče objave</string>
|
||||
<string name="follow_back">Sledijo nazaj</string>
|
||||
|
@ -455,8 +457,11 @@
|
|||
<!-- %s is the app name (Mastodon, key app_name). I made it a placeholder so everything Just Works™ with forks -->
|
||||
<string name="about_app">O programu %s</string>
|
||||
<string name="default_post_language">Privzeti jezik objave</string>
|
||||
<string name="settings_confirm_delete_post">Vprašaj pred brisanjem objav</string>
|
||||
<string name="pause_all_notifications">Premor za vse</string>
|
||||
<string name="pause_notifications_off">Izklopljeno</string>
|
||||
<string name="notifications_policy_anyone">Kdor koli</string>
|
||||
<string name="notifications_policy_followed">Ljudje, ki vam sledijo</string>
|
||||
<string name="notifications_policy_follower">Ljudje, ki jim sledite</string>
|
||||
<string name="notifications_policy_no_one">Nihče</string>
|
||||
<string name="notification_type_mentions_and_replies">Omembe in odgovori</string>
|
||||
|
@ -504,6 +509,7 @@
|
|||
<string name="filter_context_profiles">Profili</string>
|
||||
<string name="settings_filter_title">Naslov</string>
|
||||
<string name="settings_delete_filter_title">Ali želite izbrisati filter »%s«?</string>
|
||||
<string name="settings_delete_filter_confirmation">Ta filter bo izbrisan iz vašega računa na vseh vaših napravah.</string>
|
||||
<string name="add_muted_word">Dodaj utišano besedo</string>
|
||||
<string name="edit_muted_word">Uredi utišano besedo</string>
|
||||
<string name="add">Dodaj</string>
|
||||
|
@ -532,4 +538,13 @@
|
|||
<string name="time_minutes_ago_short">pred %d meseci</string>
|
||||
<string name="time_hours_ago_short">pred %dh urami</string>
|
||||
<string name="time_days_ago_short">pred %d dnemi</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Prevedi iz jezika: %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">Prevedeno iz %1$s s pomočjo %2$s</string>
|
||||
<string name="translation_show_original">Pokaži izvirnik</string>
|
||||
<string name="translation_failed">Prevod je spodletel. Morda skrbnik ni omogočil prevajanja na tem strežniku ali pa strežnik teče na starejši različici Masotodona, na kateri prevajanje še ni podprto.</string>
|
||||
<string name="settings_privacy">Zasebnost in dosegljivost</string>
|
||||
<string name="settings_discoverable">Izpostavljaj profile in objave v algoritmih odkrivanja</string>
|
||||
<string name="settings_indexable">Med zadetke iskanja vključi javne objave</string>
|
||||
</resources>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<string name="in_reply_to">Som svar på %s</string>
|
||||
<string name="notifications">Notiser</string>
|
||||
<string name="user_followed_you">%s följde dig</string>
|
||||
<string name="user_favorited">%s favoritmarkerade ditt inlägg</string>
|
||||
<string name="share_toot_title">Dela</string>
|
||||
<string name="settings">Inställningar</string>
|
||||
<string name="publish">Publicera</string>
|
||||
|
@ -229,6 +230,7 @@
|
|||
<string name="file_saved">Filen sparad</string>
|
||||
<string name="downloading">Laddar ner…</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="recommended_accounts_info_banner">Du kanske gillar dessa konton baserat på andra konton du följer.</string>
|
||||
<string name="see_new_posts">Se nya inlägg</string>
|
||||
<string name="load_missing_posts">Ladda saknade inlägg</string>
|
||||
<string name="follow_back">Följ tillbaka</string>
|
||||
|
@ -353,6 +355,8 @@
|
|||
<string name="attachment_description_video">%s video</string>
|
||||
<string name="attachment_description_audio">%s ljud</string>
|
||||
<string name="attachment_description_unknown">%s fil</string>
|
||||
<string name="attachment_type_image">Bild</string>
|
||||
<string name="attachment_type_video">Video</string>
|
||||
<string name="attachment_type_audio">Ljud</string>
|
||||
<string name="attachment_type_gif">GIF</string>
|
||||
<string name="attachment_type_unknown">Fil</string>
|
||||
|
@ -383,6 +387,7 @@
|
|||
<string name="about_server">Om</string>
|
||||
<string name="server_rules">Regler</string>
|
||||
<string name="server_administrator">Administratör</string>
|
||||
<string name="settings_show_emoji_in_names">Anpassad emoji i visningsnamn</string>
|
||||
<plurals name="in_x_hours">
|
||||
<item quantity="one">om %d timme</item>
|
||||
<item quantity="other">om %d timmar</item>
|
||||
|
@ -391,6 +396,9 @@
|
|||
<item quantity="one">%d timme sedan</item>
|
||||
<item quantity="other">%d timmar sedan</item>
|
||||
</plurals>
|
||||
<string name="count_two">Två</string>
|
||||
<string name="count_three">Tre</string>
|
||||
<string name="count_four">Fyra</string>
|
||||
<!-- %s is the username -->
|
||||
<string name="filter_active">Aktiv</string>
|
||||
<string name="filter_inactive">Inaktiv</string>
|
||||
|
@ -401,12 +409,19 @@
|
|||
<string name="selection_2_options">%1$s och %2$s</string>
|
||||
<string name="selection_3_options">%1$s, %2$s och %3$s</string>
|
||||
<string name="filter_context_profiles">Profiler</string>
|
||||
<string name="settings_delete_filter_confirmation">Detta filter kommer raderas från ditt konto på alla dina enheter.</string>
|
||||
<string name="add">Lägg till</string>
|
||||
<string name="filter_word_or_phrase">Ord eller fras</string>
|
||||
<string name="enter_selection_mode">Välj</string>
|
||||
<string name="select_all">Välj alla</string>
|
||||
<plurals name="settings_delete_x_filter_words">
|
||||
<item quantity="one">Radera %d ord?</item>
|
||||
<item quantity="other">Radera %d ord?</item>
|
||||
</plurals>
|
||||
<string name="app_update_version">Version %s</string>
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<string name="post_matches_filter_x">Matchar filter \"%s\"</string>
|
||||
<string name="search_mastodon">Sök i Mastodon</string>
|
||||
<string name="clear_all">Rensa alla</string>
|
||||
<string name="search_open_url">Öppna URL i Mastodon</string>
|
||||
<string name="posts_matching_hashtag">Inlägg med \"%s\"</string>
|
||||
|
@ -416,4 +431,7 @@
|
|||
<string name="time_minutes_ago_short">%dm sedan</string>
|
||||
<string name="time_hours_ago_short">%dt sedan</string>
|
||||
<string name="time_days_ago_short">%dd sedan</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Översätt från %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -553,4 +553,19 @@
|
|||
<string name="time_minutes_ago_short">%d นาทีที่แล้ว</string>
|
||||
<string name="time_hours_ago_short">%d ชั่วโมงที่แล้ว</string>
|
||||
<string name="time_days_ago_short">%d วันที่แล้ว</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">แปลจาก %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">แปลจาก %1$s โดยใช้ %2$s</string>
|
||||
<string name="translation_show_original">แสดงดั้งเดิม</string>
|
||||
<string name="translation_failed">การแปลล้มเหลว บางทีผู้ดูแลอาจไม่ได้เปิดใช้งานการแปลในเซิร์ฟเวอร์นี้หรือเซิร์ฟเวอร์นี้กำลังใช้ Mastodon รุ่นเก่ากว่าที่ยังไม่รองรับการแปล</string>
|
||||
<string name="settings_privacy">ความเป็นส่วนตัวและการเข้าถึง</string>
|
||||
<string name="settings_discoverable">แสดงโปรไฟล์และโพสต์ในอัลกอริทึมการค้นพบ</string>
|
||||
<string name="settings_indexable">รวมโพสต์สาธารณะในผลลัพธ์การค้นหา</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="other">%,d ผู้มีส่วนร่วม</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="other">%,d โพสต์วันนี้</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -387,6 +387,7 @@
|
|||
<string name="welcome_to_mastodon">Mastodon\'a hoş geldiniz</string>
|
||||
<string name="welcome_paragraph1">Mastodon merkezi olmayan bir sosyal ağdır, yani onu tek bir şirket kontrol etmiyor. Hepsi birbirine bağlı, bağımsız olarak çalışan birçok sunucudan oluşur.</string>
|
||||
<string name="what_are_servers">Sunucular nedir?</string>
|
||||
<string name="welcome_paragraph2">Her Mastodon hesabı bir sunucuda barındırılır - her birinin kendi değerleri, kuralları ve yöneticileri vardır. Hangisini seçerseniz seçin, herhangi bir sunucudaki insanları takip edebilir ve onlarla etkileşime geçebilirsiniz.</string>
|
||||
<string name="opening_link">Bağlantı açılıyor…</string>
|
||||
<string name="link_not_supported">Bu bağlantı uygulamada desteklenmiyor</string>
|
||||
<string name="log_out_all_accounts">Tüm hesaplardan çıkış yap</string>
|
||||
|
@ -581,4 +582,21 @@
|
|||
<string name="time_minutes_ago_short">%ddk önce</string>
|
||||
<string name="time_hours_ago_short">%dsa önce</string>
|
||||
<string name="time_days_ago_short">%dg önce</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">%s dilinden çevrildi</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">%2$s kullanılarak %1$s dilinden çevrildi</string>
|
||||
<string name="translation_show_original">Özgün içeriği göster</string>
|
||||
<string name="translation_failed">Çeviri başarısız oldu. Yönetici bu sunucuda çevirileri etkinleştirmemiş olabilir veya bu sunucu çevirilerin henüz desteklenmediği eski bir Mastodon sürümünü çalıştırıyor olabilir.</string>
|
||||
<string name="settings_privacy">Gizlilik ve erişim</string>
|
||||
<string name="settings_discoverable">Profil ve gönderileri keşif algoritmalarında kullan</string>
|
||||
<string name="settings_indexable">Herkese açık gönderileri arama sonuçlarına ekle</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="one">%d katılımcılar</item>
|
||||
<item quantity="other">%d katılımcılar</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="one">%,d bunu gönder</item>
|
||||
<item quantity="other">%,d bunları gönder</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -425,6 +425,7 @@
|
|||
<string name="welcome_to_mastodon">Вітаємо у Mastodon</string>
|
||||
<string name="welcome_paragraph1">Mastodon - це децентралізована соціальна мережа, тобто жодна компанія не контролює її. Вона складається з багатьох незалежних серверів, які з\'єднані між собою.</string>
|
||||
<string name="what_are_servers">Що таке сервери?</string>
|
||||
<string name="welcome_paragraph2">Кожен обліковий запис Mastodon розміщений на сервері - кожен сервер має свої цінності, правила, й & адмінів. Немає різниці, який ви оберете, ви зможете підписуватися та спілкуватися з користувачами з будь-якого.</string>
|
||||
<string name="opening_link">Відкриття посилання…</string>
|
||||
<string name="link_not_supported">Це посилання не підтримується застосунком</string>
|
||||
<string name="log_out_all_accounts">Вийти з усіх акаунтів</string>
|
||||
|
@ -639,4 +640,25 @@
|
|||
<string name="time_minutes_ago_short">%dхв. тому</string>
|
||||
<string name="time_hours_ago_short">%dгод. тому</string>
|
||||
<string name="time_days_ago_short">%dд. тому</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Перекласти з %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">Перекладено з %1$s за допомогою %2$s</string>
|
||||
<string name="translation_show_original">Показати оригінал</string>
|
||||
<string name="translation_failed">Не вдалося виконати переклад. Можливо, адміністратор не активував переклади на цьому сервері або цей сервер використовує стару версію Mastodon, де переклади ще не підтримуються.</string>
|
||||
<string name="settings_privacy">Приватність і досяжність</string>
|
||||
<string name="settings_discoverable">Враховувати профіль та дописи в алгоритмах пошуку</string>
|
||||
<string name="settings_indexable">Включити загальнодоступні дописи в результати пошуку</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="one">%,d учасник</item>
|
||||
<item quantity="few">%,d учасники</item>
|
||||
<item quantity="many">%,d учасників</item>
|
||||
<item quantity="other">%,d учасника</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="one">%,d допис сьогодні</item>
|
||||
<item quantity="few">%,d дописи сьогодні</item>
|
||||
<item quantity="many">%,d дописів сьогодні</item>
|
||||
<item quantity="other">%,d дописа сьогодні</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -20,4 +20,6 @@
|
|||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||
<!-- Shown like a content warning, %s is the name of the filter -->
|
||||
<!-- Shown in the post header. Please keep it short -->
|
||||
<!-- %s is the name of the post language -->
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
</resources>
|
||||
|
|
|
@ -266,7 +266,7 @@
|
|||
<item quantity="other">%,d lượt thích</item>
|
||||
</plurals>
|
||||
<plurals name="x_reblogs">
|
||||
<item quantity="other">%,đăng lại</item>
|
||||
<item quantity="other">%,d đăng lại</item>
|
||||
</plurals>
|
||||
<string name="timestamp_via_app">%1$s qua %2$s</string>
|
||||
<string name="time_now">vừa xong</string>
|
||||
|
@ -553,4 +553,16 @@
|
|||
<string name="time_minutes_ago_short">%dp</string>
|
||||
<string name="time_hours_ago_short">%dh</string>
|
||||
<string name="time_days_ago_short">%d ngày</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Dịch từ %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">Dịch từ %1$s bằng %2$s</string>
|
||||
<string name="translation_show_original">Bản gốc</string>
|
||||
<string name="translation_failed">Dịch không thành công. Có thể quản trị viên chưa bật dịch trên máy chủ này hoặc máy chủ này đang chạy phiên bản cũ hơn của Mastodon chưa hỗ trợ dịch.</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="other">%,d người thảo luận</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="other">%,d tút hôm nay</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -552,4 +552,13 @@
|
|||
<string name="time_minutes_ago_short">%d 分钟前</string>
|
||||
<string name="time_hours_ago_short">%d 小时前</string>
|
||||
<string name="time_days_ago_short">%d 天前</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">从 %s 翻译</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">从 %1$s 翻译成 %2$s</string>
|
||||
<string name="translation_show_original">显示原文</string>
|
||||
<string name="translation_failed">翻译失败。此服务器运行的 Mastodon 版本不支持翻译功能,或管理员未将翻译功能开启。</string>
|
||||
<string name="settings_privacy">隐私与可达性</string>
|
||||
<string name="settings_discoverable">在发现算法中展示您的个人资料和嘟文</string>
|
||||
<string name="settings_indexable">将您的公开嘟文纳入搜索范围</string>
|
||||
</resources>
|
||||
|
|
|
@ -553,4 +553,19 @@
|
|||
<string name="time_minutes_ago_short">%d 分鐘前</string>
|
||||
<string name="time_hours_ago_short">%d 小時前</string>
|
||||
<string name="time_days_ago_short">%d 天前</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">翻譯自 %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">透過 %2$s 翻譯 %1$s</string>
|
||||
<string name="translation_show_original">顯示原文</string>
|
||||
<string name="translation_failed">翻譯失敗。也許管理員未於此伺服器啟用翻譯功能,或此伺服器為未支援翻譯功能之舊版本 Mastodon。</string>
|
||||
<string name="settings_privacy">隱私權及觸及</string>
|
||||
<string name="settings_discoverable">於探索演算法中推薦個人檔案及嘟文</string>
|
||||
<string name="settings_indexable">允許公開嘟文顯示於搜尋結果中</string>
|
||||
<plurals name="x_participants">
|
||||
<item quantity="other">%,d 位參與者</item>
|
||||
</plurals>
|
||||
<plurals name="x_posts_today">
|
||||
<item quantity="other">本日共 %,d 則嘟文</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
<item name="android:windowActionModeOverlay">true</item>
|
||||
<item name="android:actionModeBackground">?colorM3PrimaryContainer</item>
|
||||
<item name="android:actionModeCloseDrawable">@drawable/ic_fluent_dismiss_24_regular</item>
|
||||
<!-- <item name="appkitEmptyTextAppearance">@style/empty_text</item>-->
|
||||
|
||||
<item name="android:statusBarColor">?colorM3Background</item>
|
||||
<item name="android:navigationBarColor">?colorM3Background</item>
|
||||
|
@ -72,6 +73,7 @@
|
|||
<item name="android:windowActionModeOverlay">true</item>
|
||||
<item name="android:actionModeBackground">?colorM3PrimaryContainer</item>
|
||||
<item name="android:actionModeCloseDrawable">@drawable/ic_fluent_dismiss_24_regular</item>
|
||||
<!-- <item name="appkitEmptyTextAppearance">@style/empty_text</item>-->
|
||||
|
||||
<item name="colorM3DisabledBackground">#1FE3E3E3</item>
|
||||
<item name="colorM3Error">#F2B8B5</item>
|
||||
|
@ -381,4 +383,8 @@
|
|||
<style name="window_fade_out">
|
||||
<item name="android:windowExitAnimation">@anim/fade_out_fast</item>
|
||||
</style>
|
||||
|
||||
<style name="empty_text" parent="m3_body_large">
|
||||
<item name="android:textColor">?colorM3OnSurfaceVariant</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -0,0 +1,116 @@
|
|||
// run: java tools/VerifyTranslatedStringFormatting.java
|
||||
// Reads all localized strings and makes sure they contain valid formatting placeholders matching the original English strings to avoid crashes.
|
||||
|
||||
import org.w3c.dom.*;
|
||||
import javax.xml.parsers.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
|
||||
public class VerifyTranslatedStringFormatting{
|
||||
// %[argument_index$][flags][width][.precision][t]conversion
|
||||
private static final String formatSpecifier="%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
|
||||
private static final Pattern fsPattern=Pattern.compile(formatSpecifier);
|
||||
|
||||
private static HashMap<String, List<String>> placeholdersInStrings=new HashMap<>();
|
||||
private static int errorCount=0;
|
||||
|
||||
public static void main(String[] args) throws Exception{
|
||||
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(false);
|
||||
DocumentBuilder builder=factory.newDocumentBuilder();
|
||||
Document doc;
|
||||
try(FileInputStream in=new FileInputStream("mastodon/src/main/res/values/strings.xml")){
|
||||
doc=builder.parse(in);
|
||||
}
|
||||
NodeList list=doc.getDocumentElement().getChildNodes(); // why does this stupid NodeList thing exist at all?
|
||||
for(int i=0;i<list.getLength();i++){
|
||||
if(list.item(i) instanceof Element el){
|
||||
String name=el.getAttribute("name");
|
||||
String value;
|
||||
if("string".equals(el.getTagName())){
|
||||
value=el.getTextContent();
|
||||
}else if("plurals".equals(el.getTagName())){
|
||||
value=el.getElementsByTagName("item").item(0).getTextContent();
|
||||
}else{
|
||||
System.out.println("Warning: unexpected tag "+name);
|
||||
continue;
|
||||
}
|
||||
ArrayList<String> placeholders=new ArrayList<>();
|
||||
Matcher matcher=fsPattern.matcher(value);
|
||||
while(matcher.find()){
|
||||
placeholders.add(matcher.group());
|
||||
}
|
||||
placeholdersInStrings.put(name, placeholders);
|
||||
}
|
||||
}
|
||||
for(File file:new File("mastodon/src/main/res").listFiles()){
|
||||
if(file.getName().startsWith("values-")){
|
||||
File stringsXml=new File(file, "strings.xml");
|
||||
if(stringsXml.exists()){
|
||||
processFile(stringsXml);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(errorCount>0){
|
||||
System.err.println("Found "+errorCount+" problems in localized strings");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void processFile(File file) throws Exception{
|
||||
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(false);
|
||||
DocumentBuilder builder=factory.newDocumentBuilder();
|
||||
Document doc;
|
||||
try(FileInputStream in=new FileInputStream(file)){
|
||||
doc=builder.parse(in);
|
||||
}
|
||||
NodeList list=doc.getDocumentElement().getChildNodes();
|
||||
for(int i=0;i<list.getLength();i++){
|
||||
if(list.item(i) instanceof Element el){
|
||||
String name=el.getAttribute("name");
|
||||
String value;
|
||||
if("string".equals(el.getTagName())){
|
||||
value=el.getTextContent();
|
||||
if(!verifyString(value, placeholdersInStrings.get(name))){
|
||||
errorCount++;
|
||||
System.out.println(file+": string "+name+" is missing placeholders");
|
||||
}
|
||||
}else if("plurals".equals(el.getTagName())){
|
||||
NodeList items=el.getElementsByTagName("item");
|
||||
for(int j=0;j<items.getLength();j++){
|
||||
Element item=(Element)items.item(j);
|
||||
value=item.getTextContent();
|
||||
String quantity=item.getAttribute("quantity");
|
||||
if(!verifyString(value, placeholdersInStrings.get(name))){
|
||||
// Some languages use zero/one/two for just these numbers so they may skip the placeholder
|
||||
// still make sure that there's no '%' characters to avoid crashes
|
||||
if(List.of("zero", "one", "two").contains(quantity) && !value.contains("%")){
|
||||
continue;
|
||||
}
|
||||
errorCount++;
|
||||
System.out.println(file+": string "+name+"["+quantity+"] is missing placeholders");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
System.out.println("Warning: unexpected tag "+name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean verifyString(String str, List<String> placeholders){
|
||||
for(String placeholder:placeholders){
|
||||
if(placeholder.equals("%,d")){
|
||||
// %,d and %d are interchangeable but %,d provides nicer formatting
|
||||
if(!str.contains(placeholder) && !str.contains("%d"))
|
||||
return false;
|
||||
}else if(!str.contains(placeholder)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue