Compare commits
8 Commits
v1.1.1+for
...
v1.1.1+for
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1e67c4f73 | ||
|
|
e0e48f87eb | ||
|
|
b2db64022f | ||
|
|
0ec14fe8fa | ||
|
|
01a2f1d95c | ||
|
|
67b3e85837 | ||
|
|
9f4d330ab1 | ||
|
|
25092fbcfb |
@@ -1,3 +1,5 @@
|
||||

|
||||
|
||||
# Mastodon for Android Fork
|
||||
|
||||
## Changes
|
||||
|
||||
@@ -9,8 +9,8 @@ android {
|
||||
applicationId "org.joinmastodon.android.sk"
|
||||
minSdk 23
|
||||
targetSdk 31
|
||||
versionCode 18
|
||||
versionName '1.1.1+fork.18'
|
||||
versionCode 19
|
||||
versionName '1.1.1+fork.19'
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.joinmastodon.android.api;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class AvatarResizedImageRequestBody extends ResizedImageRequestBody{
|
||||
public AvatarResizedImageRequestBody(Uri uri, ProgressListener progressListener) throws IOException{
|
||||
super(uri, 0, progressListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] getTargetSize(int srcWidth, int srcHeight){
|
||||
float factor=400f/Math.min(srcWidth, srcHeight);
|
||||
return new int[]{Math.round(srcWidth*factor), Math.round(srcHeight*factor)};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needResize(int srcWidth, int srcHeight){
|
||||
return srcHeight>400 || srcWidth!=srcHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needCrop(int srcWidth, int srcHeight){
|
||||
return srcWidth!=srcHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rect getCropBounds(int srcWidth, int srcHeight){
|
||||
Rect rect=new Rect();
|
||||
if(srcWidth>srcHeight){
|
||||
rect.set(srcWidth/2-srcHeight/2, 0, srcWidth/2-srcHeight/2+srcHeight, srcHeight);
|
||||
}else{
|
||||
rect.set(0, srcHeight/2-srcWidth/2, srcWidth, srcHeight/2-srcWidth/2+srcWidth);
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import android.os.Build;
|
||||
import android.provider.OpenableColumns;
|
||||
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -30,62 +31,105 @@ public class ResizedImageRequestBody extends CountingRequestBody{
|
||||
private File tempFile;
|
||||
private Uri uri;
|
||||
private String contentType;
|
||||
private int maxSize;
|
||||
|
||||
public ResizedImageRequestBody(Uri uri, int maxSize, ProgressListener progressListener) throws IOException{
|
||||
super(progressListener);
|
||||
this.uri=uri;
|
||||
contentType=MastodonApp.context.getContentResolver().getType(uri);
|
||||
this.maxSize=maxSize;
|
||||
BitmapFactory.Options opts=new BitmapFactory.Options();
|
||||
opts.inJustDecodeBounds=true;
|
||||
try(InputStream in=MastodonApp.context.getContentResolver().openInputStream(uri)){
|
||||
BitmapFactory.decodeStream(in, null, opts);
|
||||
if("file".equals(uri.getScheme())){
|
||||
BitmapFactory.decodeFile(uri.getPath(), opts);
|
||||
contentType=UiUtils.getFileMediaType(new File(uri.getPath())).type();
|
||||
}else{
|
||||
try(InputStream in=MastodonApp.context.getContentResolver().openInputStream(uri)){
|
||||
BitmapFactory.decodeStream(in, null, opts);
|
||||
}
|
||||
contentType=MastodonApp.context.getContentResolver().getType(uri);
|
||||
}
|
||||
if(opts.outWidth*opts.outHeight>maxSize){
|
||||
if(needResize(opts.outWidth, opts.outHeight) || needCrop(opts.outWidth, opts.outHeight)){
|
||||
Bitmap bitmap;
|
||||
if(Build.VERSION.SDK_INT>=29){
|
||||
bitmap=ImageDecoder.decodeBitmap(ImageDecoder.createSource(MastodonApp.context.getContentResolver(), uri), (decoder, info, source)->{
|
||||
int targetWidth=Math.round((float)Math.sqrt((float)maxSize*((float)info.getSize().getWidth()/info.getSize().getHeight())));
|
||||
int targetHeight=Math.round((float)Math.sqrt((float)maxSize*((float)info.getSize().getHeight()/info.getSize().getWidth())));
|
||||
if(Build.VERSION.SDK_INT>=28){
|
||||
ImageDecoder.Source source;
|
||||
if("file".equals(uri.getScheme())){
|
||||
source=ImageDecoder.createSource(new File(uri.getPath()));
|
||||
}else{
|
||||
source=ImageDecoder.createSource(MastodonApp.context.getContentResolver(), uri);
|
||||
}
|
||||
bitmap=ImageDecoder.decodeBitmap(source, (decoder, info, _source)->{
|
||||
int[] size=getTargetSize(info.getSize().getWidth(), info.getSize().getHeight());
|
||||
decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
|
||||
decoder.setTargetSize(targetWidth, targetHeight);
|
||||
decoder.setTargetSize(size[0], size[1]);
|
||||
// Breaks images in mysterious ways
|
||||
// if(needCrop(size[0], size[1]))
|
||||
// decoder.setCrop(getCropBounds(size[0], size[1]));
|
||||
});
|
||||
if(needCrop(bitmap.getWidth(), bitmap.getHeight())){
|
||||
Rect crop=getCropBounds(bitmap.getWidth(), bitmap.getHeight());
|
||||
bitmap=Bitmap.createBitmap(bitmap, crop.left, crop.top, crop.width(), crop.height());
|
||||
}
|
||||
}else{
|
||||
int targetWidth=Math.round((float)Math.sqrt((float)maxSize*((float)opts.outWidth/opts.outHeight)));
|
||||
int targetHeight=Math.round((float)Math.sqrt((float)maxSize*((float)opts.outHeight/opts.outWidth)));
|
||||
int[] size=getTargetSize(opts.outWidth, opts.outHeight);
|
||||
int targetWidth=size[0];
|
||||
int targetHeight=size[1];
|
||||
float factor=opts.outWidth/(float)targetWidth;
|
||||
opts=new BitmapFactory.Options();
|
||||
opts.inSampleSize=(int)factor;
|
||||
try(InputStream in=MastodonApp.context.getContentResolver().openInputStream(uri)){
|
||||
bitmap=BitmapFactory.decodeStream(in, null, opts);
|
||||
if("file".equals(uri.getScheme())){
|
||||
bitmap=BitmapFactory.decodeFile(uri.getPath(), opts);
|
||||
}else{
|
||||
try(InputStream in=MastodonApp.context.getContentResolver().openInputStream(uri)){
|
||||
bitmap=BitmapFactory.decodeStream(in, null, opts);
|
||||
}
|
||||
}
|
||||
if(factor%1f!=0f){
|
||||
Bitmap scaled=Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
|
||||
new Canvas(scaled).drawBitmap(bitmap, null, new Rect(0, 0, targetWidth, targetHeight), new Paint(Paint.FILTER_BITMAP_FLAG));
|
||||
boolean needCrop=needCrop(targetWidth, targetHeight);
|
||||
if(factor%1f!=0f || needCrop){
|
||||
Rect srcBounds=null;
|
||||
Rect dstBounds;
|
||||
if(needCrop){
|
||||
Rect crop=getCropBounds(targetWidth, targetHeight);
|
||||
dstBounds=new Rect(0, 0, crop.width(), crop.height());
|
||||
srcBounds=new Rect(
|
||||
Math.round(crop.left/(float)targetWidth*bitmap.getWidth()),
|
||||
Math.round(crop.top/(float)targetHeight*bitmap.getHeight()),
|
||||
Math.round(crop.right/(float)targetWidth*bitmap.getWidth()),
|
||||
Math.round(crop.bottom/(float)targetHeight*bitmap.getHeight())
|
||||
);
|
||||
}else{
|
||||
dstBounds=new Rect(0, 0, targetWidth, targetHeight);
|
||||
}
|
||||
Bitmap scaled=Bitmap.createBitmap(dstBounds.width(), dstBounds.height(), Bitmap.Config.ARGB_8888);
|
||||
new Canvas(scaled).drawBitmap(bitmap, srcBounds, dstBounds, new Paint(Paint.FILTER_BITMAP_FLAG));
|
||||
bitmap=scaled;
|
||||
}
|
||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
|
||||
int rotation;
|
||||
int orientation=0;
|
||||
if("file".equals(uri.getScheme())){
|
||||
ExifInterface exif=new ExifInterface(uri.getPath());
|
||||
orientation=exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
|
||||
}else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
|
||||
try(InputStream in=MastodonApp.context.getContentResolver().openInputStream(uri)){
|
||||
ExifInterface exif=new ExifInterface(in);
|
||||
int orientation=exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
|
||||
rotation=switch(orientation){
|
||||
case ExifInterface.ORIENTATION_ROTATE_90 -> 90;
|
||||
case ExifInterface.ORIENTATION_ROTATE_180 -> 180;
|
||||
case ExifInterface.ORIENTATION_ROTATE_270 -> 270;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
if(rotation!=0){
|
||||
Matrix matrix=new Matrix();
|
||||
matrix.setRotate(rotation);
|
||||
bitmap=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
|
||||
orientation=exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
|
||||
}
|
||||
}
|
||||
int rotation=switch(orientation){
|
||||
case ExifInterface.ORIENTATION_ROTATE_90 -> 90;
|
||||
case ExifInterface.ORIENTATION_ROTATE_180 -> 180;
|
||||
case ExifInterface.ORIENTATION_ROTATE_270 -> 270;
|
||||
default -> 0;
|
||||
};
|
||||
if(rotation!=0){
|
||||
Matrix matrix=new Matrix();
|
||||
matrix.setRotate(rotation);
|
||||
bitmap=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
|
||||
}
|
||||
}
|
||||
|
||||
tempFile=new File(MastodonApp.context.getCacheDir(), "tmp_upload_image");
|
||||
boolean isPNG="image/png".equals(contentType);
|
||||
tempFile=File.createTempFile("mastodon_tmp_resized", null);
|
||||
try(FileOutputStream out=new FileOutputStream(tempFile)){
|
||||
if("image/png".equals(contentType)){
|
||||
if(isPNG){
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 0, out);
|
||||
}else{
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 97, out);
|
||||
@@ -94,9 +138,13 @@ public class ResizedImageRequestBody extends CountingRequestBody{
|
||||
}
|
||||
length=tempFile.length();
|
||||
}else{
|
||||
try(Cursor cursor=MastodonApp.context.getContentResolver().query(uri, new String[]{OpenableColumns.SIZE}, null, null, null)){
|
||||
cursor.moveToFirst();
|
||||
length=cursor.getInt(0);
|
||||
if("file".equals(uri.getScheme())){
|
||||
length=new File(uri.getPath()).length();
|
||||
}else{
|
||||
try(Cursor cursor=MastodonApp.context.getContentResolver().query(uri, new String[]{OpenableColumns.SIZE}, null, null, null)){
|
||||
cursor.moveToFirst();
|
||||
length=cursor.getInt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,4 +173,22 @@ public class ResizedImageRequestBody extends CountingRequestBody{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected int[] getTargetSize(int srcWidth, int srcHeight){
|
||||
int targetWidth=Math.round((float)Math.sqrt((float)maxSize*((float)srcWidth/srcHeight)));
|
||||
int targetHeight=Math.round((float)Math.sqrt((float)maxSize*((float)srcHeight/srcWidth)));
|
||||
return new int[]{targetWidth, targetHeight};
|
||||
}
|
||||
|
||||
protected boolean needResize(int srcWidth, int srcHeight){
|
||||
return srcWidth*srcHeight>maxSize;
|
||||
}
|
||||
|
||||
protected boolean needCrop(int srcWidth, int srcHeight){
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Rect getCropBounds(int srcWidth, int srcHeight){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,16 @@ package org.joinmastodon.android.api.requests.accounts;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import org.joinmastodon.android.api.AvatarResizedImageRequestBody;
|
||||
import org.joinmastodon.android.api.ContentUriRequestBody;
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.api.ResizedImageRequestBody;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.AccountField;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.MultipartBody;
|
||||
@@ -39,21 +42,21 @@ public class UpdateAccountCredentials extends MastodonAPIRequest<Account>{
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestBody getRequestBody(){
|
||||
public RequestBody getRequestBody() throws IOException{
|
||||
MultipartBody.Builder bldr=new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart("display_name", displayName)
|
||||
.addFormDataPart("note", bio);
|
||||
|
||||
if(avatar!=null){
|
||||
bldr.addFormDataPart("avatar", UiUtils.getFileName(avatar), new ContentUriRequestBody(avatar, null));
|
||||
bldr.addFormDataPart("avatar", UiUtils.getFileName(avatar), new AvatarResizedImageRequestBody(avatar, null));
|
||||
}else if(avatarFile!=null){
|
||||
bldr.addFormDataPart("avatar", avatarFile.getName(), RequestBody.create(UiUtils.getFileMediaType(avatarFile), avatarFile));
|
||||
bldr.addFormDataPart("avatar", avatarFile.getName(), new AvatarResizedImageRequestBody(Uri.fromFile(avatarFile), null));
|
||||
}
|
||||
if(cover!=null){
|
||||
bldr.addFormDataPart("header", UiUtils.getFileName(cover), new ContentUriRequestBody(cover, null));
|
||||
bldr.addFormDataPart("header", UiUtils.getFileName(cover), new ResizedImageRequestBody(cover, 1500*500, null));
|
||||
}else if(coverFile!=null){
|
||||
bldr.addFormDataPart("header", coverFile.getName(), RequestBody.create(UiUtils.getFileMediaType(coverFile), coverFile));
|
||||
bldr.addFormDataPart("header", coverFile.getName(), new ResizedImageRequestBody(Uri.fromFile(coverFile), 1500*500, null));
|
||||
}
|
||||
if(fields.isEmpty()){
|
||||
bldr.addFormDataPart("fields_attributes[0][name]", "").addFormDataPart("fields_attributes[0][value]", "");
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Mastodon</string>
|
||||
<string name="get_started">开始使用</string>
|
||||
<string name="log_in">登录</string>
|
||||
<string name="next">下一步</string>
|
||||
@@ -8,12 +7,15 @@
|
||||
<string name="error">错误</string>
|
||||
<string name="not_a_mastodon_instance">%s 似乎不是Mastodon实例。</string>
|
||||
<string name="ok">确定</string>
|
||||
<string name="preparing_auth">正在跳转...</string>
|
||||
<string name="finishing_auth">正在完成身份验证…</string>
|
||||
<string name="in_reply_to">回复给 %s</string>
|
||||
<string name="preparing_auth">正在准备身份认证…</string>
|
||||
<string name="finishing_auth">正在完成身份认证…</string>
|
||||
<string name="user_boosted">%s 转发了</string>
|
||||
<string name="in_reply_to">回复 %s</string>
|
||||
<string name="notifications">通知</string>
|
||||
<string name="user_followed_you">关注了你</string>
|
||||
<string name="user_sent_follow_request">向您发送了关注请求</string>
|
||||
<string name="user_sent_follow_request">向你发送了关注请求</string>
|
||||
<string name="user_favorited">喜欢了你的嘟文</string>
|
||||
<string name="notification_boosted">转发了你的嘟文</string>
|
||||
<string name="poll_ended">投票已结束</string>
|
||||
<string name="time_seconds">%d 秒前</string>
|
||||
<string name="time_minutes">%d 分钟前</string>
|
||||
@@ -22,7 +24,7 @@
|
||||
<string name="share_toot_title">分享</string>
|
||||
<string name="settings">设置</string>
|
||||
<string name="publish">发布</string>
|
||||
<string name="discard_draft">舍弃草稿?</string>
|
||||
<string name="discard_draft">丢弃草稿?</string>
|
||||
<string name="discard">丢弃</string>
|
||||
<string name="cancel">取消</string>
|
||||
<plurals name="followers">
|
||||
@@ -32,175 +34,302 @@
|
||||
<item quantity="other">正在关注</item>
|
||||
</plurals>
|
||||
<plurals name="posts">
|
||||
<item quantity="other">帖子</item>
|
||||
<item quantity="other">嘟文</item>
|
||||
</plurals>
|
||||
<string name="posts">帖子</string>
|
||||
<string name="posts_and_replies">帖子与回复</string>
|
||||
<string name="media">媒体文件</string>
|
||||
<string name="posts">嘟文</string>
|
||||
<string name="posts_and_replies">嘟文和回复</string>
|
||||
<string name="pinned_posts">置顶</string>
|
||||
<string name="media">媒体</string>
|
||||
<string name="profile_about">关于</string>
|
||||
<string name="button_follow">关注</string>
|
||||
<string name="button_following">正在关注</string>
|
||||
<string name="edit_profile">修改个人资料</string>
|
||||
<string name="mention_user">提及 %s</string>
|
||||
<string name="share_user">分享 %s</string>
|
||||
<string name="mute_user">静音 %s</string>
|
||||
<string name="unmute_user">不再静音 %s</string>
|
||||
<string name="mute_user">隐藏 %s</string>
|
||||
<string name="unmute_user">不再隐藏 %s</string>
|
||||
<string name="block_user">屏蔽 %s</string>
|
||||
<string name="unblock_user">解除屏蔽 %s</string>
|
||||
<string name="unblock_user">不再屏蔽 %s</string>
|
||||
<string name="report_user">举报 %s</string>
|
||||
<string name="block_domain">屏蔽 %s</string>
|
||||
<string name="unblock_domain">解除屏蔽 %s</string>
|
||||
<string name="block_domain">屏蔽 %s 实例</string>
|
||||
<string name="unblock_domain">不再屏蔽 %s 实例</string>
|
||||
<plurals name="x_posts">
|
||||
<item quantity="other">%d 个帖子</item>
|
||||
<item quantity="other">%d 条嘟文</item>
|
||||
</plurals>
|
||||
<string name="profile_joined">加入于</string>
|
||||
<string name="done">完成</string>
|
||||
<string name="loading">加载中...</string>
|
||||
<string name="loading">正在加载…</string>
|
||||
<string name="field_label">标签</string>
|
||||
<string name="saving">保存中...</string>
|
||||
<string name="post_from_user">来自 %s 的帖子</string>
|
||||
<string name="poll_option_hint">选项 %d</string>
|
||||
<string name="field_content">内容</string>
|
||||
<string name="saving">正在保存…</string>
|
||||
<string name="post_from_user">来自 %s 的嘟文</string>
|
||||
<string name="poll_option_hint">"选项 %d"</string>
|
||||
<plurals name="x_minutes">
|
||||
<item quantity="other">%d分钟</item>
|
||||
<item quantity="other">%d 分钟</item>
|
||||
</plurals>
|
||||
<plurals name="x_hours">
|
||||
<item quantity="other">%d小时</item>
|
||||
<item quantity="other">%d 小时</item>
|
||||
</plurals>
|
||||
<plurals name="x_days">
|
||||
<item quantity="other">%d天</item>
|
||||
<item quantity="other">%d 天</item>
|
||||
</plurals>
|
||||
<string name="compose_poll_duration">时长: %s</string>
|
||||
<string name="compose_poll_duration">时长:%s</string>
|
||||
<plurals name="x_seconds_left">
|
||||
<item quantity="other">剩余 %d 秒</item>
|
||||
<item quantity="other">%d 秒后结束</item>
|
||||
</plurals>
|
||||
<plurals name="x_minutes_left">
|
||||
<item quantity="other">剩余 %d 分钟</item>
|
||||
<item quantity="other">%d 分钟后结束</item>
|
||||
</plurals>
|
||||
<plurals name="x_hours_left">
|
||||
<item quantity="other">%d 小时后结束</item>
|
||||
</plurals>
|
||||
<plurals name="x_days_left">
|
||||
<item quantity="other">%d 天后结束</item>
|
||||
</plurals>
|
||||
<plurals name="x_voters">
|
||||
<item quantity="other">%d 人已投票</item>
|
||||
</plurals>
|
||||
<string name="poll_closed">已关闭</string>
|
||||
<string name="tap_to_reveal">点击以显示</string>
|
||||
<string name="confirm_mute_title">隐藏用户</string>
|
||||
<string name="confirm_mute">确定要隐藏 %s 吗?</string>
|
||||
<string name="do_mute">确定</string>
|
||||
<string name="confirm_unmute_title">取消隐藏</string>
|
||||
<string name="confirm_unmute">确定不再隐藏 %s 吗?</string>
|
||||
<string name="do_unmute">确定</string>
|
||||
<string name="confirm_block_title">屏蔽用户</string>
|
||||
<string name="confirm_block_domain_title">屏蔽域名</string>
|
||||
<string name="confirm_block">确定要屏蔽 %s 吗?</string>
|
||||
<string name="do_block">确定</string>
|
||||
<string name="confirm_unblock_title">解除屏蔽</string>
|
||||
<string name="confirm_unblock_domain_title">解除屏蔽</string>
|
||||
<string name="confirm_unblock">确定不再屏蔽 %s 吗?</string>
|
||||
<string name="do_unblock">确定</string>
|
||||
<string name="button_muted">已隐藏</string>
|
||||
<string name="button_blocked">已屏蔽</string>
|
||||
<string name="action_vote">投票</string>
|
||||
<string name="tap_to_reveal">点击显示</string>
|
||||
<string name="delete">删除</string>
|
||||
<string name="delete_and_redraft">删除以重新编辑</string>
|
||||
<string name="confirm_delete_title">删除嘟文</string>
|
||||
<string name="confirm_delete_and_redraft_title">删除嘟文并重新编辑</string>
|
||||
<string name="confirm_delete">确定要删除这条嘟文吗?</string>
|
||||
<string name="confirm_delete_and_redraft">确定要删除这条嘟文并重新编辑吗?</string>
|
||||
<string name="deleting">正在删除…</string>
|
||||
<string name="pin_post">置顶</string>
|
||||
<string name="confirm_pin_post_title">置顶嘟文</string>
|
||||
<string name="confirm_pin_post">确定要在你的资料页置顶这条嘟文吗?</string>
|
||||
<string name="pinning">正在置顶嘟文…</string>
|
||||
<string name="unpin_post">取消置顶</string>
|
||||
<string name="confirm_unpin_post_title">取消嘟文置顶</string>
|
||||
<string name="confirm_unpin_post">确定不再置顶这条嘟文吗?</string>
|
||||
<string name="unpinning">正在取消置顶…</string>
|
||||
<string name="notification_channel_audio_player">音频播放</string>
|
||||
<string name="play">播放</string>
|
||||
<string name="pause">暂停</string>
|
||||
<string name="log_out">登出</string>
|
||||
<string name="log_out">退出账户</string>
|
||||
<string name="add_account">添加账户</string>
|
||||
<string name="search_hint">搜索</string>
|
||||
<string name="hashtags">话题</string>
|
||||
<string name="for_you">推荐</string>
|
||||
<string name="news">新闻</string>
|
||||
<string name="for_you">推荐关注</string>
|
||||
<string name="all_notifications">全部</string>
|
||||
<string name="mentions">提及我</string>
|
||||
<string name="mentions">提及</string>
|
||||
<plurals name="x_people_talking">
|
||||
<item quantity="other">%d 人在讨论</item>
|
||||
</plurals>
|
||||
<plurals name="discussed_x_times">
|
||||
<item quantity="other">讨论了 %d 次</item>
|
||||
</plurals>
|
||||
<string name="report_title">举报 %s</string>
|
||||
<string name="report_choose_reason">这个帖子有什么问题?</string>
|
||||
<string name="report_choose_reason">这条嘟文有什么问题?</string>
|
||||
<string name="report_choose_reason_account">%s 有什么问题?</string>
|
||||
<string name="report_choose_reason_subtitle">选择最佳匹配</string>
|
||||
<string name="report_choose_reason_subtitle">选择最匹配的理由</string>
|
||||
<string name="report_reason_personal">我不喜欢它</string>
|
||||
<string name="report_reason_personal_subtitle">这不是你想看到的东西</string>
|
||||
<string name="report_reason_spam">它是垃圾信息</string>
|
||||
<string name="report_reason_spam_subtitle">恶意链接,虚假互动或重复回复</string>
|
||||
<string name="report_reason_violation">它违反了服务器规则</string>
|
||||
<string name="report_reason_violation_subtitle">你知道它会破坏特定规则</string>
|
||||
<string name="report_reason_spam">垃圾信息</string>
|
||||
<string name="report_reason_spam_subtitle">恶意链接、虚假互动或重复回复</string>
|
||||
<string name="report_reason_violation">违反社区规则</string>
|
||||
<string name="report_reason_violation_subtitle">你发现它违反了特定的规则</string>
|
||||
<string name="report_reason_other">其他原因</string>
|
||||
<string name="report_reason_other_subtitle">该问题不符合其他类别</string>
|
||||
<string name="report_reason_other_subtitle">以上理由都不适用</string>
|
||||
<string name="report_choose_rule">违反了哪些规则?</string>
|
||||
<string name="report_choose_rule_subtitle">选择所有适用项</string>
|
||||
<string name="report_choose_posts">是否有任何帖子支持此报告?</string>
|
||||
<string name="report_choose_posts">是否有任何嘟文支持此举报?</string>
|
||||
<string name="report_choose_posts_subtitle">选择所有适用项</string>
|
||||
<string name="report_comment_title">还有什么你认为我们应该知道的吗?</string>
|
||||
<string name="report_comment_title">还有什么要告诉我们的吗?</string>
|
||||
<string name="report_comment_hint">备注</string>
|
||||
<string name="sending_report">报告发送中...</string>
|
||||
<string name="report_sent_title">感谢提交举报,我们将会进行处理。</string>
|
||||
<string name="report_sent_subtitle">当我们审查这个问题时,你可以对 %s 采取行动。</string>
|
||||
<string name="unfollow_user">取消关注 %s</string>
|
||||
<string name="sending_report">正在提交举报…</string>
|
||||
<string name="report_sent_title">感谢举报,我们将会处理。</string>
|
||||
<string name="report_sent_subtitle">我们审查此问题期间,你也可以对 %s 采取行动。</string>
|
||||
<string name="unfollow_user">不再关注 %s</string>
|
||||
<string name="unfollow">取消关注</string>
|
||||
<string name="mute_user_explain">你不会在你的主页里看到他们的帖子或重新博客。他们不会知道他们被静音了。</string>
|
||||
<string name="block_user_explain">他们将不再能够关注或看到你的帖子,但他们可以看到他们是否被阻止。</string>
|
||||
<string name="report_personal_title">不想看到这个内容?</string>
|
||||
<string name="report_personal_subtitle">当您在Mastodon看到您不喜欢的东西时,您可以从您的体验中移除该人。</string>
|
||||
<string name="mute_user_explain">你不会在你的主页里看到他们的嘟文和转发,他们也不会知道你隐藏了他们。</string>
|
||||
<string name="block_user_explain">他们不能再关注你或看到你的嘟文,但他们能知道他们是否被屏蔽。</string>
|
||||
<string name="report_personal_title">不想看到这个?</string>
|
||||
<string name="report_personal_subtitle">如果在Mastodon看到不喜欢的东西,可以尝试移除它。</string>
|
||||
<string name="back">返回</string>
|
||||
<string name="instance_catalog_title">Mastodon由来自不同服务器的用户组成。</string>
|
||||
<string name="instance_catalog_subtitle">根据你的兴趣、地区或其他目的挑选一个服务器。无论你选择哪个服务器,你都可以跟所有人交流。</string>
|
||||
<string name="search_communities">搜索或输入网址</string>
|
||||
<string name="instance_rules_title">一些基本规则</string>
|
||||
<string name="instance_rules_subtitle">请花一分钟来审阅规则设置,并由 %s 管理员执行。</string>
|
||||
<string name="signup_title">让我们让您在 %s 上设置</string>
|
||||
<string name="instance_rules_subtitle">请花一分钟来审阅规则,这是由管理员 %s 设置和执行的。</string>
|
||||
<string name="signup_title">让我们在 %s 上开始</string>
|
||||
<string name="edit_photo">编辑</string>
|
||||
<string name="display_name">昵称</string>
|
||||
<string name="username">用户名</string>
|
||||
<string name="email">电子邮箱</string>
|
||||
<string name="password">密码</string>
|
||||
<string name="password_note">包括大写字母、特殊字符和数字以增加您的密码强度。</string>
|
||||
<string name="password_note">包括大写字母、特殊字符和数字以增加你的密码强度。</string>
|
||||
<string name="category_academia">学术</string>
|
||||
<string name="category_activism">行动主义</string>
|
||||
<string name="category_all">全部</string>
|
||||
<string name="category_art">艺术</string>
|
||||
<string name="category_food">食品</string>
|
||||
<string name="category_food">美食</string>
|
||||
<string name="category_furry">兽迷</string>
|
||||
<string name="category_games">游戏</string>
|
||||
<string name="category_general">通用</string>
|
||||
<string name="category_journalism">新闻</string>
|
||||
<string name="category_lgbt">性少数</string>
|
||||
<string name="category_music">音乐</string>
|
||||
<string name="category_regional">地区</string>
|
||||
<string name="category_tech">科技</string>
|
||||
<string name="confirm_email_title">还有一件事</string>
|
||||
<string name="confirm_email_subtitle">点击我们发送给你的链接来验证你的账户。</string>
|
||||
<string name="resend">重新发送</string>
|
||||
<string name="open_email_app">打开电子邮件应用</string>
|
||||
<string name="resent_email">确认邮件已发送</string>
|
||||
<string name="resent_email">邮件已发送</string>
|
||||
<string name="compose_hint">写下你的想法</string>
|
||||
<string name="content_warning">内容警告</string>
|
||||
<string name="image_description">图片描述</string>
|
||||
<string name="add_image_description">添加图片描述…</string>
|
||||
<string name="retry_upload">重新上传</string>
|
||||
<string name="image_upload_failed">图片上传失败</string>
|
||||
<string name="video_upload_failed">视频上传失败</string>
|
||||
<string name="edit_image">编辑图片</string>
|
||||
<string name="save">保存</string>
|
||||
<string name="add_alt_text">添加备注</string>
|
||||
<string name="alt_text_subtitle">备注可以为视障人士描述你的图片,请尽量只包含足以理解内容的信息。</string>
|
||||
<string name="alt_text_hint">例如,镜头前有一只狗眯着眼睛警惕地看着四周。</string>
|
||||
<string name="visibility_public">公开</string>
|
||||
<string name="visibility_unlisted">不公开</string>
|
||||
<string name="visibility_followers_only">仅关注者</string>
|
||||
<string name="visibility_private">仅我提到的人</string>
|
||||
<string name="visibility_private">仅提及的人</string>
|
||||
<string name="search_all">全部</string>
|
||||
<string name="search_people">用户</string>
|
||||
<string name="recent_searches">最近搜索</string>
|
||||
<string name="step_x_of_n">第 %1$d 步(共 %2$d 步)</string>
|
||||
<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_mention">提及</string>
|
||||
<string name="notification_type_poll">投票</string>
|
||||
<string name="choose_account">选择账户</string>
|
||||
<string name="err_not_logged_in">请先登陆到Mastodon</string>
|
||||
<plurals name="cant_add_more_than_x_attachments">
|
||||
<item quantity="other">你不能添加超过 %d 个媒体附件</item>
|
||||
</plurals>
|
||||
<string name="media_attachment_unsupported_type">文件 %s 是不支持的类型</string>
|
||||
<string name="media_attachment_too_big">文件 %1$s 的大小超出了 %2$s MB的限制</string>
|
||||
<string name="settings_theme">外观</string>
|
||||
<string name="theme_auto">自动</string>
|
||||
<string name="theme_light">浅色</string>
|
||||
<string name="theme_dark">深色</string>
|
||||
<string name="theme_true_black">纯黑模式</string>
|
||||
<string name="settings_behavior">行为</string>
|
||||
<string name="settings_gif">播放动态头像和表情</string>
|
||||
<string name="settings_custom_tabs">使用内置浏览器</string>
|
||||
<string name="settings_notifications">通知</string>
|
||||
<string name="notify_me_when">接收通知的范围</string>
|
||||
<string name="notify_anyone">任何人</string>
|
||||
<string name="notify_follower">关注者</string>
|
||||
<string name="notify_followed">我关注的</string>
|
||||
<string name="notify_none">没有人</string>
|
||||
<string name="notify_favorites">喜欢我的帖子</string>
|
||||
<string name="notify_none">关闭通知</string>
|
||||
<string name="notify_favorites">喜欢我的嘟文</string>
|
||||
<string name="notify_follow">关注我</string>
|
||||
<string name="notify_reblog">转发我的帖子</string>
|
||||
<string name="notify_reblog">转发我的嘟文</string>
|
||||
<string name="notify_mention">提及我</string>
|
||||
<string name="settings_boring">潜水区</string>
|
||||
<string name="settings_account">帐户设置</string>
|
||||
<string name="settings_boring">更多</string>
|
||||
<string name="settings_account">账户设置</string>
|
||||
<string name="settings_contribute">贡献给Mastodon</string>
|
||||
<string name="settings_tos">使用条款</string>
|
||||
<string name="settings_privacy_policy">隐私政策</string>
|
||||
<string name="settings_spicy">The Spicy Zone</string>
|
||||
<string name="settings_clear_cache">清除图片缓存</string>
|
||||
<string name="settings_spicy">危险地带</string>
|
||||
<string name="settings_clear_cache">清除媒体缓存</string>
|
||||
<string name="settings_app_version">Mastodon for Android v%1$s (%2$d)</string>
|
||||
<string name="media_cache_cleared">媒体缓存已清除</string>
|
||||
<string name="confirm_log_out">您确定要退出吗?</string>
|
||||
<string name="confirm_log_out">确定要退出账户吗?</string>
|
||||
<string name="sensitive_content">敏感内容</string>
|
||||
<string name="sensitive_content_explain">作者将此媒体标记为敏感。点击以显示。</string>
|
||||
<string name="media_hidden">点击以显示</string>
|
||||
<string name="avatar_description">跳转到 %s 的资料</string>
|
||||
<string name="sensitive_content_explain">作者将此媒体标记为敏感内容,点击显示。</string>
|
||||
<string name="media_hidden">点击显示</string>
|
||||
<string name="avatar_description">跳转到 %s 的资料页</string>
|
||||
<string name="more_options">更多选项</string>
|
||||
<string name="reveal_content">显示内容</string>
|
||||
<string name="hide_content">隐藏内容</string>
|
||||
<string name="new_post">新帖子</string>
|
||||
<string name="new_post">新嘟文</string>
|
||||
<string name="button_reply">回复</string>
|
||||
<string name="button_reblog">转发</string>
|
||||
<string name="button_favorite">喜欢</string>
|
||||
<string name="button_share">分享</string>
|
||||
<string name="button_bookmark">添加到书签</string>
|
||||
<string name="bookmarks">书签</string>
|
||||
<string name="media_no_description">没有描述的媒体</string>
|
||||
<string name="add_media">添加媒体</string>
|
||||
<string name="add_poll">添加投票</string>
|
||||
<string name="add_poll">发起投票</string>
|
||||
<string name="emoji">表情</string>
|
||||
<string name="post_visibility">帖子可见性</string>
|
||||
<string name="post_visibility">嘟文可见性</string>
|
||||
<string name="home_timeline">主页时间轴</string>
|
||||
<string name="my_profile">我的资料</string>
|
||||
<string name="media_viewer">媒体查看器</string>
|
||||
<string name="follow_user">关注 %s</string>
|
||||
<string name="unfollowed_user">取消关注 %s</string>
|
||||
<string name="followed_user">您正在关注 %s</string>
|
||||
<string name="followed_user">你正在关注 %s</string>
|
||||
<string name="open_in_browser">在浏览器中打开</string>
|
||||
<string name="signup_reason">加入的理由是?</string>
|
||||
<string name="signup_reason_note">这会有助于我们处理你的申请.</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>
|
||||
<string name="profile_header">顶部图片</string>
|
||||
<string name="profile_picture">个人资料照片</string>
|
||||
<string name="profile_header">资料页横幅图片</string>
|
||||
<string name="profile_picture">头像</string>
|
||||
<string name="reorder">重新排序</string>
|
||||
<string name="download">下载</string>
|
||||
<string name="permission_required">需要相应权限</string>
|
||||
<string name="trending_posts_info_banner">这些是在你的 Mastodon 宇宙中备受关注的内容。</string>
|
||||
<string name="trending_hashtags_info_banner">这些是在你的 Mastodon 宇宙中备受关注的话题</string>
|
||||
<string name="local_timeline_info_banner">这些是与您使用相同 Mastodon 服务器的人的最新帖子。</string>
|
||||
<string name="follows_you">关注了你</string>
|
||||
<string name="current_account">当前账号</string>
|
||||
<string name="permission_required">需要权限</string>
|
||||
<string name="storage_permission_to_download">应用程序需要存储权限才能保存文件。</string>
|
||||
<string name="open_settings">打开「设置」</string>
|
||||
<string name="error_saving_file">保存文件时出错</string>
|
||||
<string name="file_saved">文件已保存</string>
|
||||
<string name="downloading">正在下载…</string>
|
||||
<string name="no_app_to_handle_action">未找到可处理此操作的应用</string>
|
||||
<string name="local_timeline">本站时间轴</string>
|
||||
<string name="federated_timeline">联邦时间轴</string>
|
||||
<string name="trending_posts_info_banner">这是在你的Mastodon角落备受关注的内容。</string>
|
||||
<string name="trending_hashtags_info_banner">这是在你的Mastodon角落备受关注的话题。</string>
|
||||
<string name="trending_links_info_banner">这是在你的Mastodon角落分享最多的新闻故事。</string>
|
||||
<string name="local_timeline_info_banner">这是你所在的Mastodon服务器上的用户发布的最新嘟文。</string>
|
||||
<string name="federated_timeline_info_banner">这是在你的联邦宇宙中最新发布的嘟文。</string>
|
||||
<string name="dismiss">驳回</string>
|
||||
<string name="see_new_posts">查看新嘟文</string>
|
||||
<string name="load_missing_posts">加载嘟文</string>
|
||||
<string name="follow_back">关注</string>
|
||||
<string name="button_follow_pending">已发送关注请求</string>
|
||||
<string name="follows_you">已关注你</string>
|
||||
<string name="manually_approves_followers">手动批准关注请求</string>
|
||||
<string name="current_account">当前账户</string>
|
||||
<string name="log_out_account">退出 %s</string>
|
||||
<!-- translators: %,d is a valid placeholder, it formats the number with locale-dependent grouping separators -->
|
||||
<plurals name="x_followers">
|
||||
<item quantity="other">%,d 名关注者</item>
|
||||
</plurals>
|
||||
<plurals name="x_following">
|
||||
<item quantity="other">关注 %,d 人</item>
|
||||
</plurals>
|
||||
<plurals name="x_favorites">
|
||||
<item quantity="other">%,d 次喜欢</item>
|
||||
</plurals>
|
||||
<plurals name="x_reblogs">
|
||||
<item quantity="other">%,d 次转发</item>
|
||||
</plurals>
|
||||
<string name="timestamp_via_app">%1$s 来自 %2$s</string>
|
||||
<string name="time_now">刚刚</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user