Compare commits
16 Commits
v1.1.1+for
...
v1.1.1+for
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1e67c4f73 | ||
|
|
e0e48f87eb | ||
|
|
b2db64022f | ||
|
|
0ec14fe8fa | ||
|
|
01a2f1d95c | ||
|
|
67b3e85837 | ||
|
|
9f4d330ab1 | ||
|
|
25092fbcfb | ||
|
|
705e98729d | ||
|
|
108d16a157 | ||
|
|
e55ca6cc05 | ||
|
|
b8be1f184d | ||
|
|
aa96ec54a3 | ||
|
|
e8b43c7179 | ||
|
|
b51b4a10ee | ||
|
|
f2b9ede27c |
19
README.md
@@ -1,8 +1,6 @@
|
||||
# Forked Mastodon for Android
|
||||

|
||||
|
||||
This is the repository for an officially forked Android app for Mastodon.
|
||||
|
||||
Learn more about the official app in the [blog post](https://blog.joinmastodon.org/2022/02/official-mastodon-for-android-app-is-coming-soon/).
|
||||
# Mastodon for Android Fork
|
||||
|
||||
## Changes
|
||||
|
||||
@@ -18,6 +16,19 @@ Learn more about the official app in the [blog post](https://blog.joinmastodon.o
|
||||
* [Implement a bookmark button and list](https://github.com/sk22/mastodon-android-fork/tree/feature/bookmarks) ([Fixes issue](https://github.com/mastodon/mastodon-android/issues/22))
|
||||
* [Implement deleting and re-drafting](https://github.com/sk22/mastodon-android-fork/tree/feature/delete-redraft) ([Fixes issue](https://github.com/mastodon/mastodon-android/issues/21))
|
||||
|
||||
## Fork-specific changes
|
||||
|
||||
* Custom app name
|
||||
* Custom icon: Modulate upstream icon's hue by `161%` using ImageMagick
|
||||
|
||||
```bash
|
||||
mogrify -modulate 100,100,161 mastodon/src/main/res/mipmap-*/ic_launcher*.png
|
||||
```
|
||||
|
||||
* Custom primary color: Hue of all `primary` colors in `colors.xml` is rotated
|
||||
by `109.8°` (equivalent of `161%`, done by hand using
|
||||
[PineTools](https://pinetools.com/shift-hue-color))
|
||||
|
||||
## Building
|
||||
|
||||
As this app is using Java 17 features, you need JDK 17 or newer to build it. Other than that, everything is pretty standard. You can either import the project into Android Studio and build it from there, or run the following command in the project directory:
|
||||
|
||||
@@ -9,8 +9,8 @@ android {
|
||||
applicationId "org.joinmastodon.android.sk"
|
||||
minSdk 23
|
||||
targetSdk 31
|
||||
versionCode 15
|
||||
versionName '1.1.1+fork.15'
|
||||
versionCode 19
|
||||
versionName '1.1.1+fork.19'
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
||||
5
mastodon/proguard-rules.pro
vendored
@@ -47,3 +47,8 @@
|
||||
-keep class org.joinmastodon.android.AppCenterWrapper { *; }
|
||||
|
||||
-keepattributes LineNumberTable
|
||||
|
||||
# Parceler library
|
||||
-keep interface org.parceler.Parcel
|
||||
-keep @org.parceler.Parcel class * { *; }
|
||||
-keep class **$$Parcelable { *; }
|
||||
|
||||
@@ -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;
|
||||
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);
|
||||
}
|
||||
if(opts.outWidth*opts.outHeight>maxSize){
|
||||
contentType=MastodonApp.context.getContentResolver().getType(uri);
|
||||
}
|
||||
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())));
|
||||
decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
|
||||
decoder.setTargetSize(targetWidth, targetHeight);
|
||||
});
|
||||
if(Build.VERSION.SDK_INT>=28){
|
||||
ImageDecoder.Source source;
|
||||
if("file".equals(uri.getScheme())){
|
||||
source=ImageDecoder.createSource(new File(uri.getPath()));
|
||||
}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)));
|
||||
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(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[] 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;
|
||||
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){
|
||||
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);
|
||||
@@ -93,6 +137,9 @@ public class ResizedImageRequestBody extends CountingRequestBody{
|
||||
}
|
||||
}
|
||||
length=tempFile.length();
|
||||
}else{
|
||||
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();
|
||||
@@ -100,6 +147,7 @@ public class ResizedImageRequestBody extends CountingRequestBody{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Source openSource() throws IOException{
|
||||
@@ -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]", "");
|
||||
|
||||
@@ -11,7 +11,7 @@ public class CreateOAuthApp extends MastodonAPIRequest<Application>{
|
||||
}
|
||||
|
||||
private static class Request{
|
||||
public String clientName="Mastadon for Android";
|
||||
public String clientName="Mastodon for Android Fork";
|
||||
public String redirectUris=AccountSessionManager.REDIRECT_URI;
|
||||
public String scopes=AccountSessionManager.SCOPE;
|
||||
public String website="https://github.com/sk22/mastodon-android-fork";
|
||||
|
||||
@@ -213,6 +213,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
replyTo=Parcels.unwrap(getArguments().getParcelable("replyTo"));
|
||||
statusVisibility=replyTo.visibility;
|
||||
}
|
||||
|
||||
if(getArguments().containsKey("visibility")){
|
||||
statusVisibility=(StatusPrivacy) getArguments().getSerializable("visibility");
|
||||
}
|
||||
|
||||
if(savedInstanceState!=null){
|
||||
statusVisibility=(StatusPrivacy) savedInstanceState.getSerializable("visibility");
|
||||
}
|
||||
|
||||
@@ -137,10 +137,10 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
int id=menuItem.getItemId();
|
||||
if(id==R.id.delete){
|
||||
UiUtils.confirmDeletePost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{});
|
||||
}else if(id==R.id.pin || id==R.id.unpin){
|
||||
UiUtils.confirmPinPost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, !item.status.pinned, s->{});
|
||||
}else if(id==R.id.delete_and_redraft) {
|
||||
UiUtils.confirmDeleteAndRedraftPost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{});
|
||||
}else if(id==R.id.pin || id==R.id.unpin){
|
||||
UiUtils.confirmPinPost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, !item.status.pinned, s->{});
|
||||
}else if(id==R.id.mute){
|
||||
UiUtils.confirmToggleMuteUser(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), account, relationship!=null && relationship.muting, r->{});
|
||||
}else if(id==R.id.block){
|
||||
@@ -254,6 +254,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
Menu menu=optionsMenu.getMenu();
|
||||
boolean isOwnPost=AccountSessionManager.getInstance().isSelf(item.parentFragment.getAccountID(), account);
|
||||
menu.findItem(R.id.delete).setVisible(item.status!=null && isOwnPost);
|
||||
menu.findItem(R.id.delete_and_redraft).setVisible(item.status!=null && isOwnPost);
|
||||
menu.findItem(R.id.pin).setVisible(item.status!=null && isOwnPost && !item.status.pinned);
|
||||
menu.findItem(R.id.unpin).setVisible(item.status!=null && isOwnPost && item.status.pinned);
|
||||
menu.findItem(R.id.open_in_browser).setVisible(item.status!=null);
|
||||
|
||||
@@ -56,6 +56,7 @@ import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Emoji;
|
||||
import org.joinmastodon.android.model.Relationship;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.model.StatusPrivacy;
|
||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||
import org.joinmastodon.android.ui.text.CustomEmojiSpan;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
@@ -82,6 +83,10 @@ import androidx.annotation.StringRes;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
@@ -415,6 +420,7 @@ public class UiUtils{
|
||||
args.putBoolean("hasDraft", true);
|
||||
args.putString("prefilledText", HtmlParser.parse(status.content, status.emojis, status.mentions, status.tags, accountID).toString());
|
||||
args.putString("spoilerText", status.spoilerText);
|
||||
args.putSerializable("visibility", status.visibility);
|
||||
if(status.poll!=null){
|
||||
args.putInt("pollDuration", (int)status.poll.expiresAt.minus(status.createdAt.getEpochSecond(), ChronoUnit.SECONDS).getEpochSecond());
|
||||
ArrayList<String> opts=status.poll.options.stream().map(o -> o.title).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 34 KiB |
@@ -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>
|
||||
|
||||
@@ -19,17 +19,17 @@
|
||||
<color name="gray_800t">#CC282C37</color>
|
||||
<color name="gray_900">#101828</color>
|
||||
|
||||
<color name="primary_25">#FAFDFF</color>
|
||||
<color name="primary_50">#EAF4FB</color>
|
||||
<color name="primary_100">#D5E9F7</color>
|
||||
<color name="primary_200">#BFDEF4</color>
|
||||
<color name="primary_300">#AAD3F0</color>
|
||||
<color name="primary_400">#95C8EC</color>
|
||||
<color name="primary_500">#80BCE8</color>
|
||||
<color name="primary_600">#55A6E1</color>
|
||||
<color name="primary_700">#2B90D9</color>
|
||||
<color name="primary_800">#2273AE</color>
|
||||
<color name="primary_900">#16486D</color>
|
||||
<color name="primary_25">#fffafd</color>
|
||||
<color name="primary_50">#fbeaf6</color>
|
||||
<color name="primary_100">#f7d4ee</color>
|
||||
<color name="primary_200">#f4bfe7</color>
|
||||
<color name="primary_300">#f0aade</color>
|
||||
<color name="primary_400">#ec94d6</color>
|
||||
<color name="primary_500">#e780cd</color>
|
||||
<color name="primary_600">#e055bd</color>
|
||||
<color name="primary_700">#d92aad</color>
|
||||
<color name="primary_800">#ae218a</color>
|
||||
<color name="primary_900">#6d1556</color>
|
||||
<color name="error_25">#FFFBFA</color>
|
||||
<color name="error_50">#FEF3F2</color>
|
||||
<color name="error_100">#FEE4E2</color>
|
||||
|
||||